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

Craig Silverstein csilvers2000 at yahoo.com
Wed Oct 20 14:13:35 PDT 2010


Author: csilvers
Date: Wed Oct 20 16:13:35 2010
New Revision: 116945

URL: http://llvm.org/viewvc/llvm-project?rev=116945&view=rev
Log:
Get FunctionDecl to recurse on FunctionTypeLoc rather than
FunctionType!  I didn't realize it was available, until rjmccall
pointed out that DeclaratorDecl made the typeloc available.  This
makes FunctionDecl recursion *much* easier, because the typeloc can
take care of default parameters, so we no longer have to do that
separately, which means we can just do a normal type traversal instead
of this special-case WalkUp stuff we did before.

The only downside -- and it's minor -- is that because the TypeLoc
handles both the return type and the argument types, we can't recurse
on the explicit template args in the right place (which would be
between them).  I do it beforehand instead.  So for
   int MyFunc<float>(char x);
we get callbacks in the order: float, int, char.

Reviewed by chandlerc

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=116945&r1=116944&r2=116945&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed Oct 20 16:13:35 2010
@@ -143,7 +143,7 @@
   /// \brief Return whether this visitor should recurse into
   /// template instantiations.
   bool shouldVisitTemplateInstantiations() const { return false; }
-  
+
   /// \brief Recursively visit a statement or expression, by
   /// dispatching to Traverse*() based on the argument's dynamic type.
   ///
@@ -368,7 +368,7 @@
   bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
   bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern);
   bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ;
-  bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, 
+  bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
                                           unsigned Count);
   bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
   bool TraverseRecordHelper(RecordDecl *D);
@@ -867,22 +867,16 @@
     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?
+// FIXME: location of exception specifications (attributes?)
 DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
     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) {
@@ -1175,7 +1169,7 @@
       if (D->isThisDeclarationADefinition())
         TRY_TO(TraverseClassInstantiations(D, 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.
@@ -1208,10 +1202,10 @@
       assert(false && "Unknown specialization kind.");
     }
   }
-  
+
   return true;
 }
-  
+
 DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
     TRY_TO(TraverseDecl(D->getTemplatedDecl()));
     TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
@@ -1412,47 +1406,11 @@
 bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
   TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
 
-  // Visit the function type itself, which can be either
-  // FunctionNoProtoType or FunctionProtoType, or a typedef.  If it's
-  // not a Function*ProtoType, then it can't have a body or arguments,
-  // so we have to do less work.
-  Type *FuncType = D->getType().getTypePtr();
-  if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) {
-    if (D->isThisDeclarationADefinition()) {
-      // Don't call Traverse*, or the result type and parameter types
-      // will be double counted.
-      TRY_TO(WalkUpFromFunctionProtoType(FuncProto));
-    } else {
-      // This works around a bug in Clang that does not add the parameters
-      // to decls_begin/end for function declarations (as opposed to
-      // definitions):
-      //    http://llvm.org/PR7442
-      // We work around this here by traversing the function type.
-      // This isn't perfect because we don't traverse the default
-      // values, if any.  It also may not interact great with
-      // templates.  But it's the best we can do until the bug is
-      // fixed.
-      // FIXME: replace the entire 'if' statement with
-      //   TRY_TO(WalkUpFromFunctionProtoType(FuncProto));
-      // when the bug is fixed.
-      TRY_TO(TraverseFunctionProtoType(FuncProto));
-      return true;
-    }
-  } else if (FunctionNoProtoType *FuncNoProto =
-      dyn_cast<FunctionNoProtoType>(FuncType)) {
-    // Don't call Traverse*, or the result type will be double
-    // counted.
-    TRY_TO(WalkUpFromFunctionNoProtoType(FuncNoProto));
-  } else {   // a typedef type, or who knows what
-    assert(!D->isThisDeclarationADefinition() && "Unexpected function type");
-    TRY_TO(TraverseType(D->getType()));
-    return true;
-  }
-
-  TRY_TO(TraverseType(D->getResultType()));
-
   // If we're an explicit template specialization, iterate over the
-  // template args that were explicitly specified.
+  // template args that were explicitly specified.  If we were doing
+  // this in typing order, we'd do it between the return type and
+  // the function args, but both are handled by the FunctionTypeLoc
+  // above, so we have to choose one side.  I've decided to do before.
   if (const FunctionTemplateSpecializationInfo *FTSI =
       D->getTemplateSpecializationInfo()) {
     if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
@@ -1467,28 +1425,11 @@
     }
   }
 
-  for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end();
-       I != E; ++I) {
-    TRY_TO(TraverseDecl(*I));
-  }
-
-  if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) {
-    if (D->isThisDeclarationADefinition()) {
-      // This would be visited if we called TraverseType(D->getType())
-      // above, but we don't (at least, not in the
-      // declaration-is-a-definition case), in order to avoid duplicate
-      // visiting for parameters.  (We need to check parameters here,
-      // rather than letting D->getType() do it, so we visit default
-      // parameter values).  So we need to re-do some of the work the
-      // type would do.
-      for (FunctionProtoType::exception_iterator
-               E = FuncProto->exception_begin(),
-               EEnd = FuncProto->exception_end();
-           E != EEnd; ++E) {
-        TRY_TO(TraverseType(*E));
-      }
-    }
-  }
+  // Visit the function type itself, which can be either
+  // FunctionNoProtoType or FunctionProtoType, or a typedef.  This
+  // also covers the return type and the function parameters,
+  // including exception specifications.
+  TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
 
   if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
     // Constructor initializers.





More information about the cfe-commits mailing list