[cfe-commits] r123493 - in /cfe/trunk: include/clang/AST/TemplateBase.h lib/AST/ASTContext.cpp lib/AST/ASTImporter.cpp lib/AST/DeclTemplate.cpp lib/AST/TemplateBase.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp

Douglas Gregor dgregor at apple.com
Fri Jan 14 15:41:42 PST 2011


Author: dgregor
Date: Fri Jan 14 17:41:42 2011
New Revision: 123493

URL: http://llvm.org/viewvc/llvm-project?rev=123493&view=rev
Log:
Teach template template argument pack expansions to keep track of the
number of expansions, when we know it, and propagate that information
through Sema.

Modified:
    cfe/trunk/include/clang/AST/TemplateBase.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/AST/TemplateBase.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp

Modified: cfe/trunk/include/clang/AST/TemplateBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateBase.h?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TemplateBase.h (original)
+++ cfe/trunk/include/clang/AST/TemplateBase.h Fri Jan 14 17:41:42 2011
@@ -80,8 +80,14 @@
       const TemplateArgument *Args;
       unsigned NumArgs;
     } Args;
+    struct {
+      void *Name;
+      unsigned NumExpansions;
+    } TemplateArg;
   };
 
+  TemplateArgument(TemplateName, bool); // DO NOT USE
+  
 public:
   /// \brief Construct an empty, invalid template argument.
   TemplateArgument() : Kind(Null), TypeOrValue(0) { }
@@ -107,8 +113,7 @@
     Integer.Type = Type.getAsOpaquePtr();
   }
 
-  /// \brief Construct a template argument that is a template or a pack
-  /// expansion of templates.
+  /// \brief Construct a template argument that is a template.
   ///
   /// This form of template argument is generally used for template template
   /// parameters. However, the template name could be a dependent template
@@ -116,13 +121,33 @@
   /// is taken.
   ///
   /// \param Name The template name.
-  /// \param PackExpansion Whether this template argument is a pack expansion.
-  TemplateArgument(TemplateName Name, bool PackExpansion = false) 
-    : Kind(PackExpansion? TemplateExpansion : Template) 
+  TemplateArgument(TemplateName Name) : Kind(Template) 
   {
-    TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
+    TemplateArg.Name = Name.getAsVoidPointer();
+    TemplateArg.NumExpansions = 0;
   }
-  
+
+  /// \brief Construct a template argument that is a template pack expansion.
+  ///
+  /// This form of template argument is generally used for template template
+  /// parameters. However, the template name could be a dependent template
+  /// name that ends up being instantiated to a function template whose address
+  /// is taken.
+  ///
+  /// \param Name The template name.
+  ///
+  /// \param NumExpansions The number of expansions that will be generated by
+  /// instantiating
+  TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions)
+    : Kind(TemplateExpansion) 
+  {
+    TemplateArg.Name = Name.getAsVoidPointer();
+    if (NumExpansions)
+      TemplateArg.NumExpansions = *NumExpansions + 1;
+    else
+      TemplateArg.NumExpansions = 0;
+  }
+
   /// \brief Construct a template argument that is an expression.
   ///
   /// This form of template argument only occurs in template argument
@@ -151,6 +176,9 @@
     } else if (Kind == Pack) {
       Args.NumArgs = Other.Args.NumArgs;
       Args.Args = Other.Args.Args;
+    } else if (Kind == Template || Kind == TemplateExpansion) {
+      TemplateArg.Name = Other.TemplateArg.Name;
+      TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
     } else
       TypeOrValue = Other.TypeOrValue;
   }
@@ -177,6 +205,9 @@
     } else if (Other.Kind == Pack) {
       Args.NumArgs = Other.Args.NumArgs;
       Args.Args = Other.Args.Args;
+    } else if (Kind == Template || Kind == TemplateExpansion) {
+      TemplateArg.Name = Other.TemplateArg.Name;
+      TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
     } else {
       TypeOrValue = Other.TypeOrValue;
     }
@@ -234,8 +265,7 @@
     if (Kind != Template)
       return TemplateName();
     
