goto でスコープを抜けるとクラスのデストラクタが呼び出されない現象に遭遇

ここ一週間ほど仕事でハマった現象。

以下サンプル。

class Foo {
public:
    Foo() { puts("constructor"); }
    ~Foo() { puts("destructor"); }
};

int main(int argc, char *argv[]) {
    int flag = 0;
L0:
    if (flag++ == 0) goto L1;
    else goto L2;
L1:
    {
        Foo foo;
        goto L0;
    }
    
L2:
    return 0;
}

auto 変数のクラスインスタンスはスコープを抜ける際にデストラクタが呼ばれるが、goto でスコープを抜ける場合もデストラクタが呼ばれることは C++ の言語仕様として保証されている、らしい。実際そのように動作している。

goto では、デストラクタは呼ばれる - masugata_kの日記

ただ、どのような条件かはわからないが、デストラクタが呼び出されないことがある。アセンブラやその他の中間コードを調べたところ、確かにデストラクタが実行されているコードがそれらに存在しない。

何故デストラクタが呼び出されないのか原因が良くわからない。使用しているコンパイラのバグではないかと考えているが、確証が持てない。とりあえず回避方法は以下のように行ったが、根本的ではないのでモヤモヤする。

class Foo {
public:
    Foo() { puts("constructor"); }
    ~Foo() { puts("destructor"); }
};

int main(int argc, char *argv[]) {
    int flag = 0;
L0:
    if (flag++ == 0) goto L1;
    else goto L2;
L1:
    {
        {
            // もうひとつブロックをネストして、
            // こちらのブロックのスコープでデストラクタを呼び出す
            Foo foo;
        }
        goto L0;
    }
    
L2:
    return 0;
}