Hi rsmith, rnk,

The MS mangling scheme apparently has separate manglings for type and
non-type parameter packs when they are empty.  Add state to
TemplateArgument to track this.

http://reviews.llvm.org/D4792

Files:
  include/clang/AST/TemplateBase.h
  lib/AST/ASTContext.cpp
  lib/AST/ASTImporter.cpp
  lib/AST/DeclTemplate.cpp
  lib/AST/ExprCXX.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/TemplateBase.cpp
  lib/AST/TemplateName.cpp
  lib/AST/Type.cpp
  lib/Sema/SemaTemplate.cpp
  lib/Sema/SemaTemplateDeduction.cpp
  lib/Serialization/ASTReader.cpp
  test/CodeGenCXX/mangle-ms-cxx11.cpp
Index: include/clang/AST/TemplateBase.h
===================================================================
--- include/clang/AST/TemplateBase.h
+++ include/clang/AST/TemplateBase.h
@@ -94,7 +94,8 @@
   };
   struct A {
     unsigned Kind;
-    unsigned NumArgs;
+    unsigned NumArgs : 31;
+    unsigned IsNonType : 1;
     const TemplateArgument *Args;
   };
   struct TA {
@@ -198,22 +199,25 @@
   ///
   /// We assume that storage for the template arguments provided
   /// outlives the TemplateArgument itself.
-  TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) {
+  TemplateArgument(const TemplateArgument *Args, unsigned NumArgs,
+                   bool IsNonType) {
+    assert(NumArgs <= ((1U << 31) - 1) && "too many template args!");
     this->Args.Kind = Pack;
     this->Args.Args = Args;
     this->Args.NumArgs = NumArgs;
+    this->Args.IsNonType = IsNonType;
   }
 
-  static TemplateArgument getEmptyPack() {
-    return TemplateArgument((TemplateArgument*)nullptr, 0);
+  static TemplateArgument getEmptyPack(bool IsNonType) {
+    return TemplateArgument((TemplateArgument*)nullptr, 0, IsNonType);
   }
 
   /// \brief Create a new template argument pack by copying the given set of
   /// template arguments.
   static TemplateArgument CreatePackCopy(ASTContext &Context,
                                          const TemplateArgument *Args,
-                                         unsigned NumArgs);
-  
+                                         unsigned NumArgs, bool IsNonType);
+
   /// \brief Return the kind of stored template argument.
   ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
 
@@ -347,6 +351,11 @@
     return ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs);
   }
 
+  bool isPackNonType() const {
+    assert(getKind() == Pack);
+    return Args.IsNonType;
+  }
+
   /// \brief Determines whether two template arguments are superficially the
   /// same.
   bool structurallyEquals(const TemplateArgument &Other) const;
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -4139,7 +4139,7 @@
            A != AEnd; (void)++A, ++Idx)
         CanonArgs[Idx] = getCanonicalTemplateArgument(*A);
 
-      return TemplateArgument(CanonArgs, Arg.pack_size());
+      return TemplateArgument(CanonArgs, Arg.pack_size(), Arg.isPackNonType());
     }
   }
 
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -2136,7 +2136,7 @@
     TemplateArgument *ToArgs 
       = new (Importer.getToContext()) TemplateArgument[ToPack.size()];
     std::copy(ToPack.begin(), ToPack.end(), ToArgs);
-    return TemplateArgument(ToArgs, ToPack.size());
+    return TemplateArgument(ToArgs, ToPack.size(), From.isPackNonType());
   }
   }
   
Index: lib/AST/DeclTemplate.cpp
===================================================================
--- lib/AST/DeclTemplate.cpp
+++ lib/AST/DeclTemplate.cpp
@@ -208,8 +208,9 @@
     }
     
     if ((*Param)->isTemplateParameterPack())
-      Arg = TemplateArgument::CreatePackCopy(Context, &Arg, 1);
-    
+      Arg = TemplateArgument::CreatePackCopy(
+          Context, &Arg, 1, isa<NonTypeTemplateParmDecl>(*Param));
+
     *Args++ = Arg;
   }
 }
Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp
+++ lib/AST/ExprCXX.cpp
@@ -1432,7 +1432,7 @@
     NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { }
 
 TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
