[cfe-commits] r122843 - in /cfe/trunk: lib/Sema/SemaTemplateDeduction.cpp test/CXX/temp/temp.decls/temp.variadic/deduction.cpp
Douglas Gregor
dgregor at apple.com
Tue Jan 4 14:13:36 PST 2011
Author: dgregor
Date: Tue Jan 4 16:13:36 2011
New Revision: 122843
URL: http://llvm.org/viewvc/llvm-project?rev=122843&view=rev
Log:
Improve the checking of deduced template arguments stored within template argument packs when finishing template argument deduction for a function template
Added:
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp
Modified:
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=122843&r1=122842&r2=122843&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Jan 4 16:13:36 2011
@@ -1677,6 +1677,55 @@
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 @@
// [...] 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 @@
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;
}
Added: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp?rev=122843&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp Tue Jan 4 16:13:36 2011
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+namespace DeductionForInstantiation {
+ template<unsigned I, typename ...Types>
+ struct X { };
+
+ template<typename ...Types>
+ void f0(X<sizeof...(Types), Types&...>) { }
+
+ // No explicitly-specified arguments
+ template void f0(X<0>);
+ template void f0(X<1, int&>);
+ template void f0(X<2, int&, short&>);
+
+ // One explicitly-specified argument
+ template void f0<float>(X<1, float&>);
+ template void f0<double>(X<1, double&>);
+
+ // Two explicitly-specialized arguments
+ template void f0<char, unsigned char>(X<2, char&, unsigned char&>);
+ template void f0<signed char, char>(X<2, signed char&, char&>);
+
+ // FIXME: Extension of explicitly-specified arguments
+ // template void f0<short, int>(X<3, short&, int&, long&>);
+}
More information about the cfe-commits
mailing list