Ответ 1
Это ошибка в libstdС++ из потока cfe-dev
списка рассылки с заголовком -fsanitize = undefined и разделяемыми библиотеками:
Это ошибка в libstdС++. Вы сможете обойти его с помощью sanlister blacklist file, как только будет патч для этих земель, но для теперь фильтрация их вручную, вероятно, будет вашим лучшим вариантом.
Вот исправление для исправления; Я буду искать в этом libstdС++ вверх по течению в течение следующих нескольких дней. [...]
Как я уже отмечал dyp в комментариях, не редко встречаются системы, в которых clang
использует libstdc++
в отличие от libc++
, и если мы проверим это на Coliru явно использует libstdС++ через -stdlib=libstdc++
, мы действительно можем воспроизвести проблему.
Следующий отчет об ошибке libstdc++
: плохие значения перечисления, рассчитанные оператором ~ в ios_base.h, охватывают эту проблему и говорят:
Перегруженный оператор ~ s, определенный для перечислений в ios_base.h имеют следующую форму:
Enum operator~(Enum e) { return Enum(~static_cast<int>(e)); }
~ создает значения вне диапазона значений перечисления типа, поэтому для возврата к типу Enum задано неопределенное значение (см. [expr.static.cast] p10), и на практике он производит значение Enum вне диапазона представляемых значений для типа Enum, поэтому поведение undefined.
Для справки [expr.static.cast] p10 говорит:
Значение интегрального или перечисляемого типа может быть явно преобразовано в тип перечисления. Значение не изменяется, если исходное значение находится в диапазоне значений перечисления (7.2). В противном случае результат значение не указано (и может быть не в этом диапазоне). Значение типа с плавающей запятой также может быть преобразовано к типу перечисления. Полученное значение совпадает с преобразованием исходного значения в базовый тип перечисления (4.9), а затем тип перечисления.
а hvd говорит, что это формально неопределенное поведение, но Ричард указывает, что на практике это поведение undefined.
T.C. указывает, что это было изменено с неуказанного на undefined поведение DR 1766: значения вне диапазона значений перечисления:
Хотя проблема 1094 пояснила, что значение выражения типа перечисления может не находиться в пределах диапазона значений перечисления после преобразования в тип перечисления (см. 5.2.9 [expr.static.cast], пункт 10), результатом будет просто неопределенное значение. Вероятно, это должно быть усилено для создания поведения undefined в свете того факта, что поведение undefined делает выражение непостоянным. См. Также пункт 9.6 [class.bit].
Новая редакция появится в проекте стандарта в N4431.