static_assert without UB

Jens Gustedt, INRIA and ICube, France

2025-04-02

target

integration into IS ISO/IEC 9899:202y

document history

document number date comment
n3525 202504 Original proposal

license

CC BY, see https://creativecommons.org/licenses/by/4.0

1 Motivation and approach

The present paper deals with UB that would be the result of the controlling expression of a static_assert being a constant expression of integer type, but not an integer constant expression.

Indeed, the current text has the requirement for the expression with a “shall” in the semantics section. Thus it is UB if the expression were not an integer constant expression. Take the following example

extern int a;
static_assert(1 || a);

Here a is obviously not a constant expression, but also not evaluated. If we suppose that an implementation accepts 1 || a as a constant expression of integer type, but not as an integer constant expression, the above static_assert is valid. This is indeed the path that gcc and clang seem to have chosen unless presented with a --pendantic commandline option. In fact they accept the above but not

extern int a;
static int X[1 || a];

which would need an integer constant expression as array length expression to be conforming.

As a consequence, the above use of static_assert has a risk of not being accepted by other implementations. But even worse, since the current texts implies undefined behavior, other implementations could even crash without notice when they stumble on this not-so-static assertion. The same holds for other constant expressions of integer type that are not integer constant expressions, such as casts of non-trivial floating expressions; the current text allows implementations to behave erratically when they encounter them.

In any case, the static_assert feature needs a reliable framework that makes sure that the validity of the expression is decided in translation phase 7 and not delayed to linkage or, even worse, to execution time. The simplest way to achieve this is to change the current UB to a constraint violation.

Also, the current text has a “shall” formulating a requirement for the implementation, avoid that.

2 Suggested Wording

New text is underlined green, removed text is stroke-out red.

2.1 In clause 6.7.12, Static assertions

Constraints

2 The constant expression shall compare unequal to 0 be an integer constant expression with a nonzero value.

Semantics

3 The constant expression shall be an integer constant expression. If the value of the constant expression compares unequal to 0, the declaration A static assertion has no effect. Otherwise,

Recommended practice

3′ If the constraint is violated and the implementation shall produce a with an integer constant expression of value zero, the diagnostic message which should include the text of the string literal, if present.

3 Note to the editors and other interested parties

There is a branch on WG14’s gitlab that reflects the proposed changes:

https://gitlab.gwdg.de/iso-c/draft/-/tree/static_assert-UB

Aknowledments

Thanks to Vincent Mailhol and Joseph Myers for review and for providing us with an example.