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

/*
* 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();
}
}