Skip to content

Commit 35e3cea

Browse files
t-rasmudRashmi Mudduluru
authored andcommitted
[analyzer] Add support for __attribute__((returns_nonnull)).
Differential Revision: https://reviews.llvm.org/D118657 (cherry picked from commit faabdfc)
1 parent e6fbc13 commit 35e3cea

File tree

7 files changed

+90
-0
lines changed

7 files changed

+90
-0
lines changed

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,11 @@ def TrustNonnullChecker : Checker<"TrustNonnull">,
376376
"are not null">,
377377
Documentation<NotDocumented>;
378378

379+
def TrustReturnsNonnullChecker : Checker<"TrustReturnsNonnull">,
380+
HelpText<"Trust that returns from methods annotated with returns_nonnull "
381+
"are not null">,
382+
Documentation<NotDocumented>;
383+
379384
} // end "apiModeling"
380385

381386
//===----------------------------------------------------------------------===//

clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ add_clang_library(clangStaticAnalyzerCheckers
111111
TestAfterDivZeroChecker.cpp
112112
TraversalChecker.cpp
113113
TrustNonnullChecker.cpp
114+
TrustReturnsNonnullChecker.cpp
114115
UndefBranchChecker.cpp
115116
UndefCapturedBlockVarChecker.cpp
116117
UndefResultChecker.cpp
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//== TrustReturnsNonnullChecker.cpp -- API nullability modeling -*- C++ -*--==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This checker adds nullability-related assumptions to methods annotated with
10+
// returns_nonnull attribute.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "clang/AST/Attr.h"
15+
#include "clang/AST/Decl.h"
16+
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
17+
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
18+
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
19+
20+
using namespace clang;
21+
using namespace ento;
22+
23+
namespace {
24+
25+
class TrustReturnsNonnullChecker : public Checker<check::PostCall> {
26+
27+
public:
28+
TrustReturnsNonnullChecker(ASTContext &Ctx) {}
29+
30+
void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
31+
ProgramStateRef State = C.getState();
32+
33+
if (isNonNullPtr(Call))
34+
if (auto L = Call.getReturnValue().getAs<Loc>())
35+
State = State->assume(*L, /*assumption=*/true);
36+
37+
C.addTransition(State);
38+
}
39+
40+
private:
41+
/// \returns Whether the method declaration has the attribute returns_nonnull.
42+
bool isNonNullPtr(const CallEvent &Call) const {
43+
QualType ExprRetType = Call.getResultType();
44+
const Decl *CallDeclaration = Call.getDecl();
45+
if (!ExprRetType->isAnyPointerType() || !CallDeclaration)
46+
return false;
47+
48+
return CallDeclaration->hasAttr<ReturnsNonNullAttr>();
49+
}
50+
};
51+
52+
} // namespace
53+
54+
void ento::registerTrustReturnsNonnullChecker(CheckerManager &Mgr) {
55+
Mgr.registerChecker<TrustReturnsNonnullChecker>(Mgr.getASTContext());
56+
}
57+
58+
bool ento::shouldRegisterTrustReturnsNonnullChecker(const CheckerManager &mgr) {
59+
return true;
60+
}

clang/test/Analysis/analyzer-enabled-checkers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// CHECK-NEXT: core.CallAndMessageModeling
1010
// CHECK-NEXT: apiModeling.StdCLibraryFunctions
1111
// CHECK-NEXT: apiModeling.TrustNonnull
12+
// CHECK-NEXT: apiModeling.TrustReturnsNonnull
1213
// CHECK-NEXT: apiModeling.llvm.CastValue
1314
// CHECK-NEXT: apiModeling.llvm.ReturnValue
1415
// CHECK-NEXT: core.CallAndMessage
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,apiModeling.TrustReturnsNonnull -verify %s
2+
3+
int *foo() __attribute__((returns_nonnull));
4+
5+
int *foo_no_attribute();
6+
7+
int test_foo() {
8+
int *x = foo();
9+
if (x) {}
10+
return *x; // no-warning
11+
}
12+
13+
int test_foo_no_attribute() {
14+
int *x = foo_no_attribute();
15+
if (x) {}
16+
return *x; // expected-warning{{Dereference of null pointer}}
17+
}
18+
19+
void test(void *(*f)(void)) {
20+
f(); // Shouldn't crash compiler
21+
}

clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
// CHECK-NEXT: apiModeling.StdCLibraryFunctions
2323
// CHECK-NEXT: alpha.unix.StdCLibraryFunctionArgs
2424
// CHECK-NEXT: apiModeling.TrustNonnull
25+
// CHECK-NEXT: apiModeling.TrustReturnsNonnull
2526
// CHECK-NEXT: apiModeling.llvm.CastValue
2627
// CHECK-NEXT: apiModeling.llvm.ReturnValue
2728
// CHECK-NEXT: core.DivideZero

llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ static_library("Checkers") {
118118
"TestAfterDivZeroChecker.cpp",
119119
"TraversalChecker.cpp",
120120
"TrustNonnullChecker.cpp",
121+
"TrustReturnsNonnullChecker.cpp",
121122
"UndefBranchChecker.cpp",
122123
"UndefCapturedBlockVarChecker.cpp",
123124
"UndefResultChecker.cpp",

0 commit comments

Comments
 (0)