diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/cp-tree.h | 26 | ||||
-rw-r--r-- | gcc/cp/module.cc | 101 | ||||
-rw-r--r-- | gcc/cp/parser.cc | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/lambda-7.h | 42 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/lambda-7_a.H | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/lambda-7_b.C | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/lambda-7_c.C | 41 |
7 files changed, 174 insertions, 55 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 334c113..04c3aa6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1773,9 +1773,8 @@ check_constraint_info (tree t) (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (NODE))->u.base.module_entity_p) /* DECL that has attached decls for ODR-relatedness. */ -#define DECL_MODULE_KEYED_DECLS_P(NODE) \ - (DECL_LANG_SPECIFIC (TREE_CHECK2(NODE,FUNCTION_DECL,VAR_DECL))\ - ->u.base.module_keyed_decls_p) +#define DECL_MODULE_KEYED_DECLS_P(NODE) \ + (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (NODE))->u.base.module_keyed_decls_p) /* Whether this is an exported DECL. Held on any decl that can appear at namespace scope (function, var, type, template, const or @@ -2887,21 +2886,20 @@ struct GTY(()) lang_decl_base { unsigned friend_or_tls : 1; /* var, fn, type or template */ unsigned unknown_bound_p : 1; /* var */ unsigned odr_used : 1; /* var or fn */ - unsigned concept_p : 1; /* applies to vars and functions */ + unsigned concept_p : 1; /* applies to vars and functions */ unsigned var_declared_inline_p : 1; /* var */ unsigned dependent_init_p : 1; /* var */ - /* The following apply to VAR, FUNCTION, TYPE, CONCEPT, & NAMESPACE + /* The following four apply to VAR, FUNCTION, TYPE, CONCEPT, & NAMESPACE decls. */ - unsigned module_purview_p : 1; // in named-module purview - unsigned module_attach_p : 1; // attached to named module - unsigned module_import_p : 1; /* from an import */ - unsigned module_entity_p : 1; /* is in the entitity ary & - hash. */ - /* VAR_DECL or FUNCTION_DECL has keyed decls. */ - unsigned module_keyed_decls_p : 1; - - /* 12 spare bits. */ + unsigned module_purview_p : 1; /* in named-module purview */ + unsigned module_attach_p : 1; /* attached to named module */ + unsigned module_import_p : 1; /* from an import */ + unsigned module_entity_p : 1; /* is in the entitity ary & hash */ + + unsigned module_keyed_decls_p : 1; /* has keys, applies to all decls */ + + /* 11 spare bits. */ }; /* True for DECL codes which have template info and access. */ diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 106af7b..1b2ba2e 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -5664,8 +5664,7 @@ trees_out::lang_decl_bools (tree t) want to mark them as in module purview. */ WB (lang->u.base.module_purview_p && !header_module_p ()); WB (lang->u.base.module_attach_p); - if (VAR_OR_FUNCTION_DECL_P (t)) - WB (lang->u.base.module_keyed_decls_p); + WB (lang->u.base.module_keyed_decls_p); switch (lang->u.base.selector) { default: @@ -5738,8 +5737,7 @@ trees_in::lang_decl_bools (tree t) RB (lang->u.base.dependent_init_p); RB (lang->u.base.module_purview_p); RB (lang->u.base.module_attach_p); - if (VAR_OR_FUNCTION_DECL_P (t)) - RB (lang->u.base.module_keyed_decls_p); + RB (lang->u.base.module_keyed_decls_p); switch (lang->u.base.selector) { default: @@ -7871,8 +7869,7 @@ trees_out::decl_value (tree decl, depset *dep) install_entity (decl, dep); } - if (VAR_OR_FUNCTION_DECL_P (inner) - && DECL_LANG_SPECIFIC (inner) + if (DECL_LANG_SPECIFIC (inner) && DECL_MODULE_KEYED_DECLS_P (inner) && !is_key_order ()) { @@ -8172,8 +8169,7 @@ trees_in::decl_value () bool installed = install_entity (existing); bool is_new = existing == decl; - if (VAR_OR_FUNCTION_DECL_P (inner) - && DECL_LANG_SPECIFIC (inner) + if (DECL_LANG_SPECIFIC (inner) && DECL_MODULE_KEYED_DECLS_P (inner)) { /* Read and maybe install the attached entities. */ @@ -9187,6 +9183,13 @@ trees_in::tree_value () return NULL_TREE; } + if (TREE_CODE (t) == LAMBDA_EXPR + && CLASSTYPE_LAMBDA_EXPR (TREE_TYPE (t))) + { + existing = CLASSTYPE_LAMBDA_EXPR (TREE_TYPE (t)); + back_refs[~tag] = existing; + } + dump (dumper::TREE) && dump ("Read tree:%d %C:%N", tag, TREE_CODE (t), t); if (TREE_CODE (existing) == INTEGER_CST && !TREE_OVERFLOW (existing)) @@ -10484,12 +10487,17 @@ trees_out::get_merge_kind (tree decl, depset *dep) if (tree scope = LAMBDA_EXPR_EXTRA_SCOPE (CLASSTYPE_LAMBDA_EXPR (TREE_TYPE (decl)))) - if (TREE_CODE (scope) == VAR_DECL - && DECL_MODULE_KEYED_DECLS_P (scope)) - { - mk = MK_keyed; - break; - } + { + /* Lambdas attached to fields are keyed to its class. */ + if (TREE_CODE (scope) == FIELD_DECL) + scope = TYPE_NAME (DECL_CONTEXT (scope)); + if (DECL_LANG_SPECIFIC (scope) + && DECL_MODULE_KEYED_DECLS_P (scope)) + { + mk = MK_keyed; + break; + } + } if (RECORD_OR_UNION_TYPE_P (ctx)) { @@ -10789,7 +10797,13 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, gcc_checking_assert (LAMBDA_TYPE_P (TREE_TYPE (inner))); tree scope = LAMBDA_EXPR_EXTRA_SCOPE (CLASSTYPE_LAMBDA_EXPR (TREE_TYPE (inner))); - gcc_checking_assert (TREE_CODE (scope) == VAR_DECL); + gcc_checking_assert (TREE_CODE (scope) == VAR_DECL + || TREE_CODE (scope) == FIELD_DECL + || TREE_CODE (scope) == PARM_DECL + || TREE_CODE (scope) == TYPE_DECL); + /* Lambdas attached to fields are keyed to the class. */ + if (TREE_CODE (scope) == FIELD_DECL) + scope = TYPE_NAME (DECL_CONTEXT (scope)); auto *root = keyed_table->get (scope); unsigned ix = root->length (); /* If we don't find it, we'll write a really big number @@ -11067,6 +11081,26 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, } } } + else if (mk == MK_keyed + && DECL_LANG_SPECIFIC (name) + && DECL_MODULE_KEYED_DECLS_P (name)) + { + gcc_checking_assert (TREE_CODE (container) == NAMESPACE_DECL + || TREE_CODE (container) == TYPE_DECL); + if (auto *set = keyed_table->get (name)) + if (key.index < set->length ()) + { + existing = (*set)[key.index]; + if (existing) + { + gcc_checking_assert + (DECL_IMPLICIT_TYPEDEF_P (existing)); + if (inner != decl) + existing + = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (existing)); + } + } + } else switch (TREE_CODE (container)) { @@ -11074,27 +11108,8 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, gcc_unreachable (); case NAMESPACE_DECL: - if (mk == MK_keyed) - { - if (DECL_LANG_SPECIFIC (name) - && VAR_OR_FUNCTION_DECL_P (name) - && DECL_MODULE_KEYED_DECLS_P (name)) - if (auto *set = keyed_table->get (name)) - if (key.index < set->length ()) - { - existing = (*set)[key.index]; - if (existing) - { - gcc_checking_assert - (DECL_IMPLICIT_TYPEDEF_P (existing)); - if (inner != decl) - existing - = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (existing)); - } - } - } - else if (is_attached - && !(state->is_module () || state->is_partition ())) + if (is_attached + && !(state->is_module () || state->is_partition ())) kind = "unique"; else { @@ -18984,11 +18999,19 @@ maybe_key_decl (tree ctx, tree decl) if (!modules_p ()) return; - // FIXME: For now just deal with lambdas attached to var decls. - // This might be sufficient? - if (TREE_CODE (ctx) != VAR_DECL) + /* We only need to deal with lambdas attached to var, field, + parm, or type decls. */ + if (TREE_CODE (ctx) != VAR_DECL + && TREE_CODE (ctx) != FIELD_DECL + && TREE_CODE (ctx) != PARM_DECL + && TREE_CODE (ctx) != TYPE_DECL) return; + /* For fields, key it to the containing type to handle deduplication + correctly. */ + if (TREE_CODE (ctx) == FIELD_DECL) + ctx = TYPE_NAME (DECL_CONTEXT (ctx)); + if (!keyed_table) keyed_table = new keyed_map_t (EXPERIMENT (1, 400)); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index b2ed2ba..3ee9d49 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -27678,10 +27678,16 @@ cp_parser_class_head (cp_parser* parser, if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) { if (type) - pushclass (type); + { + pushclass (type); + start_lambda_scope (TYPE_NAME (type)); + } bases = cp_parser_base_clause (parser); if (type) - popclass (); + { + finish_lambda_scope (); + popclass (); + } } else bases = NULL_TREE; diff --git a/gcc/testsuite/g++.dg/modules/lambda-7.h b/gcc/testsuite/g++.dg/modules/lambda-7.h new file mode 100644 index 0000000..6f6080c --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-7.h @@ -0,0 +1,42 @@ +struct S { + int (*a)(int) = [](int x) { return x * 2; }; + + int b(int x, int (*f)(int) = [](int x) { return x * 3; }) { + return f(x); + } + + static int c(int x, int (*f)(int) = [](int x) { return x * 4; }) { + return f(x); + } +}; + +inline int d(int x, int (*f)(int) = [](int x) { return x * 5; }) { + return f(x); +} + +// unevaluated lambdas +#if __cplusplus >= 202002L +struct E : decltype([](int x) { return x * 6; }) { + decltype([](int x) { return x * 7; }) f; +}; + +template <typename T> +struct G : decltype([](int x) { return x * 8; }) { + decltype([](int x) { return x * 9; }) h; +}; + +template <> +struct G<double> : decltype([](int x) { return x * 10; }) { + decltype([](int x) { return x * 11; }) i; +}; +#endif + +// concepts +#if __cpp_concepts >= 201907L +template <typename T> +concept J = requires { []{ T(); }; }; + +template <typename T> +concept K = []{ return sizeof(T) == 1; }(); +#endif + diff --git a/gcc/testsuite/g++.dg/modules/lambda-7_a.H b/gcc/testsuite/g++.dg/modules/lambda-7_a.H new file mode 100644 index 0000000..5197114 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-7_a.H @@ -0,0 +1,4 @@ +// { dg-additional-options "-fmodule-header -Wno-subobject-linkage" } +// { dg-module-cmi {} } + +#include "lambda-7.h" diff --git a/gcc/testsuite/g++.dg/modules/lambda-7_b.C b/gcc/testsuite/g++.dg/modules/lambda-7_b.C new file mode 100644 index 0000000..2d781e9 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-7_b.C @@ -0,0 +1,5 @@ +// { dg-additional-options "-fmodules-ts -fno-module-lazy -Wno-subobject-linkage" } +// Test for ODR deduplication + +#include "lambda-7.h" +import "lambda-7_a.H"; diff --git a/gcc/testsuite/g++.dg/modules/lambda-7_c.C b/gcc/testsuite/g++.dg/modules/lambda-7_c.C new file mode 100644 index 0000000..f283681 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-7_c.C @@ -0,0 +1,41 @@ +// { dg-module-do run } +// { dg-additional-options "-fmodules-ts -fno-module-lazy -Wno-subobject-linkage" } + +import "lambda-7_a.H"; + +int main() { + S s; + if (s.a(10) != 20) + __builtin_abort(); + if (s.b(10) != 30) + __builtin_abort(); + if (s.c(10) != 40) + __builtin_abort(); + if (d(10) != 50) + __builtin_abort(); + +#if __cplusplus >= 202002L + E e; + if (e(10) != 60) + __builtin_abort(); + if (e.f(10) != 70) + __builtin_abort(); + + G<int> g1; + if (g1(10) != 80) + __builtin_abort(); + if (g1.h(10) != 90) + __builtin_abort(); + + G<double> g2; + if (g2(10) != 100) + __builtin_abort(); + if (g2.i(10) != 110) + __builtin_abort(); +#endif + +#if __cpp_concepts >= 201907L + static_assert(J<char>); + static_assert(K<char>); +#endif +} |