[c++1z] Diagnose non-deducible template parameters in deduction guide templates, per [temp.param]p11.

llvm-svn: 295264
This commit is contained in:
Richard Smith 2017-02-16 00:36:47 +00:00
parent 7386ceac74
commit 4e05eaa9e8
6 changed files with 73 additions and 21 deletions

View File

@ -2002,6 +2002,10 @@ def err_deduction_guide_explicit_mismatch : Error<
"previous declaration was%select{ not|}0">;
def err_deduction_guide_specialized : Error<"deduction guide cannot be "
"%select{explicitly instantiated|explicitly specialized}0">;
def err_deduction_guide_template_not_deducible : Error<
"deduction guide template contains "
"%select{a template parameter|template parameters}0 that cannot be "
"deduced">;
// C++1y deduced return types
def err_auto_fn_deduction_failure : Error<
@ -4146,7 +4150,7 @@ def ext_partial_specs_not_deducible : ExtWarn<
"%select{a template parameter|template parameters}1 that cannot be "
"deduced; this partial specialization will never be used">,
DefaultError, InGroup<DiagGroup<"unusable-partial-specialization">>;
def note_partial_spec_unused_parameter : Note<
def note_non_deducible_parameter : Note<
"non-deducible template parameter %0">;
def err_partial_spec_ordering_ambiguous : Error<
"ambiguous partial specializations of %0">;

View File

@ -5624,6 +5624,7 @@ public:
Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
void CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
StorageClass &SC);
void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD);
void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD);
void CheckExplicitlyDefaultedMemberExceptionSpec(CXXMethodDecl *MD,

View File

@ -9152,13 +9152,15 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
} else if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(NewFD)) {
ActOnConversionDeclarator(Conversion);
} else if (NewFD->isDeductionGuide() &&
NewFD->getTemplateSpecializationKind() ==
TSK_ExplicitSpecialization) {
} else if (NewFD->isDeductionGuide()) {
if (auto *TD = NewFD->getDescribedFunctionTemplate())
CheckDeductionGuideTemplate(TD);
// A deduction guide is not on the list of entities that can be
// explicitly specialized.
Diag(NewFD->getLocStart(), diag::err_deduction_guide_specialized)
<< /*explicit specialization*/ 1;
if (NewFD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
Diag(NewFD->getLocStart(), diag::err_deduction_guide_specialized)
<< /*explicit specialization*/ 1;
}
// Find any virtual functions that this function overrides.

View File

@ -3162,6 +3162,23 @@ static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl *Partial) {
S.Diag(Template->getLocation(), diag::note_template_decl_here);
}
static void
noteNonDeducibleParameters(Sema &S, TemplateParameterList *TemplateParams,
const llvm::SmallBitVector &DeducibleParams) {
for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
if (!DeducibleParams[I]) {
NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
if (Param->getDeclName())
S.Diag(Param->getLocation(), diag::note_non_deducible_parameter)
<< Param->getDeclName();
else
S.Diag(Param->getLocation(), diag::note_non_deducible_parameter)
<< "(anonymous)";
}
}
}
template<typename PartialSpecDecl>
static void checkTemplatePartialSpecialization(Sema &S,
PartialSpecDecl *Partial) {
@ -3189,19 +3206,7 @@ static void checkTemplatePartialSpecialization(Sema &S,
<< (NumNonDeducible > 1)
<< SourceRange(Partial->getLocation(),
Partial->getTemplateArgsAsWritten()->RAngleLoc);
for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
if (!DeducibleParams[I]) {
NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
if (Param->getDeclName())
S.Diag(Param->getLocation(),
diag::note_partial_spec_unused_parameter)
<< Param->getDeclName();
else
S.Diag(Param->getLocation(),
diag::note_partial_spec_unused_parameter)
<< "(anonymous)";
}
}
noteNonDeducibleParameters(S, TemplateParams, DeducibleParams);
}
}
@ -3215,6 +3220,29 @@ void Sema::CheckTemplatePartialSpecialization(
checkTemplatePartialSpecialization(*this, Partial);
}
void Sema::CheckDeductionGuideTemplate(FunctionTemplateDecl *TD) {
// C++1z [temp.param]p11:
// A template parameter of a deduction guide template that does not have a
// default-argument shall be deducible from the parameter-type-list of the
// deduction guide template.
auto *TemplateParams = TD->getTemplateParameters();
llvm::SmallBitVector DeducibleParams(TemplateParams->size());
MarkDeducedTemplateParameters(TD, DeducibleParams);
for (unsigned I = 0; I != TemplateParams->size(); ++I) {
// A parameter pack is deducible (to an empty pack).
auto *Param = TemplateParams->getParam(I);
if (Param->isParameterPack() || hasVisibleDefaultArgument(Param))
DeducibleParams[I] = true;
}
if (!DeducibleParams.all()) {
unsigned NumNonDeducible = DeducibleParams.size() - DeducibleParams.count();
Diag(TD->getLocation(), diag::err_deduction_guide_template_not_deducible)
<< (NumNonDeducible > 1);
noteNonDeducibleParameters(*this, TemplateParams, DeducibleParams);
}
}
DeclResult Sema::ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,
TemplateParameterList *TemplateParams, StorageClass SC,

View File

@ -150,3 +150,21 @@ namespace look_into_current_instantiation {
C c = {1, 2};
}
namespace nondeducible {
template<typename A, typename B> struct X {};
template<typename A> // expected-note {{non-deducible template parameter 'A'}}
X() -> X<A, int>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
template<typename A> // expected-note {{non-deducible template parameter 'A'}}
X(typename X<A, int>::type) -> X<A, int>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
template<typename A = int,
typename B> // expected-note {{non-deducible template parameter 'B'}}
X(int) -> X<A, B>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
template<typename A = int,
typename ...B>
X(float) -> X<A, B...>; // ok
}

View File

@ -684,11 +684,10 @@ as the draft C++1z standard evolves.
<tr>
<td rowspan="2">Template argument deduction for class templates</td>
<td><a href="http://wg21.link/p0091r3">P0091R3</a></td>
<td class="svn" align="center">SVN</td>
<td rowspan="2" class="svn" align="center">SVN</td>
</tr>
<tr> <!-- from Issaquah -->
<td><a href="http://wg21.link/p0512r0">P0512R0</a></td>
<td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Non-type template parameters with <tt>auto</tt> type</td>