]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix "PR c++/91073 if constexpr no longer works directly with Concepts."
authorPaolo Carlini <paolo.carlini@oracle.com>
Wed, 15 Jan 2020 21:28:46 +0000 (22:28 +0100)
committerPaolo Carlini <paolo.carlini@oracle.com>
Wed, 15 Jan 2020 21:28:46 +0000 (22:28 +0100)
This is a rather serious regression, filed in July 2019. Luckily the
fix is simple: is localized to parser.c and cp-tree.h in cp and boils
down to only a few lines.

Testing OK on x86_64-linux. Approved off-line by Jason Merrill.

/cp
PR c++/91073
* cp-tree.h (is_constrained_auto): New.
* parser.c (cp_parser_maybe_commit_to_declaration): Correctly
handle concept-check expressions; take a cp_decl_specifier_seq*
instead of a bool.
(cp_parser_condition): Update call.
(cp_parser_simple_declaration): Likewise.
(cp_parser_placeholder_type_specifier): Correctly handle
concept-check expressions.

/testsuite
PR c++/91073
* g++.dg/concepts/pr91073-1.C: New.
* g++.dg/concepts/pr91073-2.C: Likewise.

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/concepts/pr91073-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/concepts/pr91073-2.C [new file with mode: 0644]

index 4a155795493ca94c9e31b8eddfa7ac676338e8c7..47d55e5066d608a96d9bdca9fe1058eaa8b3a88a 100644 (file)
@@ -1,3 +1,15 @@
+2020-01-15  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/91073
+       * cp-tree.h (is_constrained_auto): New.
+       * parser.c (cp_parser_maybe_commit_to_declaration): Correctly
+       handle concept-check expressions; take a cp_decl_specifier_seq*
+       instead of a bool.
+       (cp_parser_condition): Update call.
+       (cp_parser_simple_declaration): Likewise.
+       (cp_parser_placeholder_type_specifier): Correctly handle
+       concept-check expressions.
+
 2020-01-15  Jason Merrill  <jason@redhat.com>
 
        Revert
index 2b08d1b50cd822d38adf49d85e63f3ad5373675d..48cc44134bc8e9cedc4f3f2d526bd3b92d9f2365 100644 (file)
@@ -8069,6 +8069,14 @@ concept_check_p (const_tree t)
   return false;
 }
 
+/* True if t is a "constrained auto" type-specifier.  */
+
+inline bool
+is_constrained_auto (const_tree t)
+{
+  return is_auto (t) && PLACEHOLDER_TYPE_CONSTRAINTS (t);
+}
+
 #if CHECKING_P
 namespace selftest {
   extern void run_cp_tests (void);
index 2ddbe138ae66ade924bf137c1a9348a16e957c43..c5f9798a5edff308940d81d9ad2a7c47354d2bc2 100644 (file)
@@ -12053,18 +12053,22 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
 }
 
 /* Helper function for cp_parser_condition and cp_parser_simple_declaration.
-   If we have seen at least one decl-specifier, and the next token
-   is not a parenthesis, then we must be looking at a declaration.
-   (After "int (" we might be looking at a functional cast.)  */
+   If we have seen at least one decl-specifier, and the next token is not
+   a parenthesis (after "int (" we might be looking at a functional cast)
+   neither we are dealing with a concept-check expression then we must be
+   looking at a declaration.  */
 
 static void
 cp_parser_maybe_commit_to_declaration (cp_parser* parser,
-                                      bool any_specifiers_p)
+                                      cp_decl_specifier_seq *decl_specs)
 {
-  if (any_specifiers_p
+  if (decl_specs->any_specifiers_p
       && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)
       && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
-      && !cp_parser_error_occurred (parser))
+      && !cp_parser_error_occurred (parser)
+      && !(decl_specs->type
+          && TREE_CODE (decl_specs->type) == TYPE_DECL
+          && is_constrained_auto (TREE_TYPE (decl_specs->type))))
     cp_parser_commit_to_tentative_parse (parser);
 }
 
@@ -12139,8 +12143,7 @@ cp_parser_condition (cp_parser* parser)
      decl-specifiers.  */
   tree prefix_attributes = type_specifiers.attributes;
 
-  cp_parser_maybe_commit_to_declaration (parser,
-                                        type_specifiers.any_specifiers_p);
+  cp_parser_maybe_commit_to_declaration (parser, &type_specifiers);
 
   /* If all is well, we might be looking at a declaration.  */
   if (!cp_parser_error_occurred (parser))
@@ -13535,8 +13538,7 @@ cp_parser_simple_declaration (cp_parser* parser,
       goto done;
     }
 
-  cp_parser_maybe_commit_to_declaration (parser,
-                                        decl_specifiers.any_specifiers_p);
+  cp_parser_maybe_commit_to_declaration (parser, &decl_specifiers);
 
   /* Look for C++17 decomposition declaration.  */
   for (size_t n = 1; ; n++)
@@ -18266,6 +18268,10 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc,
       && !parser->in_result_type_constraint_p
       && !placeholder)
     {
+      if (tentative)
+       /* Perhaps it's a concept-check expression (c++/91073).  */
+       return error_mark_node;
+
       tree id = build_nt (TEMPLATE_ID_EXPR, tmpl, args);
       tree expr = DECL_P (orig_tmpl) ? DECL_NAME (con) : id;
       error_at (input_location,
index 769020d67ca622324f3c7ccdc5d5d52bc944d61d..143fda91d17d80cf2c10b8b4b1a9214510276f9c 100644 (file)
@@ -1,3 +1,9 @@
+2020-01-15  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/91073
+       * g++.dg/concepts/pr91073-1.C: New.
+       * g++.dg/concepts/pr91073-2.C: Likewise.
+
 2020-01-15  Wilco Dijkstra  <wdijkstr@arm.com>
 
        * gcc.dg/pr90838.c: New test.
diff --git a/gcc/testsuite/g++.dg/concepts/pr91073-1.C b/gcc/testsuite/g++.dg/concepts/pr91073-1.C
new file mode 100644 (file)
index 0000000..f5f3821
--- /dev/null
@@ -0,0 +1,37 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-fconcepts" }
+
+template<typename T, typename... Params>
+concept HasInit = requires(T t, Params... p) { t.init(p...); };
+
+struct Initable { void init(int) { } };
+struct Createable { void create(int) { } };
+
+struct Foo{
+  template<typename CB>
+  void for_each(CB&& cb)
+  {
+    Initable i;
+    Createable c;
+    cb(i);
+    cb(c);
+  }
+
+  Foo()
+  {
+    struct Bar { int x; };
+    for_each(
+            [&](auto& foo){
+             if constexpr (HasInit<decltype(foo), int>)
+                {
+                    foo.init(5);
+                }
+            });
+  }
+};
+
+int main()
+{
+  Foo f;
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/concepts/pr91073-2.C b/gcc/testsuite/g++.dg/concepts/pr91073-2.C
new file mode 100644 (file)
index 0000000..2900aae
--- /dev/null
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-fconcepts" }
+
+template<typename P, typename Arghhh = void>
+concept one_or_two = true;
+
+template<typename P>
+concept one = one_or_two<P>;
+
+template<typename T>
+constexpr void
+foo()
+{
+  if (one<T>) // OK
+  { }
+
+  if (one_or_two<T>) // { dg-bogus "before" }
+  { }
+}