diff options
Diffstat (limited to 'lib')
-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 |
4 files changed, 33 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); |