/* true for SK_FUNCTION_PARMS of immediate functions. */
unsigned immediate_fn_ctx_p : 1;
- /* 22 bits left to fill a 32-bit word. */
+ /* True for SK_FUNCTION_PARMS of a requires-expression. */
+ unsigned requires_expression: 1;
+
+ /* 21 bits left to fill a 32-bit word. */
};
/* The binding level currently in effect. */
scope_sentinel ()
{
++cp_unevaluated_operand;
- begin_scope (sk_block, NULL_TREE);
+ begin_scope (sk_function_parms, NULL_TREE);
+ current_binding_level->requires_expression = true;
}
~scope_sentinel ()
synthesize_implicit_template_parm (cp_parser *parser, tree constr)
{
/* A requires-clause is not a function and cannot have placeholders. */
- if (current_binding_level->kind == sk_block)
+ if (current_binding_level->requires_expression)
{
error ("placeholder type not allowed in this context");
return error_mark_node;
template<typename T>
concept C1 = requires (C1 auto x) { // { dg-error "not been declared|placeholder|two or more|in requirements" }
x; // { dg-error "not declared" }
- { x } -> c; // { dg-message "is invalid" }
+ { x } -> c; // { dg-message "is invalid|not declared" }
};
template<typename T>
--- /dev/null
+// PR c++/101677
+// { dg-do compile { target c++20 } }
+
+template<class T>
+concept C_bug_with_forward_decl = requires(T& t){
+ t.template f<class S>();
+};
+
+struct good {
+ template<class T> void f() {}
+};
+
+static_assert(C_bug_with_forward_decl<good>);