From 561fe54a1a844e009a8f17d25a113353cee6d07d Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Fri, 20 Dec 2013 02:02:54 +0000 Subject: Move tools/libclang/RecursiveASTVisitor.h -> include/clang/AST/DataRecursiveASTVisitor.h This is to make it available so the static analyzer can use it. llvm-svn: 197766 --- clang/tools/libclang/RecursiveASTVisitor.h | 2387 ---------------------------- 1 file changed, 2387 deletions(-) delete mode 100644 clang/tools/libclang/RecursiveASTVisitor.h (limited to 'clang/tools/libclang/RecursiveASTVisitor.h') diff --git a/clang/tools/libclang/RecursiveASTVisitor.h b/clang/tools/libclang/RecursiveASTVisitor.h deleted file mode 100644 index fa574f66a1b..00000000000 --- a/clang/tools/libclang/RecursiveASTVisitor.h +++ /dev/null @@ -1,2387 +0,0 @@ -//===--- RecursiveASTVisitor.h - Recursive AST Visitor ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the RecursiveASTVisitor interface, which recursively -// traverses the entire AST. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIBCLANG_RECURSIVEASTVISITOR_H -#define LLVM_CLANG_LIBCLANG_RECURSIVEASTVISITOR_H - -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclFriend.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclOpenMP.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/Stmt.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h" -#include "clang/AST/StmtOpenMP.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/TemplateName.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeLoc.h" - -// The following three macros are used for meta programming. The code -// using them is responsible for defining macro OPERATOR(). - -// All unary operators. -#define UNARYOP_LIST() \ - OPERATOR(PostInc) OPERATOR(PostDec) \ - OPERATOR(PreInc) OPERATOR(PreDec) \ - OPERATOR(AddrOf) OPERATOR(Deref) \ - OPERATOR(Plus) OPERATOR(Minus) \ - OPERATOR(Not) OPERATOR(LNot) \ - OPERATOR(Real) OPERATOR(Imag) \ - OPERATOR(Extension) - -// All binary operators (excluding compound assign operators). -#define BINOP_LIST() \ - OPERATOR(PtrMemD) OPERATOR(PtrMemI) \ - OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) \ - OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) \ - OPERATOR(Shr) \ - \ - OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) \ - OPERATOR(GE) OPERATOR(EQ) OPERATOR(NE) \ - OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \ - OPERATOR(LAnd) OPERATOR(LOr) \ - \ - OPERATOR(Assign) \ - OPERATOR(Comma) - -// All compound assign operators. -#define CAO_LIST() \ - OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \ - OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) - -namespace clang { -namespace cxindex { - -// A helper macro to implement short-circuiting when recursing. It -// invokes CALL_EXPR, which must be a method call, on the derived -// object (s.t. a user of RecursiveASTVisitor can override the method -// in CALL_EXPR). -#define TRY_TO(CALL_EXPR) \ - do { if (!getDerived().CALL_EXPR) return false; } while (0) - -/// \brief A class that does preorder depth-first traversal on the -/// entire Clang AST and visits each node. -/// -/// This class performs three distinct tasks: -/// 1. traverse the AST (i.e. go to each node); -/// 2. at a given node, walk up the class hierarchy, starting from -/// the node's dynamic type, until the top-most class (e.g. Stmt, -/// Decl, or Type) is reached. -/// 3. given a (node, class) combination, where 'class' is some base -/// class of the dynamic type of 'node', call a user-overridable -/// function to actually visit the node. -/// -/// These tasks are done by three groups of methods, respectively: -/// 1. TraverseDecl(Decl *x) does task #1. It is the entry point -/// for traversing an AST rooted at x. This method simply -/// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo -/// is the dynamic type of *x, which calls WalkUpFromFoo(x) and -/// then recursively visits the child nodes of x. -/// TraverseStmt(Stmt *x) and TraverseType(QualType x) work -/// similarly. -/// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit -/// any child node of x. Instead, it first calls WalkUpFromBar(x) -/// where Bar is the direct parent class of Foo (unless Foo has -/// no parent), and then calls VisitFoo(x) (see the next list item). -/// 3. VisitFoo(Foo *x) does task #3. -/// -/// These three method groups are tiered (Traverse* > WalkUpFrom* > -/// Visit*). A method (e.g. Traverse*) may call methods from the same -/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*). -/// It may not call methods from a higher tier. -/// -/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar -/// is Foo's super class) before calling VisitFoo(), the result is -/// that the Visit*() methods for a given node are called in the -/// top-down order (e.g. for a node of type NamedDecl, the order will -/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()). -/// -/// This scheme guarantees that all Visit*() calls for the same AST -/// node are grouped together. In other words, Visit*() methods for -/// different nodes are never interleaved. -/// -/// Stmts are traversed internally using a data queue to avoid a stack overflow -/// with hugely nested ASTs. -/// -/// Clients of this visitor should subclass the visitor (providing -/// themselves as the template argument, using the curiously recurring -/// template pattern) and override any of the Traverse*, WalkUpFrom*, -/// and Visit* methods for declarations, types, statements, -/// expressions, or other AST nodes where the visitor should customize -/// behavior. Most users only need to override Visit*. Advanced -/// users may override Traverse* and WalkUpFrom* to implement custom -/// traversal strategies. Returning false from one of these overridden -/// functions will abort the entire traversal. -/// -/// By default, this visitor tries to visit every part of the explicit -/// source code exactly once. The default policy towards templates -/// is to descend into the 'pattern' class or function body, not any -/// explicit or implicit instantiations. Explicit specializations -/// are still visited, and the patterns of partial specializations -/// are visited separately. This behavior can be changed by -/// overriding shouldVisitTemplateInstantiations() in the derived class -/// to return true, in which case all known implicit and explicit -/// instantiations will be visited at the same time as the pattern -/// from which they were produced. -template -class RecursiveASTVisitor { -public: - /// \brief Return a reference to the derived class. - Derived &getDerived() { return *static_cast(this); } - - /// \brief Return whether this visitor should recurse into - /// template instantiations. - bool shouldVisitTemplateInstantiations() const { return false; } - - /// \brief Return whether this visitor should recurse into the types of - /// TypeLocs. - bool shouldWalkTypesOfTypeLocs() const { return true; } - - /// \brief 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 NULL). - bool TraverseStmt(Stmt *S); - - /// \brief 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). - bool TraverseType(QualType T); - - /// \brief 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). - bool TraverseTypeLoc(TypeLoc TL); - - /// \brief 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). - bool TraverseDecl(Decl *D); - - /// \brief Recursively visit a C++ nested-name-specifier. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); - - /// \brief Recursively visit a C++ nested-name-specifier with location - /// information. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); - - /// \brief Recursively visit a name with its location information. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo); - - /// \brief Recursively visit a template name and dispatch to the - /// appropriate method. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseTemplateName(TemplateName Template); - - /// \brief 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. - bool TraverseTemplateArgument(const TemplateArgument &Arg); - - /// \brief 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. - bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc); - - /// \brief Recursively visit a set of template arguments. - /// This can be overridden by a subclass, but it's not expected that - /// will be needed -- this visitor always dispatches to another. - /// - /// \returns false if the visitation was terminated early, true otherwise. - // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead. - bool TraverseTemplateArguments(const TemplateArgument *Args, - unsigned NumArgs); - - /// \brief 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. - bool TraverseConstructorInitializer(CXXCtorInitializer *Init); - - /// \brief Recursively visit a lambda capture. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseLambdaCapture(LambdaExpr::Capture C); - - // ---- Methods on Stmts ---- - - // Declare Traverse*() for all concrete Stmt classes. -#define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ - bool Traverse##CLASS(CLASS *S); -#include "clang/AST/StmtNodes.inc" - // The above header #undefs ABSTRACT_STMT and STMT upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all Stmt classes. - bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } - bool VisitStmt(Stmt *S) { return true; } -#define STMT(CLASS, PARENT) \ - bool WalkUpFrom##CLASS(CLASS *S) { \ - TRY_TO(WalkUpFrom##PARENT(S)); \ - TRY_TO(Visit##CLASS(S)); \ - return true; \ - } \ - bool Visit##CLASS(CLASS *S) { return true; } -#include "clang/AST/StmtNodes.inc" - - // Define Traverse*(), WalkUpFrom*(), and Visit*() for unary - // operator methods. Unary operators are not classes in themselves - // (they're all opcodes in UnaryOperator) but do have visitors. -#define OPERATOR(NAME) \ - bool TraverseUnary##NAME(UnaryOperator *S) { \ - TRY_TO(WalkUpFromUnary##NAME(S)); \ - StmtQueueAction StmtQueue(*this); \ - StmtQueue.queue(S->getSubExpr()); \ - return true; \ - } \ - bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ - TRY_TO(WalkUpFromUnaryOperator(S)); \ - TRY_TO(VisitUnary##NAME(S)); \ - return true; \ - } \ - bool VisitUnary##NAME(UnaryOperator *S) { return true; } - - UNARYOP_LIST() -#undef OPERATOR - - // Define Traverse*(), WalkUpFrom*(), and Visit*() for binary - // operator methods. Binary operators are not classes in themselves - // (they're all opcodes in BinaryOperator) but do have visitors. -#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ - bool TraverseBin##NAME(BINOP_TYPE *S) { \ - TRY_TO(WalkUpFromBin##NAME(S)); \ - StmtQueueAction StmtQueue(*this); \ - StmtQueue.queue(S->getLHS()); \ - StmtQueue.queue(S->getRHS()); \ - return true; \ - } \ - bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ - TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \ - TRY_TO(VisitBin##NAME(S)); \ - return true; \ - } \ - bool VisitBin##NAME(BINOP_TYPE *S) { return true; } - -#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator) - BINOP_LIST() -#undef OPERATOR - - // Define Traverse*(), WalkUpFrom*(), and Visit*() for compound - // assignment methods. Compound assignment operators are not - // classes in themselves (they're all opcodes in - // CompoundAssignOperator) but do have visitors. -#define OPERATOR(NAME) \ - GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator) - - CAO_LIST() -#undef OPERATOR -#undef GENERAL_BINOP_FALLBACK - - // ---- Methods on Types ---- - // FIXME: revamp to take TypeLoc's rather than Types. - - // Declare Traverse*() for all concrete Type classes. -#define ABSTRACT_TYPE(CLASS, BASE) -#define TYPE(CLASS, BASE) \ - bool Traverse##CLASS##Type(CLASS##Type *T); -#include "clang/AST/TypeNodes.def" - // The above header #undefs ABSTRACT_TYPE and TYPE upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all Type classes. - bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); } - bool VisitType(Type *T) { return true; } -#define TYPE(CLASS, BASE) \ - bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ - TRY_TO(WalkUpFrom##BASE(T)); \ - TRY_TO(Visit##CLASS##Type(T)); \ - return true; \ - } \ - bool Visit##CLASS##Type(CLASS##Type *T) { return true; } -#include "clang/AST/TypeNodes.def" - - // ---- Methods on TypeLocs ---- - // FIXME: this currently just calls the matching Type methods - - // Declare Traverse*() for all concrete Type classes. -#define ABSTRACT_TYPELOC(CLASS, BASE) -#define TYPELOC(CLASS, BASE) \ - bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); -#include "clang/AST/TypeLocNodes.def" - // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes. - bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); } - bool VisitTypeLoc(TypeLoc TL) { return true; } - - // QualifiedTypeLoc and UnqualTypeLoc are not declared in - // TypeNodes.def and thus need to be handled specially. - bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) { - return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); - } - bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; } - bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) { - return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); - } - bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; } - - // Note that BASE includes trailing 'Type' which CLASS doesn't. -#define TYPE(CLASS, BASE) \ - bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ - TRY_TO(WalkUpFrom##BASE##Loc(TL)); \ - TRY_TO(Visit##CLASS##TypeLoc(TL)); \ - return true; \ - } \ - bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } -#include "clang/AST/TypeNodes.def" - - // ---- Methods on Decls ---- - - // Declare Traverse*() for all concrete Decl classes. -#define ABSTRACT_DECL(DECL) -#define DECL(CLASS, BASE) \ - bool Traverse##CLASS##Decl(CLASS##Decl *D); -#include "clang/AST/DeclNodes.inc" - // The above header #undefs ABSTRACT_DECL and DECL upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all Decl classes. - bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); } - bool VisitDecl(Decl *D) { return true; } -#define DECL(CLASS, BASE) \ - bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ - TRY_TO(WalkUpFrom##BASE(D)); \ - TRY_TO(Visit##CLASS##Decl(D)); \ - return true; \ - } \ - bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } -#include "clang/AST/DeclNodes.inc" - -private: - // These are helper methods used by more than one Traverse* method. - bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); - bool TraverseClassInstantiations(ClassTemplateDecl *D); - bool TraverseVariableInstantiations(VarTemplateDecl *D); - bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ; - bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, - unsigned Count); - bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); - bool TraverseRecordHelper(RecordDecl *D); - bool TraverseCXXRecordHelper(CXXRecordDecl *D); - bool TraverseDeclaratorHelper(DeclaratorDecl *D); - bool TraverseDeclContextHelper(DeclContext *DC); - bool TraverseFunctionHelper(FunctionDecl *D); - bool TraverseVarHelper(VarDecl *D); - bool TraverseOMPClause(OMPClause *C); -#define OPENMP_CLAUSE(Name, Class) \ - bool Visit##Class(Class *C); -#include "clang/Basic/OpenMPKinds.def" - /// \brief Process clauses with list of variables. - template - void VisitOMPClauseList(T *Node); - - typedef SmallVector StmtsTy; - typedef SmallVector QueuesTy; - - QueuesTy Queues; - - class NewQueueRAII { - RecursiveASTVisitor &RAV; - public: - NewQueueRAII(StmtsTy &queue, RecursiveASTVisitor &RAV) : RAV(RAV) { - RAV.Queues.push_back(&queue); - } - ~NewQueueRAII() { - RAV.Queues.pop_back(); - } - }; - - StmtsTy &getCurrentQueue() { - assert(!Queues.empty() && "base TraverseStmt was never called?"); - return *Queues.back(); - } - -public: - class StmtQueueAction { - StmtsTy &CurrQueue; - public: - explicit StmtQueueAction(RecursiveASTVisitor &RAV) - : CurrQueue(RAV.getCurrentQueue()) { } - - void queue(Stmt *S) { - CurrQueue.push_back(S); - } - }; -}; - -#define DISPATCH(NAME, CLASS, VAR) \ - return getDerived().Traverse##NAME(static_cast(VAR)) - -template -bool RecursiveASTVisitor::TraverseStmt(Stmt *S) { - if (!S) - return true; - - StmtsTy Queue, StmtsToEnqueu; - Queue.push_back(S); - NewQueueRAII NQ(StmtsToEnqueu, *this); - - while (!Queue.empty()) { - S = Queue.pop_back_val(); - if (!S) - continue; - - StmtsToEnqueu.clear(); - -#define DISPATCH_STMT(NAME, CLASS, VAR) \ - TRY_TO(Traverse##NAME(static_cast(VAR))); break - - // If we have a binary expr, dispatch to the subcode of the binop. A smart - // optimizer (e.g. LLVM) will fold this comparison into the switch stmt - // below. - if (BinaryOperator *BinOp = dyn_cast(S)) { - switch (BinOp->getOpcode()) { -#define OPERATOR(NAME) \ - case BO_##NAME: DISPATCH_STMT(Bin##NAME, BinaryOperator, S); - - BINOP_LIST() -#undef OPERATOR -#undef BINOP_LIST - -#define OPERATOR(NAME) \ - case BO_##NAME##Assign: \ - DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S); - - CAO_LIST() -#undef OPERATOR -#undef CAO_LIST - } - } else if (UnaryOperator *UnOp = dyn_cast(S)) { - switch (UnOp->getOpcode()) { -#define OPERATOR(NAME) \ - case UO_##NAME: DISPATCH_STMT(Unary##NAME, UnaryOperator, S); - - UNARYOP_LIST() -#undef OPERATOR -#undef UNARYOP_LIST - } - } else { - - // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. - switch (S->getStmtClass()) { - case Stmt::NoStmtClass: break; -#define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ - case Stmt::CLASS##Class: DISPATCH_STMT(CLASS, CLASS, S); -#include "clang/AST/StmtNodes.inc" - } - } - - for (SmallVectorImpl::reverse_iterator - RI = StmtsToEnqueu.rbegin(), - RE = StmtsToEnqueu.rend(); RI != RE; ++RI) - Queue.push_back(*RI); - } - - return true; -} - -template -bool RecursiveASTVisitor::TraverseType(QualType T) { - if (T.isNull()) - return true; - - switch (T->getTypeClass()) { -#define ABSTRACT_TYPE(CLASS, BASE) -#define TYPE(CLASS, BASE) \ - case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, \ - const_cast(T.getTypePtr())); -#include "clang/AST/TypeNodes.def" - } - - return true; -} - -template -bool RecursiveASTVisitor::TraverseTypeLoc(TypeLoc TL) { - if (TL.isNull()) - return true; - - switch (TL.getTypeLocClass()) { -#define ABSTRACT_TYPELOC(CLASS, BASE) -#define TYPELOC(CLASS, BASE) \ - case TypeLoc::CLASS: \ - return getDerived().Traverse##CLASS##TypeLoc(TL.castAs()); -#include "clang/AST/TypeLocNodes.def" - } - - return true; -} - - -template -bool RecursiveASTVisitor::TraverseDecl(Decl *D) { - if (!D) - return true; - - // As a syntax visitor, we want to ignore declarations for - // implicitly-defined declarations (ones not typed explicitly by the - // user). - if (D->isImplicit()) - return true; - - switch (D->getKind()) { -#define ABSTRACT_DECL(DECL) -#define DECL(CLASS, BASE) \ - case Decl::CLASS: DISPATCH(CLASS##Decl, CLASS##Decl, D); -#include "clang/AST/DeclNodes.inc" - } - - return true; -} - -#undef DISPATCH - -template -bool RecursiveASTVisitor::TraverseNestedNameSpecifier( - NestedNameSpecifier *NNS) { - if (!NNS) - return true; - - if (NNS->getPrefix()) - TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix())); - - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - case NestedNameSpecifier::Global: - return true; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - TRY_TO(TraverseType(QualType(NNS->getAsType(), 0))); - } - - return true; -} - -template -bool RecursiveASTVisitor::TraverseNestedNameSpecifierLoc( - NestedNameSpecifierLoc NNS) { - if (!NNS) - return true; - - if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) - TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); - - switch (NNS.getNestedNameSpecifier()->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - case NestedNameSpecifier::Global: - return true; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); - break; - } - - return true; -} - -template -bool RecursiveASTVisitor::TraverseDeclarationNameInfo( - DeclarationNameInfo NameInfo) { - switch (NameInfo.getName().getNameKind()) { - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) - TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc())); - - break; - - case DeclarationName::Identifier: - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - case DeclarationName::CXXOperatorName: - case DeclarationName::CXXLiteralOperatorName: - case DeclarationName::CXXUsingDirective: - break; - } - - return true; -} - -template -bool RecursiveASTVisitor::TraverseTemplateName(TemplateName Template) { - if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) - TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier())); - else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) - TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier())); - - return true; -} - -template -bool RecursiveASTVisitor::TraverseTemplateArgument( - const TemplateArgument &Arg) { - switch (Arg.getKind()) { - case TemplateArgument::Null: - case TemplateArgument::Declaration: - case TemplateArgument::Integral: - case TemplateArgument::NullPtr: - return true; - - case TemplateArgument::Type: - return getDerived().TraverseType(Arg.getAsType()); - - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - return getDerived().TraverseTemplateName( - Arg.getAsTemplateOrTemplatePattern()); - - case TemplateArgument::Expression: - return getDerived().TraverseStmt(Arg.getAsExpr()); - - case TemplateArgument::Pack: - return getDerived().TraverseTemplateArguments(Arg.pack_begin(), - Arg.pack_size()); - } - - return true; -} - -// FIXME: no template name location? -// FIXME: no source locations for a template argument pack? -template -bool RecursiveASTVisitor::TraverseTemplateArgumentLoc( - const TemplateArgumentLoc &ArgLoc) { - const TemplateArgument &Arg = ArgLoc.getArgument(); - - switch (Arg.getKind()) { - case TemplateArgument::Null: - case TemplateArgument::Declaration: - case TemplateArgument::Integral: - case TemplateArgument::NullPtr: - return true; - - case TemplateArgument::Type: { - // FIXME: how can TSI ever be NULL? - if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) - return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); - else - return getDerived().TraverseType(Arg.getAsType()); - } - - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - if (ArgLoc.getTemplateQualifierLoc()) - TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( - ArgLoc.getTemplateQualifierLoc())); - return getDerived().TraverseTemplateName( - Arg.getAsTemplateOrTemplatePattern()); - - case TemplateArgument::Expression: - return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); - - case TemplateArgument::Pack: - return getDerived().TraverseTemplateArguments(Arg.pack_begin(), - Arg.pack_size()); - } - - return true; -} - -template -bool RecursiveASTVisitor::TraverseTemplateArguments( - const TemplateArgument *Args, - unsigned NumArgs) { - for (unsigned I = 0; I != NumArgs; ++I) { - TRY_TO(TraverseTemplateArgument(Args[I])); - } - - return true; -} - -template -bool RecursiveASTVisitor::TraverseConstructorInitializer( - CXXCtorInitializer *Init) { - if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) - TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); - - if (Init->isWritten()) - TRY_TO(TraverseStmt(Init->getInit())); - return true; -} - -template -bool RecursiveASTVisitor::TraverseLambdaCapture(LambdaExpr::Capture C){ - return true; -} - -// ----------------- Type traversal ----------------- - -// This macro makes available a variable T, the passed-in type. -#define DEF_TRAVERSE_TYPE(TYPE, CODE) \ - template \ - bool RecursiveASTVisitor::Traverse##TYPE (TYPE *T) { \ - TRY_TO(WalkUpFrom##TYPE (T)); \ - { CODE; } \ - return true; \ - } - -DEF_TRAVERSE_TYPE(BuiltinType, { }) - -DEF_TRAVERSE_TYPE(ComplexType, { - TRY_TO(TraverseType(T->getElementType())); - }) - -DEF_TRAVERSE_TYPE(PointerType, { - TRY_TO(TraverseType(T->getPointeeType())); - }) - -DEF_TRAVERSE_TYPE(BlockPointerType, { - TRY_TO(TraverseType(T->getPointeeType())); - }) - -DEF_TRAVERSE_TYPE(LValueReferenceType, { - TRY_TO(TraverseType(T->getPointeeType())); - }) - -DEF_TRAVERSE_TYPE(RValueReferenceType, { - TRY_TO(TraverseType(T->getPointeeType())); - }) - -DEF_TRAVERSE_TYPE(MemberPointerType, { - TRY_TO(TraverseType(QualType(T->getClass(), 0))); - TRY_TO(TraverseType(T->getPointeeType())); - }) - -DEF_TRAVERSE_TYPE(DecayedType, { - TRY_TO(TraverseType(T->getOriginalType())); - }) - -DEF_TRAVERSE_TYPE(AdjustedType, { - TRY_TO(TraverseType(T->getOriginalType())); - }) - -DEF_TRAVERSE_TYPE(ConstantArrayType, { - TRY_TO(TraverseType(T->getElementType())); - }) - -DEF_TRAVERSE_TYPE(IncompleteArrayType, { - TRY_TO(TraverseType(T->getElementType())); - }) - -DEF_TRAVERSE_TYPE(VariableArrayType, { - TRY_TO(TraverseType(T->getElementType())); - TRY_TO(TraverseStmt(T->getSizeExpr())); - }) - -DEF_TRAVERSE_TYPE(DependentSizedArrayType, { - TRY_TO(TraverseType(T->getElementType())); - if (T->getSizeExpr()) - TRY_TO(TraverseStmt(T->getSizeExpr())); - }) - -DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { - if (T->getSizeExpr()) - TRY_TO(TraverseStmt(T->getSizeExpr())); - TRY_TO(TraverseType(T->getElementType())); - }) - -DEF_TRAVERSE_TYPE(VectorType, { - TRY_TO(TraverseType(T->getElementType())); - }) - -DEF_TRAVERSE_TYPE(ExtVectorType, { - TRY_TO(TraverseType(T->getElementType())); - }) - -DEF_TRAVERSE_TYPE(FunctionNoProtoType, { - TRY_TO(TraverseType(T->getResultType())); - }) - -DEF_TRAVERSE_TYPE(FunctionProtoType, { - TRY_TO(TraverseType(T->getResultType())); - - for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), - AEnd = T->arg_type_end(); - A != AEnd; ++A) { - TRY_TO(TraverseType(*A)); - } - - for (FunctionProtoType::exception_iterator E = T->exception_begin(), - EEnd = T->exception_end(); - E != EEnd; ++E) { - TRY_TO(TraverseType(*E)); - } - }) - -DEF_TRAVERSE_TYPE(UnresolvedUsingType, { }) -DEF_TRAVERSE_TYPE(TypedefType, { }) - -DEF_TRAVERSE_TYPE(TypeOfExprType, { - TRY_TO(TraverseStmt(T->getUnderlyingExpr())); - }) - -DEF_TRAVERSE_TYPE(TypeOfType, { - TRY_TO(TraverseType(T->getUnderlyingType())); - }) - -DEF_TRAVERSE_TYPE(DecltypeType, { - TRY_TO(TraverseStmt(T->getUnderlyingExpr())); - }) - -DEF_TRAVERSE_TYPE(UnaryTransformType, { - TRY_TO(TraverseType(T->getBaseType())); - TRY_TO(TraverseType(T->getUnderlyingType())); - }) - -DEF_TRAVERSE_TYPE(AutoType, { - TRY_TO(TraverseType(T->getDeducedType())); - }) - -DEF_TRAVERSE_TYPE(RecordType, { }) -DEF_TRAVERSE_TYPE(EnumType, { }) -DEF_TRAVERSE_TYPE(TemplateTypeParmType, { }) -DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { }) -DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { }) - -DEF_TRAVERSE_TYPE(TemplateSpecializationType, { - TRY_TO(TraverseTemplateName(T->getTemplateName())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); - }) - -DEF_TRAVERSE_TYPE(InjectedClassNameType, { }) - -DEF_TRAVERSE_TYPE(AttributedType, { - TRY_TO(TraverseType(T->getModifiedType())); - }) - -DEF_TRAVERSE_TYPE(ParenType, { - TRY_TO(TraverseType(T->getInnerType())); - }) - -DEF_TRAVERSE_TYPE(ElaboratedType, { - if (T->getQualifier()) { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - } - TRY_TO(TraverseType(T->getNamedType())); - }) - -DEF_TRAVERSE_TYPE(DependentNameType, { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - }) - -DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); - }) - -DEF_TRAVERSE_TYPE(PackExpansionType, { - TRY_TO(TraverseType(T->getPattern())); - }) - -DEF_TRAVERSE_TYPE(ObjCInterfaceType, { }) - -DEF_TRAVERSE_TYPE(ObjCObjectType, { - // We have to watch out here because an ObjCInterfaceType's base - // type is itself. - if (T->getBaseType().getTypePtr() != T) - TRY_TO(TraverseType(T->getBaseType())); - }) - -DEF_TRAVERSE_TYPE(ObjCObjectPointerType, { - TRY_TO(TraverseType(T->getPointeeType())); - }) - -DEF_TRAVERSE_TYPE(AtomicType, { - TRY_TO(TraverseType(T->getValueType())); - }) - -#undef DEF_TRAVERSE_TYPE - -// ----------------- TypeLoc traversal ----------------- - -// This macro makes available a variable TL, the passed-in TypeLoc. -// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc, -// in addition to WalkUpFrom* for the TypeLoc itself, such that existing -// clients that override the WalkUpFrom*Type() and/or Visit*Type() methods -// continue to work. -#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ - template \ - bool RecursiveASTVisitor::Traverse##TYPE##Loc(TYPE##Loc TL) { \ - if (getDerived().shouldWalkTypesOfTypeLocs()) \ - TRY_TO(WalkUpFrom##TYPE(const_cast(TL.getTypePtr()))); \ - TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ - { CODE; } \ - return true; \ - } - -template -bool RecursiveASTVisitor::TraverseQualifiedTypeLoc( - QualifiedTypeLoc TL) { - // Move this over to the 'main' typeloc tree. Note that this is a - // move -- we pretend that we were really looking at the unqualified - // typeloc all along -- rather than a recursion, so we don't follow - // the normal CRTP plan of going through - // getDerived().TraverseTypeLoc. If we did, we'd be traversing - // twice for the same type (once as a QualifiedTypeLoc version of - // the type, once as an UnqualifiedTypeLoc version of the type), - // which in effect means we'd call VisitTypeLoc twice with the - // 'same' type. This solves that problem, at the cost of never - // seeing the qualified version of the type (unless the client - // subclasses TraverseQualifiedTypeLoc themselves). It's not a - // perfect solution. A perfect solution probably requires making - // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a - // wrapper around Type* -- rather than being its own class in the - // type hierarchy. - return TraverseTypeLoc(TL.getUnqualifiedLoc()); -} - -DEF_TRAVERSE_TYPELOC(BuiltinType, { }) - -// FIXME: ComplexTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(ComplexType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); - }) - -DEF_TRAVERSE_TYPELOC(PointerType, { - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) - -DEF_TRAVERSE_TYPELOC(BlockPointerType, { - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) - -DEF_TRAVERSE_TYPELOC(LValueReferenceType, { - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) - -DEF_TRAVERSE_TYPELOC(RValueReferenceType, { - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) - -// FIXME: location of base class? -// We traverse this in the type case as well, but how is it not reached through -// the pointee type? -DEF_TRAVERSE_TYPELOC(MemberPointerType, { - TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) - -DEF_TRAVERSE_TYPELOC(DecayedType, { - TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); - }) - -DEF_TRAVERSE_TYPELOC(AdjustedType, { - TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); - }) - -template -bool RecursiveASTVisitor::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { - // This isn't available for ArrayType, but is for the ArrayTypeLoc. - TRY_TO(TraverseStmt(TL.getSizeExpr())); - return true; -} - -DEF_TRAVERSE_TYPELOC(ConstantArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); - }) - -DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); - }) - -DEF_TRAVERSE_TYPELOC(VariableArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); - }) - -DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); - }) - -// FIXME: order? why not size expr first? -// FIXME: base VectorTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { - if (TL.getTypePtr()->getSizeExpr()) - TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); - }) - -// FIXME: VectorTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(VectorType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); - }) - -// FIXME: size and attributes -// FIXME: base VectorTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(ExtVectorType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); - }) - -DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, { - TRY_TO(TraverseTypeLoc(TL.getResultLoc())); - }) - -// FIXME: location of exception specifications (attributes?) -DEF_TRAVERSE_TYPELOC(FunctionProtoType, { - TRY_TO(TraverseTypeLoc(TL.getResultLoc())); - - const FunctionProtoType *T = TL.getTypePtr(); - - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - if (TL.getArg(I)) { - TRY_TO(TraverseDecl(TL.getArg(I))); - } else if (I < T->getNumArgs()) { - TRY_TO(TraverseType(T->getArgType(I))); - } - } - - for (FunctionProtoType::exception_iterator E = T->exception_begin(), - EEnd = T->exception_end(); - E != EEnd; ++E) { - TRY_TO(TraverseType(*E)); - } - }) - -DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, { }) -DEF_TRAVERSE_TYPELOC(TypedefType, { }) - -DEF_TRAVERSE_TYPELOC(TypeOfExprType, { - TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); - }) - -DEF_TRAVERSE_TYPELOC(TypeOfType, { - TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); - }) - -// FIXME: location of underlying expr -DEF_TRAVERSE_TYPELOC(DecltypeType, { - TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); - }) - -DEF_TRAVERSE_TYPELOC(UnaryTransformType, { - TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); - }) - -DEF_TRAVERSE_TYPELOC(AutoType, { - TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); - }) - -DEF_TRAVERSE_TYPELOC(RecordType, { }) -DEF_TRAVERSE_TYPELOC(EnumType, { }) -DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, { }) -DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { }) -DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { }) - -// FIXME: use the loc for the template name? -DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { - TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); - } - }) - -DEF_TRAVERSE_TYPELOC(InjectedClassNameType, { }) - -DEF_TRAVERSE_TYPELOC(ParenType, { - TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); - }) - -DEF_TRAVERSE_TYPELOC(AttributedType, { - TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); - }) - -DEF_TRAVERSE_TYPELOC(ElaboratedType, { - if (TL.getQualifierLoc()) { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); - } - TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); - }) - -DEF_TRAVERSE_TYPELOC(DependentNameType, { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); - }) - -DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { - if (TL.getQualifierLoc()) { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); - } - - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); - } - }) - -DEF_TRAVERSE_TYPELOC(PackExpansionType, { - TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); - }) - -DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, { }) - -DEF_TRAVERSE_TYPELOC(ObjCObjectType, { - // We have to watch out here because an ObjCInterfaceType's base - // type is itself. - if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr()) - TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); - }) - -DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, { - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) - -DEF_TRAVERSE_TYPELOC(AtomicType, { - TRY_TO(TraverseTypeLoc(TL.getValueLoc())); - }) - -#undef DEF_TRAVERSE_TYPELOC - -// ----------------- Decl traversal ----------------- -// -// For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing -// the children that come from the DeclContext associated with it. -// Therefore each Traverse* only needs to worry about children other -// than those. - -template -bool RecursiveASTVisitor::TraverseDeclContextHelper(DeclContext *DC) { - if (!DC) - return true; - - for (DeclContext::decl_iterator Child = DC->decls_begin(), - ChildEnd = DC->decls_end(); - Child != ChildEnd; ++Child) { - // BlockDecls and CapturedDecls are traversed through BlockExprs and - // CapturedStmts respectively. - if (!isa(*Child) && !isa(*Child)) - TRY_TO(TraverseDecl(*Child)); - } - - return true; -} - -// This macro makes available a variable D, the passed-in decl. -#define DEF_TRAVERSE_DECL(DECL, CODE) \ -template \ -bool RecursiveASTVisitor::Traverse##DECL (DECL *D) { \ - TRY_TO(WalkUpFrom##DECL (D)); \ - { CODE; } \ - TRY_TO(TraverseDeclContextHelper(dyn_cast(D))); \ - return true; \ -} - -DEF_TRAVERSE_DECL(AccessSpecDecl, { }) - -DEF_TRAVERSE_DECL(BlockDecl, { - if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) - TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); - TRY_TO(TraverseStmt(D->getBody())); - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; - }) - -DEF_TRAVERSE_DECL(CapturedDecl, { - TRY_TO(TraverseStmt(D->getBody())); - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; - }) - -DEF_TRAVERSE_DECL(EmptyDecl, { }) - -DEF_TRAVERSE_DECL(FileScopeAsmDecl, { - TRY_TO(TraverseStmt(D->getAsmString())); - }) - -DEF_TRAVERSE_DECL(ImportDecl, { }) - -DEF_TRAVERSE_DECL(FriendDecl, { - // Friend is either decl or a type. - if (D->getFriendType()) - TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); - else - TRY_TO(TraverseDecl(D->getFriendDecl())); - }) - -DEF_TRAVERSE_DECL(FriendTemplateDecl, { - if (D->getFriendType()) - TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); - else - TRY_TO(TraverseDecl(D->getFriendDecl())); - for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) { - TemplateParameterList *TPL = D->getTemplateParameterList(I); - for (TemplateParameterList::iterator ITPL = TPL->begin(), - ETPL = TPL->end(); - ITPL != ETPL; ++ITPL) { - TRY_TO(TraverseDecl(*ITPL)); - } - } - }) - -DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, { - TRY_TO(TraverseDecl(D->getSpecialization())); - }) - -DEF_TRAVERSE_DECL(LinkageSpecDecl, { }) - -DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, { - // FIXME: implement this - }) - -DEF_TRAVERSE_DECL(StaticAssertDecl, { - TRY_TO(TraverseStmt(D->getAssertExpr())); - TRY_TO(TraverseStmt(D->getMessage())); - }) - -DEF_TRAVERSE_DECL(TranslationUnitDecl, { - // Code in an unnamed namespace shows up automatically in - // decls_begin()/decls_end(). Thus we don't need to recurse on - // D->getAnonymousNamespace(). - }) - -DEF_TRAVERSE_DECL(NamespaceAliasDecl, { - // We shouldn't traverse an aliased namespace, since it will be - // defined (and, therefore, traversed) somewhere else. - // - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; - }) - -DEF_TRAVERSE_DECL(LabelDecl, { - // There is no code in a LabelDecl. -}) - - -DEF_TRAVERSE_DECL(NamespaceDecl, { - // Code in an unnamed namespace shows up automatically in - // decls_begin()/decls_end(). Thus we don't need to recurse on - // D->getAnonymousNamespace(). - }) - -DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, { - // FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCCategoryDecl, { - // FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, { - // FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCImplementationDecl, { - // FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCInterfaceDecl, { - // FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCProtocolDecl, { - // FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCMethodDecl, { - if (D->getResultTypeSourceInfo()) { - TRY_TO(TraverseTypeLoc(D->getResultTypeSourceInfo()->getTypeLoc())); - } - for (ObjCMethodDecl::param_iterator - I = D->param_begin(), E = D->param_end(); I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - if (D->isThisDeclarationADefinition()) { - TRY_TO(TraverseStmt(D->getBody())); - } - return true; - }) - -DEF_TRAVERSE_DECL(ObjCPropertyDecl, { - // FIXME: implement - }) - -DEF_TRAVERSE_DECL(UsingDecl, { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); - }) - -DEF_TRAVERSE_DECL(UsingDirectiveDecl, { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - }) - -DEF_TRAVERSE_DECL(UsingShadowDecl, { }) - -DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { - for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(), - E = D->varlist_end(); - I != E; ++I) { - TRY_TO(TraverseStmt(*I)); - } - }) - -// A helper method for TemplateDecl's children. -template -bool RecursiveASTVisitor::TraverseTemplateParameterListHelper( - TemplateParameterList *TPL) { - if (TPL) { - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - } - return true; -} - -// A helper method for traversing the implicit instantiations of a -// class template. -template -bool RecursiveASTVisitor::TraverseClassInstantiations( - ClassTemplateDecl *D) { - ClassTemplateDecl::spec_iterator end = D->spec_end(); - for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { - ClassTemplateSpecializationDecl* SD = *it; - - switch (SD->getSpecializationKind()) { - // Visit the implicit instantiations with the requested pattern. - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - TRY_TO(TraverseDecl(SD)); - break; - - // We don't need to do anything on an explicit instantiation - // or explicit specialization because there will be an explicit - // node for it elsewhere. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - case TSK_ExplicitSpecialization: - break; - } - } - - return true; -} - -DEF_TRAVERSE_DECL(ClassTemplateDecl, { - CXXRecordDecl* TempDecl = D->getTemplatedDecl(); - TRY_TO(TraverseDecl(TempDecl)); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - - // By default, we do not traverse the instantiations of - // class templates since they do not appear in the user code. The - // following code optionally traverses them. - // - // We only traverse the class instantiations when we see the canonical - // declaration of the template, to ensure we only visit them once. - if (getDerived().shouldVisitTemplateInstantiations() && - D == D->getCanonicalDecl()) - TRY_TO(TraverseClassInstantiations(D)); - - // Note that getInstantiatedFromMemberTemplate() is just a link - // from a template instantiation back to the template from which - // it was instantiated, and thus should not be traversed. - }) - -// A helper method for traversing the implicit instantiations of a -// class template. -template -bool RecursiveASTVisitor::TraverseVariableInstantiations( - VarTemplateDecl *D) { - VarTemplateDecl::spec_iterator end = D->spec_end(); - for (VarTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { - VarTemplateSpecializationDecl *SD = *it; - - switch (SD->getSpecializationKind()) { - // Visit the implicit instantiations with the requested pattern. - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - TRY_TO(TraverseDecl(SD)); - break; - - // We don't need to do anything on an explicit instantiation - // or explicit specialization because there will be an explicit - // node for it elsewhere. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - case TSK_ExplicitSpecialization: - break; - } - } - - return true; -} - -DEF_TRAVERSE_DECL( - VarTemplateDecl, - { - VarDecl *TempDecl = D->getTemplatedDecl(); - TRY_TO(TraverseDecl(TempDecl)); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - - // By default, we do not traverse the instantiations of - // variable templates since they do not appear in the user code. The - // following code optionally traverses them. - // - // We only traverse the variable instantiations when we see the canonical - // declaration of the template, to ensure we only visit them once. - if (getDerived().shouldVisitTemplateInstantiations() && - D == D->getCanonicalDecl()) - TRY_TO(TraverseVariableInstantiations(D)); - - // Note that getInstantiatedFromMemberTemplate() is just a link - // from a template instantiation back to the template from which - // it was instantiated, and thus should not be traversed. -}) - -// A helper method for traversing the instantiations of a -// function while skipping its specializations. -template -bool RecursiveASTVisitor::TraverseFunctionInstantiations( - FunctionTemplateDecl *D) { - FunctionTemplateDecl::spec_iterator end = D->spec_end(); - for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; - ++it) { - FunctionDecl* FD = *it; - switch (FD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - // We don't know what kind of FunctionDecl this is. - TRY_TO(TraverseDecl(FD)); - break; - - // No need to visit explicit instantiations, we'll find the node - // eventually. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - break; - - case TSK_ExplicitSpecialization: - break; - } - } - - return true; -} - -DEF_TRAVERSE_DECL(FunctionTemplateDecl, { - TRY_TO(TraverseDecl(D->getTemplatedDecl())); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - - // By default, we do not traverse the instantiations of - // function templates since they do not appear in the user code. The - // following code optionally traverses them. - // - // We only traverse the function instantiations when we see the canonical - // declaration of the template, to ensure we only visit them once. - if (getDerived().shouldVisitTemplateInstantiations() && - D == D->getCanonicalDecl()) - TRY_TO(TraverseFunctionInstantiations(D)); - }) - -DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { - // D is the "T" in something like - // template