4149. User defined macros without standard headers (294 redux)

Section: 16.4.5.3.3 [macro.names] Status: New Submitter: Jonathan Wakely Opened: 2024-09-05 Last modified: 2024-09-05

Priority: Not Prioritized

View other active issues in [macro.names].

View all other issues in [macro.names].

View all issues with New status.

Discussion:

Issue 294 changed 16.4.5.3.3 [macro.names] from:

A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords.
to:
A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.

A translation unit shall not #define or #undef names lexically identical to keywords.

Note that the second sentence of the original says "such a translation unit" when prohibiting things like #define while. This means the prohibition only applies to "a translation unit that includes a header". The replacement has the prohibition in a separate paragraph and does not clearly say that it only applies when a header is included.

The issue discussion seems clear that the concern is about C++ headers including other unspecified headers, which is allowed in C++ (though not in C). There is no justification for broadening the second sentence to apply unconditionally. Such a rule would belong in 15 [cpp] anyway, not in library wording. That overreach doesn't appear to have been intended, and we should clarify what the library is prohibiting.

It was pointed out on the reflector that it's not enough to only prohibit defining such macros after including headers, because in some cases that could still break the library header. For example, the library macro assert typically uses void and so #define void ... would break assert even if it happens after including <cassert>.

Proposed resolution:

This wording is relative to N4986.

  1. Modify 16.4.5.3.3 [macro.names] as indicated:

    -1- A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.

    -2- A translation unit that includes a standard library header shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 4, or to the attribute-tokens described in 9.12 [dcl.attr], except that the names likely and unlikely may be defined as function-like macros (15.6 [cpp.replace]).