[cfe-commits] r123493 - in /cfe/trunk: include/clang/AST/TemplateBase.h lib/AST/ASTContext.cpp lib/AST/ASTImporter.cpp lib/AST/DeclTemplate.cpp lib/AST/TemplateBase.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
Douglas Gregor
dgregor at apple.com
Fri Jan 14 15:41:42 PST 2011
Author: dgregor
Date: Fri Jan 14 17:41:42 2011
New Revision: 123493
URL: http://llvm.org/viewvc/llvm-project?rev=123493&view=rev
Log:
Teach template template argument pack expansions to keep track of the
number of expansions, when we know it, and propagate that information
through Sema.
Modified:
cfe/trunk/include/clang/AST/TemplateBase.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/ASTImporter.cpp
cfe/trunk/lib/AST/DeclTemplate.cpp
cfe/trunk/lib/AST/TemplateBase.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
Modified: cfe/trunk/include/clang/AST/TemplateBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateBase.h?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TemplateBase.h (original)
+++ cfe/trunk/include/clang/AST/TemplateBase.h Fri Jan 14 17:41:42 2011
@@ -80,8 +80,14 @@
const TemplateArgument *Args;
unsigned NumArgs;
} Args;
+ struct {
+ void *Name;
+ unsigned NumExpansions;
+ } TemplateArg;
};
+ TemplateArgument(TemplateName, bool); // DO NOT USE
+
public:
/// \brief Construct an empty, invalid template argument.
TemplateArgument() : Kind(Null), TypeOrValue(0) { }
@@ -107,8 +113,7 @@
Integer.Type = Type.getAsOpaquePtr();
}
- /// \brief Construct a template argument that is a template or a pack
- /// expansion of templates.
+ /// \brief Construct a template argument that is a template.
///
/// This form of template argument is generally used for template template
/// parameters. However, the template name could be a dependent template
@@ -116,13 +121,33 @@
/// is taken.
///
/// \param Name The template name.
- /// \param PackExpansion Whether this template argument is a pack expansion.
- TemplateArgument(TemplateName Name, bool PackExpansion = false)
- : Kind(PackExpansion? TemplateExpansion : Template)
+ TemplateArgument(TemplateName Name) : Kind(Template)
{
- TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
+ TemplateArg.Name = Name.getAsVoidPointer();
+ TemplateArg.NumExpansions = 0;
}
-
+
+ /// \brief Construct a template argument that is a template pack expansion.
+ ///
+ /// This form of template argument is generally used for template template
+ /// parameters. However, the template name could be a dependent template
+ /// name that ends up being instantiated to a function template whose address
+ /// is taken.
+ ///
+ /// \param Name The template name.
+ ///
+ /// \param NumExpansions The number of expansions that will be generated by
+ /// instantiating
+ TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions)
+ : Kind(TemplateExpansion)
+ {
+ TemplateArg.Name = Name.getAsVoidPointer();
+ if (NumExpansions)
+ TemplateArg.NumExpansions = *NumExpansions + 1;
+ else
+ TemplateArg.NumExpansions = 0;
+ }
+
/// \brief Construct a template argument that is an expression.
///
/// This form of template argument only occurs in template argument
@@ -151,6 +176,9 @@
} else if (Kind == Pack) {
Args.NumArgs = Other.Args.NumArgs;
Args.Args = Other.Args.Args;
+ } else if (Kind == Template || Kind == TemplateExpansion) {
+ TemplateArg.Name = Other.TemplateArg.Name;
+ TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
} else
TypeOrValue = Other.TypeOrValue;
}
@@ -177,6 +205,9 @@
} else if (Other.Kind == Pack) {
Args.NumArgs = Other.Args.NumArgs;
Args.Args = Other.Args.Args;
+ } else if (Kind == Template || Kind == TemplateExpansion) {
+ TemplateArg.Name = Other.TemplateArg.Name;
+ TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
} else {
TypeOrValue = Other.TypeOrValue;
}
@@ -234,8 +265,7 @@
if (Kind != Template)
return TemplateName();
- return TemplateName::getFromVoidPointer(
- reinterpret_cast<void*>(TypeOrValue));
+ return TemplateName::getFromVoidPointer(TemplateArg.Name);
}
/// \brief Retrieve the template argument as a template name; if the argument
@@ -244,10 +274,13 @@
if (Kind != Template && Kind != TemplateExpansion)
return TemplateName();
- return TemplateName::getFromVoidPointer(
- reinterpret_cast<void*>(TypeOrValue));
+ return TemplateName::getFromVoidPointer(TemplateArg.Name);
}
+ /// \brief Retrieve the number of expansions that a template template argument
+ /// expansion will produce, if known.
+ llvm::Optional<unsigned> getNumTemplateExpansions() const;
+
/// \brief Retrieve the template argument as an integral value.
llvm::APSInt *getAsIntegral() {
if (Kind != Integral)
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jan 14 17:41:42 2011
@@ -2768,7 +2768,7 @@
case TemplateArgument::TemplateExpansion:
return TemplateArgument(getCanonicalTemplateName(
Arg.getAsTemplateOrTemplatePattern()),
- true);
+ Arg.getNumTemplateExpansions());
case TemplateArgument::Integral:
return TemplateArgument(*Arg.getAsIntegral(),
Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Fri Jan 14 17:41:42 2011
@@ -1823,7 +1823,7 @@
if (ToTemplate.isNull())
return TemplateArgument();
- return TemplateArgument(ToTemplate, true);
+ return TemplateArgument(ToTemplate, From.getNumTemplateExpansions());
}
case TemplateArgument::Expression:
Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Fri Jan 14 17:41:42 2011
@@ -337,7 +337,10 @@
Arg = TemplateArgument(E);
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
- Arg = TemplateArgument(TemplateName(TTP), TTP->isParameterPack());
+ if (TTP->isParameterPack())
+ Arg = TemplateArgument(TemplateName(TTP), llvm::Optional<unsigned>());
+ else
+ Arg = TemplateArgument(TemplateName(TTP));
}
if ((*Param)->isTemplateParameterPack())
Modified: cfe/trunk/lib/AST/TemplateBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateBase.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TemplateBase.cpp (original)
+++ cfe/trunk/lib/AST/TemplateBase.cpp Fri Jan 14 17:41:42 2011
@@ -135,6 +135,14 @@
return false;
}
+llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
+ assert(Kind == TemplateExpansion);
+ if (TemplateArg.NumExpansions)
+ return TemplateArg.NumExpansions - 1;
+
+ return llvm::Optional<unsigned>();
+}
+
void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context) const {
ID.AddInteger(Kind);
@@ -223,7 +231,7 @@
return cast<PackExpansionExpr>(getAsExpr())->getPattern();
case TemplateExpansion:
- return TemplateArgument(getAsTemplateOrTemplatePattern(), false);
+ return TemplateArgument(getAsTemplateOrTemplatePattern());
case Declaration:
case Integral:
@@ -389,8 +397,8 @@
}
case TemplateArgument::TemplateExpansion:
- // FIXME: Variadic templates num expansions
Ellipsis = getTemplateEllipsisLoc();
+ NumExpansions = Argument.getNumTemplateExpansions();
return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
getTemplateQualifierRange(),
getTemplateNameLoc());
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Jan 14 17:41:42 2011
@@ -467,8 +467,12 @@
case ParsedTemplateArgument::Template: {
TemplateName Template = Arg.getAsTemplate().get();
- return TemplateArgumentLoc(TemplateArgument(Template,
- Arg.getEllipsisLoc().isValid()),
+ TemplateArgument TArg;
+ if (Arg.getEllipsisLoc().isValid())
+ TArg = TemplateArgument(Template, llvm::Optional<unsigned int>());
+ else
+ TArg = Template;
+ return TemplateArgumentLoc(TArg,
Arg.getScopeSpec().getRange(),
Arg.getLocation(),
Arg.getEllipsisLoc());
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Jan 14 17:41:42 2011
@@ -809,11 +809,8 @@
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
- if (getSema().ArgumentPackSubstitutionIndex == -1) {
- // FIXME: Variadic templates fun case.
- getSema().Diag(Loc, diag::err_pack_expansion_mismatch_unsupported);
+ if (getSema().ArgumentPackSubstitutionIndex == -1)
return 0;
- }
assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Jan 14 17:41:42 2011
@@ -2188,7 +2188,7 @@
case TemplateArgument::Template:
return TemplateArgumentLoc(TemplateArgument(
Pattern.getArgument().getAsTemplate(),
- true),
+ NumExpansions),
Pattern.getTemplateQualifierRange(),
Pattern.getTemplateNameLoc(),
EllipsisLoc);
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Jan 14 17:41:42 2011
@@ -4290,9 +4290,13 @@
return TemplateArgument(Value, T);
}
case TemplateArgument::Template:
+ return TemplateArgument(ReadTemplateName(Record, Idx));
case TemplateArgument::TemplateExpansion: {
TemplateName Name = ReadTemplateName(Record, Idx);
- return TemplateArgument(Name, Kind == TemplateArgument::TemplateExpansion);
+ llvm::Optional<unsigned> NumTemplateExpansions;
+ if (unsigned NumExpansions = Record[Idx++])
+ NumTemplateExpansions = NumExpansions - 1;
+ return TemplateArgument(Name, NumTemplateExpansions);
}
case TemplateArgument::Expression:
return TemplateArgument(ReadExpr(F));
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=123493&r1=123492&r2=123493&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Jan 14 17:41:42 2011
@@ -3231,8 +3231,14 @@
AddTypeRef(Arg.getIntegralType(), Record);
break;
case TemplateArgument::Template:
+ AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
+ break;
case TemplateArgument::TemplateExpansion:
AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
+ if (llvm::Optional<unsigned> NumExpansions = Arg.getNumTemplateExpansions())
+ Record.push_back(*NumExpansions + 1);
+ else
+ Record.push_back(0);
break;
case TemplateArgument::Expression:
AddStmt(Arg.getAsExpr());
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=123493&r1=123492&r2=123493&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 17:41:42 2011
@@ -88,4 +88,42 @@
pair<int, unsigned int>,
pair<long, unsigned long>)
>::value == 1? 1 : -1];
+
+ template<typename T, typename U>
+ struct some_function_object {
+ template<typename>
+ struct result_of;
+ };
+
+ template<template<class> class...> struct metafun_tuple { };
+
+ template<typename ...Types1>
+ struct X3 {
+ template<typename, typename> struct Inner {
+ static const unsigned value = 0;
+ };
+
+ template<typename ...Types2>
+ struct Inner<tuple<pair<Types1, Types2>...>,
+ metafun_tuple<some_function_object<Types1, Types2>::template result_of...> > {
+ static const unsigned value = 1;
+ };
+ };
+
+ int check6[X3<short, int, long>::Inner<tuple<pair<short, unsigned short>,
+ pair<int, unsigned int>,
+ pair<long, unsigned long>>,
+ metafun_tuple<
+ some_function_object<short, unsigned short>::result_of,
+ some_function_object<int, unsigned int>::result_of,
+ some_function_object<long, unsigned long>::result_of>
+ >::value == 1? 1 : -1];
+ int check7[X3<short, int>::Inner<tuple<pair<short, unsigned short>,
+ pair<int, unsigned int>,
+ pair<long, unsigned long>>,
+ metafun_tuple<
+ some_function_object<short, unsigned short>::result_of,
+ some_function_object<int, unsigned int>::result_of,
+ some_function_object<long, unsigned long>::result_of>
+ >::value == 0? 1 : -1];
}
More information about the cfe-commits
mailing list