[cfe-commits] [Patch][Review request] RecursiveASTVisitor can now traverse template specializations

Tom Care tcare at apple.com
Thu Aug 26 12:57:43 PDT 2010


Hi Benoit,

You can find some coding style guidelines at http://llvm.org/docs/CodingStandards.html.

We tend to cuddle brackets to the same line, and avoid putting spaces around a condition inside parentheses.

Tom

On Aug 26, 2010, at 12:24 PM, Benoit Belley wrote:

> Hi Everyone,
> 
> I have modified the RecursiveASTVisitor so that it can now optionally visit every template specialization (class and fucntion templates, implicit and explicit instantiations). 
> 
> By default this visitor will not recurse in template specializations since the instatiated class isn’t written in the source code anywhere. This behavior can now be changed by calling setVisitingTemplateSpecializations(true) before starting the traversal.
> 
> Please feel free to comment on the coding style also. I am new to Clang.
> 
> Thanks,
> Benoit
> 
> Index: include/clang/AST/RecursiveASTVisitor.h
> ===================================================================
> --- include/clang/AST/RecursiveASTVisitor.h	(revision 111934)
> +++ include/clang/AST/RecursiveASTVisitor.h	(working copy)
> @@ -123,12 +123,35 @@
> /// 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 will not recurse in template
> +/// specializations ("set<int> x;") since the instatiated class isn't
> +/// written in the source code anywhere. This behavior can be changed
> +/// by calling setVisitingTemplateSpecializations(true) before
> +/// starting the traversal.
> template<typename Derived>
> class RecursiveASTVisitor {
> public:
> +  RecursiveASTVisitor() : visitingTemplateSpecializations(false) {}
> +  
> +
>   /// \brief Return a reference to the derived class.
>   Derived &getDerived() { return *static_cast<Derived*>(this); }
> 
> +  /// \brief Control whether this visitor should recurse into
> +  /// template specializations.
> +  void setVisitingTemplateSpecializations(bool flag)
> +  {
> +    visitingTemplateSpecializations = flag;
> +  }
> +  
> +  /// \brief Return whether this visitor should recurse into
> +  /// template specializations.
> +  bool isVisitingTemplateSpecializations() const
> +  {
> +    return visitingTemplateSpecializations;
> +  }
> +  
>   /// \brief Recursively visit a statement or expression, by
>   /// dispatching to Traverse*() based on the argument's dynamic type.
>   ///
> @@ -360,6 +383,10 @@
>   bool TraverseDeclContextHelper(DeclContext *DC);
>   bool TraverseFunctionHelper(FunctionDecl *D);
>   bool TraverseVarHelper(VarDecl *D);
> +
> +  // This flag indicates that the RecursiveASTVisitor should visit
> +  // template specializations.
> +  bool visitingTemplateSpecializations;
> };
> 
> #define DISPATCH(NAME, CLASS, VAR) \
> @@ -1095,16 +1122,58 @@
> DEF_TRAVERSE_DECL(ClassTemplateDecl, {
>     TRY_TO(TraverseDecl(D->getTemplatedDecl()));
>     TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
> -    // We should not traverse the specializations/partial
> -    // specializations.  Those will show up in other contexts.
> -    // getInstantiatedFromMemberTemplate() is just a link from a
> -    // template instantiation back to the template from which it was
> -    // instantiated, and thus should not be traversed either.
> +    // By default, we do not traverse the specializations/partial
> +    // specializations. Implicitely instantiated templates do not
> +    // apprear in the user code and explicitely instantiated templates
> +    // show up in other contexts.
> +    //
> +    // 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.
> +    //
> +    // FIXME: When visiting implicitely instantiated templates, the
> +    // specialization of an explicit instantiation will be visited
> +    // twice, once at the template function declaration and another
> +    // time at the template instantiation site. Is this an issue ? If
> +    // so, when should be visited.
> +    if ( isVisitingTemplateSpecializations() ) {
> +      {
> +        ClassTemplateDecl::spec_iterator end = D->spec_end();
> +        for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
> +          TRY_TO(TraverseClassTemplateSpecializationDecl(*it));
> +        }
> +      }
> +
> +      {
> +        ClassTemplateDecl::partial_spec_iterator end = D->partial_spec_end();
> +        for (ClassTemplateDecl::partial_spec_iterator it = D->partial_spec_begin(); it != end; ++it) {
> +          TRY_TO(TraverseClassTemplatePartialSpecializationDecl(*it));
> +        }
> +      }
> +    }
>   })
> 
> DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
>     TRY_TO(TraverseDecl(D->getTemplatedDecl()));
>     TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
> +
> +    // By default, we do not traverse the function
> +    // specializations. Implicitely instantiated templates do not
> +    // apprear in the user code and explicitely instantiated templates
> +    // show up in other contexts.
> +    //
> +    // FIXME: When visiting implicitely instantiated templates, the
> +    // specialization of an explicit instantiation will be visited
> +    // twice, once at the template function declaration and another
> +    // time at the template instantiation site. Is this an issue ? If
> +    // so, when should be visited.
> +    if ( isVisitingTemplateSpecializations() ) {
> +      FunctionTemplateDecl::spec_iterator end = D->spec_end();
> +      for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
> +        TRY_TO(TraverseFunctionDecl(*it));
> +      }
> +    }
> +
>   })
> 
> DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
> @@ -1192,18 +1261,22 @@
>   })
> 
> 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.
> -    // FIXME: see how we want to handle template specializations.
> -    if (TypeSourceInfo *TSI = D->getTypeAsWritten())
> -      TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
> -    return true;
> +    if ( isVisitingTemplateSpecializations() ) {
> +      TRY_TO(TraverseCXXRecordHelper(D));
> +    }
> +    else {
> +      // 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.
> +      // FIXME: see how we want to handle template specializations.
> +      if (TypeSourceInfo *TSI = D->getTypeAsWritten())
> +        TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
> +    }
>   })
> 
> template <typename Derived>
> 
> Thanks
> Benoit 
> 
> 
> <RecursiveASTVisitor-TemplSpec.patch><ATT00001..txt><image002.gif><ATT00002..txt>_______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits





More information about the cfe-commits mailing list