[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