[clang] 1cdc0e8 - [Clang] Check type-constraints applied to placeholder types
Corentin Jabot via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 10 08:33:16 PDT 2023
Author: Corentin Jabot
Date: 2023-04-10T17:33:09+02:00
New Revision: 1cdc0e83c8ce35702ddbc6b26959a5da44776a49
URL: https://github.com/llvm/llvm-project/commit/1cdc0e83c8ce35702ddbc6b26959a5da44776a49
DIFF: https://github.com/llvm/llvm-project/commit/1cdc0e83c8ce35702ddbc6b26959a5da44776a49.diff
LOG: [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
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Sema/Sema.h
clang/lib/Parse/ParseDecl.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/test/Parser/cxx2a-placeholder-type-constraint.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3fc2839b93e50..c9187f225cad3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index a46bc758dd6af..33d6c40f157fe 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8107,6 +8107,8 @@ class Sema final {
SourceLocation EqualLoc,
ParsedType DefaultArg, bool HasTypeConstraint);
+ bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
+
bool ActOnTypeConstraint(const CXXScopeSpec &SS,
TemplateIdAnnotation *TypeConstraint,
TemplateTypeParmDecl *ConstrainedParameter,
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 91376cf6a34e4..450c703a27d0c 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -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)) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e277dccb31875..d4f89cc1f0dfd 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -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);
diff --git a/clang/test/Parser/cxx2a-placeholder-type-constraint.cpp b/clang/test/Parser/cxx2a-placeholder-type-constraint.cpp
index ba1b1ea62c300..8e61349ea8768 100644
--- a/clang/test/Parser/cxx2a-placeholder-type-constraint.cpp
+++ b/clang/test/Parser/cxx2a-placeholder-type-constraint.cpp
@@ -47,3 +47,23 @@ void foo2(C const &a){}
void foo3(C auto const &a){}
void foo4(const C &a){}
// expected-error at -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}}
+}
More information about the cfe-commits
mailing list