aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-tree.h26
-rw-r--r--gcc/cp/module.cc101
-rw-r--r--gcc/cp/parser.cc10
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-7.h42
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-7_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-7_b.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-7_c.C41
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
+}