aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-05 20:52:18 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-05 20:52:18 +0000
commitd53e16abd1dcaa2942d5183f48e7f63d0e75b35a (patch)
tree9511181c171a8ec025a39e323ea90958e4fc8058
parentb1fa3dc2f914aaa8b5a851c6b5115ec239d20495 (diff)
When we're converting deduced template arguments to the type of the
corresponding template parameter, make sure that prior converted template arguments are available for substitution. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122902 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp30
-rw-r--r--test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp27
2 files changed, 54 insertions, 3 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 5837ebd8e5..f6dacc7cea 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -1402,12 +1402,19 @@ static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
for (TemplateArgument::pack_iterator PA = Arg.pack_begin(),
PAEnd = Arg.pack_end();
PA != PAEnd; ++PA) {
+ // When converting the deduced template argument, append it to the
+ // general output list. We need to do this so that the template argument
+ // checking logic has all of the prior template arguments available.
DeducedTemplateArgument InnerArg(*PA);
InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template,
NTTPType, Info,
- InFunctionTemplate, PackedArgsBuilder))
+ InFunctionTemplate, Output))
return true;
+
+ // Move the converted template argument into our argument pack.
+ PackedArgsBuilder.push_back(Output.back());
+ Output.pop_back();
}
// Create the resulting argument pack.
@@ -1472,9 +1479,26 @@ FinishTemplateArgumentDeduction(Sema &S,
// corresponding non-type template parameter.
QualType NTTPType;
if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(Param))
+ = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
NTTPType = NTTP->getType();
-
+ if (NTTPType->isDependentType()) {
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Builder.data(), Builder.size());
+ NTTPType = S.SubstType(NTTPType,
+ MultiLevelTemplateArgumentList(TemplateArgs),
+ NTTP->getLocation(),
+ NTTP->getDeclName());
+ if (NTTPType.isNull()) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context,
+ Builder.data(),
+ Builder.size()));
+ return Sema::TDK_SubstitutionFailure;
+ }
+ }
+ }
+
if (ConvertDeducedTemplateArgument(S, Param, Deduced[I],
Partial, NTTPType, Info, false,
Builder)) {
diff --git a/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp b/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp
index 75181081ad..5c0eb74875 100644
--- a/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp
+++ b/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp
@@ -118,6 +118,33 @@ namespace Math {
}
}
+namespace ListMath {
+ template<typename T, T ... V> struct add;
+
+ template<typename T, T i, T ... V>
+ struct add<T, i, V...> {
+ static const T value = i + add<T, V...>::value;
+ };
+
+ template<typename T>
+ struct add<T> {
+ static const T value = T();
+ };
+
+ template<typename T, T ... V>
+ struct List {
+ struct sum {
+ static const T value = add<T, V...>::value;
+ };
+ };
+
+ template<int ... V>
+ struct ListI : public List<int, V...> {
+ };
+
+ int check0[ListI<1, 2, 3>::sum::value == 6? 1 : -1];
+}
+
namespace Indices {
template<unsigned I, unsigned N, typename IntTuple>
struct build_indices_impl;