1 //== TrustNonnullChecker.cpp - Checker for trusting annotations -*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This checker adds an assumption that methods annotated with _Nonnull
11 // which come from system headers actually return a non-null pointer.
13 //===----------------------------------------------------------------------===//
15 #include "ClangSACheckers.h"
16 #include "clang/StaticAnalyzer/Core/Checker.h"
17 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
22 using namespace clang;
27 class TrustNonnullChecker : public Checker<check::PostCall> {
29 /// \returns Whether we trust the result of the method call to be
30 /// a non-null pointer.
31 bool isNonNullPtr(const CallEvent &Call, CheckerContext &C) const {
32 QualType ExprRetType = Call.getResultType();
33 if (!ExprRetType->isAnyPointerType())
36 if (getNullabilityAnnotation(ExprRetType) == Nullability::Nonnull)
39 // The logic for ObjC instance method calls is more complicated,
40 // as the return value is nil when the receiver is nil.
41 if (!isa<ObjCMethodCall>(&Call))
44 const auto *MCall = cast<ObjCMethodCall>(&Call);
45 const ObjCMethodDecl *MD = MCall->getDecl();
47 // Distrust protocols.
48 if (isa<ObjCProtocolDecl>(MD->getDeclContext()))
51 QualType DeclRetType = MD->getReturnType();
52 if (getNullabilityAnnotation(DeclRetType) != Nullability::Nonnull)
55 // For class messages it is sufficient for the declaration to be
56 // annotated _Nonnull.
57 if (!MCall->isInstanceMessage())
60 // Alternatively, the analyzer could know that the receiver is not null.
61 SVal Receiver = MCall->getReceiverSVal();
62 ConditionTruthVal TV = C.getState()->isNonNull(Receiver);
63 if (TV.isConstrainedTrue())
70 void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
71 // Only trust annotations for system headers for non-protocols.
72 if (!Call.isInSystemHeader())
75 ProgramStateRef State = C.getState();
77 if (isNonNullPtr(Call, C))
78 if (auto L = Call.getReturnValue().getAs<Loc>())
79 State = State->assume(*L, /*Assumption=*/true);
81 C.addTransition(State);
85 } // end empty namespace
88 void ento::registerTrustNonnullChecker(CheckerManager &Mgr) {
89 Mgr.registerChecker<TrustNonnullChecker>();