-    return TemplateName::getFromVoidPointer(
-                                          reinterpret_cast<void*>(TypeOrValue));
+    return TemplateName::getFromVoidPointer(TemplateArg.Name);
   }
 
   /// \brief Retrieve the template argument as a template name; if the argument
@@ -244,10 +274,13 @@
     if (Kind != Template && Kind != TemplateExpansion)
       return TemplateName();
     
-    return TemplateName::getFromVoidPointer(
-                                          reinterpret_cast<void*>(TypeOrValue));
+    return TemplateName::getFromVoidPointer(TemplateArg.Name);
   }
 
+  /// \brief Retrieve the number of expansions that a template template argument
+  /// expansion will produce, if known.
+  llvm::Optional<unsigned> getNumTemplateExpansions() const;
+  
   /// \brief Retrieve the template argument as an integral value.
   llvm::APSInt *getAsIntegral() {
     if (Kind != Integral)

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jan 14 17:41:42 2011
@@ -2768,7 +2768,7 @@
     case TemplateArgument::TemplateExpansion:
       return TemplateArgument(getCanonicalTemplateName(
                                          Arg.getAsTemplateOrTemplatePattern()),
-                              true);
+                              Arg.getNumTemplateExpansions());
 
     case TemplateArgument::Integral:
       return TemplateArgument(*Arg.getAsIntegral(),

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Fri Jan 14 17:41:42 2011
@@ -1823,7 +1823,7 @@
     if (ToTemplate.isNull())
       return TemplateArgument();
     
-    return TemplateArgument(ToTemplate, true);
+    return TemplateArgument(ToTemplate, From.getNumTemplateExpansions());
   }
 
   case TemplateArgument::Expression:

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Fri Jan 14 17:41:42 2011
@@ -337,7 +337,10 @@
       Arg = TemplateArgument(E);
     } else {
       TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
-      Arg = TemplateArgument(TemplateName(TTP), TTP->isParameterPack());
+      if (TTP->isParameterPack())
+        Arg = TemplateArgument(TemplateName(TTP), llvm::Optional<unsigned>());
+      else
+        Arg = TemplateArgument(TemplateName(TTP));
     }
     
     if ((*Param)->isTemplateParameterPack())

Modified: cfe/trunk/lib/AST/TemplateBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateBase.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TemplateBase.cpp (original)
+++ cfe/trunk/lib/AST/TemplateBase.cpp Fri Jan 14 17:41:42 2011
@@ -135,6 +135,14 @@
   return false;
 }
 
+llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
+  assert(Kind == TemplateExpansion);
+  if (TemplateArg.NumExpansions)
+    return TemplateArg.NumExpansions - 1;
+  
+  return llvm::Optional<unsigned>();
+}
+
 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
                                const ASTContext &Context) const {
   ID.AddInteger(Kind);
@@ -223,7 +231,7 @@
     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
     
   case TemplateExpansion:
-    return TemplateArgument(getAsTemplateOrTemplatePattern(), false);
+    return TemplateArgument(getAsTemplateOrTemplatePattern());
     
   case Declaration:
   case Integral:
@@ -389,8 +397,8 @@
   }
 
   case TemplateArgument::TemplateExpansion:
-    // FIXME: Variadic templates num expansions
     Ellipsis = getTemplateEllipsisLoc();
