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", _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits