This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/79658] [-Wuninitialized] referencing uninitialized field of POD struct should warn
- From: "palves at redhat dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 21 Feb 2017 14:45:54 +0000
- Subject: [Bug c++/79658] [-Wuninitialized] referencing uninitialized field of POD struct should warn
- Auto-submitted: auto-generated
- References: <bug-79658-4@http.gcc.gnu.org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79658
--- Comment #4 from Pedro Alves <palves at redhat dot com> ---
Here's a better one:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <typename E>
struct enum_flags
{
enum_flags &operator|= (E e)
{
m_enum_value = (E) (m_enum_value | e);
return *this;
}
operator E () const
{ return m_enum_value; }
E m_enum_value;
};
enum flag
{
FLAG1 = 1,
};
typedef enum_flags<flag> eflags;
extern void bar ();
void
foo_0 (int param)
{
eflags f0;
if (param)
f0 |= FLAG1;
if (f0 != 0) // doesn't warn
bar ();
}
void
foo_1 (int param)
{
eflags f1;
if (param)
f1 |= FLAG1;
if (f1 != FLAG1) // warns
bar ();
}
void
foo_2 (int param)
{
eflags f2;
if (param)
f2 |= FLAG1;
if (f2 != 1) // doesn't warn
bar ();
}
void
foo_3 (int param)
{
eflags f3;
if (param)
f3 |= FLAG1;
if (f3 != 3) // warns
bar ();
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We get:
$ /opt/gcc/bin/g++ -std=gnu++11 enum_flags2.cc -o enum_flags.o -g3 -O2
-Wuninitialized -c -Wall -Wextra
enum_flags2.cc: In function ‘void foo_1(int)’:
enum_flags2.cc:6:25: warning: ‘f1’ may be used uninitialized in this function
[-Wmaybe-uninitialized]
m_enum_value = (E) (m_enum_value | e);
^~~~~~~~~~~~
enum_flags2.cc:40:10: note: ‘f1’ was declared here
eflags f1;
^~
enum_flags2.cc: In function ‘void foo_3(int)’:
enum_flags2.cc:6:25: warning: ‘f3’ may be used uninitialized in this function
[-Wmaybe-uninitialized]
m_enum_value = (E) (m_enum_value | e);
^~~~~~~~~~~~
enum_flags2.cc:64:10: note: ‘f3’ was declared here
eflags f3;
^~
In particular, note that the uses in foo_0 and foo_2 did NOT warn while the
uses in foo_1 and foo_3 did warn. Why's that?
The use I was originally most interested in catching was the one like in foo_0,
where we compare against 0. The original code has means to make comparing
enum_flags against other integer literals fail to compile. (0 means bit flags
not set, the code is implementing a type-safe enum flags wrapper). I just
tried the other values for completeness, thinking that maybe 0 was being given
"special" treatment, though foo_2 seems to show otherwise.
FWIW, adding enum values to cover all the compared-to values makes no
difference:
enum flag
{
FLAG0 = 0,
FLAG1 = 1,
FLAG2 = 2,
FLAG3 = 3,
};
Same set of warnings.