You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
3.6 KiB
171 lines
3.6 KiB
/*
|
|
* Copyright (c) 2017-present, Facebook, Inc.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
bool star();
|
|
|
|
class T {
|
|
public:
|
|
int x;
|
|
T* field;
|
|
|
|
public:
|
|
int* _Nullable mayReturnNullPointer() {
|
|
if (star()) {
|
|
return nullptr;
|
|
} else {
|
|
return new int;
|
|
}
|
|
}
|
|
|
|
public:
|
|
T* _Nullable mayReturnNullObject() {
|
|
if (star()) {
|
|
return nullptr;
|
|
} else {
|
|
return this;
|
|
}
|
|
}
|
|
|
|
public:
|
|
T* doesNotReturnNullObject() { return new T(); }
|
|
|
|
public:
|
|
void doSomething() {}
|
|
};
|
|
|
|
void assignNullableValueBad(T* t) {
|
|
int* p = t->mayReturnNullPointer();
|
|
*p = 42;
|
|
}
|
|
|
|
void reassigningNullablePointerOkay(T* t) {
|
|
int* p = t->mayReturnNullPointer();
|
|
p = new int; // does not report here
|
|
*p = 42; // does not report here
|
|
}
|
|
|
|
void reassigningNullablePointerToNullOkay(T* t) {
|
|
int* p = t->mayReturnNullPointer();
|
|
p = nullptr; // does not report here
|
|
}
|
|
|
|
void callMethodOnNullableObjectBad(T* t) {
|
|
t->mayReturnNullObject()->doSomething();
|
|
}
|
|
|
|
void callMethodOnNullableObjectOkay(T* t) {
|
|
T* p = t->mayReturnNullObject();
|
|
if (p != nullptr) {
|
|
p->doSomething();
|
|
}
|
|
}
|
|
|
|
void dereferenceFieldOfNullableObjectBad(T* t) {
|
|
T* p = t->mayReturnNullObject();
|
|
p->x = 42;
|
|
}
|
|
|
|
void methodCallOnFieldOfNullableObjectBad(T* t) {
|
|
T* p = t->mayReturnNullObject();
|
|
p->field->doSomething();
|
|
}
|
|
|
|
void avoidDoubleReportingBad(T* t) {
|
|
T* p = t->mayReturnNullObject();
|
|
p->doSomething(); // reports here
|
|
p->doSomething(); // does not report here
|
|
}
|
|
|
|
void nullableAssignmentInOneBranchBad(T* t) {
|
|
T* p;
|
|
if (star()) {
|
|
p = t->mayReturnNullObject();
|
|
} else {
|
|
p = t->doesNotReturnNullObject();
|
|
}
|
|
p->doSomething(); // reports here
|
|
}
|
|
|
|
void methodCheckedForNullOkay(T* t) {
|
|
if (t->mayReturnNullObject() != nullptr) {
|
|
t->mayReturnNullObject()->doSomething(); // does not report here
|
|
}
|
|
}
|
|
|
|
void methodCheckedForNullAndReturnOkay(T* t) {
|
|
if (t->mayReturnNullObject() == nullptr) {
|
|
return;
|
|
}
|
|
t->mayReturnNullObject()->doSomething(); // does not report here
|
|
}
|
|
|
|
void reportsViolationOutsideOfNullCheckBad(T* t) {
|
|
if (t->mayReturnNullObject() != nullptr) {
|
|
t->mayReturnNullObject()->doSomething(); // does not report here
|
|
}
|
|
t->mayReturnNullObject()->doSomething(); // reports here
|
|
}
|
|
|
|
void reportsViolationInNullBranchBad(T* t) {
|
|
if (t->mayReturnNullObject() == nullptr) {
|
|
t->mayReturnNullObject()->doSomething(); // reports here
|
|
}
|
|
}
|
|
|
|
void reportsViolationInNotNullElseBranchBad(T* t) {
|
|
if (t->mayReturnNullObject() != nullptr) {
|
|
} else {
|
|
t->mayReturnNullObject()->doSomething(); // reports here
|
|
}
|
|
}
|
|
|
|
void methodAlwaysCheckedForNullOkay(T* t) {
|
|
if (star() && t->mayReturnNullObject() != nullptr) {
|
|
t->mayReturnNullObject()->doSomething(); // does not report here
|
|
}
|
|
}
|
|
|
|
void methodNotAlwaysCheckedForNullBad(T* t) {
|
|
if (star() || t->mayReturnNullObject() != nullptr) {
|
|
t->mayReturnNullObject()->doSomething(); // reports here
|
|
}
|
|
}
|
|
|
|
void onlyReportOnceBad(T* t) {
|
|
t->mayReturnNullObject()->doSomething(); // reports here
|
|
// ...
|
|
t->mayReturnNullObject()->doSomething(); // does not report here
|
|
}
|
|
|
|
void dereferenceOfAliasesCheckedForNullOkay(T* t) {
|
|
T* s = t->mayReturnNullObject();
|
|
T* r = s;
|
|
if (r != nullptr) {
|
|
s->doSomething();
|
|
}
|
|
}
|
|
|
|
void pointerTestOkay(T* t) {
|
|
T* p = t->mayReturnNullObject();
|
|
if (p) {
|
|
p->doSomething();
|
|
}
|
|
}
|
|
|
|
void pointerTestBad(T* t) {
|
|
T* p = t->mayReturnNullObject();
|
|
if (p) {
|
|
// ...
|
|
}
|
|
p->doSomething();
|
|
}
|
|
|
|
void methodTestedForNullOkay(T* t) {
|
|
if (t->mayReturnNullObject()) {
|
|
t->mayReturnNullObject()->doSomething();
|
|
}
|
|
}
|