[Clang] [NFC] Introduce ConstDynamicRecursiveASTVisitor (#122991)
After some discussion around #116823, it was decided that it would be nice to have a `const` variant of `DynamicRecursiveASTVisitor`, so this pr does exactly that by making the main DRAV implementation a template with a single `bool` template parameter that turns several function parameters from a `T*` or `T&` to a `const T*` or `const T&`. Since that made the implementation of a bunch of DRAV functions quite a bit more verbose, I’ve moved most of them to be stamped out by a macro, which imo makes it easier to understand what’s actually going on there. For functions which already accepted `const` parameters in the original RAV implementation, the parameter is `const` in both versions (e.g. `TraverseTemplateArgument()` always takes a `const TemplateArgument&`); conversely, parameters that are passed by value (e.g. in `TraverseType()`, which takes a `QualType` by value) are *not* `const` in either variant (i.e. the `QualType` argument is always just a `QualType`, never a `const QualType`). As a sanity check, I’ve also migrated some random visitor in the static analyser to the `const` version (and indeed, it ends up simplifying the code around that particular visitor actually). It would make sense to do a pass over all visitors and change all which can be `const` use the `const` version, but that can be done in a follow-up pr. The [performance impact](https://llvm-compile-time-tracker.com/compare.php?from=e3cd88a7be1dfd912bb6e7c7e888e7b442ffb5de&to=d55c5afe4a485b6d0431386e6f45cb44c1fc8883&stat=instructions:u) of this change seems to be negligible. Clang’s binary size went up by 0.5%, but that’s expected considering that this effectively adds an extra instantiation of `RecursiveASTVisitor`. Fortunately, this is of course a one-time cost.
This commit is contained in:
@@ -52,7 +52,11 @@ class ASTContext;
|
||||
/// WalkUpFromX or post-order traversal).
|
||||
///
|
||||
/// \see RecursiveASTVisitor.
|
||||
class DynamicRecursiveASTVisitor {
|
||||
template <bool IsConst> class DynamicRecursiveASTVisitorBase {
|
||||
protected:
|
||||
template <typename ASTNode>
|
||||
using MaybeConst = std::conditional_t<IsConst, const ASTNode, ASTNode>;
|
||||
|
||||
public:
|
||||
/// Whether this visitor should recurse into template instantiations.
|
||||
bool ShouldVisitTemplateInstantiations = false;
|
||||
@@ -68,28 +72,29 @@ public:
|
||||
bool ShouldVisitLambdaBody = true;
|
||||
|
||||
protected:
|
||||
DynamicRecursiveASTVisitor() = default;
|
||||
DynamicRecursiveASTVisitor(DynamicRecursiveASTVisitor &&) = default;
|
||||
DynamicRecursiveASTVisitor(const DynamicRecursiveASTVisitor &) = default;
|
||||
DynamicRecursiveASTVisitor &
|
||||
operator=(DynamicRecursiveASTVisitor &&) = default;
|
||||
DynamicRecursiveASTVisitor &
|
||||
operator=(const DynamicRecursiveASTVisitor &) = default;
|
||||
DynamicRecursiveASTVisitorBase() = default;
|
||||
DynamicRecursiveASTVisitorBase(DynamicRecursiveASTVisitorBase &&) = default;
|
||||
DynamicRecursiveASTVisitorBase(const DynamicRecursiveASTVisitorBase &) =
|
||||
default;
|
||||
DynamicRecursiveASTVisitorBase &
|
||||
operator=(DynamicRecursiveASTVisitorBase &&) = default;
|
||||
DynamicRecursiveASTVisitorBase &
|
||||
operator=(const DynamicRecursiveASTVisitorBase &) = default;
|
||||
|
||||
public:
|
||||
virtual void anchor();
|
||||
virtual ~DynamicRecursiveASTVisitor() = default;
|
||||
virtual ~DynamicRecursiveASTVisitorBase() = default;
|
||||
|
||||
/// Recursively visits an entire AST, starting from the TranslationUnitDecl.
|
||||
/// \returns false if visitation was terminated early.
|
||||
virtual bool TraverseAST(ASTContext &AST);
|
||||
virtual bool TraverseAST(MaybeConst<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);
|
||||
virtual bool TraverseAttr(MaybeConst<Attr> *At);
|
||||
|
||||
/// Recursively visit a constructor initializer. This
|
||||
/// automatically dispatches to another visitor for the initializer
|
||||
@@ -97,7 +102,8 @@ public:
|
||||
/// 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);
|
||||
virtual bool
|
||||
TraverseConstructorInitializer(MaybeConst<CXXCtorInitializer> *Init);
|
||||
|
||||
/// Recursively visit a base specifier. This can be overridden by a
|
||||
/// subclass.
|
||||
@@ -110,7 +116,7 @@ public:
|
||||
///
|
||||
/// \returns false if the visitation was terminated early, true
|
||||
/// otherwise (including when the argument is NULL).
|
||||
virtual bool TraverseDecl(Decl *D);
|
||||
virtual bool TraverseDecl(MaybeConst<Decl> *D);
|
||||
|
||||
/// Recursively visit a name with its location information.
|
||||
///
|
||||
@@ -121,13 +127,15 @@ public:
|
||||
/// 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);
|
||||
virtual bool TraverseLambdaCapture(MaybeConst<LambdaExpr> *LE,
|
||||
const LambdaCapture *C,
|
||||
MaybeConst<Expr> *Init);
|
||||
|
||||
/// Recursively visit a C++ nested-name-specifier.
|
||||
///
|
||||
/// \returns false if the visitation was terminated early, true otherwise.
|
||||
virtual bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
|
||||
virtual bool
|
||||
TraverseNestedNameSpecifier(MaybeConst<NestedNameSpecifier> *NNS);
|
||||
|
||||
/// Recursively visit a C++ nested-name-specifier with location
|
||||
/// information.
|
||||
@@ -140,7 +148,7 @@ public:
|
||||
///
|
||||
/// \returns false if the visitation was terminated early, true
|
||||
/// otherwise (including when the argument is nullptr).
|
||||
virtual bool TraverseStmt(Stmt *S);
|
||||
virtual bool TraverseStmt(MaybeConst<Stmt> *S);
|
||||
|
||||
/// Recursively visit a template argument and dispatch to the
|
||||
/// appropriate method for the argument type.
|
||||
@@ -190,41 +198,51 @@ public:
|
||||
|
||||
/// 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; }
|
||||
virtual bool TraverseConceptRequirement(MaybeConst<concepts::Requirement> *R);
|
||||
|
||||
virtual bool
|
||||
TraverseConceptTypeRequirement(MaybeConst<concepts::TypeRequirement> *R);
|
||||
|
||||
virtual bool
|
||||
TraverseConceptExprRequirement(MaybeConst<concepts::ExprRequirement> *R);
|
||||
|
||||
virtual bool
|
||||
TraverseConceptNestedRequirement(MaybeConst<concepts::NestedRequirement> *R);
|
||||
|
||||
virtual bool TraverseConceptReference(MaybeConst<ConceptReference> *CR);
|
||||
virtual bool VisitConceptReference(MaybeConst<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 VisitAttr(MaybeConst<Attr> *A) { return true; }
|
||||
virtual bool VisitDecl(MaybeConst<Decl> *D) { return true; }
|
||||
virtual bool VisitStmt(MaybeConst<Stmt> *S) { return true; }
|
||||
virtual bool VisitType(MaybeConst<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 WalkUpFromDecl(MaybeConst<Decl> *D) { return VisitDecl(D); }
|
||||
bool WalkUpFromStmt(MaybeConst<Stmt> *S) { return VisitStmt(S); }
|
||||
bool WalkUpFromType(MaybeConst<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; }
|
||||
virtual bool dataTraverseStmtPre(MaybeConst<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);
|
||||
virtual bool dataTraverseStmtPost(MaybeConst<Stmt> *S) { return true; }
|
||||
virtual bool dataTraverseNode(MaybeConst<Stmt> *S);
|
||||
|
||||
#define DEF_TRAVERSE_TMPL_INST(kind) \
|
||||
virtual bool TraverseTemplateInstantiations(kind##TemplateDecl *D);
|
||||
virtual bool TraverseTemplateInstantiations( \
|
||||
MaybeConst<kind##TemplateDecl> *D);
|
||||
DEF_TRAVERSE_TMPL_INST(Class)
|
||||
DEF_TRAVERSE_TMPL_INST(Var)
|
||||
DEF_TRAVERSE_TMPL_INST(Function)
|
||||
@@ -232,32 +250,34 @@ public:
|
||||
|
||||
// Decls.
|
||||
#define ABSTRACT_DECL(DECL)
|
||||
#define DECL(CLASS, BASE) virtual bool Traverse##CLASS##Decl(CLASS##Decl *D);
|
||||
#define DECL(CLASS, BASE) \
|
||||
virtual bool Traverse##CLASS##Decl(MaybeConst<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; }
|
||||
bool WalkUpFrom##CLASS##Decl(MaybeConst<CLASS##Decl> *D); \
|
||||
virtual bool Visit##CLASS##Decl(MaybeConst<CLASS##Decl> *D) { return true; }
|
||||
#include "clang/AST/DeclNodes.inc"
|
||||
|
||||
// Stmts.
|
||||
#define ABSTRACT_STMT(STMT)
|
||||
#define STMT(CLASS, PARENT) virtual bool Traverse##CLASS(CLASS *S);
|
||||
#define STMT(CLASS, PARENT) virtual bool Traverse##CLASS(MaybeConst<CLASS> *S);
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
|
||||
#define STMT(CLASS, PARENT) \
|
||||
bool WalkUpFrom##CLASS(CLASS *S); \
|
||||
virtual bool Visit##CLASS(CLASS *S) { return true; }
|
||||
bool WalkUpFrom##CLASS(MaybeConst<CLASS> *S); \
|
||||
virtual bool Visit##CLASS(MaybeConst<CLASS> *S) { return true; }
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
|
||||
// Types.
|
||||
#define ABSTRACT_TYPE(CLASS, BASE)
|
||||
#define TYPE(CLASS, BASE) virtual bool Traverse##CLASS##Type(CLASS##Type *T);
|
||||
#define TYPE(CLASS, BASE) \
|
||||
virtual bool Traverse##CLASS##Type(MaybeConst<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; }
|
||||
bool WalkUpFrom##CLASS##Type(MaybeConst<CLASS##Type> *T); \
|
||||
virtual bool Visit##CLASS##Type(MaybeConst<CLASS##Type> *T) { return true; }
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
|
||||
// TypeLocs.
|
||||
@@ -271,6 +291,14 @@ public:
|
||||
virtual bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
};
|
||||
|
||||
extern template class DynamicRecursiveASTVisitorBase<false>;
|
||||
extern template class DynamicRecursiveASTVisitorBase<true>;
|
||||
|
||||
using DynamicRecursiveASTVisitor =
|
||||
DynamicRecursiveASTVisitorBase</*Const=*/false>;
|
||||
using ConstDynamicRecursiveASTVisitor =
|
||||
DynamicRecursiveASTVisitorBase</*Const=*/true>;
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
|
||||
|
||||
@@ -89,9 +89,9 @@ using namespace clang;
|
||||
//
|
||||
// End result: RAV::TraverseCallExpr() is executed,
|
||||
namespace {
|
||||
struct Impl : RecursiveASTVisitor<Impl> {
|
||||
DynamicRecursiveASTVisitor &Visitor;
|
||||
Impl(DynamicRecursiveASTVisitor &Visitor) : Visitor(Visitor) {}
|
||||
template <bool Const> struct Impl : RecursiveASTVisitor<Impl<Const>> {
|
||||
DynamicRecursiveASTVisitorBase<Const> &Visitor;
|
||||
Impl(DynamicRecursiveASTVisitorBase<Const> &Visitor) : Visitor(Visitor) {}
|
||||
|
||||
bool shouldVisitTemplateInstantiations() const {
|
||||
return Visitor.ShouldVisitTemplateInstantiations;
|
||||
@@ -189,8 +189,10 @@ struct Impl : RecursiveASTVisitor<Impl> {
|
||||
|
||||
// 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
|
||||
bool dataTraverseNode(
|
||||
Stmt *S,
|
||||
typename RecursiveASTVisitor<Impl>::DataRecursionQueue * = nullptr) {
|
||||
// But since we 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);
|
||||
@@ -266,187 +268,108 @@ struct Impl : RecursiveASTVisitor<Impl> {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
void DynamicRecursiveASTVisitor::anchor() {}
|
||||
template <bool Const> void DynamicRecursiveASTVisitorBase<Const>::anchor() {}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseAST(ASTContext &AST) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseAST(AST);
|
||||
}
|
||||
// Helper macros to forward a call to the base implementation since that
|
||||
// ends up getting very verbose otherwise.
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseAttr(Attr *At) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseAttr(At);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseConstructorInitializer(
|
||||
CXXCtorInitializer *Init) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConstructorInitializer(
|
||||
Init);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseDecl(Decl *D) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseDecl(D);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseLambdaCapture(LambdaExpr *LE,
|
||||
const LambdaCapture *C,
|
||||
Expr *Init) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseLambdaCapture(LE, C,
|
||||
Init);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseStmt(Stmt *S) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseStmt(S);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseTemplateArgument(
|
||||
const TemplateArgument &Arg) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateArgument(Arg);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseTemplateArguments(
|
||||
ArrayRef<TemplateArgument> Args) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateArguments(Args);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(
|
||||
const TemplateArgumentLoc &ArgLoc) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateArgumentLoc(
|
||||
ArgLoc);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseTemplateName(TemplateName Template) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateName(Template);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseType(QualType T) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseType(T);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseTypeLoc(TypeLoc TL) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTypeLoc(TL);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseTypeConstraint(
|
||||
const TypeConstraint *C) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTypeConstraint(C);
|
||||
}
|
||||
bool DynamicRecursiveASTVisitor::TraverseObjCProtocolLoc(
|
||||
ObjCProtocolLoc ProtocolLoc) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseObjCProtocolLoc(
|
||||
ProtocolLoc);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseConceptRequirement(
|
||||
concepts::Requirement *R) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptRequirement(R);
|
||||
}
|
||||
bool DynamicRecursiveASTVisitor::TraverseConceptTypeRequirement(
|
||||
concepts::TypeRequirement *R) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptTypeRequirement(
|
||||
R);
|
||||
}
|
||||
bool DynamicRecursiveASTVisitor::TraverseConceptExprRequirement(
|
||||
concepts::ExprRequirement *R) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptExprRequirement(
|
||||
R);
|
||||
}
|
||||
bool DynamicRecursiveASTVisitor::TraverseConceptNestedRequirement(
|
||||
concepts::NestedRequirement *R) {
|
||||
return Impl(*this)
|
||||
.RecursiveASTVisitor<Impl>::TraverseConceptNestedRequirement(R);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseConceptReference(
|
||||
ConceptReference *CR) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptReference(CR);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseCXXBaseSpecifier(
|
||||
const CXXBaseSpecifier &Base) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseCXXBaseSpecifier(Base);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseDeclarationNameInfo(
|
||||
DeclarationNameInfo NameInfo) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseDeclarationNameInfo(
|
||||
NameInfo);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifier(
|
||||
NestedNameSpecifier *NNS) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseNestedNameSpecifier(
|
||||
NNS);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(
|
||||
NestedNameSpecifierLoc NNS) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::TraverseNestedNameSpecifierLoc(
|
||||
NNS);
|
||||
}
|
||||
|
||||
bool DynamicRecursiveASTVisitor::dataTraverseNode(Stmt *S) {
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::dataTraverseNode(S, nullptr);
|
||||
}
|
||||
|
||||
#define DEF_TRAVERSE_TMPL_INST(kind) \
|
||||
bool DynamicRecursiveASTVisitor::TraverseTemplateInstantiations( \
|
||||
kind##TemplateDecl *D) { \
|
||||
return Impl(*this) \
|
||||
.RecursiveASTVisitor<Impl>::TraverseTemplateInstantiations(D); \
|
||||
// This calls the RecursiveASTVisitor implementation of the same function,
|
||||
// stripping any 'const' that the DRAV implementation may have added since
|
||||
// the RAV implementation largely doesn't use 'const'.
|
||||
#define FORWARD_TO_BASE(Function, Type, RefOrPointer) \
|
||||
template <bool Const> \
|
||||
bool DynamicRecursiveASTVisitorBase<Const>::Function( \
|
||||
MaybeConst<Type> RefOrPointer Param) { \
|
||||
return Impl<Const>(*this) \
|
||||
.template RecursiveASTVisitor<Impl<Const>>::Function( \
|
||||
const_cast<Type RefOrPointer>(Param)); \
|
||||
}
|
||||
DEF_TRAVERSE_TMPL_INST(Class)
|
||||
DEF_TRAVERSE_TMPL_INST(Var)
|
||||
DEF_TRAVERSE_TMPL_INST(Function)
|
||||
#undef DEF_TRAVERSE_TMPL_INST
|
||||
|
||||
// Same as 'FORWARD_TO_BASE', but doesn't change the parameter type in any way.
|
||||
#define FORWARD_TO_BASE_EXACT(Function, Type) \
|
||||
template <bool Const> \
|
||||
bool DynamicRecursiveASTVisitorBase<Const>::Function(Type Param) { \
|
||||
return Impl<Const>(*this) \
|
||||
.template RecursiveASTVisitor<Impl<Const>>::Function(Param); \
|
||||
}
|
||||
|
||||
FORWARD_TO_BASE(TraverseAST, ASTContext, &)
|
||||
FORWARD_TO_BASE(TraverseAttr, Attr, *)
|
||||
FORWARD_TO_BASE(TraverseConstructorInitializer, CXXCtorInitializer, *)
|
||||
FORWARD_TO_BASE(TraverseDecl, Decl, *)
|
||||
FORWARD_TO_BASE(TraverseStmt, Stmt, *)
|
||||
FORWARD_TO_BASE(TraverseNestedNameSpecifier, NestedNameSpecifier, *)
|
||||
FORWARD_TO_BASE(TraverseTemplateInstantiations, ClassTemplateDecl, *)
|
||||
FORWARD_TO_BASE(TraverseTemplateInstantiations, VarTemplateDecl, *)
|
||||
FORWARD_TO_BASE(TraverseTemplateInstantiations, FunctionTemplateDecl, *)
|
||||
FORWARD_TO_BASE(TraverseConceptRequirement, concepts::Requirement, *)
|
||||
FORWARD_TO_BASE(TraverseConceptTypeRequirement, concepts::TypeRequirement, *)
|
||||
FORWARD_TO_BASE(TraverseConceptExprRequirement, concepts::ExprRequirement, *)
|
||||
FORWARD_TO_BASE(TraverseConceptReference, ConceptReference, *)
|
||||
FORWARD_TO_BASE(TraverseConceptNestedRequirement,
|
||||
concepts::NestedRequirement, *)
|
||||
|
||||
FORWARD_TO_BASE_EXACT(TraverseCXXBaseSpecifier, const CXXBaseSpecifier &)
|
||||
FORWARD_TO_BASE_EXACT(TraverseDeclarationNameInfo, DeclarationNameInfo)
|
||||
FORWARD_TO_BASE_EXACT(TraverseTemplateArgument, const TemplateArgument &)
|
||||
FORWARD_TO_BASE_EXACT(TraverseTemplateArguments, ArrayRef<TemplateArgument>)
|
||||
FORWARD_TO_BASE_EXACT(TraverseTemplateArgumentLoc, const TemplateArgumentLoc &)
|
||||
FORWARD_TO_BASE_EXACT(TraverseTemplateName, TemplateName)
|
||||
FORWARD_TO_BASE_EXACT(TraverseType, QualType)
|
||||
FORWARD_TO_BASE_EXACT(TraverseTypeLoc, TypeLoc)
|
||||
FORWARD_TO_BASE_EXACT(TraverseTypeConstraint, const TypeConstraint *)
|
||||
FORWARD_TO_BASE_EXACT(TraverseObjCProtocolLoc, ObjCProtocolLoc)
|
||||
FORWARD_TO_BASE_EXACT(TraverseNestedNameSpecifierLoc, NestedNameSpecifierLoc)
|
||||
|
||||
template <bool Const>
|
||||
bool DynamicRecursiveASTVisitorBase<Const>::TraverseLambdaCapture(
|
||||
MaybeConst<LambdaExpr> *LE, const LambdaCapture *C,
|
||||
MaybeConst<Expr> *Init) {
|
||||
return Impl<Const>(*this)
|
||||
.template RecursiveASTVisitor<Impl<Const>>::TraverseLambdaCapture(
|
||||
const_cast<LambdaExpr *>(LE), C, const_cast<Expr *>(Init));
|
||||
}
|
||||
|
||||
template <bool Const>
|
||||
bool DynamicRecursiveASTVisitorBase<Const>::dataTraverseNode(
|
||||
MaybeConst<Stmt> *S) {
|
||||
return Impl<Const>(*this)
|
||||
.template RecursiveASTVisitor<Impl<Const>>::dataTraverseNode(
|
||||
const_cast<Stmt *>(S), nullptr);
|
||||
}
|
||||
|
||||
// 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<Impl>::Traverse##CLASS##Decl(D); \
|
||||
} \
|
||||
bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS##Decl(D); \
|
||||
}
|
||||
FORWARD_TO_BASE(Traverse##CLASS##Decl, CLASS##Decl, *) \
|
||||
FORWARD_TO_BASE(WalkUpFrom##CLASS##Decl, CLASS##Decl, *)
|
||||
#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<Impl>::Traverse##CLASS(S); \
|
||||
}
|
||||
#define STMT(CLASS, PARENT) FORWARD_TO_BASE(Traverse##CLASS, CLASS, *)
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
|
||||
#define STMT(CLASS, PARENT) \
|
||||
bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS(CLASS *S) { \
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS(S); \
|
||||
}
|
||||
#define STMT(CLASS, PARENT) FORWARD_TO_BASE(WalkUpFrom##CLASS, CLASS, *)
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
|
||||
// Declare Traverse*() and friends for all concrete Typeclasses.
|
||||
// Declare Traverse*() and friends for all concrete Type classes.
|
||||
#define ABSTRACT_TYPE(CLASS, BASE)
|
||||
#define TYPE(CLASS, BASE) \
|
||||
bool DynamicRecursiveASTVisitor::Traverse##CLASS##Type(CLASS##Type *T) { \
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS##Type(T); \
|
||||
} \
|
||||
bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##Type(CLASS##Type *T) { \
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS##Type(T); \
|
||||
}
|
||||
FORWARD_TO_BASE(Traverse##CLASS##Type, CLASS##Type, *) \
|
||||
FORWARD_TO_BASE(WalkUpFrom##CLASS##Type, CLASS##Type, *)
|
||||
#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<Impl>::Traverse##CLASS##TypeLoc( \
|
||||
TL); \
|
||||
}
|
||||
FORWARD_TO_BASE_EXACT(Traverse##CLASS##TypeLoc, CLASS##TypeLoc)
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
#define TYPELOC(CLASS, BASE) \
|
||||
bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##TypeLoc( \
|
||||
CLASS##TypeLoc TL) { \
|
||||
return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS##TypeLoc( \
|
||||
TL); \
|
||||
}
|
||||
FORWARD_TO_BASE_EXACT(WalkUpFrom##CLASS##TypeLoc, CLASS##TypeLoc)
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
namespace clang {
|
||||
template class DynamicRecursiveASTVisitorBase<false>;
|
||||
template class DynamicRecursiveASTVisitorBase<true>;
|
||||
} // namespace clang
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
// 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 : DynamicRecursiveASTVisitor {
|
||||
struct LocalVisitor : ConstDynamicRecursiveASTVisitor {
|
||||
const RawPtrRefMemberChecker *Checker;
|
||||
explicit LocalVisitor(const RawPtrRefMemberChecker *Checker)
|
||||
: Checker(Checker) {
|
||||
@@ -57,14 +57,14 @@ public:
|
||||
ShouldVisitImplicitCode = false;
|
||||
}
|
||||
|
||||
bool VisitRecordDecl(RecordDecl *RD) override {
|
||||
bool VisitRecordDecl(const RecordDecl *RD) override {
|
||||
Checker->visitRecordDecl(RD);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
LocalVisitor visitor(this);
|
||||
visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
|
||||
visitor.TraverseDecl(TUD);
|
||||
}
|
||||
|
||||
void visitRecordDecl(const RecordDecl *RD) const {
|
||||
|
||||
Reference in New Issue
Block a user