Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -792,7 +792,7 @@ /// IgnoreParens() + IgnoreImpCasts() until reaching a fixed point. However /// this is currently not the case. Instead IgnoreParenImpCasts() skips: /// * What IgnoreParens() skips. - /// * ImplicitCastExpr. + /// * What IgnoreImpCasts() skips. /// * MaterializeTemporaryExpr. /// * SubstNonTypeTemplateParmExpr. Expr *IgnoreParenImpCasts() LLVM_READONLY; Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -2556,192 +2556,176 @@ return QualType(); } -Expr *Expr::IgnoreImpCasts() { - Expr *E = this; - while (true) - if (ImplicitCastExpr *ICE = dyn_cast(E)) - E = ICE->getSubExpr(); - else if (FullExpr *FE = dyn_cast(E)) - E = FE->getSubExpr(); - else - break; +static Expr *IgnoreImpCastsSingleStep(Expr *E) { + if (auto *ICE = dyn_cast_or_null(E)) + return ICE->getSubExpr(); + + else if (auto *FE = dyn_cast_or_null(E)) + return FE->getSubExpr(); + + return E; +} + +static Expr *IgnoreImpCastsExtraSingleStep(Expr *E) { + // FIXME: Skip MaterializeTemporaryExpr and SubstNonTypeTemplateParmExpr in + // addition to what IgnoreImpCasts() skips to account for the current + // behaviour of IgnoreParenImpCasts(). + Expr *SubE = IgnoreImpCastsSingleStep(E); + if (SubE != E) + return SubE; + + if (auto *MTE = dyn_cast_or_null(E)) + return MTE->GetTemporaryExpr(); + + else if (auto *NTTP = dyn_cast_or_null(E)) + return NTTP->getReplacement(); + return E; } -Expr *Expr::IgnoreImplicit() { - Expr *E = this; +static Expr *IgnoreCastsSingleStep(Expr *E) { + if (auto *CE = dyn_cast_or_null(E)) + return CE->getSubExpr(); + + else if (auto *FE = dyn_cast_or_null(E)) + return FE->getSubExpr(); + + else if (auto *MTE = dyn_cast_or_null(E)) + return MTE->GetTemporaryExpr(); + + else if (auto *NTTP = dyn_cast_or_null(E)) + return NTTP->getReplacement(); + + return E; +} + +static Expr *IgnoreLValueCastsSingleStep(Expr *E) { + // Skip what IgnoreCastsSingleStep skips, except that only + // lvalue-to-rvalue casts are skipped. + if (auto *CE = dyn_cast_or_null(E)) + if (CE->getCastKind() != CK_LValueToRValue) + return E; + + return IgnoreCastsSingleStep(E); +} + +static Expr *IgnoreBaseCastsSingleStep(Expr *E) { + if (auto *CE = dyn_cast_or_null(E)) + if (CE->getCastKind() == CK_DerivedToBase || + CE->getCastKind() == CK_UncheckedDerivedToBase || + CE->getCastKind() == CK_NoOp) + return CE->getSubExpr(); + + return E; +} + +static Expr *IgnoreImplicitSingleStep(Expr *E) { + Expr *SubE = IgnoreImpCastsSingleStep(E); + if (SubE != E) + return SubE; + + if (auto *MTE = dyn_cast_or_null(E)) + return MTE->GetTemporaryExpr(); + + else if (auto *BTE = dyn_cast_or_null(E)) + return BTE->getSubExpr(); + + return E; +} + +static Expr *IgnoreParensSingleStep(Expr *E) { + if (auto *PE = dyn_cast_or_null(E)) + return PE->getSubExpr(); + + else if (auto *UO = dyn_cast_or_null(E)) { + if (UO->getOpcode() == UO_Extension) + return UO->getSubExpr(); + } + + else if (auto *GSE = dyn_cast_or_null(E)) { + if (!GSE->isResultDependent()) + return GSE->getResultExpr(); + } + + else if (auto *CE = dyn_cast_or_null(E)) { + if (!CE->isConditionDependent()) + return CE->getChosenSubExpr(); + } + + else if (auto *CE = dyn_cast_or_null(E)) + return CE->getSubExpr(); + + return E; +} + +static Expr *IgnoreNoopCastsSingleStep(const ASTContext &Ctx, Expr *E) { + if (auto *CE = dyn_cast_or_null(E)) { + // We ignore integer <-> casts that are of the same width, ptr<->ptr and + // ptr<->int casts of the same width. We also ignore all identity casts. + Expr *SubExpr = CE->getSubExpr(); + bool IsIdentityCast = + Ctx.hasSameUnqualifiedType(E->getType(), SubExpr->getType()); + bool IsSameWidthCast = + (E->getType()->isPointerType() || E->getType()->isIntegralType(Ctx)) && + (SubExpr->getType()->isPointerType() || + SubExpr->getType()->isIntegralType(Ctx)) && + (Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SubExpr->getType())); + + if (IsIdentityCast || IsSameWidthCast) + return SubExpr; + } + + else if (auto *NTTP = dyn_cast_or_null(E)) + return NTTP->getReplacement(); + + return E; +} + +namespace { + +Expr *IgnoreExprNodesImpl(Expr *E) { return E; } +template +Expr *IgnoreExprNodesImpl(Expr *E, FnTy &&Fn, FnTys &&... Fns) { + return IgnoreExprNodesImpl(Fn(E), std::forward(Fns)...); +} + +/// Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, +/// Recursively apply each of the functions to E until reaching a fixed point. +/// Note that a null E is valid; in this case nothing is done. +template Expr *IgnoreExprNodes(Expr *E, FnTys &&... Fns) { Expr *LastE = nullptr; while (E != LastE) { LastE = E; - - if (auto *ICE = dyn_cast(E)) - E = ICE->getSubExpr(); - - if (auto *FE = dyn_cast(E)) - E = FE->getSubExpr(); - - if (auto *MTE = dyn_cast(E)) - E = MTE->GetTemporaryExpr(); - - if (auto *BTE = dyn_cast(E)) - E = BTE->getSubExpr(); + E = IgnoreExprNodesImpl(E, std::forward(Fns)...); } return E; } -Expr* Expr::IgnoreParens() { - Expr* E = this; - while (true) { - if (ParenExpr* P = dyn_cast(E)) { - E = P->getSubExpr(); - continue; - } - if (UnaryOperator* P = dyn_cast(E)) { - if (P->getOpcode() == UO_Extension) { - E = P->getSubExpr(); - continue; - } - } - if (GenericSelectionExpr* P = dyn_cast(E)) { - if (!P->isResultDependent()) { - E = P->getResultExpr(); - continue; - } - } - if (ChooseExpr* P = dyn_cast(E)) { - if (!P->isConditionDependent()) { - E = P->getChosenSubExpr(); - continue; - } - } - if (ConstantExpr *CE = dyn_cast(E)) { - E = CE->getSubExpr(); - continue; - } - return E; - } -} +} // anonymous namespace -/// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr -/// or CastExprs or ImplicitCastExprs, returning their operand. -Expr *Expr::IgnoreParenCasts() { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - if (CastExpr *P = dyn_cast(E)) { - E = P->getSubExpr(); - continue; - } - if (MaterializeTemporaryExpr *Materialize - = dyn_cast(E)) { - E = Materialize->GetTemporaryExpr(); - continue; - } - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast(E)) { - E = NTTP->getReplacement(); - continue; - } - if (FullExpr *FE = dyn_cast(E)) { - E = FE->getSubExpr(); - continue; - } - return E; - } +Expr *Expr::IgnoreImpCasts() { + return IgnoreExprNodes(this, IgnoreImpCastsSingleStep); } Expr *Expr::IgnoreCasts() { - Expr *E = this; - while (true) { - if (CastExpr *P = dyn_cast(E)) { - E = P->getSubExpr(); - continue; - } - if (MaterializeTemporaryExpr *Materialize - = dyn_cast(E)) { - E = Materialize->GetTemporaryExpr(); - continue; - } - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast(E)) { - E = NTTP->getReplacement(); - continue; - } - if (FullExpr *FE = dyn_cast(E)) { - E = FE->getSubExpr(); - continue; - } - return E; - } + return IgnoreExprNodes(this, IgnoreCastsSingleStep); } -/// IgnoreParenLValueCasts - Ignore parentheses and lvalue-to-rvalue -/// casts. This is intended purely as a temporary workaround for code -/// that hasn't yet been rewritten to do the right thing about those -/// casts, and may disappear along with the last internal use. -Expr *Expr::IgnoreParenLValueCasts() { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - if (CastExpr *P = dyn_cast(E)) { - if (P->getCastKind() == CK_LValueToRValue) { - E = P->getSubExpr(); - continue; - } - } else if (MaterializeTemporaryExpr *Materialize - = dyn_cast(E)) { - E = Materialize->GetTemporaryExpr(); - continue; - } else if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast(E)) { - E = NTTP->getReplacement(); - continue; - } else if (FullExpr *FE = dyn_cast(E)) { - E = FE->getSubExpr(); - continue; - } - break; - } - return E; +Expr *Expr::IgnoreImplicit() { + return IgnoreExprNodes(this, IgnoreImplicitSingleStep); } -Expr *Expr::ignoreParenBaseCasts() { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - if (CastExpr *CE = dyn_cast(E)) { - if (CE->getCastKind() == CK_DerivedToBase || - CE->getCastKind() == CK_UncheckedDerivedToBase || - CE->getCastKind() == CK_NoOp) { - E = CE->getSubExpr(); - continue; - } - } - - return E; - } +Expr *Expr::IgnoreParens() { + return IgnoreExprNodes(this, IgnoreParensSingleStep); } Expr *Expr::IgnoreParenImpCasts() { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - if (ImplicitCastExpr *P = dyn_cast(E)) { - E = P->getSubExpr(); - continue; - } - if (MaterializeTemporaryExpr *Materialize - = dyn_cast(E)) { - E = Materialize->GetTemporaryExpr(); - continue; - } - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast(E)) { - E = NTTP->getReplacement(); - continue; - } - return E; - } + return IgnoreExprNodes(this, IgnoreParensSingleStep, + IgnoreImpCastsExtraSingleStep); +} + +Expr *Expr::IgnoreParenCasts() { + return IgnoreExprNodes(this, IgnoreParensSingleStep, IgnoreCastsSingleStep); } Expr *Expr::IgnoreConversionOperator() { @@ -2752,42 +2736,20 @@ return this; } -/// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the -/// value (including ptr->int casts of the same size). Strip off any -/// ParenExpr or CastExprs, returning their operand. +Expr *Expr::IgnoreParenLValueCasts() { + return IgnoreExprNodes(this, IgnoreParensSingleStep, + IgnoreLValueCastsSingleStep); +} + +Expr *Expr::ignoreParenBaseCasts() { + return IgnoreExprNodes(this, IgnoreParensSingleStep, + IgnoreBaseCastsSingleStep); +} + Expr *Expr::IgnoreParenNoopCasts(const ASTContext &Ctx) { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - - if (CastExpr *P = dyn_cast(E)) { - // We ignore integer <-> casts that are of the same width, ptr<->ptr and - // ptr<->int casts of the same width. We also ignore all identity casts. - Expr *SE = P->getSubExpr(); - - if (Ctx.hasSameUnqualifiedType(E->getType(), SE->getType())) { - E = SE; - continue; - } - - if ((E->getType()->isPointerType() || - E->getType()->isIntegralType(Ctx)) && - (SE->getType()->isPointerType() || - SE->getType()->isIntegralType(Ctx)) && - Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) { - E = SE; - continue; - } - } - - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast(E)) { - E = NTTP->getReplacement(); - continue; - } - - return E; - } + return IgnoreExprNodes(this, IgnoreParensSingleStep, [&Ctx](Expr *E) { + return IgnoreNoopCastsSingleStep(Ctx, E); + }); } bool Expr::isDefaultArgument() const {