summaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp338
1 files changed, 224 insertions, 114 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 1184446796eb..f961244da072 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1050,7 +1050,8 @@ makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
return TemplateArgs;
}
-bool Sema::ActOnTypeConstraint(TemplateIdAnnotation *TypeConstr,
+bool Sema::ActOnTypeConstraint(const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstr,
TemplateTypeParmDecl *ConstrainedParameter,
SourceLocation EllipsisLoc) {
ConceptDecl *CD =
@@ -1080,14 +1081,57 @@ bool Sema::ActOnTypeConstraint(TemplateIdAnnotation *TypeConstr,
makeTemplateArgumentListInfo(*this, *TypeConstr);
}
return AttachTypeConstraint(
- TypeConstr->SS.isSet() ? TypeConstr->SS.getWithLocInContext(Context) :
- NestedNameSpecifierLoc(),
+ SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc(),
DeclarationNameInfo(DeclarationName(TypeConstr->Name),
TypeConstr->TemplateNameLoc), CD,
TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr,
ConstrainedParameter, EllipsisLoc);
}
+template<typename ArgumentLocAppender>
+static ExprResult formImmediatelyDeclaredConstraint(
+ Sema &S, NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo,
+ ConceptDecl *NamedConcept, SourceLocation LAngleLoc,
+ SourceLocation RAngleLoc, QualType ConstrainedType,
+ SourceLocation ParamNameLoc, ArgumentLocAppender Appender,
+ SourceLocation EllipsisLoc) {
+
+ TemplateArgumentListInfo ConstraintArgs;
+ ConstraintArgs.addArgument(
+ S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType),
+ /*NTTPType=*/QualType(), ParamNameLoc));
+
+ ConstraintArgs.setRAngleLoc(RAngleLoc);
+ ConstraintArgs.setLAngleLoc(LAngleLoc);
+ Appender(ConstraintArgs);
+
+ // C++2a [temp.param]p4:
+ // [...] This constraint-expression E is called the immediately-declared
+ // constraint of T. [...]
+ CXXScopeSpec SS;
+ SS.Adopt(NS);
+ ExprResult ImmediatelyDeclaredConstraint = S.CheckConceptTemplateId(
+ SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo,
+ /*FoundDecl=*/NamedConcept, NamedConcept, &ConstraintArgs);
+ if (ImmediatelyDeclaredConstraint.isInvalid() || !EllipsisLoc.isValid())
+ return ImmediatelyDeclaredConstraint;
+
+ // C++2a [temp.param]p4:
+ // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
+ //
+ // We have the following case:
+ //
+ // template<typename T> concept C1 = true;
+ // template<C1... T> struct s1;
+ //
+ // The constraint: (C1<T> && ...)
+ return S.BuildCXXFoldExpr(/*LParenLoc=*/SourceLocation(),
+ ImmediatelyDeclaredConstraint.get(), BO_LAnd,
+ EllipsisLoc, /*RHS=*/nullptr,
+ /*RParenLoc=*/SourceLocation(),
+ /*NumExpansions=*/None);
+}
+
/// Attach a type-constraint to a template parameter.
/// \returns true if an error occured. This can happen if the
/// immediately-declared constraint could not be formed (e.g. incorrect number
@@ -1106,51 +1150,21 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS,
*TemplateArgs) : nullptr;
QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0);
- TemplateArgumentListInfo ConstraintArgs;
- ConstraintArgs.addArgument(
- TemplateArgumentLoc(
- TemplateArgument(ParamAsArgument),
- TemplateArgumentLocInfo(
- Context.getTrivialTypeSourceInfo(ParamAsArgument,
- ConstrainedParameter->getLocation()))));
- if (TemplateArgs) {
- ConstraintArgs.setRAngleLoc(TemplateArgs->getRAngleLoc());
- ConstraintArgs.setLAngleLoc(TemplateArgs->getLAngleLoc());
- for (const TemplateArgumentLoc &ArgLoc : TemplateArgs->arguments())
- ConstraintArgs.addArgument(ArgLoc);
- }
- // C++2a [temp.param]p4:
- // [...] This constraint-expression E is called the immediately-declared
- // constraint of T. [...]
- CXXScopeSpec SS;
- SS.Adopt(NS);
- ExprResult ImmediatelyDeclaredConstraint = CheckConceptTemplateId(SS,
- /*TemplateKWLoc=*/SourceLocation(), NameInfo, /*FoundDecl=*/NamedConcept,
- NamedConcept, &ConstraintArgs);
+ ExprResult ImmediatelyDeclaredConstraint =
+ formImmediatelyDeclaredConstraint(
+ *this, NS, NameInfo, NamedConcept,
+ TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(),
+ TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(),
+ ParamAsArgument, ConstrainedParameter->getLocation(),
+ [&] (TemplateArgumentListInfo &ConstraintArgs) {
+ if (TemplateArgs)
+ for (const auto &ArgLoc : TemplateArgs->arguments())
+ ConstraintArgs.addArgument(ArgLoc);
+ }, EllipsisLoc);
if (ImmediatelyDeclaredConstraint.isInvalid())
return true;
- if (ConstrainedParameter->isParameterPack()) {
- // C++2a [temp.param]p4:
- // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
- //
- // We have the following case:
- //
- // template<typename T> concept C1 = true;
- // template<C1... T> struct s1;
- //
- // The constraint: (C1<T> && ...)
- ImmediatelyDeclaredConstraint =
- BuildCXXFoldExpr(/*LParenLoc=*/SourceLocation(),
- ImmediatelyDeclaredConstraint.get(), BO_LAnd,
- EllipsisLoc, /*RHS=*/nullptr,
- /*RParenLoc=*/SourceLocation(),
- /*NumExpansions=*/None).get();
- if (ImmediatelyDeclaredConstraint.isInvalid())
- return true;
- }
-
ConstrainedParameter->setTypeConstraint(NS, NameInfo,
/*FoundDecl=*/NamedConcept,
NamedConcept, ArgsAsWritten,
@@ -1158,6 +1172,38 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS,
return false;
}
+bool Sema::AttachTypeConstraint(AutoTypeLoc TL, NonTypeTemplateParmDecl *NTTP,
+ SourceLocation EllipsisLoc) {
+ if (NTTP->getType() != TL.getType() ||
+ TL.getAutoKeyword() != AutoTypeKeyword::Auto) {
+ Diag(NTTP->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+ diag::err_unsupported_placeholder_constraint)
+ << NTTP->getTypeSourceInfo()->getTypeLoc().getSourceRange();
+ return true;
+ }
+ // FIXME: Concepts: This should be the type of the placeholder, but this is
+ // unclear in the wording right now.
+ DeclRefExpr *Ref = BuildDeclRefExpr(NTTP, NTTP->getType(), VK_RValue,
+ NTTP->getLocation());
+ if (!Ref)
+ return true;
+ ExprResult ImmediatelyDeclaredConstraint =
+ formImmediatelyDeclaredConstraint(
+ *this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
+ TL.getNamedConcept(), TL.getLAngleLoc(), TL.getRAngleLoc(),
+ BuildDecltypeType(Ref, NTTP->getLocation()), NTTP->getLocation(),
+ [&] (TemplateArgumentListInfo &ConstraintArgs) {
+ for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
+ ConstraintArgs.addArgument(TL.getArgLoc(I));
+ }, EllipsisLoc);
+ if (ImmediatelyDeclaredConstraint.isInvalid() ||
+ !ImmediatelyDeclaredConstraint.isUsable())
+ return true;
+
+ NTTP->setPlaceholderTypeConstraint(ImmediatelyDeclaredConstraint.get());
+ return false;
+}
+
/// Check that the type of a non-type template parameter is
/// well-formed.
///
@@ -1319,6 +1365,11 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
TInfo);
Param->setAccess(AS_public);
+ if (AutoTypeLoc TL = TInfo->getTypeLoc().getContainedAutoTypeLoc())
+ if (TL.isConstrained())
+ if (AttachTypeConstraint(TL, Param, D.getEllipsisLoc()))
+ Invalid = true;
+
if (Invalid)
Param->setInvalidDecl();
@@ -2762,7 +2813,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS,
TemplateIdAnnotation *TemplateId,
ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
- bool &IsMemberSpecialization, bool &Invalid) {
+ bool &IsMemberSpecialization, bool &Invalid, bool SuppressDiagnostic) {
IsMemberSpecialization = false;
Invalid = false;
@@ -2870,8 +2921,9 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
auto CheckExplicitSpecialization = [&](SourceRange Range, bool Recovery) {
if (SawNonEmptyTemplateParameterList) {
- Diag(DeclLoc, diag::err_specialize_member_of_template)
- << !Recovery << Range;
+ if (!SuppressDiagnostic)
+ Diag(DeclLoc, diag::err_specialize_member_of_template)
+ << !Recovery << Range;
Invalid = true;
IsMemberSpecialization = false;
return true;
@@ -2892,9 +2944,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
else
ExpectedTemplateLoc = DeclStartLoc;
- Diag(DeclLoc, diag::err_template_spec_needs_header)
- << Range
- << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
+ if (!SuppressDiagnostic)
+ Diag(DeclLoc, diag::err_template_spec_needs_header)
+ << Range
+ << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
return false;
};
@@ -2984,12 +3037,13 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() > 0) {
// The header has template parameters when it shouldn't. Complain.
- Diag(ParamLists[ParamIdx]->getTemplateLoc(),
- diag::err_template_param_list_matches_nontemplate)
- << T
- << SourceRange(ParamLists[ParamIdx]->getLAngleLoc(),
- ParamLists[ParamIdx]->getRAngleLoc())
- << getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
+ if (!SuppressDiagnostic)
+ Diag(ParamLists[ParamIdx]->getTemplateLoc(),
+ diag::err_template_param_list_matches_nontemplate)
+ << T
+ << SourceRange(ParamLists[ParamIdx]->getLAngleLoc(),
+ ParamLists[ParamIdx]->getRAngleLoc())
+ << getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
Invalid = true;
return nullptr;
}
@@ -3025,7 +3079,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
if (ExpectedTemplateParams &&
!TemplateParameterListsAreEqual(ParamLists[ParamIdx],
ExpectedTemplateParams,
- true, TPL_TemplateMatch))
+ !SuppressDiagnostic, TPL_TemplateMatch))
Invalid = true;
if (!Invalid &&
@@ -3037,9 +3091,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
continue;
}
- Diag(DeclLoc, diag::err_template_spec_needs_template_parameters)
- << T
- << getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
+ if (!SuppressDiagnostic)
+ Diag(DeclLoc, diag::err_template_spec_needs_template_parameters)
+ << T
+ << getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
Invalid = true;
continue;
}
@@ -3075,16 +3130,18 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
AllExplicitSpecHeaders = false;
}
- Diag(ParamLists[ParamIdx]->getTemplateLoc(),
- AllExplicitSpecHeaders ? diag::warn_template_spec_extra_headers
- : diag::err_template_spec_extra_headers)
- << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(),
- ParamLists[ParamLists.size() - 2]->getRAngleLoc());
+ if (!SuppressDiagnostic)
+ Diag(ParamLists[ParamIdx]->getTemplateLoc(),
+ AllExplicitSpecHeaders ? diag::warn_template_spec_extra_headers
+ : diag::err_template_spec_extra_headers)
+ << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(),
+ ParamLists[ParamLists.size() - 2]->getRAngleLoc());
// If there was a specialization somewhere, such that 'template<>' is
// not required, and there were any 'template<>' headers, note where the
// specialization occurred.
- if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader)
+ if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader &&
+ !SuppressDiagnostic)
Diag(ExplicitSpecLoc,
diag::note_explicit_template_spec_does_not_need_header)
<< NestedTypes.back();
@@ -4044,7 +4101,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(),
Converted) &&
- (!Context.getLangOpts().ConceptsTS ||
+ (!Context.getLangOpts().CPlusPlus2a ||
!TemplateParams->hasAssociatedConstraints())) {
// C++ [temp.class.spec]p9b3:
//
@@ -6530,7 +6587,12 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
DeductionArg = PE->getPattern();
if (DeduceAutoType(
Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()),
- DeductionArg, ParamType, Depth) == DAR_Failed) {
+ DeductionArg, ParamType, Depth,
+ // We do not check constraints right now because the
+ // immediately-declared constraint of the auto type is also an
+ // associated constraint, and will be checked along with the other
+ // associated constraints after checking the template argument list.
+ /*IgnoreConstraints=*/true) == DAR_Failed) {
Diag(Arg->getExprLoc(),
diag::err_non_type_template_parm_type_deduction_failure)
<< Param->getDeclName() << Param->getType() << Arg->getType()
@@ -7102,6 +7164,11 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
// [temp.constr.order].
SmallVector<const Expr *, 3> ParamsAC, TemplateAC;
Params->getAssociatedConstraints(ParamsAC);
+ // C++2a[temp.arg.template]p3
+ // [...] In this comparison, if P is unconstrained, the constraints on A
+ // are not considered.
+ if (ParamsAC.empty())
+ return false;
Template->getAssociatedConstraints(TemplateAC);
bool IsParamAtLeastAsConstrained;
if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
@@ -7872,13 +7939,11 @@ bool Sema::CheckTemplatePartialSpecializationArgs(
DeclResult Sema::ActOnClassTemplateSpecialization(
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
- SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId,
- const ParsedAttributesView &Attr,
+ SourceLocation ModulePrivateLoc, CXXScopeSpec &SS,
+ TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr,
MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) {
assert(TUK != TUK_Reference && "References are not specializations");
- CXXScopeSpec &SS = TemplateId.SS;
-
// NOTE: KWLoc is the location of the tag keyword. This will instead
// store the location of the outermost template keyword in the declaration.
SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
@@ -8048,7 +8113,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
if (Context.hasSameType(CanonType,
ClassTemplate->getInjectedClassNameSpecialization()) &&
- (!Context.getLangOpts().ConceptsTS ||
+ (!Context.getLangOpts().CPlusPlus2a ||
!TemplateParams->hasAssociatedConstraints())) {
// C++ [temp.class.spec]p9b3:
//
@@ -10012,24 +10077,12 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
<< FixItHint::CreateRemoval(TypenameLoc);
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
+ TypeSourceInfo *TSI = nullptr;
QualType T = CheckTypenameType(TypenameLoc.isValid()? ETK_Typename : ETK_None,
- TypenameLoc, QualifierLoc, II, IdLoc);
+ TypenameLoc, QualifierLoc, II, IdLoc, &TSI,
+ /*DeducedTSTContext=*/true);
if (T.isNull())
return true;
-
- TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
- if (isa<DependentNameType>(T)) {
- DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>();
- TL.setElaboratedKeywordLoc(TypenameLoc);
- TL.setQualifierLoc(QualifierLoc);
- TL.setNameLoc(IdLoc);
- } else {
- ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>();
- TL.setElaboratedKeywordLoc(TypenameLoc);
- TL.setQualifierLoc(QualifierLoc);
- TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc);
- }
-
return CreateParsedType(T, TSI);
}
@@ -10166,6 +10219,35 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
return true;
}
+QualType
+Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
+ SourceLocation KeywordLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ const IdentifierInfo &II,
+ SourceLocation IILoc,
+ TypeSourceInfo **TSI,
+ bool DeducedTSTContext) {
+ QualType T = CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, II, IILoc,
+ DeducedTSTContext);
+ if (T.isNull())
+ return QualType();
+
+ *TSI = Context.CreateTypeSourceInfo(T);
+ if (isa<DependentNameType>(T)) {
+ DependentNameTypeLoc TL =
+ (*TSI)->getTypeLoc().castAs<DependentNameTypeLoc>();
+ TL.setElaboratedKeywordLoc(KeywordLoc);
+ TL.setQualifierLoc(QualifierLoc);
+ TL.setNameLoc(IILoc);
+ } else {
+ ElaboratedTypeLoc TL = (*TSI)->getTypeLoc().castAs<ElaboratedTypeLoc>();
+ TL.setElaboratedKeywordLoc(KeywordLoc);
+ TL.setQualifierLoc(QualifierLoc);
+ TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IILoc);
+ }
+ return T;
+}
+
/// Build the type that describes a C++ typename specifier,
/// e.g., "typename T::type".
QualType
@@ -10173,32 +10255,38 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
SourceLocation KeywordLoc,
NestedNameSpecifierLoc QualifierLoc,
const IdentifierInfo &II,
- SourceLocation IILoc) {
+ SourceLocation IILoc, bool DeducedTSTContext) {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
- DeclContext *Ctx = computeDeclContext(SS);
- if (!Ctx) {
- // If the nested-name-specifier is dependent and couldn't be
- // resolved to a type, build a typename type.
- assert(QualifierLoc.getNestedNameSpecifier()->isDependent());
- return Context.getDependentNameType(Keyword,
- QualifierLoc.getNestedNameSpecifier(),
- &II);
+ DeclContext *Ctx = nullptr;
+ if (QualifierLoc) {
+ Ctx = computeDeclContext(SS);
+ if (!Ctx) {
+ // If the nested-name-specifier is dependent and couldn't be
+ // resolved to a type, build a typename type.
+ assert(QualifierLoc.getNestedNameSpecifier()->isDependent());
+ return Context.getDependentNameType(Keyword,
+ QualifierLoc.getNestedNameSpecifier(),
+ &II);
+ }
+
+ // If the nested-name-specifier refers to the current instantiation,
+ // the "typename" keyword itself is superfluous. In C++03, the
+ // program is actually ill-formed. However, DR 382 (in C++0x CD1)
+ // allows such extraneous "typename" keywords, and we retroactively
+ // apply this DR to C++03 code with only a warning. In any case we continue.
+
+ if (RequireCompleteDeclContext(SS, Ctx))
+ return QualType();
}
- // If the nested-name-specifier refers to the current instantiation,
- // the "typename" keyword itself is superfluous. In C++03, the
- // program is actually ill-formed. However, DR 382 (in C++0x CD1)
- // allows such extraneous "typename" keywords, and we retroactively
- // apply this DR to C++03 code with only a warning. In any case we continue.
-
- if (RequireCompleteDeclContext(SS, Ctx))
- return QualType();
-
DeclarationName Name(&II);
LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
- LookupQualifiedName(Result, Ctx, SS);
+ if (Ctx)
+ LookupQualifiedName(Result, Ctx, SS);
+ else
+ LookupName(Result, CurScope);
unsigned DiagID = 0;
Decl *Referenced = nullptr;
switch (Result.getResultKind()) {
@@ -10207,7 +10295,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
// a more specific diagnostic.
SourceRange CondRange;
Expr *Cond = nullptr;
- if (isEnableIf(QualifierLoc, II, CondRange, Cond)) {
+ if (Ctx && isEnableIf(QualifierLoc, II, CondRange, Cond)) {
// If we have a condition, narrow it down to the specific failed
// condition.
if (Cond) {
@@ -10223,12 +10311,14 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
return QualType();
}
- Diag(CondRange.getBegin(), diag::err_typename_nested_not_found_enable_if)
+ Diag(CondRange.getBegin(),
+ diag::err_typename_nested_not_found_enable_if)
<< Ctx << CondRange;
return QualType();
}
- DiagID = diag::err_typename_nested_not_found;
+ DiagID = Ctx ? diag::err_typename_nested_not_found
+ : diag::err_unknown_typename;
break;
}
@@ -10294,6 +10384,19 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
// is a placeholder for a deduced class type [...].
if (getLangOpts().CPlusPlus17) {
if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) {
+ if (!DeducedTSTContext) {
+ QualType T(QualifierLoc
+ ? QualifierLoc.getNestedNameSpecifier()->getAsType()
+ : nullptr, 0);
+ if (!T.isNull())
+ Diag(IILoc, diag::err_dependent_deduced_tst)
+ << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << T;
+ else
+ Diag(IILoc, diag::err_deduced_tst)
+ << (int)getTemplateNameKindForDiagnostics(TemplateName(TD));
+ Diag(TD->getLocation(), diag::note_template_decl_here);
+ return QualType();
+ }
return Context.getElaboratedType(
Keyword, QualifierLoc.getNestedNameSpecifier(),
Context.getDeducedTemplateSpecializationType(TemplateName(TD),
@@ -10301,12 +10404,14 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
}
}
- DiagID = diag::err_typename_nested_not_type;
+ DiagID = Ctx ? diag::err_typename_nested_not_type
+ : diag::err_typename_not_type;
Referenced = Result.getFoundDecl();
break;
case LookupResult::FoundOverloaded:
- DiagID = diag::err_typename_nested_not_type;
+ DiagID = Ctx ? diag::err_typename_nested_not_type
+ : diag::err_typename_not_type;
Referenced = *Result.begin();
break;
@@ -10318,9 +10423,14 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
// type. Emit an appropriate diagnostic and return an error.
SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(),
IILoc);
- Diag(IILoc, DiagID) << FullRange << Name << Ctx;
+ if (Ctx)
+ Diag(IILoc, DiagID) << FullRange << Name << Ctx;
+ else
+ Diag(IILoc, DiagID) << FullRange << Name;
if (Referenced)
- Diag(Referenced->getLocation(), diag::note_typename_refers_here)
+ Diag(Referenced->getLocation(),
+ Ctx ? diag::note_typename_member_refers_here
+ : diag::note_typename_refers_here)
<< Name;
return QualType();
}