+    NumExpansions = Argument.getNumTemplateExpansions();
     return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
                                getTemplateQualifierRange(),
                                getTemplateNameLoc());

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Jan 14 17:41:42 2011
@@ -467,8 +467,12 @@
     
   case ParsedTemplateArgument::Template: {
     TemplateName Template = Arg.getAsTemplate().get();
-    return TemplateArgumentLoc(TemplateArgument(Template,
-                                                Arg.getEllipsisLoc().isValid()),
+    TemplateArgument TArg;
+    if (Arg.getEllipsisLoc().isValid())
+      TArg = TemplateArgument(Template, llvm::Optional<unsigned int>());
+    else
+      TArg = Template;
+    return TemplateArgumentLoc(TArg,
                                Arg.getScopeSpec().getRange(),
                                Arg.getLocation(),
                                Arg.getEllipsisLoc());

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Jan 14 17:41:42 2011
@@ -809,11 +809,8 @@
         assert(Arg.getKind() == TemplateArgument::Pack && 
                "Missing argument pack");
         
-        if (getSema().ArgumentPackSubstitutionIndex == -1) {
-          // FIXME: Variadic templates fun case.
-          getSema().Diag(Loc, diag::err_pack_expansion_mismatch_unsupported);
+        if (getSema().ArgumentPackSubstitutionIndex == -1)
           return 0;
-        }
         
         assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
         Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Jan 14 17:41:42 2011
@@ -2188,7 +2188,7 @@
     case TemplateArgument::Template:
       return TemplateArgumentLoc(TemplateArgument(
                                           Pattern.getArgument().getAsTemplate(),
-                                                  true),
+                                                  NumExpansions),
                                  Pattern.getTemplateQualifierRange(),
                                  Pattern.getTemplateNameLoc(),
                                  EllipsisLoc);

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Jan 14 17:41:42 2011
@@ -4290,9 +4290,13 @@
     return TemplateArgument(Value, T);
   }
   case TemplateArgument::Template: 
+    return TemplateArgument(ReadTemplateName(Record, Idx));
   case TemplateArgument::TemplateExpansion: {
     TemplateName Name = ReadTemplateName(Record, Idx);
-    return TemplateArgument(Name, Kind == TemplateArgument::TemplateExpansion);
+    llvm::Optional<unsigned> NumTemplateExpansions;
+    if (unsigned NumExpansions = Record[Idx++])
+      NumTemplateExpansions = NumExpansions - 1;
+    return TemplateArgument(Name, NumTemplateExpansions);
   }
   case TemplateArgument::Expression:
     return TemplateArgument(ReadExpr(F));

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Jan 14 17:41:42 2011
@@ -3231,8 +3231,14 @@
     AddTypeRef(Arg.getIntegralType(), Record);
     break;
   case TemplateArgument::Template:
+    AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
+    break;
   case TemplateArgument::TemplateExpansion:
     AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
+    if (llvm::Optional<unsigned> NumExpansions = Arg.getNumTemplateExpansions())
+      Record.push_back(*NumExpansions + 1);
+    else
+      Record.push_back(0);
     break;
   case TemplateArgument::Expression:
     AddStmt(Arg.getAsExpr());

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp Fri Jan 14 17:41:42 2011
@@ -88,4 +88,42 @@
                                        pair<int, unsigned int>,
                                        pair<long, unsigned long>)
                                      >::value == 1? 1 : -1]; 
+
+  template<typename T, typename U>
+  struct some_function_object {
+    template<typename>
+    struct result_of;
+  };
+
+  template<template<class> class...> struct metafun_tuple { };
+
+  template<typename ...Types1>
+  struct X3 {
+    template<typename, typename> struct Inner {
+      static const unsigned value = 0;
+    };
+
+    template<typename ...Types2>
+    struct Inner<tuple<pair<Types1, Types2>...>,
+                 metafun_tuple<some_function_object<Types1, Types2>::template result_of...> > {
+      static const unsigned value = 1;
+    };
+  };
+
+  int check6[X3<short, int, long>::Inner<tuple<pair<short, unsigned short>,
+                                               pair<int, unsigned int>,
+                                               pair<long, unsigned long>>,
+                                 metafun_tuple<
+                         some_function_object<short, unsigned short>::result_of,
+                         some_function_object<int, unsigned int>::result_of,
+                         some_function_object<long, unsigned long>::result_of>
+                                     >::value == 1? 1 : -1];
+  int check7[X3<short, int>::Inner<tuple<pair<short, unsigned short>,
+                                               pair<int, unsigned int>,
+                                               pair<long, unsigned long>>,
+                                 metafun_tuple<
+                         some_function_object<short, unsigned short>::result_of,
+                         some_function_object<int, unsigned int>::result_of,
+                         some_function_object<long, unsigned long>::result_of>
+                                     >::value == 0? 1 : -1];
 }





More information about the cfe-commits mailing list