[[maybe_unused]] on member variable, GCC warns (incorrectly?) that attribute is ignored

Any attribute can be "ignored by the compiler" for any reason, except where the standard says otherwise (such as using an attribute in a location where it is expressly forbidden).

GCC isn't saying you can't put one there; it's saying that putting one there won't do anything, because they probably don't warn about maybe-unused member variables.


GCC won't warn you for unused member variables in the first place so that attribute has no purpose, that's why it's warning you for ignoring it. It's only a warning, your code is still legal.


As far as I can tell, this should be legal (and not ignored by the compiler).

Correction:

  • shall be legal: yes, it may be applied to a declaration of a non-static data member,
  • shall not be ignored: no, it's up to the implementation to decide whether or not and how to use this attribute.

Whilst [dcl.attr.unused]/2 specified that the maybe_unused attribute may be applied to a declaration of a non-static data member [emphasis mine]:

The attribute may be applied to the declaration of a class, a typedef-name, a variable (including a structured binding declaration), a non-static data member, a function, an enumeration, or an enumerator.

there is no strict requirement on implementations on how to apply this attribute, only a recommendation as for how implementations should apply it, as per [dcl.attr.unused]/4 [emphasis mine]:

Recommended practice: For an entity marked maybe_­unused, implementations should not emit a warning that the entity or its structured bindings (if any) are used or unused. For a structured binding declaration not marked maybe_­unused, implementations should not emit such a warning unless all of its structured bindings are unused.

This means as long as implementations allow it to be applied to a declaration of a non-static data member, they are standard compliant, and it is not a compiler bug that the attribute is non implemented using the recommended practice, even if we can argue that a compiler should be able to diagnose an unused non-static data member of a class defined with internal linkage within a single translation unit. E.g. in the following example:

// test.cpp
namespace {
struct Foo {
    int member{1};
    void bar() {
        [[maybe_unused]] int local = 0;
    }
};

void bar() {
    Foo f{};
    f.bar();
}
}  // namespace

The non-static data member member of Foo is not used; this is diagnosable and the maybe_unused attribute could arguably be used to suppress such an implementation-defined unused warning. However, neither GCC nor Clang warns for the case above, and afaict there are no warnings related to "unused public field of local class or class hidden with internal linkage" neither for GCC nor Clang.

Then we may as ourselves why Clang does not emit an implementation-defined warning that the attribute will be ignored for the case of non-static data members? The reason is that Clang does emit a -Wunused-private-field warning for non-used private static data members:

struct Foo {
    void bar() {
        int local = 0;
    }
private:
    int member{1};
    // Clang: warning: private field 'member' is not used 
};

Whereas GCC does not, which would also include why GCC (correctly) warns the maybe_unused attribute will be ignored by it for non-static data members (even private ones), as it will simply not diagnose non-used private data members (whereas Clang does). These behaviours are both correct, as it lies in the domain of implementation-defined behaviour.

We may note that there exists a GCC bug report from 2016 that asks for the feature which Clang implements:

  • Bug 72789 - add -Wunused-private-field

which has been

... Confirming as an enhancement.

In a duplicate-marked bug report, Bug 87409 - Implement -Wunused-private-field, Jonathan Wakely comments that if this feature were to be implemented in GCC, they would also need to implement the suppression of it for the (maybe) unused attribute:

Clang suppresses the warning if the member declaration has attribute unused, which we would need to do too.


Dealing with implementation variance in implementation-defined behaviour

As there are no compiler bugs to hammer down on here, a "portable" (for the specific compilers chosen) implementation of the Foo class (if it it were to have, say, (maybe) non-used private data members), w.r.t. unused warnings, would e.g. be to use implementation-specific pragmas, as shown e.g. in @0x5453: self-answer, to attempt to align the implementation-defined behaviours of the selected compilers.

An alternative approach would be to consider entirely removing Clang's -Wunused-private-field warning globally (-Wno-unused-private-field), leaving these kind of diagnostics to a static analysis tool instead.