Bug 99032

Summary: GCC accepts attributes on friend declarations (not definitions)
Product: gcc Reporter: Giuseppe D'Angelo <dangelog>
Component: c++Assignee: Marek Polacek <mpolacek>
Status: RESOLVED FIXED    
Severity: normal CC: mpolacek, webrown.cpp
Priority: P3 Keywords: accepts-invalid
Version: 10.2.1   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2021-02-09 00:00:00

Description Giuseppe D'Angelo 2021-02-09 17:39:09 UTC
Hi,

The following code is accepted by GCC 10.2:

  struct S { [[deprecated]] friend void f(); };

No errors and no warnings are generated under -Wall -Wextra -pedantic.

The code is however ill-formed: an attribute cannot appear on a friend  declaration which isn't also a definition:

https://eel.is/c++draft/dcl.attr#grammar-5.sentence-3

    If an attribute-specifier-seq appertains to a friend declaration ([class.friend]), that declaration shall be a definition.


For comparison, Clang rejects this, and MSVC accepts it (without warnings).
Comment 1 Marek Polacek 2021-02-09 17:44:58 UTC
Mine for GCC 12.
Comment 2 Marek Polacek 2021-05-11 20:04:32 UTC
Current test:

class X { };
template<typename T1, typename T2>
void foo (T1, T2);

struct S {
  [[deprecated]] friend void f(); // error
  [[deprecated]] friend void f2() { }
  friend void f3 [[deprecated]] (); // error
  friend void f4 [[deprecated]] () { }
  [[deprecated]] friend void; // error
  [[deprecated]] friend X; // error
  [[deprecated]] friend class N; // error
  friend class [[deprecated]] N2; // error
  [[deprecated]] friend void foo<>(int, int); // error
  // FIXME: When PR100339 is resolved.
  //[[deprecated]] friend void ::foo(int, int); // error
};

template<typename T>
class node { };

template<typename T>
struct A {
  [[deprecated]] friend T; // error
  [[deprecated]] friend class node<T>; // we warn
  template<typename>
  [[deprecated]] friend class A; // we warn
  template<typename>
  [[deprecated]] friend void bar () { } // OK
  template<typename>
  [[deprecated]] friend void baz (); // error
};
Comment 3 GCC Commits 2021-05-14 01:13:49 UTC
The master branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

https://gcc.gnu.org/g:149061188c7c6ddf27663c8c00b7574fc8d0fd23

commit r12-786-g149061188c7c6ddf27663c8c00b7574fc8d0fd23
Author: Marek Polacek <polacek@redhat.com>
Date:   Thu Apr 29 21:38:14 2021 -0400

    c++: Check attributes on friend declarations [PR99032]
    
    This patch implements [dcl.attr.grammar]/5: "If an attribute-specifier-seq
    appertains to a friend declaration ([class.friend]), that declaration shall
    be a definition."
    
    This restriction applies to C++11-style attributes as well as GNU
    attributes with the exception that we allow GNU attributes that require
    a type, such as vector_size to continue accepting code as in attrib63.C.
    There are various forms of friend declarations, we have friend
    templates, C++11 extended friend declarations, and so on.  In some cases
    we already ignore the attribute and warn that it was ignored.  But
    certain cases weren't diagnosed, and with this patch we'll give a hard
    error.  I tried hard not to emit both a warning and error and I think it
    worked out.
    
    Jason provided the cp_parser_decl_specifier_seq hunk to detect using
    standard attributes in the middle of decl-specifiers, which is invalid.
    
    Co-authored-by: Jason Merrill <jason@redhat.com>
    
    gcc/cp/ChangeLog:
    
            PR c++/99032
            * cp-tree.h (any_non_type_attribute_p): Declare.
            * decl.c (grokdeclarator): Diagnose when an attribute appertains to
            a friend declaration that is not a definition.
            * decl2.c (any_non_type_attribute_p): New.
            * parser.c (cp_parser_decl_specifier_seq): Diagnose standard attributes
            in the middle of decl-specifiers.
            (cp_parser_elaborated_type_specifier): Diagnose when an attribute
            appertains to a friend declaration that is not a definition.
            (cp_parser_member_declaration): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/99032
            * g++.dg/cpp0x/friend7.C: New test.
            * g++.dg/cpp0x/gen-attrs-4.C: Add dg-error.
            * g++.dg/cpp0x/gen-attrs-39-1.C: Likewise.
            * g++.dg/cpp0x/gen-attrs-74.C: New test.
            * g++.dg/ext/attrib63.C: New test.
Comment 4 Marek Polacek 2021-05-14 01:14:20 UTC
Fixed in GCC 12.