It’s important for us to reason about the cast as it is used in std::addressof. The reason we did not handle the cast previously was a crash on a test case (see commit r157478). The crash was in processing array to pointer decay when the region type was not an array. Address the issue, by just returning an unknown in that case. llvm-svn: 182808
105 lines
2.1 KiB
C++
105 lines
2.1 KiB
C++
// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
|
|
|
|
void clang_analyzer_eval(bool);
|
|
|
|
typedef struct Opaque *Data;
|
|
struct IntWrapper {
|
|
int x;
|
|
};
|
|
|
|
struct Child : public IntWrapper {
|
|
void set() { x = 42; }
|
|
};
|
|
|
|
void test(Data data) {
|
|
Child *wrapper = reinterpret_cast<Child*>(data);
|
|
// Don't crash when upcasting here.
|
|
// We don't actually know if 'data' is a Child.
|
|
wrapper->set();
|
|
clang_analyzer_eval(wrapper->x == 42); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
namespace PR14872 {
|
|
class Base1 {};
|
|
class Derived1 : public Base1 {};
|
|
|
|
Derived1 *f1();
|
|
|
|
class Base2 {};
|
|
class Derived2 : public Base2 {};
|
|
|
|
void f2(Base2 *foo);
|
|
|
|
void f3(void** out)
|
|
{
|
|
Base1 *v;
|
|
v = f1();
|
|
*out = v;
|
|
}
|
|
|
|
void test()
|
|
{
|
|
Derived2 *p;
|
|
f3(reinterpret_cast<void**>(&p));
|
|
// Don't crash when upcasting here.
|
|
// In this case, 'p' actually refers to a Derived1.
|
|
f2(p);
|
|
}
|
|
}
|
|
|
|
namespace rdar13249297 {
|
|
struct IntWrapperSubclass : public IntWrapper {};
|
|
|
|
struct IntWrapperWrapper {
|
|
IntWrapper w;
|
|
};
|
|
|
|
void test(IntWrapperWrapper *ww) {
|
|
reinterpret_cast<IntWrapperSubclass *>(ww)->x = 42;
|
|
clang_analyzer_eval(reinterpret_cast<IntWrapperSubclass *>(ww)->x == 42); // expected-warning{{TRUE}}
|
|
|
|
clang_analyzer_eval(ww->w.x == 42); // expected-warning{{TRUE}}
|
|
ww->w.x = 0;
|
|
|
|
clang_analyzer_eval(reinterpret_cast<IntWrapperSubclass *>(ww)->x == 42); // expected-warning{{FALSE}}
|
|
}
|
|
}
|
|
|
|
namespace PR15345 {
|
|
class C {};
|
|
|
|
class Base {
|
|
public:
|
|
void (*f)();
|
|
int x;
|
|
};
|
|
|
|
class Derived : public Base {};
|
|
|
|
void test() {
|
|
Derived* p;
|
|
*(reinterpret_cast<void**>(&p)) = new C;
|
|
p->f();
|
|
|
|
// We should still be able to do some reasoning about bindings.
|
|
p->x = 42;
|
|
clang_analyzer_eval(p->x == 42); // expected-warning{{TRUE}}
|
|
};
|
|
}
|
|
|
|
int trackpointer_std_addressof() {
|
|
int x;
|
|
int *p = (int*)&reinterpret_cast<const volatile char&>(x);
|
|
*p = 6;
|
|
return x; // no warning
|
|
}
|
|
|
|
void set_x1(int *&);
|
|
void set_x2(void *&);
|
|
int radar_13146953(void) {
|
|
int *x = 0, *y = 0;
|
|
|
|
set_x1(x);
|
|
set_x2((void *&)y);
|
|
return *x + *y; // no warning
|
|
} |