[clang] [clang][ExprConst] Fix second arg of __builtin_{clzg,ctzg} not always being evaluated (PR #86742)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 26 14:30:03 PDT 2024
https://github.com/overmighty created https://github.com/llvm/llvm-project/pull/86742
See https://github.com/llvm/llvm-project/pull/86577#discussion_r1540069558.
cc @efriedma-quic @nickdesaulniers
>From c615f656153fcb1d4158548660f87d1d69960864 Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Tue, 26 Mar 2024 21:25:59 +0000
Subject: [PATCH] [clang][ExprConst] Fix second arg of __builtin_{clzg,ctzg}
not always being evaluated
---
clang/lib/AST/ExprConstant.cpp | 30 +++++++++-----
.../constant-builtins-all-args-evaluated.cpp | 39 +++++++++++++++++++
2 files changed, 59 insertions(+), 10 deletions(-)
create mode 100644 clang/test/Sema/constant-builtins-all-args-evaluated.cpp
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 5a36621dc5cce2..dae8f32fc02951 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -12361,12 +12361,17 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
if (!EvaluateInteger(E->getArg(0), Val, Info))
return false;
+ std::optional<APSInt> Fallback;
+ if (BuiltinOp == Builtin::BI__builtin_clzg && E->getNumArgs() > 1) {
+ APSInt FallbackTemp;
+ if (!EvaluateInteger(E->getArg(1), FallbackTemp, Info))
+ return false;
+ Fallback = FallbackTemp;
+ }
+
if (!Val) {
- if (BuiltinOp == Builtin::BI__builtin_clzg && E->getNumArgs() > 1) {
- if (!EvaluateInteger(E->getArg(1), Val, Info))
- return false;
- return Success(Val, E);
- }
+ if (Fallback)
+ return Success(*Fallback, E);
// When the argument is 0, the result of GCC builtins is undefined,
// whereas for Microsoft intrinsics, the result is the bit-width of the
@@ -12425,12 +12430,17 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
if (!EvaluateInteger(E->getArg(0), Val, Info))
return false;
+ std::optional<APSInt> Fallback;
+ if (BuiltinOp == Builtin::BI__builtin_ctzg && E->getNumArgs() > 1) {
+ APSInt FallbackTemp;
+ if (!EvaluateInteger(E->getArg(1), FallbackTemp, Info))
+ return false;
+ Fallback = FallbackTemp;
+ }
+
if (!Val) {
- if (BuiltinOp == Builtin::BI__builtin_ctzg && E->getNumArgs() > 1) {
- if (!EvaluateInteger(E->getArg(1), Val, Info))
- return false;
- return Success(Val, E);
- }
+ if (Fallback)
+ return Success(*Fallback, E);
return Error(E);
}
diff --git a/clang/test/Sema/constant-builtins-all-args-evaluated.cpp b/clang/test/Sema/constant-builtins-all-args-evaluated.cpp
new file mode 100644
index 00000000000000..0dee74ddf690cf
--- /dev/null
+++ b/clang/test/Sema/constant-builtins-all-args-evaluated.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr int increment(int& x) {
+ x++;
+ return x;
+}
+
+constexpr int test_clzg_0() {
+ int x = 0;
+ [[maybe_unused]] int unused = __builtin_clzg(0U, increment(x));
+ return x;
+}
+
+static_assert(test_clzg_0() == 1);
+
+constexpr int test_clzg_1() {
+ int x = 0;
+ [[maybe_unused]] int unused = __builtin_clzg(1U, increment(x));
+ return x;
+}
+
+static_assert(test_clzg_1() == 1);
+
+constexpr int test_ctzg_0() {
+ int x = 0;
+ [[maybe_unused]] int unused = __builtin_ctzg(0U, increment(x));
+ return x;
+}
+
+static_assert(test_ctzg_0() == 1);
+
+constexpr int test_ctzg_1() {
+ int x = 0;
+ [[maybe_unused]] int unused = __builtin_ctzg(1U, increment(x));
+ return x;
+}
+
+static_assert(test_ctzg_1() == 1);
More information about the cfe-commits
mailing list