[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#931182: gcc-8: does not issue a warning with -Wall when a named enum value is overridden by a variable with the same name



Package: gcc-8
Version: 8.3.0-6
Severity: normal
Tags: upstream

Dear Maintainer,

In a C program, when an enum's value is overridden by a variable with
the same name, and it is compiled by gcc with -Wall, no warning is
emitted even though it is questionable to override an enum. See the
program below:
#include <stdio.h>

int main(void) {
  enum {g, h, i} foo[3];

  /* Set all elements of `foo' to `i' (2), or so you would think */
  for (int i = 0; i < sizeof(foo) / sizeof(*foo); i++) {
    foo[i] = i; /* <-- this doesn't do what you think */
  }

  /* Now print all the elements (note we use `iterator' instead of `i'
     to avoid the situation above) */
  for (int iterator = 0; iterator < sizeof(foo) / sizeof(*foo); iterator++) {
    printf("foo[%d] is ", iterator);

    switch (foo[iterator]) {
    case g:
      puts("g");
      break;
    case h:
      puts("h");
      break;
    case i:
      puts("i");
      break;
    default:
      printf("something else: %d\n", foo[iterator]);
      break;
    }
  }

  return 0;
}
In line 8, "foo[i] = i;", foo[i] is indexed using the "i" which was
declared at the beginning of the loop ("int i = 0;"), as you would
expect. However, it is not clear what the second "i" (the one on the
right of the assignment) is referring to. It could be referring to the
value "2" (since that is the value `i' is assigned to in the enum), or
it could also be referring to the "i" which was declared at the
beginning of the loop. It is in fact referring to the loop `i' as you
can see if you compile and run the program.

  $ gcc -Wall -o enum-test enum-test.c
  $ ./enum-test
  foo[0] is g
  foo[1] is h
  foo[2] is i

However, note that gcc succeeded with *no output* even though -Wall was
passed. Since overriding enum values is unclear and may not do what you
think, and it's easily avoidable (just change the variable or enum value
name), it should be warned against when -Wall is passed.

From the "(gcc) Warning Options" info node,

  '-Wall'
       This enables all the warnings about constructions that some users
       consider questionable, and that are easy to avoid (or modify to
       prevent the warning), even in conjunction with macros.

So I think this should definitely be warned against by -Wall.

Clang too, does not warn against this:

  $ clang -Wall -o enum-test enum-test.c
  $ ./enum-test
  foo[0] is g
  foo[1] is h
  foo[2] is i

(As you can see, the runtime behavior of the program is the same as when
compiled with gcc, as you would expect.)

Curiously, both g++ and clang++ raise an error when an enum is
overridden (along with a few warnings since the program was not meant to
be compiled as C++).

  $ g++ -Wall -o enum-test enum-test.c
  enum-test.c: In function ‘int main()’:
  enum-test.c:7:21: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
     for (int i = 0; i < sizeof(foo) / sizeof(*foo); i++) {
                     ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
  enum-test.c:8:14: error: invalid conversion from ‘int’ to ‘main()::<unnamed enum>’ [-fpermissive]
       foo[i] = i; /* <-- this doesn't do what you think */
                ^
  enum-test.c:13:35: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
     for (int iterator = 0; iterator < sizeof(foo) / sizeof(*foo); iterator++) {
                            ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
  $ clang++ -Wall -o enum-test enum-test.c
  clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
  enum-test.c:8:14: error: assigning to 'enum (anonymous enum at enum-test.c:4:3)' from incompatible type 'int'
      foo[i] = i; /* <-- this doesn't do what you think */
               ^
  1 error generated.

I haven't reported a bug against clang since you can only report a bug
against one package, but perhaps a bug should be reported against clang
referencing this one to alert the clang people about this too.


-- System Information:
Debian Release: 10.0
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 4.19.0-5-amd64 (SMP w/2 CPU cores)
Kernel taint flags: TAINT_FIRMWARE_WORKAROUND
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages gcc-8 depends on:
ii  binutils      2.31.1-16
ii  cpp-8         8.3.0-6
ii  gcc-8-base    8.3.0-6
ii  libc6         2.28-10
ii  libcc1-0      8.3.0-6
ii  libgcc-8-dev  8.3.0-6
ii  libgcc1       1:8.3.0-6
ii  libgmp10      2:6.1.2+dfsg-4
ii  libisl19      0.20-2
ii  libmpc3       1.1.0-1
ii  libmpfr6      4.0.2-1
ii  libstdc++6    8.3.0-6
ii  zlib1g        1:1.2.11.dfsg-1

Versions of packages gcc-8 recommends:
ii  libc6-dev  2.28-10

Versions of packages gcc-8 suggests:
pn  gcc-8-doc         <none>
pn  gcc-8-locales     <none>
pn  gcc-8-multilib    <none>
pn  libasan5-dbg      <none>
pn  libatomic1-dbg    <none>
pn  libgcc1-dbg       <none>
pn  libgomp1-dbg      <none>
pn  libitm1-dbg       <none>
pn  liblsan0-dbg      <none>
pn  libmpx2-dbg       <none>
pn  libquadmath0-dbg  <none>
pn  libtsan0-dbg      <none>
pn  libubsan1-dbg     <none>

-- no debconf information

Attachment: signature.asc
Description: PGP signature


Reply to: