[cfe-commits] r122986 - in /cfe/trunk: include/clang/AST/TypeLoc.h include/clang/Sema/Sema.h lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/TreeTransform.h test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp test/SemaTemplate/temp_arg_nontype.cpp

Douglas Gregor dgregor at apple.com
Thu Jan 6 16:20:55 PST 2011


Author: dgregor
Date: Thu Jan  6 18:20:55 2011
New Revision: 122986

URL: http://llvm.org/viewvc/llvm-project?rev=122986&view=rev
Log:
Factor out the template transformation of a sequence of function
parameters into parameter types, so that substitution of
explicitly-specified function template arguments uses the same
path. This enables the use of explicitly-specified function template
arguments with variadic templates.

Added:
    cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp
Modified:
    cfe/trunk/include/clang/AST/TypeLoc.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp

Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=122986&r1=122985&r2=122986&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Thu Jan  6 18:20:55 2011
@@ -1008,11 +1008,6 @@
                                                FunctionTypeLoc,
                                                FunctionType,
                                                FunctionLocInfo> {
-  // ParmVarDecls* are stored after Info, one for each argument.
-  ParmVarDecl **getParmArray() const {
-    return (ParmVarDecl**) getExtraLocalData();
-  }
-
 public:
   SourceLocation getLParenLoc() const {
     return getLocalData()->LParenLoc;
@@ -1035,6 +1030,11 @@
     getLocalData()->TrailingReturn = Trailing;
   }
 
+  // ParmVarDecls* are stored after Info, one for each argument.
+  ParmVarDecl **getParmArray() const {
+    return (ParmVarDecl**) getExtraLocalData();
+  }
+
   unsigned getNumArgs() const {
     if (isa<FunctionNoProtoType>(getTypePtr()))
       return 0;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122986&r1=122985&r2=122986&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jan  6 18:20:55 2011
@@ -3890,6 +3890,10 @@
                                         DeclarationName Entity);
   ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
                             const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool SubstParmTypes(SourceLocation Loc, 
+                      ParmVarDecl **Params, unsigned NumParams,
+                      const MultiLevelTemplateArgumentList &TemplateArgs,
+                      llvm::SmallVectorImpl<QualType> &ParamTypes);
   ExprResult SubstExpr(Expr *E,
                        const MultiLevelTemplateArgumentList &TemplateArgs);
 

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=122986&r1=122985&r2=122986&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Thu Jan  6 18:20:55 2011
@@ -1889,19 +1889,11 @@
 
   // Instantiate the types of each of the function parameters given the
   // explicitly-specified template arguments.
-  for (FunctionDecl::param_iterator P = Function->param_begin(),
-                                PEnd = Function->param_end();
-       P != PEnd;
-       ++P) {
-    QualType ParamType
-      = SubstType((*P)->getType(),
-                  MultiLevelTemplateArgumentList(*ExplicitArgumentList),
-                  (*P)->getLocation(), (*P)->getDeclName());
-    if (ParamType.isNull() || Trap.hasErrorOccurred())
-      return TDK_SubstitutionFailure;
-
-    ParamTypes.push_back(ParamType);
-  }
+  if (SubstParmTypes(Function->getLocation(), 
+                     Function->param_begin(), Function->getNumParams(),
+                     MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+                     ParamTypes))
+    return TDK_SubstitutionFailure;
 
   // If the caller wants a full function type back, instantiate the return
   // type and form that function type.

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=122986&r1=122985&r2=122986&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Jan  6 18:20:55 2011
@@ -1221,6 +1221,23 @@
   return NewParm;  
 }
 
+/// \brief Substitute the given template arguments into the given set of
+/// parameters, producing the set of parameter types that would be generated
+/// from such a substitution.
+bool Sema::SubstParmTypes(SourceLocation Loc, 
+                          ParmVarDecl **Params, unsigned NumParams,
+                          const MultiLevelTemplateArgumentList &TemplateArgs,
+                          llvm::SmallVectorImpl<QualType> &ParamTypes) {
+  assert(!ActiveTemplateInstantiations.empty() &&
+         "Cannot perform an instantiation without some context on the "
+         "instantiation stack");
+  
+  TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, 
+                                    DeclarationName());
+  return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams, 0,
+                                                  ParamTypes, 0);
+}
+
 /// \brief Perform substitution on the base class specifiers of the
 /// given class template specialization.
 ///

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=122986&r1=122985&r2=122986&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jan  6 18:20:55 2011
@@ -439,9 +439,11 @@
   /// variables vector are acceptable.
   ///
   /// Return true on error.
-  bool TransformFunctionTypeParams(FunctionProtoTypeLoc TL,
+  bool TransformFunctionTypeParams(SourceLocation Loc,
+                                   ParmVarDecl **Params, unsigned NumParams,
+                                   const QualType *ParamTypes,
                                    llvm::SmallVectorImpl<QualType> &PTypes,
-                                   llvm::SmallVectorImpl<ParmVarDecl*> &PVars);
+                                   llvm::SmallVectorImpl<ParmVarDecl*> *PVars);
 
   /// \brief Transforms a single function-type parameter.  Return null
   /// on error.
@@ -3390,13 +3392,13 @@
 
 template<typename Derived>
 bool TreeTransform<Derived>::
