hsutter / cppfront

A personal experimental C++ Syntax 2 -> Syntax 1 compiler
Other
5.46k stars 238 forks source link

Emit the `[[maybe_unused]]` attribute on anonymous objects to silence C++ compiler warnings #969

Closed bluetarpmedia closed 4 months ago

bluetarpmedia commented 8 months ago

C++ compilers at high warning levels warn about unused variables or class members.

This PR adds [[maybe_unused]] to anonymous objects (named _) at function and class scope (excludes namespace scope, since it's not needed there).

Using this code as an example:

foo: type = {
    _: double = 90.0;
}

_: foo = ();

ns: namespace = {
    _: bool = true;
}

main: () -> int = {
    _: int = 0;
    return 0;
}

Before this PR, Clang produces these warnings (with -Wall). Similar warnings with MSVC and GCC.

main.cpp2:12:9: warning: unused variable 'auto_1' [-Wunused-variable]
   12 |     int auto_1 {0}; 
      |         ^~~~~~
main.cpp2:2:21: warning: private field 'auto_1' is not used [-Wunused-private-field]
    2 |     private: double auto_1 {90.0}; 
      |                     ^

After this PR, there are no warnings, since the relevant code lowers to:

private: [[maybe_unused]] double auto_1 {90.0}; 

and

[[maybe_unused]] int auto_1 {0}; 
bluetarpmedia commented 7 months ago

I think you should change the tests instead. You shouldn't be making anonymous objects using a trivial constructor with trivial destruction.

The motivation wasn't to fix the warnings in the tests (that's just a byproduct), but rather for cases like this:

initialize: () -> int = {
    std::cout << "Setup\n";
    return 0;
}

main: () -> int = {
    _:int = initialize();
    return 0;
}

It's arguable that programmers should always check return values, but in this case the user has deliberately written a placeholder to say that they don't care about the return value. But this results in an unused variable warning, even though the user said they don't want it. Godbolt

JohelEGP commented 7 months ago

Well, you shouldn't make an object out of it, but instead discard it by leaving out the : and the type: _ = initialize();.

bluetarpmedia commented 7 months ago

Well, you shouldn't make an object out of it, but instead discard it by leaving out the : and the type: _ = initialize();.

Oh, of course, I completely missed that!

Hmm, so maybe cppfront could suggest to write _ = initialize(); instead of _:int = initialize();