180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks//===--- NonNullParamChecker.cpp - Undefined arguments checker -*- C++ -*--===//
294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//                     The LLVM Compiler Infrastructure
494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// This file is distributed under the University of Illinois Open Source
694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// License. See LICENSE.TXT for details.
794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//===----------------------------------------------------------------------===//
994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
1080412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks// This defines NonNullParamChecker, which checks for arguments expected not to
1180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks// be null due to:
1280412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks//   - the corresponding parameters being declared to have nonnull attribute
1380412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks//   - the corresponding parameters being references; since the call would form
1480412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks//     a reference to a null pointer
1594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
1694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//===----------------------------------------------------------------------===//
1794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
18bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "ClangSACheckers.h"
192fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h"
2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
21ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
22bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
23f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
24bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
2594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
2694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xuusing namespace clang;
279ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
2894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
29f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremeneknamespace {
3080412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksclass NonNullParamChecker
3187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  : public Checker< check::PreCall, EventDispatcher<ImplicitNullDerefEvent> > {
32651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  mutable std::unique_ptr<BugType> BTAttrNonNull;
33651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  mutable std::unique_ptr<BugType> BTNullRefArg;
34651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
35f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenekpublic:
36bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis
37fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
38018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
3987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  std::unique_ptr<BugReport>
4087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  genReportNullAttrNonNull(const ExplodedNode *ErrorN, const Expr *ArgE) const;
4187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  std::unique_ptr<BugReport>
4287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  genReportReferenceToNullPointer(const ExplodedNode *ErrorN,
4387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                                  const Expr *ArgE) const;
44f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek};
45f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek} // end anonymous namespace
46f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek
4780412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksvoid NonNullParamChecker::checkPreCall(const CallEvent &Call,
48651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                       CheckerContext &C) const {
49fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  const Decl *FD = Call.getDecl();
5094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  if (!FD)
5194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    return;
5294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
53176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Merge all non-null attributes
54176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  unsigned NumArgs = Call.getNumArgs();
55176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::SmallBitVector AttrNonNull(NumArgs);
56176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) {
57176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (!NonNull->args_size()) {
58176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      AttrNonNull.set(0, NumArgs);
59176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      break;
60176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
61176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    for (unsigned Val : NonNull->args()) {
62176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Val >= NumArgs)
63176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        continue;
64176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      AttrNonNull.set(Val);
65176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
66176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
6794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
68fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  ProgramStateRef state = C.getState();
6994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
70018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  CallEvent::param_type_iterator TyI = Call.param_type_begin(),
71018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                 TyE = Call.param_type_end();
72018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
73176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  for (unsigned idx = 0; idx < NumArgs; ++idx) {
74018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
75018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // Check if the parameter is a reference. We want to report when reference
76018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // to a null pointer is passed as a paramter.
77018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bool haveRefTypeParam = false;
78018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    if (TyI != TyE) {
79018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks      haveRefTypeParam = (*TyI)->isReferenceType();
80018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks      TyI++;
81018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    }
82018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
83176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    bool haveAttrNonNull = AttrNonNull[idx];
84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!haveAttrNonNull) {
85651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Check if the parameter is also marked 'nonnull'.
86651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ArrayRef<ParmVarDecl*> parms = Call.parameters();
87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (idx < parms.size())
88651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        haveAttrNonNull = parms[idx]->hasAttr<NonNullAttr>();
89651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
90018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
91018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    if (!haveRefTypeParam && !haveAttrNonNull)
9294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      continue;
9394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
94018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // If the value is unknown or undefined, we can't perform this check.
95018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    const Expr *ArgE = Call.getArgExpr(idx);
96fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose    SVal V = Call.getArgSVal(idx);
97dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie    Optional<DefinedSVal> DV = V.getAs<DefinedSVal>();
989a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose    if (!DV)
999a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose      continue;
10094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
101018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // Process the case when the argument is not a location.
102018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    assert(!haveRefTypeParam || DV->getAs<Loc>());
103018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
104018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    if (haveAttrNonNull && !DV->getAs<Loc>()) {
105bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      // If the argument is a union type, we want to handle a potential
106fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      // transparent_union GCC extension.
107fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      if (!ArgE)
108fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose        continue;
109fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose
110fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      QualType T = ArgE->getType();
111bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      const RecordType *UT = T->getAsUnionType();
112bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
113bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        continue;
114fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose
115dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie      if (Optional<nonloc::CompoundVal> CSV =
1165251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie              DV->getAs<nonloc::CompoundVal>()) {
117bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        nonloc::CompoundVal::iterator CSV_I = CSV->begin();
118bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        assert(CSV_I != CSV->end());
119bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        V = *CSV_I;
1205251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie        DV = V.getAs<DefinedSVal>();
121bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        assert(++CSV_I == CSV->end());
122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        // FIXME: Handle (some_union){ some_other_union_val }, which turns into
123651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        // a LazyCompoundVal inside a CompoundVal.
124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        if (!V.getAs<Loc>())
12542773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks          continue;
12642773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks        // Retrieve the corresponding expression.
12742773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks        if (const CompoundLiteralExpr *CE = dyn_cast<CompoundLiteralExpr>(ArgE))
12842773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks          if (const InitListExpr *IE =
12942773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks                dyn_cast<InitListExpr>(CE->getInitializer()))
13042773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks             ArgE = dyn_cast<Expr>(*(IE->begin()));
13142773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks
132fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      } else {
133bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        // FIXME: Handle LazyCompoundVals?
134bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        continue;
135bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      }
136bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek    }
137bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek
13894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    ConstraintManager &CM = C.getConstraintManager();
1398bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek    ProgramStateRef stateNotNull, stateNull;
140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
14194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
14287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (stateNull) {
14387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (!stateNotNull) {
14487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        // Generate an error node.  Check for a null node in case
14587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        // we cache out.
14687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        if (ExplodedNode *errorNode = C.generateErrorNode(stateNull)) {
14794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
14887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          std::unique_ptr<BugReport> R;
14987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          if (haveAttrNonNull)
15087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            R = genReportNullAttrNonNull(errorNode, ArgE);
15187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          else if (haveRefTypeParam)
15287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            R = genReportReferenceToNullPointer(errorNode, ArgE);
15394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
15487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          // Highlight the range of the argument that was null.
15587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          R->addRange(Call.getArgSourceRange(idx));
156018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
15787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          // Emit the bug report.
15887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          C.emitReport(std::move(R));
15987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        }
16094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
16187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        // Always return.  Either we cached out or we just emitted an error.
16287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return;
16387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      }
16487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (ExplodedNode *N = C.generateSink(stateNull, C.getPredecessor())) {
16587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        ImplicitNullDerefEvent event = {
16687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            V, false, N, &C.getBugReporter(),
16787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            /*IsDirectDereference=*/haveRefTypeParam};
16887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        dispatchEvent(event);
16987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      }
17094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    }
17194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
17294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    // If a pointer value passed the check we should assume that it is
17394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    // indeed not null from this point forward.
17494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    assert(stateNotNull);
17594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    state = stateNotNull;
17694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  }
17794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
17894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  // If we reach here all of the arguments passed the nonnull check.
17994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  // If 'state' has been updated generated a new node.
1800bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks  C.addTransition(state);
18194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu}
182bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis
18387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstd::unique_ptr<BugReport>
18487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarNonNullParamChecker::genReportNullAttrNonNull(const ExplodedNode *ErrorNode,
18587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                                              const Expr *ArgE) const {
186018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  // Lazily allocate the BugType object if it hasn't already been
187018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  // created. Ownership is transferred to the BugReporter object once
188018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  // the BugReport is passed to 'EmitWarning'.
189018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (!BTAttrNonNull)
190018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    BTAttrNonNull.reset(new BugType(
191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        this, "Argument with 'nonnull' attribute passed null", "API"));
192018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
19387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  auto R = llvm::make_unique<BugReport>(
19487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      *BTAttrNonNull,
19587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      "Null pointer passed as an argument to a 'nonnull' parameter", ErrorNode);
196018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (ArgE)
197018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bugreporter::trackNullOrUndefValue(ErrorNode, ArgE, *R);
198018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
199018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  return R;
200018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks}
201018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
20287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstd::unique_ptr<BugReport> NonNullParamChecker::genReportReferenceToNullPointer(
20387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const ExplodedNode *ErrorNode, const Expr *ArgE) const {
204018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (!BTNullRefArg)
205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BTNullRefArg.reset(new BuiltinBug(this, "Dereference of null pointer"));
206018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
20787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  auto R = llvm::make_unique<BugReport>(
20887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      *BTNullRefArg, "Forming reference to null pointer", ErrorNode);
209018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (ArgE) {
210018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE);
2116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!ArgEDeref)
212018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks      ArgEDeref = ArgE;
213018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bugreporter::trackNullOrUndefValue(ErrorNode,
214018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                       ArgEDeref,
215018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                       *R);
216018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  }
217018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  return R;
218018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
219018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks}
220018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
22180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksvoid ento::registerNonNullParamChecker(CheckerManager &mgr) {
22280412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks  mgr.registerChecker<NonNullParamChecker>();
223bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis}
224