Является ли компилятор допустимым в отношении поведения undefined в постоянном выражении?

Мы знаем, что операции которые вызывают поведение undefined, не являются основными константными выражениями (раздел 5.19 параграфа 2 из черновик стандарта С++)

В тестах я выполнял как clang, так и gcc поведение undefined в constexpr как ошибку, но они несовместимы в случае сдвига вправо влево. Например, во всех этих случаях, которые рассматриваются как поведение undefined в соответствии с разделом 5.8 Операторы сдвига с 1 по 3:

constexpr int x1 =  1 << 33 ; //Assuming 32-bit int
constexpr int x2 =  1 << -1 ;
constexpr int x3 =  -1 << 1 ;
constexpr int x4 =  1 >> 33 ; //Assuming 32-bit int
constexpr int x5 =  1 >> -1 ;

clang приведет к ошибке (увидеть его в прямом эфире):

error: constexpr variable 'x1' must be initialized by a constant expression
    constexpr int x1 =  1 << 33 ; //Assuming 32-bit int
                  ^     ~~~~~~~
note: shift count 33 >= width of type 'int' (32 bits)
    constexpr int x1 =  1 << 33 ; //Assuming 32-bit int
....

while gcc выдаст предупреждение, но все равно будет считать, что каждая переменная является постоянным выражением (видеть ее в прямом эфире):

warning: left shift count >= width of type [enabled by default]
 constexpr int x1 =  1 << 33 ; //Assuming 32-bit int
                          ^
warning: left shift count is negative [enabled by default]
 constexpr int x2 =  1 << -1 ;
...

Это выглядит как ошибка gcc, но я знаю, что компилятор может сделать более сильные гарантии для поведения, который, по словам стандарта, undefined, и он выглядит как gcc дает более сильные гарантии для смены. Это может оказаться ошибкой, но это заставляет меня задаться вопросом, разрешил ли компилятор тот же доступ в контексте constexpr, или компилятор должен строго придерживаться того, что говорит стандарт, - это поведение undefined здесь?

Обновить

Как упоминает Алан, действительно верно, что диагностика плохо сформированной программы может быть либо ошибкой, либо предупреждением, но в этом случае gcc, похоже, не считает программу плохо сформированной. В отличие от других экземпляров, например, в случае overflow, gcc не жалуется на недопустимый constexpr, но предупреждает о смене. Таким образом, казалось бы, либо это ошибка, либо gcc не рассматривает эти случаи как undefined и, следовательно, мой вопрос.

Ответы

Ответ 1

Поскольку Йоханнес, похоже, не хочет преобразовать свой комментарий в ответ, тогда я сам отвечу. У меня был автономный разговор с Howard Hinnant, и он подтвердил консенсус в комментариях о том, что поведение gccs в этом контексте действительно соответствует.

Соответствующим разделом из проекта стандарта будет раздел 1.4 Соответствие реализации, которое гласит в пункте 2:

Хотя в этом международном стандарте указаны только требования к реализациям на С++, эти требования часто легче понять, если они сформулированы как требования к программам, частям программ или выполнению программ. Такие требования имеют следующее значение:

и имеет следующую пулю (выделение мое):

Если программа содержит нарушение любого диагностируемого правила или появление конструкции, описанной в этом стандарте, как "условно-поддерживаемая", когда реализация не поддерживает эту конструкцию, соответствующая реализация должна выдать хотя бы одну диагностику сообщение.

Диагностика может быть предупреждением или ошибкой. Поэтому, когда gcc предоставляет предупреждение о поведении undefined, это не требует последующего предупреждения о самом constexpr.

Хотя это соответствует поведению, порождающему ошибку для constexpr и позволяющее SFINAE казаться более надежным. Учитывая, что gcc выдает ошибки в других экземплярах поведения undefined в constexpr, это не похоже на предполагаемое поведение или если это было, по крайней мере, непоследовательное поведение, поэтому я отправил отчет об ошибке.