This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/79658] [-Wuninitialized] referencing uninitialized field of POD struct should warn


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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]