From: Yuxuan Chen <[email protected]>

Removing trivial_abi from only the main type can leave qualified variants
with different attributes despite sharing a canonical type.  Remove the
rejected attribute from all variants.

gcc/cp/ChangeLog:

        PR c++/125064
        * tree.cc (validate_trivial_abi_attribute): Remove a rejected
        trivial_abi attribute from all variants.

gcc/testsuite/ChangeLog:

        PR c++/125064
        * g++.dg/cpp0x/attr-trivial_abi9.C: New test.
---
 gcc/cp/tree.cc                                | 22 ++++++++++---------
 .../g++.dg/cpp0x/attr-trivial_abi9.C          | 13 +++++++++++
 2 files changed, 25 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/attr-trivial_abi9.C

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index e543cf14519..086960d1855 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -6086,6 +6086,13 @@ validate_trivial_abi_attribute (tree type)
 
   gcc_assert (COMPLETE_TYPE_P (type));
 
+  auto remove_trivial_abi_attribute = [type] {
+    for (tree variant = TYPE_MAIN_VARIANT (type); variant;
+        variant = TYPE_NEXT_VARIANT (variant))
+      TYPE_ATTRIBUTES (variant)
+       = remove_attribute ("trivial_abi", TYPE_ATTRIBUTES (variant));
+  };
+
   /* Check for virtual bases.  */
   if (CLASSTYPE_VBASECLASSES (type))
     {
@@ -6093,8 +6100,7 @@ validate_trivial_abi_attribute (tree type)
       if (warning (OPT_Wattributes, "%<trivial_abi%> cannot be applied to %qT",
                   type))
        inform (input_location, "has a virtual base");
-      TYPE_ATTRIBUTES (type)
-       = remove_attribute ("trivial_abi", TYPE_ATTRIBUTES (type));
+      remove_trivial_abi_attribute ();
       return;
     }
 
@@ -6105,8 +6111,7 @@ validate_trivial_abi_attribute (tree type)
       if (warning (OPT_Wattributes, "%<trivial_abi%> cannot be applied to %qT",
                   type))
        inform (input_location, "is polymorphic");
-      TYPE_ATTRIBUTES (type)
-       = remove_attribute ("trivial_abi", TYPE_ATTRIBUTES (type));
+      remove_trivial_abi_attribute ();
       return;
     }
 
@@ -6126,8 +6131,7 @@ validate_trivial_abi_attribute (tree type)
                           "%<trivial_abi%> cannot be applied to %qT", type))
                inform (input_location, "has a non-trivial base class %qT",
                        base_type);
-             TYPE_ATTRIBUTES (type)
-               = remove_attribute ("trivial_abi", TYPE_ATTRIBUTES (type));
+             remove_trivial_abi_attribute ();
              return;
            }
        }
@@ -6147,8 +6151,7 @@ validate_trivial_abi_attribute (tree type)
                           "%<trivial_abi%> cannot be applied to %qT", type))
                inform (input_location, "has a non-static data member "
                        "of non-trivial type %qT", field_type);
-             TYPE_ATTRIBUTES (type)
-               = remove_attribute ("trivial_abi", TYPE_ATTRIBUTES (type));
+             remove_trivial_abi_attribute ();
              return;
            }
        }
@@ -6162,8 +6165,7 @@ validate_trivial_abi_attribute (tree type)
                   type))
        inform (input_location,
                "copy constructors and move constructors are all deleted");
-      TYPE_ATTRIBUTES (type)
-       = remove_attribute ("trivial_abi", TYPE_ATTRIBUTES (type));
+      remove_trivial_abi_attribute ();
       return;
     }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/attr-trivial_abi9.C 
b/gcc/testsuite/g++.dg/cpp0x/attr-trivial_abi9.C
new file mode 100644
index 00000000000..a7b18457ae1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/attr-trivial_abi9.C
@@ -0,0 +1,13 @@
+// PR c++/125064
+// { dg-do compile { target c++17 } }
+
+struct A;
+class [[clang::trivial_abi]] B {
+  B(B &&);
+};
+void f(A);
+struct [[clang::trivial_abi]] A { // { dg-warning "cannot be applied" }
+  A(...);
+  B b;
+};
+void g() { f(1); }
-- 
2.55.0

Reply via email to