diff options
author | Jakub Jelinek <jakub@redhat.com> | 2025-03-06 18:26:37 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2025-03-06 18:26:37 +0100 |
commit | 179e01085b0aed111ef1f7908c4b87c800f880e9 (patch) | |
tree | d3ca396d5628fd1ed79880a8ca9c6d619e915da4 /gcc/testsuite/g++.dg/cpp0x | |
parent | 0ba3e5ff14a48f1fb7ca53cb86194e08d5b5da66 (diff) | |
download | gcc-179e01085b0aed111ef1f7908c4b87c800f880e9.zip gcc-179e01085b0aed111ef1f7908c4b87c800f880e9.tar.gz gcc-179e01085b0aed111ef1f7908c4b87c800f880e9.tar.bz2 |
c++: Update TYPE_FIELDS of variant types if cp_parser_late_parsing_default_args etc. modify it [PR98533]
The following testcases ICE during type verification, because TYPE_FIELDS
of e.g. S RECORD_TYPE in pr119123.C is different from TYPE_FIELDS of const S.
Various decls are added to S's TYPE_FIELDS first, then finish_struct
indirectly calls fixup_type_variants to sync the variant copies.
But later on cp_parser_class_specifier calls
cp_parser_late_parsing_default_args and that apparently adds a lambda
type (from default argument) to TYPE_FIELDS of S.
Dunno if that is right or not, assuming it is right, the following
patch fixes it by updating TYPE_FIELDS of variant types if there were
any changes in the various functions cp_parser_class_specifier defers and
calls on the outermost enclosing class.
There was quite a lot of code repetition already before, so the patch
uses a lambda to avoid the repetitions.
To my surprise, in some of the contract testcases (
g++.dg/contracts/contracts-friend1.C
g++.dg/contracts/contracts-nested-class1.C
g++.dg/contracts/contracts-nested-class2.C
g++.dg/contracts/contracts-redecl7.C
g++.dg/contracts/contracts-redecl8.C
) it is actually setting class_type and pushing TRANSLATION_UNIT_DECL
rather than some class types in some cases.
Or should the lambda pushing into the containing class be somehow avoided?
2025-03-06 Jakub Jelinek <jakub@redhat.com>
PR c++/98533
PR c++/119123
* parser.cc (cp_parser_class_specifier): Update TYPE_FIELDS of
variant types in case cp_parser_late_parsing_default_args etc. change
TYPE_FIELDS on the main variant. Add switch_to_class lambda and
use it to simplify repeated class switching code.
* g++.dg/cpp0x/pr98533.C: New test.
* g++.dg/cpp0x/pr119123.C: New test.
Diffstat (limited to 'gcc/testsuite/g++.dg/cpp0x')
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr119123.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr98533.C | 25 |
2 files changed, 35 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr119123.C b/gcc/testsuite/g++.dg/cpp0x/pr119123.C new file mode 100644 index 0000000..bbc1ca0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr119123.C @@ -0,0 +1,10 @@ +// PR c++/119123 +// { dg-do compile { target c++11 } } +// { dg-options "-O2 -g" } + +struct S { + template <typename> void foo (int = [] {}) const; +}; +struct T { + static void bar (const S &); +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr98533.C b/gcc/testsuite/g++.dg/cpp0x/pr98533.C new file mode 100644 index 0000000..c279d02 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr98533.C @@ -0,0 +1,25 @@ +// PR c++/98533 +// { dg-do compile { target c++11 } } +// { dg-options "-g" } + +class IR; +struct Pass { + explicit Pass(IR *ir) : ir_(ir) {} + virtual ~Pass() = default; + IR *ir_ {nullptr}; +}; +struct PassManager { + template <typename T> void RunPass() { T pass(ir_); } + IR *ir_ {nullptr}; +}; +struct IR final { + template <typename T> void RunPass() { pass_manager_.RunPass<T>(); } + PassManager pass_manager_; +}; +struct ThePass : Pass { + explicit ThePass(IR *ir) : Pass(ir) {} + ThePass(const ThePass &) = delete; + template <typename Func = bool (*)(void *)> void Bar(void *inst, Func func = [](void *) {}); +}; + +void foo(IR *ir) { ir->RunPass<ThePass>(); } |