-  return TemplateArgument(Arguments, NumArguments);
+  return TemplateArgument(Arguments, NumArguments, /*IsNonType=*/true);
 }
 
 FunctionParmPackExpr::FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -1172,7 +1172,10 @@
   case TemplateArgument::Pack: {
     ArrayRef<TemplateArgument> TemplateArgs = TA.getPackAsArray();
     if (TemplateArgs.empty()) {
-      Out << "$S";
+      if (TA.isPackNonType())
+        Out << "$S";
+      else
+        Out << "$$$V";
     } else {
       for (const TemplateArgument &PA : TemplateArgs)
         mangleTemplateArg(TD, PA);
Index: lib/AST/TemplateBase.cpp
===================================================================
--- lib/AST/TemplateBase.cpp
+++ lib/AST/TemplateBase.cpp
@@ -75,13 +75,14 @@
 
 TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
                                                   const TemplateArgument *Args,
-                                                  unsigned NumArgs) {
+                                                  unsigned NumArgs,
+                                                  bool IsNonType) {
   if (NumArgs == 0)
-    return getEmptyPack();
+    return getEmptyPack(IsNonType);
   
   TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
   std::copy(Args, Args + NumArgs, Storage);
-  return TemplateArgument(Storage, NumArgs);
+  return TemplateArgument(Storage, NumArgs, IsNonType);
 }
 
 bool TemplateArgument::isDependent() const {
Index: lib/AST/TemplateName.cpp
===================================================================
--- lib/AST/TemplateName.cpp
+++ lib/AST/TemplateName.cpp
@@ -24,7 +24,7 @@
 
 TemplateArgument 
 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
-  return TemplateArgument(Arguments, size());
+  return TemplateArgument(Arguments, size(), /*IsNonType=*/false);
 }
 
 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
@@ -40,7 +40,8 @@
 
 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
                                                    ASTContext &Context) {
-  Profile(ID, Context, Parameter, TemplateArgument(Arguments, size()));
+  Profile(ID, Context, Parameter,
+          TemplateArgument(Arguments, size(), /*IsNonType=*/false));
 }
 
 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, 
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -1941,7 +1941,7 @@
 }
 
 TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
-  return TemplateArgument(Arguments, NumArguments);
+  return TemplateArgument(Arguments, NumArguments, /*IsNonType=*/false);
 }
 
 void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) {
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -3662,10 +3662,9 @@
       if (*Expansions == ArgumentPack.size()) {
         // We're done with this parameter pack. Pack up its arguments and add
         // them to the list.
-        Converted.push_back(
-          TemplateArgument::CreatePackCopy(Context,
-                                           ArgumentPack.data(),
-                                           ArgumentPack.size()));
+        Converted.push_back(TemplateArgument::CreatePackCopy(
+            Context, ArgumentPack.data(), ArgumentPack.size(),
+            isa<NonTypeTemplateParmDecl>(*Param)));
         ArgumentPack.clear();
 
         // This argument is assigned to the next parameter.
@@ -3747,10 +3746,9 @@
 
         // Push the argument pack onto the list of converted arguments.
         if (InFinalParameterPack) {
-          Converted.push_back(
-            TemplateArgument::CreatePackCopy(Context,
-                                             ArgumentPack.data(),
-                                             ArgumentPack.size()));
+          Converted.push_back(TemplateArgument::CreatePackCopy(
+              Context, ArgumentPack.data(), ArgumentPack.size(),
+              isa<NonTypeTemplateParmDecl>(*Param)));
           ArgumentPack.clear();
         }
 
@@ -3763,10 +3761,10 @@
     // If we're checking a partial template argument list, we're done.
     if (PartialTemplateArgs) {
       if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty())
-        Converted.push_back(TemplateArgument::CreatePackCopy(Context,
-                                                         ArgumentPack.data(),
-                                                         ArgumentPack.size()));
-        
+        Converted.push_back(TemplateArgument::CreatePackCopy(
+            Context, ArgumentPack.data(), ArgumentPack.size(),
+            isa<NonTypeTemplateParmDecl>(*Param)));
+
       return false;
     }
 
@@ -3782,9 +3780,9 @@
       if (Param + 1 != ParamEnd)
         return true;
 
-      Converted.push_back(TemplateArgument::CreatePackCopy(Context,
-                                                       ArgumentPack.data(),
-                                                       ArgumentPack.size()));
+      Converted.push_back(TemplateArgument::CreatePackCopy(
+          Context, ArgumentPack.data(), ArgumentPack.size(),
+          isa<NonTypeTemplateParmDecl>(*Param)));
       ArgumentPack.clear();
 
       ++Param;
Index: lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- lib/Sema/SemaTemplateDeduction.cpp
+++ lib/Sema/SemaTemplateDeduction.cpp
@@ -678,7 +678,7 @@
   /// \brief Finish template argument deduction for a set of argument packs,
   /// producing the argument packs and checking for consistency with prior
   /// deductions.
-  Sema::TemplateDeductionResult finish(bool HasAnyArguments) {
+  Sema::TemplateDeductionResult finish(bool HasAnyArguments, bool IsNonType) {
     // Build argument packs for each of the parameter packs expanded by this
     // pack expansion.
     for (auto &Pack : Packs) {
@@ -699,13 +699,14 @@
         Pack.DeferredDeduction = TemplateArgument();
       } else if (Pack.New.empty()) {
         // If we deduced an empty argument pack, create it now.
-        NewPack = DeducedTemplateArgument(TemplateArgument::getEmptyPack());
+        NewPack =
+            DeducedTemplateArgument(TemplateArgument::getEmptyPack(IsNonType));
       } else {
         TemplateArgument *ArgumentPack =
             new (S.Context) TemplateArgument[Pack.New.size()];
         std::copy(Pack.New.begin(), Pack.New.end(), ArgumentPack);
         NewPack = DeducedTemplateArgument(
-            TemplateArgument(ArgumentPack, Pack.New.size()),
+            TemplateArgument(ArgumentPack, Pack.New.size(), IsNonType),
             Pack.New[0].wasDeducedFromArrayBound());
       }
 
@@ -879,7 +880,8 @@
 
     // Build argument packs for each of the parameter packs expanded by this
     // pack expansion.
-    if (auto Result = PackScope.finish(HasAnyArguments))
+    if (auto Result = PackScope.finish(HasAnyArguments,
+                                       /*IsNonType=*/false))
       return Result;
   }
 
@@ -1928,7 +1930,15 @@
 
     // Build argument packs for each of the parameter packs expanded by this
     // pack expansion.
-    if (auto Result = PackScope.finish(HasAnyArguments))
+    TemplateArgument::ArgKind AK = Params[ParamIdx].getKind();
+    bool IsNonType;
+    if (AK == TemplateArgument::Pack)
+      IsNonType = Params[ParamIdx].isPackNonType();
+    else
+      IsNonType = AK == TemplateArgument::Integral ||
+                  AK == TemplateArgument::NullPtr ||
+                  AK == TemplateArgument::Declaration;
+    if (auto Result = PackScope.finish(HasAnyArguments, IsNonType))
       return Result;
   }
 
@@ -2114,9 +2124,9 @@
     }
 
     // Create the resulting argument pack.
