https://gcc.gnu.org/g:19505078164bf791d661d87d1069e5f50cd33417

commit r16-8396-g19505078164bf791d661d87d1069e5f50cd33417
Author: Jakub Jelinek <[email protected]>
Date:   Wed Apr 1 20:13:23 2026 +0200

    c++: Implement CWG3124 - Disallow annotations on block-scope externs and 
non-unique friend declarations
    
    This issue says it is invalid to declare annotations on local externs or
    non-defining friends and their arguments (if any).
    
    2026-04-01  Jakub Jelinek  <[email protected]>
    
            * name-lookup.cc (push_local_extern_decl_alias): Diagnose 
annotations
            on local externs and their arguments.
            * decl.cc (grokdeclarator): Diagnose annotations on non-defining
            friends and their arguments.
    
            * g++.dg/reflect/annotations17.C: New test.

Diff:
---
 gcc/cp/decl.cc                               | 21 +++++++++++
 gcc/cp/name-lookup.cc                        | 16 +++++++++
 gcc/testsuite/g++.dg/reflect/annotations17.C | 53 ++++++++++++++++++++++++++++
 3 files changed, 90 insertions(+)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 74099c34348a..8409752aa0c8 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -16618,6 +16618,27 @@ grokdeclarator (const cp_declarator *declarator,
 
        if (friendp)
          {
+           if (flag_reflection && !funcdef_flag && decl)
+             {
+               if (attrlist
+                   && lookup_attribute ("internal ", "annotation ",
+                                        *attrlist))
+                 {
+                   /* Remove the annotations to avoid spurious warning
+                      below.  */
+                   *attrlist = remove_attribute ("internal ", "annotation ",
+                                                 *attrlist);
+                   error_at (id_loc, "annotation applied to non-defining "
+                                     "friend declaration %qD", decl);
+                 }
+               for (tree arg = DECL_ARGUMENTS (decl);
+                    arg; arg = DECL_CHAIN (arg))
+                 if (lookup_attribute ("internal ", "annotation ",
+                                       DECL_ATTRIBUTES (arg)))
+                   error_at (DECL_SOURCE_LOCATION (arg),
+                             "annotation applied to parameter %qD of "
+                             "non-defining friend declaration", arg);
+             }
            /* Packages tend to use GNU attributes on friends, so we only
               warn for standard attributes.  */
            if (attrlist
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 13aafab4e685..c0f48b5496dc 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -3690,6 +3690,22 @@ set_decl_context_in_fn (tree ctx, tree decl)
 void
 push_local_extern_decl_alias (tree decl)
 {
+  if (flag_reflection)
+    {
+      if (lookup_attribute ("internal ", "annotation ",
+                           DECL_ATTRIBUTES (decl)))
+       error_at (DECL_SOURCE_LOCATION (decl),
+                 "annotation applied to block scope extern %qD",
+                 decl);
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       for (tree arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg))
+         if (lookup_attribute ("internal ", "annotation ",
+                               DECL_ATTRIBUTES (arg)))
+           error_at (DECL_SOURCE_LOCATION (arg),
+                     "annotation applied to parameter %qD of block scope "
+                     "extern", arg);
+    }
+
   if (dependent_type_p (TREE_TYPE (decl))
       || (processing_template_decl
          && VAR_P (decl)
diff --git a/gcc/testsuite/g++.dg/reflect/annotations17.C 
b/gcc/testsuite/g++.dg/reflect/annotations17.C
new file mode 100644
index 000000000000..caecec207491
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/annotations17.C
@@ -0,0 +1,53 @@
+// CWG3124 - Disallow annotations on block-scope externs and non-unique friend 
declarations
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+void
+foo ()
+{
+  [[=1]] extern int a;                 // { dg-error "annotation applied to 
block scope extern 'a'" }
+  extern int b [[=2]];                 // { dg-error "annotation applied to 
block scope extern 'b'" }
+  [[=3]] extern int bar (int);         // { dg-error "annotation applied to 
block scope extern 'int bar\\\(int\\\)'" }
+  extern int baz [[=4]] (int);         // { dg-error "annotation applied to 
block scope extern 'int baz\\\(int\\\)'" }
+  extern int qux (int a[[=5]]);                // { dg-error "annotation 
applied to parameter 'a' of block scope extern" }
+}
+
+class S
+{
+  int s;
+  S ();
+  [[=6]] friend void corge ();         // { dg-error "annotation applied to 
non-defining friend declaration 'void corge\\\(\\\)'" }
+  friend void garply ([[=7]] int a);   // { dg-error "annotation applied to 
parameter 'a' of non-defining friend declaration" }
+  [[=8]] friend void fred () {}
+  friend void xyzzy (int a[[=9]]) {}
+  template <typename T>
+  [[=10]] friend void quux ();         // { dg-error "annotation applied to 
non-defining friend declaration 'void quux\\\(\\\)'" }
+  template <typename T>
+  friend void grault ([[=11]] int a);  // { dg-error "annotation applied to 
parameter 'a' of non-defining friend declaration" }
+  template <typename T>
+  [[=12]] friend void waldo () {}
+  template <typename T>
+  friend void thud (int a[[=13]]) {}
+};
+
+template <typename T>
+class U
+{
+  int u;
+  [[=14]] friend void corge (long);    // { dg-error "annotation applied to 
non-defining friend declaration 'void corge\\\(long int\\\)'" }
+  friend void garply (long, [[=16]] int a);    // { dg-error "annotation 
applied to parameter 'a' of non-defining friend declaration" }
+  [[=16]] friend void fred (long) {}
+  friend void xyzzy (long, int a[[=17]]) {}
+  template <typename V>
+  [[=18]] friend void quux (long);     // { dg-error "annotation applied to 
non-defining friend declaration 'void quux\\\(long int\\\)'" }
+  template <typename V>
+  friend void grault (long, [[=19]] int a);    // { dg-error "annotation 
applied to parameter 'a' of non-defining friend declaration" }
+  template <typename V>
+  [[=20]] friend void waldo (long) {}
+  template <typename V>
+  friend void thud (long, int a[[=21]]) {}
+public:
+  U () : u (42) {}
+};
+
+U <int> u;

Reply via email to