[llvm] faabdfc - [analyzer] Add support for __attribute__((returns_nonnull)).
Artem Dergachev via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 2 11:46:59 PST 2022
Author: Rashmi Mudduluru
Date: 2022-02-02T11:46:52-08:00
New Revision: faabdfcf7f6704d5a7241d8b79b4dd5cc7a5527e
URL: https://github.com/llvm/llvm-project/commit/faabdfcf7f6704d5a7241d8b79b4dd5cc7a5527e
DIFF: https://github.com/llvm/llvm-project/commit/faabdfcf7f6704d5a7241d8b79b4dd5cc7a5527e.diff
LOG: [analyzer] Add support for __attribute__((returns_nonnull)).
Differential Revision: https://reviews.llvm.org/D118657
Added:
clang/lib/StaticAnalyzer/Checkers/TrustReturnsNonnullChecker.cpp
clang/test/Analysis/returns_nonnull-attribute.cpp
Modified:
clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
clang/test/Analysis/analyzer-enabled-checkers.c
clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c
llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn
Removed:
################################################################################
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index f037c33a1304e..fae4240e9d701 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -376,6 +376,11 @@ def TrustNonnullChecker : Checker<"TrustNonnull">,
"are not null">,
Documentation<NotDocumented>;
+def TrustReturnsNonnullChecker : Checker<"TrustReturnsNonnull">,
+ HelpText<"Trust that returns from methods annotated with returns_nonnull "
+ "are not null">,
+ Documentation<NotDocumented>;
+
} // end "apiModeling"
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 3e85fadef0a2a..44fa2a06c3994 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -111,6 +111,7 @@ add_clang_library(clangStaticAnalyzerCheckers
TestAfterDivZeroChecker.cpp
TraversalChecker.cpp
TrustNonnullChecker.cpp
+ TrustReturnsNonnullChecker.cpp
UndefBranchChecker.cpp
UndefCapturedBlockVarChecker.cpp
UndefResultChecker.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/TrustReturnsNonnullChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/TrustReturnsNonnullChecker.cpp
new file mode 100644
index 0000000000000..d80559c6a9152
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/TrustReturnsNonnullChecker.cpp
@@ -0,0 +1,60 @@
+//== TrustReturnsNonnullChecker.cpp -- API nullability modeling -*- C++ -*--==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker adds nullability-related assumptions to methods annotated with
+// returns_nonnull attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class TrustReturnsNonnullChecker : public Checker<check::PostCall> {
+
+public:
+ TrustReturnsNonnullChecker(ASTContext &Ctx) {}
+
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+
+ if (isNonNullPtr(Call))
+ if (auto L = Call.getReturnValue().getAs<Loc>())
+ State = State->assume(*L, /*assumption=*/true);
+
+ C.addTransition(State);
+ }
+
+private:
+ /// \returns Whether the method declaration has the attribute returns_nonnull.
+ bool isNonNullPtr(const CallEvent &Call) const {
+ QualType ExprRetType = Call.getResultType();
+ const Decl *CallDeclaration = Call.getDecl();
+ if (!ExprRetType->isAnyPointerType() || !CallDeclaration)
+ return false;
+
+ return CallDeclaration->hasAttr<ReturnsNonNullAttr>();
+ }
+};
+
+} // namespace
+
+void ento::registerTrustReturnsNonnullChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<TrustReturnsNonnullChecker>(Mgr.getASTContext());
+}
+
+bool ento::shouldRegisterTrustReturnsNonnullChecker(const CheckerManager &mgr) {
+ return true;
+}
diff --git a/clang/test/Analysis/analyzer-enabled-checkers.c b/clang/test/Analysis/analyzer-enabled-checkers.c
index 7c00e78c16acd..7437e79a498f1 100644
--- a/clang/test/Analysis/analyzer-enabled-checkers.c
+++ b/clang/test/Analysis/analyzer-enabled-checkers.c
@@ -9,6 +9,7 @@
// CHECK-NEXT: core.CallAndMessageModeling
// CHECK-NEXT: apiModeling.StdCLibraryFunctions
// CHECK-NEXT: apiModeling.TrustNonnull
+// CHECK-NEXT: apiModeling.TrustReturnsNonnull
// CHECK-NEXT: apiModeling.llvm.CastValue
// CHECK-NEXT: apiModeling.llvm.ReturnValue
// CHECK-NEXT: core.CallAndMessage
diff --git a/clang/test/Analysis/returns_nonnull-attribute.cpp b/clang/test/Analysis/returns_nonnull-attribute.cpp
new file mode 100644
index 0000000000000..32d7b5200ef33
--- /dev/null
+++ b/clang/test/Analysis/returns_nonnull-attribute.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,apiModeling.TrustReturnsNonnull -verify %s
+
+int *foo() __attribute__((returns_nonnull));
+
+int *foo_no_attribute();
+
+int test_foo() {
+ int *x = foo();
+ if (x) {}
+ return *x; // no-warning
+}
+
+int test_foo_no_attribute() {
+ int *x = foo_no_attribute();
+ if (x) {}
+ return *x; // expected-warning{{Dereference of null pointer}}
+}
+
+void test(void *(*f)(void)) {
+ f(); // Shouldn't crash compiler
+}
diff --git a/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c b/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c
index 9ad1be0538517..a64ec4a71487a 100644
--- a/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c
+++ b/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c
@@ -22,6 +22,7 @@
// CHECK-NEXT: apiModeling.StdCLibraryFunctions
// CHECK-NEXT: alpha.unix.StdCLibraryFunctionArgs
// CHECK-NEXT: apiModeling.TrustNonnull
+// CHECK-NEXT: apiModeling.TrustReturnsNonnull
// CHECK-NEXT: apiModeling.llvm.CastValue
// CHECK-NEXT: apiModeling.llvm.ReturnValue
// CHECK-NEXT: core.DivideZero
diff --git a/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn
index 95868a290c27a..8287c9f7e39a0 100644
--- a/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn
@@ -118,6 +118,7 @@ static_library("Checkers") {
"TestAfterDivZeroChecker.cpp",
"TraversalChecker.cpp",
"TrustNonnullChecker.cpp",
+ "TrustReturnsNonnullChecker.cpp",
"UndefBranchChecker.cpp",
"UndefCapturedBlockVarChecker.cpp",
"UndefResultChecker.cpp",
More information about the llvm-commits
mailing list