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