diff options
Diffstat (limited to 'include/clang/AST/RecursiveASTVisitor.h')
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 330 |
1 files changed, 220 insertions, 110 deletions
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index b5a4b5e..d09550f 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -27,6 +27,7 @@ #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" @@ -108,7 +109,7 @@ namespace clang { /// 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 +/// top-down order (e.g. for a node of type NamespaceDecl, the order will /// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()). /// /// This scheme guarantees that all Visit*() calls for the same AST @@ -243,8 +244,16 @@ public: /// \brief Recursively visit a lambda capture. /// /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseLambdaCapture(LambdaExpr::Capture C); - + bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaExpr::Capture *C); + + /// \brief Recursively visit the body of a lambda expression. + /// + /// This provides a hook for visitors that need more context when visiting + /// \c LE->getBody(). + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseLambdaBody(LambdaExpr *LE); + // ---- Methods on Stmts ---- // Declare Traverse*() for all concrete Stmt classes. @@ -342,7 +351,7 @@ public: // ---- Methods on TypeLocs ---- // FIXME: this currently just calls the matching Type methods - // Declare Traverse*() for all concrete Type classes. + // Declare Traverse*() for all concrete TypeLoc classes. #define ABSTRACT_TYPELOC(CLASS, BASE) #define TYPELOC(CLASS, BASE) \ bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); @@ -398,8 +407,12 @@ public: private: // These are helper methods used by more than one Traverse* method. bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); - bool TraverseClassInstantiations(ClassTemplateDecl *D); - bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ; +#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ + bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D); + DEF_TRAVERSE_TMPL_INST(Class) + DEF_TRAVERSE_TMPL_INST(Var) + DEF_TRAVERSE_TMPL_INST(Function) +#undef DEF_TRAVERSE_TMPL_INST bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, unsigned Count); bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); @@ -409,6 +422,13 @@ private: 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 <typename T> + void VisitOMPClauseList(T *Node); struct EnqueueJob { Stmt *S; @@ -802,10 +822,20 @@ bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( } template<typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr::Capture C){ +bool RecursiveASTVisitor<Derived>::TraverseLambdaCapture( + LambdaExpr *LE, const LambdaExpr::Capture *C) { + if (C->isInitCapture()) + TRY_TO(TraverseDecl(C->getCapturedVar())); + return true; +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) { + TRY_TO(TraverseStmt(LE->getBody())); return true; } + // ----------------- Type traversal ----------------- // This macro makes available a variable T, the passed-in type. @@ -844,6 +874,10 @@ DEF_TRAVERSE_TYPE(MemberPointerType, { TRY_TO(TraverseType(T->getPointeeType())); }) +DEF_TRAVERSE_TYPE(DecayedType, { + TRY_TO(TraverseType(T->getOriginalType())); + }) + DEF_TRAVERSE_TYPE(ConstantArrayType, { TRY_TO(TraverseType(T->getElementType())); }) @@ -1050,6 +1084,10 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) +DEF_TRAVERSE_TYPELOC(DecayedType, { + TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); + }) + template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { // This isn't available for ArrayType, but is for the ArrayTypeLoc. @@ -1420,59 +1458,44 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( return true; } -// A helper method for traversing the implicit instantiations of a -// class template. -template<typename Derived> -bool RecursiveASTVisitor<Derived>::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; +#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ +/* A helper method for traversing the implicit instantiations of a + class or variable template. */ \ +template<typename Derived> \ +bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( \ + TMPLDECLKIND##TemplateDecl *D) { \ + TMPLDECLKIND##TemplateDecl::spec_iterator end = D->spec_end(); \ + for (TMPLDECLKIND##TemplateDecl::spec_iterator it = D->spec_begin(); \ + it != end; ++it) { \ + TMPLDECLKIND##TemplateSpecializationDecl* 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. - }) + +DEF_TRAVERSE_TMPL_INST(Class) +DEF_TRAVERSE_TMPL_INST(Var) // A helper method for traversing the instantiations of a // function while skipping its specializations. template<typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( +bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( FunctionTemplateDecl *D) { FunctionTemplateDecl::spec_iterator end = D->spec_end(); for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; @@ -1500,20 +1523,31 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( 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)); - }) +// This macro unifies the traversal of class, variable and function +// template declarations. +#define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \ +DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \ + TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ + 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(TraverseTemplateInstantiations(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. */ \ + }) + +DEF_TRAVERSE_TMPL_DECL(Class) +DEF_TRAVERSE_TMPL_DECL(Var) +DEF_TRAVERSE_TMPL_DECL(Function) DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { // D is the "T" in something like @@ -1607,26 +1641,30 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) -DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, { - // For implicit instantiations ("set<int> x;"), we don't want to - // recurse at all, since the instatiated class isn't written in - // the source code anywhere. (Note the instatiated *type* -- - // set<int> -- is written, and will still get a callback of - // TemplateSpecializationType). For explicit instantiations - // ("template set<int>;"), we do need a callback, since this - // is the only callback that's made for this instantiation. - // We use getTypeAsWritten() to distinguish. - if (TypeSourceInfo *TSI = D->getTypeAsWritten()) - TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); - - if (!getDerived().shouldVisitTemplateInstantiations() && - D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) - // Returning from here skips traversing the - // declaration context of the ClassTemplateSpecializationDecl - // (embedded in the DEF_TRAVERSE_DECL() macro) - // which contains the instantiated members of the class. - return true; - }) +#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \ +DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ + /* For implicit instantiations ("set<int> x;"), we don't want to + recurse at all, since the instatiated template isn't written in + the source code anywhere. (Note the instatiated *type* -- + set<int> -- is written, and will still get a callback of + TemplateSpecializationType). For explicit instantiations + ("template set<int>;"), we do need a callback, since this + is the only callback that's made for this instantiation. + We use getTypeAsWritten() to distinguish. */ \ + if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ + \ + if (!getDerived().shouldVisitTemplateInstantiations() && \ + D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \ + /* Returning from here skips traversing the + declaration context of the *TemplateSpecializationDecl + (embedded in the DEF_TRAVERSE_DECL() macro) + which contains the instantiated members of the template. */ \ + return true; \ + }) + +DEF_TRAVERSE_TMPL_SPEC_DECL(Class) +DEF_TRAVERSE_TMPL_SPEC_DECL(Var) template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( @@ -1637,25 +1675,30 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( return true; } -DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, { - // The partial specialization. - if (TemplateParameterList *TPL = D->getTemplateParameters()) { - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - } - // The args that remains unspecialized. - TRY_TO(TraverseTemplateArgumentLocsHelper( - D->getTemplateArgsAsWritten(), D->getNumTemplateArgsAsWritten())); - - // Don't need the ClassTemplatePartialSpecializationHelper, even - // though that's our parent class -- we already visit all the - // template args here. - TRY_TO(TraverseCXXRecordHelper(D)); - - // Instantiations will have been visited with the primary template. - }) +#define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ +DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ + /* The partial specialization. */ \ + if (TemplateParameterList *TPL = D->getTemplateParameters()) { \ + for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \ + I != E; ++I) { \ + TRY_TO(TraverseDecl(*I)); \ + } \ + } \ + /* The args that remains unspecialized. */ \ + TRY_TO(TraverseTemplateArgumentLocsHelper( \ + D->getTemplateArgsAsWritten()->getTemplateArgs(), \ + D->getTemplateArgsAsWritten()->NumTemplateArgs)); \ + \ + /* Don't need the *TemplatePartialSpecializationHelper, even + though that's our parent class -- we already visit all the + template args here. */ \ + TRY_TO(Traverse##DECLKIND##Helper(D)); \ + \ + /* Instantiations will have been visited with the primary template. */ \ + }) + +DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord) +DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var) DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); @@ -1736,6 +1779,14 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { // including exception specifications. if (TypeSourceInfo *TSI = D->getTypeSourceInfo()) { TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); + } else if (getDerived().shouldVisitImplicitCode()) { + // Visit parameter variable declarations of the implicit function + // if the traverser is visiting implicit code. Parameter variable + // declarations do not have valid TypeSourceInfo, so to visit them + // we need to traverse the declarations explicitly. + for (FunctionDecl::param_const_iterator I = D->param_begin(), + E = D->param_end(); I != E; ++I) + TRY_TO(TraverseDecl(*I)); } if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { @@ -2117,10 +2168,12 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { // Walk only the visible parts of lambda expressions. template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { + TRY_TO(WalkUpFromLambdaExpr(S)); + for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), CEnd = S->explicit_capture_end(); C != CEnd; ++C) { - TRY_TO(TraverseLambdaCapture(*C)); + TRY_TO(TraverseLambdaCapture(S, C)); } if (S->hasExplicitParameters() || S->hasExplicitResultType()) { @@ -2140,7 +2193,7 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { } } - TRY_TO(TraverseStmt(S->getBody())); + TRY_TO(TraverseLambdaBody(S)); return true; } @@ -2174,6 +2227,7 @@ DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { }) DEF_TRAVERSE_STMT(CXXDeleteExpr, { }) DEF_TRAVERSE_STMT(ExprWithCleanups, { }) DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) +DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, { }) DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) @@ -2211,6 +2265,7 @@ DEF_TRAVERSE_STMT(ParenExpr, { }) DEF_TRAVERSE_STMT(ParenListExpr, { }) DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) +DEF_TRAVERSE_STMT(ConvertVectorExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); @@ -2269,6 +2324,61 @@ DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { }) // Traverse OpenCL: AsType, Convert. DEF_TRAVERSE_STMT(AsTypeExpr, { }) +// OpenMP directives. +DEF_TRAVERSE_STMT(OMPParallelDirective, { + ArrayRef<OMPClause *> Clauses = S->clauses(); + for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end(); + I != E; ++I) + if (!TraverseOMPClause(*I)) return false; +}) + +// OpenMP clauses. +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { + if (!C) return true; + switch (C->getClauseKind()) { +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_##Name: \ + return getDerived().Visit##Class(static_cast<Class*>(C)); +#include "clang/Basic/OpenMPKinds.def" + default: break; + } + return true; +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) { + return true; +} + +template<typename Derived> +template<typename T> +void RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { + for (typename T::varlist_iterator I = Node->varlist_begin(), + E = Node->varlist_end(); + I != E; ++I) + TraverseStmt(*I); +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { + VisitOMPClauseList(C); + return true; +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( + OMPFirstprivateClause *C) { + VisitOMPClauseList(C); + return true; +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) { + VisitOMPClauseList(C); + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm |