title: Should a switch statement always contain a default if it initializes local variables?
body: <p>Here's a piece of code from the <a href="https://github.com/Auburns/FastNoise" rel="nofollow noreferrer">FastNoise library of Jordan Peck</a>. It gives a whole lot of compiler warnings, among which is this particular switch statement. Here you can see that variables <code>xs</code>, <code>ys</code> and <code>zs</code> are supposed to always get their values from a switch statement that lacks a default case. The justification is that since <code>m_interp</code> is an enum, "all" cases are covered explicitly in the switch.</p>
  
  <p>However, when compiling this code with the latest gcc version 9.3.0 (Arch Linux 9.3.0-1), it warns about the mentioned variables (<code>-Wmaybe-uninitialized</code>). Indeed this is very bad, if it ever happens that an unexpected value reaches this switch statement, because it is tedious to debug code that uses uninitialized variables. For example, we cannot assume that <code>xs</code>, <code>ys</code> and <code>zs</code> are zero-initialized. They most likely contain garbage before we get into the switch statement. It has also been suggested that the latest gcc compiler is at fault here as it should not issue such a warning in the first place.</p>
  
  <p>I know similar question has already been asked but it fails to mention the special case where variables are given their value for the first time within the switch statement. While normally it may be OK to omit the default case, doing it here can result in very disturbing bugs (undefined behavior). Is the GCC latest version at fault here, giving a false-positive warning? Or is this actually bad programming practice and the library's creator is at fault? Looking at the rest of the code I'd say it's the latter because the code also uses tabs instead of spaces, DOS-style line endings instead of Unix style and in addition to <code>-Wmaybe-uninitialized</code> it also has issues with <code>-Wstrict-aliasing</code> and <code>-Wimplicit-fallthrough</code>.</p>
  
  <p>If GCC is giving a false-positive here, then I'm sure it should be reported accordingly. The question is, is it really a false-positive?</p>
  
  <p>For the record, I would have amended the original discussion but apparently my Stackoverflow reputation is too low so I can't even make comments. Hence, I had no other way than to create a new topic to discuss this matter.</p>
  
  <pre><code>
  FN_DECIMAL FastNoise::SingleValue(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const
  {
      int x0 = FastFloor(x);
      int y0 = FastFloor(y);
      int z0 = FastFloor(z);
      int x1 = x0 + 1;
      int y1 = y0 + 1;
      int z1 = z0 + 1;
  
      FN_DECIMAL xs, ys, zs;
      switch (m_interp)
      {
      case Linear:
          xs = x - (FN_DECIMAL)x0;
          ys = y - (FN_DECIMAL)y0;
          zs = z - (FN_DECIMAL)z0;
          break;
      case Hermite:
          xs = InterpHermiteFunc(x - (FN_DECIMAL)x0);
          ys = InterpHermiteFunc(y - (FN_DECIMAL)y0);
          zs = InterpHermiteFunc(z - (FN_DECIMAL)z0);
          break;
      case Quintic:
          xs = InterpQuinticFunc(x - (FN_DECIMAL)x0);
          ys = InterpQuinticFunc(y - (FN_DECIMAL)y0);
          zs = InterpQuinticFunc(z - (FN_DECIMAL)z0);
          break;
      }
  
      FN_DECIMAL xf00 = Lerp(ValCoord3DFast(offset, x0, y0, z0), ValCoord3DFast(offset, x1, y0, z0), xs);
      FN_DECIMAL xf10 = Lerp(ValCoord3DFast(offset, x0, y1, z0), ValCoord3DFast(offset, x1, y1, z0), xs);
      FN_DECIMAL xf01 = Lerp(ValCoord3DFast(offset, x0, y0, z1), ValCoord3DFast(offset, x1, y0, z1), xs);
      FN_DECIMAL xf11 = Lerp(ValCoord3DFast(offset, x0, y1, z1), ValCoord3DFast(offset, x1, y1, z1), xs);
  
      FN_DECIMAL yf0 = Lerp(xf00, xf10, ys);
      FN_DECIMAL yf1 = Lerp(xf01, xf11, ys);
  
      return Lerp(yf0, yf1, zs);
  }
  </code></pre>