Clang Project

clang_source_code/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
1//===--- CallAndMessageChecker.cpp ------------------------------*- 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 defines CallAndMessageChecker, a builtin checker that checks for various
10// errors of call and objc message expressions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
15#include "clang/AST/ParentMap.h"
16#include "clang/Basic/TargetInfo.h"
17#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18#include "clang/StaticAnalyzer/Core/Checker.h"
19#include "clang/StaticAnalyzer/Core/CheckerManager.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
21#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
22#include "llvm/ADT/SmallString.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/Support/raw_ostream.h"
25
26using namespace clang;
27using namespace ento;
28
29namespace {
30
31class CallAndMessageChecker
32  : public Checker< check::PreStmt<CallExpr>,
33                    check::PreStmt<CXXDeleteExpr>,
34                    check::PreObjCMessage,
35                    check::ObjCMessageNil,
36                    check::PreCall > {
37  mutable std::unique_ptr<BugTypeBT_call_null;
38  mutable std::unique_ptr<BugTypeBT_call_undef;
39  mutable std::unique_ptr<BugTypeBT_cxx_call_null;
40  mutable std::unique_ptr<BugTypeBT_cxx_call_undef;
41  mutable std::unique_ptr<BugTypeBT_call_arg;
42  mutable std::unique_ptr<BugTypeBT_cxx_delete_undef;
43  mutable std::unique_ptr<BugTypeBT_msg_undef;
44  mutable std::unique_ptr<BugTypeBT_objc_prop_undef;
45  mutable std::unique_ptr<BugTypeBT_objc_subscript_undef;
46  mutable std::unique_ptr<BugTypeBT_msg_arg;
47  mutable std::unique_ptr<BugTypeBT_msg_ret;
48  mutable std::unique_ptr<BugTypeBT_call_few_args;
49
50public:
51  DefaultBool Check_CallAndMessageUnInitRefArg;
52  CheckName CheckName_CallAndMessageUnInitRefArg;
53
54  void checkPreStmt(const CallExpr *CECheckerContext &Cconst;
55  void checkPreStmt(const CXXDeleteExpr *DECheckerContext &Cconst;
56  void checkPreObjCMessage(const ObjCMethodCall &msgCheckerContext &Cconst;
57
58  /// Fill in the return value that results from messaging nil based on the
59  /// return type and architecture and diagnose if the return value will be
60  /// garbage.
61  void checkObjCMessageNil(const ObjCMethodCall &msgCheckerContext &Cconst;
62
63  void checkPreCall(const CallEvent &CallCheckerContext &Cconst;
64
65private:
66  bool PreVisitProcessArg(CheckerContext &CSVal VSourceRange ArgRange,
67                          const Expr *ArgExint ArgumentNumber,
68                          bool CheckUninitFieldsconst CallEvent &Call,
69                          std::unique_ptr<BugType> &BT,
70                          const ParmVarDecl *ParamDeclconst;
71
72  static void emitBadCall(BugType *BTCheckerContext &Cconst Expr *BadE);
73  void emitNilReceiverBug(CheckerContext &Cconst ObjCMethodCall &msg,
74                          ExplodedNode *Nconst;
75
76  void HandleNilReceiver(CheckerContext &C,
77                         ProgramStateRef state,
78                         const ObjCMethodCall &msgconst;
79
80  void LazyInit_BT(const char *descstd::unique_ptr<BugType> &BTconst {
81    if (!BT)
82      BT.reset(new BuiltinBug(this, desc));
83  }
84  bool uninitRefOrPointer(CheckerContext &Cconst SVal &V,
85                          SourceRange ArgRangeconst Expr *ArgEx,
86                          std::unique_ptr<BugType> &BT,
87                          const ParmVarDecl *ParamDeclconst char *BD,
88                          int ArgumentNumberconst;
89};
90// end anonymous namespace
91
92void CallAndMessageChecker::emitBadCall(BugType *BTCheckerContext &C,
93                                        const Expr *BadE) {
94  ExplodedNode *N = C.generateErrorNode();
95  if (!N)
96    return;
97
98  auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N);
99  if (BadE) {
100    R->addRange(BadE->getSourceRange());
101    if (BadE->isGLValue())
102      BadE = bugreporter::getDerefExpr(BadE);
103    bugreporter::trackExpressionValue(N, BadE, *R);
104  }
105  C.emitReport(std::move(R));
106}
107
108static void describeUninitializedArgumentInCall(const CallEvent &Call,
109                                                int ArgumentNumber,
110                                                llvm::raw_svector_ostream &Os) {
111  switch (Call.getKind()) {
112  case CE_ObjCMessage: {
113    const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
114    switch (Msg.getMessageKind()) {
115    case OCM_Message:
116      Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
117         << " argument in message expression is an uninitialized value";
118      return;
119    case OCM_PropertyAccess:
120       (0) . __assert_fail ("Msg.isSetter() && \"Getters have no args\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp", 120, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Msg.isSetter() && "Getters have no args");
121      Os << "Argument for property setter is an uninitialized value";
122      return;
123    case OCM_Subscript:
124      if (Msg.isSetter() && (ArgumentNumber == 0))
125        Os << "Argument for subscript setter is an uninitialized value";
126      else
127        Os << "Subscript index is an uninitialized value";
128      return;
129    }
130    llvm_unreachable("Unknown message kind.");
131  }
132  case CE_Block:
133    Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
134       << " block call argument is an uninitialized value";
135    return;
136  default:
137    Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
138       << " function call argument is an uninitialized value";
139    return;
140  }
141}
142
143bool CallAndMessageChecker::uninitRefOrPointer(
144    CheckerContext &Cconst SVal &VSourceRange ArgRangeconst Expr *ArgEx,
145    std::unique_ptr<BugType> &BTconst ParmVarDecl *ParamDeclconst char *BD,
146    int ArgumentNumberconst {
147  if (!Check_CallAndMessageUnInitRefArg)
148    return false;
149
150  // No parameter declaration available, i.e. variadic function argument.
151  if(!ParamDecl)
152    return false;
153
154  // If parameter is declared as pointer to const in function declaration,
155  // then check if corresponding argument in function call is
156  // pointing to undefined symbol value (uninitialized memory).
157  SmallString<200Buf;
158  llvm::raw_svector_ostream Os(Buf);
159
160  if (ParamDecl->getType()->isPointerType()) {
161    Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
162       << " function call argument is a pointer to uninitialized value";
163  } else if (ParamDecl->getType()->isReferenceType()) {
164    Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
165       << " function call argument is an uninitialized value";
166  } else
167    return false;
168
169  if(!ParamDecl->getType()->getPointeeType().isConstQualified())
170    return false;
171
172  if (const MemRegion *SValMemRegion = V.getAsRegion()) {
173    const ProgramStateRef State = C.getState();
174    const SVal PSV = State->getSVal(SValMemRegion, C.getASTContext().CharTy);
175    if (PSV.isUndef()) {
176      if (ExplodedNode *N = C.generateErrorNode()) {
177        LazyInit_BT(BDBT);
178        auto R = llvm::make_unique<BugReport>(*BT, Os.str(), N);
179        R->addRange(ArgRange);
180        if (ArgEx)
181          bugreporter::trackExpressionValue(N, ArgEx, *R);
182
183        C.emitReport(std::move(R));
184      }
185      return true;
186    }
187  }
188  return false;
189}
190
191namespace {
192class FindUninitializedField {
193public:
194  SmallVector<const FieldDecl *, 10FieldChain;
195
196private:
197  StoreManager &StoreMgr;
198  MemRegionManager &MrMgr;
199  Store store;
200
201public:
202  FindUninitializedField(StoreManager &storeMgrMemRegionManager &mrMgr,
203                         Store s)
204      : StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
205
206  bool Find(const TypedValueRegion *R) {
207    QualType T = R->getValueType();
208    if (const RecordType *RT = T->getAsStructureType()) {
209      const RecordDecl *RD = RT->getDecl()->getDefinition();
210       (0) . __assert_fail ("RD && \"Referred record has no definition\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp", 210, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(RD && "Referred record has no definition");
211      for (const auto *I : RD->fields()) {
212        const FieldRegion *FR = MrMgr.getFieldRegion(I, R);
213        FieldChain.push_back(I);
214        T = I->getType();
215        if (T->getAsStructureType()) {
216          if (Find(FR))
217            return true;
218        } else {
219          const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
220          if (V.isUndef())
221            return true;
222        }
223        FieldChain.pop_back();
224      }
225    }
226
227    return false;
228  }
229};
230// namespace
231
232bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
233                                               SVal V,
234                                               SourceRange ArgRange,
235                                               const Expr *ArgEx,
236                                               int ArgumentNumber,
237                                               bool CheckUninitFields,
238                                               const CallEvent &Call,
239                                               std::unique_ptr<BugType> &BT,
240                                               const ParmVarDecl *ParamDecl
241                                               ) const {
242  const char *BD = "Uninitialized argument value";
243
244  if (uninitRefOrPointer(CVArgRangeArgExBTParamDeclBD,
245                         ArgumentNumber))
246    return true;
247
248  if (V.isUndef()) {
249    if (ExplodedNode *N = C.generateErrorNode()) {
250      LazyInit_BT(BDBT);
251      // Generate a report for this bug.
252      SmallString<200Buf;
253      llvm::raw_svector_ostream Os(Buf);
254      describeUninitializedArgumentInCall(Call, ArgumentNumber, Os);
255      auto R = llvm::make_unique<BugReport>(*BT, Os.str(), N);
256
257      R->addRange(ArgRange);
258      if (ArgEx)
259        bugreporter::trackExpressionValue(N, ArgEx, *R);
260      C.emitReport(std::move(R));
261    }
262    return true;
263  }
264
265  if (!CheckUninitFields)
266    return false;
267
268  if (auto LV = V.getAs<nonloc::LazyCompoundVal>()) {
269    const LazyCompoundValData *D = LV->getCVData();
270    FindUninitializedField F(C.getState()->getStateManager().getStoreManager(),
271                             C.getSValBuilder().getRegionManager(),
272                             D->getStore());
273
274    if (F.Find(D->getRegion())) {
275      if (ExplodedNode *N = C.generateErrorNode()) {
276        LazyInit_BT(BDBT);
277        SmallString<512Str;
278        llvm::raw_svector_ostream os(Str);
279        os << "Passed-by-value struct argument contains uninitialized data";
280
281        if (F.FieldChain.size() == 1)
282          os << " (e.g., field: '" << *F.FieldChain[0] << "')";
283        else {
284          os << " (e.g., via the field chain: '";
285          bool first = true;
286          for (SmallVectorImpl<const FieldDecl *>::iterator
287               DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){
288            if (first)
289              first = false;
290            else
291              os << '.';
292            os << **DI;
293          }
294          os << "')";
295        }
296
297        // Generate a report for this bug.
298        auto R = llvm::make_unique<BugReport>(*BT, os.str(), N);
299        R->addRange(ArgRange);
300
301        if (ArgEx)
302          bugreporter::trackExpressionValue(N, ArgEx, *R);
303        // FIXME: enhance track back for uninitialized value for arbitrary
304        // memregions
305        C.emitReport(std::move(R));
306      }
307      return true;
308    }
309  }
310
311  return false;
312}
313
314void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
315                                         CheckerContext &Cconst{
316
317  const Expr *Callee = CE->getCallee()->IgnoreParens();
318  ProgramStateRef State = C.getState();
319  const LocationContext *LCtx = C.getLocationContext();
320  SVal L = State->getSVal(Callee, LCtx);
321
322  if (L.isUndef()) {
323    if (!BT_call_undef)
324      BT_call_undef.reset(new BuiltinBug(
325          this"Called function pointer is an uninitialized pointer value"));
326    emitBadCall(BT_call_undef.get(), CCallee);
327    return;
328  }
329
330  ProgramStateRef StNonNullStNull;
331  std::tie(StNonNull, StNull) = State->assume(L.castAs<DefinedOrUnknownSVal>());
332
333  if (StNull && !StNonNull) {
334    if (!BT_call_null)
335      BT_call_null.reset(new BuiltinBug(
336          this"Called function pointer is null (null dereference)"));
337    emitBadCall(BT_call_null.get(), CCallee);
338    return;
339  }
340
341  C.addTransition(StNonNull);
342}
343
344void CallAndMessageChecker::checkPreStmt(const CXXDeleteExpr *DE,
345                                         CheckerContext &Cconst {
346
347  SVal Arg = C.getSVal(DE->getArgument());
348  if (Arg.isUndef()) {
349    StringRef Desc;
350    ExplodedNode *N = C.generateErrorNode();
351    if (!N)
352      return;
353    if (!BT_cxx_delete_undef)
354      BT_cxx_delete_undef.reset(
355          new BuiltinBug(this"Uninitialized argument value"));
356    if (DE->isArrayFormAsWritten())
357      Desc = "Argument to 'delete[]' is uninitialized";
358    else
359      Desc = "Argument to 'delete' is uninitialized";
360    BugType *BT = BT_cxx_delete_undef.get();
361    auto R = llvm::make_unique<BugReport>(*BT, Desc, N);
362    bugreporter::trackExpressionValue(N, DE, *R);
363    C.emitReport(std::move(R));
364    return;
365  }
366}
367
368void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
369                                         CheckerContext &Cconst {
370  ProgramStateRef State = C.getState();
371
372  // If this is a call to a C++ method, check if the callee is null or
373  // undefined.
374  if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) {
375    SVal V = CC->getCXXThisVal();
376    if (V.isUndef()) {
377      if (!BT_cxx_call_undef)
378        BT_cxx_call_undef.reset(
379            new BuiltinBug(this"Called C++ object pointer is uninitialized"));
380      emitBadCall(BT_cxx_call_undef.get(), CCC->getCXXThisExpr());
381      return;
382    }
383
384    ProgramStateRef StNonNullStNull;
385    std::tie(StNonNull, StNull) =
386        State->assume(V.castAs<DefinedOrUnknownSVal>());
387
388    if (StNull && !StNonNull) {
389      if (!BT_cxx_call_null)
390        BT_cxx_call_null.reset(
391            new BuiltinBug(this"Called C++ object pointer is null"));
392      emitBadCall(BT_cxx_call_null.get(), CCC->getCXXThisExpr());
393      return;
394    }
395
396    State = StNonNull;
397  }
398
399  const Decl *D = Call.getDecl();
400  if (D && (isa<FunctionDecl>(D) || isa<BlockDecl>(D))) {
401    // If we have a function or block declaration, we can make sure we pass
402    // enough parameters.
403    unsigned Params = Call.parameters().size();
404    if (Call.getNumArgs() < Params) {
405      ExplodedNode *N = C.generateErrorNode();
406      if (!N)
407        return;
408
409      LazyInit_BT("Function call with too few arguments"BT_call_few_args);
410
411      SmallString<512Str;
412      llvm::raw_svector_ostream os(Str);
413      if (isa<FunctionDecl>(D)) {
414        os << "Function ";
415      } else {
416        (D)", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp", 416, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isa<BlockDecl>(D));
417        os << "Block ";
418      }
419      os << "taking " << Params << " argument"
420         << (Params == 1 ? "" : "s") << " is called with fewer ("
421         << Call.getNumArgs() << ")";
422
423      C.emitReport(
424          llvm::make_unique<BugReport>(*BT_call_few_args, os.str(), N));
425    }
426  }
427
428  // Don't check for uninitialized field values in arguments if the
429  // caller has a body that is available and we have the chance to inline it.
430  // This is a hack, but is a reasonable compromise betweens sometimes warning
431  // and sometimes not depending on if we decide to inline a function.
432  const bool checkUninitFields =
433    !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));
434
435  std::unique_ptr<BugType> *BT;
436  if (isa<ObjCMethodCall>(Call))
437    BT = &BT_msg_arg;
438  else
439    BT = &BT_call_arg;
440
441  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
442  for (unsigned i = 0e = Call.getNumArgs(); i != e; ++i) {
443    const ParmVarDecl *ParamDecl = nullptr;
444    if(FD && i < FD->getNumParams())
445      ParamDecl = FD->getParamDecl(i);
446    if (PreVisitProcessArg(CCall.getArgSVal(i), Call.getArgSourceRange(i),
447                           Call.getArgExpr(i), i,
448                           checkUninitFieldsCall*BTParamDecl))
449      return;
450  }
451
452  // If we make it here, record our assumptions about the callee.
453  C.addTransition(State);
454}
455
456void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
457                                                CheckerContext &Cconst {
458  SVal recVal = msg.getReceiverSVal();
459  if (recVal.isUndef()) {
460    if (ExplodedNode *N = C.generateErrorNode()) {
461      BugType *BT = nullptr;
462      switch (msg.getMessageKind()) {
463      case OCM_Message:
464        if (!BT_msg_undef)
465          BT_msg_undef.reset(new BuiltinBug(this,
466                                            "Receiver in message expression "
467                                            "is an uninitialized value"));
468        BT = BT_msg_undef.get();
469        break;
470      case OCM_PropertyAccess:
471        if (!BT_objc_prop_undef)
472          BT_objc_prop_undef.reset(new BuiltinBug(
473              this"Property access on an uninitialized object pointer"));
474        BT = BT_objc_prop_undef.get();
475        break;
476      case OCM_Subscript:
477        if (!BT_objc_subscript_undef)
478          BT_objc_subscript_undef.reset(new BuiltinBug(
479              this"Subscript access on an uninitialized object pointer"));
480        BT = BT_objc_subscript_undef.get();
481        break;
482      }
483       (0) . __assert_fail ("BT && \"Unknown message kind.\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp", 483, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(BT && "Unknown message kind.");
484
485      auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N);
486      const ObjCMessageExpr *ME = msg.getOriginExpr();
487      R->addRange(ME->getReceiverRange());
488
489      // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet.
490      if (const Expr *ReceiverE = ME->getInstanceReceiver())
491        bugreporter::trackExpressionValue(N, ReceiverE, *R);
492      C.emitReport(std::move(R));
493    }
494    return;
495  }
496}
497
498void CallAndMessageChecker::checkObjCMessageNil(const ObjCMethodCall &msg,
499                                                CheckerContext &Cconst {
500  HandleNilReceiver(CC.getState(), msg);
501}
502
503void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
504                                               const ObjCMethodCall &msg,
505                                               ExplodedNode *Nconst {
506
507  if (!BT_msg_ret)
508    BT_msg_ret.reset(
509        new BuiltinBug(this"Receiver in message expression is 'nil'"));
510
511  const ObjCMessageExpr *ME = msg.getOriginExpr();
512
513  QualType ResTy = msg.getResultType();
514
515  SmallString<200buf;
516  llvm::raw_svector_ostream os(buf);
517  os << "The receiver of message '";
518  ME->getSelector().print(os);
519  os << "' is nil";
520  if (ResTy->isReferenceType()) {
521    os << ", which results in forming a null reference";
522  } else {
523    os << " and returns a value of type '";
524    msg.getResultType().print(os, C.getLangOpts());
525    os << "' that will be garbage";
526  }
527
528  auto report = llvm::make_unique<BugReport>(*BT_msg_ret, os.str(), N);
529  report->addRange(ME->getReceiverRange());
530  // FIXME: This won't track "self" in messages to super.
531  if (const Expr *receiver = ME->getInstanceReceiver()) {
532    bugreporter::trackExpressionValue(N, receiver, *report);
533  }
534  C.emitReport(std::move(report));
535}
536
537static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
538  return (triple.getVendor() == llvm::Triple::Apple &&
539          (triple.isiOS() || triple.isWatchOS() ||
540           !triple.isMacOSXVersionLT(10,5)));
541}
542
543void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
544                                              ProgramStateRef state,
545                                              const ObjCMethodCall &Msgconst {
546  ASTContext &Ctx = C.getASTContext();
547  static CheckerProgramPointTag Tag(this"NilReceiver");
548
549  // Check the return type of the message expression.  A message to nil will
550  // return different values depending on the return type and the architecture.
551  QualType RetTy = Msg.getResultType();
552  CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
553  const LocationContext *LCtx = C.getLocationContext();
554
555  if (CanRetTy->isStructureOrClassType()) {
556    // Structure returns are safe since the compiler zeroes them out.
557    SVal V = C.getSValBuilder().makeZeroVal(RetTy);
558    C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V), &Tag);
559    return;
560  }
561
562  // Other cases: check if sizeof(return type) > sizeof(void*)
563  if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap()
564                                  .isConsumedExpr(Msg.getOriginExpr())) {
565    // Compute: sizeof(void *) and sizeof(return type)
566    const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
567    const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
568
569    if (CanRetTy.getTypePtr()->isReferenceType()||
570        (voidPtrSize < returnTypeSize &&
571         !(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) &&
572           (Ctx.FloatTy == CanRetTy ||
573            Ctx.DoubleTy == CanRetTy ||
574            Ctx.LongDoubleTy == CanRetTy ||
575            Ctx.LongLongTy == CanRetTy ||
576            Ctx.UnsignedLongLongTy == CanRetTy)))) {
577      if (ExplodedNode *N = C.generateErrorNode(state, &Tag))
578        emitNilReceiverBug(CMsgN);
579      return;
580    }
581
582    // Handle the safe cases where the return value is 0 if the
583    // receiver is nil.
584    //
585    // FIXME: For now take the conservative approach that we only
586    // return null values if we *know* that the receiver is nil.
587    // This is because we can have surprises like:
588    //
589    //   ... = [[NSScreens screens] objectAtIndex:0];
590    //
591    // What can happen is that [... screens] could return nil, but
592    // it most likely isn't nil.  We should assume the semantics
593    // of this case unless we have *a lot* more knowledge.
594    //
595    SVal V = C.getSValBuilder().makeZeroVal(RetTy);
596    C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V), &Tag);
597    return;
598  }
599
600  C.addTransition(state);
601}
602
603void ento::registerCallAndMessageChecker(CheckerManager &mgr) {
604  mgr.registerChecker<CallAndMessageChecker>();
605}
606
607bool ento::shouldRegisterCallAndMessageChecker(const LangOptions &LO) {
608  return true;
609}
610
611void ento::registerCallAndMessageUnInitRefArg(CheckerManager &mgr) {
612  CallAndMessageChecker *Checker = mgr.getChecker<CallAndMessageChecker>();
613  Checker->Check_CallAndMessageUnInitRefArg = true;
614  Checker->CheckName_CallAndMessageUnInitRefArg = mgr.getCurrentCheckName();
615}
616
617bool ento::shouldRegisterCallAndMessageUnInitRefArg(const LangOptions &LO) {
618  return true;
619}
620