Skip to content

Commit cf73f13

Browse files
overmightyzygoloid
andauthored
[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 <[email protected]>
1 parent 12fdf04 commit cf73f13

File tree

2 files changed

+54
-10
lines changed

2 files changed

+54
-10
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12361,12 +12361,17 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1236112361
if (!EvaluateInteger(E->getArg(0), Val, Info))
1236212362
return false;
1236312363

12364+
std::optional<APSInt> Fallback;
12365+
if (BuiltinOp == Builtin::BI__builtin_clzg && E->getNumArgs() > 1) {
12366+
APSInt FallbackTemp;
12367+
if (!EvaluateInteger(E->getArg(1), FallbackTemp, Info))
12368+
return false;
12369+
Fallback = FallbackTemp;
12370+
}
12371+
1236412372
if (!Val) {
12365-
if (BuiltinOp == Builtin::BI__builtin_clzg && E->getNumArgs() > 1) {
12366-
if (!EvaluateInteger(E->getArg(1), Val, Info))
12367-
return false;
12368-
return Success(Val, E);
12369-
}
12373+
if (Fallback)
12374+
return Success(*Fallback, E);
1237012375

1237112376
// When the argument is 0, the result of GCC builtins is undefined,
1237212377
// whereas for Microsoft intrinsics, the result is the bit-width of the
@@ -12425,12 +12430,17 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1242512430
if (!EvaluateInteger(E->getArg(0), Val, Info))
1242612431
return false;
1242712432

12433+
std::optional<APSInt> Fallback;
12434+
if (BuiltinOp == Builtin::BI__builtin_ctzg && E->getNumArgs() > 1) {
12435+
APSInt FallbackTemp;
12436+
if (!EvaluateInteger(E->getArg(1), FallbackTemp, Info))
12437+
return false;
12438+
Fallback = FallbackTemp;
12439+
}
12440+
1242812441
if (!Val) {
12429-
if (BuiltinOp == Builtin::BI__builtin_ctzg && E->getNumArgs() > 1) {
12430-
if (!EvaluateInteger(E->getArg(1), Val, Info))
12431-
return false;
12432-
return Success(Val, E);
12433-
}
12442+
if (Fallback)
12443+
return Success(*Fallback, E);
1243412444

1243512445
return Error(E);
1243612446
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
// expected-no-diagnostics
3+
4+
constexpr int test_clzg_0() {
5+
int x = 0;
6+
(void)__builtin_clzg(0U, ++x);
7+
return x;
8+
}
9+
10+
static_assert(test_clzg_0() == 1);
11+
12+
constexpr int test_clzg_1() {
13+
int x = 0;
14+
(void)__builtin_clzg(1U, ++x);
15+
return x;
16+
}
17+
18+
static_assert(test_clzg_1() == 1);
19+
20+
constexpr int test_ctzg_0() {
21+
int x = 0;
22+
(void)__builtin_ctzg(0U, ++x);
23+
return x;
24+
}
25+
26+
static_assert(test_ctzg_0() == 1);
27+
28+
constexpr int test_ctzg_1() {
29+
int x = 0;
30+
(void)__builtin_ctzg(1U, ++x);
31+
return x;
32+
}
33+
34+
static_assert(test_ctzg_1() == 1);

0 commit comments

Comments
 (0)