GCC/Clang attributes guiding warnings about unused entities

Florian Weimer fweimer@redhat.com
Fri Apr 28 09:55:00 GMT 2023


* Stephan Bergmann via Gcc:

> [cross-posting this to both the GCC and Clang communities]

I don't see your post here:

  <https://discourse.llvm.org/search?expanded=true&q=unused%20after%3A2023-04-20>

I don't think this is expected to work from a Discourse point of view.

> * __attribute__((unused)) behaves mostly the same as [[maybe_unused]].
>
> The one difference is that __attribute__((unused)) applied to a type
> does not warn about that type being unused, but rather warns about
> unreferenced variables of that type.  And it appears that both GCC and
> Clang implement [[maybe_unused]] with the same semantics as
> __attribute__((unused)), and cause [[maybe_unused]] applied to a type
> to warn about unreferenced variables of that type.  The mailing list
> thread starting at
> <https://lists.isocpp.org/std-discussion/2023/04/2158.php>
> "[[maybe_unused]] classes" discussed this, and argues that those
> special semantics of __attribute__((unused)) and [[maybe_unused]]
> applied to a type are not actually useful:  The GCC documentation
> cites as a use case "lock or thread classes, which are usually defined
> and then not referenced, but contain constructors and destructors that
> have nontrivial bookkeeping functions".  But the presence of those
> non-trivial con-/destructors will already prevent the compiler from
> emitting warnings about seemingly unused variables of such types.  So
> applying __attribute__((unused)) to such types looks like it does not
> bring any additional value.  Or what do other people think?

Not sure if I quite understand this.  If the attribute cannot be used to
mark (indirectly) variables of type (say) std::string as worthy of
warnings if they are unused, I think these special cases are not useful.

The assumption might be that compilers need to suppress warnings for
RAII guard variables, but GCC does not warn for them anyway.  This is
discussed occasionally, and the assumption is that such warnings would
not be useful.

> * __attribute__((warn_unused_result)) (which can only be applied to
>   functions) behaves the same as [[nodiscard]] applied to functions.

This is not entirely accurate because warn_unused_result is much harder
to suppress at the call site (at least in GCC).

> * __attribute__((warn_unused)) (which can be applied to class types)
>   is meant to allow warnings about unreferenced variables of the given
>   type, where the compiler could otherwise not infer that those
>   variables are truely unused (because the type has non-trivial
>   con-/destructors). (This attribute does not have a standard
>  counterpart.)
>
> Similarly to how [[nodiscard]] can be applied to individual
> constructors, it looks beneficial to me to allow
> __attribute__((warn_unused)) to be applied to individual constructors,
> too.  One example use case is a RAII class that has one constructor
> that does not acquire a resource (often the default constructor) and
> another constructor that does acquire a resource.  So the class itself
> cannot be marked __attribute__((warn_unused)).  But if the
> non-acquiring constructor could individually be marked
> __attribute__((warn_unused)), the compiler could warn about
> unreferenced variables that are initialized via that constructor.
> <https://reviews.llvm.org/D148505> "Allow
> `__attribute__((warn_unused))` on individual constructors" would
> implement that for Clang---but was met with some reservation for now,
> due to the already somewhat confusing landscape of standard and
> GCC/Clang-specific attributes guiding warnings about unused entities
> as outlined in this post.  What do other people think about it?  Would
> it be something that GCC would also want to implement?

How does this interact with deriving warn_unused for std::vector<T> if T
is warn_unused?  That seems like a useful feature, and appears to
require that this is a type property, not a constructor property.

And maybe there is a trend to use constructor functions for these guard
variables and auto?  So

  auto g = make_guard(obj);

instead of:

  guard<decl_type(obj)> g(obj);

Thanks,
Florian



More information about the Gcc mailing list