跳过变量初始化格式错误还是会导致未定义的行为?

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

考虑这段代码:

void foo()
{
    goto bar;
    int x = 0;
    bar: ;
}

GCC 和 Clang reject it,因为跳转到 bar: 绕过了变量初始化。 MSVC 根本没有抱怨(除了在 bar: 之后使用 x 会导致警告)。

我们可以用 switch:

做类似的事情
void foo()
{
    switch (0)
    {
        int x = 0;
        case 0: ;
    }
}

现在所有三个编译器 emit errors

这些片段格式不正确吗?还是它们会导致 UB?

我曾经认为两者都是错误的,但我找不到标准的相关部分。 [stmt.goto] doesn't say anything about this, and neither does [stmt.select].

当初始化是非空的时,它是病式的。

[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.

初始化程序使初始化非空。相比之下,这个

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

将是合式的。尽管有关使用具有不确定值的 x 的通常注意事项将适用。

来自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