(((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->locus)
/* The mangling scope for the lambda: FUNCTION_DECL, PARM_DECL, VAR_DECL,
- FIELD_DECL or NULL_TREE. If this is NULL_TREE, we have no linkage. */
+ FIELD_DECL, TYPE_DECL, or NULL_TREE. If this is NULL_TREE, we have no
+ linkage. */
#define LAMBDA_EXPR_EXTRA_SCOPE(NODE) \
(((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_scope)
if (!braces.require_open (parser))
{
pop_deferring_access_checks ();
+ if (type != error_mark_node)
+ finish_lambda_scope ();
return error_mark_node;
}
if (cp_parser_allow_gnu_extensions_p (parser))
attributes = cp_parser_gnu_attributes_opt (parser);
if (type != error_mark_node)
- type = finish_struct (type, attributes);
+ {
+ type = finish_struct (type, attributes);
+ finish_lambda_scope ();
+ }
if (nested_name_specifier_p)
pop_inner_scope (old_scope, scope);
if (flag_concepts)
type = associate_classtype_constraints (type);
+ /* Lambdas in bases and members must have the same mangling scope for ABI.
+ We open this scope now, and will close it in cp_parser_class_specifier
+ after parsing the member list. */
+ if (type && type != error_mark_node)
+ start_lambda_scope (TYPE_NAME (type));
+
/* We will have entered the scope containing the class; the names of
base classes should be looked up in that context. For example:
if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
if (type)
- {
- pushclass (type);
- start_lambda_scope (TYPE_NAME (type));
- }
+ pushclass (type);
bases = cp_parser_base_clause (parser);
if (type)
- {
- finish_lambda_scope ();
- popclass ();
- }
+ popclass ();
}
else
bases = NULL_TREE;
gcc_assert (!DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (pattern))
|| COMPLETE_OR_OPEN_TYPE_P (TYPE_CONTEXT (type)));
+ /* When instantiating nested lambdas, ensure that they get the mangling
+ scope of the new class type. */
+ start_lambda_scope (TYPE_NAME (type));
+
base_list = NULL_TREE;
/* Defer access checking while we substitute into the types named in
the base-clause. */
finish_struct_1 (type);
TYPE_BEING_DEFINED (type) = 0;
+ finish_lambda_scope ();
+
/* Remember if instantiating this class ran into errors, so we can avoid
instantiating member functions in limit_bad_template_recursion. We set
this flag even if the problem was in another instantiation triggered by
--- /dev/null
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fkeep-inline-functions" }
+// See also https://github.com/itanium-cxx-abi/cxx-abi/pull/85
+
+struct A {
+ decltype([]{ return 1; }) f;
+};
+
+struct B : decltype([]{ return 2; }) {
+ decltype([]{ return 3; }) f;
+};
+
+template <typename T>
+struct C : decltype([]{ return 4; }) {
+ decltype([]{ return 5; }) f;
+};
+
+template struct C<int>;
+template struct C<double>;
+
+// { dg-final { scan-assembler {_ZNK1AUlvE_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1BUlvE_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1BUlvE0_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1CIiEUlvE_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1CIiEUlvE0_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1CIdEUlvE_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1CIdEUlvE0_clEv:} } }
--- /dev/null
+// { dg-do compile { target c++20 } }
+
+struct S {
+ template <int I>
+ using T = decltype([]{ return I; });
+
+ template <int I>
+ decltype([]{ return I; }) f() { return {}; }
+};
+
+void a(S::T<0>*); // { dg-error "declared using local type" }
+void b(S::T<1>*); // { dg-error "declared using local type" }
+void c(decltype(S{}.f<0>())*); // { dg-error "declared using local type" }
+void d(decltype(S{}.f<1>())*); // { dg-error "declared using local type" }
+
+int main() {
+ a(nullptr);
+ b(nullptr);
+ c(nullptr);
+ d(nullptr);
+}
--- /dev/null
+// PR c++/118245
+// { dg-do compile { target c++20 } }
+
+template<auto> struct Cask {};
+struct T1 : Cask<[]{}> {
+ Cask<[]{}> c{};
+};