[PATCH] Add TemplateSpecializationType polymorphism for hasTemplateArgument and hasAnyTemplateArgument, and (out of necessity) a refersToExpr matcher.

Peter Collingbourne peter at pcc.me.uk
Wed Feb 19 17:41:29 PST 2014

Comment at: include/clang/ASTMatchers/ASTMatchers.h:338-345
@@ -325,7 +337,10 @@
 ///   matches the specialization \c A<int>
-AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument,
-              internal::Matcher<TemplateArgument>, InnerMatcher) {
-  llvm::ArrayRef<TemplateArgument> List = Node.getTemplateArgs().asArray();
+    hasAnyTemplateArgument,
+    AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl,
+                                      TemplateSpecializationType),
+    internal::Matcher<TemplateArgument>, InnerMatcher) {
+  llvm::ArrayRef<TemplateArgument> List = getTemplateSpecializationArgs(Node);
   return matchesFirstInRange(InnerMatcher, List.begin(), List.end(), Finder,
Richard Smith wrote:
> What about the template argument list in a DeclRefExpr (for either a function template specialization or a variable template specialization)?
Yes, these should probably be accessible via this matcher, eventually. (It seems a little tricky to do right now because they store arrays of TemplateArgumentLocs rather than TemplateArguments. We might want to expose TemplateArgumentLoc to matcher clients when we do this.)

Comment at: include/clang/AST/TemplateBase.h:37-38
@@ -36,4 +36,4 @@
 /// \brief Represents a template argument within a class template
-/// specialization.
+/// specialization or a template specialization type.
 class TemplateArgument {
Richard Smith wrote:
> This list is still incomplete. Maybe just "Represents a template argument."?

Comment at: include/clang/AST/TemplateBase.h:63-66
@@ -62,4 +62,6 @@
-    /// The template argument is a value- or type-dependent expression or a
-    /// non-dependent __uuidof expression stored in an Expr*.
+    /// If owned by a template specialization type, the template argument is any
+    /// expression. Otherwise, the template argument is a value- or
+    /// type-dependent expression or a non-dependent __uuidof expression stored
+    /// in an Expr*.
Richard Smith wrote:
> I'd prefer for us to say something a bit more general here:
>   The template argument is an expression, and we've not resolved it
>   to one of the above forms yet, either because it's dependent or
>   because we're representing a non-canonical template argument
>   (for instance, in a TemplateSpecializationType). Also used to
>   represent a non-dependent __uuidof expression (a Microsoft extension).
Done. Substituted "other" for "above" since I guess it could also be a pack expansion, right?

Comment at: include/clang/ASTMatchers/ASTMatchers.h:326-327
@@ -314,3 +325,4 @@
 /// \brief Matches classTemplateSpecializations that have at least one
 /// TemplateArgument matching the given InnerMatcher.
Richard Smith wrote:
> What about default arguments? For `hasAnyTemplateArgument(isInt)`:
>   template<typename T = int> // match here? (I assume yes)
>   struct S {};
>   S<> s; // match here? (I assume no)
> What about deduced arguments:
>   template<typename T> void f(T);
>   f<int>(); // match here? (yes?)
>   f<>(0); // match here? (no?)
>   f(0); // match here? (no?)
> In the above case, do we match the implicit instantiations of the function template?
My intuition is that a separate set of matchers should be provided for default template arguments (maybe something with "default" in the name) if only for the sake of readability.

As for deduced arguments, I don't think we need to provide them as properties of the expression. They can be retrieved from the declaration easily enough by following the reference if needed.


More information about the cfe-commits mailing list