Hi, The following C++ code fails to compile with gcc trunk but works on gcc 9 and 10 (tested on compiler explorer): #include <memory> struct A { std::unique_ptr<int> _member; virtual ~A(){} }; A a; Compiled without any CXXFLAGS on x64 Linux. Compiler explorer shows: <source>:10:4: internal compiler error: in output_constructor_regular_field, at varasm.c:5491 10 | A a; | ^ 0x1cba449 internal_error(char const*, ...) ???:0 0x6b0031 fancy_abort(char const*, int, char const*) ???:0 0x13ceaf3 assemble_variable(tree_node*, int, int, int) ???:0 0xb4207f symbol_table::finalize_compilation_unit() ???:0 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. Compiler returned: 1 Cheers, Romain
This is triggered by r11-2720.
That just exposes a latent compiler bug though. Slightly reduced: #include <tuple> struct empty { }; struct A { std::tuple<int, empty> _member; virtual ~A(){} }; A a;
Hi, While I initially flagged this as a regression in gcc 11, it's indeed a latent gcc bug which predates gcc 11. What makes it for my specific test case a regression is because now tuple use [[no_unique_address]] which seems to be already identified as creating ICEs in issues #96863 and #97804. Cheers, Romain
Reduced testcase: template <typename T> struct A { constexpr A () : a() {} [[no_unique_address]] T a; }; template <unsigned long, typename...> struct B; template <unsigned long T, typename U, typename... V> struct B<T, U, V...> : B<1, V...>, A<U> {}; template <unsigned long T, typename U> struct B<T, U> : A<U> {}; template <typename... h> struct C : B<0, h...> {}; struct D {}; struct E { C<int, D> k; virtual ~E (); } a; Started to ICE with r9-5710-g7e574f68fa82e7c5f879fd468291ec8b5ebecc83
On #c4, I think the problem is during cxx_eval_store_expression of ((struct A *) this)->a = {}; where this has A * type, but the *valp CONSTRUCTOR we try to get_or_insert_ctor_field it into has type B. We insert it with FIELD_DECL a which is A's member, but the CONSTRUCTOR handling assumes (rightfully) that the FIELD_DECLs in the CONSTRUCTOR_ELTS indexes are from the type of the CONSTRUCTOR.
Created attachment 49911 [details] gcc11-pr98463.patch Untested fix. Before the PR49290 changes, the empty_base = true; stuff has been guarded on !addr i.e. !lval, but since r0-109524-g11f449abc6fc745486699f2f7079497d4c582d40 it doesn't do that anymore. This patch just restores that behavior.
Unfortunately that patch regresses +FAIL: g++.dg/cpp0x/constexpr-empty9.C -std=c++11 (test for excess errors) +FAIL: g++.dg/cpp0x/constexpr-empty9.C -std=c++14 (test for excess errors) +FAIL: g++.dg/cpp0x/constexpr-tuple2.C -std=c++11 (test for excess errors) +FAIL: g++.dg/cpp0x/constexpr-tuple2.C -std=c++14 (test for excess errors) +FAIL: g++.dg/cpp1y/constexpr-empty2.C -std=c++14 (test for excess errors) +FAIL: g++.dg/cpp1y/constexpr-tracking-const24.C -std=c++14 (test for excess errors) +FAIL: 20_util/tuple/comparison_operators/overloaded.cc (test for excess errors) Out of ideas what to do with this.
With the patch for C++14 and older the problem is that the empty base has no FIELD_DECL in the RECORD_TYPE at all, so it then doesn't find anything. So for the empty_base && lval case it might be better to return some tree that would make it clear to the caller that the code is valid but that it shouldn't really store anything into it. But still, for C++17 and onwards, we shouldn't be setting empty_base for the lval case if we can find the FIELD_DECL for it (so perhaps for lval move the is_empty_class check to the end) and otherwise figure out what to return. A freshly created VAR_DECL, or one that is cached (same VAR_DECL for the same type), something else?
*** Bug 98579 has been marked as a duplicate of this bug. ***
*** Bug 96863 has been marked as a duplicate of this bug. ***
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:94ff4c9dd98f39280fba22d1ad0958fb25a5363b commit r11-6895-g94ff4c9dd98f39280fba22d1ad0958fb25a5363b Author: Jason Merrill <jason@redhat.com> Date: Fri Jan 22 13:17:10 2021 -0500 c++: [[no_unique_address]] in empty base [PR98463] In this testcase, cxx_eval_store_expression got confused trying to build up CONSTRUCTORs for initializing a subobject because the subobject is a member of an empty base. In C++14 mode and below we don't build FIELD_DECLs for empty bases, so the CONSTRUCTOR skipped the empty base, and treated the member as a member of the derived class, which breaks. Fixed by recognizing this situation and giving up on trying to build a CONSTRUCTOR for the inner target at that point; since it doesn't have any data, we don't need to actually store anything. gcc/cp/ChangeLog: PR c++/98463 * constexpr.c (get_or_insert_ctor_field): Add check. (cxx_eval_store_expression): Handle discontinuity of refs. gcc/testsuite/ChangeLog: PR c++/98463 * g++.dg/cpp2a/no_unique_address8.C: New test.
Fixed.
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:a4dfd0f089af33f2af57bf422f9859405b9b4a16 commit r11-6918-ga4dfd0f089af33f2af57bf422f9859405b9b4a16 Author: Jason Merrill <jason@redhat.com> Date: Sun Jan 24 00:55:49 2021 -0500 c++: constexpr and empty fields [PR97566] In the discussion of PR98463, Jakub pointed out that in C++17 and up, cxx_fold_indirect_ref_1 could use the field we build for an empty base. I tried implementing that, but it broke one of the tuple tests, so I did some more digging. To start with, I generalized the PR98463 patch to handle the case where we do have a field, for an empty base or [[no_unique_address]] member. This is enough also for the no-field case because the member of the empty base must itself be an empty field; if it weren't, the base would not be empty. I looked for related PRs and found 97566, which was also fixed by the patch. After some poking around to figure out why, I noticed that the testcase had been breaking because E, though an empty class, has an ABI nvsize of one byte, and we were giving the [[no_unique_address]] FIELD_DECL that DECL_SIZE, whereas in build_base_field_1 empty base fields always get DECL_SIZE zero, and various places were relying on that to recognize empty fields. So I adjusted both the size and the checking. When I adjusted check_bases I wondered if we were correctly handling bases with only empty data members, but it appears we do. I'm deferring the cxx_fold_indirect_ref_1 change until stage 1, as I don't think it actually fixes anything. gcc/cp/ChangeLog: PR c++/97566 PR c++/98463 * class.c (layout_class_type): An empty field gets size 0. (is_empty_field): New. (check_bases): Check it. * cp-tree.h (is_empty_field): Declare it. * constexpr.c (cxx_eval_store_expression): Check it. (cx_check_missing_mem_inits): Likewise. * init.c (perform_member_init): Likewise. * typeck2.c (process_init_constructor_record): Likewise. gcc/testsuite/ChangeLog: PR c++/97566 * g++.dg/cpp2a/no_unique_address10.C: New test. * g++.dg/cpp2a/no_unique_address9.C: New test.
The releases/gcc-10 branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:2127d2c3ee23bbd03f02d88fd82403408696ee4a commit r10-9314-g2127d2c3ee23bbd03f02d88fd82403408696ee4a Author: Jason Merrill <jason@redhat.com> Date: Fri Jan 22 13:17:10 2021 -0500 c++: [[no_unique_address]] in empty base [PR98463] In this testcase, cxx_eval_store_expression got confused trying to build up CONSTRUCTORs for initializing a subobject because the subobject is a member of an empty base. In C++14 mode and below we don't build FIELD_DECLs for empty bases, so the CONSTRUCTOR skipped the empty base, and treated the member as a member of the derived class, which breaks. Fixed by recognizing this situation and giving up on trying to build a CONSTRUCTOR for the inner target at that point; since it doesn't have any data, we don't need to actually store anything. gcc/cp/ChangeLog: PR c++/98463 * constexpr.c (get_or_insert_ctor_field): Add check. (cxx_eval_store_expression): Handle discontinuity of refs. gcc/testsuite/ChangeLog: PR c++/98463 * g++.dg/cpp2a/no_unique_address8.C: New test.