-  TransformFunctionTypeParams(FunctionProtoTypeLoc TL,
-                              llvm::SmallVectorImpl<QualType> &PTypes,
-                              llvm::SmallVectorImpl<ParmVarDecl*> &PVars) {
-  FunctionProtoType *T = TL.getTypePtr();
-
-  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
-    if (ParmVarDecl *OldParm = TL.getArg(i)) {
+  TransformFunctionTypeParams(SourceLocation Loc,
+                              ParmVarDecl **Params, unsigned NumParams,
+                              const QualType *ParamTypes,
+                              llvm::SmallVectorImpl<QualType> &OutParamTypes,
+                              llvm::SmallVectorImpl<ParmVarDecl*> *PVars) {
+  for (unsigned i = 0; i != NumParams; ++i) {
+    if (ParmVarDecl *OldParm = Params[i]) {
       if (OldParm->isParameterPack()) {
         // We have a function parameter pack that may need to be expanded.
         llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
@@ -3428,8 +3430,9 @@
             if (!NewParm)
               return true;
             
-            PTypes.push_back(NewParm->getType());
-            PVars.push_back(NewParm);
+            OutParamTypes.push_back(NewParm->getType());
+            if (PVars)
+              PVars->push_back(NewParm);
           }
           
           // We're done with the pack expansion.
@@ -3445,14 +3448,15 @@
       if (!NewParm)
         return true;
       
-      PTypes.push_back(NewParm->getType());
-      PVars.push_back(NewParm);
+      OutParamTypes.push_back(NewParm->getType());
+      if (PVars)
+        PVars->push_back(NewParm);
       continue;
     }
 
     // Deal with the possibility that we don't have a parameter
     // declaration for this parameter.
-    QualType OldType = T->getArgType(i);
+    QualType OldType = ParamTypes[i];
     bool IsPackExpansion = false;
     if (const PackExpansionType *Expansion 
                                        = dyn_cast<PackExpansionType>(OldType)) {
@@ -3464,7 +3468,7 @@
       // Determine whether we should expand the parameter packs.
       bool ShouldExpand = false;
       unsigned NumExpansions = 0;
-      if (getDerived().TryExpandParameterPacks(TL.getBeginLoc(), SourceRange(),
+      if (getDerived().TryExpandParameterPacks(Loc, SourceRange(),
                                                Unexpanded.data(), 
                                                Unexpanded.size(),
                                                ShouldExpand, NumExpansions)) {
@@ -3480,8 +3484,9 @@
           if (NewType.isNull())
             return true;
 
-          PTypes.push_back(NewType);
-          PVars.push_back(0);
+          OutParamTypes.push_back(NewType);
+          if (PVars)
+            PVars->push_back(0);
         }
         
         // We're done with the pack expansion.
@@ -3502,8 +3507,9 @@
     if (IsPackExpansion)
       NewType = getSema().Context.getPackExpansionType(NewType);
       
-    PTypes.push_back(NewType);
-    PVars.push_back(0);
+    OutParamTypes.push_back(NewType);
+    if (PVars)
+      PVars->push_back(0);
   }
 
   return false;
@@ -3530,7 +3536,11 @@
   QualType ResultType;
 
   if (TL.getTrailingReturn()) {
-    if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls))
+    if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(), 
+                                                 TL.getParmArray(),
+                                                 TL.getNumArgs(),
+                                             TL.getTypePtr()->arg_type_begin(),                                                
+                                                 ParamTypes, &ParamDecls))
       return QualType();
 
     ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
@@ -3542,7 +3552,11 @@
     if (ResultType.isNull())
       return QualType();
 
-    if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls))
+    if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(), 
+                                                 TL.getParmArray(),
+                                                 TL.getNumArgs(),
+                                             TL.getTypePtr()->arg_type_begin(),                                                
+                                                 ParamTypes, &ParamDecls))
       return QualType();
   }
 

Added: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp?rev=122986&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp Thu Jan  6 18:20:55 2011
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// Metafunction to extract the Nth type from a set of types.
+template<unsigned N, typename ...Types> struct get_nth_type;
+
+template<unsigned N, typename Head, typename ...Tail>
+struct get_nth_type<N, Head, Tail...> : get_nth_type<N-1, Tail...> { };
+
+template<typename Head, typename ...Tail>
+struct get_nth_type<0, Head, Tail...> {
+  typedef Head type;
+};
+
+// Placeholder type  when get_nth_type fails.
+struct no_type {};
+
+template<unsigned N>
+struct get_nth_type<N> {
+  typedef no_type type;
+};
+
+template<typename ...Args>
+typename get_nth_type<0, Args...>::type first_arg(Args...);
+
+template<typename ...Args>
+typename get_nth_type<1, Args...>::type second_arg(Args...);
+
+// Test explicit specification of function template arguments.
+void test_explicit_spec_simple() {
+  int *ip1 = first_arg<int *>(0);
+  int *ip2 = first_arg<int *, float*>(0, 0);
+  float *fp1 = first_arg<float *, double*, int*>(0, 0, 0);
+}
+
+// Template argument deduction can extend the sequence of template
+// arguments corresponding to a template parameter pack, even when the
+// sequence contains explicitly specified template arguments.
+// FIXME: Actually test what this paragraph specifies.
+#if 0
+void test_explicit_spec_extension() {
+  int *ip1 = first_arg<int *>(0, 0);
+  int *ip2 = first_arg<int *, float*>(0, 0, 0, 0);
+  float *fp1 = first_arg<float *, double*, int*>(0, 0, 0);  
+  int i1 = second_arg<float *>(0, 0, 0);  
+}
+#endif
+

Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp?rev=122986&r1=122985&r2=122986&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp Thu Jan  6 18:20:55 2011
@@ -169,7 +169,8 @@
 }
 
 namespace PR6723 {
-  template<unsigned char C> void f(int (&a)[C]); // expected-note 2{{candidate template ignored}}
+  template<unsigned char C> void f(int (&a)[C]); // expected-note {{candidate template ignored}} \
+  // expected-note{{candidate function [with C = 0] not viable: no known conversion from 'int [512]' to 'int (&)[0]' for 1st argument}}
   void g() {
     int arr512[512];
     f(arr512); // expected-error{{no matching function for call}}





More information about the cfe-commits mailing list