https://gcc.gnu.org/g:e13e751d8144c9cfb7a9f1cd38119d1fa4ab38cf

commit r15-7122-ge13e751d8144c9cfb7a9f1cd38119d1fa4ab38cf
Author: Simon Martin <si...@nasilyan.com>
Date:   Wed Jan 22 10:44:32 2025 +0100

    c++: Clear TARGET_EXPR_ELIDING_P when forced to use a copy constructor due 
to __no_unique_address__ [PR118199]
    
    We currently fail with a checking assert upon the following valid code
    when using -fno-elide-constructors
    
    === cut here ===
    struct d { ~d(); };
    d &b();
    struct f {
      [[__no_unique_address__]] d e;
    };
    struct h : f  {
      h() : f{b()} {}
    } i;
    === cut here ===
    
    The problem is that split_nonconstant_init_1 detects that it cannot
    elide the copy constructor due to __no_unique_address__ but does not
    clear TARGET_EXPR_ELIDING_P, and due to -fno-elide-constructors, we trip
    on a checking assert in cp_gimplify_expr.
    
    This patch fixes this by making sure that we clear TARGET_EXPR_ELIDING_P
    if we determine that we have to keep the copy constructor due to
    __no_unique_address__. An alternative would be to just check for
    elide_constructors in that assert, but I think it'd lose most of its
    value if we did so.
    
            PR c++/118199
    
    gcc/cp/ChangeLog:
    
            * typeck2.cc (split_nonconstant_init_1): Clear
            TARGET_EXPR_ELIDING_P if we need to use a copy constructor
            because of __no_unique_address__.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/init/no-elide3.C: New test.

Diff:
---
 gcc/cp/typeck2.cc                     |  5 +++++
 gcc/testsuite/g++.dg/init/no-elide3.C | 12 ++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 15528baf0427..e88f6f0ad51d 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -655,6 +655,11 @@ split_nonconstant_init_1 (tree dest, tree init, bool last,
                          && make_safe_copy_elision (sub, value))
                        goto build_init;
 
+                     if (TREE_CODE (value) == TARGET_EXPR)
+                       /* We have to add this constructor, so we will not
+                          elide.  */
+                       TARGET_EXPR_ELIDING_P (value) = false;
+
                      tree name = (DECL_FIELD_IS_BASE (field_index)
                                   ? base_ctor_identifier
                                   : complete_ctor_identifier);
diff --git a/gcc/testsuite/g++.dg/init/no-elide3.C 
b/gcc/testsuite/g++.dg/init/no-elide3.C
new file mode 100644
index 000000000000..659eb19bc95a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/no-elide3.C
@@ -0,0 +1,12 @@
+// PR c++/118199
+// { dg-do "compile" { target c++11 } }
+// { dg-options "-fno-elide-constructors" } 
+
+struct d { ~d(); };
+d &b();
+struct f {
+  [[__no_unique_address__]] d e;
+};
+struct h : f  {
+  h() : f{b()} {}
+} i;

Reply via email to