forked from OSchip/llvm-project
[c++1z] Diagnose non-deducible template parameters in deduction guide templates, per [temp.param]p11.
llvm-svn: 295264
This commit is contained in:
parent
7386ceac74
commit
4e05eaa9e8
|
@ -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">;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue