[clang] cf73f13 - [clang][ExprConst] Fix second arg of __builtin_{clzg,ctzg} not always being evaluated (#86742)

via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 29 14:01:23 PDT 2024


Author: OverMighty
Date: 2024-03-29T14:01:19-07:00
New Revision: cf73f136c5e22e7e4090fc762456ace47752a898

URL: https://github.com/llvm/llvm-project/commit/cf73f136c5e22e7e4090fc762456ace47752a898
DIFF: https://github.com/llvm/llvm-project/commit/cf73f136c5e22e7e4090fc762456ace47752a898.diff

LOG: [clang][ExprConst] Fix second arg of __builtin_{clzg,ctzg} not always being evaluated (#86742)

Even if we don't actually use the value of the second argument, we have to evaluate it for side-effects.

---------

Co-authored-by: Richard Smith <richard at metafoo.co.uk>

Added: 
    clang/test/Sema/constant-builtins-all-args-evaluated.cpp

Modified: 
    clang/lib/AST/ExprConstant.cpp

Removed: 
    


################################################################################
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..db55e24cecda7a
--- /dev/null
+++ b/clang/test/Sema/constant-builtins-all-args-evaluated.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr int test_clzg_0() {
+  int x = 0;
+  (void)__builtin_clzg(0U, ++x);
+  return x;
+}
+
+static_assert(test_clzg_0() == 1);
+
+constexpr int test_clzg_1() {
+  int x = 0;
+  (void)__builtin_clzg(1U, ++x);
+  return x;
+}
+
+static_assert(test_clzg_1() == 1);
+
+constexpr int test_ctzg_0() {
+  int x = 0;
+  (void)__builtin_ctzg(0U, ++x);
+  return x;
+}
+
+static_assert(test_ctzg_0() == 1);
+
+constexpr int test_ctzg_1() {
+  int x = 0;
+  (void)__builtin_ctzg(1U, ++x);
+  return x;
+}
+
+static_assert(test_ctzg_1() == 1);


        


More information about the cfe-commits mailing list