Is jumping over a variable initialization ill-formed or does it cause undefined behaviour?

It's ill-formed when the initialization is non-vacuous.

[stmt.dcl]

3 It is possible to transfer into a block, but not in a way that bypasses declarations with initialization (including ones in conditions and init-statements). A program that jumps from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has vacuous initialization ([basic.life]). In such a case, the variables with vacuous initialization are constructed in the order of their declaration.

The initializer makes the initialization non-vacuous. To contrast, this

void foo()
{
    goto bar;
    int x; // no initializer
    bar: ;
}

would be well-formed. Though the usual caveats about using x with an indeterminate value would apply.


From goto statement:

If transfer of control enters the scope of any automatic variables (e.g. by jumping forward over a declaration statement), the program is ill-formed (cannot be compiled), unless all variables whose scope is entered have

  1. scalar types declared without initializers
  2. class types with trivial default constructors and trivial destructors declared without initializers
  3. cv-qualified versions of one of the above
  4. arrays of one of the above