[clang] Clang/Preprocessor: Support short circuit in directive (PR #123912)
YunQiang Su via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 22 02:34:43 PST 2025
https://github.com/wzssyqa updated https://github.com/llvm/llvm-project/pull/123912
>From f0010f932ae3c89651c631736a7aa495027e8fdc Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Wed, 22 Jan 2025 09:04:44 +0000
Subject: [PATCH] Clang/Preprocessor: Support short circuit in directive
Don't Evaluate RHS in if directive when short circuit.
Examples include
#if 0 && another_condition
#if 1 || another_condition
---
clang/lib/Lex/PPExpressions.cpp | 28 ++++++-
clang/test/C/drs/dr2xx.c | 2 +-
...wavefront-size-deprecation-diagnostics.hip | 2 +-
.../Preprocessor/directive-short-circuit.c | 74 +++++++++++++++++++
4 files changed, 103 insertions(+), 3 deletions(-)
create mode 100644 clang/test/Preprocessor/directive-short-circuit.c
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/C/drs/dr2xx.c b/clang/test/C/drs/dr2xx.c
index ffdf5aac377d97..a1e24257f2e8ed 100644
--- a/clang/test/C/drs/dr2xx.c
+++ b/clang/test/C/drs/dr2xx.c
@@ -258,7 +258,7 @@ void dr252(void) {
void dr258(void) {
/* We get the diagnostic twice because the argument is used twice in the
* expansion. */
-#define repeat(x) x && x
+#define repeat(x) x || x
#if repeat(defined fred) /* expected-warning 2 {{macro expansion producing 'defined' has undefined behavior}} */
#endif
diff --git a/clang/test/Driver/hip-wavefront-size-deprecation-diagnostics.hip b/clang/test/Driver/hip-wavefront-size-deprecation-diagnostics.hip
index 8a60f5a150048f..dcd0b4f6f9fdd6 100644
--- a/clang/test/Driver/hip-wavefront-size-deprecation-diagnostics.hip
+++ b/clang/test/Driver/hip-wavefront-size-deprecation-diagnostics.hip
@@ -23,7 +23,7 @@ template<int N> __attribute__((host, device)) int templatify(int x) {
__attribute__((device)) const int GlobalConst = __AMDGCN_WAVEFRONT_SIZE__; // expected-warning {{macro '__AMDGCN_WAVEFRONT_SIZE__' has been marked as deprecated}}
constexpr int GlobalConstExpr = __AMDGCN_WAVEFRONT_SIZE__; // expected-warning {{macro '__AMDGCN_WAVEFRONT_SIZE__' has been marked as deprecated}}
-#if defined(__HIP_DEVICE_COMPILE__) && (__AMDGCN_WAVEFRONT_SIZE__ == 64) // expected-warning {{macro '__AMDGCN_WAVEFRONT_SIZE__' has been marked as deprecated}}
+#if (__AMDGCN_WAVEFRONT_SIZE__ == 64) && defined(__HIP_DEVICE_COMPILE__) // expected-warning {{macro '__AMDGCN_WAVEFRONT_SIZE__' has been marked as deprecated}}
int foo(void);
#endif
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
More information about the cfe-commits
mailing list