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