rnk created this revision. rnk added reviewers: arphaman, rsmith. RecursiveASTVisitor is very expensive to instantiate and results in needlessly slow compilation. For these availability check fixits, we don't need to instantiate the full complexity of the declaration walking machinery, we can use a plain StmtVisitor.
This change reduces time to compile SemaDeclAttr.cpp and saves object file size: | before | after time (s) | 1m7.821s | 0m52.459s obj (kb) | 13280 | 11364 So, 15s and 1.9 MB of object file. If clang had presubmits checks, I'd add a check that warned on new inclusions of RecursiveASTVisitor.h. =/ I won't promise that this doesn't change functionality, since RAV walks through quite a number of things that StmtVisitor doesn't, like blocks and lambdas. I noticed that SemaOpenMP has a very similar utility called LocalVarRefChecker, so there is definitely some opportunity for refactoring further after this. https://reviews.llvm.org/D57208 Files: clang/lib/Sema/SemaDeclAttr.cpp
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<IfStmt>(Parent)->getThen() == S || @@ -8064,30 +8063,49 @@ } } -class StmtUSEFinder : public RecursiveASTVisitor<StmtUSEFinder> { +namespace { + +class StmtUSEFinder : public ConstStmtVisitor<StmtUSEFinder, bool> { 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<Decl *>(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<LastDeclUSEFinder> { +class LastDeclUSEFinder : public ConstStmtVisitor<LastDeclUSEFinder, bool> { 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<Stmt *>(S))) + if (S && Visitor.Visit(S)) return S; } return nullptr; @@ -8272,9 +8290,12 @@ const Stmt *LastStmtOfUse = nullptr; if (isa<DeclStmt>(StmtOfUse) && Scope) { for (const Decl *D : cast<DeclStmt>(StmtOfUse)->decls()) { - if (StmtUSEFinder::isContained(StmtStack.back(), D)) { - LastStmtOfUse = LastDeclUSEFinder::findLastStmtThatUsesDecl(D, Scope); - break; + if (const auto *VD = dyn_cast<VarDecl>(D)) { + if (StmtUSEFinder::isContained(StmtStack.back(), VD)) { + LastStmtOfUse = + LastDeclUSEFinder::findLastStmtThatUsesDecl(VD, Scope); + break; + } } } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits