[clang] [analyzer] Report violations of the "returns_nonnull" attribute (PR #106048)
DonĂ¡t Nagy via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 26 06:38:55 PDT 2024
================
@@ -10,3 +12,42 @@ void block_arity_mismatch() {
void(^b)() = ^(int a, int b) { };
b(1); // no-crash expected-warning {{Block taking 2 arguments is called with fewer (1)}}
}
+
+int *nonnull_return_annotation_indirect() __attribute__((returns_nonnull));
+int *nonnull_return_annotation_indirect() {
+ int *x = 0;
+ return x; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
+}
+
+int *nonnull_return_annotation_direct() __attribute__((returns_nonnull));
+int *nonnull_return_annotation_direct() {
+ return 0; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
+} // expected-warning at -1 {{null returned from function that requires a non-null return value}}
+
+int *nonnull_return_annotation_assumed() __attribute__((returns_nonnull));
+int *nonnull_return_annotation_assumed(int* ptr) {
+ if (ptr) {
+ return ptr;
+ }
+ return ptr; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
+}
+
+int *produce_nonnull_ptr() __attribute__((returns_nonnull));
+
+__attribute__((returns_nonnull))
+int *cannot_return_null() {
+ int *x = produce_nonnull_ptr();
+ if (!x) {
+ clang_analyzer_warnIfReached();
+ // Incorrect: expected-warning at -1 {{REACHABLE}}
+ // According to produce_nonnull_ptr contract, x cannot be null.
+ }
+ // Regardless of the potential state split above, x cannot be nullptr
+ // according to the produce_nonnull_ptr annotation.
+ return x;
+ // False positive: expected-warning at -1 {{Null returned from a function that is expected to return a non-null value}}
+}
+
+__attribute__((returns_nonnull)) int *passthrough(int *p) {
+ return p; // no-warning: we have no evidence that `p` is null, i.e., violating the contract
+}
----------------
NagyDonat wrote:
Consider adding a variant of this where a passthrough function is used in a situation where it's known to return null.
```cpp
__attribute__((returns_nonnull)) int *passthrough2(int *p) {
return p;
}
void call_with_null(void) {
passthrough2(NULL);
}
```
https://github.com/llvm/llvm-project/pull/106048
More information about the cfe-commits
mailing list