llvm-project/clang/test/Analysis/builtin_bitcast.cpp
Ziqing Luo 41229581a4
[analyzer] Fix crashing __builtin_bit_cast (#139188)
Previously, CSA did not handle __builtin_bit_cast correctly. It
evaluated the LvalueToRvalue conversion for the casting expression,
but did not actually convert the value of the expression to be of the
destination type.
This commit fixes the problem.

rdar://149987320
2025-05-13 10:24:02 -07:00

69 lines
2.2 KiB
C++

// RUN: %clang_analyze_cc1 -triple x86_64-unknown-unknown -verify %s \
// RUN: -analyzer-checker=core,debug.ExprInspection -analyzer-disable-checker=core.FixedAddressDereference
template <typename T> void clang_analyzer_dump(T);
using size_t = decltype(sizeof(int));
__attribute__((always_inline)) static inline constexpr unsigned int _castf32_u32(float __A) {
return __builtin_bit_cast(unsigned int, __A); // no-warning
}
void test(int i) {
_castf32_u32(42);
float f = 42;
// Loading from a floating point value results in unknown,
// which later materializes as a conjured value.
auto g = __builtin_bit_cast(unsigned int, f);
clang_analyzer_dump(g);
// expected-warning-re@-1 {{{{^conj_\$[0-9]+{unsigned int,}}}}
auto g2 = __builtin_bit_cast(unsigned int, 42.0f);
clang_analyzer_dump(g2);
// expected-warning-re@-1 {{{{^conj_\$[0-9]+{unsigned int,}}}}
auto g3 = __builtin_bit_cast(unsigned int, i);
clang_analyzer_dump(g3);
// expected-warning-re@-1 {{{{^reg_\$[0-9]+<int i>}}}}
auto g4 = __builtin_bit_cast(unsigned long, &i);
clang_analyzer_dump(g4);
// expected-warning@-1 {{&i [as 64 bit integer]}}
}
struct A {
int n;
void set(int x) {
n = x;
}
};
void gh_69922(size_t p) {
// expected-warning@+1 {{Unknown}}
clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));
__builtin_bit_cast(A*, p & 1)->set(2); // no-crash
// However, since the `this` pointer is expected to be a Loc, but we have
// NonLoc there, we simply give up and resolve it as `Unknown`.
// Then, inside the `set()` member function call we can't evaluate the
// store to the member variable `n`.
clang_analyzer_dump(__builtin_bit_cast(A*, p & 1)->n); // Ideally, this should print "2".
// expected-warning@-1 {{Unknown}}
}
namespace {
typedef unsigned long uintptr_t;
bool previously_crash(const void *& ptr) {
clang_analyzer_dump(__builtin_bit_cast(void*, static_cast<uintptr_t>(-1)));
// expected-warning-re@-1 {{{{[0-9]+}} (Loc)}}
return ptr == __builtin_bit_cast(void*, static_cast<uintptr_t>(-1));
}
void check_loc_concreteInt() {
clang_analyzer_dump(__builtin_bit_cast(unsigned, *(reinterpret_cast<int*>(0xdeadbeef))));
// expected-warning@-1 {{Unknown}}
}
}