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