[cfe-commits] r123488 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/TreeTransform.h test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp

Douglas Gregor dgregor at apple.com
Fri Jan 14 14:40:04 PST 2011


Author: dgregor
Date: Fri Jan 14 16:40:04 2011
New Revision: 123488

URL: http://llvm.org/viewvc/llvm-project?rev=123488&view=rev
Log:
Handle substitutions into function parameter packs whose patterns
contain multiple parameter packs at different levels.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=123488&r1=123487&r2=123488&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jan 14 16:40:04 2011
@@ -3935,7 +3935,8 @@
                                         SourceLocation Loc,
                                         DeclarationName Entity);
   ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
-                            const MultiLevelTemplateArgumentList &TemplateArgs);
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                                llvm::Optional<unsigned> NumExpansions);
   bool SubstParmTypes(SourceLocation Loc, 
                       ParmVarDecl **Params, unsigned NumParams,
                       const MultiLevelTemplateArgumentList &TemplateArgs,

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=123488&r1=123487&r2=123488&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Jan 14 16:40:04 2011
@@ -705,7 +705,8 @@
 
     QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
                                         FunctionProtoTypeLoc TL);
-    ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm);
+    ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                      llvm::Optional<unsigned> NumExpansions);
 
     /// \brief Transforms a template type parameter type by performing
     /// substitution of the corresponding template type argument.
@@ -1000,8 +1001,10 @@
 }
 
 ParmVarDecl *
-TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm) {
-  return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs);
+TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                       llvm::Optional<unsigned> NumExpansions) {
+  return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs,
+                                  NumExpansions);
 }
 
 QualType
@@ -1241,7 +1244,8 @@
 }
 
 ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, 
-                          const MultiLevelTemplateArgumentList &TemplateArgs) {
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                                    llvm::Optional<unsigned> NumExpansions) {
   TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
   TypeSourceInfo *NewDI = 0;
   
@@ -1260,9 +1264,8 @@
       // We still have unexpanded parameter packs, which means that
       // our function parameter is still a function parameter pack.
       // Therefore, make its type a pack expansion type.
-      // FIXME: Variadic templates num expansions.
       NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(),
-                                 llvm::Optional<unsigned>());
+                                 NumExpansions);
     }
   } else {
     NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(), 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=123488&r1=123487&r2=123488&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Jan 14 16:40:04 2011
@@ -1425,7 +1425,7 @@
 }
 
 ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
-  return SemaRef.SubstParmVarDecl(D, TemplateArgs);
+  return SemaRef.SubstParmVarDecl(D, TemplateArgs, llvm::Optional<unsigned>());
 }
 
 Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=123488&r1=123487&r2=123488&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Jan 14 16:40:04 2011
@@ -494,7 +494,8 @@
 
   /// \brief Transforms a single function-type parameter.  Return null
   /// on error.
-  ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm);
+  ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                        llvm::Optional<unsigned> NumExpansions);
 
   QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
 
@@ -3473,9 +3474,38 @@
 
 template<typename Derived>
 ParmVarDecl *
-TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm) {
+TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                       llvm::Optional<unsigned> NumExpansions) {
   TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
-  TypeSourceInfo *NewDI = getDerived().TransformType(OldDI);
+  TypeSourceInfo *NewDI = 0;
+  
+  if (NumExpansions && isa<PackExpansionType>(OldDI->getType())) {
+    // If we're substituting into a pack expansion type and we know the 
+    TypeLoc OldTL = OldDI->getTypeLoc();
+    PackExpansionTypeLoc OldExpansionTL = cast<PackExpansionTypeLoc>(OldTL);
+    
+    TypeLocBuilder TLB;
+    TypeLoc NewTL = OldDI->getTypeLoc();
+    TLB.reserve(NewTL.getFullDataSize());
+    
+    QualType Result = getDerived().TransformType(TLB, 
+                                               OldExpansionTL.getPatternLoc());
+    if (Result.isNull())
+      return 0;
+   
+    Result = RebuildPackExpansionType(Result, 
+                                OldExpansionTL.getPatternLoc().getSourceRange(), 
+                                      OldExpansionTL.getEllipsisLoc(),
+                                      NumExpansions);
+    if (Result.isNull())
+      return 0;
+    
+    PackExpansionTypeLoc NewExpansionTL
+      = TLB.push<PackExpansionTypeLoc>(Result);
+    NewExpansionTL.setEllipsisLoc(OldExpansionTL.getEllipsisLoc());
+    NewDI = TLB.getTypeSourceInfo(SemaRef.Context, Result);
+  } else
+    NewDI = getDerived().TransformType(OldDI);
   if (!NewDI)
     return 0;
 
@@ -3502,6 +3532,7 @@
                               llvm::SmallVectorImpl<ParmVarDecl*> *PVars) {
   for (unsigned i = 0; i != NumParams; ++i) {
     if (ParmVarDecl *OldParm = Params[i]) {
+      llvm::Optional<unsigned> NumExpansions;
       if (OldParm->isParameterPack()) {
         // We have a function parameter pack that may need to be expanded.
         llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
@@ -3515,7 +3546,9 @@
         // Determine whether we should expand the parameter packs.
         bool ShouldExpand = false;
         bool RetainExpansion = false;
-        llvm::Optional<unsigned> NumExpansions;
+        llvm::Optional<unsigned> OrigNumExpansions
+          = ExpansionTL.getTypePtr()->getNumExpansions();
+        NumExpansions = OrigNumExpansions;
         if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
                                                  Pattern.getSourceRange(),
                                                  Unexpanded.data(), 
@@ -3533,7 +3566,8 @@
           for (unsigned I = 0; I != *NumExpansions; ++I) {
             Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
             ParmVarDecl *NewParm 
-              = getDerived().TransformFunctionTypeParam(OldParm);
+              = getDerived().TransformFunctionTypeParam(OldParm,
+                                                        OrigNumExpansions);
             if (!NewParm)
               return true;
             
@@ -3547,7 +3581,8 @@
           if (RetainExpansion) {
             ForgetPartiallySubstitutedPackRAII Forget(getDerived());
             ParmVarDecl *NewParm 
-              = getDerived().TransformFunctionTypeParam(OldParm);
+              = getDerived().TransformFunctionTypeParam(OldParm,
+                                                        OrigNumExpansions);
             if (!NewParm)
               return true;
             
@@ -3564,9 +3599,9 @@
         // expansion.
       }
       
-      // FIXME: Variadic templates num expansions
       Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
-      ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm);
+      ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm,
+                                                                 NumExpansions);
       if (!NewParm)
         return true;
       
@@ -7053,7 +7088,8 @@
   for (BlockDecl::param_const_iterator P = BD->param_begin(),
        EN = BD->param_end(); P != EN; ++P) {
     ParmVarDecl *OldParm = (*P);
-    ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm);
+    ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm,
+                                                   llvm::Optional<unsigned>());
     QualType NewType = NewParm->getType();
     Params.push_back(NewParm);
     ParamTypes.push_back(NewParm->getType());

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=123488&r1=123487&r2=123488&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 16:40:04 2011
@@ -66,4 +66,26 @@
                                      sizeof(int) + sizeof(unsigned int),
                                      sizeof(long) + sizeof(unsigned long)>
                                        >::value == 0? 1 : -1];
+
+  template<typename ...Types>
+  struct X2 {
+    template<typename> struct Inner {
+      static const unsigned value = 1;
+    };
+
+    template<typename R, typename ...YTypes>
+    struct Inner<R(pair<Types, YTypes>...)> {
+      static const unsigned value = sizeof...(Types) - sizeof...(YTypes);
+    };
+  };
+
+  int check4[X2<short, int, long>::Inner<int(pair<short, unsigned short>,
+                                            pair<int, unsigned int>,
+                                            pair<long, unsigned long>)
+                                     >::value == 0? 1 : -1];
+
+  int check5[X2<short, int>::Inner<int(pair<short, unsigned short>,
+                                       pair<int, unsigned int>,
+                                       pair<long, unsigned long>)
+                                     >::value == 1? 1 : -1]; 
 }





More information about the cfe-commits mailing list