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