Reject invalid integer constants in unevaluated preprocessor operands (#134884)

Clang was previously accepting invalid code like:
```
  #if 1 ? 1 : 999999999999999999999
  #endif
```
because the integer constant (which is too large to fit into any
standard or extended integer type) was in an unevaluated branch of the
conditional operator. Similar invalid code involving || or && was also
accepted and is now rejected.

Fixes #134658
This commit is contained in:
Aaron Ballman 2025-04-08 14:25:59 -04:00 committed by GitHub
parent 7e70d708a3
commit 9ba1a3fcb5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 3 deletions

View File

@ -354,6 +354,14 @@ Bug Fixes in This Version
- Defining an integer literal suffix (e.g., ``LL``) before including
``<stdint.h>`` in a freestanding build no longer causes invalid token pasting
when using the ``INTn_C`` macros. (#GH85995)
- Clang no longer accepts invalid integer constants which are too large to fit
into any (standard or extended) integer type when the constant is unevaluated.
Merely forming the token is sufficient to render the program invalid. Code
like this was previously accepted and is now rejected (#GH134658):
.. code-block:: c
#if 1 ? 1 : 999999999999999999999
#endif
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -345,9 +345,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// Parse the integer literal into Result.
if (Literal.GetIntegerValue(Result.Val)) {
// Overflow parsing integer literal.
if (ValueLive)
PP.Diag(PeekTok, diag::err_integer_literal_too_large)
<< /* Unsigned */ 1;
PP.Diag(PeekTok, diag::err_integer_literal_too_large) << /* Unsigned */ 1;
Result.Val.setIsUnsigned(true);
} else {
// Set the signedness of the result to match whether there was a U suffix

View File

@ -0,0 +1,40 @@
// RUN: %clang_cc1 -E -verify %s
// C++ [lex.icon]p4 and C 6.4.4.1p2 + 6.4.4.2p7 both require C and C++ to
// validate the integer constant value when converting a preprocessing token
// into a token for semantic analysis, even within the preprocessor itself.
// Plain integer constant.
#if 999999999999999999999 // expected-error {{integer literal is too large to be represented in any integer type}}
#endif
// These cases were previously incorrectly accepted. See GH134658.
// Integer constant in an unevaluated branch of a conditional.
#if 1 ? 1 : 999999999999999999999 // expected-error {{integer literal is too large to be represented in any integer type}}
#endif
// Integer constant in an unevaluated operand of a logical operator.
#if 0 && 999999999999999999999 // expected-error {{integer literal is too large to be represented in any integer type}}
#endif
#if 1 || 999999999999999999999 // expected-error {{integer literal is too large to be represented in any integer type}}
#endif
// Make sure we also catch it in an elif condition.
#if 0
#elif 1 || 999999999999999999999 // expected-error {{integer literal is too large to be represented in any integer type}}
#endif
// However, if the block is skipped entirely, then it doesn't matter how
// invalid the constant value is.
#if 0
int x = 999999999999999999999;
#if 999999999999999999999
#endif
#if 0 && 999999999999999999999
#endif
#endif