c++: Concepts and local externs
authorNathan Sidwell <nathan@acm.org>
Fri, 11 Sep 2020 20:42:59 +0000 (13:42 -0700)
committerNathan Sidwell <nathan@acm.org>
Fri, 11 Sep 2020 20:55:45 +0000 (13:55 -0700)
I discovered that we'd accept constraints on block-scope function
decls inside templates.  This fixes that.

gcc/cp/
* decl.c (grokfndecl): Don't attach to local extern.

gcc/cp/decl.c
gcc/testsuite/g++.dg/concepts/local-extern.C [new file with mode: 0644]

index 8922ef54d7448327cbdab3059a5a51b55a8f3a63..ad2a30fcf71867bf2347b6fda2773211d6ec7e1a 100644 (file)
@@ -9457,7 +9457,10 @@ grokfndecl (tree ctype,
     {
       tree tmpl_reqs = NULL_TREE;
       tree ctx = friendp ? current_class_type : ctype;
-      bool memtmpl = (processing_template_decl > template_class_depth (ctx));
+      bool block_local = TREE_CODE (current_scope ()) == FUNCTION_DECL;
+      bool memtmpl = (!block_local
+                     && (processing_template_decl
+                         > template_class_depth (ctx)));
       if (memtmpl)
         tmpl_reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
       tree ci = build_constraints (tmpl_reqs, decl_reqs);
@@ -9467,9 +9470,11 @@ grokfndecl (tree ctype,
           ci = NULL_TREE;
         }
       /* C++20 CA378: Remove non-templated constrained functions.  */
-      if (ci && !flag_concepts_ts
-         && (!processing_template_decl
-             || (friendp && !memtmpl && !funcdef_flag)))
+      if (ci
+         && (block_local
+             || (!flag_concepts_ts
+                 && (!processing_template_decl
+                     || (friendp && !memtmpl && !funcdef_flag)))))
        {
          error_at (location, "constraints on a non-templated function");
          ci = NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/concepts/local-extern.C b/gcc/testsuite/g++.dg/concepts/local-extern.C
new file mode 100644 (file)
index 0000000..69ecc23
--- /dev/null
@@ -0,0 +1,39 @@
+// { dg-do compile { target c++17 } }
+// { dg-additional-options -fconcepts }
+
+// Don't attach constraints to block-scope fn-decls and ICE
+
+template<typename _Iter>
+    concept input_or_output_iterator
+      = requires(_Iter __i) { { *__i } ; };
+
+
+  template<input_or_output_iterator _It>
+  class common_iterator
+  {
+
+  public:
+    
+void
+      frob ()
+    {
+      if (__builtin_is_constant_evaluated())
+       {
+         void __failed_assertion(); // ICEd
+         if (!bool(_M_index == 0)) __failed_assertion();
+       }
+
+    }
+
+  private:
+    unsigned char _M_index;
+  };
+
+template <typename T> concept C = true;
+
+template<typename T>
+void F ()
+{
+  void bad () requires C<T>; // { dg-error "a non-templated function" }
+  
+}