A C++ overloaded operator may be implemented as an instance method, and that instance method may be called on an rvalue object, which has no associated region. The analyzer handles this by creating a temporary region just for the evaluation of this call; however, it is possible that /by creating the region/, the analyzer ends up in a previously-explored state. In this case we don't need to continue along this path. This doesn't actually show any behavioral change now, but it starts being used with the next commit and prevents an assertion failure there. llvm-svn: 179766
88 lines
1.7 KiB
C++
88 lines
1.7 KiB
C++
// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s
|
|
void clang_analyzer_eval(bool);
|
|
|
|
struct X0 { };
|
|
bool operator==(const X0&, const X0&);
|
|
|
|
// PR7287
|
|
struct test { int a[2]; };
|
|
|
|
void t2() {
|
|
test p = {{1,2}};
|
|
test q;
|
|
q = p;
|
|
}
|
|
|
|
bool PR7287(X0 a, X0 b) {
|
|
return operator==(a, b);
|
|
}
|
|
|
|
|
|
// Inlining non-static member operators mistakenly treated 'this' as the first
|
|
// argument for a while.
|
|
|
|
struct IntComparable {
|
|
bool operator==(int x) const {
|
|
return x == 0;
|
|
}
|
|
};
|
|
|
|
void testMemberOperator(IntComparable B) {
|
|
clang_analyzer_eval(B == 0); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
|
|
|
|
namespace UserDefinedConversions {
|
|
class Convertible {
|
|
public:
|
|
operator int() const {
|
|
return 42;
|
|
}
|
|
operator bool() const {
|
|
return true;
|
|
}
|
|
};
|
|
|
|
void test(const Convertible &obj) {
|
|
clang_analyzer_eval((int)obj == 42); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(obj); // expected-warning{{TRUE}}
|
|
}
|
|
}
|
|
|
|
|
|
namespace RValues {
|
|
struct SmallOpaque {
|
|
float x;
|
|
int operator +() const {
|
|
return (int)x;
|
|
}
|
|
};
|
|
|
|
struct LargeOpaque {
|
|
float x[4];
|
|
int operator +() const {
|
|
return (int)x[0];
|
|
}
|
|
};
|
|
|
|
SmallOpaque getSmallOpaque() {
|
|
SmallOpaque obj;
|
|
obj.x = 1.0;
|
|
return obj;
|
|
}
|
|
|
|
LargeOpaque getLargeOpaque() {
|
|
LargeOpaque obj = LargeOpaque();
|
|
obj.x[0] = 1.0;
|
|
return obj;
|
|
}
|
|
|
|
void test(int coin) {
|
|
// Force a cache-out when we try to conjure a temporary region for the operator call.
|
|
// ...then, don't crash.
|
|
clang_analyzer_eval(+(coin ? getSmallOpaque() : getSmallOpaque())); // expected-warning{{UNKNOWN}}
|
|
clang_analyzer_eval(+(coin ? getLargeOpaque() : getLargeOpaque())); // expected-warning{{UNKNOWN}}
|
|
}
|
|
}
|