diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-11 01:52:23 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-11 01:52:23 +0000 |
commit | 7d5c0c1273bdc1cb3dff1cb5a62d07b1439e82c7 (patch) | |
tree | 978f21cec876212e836022e75a4d1708d5aa4e88 | |
parent | 4d484a753f38a231e17c364cba496f8c6d2d771e (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.cpp | 13 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 | ||||
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp | 15 | ||||
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp | 22 |
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]; + + |