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(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(*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 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(*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(*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(*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(*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(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(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 +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 struct A {};