2

MSVC warning for potentially uninitialized variables is not particularly good, in particular it falsely claims that i can be uninitialized in this program:

#include<cstdlib>


enum class Color{
    Red, 
    Green
};
int f(Color c){
    int i;
    switch(c){
        case Color::Red:
          i=11;
        case Color::Green:
          i=22;
    };
    return i;
}

int main(){
    return f(rand()?Color::Red : Color::Green);
}

warning C4701: potentially uninitialized local variable 'i' used

I can obviously just initialize the i to 0 or disable warnings with pargmas, but then this warning will not fire if I add enum Blue and I never handle it in switch and I want it to fire in that case.

Is there any way to make this MSVC warning work as expected?

NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • why use `i` in the first place? isnt there a different warning for not handling all cases? Perhaps replace `i=11;` with `return 11;` – 463035818_is_not_an_ai Feb 06 '20 at 13:00
  • enum can have values outside the given one. – Jarod42 Feb 06 '20 at 13:12
  • 1
    How do you define "sane use"? `enum class Flag { A = 0x01, B = 0x02, C = 0x04 }` and using `|` and `&` seems not insane. – Jarod42 Feb 06 '20 at 13:17
  • Have you considered to do the mapping of `enum` to other with an array instead of the `switch`? (Then you could ensure by range check whether a value can be mapped or not.) It relies on contiguous `enum` values, of course, but this how the exposed sample looks like. – Scheff's Cat Feb 06 '20 at 13:20
  • Maybe a duplicate but it is not specifically about MSVC: https://stackoverflow.com/questions/54148815/make-compiler-assume-that-all-cases-are-handled-in-switch-without-default – Piotr Siupa Feb 06 '20 at 13:21
  • Would it hurt so much to initialize `i` with anything? The performance impact cannot be that big. – Scheff's Cat Feb 06 '20 at 13:22
  • 2
    When initializizing `i = 0` you won't get this particular warning but you should get a warning for not explicitly handling the enum you added (Blue in your example). Wouldnt this be the more appropriate warning anyway? – Odysseus Feb 06 '20 at 13:24
  • @NO_NAME nice find... – NoSenseEtAl Feb 06 '20 at 14:05
  • @Odysseus good point, I totally forgot about this since my current setup does not have C4061/4062 enabled. Feel free to add that as an answer – NoSenseEtAl Feb 06 '20 at 14:12

2 Answers2

5

The switch statement has no the default label. So indeed the variable i can be uninitialized.

You can rewrite the function for example like

int f(Color c){
    int i = 11;    // Color::Red

    switch(c){
        case Color::Green:
          i=22;
          break;
    }

    return i;
}

Another approach is to add the default label for example like

int f(Color c){
    int i;

    switch(c){
        default: 
        case Color::Red:
          i=11;
          break;
        case Color::Green:
          i=22;
          breal;
    }

    return i;
}

In this case as you pointed out yourself you can include a statement with an assertion check after the default label.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I do not care if somebody casts 42 to Color, I handle all the valid enums. – NoSenseEtAl Feb 06 '20 at 12:51
  • @NoSenseEtAl Concerning _I do not care if somebody casts 42 to Color, I handle all the valid enums._: This is something you know but not the compiler. ;-) You could simply insert a "useless" `default:` before one of the `case`s to make the compiler silent. This shouldn't have any performance impact... – Scheff's Cat Feb 06 '20 at 13:00
  • 1
    @Scheff like explained in the question problem is that when I add Blue it will be handled(if I forget to modify swtich) and I do not want that. – NoSenseEtAl Feb 06 '20 at 13:14
  • 2
    @NoSenseEtAl Technically all valid values are whatever the underlying type holds. That means you have a potential path to return an uninitialized variable. – NathanOliver Feb 06 '20 at 13:14
1

As pointed out in my comment above, you can initialize i in some way and won't get the C4701 warning anymore.

But when adding a color which is not handled in your switch-statement, the warning

C4061 "enumerator 'enumerator' in switch of enum 'enumeration' is not explicitly handled by a case label"

should show up (when enabled) - telling you right away what you missed

Odysseus
  • 1,213
  • 4
  • 12