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