94 lines
2.1 KiB
C++
94 lines
2.1 KiB
C++
// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c %s
|
|
// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c++ -analyzer-config c++-inlining=constructors %s
|
|
|
|
void clang_analyzer_eval(int);
|
|
|
|
struct S {
|
|
int field;
|
|
|
|
#if __cplusplus
|
|
const struct S *getThis() const { return this; }
|
|
#endif
|
|
};
|
|
|
|
struct S getS();
|
|
|
|
|
|
void testAssignment() {
|
|
struct S s = getS();
|
|
|
|
if (s.field != 42) return;
|
|
clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
|
|
|
|
s.field = 0;
|
|
clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}}
|
|
|
|
#if __cplusplus
|
|
clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
|
|
#endif
|
|
}
|
|
|
|
|
|
void testImmediateUse() {
|
|
int x = getS().field;
|
|
|
|
if (x != 42) return;
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
|
|
#if __cplusplus
|
|
clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}}
|
|
#endif
|
|
}
|
|
|
|
int getConstrainedField(struct S s) {
|
|
if (s.field != 42) return 42;
|
|
return s.field;
|
|
}
|
|
|
|
int getAssignedField(struct S s) {
|
|
s.field = 42;
|
|
return s.field;
|
|
}
|
|
|
|
void testArgument() {
|
|
clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}
|
|
#if __cplusplus
|
|
// FIXME: Passing the struct by value seems to be confusing C++.
|
|
// Possibly related to <rdar://problem/12137950>.
|
|
// expected-warning@-4{{UNKNOWN}}
|
|
#endif
|
|
|
|
clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
|
|
//--------------------
|
|
// C++-only tests
|
|
//--------------------
|
|
|
|
#if __cplusplus
|
|
void testReferenceAssignment() {
|
|
const S &s = getS();
|
|
|
|
if (s.field != 42) return;
|
|
clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
|
|
|
|
clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
|
|
int getConstrainedFieldRef(const S &s) {
|
|
if (s.field != 42) return 42;
|
|
return s.field;
|
|
}
|
|
|
|
bool checkThis(const S &s) {
|
|
return s.getThis() == &s;
|
|
}
|
|
|
|
void testReferenceArgument() {
|
|
clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
|
|
}
|
|
#endif
|