Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -794,7 +794,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,185 +2556,173 @@ return QualType(); } -Expr *Expr::IgnoreImpCasts() { - Expr *E = this; - while (true) { - if (auto *ICE = dyn_cast(E)) - E = ICE->getSubExpr(); - else if (auto *FE = dyn_cast(E)) - E = FE->getSubExpr(); - else - break; - } +static Expr *IgnoreImpCastsSingleStep(Expr *E) { + if (auto *ICE = dyn_cast(E)) + return ICE->getSubExpr(); + + if (auto *FE = dyn_cast(E)) + return FE->getSubExpr(); + return E; } -Expr *Expr::IgnoreImplicit() { - Expr *E = this; - Expr *LastE = nullptr; - while (E != LastE) { - LastE = 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 *ICE = dyn_cast(E)) - E = ICE->getSubExpr(); + if (auto *MTE = dyn_cast(E)) + return MTE->GetTemporaryExpr(); - if (auto *FE = dyn_cast(E)) - E = FE->getSubExpr(); + if (auto *NTTP = dyn_cast(E)) + return NTTP->getReplacement(); - if (auto *MTE = dyn_cast(E)) - E = MTE->GetTemporaryExpr(); + return E; +} + +static Expr *IgnoreCastsSingleStep(Expr *E) { + if (auto *CE = dyn_cast(E)) + return CE->getSubExpr(); + + if (auto *FE = dyn_cast(E)) + return FE->getSubExpr(); + + if (auto *MTE = dyn_cast(E)) + return MTE->GetTemporaryExpr(); + + if (auto *NTTP = dyn_cast(E)) + return NTTP->getReplacement(); - if (auto *BTE = dyn_cast(E)) - E = BTE->getSubExpr(); - } return E; } -Expr *Expr::IgnoreParens() { - Expr *E = this; - while (true) { - if (auto *PE = dyn_cast(E)) { - E = PE->getSubExpr(); - continue; - } - if (auto *UO = dyn_cast(E)) { - if (UO->getOpcode() == UO_Extension) { - E = UO->getSubExpr(); - continue; - } - } - if (auto *GSE = dyn_cast(E)) { - if (!GSE->isResultDependent()) { - E = GSE->getResultExpr(); - continue; - } - } - if (auto *CE = dyn_cast(E)) { - if (!CE->isConditionDependent()) { - E = CE->getChosenSubExpr(); - continue; - } - } - if (auto *CE = dyn_cast(E)) { - E = CE->getSubExpr(); - continue; - } - 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(E)) + if (CE->getCastKind() != CK_LValueToRValue) + return E; + + return IgnoreCastsSingleStep(E); } -/// 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 (auto *CE = dyn_cast(E)) { - E = CE->getSubExpr(); - continue; - } - if (auto *MTE = dyn_cast(E)) { - E = MTE->GetTemporaryExpr(); - continue; - } - if (auto *NTTP = dyn_cast(E)) { - E = NTTP->getReplacement(); - continue; - } - if (auto *FE = dyn_cast(E)) { - E = FE->getSubExpr(); - continue; - } - return E; - } +static Expr *IgnoreBaseCastsSingleStep(Expr *E) { + if (auto *CE = dyn_cast(E)) + if (CE->getCastKind() == CK_DerivedToBase || + CE->getCastKind() == CK_UncheckedDerivedToBase || + CE->getCastKind() == CK_NoOp) + return CE->getSubExpr(); + + return E; } -Expr *Expr::IgnoreCasts() { - Expr *E = this; - while (true) { - if (auto *CE = dyn_cast(E)) { - E = CE->getSubExpr(); - continue; - } - if (auto *MTE = dyn_cast(E)) { - E = MTE->GetTemporaryExpr(); - continue; - } - if (auto *NTTP = dyn_cast(E)) { - E = NTTP->getReplacement(); - continue; - } - if (auto *FE = dyn_cast(E)) { - E = FE->getSubExpr(); - continue; - } - return E; +static Expr *IgnoreImplicitSingleStep(Expr *E) { + Expr *SubE = IgnoreImpCastsSingleStep(E); + if (SubE != E) + return SubE; + + if (auto *MTE = dyn_cast(E)) + return MTE->GetTemporaryExpr(); + + if (auto *BTE = dyn_cast(E)) + return BTE->getSubExpr(); + + return E; +} + +static Expr *IgnoreParensSingleStep(Expr *E) { + if (auto *PE = dyn_cast(E)) + return PE->getSubExpr(); + + if (auto *UO = dyn_cast(E)) { + if (UO->getOpcode() == UO_Extension) + return UO->getSubExpr(); + } + + else if (auto *GSE = dyn_cast(E)) { + if (!GSE->isResultDependent()) + return GSE->getResultExpr(); + } + + else if (auto *CE = dyn_cast(E)) { + if (!CE->isConditionDependent()) + return CE->getChosenSubExpr(); } + + else if (auto *CE = dyn_cast(E)) + return CE->getSubExpr(); + + return E; } -/// 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 (auto *CE = dyn_cast(E)) { - if (CE->getCastKind() == CK_LValueToRValue) { - E = CE->getSubExpr(); - continue; - } - } else if (auto *MTE = dyn_cast(E)) { - E = MTE->GetTemporaryExpr(); - continue; - } else if (auto *NTTP = dyn_cast(E)) { - E = NTTP->getReplacement(); - continue; - } else if (auto *FE = dyn_cast(E)) { - E = FE->getSubExpr(); - continue; - } - break; +static Expr *IgnoreNoopCastsSingleStep(const ASTContext &Ctx, Expr *E) { + if (auto *CE = 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 *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(E)) + return NTTP->getReplacement(); + return E; } -Expr *Expr::ignoreParenBaseCasts() { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - if (auto *CE = dyn_cast(E)) { - if (CE->getCastKind() == CK_DerivedToBase || - CE->getCastKind() == CK_UncheckedDerivedToBase || - CE->getCastKind() == CK_NoOp) { - E = CE->getSubExpr(); - continue; - } - } +static Expr *IgnoreExprNodesImpl(Expr *E) { return E; } +template +static Expr *IgnoreExprNodesImpl(Expr *E, FnTy &&Fn, FnTys &&... Fns) { + return IgnoreExprNodesImpl(Fn(E), std::forward(Fns)...); +} - return E; +/// 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 +static Expr *IgnoreExprNodes(Expr *E, FnTys &&... Fns) { + Expr *LastE = nullptr; + while (E != LastE) { + LastE = E; + E = IgnoreExprNodesImpl(E, std::forward(Fns)...); } + return E; +} + +Expr *Expr::IgnoreImpCasts() { + return IgnoreExprNodes(this, IgnoreImpCastsSingleStep); +} + +Expr *Expr::IgnoreCasts() { + return IgnoreExprNodes(this, IgnoreCastsSingleStep); +} + +Expr *Expr::IgnoreImplicit() { + return IgnoreExprNodes(this, IgnoreImplicitSingleStep); +} + +Expr *Expr::IgnoreParens() { + return IgnoreExprNodes(this, IgnoreParensSingleStep); } Expr *Expr::IgnoreParenImpCasts() { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - if (auto *ICE = dyn_cast(E)) { - E = ICE->getSubExpr(); - continue; - } - if (auto *MTE = dyn_cast(E)) { - E = MTE->GetTemporaryExpr(); - continue; - } - if (auto *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() { @@ -2745,41 +2733,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::IgnoreParenNoopCasts(const ASTContext &Ctx) { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - - if (auto *CE = 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 = CE->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; - } - } +Expr *Expr::IgnoreParenLValueCasts() { + return IgnoreExprNodes(this, IgnoreParensSingleStep, + IgnoreLValueCastsSingleStep); +} - if (auto *NTTP = dyn_cast(E)) { - E = NTTP->getReplacement(); - continue; - } +Expr *Expr::ignoreParenBaseCasts() { + return IgnoreExprNodes(this, IgnoreParensSingleStep, + IgnoreBaseCastsSingleStep); +} - return E; - } +Expr *Expr::IgnoreParenNoopCasts(const ASTContext &Ctx) { + return IgnoreExprNodes(this, IgnoreParensSingleStep, [&Ctx](Expr *E) { + return IgnoreNoopCastsSingleStep(Ctx, E); + }); } bool Expr::isDefaultArgument() const {