diff options
author | Nathan Sidwell <nathan@acm.org> | 2023-10-20 12:20:37 -0400 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2023-10-20 16:24:49 -0400 |
commit | 084addf8a700fab9222d4127ab8524920d0ca481 (patch) | |
tree | 1ce1f519ced10494d25476a8a194e7e2ed2d124a /gcc | |
parent | 7069ea909f5292a17d22e5e68218373186820d29 (diff) | |
download | gcc-084addf8a700fab9222d4127ab8524920d0ca481.zip gcc-084addf8a700fab9222d4127ab8524920d0ca481.tar.gz gcc-084addf8a700fab9222d4127ab8524920d0ca481.tar.bz2 |
c++: Constructor streaming [PR105322]
An expresion node's type is streamed after the expression's operands,
because the type can come from some aspect of an operand (for instance
decltype and noexcept). There's a comment in the code explaining that.
But that doesn't work for constructors, which can directly reference
components of their type (eg FIELD_DECLS). If this is a
type-introducing CONSTRUCTOR, we need to ensure the type has been
streamed first. So move CONSTRUCTOR stream to after the type streaming.
The reason things like COMPONENT_REF work is that they stream their
first operand first, and that introduces the type that their second
operand looks up a field in.
gcc/cp/
PR c++/105322
* module.cc (trees_out::core_vals): Stream CONSTRUCTOR operands
after the type.
(trees_in::core_vals): Likewise.
gcc/testsuite/
* g++.dg/modules/decltype-1_a.C: New.
* g++.dg/modules/decltype-1_b.C: New.
* g++.dg/modules/lambda-5_a.C: New.
* g++.dg/modules/lambda-5_b.C: New.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/module.cc | 58 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/decltype-1_a.C | 28 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/decltype-1_b.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/lambda-5_a.C | 24 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/lambda-5_b.C | 10 |
5 files changed, 105 insertions, 25 deletions
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index bbb1e20..539518d 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -6212,19 +6212,9 @@ trees_out::core_vals (tree t) break; case CONSTRUCTOR: - { - unsigned len = vec_safe_length (t->constructor.elts); - if (streaming_p ()) - WU (len); - if (len) - for (unsigned ix = 0; ix != len; ix++) - { - const constructor_elt &elt = (*t->constructor.elts)[ix]; - - WT (elt.index); - WT (elt.value); - } - } + // This must be streamed /after/ we've streamed the type, + // because it can directly refer to elements of the type. Eg, + // FIELD_DECLs of a RECORD_TYPE. break; case OMP_CLAUSE: @@ -6458,6 +6448,21 @@ trees_out::core_vals (tree t) WU (prec); } + if (TREE_CODE (t) == CONSTRUCTOR) + { + unsigned len = vec_safe_length (t->constructor.elts); + if (streaming_p ()) + WU (len); + if (len) + for (unsigned ix = 0; ix != len; ix++) + { + const constructor_elt &elt = (*t->constructor.elts)[ix]; + + WT (elt.index); + WT (elt.value); + } + } + #undef WT #undef WU } @@ -6717,18 +6722,7 @@ trees_in::core_vals (tree t) break; case CONSTRUCTOR: - if (unsigned len = u ()) - { - vec_alloc (t->constructor.elts, len); - for (unsigned ix = 0; ix != len; ix++) - { - constructor_elt elt; - - RT (elt.index); - RTU (elt.value); - t->constructor.elts->quick_push (elt); - } - } + // Streamed after the node's type. break; case OMP_CLAUSE: @@ -6901,6 +6895,20 @@ trees_in::core_vals (tree t) t->typed.type = type; } + if (TREE_CODE (t) == CONSTRUCTOR) + if (unsigned len = u ()) + { + vec_alloc (t->constructor.elts, len); + for (unsigned ix = 0; ix != len; ix++) + { + constructor_elt elt; + + RT (elt.index); + RTU (elt.value); + t->constructor.elts->quick_push (elt); + } + } + #undef RT #undef RM #undef RU diff --git a/gcc/testsuite/g++.dg/modules/decltype-1_a.C b/gcc/testsuite/g++.dg/modules/decltype-1_a.C new file mode 100644 index 0000000..ca66e8b --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/decltype-1_a.C @@ -0,0 +1,28 @@ +// PR c++/105322 +// { dg-module-do link +// { dg-additional-options -fmodules-ts } +// { dg-module-cmi pr105322.Decltype } + +export module pr105322.Decltype; + +auto f() { + struct A { int m; + int get () { return m; } + }; + return A{}; +} + +export +inline void g1() { + auto r = decltype(f()){0}; +} + +export +inline void g2() { + auto r = f().m; +} + +export +inline void g3() { + auto r = f().get(); +} diff --git a/gcc/testsuite/g++.dg/modules/decltype-1_b.C b/gcc/testsuite/g++.dg/modules/decltype-1_b.C new file mode 100644 index 0000000..6bebe13 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/decltype-1_b.C @@ -0,0 +1,10 @@ +// PR c++/105322 +// { dg-additional-options -fmodules-ts } + +import pr105322.Decltype; + +int main() { + g1(); + g2(); + g3(); +} diff --git a/gcc/testsuite/g++.dg/modules/lambda-5_a.C b/gcc/testsuite/g++.dg/modules/lambda-5_a.C new file mode 100644 index 0000000..6b589d4 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-5_a.C @@ -0,0 +1,24 @@ +// PR c++/105322 +// { dg-module-do link +// { dg-additional-options -fmodules-ts } +// { dg-module-cmi pr105322.Lambda } + +export module pr105322.Lambda; + +struct A { }; + +export +inline void f1() { + A a; + auto g1 = [a] { }; // used to ICE here during stream out +} + +export +template<class...> +void f2() { + A a; + auto g2 = [a] { }; +} + +export +inline auto g3 = [a=A{}] { }; diff --git a/gcc/testsuite/g++.dg/modules/lambda-5_b.C b/gcc/testsuite/g++.dg/modules/lambda-5_b.C new file mode 100644 index 0000000..a7ce709 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-5_b.C @@ -0,0 +1,10 @@ +// PR c++/105322 +// { dg-additional-options -fmodules-ts } + +import pr105322.Lambda; + +int main() { + f1(); + f2(); + g3(); +} |