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