[cfe-commits] r122843 - in /cfe/trunk: lib/Sema/SemaTemplateDeduction.cpp test/CXX/temp/temp.decls/temp.variadic/deduction.cpp

Douglas Gregor dgregor at apple.com
Tue Jan 4 14:13:36 PST 2011


Author: dgregor
Date: Tue Jan  4 16:13:36 2011
New Revision: 122843

URL: http://llvm.org/viewvc/llvm-project?rev=122843&view=rev
Log:
Improve the checking of deduced template arguments stored within template argument packs when finishing template argument deduction for a function template

Added:
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp
Modified:
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=122843&r1=122842&r2=122843&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Jan  4 16:13:36 2011
@@ -1677,6 +1677,55 @@
   return TemplateArgumentLoc();
 }
 
+/// \brief Convert the given deduced template argument and add it to the set of
+/// fully-converted template arguments.
+static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, 
+                                           DeducedTemplateArgument Arg,
+                                         FunctionTemplateDecl *FunctionTemplate, 
+                                           QualType NTTPType, 
+                                           TemplateDeductionInfo &Info,
+                       llvm::SmallVectorImpl<TemplateArgument> &Output) {
+  if (Arg.getKind() == TemplateArgument::Pack) {
+    // This is a template argument pack, so check each of its arguments against
+    // the template parameter.
+    llvm::SmallVector<TemplateArgument, 2> PackedArgsBuilder;
+    for (TemplateArgument::pack_iterator PA = Arg.pack_begin(), 
+                                      PAEnd = Arg.pack_end();
+         PA != PAEnd; ++PA) {
+      DeducedTemplateArgument InnerArg(*PA);
+      InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
+      if (ConvertDeducedTemplateArgument(S, Param, InnerArg, FunctionTemplate, 
+                                         NTTPType, Info, PackedArgsBuilder))
+        return true;
+    }
+    
+    // Create the resulting argument pack.
+    TemplateArgument *PackedArgs = 0;
+    if (!PackedArgsBuilder.empty()) {
+      PackedArgs = new (S.Context) TemplateArgument[PackedArgsBuilder.size()];
+      std::copy(PackedArgsBuilder.begin(), PackedArgsBuilder.end(), PackedArgs);
+    }
+    Output.push_back(TemplateArgument(PackedArgs, PackedArgsBuilder.size()));
+    return false;
+  }
+  
+  // Convert the deduced template argument into a template
+  // argument that we can check, almost as if the user had written
+  // the template argument explicitly.
+  TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType,
+                                                           Info.getLocation());
+
+  // Check the template argument, converting it as necessary.
+  return S.CheckTemplateArgument(Param, ArgLoc,
+                                 FunctionTemplate,
+                                 FunctionTemplate->getLocation(),
+                                 FunctionTemplate->getSourceRange().getEnd(),
+                                 Output,
+                                 Arg.wasDeducedFromArrayBound()
+                                  ? Sema::CTAK_DeducedFromArrayBound 
+                                  : Sema::CTAK_Deduced);
+}
+
 /// \brief Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template specialization.
@@ -1708,9 +1757,8 @@
   //   [...] or if any template argument remains neither deduced nor
   //   explicitly specified, template argument deduction fails.
   llvm::SmallVector<TemplateArgument, 4> Builder;
-  for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {    
-    // FIXME: Variadic templates. Unwrap argument packs?
-    NamedDecl *Param = FunctionTemplate->getTemplateParameters()->getParam(I);
+  for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+    NamedDecl *Param = TemplateParams->getParam(I);
     
     if (!Deduced[I].isNull()) {
       if (I < NumExplicitlySpecified) {
@@ -1730,49 +1778,32 @@
       QualType NTTPType;
       if (NonTypeTemplateParmDecl *NTTP 
                                 = dyn_cast<NonTypeTemplateParmDecl>(Param)) { 
-        if (Deduced[I].getKind() == TemplateArgument::Declaration) {
-          NTTPType = NTTP->getType();
-          if (NTTPType->isDependentType()) {
-            TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, 
-                                              Builder.data(), Builder.size());
-            NTTPType = SubstType(NTTPType,
-                                 MultiLevelTemplateArgumentList(TemplateArgs),
-                                 NTTP->getLocation(),
-                                 NTTP->getDeclName());
-            if (NTTPType.isNull()) {
-              Info.Param = makeTemplateParameter(Param);
-              // FIXME: These template arguments are temporary. Free them!
-              Info.reset(TemplateArgumentList::CreateCopy(Context, 
-                                                          Builder.data(), 
-                                                          Builder.size()));
-              return TDK_SubstitutionFailure;
-            }
+        NTTPType = NTTP->getType();
+        if (NTTPType->isDependentType()) {
+          TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, 
+                                            Builder.data(), Builder.size());
+          NTTPType = SubstType(NTTPType,
+                               MultiLevelTemplateArgumentList(TemplateArgs),
+                               NTTP->getLocation(),
+                               NTTP->getDeclName());
+          if (NTTPType.isNull()) {
+            Info.Param = makeTemplateParameter(Param);
+            // FIXME: These template arguments are temporary. Free them!
+            Info.reset(TemplateArgumentList::CreateCopy(Context, 
+                                                        Builder.data(), 
+                                                        Builder.size()));
+            return TDK_SubstitutionFailure;
           }
         }
       }
 
-      // Convert the deduced template argument into a template
-      // argument that we can check, almost as if the user had written
-      // the template argument explicitly.
-      TemplateArgumentLoc Arg = getTrivialTemplateArgumentLoc(*this,
-                                                              Deduced[I],
-                                                              NTTPType,
-                                                            Info.getLocation());
-
-      // Check the template argument, converting it as necessary.
-      if (CheckTemplateArgument(Param, Arg,
-                                FunctionTemplate,
-                                FunctionTemplate->getLocation(),
-                                FunctionTemplate->getSourceRange().getEnd(),
-                                Builder,
-                                Deduced[I].wasDeducedFromArrayBound()
-                                  ? CTAK_DeducedFromArrayBound 
-                                  : CTAK_Deduced)) {
-        Info.Param = makeTemplateParameter(
-                         const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+      if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
+                                         FunctionTemplate, NTTPType, Info,
+                                         Builder)) {
+        Info.Param = makeTemplateParameter(Param);
         // FIXME: These template arguments are temporary. Free them!
         Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(), 
-                                                    Builder.size()));
+                                                    Builder.size()));  
         return TDK_SubstitutionFailure;
       }
 

Added: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp?rev=122843&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp Tue Jan  4 16:13:36 2011
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+namespace DeductionForInstantiation {
+  template<unsigned I, typename ...Types>
+  struct X { };
+
+  template<typename ...Types>
+  void f0(X<sizeof...(Types), Types&...>) { }
+
+  // No explicitly-specified arguments
+  template void f0(X<0>);
+  template void f0(X<1, int&>);
+  template void f0(X<2, int&, short&>);
+
+  // One explicitly-specified argument
+  template void f0<float>(X<1, float&>);
+  template void f0<double>(X<1, double&>);
+
+  // Two explicitly-specialized arguments
+  template void f0<char, unsigned char>(X<2, char&, unsigned char&>);
+  template void f0<signed char, char>(X<2, signed char&, char&>);
+
+  // FIXME: Extension of explicitly-specified arguments
+  //  template void f0<short, int>(X<3, short&, int&, long&>);
+}





More information about the cfe-commits mailing list