`friend` member functions and attributes - gcc vs clang
Asked Answered
S

2

12

The following code snippet:

struct a
{
    [[nodiscard]] friend int b();
};

Produces this error when compiling on clang++ (trunk 342102) with -std=c++17:

<source>:3:5: error: an attribute list cannot appear here
    [[nodiscard]] friend int b();
    ^~~~~~~~~~~~~

Removing friend or adding a body to b prevents the error.

g++ (trunk) compiles the code just fine.

Live example on godbolt: https://gcc.godbolt.org/z/ttTDuZ


  • Is this a clang++ bug? Or is there some rule in the Standard that makes this code ill-formed?

  • If clang++ is correct, what's the proper way of marking a friend member function as [[nodiscard]]?

Smyth answered 14/9, 2018 at 12:37 Comment(0)
K
15

Per [dcl.attr.grammar]/5

Each attribute-specifier-seq is said to appertain to some entity or statement, identified by the syntactic context where it appears ([stmt.stmt], [dcl.dcl], [dcl.decl]). If an attribute-specifier-seq that appertains to some entity or statement contains an attribute or alignment-specifier that is not allowed to apply to that entity or statement, the program is ill-formed. If an attribute-specifier-seq appertains to a friend declaration, that declaration shall be a definition. No attribute-specifier-seq shall appertain to an explicit instantiation.

emphasis mine

So, clang is right here. If you have an attribute, the function must have a definition if it is a friend function.

Kosiur answered 14/9, 2018 at 12:48 Comment(2)
I see. So this is actually a gcc bugSmyth
@VittorioRomeo Looks that way. I tried adding -pedantic and -Wextra to g++'s compile options and I still couldn't get an error or warning out of it.Kosiur
N
0

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99032

The bug is fixed in GCC 12, you now have the following warning.

test.cpp:3:30: warning: attribute ignored [-Wattributes]
    3 |     [[nodiscard]] friend int b();
      |                              ^
test.cpp:3:30: note: an attribute that appertains to a friend declaration that is not a definition is ignored

The proper way of marking a friend member function as [[nodiscard]] is to put the attribute on its definition.

struct a
{
    friend int b();
};

[[nodiscard]] int b(){ return 42; }
Nippy answered 3/5, 2023 at 15:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.