Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -21,6 +21,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/StmtVisitor.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -8038,10 +8039,8 @@ ObjCPropertyAccess); } -namespace { - /// Returns true if the given statement can be a body-like child of \p Parent. -bool isBodyLikeChildStmt(const Stmt *S, const Stmt *Parent) { +static bool isBodyLikeChildStmt(const Stmt *S, const Stmt *Parent) { switch (Parent->getStmtClass()) { case Stmt::IfStmtClass: return cast(Parent)->getThen() == S || @@ -8064,30 +8063,49 @@ } } -class StmtUSEFinder : public RecursiveASTVisitor { +namespace { + +class StmtUSEFinder : public ConstStmtVisitor { const Stmt *Target; public: - bool VisitStmt(Stmt *S) { return S != Target; } + bool VisitStmt(const Stmt *S) { + if (S == Target) + return true; + for (const Stmt *Child : S->children()) + if (Child && Visit(Child)) + return true; + return false; + } /// Returns true if the given statement is present in the given declaration. - static bool isContained(const Stmt *Target, const Decl *D) { + /// Typically statements are contained in variable initializers. + static bool isContained(const Stmt *Target, const VarDecl *VD) { StmtUSEFinder Visitor; Visitor.Target = Target; - return !Visitor.TraverseDecl(const_cast(D)); + if (const Expr *Init = VD->getInit()) + return Visitor.Visit(Init); + return false; } }; /// Traverses the AST and finds the last statement that used a given /// declaration. -class LastDeclUSEFinder : public RecursiveASTVisitor { +class LastDeclUSEFinder : public ConstStmtVisitor { const Decl *D; public: - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(const DeclRefExpr *DRE) { if (DRE->getDecl() == D) - return false; - return true; + return true; + return false; + } + + bool VisitStmt(const Stmt *S) { + for (const Stmt *Child : S->children()) + if (Child && Visit(Child)) + return true; + return false; } static const Stmt *findLastStmtThatUsesDecl(const Decl *D, @@ -8096,7 +8114,7 @@ Visitor.D = D; for (auto I = Scope->body_rbegin(), E = Scope->body_rend(); I != E; ++I) { const Stmt *S = *I; - if (!Visitor.TraverseStmt(const_cast(S))) + if (S && Visitor.Visit(S)) return S; } return nullptr; @@ -8272,9 +8290,12 @@ const Stmt *LastStmtOfUse = nullptr; if (isa(StmtOfUse) && Scope) { for (const Decl *D : cast(StmtOfUse)->decls()) { - if (StmtUSEFinder::isContained(StmtStack.back(), D)) { - LastStmtOfUse = LastDeclUSEFinder::findLastStmtThatUsesDecl(D, Scope); - break; + if (const auto *VD = dyn_cast(D)) { + if (StmtUSEFinder::isContained(StmtStack.back(), VD)) { + LastStmtOfUse = + LastDeclUSEFinder::findLastStmtThatUsesDecl(VD, Scope); + break; + } } } }