-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Reject invalid integer constants in unevaluated preprocessor operands #134884
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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 llvm#134658
@llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) ChangesClang was previously accepting invalid code like:
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 Full diff: https://github.com/llvm/llvm-project/pull/134884.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f8f4dfbafb4f8..6c86406ef36db 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -351,6 +351,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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp
index b031571907441..6a6762828a20e 100644
--- a/clang/lib/Lex/PPExpressions.cpp
+++ b/clang/lib/Lex/PPExpressions.cpp
@@ -345,9 +345,8 @@ 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
diff --git a/clang/test/Preprocessor/constants.c b/clang/test/Preprocessor/constants.c
new file mode 100644
index 0000000000000..d6241a4f1ceee
--- /dev/null
+++ b/clang/test/Preprocessor/constants.c
@@ -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
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
I suppose if people complain, we can make the non-live value case a warning rather than an error, but given no other implementation does, I think it makes sense not to do that speculatively.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/17916 Here is the relevant piece of the build log for the reference
|
…llvm#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 llvm#134658
Clang was previously accepting invalid code like:
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