[clang] Clang/Preprocessor: Support short circuit in directive (PR #123912)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 22 01:11:42 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: YunQiang Su (wzssyqa)
<details>
<summary>Changes</summary>
Don't Evaluate RHS in if directive when short circuit. Examples include
#if 0 && another_condition
#if 1 || another_condition
---
Full diff: https://github.com/llvm/llvm-project/pull/123912.diff
2 Files Affected:
- (modified) clang/lib/Lex/PPExpressions.cpp (+27-1)
- (added) clang/test/Preprocessor/directive-short-circuit.c (+74)
``````````diff
diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp
index a3b1384f0fa1d6..7e413ec6076642 100644
--- a/clang/lib/Lex/PPExpressions.cpp
+++ b/clang/lib/Lex/PPExpressions.cpp
@@ -624,7 +624,33 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
// Consume the operator, remembering the operator's location for reporting.
SourceLocation OpLoc = PeekTok.getLocation();
- PP.LexNonComment(PeekTok);
+
+ if (!RHSIsLive && (Operator == tok::ampamp || Operator == tok::pipepipe)) {
+ unsigned ThisPrec = PeekPrec;
+ while (true) {
+ PP.LexUnexpandedNonComment(PeekTok);
+ if (PeekTok.is(tok::l_paren)) {
+ unsigned NestParen = 1;
+ while (true) {
+ PP.LexUnexpandedNonComment(PeekTok);
+ if (PeekTok.is(tok::l_paren))
+ NestParen++;
+ else if (PeekTok.is(tok::r_paren))
+ NestParen--;
+ if (NestParen == 0)
+ break;
+ }
+ PP.LexUnexpandedNonComment(PeekTok);
+ }
+ PeekPrec = getPrecedence(PeekTok.getKind());
+ if (PeekPrec <= ThisPrec) {
+ LHS.setEnd(PeekTok.getEndLoc());
+ break;
+ }
+ }
+ continue;
+ } else
+ PP.LexNonComment(PeekTok);
PPValue RHS(LHS.getBitWidth());
// Parse the RHS of the operator.
diff --git a/clang/test/Preprocessor/directive-short-circuit.c b/clang/test/Preprocessor/directive-short-circuit.c
new file mode 100644
index 00000000000000..d137f8198cbbcf
--- /dev/null
+++ b/clang/test/Preprocessor/directive-short-circuit.c
@@ -0,0 +1,74 @@
+// RUN: %clang -E -MD -MF - %s | FileCheck -check-prefix ZERO_AND_HAS_INCLUDE %s
+//
+// ZERO_AND_HAS_INCLUDE-NOT: limits.h
+//
+#if 0 && __has_include(<limits.h>)
+#include <limits.h>
+#endif
+
+#if 4==5 && __has_include(<limits.h>)
+#include <limits.h>
+#endif
+
+#if defined(_THIS_IS_NOT_DEFINED) && __has_include(<limits.h>)
+#include <limits.h>
+#endif
+
+#if 0 && (__has_include(<limits.h>))
+#include <limits.h>
+#endif
+
+#if 4==5 && (__has_include(<limits.h>))
+#include <limits.h>
+#endif
+
+#if defined(_THIS_IS_NOT_DEFINED) && (__has_include(<limits.h>))
+#include <limits.h>
+#endif
+
+#if 0 && (5==5 && __has_include(<limits.h>))
+#include <limits.h>
+#endif
+
+#if 1 && (4==5 && __has_include(<limits.h>))
+#include <limits.h>
+#endif
+
+
+
+
+
+
+#if 1 || __has_include(<limits.h>)
+XXXXXXXXXX
+#endif
+#if 5==5 || __has_include(<limits.h>)
+XXXXXXXXXX
+#endif
+
+#if defined(__clang__) || __has_include(<limits.h>)
+XXXXXXXXXX
+#endif
+
+#if 1 || (__has_include(<limits.h>))
+#endif
+
+#if 5==5 || (__has_include(<limits.h>))
+XXXXXXXXXX
+#endif
+
+#if defined(__clang__) || (__has_include(<limits.h>))
+XXXXXXXXXX
+#endif
+
+#if 1 && (5==5 || __has_include(<limits.h>))
+XXXXXXXXXX
+#endif
+
+#if 1 || (5==5 || __has_include(<limits.h>))
+XXXXXXXXXX
+#endif
+
+#if 0 || (5==5 || __has_include(<limits.h>))
+XXXXXXXXXX
+#endif
``````````
</details>
https://github.com/llvm/llvm-project/pull/123912
More information about the cfe-commits
mailing list