aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Carlini <paolo.carlini@oracle.com>2020-01-15 22:28:46 +0100
committerPaolo Carlini <paolo.carlini@oracle.com>2020-01-15 22:28:46 +0100
commit83fe2b921830c177e3dee514aa07cbc7c8ceef1c (patch)
tree9754091a4864e4d6aa92c7df7031bc5253b07d07
parent299ddc612136421f1d9865ea4f2f84f7e3791824 (diff)
downloadgcc-83fe2b921830c177e3dee514aa07cbc7c8ceef1c.zip
gcc-83fe2b921830c177e3dee514aa07cbc7c8ceef1c.tar.gz
gcc-83fe2b921830c177e3dee514aa07cbc7c8ceef1c.tar.bz2
Fix "PR c++/91073 if constexpr no longer works directly with Concepts."
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.
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/cp-tree.h8
-rw-r--r--gcc/cp/parser.c26
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr91073-1.C37
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr91073-2.C19
6 files changed, 98 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4a15579..47d55e5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2b08d1b..48cc441 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2ddbe13..c5f9798 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 769020d..143fda9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..f5f3821
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr91073-1.C
@@ -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
index 0000000..2900aae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr91073-2.C
@@ -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" }
+ { }
+}