[PATCH] D147070: Improve requirement clause limitation on non templated function

Erich Keane via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 28 11:16:30 PDT 2023


erichkeane created this revision.
erichkeane added reviewers: clang-language-wg, shafik.
Herald added a project: All.
erichkeane requested review of this revision.

The current implementation 6da3d66f03f9162ef341cc67218be40e22fe9808 <https://reviews.llvm.org/rG6da3d66f03f9162ef341cc67218be40e22fe9808>
got a few things wrong, particularly that a template, or  definition
or member in a templated entity is required to be allowed to have a
trailing requires clause.

This patch corrects this, as reproted by #61748

Fixes: #61748

      


https://reviews.llvm.org/D147070

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CXX/dcl.decl/dcl.decl.general/p4-20.cpp


Index: clang/test/CXX/dcl.decl/dcl.decl.general/p4-20.cpp
===================================================================
--- clang/test/CXX/dcl.decl/dcl.decl.general/p4-20.cpp
+++ clang/test/CXX/dcl.decl/dcl.decl.general/p4-20.cpp
@@ -23,3 +23,23 @@
 // expected-error at +1{{expected expression}}
 auto *p = new void(*)(char)
   requires true;
+
+namespace GH61748 {
+template<typename T>
+struct S {
+  // expected-error at +1 {{non-templated function cannot have a requires clause}}
+  friend void declared_friend() requires(sizeof(T) > 1);
+  // OK, is a definition.
+  friend void defined_friend() requires(sizeof(T) > 1){}
+  // OK, is a member.
+  void member() requires(sizeof(T) > 1);
+};
+
+template<typename T>
+void ContainingFunction() {
+  // expected-error at +1 {{non-templated function cannot have a requires clause}}
+  void bad() requires(sizeof(T) > 1);
+  // expected-error at +1 {{function definition is not allowed here}}
+  void still_bad() requires(sizeof(T) > 1) {}
+}
+}
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -11876,8 +11876,33 @@
     // member-declarator shall be present only if the declarator declares a
     // templated function ([dcl.fct]).
     if (Expr *TRC = NewFD->getTrailingRequiresClause()) {
-      if (!NewFD->isTemplated() && !NewFD->isTemplateInstantiation())
+      // [temp.pre]/8:
+      // An entity is templated if it is
+      // - a template,
+      // - an entity defined ([basic.def]) or created ([class.temporary]) in a
+      // templated entity,
+      // - a member of a templated entity,
+      // - an enumerator for an enumeration that is a templated entity, or
+      // - the closure type of a lambda-expression ([expr.prim.lambda.closure])
+      // appearing in the declaration of a templated entity. [Note 6: A local
+      // class, a local or block variable, or a friend function defined in a
+      // templated entity is a templated entity.  — end note]
+      //
+      // A templated function is a function template or a function that is
+      // templated. A templated class is a class template or a class that is
+      // templated. A templated variable is a variable template or a variable
+      // that is templated.
+
+      if (!NewFD->getDescribedFunctionTemplate() && // -a template
+          // defined... in a templated entity
+          !(DeclIsDefn && NewFD->isTemplated()) &&
+          // a member of a templated entity
+          !(isa<CXXMethodDecl>(NewFD) && NewFD->isTemplated()) &&
+          // Don't complain about instantiations, they've already had these
+          // rules + others enforced.
+          !NewFD->isTemplateInstantiation()) {
         Diag(TRC->getBeginLoc(), diag::err_constrained_non_templated_function);
+      }
     }
 
     if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -248,7 +248,10 @@
 - Fix false-positive diagnostic issued for consteval initializers of temporary
   objects.
   (`#60286 <https://github.com/llvm/llvm-project/issues/60286>`_)
-
+- Correct restriction of trailing requirements clauses on a templated function.
+  Previously we only rejected non-'templated' things, but the restrictions ALSO need
+  to limit non-defined/non-member functions as well.
+  (`#61748 <https://github.com/llvm/llvm-project/issues/61748>`_)
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D147070.509078.patch
Type: text/x-patch
Size: 3647 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230328/c5fb33ca/attachment.bin>


More information about the cfe-commits mailing list