diff --git a/clang/docs/RAVFrontendAction.rst b/clang/docs/RAVFrontendAction.rst index 2e387b4b339d6..28a99d1744b7b 100644 --- a/clang/docs/RAVFrontendAction.rst +++ b/clang/docs/RAVFrontendAction.rst @@ -70,10 +70,9 @@ CXXRecordDecl's. :: - class FindNamedClassVisitor - : public RecursiveASTVisitor { + class FindNamedClassVisitor : public DynamicRecursiveASTVisitor { public: - bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) { + bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) override { // For debugging, dumping the AST nodes will show which nodes are already // being visited. Declaration->dump(); @@ -91,7 +90,7 @@ can check for a specific qualified name: :: - bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) { + bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) override { if (Declaration->getQualifiedNameAsString() == "n::m::C") Declaration->dump(); return true; @@ -122,7 +121,7 @@ locations: :: - bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) { + bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) override { if (Declaration->getQualifiedNameAsString() == "n::m::C") { // getFullLoc uses the ASTContext's SourceManager to resolve the source // location and break it up into its line and column parts. @@ -143,20 +142,20 @@ Now we can combine all of the above into a small example program: :: #include "clang/AST/ASTConsumer.h" - #include "clang/AST/RecursiveASTVisitor.h" + #include "clang/AST/DynamicRecursiveASTVisitor.h" + #include "clang/AST/DeclCXX.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Tooling/Tooling.h" using namespace clang; - class FindNamedClassVisitor - : public RecursiveASTVisitor { + class FindNamedClassVisitor final : public DynamicRecursiveASTVisitor { public: explicit FindNamedClassVisitor(ASTContext *Context) : Context(Context) {} - bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) { + bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) override { if (Declaration->getQualifiedNameAsString() == "n::m::C") { FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getBeginLoc()); if (FullLocation.isValid()) diff --git a/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp b/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp index 12d4c311586e6..036c54e593dab 100644 --- a/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp +++ b/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp @@ -25,7 +25,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Sema.h" @@ -41,13 +41,14 @@ bool isMarkedAsCallSuper(const CXXMethodDecl *D) { return MarkedMethods.contains(D); } -class MethodUsageVisitor : public RecursiveASTVisitor { +class MethodUsageVisitor final : public DynamicRecursiveASTVisitor { public: bool IsOverriddenUsed = false; explicit MethodUsageVisitor( llvm::SmallPtrSet &MustCalledMethods) : MustCalledMethods(MustCalledMethods) {} - bool VisitCallExpr(CallExpr *CallExpr) { + + bool VisitCallExpr(CallExpr *CallExpr) override { const CXXMethodDecl *Callee = nullptr; for (const auto &MustCalled : MustCalledMethods) { if (CallExpr->getCalleeDecl() == MustCalled) { @@ -67,7 +68,7 @@ class MethodUsageVisitor : public RecursiveASTVisitor { llvm::SmallPtrSet &MustCalledMethods; }; -class CallSuperVisitor : public RecursiveASTVisitor { +class CallSuperVisitor final : public DynamicRecursiveASTVisitor { public: CallSuperVisitor(DiagnosticsEngine &Diags) : Diags(Diags) { WarningSuperNotCalled = Diags.getCustomDiagID( @@ -77,7 +78,8 @@ class CallSuperVisitor : public RecursiveASTVisitor { NotePreviousCallSuperDeclaration = Diags.getCustomDiagID( DiagnosticsEngine::Note, "function marked 'call_super' here"); } - bool VisitCXXMethodDecl(CXXMethodDecl *MethodDecl) { + + bool VisitCXXMethodDecl(CXXMethodDecl *MethodDecl) override { if (MethodDecl->isThisDeclarationADefinition() && MethodDecl->hasBody()) { // First find out which overridden methods are marked as 'call_super' llvm::SmallPtrSet OverriddenMarkedMethods; diff --git a/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp b/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp index b2b785b87c25c..9f95bbd847f2a 100644 --- a/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp +++ b/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp @@ -11,11 +11,11 @@ // //===----------------------------------------------------------------------===// -#include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/AST/AST.h" #include "clang/AST/ASTConsumer.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Sema/Sema.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -52,11 +52,12 @@ class PrintFunctionsConsumer : public ASTConsumer { // The advantage of doing this in HandleTranslationUnit() is that all // codegen (when using -add-plugin) is completely finished and this can't // affect the compiler output. - struct Visitor : public RecursiveASTVisitor { + struct Visitor final : DynamicRecursiveASTVisitor { const std::set &ParsedTemplates; Visitor(const std::set &ParsedTemplates) : ParsedTemplates(ParsedTemplates) {} - bool VisitFunctionDecl(FunctionDecl *FD) { + + bool VisitFunctionDecl(FunctionDecl *FD) override { if (FD->isLateTemplateParsed() && ParsedTemplates.count(FD->getNameAsString())) LateParsedDecls.insert(FD); diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h new file mode 100644 index 0000000000000..1390977c09ea7 --- /dev/null +++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h @@ -0,0 +1,252 @@ +#ifndef LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H +#define LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H + +#include "clang/AST/Attr.h" +#include "clang/AST/ExprConcepts.h" +#include "clang/AST/TypeLoc.h" + +namespace clang { +class ASTContext; + +/// Recursive AST visitor that supports extension via dynamic dispatch. +/// +/// This only supports some of the more common visitation operations; in +/// particular, it does not support overriding WalkUpFromX or post-order +/// traversal. +/// +/// Features that are currently not supported: +/// +/// - Visiting attributes +/// - Post-order traversal +/// - Overriding WalkUpFromX +/// - Overriding getStmtChildren() +/// +/// \see RecursiveASTVisitor +class DynamicRecursiveASTVisitor { +public: + /// Whether this visitor should recurse into template instantiations. + bool ShouldVisitTemplateInstantiations = false; + + /// Whether this visitor should recurse into the types of TypeLocs. + bool ShouldWalkTypesOfTypeLocs = true; + + /// Whether this visitor should recurse into implicit code, e.g. + /// implicit constructors and destructors. + bool ShouldVisitImplicitCode = false; + + /// Whether this visitor should recurse into lambda body + bool ShouldVisitLambdaBody = true; + +protected: + DynamicRecursiveASTVisitor() = default; + +public: + virtual void anchor(); + + // Copying/moving a polymorphic type is a bad idea. + DynamicRecursiveASTVisitor(DynamicRecursiveASTVisitor &&) = delete; + DynamicRecursiveASTVisitor(const DynamicRecursiveASTVisitor &) = delete; + DynamicRecursiveASTVisitor &operator=(DynamicRecursiveASTVisitor &&) = delete; + DynamicRecursiveASTVisitor & + operator=(const DynamicRecursiveASTVisitor &) = delete; + virtual ~DynamicRecursiveASTVisitor() = default; + + /// Recursively visits an entire AST, starting from the TranslationUnitDecl. + /// \returns false if visitation was terminated early. + virtual bool TraverseAST(ASTContext &AST); + + /// Recursively visit an attribute, by dispatching to + /// Traverse*Attr() based on the argument's dynamic type. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is a Null type location). + virtual bool TraverseAttr(Attr *At); + + /// Recursively visit a constructor initializer. This + /// automatically dispatches to another visitor for the initializer + /// expression, but not for the name of the initializer, so may + /// be overridden for clients that need access to the name. + /// + /// \returns false if the visitation was terminated early, true otherwise. + virtual bool TraverseConstructorInitializer(CXXCtorInitializer *Init); + + /// Recursively visit a base specifier. This can be overridden by a + /// subclass. + /// + /// \returns false if the visitation was terminated early, true otherwise. + virtual bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base); + + /// Recursively visit a declaration, by dispatching to + /// Traverse*Decl() based on the argument's dynamic type. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is NULL). + virtual bool TraverseDecl(Decl *D); + + /// Recursively visit a name with its location information. + /// + /// \returns false if the visitation was terminated early, true otherwise. + virtual bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo); + + /// Recursively visit a lambda capture. \c Init is the expression that + /// will be used to initialize the capture. + /// + /// \returns false if the visitation was terminated early, true otherwise. + virtual bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, + Expr *Init); + + /// Recursively visit a C++ nested-name-specifier. + /// + /// \returns false if the visitation was terminated early, true otherwise. + virtual bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); + + /// Recursively visit a C++ nested-name-specifier with location + /// information. + /// + /// \returns false if the visitation was terminated early, true otherwise. + virtual bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); + + /// Recursively visit a statement or expression, by + /// dispatching to Traverse*() based on the argument's dynamic type. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is nullptr). + virtual bool TraverseStmt(Stmt *S); + + /// Recursively visit a template argument and dispatch to the + /// appropriate method for the argument type. + /// + /// \returns false if the visitation was terminated early, true otherwise. + // FIXME: migrate callers to TemplateArgumentLoc instead. + virtual bool TraverseTemplateArgument(const TemplateArgument &Arg); + + /// Recursively visit a template argument location and dispatch to the + /// appropriate method for the argument type. + /// + /// \returns false if the visitation was terminated early, true otherwise. + virtual bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc); + + /// Recursively visit a set of template arguments. + /// + /// \returns false if the visitation was terminated early, true otherwise. + // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead. + bool + TraverseTemplateArguments(ArrayRef Args); // NOT virtual + + /// Recursively visit a template name and dispatch to the + /// appropriate method. + /// + /// \returns false if the visitation was terminated early, true otherwise. + virtual bool TraverseTemplateName(TemplateName Template); + + /// Recursively visit a type, by dispatching to + /// Traverse*Type() based on the argument's getTypeClass() property. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is a Null type). + virtual bool TraverseType(QualType T); + + /// Recursively visit a type with location, by dispatching to + /// Traverse*TypeLoc() based on the argument type's getTypeClass() property. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is a Null type location). + virtual bool TraverseTypeLoc(TypeLoc TL); + + /// Recursively visit an Objective-C protocol reference with location + /// information. + /// + /// \returns false if the visitation was terminated early, true otherwise. + virtual bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc); + + /// Traverse a concept (requirement). + virtual bool TraverseTypeConstraint(const TypeConstraint *C); + virtual bool TraverseConceptRequirement(concepts::Requirement *R); + virtual bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R); + virtual bool TraverseConceptExprRequirement(concepts::ExprRequirement *R); + virtual bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R); + virtual bool TraverseConceptReference(ConceptReference *CR); + virtual bool VisitConceptReference(ConceptReference *CR) { return true; } + + /// Visit a node. + virtual bool VisitAttr(Attr *A) { return true; } + virtual bool VisitDecl(Decl *D) { return true; } + virtual bool VisitStmt(Stmt *S) { return true; } + virtual bool VisitType(Type *T) { return true; } + virtual bool VisitTypeLoc(TypeLoc TL) { return true; } + + /// Walk up from a node. + bool WalkUpFromDecl(Decl *D) { return VisitDecl(D); } + bool WalkUpFromStmt(Stmt *S) { return VisitStmt(S); } + bool WalkUpFromType(Type *T) { return VisitType(T); } + bool WalkUpFromTypeLoc(TypeLoc TL) { return VisitTypeLoc(TL); } + + /// Invoked before visiting a statement or expression via data recursion. + /// + /// \returns false to skip visiting the node, true otherwise. + virtual bool dataTraverseStmtPre(Stmt *S) { return true; } + + /// Invoked after visiting a statement or expression via data recursion. + /// This is not invoked if the previously invoked \c dataTraverseStmtPre + /// returned false. + /// + /// \returns false if the visitation was terminated early, true otherwise. + virtual bool dataTraverseStmtPost(Stmt *S) { return true; } + virtual bool dataTraverseNode(Stmt *S); + + /*// Declare Traverse*() and friends for attributes. +#define DYNAMIC_ATTR_VISITOR_DECLS +#include "clang/AST/AttrVisitor.inc" +#undef DYNAMIC_ATTR_VISITOR_DECLS*/ + + // Not virtual for now because no-one overrides them. +#define DEF_TRAVERSE_TMPL_INST(kind) \ + virtual bool TraverseTemplateInstantiations(kind##TemplateDecl *D); + DEF_TRAVERSE_TMPL_INST(Class) + DEF_TRAVERSE_TMPL_INST(Var) + DEF_TRAVERSE_TMPL_INST(Function) +#undef DEF_TRAVERSE_TMPL_INST + + // Declare Traverse*() for and friends all concrete Decl classes. +#define ABSTRACT_DECL(DECL) +#define DECL(CLASS, BASE) virtual bool Traverse##CLASS##Decl(CLASS##Decl *D); +#include "clang/AST/DeclNodes.inc" + +#define DECL(CLASS, BASE) \ + bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D); \ + virtual bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } +#include "clang/AST/DeclNodes.inc" + + // Declare Traverse*() and friends for all concrete Stmt classes. +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) virtual bool Traverse##CLASS(CLASS *S); +#include "clang/AST/StmtNodes.inc" + +#define STMT(CLASS, PARENT) \ + bool WalkUpFrom##CLASS(CLASS *S); \ + virtual bool Visit##CLASS(CLASS *S) { return true; } +#include "clang/AST/StmtNodes.inc" + + // Declare Traverse*() and friends for all concrete Type classes. +#define ABSTRACT_TYPE(CLASS, BASE) +#define TYPE(CLASS, BASE) virtual bool Traverse##CLASS##Type(CLASS##Type *T); +#include "clang/AST/TypeNodes.inc" + +#define TYPE(CLASS, BASE) \ + bool WalkUpFrom##CLASS##Type(CLASS##Type *T); \ + virtual bool Visit##CLASS##Type(CLASS##Type *T) { return true; } +#include "clang/AST/TypeNodes.inc" + +#define ABSTRACT_TYPELOC(CLASS, BASE) +#define TYPELOC(CLASS, BASE) \ + virtual bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); +#include "clang/AST/TypeLocNodes.def" + +#define TYPELOC(CLASS, BASE) \ + bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL); \ + virtual bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } +#include "clang/AST/TypeLocNodes.def" +}; +} // namespace clang + +#endif // LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 2b35997bd539a..8c0ed24c01149 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -327,11 +327,11 @@ template class RecursiveASTVisitor { bool VisitAttr(Attr *A) { return true; } // Declare Traverse* and empty Visit* for all Attr classes. -#define ATTR_VISITOR_DECLS_ONLY +#define ATTR_VISITOR_DECLS #include "clang/AST/AttrVisitor.inc" -#undef ATTR_VISITOR_DECLS_ONLY +#undef ATTR_VISITOR_DECLS -// ---- Methods on Stmts ---- + // ---- Methods on Stmts ---- Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } @@ -727,9 +727,11 @@ bool RecursiveASTVisitor::TraverseTypeLoc(TypeLoc TL) { } // Define the Traverse*Attr(Attr* A) methods +#define ATTR_VISITOR_IMPL #define VISITORCLASS RecursiveASTVisitor #include "clang/AST/AttrVisitor.inc" #undef VISITORCLASS +#undef ATTR_VISITOR_IMPL template bool RecursiveASTVisitor::TraverseDecl(Decl *D) { diff --git a/clang/include/clang/Analysis/CallGraph.h b/clang/include/clang/Analysis/CallGraph.h index 78f8d11555017..4266ebfd2f782 100644 --- a/clang/include/clang/Analysis/CallGraph.h +++ b/clang/include/clang/Analysis/CallGraph.h @@ -18,7 +18,8 @@ #define LLVM_CLANG_ANALYSIS_CALLGRAPH_H #include "clang/AST/Decl.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/STLExtras.h" @@ -39,7 +40,7 @@ class Stmt; /// The call graph extends itself with the given declarations by implementing /// the recursive AST visitor, which constructs the graph by visiting the given /// declarations. -class CallGraph : public RecursiveASTVisitor { +class CallGraph final : public DynamicRecursiveASTVisitor { friend class CallGraphNode; using FunctionMapTy = @@ -109,7 +110,7 @@ class CallGraph : public RecursiveASTVisitor { /// Part of recursive declaration visitation. We recursively visit all the /// declarations to collect the root functions. - bool VisitFunctionDecl(FunctionDecl *FD) { + bool VisitFunctionDecl(FunctionDecl *FD) override { // We skip function template definitions, as their semantics is // only determined when they are instantiated. if (includeInGraph(FD) && FD->isThisDeclarationADefinition()) { @@ -124,7 +125,7 @@ class CallGraph : public RecursiveASTVisitor { } /// Part of recursive declaration visitation. - bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { + bool VisitObjCMethodDecl(ObjCMethodDecl *MD) override { if (includeInGraph(MD)) { addNodesForBlocks(MD); addNodeForDecl(MD, true); @@ -133,11 +134,7 @@ class CallGraph : public RecursiveASTVisitor { } // We are only collecting the declarations, so do not step into the bodies. - bool TraverseStmt(Stmt *S) { return true; } - - bool shouldWalkTypesOfTypeLocs() const { return false; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return true; } + bool TraverseStmt(Stmt *S) override { return true; } private: /// Add the given declaration to the call graph. diff --git a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h index ec4d041254877..6294c810626a7 100644 --- a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h +++ b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h @@ -14,8 +14,9 @@ #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H #include "clang/AST/Decl.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/Type.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "llvm/ADT/DenseSet.h" @@ -88,14 +89,14 @@ class RecordInitListHelper { /// the function to analyze. Don't call `TraverseDecl()` on the function itself; /// this won't work as `TraverseDecl()` contains code to avoid traversing nested /// functions. -template -class AnalysisASTVisitor : public RecursiveASTVisitor { +class AnalysisASTVisitor : public DynamicRecursiveASTVisitor { public: - bool shouldVisitImplicitCode() { return true; } - - bool shouldVisitLambdaBody() const { return false; } + AnalysisASTVisitor() { + ShouldVisitImplicitCode = true; + ShouldVisitLambdaBody = false; + } - bool TraverseDecl(Decl *D) { + bool TraverseDecl(Decl *D) override { // Don't traverse nested record or function declarations. // - We won't be analyzing code contained in these anyway // - We don't model fields that are used only in these nested declaration, @@ -104,30 +105,30 @@ class AnalysisASTVisitor : public RecursiveASTVisitor { if (isa_and_nonnull(D) || isa_and_nonnull(D)) return true; - return RecursiveASTVisitor::TraverseDecl(D); + return DynamicRecursiveASTVisitor::TraverseDecl(D); } // Don't traverse expressions in unevaluated contexts, as we don't model // fields that are only used in these. // Note: The operand of the `noexcept` operator is an unevaluated operand, but // nevertheless it appears in the Clang CFG, so we don't exclude it here. - bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) { return true; } - bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) { return true; } - bool TraverseCXXTypeidExpr(CXXTypeidExpr *TIE) { + bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) override { return true; } + bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) override { return true; } + bool TraverseCXXTypeidExpr(CXXTypeidExpr *TIE) override { if (TIE->isPotentiallyEvaluated()) - return RecursiveASTVisitor::TraverseCXXTypeidExpr(TIE); + return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(TIE); return true; } - bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) { + bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) override { return true; } - bool TraverseBindingDecl(BindingDecl *BD) { + bool TraverseBindingDecl(BindingDecl *BD) override { // `RecursiveASTVisitor` doesn't traverse holding variables for // `BindingDecl`s by itself, so we need to tell it to. if (VarDecl *HoldingVar = BD->getHoldingVar()) TraverseDecl(HoldingVar); - return RecursiveASTVisitor::TraverseBindingDecl(BD); + return DynamicRecursiveASTVisitor::TraverseBindingDecl(BD); } }; diff --git a/clang/include/clang/InstallAPI/Visitor.h b/clang/include/clang/InstallAPI/Visitor.h index 3680ee566ca87..a04100b7b147b 100644 --- a/clang/include/clang/InstallAPI/Visitor.h +++ b/clang/include/clang/InstallAPI/Visitor.h @@ -13,8 +13,8 @@ #ifndef LLVM_CLANG_INSTALLAPI_VISITOR_H #define LLVM_CLANG_INSTALLAPI_VISITOR_H +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Mangle.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/TargetInfo.h" #include "clang/Frontend/FrontendActions.h" #include "clang/InstallAPI/Context.h" @@ -26,35 +26,37 @@ namespace installapi { /// ASTVisitor for collecting declarations that represent global symbols. class InstallAPIVisitor final : public ASTConsumer, - public RecursiveASTVisitor { + public DynamicRecursiveASTVisitor { public: InstallAPIVisitor(ASTContext &ASTCtx, InstallAPIContext &Ctx, SourceManager &SrcMgr, Preprocessor &PP) : Ctx(Ctx), SrcMgr(SrcMgr), PP(PP), MC(ItaniumMangleContext::create(ASTCtx, ASTCtx.getDiagnostics())), - Layout(ASTCtx.getTargetInfo().getDataLayoutString()) {} + Layout(ASTCtx.getTargetInfo().getDataLayoutString()) { + ShouldVisitTemplateInstantiations = true; + } + void HandleTranslationUnit(ASTContext &ASTCtx) override; - bool shouldVisitTemplateInstantiations() const { return true; } /// Collect global variables. - bool VisitVarDecl(const VarDecl *D); + bool VisitVarDecl(VarDecl *D) override; /// Collect global functions. - bool VisitFunctionDecl(const FunctionDecl *D); + bool VisitFunctionDecl(FunctionDecl *D) override; /// Collect Objective-C Interface declarations. /// Every Objective-C class has an interface declaration that lists all the /// ivars, properties, and methods of the class. - bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D); + bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) override; /// Collect Objective-C Category/Extension declarations. /// /// The class that is being extended might come from a different library and /// is therefore itself not collected. - bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D); + bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) override; /// Collect global c++ declarations. - bool VisitCXXRecordDecl(const CXXRecordDecl *D); + bool VisitCXXRecordDecl(CXXRecordDecl *D) override; private: std::string getMangledName(const NamedDecl *D) const; diff --git a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h index 015dbba26f688..09c58ee02fea1 100644 --- a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h +++ b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h @@ -24,27 +24,23 @@ namespace tooling { /// Traverses the AST and visits the occurrence of each named symbol in the /// given nodes. -template -class RecursiveSymbolVisitor - : public RecursiveASTVisitor> { - using BaseType = RecursiveASTVisitor>; - +class RecursiveSymbolVisitor : public DynamicRecursiveASTVisitor { public: RecursiveSymbolVisitor(const SourceManager &SM, const LangOptions &LangOpts) : SM(SM), LangOpts(LangOpts) {} - bool visitSymbolOccurrence(const NamedDecl *ND, - ArrayRef NameRanges) { + virtual bool visitSymbolOccurrence(const NamedDecl *ND, + ArrayRef NameRanges) { return true; } // Declaration visitors: - bool VisitNamedDecl(const NamedDecl *D) { + bool VisitNamedDecl(NamedDecl *D) override { return isa(D) ? true : visit(D, D->getLocation()); } - bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) { + bool VisitCXXConstructorDecl(CXXConstructorDecl *CD) override { for (const auto *Initializer : CD->inits()) { // Ignore implicit initializers. if (!Initializer->isWritten()) @@ -61,15 +57,15 @@ class RecursiveSymbolVisitor // Expression visitors: - bool VisitDeclRefExpr(const DeclRefExpr *Expr) { + bool VisitDeclRefExpr(DeclRefExpr *Expr) override { return visit(Expr->getFoundDecl(), Expr->getLocation()); } - bool VisitMemberExpr(const MemberExpr *Expr) { + bool VisitMemberExpr(MemberExpr *Expr) override { return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc()); } - bool VisitOffsetOfExpr(const OffsetOfExpr *S) { + bool VisitOffsetOfExpr(OffsetOfExpr *S) override { for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) { const OffsetOfNode &Component = S->getComponent(I); if (Component.getKind() == OffsetOfNode::Field) { @@ -83,7 +79,7 @@ class RecursiveSymbolVisitor // Other visitors: - bool VisitTypeLoc(const TypeLoc Loc) { + bool VisitTypeLoc(TypeLoc Loc) override { const SourceLocation TypeBeginLoc = Loc.getBeginLoc(); const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken(TypeBeginLoc, 0, SM, LangOpts); @@ -105,13 +101,13 @@ class RecursiveSymbolVisitor return true; } - bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { + bool VisitTypedefTypeLoc(TypedefTypeLoc TL) override { const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts); return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc); } - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override { // The base visitor will visit NNSL prefixes, so we should only look at // the current NNS. if (NNS) { @@ -119,10 +115,10 @@ class RecursiveSymbolVisitor if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc())) return false; } - return BaseType::TraverseNestedNameSpecifierLoc(NNS); + return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNS); } - bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) { + bool VisitDesignatedInitExpr(DesignatedInitExpr *E) override { for (const DesignatedInitExpr::Designator &D : E->designators()) { if (D.isFieldDesignator()) { if (const FieldDecl *Decl = D.getFieldDecl()) { @@ -140,8 +136,7 @@ class RecursiveSymbolVisitor bool visit(const NamedDecl *ND, SourceLocation BeginLoc, SourceLocation EndLoc) { - return static_cast(this)->visitSymbolOccurrence( - ND, SourceRange(BeginLoc, EndLoc)); + return visitSymbolOccurrence(ND, SourceRange(BeginLoc, EndLoc)); } bool visit(const NamedDecl *ND, SourceLocation Loc) { return visit(ND, Loc, Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts)); diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index c1bc7c762088f..2f1a11b8e3c41 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -309,67 +309,68 @@ namespace { return true; } -class ObjCMigrator : public RecursiveASTVisitor { - ObjCMigrateASTConsumer &Consumer; - ParentMap &PMap; - -public: - ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap) - : Consumer(consumer), PMap(PMap) { } - - bool shouldVisitTemplateInstantiations() const { return false; } - bool shouldWalkTypesOfTypeLocs() const { return false; } - - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { - if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) { - edit::Commit commit(*Consumer.Editor); - edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap); - Consumer.Editor->commit(commit); + class ObjCMigrator final : public DynamicRecursiveASTVisitor { + ObjCMigrateASTConsumer &Consumer; + ParentMap &PMap; + + public: + ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap) + : Consumer(consumer), PMap(PMap) { + ShouldVisitTemplateInstantiations = false; + ShouldWalkTypesOfTypeLocs = false; } - if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) { - edit::Commit commit(*Consumer.Editor); - edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit); - Consumer.Editor->commit(commit); - } + bool VisitObjCMessageExpr(ObjCMessageExpr *E) override { + if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) { + edit::Commit commit(*Consumer.Editor); + edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap); + Consumer.Editor->commit(commit); + } - if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_PropertyDotSyntax) { - edit::Commit commit(*Consumer.Editor); - rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj, - commit, &PMap); - Consumer.Editor->commit(commit); - } + if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) { + edit::Commit commit(*Consumer.Editor); + edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit); + Consumer.Editor->commit(commit); + } - return true; - } + if (Consumer.ASTMigrateActions & + FrontendOptions::ObjCMT_PropertyDotSyntax) { + edit::Commit commit(*Consumer.Editor); + rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj, commit, + &PMap); + Consumer.Editor->commit(commit); + } - bool TraverseObjCMessageExpr(ObjCMessageExpr *E) { - // Do depth first; we want to rewrite the subexpressions first so that if - // we have to move expressions we will move them already rewritten. - for (Stmt *SubStmt : E->children()) - if (!TraverseStmt(SubStmt)) - return false; + return true; + } - return WalkUpFromObjCMessageExpr(E); - } -}; + bool TraverseObjCMessageExpr(ObjCMessageExpr *E) override { + // Do depth first; we want to rewrite the subexpressions first so that if + // we have to move expressions we will move them already rewritten. + for (Stmt *SubStmt : E->children()) + if (!TraverseStmt(SubStmt)) + return false; -class BodyMigrator : public RecursiveASTVisitor { - ObjCMigrateASTConsumer &Consumer; - std::unique_ptr PMap; + return WalkUpFromObjCMessageExpr(E); + } + }; -public: - BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { } + class BodyMigrator final : public DynamicRecursiveASTVisitor { + ObjCMigrateASTConsumer &Consumer; + std::unique_ptr PMap; - bool shouldVisitTemplateInstantiations() const { return false; } - bool shouldWalkTypesOfTypeLocs() const { return false; } + public: + BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { + ShouldVisitTemplateInstantiations = false; + ShouldWalkTypesOfTypeLocs = false; + } - bool TraverseStmt(Stmt *S) { - PMap.reset(new ParentMap(S)); - ObjCMigrator(Consumer, *PMap).TraverseStmt(S); - return true; - } -}; + bool TraverseStmt(Stmt *S) override { + PMap.reset(new ParentMap(S)); + ObjCMigrator(Consumer, *PMap).TraverseStmt(S); + return true; + } + }; } // end anonymous namespace void ObjCMigrateASTConsumer::migrateDecl(Decl *D) { @@ -1672,12 +1673,14 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation( } namespace { -class SuperInitChecker : public RecursiveASTVisitor { +class SuperInitChecker final : public DynamicRecursiveASTVisitor { public: - bool shouldVisitTemplateInstantiations() const { return false; } - bool shouldWalkTypesOfTypeLocs() const { return false; } + SuperInitChecker() { + ShouldVisitTemplateInstantiations = false; + ShouldWalkTypesOfTypeLocs = false; + } - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + bool VisitObjCMessageExpr(ObjCMessageExpr *E) override { if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) { if (E->getMethodFamily() == OMF_init) return false; diff --git a/clang/lib/ARCMigrate/TransAPIUses.cpp b/clang/lib/ARCMigrate/TransAPIUses.cpp index 8f5d4f4bde06c..1ec65d730a81e 100644 --- a/clang/lib/ARCMigrate/TransAPIUses.cpp +++ b/clang/lib/ARCMigrate/TransAPIUses.cpp @@ -27,7 +27,7 @@ using namespace trans; namespace { -class APIChecker : public RecursiveASTVisitor { +class APIChecker final : public DynamicRecursiveASTVisitor { MigrationPass &Pass; Selector getReturnValueSel, setReturnValueSel; @@ -51,7 +51,7 @@ class APIChecker : public RecursiveASTVisitor { zoneSel = sels.getNullarySelector(&ids.get("zone")); } - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + bool VisitObjCMessageExpr(ObjCMessageExpr *E) override { // NSInvocation. if (E->isInstanceMessage() && E->getReceiverInterface() && diff --git a/clang/lib/ARCMigrate/TransARCAssign.cpp b/clang/lib/ARCMigrate/TransARCAssign.cpp index d1d5b9e014b17..8d93b10414ce6 100644 --- a/clang/lib/ARCMigrate/TransARCAssign.cpp +++ b/clang/lib/ARCMigrate/TransARCAssign.cpp @@ -31,14 +31,14 @@ using namespace trans; namespace { -class ARCAssignChecker : public RecursiveASTVisitor { +class ARCAssignChecker final : public DynamicRecursiveASTVisitor { MigrationPass &Pass; llvm::DenseSet ModifiedVars; public: ARCAssignChecker(MigrationPass &pass) : Pass(pass) { } - bool VisitBinaryOperator(BinaryOperator *Exp) { + bool VisitBinaryOperator(BinaryOperator *Exp) override { if (Exp->getType()->isDependentType()) return true; diff --git a/clang/lib/ARCMigrate/TransAutoreleasePool.cpp b/clang/lib/ARCMigrate/TransAutoreleasePool.cpp index 6d501228e712b..6a00bb1cbc5ed 100644 --- a/clang/lib/ARCMigrate/TransAutoreleasePool.cpp +++ b/clang/lib/ARCMigrate/TransAutoreleasePool.cpp @@ -39,7 +39,7 @@ using namespace trans; namespace { -class ReleaseCollector : public RecursiveASTVisitor { +class ReleaseCollector final : public DynamicRecursiveASTVisitor { Decl *Dcl; SmallVectorImpl &Releases; @@ -47,7 +47,7 @@ class ReleaseCollector : public RecursiveASTVisitor { ReleaseCollector(Decl *D, SmallVectorImpl &releases) : Dcl(D), Releases(releases) { } - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + bool VisitObjCMessageExpr(ObjCMessageExpr *E) override { if (!E->isInstanceMessage()) return true; if (E->getMethodFamily() != OMF_release) @@ -60,7 +60,6 @@ class ReleaseCollector : public RecursiveASTVisitor { return true; } }; - } namespace { @@ -245,7 +244,7 @@ class AutoreleasePoolRewriter } }; - class NameReferenceChecker : public RecursiveASTVisitor{ + class NameReferenceChecker final : public DynamicRecursiveASTVisitor { ASTContext &Ctx; SourceRange ScopeRange; SourceLocation &referenceLoc, &declarationLoc; @@ -260,15 +259,15 @@ class AutoreleasePoolRewriter (*scope.End)->getBeginLoc()); } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { return checkRef(E->getLocation(), E->getDecl()->getLocation()); } - bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { + bool VisitTypedefTypeLoc(TypedefTypeLoc TL) override { return checkRef(TL.getBeginLoc(), TL.getTypedefNameDecl()->getLocation()); } - bool VisitTagTypeLoc(TagTypeLoc TL) { + bool VisitTagTypeLoc(TagTypeLoc TL) override { return checkRef(TL.getBeginLoc(), TL.getDecl()->getLocation()); } diff --git a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp index 1e4db33135b6a..2d3cec91b96aa 100644 --- a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp +++ b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp @@ -36,18 +36,16 @@ using namespace trans; namespace { -class RootBlockObjCVarRewriter : - public RecursiveASTVisitor { +class RootBlockObjCVarRewriter final : public DynamicRecursiveASTVisitor { llvm::DenseSet &VarsToChange; - class BlockVarChecker : public RecursiveASTVisitor { + class BlockVarChecker final : public DynamicRecursiveASTVisitor { VarDecl *Var; - typedef RecursiveASTVisitor base; public: BlockVarChecker(VarDecl *var) : Var(var) { } - bool TraverseImplicitCastExpr(ImplicitCastExpr *castE) { + bool TraverseImplicitCastExpr(ImplicitCastExpr *castE) override { if (DeclRefExpr * ref = dyn_cast(castE->getSubExpr())) { if (ref->getDecl() == Var) { @@ -59,10 +57,10 @@ class RootBlockObjCVarRewriter : } } - return base::TraverseImplicitCastExpr(castE); + return DynamicRecursiveASTVisitor::TraverseImplicitCastExpr(castE); } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { if (E->getDecl() == Var) return false; // The reference of the variable, and not just its value, // is needed. @@ -74,7 +72,7 @@ class RootBlockObjCVarRewriter : RootBlockObjCVarRewriter(llvm::DenseSet &VarsToChange) : VarsToChange(VarsToChange) { } - bool VisitBlockDecl(BlockDecl *block) { + bool VisitBlockDecl(BlockDecl *block) override { SmallVector BlockVars; for (const auto &I : block->captures()) { @@ -108,14 +106,14 @@ class RootBlockObjCVarRewriter : } }; -class BlockObjCVarRewriter : public RecursiveASTVisitor { +class BlockObjCVarRewriter final : public DynamicRecursiveASTVisitor { llvm::DenseSet &VarsToChange; public: BlockObjCVarRewriter(llvm::DenseSet &VarsToChange) : VarsToChange(VarsToChange) { } - bool TraverseBlockDecl(BlockDecl *block) { + bool TraverseBlockDecl(BlockDecl *block) override { RootBlockObjCVarRewriter(VarsToChange).TraverseDecl(block); return true; } diff --git a/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp index e9c21b8106d7d..a63e1750b95da 100644 --- a/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp +++ b/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp @@ -143,14 +143,13 @@ class EmptyChecker : public StmtVisitor { } }; -class EmptyStatementsRemover : - public RecursiveASTVisitor { +class EmptyStatementsRemover final : public DynamicRecursiveASTVisitor { MigrationPass &Pass; public: EmptyStatementsRemover(MigrationPass &pass) : Pass(pass) { } - bool TraverseStmtExpr(StmtExpr *E) { + bool TraverseStmtExpr(StmtExpr *E) override { CompoundStmt *S = E->getSubStmt(); for (CompoundStmt::body_iterator I = S->body_begin(), E = S->body_end(); I != E; ++I) { @@ -161,7 +160,7 @@ class EmptyStatementsRemover : return true; } - bool VisitCompoundStmt(CompoundStmt *S) { + bool VisitCompoundStmt(CompoundStmt *S) override { for (auto *I : S->body()) check(I); return true; diff --git a/clang/lib/ARCMigrate/TransGCAttrs.cpp b/clang/lib/ARCMigrate/TransGCAttrs.cpp index 85e3fe77660b5..bcf874c0fd56d 100644 --- a/clang/lib/ARCMigrate/TransGCAttrs.cpp +++ b/clang/lib/ARCMigrate/TransGCAttrs.cpp @@ -23,26 +23,24 @@ using namespace trans; namespace { /// Collects all the places where GC attributes __strong/__weak occur. -class GCAttrsCollector : public RecursiveASTVisitor { +class GCAttrsCollector final : public DynamicRecursiveASTVisitor { MigrationContext &MigrateCtx; bool FullyMigratable; std::vector &AllProps; - typedef RecursiveASTVisitor base; public: GCAttrsCollector(MigrationContext &ctx, std::vector &AllProps) - : MigrateCtx(ctx), FullyMigratable(false), - AllProps(AllProps) { } - - bool shouldWalkTypesOfTypeLocs() const { return false; } + : MigrateCtx(ctx), FullyMigratable(false), AllProps(AllProps) { + ShouldWalkTypesOfTypeLocs = false; + } - bool VisitAttributedTypeLoc(AttributedTypeLoc TL) { + bool VisitAttributedTypeLoc(AttributedTypeLoc TL) override { handleAttr(TL); return true; } - bool TraverseDecl(Decl *D) { + bool TraverseDecl(Decl *D) override { if (!D || D->isImplicit()) return true; @@ -54,7 +52,7 @@ class GCAttrsCollector : public RecursiveASTVisitor { } else if (DeclaratorDecl *DD = dyn_cast(D)) { lookForAttribute(DD, DD->getTypeSourceInfo()); } - return base::TraverseDecl(D); + return DynamicRecursiveASTVisitor::TraverseDecl(D); } void lookForAttribute(Decl *D, TypeSourceInfo *TInfo) { diff --git a/clang/lib/ARCMigrate/TransGCCalls.cpp b/clang/lib/ARCMigrate/TransGCCalls.cpp index 43233e2d0b456..de758f33fdcd6 100644 --- a/clang/lib/ARCMigrate/TransGCCalls.cpp +++ b/clang/lib/ARCMigrate/TransGCCalls.cpp @@ -17,8 +17,7 @@ using namespace trans; namespace { -class GCCollectableCallsChecker : - public RecursiveASTVisitor { +class GCCollectableCallsChecker final : public DynamicRecursiveASTVisitor { MigrationContext &MigrateCtx; IdentifierInfo *NSMakeCollectableII; IdentifierInfo *CFMakeCollectableII; @@ -29,11 +28,10 @@ class GCCollectableCallsChecker : IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents; NSMakeCollectableII = &Ids.get("NSMakeCollectable"); CFMakeCollectableII = &Ids.get("CFMakeCollectable"); + ShouldWalkTypesOfTypeLocs = false; } - bool shouldWalkTypesOfTypeLocs() const { return false; } - - bool VisitCallExpr(CallExpr *E) { + bool VisitCallExpr(CallExpr *E) override { TransformActions &TA = MigrateCtx.Pass.TA; if (MigrateCtx.isGCOwnedNonObjC(E->getType())) { diff --git a/clang/lib/ARCMigrate/TransProtectedScope.cpp b/clang/lib/ARCMigrate/TransProtectedScope.cpp index 154e0b54800f9..ef526f7edcaa9 100644 --- a/clang/lib/ARCMigrate/TransProtectedScope.cpp +++ b/clang/lib/ARCMigrate/TransProtectedScope.cpp @@ -23,14 +23,14 @@ using namespace trans; namespace { -class LocalRefsCollector : public RecursiveASTVisitor { +class LocalRefsCollector final : public DynamicRecursiveASTVisitor { SmallVectorImpl &Refs; public: LocalRefsCollector(SmallVectorImpl &refs) : Refs(refs) { } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { if (ValueDecl *D = E->getDecl()) if (D->getDeclContext()->getRedeclContext()->isFunctionOrMethod()) Refs.push_back(E); @@ -52,7 +52,7 @@ struct CaseInfo { : SC(S), Range(Range), State(St_Unchecked) {} }; -class CaseCollector : public RecursiveASTVisitor { +class CaseCollector final : public DynamicRecursiveASTVisitor { ParentMap &PMap; SmallVectorImpl &Cases; @@ -60,7 +60,7 @@ class CaseCollector : public RecursiveASTVisitor { CaseCollector(ParentMap &PMap, SmallVectorImpl &Cases) : PMap(PMap), Cases(Cases) { } - bool VisitSwitchStmt(SwitchStmt *S) { + bool VisitSwitchStmt(SwitchStmt *S) override { SwitchCase *Curr = S->getSwitchCaseList(); if (!Curr) return true; diff --git a/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp index 81e67628fb1f4..a606a52b82661 100644 --- a/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp +++ b/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp @@ -22,10 +22,7 @@ using namespace trans; namespace { -class ZeroOutInDeallocRemover : - public RecursiveASTVisitor { - typedef RecursiveASTVisitor base; - +class ZeroOutInDeallocRemover final : public DynamicRecursiveASTVisitor { MigrationPass &Pass; llvm::DenseMap SynthesizedProperties; @@ -39,7 +36,7 @@ class ZeroOutInDeallocRemover : Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize")); } - bool VisitObjCMessageExpr(ObjCMessageExpr *ME) { + bool VisitObjCMessageExpr(ObjCMessageExpr *ME) override { ASTContext &Ctx = Pass.Ctx; TransformActions &TA = Pass.TA; @@ -78,7 +75,7 @@ class ZeroOutInDeallocRemover : return true; } - bool VisitPseudoObjectExpr(PseudoObjectExpr *POE) { + bool VisitPseudoObjectExpr(PseudoObjectExpr *POE) override { if (isZeroingPropIvar(POE) && isRemovable(POE)) { Transaction Trans(Pass.TA); Pass.TA.removeStmt(POE); @@ -87,7 +84,7 @@ class ZeroOutInDeallocRemover : return true; } - bool VisitBinaryOperator(BinaryOperator *BOE) { + bool VisitBinaryOperator(BinaryOperator *BOE) override { if (isZeroingPropIvar(BOE) && isRemovable(BOE)) { Transaction Trans(Pass.TA); Pass.TA.removeStmt(BOE); @@ -96,7 +93,7 @@ class ZeroOutInDeallocRemover : return true; } - bool TraverseObjCMethodDecl(ObjCMethodDecl *D) { + bool TraverseObjCMethodDecl(ObjCMethodDecl *D) override { if (D->getMethodFamily() != OMF_dealloc && !(D->isInstanceMethod() && D->getSelector() == FinalizeSel)) return true; @@ -128,7 +125,7 @@ class ZeroOutInDeallocRemover : } // Now, remove all zeroing of ivars etc. - base::TraverseObjCMethodDecl(D); + DynamicRecursiveASTVisitor::TraverseObjCMethodDecl(D); // clear out for next method. SynthesizedProperties.clear(); @@ -137,9 +134,9 @@ class ZeroOutInDeallocRemover : return true; } - bool TraverseFunctionDecl(FunctionDecl *D) { return true; } - bool TraverseBlockDecl(BlockDecl *block) { return true; } - bool TraverseBlockExpr(BlockExpr *block) { return true; } + bool TraverseFunctionDecl(FunctionDecl *D) override { return true; } + bool TraverseBlockDecl(BlockDecl *block) override { return true; } + bool TraverseBlockExpr(BlockExpr *block) override { return true; } private: bool isRemovable(Expr *E) const { diff --git a/clang/lib/ARCMigrate/Transforms.cpp b/clang/lib/ARCMigrate/Transforms.cpp index fda0e1c932fc0..ca24b512b4d9e 100644 --- a/clang/lib/ARCMigrate/Transforms.cpp +++ b/clang/lib/ARCMigrate/Transforms.cpp @@ -10,7 +10,6 @@ #include "Internals.h" #include "clang/ARCMigrate/ARCMT.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Analysis/DomainSpecific/CocoaConventions.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -211,14 +210,17 @@ StringRef trans::getNilString(MigrationPass &Pass) { namespace { -class ReferenceClear : public RecursiveASTVisitor { +class ReferenceClear final : public DynamicRecursiveASTVisitor { ExprSet &Refs; public: ReferenceClear(ExprSet &refs) : Refs(refs) { } - bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; } + bool VisitDeclRefExpr(DeclRefExpr *E) override { + Refs.erase(E); + return true; + } }; -class ReferenceCollector : public RecursiveASTVisitor { +class ReferenceCollector final : public DynamicRecursiveASTVisitor { ValueDecl *Dcl; ExprSet &Refs; @@ -226,23 +228,22 @@ class ReferenceCollector : public RecursiveASTVisitor { ReferenceCollector(ValueDecl *D, ExprSet &refs) : Dcl(D), Refs(refs) { } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { if (E->getDecl() == Dcl) Refs.insert(E); return true; } }; -class RemovablesCollector : public RecursiveASTVisitor { +class RemovablesCollector final : public DynamicRecursiveASTVisitor { ExprSet &Removables; public: - RemovablesCollector(ExprSet &removables) - : Removables(removables) { } - - bool shouldWalkTypesOfTypeLocs() const { return false; } + RemovablesCollector(ExprSet &removables) : Removables(removables) { + ShouldWalkTypesOfTypeLocs = false; + } - bool TraverseStmtExpr(StmtExpr *E) { + bool TraverseStmtExpr(StmtExpr *E) override { CompoundStmt *S = E->getSubStmt(); for (CompoundStmt::body_iterator I = S->body_begin(), E = S->body_end(); I != E; ++I) { @@ -253,29 +254,29 @@ class RemovablesCollector : public RecursiveASTVisitor { return true; } - bool VisitCompoundStmt(CompoundStmt *S) { + bool VisitCompoundStmt(CompoundStmt *S) override { for (auto *I : S->body()) mark(I); return true; } - bool VisitIfStmt(IfStmt *S) { + bool VisitIfStmt(IfStmt *S) override { mark(S->getThen()); mark(S->getElse()); return true; } - bool VisitWhileStmt(WhileStmt *S) { + bool VisitWhileStmt(WhileStmt *S) override { mark(S->getBody()); return true; } - bool VisitDoStmt(DoStmt *S) { + bool VisitDoStmt(DoStmt *S) override { mark(S->getBody()); return true; } - bool VisitForStmt(ForStmt *S) { + bool VisitForStmt(ForStmt *S) override { mark(S->getInit()); mark(S->getInc()); mark(S->getBody()); @@ -315,26 +316,25 @@ void trans::collectRemovables(Stmt *S, ExprSet &exprs) { namespace { -class ASTTransform : public RecursiveASTVisitor { +class ASTTransform final : public DynamicRecursiveASTVisitor { MigrationContext &MigrateCtx; - typedef RecursiveASTVisitor base; public: - ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { } - - bool shouldWalkTypesOfTypeLocs() const { return false; } + ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { + ShouldWalkTypesOfTypeLocs = false; + } - bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) { + bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) override { ObjCImplementationContext ImplCtx(MigrateCtx, D); for (MigrationContext::traverser_iterator I = MigrateCtx.traversers_begin(), E = MigrateCtx.traversers_end(); I != E; ++I) (*I)->traverseObjCImplementation(ImplCtx); - return base::TraverseObjCImplementationDecl(D); + return DynamicRecursiveASTVisitor::TraverseObjCImplementationDecl(D); } - bool TraverseStmt(Stmt *rootS) { + bool TraverseStmt(Stmt *rootS) override { if (!rootS) return true; @@ -347,7 +347,6 @@ class ASTTransform : public RecursiveASTVisitor { return true; } }; - } MigrationContext::~MigrationContext() { diff --git a/clang/lib/ARCMigrate/Transforms.h b/clang/lib/ARCMigrate/Transforms.h index 37e2d6b2a7e12..07de28e3b3e3d 100644 --- a/clang/lib/ARCMigrate/Transforms.h +++ b/clang/lib/ARCMigrate/Transforms.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H #define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ParentMap.h" #include "clang/AST/RecursiveASTVisitor.h" #include "llvm/ADT/DenseSet.h" diff --git a/clang/lib/AST/ASTImporterLookupTable.cpp b/clang/lib/AST/ASTImporterLookupTable.cpp index 07d39dcee2583..37807de07e759 100644 --- a/clang/lib/AST/ASTImporterLookupTable.cpp +++ b/clang/lib/AST/ASTImporterLookupTable.cpp @@ -13,18 +13,22 @@ #include "clang/AST/ASTImporterLookupTable.h" #include "clang/AST/Decl.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "llvm/Support/FormatVariadic.h" namespace clang { namespace { -struct Builder : RecursiveASTVisitor { +struct Builder final : DynamicRecursiveASTVisitor { ASTImporterLookupTable < - Builder(ASTImporterLookupTable <) : LT(LT) {} + Builder(ASTImporterLookupTable <) : LT(LT) { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = true; + } - bool VisitTypedefNameDecl(TypedefNameDecl *D) { + bool VisitTypedefNameDecl(TypedefNameDecl *D) override { QualType Ty = D->getUnderlyingType(); Ty = Ty.getCanonicalType(); if (const auto *RTy = dyn_cast(Ty)) { @@ -37,7 +41,7 @@ struct Builder : RecursiveASTVisitor { return true; } - bool VisitNamedDecl(NamedDecl *D) { + bool VisitNamedDecl(NamedDecl *D) override { LT.add(D); return true; } @@ -46,7 +50,7 @@ struct Builder : RecursiveASTVisitor { // visitation. However, there are cases when the befriended class is not a // child, thus it must be fetched explicitly from the FriendDecl, and only // then can we add it to the lookup table. - bool VisitFriendDecl(FriendDecl *D) { + bool VisitFriendDecl(FriendDecl *D) override { if (D->getFriendType()) { QualType Ty = D->getFriendType()->getType(); if (isa(Ty)) @@ -76,10 +80,6 @@ struct Builder : RecursiveASTVisitor { } return true; } - - // Override default settings of base. - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return true; } }; } // anonymous namespace diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 041252b6830e0..fdc94485f0a93 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -53,6 +53,7 @@ add_clang_library(clangAST DeclOpenMP.cpp DeclPrinter.cpp DeclTemplate.cpp + DynamicRecursiveASTVisitor.cpp ParentMapContext.cpp Expr.cpp ExprClassification.cpp diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp new file mode 100644 index 0000000000000..b5dc7915413cb --- /dev/null +++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp @@ -0,0 +1,386 @@ +//=== DynamicRecursiveASTVisitor.cpp - Dynamic AST Visitor Implementation -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements an AST visitor that does not require any template +// instantiation to allow users to override its behaviour. +// +//===----------------------------------------------------------------------===// +#include "clang/AST/DynamicRecursiveASTVisitor.h" +#include "clang/AST/RecursiveASTVisitor.h" + +using namespace clang; + +namespace { +struct Impl : RecursiveASTVisitor { + DynamicRecursiveASTVisitor &Visitor; + Impl(DynamicRecursiveASTVisitor &Visitor) : Visitor(Visitor) {} + + bool shouldVisitTemplateInstantiations() const { + return Visitor.ShouldVisitTemplateInstantiations; + } + + bool shouldWalkTypesOfTypeLocs() const { + return Visitor.ShouldWalkTypesOfTypeLocs; + } + + bool shouldVisitImplicitCode() const { + return Visitor.ShouldVisitImplicitCode; + } + + bool shouldVisitLambdaBody() const { return Visitor.ShouldVisitLambdaBody; } + + bool shouldTraversePostOrder() const { return false; } + + bool TraverseAST(ASTContext &AST) { return Visitor.TraverseAST(AST); } + bool TraverseAttr(Attr *At) { return Visitor.TraverseAttr(At); } + bool TraverseDecl(Decl *D) { return Visitor.TraverseDecl(D); } + bool TraverseType(QualType T) { return Visitor.TraverseType(T); } + bool TraverseTypeLoc(TypeLoc TL) { return Visitor.TraverseTypeLoc(TL); } + bool TraverseStmt(Stmt *S) { return Visitor.TraverseStmt(S); } + + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { + return Visitor.TraverseConstructorInitializer(Init); + } + + bool TraverseTemplateArgument(const TemplateArgument &Arg) { + return Visitor.TraverseTemplateArgument(Arg); + } + + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { + return Visitor.TraverseTemplateArgumentLoc(ArgLoc); + } + + bool TraverseTemplateName(TemplateName Template) { + return Visitor.TraverseTemplateName(Template); + } + + bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc) { + return Visitor.TraverseObjCProtocolLoc(ProtocolLoc); + } + + bool TraverseTypeConstraint(const TypeConstraint *C) { + return Visitor.TraverseTypeConstraint(C); + } + bool TraverseConceptRequirement(concepts::Requirement *R) { + return Visitor.TraverseConceptRequirement(R); + } + bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R) { + return Visitor.TraverseConceptTypeRequirement(R); + } + bool TraverseConceptExprRequirement(concepts::ExprRequirement *R) { + return Visitor.TraverseConceptExprRequirement(R); + } + bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R) { + return Visitor.TraverseConceptNestedRequirement(R); + } + + bool TraverseConceptReference(ConceptReference *CR) { + return Visitor.TraverseConceptReference(CR); + } + + bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) { + return Visitor.TraverseCXXBaseSpecifier(Base); + } + + bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo) { + return Visitor.TraverseDeclarationNameInfo(NameInfo); + } + + bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, + Expr *Init) { + return Visitor.TraverseLambdaCapture(LE, C, Init); + } + + bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { + return Visitor.TraverseNestedNameSpecifier(NNS); + } + + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + return Visitor.TraverseNestedNameSpecifierLoc(NNS); + } + + bool VisitConceptReference(ConceptReference *CR) { + return Visitor.VisitConceptReference(CR); + } + + bool dataTraverseStmtPre(Stmt *S) { return Visitor.dataTraverseStmtPre(S); } + bool dataTraverseStmtPost(Stmt *S) { return Visitor.dataTraverseStmtPost(S); } + + // TraverseStmt() always passes in a queue, so we have no choice but to + // accept it as a parameter here. + bool dataTraverseNode(Stmt *S, DataRecursionQueue * = nullptr) { + // But since don't support postorder traversal, we don't need it, so + // simply discard it here. This way, derived classes don't need to worry + // about including it as a parameter that they never use. + return Visitor.dataTraverseNode(S); + } + + /// Visit a node. + bool VisitAttr(Attr *A) { return Visitor.VisitAttr(A); } + bool VisitDecl(Decl *D) { return Visitor.VisitDecl(D); } + bool VisitStmt(Stmt *S) { return Visitor.VisitStmt(S); } + bool VisitType(Type *T) { return Visitor.VisitType(T); } + bool VisitTypeLoc(TypeLoc TL) { return Visitor.VisitTypeLoc(TL); } + + /*#define ATTR_VISITOR_DECLS + #include "clang/AST/AttrVisitor.inc" + #undef ATTR_VISITOR_DECLS*/ + +#define DEF_TRAVERSE_TMPL_INST(kind) \ + bool TraverseTemplateInstantiations(kind##TemplateDecl *D) { \ + return Visitor.TraverseTemplateInstantiations(D); \ + } + DEF_TRAVERSE_TMPL_INST(Class) + DEF_TRAVERSE_TMPL_INST(Var) + DEF_TRAVERSE_TMPL_INST(Function) +#undef DEF_TRAVERSE_TMPL_INST + + // Declarations. +#define ABSTRACT_DECL(DECL) +#define DECL(CLASS, BASE) \ + bool Traverse##CLASS##Decl(CLASS##Decl *D) { \ + return Visitor.Traverse##CLASS##Decl(D); \ + } +#include "clang/AST/DeclNodes.inc" + +#define DECL(CLASS, BASE) \ + bool Visit##CLASS##Decl(CLASS##Decl *D) { \ + return Visitor.Visit##CLASS##Decl(D); \ + } +#include "clang/AST/DeclNodes.inc" + + // Statements. +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ + bool Traverse##CLASS(CLASS *S) { return Visitor.Traverse##CLASS(S); } +#include "clang/AST/StmtNodes.inc" + +#define STMT(CLASS, PARENT) \ + bool Visit##CLASS(CLASS *S) { return Visitor.Visit##CLASS(S); } +#include "clang/AST/StmtNodes.inc" + + // Types. +#define ABSTRACT_TYPE(CLASS, BASE) +#define TYPE(CLASS, BASE) \ + bool Traverse##CLASS##Type(CLASS##Type *T) { \ + return Visitor.Traverse##CLASS##Type(T); \ + } +#include "clang/AST/TypeNodes.inc" + +#define TYPE(CLASS, BASE) \ + bool Visit##CLASS##Type(CLASS##Type *T) { \ + return Visitor.Visit##CLASS##Type(T); \ + } +#include "clang/AST/TypeNodes.inc" + + // TypeLocs. +#define ABSTRACT_TYPELOC(CLASS, BASE) +#define TYPELOC(CLASS, BASE) \ + bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ + return Visitor.Traverse##CLASS##TypeLoc(TL); \ + } +#include "clang/AST/TypeLocNodes.def" + +#define TYPELOC(CLASS, BASE) \ + bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ + return Visitor.Visit##CLASS##TypeLoc(TL); \ + } +#include "clang/AST/TypeLocNodes.def" +}; +} // namespace + +void DynamicRecursiveASTVisitor::anchor() {} + +bool DynamicRecursiveASTVisitor::TraverseAST(ASTContext &AST) { + return Impl(*this).RecursiveASTVisitor::TraverseAST(AST); +} + +bool DynamicRecursiveASTVisitor::TraverseAttr(Attr *At) { + return Impl(*this).RecursiveASTVisitor::TraverseAttr(At); +} + +bool DynamicRecursiveASTVisitor::TraverseConstructorInitializer( + CXXCtorInitializer *Init) { + return Impl(*this).RecursiveASTVisitor::TraverseConstructorInitializer( + Init); +} + +bool DynamicRecursiveASTVisitor::TraverseDecl(Decl *D) { + return Impl(*this).RecursiveASTVisitor::TraverseDecl(D); +} + +bool DynamicRecursiveASTVisitor::TraverseLambdaCapture(LambdaExpr *LE, + const LambdaCapture *C, + Expr *Init) { + return Impl(*this).RecursiveASTVisitor::TraverseLambdaCapture(LE, C, + Init); +} + +bool DynamicRecursiveASTVisitor::TraverseStmt(Stmt *S) { + return Impl(*this).RecursiveASTVisitor::TraverseStmt(S); +} + +bool DynamicRecursiveASTVisitor::TraverseTemplateArgument( + const TemplateArgument &Arg) { + return Impl(*this).RecursiveASTVisitor::TraverseTemplateArgument(Arg); +} + +bool DynamicRecursiveASTVisitor::TraverseTemplateArguments( + ArrayRef Args) { + return Impl(*this).RecursiveASTVisitor::TraverseTemplateArguments(Args); +} + +bool DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc( + const TemplateArgumentLoc &ArgLoc) { + return Impl(*this).RecursiveASTVisitor::TraverseTemplateArgumentLoc( + ArgLoc); +} + +bool DynamicRecursiveASTVisitor::TraverseTemplateName(TemplateName Template) { + return Impl(*this).RecursiveASTVisitor::TraverseTemplateName(Template); +} + +bool DynamicRecursiveASTVisitor::TraverseType(QualType T) { + return Impl(*this).RecursiveASTVisitor::TraverseType(T); +} + +bool DynamicRecursiveASTVisitor::TraverseTypeLoc(TypeLoc TL) { + return Impl(*this).RecursiveASTVisitor::TraverseTypeLoc(TL); +} + +bool DynamicRecursiveASTVisitor::TraverseTypeConstraint( + const TypeConstraint *C) { + return Impl(*this).RecursiveASTVisitor::TraverseTypeConstraint(C); +} +bool DynamicRecursiveASTVisitor::TraverseObjCProtocolLoc( + ObjCProtocolLoc ProtocolLoc) { + return Impl(*this).RecursiveASTVisitor::TraverseObjCProtocolLoc( + ProtocolLoc); +} + +bool DynamicRecursiveASTVisitor::TraverseConceptRequirement( + concepts::Requirement *R) { + return Impl(*this).RecursiveASTVisitor::TraverseConceptRequirement(R); +} +bool DynamicRecursiveASTVisitor::TraverseConceptTypeRequirement( + concepts::TypeRequirement *R) { + return Impl(*this).RecursiveASTVisitor::TraverseConceptTypeRequirement( + R); +} +bool DynamicRecursiveASTVisitor::TraverseConceptExprRequirement( + concepts::ExprRequirement *R) { + return Impl(*this).RecursiveASTVisitor::TraverseConceptExprRequirement( + R); +} +bool DynamicRecursiveASTVisitor::TraverseConceptNestedRequirement( + concepts::NestedRequirement *R) { + return Impl(*this) + .RecursiveASTVisitor::TraverseConceptNestedRequirement(R); +} + +bool DynamicRecursiveASTVisitor::TraverseConceptReference( + ConceptReference *CR) { + return Impl(*this).RecursiveASTVisitor::TraverseConceptReference(CR); +} + +bool DynamicRecursiveASTVisitor::TraverseCXXBaseSpecifier( + const CXXBaseSpecifier &Base) { + return Impl(*this).RecursiveASTVisitor::TraverseCXXBaseSpecifier(Base); +} + +bool DynamicRecursiveASTVisitor::TraverseDeclarationNameInfo( + DeclarationNameInfo NameInfo) { + return Impl(*this).RecursiveASTVisitor::TraverseDeclarationNameInfo( + NameInfo); +} + +bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifier( + NestedNameSpecifier *NNS) { + return Impl(*this).RecursiveASTVisitor::TraverseNestedNameSpecifier( + NNS); +} + +bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS) { + return Impl(*this).RecursiveASTVisitor::TraverseNestedNameSpecifierLoc( + NNS); +} + +bool DynamicRecursiveASTVisitor::dataTraverseNode(Stmt *S) { + return Impl(*this).RecursiveASTVisitor::dataTraverseNode(S, nullptr); +} + +/* +#define DYNAMIC_ATTR_VISITOR_IMPL +#include "clang/AST/AttrVisitor.inc" +#undef DYNAMIC_ATTR_VISITOR_IMPL +*/ + +#define DEF_TRAVERSE_TMPL_INST(kind) \ + bool DynamicRecursiveASTVisitor::TraverseTemplateInstantiations( \ + kind##TemplateDecl *D) { \ + return Impl(*this) \ + .RecursiveASTVisitor::TraverseTemplateInstantiations(D); \ + } +DEF_TRAVERSE_TMPL_INST(Class) +DEF_TRAVERSE_TMPL_INST(Var) +DEF_TRAVERSE_TMPL_INST(Function) +#undef DEF_TRAVERSE_TMPL_INST + +// Declare Traverse*() for and friends all concrete Decl classes. +#define ABSTRACT_DECL(DECL) +#define DECL(CLASS, BASE) \ + bool DynamicRecursiveASTVisitor::Traverse##CLASS##Decl(CLASS##Decl *D) { \ + return Impl(*this).RecursiveASTVisitor::Traverse##CLASS##Decl(D); \ + } \ + bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ + return Impl(*this).RecursiveASTVisitor::WalkUpFrom##CLASS##Decl(D); \ + } +#include "clang/AST/DeclNodes.inc" + +// Declare Traverse*() and friends for all concrete Stmt classes. +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ + bool DynamicRecursiveASTVisitor::Traverse##CLASS(CLASS *S) { \ + return Impl(*this).RecursiveASTVisitor::Traverse##CLASS(S); \ + } +#include "clang/AST/StmtNodes.inc" + +#define STMT(CLASS, PARENT) \ + bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS(CLASS *S) { \ + return Impl(*this).RecursiveASTVisitor::WalkUpFrom##CLASS(S); \ + } +#include "clang/AST/StmtNodes.inc" + +// Declare Traverse*() and friends for all concrete Typeclasses. +#define ABSTRACT_TYPE(CLASS, BASE) +#define TYPE(CLASS, BASE) \ + bool DynamicRecursiveASTVisitor::Traverse##CLASS##Type(CLASS##Type *T) { \ + return Impl(*this).RecursiveASTVisitor::Traverse##CLASS##Type(T); \ + } \ + bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ + return Impl(*this).RecursiveASTVisitor::WalkUpFrom##CLASS##Type(T); \ + } +#include "clang/AST/TypeNodes.inc" + +#define ABSTRACT_TYPELOC(CLASS, BASE) +#define TYPELOC(CLASS, BASE) \ + bool DynamicRecursiveASTVisitor::Traverse##CLASS##TypeLoc( \ + CLASS##TypeLoc TL) { \ + return Impl(*this).RecursiveASTVisitor::Traverse##CLASS##TypeLoc( \ + TL); \ + } +#include "clang/AST/TypeLocNodes.def" + +#define TYPELOC(CLASS, BASE) \ + bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##TypeLoc( \ + CLASS##TypeLoc TL) { \ + return Impl(*this).RecursiveASTVisitor::WalkUpFrom##CLASS##TypeLoc( \ + TL); \ + } +#include "clang/AST/TypeLocNodes.def" diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp index 9723c0cfa83bb..a5420f2875095 100644 --- a/clang/lib/AST/ParentMapContext.cpp +++ b/clang/lib/AST/ParentMapContext.cpp @@ -12,9 +12,10 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ParentMapContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Decl.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/TemplateBase.h" using namespace clang; @@ -352,19 +353,14 @@ template <> DynTypedNode createDynTypedNode(const ObjCProtocolLoc &Node) { /// traversal - there are other relationships (for example declaration context) /// in the AST that are better modeled by special matchers. class ParentMapContext::ParentMap::ASTVisitor - : public RecursiveASTVisitor { + : public DynamicRecursiveASTVisitor { public: - ASTVisitor(ParentMap &Map) : Map(Map) {} + ASTVisitor(ParentMap &Map) : Map(Map) { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = true; + } private: - friend class RecursiveASTVisitor; - - using VisitorBase = RecursiveASTVisitor; - - bool shouldVisitTemplateInstantiations() const { return true; } - - bool shouldVisitImplicitCode() const { return true; } - /// Record the parent of the node we're visiting. /// MapNode is the child, the parent is on top of ParentStack. /// Parents is the parent storage (either PointerParents or OtherParents). @@ -427,42 +423,53 @@ class ParentMapContext::ParentMap::ASTVisitor return Result; } - bool TraverseDecl(Decl *DeclNode) { + bool TraverseDecl(Decl *DeclNode) override { return TraverseNode( - DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); }, + DeclNode, DeclNode, + [&] { return DynamicRecursiveASTVisitor::TraverseDecl(DeclNode); }, &Map.PointerParents); } - bool TraverseTypeLoc(TypeLoc TypeLocNode) { + bool TraverseTypeLoc(TypeLoc TypeLocNode) override { return TraverseNode( TypeLocNode, DynTypedNode::create(TypeLocNode), - [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); }, + [&] { + return DynamicRecursiveASTVisitor::TraverseTypeLoc(TypeLocNode); + }, &Map.OtherParents); } - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) { + bool + TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) override { return TraverseNode( NNSLocNode, DynTypedNode::create(NNSLocNode), - [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); }, + [&] { + return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc( + NNSLocNode); + }, &Map.OtherParents); } - bool TraverseAttr(Attr *AttrNode) { + bool TraverseAttr(Attr *AttrNode) override { return TraverseNode( - AttrNode, AttrNode, [&] { return VisitorBase::TraverseAttr(AttrNode); }, + AttrNode, AttrNode, + [&] { return DynamicRecursiveASTVisitor::TraverseAttr(AttrNode); }, &Map.PointerParents); } - bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) { + bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) override { return TraverseNode( ProtocolLocNode, DynTypedNode::create(ProtocolLocNode), - [&] { return VisitorBase::TraverseObjCProtocolLoc(ProtocolLocNode); }, + [&] { + return DynamicRecursiveASTVisitor::TraverseObjCProtocolLoc( + ProtocolLocNode); + }, &Map.OtherParents); } // Using generic TraverseNode for Stmt would prevent data-recursion. - bool dataTraverseStmtPre(Stmt *StmtNode) { + bool dataTraverseStmtPre(Stmt *StmtNode) override { addParent(StmtNode, &Map.PointerParents); ParentStack.push_back(DynTypedNode::create(*StmtNode)); return true; } - bool dataTraverseStmtPost(Stmt *StmtNode) { + bool dataTraverseStmtPost(Stmt *StmtNode) override { ParentStack.pop_back(); return true; } diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp index 2d864a2885796..366f4e8df0885 100644 --- a/clang/lib/AST/StmtOpenACC.cpp +++ b/clang/lib/AST/StmtOpenACC.cpp @@ -12,7 +12,7 @@ #include "clang/AST/StmtOpenACC.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" using namespace clang; @@ -44,17 +44,17 @@ OpenACCComputeConstruct *OpenACCComputeConstruct::Create( } void OpenACCComputeConstruct::findAndSetChildLoops() { - struct LoopConstructFinder : RecursiveASTVisitor { + struct LoopConstructFinder final : DynamicRecursiveASTVisitor { OpenACCComputeConstruct *Construct = nullptr; LoopConstructFinder(OpenACCComputeConstruct *Construct) : Construct(Construct) {} - bool TraverseOpenACCComputeConstruct(OpenACCComputeConstruct *C) { + bool TraverseOpenACCComputeConstruct(OpenACCComputeConstruct *C) override { // Stop searching if we find a compute construct. return true; } - bool TraverseOpenACCLoopConstruct(OpenACCLoopConstruct *C) { + bool TraverseOpenACCLoopConstruct(OpenACCLoopConstruct *C) override { // Stop searching if we find a loop construct, after taking ownership of // it. C->setParentComputeConstruct(Construct); diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 0bac2ed63a927..1840bf021e174 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -19,7 +19,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" @@ -87,11 +87,8 @@ struct MemoizedMatchResult { // A RecursiveASTVisitor that traverses all children or all descendants of // a node. -class MatchChildASTVisitor - : public RecursiveASTVisitor { +class MatchChildASTVisitor final : public DynamicRecursiveASTVisitor { public: - typedef RecursiveASTVisitor VisitorBase; - // Creates an AST visitor that matches 'matcher' on all children or // descendants of a traversed node. max_depth is the maximum depth // to traverse: use 1 for matching the children and INT_MAX for @@ -101,8 +98,10 @@ class MatchChildASTVisitor bool IgnoreImplicitChildren, ASTMatchFinder::BindKind Bind) : Matcher(Matcher), Finder(Finder), Builder(Builder), CurrentDepth(0), - MaxDepth(MaxDepth), IgnoreImplicitChildren(IgnoreImplicitChildren), - Bind(Bind), Matches(false) {} + MaxDepth(MaxDepth), Bind(Bind), Matches(false) { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = !IgnoreImplicitChildren; + } // Returns true if a match is found in the subtree rooted at the // given AST node. This is done via a set of mutually recursive @@ -111,7 +110,7 @@ class MatchChildASTVisitor // // - Traverse(node) calls BaseTraverse(node) when it needs // to visit the descendants of node. - // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node)) + // - BaseTraverse(node) then calls (via the DynamicRecursiveASTVisitor) // Traverse*(c) for each child c of 'node'. // - Traverse*(c) in turn calls Traverse(c), completing the // recursion. @@ -151,7 +150,7 @@ class MatchChildASTVisitor // The following are overriding methods from the base visitor class. // They are public only to allow CRTP to work. They are *not *part // of the public API of this class. - bool TraverseDecl(Decl *DeclNode) { + bool TraverseDecl(Decl *DeclNode) override { if (DeclNode && DeclNode->isImplicit() && Finder->isTraversalIgnoringImplicitNodes()) @@ -175,26 +174,22 @@ class MatchChildASTVisitor return StmtToTraverse; } - bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) { - // If we need to keep track of the depth, we can't perform data recursion. - if (CurrentDepth == 0 || (CurrentDepth <= MaxDepth && MaxDepth < INT_MAX)) - Queue = nullptr; - + bool TraverseStmt(Stmt *StmtNode) override { ScopedIncrement ScopedDepth(&CurrentDepth); Stmt *StmtToTraverse = getStmtToTraverse(StmtNode); if (!StmtToTraverse) return true; - if (IgnoreImplicitChildren && isa(StmtNode)) + if (!ShouldVisitImplicitCode && isa(StmtNode)) return true; if (!match(*StmtToTraverse)) return false; - return VisitorBase::TraverseStmt(StmtToTraverse, Queue); + return DynamicRecursiveASTVisitor::TraverseStmt(StmtToTraverse); } // We assume that the QualType and the contained type are on the same // hierarchy level. Thus, we try to match either of them. - bool TraverseType(QualType TypeNode) { + bool TraverseType(QualType TypeNode) override { if (TypeNode.isNull()) return true; ScopedIncrement ScopedDepth(&CurrentDepth); @@ -206,7 +201,7 @@ class MatchChildASTVisitor } // We assume that the TypeLoc, contained QualType and contained Type all are // on the same hierarchy level. Thus, we try to match all of them. - bool TraverseTypeLoc(TypeLoc TypeLocNode) { + bool TraverseTypeLoc(TypeLoc TypeLocNode) override { if (TypeLocNode.isNull()) return true; ScopedIncrement ScopedDepth(&CurrentDepth); @@ -219,11 +214,11 @@ class MatchChildASTVisitor // The TypeLoc is matched inside traverse. return traverse(TypeLocNode); } - bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { + bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) override { ScopedIncrement ScopedDepth(&CurrentDepth); return (NNS == nullptr) || traverse(*NNS); } - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override { if (!NNS) return true; ScopedIncrement ScopedDepth(&CurrentDepth); @@ -231,19 +226,19 @@ class MatchChildASTVisitor return false; return traverse(NNS); } - bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) { + bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) override { if (!CtorInit) return true; ScopedIncrement ScopedDepth(&CurrentDepth); return traverse(*CtorInit); } - bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) { + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &TAL) override { ScopedIncrement ScopedDepth(&CurrentDepth); return traverse(TAL); } - bool TraverseCXXForRangeStmt(CXXForRangeStmt *Node) { + bool TraverseCXXForRangeStmt(CXXForRangeStmt *Node) override { if (!Finder->isTraversalIgnoringImplicitNodes()) - return VisitorBase::TraverseCXXForRangeStmt(Node); + return DynamicRecursiveASTVisitor::TraverseCXXForRangeStmt(Node); if (!Node) return true; ScopedIncrement ScopedDepth(&CurrentDepth); @@ -253,22 +248,24 @@ class MatchChildASTVisitor if (!match(*Node->getLoopVariable())) return false; if (match(*Node->getRangeInit())) - if (!VisitorBase::TraverseStmt(Node->getRangeInit())) + if (!DynamicRecursiveASTVisitor::TraverseStmt(Node->getRangeInit())) return false; if (!match(*Node->getBody())) return false; - return VisitorBase::TraverseStmt(Node->getBody()); + return DynamicRecursiveASTVisitor::TraverseStmt(Node->getBody()); } - bool TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *Node) { + bool TraverseCXXRewrittenBinaryOperator( + CXXRewrittenBinaryOperator *Node) override { if (!Finder->isTraversalIgnoringImplicitNodes()) - return VisitorBase::TraverseCXXRewrittenBinaryOperator(Node); + return DynamicRecursiveASTVisitor::TraverseCXXRewrittenBinaryOperator( + Node); if (!Node) return true; ScopedIncrement ScopedDepth(&CurrentDepth); return match(*Node->getLHS()) && match(*Node->getRHS()); } - bool TraverseAttr(Attr *A) { + bool TraverseAttr(Attr *A) override { if (A == nullptr || (A->isImplicit() && Finder->getASTContext().getParentMapContext().getTraversalKind() == @@ -277,9 +274,9 @@ class MatchChildASTVisitor ScopedIncrement ScopedDepth(&CurrentDepth); return traverse(*A); } - bool TraverseLambdaExpr(LambdaExpr *Node) { + bool TraverseLambdaExpr(LambdaExpr *Node) override { if (!Finder->isTraversalIgnoringImplicitNodes()) - return VisitorBase::TraverseLambdaExpr(Node); + return DynamicRecursiveASTVisitor::TraverseLambdaExpr(Node); if (!Node) return true; ScopedIncrement ScopedDepth(&CurrentDepth); @@ -309,12 +306,9 @@ class MatchChildASTVisitor if (!match(*Node->getBody())) return false; - return VisitorBase::TraverseStmt(Node->getBody()); + return DynamicRecursiveASTVisitor::TraverseStmt(Node->getBody()); } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return !IgnoreImplicitChildren; } - private: // Used for updating the depth during traversal. struct ScopedIncrement { @@ -334,33 +328,36 @@ class MatchChildASTVisitor // Forwards the call to the corresponding Traverse*() method in the // base visitor class. bool baseTraverse(const Decl &DeclNode) { - return VisitorBase::TraverseDecl(const_cast(&DeclNode)); + return DynamicRecursiveASTVisitor::TraverseDecl( + const_cast(&DeclNode)); } bool baseTraverse(const Stmt &StmtNode) { - return VisitorBase::TraverseStmt(const_cast(&StmtNode)); + return DynamicRecursiveASTVisitor::TraverseStmt( + const_cast(&StmtNode)); } bool baseTraverse(QualType TypeNode) { - return VisitorBase::TraverseType(TypeNode); + return DynamicRecursiveASTVisitor::TraverseType(TypeNode); } bool baseTraverse(TypeLoc TypeLocNode) { - return VisitorBase::TraverseTypeLoc(TypeLocNode); + return DynamicRecursiveASTVisitor::TraverseTypeLoc(TypeLocNode); } bool baseTraverse(const NestedNameSpecifier &NNS) { - return VisitorBase::TraverseNestedNameSpecifier( - const_cast(&NNS)); + return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifier( + const_cast(&NNS)); } bool baseTraverse(NestedNameSpecifierLoc NNS) { - return VisitorBase::TraverseNestedNameSpecifierLoc(NNS); + return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNS); } bool baseTraverse(const CXXCtorInitializer &CtorInit) { - return VisitorBase::TraverseConstructorInitializer( + return DynamicRecursiveASTVisitor::TraverseConstructorInitializer( const_cast(&CtorInit)); } bool baseTraverse(TemplateArgumentLoc TAL) { - return VisitorBase::TraverseTemplateArgumentLoc(TAL); + return DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(TAL); } bool baseTraverse(const Attr &AttrNode) { - return VisitorBase::TraverseAttr(const_cast(&AttrNode)); + return DynamicRecursiveASTVisitor::TraverseAttr( + const_cast(&AttrNode)); } // Sets 'Matched' to true if 'Matcher' matches 'Node' and: @@ -410,19 +407,25 @@ class MatchChildASTVisitor BoundNodesTreeBuilder ResultBindings; int CurrentDepth; const int MaxDepth; - const bool IgnoreImplicitChildren; const ASTMatchFinder::BindKind Bind; bool Matches; }; // Controls the outermost traversal of the AST and allows to match multiple // matchers. -class MatchASTVisitor : public RecursiveASTVisitor, - public ASTMatchFinder { +class MatchASTVisitor final : public DynamicRecursiveASTVisitor, + public ASTMatchFinder { public: MatchASTVisitor(const MatchFinder::MatchersByType *Matchers, const MatchFinder::MatchFinderOptions &Options) - : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {} + : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = true; + + // We visit the lambda body explicitly, so instruct the RAV + // to not visit it on our behalf too. + ShouldVisitLambdaBody = false; + } ~MatchASTVisitor() override { if (Options.CheckProfiling) { @@ -454,10 +457,7 @@ class MatchASTVisitor : public RecursiveASTVisitor, ActiveASTContext = NewActiveASTContext; } - // The following Visit*() and Traverse*() functions "override" - // methods in RecursiveASTVisitor. - - bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) { + bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) override { // When we see 'typedef A B', we add name 'B' to the set of names // A's canonical type maps to. This is necessary for implementing // isDerivedFrom(x) properly, where x can be the name of the base @@ -492,23 +492,23 @@ class MatchASTVisitor : public RecursiveASTVisitor, return true; } - bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { + bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) override { const ObjCInterfaceDecl *InterfaceDecl = CAD->getClassInterface(); CompatibleAliases[InterfaceDecl].insert(CAD); return true; } - bool TraverseDecl(Decl *DeclNode); - bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr); - bool TraverseType(QualType TypeNode); - bool TraverseTypeLoc(TypeLoc TypeNode); - bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); - bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit); - bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL); - bool TraverseAttr(Attr *AttrNode); + bool TraverseDecl(Decl *DeclNode) override; + bool TraverseStmt(Stmt *StmtNode) override; + bool TraverseType(QualType TypeNode) override; + bool TraverseTypeLoc(TypeLoc TypeNode) override; + bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) override; + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override; + bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) override; + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &TAL) override; + bool TraverseAttr(Attr *AttrNode) override; - bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) { + bool dataTraverseNode(Stmt *S) override { if (auto *RF = dyn_cast(S)) { { ASTNodeNotAsIsSourceScope RAII(this, true); @@ -579,7 +579,7 @@ class MatchASTVisitor : public RecursiveASTVisitor, TraverseType(E); if (Expr *NE = T->getNoexceptExpr()) - TraverseStmt(NE, Queue); + TraverseStmt(NE); if (LE->hasExplicitResultType()) TraverseTypeLoc(Proto.getReturnLoc()); @@ -589,7 +589,7 @@ class MatchASTVisitor : public RecursiveASTVisitor, TraverseStmt(LE->getBody()); return true; } - return RecursiveASTVisitor::dataTraverseNode(S, Queue); + return DynamicRecursiveASTVisitor::dataTraverseNode(S); } // Matches children or descendants of 'Node' with 'BaseMatcher'. @@ -733,13 +733,6 @@ class MatchASTVisitor : public RecursiveASTVisitor, // Implements ASTMatchFinder::getASTContext. ASTContext &getASTContext() const override { return *ActiveASTContext; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return true; } - - // We visit the lambda body explicitly, so instruct the RAV - // to not visit it on our behalf too. - bool shouldVisitLambdaBody() const { return false; } - bool IsMatchingInASTNodeNotSpelledInSource() const override { return TraversingASTNodeNotSpelledInSource; } @@ -754,22 +747,19 @@ class MatchASTVisitor : public RecursiveASTVisitor, return TraversingASTNodeNotAsIs; } - bool TraverseTemplateInstantiations(ClassTemplateDecl *D) { + bool TraverseTemplateInstantiations(ClassTemplateDecl *D) override { ASTNodeNotSpelledInSourceScope RAII(this, true); - return RecursiveASTVisitor::TraverseTemplateInstantiations( - D); + return DynamicRecursiveASTVisitor::TraverseTemplateInstantiations(D); } - bool TraverseTemplateInstantiations(VarTemplateDecl *D) { + bool TraverseTemplateInstantiations(VarTemplateDecl *D) override { ASTNodeNotSpelledInSourceScope RAII(this, true); - return RecursiveASTVisitor::TraverseTemplateInstantiations( - D); + return DynamicRecursiveASTVisitor::TraverseTemplateInstantiations(D); } - bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) { + bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) override { ASTNodeNotSpelledInSourceScope RAII(this, true); - return RecursiveASTVisitor::TraverseTemplateInstantiations( - D); + return DynamicRecursiveASTVisitor::TraverseTemplateInstantiations(D); } private: @@ -1468,10 +1458,10 @@ bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) { ASTChildrenNotSpelledInSourceScope RAII2(this, ScopedChildren); match(*DeclNode); - return RecursiveASTVisitor::TraverseDecl(DeclNode); + return DynamicRecursiveASTVisitor::TraverseDecl(DeclNode); } -bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) { +bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode) { if (!StmtNode) { return true; } @@ -1480,12 +1470,12 @@ bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) { ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal); match(*StmtNode); - return RecursiveASTVisitor::TraverseStmt(StmtNode, Queue); + return DynamicRecursiveASTVisitor::TraverseStmt(StmtNode); } bool MatchASTVisitor::TraverseType(QualType TypeNode) { match(TypeNode); - return RecursiveASTVisitor::TraverseType(TypeNode); + return DynamicRecursiveASTVisitor::TraverseType(TypeNode); } bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) { @@ -1496,12 +1486,12 @@ bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) { // each TypeLoc. match(TypeLocNode); match(TypeLocNode.getType()); - return RecursiveASTVisitor::TraverseTypeLoc(TypeLocNode); + return DynamicRecursiveASTVisitor::TraverseTypeLoc(TypeLocNode); } bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { match(*NNS); - return RecursiveASTVisitor::TraverseNestedNameSpecifier(NNS); + return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifier(NNS); } bool MatchASTVisitor::TraverseNestedNameSpecifierLoc( @@ -1515,8 +1505,7 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc( // because the traversal is already done in the parallel "Loc"-hierarchy. if (NNS.hasQualifier()) match(*NNS.getNestedNameSpecifier()); - return - RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNS); + return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNS); } bool MatchASTVisitor::TraverseConstructorInitializer( @@ -1534,18 +1523,18 @@ bool MatchASTVisitor::TraverseConstructorInitializer( match(*CtorInit); - return RecursiveASTVisitor::TraverseConstructorInitializer( - CtorInit); + return DynamicRecursiveASTVisitor::TraverseConstructorInitializer(CtorInit); } -bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) { +bool MatchASTVisitor::TraverseTemplateArgumentLoc( + const TemplateArgumentLoc &Loc) { match(Loc); - return RecursiveASTVisitor::TraverseTemplateArgumentLoc(Loc); + return DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(Loc); } bool MatchASTVisitor::TraverseAttr(Attr *AttrNode) { match(*AttrNode); - return RecursiveASTVisitor::TraverseAttr(AttrNode); + return DynamicRecursiveASTVisitor::TraverseAttr(AttrNode); } class MatchASTConsumer : public ASTConsumer { diff --git a/clang/lib/ASTMatchers/GtestMatchers.cpp b/clang/lib/ASTMatchers/GtestMatchers.cpp index a556d8ef2da06..d2a672535f2c5 100644 --- a/clang/lib/ASTMatchers/GtestMatchers.cpp +++ b/clang/lib/ASTMatchers/GtestMatchers.cpp @@ -18,7 +18,6 @@ #include "clang/ASTMatchers/GtestMatchers.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" diff --git a/clang/lib/Analysis/CallGraph.cpp b/clang/lib/Analysis/CallGraph.cpp index f892980ed3138..958dbfec42634 100644 --- a/clang/lib/Analysis/CallGraph.cpp +++ b/clang/lib/Analysis/CallGraph.cpp @@ -148,6 +148,9 @@ void CallGraph::addNodesForBlocks(DeclContext *D) { CallGraph::CallGraph() { Root = getOrInsertNode(nullptr); + ShouldWalkTypesOfTypeLocs = false; + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = true; } CallGraph::~CallGraph() = default; diff --git a/clang/lib/Analysis/CalledOnceCheck.cpp b/clang/lib/Analysis/CalledOnceCheck.cpp index 30cbd257b65e8..f97339bc9381e 100644 --- a/clang/lib/Analysis/CalledOnceCheck.cpp +++ b/clang/lib/Analysis/CalledOnceCheck.cpp @@ -11,11 +11,11 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" @@ -426,7 +426,7 @@ const Expr *getCondition(const Stmt *S) { /// of the AST will end up in the results. /// Results might have duplicate names, if this is a problem, convert to /// string sets afterwards. -class NamesCollector : public RecursiveASTVisitor { +class NamesCollector final : public DynamicRecursiveASTVisitor { public: static constexpr unsigned EXPECTED_NUMBER_OF_NAMES = 5; using NameCollection = @@ -438,12 +438,12 @@ class NamesCollector : public RecursiveASTVisitor { return Impl.Result; } - bool VisitDeclRefExpr(const DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { Result.push_back(E->getDecl()->getName()); return true; } - bool VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) { + bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) override { llvm::StringRef Name; if (E->isImplicitProperty()) { diff --git a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp index fdba139628d8f..bd161c55f12b5 100644 --- a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp +++ b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp @@ -198,8 +198,7 @@ static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) { return nullptr; } -class ReferencedDeclsVisitor - : public AnalysisASTVisitor { +class ReferencedDeclsVisitor : public AnalysisASTVisitor { public: ReferencedDeclsVisitor(ReferencedDecls &Referenced) : Referenced(Referenced) {} @@ -225,21 +224,21 @@ class ReferencedDeclsVisitor } } - bool VisitDecl(Decl *D) { + bool VisitDecl(Decl *D) override { insertIfGlobal(*D, Referenced.Globals); insertIfLocal(*D, Referenced.Locals); insertIfFunction(*D, Referenced.Functions); return true; } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { insertIfGlobal(*E->getDecl(), Referenced.Globals); insertIfLocal(*E->getDecl(), Referenced.Locals); insertIfFunction(*E->getDecl(), Referenced.Functions); return true; } - bool VisitCXXMemberCallExpr(CXXMemberCallExpr *C) { + bool VisitCXXMemberCallExpr(CXXMemberCallExpr *C) override { // If this is a method that returns a member variable but does nothing else, // model the field of the return value. if (MemberExpr *E = getMemberForAccessor(*C)) @@ -248,7 +247,7 @@ class ReferencedDeclsVisitor return true; } - bool VisitMemberExpr(MemberExpr *E) { + bool VisitMemberExpr(MemberExpr *E) override { // FIXME: should we be using `E->getFoundDecl()`? const ValueDecl *VD = E->getMemberDecl(); insertIfGlobal(*VD, Referenced.Globals); @@ -258,14 +257,14 @@ class ReferencedDeclsVisitor return true; } - bool VisitInitListExpr(InitListExpr *InitList) { + bool VisitInitListExpr(InitListExpr *InitList) override { if (InitList->getType()->isRecordType()) for (const auto *FD : getFieldsForInitListExpr(InitList)) Referenced.Fields.insert(FD); return true; } - bool VisitCXXParenListInitExpr(CXXParenListInitExpr *ParenInitList) { + bool VisitCXXParenListInitExpr(CXXParenListInitExpr *ParenInitList) override { if (ParenInitList->getType()->isRecordType()) for (const auto *FD : getFieldsForInitListExpr(ParenInitList)) Referenced.Fields.insert(FD); diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index e1f68e493f355..ff2a213f5d753 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -16,7 +16,6 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" #include "clang/Analysis/FlowSensitive/ASTOps.h" @@ -298,7 +297,7 @@ namespace { // Visitor that builds a map from record prvalues to result objects. // For each result object that it encounters, it propagates the storage location // of the result object to all record prvalues that can initialize it. -class ResultObjectVisitor : public AnalysisASTVisitor { +class ResultObjectVisitor : public AnalysisASTVisitor { public: // `ResultObjectMap` will be filled with a map from record prvalues to result // object. If this visitor will traverse a function that returns a record by @@ -339,7 +338,7 @@ class ResultObjectVisitor : public AnalysisASTVisitor { } } - bool VisitVarDecl(VarDecl *VD) { + bool VisitVarDecl(VarDecl *VD) override { if (VD->getType()->isRecordType() && VD->hasInit()) PropagateResultObject( VD->getInit(), @@ -347,7 +346,7 @@ class ResultObjectVisitor : public AnalysisASTVisitor { return true; } - bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) { + bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) override { if (MTE->getType()->isRecordType()) PropagateResultObject( MTE->getSubExpr(), @@ -355,7 +354,7 @@ class ResultObjectVisitor : public AnalysisASTVisitor { return true; } - bool VisitReturnStmt(ReturnStmt *Return) { + bool VisitReturnStmt(ReturnStmt *Return) override { Expr *RetValue = Return->getRetValue(); if (RetValue != nullptr && RetValue->getType()->isRecordType() && RetValue->isPRValue()) @@ -363,7 +362,7 @@ class ResultObjectVisitor : public AnalysisASTVisitor { return true; } - bool VisitExpr(Expr *E) { + bool VisitExpr(Expr *E) override { // Clang's AST can have record-type prvalues without a result object -- for // example as full-expressions contained in a compound statement or as // arguments of call expressions. We notice this if we get here and a diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp index acbe1470b3899..344047beaac72 100644 --- a/clang/lib/Analysis/ReachableCode.cpp +++ b/clang/lib/Analysis/ReachableCode.cpp @@ -13,11 +13,11 @@ #include "clang/Analysis/Analyses/ReachableCode.h" #include "clang/AST/Attr.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" @@ -476,17 +476,19 @@ static bool isInCoroutineStmt(const Stmt *DeadStmt, const CFGBlock *Block) { } if (!CoroStmt) return false; - struct Checker : RecursiveASTVisitor { + struct Checker final : DynamicRecursiveASTVisitor { const Stmt *DeadStmt; bool CoroutineSubStmt = false; - Checker(const Stmt *S) : DeadStmt(S) {} - bool VisitStmt(const Stmt *S) { + Checker(const Stmt *S) : DeadStmt(S) { + // Statements captured in the CFG can be implicit. + ShouldVisitImplicitCode = true; + } + + bool VisitStmt(Stmt *S) override { if (S == DeadStmt) CoroutineSubStmt = true; return true; } - // Statements captured in the CFG can be implicit. - bool shouldVisitImplicitCode() const { return true; } }; Checker checker(DeadStmt); checker.TraverseStmt(const_cast(CoroStmt)); diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index da7446913f7c8..0fc99dc9fb5b7 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -9,8 +9,8 @@ #include "clang/Analysis/Analyses/UnsafeBufferUsage.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -81,11 +81,8 @@ static std::string getDREAncestorString(const DeclRefExpr *DRE, namespace clang::ast_matchers { // A `RecursiveASTVisitor` that traverses all descendants of a given node "n" // except for those belonging to a different callable of "n". -class MatchDescendantVisitor - : public RecursiveASTVisitor { +class MatchDescendantVisitor final : public DynamicRecursiveASTVisitor { public: - typedef RecursiveASTVisitor VisitorBase; - // Creates an AST visitor that matches `Matcher` on all // descendants of a given node "n" except for the ones // belonging to a different callable of "n". @@ -95,7 +92,10 @@ class MatchDescendantVisitor internal::ASTMatchFinder::BindKind Bind, const bool ignoreUnevaluatedContext) : Matcher(Matcher), Finder(Finder), Builder(Builder), Bind(Bind), - Matches(false), ignoreUnevaluatedContext(ignoreUnevaluatedContext) {} + Matches(false), ignoreUnevaluatedContext(ignoreUnevaluatedContext) { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; // TODO: let's ignore implicit code for now + } // Returns true if a match is found in a subtree of `DynNode`, which belongs // to the same callable of `DynNode`. @@ -116,7 +116,7 @@ class MatchDescendantVisitor // For the matchers so far used in safe buffers, we only need to match // `Stmt`s. To override more as needed. - bool TraverseDecl(Decl *Node) { + bool TraverseDecl(Decl *Node) override { if (!Node) return true; if (!match(*Node)) @@ -125,63 +125,58 @@ class MatchDescendantVisitor if (isa(Node)) return true; // Traverse descendants - return VisitorBase::TraverseDecl(Node); + return DynamicRecursiveASTVisitor::TraverseDecl(Node); } - bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) { + bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) override { // These are unevaluated, except the result expression. if (ignoreUnevaluatedContext) return TraverseStmt(Node->getResultExpr()); - return VisitorBase::TraverseGenericSelectionExpr(Node); + return DynamicRecursiveASTVisitor::TraverseGenericSelectionExpr(Node); } - bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) { + bool + TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return VisitorBase::TraverseUnaryExprOrTypeTraitExpr(Node); + return DynamicRecursiveASTVisitor::TraverseUnaryExprOrTypeTraitExpr(Node); } - bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) { + bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return VisitorBase::TraverseTypeOfExprTypeLoc(Node); + return DynamicRecursiveASTVisitor::TraverseTypeOfExprTypeLoc(Node); } - bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) { + bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return VisitorBase::TraverseDecltypeTypeLoc(Node); + return DynamicRecursiveASTVisitor::TraverseDecltypeTypeLoc(Node); } - bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) { + bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return VisitorBase::TraverseCXXNoexceptExpr(Node); + return DynamicRecursiveASTVisitor::TraverseCXXNoexceptExpr(Node); } - bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) { + bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return VisitorBase::TraverseCXXTypeidExpr(Node); + return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(Node); } - bool TraverseStmt(Stmt *Node, DataRecursionQueue *Queue = nullptr) { + bool TraverseStmt(Stmt *Node) override { if (!Node) return true; if (!match(*Node)) return false; - return VisitorBase::TraverseStmt(Node); - } - - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { - // TODO: let's ignore implicit code for now - return false; + return DynamicRecursiveASTVisitor::TraverseStmt(Node); } private: diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 7ad3088f0ab75..2aff23aa27158 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -25,9 +25,9 @@ #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/VTableBuilder.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/FileManager.h" @@ -5446,10 +5446,9 @@ static bool ReferencesAnonymousEntity(ArrayRef Args) { case TemplateArgument::Pack: return ReferencesAnonymousEntity(TA.getPackAsArray()); case TemplateArgument::Type: { - struct ReferencesAnonymous - : public RecursiveASTVisitor { + struct ReferencesAnonymous final : DynamicRecursiveASTVisitor { bool RefAnon = false; - bool VisitRecordType(RecordType *RT) { + bool VisitRecordType(RecordType *RT) override { if (ReferencesAnonymousEntity(RT)) { RefAnon = true; return false; @@ -5470,17 +5469,17 @@ static bool ReferencesAnonymousEntity(ArrayRef Args) { }); } namespace { -struct ReconstitutableType : public RecursiveASTVisitor { +struct ReconstitutableType final : DynamicRecursiveASTVisitor { bool Reconstitutable = true; - bool VisitVectorType(VectorType *FT) { + bool VisitVectorType(VectorType *FT) override { Reconstitutable = false; return false; } - bool VisitAtomicType(AtomicType *FT) { + bool VisitAtomicType(AtomicType *FT) override { Reconstitutable = false; return false; } - bool VisitType(Type *T) { + bool VisitType(Type *T) override { // _BitInt(N) isn't reconstitutable because the bit width isn't encoded in // the DWARF, only the byte width. if (T->isBitIntType()) { @@ -5489,7 +5488,7 @@ struct ReconstitutableType : public RecursiveASTVisitor { } return true; } - bool TraverseEnumType(EnumType *ET) { + bool TraverseEnumType(EnumType *ET) override { // Unnamed enums can't be reconstituted due to a lack of column info we // produce in the DWARF, so we can't get Clang's full name back. if (const auto *ED = dyn_cast(ET->getDecl())) { @@ -5504,13 +5503,13 @@ struct ReconstitutableType : public RecursiveASTVisitor { } return true; } - bool VisitFunctionProtoType(FunctionProtoType *FT) { + bool VisitFunctionProtoType(FunctionProtoType *FT) override { // noexcept is not encoded in DWARF, so the reversi Reconstitutable &= !isNoexceptExceptionSpec(FT->getExceptionSpecType()); Reconstitutable &= !FT->getNoReturnAttr(); return Reconstitutable; } - bool VisitRecordType(RecordType *RT) { + bool VisitRecordType(RecordType *RT) override { if (ReferencesAnonymousEntity(RT)) { Reconstitutable = false; return false; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 0b61ef0f89989..a2a71ef0cf371 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -34,8 +34,8 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Mangle.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/CharInfo.h" @@ -3957,13 +3957,12 @@ namespace { }; // Make sure we're not referencing non-imported vars or functions. - struct DLLImportFunctionVisitor - : public RecursiveASTVisitor { + struct DLLImportFunctionVisitor final : DynamicRecursiveASTVisitor { bool SafeToInline = true; - bool shouldVisitImplicitCode() const { return true; } + DLLImportFunctionVisitor() { ShouldVisitImplicitCode = true; } - bool VisitVarDecl(VarDecl *VD) { + bool VisitVarDecl(VarDecl *VD) override { if (VD->getTLSKind()) { // A thread-local variable cannot be imported. SafeToInline = false; @@ -3977,13 +3976,13 @@ namespace { return SafeToInline; } - bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) override { if (const auto *D = E->getTemporary()->getDestructor()) SafeToInline = D->hasAttr(); return SafeToInline; } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { ValueDecl *VD = E->getDecl(); if (isa(VD)) SafeToInline = VD->hasAttr(); @@ -3992,12 +3991,12 @@ namespace { return SafeToInline; } - bool VisitCXXConstructExpr(CXXConstructExpr *E) { + bool VisitCXXConstructExpr(CXXConstructExpr *E) override { SafeToInline = E->getConstructor()->hasAttr(); return SafeToInline; } - bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { + bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) override { CXXMethodDecl *M = E->getMethodDecl(); if (!M) { // Call through a pointer to member function. This is safe to inline. @@ -4008,12 +4007,12 @@ namespace { return SafeToInline; } - bool VisitCXXDeleteExpr(CXXDeleteExpr *E) { + bool VisitCXXDeleteExpr(CXXDeleteExpr *E) override { SafeToInline = E->getOperatorDelete()->hasAttr(); return SafeToInline; } - bool VisitCXXNewExpr(CXXNewExpr *E) { + bool VisitCXXNewExpr(CXXNewExpr *E) override { SafeToInline = E->getOperatorNew()->hasAttr(); return SafeToInline; } diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index cfcdb5911b581..833c491d2c593 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -13,7 +13,7 @@ #include "CodeGenPGO.h" #include "CodeGenFunction.h" #include "CoverageMappingGen.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/MDBuilder.h" @@ -156,9 +156,7 @@ static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader, } /// A RecursiveASTVisitor that fills a map of statements to PGO counters. -struct MapRegionCounters : public RecursiveASTVisitor { - using Base = RecursiveASTVisitor; - +struct MapRegionCounters final : DynamicRecursiveASTVisitor { /// The next counter value to assign. unsigned NextCounter; /// The function hash. @@ -184,16 +182,16 @@ struct MapRegionCounters : public RecursiveASTVisitor { // Blocks and lambdas are handled as separate functions, so we need not // traverse them in the parent context. - bool TraverseBlockExpr(BlockExpr *BE) { return true; } - bool TraverseLambdaExpr(LambdaExpr *LE) { + bool TraverseBlockExpr(BlockExpr *BE) override { return true; } + bool TraverseLambdaExpr(LambdaExpr *LE) override { // Traverse the captures, but not the body. for (auto C : zip(LE->captures(), LE->capture_inits())) TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C)); return true; } - bool TraverseCapturedStmt(CapturedStmt *CS) { return true; } + bool TraverseCapturedStmt(CapturedStmt *CS) override { return true; } - bool VisitDecl(const Decl *D) { + bool VisitDecl(Decl *D) override { switch (D->getKind()) { default: break; @@ -235,7 +233,7 @@ struct MapRegionCounters : public RecursiveASTVisitor { SmallVector LogOpStack; // Hook: dataTraverseStmtPre() is invoked prior to visiting an AST Stmt node. - bool dataTraverseStmtPre(Stmt *S) { + bool dataTraverseStmtPre(Stmt *S) override { /// If MC/DC is not enabled, MCDCMaxCond will be set to 0. Do nothing. if (MCDCMaxCond == 0) return true; @@ -275,7 +273,7 @@ struct MapRegionCounters : public RecursiveASTVisitor { // Hook: dataTraverseStmtPost() is invoked by the AST visitor after visiting // an AST Stmt node. MC/DC will use it to to signal when the top of a // logical operation (boolean expression) nest is encountered. - bool dataTraverseStmtPost(Stmt *S) { + bool dataTraverseStmtPost(Stmt *S) override { /// If MC/DC is not enabled, MCDCMaxCond will be set to 0. Do nothing. if (MCDCMaxCond == 0) return true; @@ -328,7 +326,7 @@ struct MapRegionCounters : public RecursiveASTVisitor { /// semantics of the operator. This is only valid for ">= v7" of the profile /// version so that we facilitate backward compatibility. In addition, in /// order to use MC/DC, count the number of total LHS and RHS conditions. - bool VisitBinaryOperator(BinaryOperator *S) { + bool VisitBinaryOperator(BinaryOperator *S) override { if (S->isLogicalOp()) { if (CodeGenFunction::isInstrumentedCondition(S->getLHS())) NumCond++; @@ -340,19 +338,19 @@ struct MapRegionCounters : public RecursiveASTVisitor { NumCond++; } } - return Base::VisitBinaryOperator(S); + return DynamicRecursiveASTVisitor::VisitBinaryOperator(S); } - bool VisitConditionalOperator(ConditionalOperator *S) { + bool VisitConditionalOperator(ConditionalOperator *S) override { if (llvm::EnableSingleByteCoverage && S->getTrueExpr()) CounterMap[S->getTrueExpr()] = NextCounter++; if (llvm::EnableSingleByteCoverage && S->getFalseExpr()) CounterMap[S->getFalseExpr()] = NextCounter++; - return Base::VisitConditionalOperator(S); + return DynamicRecursiveASTVisitor::VisitConditionalOperator(S); } /// Include \p S in the function hash. - bool VisitStmt(Stmt *S) { + bool VisitStmt(Stmt *S) override { auto Type = updateCounterMappings(S); if (Hash.getHashVersion() != PGO_HASH_V1) Type = getHashType(Hash.getHashVersion(), S); @@ -361,10 +359,10 @@ struct MapRegionCounters : public RecursiveASTVisitor { return true; } - bool TraverseIfStmt(IfStmt *If) { + bool TraverseIfStmt(IfStmt *If) override { // If we used the V1 hash, use the default traversal. if (Hash.getHashVersion() == PGO_HASH_V1) - return Base::TraverseIfStmt(If); + return DynamicRecursiveASTVisitor::TraverseIfStmt(If); // When single byte coverage mode is enabled, add a counter to then and // else. @@ -394,7 +392,7 @@ struct MapRegionCounters : public RecursiveASTVisitor { return true; } - bool TraverseWhileStmt(WhileStmt *While) { + bool TraverseWhileStmt(WhileStmt *While) override { // When single byte coverage mode is enabled, add a counter to condition and // body. bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage; @@ -407,13 +405,13 @@ struct MapRegionCounters : public RecursiveASTVisitor { CounterMap[While->getBody()] = NextCounter++; } - Base::TraverseWhileStmt(While); + DynamicRecursiveASTVisitor::TraverseWhileStmt(While); if (Hash.getHashVersion() != PGO_HASH_V1) Hash.combine(PGOHash::EndOfScope); return true; } - bool TraverseDoStmt(DoStmt *Do) { + bool TraverseDoStmt(DoStmt *Do) override { // When single byte coverage mode is enabled, add a counter to condition and // body. bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage; @@ -426,13 +424,13 @@ struct MapRegionCounters : public RecursiveASTVisitor { CounterMap[Do->getBody()] = NextCounter++; } - Base::TraverseDoStmt(Do); + DynamicRecursiveASTVisitor::TraverseDoStmt(Do); if (Hash.getHashVersion() != PGO_HASH_V1) Hash.combine(PGOHash::EndOfScope); return true; } - bool TraverseForStmt(ForStmt *For) { + bool TraverseForStmt(ForStmt *For) override { // When single byte coverage mode is enabled, add a counter to condition, // increment and body. bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage; @@ -447,13 +445,13 @@ struct MapRegionCounters : public RecursiveASTVisitor { CounterMap[For->getBody()] = NextCounter++; } - Base::TraverseForStmt(For); + DynamicRecursiveASTVisitor::TraverseForStmt(For); if (Hash.getHashVersion() != PGO_HASH_V1) Hash.combine(PGOHash::EndOfScope); return true; } - bool TraverseCXXForRangeStmt(CXXForRangeStmt *ForRange) { + bool TraverseCXXForRangeStmt(CXXForRangeStmt *ForRange) override { // When single byte coverage mode is enabled, add a counter to body. bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage; for (Stmt *CS : ForRange->children()) { @@ -463,7 +461,7 @@ struct MapRegionCounters : public RecursiveASTVisitor { CounterMap[ForRange->getBody()] = NextCounter++; } - Base::TraverseCXXForRangeStmt(ForRange); + DynamicRecursiveASTVisitor::TraverseCXXForRangeStmt(ForRange); if (Hash.getHashVersion() != PGO_HASH_V1) Hash.combine(PGOHash::EndOfScope); return true; @@ -473,8 +471,8 @@ struct MapRegionCounters : public RecursiveASTVisitor { // stability, define a custom traversal which tracks the end of the statement // in the hash (provided we're not using the V1 hash). #define DEFINE_NESTABLE_TRAVERSAL(N) \ - bool Traverse##N(N *S) { \ - Base::Traverse##N(S); \ + bool Traverse##N(N *S) override { \ + DynamicRecursiveASTVisitor::Traverse##N(S); \ if (Hash.getHashVersion() != PGO_HASH_V1) \ Hash.combine(PGOHash::EndOfScope); \ return true; \ diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp index 3a1f745d9ed77..848030dd30006 100644 --- a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp +++ b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp @@ -11,8 +11,8 @@ #include "CodeGenModule.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/TargetInfo.h" @@ -58,7 +58,7 @@ class PCHContainerGenerator : public ASTConsumer { std::shared_ptr Buffer; /// Visit every type and emit debug info for it. - struct DebugTypeVisitor : public RecursiveASTVisitor { + struct DebugTypeVisitor final : DynamicRecursiveASTVisitor { clang::CodeGen::CGDebugInfo &DI; ASTContext &Ctx; DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx) @@ -69,13 +69,13 @@ class PCHContainerGenerator : public ASTConsumer { return !Ty->isDependentType() && !Ty->isUndeducedType(); } - bool VisitImportDecl(ImportDecl *D) { + bool VisitImportDecl(ImportDecl *D) override { if (!D->getImportedOwningModule()) DI.EmitImportDecl(*D); return true; } - bool VisitTypeDecl(TypeDecl *D) { + bool VisitTypeDecl(TypeDecl *D) override { // TagDecls may be deferred until after all decls have been merged and we // know the complete type. Pure forward declarations will be skipped, but // they don't need to be emitted into the module anyway. @@ -89,14 +89,14 @@ class PCHContainerGenerator : public ASTConsumer { return true; } - bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { + bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) override { QualType QualTy(D->getTypeForDecl(), 0); if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) DI.getOrCreateStandaloneType(QualTy, D->getLocation()); return true; } - bool VisitFunctionDecl(FunctionDecl *D) { + bool VisitFunctionDecl(FunctionDecl *D) override { // Skip deduction guides. if (isa(D)) return true; @@ -117,7 +117,7 @@ class PCHContainerGenerator : public ASTConsumer { return true; } - bool VisitObjCMethodDecl(ObjCMethodDecl *D) { + bool VisitObjCMethodDecl(ObjCMethodDecl *D) override { if (!D->getClassInterface()) return true; diff --git a/clang/lib/Frontend/ASTConsumers.cpp b/clang/lib/Frontend/ASTConsumers.cpp index 7b58eaa04df95..180075119db0c 100644 --- a/clang/lib/Frontend/ASTConsumers.cpp +++ b/clang/lib/Frontend/ASTConsumers.cpp @@ -14,9 +14,9 @@ #include "clang/AST/AST.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/RecordLayout.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/Path.h" @@ -28,132 +28,129 @@ using namespace clang; /// ASTPrinter - Pretty-printer and dumper of ASTs namespace { - class ASTPrinter : public ASTConsumer, - public RecursiveASTVisitor { - typedef RecursiveASTVisitor base; - - public: - enum Kind { DumpFull, Dump, Print, None }; - ASTPrinter(std::unique_ptr Out, Kind K, - ASTDumpOutputFormat Format, StringRef FilterString, - bool DumpLookups = false, bool DumpDeclTypes = false) - : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)), - OutputKind(K), OutputFormat(Format), FilterString(FilterString), - DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {} - - void HandleTranslationUnit(ASTContext &Context) override { - TranslationUnitDecl *D = Context.getTranslationUnitDecl(); - - if (FilterString.empty()) - return print(D); - - TraverseDecl(D); - } +class ASTPrinter : public ASTConsumer, public DynamicRecursiveASTVisitor { +public: + enum Kind { DumpFull, Dump, Print, None }; + ASTPrinter(std::unique_ptr Out, Kind K, + ASTDumpOutputFormat Format, StringRef FilterString, + bool DumpLookups = false, bool DumpDeclTypes = false) + : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)), OutputKind(K), + OutputFormat(Format), FilterString(FilterString), + DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) { + ShouldWalkTypesOfTypeLocs = false; + } - bool shouldWalkTypesOfTypeLocs() const { return false; } - - bool TraverseDecl(Decl *D) { - if (D && filterMatches(D)) { - bool ShowColors = Out.has_colors(); - if (ShowColors) - Out.changeColor(raw_ostream::BLUE); - - if (OutputFormat == ADOF_Default) - Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D) - << ":\n"; - - if (ShowColors) - Out.resetColor(); - print(D); - Out << "\n"; - // Don't traverse child nodes to avoid output duplication. - return true; - } - return base::TraverseDecl(D); - } + void HandleTranslationUnit(ASTContext &Context) override { + TranslationUnitDecl *D = Context.getTranslationUnitDecl(); - private: - std::string getName(Decl *D) { - if (isa(D)) - return cast(D)->getQualifiedNameAsString(); - return ""; - } - bool filterMatches(Decl *D) { - return getName(D).find(FilterString) != std::string::npos; + if (FilterString.empty()) + return print(D); + + TraverseDecl(D); + } + + bool TraverseDecl(Decl *D) override { + if (D && filterMatches(D)) { + bool ShowColors = Out.has_colors(); + if (ShowColors) + Out.changeColor(raw_ostream::BLUE); + + if (OutputFormat == ADOF_Default) + Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D) + << ":\n"; + + if (ShowColors) + Out.resetColor(); + print(D); + Out << "\n"; + // Don't traverse child nodes to avoid output duplication. + return true; } - void print(Decl *D) { - if (DumpLookups) { - if (DeclContext *DC = dyn_cast(D)) { - if (DC == DC->getPrimaryContext()) - DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull); - else - Out << "Lookup map is in primary DeclContext " - << DC->getPrimaryContext() << "\n"; - } else - Out << "Not a DeclContext\n"; - } else if (OutputKind == Print) { - PrintingPolicy Policy(D->getASTContext().getLangOpts()); - D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true); - } else if (OutputKind != None) { - D->dump(Out, OutputKind == DumpFull, OutputFormat); - } - - if (DumpDeclTypes) { - Decl *InnerD = D; - if (auto *TD = dyn_cast(D)) - InnerD = TD->getTemplatedDecl(); - - // FIXME: Support OutputFormat in type dumping. - // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups. - if (auto *VD = dyn_cast(InnerD)) - VD->getType().dump(Out, VD->getASTContext()); - if (auto *TD = dyn_cast(InnerD)) - TD->getTypeForDecl()->dump(Out, TD->getASTContext()); - } + return DynamicRecursiveASTVisitor::TraverseDecl(D); + } + +private: + std::string getName(Decl *D) { + if (isa(D)) + return cast(D)->getQualifiedNameAsString(); + return ""; + } + bool filterMatches(Decl *D) { + return getName(D).find(FilterString) != std::string::npos; + } + void print(Decl *D) { + if (DumpLookups) { + if (DeclContext *DC = dyn_cast(D)) { + if (DC == DC->getPrimaryContext()) + DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull); + else + Out << "Lookup map is in primary DeclContext " + << DC->getPrimaryContext() << "\n"; + } else + Out << "Not a DeclContext\n"; + } else if (OutputKind == Print) { + PrintingPolicy Policy(D->getASTContext().getLangOpts()); + D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true); + } else if (OutputKind != None) { + D->dump(Out, OutputKind == DumpFull, OutputFormat); } - raw_ostream &Out; - std::unique_ptr OwnedOut; + if (DumpDeclTypes) { + Decl *InnerD = D; + if (auto *TD = dyn_cast(D)) + InnerD = TD->getTemplatedDecl(); + + // FIXME: Support OutputFormat in type dumping. + // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups. + if (auto *VD = dyn_cast(InnerD)) + VD->getType().dump(Out, VD->getASTContext()); + if (auto *TD = dyn_cast(InnerD)) + TD->getTypeForDecl()->dump(Out, TD->getASTContext()); + } + } - /// How to output individual declarations. - Kind OutputKind; + raw_ostream &Out; + std::unique_ptr OwnedOut; - /// What format should the output take? - ASTDumpOutputFormat OutputFormat; + /// How to output individual declarations. + Kind OutputKind; - /// Which declarations or DeclContexts to display. - std::string FilterString; + /// What format should the output take? + ASTDumpOutputFormat OutputFormat; - /// Whether the primary output is lookup results or declarations. Individual - /// results will be output with a format determined by OutputKind. This is - /// incompatible with OutputKind == Print. - bool DumpLookups; + /// Which declarations or DeclContexts to display. + std::string FilterString; - /// Whether to dump the type for each declaration dumped. - bool DumpDeclTypes; - }; + /// Whether the primary output is lookup results or declarations. Individual + /// results will be output with a format determined by OutputKind. This is + /// incompatible with OutputKind == Print. + bool DumpLookups; - class ASTDeclNodeLister : public ASTConsumer, - public RecursiveASTVisitor { - public: - ASTDeclNodeLister(raw_ostream *Out = nullptr) - : Out(Out ? *Out : llvm::outs()) {} + /// Whether to dump the type for each declaration dumped. + bool DumpDeclTypes; +}; - void HandleTranslationUnit(ASTContext &Context) override { - TraverseDecl(Context.getTranslationUnitDecl()); - } +class ASTDeclNodeLister : public ASTConsumer, + public DynamicRecursiveASTVisitor { +public: + ASTDeclNodeLister(raw_ostream *Out = nullptr) + : Out(Out ? *Out : llvm::outs()) { + ShouldWalkTypesOfTypeLocs = false; + } - bool shouldWalkTypesOfTypeLocs() const { return false; } + void HandleTranslationUnit(ASTContext &Context) override { + TraverseDecl(Context.getTranslationUnitDecl()); + } - bool VisitNamedDecl(NamedDecl *D) { - D->printQualifiedName(Out); - Out << '\n'; - return true; - } + bool VisitNamedDecl(NamedDecl *D) override { + D->printQualifiedName(Out); + Out << '\n'; + return true; + } - private: - raw_ostream &Out; - }; +private: + raw_ostream &Out; +}; } // end anonymous namespace std::unique_ptr diff --git a/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp b/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp index d7cfd23bb0a7a..9644fe732889f 100644 --- a/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp +++ b/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Mangle.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/TargetInfo.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" @@ -242,8 +242,8 @@ class InterfaceStubFunctionsConsumer : public ASTConsumer { : Instance(Instance), InFile(InFile), Format(Format) {} void HandleTranslationUnit(ASTContext &context) override { - struct Visitor : public RecursiveASTVisitor { - bool VisitNamedDecl(NamedDecl *ND) { + struct Visitor final : DynamicRecursiveASTVisitor { + bool VisitNamedDecl(NamedDecl *ND) override { if (const auto *FD = dyn_cast(ND)) if (FD->isLateTemplateParsed()) { LateParsedDecls.insert(FD); diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp index c18daf7faa749..215605b45c411 100644 --- a/clang/lib/Index/IndexBody.cpp +++ b/clang/lib/Index/IndexBody.cpp @@ -10,8 +10,10 @@ #include "clang/AST/ASTConcept.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/ExprConcepts.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/Type.h" using namespace clang; @@ -19,41 +21,39 @@ using namespace clang::index; namespace { -class BodyIndexer : public RecursiveASTVisitor { +class BodyIndexer final : public DynamicRecursiveASTVisitor { IndexingContext &IndexCtx; const NamedDecl *Parent; const DeclContext *ParentDC; SmallVector StmtStack; - typedef RecursiveASTVisitor base; - Stmt *getParentStmt() const { return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2]; } public: - BodyIndexer(IndexingContext &indexCtx, - const NamedDecl *Parent, const DeclContext *DC) - : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } - - bool shouldWalkTypesOfTypeLocs() const { return false; } + BodyIndexer(IndexingContext &indexCtx, const NamedDecl *Parent, + const DeclContext *DC) + : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { + ShouldWalkTypesOfTypeLocs = false; + } - bool dataTraverseStmtPre(Stmt *S) { + bool dataTraverseStmtPre(Stmt *S) override { StmtStack.push_back(S); return true; } - bool dataTraverseStmtPost(Stmt *S) { + bool dataTraverseStmtPost(Stmt *S) override { assert(StmtStack.back() == S); StmtStack.pop_back(); return true; } - bool TraverseTypeLoc(TypeLoc TL) { + bool TraverseTypeLoc(TypeLoc TL) override { IndexCtx.indexTypeLoc(TL, Parent, ParentDC); return true; } - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override { IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); return true; } @@ -137,25 +137,25 @@ class BodyIndexer : public RecursiveASTVisitor { Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD); } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { SmallVector Relations; SymbolRoleSet Roles = getRolesForRef(E, Relations); return IndexCtx.handleReference(E->getDecl(), E->getLocation(), Parent, ParentDC, Roles, Relations, E); } - bool VisitGotoStmt(GotoStmt *S) { + bool VisitGotoStmt(GotoStmt *S) override { return IndexCtx.handleReference(S->getLabel(), S->getLabelLoc(), Parent, ParentDC); } - bool VisitLabelStmt(LabelStmt *S) { + bool VisitLabelStmt(LabelStmt *S) override { if (IndexCtx.shouldIndexFunctionLocalSymbols()) return IndexCtx.handleDecl(S->getDecl()); return true; } - bool VisitMemberExpr(MemberExpr *E) { + bool VisitMemberExpr(MemberExpr *E) override { SourceLocation Loc = E->getMemberLoc(); if (Loc.isInvalid()) Loc = E->getBeginLoc(); @@ -197,14 +197,15 @@ class BodyIndexer : public RecursiveASTVisitor { Relations, E); } - bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { + bool + VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) override { const DeclarationNameInfo &Info = E->getMemberNameInfo(); return indexDependentReference( E, E->getBaseType().getTypePtrOrNull(), Info, [](const NamedDecl *D) { return D->isCXXInstanceMember(); }); } - bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { + bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) override { const DeclarationNameInfo &Info = E->getNameInfo(); const NestedNameSpecifier *NNS = E->getQualifier(); return indexDependentReference( @@ -212,7 +213,7 @@ class BodyIndexer : public RecursiveASTVisitor { [](const NamedDecl *D) { return !D->isCXXInstanceMember(); }); } - bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { + bool VisitDesignatedInitExpr(DesignatedInitExpr *E) override { for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { if (D.isFieldDesignator()) { if (const FieldDecl *FD = D.getFieldDecl()) { @@ -224,14 +225,14 @@ class BodyIndexer : public RecursiveASTVisitor { return true; } - bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) override { SmallVector Relations; SymbolRoleSet Roles = getRolesForRef(E, Relations); return IndexCtx.handleReference(E->getDecl(), E->getLocation(), Parent, ParentDC, Roles, Relations, E); } - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + bool VisitObjCMessageExpr(ObjCMessageExpr *E) override { auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool { if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance) return false; @@ -303,7 +304,7 @@ class BodyIndexer : public RecursiveASTVisitor { return true; } - bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { + bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) override { if (E->isExplicitProperty()) { SmallVector Relations; SymbolRoleSet Roles = getRolesForRef(E, Relations); @@ -328,12 +329,12 @@ class BodyIndexer : public RecursiveASTVisitor { return true; } - bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { + bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) override { return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent, ParentDC, SymbolRoleSet(), {}, E); } - bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { + bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) override { return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), Parent, ParentDC, SymbolRoleSet(), {}, E); } @@ -347,28 +348,28 @@ class BodyIndexer : public RecursiveASTVisitor { Roles, Relations, E); } - bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { + bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) override { if (ObjCMethodDecl *MD = E->getBoxingMethod()) { return passObjCLiteralMethodCall(MD, E); } return true; } - bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { + bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) override { if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) { return passObjCLiteralMethodCall(MD, E); } return true; } - bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { + bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) override { if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) { return passObjCLiteralMethodCall(MD, E); } return true; } - bool VisitCXXConstructExpr(CXXConstructExpr *E) { + bool VisitCXXConstructExpr(CXXConstructExpr *E) override { SymbolRoleSet Roles{}; SmallVector Relations; addCallRole(Roles, Relations); @@ -376,14 +377,13 @@ class BodyIndexer : public RecursiveASTVisitor { Parent, ParentDC, Roles, Relations, E); } - bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E, - DataRecursionQueue *Q = nullptr) { + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) override { if (E->getOperatorLoc().isInvalid()) return true; // implicit. - return base::TraverseCXXOperatorCallExpr(E, Q); + return DynamicRecursiveASTVisitor::TraverseCXXOperatorCallExpr(E); } - bool VisitDeclStmt(DeclStmt *S) { + bool VisitDeclStmt(DeclStmt *S) override { if (IndexCtx.shouldIndexFunctionLocalSymbols()) { IndexCtx.indexDeclGroupRef(S->getDeclGroup()); return true; @@ -402,11 +402,11 @@ class BodyIndexer : public RecursiveASTVisitor { } bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, - Expr *Init) { + Expr *Init) override { if (C->capturesThis() || C->capturesVLAType()) return true; - if (!base::TraverseStmt(Init)) + if (!DynamicRecursiveASTVisitor::TraverseStmt(Init)) return false; if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) @@ -420,10 +420,10 @@ class BodyIndexer : public RecursiveASTVisitor { // the things that we visit. Make sure to only visit the semantic form. // Also visit things that are in the syntactic form but not the semantic one, // for example the indices in DesignatedInitExprs. - bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) { + bool TraverseInitListExpr(InitListExpr *S) override { auto visitForm = [&](InitListExpr *Form) { for (Stmt *SubStmt : Form->children()) { - if (!TraverseStmt(SubStmt, Q)) + if (!TraverseStmt(SubStmt)) return false; } return true; @@ -464,7 +464,7 @@ class BodyIndexer : public RecursiveASTVisitor { return true; } - bool VisitOffsetOfExpr(OffsetOfExpr *S) { + bool VisitOffsetOfExpr(OffsetOfExpr *S) override { for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) { const OffsetOfNode &Component = S->getComponent(I); if (Component.getKind() == OffsetOfNode::Field) @@ -475,7 +475,7 @@ class BodyIndexer : public RecursiveASTVisitor { return true; } - bool VisitParmVarDecl(ParmVarDecl* D) { + bool VisitParmVarDecl(ParmVarDecl *D) override { // Index the parameters of lambda expression and requires expression. if (IndexCtx.shouldIndexFunctionLocalSymbols()) { const auto *DC = D->getDeclContext(); @@ -485,7 +485,7 @@ class BodyIndexer : public RecursiveASTVisitor { return true; } - bool VisitOverloadExpr(OverloadExpr *E) { + bool VisitOverloadExpr(OverloadExpr *E) override { SmallVector Relations; SymbolRoleSet Roles = getRolesForRef(E, Relations); for (auto *D : E->decls()) @@ -494,16 +494,16 @@ class BodyIndexer : public RecursiveASTVisitor { return true; } - bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) { + bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) override { IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(), Parent, ParentDC); return true; } - bool TraverseTypeConstraint(const TypeConstraint *C) { + bool TraverseTypeConstraint(const TypeConstraint *C) override { IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(), Parent, ParentDC); - return RecursiveASTVisitor::TraverseTypeConstraint(C); + return DynamicRecursiveASTVisitor::TraverseTypeConstraint(C); } }; diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp index b986ccde57452..0abcc2e343a88 100644 --- a/clang/lib/Index/IndexTypeSourceInfo.cpp +++ b/clang/lib/Index/IndexTypeSourceInfo.cpp @@ -8,8 +8,9 @@ #include "IndexingContext.h" #include "clang/AST/ASTConcept.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/PrettyPrinter.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" #include "llvm/ADT/ScopeExit.h" @@ -18,15 +19,13 @@ using namespace index; namespace { -class TypeIndexer : public RecursiveASTVisitor { +class TypeIndexer final : public DynamicRecursiveASTVisitor { IndexingContext &IndexCtx; const NamedDecl *Parent; const DeclContext *ParentDC; bool IsBase; SmallVector Relations; - typedef RecursiveASTVisitor base; - public: TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent, const DeclContext *DC, bool isBase, bool isIBType) @@ -39,9 +38,9 @@ class TypeIndexer : public RecursiveASTVisitor { assert(Parent); Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent); } - } - bool shouldWalkTypesOfTypeLocs() const { return false; } + ShouldWalkTypesOfTypeLocs = false; + } #define TRY_TO(CALL_EXPR) \ do { \ @@ -49,14 +48,14 @@ class TypeIndexer : public RecursiveASTVisitor { return false; \ } while (0) - bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) { + bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) override { SourceLocation Loc = TTPL.getNameLoc(); TemplateTypeParmDecl *TTPD = TTPL.getDecl(); return IndexCtx.handleReference(TTPD, Loc, Parent, ParentDC, SymbolRoleSet()); } - bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { + bool VisitTypedefTypeLoc(TypedefTypeLoc TL) override { SourceLocation Loc = TL.getNameLoc(); TypedefNameDecl *ND = TL.getTypedefNameDecl(); if (ND->isTransparentTag()) { @@ -80,7 +79,7 @@ class TypeIndexer : public RecursiveASTVisitor { return true; } - bool VisitAutoTypeLoc(AutoTypeLoc TL) { + bool VisitAutoTypeLoc(AutoTypeLoc TL) override { if (auto *C = TL.getNamedConcept()) return IndexCtx.handleReference(C, TL.getConceptNameLoc(), Parent, ParentDC); @@ -94,7 +93,7 @@ class TypeIndexer : public RecursiveASTVisitor { return true; } - bool TraverseParmVarDecl(ParmVarDecl *D) { + bool TraverseParmVarDecl(ParmVarDecl *D) override { // Avoid visiting default arguments from the definition that were already // visited in the declaration. // FIXME: A free function definition can have default arguments. @@ -107,15 +106,15 @@ class TypeIndexer : public RecursiveASTVisitor { } } - return base::TraverseParmVarDecl(D); + return DynamicRecursiveASTVisitor::TraverseParmVarDecl(D); } - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override { IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); return true; } - bool VisitTagTypeLoc(TagTypeLoc TL) { + bool VisitTagTypeLoc(TagTypeLoc TL) override { TagDecl *D = TL.getDecl(); if (!IndexCtx.shouldIndexFunctionLocalSymbols() && D->getParentFunctionOrMethod()) @@ -131,12 +130,12 @@ class TypeIndexer : public RecursiveASTVisitor { Relations); } - bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { + bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) override { return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(), Parent, ParentDC, SymbolRoleSet(), Relations); } - bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { + bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) override { for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) { IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i), Parent, ParentDC, SymbolRoleSet(), Relations); @@ -161,7 +160,8 @@ class TypeIndexer : public RecursiveASTVisitor { } } - bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { + bool VisitTemplateSpecializationTypeLoc( + TemplateSpecializationTypeLoc TL) override { auto *T = TL.getTypePtr(); if (!T) return true; @@ -171,7 +171,8 @@ class TypeIndexer : public RecursiveASTVisitor { return true; } - bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { + bool TraverseTemplateSpecializationTypeLoc( + TemplateSpecializationTypeLoc TL) override { if (!WalkUpFromTemplateSpecializationTypeLoc(TL)) return false; if (!TraverseTemplateName(TL.getTypePtr()->getTemplateName())) @@ -191,7 +192,8 @@ class TypeIndexer : public RecursiveASTVisitor { return true; } - bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) { + bool VisitDeducedTemplateSpecializationTypeLoc( + DeducedTemplateSpecializationTypeLoc TL) override { auto *T = TL.getTypePtr(); if (!T) return true; @@ -201,12 +203,12 @@ class TypeIndexer : public RecursiveASTVisitor { return true; } - bool VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { + bool VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) override { return IndexCtx.handleReference(TL.getDecl(), TL.getNameLoc(), Parent, ParentDC, SymbolRoleSet(), Relations); } - bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { + bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) override { const DependentNameType *DNT = TL.getTypePtr(); const NestedNameSpecifier *NNS = DNT->getQualifier(); const Type *T = NNS->getAsType(); @@ -234,7 +236,7 @@ class TypeIndexer : public RecursiveASTVisitor { ParentDC, SymbolRoleSet(), Relations); } - bool TraverseStmt(Stmt *S) { + bool TraverseStmt(Stmt *S) override { IndexCtx.indexBody(S, Parent, ParentDC); return true; } diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp index a73ea0b0d124c..6b1951c54fe17 100644 --- a/clang/lib/InstallAPI/Visitor.cpp +++ b/clang/lib/InstallAPI/Visitor.cpp @@ -163,7 +163,7 @@ void InstallAPIVisitor::recordObjCInstanceVariables( } } -bool InstallAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { +bool InstallAPIVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // Skip forward declaration for classes (@class) if (!D->isThisDeclarationADefinition()) return true; @@ -195,7 +195,7 @@ bool InstallAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { return true; } -bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { +bool InstallAPIVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { StringRef CategoryName = D->getName(); // Skip over declarations that access could not be collected for. auto Access = getAccessForDecl(D); @@ -213,7 +213,7 @@ bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { return true; } -bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) { +bool InstallAPIVisitor::VisitVarDecl(VarDecl *D) { // Skip function parameters. if (isa(D)) return true; @@ -248,7 +248,7 @@ bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) { return true; } -bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) { +bool InstallAPIVisitor::VisitFunctionDecl(FunctionDecl *D) { if (const CXXMethodDecl *M = dyn_cast(D)) { // Skip member function in class templates. if (M->getParent()->getDescribedClassTemplate() != nullptr) @@ -554,7 +554,7 @@ void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D, } } -bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) { +bool InstallAPIVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) { if (!D->isCompleteDefinition()) return true; diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index e6ce89dc7ec40..3b3f3f21986ba 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -16,13 +16,13 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" @@ -1067,81 +1067,79 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, } namespace { - class FallthroughMapper : public RecursiveASTVisitor { - public: - FallthroughMapper(Sema &S) - : FoundSwitchStatements(false), - S(S) { - } +class FallthroughMapper final : public DynamicRecursiveASTVisitor { +public: + FallthroughMapper(Sema &S) : FoundSwitchStatements(false), S(S) { + ShouldWalkTypesOfTypeLocs = false; + } - bool foundSwitchStatements() const { return FoundSwitchStatements; } + bool foundSwitchStatements() const { return FoundSwitchStatements; } - void markFallthroughVisited(const AttributedStmt *Stmt) { - bool Found = FallthroughStmts.erase(Stmt); - assert(Found); - (void)Found; - } + void markFallthroughVisited(const AttributedStmt *Stmt) { + bool Found = FallthroughStmts.erase(Stmt); + assert(Found); + (void)Found; + } + + typedef llvm::SmallPtrSet AttrStmts; - typedef llvm::SmallPtrSet AttrStmts; + const AttrStmts &getFallthroughStmts() const { return FallthroughStmts; } - const AttrStmts &getFallthroughStmts() const { - return FallthroughStmts; + void fillReachableBlocks(CFG *Cfg) { + assert(ReachableBlocks.empty() && "ReachableBlocks already filled"); + std::deque BlockQueue; + + ReachableBlocks.insert(&Cfg->getEntry()); + BlockQueue.push_back(&Cfg->getEntry()); + // Mark all case blocks reachable to avoid problems with switching on + // constants, covered enums, etc. + // These blocks can contain fall-through annotations, and we don't want to + // issue a warn_fallthrough_attr_unreachable for them. + for (const auto *B : *Cfg) { + const Stmt *L = B->getLabel(); + if (isa_and_nonnull(L) && ReachableBlocks.insert(B).second) + BlockQueue.push_back(B); } - void fillReachableBlocks(CFG *Cfg) { - assert(ReachableBlocks.empty() && "ReachableBlocks already filled"); - std::deque BlockQueue; - - ReachableBlocks.insert(&Cfg->getEntry()); - BlockQueue.push_back(&Cfg->getEntry()); - // Mark all case blocks reachable to avoid problems with switching on - // constants, covered enums, etc. - // These blocks can contain fall-through annotations, and we don't want to - // issue a warn_fallthrough_attr_unreachable for them. - for (const auto *B : *Cfg) { - const Stmt *L = B->getLabel(); - if (isa_and_nonnull(L) && ReachableBlocks.insert(B).second) + while (!BlockQueue.empty()) { + const CFGBlock *P = BlockQueue.front(); + BlockQueue.pop_front(); + for (const CFGBlock *B : P->succs()) { + if (B && ReachableBlocks.insert(B).second) BlockQueue.push_back(B); } - - while (!BlockQueue.empty()) { - const CFGBlock *P = BlockQueue.front(); - BlockQueue.pop_front(); - for (const CFGBlock *B : P->succs()) { - if (B && ReachableBlocks.insert(B).second) - BlockQueue.push_back(B); - } - } } + } - bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt, - bool IsTemplateInstantiation) { - assert(!ReachableBlocks.empty() && "ReachableBlocks empty"); + bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt, + bool IsTemplateInstantiation) { + assert(!ReachableBlocks.empty() && "ReachableBlocks empty"); - int UnannotatedCnt = 0; - AnnotatedCnt = 0; + int UnannotatedCnt = 0; + AnnotatedCnt = 0; - std::deque BlockQueue(B.pred_begin(), B.pred_end()); - while (!BlockQueue.empty()) { - const CFGBlock *P = BlockQueue.front(); - BlockQueue.pop_front(); - if (!P) continue; + std::deque BlockQueue(B.pred_begin(), B.pred_end()); + while (!BlockQueue.empty()) { + const CFGBlock *P = BlockQueue.front(); + BlockQueue.pop_front(); + if (!P) + continue; - const Stmt *Term = P->getTerminatorStmt(); - if (isa_and_nonnull(Term)) - continue; // Switch statement, good. + const Stmt *Term = P->getTerminatorStmt(); + if (isa_and_nonnull(Term)) + continue; // Switch statement, good. - const SwitchCase *SW = dyn_cast_or_null(P->getLabel()); - if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end()) - continue; // Previous case label has no statements, good. + const SwitchCase *SW = dyn_cast_or_null(P->getLabel()); + if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end()) + continue; // Previous case label has no statements, good. - const LabelStmt *L = dyn_cast_or_null(P->getLabel()); - if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end()) - continue; // Case label is preceded with a normal label, good. + const LabelStmt *L = dyn_cast_or_null(P->getLabel()); + if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end()) + continue; // Case label is preceded with a normal label, good. - if (!ReachableBlocks.count(P)) { - for (const CFGElement &Elem : llvm::reverse(*P)) { - if (std::optional CS = Elem.getAs()) { + if (!ReachableBlocks.count(P)) { + for (const CFGElement &Elem : llvm::reverse(*P)) { + if (std::optional CS = Elem.getAs()) { if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) { // Don't issue a warning for an unreachable fallthrough // attribute in template instantiations as it may not be @@ -1154,95 +1152,91 @@ namespace { break; } // Don't care about other unreachable statements. - } } - // If there are no unreachable statements, this may be a special - // case in CFG: - // case X: { - // A a; // A has a destructor. - // break; - // } - // // <<<< This place is represented by a 'hanging' CFG block. - // case Y: - continue; - } - - const Stmt *LastStmt = getLastStmt(*P); - if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) { - markFallthroughVisited(AS); - ++AnnotatedCnt; - continue; // Fallthrough annotation, good. - } - - if (!LastStmt) { // This block contains no executable statements. - // Traverse its predecessors. - std::copy(P->pred_begin(), P->pred_end(), - std::back_inserter(BlockQueue)); - continue; } + // If there are no unreachable statements, this may be a special + // case in CFG: + // case X: { + // A a; // A has a destructor. + // break; + // } + // // <<<< This place is represented by a 'hanging' CFG block. + // case Y: + continue; + } - ++UnannotatedCnt; + const Stmt *LastStmt = getLastStmt(*P); + if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) { + markFallthroughVisited(AS); + ++AnnotatedCnt; + continue; // Fallthrough annotation, good. } - return !!UnannotatedCnt; - } - // RecursiveASTVisitor setup. - bool shouldWalkTypesOfTypeLocs() const { return false; } + if (!LastStmt) { // This block contains no executable statements. + // Traverse its predecessors. + std::copy(P->pred_begin(), P->pred_end(), + std::back_inserter(BlockQueue)); + continue; + } - bool VisitAttributedStmt(AttributedStmt *S) { - if (asFallThroughAttr(S)) - FallthroughStmts.insert(S); - return true; + ++UnannotatedCnt; } + return !!UnannotatedCnt; + } - bool VisitSwitchStmt(SwitchStmt *S) { - FoundSwitchStatements = true; - return true; - } + bool VisitAttributedStmt(AttributedStmt *S) override { + if (asFallThroughAttr(S)) + FallthroughStmts.insert(S); + return true; + } - // We don't want to traverse local type declarations. We analyze their - // methods separately. - bool TraverseDecl(Decl *D) { return true; } + bool VisitSwitchStmt(SwitchStmt *S) override { + FoundSwitchStatements = true; + return true; + } - // We analyze lambda bodies separately. Skip them here. - bool TraverseLambdaExpr(LambdaExpr *LE) { - // Traverse the captures, but not the body. - for (const auto C : zip(LE->captures(), LE->capture_inits())) - TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C)); - return true; - } + // We don't want to traverse local type declarations. We analyze their + // methods separately. + bool TraverseDecl(Decl *D) override { return true; } - private: + // We analyze lambda bodies separately. Skip them here. + bool TraverseLambdaExpr(LambdaExpr *LE) override { + // Traverse the captures, but not the body. + for (const auto C : zip(LE->captures(), LE->capture_inits())) + TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C)); + return true; + } - static const AttributedStmt *asFallThroughAttr(const Stmt *S) { - if (const AttributedStmt *AS = dyn_cast_or_null(S)) { - if (hasSpecificAttr(AS->getAttrs())) - return AS; - } - return nullptr; +private: + static const AttributedStmt *asFallThroughAttr(const Stmt *S) { + if (const AttributedStmt *AS = dyn_cast_or_null(S)) { + if (hasSpecificAttr(AS->getAttrs())) + return AS; } + return nullptr; + } - static const Stmt *getLastStmt(const CFGBlock &B) { - if (const Stmt *Term = B.getTerminatorStmt()) - return Term; - for (const CFGElement &Elem : llvm::reverse(B)) - if (std::optional CS = Elem.getAs()) - return CS->getStmt(); - // Workaround to detect a statement thrown out by CFGBuilder: - // case X: {} case Y: - // case X: ; case Y: - if (const SwitchCase *SW = dyn_cast_or_null(B.getLabel())) - if (!isa(SW->getSubStmt())) - return SW->getSubStmt(); - - return nullptr; - } + static const Stmt *getLastStmt(const CFGBlock &B) { + if (const Stmt *Term = B.getTerminatorStmt()) + return Term; + for (const CFGElement &Elem : llvm::reverse(B)) + if (std::optional CS = Elem.getAs()) + return CS->getStmt(); + // Workaround to detect a statement thrown out by CFGBuilder: + // case X: {} case Y: + // case X: ; case Y: + if (const SwitchCase *SW = dyn_cast_or_null(B.getLabel())) + if (!isa(SW->getSubStmt())) + return SW->getSubStmt(); - bool FoundSwitchStatements; - AttrStmts FallthroughStmts; - Sema &S; - llvm::SmallPtrSet ReachableBlocks; - }; + return nullptr; + } + + bool FoundSwitchStatements; + AttrStmts FallthroughStmts; + Sema &S; + llvm::SmallPtrSet ReachableBlocks; +}; } // anonymous namespace static StringRef getFallthroughAttrSpelling(Preprocessor &PP, @@ -2475,15 +2469,18 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { // An AST Visitor that calls a callback function on each callable DEFINITION // that is NOT in a dependent context: -class CallableVisitor : public RecursiveASTVisitor { +class CallableVisitor final : public DynamicRecursiveASTVisitor { private: llvm::function_ref Callback; public: CallableVisitor(llvm::function_ref Callback) - : Callback(Callback) {} + : Callback(Callback) { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; + } - bool VisitFunctionDecl(FunctionDecl *Node) { + bool VisitFunctionDecl(FunctionDecl *Node) override { if (cast(Node)->isDependentContext()) return true; // Not to analyze dependent decl // `FunctionDecl->hasBody()` returns true if the function has a body @@ -2494,14 +2491,14 @@ class CallableVisitor : public RecursiveASTVisitor { return true; } - bool VisitBlockDecl(BlockDecl *Node) { + bool VisitBlockDecl(BlockDecl *Node) override { if (cast(Node)->isDependentContext()) return true; // Not to analyze dependent decl Callback(Node); return true; } - bool VisitObjCMethodDecl(ObjCMethodDecl *Node) { + bool VisitObjCMethodDecl(ObjCMethodDecl *Node) override { if (cast(Node)->isDependentContext()) return true; // Not to analyze dependent decl if (Node->hasBody()) @@ -2509,12 +2506,9 @@ class CallableVisitor : public RecursiveASTVisitor { return true; } - bool VisitLambdaExpr(LambdaExpr *Node) { + bool VisitLambdaExpr(LambdaExpr *Node) override { return VisitFunctionDecl(Node->getCallOperator()); } - - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } }; void clang::sema::AnalysisBasedWarnings::IssueWarnings( diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 17566c226ec80..f23cd73037e04 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -12,8 +12,11 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/StmtObjC.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" @@ -716,11 +719,11 @@ bool isBodyLikeChildStmt(const Stmt *S, const Stmt *Parent) { } } -class StmtUSEFinder : public RecursiveASTVisitor { +class StmtUSEFinder final : public DynamicRecursiveASTVisitor { const Stmt *Target; public: - bool VisitStmt(Stmt *S) { return S != Target; } + bool VisitStmt(Stmt *S) override { return S != Target; } /// Returns true if the given statement is present in the given declaration. static bool isContained(const Stmt *Target, const Decl *D) { @@ -732,11 +735,11 @@ class StmtUSEFinder : public RecursiveASTVisitor { /// Traverses the AST and finds the last statement that used a given /// declaration. -class LastDeclUSEFinder : public RecursiveASTVisitor { +class LastDeclUSEFinder final : public DynamicRecursiveASTVisitor { const Decl *D; public: - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { if (DRE->getDecl() == D) return false; return true; @@ -760,10 +763,7 @@ class LastDeclUSEFinder : public RecursiveASTVisitor { /// to a partially available declaration. Whenever we encounter an \c if of the /// form: \c if(@available(...)), we use the version from the condition to visit /// the then statement. -class DiagnoseUnguardedAvailability - : public RecursiveASTVisitor { - typedef RecursiveASTVisitor Base; - +class DiagnoseUnguardedAvailability final : public DynamicRecursiveASTVisitor { Sema &SemaRef; Decl *Ctx; @@ -781,26 +781,30 @@ class DiagnoseUnguardedAvailability SemaRef.Context.getTargetInfo().getPlatformMinVersion()); } - bool TraverseStmt(Stmt *S) { + bool TraverseStmt(Stmt *S) override { if (!S) return true; StmtStack.push_back(S); - bool Result = Base::TraverseStmt(S); + bool Result = DynamicRecursiveASTVisitor::TraverseStmt(S); StmtStack.pop_back(); return Result; } void IssueDiagnostics(Stmt *S) { TraverseStmt(S); } - bool TraverseIfStmt(IfStmt *If); + bool TraverseIfStmt(IfStmt *If) override; // for 'case X:' statements, don't bother looking at the 'X'; it can't lead // to any useful diagnostics. - bool TraverseCaseStmt(CaseStmt *CS) { return TraverseStmt(CS->getSubStmt()); } + bool TraverseCaseStmt(CaseStmt *CS) override { + return TraverseStmt(CS->getSubStmt()); + } - bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) { return true; } + bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) override { + return true; + } - bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) { + bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) override { if (ObjCMethodDecl *D = Msg->getMethodDecl()) { ObjCInterfaceDecl *ID = nullptr; QualType ReceiverTy = Msg->getClassReceiver(); @@ -813,25 +817,25 @@ class DiagnoseUnguardedAvailability return true; } - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { DiagnoseDeclAvailability(DRE->getDecl(), SourceRange(DRE->getBeginLoc(), DRE->getEndLoc())); return true; } - bool VisitMemberExpr(MemberExpr *ME) { + bool VisitMemberExpr(MemberExpr *ME) override { DiagnoseDeclAvailability(ME->getMemberDecl(), SourceRange(ME->getBeginLoc(), ME->getEndLoc())); return true; } - bool VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) { + bool VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) override { SemaRef.Diag(E->getBeginLoc(), diag::warn_at_available_unchecked_use) << (!SemaRef.getLangOpts().ObjC); return true; } - bool VisitTypeLoc(TypeLoc Ty); + bool VisitTypeLoc(TypeLoc Ty) override; }; void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( @@ -997,7 +1001,7 @@ bool DiagnoseUnguardedAvailability::TraverseIfStmt(IfStmt *If) { return TraverseStmt(If->getThen()) && TraverseStmt(If->getElse()); } else { // This isn't an availability checking 'if', we can just continue. - return Base::TraverseIfStmt(If); + return DynamicRecursiveASTVisitor::TraverseIfStmt(If); } AvailabilityStack.push_back(CondVersion); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 88d4732c7d5c6..21dfa10e46652 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -15,6 +15,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprConcepts.h" @@ -22,7 +23,6 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/QualTypeNames.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/CharInfo.h" @@ -5424,7 +5424,7 @@ class ConceptInfo { // This visitor infers members of T based on traversing expressions/types // that involve T. It is invoked with code known to be valid for T. - class ValidVisitor : public RecursiveASTVisitor { + class ValidVisitor final : public DynamicRecursiveASTVisitor { ConceptInfo *Outer; const TemplateTypeParmType *T; @@ -5442,7 +5442,8 @@ class ConceptInfo { } // In T.foo or T->foo, `foo` is a member function/variable. - bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { + bool + VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) override { const Type *Base = E->getBaseType().getTypePtr(); bool IsArrow = E->isArrow(); if (Base->isPointerType() && IsArrow) { @@ -5455,14 +5456,14 @@ class ConceptInfo { } // In T::foo, `foo` is a static member function/variable. - bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { + bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) override { if (E->getQualifier() && isApprox(E->getQualifier()->getAsType(), T)) addValue(E, E->getDeclName(), Member::Colons); return true; } // In T::typename foo, `foo` is a type. - bool VisitDependentNameType(DependentNameType *DNT) { + bool VisitDependentNameType(DependentNameType *DNT) override { const auto *Q = DNT->getQualifier(); if (Q && isApprox(Q->getAsType(), T)) addType(DNT->getIdentifier()); @@ -5471,7 +5472,7 @@ class ConceptInfo { // In T::foo::bar, `foo` must be a type. // VisitNNS() doesn't exist, and TraverseNNS isn't always called :-( - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSL) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSL) override { if (NNSL) { NestedNameSpecifier *NNS = NNSL.getNestedNameSpecifier(); const auto *Q = NNS->getPrefix(); @@ -5479,14 +5480,14 @@ class ConceptInfo { addType(NNS->getAsIdentifier()); } // FIXME: also handle T::foo::bar - return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSL); + return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSL); } // FIXME also handle T::foo // Track the innermost caller/callee relationship so we can tell if a // nested expr is being called as a function. - bool VisitCallExpr(CallExpr *CE) { + bool VisitCallExpr(CallExpr *CE) override { Caller = CE; Callee = CE->getCallee(); return true; diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index de24bbe7eb99c..4873acc82b825 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -15,7 +15,6 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprConcepts.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/OperatorPrecedence.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 73d11ac972b02..3f767a1e2cf52 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -17,10 +17,10 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/Cuda.h" @@ -723,8 +723,7 @@ static void handleExcludeFromExplicitInstantiationAttr(Sema &S, Decl *D, namespace { /// Determines if a given Expr references any of the given function's /// ParmVarDecls, or the function's implicit `this` parameter (if applicable). -class ArgumentDependenceChecker - : public RecursiveASTVisitor { +class ArgumentDependenceChecker final : public DynamicRecursiveASTVisitor { #ifndef NDEBUG const CXXRecordDecl *ClassType; #endif @@ -748,14 +747,14 @@ class ArgumentDependenceChecker return Result; } - bool VisitCXXThisExpr(CXXThisExpr *E) { + bool VisitCXXThisExpr(CXXThisExpr *E) override { assert(E->getType()->getPointeeCXXRecordDecl() == ClassType && "`this` doesn't refer to the enclosing class?"); Result = true; return false; } - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { if (const auto *PVD = dyn_cast(DRE->getDecl())) if (Parms.count(PVD)) { Result = true; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index d89a47f3e6226..9b745716b3be8 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -19,11 +19,11 @@ #include "clang/AST/ComparisonCategories.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/RecordLayout.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" @@ -2499,10 +2499,8 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { assert(FD->isImmediateEscalating() && !FD->isConsteval() && "expected an immediate function"); assert(FD->hasBody() && "expected the function to have a body"); - struct ImmediateEscalatingExpressionsVisitor - : public RecursiveASTVisitor { - - using Base = RecursiveASTVisitor; + struct ImmediateEscalatingExpressionsVisitor final + : DynamicRecursiveASTVisitor { Sema &SemaRef; const FunctionDecl *ImmediateFn; @@ -2512,10 +2510,10 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { ImmediateEscalatingExpressionsVisitor(Sema &SemaRef, FunctionDecl *FD) : SemaRef(SemaRef), ImmediateFn(FD), - ImmediateFnIsConstructor(isa(FD)) {} - - bool shouldVisitImplicitCode() const { return true; } - bool shouldVisitLambdaBody() const { return false; } + ImmediateFnIsConstructor(isa(FD)) { + ShouldVisitImplicitCode = true; + ShouldVisitLambdaBody = false; + } void Diag(const Expr *E, const FunctionDecl *Fn, bool IsCall) { SourceLocation Loc = E->getBeginLoc(); @@ -2535,7 +2533,7 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { << (CurrentInit && !CurrentInit->isWritten()) << InitializedField << Range; } - bool TraverseCallExpr(CallExpr *E) { + bool TraverseCallExpr(CallExpr *E) override { if (const auto *DR = dyn_cast(E->getCallee()->IgnoreImplicit()); DR && DR->isImmediateEscalating()) { @@ -2544,13 +2542,13 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { } for (Expr *A : E->arguments()) - if (!getDerived().TraverseStmt(A)) + if (!TraverseStmt(A)) return false; return true; } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { if (const auto *ReferencedFn = dyn_cast(E->getDecl()); ReferencedFn && E->isImmediateEscalating()) { Diag(E, ReferencedFn, /*IsCall=*/false); @@ -2560,7 +2558,7 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { return true; } - bool VisitCXXConstructExpr(CXXConstructExpr *E) { + bool VisitCXXConstructExpr(CXXConstructExpr *E) override { CXXConstructorDecl *D = E->getConstructor(); if (E->isImmediateEscalating()) { Diag(E, D, /*IsCall=*/true); @@ -2569,18 +2567,18 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { return true; } - bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override { llvm::SaveAndRestore RAII(CurrentInit, Init); - return Base::TraverseConstructorInitializer(Init); + return DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init); } - bool TraverseCXXConstructorDecl(CXXConstructorDecl *Ctr) { + bool TraverseCXXConstructorDecl(CXXConstructorDecl *Ctr) override { llvm::SaveAndRestore RAII(CurrentConstructor, Ctr); - return Base::TraverseCXXConstructorDecl(Ctr); + return DynamicRecursiveASTVisitor::TraverseCXXConstructorDecl(Ctr); } - bool TraverseType(QualType T) { return true; } - bool VisitBlockExpr(BlockExpr *T) { return true; } + bool TraverseType(QualType T) override { return true; } + bool VisitBlockExpr(BlockExpr *T) override { return true; } } Visitor(*this, FD); Visitor.TraverseDecl(FD); @@ -18750,18 +18748,18 @@ void Sema::CheckDelegatingCtorCycles() { namespace { /// AST visitor that finds references to the 'this' expression. - class FindCXXThisExpr : public RecursiveASTVisitor { - Sema &S; +class FindCXXThisExpr final : public DynamicRecursiveASTVisitor { + Sema &S; - public: - explicit FindCXXThisExpr(Sema &S) : S(S) { } +public: + explicit FindCXXThisExpr(Sema &S) : S(S) {} - bool VisitCXXThisExpr(CXXThisExpr *E) { - S.Diag(E->getLocation(), diag::err_this_static_member_func) + bool VisitCXXThisExpr(CXXThisExpr *E) override { + S.Diag(E->getLocation(), diag::err_this_static_member_func) << E->isImplicit(); - return false; - } - }; + return false; + } +}; } bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) { diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 807453400abdd..42909dbe0fdf9 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -15,9 +15,9 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" @@ -5320,8 +5320,7 @@ SemaObjC::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, namespace { /// Used by SemaObjC::DiagnoseUnusedBackingIvarInAccessor to check if a property /// accessor references the backing ivar. -class UnusedBackingIvarChecker - : public RecursiveASTVisitor { +class UnusedBackingIvarChecker final : public DynamicRecursiveASTVisitor { public: Sema &S; const ObjCMethodDecl *Method; @@ -5336,7 +5335,7 @@ class UnusedBackingIvarChecker assert(IvarD); } - bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) override { if (E->getDecl() == IvarD) { AccessedIvar = true; return false; @@ -5344,7 +5343,7 @@ class UnusedBackingIvarChecker return true; } - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + bool VisitObjCMessageExpr(ObjCMessageExpr *E) override { if (E->getReceiverKind() == ObjCMessageExpr::Instance && S.ObjC().isSelfExpr(E->getInstanceReceiver(), Method)) { InvokedSelfMethod = true; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f495658fe5864..e6515f3393e1f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -20,6 +20,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -28,7 +29,6 @@ #include "clang/AST/MangleNumberingContext.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/ParentMapContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" @@ -5369,32 +5369,33 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, return false; } -struct ImmediateCallVisitor : public RecursiveASTVisitor { +struct ImmediateCallVisitor final : DynamicRecursiveASTVisitor { const ASTContext &Context; - ImmediateCallVisitor(const ASTContext &Ctx) : Context(Ctx) {} + ImmediateCallVisitor(const ASTContext &Ctx) : Context(Ctx) { + ShouldVisitImplicitCode = true; + } bool HasImmediateCalls = false; - bool shouldVisitImplicitCode() const { return true; } - bool VisitCallExpr(CallExpr *E) { + bool VisitCallExpr(CallExpr *E) override { if (const FunctionDecl *FD = E->getDirectCallee()) HasImmediateCalls |= FD->isImmediateFunction(); - return RecursiveASTVisitor::VisitStmt(E); + return DynamicRecursiveASTVisitor::VisitStmt(E); } - bool VisitCXXConstructExpr(CXXConstructExpr *E) { + bool VisitCXXConstructExpr(CXXConstructExpr *E) override { if (const FunctionDecl *FD = E->getConstructor()) HasImmediateCalls |= FD->isImmediateFunction(); - return RecursiveASTVisitor::VisitStmt(E); + return DynamicRecursiveASTVisitor::VisitStmt(E); } // SourceLocExpr are not immediate invocations // but CXXDefaultInitExpr/CXXDefaultArgExpr containing a SourceLocExpr // need to be rebuilt so that they refer to the correct SourceLocation and // DeclContext. - bool VisitSourceLocExpr(SourceLocExpr *E) { + bool VisitSourceLocExpr(SourceLocExpr *E) override { HasImmediateCalls = true; - return RecursiveASTVisitor::VisitStmt(E); + return DynamicRecursiveASTVisitor::VisitStmt(E); } // A nested lambda might have parameters with immediate invocations @@ -5403,15 +5404,15 @@ struct ImmediateCallVisitor : public RecursiveASTVisitor { // subexpression). // FIXME: We should consider visiting and transforming captures // with init expressions. - bool VisitLambdaExpr(LambdaExpr *E) { + bool VisitLambdaExpr(LambdaExpr *E) override { return VisitCXXMethodDecl(E->getCallOperator()); } - bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) override { return TraverseStmt(E->getExpr()); } - bool VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { + bool VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) override { return TraverseStmt(E->getExpr()); } }; @@ -17533,10 +17534,10 @@ HandleImmediateInvocations(Sema &SemaRef, RemoveNestedImmediateInvocation(SemaRef, Rec, It); } else if (Rec.ImmediateInvocationCandidates.size() == 1 && Rec.ReferenceToConsteval.size()) { - struct SimpleRemove : RecursiveASTVisitor { + struct SimpleRemove final : DynamicRecursiveASTVisitor { llvm::SmallPtrSetImpl &DRSet; SimpleRemove(llvm::SmallPtrSetImpl &S) : DRSet(S) {} - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { DRSet.erase(E); return DRSet.size(); } @@ -19826,17 +19827,15 @@ namespace { // TreeTransforms rebuilding the type in a new context. Rather than // duplicating the TreeTransform logic, we should consider reusing it here. // Currently that causes problems when rebuilding LambdaExprs. - class MarkReferencedDecls : public RecursiveASTVisitor { - Sema &S; - SourceLocation Loc; - - public: - typedef RecursiveASTVisitor Inherited; +class MarkReferencedDecls final : public DynamicRecursiveASTVisitor { + Sema &S; + SourceLocation Loc; - MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { } +public: + MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) {} - bool TraverseTemplateArgument(const TemplateArgument &Arg); - }; + bool TraverseTemplateArgument(const TemplateArgument &Arg) override; +}; } bool MarkReferencedDecls::TraverseTemplateArgument( @@ -19853,7 +19852,7 @@ bool MarkReferencedDecls::TraverseTemplateArgument( } } - return Inherited::TraverseTemplateArgument(Arg); + return DynamicRecursiveASTVisitor::TraverseTemplateArgument(Arg); } void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 5356bcf172f75..8931945b07f4e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -18,10 +18,10 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/AlignedAllocation.h" @@ -8762,13 +8762,13 @@ static ExprResult attemptRecovery(Sema &SemaRef, } namespace { -class FindTypoExprs : public RecursiveASTVisitor { +class FindTypoExprs final : public DynamicRecursiveASTVisitor { llvm::SmallSetVector &TypoExprs; public: explicit FindTypoExprs(llvm::SmallSetVector &TypoExprs) : TypoExprs(TypoExprs) {} - bool VisitTypoExpr(TypoExpr *TE) { + bool VisitTypoExpr(TypoExpr *TE) override { TypoExprs.insert(TE); return true; } diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index e3e926465e799..a78bf785fd47b 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -10,8 +10,8 @@ #include "clang/Sema/SemaHLSL.h" #include "clang/AST/Decl.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/TargetInfo.h" @@ -356,7 +356,7 @@ static bool isLegalTypeForHLSLSV_DispatchThreadID(QualType T) { return true; } -void SemaHLSL::handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL) { +void SemaHLSL::handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL) { auto *VD = cast(D); if (!isLegalTypeForHLSLSV_DispatchThreadID(VD->getType())) { Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type) @@ -552,8 +552,7 @@ namespace { /// and of all exported functions, and any functions that are referenced /// from this AST. In other words, any functions that are reachable from /// the entry points. -class DiagnoseHLSLAvailability - : public RecursiveASTVisitor { +class DiagnoseHLSLAvailability final : public DynamicRecursiveASTVisitor { Sema &SemaRef; @@ -659,14 +658,14 @@ class DiagnoseHLSLAvailability void RunOnTranslationUnit(const TranslationUnitDecl *TU); void RunOnFunction(const FunctionDecl *FD); - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { FunctionDecl *FD = llvm::dyn_cast(DRE->getDecl()); if (FD) HandleFunctionOrMethodRef(FD, DRE); return true; } - bool VisitMemberExpr(MemberExpr *ME) { + bool VisitMemberExpr(MemberExpr *ME) override { FunctionDecl *FD = llvm::dyn_cast(ME->getMemberDecl()); if (FD) HandleFunctionOrMethodRef(FD, ME); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index ba681671eb329..cc4a3a6632309 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -16,11 +16,11 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/IgnoreExpr.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/TypeLoc.h" @@ -3595,15 +3595,15 @@ namespace { /// others. Pretend that all local typedefs are always referenced, to not warn /// on this. This isn't necessary if f has internal linkage, or the typedef /// is private. -class LocalTypedefNameReferencer - : public RecursiveASTVisitor { +class LocalTypedefNameReferencer final : public DynamicRecursiveASTVisitor { public: LocalTypedefNameReferencer(Sema &S) : S(S) {} - bool VisitRecordType(const RecordType *RT); + bool VisitRecordType(RecordType *RT) override; + private: Sema &S; }; -bool LocalTypedefNameReferencer::VisitRecordType(const RecordType *RT) { +bool LocalTypedefNameReferencer::VisitRecordType(RecordType *RT) { auto *R = dyn_cast(RT->getDecl()); if (!R || !R->isLocalClass() || !R->isLocalClass()->isExternallyVisible() || R->isDependentType()) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0afe6064bab18..5f8c4d9b5352f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -14,9 +14,9 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TemplateName.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Builtins.h" @@ -2546,9 +2546,7 @@ namespace { /// A class which looks for a use of a certain level of template /// parameter. -struct DependencyChecker : RecursiveASTVisitor { - typedef RecursiveASTVisitor super; - +struct DependencyChecker final : DynamicRecursiveASTVisitor { unsigned Depth; // Whether we're looking for a use of a template parameter that makes the @@ -2586,7 +2584,7 @@ struct DependencyChecker : RecursiveASTVisitor { return false; } - bool TraverseStmt(Stmt *S, DataRecursionQueue *Q = nullptr) { + bool TraverseStmt(Stmt *S) override { // Prune out non-type-dependent expressions if requested. This can // sometimes result in us failing to find a template parameter reference // (if a value-dependent expression creates a dependent type), but this @@ -2594,51 +2592,51 @@ struct DependencyChecker : RecursiveASTVisitor { if (auto *E = dyn_cast_or_null(S)) if (IgnoreNonTypeDependent && !E->isTypeDependent()) return true; - return super::TraverseStmt(S, Q); + return DynamicRecursiveASTVisitor::TraverseStmt(S); } - bool TraverseTypeLoc(TypeLoc TL) { + bool TraverseTypeLoc(TypeLoc TL) override { if (IgnoreNonTypeDependent && !TL.isNull() && !TL.getType()->isDependentType()) return true; - return super::TraverseTypeLoc(TL); + return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL); } - bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { + bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override { return !Matches(TL.getTypePtr()->getDepth(), TL.getNameLoc()); } - bool VisitTemplateTypeParmType(const TemplateTypeParmType *T) { + bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override { // For a best-effort search, keep looking until we find a location. return IgnoreNonTypeDependent || !Matches(T->getDepth()); } - bool TraverseTemplateName(TemplateName N) { + bool TraverseTemplateName(TemplateName N) override { if (TemplateTemplateParmDecl *PD = dyn_cast_or_null(N.getAsTemplateDecl())) if (Matches(PD->getDepth())) return false; - return super::TraverseTemplateName(N); + return DynamicRecursiveASTVisitor::TraverseTemplateName(N); } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { if (NonTypeTemplateParmDecl *PD = dyn_cast(E->getDecl())) if (Matches(PD->getDepth(), E->getExprLoc())) return false; - return super::VisitDeclRefExpr(E); + return DynamicRecursiveASTVisitor::VisitDeclRefExpr(E); } - bool VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { + bool VisitSubstTemplateTypeParmType(SubstTemplateTypeParmType *T) override { return TraverseType(T->getReplacementType()); } - bool - VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { + bool VisitSubstTemplateTypeParmPackType( + SubstTemplateTypeParmPackType *T) override { return TraverseTemplateArgument(T->getArgumentPack()); } - bool TraverseInjectedClassNameType(const InjectedClassNameType *T) { + bool TraverseInjectedClassNameType(InjectedClassNameType *T) override { return TraverseType(T->getInjectedSpecializationType()); } }; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 35bc8cd713f06..890810888cfbf 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -20,10 +20,10 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -6229,8 +6229,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs( } namespace { -struct MarkUsedTemplateParameterVisitor : - RecursiveASTVisitor { +struct MarkUsedTemplateParameterVisitor final : DynamicRecursiveASTVisitor { llvm::SmallBitVector &Used; unsigned Depth; @@ -6238,23 +6237,22 @@ struct MarkUsedTemplateParameterVisitor : unsigned Depth) : Used(Used), Depth(Depth) { } - bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { + bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override { if (T->getDepth() == Depth) Used[T->getIndex()] = true; return true; } - bool TraverseTemplateName(TemplateName Template) { + bool TraverseTemplateName(TemplateName Template) override { if (auto *TTP = llvm::dyn_cast_or_null( Template.getAsTemplateDecl())) if (TTP->getDepth() == Depth) Used[TTP->getIndex()] = true; - RecursiveASTVisitor:: - TraverseTemplateName(Template); + DynamicRecursiveASTVisitor::TraverseTemplateName(Template); return true; } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { if (auto *NTTP = dyn_cast(E->getDecl())) if (NTTP->getDepth() == Depth) Used[NTTP->getIndex()] = true; diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 545da21183c3c..533be539c446d 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -21,10 +21,10 @@ #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/OperationKinds.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -637,8 +637,7 @@ struct ConvertConstructorToDeductionGuideTransform { SmallVector TemplateParamsReferencedInTemplateArgumentList( const TemplateParameterList *TemplateParamsList, ArrayRef DeducedArgs) { - struct TemplateParamsReferencedFinder - : public RecursiveASTVisitor { + struct TemplateParamsReferencedFinder final : DynamicRecursiveASTVisitor { const TemplateParameterList *TemplateParamList; llvm::BitVector ReferencedTemplateParams; @@ -647,22 +646,22 @@ SmallVector TemplateParamsReferencedInTemplateArgumentList( : TemplateParamList(TemplateParamList), ReferencedTemplateParams(TemplateParamList->size()) {} - bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) { + bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) override { // We use the index and depth to retrieve the corresponding template // parameter from the parameter list, which is more robost. Mark(TTP->getDepth(), TTP->getIndex()); return true; } - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { MarkAppeared(DRE->getFoundDecl()); return true; } - bool TraverseTemplateName(TemplateName Template) { + bool TraverseTemplateName(TemplateName Template) override { if (auto *TD = Template.getAsTemplateDecl()) MarkAppeared(TD); - return RecursiveASTVisitor::TraverseTemplateName(Template); + return DynamicRecursiveASTVisitor::TraverseTemplateName(Template); } void MarkAppeared(NamedDecl *ND) { diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index bcd31c98871e2..00e31f137c566 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -8,14 +8,15 @@ // This file implements semantic analysis for C++0x variadic templates. //===----------------------------------------------------------------------===/ -#include "clang/Sema/Sema.h" #include "TypeLocBuilder.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/TypeLoc.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include @@ -28,259 +29,256 @@ using namespace clang; namespace { /// A class that collects unexpanded parameter packs. - class CollectUnexpandedParameterPacksVisitor : - public RecursiveASTVisitor - { - typedef RecursiveASTVisitor - inherited; - - SmallVectorImpl &Unexpanded; - - bool InLambda = false; - unsigned DepthLimit = (unsigned)-1; - - void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) { - if (auto *VD = dyn_cast(ND)) { - // For now, the only problematic case is a generic lambda's templated - // call operator, so we don't need to look for all the other ways we - // could have reached a dependent parameter pack. - auto *FD = dyn_cast(VD->getDeclContext()); - auto *FTD = FD ? FD->getDescribedFunctionTemplate() : nullptr; - if (FTD && FTD->getTemplateParameters()->getDepth() >= DepthLimit) - return; - } else if (getDepthAndIndex(ND).first >= DepthLimit) +class CollectUnexpandedParameterPacksVisitor final + : public DynamicRecursiveASTVisitor { + SmallVectorImpl &Unexpanded; + + bool InLambda = false; + unsigned DepthLimit = (unsigned)-1; + + void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) { + if (auto *VD = dyn_cast(ND)) { + // For now, the only problematic case is a generic lambda's templated + // call operator, so we don't need to look for all the other ways we + // could have reached a dependent parameter pack. + auto *FD = dyn_cast(VD->getDeclContext()); + auto *FTD = FD ? FD->getDescribedFunctionTemplate() : nullptr; + if (FTD && FTD->getTemplateParameters()->getDepth() >= DepthLimit) return; + } else if (getDepthAndIndex(ND).first >= DepthLimit) + return; - Unexpanded.push_back({ND, Loc}); - } - void addUnexpanded(const TemplateTypeParmType *T, - SourceLocation Loc = SourceLocation()) { - if (T->getDepth() < DepthLimit) - Unexpanded.push_back({T, Loc}); - } + Unexpanded.push_back({ND, Loc}); + } + void addUnexpanded(const TemplateTypeParmType *T, + SourceLocation Loc = SourceLocation()) { + if (T->getDepth() < DepthLimit) + Unexpanded.push_back({T, Loc}); + } - public: - explicit CollectUnexpandedParameterPacksVisitor( - SmallVectorImpl &Unexpanded) - : Unexpanded(Unexpanded) {} +public: + explicit CollectUnexpandedParameterPacksVisitor( + SmallVectorImpl &Unexpanded) + : Unexpanded(Unexpanded) { + ShouldWalkTypesOfTypeLocs = false; + ShouldVisitImplicitCode = true; + } - bool shouldWalkTypesOfTypeLocs() const { return false; } + //------------------------------------------------------------------------ + // Recording occurrences of (unexpanded) parameter packs. + //------------------------------------------------------------------------ - // We need this so we can find e.g. attributes on lambdas. - bool shouldVisitImplicitCode() const { return true; } + /// Record occurrences of template type parameter packs. + bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override { + if (TL.getTypePtr()->isParameterPack()) + addUnexpanded(TL.getTypePtr(), TL.getNameLoc()); + return true; + } - //------------------------------------------------------------------------ - // Recording occurrences of (unexpanded) parameter packs. - //------------------------------------------------------------------------ + /// Record occurrences of template type parameter packs + /// when we don't have proper source-location information for + /// them. + /// + /// Ideally, this routine would never be used. + bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override { + if (T->isParameterPack()) + addUnexpanded(T); - /// Record occurrences of template type parameter packs. - bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { - if (TL.getTypePtr()->isParameterPack()) - addUnexpanded(TL.getTypePtr(), TL.getNameLoc()); - return true; - } + return true; + } - /// Record occurrences of template type parameter packs - /// when we don't have proper source-location information for - /// them. - /// - /// Ideally, this routine would never be used. - bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { - if (T->isParameterPack()) - addUnexpanded(T); + /// Record occurrences of function and non-type template + /// parameter packs in an expression. + bool VisitDeclRefExpr(DeclRefExpr *E) override { + if (E->getDecl()->isParameterPack()) + addUnexpanded(E->getDecl(), E->getLocation()); - return true; + return true; + } + + /// Record occurrences of template template parameter packs. + bool TraverseTemplateName(TemplateName Template) override { + if (auto *TTP = dyn_cast_or_null( + Template.getAsTemplateDecl())) { + if (TTP->isParameterPack()) + addUnexpanded(TTP); } - /// Record occurrences of function and non-type template - /// parameter packs in an expression. - bool VisitDeclRefExpr(DeclRefExpr *E) { - if (E->getDecl()->isParameterPack()) - addUnexpanded(E->getDecl(), E->getLocation()); + return DynamicRecursiveASTVisitor::TraverseTemplateName(Template); + } + /// Suppress traversal into Objective-C container literal + /// elements that are pack expansions. + bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) override { + if (!E->containsUnexpandedParameterPack()) return true; - } - /// Record occurrences of template template parameter packs. - bool TraverseTemplateName(TemplateName Template) { - if (auto *TTP = dyn_cast_or_null( - Template.getAsTemplateDecl())) { - if (TTP->isParameterPack()) - addUnexpanded(TTP); - } + for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) { + ObjCDictionaryElement Element = E->getKeyValueElement(I); + if (Element.isPackExpansion()) + continue; - return inherited::TraverseTemplateName(Template); + TraverseStmt(Element.Key); + TraverseStmt(Element.Value); } + return true; + } + //------------------------------------------------------------------------ + // Pruning the search for unexpanded parameter packs. + //------------------------------------------------------------------------ - /// Suppress traversal into Objective-C container literal - /// elements that are pack expansions. - bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { - if (!E->containsUnexpandedParameterPack()) - return true; + /// Suppress traversal into statements and expressions that + /// do not contain unexpanded parameter packs. + bool TraverseStmt(Stmt *S) override { + Expr *E = dyn_cast_or_null(S); + if ((E && E->containsUnexpandedParameterPack()) || InLambda) + return DynamicRecursiveASTVisitor::TraverseStmt(S); - for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) { - ObjCDictionaryElement Element = E->getKeyValueElement(I); - if (Element.isPackExpansion()) - continue; + return true; + } - TraverseStmt(Element.Key); - TraverseStmt(Element.Value); - } - return true; - } - //------------------------------------------------------------------------ - // Pruning the search for unexpanded parameter packs. - //------------------------------------------------------------------------ + /// Suppress traversal into types that do not contain + /// unexpanded parameter packs. + bool TraverseType(QualType T) override { + if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda) + return DynamicRecursiveASTVisitor::TraverseType(T); - /// Suppress traversal into statements and expressions that - /// do not contain unexpanded parameter packs. - bool TraverseStmt(Stmt *S) { - Expr *E = dyn_cast_or_null(S); - if ((E && E->containsUnexpandedParameterPack()) || InLambda) - return inherited::TraverseStmt(S); + return true; + } - return true; - } + /// Suppress traversal into types with location information + /// that do not contain unexpanded parameter packs. + bool TraverseTypeLoc(TypeLoc TL) override { + if ((!TL.getType().isNull() && + TL.getType()->containsUnexpandedParameterPack()) || + InLambda) + return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL); - /// Suppress traversal into types that do not contain - /// unexpanded parameter packs. - bool TraverseType(QualType T) { - if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda) - return inherited::TraverseType(T); + return true; + } + /// Suppress traversal of parameter packs. + bool TraverseDecl(Decl *D) override { + // A function parameter pack is a pack expansion, so cannot contain + // an unexpanded parameter pack. Likewise for a template parameter + // pack that contains any references to other packs. + if (D && D->isParameterPack()) return true; - } - /// Suppress traversal into types with location information - /// that do not contain unexpanded parameter packs. - bool TraverseTypeLoc(TypeLoc TL) { - if ((!TL.getType().isNull() && - TL.getType()->containsUnexpandedParameterPack()) || - InLambda) - return inherited::TraverseTypeLoc(TL); + return DynamicRecursiveASTVisitor::TraverseDecl(D); + } + /// Suppress traversal of pack-expanded attributes. + bool TraverseAttr(Attr *A) override { + if (A->isPackExpansion()) return true; - } - /// Suppress traversal of parameter packs. - bool TraverseDecl(Decl *D) { - // A function parameter pack is a pack expansion, so cannot contain - // an unexpanded parameter pack. Likewise for a template parameter - // pack that contains any references to other packs. - if (D && D->isParameterPack()) - return true; - - return inherited::TraverseDecl(D); - } - - /// Suppress traversal of pack-expanded attributes. - bool TraverseAttr(Attr *A) { - if (A->isPackExpansion()) - return true; + return DynamicRecursiveASTVisitor::TraverseAttr(A); + } - return inherited::TraverseAttr(A); - } + /// Suppress traversal of pack expansion expressions and types. + ///@{ + bool TraversePackExpansionType(PackExpansionType *T) override { return true; } + bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) override { + return true; + } + bool TraversePackExpansionExpr(PackExpansionExpr *E) override { return true; } + bool TraverseCXXFoldExpr(CXXFoldExpr *E) override { return true; } + bool TraversePackIndexingExpr(PackIndexingExpr *E) override { + return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr()); + } + bool TraversePackIndexingType(PackIndexingType *E) override { + return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr()); + } + bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL) override { + return DynamicRecursiveASTVisitor::TraverseStmt(TL.getIndexExpr()); + } - /// Suppress traversal of pack expansion expressions and types. - ///@{ - bool TraversePackExpansionType(PackExpansionType *T) { return true; } - bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; } - bool TraversePackExpansionExpr(PackExpansionExpr *E) { return true; } - bool TraverseCXXFoldExpr(CXXFoldExpr *E) { return true; } - bool TraversePackIndexingExpr(PackIndexingExpr *E) { - return inherited::TraverseStmt(E->getIndexExpr()); - } - bool TraversePackIndexingType(PackIndexingType *E) { - return inherited::TraverseStmt(E->getIndexExpr()); - } - bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL) { - return inherited::TraverseStmt(TL.getIndexExpr()); - } + ///@} - ///@} + /// Suppress traversal of using-declaration pack expansion. + bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) override { + if (D->isPackExpansion()) + return true; - /// Suppress traversal of using-declaration pack expansion. - bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { - if (D->isPackExpansion()) - return true; + return DynamicRecursiveASTVisitor::TraverseUnresolvedUsingValueDecl(D); + } - return inherited::TraverseUnresolvedUsingValueDecl(D); - } + /// Suppress traversal of using-declaration pack expansion. + bool + TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) override { + if (D->isPackExpansion()) + return true; - /// Suppress traversal of using-declaration pack expansion. - bool TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { - if (D->isPackExpansion()) - return true; + return DynamicRecursiveASTVisitor::TraverseUnresolvedUsingTypenameDecl(D); + } - return inherited::TraverseUnresolvedUsingTypenameDecl(D); - } + /// Suppress traversal of template argument pack expansions. + bool TraverseTemplateArgument(const TemplateArgument &Arg) override { + if (Arg.isPackExpansion()) + return true; - /// Suppress traversal of template argument pack expansions. - bool TraverseTemplateArgument(const TemplateArgument &Arg) { - if (Arg.isPackExpansion()) - return true; + return DynamicRecursiveASTVisitor::TraverseTemplateArgument(Arg); + } - return inherited::TraverseTemplateArgument(Arg); - } + /// Suppress traversal of template argument pack expansions. + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) override { + if (ArgLoc.getArgument().isPackExpansion()) + return true; - /// Suppress traversal of template argument pack expansions. - bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { - if (ArgLoc.getArgument().isPackExpansion()) - return true; + return DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(ArgLoc); + } - return inherited::TraverseTemplateArgumentLoc(ArgLoc); - } + /// Suppress traversal of base specifier pack expansions. + bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) override { + if (Base.isPackExpansion()) + return true; - /// Suppress traversal of base specifier pack expansions. - bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) { - if (Base.isPackExpansion()) - return true; + return DynamicRecursiveASTVisitor::TraverseCXXBaseSpecifier(Base); + } - return inherited::TraverseCXXBaseSpecifier(Base); - } + /// Suppress traversal of mem-initializer pack expansions. + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override { + if (Init->isPackExpansion()) + return true; - /// Suppress traversal of mem-initializer pack expansions. - bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { - if (Init->isPackExpansion()) - return true; + return DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init); + } - return inherited::TraverseConstructorInitializer(Init); - } + /// Note whether we're traversing a lambda containing an unexpanded + /// parameter pack. In this case, the unexpanded pack can occur anywhere, + /// including all the places where we normally wouldn't look. Within a + /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit + /// outside an expression. + bool TraverseLambdaExpr(LambdaExpr *Lambda) override { + // The ContainsUnexpandedParameterPack bit on a lambda is always correct, + // even if it's contained within another lambda. + if (!Lambda->containsUnexpandedParameterPack()) + return true; - /// Note whether we're traversing a lambda containing an unexpanded - /// parameter pack. In this case, the unexpanded pack can occur anywhere, - /// including all the places where we normally wouldn't look. Within a - /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit - /// outside an expression. - bool TraverseLambdaExpr(LambdaExpr *Lambda) { - // The ContainsUnexpandedParameterPack bit on a lambda is always correct, - // even if it's contained within another lambda. - if (!Lambda->containsUnexpandedParameterPack()) - return true; + bool WasInLambda = InLambda; + unsigned OldDepthLimit = DepthLimit; - bool WasInLambda = InLambda; - unsigned OldDepthLimit = DepthLimit; + InLambda = true; + if (auto *TPL = Lambda->getTemplateParameterList()) + DepthLimit = TPL->getDepth(); - InLambda = true; - if (auto *TPL = Lambda->getTemplateParameterList()) - DepthLimit = TPL->getDepth(); + DynamicRecursiveASTVisitor::TraverseLambdaExpr(Lambda); - inherited::TraverseLambdaExpr(Lambda); + InLambda = WasInLambda; + DepthLimit = OldDepthLimit; + return true; + } - InLambda = WasInLambda; - DepthLimit = OldDepthLimit; + /// Suppress traversal within pack expansions in lambda captures. + bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C, + Expr *Init) override { + if (C->isPackExpansion()) return true; - } - /// Suppress traversal within pack expansions in lambda captures. - bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C, - Expr *Init) { - if (C->isPackExpansion()) - return true; - - return inherited::TraverseLambdaCapture(Lambda, C, Init); - } - }; + return DynamicRecursiveASTVisitor::TraverseLambdaCapture(Lambda, C, Init); + } +}; } /// Determine whether it's possible for an unexpanded parameter pack to diff --git a/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp index e674ec43bcd9d..582bcfaec80f4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" @@ -23,7 +23,7 @@ using namespace clang; using namespace ento; namespace { -class CastToStructVisitor : public RecursiveASTVisitor { +class CastToStructVisitor final : public DynamicRecursiveASTVisitor { BugReporter &BR; const CheckerBase *Checker; AnalysisDeclContext *AC; @@ -32,11 +32,11 @@ class CastToStructVisitor : public RecursiveASTVisitor { explicit CastToStructVisitor(BugReporter &B, const CheckerBase *Checker, AnalysisDeclContext *A) : BR(B), Checker(Checker), AC(A) {} - bool VisitCastExpr(const CastExpr *CE); + bool VisitCastExpr(CastExpr *CE) override; }; } -bool CastToStructVisitor::VisitCastExpr(const CastExpr *CE) { +bool CastToStructVisitor::VisitCastExpr(CastExpr *CE) { const Expr *E = CE->getSubExpr(); ASTContext &Ctx = AC->getASTContext(); QualType OrigTy = Ctx.getCanonicalType(E->getType()); diff --git a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp index 86f446fc411ca..d51b42bcb92d9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -13,8 +13,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Lex/Lexer.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" @@ -32,27 +32,27 @@ using namespace ento; namespace { /// A simple visitor to record what VarDecls occur in EH-handling code. -class EHCodeVisitor : public RecursiveASTVisitor { +class EHCodeVisitor final : public DynamicRecursiveASTVisitor { public: bool inEH; llvm::DenseSet &S; - bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { + bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) override { SaveAndRestore inFinally(inEH, true); - return ::RecursiveASTVisitor::TraverseObjCAtFinallyStmt(S); + return DynamicRecursiveASTVisitor::TraverseObjCAtFinallyStmt(S); } - bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) { + bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) override { SaveAndRestore inCatch(inEH, true); - return ::RecursiveASTVisitor::TraverseObjCAtCatchStmt(S); + return DynamicRecursiveASTVisitor::TraverseObjCAtCatchStmt(S); } - bool TraverseCXXCatchStmt(CXXCatchStmt *S) { + bool TraverseCXXCatchStmt(CXXCatchStmt *S) override { SaveAndRestore inCatch(inEH, true); return TraverseStmt(S->getHandlerBlock()); } - bool VisitDeclRefExpr(DeclRefExpr *DR) { + bool VisitDeclRefExpr(DeclRefExpr *DR) override { if (inEH) if (const VarDecl *D = dyn_cast(DR->getDecl())) S.insert(D); diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 034774a252b11..2c48c6156384f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -20,8 +20,8 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -710,11 +710,11 @@ static bool isObjCTypeParamDependent(QualType Type) { // It is illegal to typedef parameterized types inside an interface. Therefore // an Objective-C type can only be dependent on a type parameter when the type // parameter structurally present in the type itself. - class IsObjCTypeParamDependentTypeVisitor - : public RecursiveASTVisitor { + class IsObjCTypeParamDependentTypeVisitor final + : public DynamicRecursiveASTVisitor { public: IsObjCTypeParamDependentTypeVisitor() = default; - bool VisitObjCTypeParamType(const ObjCTypeParamType *Type) { + bool VisitObjCTypeParamType(ObjCTypeParamType *Type) override { if (isa(Type->getDecl())) { Result = true; return false; diff --git a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp index 7ac34ef8164e4..dba3260bc80cf 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp @@ -15,8 +15,8 @@ /// //===----------------------------------------------------------------------===// +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" @@ -32,8 +32,7 @@ static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, //===----------------------------------------------------------------------===// namespace { -class FindIdenticalExprVisitor - : public RecursiveASTVisitor { +class FindIdenticalExprVisitor final : public DynamicRecursiveASTVisitor { BugReporter &BR; const CheckerBase *Checker; AnalysisDeclContext *AC; @@ -45,9 +44,9 @@ class FindIdenticalExprVisitor // FindIdenticalExprVisitor only visits nodes // that are binary operators, if statements or // conditional operators. - bool VisitBinaryOperator(const BinaryOperator *B); - bool VisitIfStmt(const IfStmt *I); - bool VisitConditionalOperator(const ConditionalOperator *C); + bool VisitBinaryOperator(BinaryOperator *B) override; + bool VisitIfStmt(IfStmt *I) override; + bool VisitConditionalOperator(ConditionalOperator *C) override; private: void reportIdenticalExpr(const BinaryOperator *B, bool CheckBitwise, @@ -103,7 +102,7 @@ void FindIdenticalExprVisitor::checkBitwiseOrLogicalOp(const BinaryOperator *B, } } -bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) { +bool FindIdenticalExprVisitor::VisitIfStmt(IfStmt *I) { const Stmt *Stmt1 = I->getThen(); const Stmt *Stmt2 = I->getElse(); @@ -178,7 +177,7 @@ bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) { return true; } -bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) { +bool FindIdenticalExprVisitor::VisitBinaryOperator(BinaryOperator *B) { BinaryOperator::Opcode Op = B->getOpcode(); if (BinaryOperator::isBitwiseOp(Op)) @@ -268,7 +267,7 @@ void FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) { } bool FindIdenticalExprVisitor::VisitConditionalOperator( - const ConditionalOperator *C) { + ConditionalOperator *C) { // Check if expressions in conditional expression are identical // from a symbolic point of view. diff --git a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp index f524c4c067c8c..1dd0fb7b8fbfc 100644 --- a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp @@ -17,7 +17,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/Lex/Lexer.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" @@ -1191,7 +1191,7 @@ namespace { class PluralMisuseChecker : public Checker { // A helper class, which walks the AST - class MethodCrawler : public RecursiveASTVisitor { + class MethodCrawler final : public DynamicRecursiveASTVisitor { BugReporter &BR; const CheckerBase *Checker; AnalysisDeclContext *AC; @@ -1209,13 +1209,13 @@ class PluralMisuseChecker : public Checker { AnalysisDeclContext *InAC) : BR(InBR), Checker(Checker), AC(InAC) {} - bool VisitIfStmt(const IfStmt *I); + bool VisitIfStmt(IfStmt *I) override; bool EndVisitIfStmt(IfStmt *I); - bool TraverseIfStmt(IfStmt *x); - bool VisitConditionalOperator(const ConditionalOperator *C); - bool TraverseConditionalOperator(ConditionalOperator *C); - bool VisitCallExpr(const CallExpr *CE); - bool VisitObjCMessageExpr(const ObjCMessageExpr *ME); + bool TraverseIfStmt(IfStmt *x) override; + bool VisitConditionalOperator(ConditionalOperator *C) override; + bool TraverseConditionalOperator(ConditionalOperator *C) override; + bool VisitCallExpr(CallExpr *CE) override; + bool VisitObjCMessageExpr(ObjCMessageExpr *ME) override; private: void reportPluralMisuseError(const Stmt *S) const; @@ -1274,7 +1274,7 @@ bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality( // has been shown to almost always be a function that returns a localized // string. Raise a diagnostic when this is in a statement that matches // the condition. -bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(const CallExpr *CE) { +bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(CallExpr *CE) { if (InMatchingStatement) { if (const FunctionDecl *FD = CE->getDirectCallee()) { std::string NormalizedName = @@ -1296,7 +1296,7 @@ bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(const CallExpr *CE) { // diagnostic when this is in a statement that matches // the condition. bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr( - const ObjCMessageExpr *ME) { + ObjCMessageExpr *ME) { const ObjCInterfaceDecl *OD = ME->getReceiverInterface(); if (!OD) return true; @@ -1314,7 +1314,7 @@ bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr( /// Override TraverseIfStmt so we know when we are done traversing an IfStmt bool PluralMisuseChecker::MethodCrawler::TraverseIfStmt(IfStmt *I) { - RecursiveASTVisitor::TraverseIfStmt(I); + DynamicRecursiveASTVisitor::TraverseIfStmt(I); return EndVisitIfStmt(I); } @@ -1333,7 +1333,7 @@ bool PluralMisuseChecker::MethodCrawler::EndVisitIfStmt(IfStmt *I) { return true; } -bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(const IfStmt *I) { +bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(IfStmt *I) { const Expr *Condition = I->getCond(); if (!Condition) return true; @@ -1352,7 +1352,7 @@ bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(const IfStmt *I) { // Preliminary support for conditional operators. bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator( ConditionalOperator *C) { - RecursiveASTVisitor::TraverseConditionalOperator(C); + DynamicRecursiveASTVisitor::TraverseConditionalOperator(C); MatchingStatements.pop_back(); if (!MatchingStatements.empty()) { if (MatchingStatements.back() != nullptr) @@ -1366,7 +1366,7 @@ bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator( } bool PluralMisuseChecker::MethodCrawler::VisitConditionalOperator( - const ConditionalOperator *C) { + ConditionalOperator *C) { const Expr *Condition = C->getCond()->IgnoreParenImpCasts(); if (isCheckingPlurality(Condition)) { MatchingStatements.push_back(C); diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp index 03dab4f7ada7a..4135a374dfb89 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp @@ -12,12 +12,12 @@ // //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" -#include "clang/Analysis/PathDiagnostic.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Analysis/PathDiagnostic.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" @@ -38,11 +38,11 @@ struct SelectorDescriptor { // FindSuperCallVisitor - Identify specific calls to the superclass. //===----------------------------------------------------------------------===// -class FindSuperCallVisitor : public RecursiveASTVisitor { +class FindSuperCallVisitor final : public DynamicRecursiveASTVisitor { public: explicit FindSuperCallVisitor(Selector S) : DoesCallSuper(false), Sel(S) {} - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + bool VisitObjCMessageExpr(ObjCMessageExpr *E) override { if (E->getSelector() == Sel) if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) DoesCallSuper = true; diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index 4f35d9442ad98..d64469bb09b24 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -11,12 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/RecordLayout.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Driver/DriverDiagnostic.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" @@ -45,16 +45,17 @@ class PaddingChecker : public Checker> { // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor final : DynamicRecursiveASTVisitor { const PaddingChecker *Checker; - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return true; } - explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) {} - bool VisitRecordDecl(const RecordDecl *RD) { + explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = true; + } + bool VisitRecordDecl(RecordDecl *RD) override { Checker->visitRecord(RD); return true; } - bool VisitVarDecl(const VarDecl *VD) { + bool VisitVarDecl(VarDecl *VD) override { Checker->visitVariable(VD); return true; } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp index 69a0eb3086ab7..62a42234cba13 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/NoUncountedMembersChecker.cpp @@ -12,7 +12,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -45,17 +45,16 @@ class NoUncountedMemberChecker // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor final : DynamicRecursiveASTVisitor { const NoUncountedMemberChecker *Checker; explicit LocalVisitor(const NoUncountedMemberChecker *Checker) : Checker(Checker) { assert(Checker); + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = true; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } - - bool VisitRecordDecl(const RecordDecl *RD) { + bool VisitRecordDecl(RecordDecl *RD) override { Checker->visitRecordDecl(RD); return true; } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp index 9df108e28ecdb..9455bad337750 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp @@ -10,7 +10,7 @@ #include "DiagOutputUtils.h" #include "PtrTypesSemantics.h" #include "clang/AST/CXXInheritance.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -140,17 +140,16 @@ class RefCntblBaseVirtualDtorChecker // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor final : DynamicRecursiveASTVisitor { const RefCntblBaseVirtualDtorChecker *Checker; explicit LocalVisitor(const RefCntblBaseVirtualDtorChecker *Checker) : Checker(Checker) { assert(Checker); + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } - - bool VisitCXXRecordDecl(const CXXRecordDecl *RD) { + bool VisitCXXRecordDecl(CXXRecordDecl *RD) override { if (!RD->hasDefinition()) return true; diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index 704c082a4d1d6..0acdcf8de519c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -12,7 +12,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Basic/SourceLocation.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -43,24 +43,22 @@ class UncountedCallArgsChecker // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor final : DynamicRecursiveASTVisitor { const UncountedCallArgsChecker *Checker; explicit LocalVisitor(const UncountedCallArgsChecker *Checker) : Checker(Checker) { assert(Checker); + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } - - bool TraverseClassTemplateDecl(ClassTemplateDecl *Decl) { + bool TraverseClassTemplateDecl(ClassTemplateDecl *Decl) override { if (isRefType(safeGetName(Decl))) return true; - return RecursiveASTVisitor::TraverseClassTemplateDecl( - Decl); + return DynamicRecursiveASTVisitor::TraverseClassTemplateDecl(Decl); } - bool VisitCallExpr(const CallExpr *CE) { + bool VisitCallExpr(CallExpr *CE) override { Checker->visitCallExpr(CE); return true; } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp index a226a01ec0a57..d2ae43cedff09 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp @@ -9,7 +9,7 @@ #include "DiagOutputUtils.h" #include "PtrTypesSemantics.h" #include "clang/AST/CXXInheritance.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -35,17 +35,16 @@ class UncountedLambdaCapturesChecker // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor final : DynamicRecursiveASTVisitor { const UncountedLambdaCapturesChecker *Checker; explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker) : Checker(Checker) { assert(Checker); + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } - - bool VisitLambdaExpr(LambdaExpr *L) { + bool VisitLambdaExpr(LambdaExpr *L) override { Checker->visitLambdaExpr(L); return true; } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp index 274da0baf2ce5..720fda5714167 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp @@ -12,8 +12,8 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ParentMapContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceLocation.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -119,29 +119,26 @@ class UncountedLocalVarsChecker // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor final : DynamicRecursiveASTVisitor { const UncountedLocalVarsChecker *Checker; TrivialFunctionAnalysis TFA; - using Base = RecursiveASTVisitor; - explicit LocalVisitor(const UncountedLocalVarsChecker *Checker) : Checker(Checker) { assert(Checker); + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } - - bool VisitVarDecl(VarDecl *V) { + bool VisitVarDecl(VarDecl *V) override { auto *Init = V->getInit(); if (Init && V->isLocalVarDecl()) Checker->visitVarDecl(V, Init); return true; } - bool VisitBinaryOperator(const BinaryOperator *BO) { + bool VisitBinaryOperator(BinaryOperator *BO) override { if (BO->isAssignmentOp()) { if (auto *VarRef = dyn_cast(BO->getLHS())) { if (auto *V = dyn_cast(VarRef->getDecl())) @@ -151,33 +148,33 @@ class UncountedLocalVarsChecker return true; } - bool TraverseIfStmt(IfStmt *IS) { + bool TraverseIfStmt(IfStmt *IS) override { if (!TFA.isTrivial(IS)) - return Base::TraverseIfStmt(IS); + return DynamicRecursiveASTVisitor::TraverseIfStmt(IS); return true; } - bool TraverseForStmt(ForStmt *FS) { + bool TraverseForStmt(ForStmt *FS) override { if (!TFA.isTrivial(FS)) - return Base::TraverseForStmt(FS); + return DynamicRecursiveASTVisitor::TraverseForStmt(FS); return true; } - bool TraverseCXXForRangeStmt(CXXForRangeStmt *FRS) { + bool TraverseCXXForRangeStmt(CXXForRangeStmt *FRS) override { if (!TFA.isTrivial(FRS)) - return Base::TraverseCXXForRangeStmt(FRS); + return DynamicRecursiveASTVisitor::TraverseCXXForRangeStmt(FRS); return true; } - bool TraverseWhileStmt(WhileStmt *WS) { + bool TraverseWhileStmt(WhileStmt *WS) override { if (!TFA.isTrivial(WS)) - return Base::TraverseWhileStmt(WS); + return DynamicRecursiveASTVisitor::TraverseWhileStmt(WS); return true; } - bool TraverseCompoundStmt(CompoundStmt *CS) { + bool TraverseCompoundStmt(CompoundStmt *CS) override { if (!TFA.isTrivial(CS)) - return Base::TraverseCompoundStmt(CS); + return DynamicRecursiveASTVisitor::TraverseCompoundStmt(CS); return true; } }; diff --git a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp index 84004b8e5c1cd..319b3f01a4154 100644 --- a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/BugReporter/BugSuppression.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" using namespace clang; @@ -76,13 +76,13 @@ inline bool fullyContains(SourceRange Larger, SourceRange Smaller, isLessOrEqual(Smaller.getEnd(), Larger.getEnd(), SM); } -class CacheInitializer : public RecursiveASTVisitor { +class CacheInitializer final : public DynamicRecursiveASTVisitor { public: static void initialize(const Decl *D, Ranges &ToInit) { CacheInitializer(ToInit).TraverseDecl(const_cast(D)); } - bool VisitDecl(Decl *D) { + bool VisitDecl(Decl *D) override { // Bug location could be somewhere in the init value of // a freshly declared variable. Even though it looks like the // user applied attribute to a statement, it will apply to a @@ -90,7 +90,7 @@ class CacheInitializer : public RecursiveASTVisitor { return VisitAttributedNode(D); } - bool VisitAttributedStmt(AttributedStmt *AS) { + bool VisitAttributedStmt(AttributedStmt *AS) override { // When we apply attributes to statements, it actually creates // a wrapper statement that only contains attributes and the wrapped // statement. diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 03bc40804d732..91c9b085f6829 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -15,7 +15,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/CallGraph.h" @@ -68,7 +68,7 @@ STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function."); namespace { class AnalysisConsumer : public AnalysisASTConsumer, - public RecursiveASTVisitor { + public DynamicRecursiveASTVisitor { enum { AM_None = 0, AM_Syntax = 0x1, @@ -147,6 +147,9 @@ class AnalysisConsumer : public AnalysisASTConsumer, if (Opts.ShouldDisplayMacroExpansions) MacroExpansions.registerForPreprocessor(PP); + + // Visitor options. + ShouldWalkTypesOfTypeLocs = false; } ~AnalysisConsumer() override { @@ -261,11 +264,8 @@ class AnalysisConsumer : public AnalysisASTConsumer, ExprEngine::InliningModes IMode, SetOfConstDecls *VisitedCallees); - /// Visitors for the RecursiveASTVisitor. - bool shouldWalkTypesOfTypeLocs() const { return false; } - /// Handle callbacks for arbitrary Decls. - bool VisitDecl(Decl *D) { + bool VisitDecl(Decl *D) override { AnalysisMode Mode = getModeForDecl(D, RecVisitorMode); if (Mode & AM_Syntax) { if (SyntaxCheckTimer) @@ -277,7 +277,7 @@ class AnalysisConsumer : public AnalysisASTConsumer, return true; } - bool VisitVarDecl(VarDecl *VD) { + bool VisitVarDecl(VarDecl *VD) override { if (!Opts.IsNaiveCTUEnabled) return true; @@ -306,7 +306,7 @@ class AnalysisConsumer : public AnalysisASTConsumer, return true; } - bool VisitFunctionDecl(FunctionDecl *FD) { + bool VisitFunctionDecl(FunctionDecl *FD) override { IdentifierInfo *II = FD->getIdentifier(); if (II && II->getName().starts_with("__inline")) return true; @@ -321,7 +321,7 @@ class AnalysisConsumer : public AnalysisASTConsumer, return true; } - bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { + bool VisitObjCMethodDecl(ObjCMethodDecl *MD) override { if (MD->isThisDeclarationADefinition()) { assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false); HandleCode(MD, RecVisitorMode); @@ -329,7 +329,7 @@ class AnalysisConsumer : public AnalysisASTConsumer, return true; } - bool VisitBlockDecl(BlockDecl *BD) { + bool VisitBlockDecl(BlockDecl *BD) override { if (BD->hasBody()) { assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false); // Since we skip function template definitions, we should skip blocks diff --git a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp index 5f7153cd53ac2..74e225a95f17a 100644 --- a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp +++ b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp @@ -11,8 +11,9 @@ //===----------------------------------------------------------------------===// #include "clang/Tooling/ASTDiff/ASTDiff.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/ParentMapContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/PriorityQueue.h" @@ -186,7 +187,7 @@ static bool isNodeExcluded(const SourceManager &SrcMgr, T *N) { namespace { // Sets Height, Parent and Children for each node. -struct PreorderVisitor : public RecursiveASTVisitor { +struct PreorderVisitor final : DynamicRecursiveASTVisitor { int Id = 0, Depth = 0; NodeId Parent; SyntaxTree::Impl &Tree; @@ -228,30 +229,30 @@ struct PreorderVisitor : public RecursiveASTVisitor { for (NodeId Child : N.Children) N.Height = std::max(N.Height, 1 + Tree.getNode(Child).Height); } - bool TraverseDecl(Decl *D) { + bool TraverseDecl(Decl *D) override { if (isNodeExcluded(Tree.AST.getSourceManager(), D)) return true; auto SavedState = PreTraverse(D); - RecursiveASTVisitor::TraverseDecl(D); + DynamicRecursiveASTVisitor::TraverseDecl(D); PostTraverse(SavedState); return true; } - bool TraverseStmt(Stmt *S) { + bool TraverseStmt(Stmt *S) override { if (auto *E = dyn_cast_or_null(S)) S = E->IgnoreImplicit(); if (isNodeExcluded(Tree.AST.getSourceManager(), S)) return true; auto SavedState = PreTraverse(S); - RecursiveASTVisitor::TraverseStmt(S); + DynamicRecursiveASTVisitor::TraverseStmt(S); PostTraverse(SavedState); return true; } - bool TraverseType(QualType T) { return true; } - bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { + bool TraverseType(QualType T) override { return true; } + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override { if (isNodeExcluded(Tree.AST.getSourceManager(), Init)) return true; auto SavedState = PreTraverse(Init); - RecursiveASTVisitor::TraverseConstructorInitializer(Init); + DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init); PostTraverse(SavedState); return true; } diff --git a/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp b/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp index ac8ad344623cc..aa6a571a82000 100644 --- a/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp +++ b/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp @@ -14,7 +14,7 @@ #include "clang/Tooling/Refactoring/Rename/USRFinder.h" #include "clang/AST/AST.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Basic/SourceManager.h" #include "clang/Index/USRGeneration.h" #include "clang/Lex/Lexer.h" @@ -29,8 +29,7 @@ namespace tooling { namespace { /// Recursively visits each AST node to find the symbol underneath the cursor. -class NamedDeclOccurrenceFindingVisitor - : public RecursiveSymbolVisitor { +class NamedDeclOccurrenceFindingVisitor : public RecursiveSymbolVisitor { public: // Finds the NamedDecl at a point in the source. // \param Point the location in the source to search for the NamedDecl. @@ -41,7 +40,7 @@ class NamedDeclOccurrenceFindingVisitor Point(Point), Context(Context) {} bool visitSymbolOccurrence(const NamedDecl *ND, - ArrayRef NameRanges) { + ArrayRef NameRanges) override { if (!ND) return true; for (const auto &Range : NameRanges) { @@ -98,14 +97,13 @@ namespace { /// Recursively visits each NamedDecl node to find the declaration with a /// specific name. -class NamedDeclFindingVisitor - : public RecursiveASTVisitor { +class NamedDeclFindingVisitor final : public DynamicRecursiveASTVisitor { public: explicit NamedDeclFindingVisitor(StringRef Name) : Name(Name) {} // We don't have to traverse the uses to find some declaration with a // specific name, so just visit the named declarations. - bool VisitNamedDecl(const NamedDecl *ND) { + bool VisitNamedDecl(NamedDecl *ND) override { if (!ND) return true; // Fully qualified name is used to find the declaration. diff --git a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp index 7708fea53d014..2b530a3b62364 100644 --- a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp +++ b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp @@ -17,7 +17,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Basic/FileManager.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" @@ -60,10 +60,12 @@ namespace { // AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given // Decl refers to class and adds USRs of all overridden methods if Decl refers // to virtual method. -class AdditionalUSRFinder : public RecursiveASTVisitor { +class AdditionalUSRFinder final : public DynamicRecursiveASTVisitor { public: AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context) - : FoundDecl(FoundDecl), Context(Context) {} + : FoundDecl(FoundDecl), Context(Context) { + ShouldVisitTemplateInstantiations = true; + } std::vector Find() { // Fill OverriddenMethods and PartialSpecs storages. @@ -102,9 +104,7 @@ class AdditionalUSRFinder : public RecursiveASTVisitor { return std::vector(USRSet.begin(), USRSet.end()); } - bool shouldVisitTemplateInstantiations() const { return true; } - - bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) { + bool VisitCXXMethodDecl(CXXMethodDecl *MethodDecl) override { if (MethodDecl->isVirtual()) OverriddenMethods.push_back(MethodDecl); if (MethodDecl->getInstantiatedFromMemberFunction()) diff --git a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp index c18f9290471fe..9caa818bdef39 100644 --- a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp +++ b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp @@ -15,8 +15,8 @@ #include "clang/Tooling/Refactoring/Rename/USRLocFinder.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ParentMapContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" @@ -52,8 +52,7 @@ bool IsValidEditLoc(const clang::SourceManager& SM, clang::SourceLocation Loc) { // This visitor recursively searches for all instances of a USR in a // translation unit and stores them for later usage. -class USRLocFindingASTVisitor - : public RecursiveSymbolVisitor { +class USRLocFindingASTVisitor : public RecursiveSymbolVisitor { public: explicit USRLocFindingASTVisitor(const std::vector &USRs, StringRef PrevName, @@ -64,7 +63,7 @@ class USRLocFindingASTVisitor } bool visitSymbolOccurrence(const NamedDecl *ND, - ArrayRef NameRanges) { + ArrayRef NameRanges) override { if (USRSet.find(getUSRForDecl(ND)) != USRSet.end()) { assert(NameRanges.size() == 1 && "Multiple name pieces are not supported yet!"); @@ -153,7 +152,7 @@ NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) { // // This class will traverse the AST and find every AST node whose USR is in the // given USRs' set. -class RenameLocFinder : public RecursiveASTVisitor { +class RenameLocFinder final : public DynamicRecursiveASTVisitor { public: RenameLocFinder(llvm::ArrayRef USRs, ASTContext &Context) : USRSet(USRs.begin(), USRs.end()), Context(Context) {} @@ -179,7 +178,7 @@ class RenameLocFinder : public RecursiveASTVisitor { bool IgnorePrefixQualifers; }; - bool VisitNamedDecl(const NamedDecl *Decl) { + bool VisitNamedDecl(NamedDecl *Decl) override { // UsingDecl has been handled in other place. if (llvm::isa(Decl)) return true; @@ -212,7 +211,7 @@ class RenameLocFinder : public RecursiveASTVisitor { return true; } - bool VisitMemberExpr(const MemberExpr *Expr) { + bool VisitMemberExpr(MemberExpr *Expr) override { const NamedDecl *Decl = Expr->getFoundDecl(); auto StartLoc = Expr->getMemberLoc(); auto EndLoc = Expr->getMemberLoc(); @@ -226,7 +225,7 @@ class RenameLocFinder : public RecursiveASTVisitor { return true; } - bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) { + bool VisitDesignatedInitExpr(DesignatedInitExpr *E) override { for (const DesignatedInitExpr::Designator &D : E->designators()) { if (D.isFieldDesignator()) { if (const FieldDecl *Decl = D.getFieldDecl()) { @@ -245,7 +244,7 @@ class RenameLocFinder : public RecursiveASTVisitor { return true; } - bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) { + bool VisitCXXConstructorDecl(CXXConstructorDecl *CD) override { // Fix the constructor initializer when renaming class members. for (const auto *Initializer : CD->inits()) { // Ignore implicit initializers. @@ -266,7 +265,7 @@ class RenameLocFinder : public RecursiveASTVisitor { return true; } - bool VisitDeclRefExpr(const DeclRefExpr *Expr) { + bool VisitDeclRefExpr(DeclRefExpr *Expr) override { const NamedDecl *Decl = Expr->getFoundDecl(); // Get the underlying declaration of the shadow declaration introduced by a // using declaration. @@ -340,7 +339,7 @@ class RenameLocFinder : public RecursiveASTVisitor { return true; } - bool VisitUsingDecl(const UsingDecl *Using) { + bool VisitUsingDecl(UsingDecl *Using) override { for (const auto *UsingShadow : Using->shadows()) { if (isInUSRSet(UsingShadow->getTargetDecl())) { UsingDecls.push_back(Using); @@ -369,7 +368,7 @@ class RenameLocFinder : public RecursiveASTVisitor { return true; } - bool VisitTypeLoc(TypeLoc Loc) { + bool VisitTypeLoc(TypeLoc Loc) override { auto Parents = Context.getParents(Loc); TypeLoc ParentTypeLoc; if (!Parents.empty()) { diff --git a/clang/unittests/AST/EvaluateAsRValueTest.cpp b/clang/unittests/AST/EvaluateAsRValueTest.cpp index f6261b827671b..1e17330863f26 100644 --- a/clang/unittests/AST/EvaluateAsRValueTest.cpp +++ b/clang/unittests/AST/EvaluateAsRValueTest.cpp @@ -13,7 +13,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" #include @@ -28,8 +28,8 @@ typedef std::map VarInfoMap; /// \brief Records information on variable initializers to a map. class EvaluateConstantInitializersVisitor - : public clang::RecursiveASTVisitor { - public: + : public clang::DynamicRecursiveASTVisitor { +public: explicit EvaluateConstantInitializersVisitor(VarInfoMap &VarInfo) : VarInfo(VarInfo) {} @@ -38,7 +38,7 @@ class EvaluateConstantInitializersVisitor /// /// For each VarDecl with an initializer this also records in VarInfo /// whether the initializer could be evaluated as a constant. - bool VisitVarDecl(const clang::VarDecl *VD) { + bool VisitVarDecl(clang::VarDecl *VD) override { if (const clang::Expr *Init = VD->getInit()) { clang::Expr::EvalResult Result; bool WasEvaluated = Init->EvaluateAsRValue(Result, VD->getASTContext()); @@ -109,9 +109,9 @@ TEST(EvaluateAsRValue, FailsGracefullyForUnknownTypes) { } class CheckLValueToRValueConversionVisitor - : public clang::RecursiveASTVisitor { + : public clang::DynamicRecursiveASTVisitor { public: - bool VisitDeclRefExpr(const clang::DeclRefExpr *E) { + bool VisitDeclRefExpr(clang::DeclRefExpr *E) override { clang::Expr::EvalResult Result; E->EvaluateAsRValue(Result, E->getDecl()->getASTContext(), true); diff --git a/clang/unittests/Analysis/CloneDetectionTest.cpp b/clang/unittests/Analysis/CloneDetectionTest.cpp index 738f6efd2018d..f6b2eb1897956 100644 --- a/clang/unittests/Analysis/CloneDetectionTest.cpp +++ b/clang/unittests/Analysis/CloneDetectionTest.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Analysis/CloneDetection.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" @@ -15,15 +15,14 @@ namespace clang { namespace analysis { namespace { -class CloneDetectionVisitor - : public RecursiveASTVisitor { +class CloneDetectionVisitor final : public DynamicRecursiveASTVisitor { CloneDetector &Detector; public: explicit CloneDetectionVisitor(CloneDetector &D) : Detector(D) {} - bool VisitFunctionDecl(FunctionDecl *D) { + bool VisitFunctionDecl(FunctionDecl *D) override { Detector.analyzeCodeBody(D); return true; } diff --git a/clang/unittests/Frontend/FrontendActionTest.cpp b/clang/unittests/Frontend/FrontendActionTest.cpp index 818e8cef27e51..6ce9ba6f6a088 100644 --- a/clang/unittests/Frontend/FrontendActionTest.cpp +++ b/clang/unittests/Frontend/FrontendActionTest.cpp @@ -9,7 +9,7 @@ #include "clang/Frontend/FrontendAction.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Basic/LangStandard.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" @@ -53,7 +53,7 @@ class TestASTFrontendAction : public ASTFrontendAction { } private: - class Visitor : public ASTConsumer, public RecursiveASTVisitor { + class Visitor : public ASTConsumer, public DynamicRecursiveASTVisitor { public: Visitor(CompilerInstance &CI, bool ActOnEndOfTranslationUnit, std::vector &decl_names) : @@ -67,7 +67,7 @@ class TestASTFrontendAction : public ASTFrontendAction { TraverseDecl(context.getTranslationUnitDecl()); } - virtual bool VisitNamedDecl(NamedDecl *Decl) { + bool VisitNamedDecl(NamedDecl *Decl) override { decl_names_.push_back(Decl->getQualifiedNameAsString()); return true; } diff --git a/clang/unittests/Tooling/ASTSelectionTest.cpp b/clang/unittests/Tooling/ASTSelectionTest.cpp index 38b7df8fd564f..eefbc8cca9029 100644 --- a/clang/unittests/Tooling/ASTSelectionTest.cpp +++ b/clang/unittests/Tooling/ASTSelectionTest.cpp @@ -26,7 +26,7 @@ struct FileLocation { using FileRange = std::pair; -class SelectionFinderVisitor : public TestVisitor { +class SelectionFinderVisitor : public TestVisitor { FileLocation Location; std::optional SelectionRange; llvm::function_ref { : Location(Location), SelectionRange(SelectionRange), Consumer(Consumer) { } - bool VisitTranslationUnitDecl(const TranslationUnitDecl *TU) { + bool VisitTranslationUnitDecl(TranslationUnitDecl *TU) override { const ASTContext &Context = TU->getASTContext(); const SourceManager &SM = Context.getSourceManager(); diff --git a/clang/unittests/Tooling/CRTPTestVisitor.h b/clang/unittests/Tooling/CRTPTestVisitor.h new file mode 100644 index 0000000000000..67ae36b2e3ddd --- /dev/null +++ b/clang/unittests/Tooling/CRTPTestVisitor.h @@ -0,0 +1,42 @@ +//===--- TestVisitor.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines a CRTP-based RecursiveASTVisitor helper for tests. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_UNITTESTS_TOOLING_CRTPTESTVISITOR_H +#define LLVM_CLANG_UNITTESTS_TOOLING_CRTPTESTVISITOR_H + +#include "TestVisitor.h" +#include "clang/AST/RecursiveASTVisitor.h" + +// CRTP versions of the visitors in TestVisitor.h. +namespace clang { +template +class CRTPTestVisitor : public RecursiveASTVisitor, + public detail::TestVisitorHelper { +public: + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + void InvokeTraverseDecl(TranslationUnitDecl *D) override { + RecursiveASTVisitor::TraverseDecl(D); + } +}; + +template +class CRTPExpectedLocationVisitor + : public CRTPTestVisitor, + public detail::ExpectedLocationVisitorHelper { + ASTContext *getASTContext() override { return this->Context; } +}; +} // namespace clang + +#endif // LLVM_CLANG_UNITTESTS_TOOLING_CRTPTESTVISITOR_H diff --git a/clang/unittests/Tooling/CastExprTest.cpp b/clang/unittests/Tooling/CastExprTest.cpp index eab23a5a98e5d..e5a8d994bf011 100644 --- a/clang/unittests/Tooling/CastExprTest.cpp +++ b/clang/unittests/Tooling/CastExprTest.cpp @@ -12,17 +12,17 @@ using namespace clang; namespace { -struct CastExprVisitor : TestVisitor { +struct CastExprVisitor : TestVisitor { std::function OnExplicitCast; std::function OnCast; - bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) { + bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) override { if (OnExplicitCast) OnExplicitCast(Expr); return true; } - bool VisitCastExpr(CastExpr *Expr) { + bool VisitCastExpr(CastExpr *Expr) override { if (OnCast) OnCast(Expr); return true; diff --git a/clang/unittests/Tooling/CommentHandlerTest.cpp b/clang/unittests/Tooling/CommentHandlerTest.cpp index 7eb11ccd6ee2d..edfb72e2ec599 100644 --- a/clang/unittests/Tooling/CommentHandlerTest.cpp +++ b/clang/unittests/Tooling/CommentHandlerTest.cpp @@ -22,12 +22,9 @@ struct Comment { class CommentVerifier; typedef std::vector CommentList; -class CommentHandlerVisitor : public TestVisitor, - public CommentHandler { - typedef TestVisitor base; - +class CommentHandlerVisitor : public TestVisitor, public CommentHandler { public: - CommentHandlerVisitor() : base(), PP(nullptr), Verified(false) {} + CommentHandlerVisitor() : PP(nullptr), Verified(false) {} ~CommentHandlerVisitor() override { EXPECT_TRUE(Verified) << "CommentVerifier not accessed"; @@ -64,7 +61,7 @@ class CommentHandlerVisitor : public TestVisitor, CommentList Comments; bool Verified; - class CommentHandlerAction : public base::TestAction { + class CommentHandlerAction : public TestAction { public: CommentHandlerAction(CommentHandlerVisitor *Visitor) : TestAction(Visitor) { } diff --git a/clang/unittests/Tooling/ExecutionTest.cpp b/clang/unittests/Tooling/ExecutionTest.cpp index 91ab8594f6823..b0fd7ccb950ff 100644 --- a/clang/unittests/Tooling/ExecutionTest.cpp +++ b/clang/unittests/Tooling/ExecutionTest.cpp @@ -9,7 +9,7 @@ #include "clang/Tooling/Execution.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendActions.h" @@ -30,12 +30,9 @@ namespace { // This traverses the AST and outputs function name as key and "1" as value for // each function declaration. -class ASTConsumerWithResult - : public ASTConsumer, - public RecursiveASTVisitor { +class ASTConsumerWithResult : public ASTConsumer, + public DynamicRecursiveASTVisitor { public: - using ASTVisitor = RecursiveASTVisitor; - explicit ASTConsumerWithResult(ExecutionContext *Context) : Context(Context) { assert(Context != nullptr); } @@ -44,12 +41,12 @@ class ASTConsumerWithResult TraverseDecl(Context.getTranslationUnitDecl()); } - bool TraverseFunctionDecl(clang::FunctionDecl *Decl) { + bool TraverseFunctionDecl(clang::FunctionDecl *Decl) override { Context->reportResult(Decl->getNameAsString(), Context->getRevision() + ":" + Context->getCorpus() + ":" + Context->getCurrentCompilationUnit() + "/1"); - return ASTVisitor::TraverseFunctionDecl(Decl); + return DynamicRecursiveASTVisitor::TraverseFunctionDecl(Decl); } private: diff --git a/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp b/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp index 5d16595aec801..b167eb4b81175 100644 --- a/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp +++ b/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp @@ -44,13 +44,14 @@ class LexicallyOrderedDeclVisitor llvm::SmallVector TraversalStack; }; -class DummyMatchVisitor : public ExpectedLocationVisitor { +class DummyMatchVisitor : public ExpectedLocationVisitor { bool EmitDeclIndices, EmitStmtIndices; public: DummyMatchVisitor(bool EmitDeclIndices = false, bool EmitStmtIndices = false) : EmitDeclIndices(EmitDeclIndices), EmitStmtIndices(EmitStmtIndices) {} - bool VisitTranslationUnitDecl(TranslationUnitDecl *TU) { + + bool VisitTranslationUnitDecl(TranslationUnitDecl *TU) override { const ASTContext &Context = TU->getASTContext(); const SourceManager &SM = Context.getSourceManager(); LexicallyOrderedDeclVisitor SubVisitor(*this, SM, EmitDeclIndices, diff --git a/clang/unittests/Tooling/LookupTest.cpp b/clang/unittests/Tooling/LookupTest.cpp index 2cf5ebb2a4cbd..acd1714a26e07 100644 --- a/clang/unittests/Tooling/LookupTest.cpp +++ b/clang/unittests/Tooling/LookupTest.cpp @@ -13,31 +13,31 @@ using namespace clang; namespace { -struct GetDeclsVisitor : TestVisitor { +struct GetDeclsVisitor : TestVisitor { std::function OnCall; std::function OnRecordTypeLoc; std::function OnUsingTypeLoc; SmallVector DeclStack; - bool VisitCallExpr(CallExpr *Expr) { + bool VisitCallExpr(CallExpr *Expr) override { if (OnCall) OnCall(Expr); return true; } - bool VisitRecordTypeLoc(RecordTypeLoc Loc) { + bool VisitRecordTypeLoc(RecordTypeLoc Loc) override { if (OnRecordTypeLoc) OnRecordTypeLoc(Loc); return true; } - bool VisitUsingTypeLoc(UsingTypeLoc Loc) { + bool VisitUsingTypeLoc(UsingTypeLoc Loc) override { if (OnUsingTypeLoc) OnUsingTypeLoc(Loc); return true; } - bool TraverseDecl(Decl *D) { + bool TraverseDecl(Decl *D) override { DeclStack.push_back(D); bool Ret = TestVisitor::TraverseDecl(D); DeclStack.pop_back(); diff --git a/clang/unittests/Tooling/QualTypeNamesTest.cpp b/clang/unittests/Tooling/QualTypeNamesTest.cpp index 686d189cf69eb..5ded64d4fcc8c 100644 --- a/clang/unittests/Tooling/QualTypeNamesTest.cpp +++ b/clang/unittests/Tooling/QualTypeNamesTest.cpp @@ -11,12 +11,12 @@ using namespace clang; namespace { -struct TypeNameVisitor : TestVisitor { +struct TypeNameVisitor : TestVisitor { llvm::StringMap ExpectedQualTypeNames; bool WithGlobalNsPrefix = false; // ValueDecls are the least-derived decl with both a qualtype and a name. - bool VisitValueDecl(const ValueDecl *VD) { + bool VisitValueDecl(ValueDecl *VD) override { std::string ExpectedName = ExpectedQualTypeNames.lookup(VD->getNameAsString()); if (ExpectedName != "") { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp index e207f03971ad2..6712138b23ba6 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp @@ -12,12 +12,12 @@ using namespace clang; namespace { -class VarDeclVisitor : public ExpectedLocationVisitor { +class VarDeclVisitor : public ExpectedLocationVisitor { public: - bool VisitVarDecl(VarDecl *Variable) { - Match(Variable->getNameAsString(), Variable->getBeginLoc()); - return true; - } + bool VisitVarDecl(VarDecl *Variable) override { + Match(Variable->getNameAsString(), Variable->getBeginLoc()); + return true; + } }; TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) { @@ -29,12 +29,11 @@ TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) { VarDeclVisitor::Lang_CXX11)); } -class ParmVarDeclVisitorForImplicitCode : - public ExpectedLocationVisitor { +class ParmVarDeclVisitorForImplicitCode : public ExpectedLocationVisitor { public: - bool shouldVisitImplicitCode() const { return true; } + ParmVarDeclVisitorForImplicitCode() { ShouldVisitImplicitCode = true; } - bool VisitParmVarDecl(ParmVarDecl *ParamVar) { + bool VisitParmVarDecl(ParmVarDecl *ParamVar) override { Match(ParamVar->getNameAsString(), ParamVar->getBeginLoc()); return true; } @@ -58,10 +57,9 @@ TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) { "void bar(Y a) {Y b = a;}")); } -class NamedDeclVisitor - : public ExpectedLocationVisitor { +class NamedDeclVisitor : public ExpectedLocationVisitor { public: - bool VisitNamedDecl(NamedDecl *Decl) { + bool VisitNamedDecl(NamedDecl *Decl) override { std::string NameWithTemplateArgs; llvm::raw_string_ostream OS(NameWithTemplateArgs); Decl->getNameForDiagnostic(OS, diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp index 8ac0604c09110..e2942bf8a11a5 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp @@ -11,14 +11,18 @@ // //===----------------------------------------------------------------------===// -#include "TestVisitor.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" +#include using namespace clang; namespace { - -class RecordingVisitor : public TestVisitor { - +class RecordingVisitor : public CRTPTestVisitor { bool VisitPostOrder; public: diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp index a21186265db6a..eec628ca39641 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp @@ -12,9 +12,9 @@ using namespace clang; namespace { -class TypeLocVisitor : public ExpectedLocationVisitor { +class TypeLocVisitor : public ExpectedLocationVisitor { public: - bool VisitTypeLoc(TypeLoc TypeLocation) { + bool VisitTypeLoc(TypeLoc TypeLocation) override { Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc()); return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp index 022ef8b832286..7693e77236b0c 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "TestVisitor.h" +#include "CRTPTestVisitor.h" using namespace clang; @@ -14,7 +14,7 @@ namespace { // Check to ensure that attributes and expressions within them are being // visited. -class AttrVisitor : public ExpectedLocationVisitor { +class AttrVisitor : public CRTPExpectedLocationVisitor { public: bool VisitMemberExpr(MemberExpr *ME) { Match(ME->getMemberDecl()->getNameAsString(), ME->getBeginLoc()); @@ -30,7 +30,6 @@ class AttrVisitor : public ExpectedLocationVisitor { } }; - TEST(RecursiveASTVisitor, AttributesAreVisited) { AttrVisitor Visitor; Visitor.ExpectMatch("Attr", 4, 24); diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp index c11e726fe8552..c1217179768ac 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp @@ -14,10 +14,9 @@ using namespace clang; namespace { // Check to ensure that bitfield initializers are visited. -class BitfieldInitializerVisitor - : public ExpectedLocationVisitor { +class BitfieldInitializerVisitor : public ExpectedLocationVisitor { public: - bool VisitIntegerLiteral(IntegerLiteral *IL) { + bool VisitIntegerLiteral(IntegerLiteral *IL) override { Match(std::to_string(IL->getValue().getSExtValue()), IL->getLocation()); return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp index 1fb192dcda086..4b0c4c31f2dd2 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp @@ -12,10 +12,9 @@ using namespace clang; namespace { -class CXXBoolLiteralExprVisitor - : public ExpectedLocationVisitor { +class CXXBoolLiteralExprVisitor : public ExpectedLocationVisitor { public: - bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) { + bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) override { if (BE->getValue()) Match("true", BE->getLocation()); else diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp index c7b31e06e0e8e..fe95e8987a73a 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp @@ -12,10 +12,9 @@ using namespace clang; namespace { -class CXXMemberCallVisitor - : public ExpectedLocationVisitor { +class CXXMemberCallVisitor : public ExpectedLocationVisitor { public: - bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) { + bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) override { Match(Call->getMethodDecl()->getQualifiedNameAsString(), Call->getBeginLoc()); return true; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp index 90fa84bd44812..1eeb3df81a316 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp @@ -13,25 +13,21 @@ using namespace clang; namespace { -class CXXMethodDeclVisitor - : public ExpectedLocationVisitor { +class CXXMethodDeclVisitor : public ExpectedLocationVisitor { public: - CXXMethodDeclVisitor(bool VisitImplicitCode) - : VisitImplicitCode(VisitImplicitCode) {} - - bool shouldVisitImplicitCode() const { return VisitImplicitCode; } + CXXMethodDeclVisitor(bool VisitImplicitCode) { + ShouldVisitImplicitCode = VisitImplicitCode; + } - bool VisitDeclRefExpr(DeclRefExpr *D) { + bool VisitDeclRefExpr(DeclRefExpr *D) override { Match("declref", D->getLocation()); return true; } - bool VisitParmVarDecl(ParmVarDecl *P) { + + bool VisitParmVarDecl(ParmVarDecl *P) override { Match("parm", P->getLocation()); return true; } - -private: - bool VisitImplicitCode; }; TEST(RecursiveASTVisitor, CXXMethodDeclNoDefaultBodyVisited) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp index 376874eb351de..46686199c05d4 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp @@ -12,15 +12,13 @@ using namespace clang; namespace { -class CXXOperatorCallExprTraverser - : public ExpectedLocationVisitor { +class CXXOperatorCallExprTraverser : public ExpectedLocationVisitor { public: // Use Traverse, not Visit, to check that data recursion optimization isn't // bypassing the call of this function. - bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) { + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) override { Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc()); - return ExpectedLocationVisitor:: - TraverseCXXOperatorCallExpr(CE); + return ExpectedLocationVisitor::TraverseCXXOperatorCallExpr(CE); } }; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h index 92e30c2d46e5f..355ecfb452e7e 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "TestVisitor.h" +#include "CRTPTestVisitor.h" using namespace clang; @@ -21,7 +21,7 @@ enum class ShouldTraversePostOrder : bool { /// sequence of calls to user-defined callbacks like Traverse*(), WalkUp*(), /// Visit*(). template -class RecordingVisitorBase : public TestVisitor { +class RecordingVisitorBase : public CRTPTestVisitor { ShouldTraversePostOrder ShouldTraversePostOrderValue; public: diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp index 3ea5abd46a1ec..79dc84b2fdb7b 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp @@ -14,10 +14,11 @@ namespace { // Checks for lambda classes that are not marked as implicitly-generated. // (There should be none.) -class ClassVisitor : public ExpectedLocationVisitor { +class ClassVisitor : public ExpectedLocationVisitor { public: ClassVisitor() : SawNonImplicitLambdaClass(false) {} - bool VisitCXXRecordDecl(CXXRecordDecl* record) { + + bool VisitCXXRecordDecl(CXXRecordDecl *record) override { if (record->isLambda() && !record->isImplicit()) SawNonImplicitLambdaClass = true; return true; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp index 6a8d91672f1d9..6dd28e27d7ec2 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp @@ -16,78 +16,87 @@ using namespace clang; namespace { -struct ConceptVisitor : ExpectedLocationVisitor { - bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) { +struct ConceptVisitor : ExpectedLocationVisitor { + ConceptVisitor(bool VisitImplicitCode = false) { + ShouldVisitImplicitCode = VisitImplicitCode; + } + + bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) override { ++ConceptSpecializationExprsVisited; return true; } - bool TraverseTypeConstraint(const TypeConstraint *C) { + bool TraverseTypeConstraint(const TypeConstraint *C) override { ++TypeConstraintsTraversed; return ExpectedLocationVisitor::TraverseTypeConstraint(C); } - bool TraverseConceptRequirement(concepts::Requirement *R) { + bool TraverseConceptRequirement(concepts::Requirement *R) override { ++ConceptRequirementsTraversed; return ExpectedLocationVisitor::TraverseConceptRequirement(R); } - bool TraverseConceptReference(ConceptReference *CR) { + bool TraverseConceptReference(ConceptReference *CR) override { ++ConceptReferencesTraversed; return ExpectedLocationVisitor::TraverseConceptReference(CR); } - bool VisitConceptReference(ConceptReference *CR) { + bool VisitConceptReference(ConceptReference *CR) override { ++ConceptReferencesVisited; return true; } - bool shouldVisitImplicitCode() { return ShouldVisitImplicitCode; } - int ConceptSpecializationExprsVisited = 0; int TypeConstraintsTraversed = 0; int ConceptRequirementsTraversed = 0; int ConceptReferencesTraversed = 0; int ConceptReferencesVisited = 0; - bool ShouldVisitImplicitCode = false; }; TEST(RecursiveASTVisitor, Concepts) { - ConceptVisitor Visitor; - Visitor.ShouldVisitImplicitCode = true; - EXPECT_TRUE(Visitor.runOver("template concept Fooable = true;\n" - "template void bar(T);", - ConceptVisitor::Lang_CXX2a)); - // Check that we traverse the "Fooable T" template parameter's - // TypeConstraint's ImmediatelyDeclaredConstraint, which is a - // ConceptSpecializationExpr. - EXPECT_EQ(1, Visitor.ConceptSpecializationExprsVisited); - // Also check we traversed the TypeConstraint that produced the expr. - EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + { + ConceptVisitor Visitor{true}; + EXPECT_TRUE( + Visitor.runOver("template concept Fooable = true;\n" + "template void bar(T);", + ConceptVisitor::Lang_CXX2a)); + // Check that we traverse the "Fooable T" template parameter's + // TypeConstraint's ImmediatelyDeclaredConstraint, which is a + // ConceptSpecializationExpr. + EXPECT_EQ(1, Visitor.ConceptSpecializationExprsVisited); + // Also check we traversed the TypeConstraint that produced the expr. + EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + } - Visitor = {}; // Don't visit implicit code now. - EXPECT_TRUE(Visitor.runOver("template concept Fooable = true;\n" - "template void bar(T);", - ConceptVisitor::Lang_CXX2a)); - // Check that we only visit the TypeConstraint, but not the implicitly - // generated immediately declared expression. - EXPECT_EQ(0, Visitor.ConceptSpecializationExprsVisited); - EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + { + ConceptVisitor Visitor; // Don't visit implicit code now. + EXPECT_TRUE( + Visitor.runOver("template concept Fooable = true;\n" + "template void bar(T);", + ConceptVisitor::Lang_CXX2a)); + // Check that we only visit the TypeConstraint, but not the implicitly + // generated immediately declared expression. + EXPECT_EQ(0, Visitor.ConceptSpecializationExprsVisited); + EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + } - Visitor = {}; - EXPECT_TRUE(Visitor.runOver("template concept A = true;\n" - "template struct vector {};\n" - "template concept B = requires(T x) {\n" - " typename vector;\n" - " {x} -> A;\n" - " requires true;\n" - "};", - ConceptVisitor::Lang_CXX2a)); - EXPECT_EQ(3, Visitor.ConceptRequirementsTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + { + ConceptVisitor Visitor; + EXPECT_TRUE( + Visitor.runOver("template concept A = true;\n" + "template struct vector {};\n" + "template concept B = requires(T x) {\n" + " typename vector;\n" + " {x} -> A;\n" + " requires true;\n" + "};", + ConceptVisitor::Lang_CXX2a)); + EXPECT_EQ(3, Visitor.ConceptRequirementsTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + } - Visitor = {}; + ConceptVisitor Visitor; llvm::StringRef Code = R"cpp( template concept True = false; @@ -107,34 +116,34 @@ struct Foo {}; EXPECT_EQ(2, Visitor.ConceptReferencesVisited); } -struct VisitDeclOnlyOnce : ExpectedLocationVisitor { - bool VisitConceptDecl(ConceptDecl *D) { +struct VisitDeclOnlyOnce : ExpectedLocationVisitor { + VisitDeclOnlyOnce() { ShouldWalkTypesOfTypeLocs = false; } + + bool VisitConceptDecl(ConceptDecl *D) override { ++ConceptDeclsVisited; return true; } - bool VisitAutoType(AutoType *) { + bool VisitAutoType(AutoType *) override { ++AutoTypeVisited; return true; } - bool VisitAutoTypeLoc(AutoTypeLoc) { + bool VisitAutoTypeLoc(AutoTypeLoc) override { ++AutoTypeLocVisited; return true; } - bool VisitConceptReference(ConceptReference *) { + bool VisitConceptReference(ConceptReference *) override { ++ConceptReferencesVisited; return true; } - bool TraverseVarDecl(VarDecl *V) { + bool TraverseVarDecl(VarDecl *V) override { // The base traversal visits only the `TypeLoc`. // However, in the test we also validate the underlying `QualType`. TraverseType(V->getType()); return ExpectedLocationVisitor::TraverseVarDecl(V); } - bool shouldWalkTypesOfTypeLocs() { return false; } - int ConceptDeclsVisited = 0; int AutoTypeVisited = 0; int AutoTypeLocVisited = 0; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp index b4f4f54dc7e2f..7b2ed9715aa80 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp @@ -18,18 +18,11 @@ namespace { /// The name recorded for the match is the name of the class whose constructor /// is invoked by the CXXConstructExpr, not the name of the class whose /// constructor the CXXConstructExpr is contained in. -class ConstructExprVisitor - : public ExpectedLocationVisitor { +class ConstructExprVisitor : public ExpectedLocationVisitor { public: - ConstructExprVisitor() : ShouldVisitImplicitCode(false) {} + ConstructExprVisitor() { ShouldVisitImplicitCode = false; } - bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } - - void setShouldVisitImplicitCode(bool NewValue) { - ShouldVisitImplicitCode = NewValue; - } - - bool VisitCXXConstructExpr(CXXConstructExpr* Expr) { + bool VisitCXXConstructExpr(CXXConstructExpr *Expr) override { if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) { if (const CXXRecordDecl* Class = Ctor->getParent()) { Match(Class->getName(), Expr->getLocation()); @@ -37,14 +30,11 @@ class ConstructExprVisitor } return true; } - - private: - bool ShouldVisitImplicitCode; }; TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) { ConstructExprVisitor Visitor; - Visitor.setShouldVisitImplicitCode(true); + Visitor.ShouldVisitImplicitCode = true; Visitor.ExpectMatch("WithCtor", 2, 8); // Simple has a constructor that implicitly initializes 'w'. Test // that a visitor that visits implicit code visits that initialization. @@ -60,7 +50,7 @@ TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) { // visits are omitted when the visitor does not include implicit code. TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) { ConstructExprVisitor Visitor; - Visitor.setShouldVisitImplicitCode(false); + Visitor.ShouldVisitImplicitCode = false; Visitor.DisallowMatch("WithCtor", 2, 8); // Simple has a constructor that implicitly initializes 'w'. Test // that a visitor that skips implicit code skips that initialization. diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp index adc972e1c3d91..6ed986c187eb5 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp @@ -12,23 +12,14 @@ using namespace clang; namespace { -class DeclRefExprVisitor : public ExpectedLocationVisitor { +class DeclRefExprVisitor : public ExpectedLocationVisitor { public: - DeclRefExprVisitor() : ShouldVisitImplicitCode(false) {} + DeclRefExprVisitor() { ShouldVisitImplicitCode = false; } - bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } - - void setShouldVisitImplicitCode(bool NewValue) { - ShouldVisitImplicitCode = NewValue; - } - - bool VisitDeclRefExpr(DeclRefExpr *Reference) { + bool VisitDeclRefExpr(DeclRefExpr *Reference) override { Match(Reference->getNameInfo().getAsString(), Reference->getLocation()); return true; } - -private: - bool ShouldVisitImplicitCode; }; TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) { @@ -73,7 +64,7 @@ TEST(RecursiveASTVisitor, VisitsUseOfImplicitLambdaCapture) { TEST(RecursiveASTVisitor, VisitsImplicitLambdaCaptureInit) { DeclRefExprVisitor Visitor; - Visitor.setShouldVisitImplicitCode(true); + Visitor.ShouldVisitImplicitCode = true; // We're expecting "i" to be visited twice: once for the initialization expr // for the captured variable "i" outside of the lambda body, and again for // the use of "i" inside the lambda. diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp index df878bfc113e5..7d03b28394799 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp @@ -13,23 +13,20 @@ using namespace clang; namespace { -class DeductionGuideVisitor - : public ExpectedLocationVisitor { +class DeductionGuideVisitor : public ExpectedLocationVisitor { public: - DeductionGuideVisitor(bool ShouldVisitImplicitCode) - : ShouldVisitImplicitCode(ShouldVisitImplicitCode) {} - bool VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { + DeductionGuideVisitor(bool VisitImplicitCode) { + ShouldVisitImplicitCode = VisitImplicitCode; + ShouldVisitTemplateInstantiations = false; + } + + bool VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) override { std::string Storage; llvm::raw_string_ostream Stream(Storage); D->print(Stream); Match(Storage, D->getLocation()); return true; } - - bool shouldVisitTemplateInstantiations() const { return false; } - - bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } - bool ShouldVisitImplicitCode; }; TEST(RecursiveASTVisitor, DeductionGuideNonImplicitMode) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp index 27999e5ef8efc..dc9455a01e488 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp @@ -13,12 +13,9 @@ using namespace clang; namespace { // A visitor that visits implicit declarations and matches constructors. -class ImplicitCtorVisitor - : public ExpectedLocationVisitor { +class ImplicitCtorVisitor : public ExpectedLocationVisitor { public: - bool shouldVisitImplicitCode() const { return true; } - - bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) { + bool VisitCXXConstructorDecl(CXXConstructorDecl *Ctor) override { if (Ctor->isImplicit()) { // Was not written in source code if (const CXXRecordDecl* Class = Ctor->getParent()) { Match(Class->getName(), Ctor->getLocation()); diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp index c762e1cffc368..ae952c33bfe78 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp @@ -12,26 +12,20 @@ using namespace clang; namespace { -class CXXCtorInitializerVisitor - : public ExpectedLocationVisitor { +class CXXCtorInitializerVisitor : public ExpectedLocationVisitor { public: - CXXCtorInitializerVisitor(bool VisitImplicitCode) - : VisitImplicitCode(VisitImplicitCode) {} - - bool shouldVisitImplicitCode() const { return VisitImplicitCode; } + CXXCtorInitializerVisitor(bool VisitImplicitCode) { + ShouldVisitImplicitCode = VisitImplicitCode; + } - bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override { if (!Init->isWritten()) VisitedImplicitInitializer = true; Match("initializer", Init->getSourceLocation()); - return ExpectedLocationVisitor< - CXXCtorInitializerVisitor>::TraverseConstructorInitializer(Init); + return ExpectedLocationVisitor::TraverseConstructorInitializer(Init); } bool VisitedImplicitInitializer = false; - -private: - bool VisitImplicitCode; }; // Check to ensure that CXXCtorInitializer is not visited when implicit code diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp index 80d9c9873505b..5836fc1b2e8de 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp @@ -6,14 +6,14 @@ // //===----------------------------------------------------------------------===// -#include "TestVisitor.h" +#include "CRTPTestVisitor.h" using namespace clang; namespace { class InitListExprPostOrderVisitor - : public ExpectedLocationVisitor { + : public CRTPExpectedLocationVisitor { public: bool shouldTraversePostOrder() const { return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp index 8750f78349443..20140d2dcbf9e 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp @@ -6,19 +6,19 @@ // //===----------------------------------------------------------------------===// -#include "TestVisitor.h" +#include "CRTPTestVisitor.h" using namespace clang; namespace { class InitListExprPostOrderNoQueueVisitor - : public ExpectedLocationVisitor { + : public CRTPExpectedLocationVisitor { public: bool shouldTraversePostOrder() const { return true; } bool TraverseInitListExpr(InitListExpr *ILE) { - return ExpectedLocationVisitor::TraverseInitListExpr(ILE); + return CRTPExpectedLocationVisitor::TraverseInitListExpr(ILE); } bool VisitInitListExpr(InitListExpr *ILE) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp index 3fa1529ea0eef..933d25898390d 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp @@ -14,21 +14,16 @@ namespace { // Check to ensure that InitListExpr is visited twice, once each for the // syntactic and semantic form. -class InitListExprPreOrderVisitor - : public ExpectedLocationVisitor { +class InitListExprPreOrderVisitor : public ExpectedLocationVisitor { public: - InitListExprPreOrderVisitor(bool VisitImplicitCode) - : VisitImplicitCode(VisitImplicitCode) {} - - bool shouldVisitImplicitCode() const { return VisitImplicitCode; } + InitListExprPreOrderVisitor(bool VisitImplicitCode) { + ShouldVisitImplicitCode = VisitImplicitCode; + } - bool VisitInitListExpr(InitListExpr *ILE) { + bool VisitInitListExpr(InitListExpr *ILE) override { Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc()); return true; } - -private: - bool VisitImplicitCode; }; TEST(RecursiveASTVisitor, InitListExprIsPreOrderVisitedTwice) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp index 8db88e1e06397..0dcd11b8027f0 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp @@ -12,14 +12,13 @@ using namespace clang; namespace { -class InitListExprPreOrderNoQueueVisitor - : public ExpectedLocationVisitor { +class InitListExprPreOrderNoQueueVisitor : public ExpectedLocationVisitor { public: - bool TraverseInitListExpr(InitListExpr *ILE) { + bool TraverseInitListExpr(InitListExpr *ILE) override { return ExpectedLocationVisitor::TraverseInitListExpr(ILE); } - bool VisitInitListExpr(InitListExpr *ILE) { + bool VisitInitListExpr(InitListExpr *ILE) override { Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc()); return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp index 3fc3cb1a99a74..83136fc11edb2 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp @@ -13,10 +13,9 @@ using namespace clang; namespace { // Check to ensure that implicit default argument expressions are visited. -class IntegerLiteralVisitor - : public ExpectedLocationVisitor { +class IntegerLiteralVisitor : public ExpectedLocationVisitor { public: - bool VisitIntegerLiteral(const IntegerLiteral *IL) { + bool VisitIntegerLiteral(IntegerLiteral *IL) override { Match("literal", IL->getLocation()); return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp index b1d6d593e733a..4a9175ed2dda2 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp @@ -13,10 +13,9 @@ using namespace clang; namespace { // Matches the (optional) capture-default of a lambda-introducer. -class LambdaDefaultCaptureVisitor - : public ExpectedLocationVisitor { +class LambdaDefaultCaptureVisitor : public ExpectedLocationVisitor { public: - bool VisitLambdaExpr(LambdaExpr *Lambda) { + bool VisitLambdaExpr(LambdaExpr *Lambda) override { if (Lambda->getCaptureDefault() != LCD_None) { Match("", Lambda->getCaptureDefaultLoc()); } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp index 337dace5fd227..0ce7f4b18762f 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp @@ -14,9 +14,11 @@ using namespace clang; namespace { -class LambdaExprVisitor : public ExpectedLocationVisitor { +class LambdaExprVisitor : public ExpectedLocationVisitor { public: - bool VisitLambdaExpr(LambdaExpr *Lambda) { + LambdaExprVisitor() { ShouldVisitImplicitCode = false; } + + bool VisitLambdaExpr(LambdaExpr *Lambda) override { PendingBodies.push(Lambda->getBody()); PendingClasses.push(Lambda->getLambdaClass()); Match("", Lambda->getIntroducerRange().getBegin()); @@ -24,12 +26,12 @@ class LambdaExprVisitor : public ExpectedLocationVisitor { } /// For each call to VisitLambdaExpr, we expect a subsequent call to visit /// the body (and maybe the lambda class, which is implicit). - bool VisitStmt(Stmt *S) { + bool VisitStmt(Stmt *S) override { if (!PendingBodies.empty() && S == PendingBodies.top()) PendingBodies.pop(); return true; } - bool VisitDecl(Decl *D) { + bool VisitDecl(Decl *D) override { if (!PendingClasses.empty() && D == PendingClasses.top()) PendingClasses.pop(); return true; @@ -38,9 +40,6 @@ class LambdaExprVisitor : public ExpectedLocationVisitor { bool allBodiesHaveBeenTraversed() const { return PendingBodies.empty(); } bool allClassesHaveBeenTraversed() const { return PendingClasses.empty(); } - bool VisitImplicitCode = false; - bool shouldVisitImplicitCode() const { return VisitImplicitCode; } - private: std::stack PendingBodies; std::stack PendingClasses; @@ -67,7 +66,7 @@ TEST(RecursiveASTVisitor, LambdaInLambda) { TEST(RecursiveASTVisitor, TopLevelLambda) { LambdaExprVisitor Visitor; - Visitor.VisitImplicitCode = true; + Visitor.ShouldVisitImplicitCode = true; Visitor.ExpectMatch("", 1, 10); Visitor.ExpectMatch("", 1, 14); EXPECT_TRUE(Visitor.runOver("auto x = []{ [] {}; };", @@ -78,7 +77,7 @@ TEST(RecursiveASTVisitor, TopLevelLambda) { TEST(RecursiveASTVisitor, VisitsLambdaExprAndImplicitClass) { LambdaExprVisitor Visitor; - Visitor.VisitImplicitCode = true; + Visitor.ShouldVisitImplicitCode = true; Visitor.ExpectMatch("", 1, 12); EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }", LambdaExprVisitor::Lang_CXX11)); diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp index c355e3f1083f9..cfac3a3c5ad98 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp @@ -13,24 +13,23 @@ using namespace clang; namespace { // Matches (optional) explicit template parameters. -class LambdaTemplateParametersVisitor - : public ExpectedLocationVisitor { +class LambdaTemplateParametersVisitor : public ExpectedLocationVisitor { public: - bool shouldVisitImplicitCode() const { return false; } + LambdaTemplateParametersVisitor() { ShouldVisitImplicitCode = false; } - bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { + bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) override { EXPECT_FALSE(D->isImplicit()); Match(D->getName(), D->getBeginLoc()); return true; } - bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { + bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) override { EXPECT_FALSE(D->isImplicit()); Match(D->getName(), D->getBeginLoc()); return true; } - bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { + bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) override { EXPECT_FALSE(D->isImplicit()); Match(D->getName(), D->getBeginLoc()); return true; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp index d67bd0395a670..587a00dd27051 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp @@ -13,16 +13,15 @@ using namespace clang; namespace { -class MemberPointerTypeLocVisitor - : public ExpectedLocationVisitor { +class MemberPointerTypeLocVisitor : public ExpectedLocationVisitor { public: - bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { + bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override { if (!TL) return true; Match(TL.getDecl()->getName(), TL.getNameLoc()); return true; } - bool VisitRecordTypeLoc(RecordTypeLoc RTL) { + bool VisitRecordTypeLoc(RecordTypeLoc RTL) override { if (!RTL) return true; Match(RTL.getDecl()->getName(), RTL.getNameLoc()); diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp index 868a3988c756d..ddc663e2b6fd3 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp @@ -13,17 +13,16 @@ using namespace clang; namespace { // Check to ensure that nested name specifiers are visited. -class NestedNameSpecifiersVisitor - : public ExpectedLocationVisitor { +class NestedNameSpecifiersVisitor : public ExpectedLocationVisitor { public: - bool VisitRecordTypeLoc(RecordTypeLoc RTL) { + bool VisitRecordTypeLoc(RecordTypeLoc RTL) override { if (!RTL) return true; Match(RTL.getDecl()->getName(), RTL.getNameLoc()); return true; } - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override { if (!NNS) return true; if (const NamespaceDecl *ND = diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp index c316f98f40ce0..89ccf20587ad0 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp @@ -12,9 +12,9 @@ using namespace clang; namespace { -class ParenExprVisitor : public ExpectedLocationVisitor { +class ParenExprVisitor : public ExpectedLocationVisitor { public: - bool VisitParenExpr(ParenExpr *Parens) { + bool VisitParenExpr(ParenExpr *Parens) override { Match("", Parens->getExprLoc()); return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp index f068e53ae9c28..3af2b13dc5daf 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp @@ -12,18 +12,16 @@ using namespace clang; namespace { -class TemplateArgumentLocTraverser - : public ExpectedLocationVisitor { +class TemplateArgumentLocTraverser : public ExpectedLocationVisitor { public: - bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) override { std::string ArgStr; llvm::raw_string_ostream Stream(ArgStr); const TemplateArgument &Arg = ArgLoc.getArgument(); Arg.print(Context->getPrintingPolicy(), Stream, /*IncludeType*/ true); Match(Stream.str(), ArgLoc.getLocation()); - return ExpectedLocationVisitor:: - TraverseTemplateArgumentLoc(ArgLoc); + return ExpectedLocationVisitor::TraverseTemplateArgumentLoc(ArgLoc); } }; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp index 9e71f9554e595..2feddf58cac7b 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp @@ -12,17 +12,17 @@ using namespace clang; namespace { -class Visitor : public ExpectedLocationVisitor { +class Visitor : public ExpectedLocationVisitor { public: Visitor(ASTContext *Context) { this->Context = Context; } - bool VisitTranslationUnitDecl(TranslationUnitDecl *D) { + bool VisitTranslationUnitDecl(TranslationUnitDecl *D) override { auto &SM = D->getParentASTContext().getSourceManager(); Match("TU", SM.getLocForStartOfFile(SM.getMainFileID())); return true; } - bool VisitNamedDecl(NamedDecl *D) { + bool VisitNamedDecl(NamedDecl *D) override { if (!D->isImplicit()) Match(D->getName(), D->getLocation()); return true; diff --git a/clang/unittests/Tooling/RefactoringTest.cpp b/clang/unittests/Tooling/RefactoringTest.cpp index 77d410f5d3b60..9df8c1b94c6a4 100644 --- a/clang/unittests/Tooling/RefactoringTest.cpp +++ b/clang/unittests/Tooling/RefactoringTest.cpp @@ -13,7 +13,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclGroup.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" @@ -648,8 +648,7 @@ TEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) { } namespace { -template -class TestVisitor : public clang::RecursiveASTVisitor { +class TestVisitor : public DynamicRecursiveASTVisitor { public: bool runOver(StringRef Code) { return runToolOnCode(std::make_unique(this), Code); @@ -699,9 +698,9 @@ void expectReplacementAt(const Replacement &Replace, EXPECT_EQ(Length, Replace.getLength()); } -class ClassDeclXVisitor : public TestVisitor { +class ClassDeclXVisitor : public TestVisitor { public: - bool VisitCXXRecordDecl(CXXRecordDecl *Record) { + bool VisitCXXRecordDecl(CXXRecordDecl *Record) override { if (Record->getName() == "X") { Replace = Replacement(*SM, Record, ""); } @@ -722,9 +721,9 @@ TEST(Replacement, ReplacesAtSpellingLocation) { expectReplacementAt(ClassDeclX.Replace, "input.cc", 17, 7); } -class CallToFVisitor : public TestVisitor { +class CallToFVisitor : public TestVisitor { public: - bool VisitCallExpr(CallExpr *Call) { + bool VisitCallExpr(CallExpr *Call) override { if (Call->getDirectCallee()->getName() == "F") { Replace = Replacement(*SM, Call, ""); } @@ -746,10 +745,9 @@ TEST(Replacement, TemplatedFunctionCall) { expectReplacementAt(CallToF.Replace, "input.cc", 43, 8); } -class NestedNameSpecifierAVisitor - : public TestVisitor { +class NestedNameSpecifierAVisitor : public TestVisitor { public: - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) override { if (NNSLoc.getNestedNameSpecifier()) { if (const NamespaceDecl* NS = NNSLoc.getNestedNameSpecifier()->getAsNamespace()) { if (NS->getName() == "a") { @@ -757,8 +755,7 @@ class NestedNameSpecifierAVisitor } } } - return TestVisitor::TraverseNestedNameSpecifierLoc( - NNSLoc); + return TestVisitor::TraverseNestedNameSpecifierLoc(NNSLoc); } Replacement Replace; }; diff --git a/clang/unittests/Tooling/SourceCodeTest.cpp b/clang/unittests/Tooling/SourceCodeTest.cpp index 3c24b6220a224..549b77752f1c2 100644 --- a/clang/unittests/Tooling/SourceCodeTest.cpp +++ b/clang/unittests/Tooling/SourceCodeTest.cpp @@ -35,8 +35,8 @@ using tooling::validateEditRange; namespace { -struct IntLitVisitor : TestVisitor { - bool VisitIntegerLiteral(IntegerLiteral *Expr) { +struct IntLitVisitor : TestVisitor { + bool VisitIntegerLiteral(IntegerLiteral *Expr) override { OnIntLit(Expr, Context); return true; } @@ -44,8 +44,8 @@ struct IntLitVisitor : TestVisitor { std::function OnIntLit; }; -struct CallsVisitor : TestVisitor { - bool VisitCallExpr(CallExpr *Expr) { +struct CallsVisitor : TestVisitor { + bool VisitCallExpr(CallExpr *Expr) override { OnCall(Expr, Context); return true; } @@ -53,8 +53,8 @@ struct CallsVisitor : TestVisitor { std::function OnCall; }; -struct TypeLocVisitor : TestVisitor { - bool VisitTypeLoc(TypeLoc TL) { +struct TypeLocVisitor : TestVisitor { + bool VisitTypeLoc(TypeLoc TL) override { OnTypeLoc(TL, Context); return true; } @@ -97,7 +97,7 @@ static ::testing::Matcher AsRange(const SourceManager &SM, // Base class for visitors that expect a single match corresponding to a // specific annotated range. -template class AnnotatedCodeVisitor : public TestVisitor { +class AnnotatedCodeVisitor : public TestVisitor { protected: int MatchCount = 0; llvm::Annotations Code; @@ -199,9 +199,8 @@ TEST(SourceCodeTest, getExtendedText) { } TEST(SourceCodeTest, maybeExtendRange_TokenRange) { - struct ExtendTokenRangeVisitor - : AnnotatedCodeVisitor { - bool VisitCallExpr(CallExpr *CE) { + struct ExtendTokenRangeVisitor : AnnotatedCodeVisitor { + bool VisitCallExpr(CallExpr *CE) override { ++MatchCount; EXPECT_THAT(getExtendedRange(*CE, tok::TokenKind::semi, *Context), EqualsAnnotatedRange(Context, Code.range("r"))); @@ -218,8 +217,8 @@ TEST(SourceCodeTest, maybeExtendRange_TokenRange) { } TEST(SourceCodeTest, maybeExtendRange_CharRange) { - struct ExtendCharRangeVisitor : AnnotatedCodeVisitor { - bool VisitCallExpr(CallExpr *CE) { + struct ExtendCharRangeVisitor : AnnotatedCodeVisitor { + bool VisitCallExpr(CallExpr *CE) override { ++MatchCount; CharSourceRange Call = Lexer::getAsCharRange(CE->getSourceRange(), Context->getSourceManager(), @@ -238,8 +237,8 @@ TEST(SourceCodeTest, maybeExtendRange_CharRange) { } TEST(SourceCodeTest, getAssociatedRange) { - struct VarDeclsVisitor : AnnotatedCodeVisitor { - bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); } + struct VarDeclsVisitor : AnnotatedCodeVisitor { + bool VisitVarDecl(VarDecl *Decl) override { return VisitDeclHelper(Decl); } }; VarDeclsVisitor Visitor; @@ -283,8 +282,10 @@ TEST(SourceCodeTest, getAssociatedRange) { } TEST(SourceCodeTest, getAssociatedRangeClasses) { - struct RecordDeclsVisitor : AnnotatedCodeVisitor { - bool VisitRecordDecl(RecordDecl *Decl) { return VisitDeclHelper(Decl); } + struct RecordDeclsVisitor : AnnotatedCodeVisitor { + bool VisitRecordDecl(RecordDecl *Decl) override { + return VisitDeclHelper(Decl); + } }; RecordDeclsVisitor Visitor; @@ -297,8 +298,8 @@ TEST(SourceCodeTest, getAssociatedRangeClasses) { } TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) { - struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor { - bool VisitCXXRecordDecl(CXXRecordDecl *Decl) { + struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor { + bool VisitCXXRecordDecl(CXXRecordDecl *Decl) override { return Decl->getTemplateSpecializationKind() != TSK_ExplicitSpecialization || VisitDeclHelper(Decl); @@ -315,8 +316,10 @@ TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) { } TEST(SourceCodeTest, getAssociatedRangeFunctions) { - struct FunctionDeclsVisitor : AnnotatedCodeVisitor { - bool VisitFunctionDecl(FunctionDecl *Decl) { return VisitDeclHelper(Decl); } + struct FunctionDeclsVisitor : AnnotatedCodeVisitor { + bool VisitFunctionDecl(FunctionDecl *Decl) override { + return VisitDeclHelper(Decl); + } }; FunctionDeclsVisitor Visitor; @@ -328,8 +331,8 @@ TEST(SourceCodeTest, getAssociatedRangeFunctions) { } TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) { - struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor { - bool VisitCXXMethodDecl(CXXMethodDecl *Decl) { + struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor { + bool VisitCXXMethodDecl(CXXMethodDecl *Decl) override { // Only consider the definition of the template. return !Decl->doesThisDeclarationHaveABody() || VisitDeclHelper(Decl); } @@ -346,8 +349,8 @@ TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) { } TEST(SourceCodeTest, getAssociatedRangeWithComments) { - struct VarDeclsVisitor : AnnotatedCodeVisitor { - bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); } + struct VarDeclsVisitor : AnnotatedCodeVisitor { + bool VisitVarDecl(VarDecl *Decl) override { return VisitDeclHelper(Decl); } }; VarDeclsVisitor Visitor; @@ -447,9 +450,9 @@ TEST(SourceCodeTest, getAssociatedRangeWithComments) { } TEST(SourceCodeTest, getAssociatedRangeInvalidForPartialExpansions) { - struct FailingVarDeclsVisitor : TestVisitor { + struct FailingVarDeclsVisitor : TestVisitor { FailingVarDeclsVisitor() {} - bool VisitVarDecl(VarDecl *Decl) { + bool VisitVarDecl(VarDecl *Decl) override { EXPECT_TRUE(getAssociatedRange(*Decl, *Context).isInvalid()); return true; } diff --git a/clang/unittests/Tooling/TestVisitor.h b/clang/unittests/Tooling/TestVisitor.h index 751ca74d1a881..fdf57a946a6e2 100644 --- a/clang/unittests/Tooling/TestVisitor.h +++ b/clang/unittests/Tooling/TestVisitor.h @@ -16,7 +16,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Tooling/Tooling.h" @@ -24,20 +24,11 @@ #include namespace clang { - -/// \brief Base class for simple RecursiveASTVisitor based tests. -/// -/// This is a drop-in replacement for RecursiveASTVisitor itself, with the -/// additional capability of running it over a snippet of code. -/// -/// Visits template instantiations and implicit code by default. -template -class TestVisitor : public RecursiveASTVisitor { +namespace detail { +// Use 'TestVisitor' or include 'CRTPTestVisitor.h' and use 'CRTPTestVisitor' +// instead of using this directly. +class TestVisitorHelper { public: - TestVisitor() { } - - virtual ~TestVisitor() { } - enum Language { Lang_C, Lang_CXX98, @@ -54,57 +45,63 @@ class TestVisitor : public RecursiveASTVisitor { bool runOver(StringRef Code, Language L = Lang_CXX) { std::vector Args; switch (L) { - case Lang_C: - Args.push_back("-x"); - Args.push_back("c"); - break; - case Lang_CXX98: Args.push_back("-std=c++98"); break; - case Lang_CXX11: Args.push_back("-std=c++11"); break; - case Lang_CXX14: Args.push_back("-std=c++14"); break; - case Lang_CXX17: Args.push_back("-std=c++17"); break; - case Lang_CXX2a: Args.push_back("-std=c++2a"); break; - case Lang_OBJC: - Args.push_back("-ObjC"); - Args.push_back("-fobjc-runtime=macosx-10.12.0"); - break; - case Lang_OBJCXX11: - Args.push_back("-ObjC++"); - Args.push_back("-std=c++11"); - Args.push_back("-fblocks"); - break; + case Lang_C: + Args.push_back("-x"); + Args.push_back("c"); + break; + case Lang_CXX98: + Args.push_back("-std=c++98"); + break; + case Lang_CXX11: + Args.push_back("-std=c++11"); + break; + case Lang_CXX14: + Args.push_back("-std=c++14"); + break; + case Lang_CXX17: + Args.push_back("-std=c++17"); + break; + case Lang_CXX2a: + Args.push_back("-std=c++2a"); + break; + case Lang_OBJC: + Args.push_back("-ObjC"); + Args.push_back("-fobjc-runtime=macosx-10.12.0"); + break; + case Lang_OBJCXX11: + Args.push_back("-ObjC++"); + Args.push_back("-std=c++11"); + Args.push_back("-fblocks"); + break; } return tooling::runToolOnCodeWithArgs(CreateTestAction(), Code, Args); } - bool shouldVisitTemplateInstantiations() const { - return true; - } - - bool shouldVisitImplicitCode() const { - return true; - } - protected: + TestVisitorHelper() = default; + virtual ~TestVisitorHelper() = default; + virtual void InvokeTraverseDecl(TranslationUnitDecl *D) = 0; + virtual std::unique_ptr CreateTestAction() { return std::make_unique(this); } class FindConsumer : public ASTConsumer { public: - FindConsumer(TestVisitor *Visitor) : Visitor(Visitor) {} + FindConsumer(TestVisitorHelper *Visitor) : Visitor(Visitor) {} void HandleTranslationUnit(clang::ASTContext &Context) override { Visitor->Context = &Context; - Visitor->TraverseDecl(Context.getTranslationUnitDecl()); + Visitor->InvokeTraverseDecl(Context.getTranslationUnitDecl()); } private: - TestVisitor *Visitor; + TestVisitorHelper *Visitor; }; class TestAction : public ASTFrontendAction { public: - TestAction(TestVisitor *Visitor) : Visitor(Visitor) {} + TestAction(TestVisitorHelper *Visitor) : Visitor(Visitor) {} std::unique_ptr CreateASTConsumer(CompilerInstance &, llvm::StringRef dummy) override { @@ -113,20 +110,13 @@ class TestVisitor : public RecursiveASTVisitor { } protected: - TestVisitor *Visitor; + TestVisitorHelper *Visitor; }; ASTContext *Context; }; -/// \brief A RecursiveASTVisitor to check that certain matches are (or are -/// not) observed during visitation. -/// -/// This is a RecursiveASTVisitor for testing the RecursiveASTVisitor itself, -/// and allows simple creation of test visitors running matches on only a small -/// subset of the Visit* methods. -template class Visitor = TestVisitor> -class ExpectedLocationVisitor : public Visitor { +class ExpectedLocationVisitorHelper { public: /// \brief Expect 'Match' *not* to occur at the given 'Line' and 'Column'. /// @@ -147,37 +137,44 @@ class ExpectedLocationVisitor : public Visitor { } /// \brief Checks that all expected matches have been found. - ~ExpectedLocationVisitor() override { - for (typename std::vector::const_iterator - It = ExpectedMatches.begin(), End = ExpectedMatches.end(); + virtual ~ExpectedLocationVisitorHelper() { + // FIXME: Range-based for loop. + for (std::vector::const_iterator + It = ExpectedMatches.begin(), + End = ExpectedMatches.end(); It != End; ++It) { It->ExpectFound(); } } protected: + virtual ASTContext *getASTContext() = 0; + /// \brief Checks an actual match against expected and disallowed matches. /// /// Implementations are required to call this with appropriate values /// for 'Name' during visitation. void Match(StringRef Name, SourceLocation Location) { - const FullSourceLoc FullLocation = this->Context->getFullLoc(Location); + const FullSourceLoc FullLocation = getASTContext()->getFullLoc(Location); - for (typename std::vector::const_iterator - It = DisallowedMatches.begin(), End = DisallowedMatches.end(); + // FIXME: Range-based for loop. + for (std::vector::const_iterator + It = DisallowedMatches.begin(), + End = DisallowedMatches.end(); It != End; ++It) { EXPECT_FALSE(It->Matches(Name, FullLocation)) << "Matched disallowed " << *It; } - for (typename std::vector::iterator - It = ExpectedMatches.begin(), End = ExpectedMatches.end(); + // FIXME: Range-based for loop. + for (std::vector::iterator It = ExpectedMatches.begin(), + End = ExpectedMatches.end(); It != End; ++It) { - It->UpdateFor(Name, FullLocation, this->Context->getSourceManager()); + It->UpdateFor(Name, FullLocation, getASTContext()->getSourceManager()); } } - private: +private: struct MatchCandidate { std::string ExpectedName; unsigned LineNumber; @@ -247,6 +244,41 @@ class ExpectedLocationVisitor : public Visitor { std::vector DisallowedMatches; std::vector ExpectedMatches; }; -} +} // namespace detail + +/// \brief Base class for simple (Dynamic)RecursiveASTVisitor based tests. +/// +/// This is a drop-in replacement for DynamicRecursiveASTVisitor itself, with +/// the additional capability of running it over a snippet of code. +/// +/// Visits template instantiations and implicit code by default. +/// +/// For post-order traversal etc. use CTRPTestVisitor from +/// CTRPTestVisitor.h instead. +class TestVisitor : public DynamicRecursiveASTVisitor, + public detail::TestVisitorHelper { +public: + TestVisitor() { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = true; + } + + void InvokeTraverseDecl(TranslationUnitDecl *D) override { TraverseDecl(D); } +}; + +/// \brief A RecursiveASTVisitor to check that certain matches are (or are +/// not) observed during visitation. +/// +/// This is a RecursiveASTVisitor for testing the RecursiveASTVisitor itself, +/// and allows simple creation of test visitors running matches on only a small +/// subset of the Visit* methods. +/// +/// For post-order traversal etc. use CTRPExpectedLocationVisitor from +/// CTRPTestVisitor.h instead. +class ExpectedLocationVisitor : public TestVisitor, + public detail::ExpectedLocationVisitorHelper { + ASTContext *getASTContext() override { return Context; } +}; +} // namespace clang #endif diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index adbe6af62d5cb..cc01fed4be147 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -3926,7 +3926,7 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { OS << " return 0;\n"; } -// Emits code used by RecursiveASTVisitor to visit attributes +// Emits code used by (Dynamic)RecursiveASTVisitor to visit attributes void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS, Records); @@ -3936,7 +3936,7 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { // Write method declarations for Traverse* methods. // We emit this here because we only generate methods for attributes that // are declared as ASTNodes. - OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n"; + OS << "#ifdef ATTR_VISITOR_DECLS\n\n"; for (const auto *Attr : Attrs) { const Record &R = *Attr; if (!R.getValueAsBit("ASTNode")) @@ -3948,9 +3948,10 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { << " return true; \n" << " }\n"; } - OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n"; + OS << "\n#endif // ATTR_VISITOR_DECLS\n\n"; // Write individual Traverse* methods for each attribute class. + OS << "#ifdef ATTR_VISITOR_IMPL\n\n"; for (const auto *Attr : Attrs) { const Record &R = *Attr; if (!R.getValueAsBit("ASTNode")) @@ -3996,7 +3997,40 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { OS << " }\n"; // end switch OS << " llvm_unreachable(\"bad attribute kind\");\n"; OS << "}\n"; // end function - OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n"; + OS << "#endif // ATTR_VISITOR_IMPL\n"; + + // Write virtual function declarations / trivial definitions. + OS << "#ifdef DYNAMIC_ATTR_VISITOR_DECLS\n\n"; + for (const auto *Attr : Attrs) { + const Record &R = *Attr; + if (!R.getValueAsBit("ASTNode")) + continue; + OS << " virtual bool Traverse" << R.getName() << "Attr(" << R.getName() + << "Attr *A);\n"; + OS << " virtual bool Visit" << R.getName() << "Attr(" << R.getName() + << "Attr *A) {\n" + << " return true; \n" + << " }\n"; + } + OS << "\n#endif // DYNAMIC_ATTR_VISITOR_DECLS\n\n"; + + // Write traversal functions that dispatch to the appropriate visitor. + OS << "#ifdef DYNAMIC_ATTR_VISITOR_IMPL\n\n"; + for (const auto *Attr : Attrs) { + const Record &R = *Attr; + if (!R.getValueAsBit("ASTNode")) + continue; + OS << "bool Impl::Traverse" << R.getName() << "Attr(" << R.getName() + << "Attr *A) {\n" + << " return Visitor.Traverse" << R.getName() << "Attr(A);\n" + << "}\n"; + OS << "bool DynamicRecursiveASTVisitor::Traverse" << R.getName() << "Attr(" + << R.getName() << "Attr *A) {\n" + << " return Impl(*this).RecursiveASTVisitor::Traverse" + << R.getName() << "Attr(A);\n" + << "}\n"; + } + OS << "\n#endif // DYNAMIC_ATTR_VISITOR_IMPL\n\n"; } void EmitClangAttrTemplateInstantiateHelper(const std::vector &Attrs,