"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<
"%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">;
Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
void CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
StorageClass &SC);
+ void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD);
void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD);
void CheckExplicitlyDefaultedMemberExceptionSpec(CXXMethodDecl *MD,
} 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.
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) {
<< (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);
}
}
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,
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
+}
<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>