diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-04 22:13:36 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-04 22:13:36 +0000 |
commit | aaa6a908acc365b0c1d8a130799f2ff5a276ffd4 (patch) | |
tree | 4575fffffc3aa5b01b876a7d856bb2e4f60869cc /clang/lib/Sema/SemaTemplateDeduction.cpp | |
parent | 87f457057f21e7cce65b622d782c664033f50225 (diff) | |
download | bcm5719-llvm-aaa6a908acc365b0c1d8a130799f2ff5a276ffd4.tar.gz bcm5719-llvm-aaa6a908acc365b0c1d8a130799f2ff5a276ffd4.zip |
Improve the checking of deduced template arguments stored within template argument packs when finishing template argument deduction for a function template
llvm-svn: 122843
Diffstat (limited to 'clang/lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 111 |
1 files changed, 71 insertions, 40 deletions
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 99b6daceed9..82693dd228d 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1677,6 +1677,55 @@ getTrivialTemplateArgumentLoc(Sema &S, return TemplateArgumentLoc(); } +/// \brief Convert the given deduced template argument and add it to the set of +/// fully-converted template arguments. +static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, + DeducedTemplateArgument Arg, + FunctionTemplateDecl *FunctionTemplate, + QualType NTTPType, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<TemplateArgument> &Output) { + if (Arg.getKind() == TemplateArgument::Pack) { + // This is a template argument pack, so check each of its arguments against + // the template parameter. + llvm::SmallVector<TemplateArgument, 2> PackedArgsBuilder; + for (TemplateArgument::pack_iterator PA = Arg.pack_begin(), + PAEnd = Arg.pack_end(); + PA != PAEnd; ++PA) { + DeducedTemplateArgument InnerArg(*PA); + InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound()); + if (ConvertDeducedTemplateArgument(S, Param, InnerArg, FunctionTemplate, + NTTPType, Info, PackedArgsBuilder)) + return true; + } + + // Create the resulting argument pack. + TemplateArgument *PackedArgs = 0; + if (!PackedArgsBuilder.empty()) { + PackedArgs = new (S.Context) TemplateArgument[PackedArgsBuilder.size()]; + std::copy(PackedArgsBuilder.begin(), PackedArgsBuilder.end(), PackedArgs); + } + Output.push_back(TemplateArgument(PackedArgs, PackedArgsBuilder.size())); + return false; + } + + // Convert the deduced template argument into a template + // argument that we can check, almost as if the user had written + // the template argument explicitly. + TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType, + Info.getLocation()); + + // Check the template argument, converting it as necessary. + return S.CheckTemplateArgument(Param, ArgLoc, + FunctionTemplate, + FunctionTemplate->getLocation(), + FunctionTemplate->getSourceRange().getEnd(), + Output, + Arg.wasDeducedFromArrayBound() + ? Sema::CTAK_DeducedFromArrayBound + : Sema::CTAK_Deduced); +} + /// \brief Finish template argument deduction for a function template, /// checking the deduced template arguments for completeness and forming /// the function template specialization. @@ -1708,9 +1757,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. llvm::SmallVector<TemplateArgument, 4> Builder; - for (unsigned I = 0, N = Deduced.size(); I != N; ++I) { - // FIXME: Variadic templates. Unwrap argument packs? - NamedDecl *Param = FunctionTemplate->getTemplateParameters()->getParam(I); + for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { + NamedDecl *Param = TemplateParams->getParam(I); if (!Deduced[I].isNull()) { if (I < NumExplicitlySpecified) { @@ -1730,49 +1778,32 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, QualType NTTPType; if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { - if (Deduced[I].getKind() == TemplateArgument::Declaration) { - NTTPType = NTTP->getType(); - if (NTTPType->isDependentType()) { - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, - Builder.data(), Builder.size()); - NTTPType = 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(Context, - Builder.data(), - Builder.size())); - return TDK_SubstitutionFailure; - } + NTTPType = NTTP->getType(); + if (NTTPType->isDependentType()) { + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Builder.data(), Builder.size()); + NTTPType = 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(Context, + Builder.data(), + Builder.size())); + return TDK_SubstitutionFailure; } } } - // Convert the deduced template argument into a template - // argument that we can check, almost as if the user had written - // the template argument explicitly. - TemplateArgumentLoc Arg = getTrivialTemplateArgumentLoc(*this, - Deduced[I], - NTTPType, - Info.getLocation()); - - // Check the template argument, converting it as necessary. - if (CheckTemplateArgument(Param, Arg, - FunctionTemplate, - FunctionTemplate->getLocation(), - FunctionTemplate->getSourceRange().getEnd(), - Builder, - Deduced[I].wasDeducedFromArrayBound() - ? CTAK_DeducedFromArrayBound - : CTAK_Deduced)) { - Info.Param = makeTemplateParameter( - const_cast<NamedDecl *>(TemplateParams->getParam(I))); + if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I], + FunctionTemplate, NTTPType, Info, + Builder)) { + Info.Param = makeTemplateParameter(Param); // FIXME: These template arguments are temporary. Free them! Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(), - Builder.size())); + Builder.size())); return TDK_SubstitutionFailure; } |