https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114309
Bug ID: 114309 Summary: Undesirable warning with [[unlikely]] Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: terra at gnome dot org Target Milestone: --- g++ warns over the following program which uses [[unlikely]] for aborting error reporting and conditionally chooses between two error messages: # /usr/local/products/gcc/13.1.0/bin/g++ -O2 -c ttt-if-dual-unlikely.C ttt-if-dual-unlikely.C: In function ‘void if_dual_warning(int)’: ttt-if-dual-unlikely.C:3:19: warning: both branches of ‘if’ statement marked as ‘unlikely’ [-Wattributes] 3 | #define barf(msg) [[unlikely]] crash(msg) | ^~~~~~~~~~~~ ttt-if-dual-unlikely.C:22:5: note: in expansion of macro ‘barf’ 22 | barf("foo"); | ^~~~ g++ is correct that both branches have [[unlikely]]. What is not correct is to warn over it. g++ should instead simply infer that the second "if" is itself unlikely to be reached. The standard, quoted from https://en.cppreference.com/w/cpp/language/attributes/likely, clearly contemplates this case: "Applies to a statement to allow the compiler to optimize for the case where paths of execution including that statement are less likely than any alternative path of execution that does not include such a statement." Note that the standard expressions itself in terms of "paths of execution" whereas g++ appears to have a narrower "branches of `if'" world view. I am not sure whether that's relevant. Issuing this warning is a made a bit worse by the lack of a simple, local way to suppress the warning in the same way that "if ((var = val)) { ... }" is a way to suppress the warning about assignment in condition. # cat ttt-if-dual-unlikely.C #include <iostream> #define barf(msg) [[unlikely]] crash(msg) void crash (const char*msg) { std::cerr << msg << std::endl; abort (); } void if_dual_warning (int i) { bool runtime_cond0 = i > 0; bool runtime_cond1 = i > 1; if (runtime_cond0) { std::cerr << "Something\n"; } else if (runtime_cond1) { barf("foo"); } else { barf("bar"); } }