[Clang] Check type-constraints applied to placeholder types
(and deduced return types) Previously, only type constraints applied to type parameter were semantically checked. A diagnostic would still be emitted on instantiation, but it was too late, lacked clarity, and was inconsistent with type parameters. Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D147925
This commit is contained in:
parent
26c57df8aa
commit
1cdc0e83c8
@ -288,6 +288,8 @@ Bug Fixes in This Version
|
|||||||
- Fix the assertion hit when a template consteval function appears in a nested
|
- Fix the assertion hit when a template consteval function appears in a nested
|
||||||
consteval/constexpr call chain.
|
consteval/constexpr call chain.
|
||||||
(`#61142 <https://github.com/llvm/llvm-project/issues/61142>`_)
|
(`#61142 <https://github.com/llvm/llvm-project/issues/61142>`_)
|
||||||
|
- Clang now better diagnose placeholder types constrained with a concept that is
|
||||||
|
not a type concept.
|
||||||
|
|
||||||
Bug Fixes to Compiler Builtins
|
Bug Fixes to Compiler Builtins
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -8107,6 +8107,8 @@ public:
|
|||||||
SourceLocation EqualLoc,
|
SourceLocation EqualLoc,
|
||||||
ParsedType DefaultArg, bool HasTypeConstraint);
|
ParsedType DefaultArg, bool HasTypeConstraint);
|
||||||
|
|
||||||
|
bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
|
||||||
|
|
||||||
bool ActOnTypeConstraint(const CXXScopeSpec &SS,
|
bool ActOnTypeConstraint(const CXXScopeSpec &SS,
|
||||||
TemplateIdAnnotation *TypeConstraint,
|
TemplateIdAnnotation *TypeConstraint,
|
||||||
TemplateTypeParmDecl *ConstrainedParameter,
|
TemplateTypeParmDecl *ConstrainedParameter,
|
||||||
|
@ -3770,6 +3770,10 @@ void Parser::ParseDeclarationSpecifiers(
|
|||||||
}
|
}
|
||||||
if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
|
if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
|
||||||
goto DoneWithDeclSpec;
|
goto DoneWithDeclSpec;
|
||||||
|
|
||||||
|
if (TemplateId && !isInvalid && Actions.CheckTypeConstraint(TemplateId))
|
||||||
|
TemplateId = nullptr;
|
||||||
|
|
||||||
ConsumeAnnotationToken();
|
ConsumeAnnotationToken();
|
||||||
SourceLocation AutoLoc = Tok.getLocation();
|
SourceLocation AutoLoc = Tok.getLocation();
|
||||||
if (TryConsumeToken(tok::kw_decltype)) {
|
if (TryConsumeToken(tok::kw_decltype)) {
|
||||||
|
@ -1107,19 +1107,8 @@ makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
|
|||||||
return TemplateArgs;
|
return TemplateArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sema::ActOnTypeConstraint(const CXXScopeSpec &SS,
|
bool Sema::CheckTypeConstraint(TemplateIdAnnotation *TypeConstr) {
|
||||||
TemplateIdAnnotation *TypeConstr,
|
|
||||||
TemplateTypeParmDecl *ConstrainedParameter,
|
|
||||||
SourceLocation EllipsisLoc) {
|
|
||||||
return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS,
|
|
||||||
TemplateIdAnnotation *TypeConstr,
|
|
||||||
TemplateTypeParmDecl *ConstrainedParameter,
|
|
||||||
SourceLocation EllipsisLoc,
|
|
||||||
bool AllowUnexpandedPack) {
|
|
||||||
TemplateName TN = TypeConstr->Template.get();
|
TemplateName TN = TypeConstr->Template.get();
|
||||||
ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
|
ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
|
||||||
|
|
||||||
@ -1137,9 +1126,32 @@ bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS,
|
|||||||
if (!WereArgsSpecified &&
|
if (!WereArgsSpecified &&
|
||||||
CD->getTemplateParameters()->getMinRequiredArguments() > 1) {
|
CD->getTemplateParameters()->getMinRequiredArguments() > 1) {
|
||||||
Diag(TypeConstr->TemplateNameLoc,
|
Diag(TypeConstr->TemplateNameLoc,
|
||||||
diag::err_type_constraint_missing_arguments) << CD;
|
diag::err_type_constraint_missing_arguments)
|
||||||
|
<< CD;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sema::ActOnTypeConstraint(const CXXScopeSpec &SS,
|
||||||
|
TemplateIdAnnotation *TypeConstr,
|
||||||
|
TemplateTypeParmDecl *ConstrainedParameter,
|
||||||
|
SourceLocation EllipsisLoc) {
|
||||||
|
return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS,
|
||||||
|
TemplateIdAnnotation *TypeConstr,
|
||||||
|
TemplateTypeParmDecl *ConstrainedParameter,
|
||||||
|
SourceLocation EllipsisLoc,
|
||||||
|
bool AllowUnexpandedPack) {
|
||||||
|
|
||||||
|
if (CheckTypeConstraint(TypeConstr))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
TemplateName TN = TypeConstr->Template.get();
|
||||||
|
ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
|
||||||
|
|
||||||
DeclarationNameInfo ConceptName(DeclarationName(TypeConstr->Name),
|
DeclarationNameInfo ConceptName(DeclarationName(TypeConstr->Name),
|
||||||
TypeConstr->TemplateNameLoc);
|
TypeConstr->TemplateNameLoc);
|
||||||
|
@ -47,3 +47,23 @@ void foo2(C const &a){}
|
|||||||
void foo3(C auto const &a){}
|
void foo3(C auto const &a){}
|
||||||
void foo4(const C &a){}
|
void foo4(const C &a){}
|
||||||
// expected-error@-1{{expected 'auto' or 'decltype(auto)' after concept name}}
|
// expected-error@-1{{expected 'auto' or 'decltype(auto)' after concept name}}
|
||||||
|
|
||||||
|
namespace non_type {
|
||||||
|
template<int v>
|
||||||
|
concept C1 = true;
|
||||||
|
|
||||||
|
auto f() -> C1 auto {} // expected-error{{concept named in type constraint is not a type concept}}
|
||||||
|
auto g(C1 auto); // expected-error{{concept named in type constraint is not a type concept}}
|
||||||
|
C1 auto a = 0; // expected-error{{concept named in type constraint is not a type concept}}
|
||||||
|
C1 decltype(auto) b = 0; // expected-error{{concept named in type constraint is not a type concept}}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace arity {
|
||||||
|
template<typename v, typename>
|
||||||
|
concept C1 = true;
|
||||||
|
|
||||||
|
auto f() -> C1 auto {} // expected-error{{'C1' requires more than 1 template argument; provide the remaining arguments explicitly to use it here}}
|
||||||
|
auto g(C1 auto); // expected-error{{'C1' requires more than 1 template argument; provide the remaining arguments explicitly to use it here}}
|
||||||
|
C1 auto a = 0; // expected-error{{'C1' requires more than 1 template argument; provide the remaining arguments explicitly to use it here}}
|
||||||
|
C1 decltype(auto) b = 0; // expected-error{{'C1' requires more than 1 template argument; provide the remaining arguments explicitly to use it here}}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user