rsmith added inline comments.

================
Comment at: include/clang/AST/RecursiveASTVisitor.h:487-489
@@ +486,5 @@
+  // Traverses template parameter lists of either a DeclaratorDecl or TagDecl.
+  template <typename T, typename Enabled = typename std::enable_if<
+      std::is_base_of<DeclaratorDecl, T>::value ||
+      std::is_base_of<TagDecl, T>::value>::type>
+  bool TraverseDeclTemplateParameterLists(T *D);
----------------
What's the purpose of the `enable_if` here?

================
Comment at: include/clang/AST/RecursiveASTVisitor.h:1728
@@ -1708,2 +1727,3 @@
 
+  TRY_TO(TraverseDeclTemplateParameterLists(D));
   TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
----------------
lukasza wrote:
> I think that tweaks of EnumDecl traversal together with tweaks of 
> TraverseRecordHelper tweaks, take care of all the relevant node types derived 
> from TagDecl:
> 
> - EnumDecl - traversal now calls TraverseDeclTemplateParameterLists 
> (+EnumDecl is covered by the new unit tests)
> - RecordDecl - TraverseRecordHelper now calls 
> TraverseDeclTemplateParameterLists (+RecordDecl is covered by the new unit 
> tests)
> - CXXRecordDecl - traversal includes a call to TraverseRecordHelper
> 
> I believe that nodes derived further from CXXRecordDecl cannot have a 
> template parameter list (?):
> - ClassTemplateSpecializationDecl
> - ClassTemplatePartialSpecializationDecl
> If this is not correct, then can you please help me see the shape of unit 
> tests that would cover these nodes?
I don't think `ClassTemplateSpecializationDecl` can have a template parameter 
list for its qualifier. A `ClassTemplatePartialSpecializationDecl` can, though:

  template<typename T> struct A {
    template<typename U> struct B; 
  };
  template<typename T> template<typename U> struct A<T>::B<U*> {};

================
Comment at: include/clang/AST/RecursiveASTVisitor.h:1823
@@ -1802,2 +1822,3 @@
 bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) 
{
+  TRY_TO(TraverseDeclTemplateParameterLists(D));
   TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
----------------
lukasza wrote:
> I think that TraverseDeclaratorHelper together with TraverseFunctionHelper 
> tweaks, this takes care of all node types derived from DeclaratorDecl:
> - FieldDecl - traversal calls TraverseDeclaratorHelper
> - FunctionDecl - traversal calls TraverseFunctionHelper
> - CXXMethodDecl - traversal calls TraverseFunctionHelper (+CXXMethodDecl is 
> covered by the new unit tests)
> - CXXConstructorDecl - traversal calls TraverseFunctionHelper
> - CXXConversionDecl - traversal calls TraverseFunctionHelper
> - CXXDestructorDecl - traversal calls TraverseFunctionHelper
> - VarDecl - TraverseVarHelper calls TraverseDeclaratorHelper (+VarDecl is 
> covered by the new unit tests)
> 
> I believe that nodes derived further from VarDecl cannot have a template 
> parameter list (?), but most of them should still be safe (because their 
> traversal goes through TraverseVarHelper):
> - DecompositionDecl - traversal calls TraverseVarHelper
> - ImplicitParamDecl - traversal calls TraverseVarHelper
> - OMPCapturedExprDecl - traversal calls TraverseVarHelper
> - ParmVarDecl - traversal calls TraverseVarHelper
> - VarTemplateSpecializationDecl
> - VarTemplatePartialSpecializationDecl
> 
> Please let me know if I am wrong above and it is indeed possible to have 
> template parameter lists next to VarTemplateSpecializationDecl and/or 
> VarTemplatePartialSpecializationDecl (and I would also appreciate if you 
> could help me see the shape of unit tests that would cover these nodes).
`VarTemplatePartialSpecializationDecl`s can have template parameter lists:

  template<typename T> struct A { template<typename U> static int n; };
  template<typename T> template<typename U> int A<T>::n<U*>;

I don't think other `VarTemplateSpecializationDecl`s can.

================
Comment at: include/clang/AST/RecursiveASTVisitor.h:1870
@@ -1848,2 +1869,3 @@
 bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
+  TRY_TO(TraverseDeclTemplateParameterLists(D));
   TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
----------------
lukasza wrote:
> Richard, in https://llvm.org/bugs/show_bug.cgi?id=29042#c6 you've suggested 
> reusing TraverseDeclaratorHelper here.  I agree that there are refactoring 
> and code reusing opportunities here (e.g. TraverseNestedNameSpecifier[Loc] 
> are getting called from both TraverseDeclaratorHelper and from 
> TraverseFunctionHelper), but I didn't pursue them in this patch, because I 
> was worried about little details:
> 
> 1. traversal order (i.e. TraverseDeclaratorHelper traverses 
> NestedNameSpecifier immediately before traversing TypeSourceInfo;  this is 
> different than TraverseFunctionHelper which traverses DeclarationNameInfo 
> in-between traversing NestedNameSpecifier and TypeSourceInfo)
> 
> 2. traversal in absence of TypeSourceInfo (i.e. when TypeSourceInfo is 
> missing, then TraverseDeclaratorHelper traverses Type;  this is different 
> than TraverseFunctionHelper which in this case 1) checks 
> shouldVisitImplicitCode condition and only then 2) traverses function 
> parameters).
> 
> Because of the above, I think that for now it is better to call 
> TraverseDeclTemplateParameterLists directly from TraverseFunctionHelper, 
> rather than trying to reuse the whole (or bigger part of) 
> TraverseDeclaratorHelper from TraverseFunctionHelper.
I'm happy to leave the refactoring (and its changes to traversal order / fixing 
missing traversal of type) to another day.

================
Comment at: unittests/ASTMatchers/ASTMatchersTraversalTest.cpp:1730
@@ +1729,3 @@
+  return type && InnerMatcher.matches(*type, Finder, Builder);
+}
+
----------------
lukasza wrote:
> I've needed this custom AST matcher in 
> https://codereview.chromium.org/2256913002 - let me try to sneak in a 
> question related to this other CL:  Can I somehow avoid introducing a new, 
> custom AST matcher?  (i.e. is it possible to express hasUnderlyingType in 
> terms of built-in matchers?)
I think this is poorly named -- "underlying type" means something specific to 
do with enumerations, which is not what you're matching here. I'm also not sure 
why you need this at all; why can't you just match a `templateTypeParmType` 
directly?

================
Comment at: unittests/ASTMatchers/ASTMatchersTraversalTest.cpp:1741
@@ +1740,3 @@
+      qualType(hasUnderlyingType(templateTypeParmType(hasDeclaration(decl(
+          hasAncestor(decl()))))))));
+}
----------------
This seems like a non-obvious way to check that you matched the right 
`TemplateTypeParmDecl`. Can you check the source location of the match instead, 
perhaps?


https://reviews.llvm.org/D24268



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to