[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
|
||||
consteval/constexpr call chain.
|
||||
(`#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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -8107,6 +8107,8 @@ public:
|
||||
SourceLocation EqualLoc,
|
||||
ParsedType DefaultArg, bool HasTypeConstraint);
|
||||
|
||||
bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
|
||||
|
||||
bool ActOnTypeConstraint(const CXXScopeSpec &SS,
|
||||
TemplateIdAnnotation *TypeConstraint,
|
||||
TemplateTypeParmDecl *ConstrainedParameter,
|
||||
|
@ -3770,6 +3770,10 @@ void Parser::ParseDeclarationSpecifiers(
|
||||
}
|
||||
if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
|
||||
goto DoneWithDeclSpec;
|
||||
|
||||
if (TemplateId && !isInvalid && Actions.CheckTypeConstraint(TemplateId))
|
||||
TemplateId = nullptr;
|
||||
|
||||
ConsumeAnnotationToken();
|
||||
SourceLocation AutoLoc = Tok.getLocation();
|
||||
if (TryConsumeToken(tok::kw_decltype)) {
|
||||
|
@ -1107,19 +1107,8 @@ makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
|
||||
return TemplateArgs;
|
||||
}
|
||||
|
||||
bool Sema::ActOnTypeConstraint(const CXXScopeSpec &SS,
|
||||
TemplateIdAnnotation *TypeConstr,
|
||||
TemplateTypeParmDecl *ConstrainedParameter,
|
||||
SourceLocation EllipsisLoc) {
|
||||
return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
|
||||
false);
|
||||
}
|
||||
bool Sema::CheckTypeConstraint(TemplateIdAnnotation *TypeConstr) {
|
||||
|
||||
bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS,
|
||||
TemplateIdAnnotation *TypeConstr,
|
||||
TemplateTypeParmDecl *ConstrainedParameter,
|
||||
SourceLocation EllipsisLoc,
|
||||
bool AllowUnexpandedPack) {
|
||||
TemplateName TN = TypeConstr->Template.get();
|
||||
ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
|
||||
|
||||
@ -1137,9 +1126,32 @@ bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS,
|
||||
if (!WereArgsSpecified &&
|
||||
CD->getTemplateParameters()->getMinRequiredArguments() > 1) {
|
||||
Diag(TypeConstr->TemplateNameLoc,
|
||||
diag::err_type_constraint_missing_arguments) << CD;
|
||||
diag::err_type_constraint_missing_arguments)
|
||||
<< CD;
|
||||
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),
|
||||
TypeConstr->TemplateNameLoc);
|
||||
|
@ -47,3 +47,23 @@ void foo2(C const &a){}
|
||||
void foo3(C auto const &a){}
|
||||
void foo4(const C &a){}
|
||||
// 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