[[maybe-unused]] vs __attribute__((unused)) vs (void) var for assert variables

When defining a variable that is used only in an assert, the LLVM style guide https://llvm.org/docs/CodingStandards.html#id47 recommends using

(void) var;

Why is this preferred over [[maybe-unused]] or _attribute_((unused))?

Thanks

This should probably be changed to [[maybe_unused]] when we have merged the C++17 standards update.

The challenge can also be addressed with control flow, but the community decided to use a c solution in a in C++ codebase.

Thanks for the reply @tschuett, please can you elaborate on ‘The challenge can also be addressed with control flow’ ?

The alternative is to use #ifndef NDEBUG, I thought. (void) is tidier to look at.

I agree it is tidier, but I also thought the intention could be a bit unclear to the uninitiated.

int var = 5;
if (assert_will_fail(var)) {
  assert(false && "bad things")
}

I don’t think this is an area where we should try to innovate. Casting to void is a tried and true idiom for indicating that a value is unused. It’s even documented in the coding standards for folks who aren’t familiar with the idiom. I don’t see value in deviating from C just for it’s own sake, there should be some value proposition, like safety, for doing so.

3 Likes

… which is unidiomatic and risks that the compiler is unable to eliminate whatever is in assert_will_fail in builds without assertions enabled. (void) or [[maybe_unused]] work better and are idiomatic.

Totally agreed, but I prefer the new [[maybe_unused]] attribute. It better describes the intent than a Cish idiom.

2 Likes

Just MHO I don’t see an advantage to using the attribute. It is more verbose and the cast to void idiom is obvious enough.

The one advantage I see of the attribute is that it is more “explicit”, but this is C++ which is full of magic and special cases (sadly). I don’t think this is better than the old C idiom.

The advantage of [[maybe_unused]] attribute is that it can apply to pretty much anything. I.e. you can mark functions/arguments with it, if there is some rarely used value (like for printf-like functions). But for simple unused variables, (void) is more concise idiom understood by pretty much everyone.

1 Like

The attribute is more verbose in terms of character length, but it is less verbose in terms of statement count:

[[maybe_unused]] int answer = 42;

vs

int answer = 42;
(void)answer;

Personally, I prefer the attribute version more. In addition, as @danilaml mentioned, the attribute is more versatile than the cast-to-void.

There is one more option to handle the unused variables which is derivative of the cast-to-void version:

#define LLVM_UNSUSED(arg) (void)(arg)
int answer = 42;
LLVM_UNUSED(answer);

It is more verbose for sure, yet probably more readable.

The statement count being shorter is persuasive to me that we should be using [[maybe_unused]], although I don’t strongly object to using the (void) approach, and wouldn’t advocate a mass-switching.

I would be fine with new code using maybe_unused, I think it’s clearer than the void cast. But I also agree we shouldn’t mass switch