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: TrustReturnsNonnullChecker(ASTContext & Ctx)28 TrustReturnsNonnullChecker(ASTContext &Ctx) {} 29 checkPostCall(const CallEvent & Call,CheckerContext & C) const30 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. isNonNullPtr(const CallEvent & Call) const42 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 registerTrustReturnsNonnullChecker(CheckerManager & Mgr)54void ento::registerTrustReturnsNonnullChecker(CheckerManager &Mgr) { 55 Mgr.registerChecker<TrustReturnsNonnullChecker>(Mgr.getASTContext()); 56 } 57 shouldRegisterTrustReturnsNonnullChecker(const CheckerManager & mgr)58bool ento::shouldRegisterTrustReturnsNonnullChecker(const CheckerManager &mgr) { 59 return true; 60 } 61