[cfe-commits] r107592 - /cfe/trunk/include/clang/AST/RecursiveASTVisitor.h

Nick Lewycky nicholas at mxc.ca
Sun Jul 4 14:29:45 PDT 2010


Author: nicholas
Date: Sun Jul  4 16:29:45 2010
New Revision: 107592

URL: http://llvm.org/viewvc/llvm-project?rev=107592&view=rev
Log:
Add TypeLoc traversal to the RecursiveASTVisitor! Because the TypeLocs don't
contain all the same information that their Types do, we will fall back to
traversing the Types instead. The default TypeLoc visitor calls the matching
Type visitor so that existing clients should continue to work with no change.

Also adds element traversal to the ExtVectorType.

Modified:
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=107592&r1=107591&r2=107592&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Sun Jul  4 16:29:45 2010
@@ -29,6 +29,7 @@
 #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().
@@ -144,6 +145,14 @@
   /// otherwise (including when the argument is a Null type).
   bool TraverseType(QualType T);
 
+  /// \brief Recursively visit a type with location, by dispatching to
+  /// Visit*TypeLoc() based on the argument type's getTypeClass() property.
+  /// This is NOT meant to be overridden by a subclass.
+  ///
+  /// \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
   /// Visit*Decl() based on the argument's dynamic type.  This is
   /// NOT meant to be overridden by a subclass.
@@ -167,9 +176,15 @@
   /// appropriate method for the argument type.
   ///
   /// \returns false if the visitation was terminated early, true otherwise.
-  // FIXME: take a TemplateArgumentLoc instead.
+  // 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.
@@ -281,6 +296,46 @@
   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 Visit*() for all TypeLoc classes.  The Visit*()
+  // methods call into the equivalent Visit*() method for Type classes.
+  bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); }
+  bool VisitTypeLoc(TypeLoc TL) {
+    return getDerived().VisitType(TL.getTypePtr());
+  }
+  bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) {
+    return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
+  }
+  bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+    return getDerived().VisitType(TL.getTypePtr());
+  }
+  bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) {
+    return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
+  }
+  bool VisitUnqualTypeLoc(UnqualTypeLoc TL) {
+    return getDerived().VisitType(TL.getTypePtr());
+  }
+  // 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 getDerived().Visit##CLASS##Type(TL.getTypePtr());    \
+  }
+#include "clang/AST/TypeNodes.def"
+
   // ---- Methods on Decls ----
 
   // Declare Traverse*() for all concrete Decl classes.
@@ -382,6 +437,23 @@
 }
 
 template<typename Derived>
+bool RecursiveASTVisitor<Derived>::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(*cast<CLASS##TypeLoc>(&TL));
+#include "clang/AST/TypeLocNodes.def"
+  }
+
+  return true;
+}
+
+
+template<typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
   if (!D)
     return true;
@@ -463,6 +535,38 @@
   return true;
 }
 
+// FIXME: no template name location?
+// FIXME: no source locations for a template argument pack?
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
+                                           const TemplateArgumentLoc &ArgLoc) {
+  const TemplateArgument &Arg = ArgLoc.getArgument();
+
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+  case TemplateArgument::Declaration:
+  case TemplateArgument::Integral:
+    return true;
+
+  case TemplateArgument::Type: {
+    TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo();
+    return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
+  }
+
+  case TemplateArgument::Template:
+    return getDerived().TraverseTemplateName(Arg.getAsTemplate());
+
+  case TemplateArgument::Expression:
+    return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
+
+  case TemplateArgument::Pack:
+    return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
+                                                  Arg.pack_size());
+  }
+
+  return true;
+}
+
 template<typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
                                                   const TemplateArgument *Args,
@@ -551,7 +655,9 @@
     TRY_TO(TraverseType(T->getElementType()));
   })
 
-DEF_TRAVERSE_TYPE(ExtVectorType, { })
+DEF_TRAVERSE_TYPE(ExtVectorType, {
+    TRY_TO(TraverseType(T->getElementType()));
+  })
 
 DEF_TRAVERSE_TYPE(FunctionNoProtoType, {
     TRY_TO(TraverseType(T->getResultType()));
@@ -631,6 +737,183 @@
 
 #undef DEF_TRAVERSE_TYPE
 
+// ----------------- TypeLoc traversal -----------------
+
+// This macro makes available a variable TL, the passed-in TypeLoc.
+#define DEF_TRAVERSE_TYPELOC(TYPELOC, CODE)                            \
+  template<typename Derived>                                           \
+  bool RecursiveASTVisitor<Derived>::Traverse##TYPELOC (TYPELOC TL) {  \
+    TRY_TO(WalkUpFrom##TYPELOC (TL));                                  \
+    { CODE; }                                                          \
+    return true;                                                       \
+  }
+
+DEF_TRAVERSE_TYPELOC(QualifiedTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getUnqualifiedLoc()));
+  })
+
+DEF_TRAVERSE_TYPELOC(BuiltinTypeLoc, { })
+
+// FIXME: ComplexTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(ComplexTypeLoc, {
+    TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+  })
+
+DEF_TRAVERSE_TYPELOC(PointerTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+  })
+
+DEF_TRAVERSE_TYPELOC(BlockPointerTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+  })
+
+DEF_TRAVERSE_TYPELOC(LValueReferenceTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+  })
+
+DEF_TRAVERSE_TYPELOC(RValueReferenceTypeLoc, {
+    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(MemberPointerTypeLoc, {
+    TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
+    TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+  })
+
+DEF_TRAVERSE_TYPELOC(ConstantArrayTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+  })
+
+DEF_TRAVERSE_TYPELOC(IncompleteArrayTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+  })
+
+DEF_TRAVERSE_TYPELOC(VariableArrayTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+    TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+  })
+
+DEF_TRAVERSE_TYPELOC(DependentSizedArrayTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+    if (TL.getTypePtr()->getSizeExpr())
+      TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+  })
+
+// FIXME: order? why not size expr first?
+// FIXME: base VectorTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorTypeLoc, {
+    if (TL.getTypePtr()->getSizeExpr())
+      TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+    TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+  })
+
+// FIXME: VectorTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(VectorTypeLoc, {
+    TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+  })
+
+// FIXME: size and attributes
+// FIXME: base VectorTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(ExtVectorTypeLoc, {
+    TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+  })
+
+DEF_TRAVERSE_TYPELOC(FunctionNoProtoTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
+  })
+
+// FIXME: location of arguments, exception specifications (attributes?)
+// Note that we have the ParmVarDecl's here. Do we want to use them?
+DEF_TRAVERSE_TYPELOC(FunctionProtoTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
+
+    FunctionProtoType *T = TL.getTypePtr();
+/*
+    for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+      TRY_TO(TraverseDecl(TL.getArg(I)));
+    }
+*/
+    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_TYPELOC(UnresolvedUsingTypeLoc, { })
+DEF_TRAVERSE_TYPELOC(TypedefTypeLoc, { })
+
+DEF_TRAVERSE_TYPELOC(TypeOfExprTypeLoc, {
+    TRY_TO(TraverseStmt(TL.getUnderlyingExpr()));
+  })
+
+DEF_TRAVERSE_TYPELOC(TypeOfTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
+  })
+
+// FIXME: location of underlying expr
+DEF_TRAVERSE_TYPELOC(DecltypeTypeLoc, {
+    TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
+  })
+
+DEF_TRAVERSE_TYPELOC(RecordTypeLoc, { })
+DEF_TRAVERSE_TYPELOC(EnumTypeLoc, { })
+DEF_TRAVERSE_TYPELOC(TemplateTypeParmTypeLoc, { })
+DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmTypeLoc, { })
+
+// FIXME: use the loc for the template name?
+DEF_TRAVERSE_TYPELOC(TemplateSpecializationTypeLoc, {
+    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(InjectedClassNameTypeLoc, { })
+
+// FIXME: use the sourceloc on qualifier?
+DEF_TRAVERSE_TYPELOC(ElaboratedTypeLoc, {
+    if (TL.getTypePtr()->getQualifier()) {
+      TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
+    }
+    TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc()));
+  })
+
+// FIXME: use the sourceloc on qualifier?
+DEF_TRAVERSE_TYPELOC(DependentNameTypeLoc, {
+    TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
+  })
+
+DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationTypeLoc, {
+    TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
+    for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+      TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
+    }
+  })
+
+DEF_TRAVERSE_TYPELOC(ObjCInterfaceTypeLoc, { })
+
+DEF_TRAVERSE_TYPELOC(ObjCObjectTypeLoc, {
+    // 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(ObjCObjectPointerTypeLoc, {
+    TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+  })
+
+#undef DEF_TRAVERSE_TYPELOC
+
 // ----------------- Decl traversal -----------------
 //
 // For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing
@@ -811,9 +1094,8 @@
     // D is the "T" in something like
     //   template <template <typename> class T> class container { };
     TRY_TO(TraverseDecl(D->getTemplatedDecl()));
-    // FIXME: pass along the full TemplateArgumentLoc
     if (D->hasDefaultArgument()) {
-      TRY_TO(TraverseTemplateArgument(D->getDefaultArgument().getArgument()));
+      TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
     }
     TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
   })
@@ -821,7 +1103,7 @@
 DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
     // D is the "T" in something like "template<typename T> class vector;"
     if (D->hasDefaultArgument())
-      TRY_TO(TraverseType(D->getDefaultArgument()));
+      TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
     if (D->getTypeForDecl())
       TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
   })
@@ -902,9 +1184,8 @@
     // is the only callback that's made for this instantiation.
     // We use getTypeAsWritten() to distinguish.
     // FIXME: see how we want to handle template specializations.
-    TypeSourceInfo *TSI = D->getTypeAsWritten();
-    if (TSI)
-      TRY_TO(TraverseType(TSI->getType()));
+    if (TypeSourceInfo *TSI = D->getTypeAsWritten())
+      TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
     return true;
   })
 
@@ -912,16 +1193,14 @@
 bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
     const TemplateArgumentLoc *TAL, unsigned Count) {
   for (unsigned I = 0; I < Count; ++I) {
-    // FIXME: pass along the loc information to this callback as well?
-    TRY_TO(TraverseTemplateArgument(TAL[I].getArgument()));
+    TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
   }
   return true;
 }
 
 DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
     // The partial specialization.
-    TemplateParameterList *TPL = D->getTemplateParameters();
-    if (TPL) {
+    if (TemplateParameterList *TPL = D->getTemplateParameters()) {
       for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
            I != E; ++I) {
         TRY_TO(TraverseDecl(*I));
@@ -951,7 +1230,7 @@
 bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
   TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
   if (D->getTypeSourceInfo())
-    TRY_TO(TraverseType(D->getTypeSourceInfo()->getType()));
+    TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
   return true;
 }
 





More information about the cfe-commits mailing list