+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
}
/* 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);
}
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))
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++)
&& !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,
--- /dev/null
+// { 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;
+}