Index: cfe/trunk/include/clang/AST/Expr.h =================================================================== --- cfe/trunk/include/clang/AST/Expr.h +++ cfe/trunk/include/clang/AST/Expr.h @@ -746,67 +746,110 @@ /// member expression. static QualType findBoundMemberType(const Expr *expr); - /// IgnoreImpCasts - Skip past any implicit casts which might - /// surround this expression. Only skips ImplicitCastExprs. + /// Skip past any implicit casts which might surround this expression until + /// reaching a fixed point. Skips: + /// * ImplicitCastExpr + /// * FullExpr Expr *IgnoreImpCasts() LLVM_READONLY; - - /// IgnoreImplicit - Skip past any implicit AST nodes which might - /// surround this expression. - Expr *IgnoreImplicit() LLVM_READONLY { - return cast(Stmt::IgnoreImplicit()); + const Expr *IgnoreImpCasts() const { + return const_cast(this)->IgnoreImpCasts(); } - const Expr *IgnoreImplicit() const LLVM_READONLY { - return const_cast(this)->IgnoreImplicit(); + /// Skip past any casts which might surround this expression until reaching + /// a fixed point. Skips: + /// * CastExpr + /// * FullExpr + /// * MaterializeTemporaryExpr + /// * SubstNonTypeTemplateParmExpr + Expr *IgnoreCasts() LLVM_READONLY; + const Expr *IgnoreCasts() const { + return const_cast(this)->IgnoreCasts(); } - /// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return - /// its subexpression. If that subexpression is also a ParenExpr, - /// then this method recursively returns its subexpression, and so forth. - /// Otherwise, the method returns the current Expr. + /// Skip past any implicit AST nodes which might surround this expression + /// until reaching a fixed point. Skips: + /// * What IgnoreImpCasts() skips + /// * MaterializeTemporaryExpr + /// * CXXBindTemporaryExpr + Expr *IgnoreImplicit() LLVM_READONLY; + const Expr *IgnoreImplicit() const { + return const_cast(this)->IgnoreImplicit(); + } + + /// Skip past any parentheses which might surround this expression until + /// reaching a fixed point. Skips: + /// * ParenExpr + /// * UnaryOperator if `UO_Extension` + /// * GenericSelectionExpr if `!isResultDependent()` + /// * ChooseExpr if `!isConditionDependent()` + /// * ConstantExpr Expr *IgnoreParens() LLVM_READONLY; + const Expr *IgnoreParens() const { + return const_cast(this)->IgnoreParens(); + } - /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr - /// or CastExprs, returning their operand. - Expr *IgnoreParenCasts() LLVM_READONLY; - - /// Ignore casts. Strip off any CastExprs, returning their operand. - Expr *IgnoreCasts() LLVM_READONLY; - - /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off - /// any ParenExpr or ImplicitCastExprs, returning their operand. + /// Skip past any parentheses and implicit casts which might surround this + /// expression until reaching a fixed point. + /// FIXME: IgnoreParenImpCasts really ought to be equivalent to + /// IgnoreParens() + IgnoreImpCasts() until reaching a fixed point. However + /// this is currently not the case. Instead IgnoreParenImpCasts() skips: + /// * What IgnoreParens() skips + /// * ImplicitCastExpr + /// * MaterializeTemporaryExpr + /// * SubstNonTypeTemplateParmExpr Expr *IgnoreParenImpCasts() LLVM_READONLY; + const Expr *IgnoreParenImpCasts() const { + return const_cast(this)->IgnoreParenImpCasts(); + } - /// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a - /// call to a conversion operator, return the argument. - Expr *IgnoreConversionOperator() LLVM_READONLY; - - const Expr *IgnoreConversionOperator() const LLVM_READONLY { - return const_cast(this)->IgnoreConversionOperator(); + /// Skip past any parentheses and casts which might surround this expression + /// until reaching a fixed point. Skips: + /// * What IgnoreParens() skips + /// * What IgnoreCasts() skips + Expr *IgnoreParenCasts() LLVM_READONLY; + const Expr *IgnoreParenCasts() const { + return const_cast(this)->IgnoreParenCasts(); } - const Expr *IgnoreParenImpCasts() const LLVM_READONLY { - return const_cast(this)->IgnoreParenImpCasts(); + /// Skip conversion operators. If this Expr is a call to a conversion + /// operator, return the argument. + Expr *IgnoreConversionOperator() LLVM_READONLY; + const Expr *IgnoreConversionOperator() const { + return const_cast(this)->IgnoreConversionOperator(); } - /// Ignore parentheses and lvalue casts. Strip off any ParenExpr and - /// CastExprs that represent lvalue casts, returning their operand. + /// Skip past any parentheses and lvalue casts which might surround this + /// expression until reaching a fixed point. Skips: + /// * What IgnoreParens() skips + /// * What IgnoreCasts() skips, except that only lvalue-to-rvalue + /// casts are skipped + /// FIXME: 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 *IgnoreParenLValueCasts() LLVM_READONLY; - - const Expr *IgnoreParenLValueCasts() const LLVM_READONLY { - return const_cast(this)->IgnoreParenLValueCasts(); + const Expr *IgnoreParenLValueCasts() const { + return const_cast(this)->IgnoreParenLValueCasts(); } - /// 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 *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY; - - /// Ignore parentheses and derived-to-base casts. + /// Skip past any parenthese and casts which do not change the value + /// (including ptr->int casts of the same size) until reaching a fixed point. + /// Skips: + /// * What IgnoreParens() skips + /// * CastExpr which do not change the value + /// * SubstNonTypeTemplateParmExpr + Expr *IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY; + const Expr *IgnoreParenNoopCasts(const ASTContext &Ctx) const { + return const_cast(this)->IgnoreParenNoopCasts(Ctx); + } + + /// Skip past any parentheses and derived-to-base casts until reaching a + /// fixed point. Skips: + /// * What IgnoreParens() skips + /// * CastExpr which represent a derived-to-base cast (CK_DerivedToBase, + /// CK_UncheckedDerivedToBase and CK_NoOp) Expr *ignoreParenBaseCasts() LLVM_READONLY; - - const Expr *ignoreParenBaseCasts() const LLVM_READONLY { - return const_cast(this)->ignoreParenBaseCasts(); + const Expr *ignoreParenBaseCasts() const { + return const_cast(this)->ignoreParenBaseCasts(); } /// Determine whether this expression is a default function argument. @@ -825,24 +868,6 @@ /// Whether this expression is an implicit reference to 'this' in C++. bool isImplicitCXXThis() const; - const Expr *IgnoreImpCasts() const LLVM_READONLY { - return const_cast(this)->IgnoreImpCasts(); - } - const Expr *IgnoreParens() const LLVM_READONLY { - return const_cast(this)->IgnoreParens(); - } - const Expr *IgnoreParenCasts() const LLVM_READONLY { - return const_cast(this)->IgnoreParenCasts(); - } - /// Strip off casts, but keep parentheses. - const Expr *IgnoreCasts() const LLVM_READONLY { - return const_cast(this)->IgnoreCasts(); - } - - const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY { - return const_cast(this)->IgnoreParenNoopCasts(Ctx); - } - static bool hasAnyTypeDependentArguments(ArrayRef Exprs); /// For an expression of class type or pointer to class type, @@ -3167,18 +3192,6 @@ friend class CastExpr; }; -inline 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; - return e; -} - /// ExplicitCastExpr - An explicit cast written in the source /// code. /// Index: cfe/trunk/include/clang/AST/Stmt.h =================================================================== --- cfe/trunk/include/clang/AST/Stmt.h +++ cfe/trunk/include/clang/AST/Stmt.h @@ -1072,13 +1072,6 @@ /// works on systems with GraphViz (Mac OS X) or dot+gv installed. void viewAST() const; - /// Skip past any implicit AST nodes which might surround this - /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes. - Stmt *IgnoreImplicit(); - const Stmt *IgnoreImplicit() const { - return const_cast(this)->IgnoreImplicit(); - } - /// Skip no-op (attributed, compound) container stmts and skip captured /// stmt at the top, if \a IgnoreCaptured is true. Stmt *IgnoreContainers(bool IgnoreCaptured = false); Index: cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp =================================================================== --- cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp +++ cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp @@ -269,8 +269,8 @@ if (prevChildS != childE) { prevStmt = *prevChildS; - if (prevStmt) - prevStmt = prevStmt->IgnoreImplicit(); + if (auto *E = dyn_cast_or_null(prevStmt)) + prevStmt = E->IgnoreImplicit(); } if (currChildS == childE) @@ -280,8 +280,8 @@ return std::make_pair(prevStmt, nextStmt); nextStmt = *currChildS; - if (nextStmt) - nextStmt = nextStmt->IgnoreImplicit(); + if (auto *E = dyn_cast_or_null(nextStmt)) + nextStmt = E->IgnoreImplicit(); return std::make_pair(prevStmt, nextStmt); } Index: cfe/trunk/lib/ARCMigrate/TransformActions.cpp =================================================================== --- cfe/trunk/lib/ARCMigrate/TransformActions.cpp +++ cfe/trunk/lib/ARCMigrate/TransformActions.cpp @@ -313,7 +313,9 @@ assert(IsInTransaction && "Actions only allowed during a transaction"); ActionData data; data.Kind = Act_RemoveStmt; - data.S = S->IgnoreImplicit(); // important for uniquing + if (auto *E = dyn_cast(S)) + S = E->IgnoreImplicit(); // important for uniquing + data.S = S; CachedActions.push_back(data); } Index: cfe/trunk/lib/ARCMigrate/Transforms.cpp =================================================================== --- cfe/trunk/lib/ARCMigrate/Transforms.cpp +++ cfe/trunk/lib/ARCMigrate/Transforms.cpp @@ -286,10 +286,11 @@ void mark(Stmt *S) { if (!S) return; - while (LabelStmt *Label = dyn_cast(S)) + while (auto *Label = dyn_cast(S)) S = Label->getSubStmt(); - S = S->IgnoreImplicit(); - if (Expr *E = dyn_cast(S)) + if (auto *E = dyn_cast(S)) + S = E->IgnoreImplicit(); + if (auto *E = dyn_cast(S)) Removables.insert(E); } }; Index: cfe/trunk/lib/AST/Expr.cpp =================================================================== --- cfe/trunk/lib/AST/Expr.cpp +++ cfe/trunk/lib/AST/Expr.cpp @@ -2556,32 +2556,66 @@ return QualType(); } -Expr* Expr::IgnoreParens() { - Expr* E = this; +Expr *Expr::IgnoreImpCasts() { + Expr *E = this; while (true) { - if (ParenExpr* P = dyn_cast(E)) { - E = P->getSubExpr(); + if (auto *ICE = dyn_cast(E)) + E = ICE->getSubExpr(); + else if (auto *FE = dyn_cast(E)) + E = FE->getSubExpr(); + else + break; + } + return E; +} + +Expr *Expr::IgnoreImplicit() { + Expr *E = this; + 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(); + } + return E; +} + +Expr *Expr::IgnoreParens() { + Expr *E = this; + while (true) { + if (auto *PE = dyn_cast(E)) { + E = PE->getSubExpr(); continue; } - if (UnaryOperator* P = dyn_cast(E)) { - if (P->getOpcode() == UO_Extension) { - E = P->getSubExpr(); + if (auto *UO = dyn_cast(E)) { + if (UO->getOpcode() == UO_Extension) { + E = UO->getSubExpr(); continue; } } - if (GenericSelectionExpr* P = dyn_cast(E)) { - if (!P->isResultDependent()) { - E = P->getResultExpr(); + if (auto *GSE = dyn_cast(E)) { + if (!GSE->isResultDependent()) { + E = GSE->getResultExpr(); continue; } } - if (ChooseExpr* P = dyn_cast(E)) { - if (!P->isConditionDependent()) { - E = P->getChosenSubExpr(); + if (auto *CE = dyn_cast(E)) { + if (!CE->isConditionDependent()) { + E = CE->getChosenSubExpr(); continue; } } - if (ConstantExpr *CE = dyn_cast(E)) { + if (auto *CE = dyn_cast(E)) { E = CE->getSubExpr(); continue; } @@ -2595,21 +2629,19 @@ Expr *E = this; while (true) { E = E->IgnoreParens(); - if (CastExpr *P = dyn_cast(E)) { - E = P->getSubExpr(); + if (auto *CE = dyn_cast(E)) { + E = CE->getSubExpr(); continue; } - if (MaterializeTemporaryExpr *Materialize - = dyn_cast(E)) { - E = Materialize->GetTemporaryExpr(); + if (auto *MTE = dyn_cast(E)) { + E = MTE->GetTemporaryExpr(); continue; } - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast(E)) { + if (auto *NTTP = dyn_cast(E)) { E = NTTP->getReplacement(); continue; } - if (FullExpr *FE = dyn_cast(E)) { + if (auto *FE = dyn_cast(E)) { E = FE->getSubExpr(); continue; } @@ -2620,21 +2652,19 @@ Expr *Expr::IgnoreCasts() { Expr *E = this; while (true) { - if (CastExpr *P = dyn_cast(E)) { - E = P->getSubExpr(); + if (auto *CE = dyn_cast(E)) { + E = CE->getSubExpr(); continue; } - if (MaterializeTemporaryExpr *Materialize - = dyn_cast(E)) { - E = Materialize->GetTemporaryExpr(); + if (auto *MTE = dyn_cast(E)) { + E = MTE->GetTemporaryExpr(); continue; } - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast(E)) { + if (auto *NTTP = dyn_cast(E)) { E = NTTP->getReplacement(); continue; } - if (FullExpr *FE = dyn_cast(E)) { + if (auto *FE = dyn_cast(E)) { E = FE->getSubExpr(); continue; } @@ -2650,20 +2680,18 @@ Expr *E = this; while (true) { E = E->IgnoreParens(); - if (CastExpr *P = dyn_cast(E)) { - if (P->getCastKind() == CK_LValueToRValue) { - E = P->getSubExpr(); + if (auto *CE = dyn_cast(E)) { + if (CE->getCastKind() == CK_LValueToRValue) { + E = CE->getSubExpr(); continue; } - } else if (MaterializeTemporaryExpr *Materialize - = dyn_cast(E)) { - E = Materialize->GetTemporaryExpr(); + } else if (auto *MTE = dyn_cast(E)) { + E = MTE->GetTemporaryExpr(); continue; - } else if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast(E)) { + } else if (auto *NTTP = dyn_cast(E)) { E = NTTP->getReplacement(); continue; - } else if (FullExpr *FE = dyn_cast(E)) { + } else if (auto *FE = dyn_cast(E)) { E = FE->getSubExpr(); continue; } @@ -2676,7 +2704,7 @@ Expr *E = this; while (true) { E = E->IgnoreParens(); - if (CastExpr *CE = dyn_cast(E)) { + if (auto *CE = dyn_cast(E)) { if (CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_UncheckedDerivedToBase || CE->getCastKind() == CK_NoOp) { @@ -2693,17 +2721,15 @@ Expr *E = this; while (true) { E = E->IgnoreParens(); - if (ImplicitCastExpr *P = dyn_cast(E)) { - E = P->getSubExpr(); + if (auto *ICE = dyn_cast(E)) { + E = ICE->getSubExpr(); continue; } - if (MaterializeTemporaryExpr *Materialize - = dyn_cast(E)) { - E = Materialize->GetTemporaryExpr(); + if (auto *MTE = dyn_cast(E)) { + E = MTE->GetTemporaryExpr(); continue; } - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast(E)) { + if (auto *NTTP = dyn_cast(E)) { E = NTTP->getReplacement(); continue; } @@ -2712,7 +2738,7 @@ } Expr *Expr::IgnoreConversionOperator() { - if (CXXMemberCallExpr *MCE = dyn_cast(this)) { + if (auto *MCE = dyn_cast(this)) { if (MCE->getMethodDecl() && isa(MCE->getMethodDecl())) return MCE->getImplicitObjectArgument(); } @@ -2722,15 +2748,15 @@ /// 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(ASTContext &Ctx) { +Expr *Expr::IgnoreParenNoopCasts(const ASTContext &Ctx) { Expr *E = this; while (true) { E = E->IgnoreParens(); - if (CastExpr *P = dyn_cast(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 *SE = P->getSubExpr(); + Expr *SE = CE->getSubExpr(); if (Ctx.hasSameUnqualifiedType(E->getType(), SE->getType())) { E = SE; @@ -2747,8 +2773,7 @@ } } - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast(E)) { + if (auto *NTTP = dyn_cast(E)) { E = NTTP->getReplacement(); continue; } Index: cfe/trunk/lib/AST/Stmt.cpp =================================================================== --- cfe/trunk/lib/AST/Stmt.cpp +++ cfe/trunk/lib/AST/Stmt.cpp @@ -117,30 +117,6 @@ StatisticsEnabled = true; } -Stmt *Stmt::IgnoreImplicit() { - Stmt *s = this; - - Stmt *lasts = nullptr; - - while (s != lasts) { - lasts = s; - - if (auto *fe = dyn_cast(s)) - s = fe->getSubExpr(); - - if (auto *mte = dyn_cast(s)) - s = mte->GetTemporaryExpr(); - - if (auto *bte = dyn_cast(s)) - s = bte->getSubExpr(); - - if (auto *ice = dyn_cast(s)) - s = ice->getSubExpr(); - } - - return s; -} - /// Skip no-op (attributed, compound) container stmts and skip captured /// stmt at the top, if \a IgnoreCaptured is true. Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) { Index: cfe/trunk/lib/Analysis/ReachableCode.cpp =================================================================== --- cfe/trunk/lib/Analysis/ReachableCode.cpp +++ cfe/trunk/lib/Analysis/ReachableCode.cpp @@ -192,9 +192,10 @@ if (!S) return false; - S = S->IgnoreImplicit(); + if (const auto *Ex = dyn_cast(S)) + S = Ex->IgnoreImplicit(); - if (const Expr *Ex = dyn_cast(S)) + if (const auto *Ex = dyn_cast(S)) S = Ex->IgnoreCasts(); // Special case looking for the sigil '()' around an integer literal. Index: cfe/trunk/lib/Tooling/ASTDiff/ASTDiff.cpp =================================================================== --- cfe/trunk/lib/Tooling/ASTDiff/ASTDiff.cpp +++ cfe/trunk/lib/Tooling/ASTDiff/ASTDiff.cpp @@ -237,8 +237,8 @@ return true; } bool TraverseStmt(Stmt *S) { - if (S) - S = S->IgnoreImplicit(); + if (auto *E = dyn_cast_or_null(S)) + S = E->IgnoreImplicit(); if (isNodeExcluded(Tree.AST.getSourceManager(), S)) return true; auto SavedState = PreTraverse(S);