Open Quuxplusone opened 5 years ago
Bugzilla Link | PR41197 |
Status | NEW |
Importance | P enhancement |
Reported by | Arnd Bergmann (arnd@linaro.org) |
Reported on | 2019-03-22 04:07:38 -0700 |
Last modified on | 2019-03-22 12:55:38 -0700 |
Version | 8.0 |
Hardware | PC Linux |
CC | dblaikie@gmail.com, htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org, ndesaulniers@google.com, neeilans@live.com, richard-llvm@metafoo.co.uk |
Fixed by commit(s) | |
Attachments | |
Blocks | PR4068 |
Blocked by | |
See also |
Another related test case modeled after real kernel code would be this one:
int f4(void)
{
int x, y;
switch (0) {
default:
x = 1;
}
if (x)
y = 1;
return y;
}
The original warning is
sound/pci/hda/patch_ca0132.c:7558:6: error: variable 'fw_entry' is used
uninitialized whenever 'if' condition is false
[-Werror,-Wsometimes-uninitialized]
if (!spec->alt_firmware_present) {
^~~~~~~~~~~~~~~~~~~~~~~~~~~
sound/pci/hda/patch_ca0132.c:7565:42: note: uninitialized use occurs here
dsp_os_image = (struct dsp_image_seg *)(fw_entry->data);
^~~~~~~~
sound/pci/hda/patch_ca0132.c:7558:2: note: remove the 'if' if its condition is
always true
if (!spec->alt_firmware_present) {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sound/pci/hda/patch_ca0132.c:7521:33: note: initialize the variable 'fw_entry'
to silence this warning
const struct firmware *fw_entry;
^
= NULL
As far as I can see, the warning is correct in both cases. The purpose of this warning is to detect cases where there is either a dead branch or an uninitialized variable, which is the case in both examples.
Are the dead branches being produced by macros? If so, we could probably suppress the warning on such cases. But if the code literally contains branch conditions that are impossible, then that's a case that this warning is intended to catch, and if you don't want to be warned on that, your should disable the warning.
(In reply to Richard Smith from comment #2)
> As far as I can see, the warning is correct in both cases. The purpose of
> this warning is to detect cases where there is either a dead branch or an
> uninitialized variable, which is the case in both examples.
Ok, I see. The part about dead branches is not obvious here,
but I see what you mean.
Just to clarify: with 'dead branch', do you mean the implied 'else'
portion of the always-true "if (x != 1)" in this?
if (x == 1)
y3 = 1;
else if (x != 1)
y3 = 1;
> Are the dead branches being produced by macros? If so, we could probably
> suppress the warning on such cases. But if the code literally contains
> branch conditions that are impossible, then that's a case that this warning
> is intended to catch, and if you don't want to be warned on that, your
> should disable the warning.
I saw one that had a "switch (0)" with the 0 generated by a macro
intended to disable all "case" statements. No need to worry about that.
A couple of cases involve a macro that sees if __builtin_expect() annotations
are actually correct:
#define __branch_check__(x, expect, is_constant) ({ \
long ______r; \
static struct ftrace_likely_data \
__aligned(4) \
__section("_ftrace_annotated_branch") \
______f = { \
.data.func = __func__, \
.data.file = __FILE__, \
.data.line = __LINE__, \
}; \
______r = __builtin_expect(!!(x), expect); \
ftrace_likely_update(&______f, ______r, \
expect, is_constant); \
______r; \
})
#ifdef CONFIG_TRACE_BRANCH_PROFILING
# define likely(x) (__branch_check__(x, 1, __builtin_constant_p(x)))
# define unlikely(x) (__branch_check__(x, 0, __builtin_constant_p(x)))
#else
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#endif
This one also confuses gcc sometimes, but it seems to reliably mess up
clangs dead code detection when combined with constant input (in cases
that behave as expected without CONFIG_TRACE_BRANCH_PROFILING). In a lot of
cases the branch with constant input can be trivially converted to an
unconditional expression, such as replacing BUG_ON(1) with BUG().