aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-11 01:52:23 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-11 01:52:23 +0000
commit7d5c0c1273bdc1cb3dff1cb5a62d07b1439e82c7 (patch)
tree978f21cec876212e836022e75a4d1708d5aa4e88
parent4d484a753f38a231e17c364cba496f8c6d2d771e (diff)
Implement the last bullet of [temp.deduct.type]p5 and part of the last
sentence of [temp.deduct.call]p1, both of which concern the non-deducibility of parameter packs not at the end of a parameter-type-list. The latter isn't fully implemented yet; see the new FIXME. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123210 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/Decl.cpp13
-rw-r--r--lib/AST/Type.cpp6
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp14
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp2
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp15
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp22
6 files changed, 70 insertions, 2 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 24fc45f4be..786f28a60d 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1444,6 +1444,9 @@ void FunctionDecl::setParams(ASTContext &C,
/// function parameters, if some of the parameters have default
/// arguments (in C++) or the last parameter is a parameter pack.
unsigned FunctionDecl::getMinRequiredArguments() const {
+ if (!getASTContext().getLangOptions().CPlusPlus)
+ return getNumParams();
+
unsigned NumRequiredArgs = getNumParams();
// If the last parameter is a parameter pack, we don't need an argument for
@@ -1458,6 +1461,16 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
getParamDecl(NumRequiredArgs-1)->hasDefaultArg())
--NumRequiredArgs;
+ // We might have parameter packs before the end. These can't be deduced,
+ // but they can still handle multiple arguments.
+ unsigned ArgIdx = NumRequiredArgs;
+ while (ArgIdx > 0) {
+ if (getParamDecl(ArgIdx - 1)->isParameterPack())
+ NumRequiredArgs = ArgIdx;
+
+ --ArgIdx;
+ }
+
return NumRequiredArgs;
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 708c344bc7..cc0d7f16e7 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1144,7 +1144,11 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
}
bool FunctionProtoType::isTemplateVariadic() const {
- return getNumArgs() && isa<PackExpansionType>(getArgType(getNumArgs() - 1));
+ for (unsigned ArgIdx = getNumArgs(); ArgIdx; --ArgIdx)
+ if (isa<PackExpansionType>(getArgType(ArgIdx - 1)))
+ return true;
+
+ return false;
}
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 842ad5c188..1bc24db27a 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -666,6 +666,13 @@ DeduceTemplateArguments(Sema &S,
continue;
}
+ // C++0x [temp.deduct.type]p5:
+ // The non-deduced contexts are:
+ // - A function parameter pack that does not occur at the end of the
+ // parameter-declaration-clause.
+ if (ParamIdx + 1 < NumParams)
+ return Sema::TDK_Success;
+
// C++0x [temp.deduct.type]p10:
// If the parameter-declaration corresponding to Pi is a function
// parameter pack, then the type of its declarator- id is compared with
@@ -2483,7 +2490,12 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// the call is compared with the type P of the declarator-id of the
// function parameter pack. Each comparison deduces template arguments
// for subsequent positions in the template parameter packs expanded by
- // the function parameter pack.
+ // the function parameter pack. For a function parameter pack that does
+ // not occur at the end of the parameter-declaration-list, the type of
+ // the parameter pack is a non-deduced context.
+ if (ParamIdx + 1 < NumParams)
+ break;
+
QualType ParamPattern = ParamExpansion->getPattern();
llvm::SmallVector<unsigned, 2> PackIndices;
{
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c29ff865b2..50b24dc41d 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1894,6 +1894,8 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
// Parameter pack: make the instantiation an argument pack.
SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(
OldParam);
+ // FIXME: Variadic templates. Figure out how many arguments are in the
+ // expansion of OldParam, so we don't gobble all of the arguments here.
while (NewIdx < NumNewParams) {
ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
Params.push_back(NewParam);
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp
index 46a6b1e081..4b480ddd3f 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp
@@ -74,3 +74,18 @@ void test_pair_deduction(int *ip, float *fp, double *dp) {
first_arg_pair(make_pair(ip, 17), 16); // expected-error{{no matching function for call to 'first_arg_pair'}}
}
+
+// For a function parameter pack that does not occur at the end of the
+// parameter-declaration-list, the type of the parameter pack is a
+// non-deduced context.
+// FIXME: We're not in a position to handle this yet.
+#if 0
+template<typename ...Types> struct tuple { };
+
+template<typename ...Types>
+void pack_not_at_end(tuple<Types...>, Types... values, int);
+
+void test_pack_not_at_end(tuple<int*, double*> t2) {
+ pack_not_at_end(t2, 0, 0, 0);
+}
+#endif
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp
new file mode 100644
index 0000000000..cf68a01a35
--- /dev/null
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// FIXME: More bullets to go!
+
+template<typename T, typename U>
+struct has_nondeduced_pack_test {
+ static const bool value = false;
+};
+
+template<typename R, typename FirstType, typename ...Types>
+struct has_nondeduced_pack_test<R(FirstType, Types..., int),
+ R(FirstType, Types...)> {
+ static const bool value = true;
+};
+
+// - A function parameter pack that does not occur at the end of the
+// parameter-declaration-clause.
+int check_nondeduced_pack_test0[
+ has_nondeduced_pack_test<int(float, double, int),
+ int(float, double)>::value? 1 : -1];
+
+