-    Output.push_back(TemplateArgument::CreatePackCopy(S.Context,
-                                                      PackedArgsBuilder.data(),
-                                                     PackedArgsBuilder.size()));
+    Output.push_back(TemplateArgument::CreatePackCopy(
+        S.Context, PackedArgsBuilder.data(), PackedArgsBuilder.size(),
+        Arg.isPackNonType()));
     return false;
   }
 
@@ -2885,13 +2895,16 @@
           CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
                                                              &NumExplicitArgs)
             == Param) {
-        Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
+        Builder.push_back(
+            TemplateArgument(ExplicitArgs, NumExplicitArgs,
+                             isa<NonTypeTemplateParmDecl>(Param)));
 
         // Forget the partially-substituted pack; it's substitution is now
         // complete.
         CurrentInstantiationScope->ResetPartiallySubstitutedPack();
       } else {
-        Builder.push_back(TemplateArgument::getEmptyPack());
+        Builder.push_back(TemplateArgument::getEmptyPack(
+            isa<NonTypeTemplateParmDecl>(Param)));
       }
       continue;
     }
@@ -3483,7 +3496,7 @@
 
     // Build argument packs for each of the parameter packs expanded by this
     // pack expansion.
-    if (auto Result = PackScope.finish(HasAnyArguments))
+    if (auto Result = PackScope.finish(HasAnyArguments, /*IsNonType=*/false))
       return Result;
 
     // After we've matching against a parameter pack, we're done.
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -7637,7 +7637,8 @@
     TemplateArgument *Args = new (Context) TemplateArgument[NumArgs];
     for (unsigned I = 0; I != NumArgs; ++I)
       Args[I] = ReadTemplateArgument(F, Record, Idx);
-    return TemplateArgument(Args, NumArgs);
+    // FIXME: this is wrong!
+    return TemplateArgument(Args, NumArgs, /*IsNonType=*/false);
   }
   }
 
Index: test/CodeGenCXX/mangle-ms-cxx11.cpp
===================================================================
--- test/CodeGenCXX/mangle-ms-cxx11.cpp
+++ test/CodeGenCXX/mangle-ms-cxx11.cpp
@@ -140,6 +140,12 @@
 template void templ_fun_with_pack<>();
 // CHECK-DAG: @"\01??$templ_fun_with_pack@$S@@YAXXZ"
 
+template <typename...>
+void templ_fun_with_type_pack() {}
+
+template void templ_fun_with_type_pack<>();
+// CHECK-DAG: @"\01??$templ_fun_with_type_pack@$$$V@@YAXXZ"
+
 namespace PR20047 {
 template <typename T>
 struct A {};
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to