Hi!

The following testcase ICEs sionce my r14-650 PR109756 change to
set TREE_VALUE (attr) to error_mark_node for unsupported attributes
for which we've just skipped over balanced tokens for arguments in order
to differentiate that from no arguments.

The problem is that handle_namespace_attrs doesn't go through the normal
attribute handling and just checked attributes by name.
So, if user uses [[visibility (whatever)]] or
[[whatever::visibility (whatever)]] or similarly abi_tag or for deprecated
(which is valid as both [[deprecated ("foo")]] and
[[gnu::deprecated ("foo")]] ) [[whatever::deprecated (whatever)]] on
a namespace, we handle it as if it was a gnu or gnu or standard attribute
even when it is not and can ICE on error_mark_node attributes.

The following patch makes sure we handle it only in the right namespaces
and emit a warning on anything else.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Not sure about backports, the patch changes behavior for say
inline namespace [[foo::abi_tag]] N or
inline namespace [[abi_tag]] N where previously it would use the name
of the namespace as abi tag and now it will ignore it and emit a warning.
One possibility is to just deal with args == error_mark_node and warn
on that attribute only in that case (that is where it would previously ICE).
But perhaps I'm worrying too much and no code in the wild is relying on
non-gnu attributes on namespaces with the same names as the gnu ones
behaving like the gnu ones.

2026-01-23  Jakub Jelinek  <[email protected]>

        PR c++/123684
        * name-lookup.cc (handle_namespace_attrs): Only handle visibility and
        abi_tag attributes in the gnu namespace and deprecated attribute in
        the standard or gnu namespaces.

        * g++.dg/cpp0x/gen-attrs-90.C: New test.

--- gcc/cp/name-lookup.cc.jj    2026-01-15 16:33:46.981098402 +0100
+++ gcc/cp/name-lookup.cc       2026-01-22 12:06:47.759515087 +0100
@@ -6626,7 +6626,8 @@ handle_namespace_attrs (tree ns, tree at
       tree name = get_attribute_name (d);
       tree args = TREE_VALUE (d);
 
-      if (is_attribute_p ("visibility", name))
+      if (is_attribute_p ("visibility", name)
+         && is_attribute_namespace_p ("gnu", d))
        {
          /* attribute visibility is a property of the syntactic block
             rather than the namespace as a whole, so we don't touch the
@@ -6648,7 +6649,8 @@ handle_namespace_attrs (tree ns, tree at
          push_visibility (TREE_STRING_POINTER (x), 1);
          saw_vis = true;
        }
-      else if (is_attribute_p ("abi_tag", name))
+      else if (is_attribute_p ("abi_tag", name)
+              && is_attribute_namespace_p ("gnu", d))
        {
          if (!DECL_NAME (ns))
            {
@@ -6675,7 +6677,8 @@ handle_namespace_attrs (tree ns, tree at
            DECL_ATTRIBUTES (ns) = tree_cons (name, args,
                                              DECL_ATTRIBUTES (ns));
        }
-      else if (is_attribute_p ("deprecated", name))
+      else if (is_attribute_p ("deprecated", name)
+              && is_attribute_namespace_p ("", d))
        {
          if (!DECL_NAME (ns))
            {
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-90.C.jj        2026-01-22 
12:11:34.095705102 +0100
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-90.C   2026-01-22 12:12:40.925584625 
+0100
@@ -0,0 +1,8 @@
+// PR c++/123684
+// { dg-do compile { target c++11 } }
+
+inline namespace [[foo::abi_tag (1, 2, 3)]] A {}       // { dg-warning 
"'abi_tag' attribute directive ignored" }
+inline namespace [[foo::visibility (1, 2, 3)]] B {}    // { dg-warning 
"'visibility' attribute directive ignored" }
+inline namespace [[foo::deprecated (1, 2, 3)]] C {}    // { dg-warning 
"'deprecated' attribute directive ignored" }
+inline namespace [[abi_tag (1, 2, 3)]] D {}            // { dg-warning 
"'abi_tag' attribute directive ignored" }
+inline namespace [[visibility (1, 2, 3)]] E {}         // { dg-warning 
"'visibility' attribute directive ignored" }

        Jakub

Reply via email to