[clang] faabdfc - [analyzer] Add support for __attribute__((returns_nonnull)).

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 2 11:47:00 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 cfe-commits mailing list