clang 22.0.0git
CallAndMessageChecker.cpp
Go to the documentation of this file.
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/AST/ExprCXX.h"
15#include "clang/AST/ParentMap.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/Support/raw_ostream.h"
25
26using namespace clang;
27using namespace ento;
28
29namespace {
30
31class CallAndMessageChecker
32 : public Checker<check::PreObjCMessage, check::ObjCMessageNil,
33 check::PreCall> {
34 const BugType CallNullBug{
35 this, "Called function pointer is null (null dereference)"};
36 const BugType CallUndefBug{
37 this, "Called function pointer is an uninitialized pointer value"};
38 const BugType CXXCallNullBug{this, "Called C++ object pointer is null"};
39 const BugType CXXCallUndefBug{this,
40 "Called C++ object pointer is uninitialized"};
41 const BugType CallArgBug{this, "Uninitialized argument value"};
42 const BugType CXXDeleteUndefBug{this, "Uninitialized argument value"};
43 const BugType MsgUndefBug{
44 this, "Receiver in message expression is an uninitialized value"};
45 const BugType ObjCPropUndefBug{
46 this, "Property access on an uninitialized object pointer"};
47 const BugType ObjCSubscriptUndefBug{
48 this, "Subscript access on an uninitialized object pointer"};
49 const BugType MsgArgBug{this, "Uninitialized argument value"};
50 const BugType MsgRetBug{this, "Receiver in message expression is 'nil'"};
51 const BugType CallFewArgsBug{this, "Function call with too few arguments"};
52
53public:
54 // Like a checker family, CallAndMessageChecker can produce many kinds of
55 // warnings which can be separately enabled or disabled. However, for
56 // historical reasons these warning kinds are represented by checker options
57 // (and not separate checker frontends with their own names) because
58 // CallAndMessage is among the oldest checkers out there, and can
59 // be responsible for the majority of the reports on any given project. This
60 // is obviously not ideal, but changing checker name has the consequence of
61 // changing the issue hashes associated with the reports, and databases
62 // relying on this (CodeChecker, for instance) would suffer greatly.
63 // If we ever end up making changes to the issue hash generation algorithm, or
64 // the warning messages here, we should totally jump on the opportunity to
65 // convert these to actual checker frontends.
66 enum CheckKind {
67 CK_FunctionPointer,
68 CK_ParameterCount,
69 CK_CXXThisMethodCall,
70 CK_CXXDeallocationArg,
71 CK_ArgInitializedness,
72 CK_ArgPointeeInitializedness,
73 CK_NilReceiver,
74 CK_UndefReceiver,
75 CK_NumCheckKinds
76 };
77
78 bool ChecksEnabled[CK_NumCheckKinds] = {false};
79
80 void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
81
82 /// Fill in the return value that results from messaging nil based on the
83 /// return type and architecture and diagnose if the return value will be
84 /// garbage.
85 void checkObjCMessageNil(const ObjCMethodCall &msg, CheckerContext &C) const;
86
87 void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
88
89 ProgramStateRef checkFunctionPointerCall(const CallExpr *CE,
90 CheckerContext &C,
91 ProgramStateRef State) const;
92
93 ProgramStateRef checkCXXMethodCall(const CXXInstanceCall *CC,
94 CheckerContext &C,
95 ProgramStateRef State) const;
96
97 ProgramStateRef checkParameterCount(const CallEvent &Call, CheckerContext &C,
98 ProgramStateRef State) const;
99
100 ProgramStateRef checkCXXDeallocation(const CXXDeallocatorCall *DC,
101 CheckerContext &C,
102 ProgramStateRef State) const;
103
104 ProgramStateRef checkArgInitializedness(const CallEvent &Call,
105 CheckerContext &C,
106 ProgramStateRef State) const;
107
108private:
109 bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange ArgRange,
110 const Expr *ArgEx, int ArgumentNumber,
111 bool CheckUninitFields, const CallEvent &Call,
112 const BugType &BT,
113 const ParmVarDecl *ParamDecl) const;
114
115 static void emitBadCall(const BugType &BT, CheckerContext &C,
116 const Expr *BadE);
117 void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg,
118 ExplodedNode *N) const;
119
120 void HandleNilReceiver(CheckerContext &C,
121 ProgramStateRef state,
122 const ObjCMethodCall &msg) const;
123
124 bool uninitRefOrPointer(CheckerContext &C, SVal V, SourceRange ArgRange,
125 const Expr *ArgEx, const BugType &BT,
126 const ParmVarDecl *ParamDecl,
127 int ArgumentNumber) const;
128};
129} // end anonymous namespace
130
131void CallAndMessageChecker::emitBadCall(const BugType &BT, CheckerContext &C,
132 const Expr *BadE) {
133 ExplodedNode *N = C.generateErrorNode();
134 if (!N)
135 return;
136
137 auto R = std::make_unique<PathSensitiveBugReport>(BT, BT.getDescription(), N);
138 if (BadE) {
139 R->addRange(BadE->getSourceRange());
140 if (BadE->isGLValue())
141 BadE = bugreporter::getDerefExpr(BadE);
143 }
144 C.emitReport(std::move(R));
145}
146
148 int ArgumentNumber,
149 llvm::raw_svector_ostream &Os) {
150 switch (Call.getKind()) {
151 case CE_ObjCMessage: {
153 switch (Msg.getMessageKind()) {
154 case OCM_Message:
155 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
156 << " argument in message expression is an uninitialized value";
157 return;
159 assert(Msg.isSetter() && "Getters have no args");
160 Os << "Argument for property setter is an uninitialized value";
161 return;
162 case OCM_Subscript:
163 if (Msg.isSetter() && (ArgumentNumber == 0))
164 Os << "Argument for subscript setter is an uninitialized value";
165 else
166 Os << "Subscript index is an uninitialized value";
167 return;
168 }
169 llvm_unreachable("Unknown message kind.");
170 }
171 case CE_Block:
172 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
173 << " block call argument is an uninitialized value";
174 return;
175 default:
176 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
177 << " function call argument is an uninitialized value";
178 return;
179 }
180}
181
182bool CallAndMessageChecker::uninitRefOrPointer(
183 CheckerContext &C, SVal V, SourceRange ArgRange, const Expr *ArgEx,
184 const BugType &BT, const ParmVarDecl *ParamDecl, int ArgumentNumber) const {
185
186 // The pointee being uninitialized is a sign of code smell, not a bug, no need
187 // to sink here.
188 if (!ChecksEnabled[CK_ArgPointeeInitializedness])
189 return false;
190
191 // No parameter declaration available, i.e. variadic function argument.
192 if(!ParamDecl)
193 return false;
194
195 // If parameter is declared as pointer to const in function declaration,
196 // then check if corresponding argument in function call is
197 // pointing to undefined symbol value (uninitialized memory).
198 SmallString<200> Buf;
199 llvm::raw_svector_ostream Os(Buf);
200
201 if (ParamDecl->getType()->isPointerType()) {
202 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
203 << " function call argument is a pointer to uninitialized value";
204 } else if (ParamDecl->getType()->isReferenceType()) {
205 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
206 << " function call argument is an uninitialized value";
207 } else
208 return false;
209
210 if(!ParamDecl->getType()->getPointeeType().isConstQualified())
211 return false;
212
213 if (const MemRegion *SValMemRegion = V.getAsRegion()) {
214 const ProgramStateRef State = C.getState();
215 const SVal PSV = State->getSVal(SValMemRegion, C.getASTContext().CharTy);
216 if (PSV.isUndef()) {
217 if (ExplodedNode *N = C.generateErrorNode()) {
218 auto R = std::make_unique<PathSensitiveBugReport>(BT, Os.str(), N);
219 R->addRange(ArgRange);
220 if (ArgEx)
222
223 C.emitReport(std::move(R));
224 }
225 return true;
226 }
227 }
228 return false;
229}
230
231namespace {
232class FindUninitializedField {
233public:
234 SmallVector<const FieldDecl *, 10> FieldChain;
235
236private:
237 StoreManager &StoreMgr;
238 MemRegionManager &MrMgr;
239 Store store;
240
241public:
242 FindUninitializedField(StoreManager &storeMgr, MemRegionManager &mrMgr,
243 Store s)
244 : StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
245
246 bool Find(const TypedValueRegion *R) {
247 QualType T = R->getValueType();
248 if (const RecordType *RT = T->getAsStructureType()) {
249 const RecordDecl *RD = RT->getDecl()->getDefinition();
250 assert(RD && "Referred record has no definition");
251 for (const auto *I : RD->fields()) {
252 if (I->isUnnamedBitField())
253 continue;
254 const FieldRegion *FR = MrMgr.getFieldRegion(I, R);
255 FieldChain.push_back(I);
256 T = I->getType();
257 if (T->isStructureType()) {
258 if (Find(FR))
259 return true;
260 } else {
261 SVal V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
262 if (V.isUndef())
263 return true;
264 }
265 FieldChain.pop_back();
266 }
267 }
268
269 return false;
270 }
271};
272} // namespace
273
274bool CallAndMessageChecker::PreVisitProcessArg(
275 CheckerContext &C, SVal V, SourceRange ArgRange, const Expr *ArgEx,
276 int ArgumentNumber, bool CheckUninitFields, const CallEvent &Call,
277 const BugType &BT, const ParmVarDecl *ParamDecl) const {
278 if (uninitRefOrPointer(C, V, ArgRange, ArgEx, BT, ParamDecl, ArgumentNumber))
279 return true;
280
281 if (V.isUndef()) {
282 if (!ChecksEnabled[CK_ArgInitializedness]) {
283 C.addSink();
284 return true;
285 }
286 if (ExplodedNode *N = C.generateErrorNode()) {
287 // Generate a report for this bug.
288 SmallString<200> Buf;
289 llvm::raw_svector_ostream Os(Buf);
290 describeUninitializedArgumentInCall(Call, ArgumentNumber, Os);
291 auto R = std::make_unique<PathSensitiveBugReport>(BT, Os.str(), N);
292
293 R->addRange(ArgRange);
294 if (ArgEx)
296 C.emitReport(std::move(R));
297 }
298 return true;
299 }
300
301 if (!CheckUninitFields)
302 return false;
303
304 if (auto LV = V.getAs<nonloc::LazyCompoundVal>()) {
305 const LazyCompoundValData *D = LV->getCVData();
306 FindUninitializedField F(C.getState()->getStateManager().getStoreManager(),
307 C.getSValBuilder().getRegionManager(),
308 D->getStore());
309
310 if (F.Find(D->getRegion())) {
311 if (!ChecksEnabled[CK_ArgInitializedness]) {
312 C.addSink();
313 return true;
314 }
315 if (ExplodedNode *N = C.generateErrorNode()) {
316 SmallString<512> Str;
317 llvm::raw_svector_ostream os(Str);
318 os << "Passed-by-value struct argument contains uninitialized data";
319
320 if (F.FieldChain.size() == 1)
321 os << " (e.g., field: '" << *F.FieldChain[0] << "')";
322 else {
323 os << " (e.g., via the field chain: '";
324 bool first = true;
325 for (const FieldDecl *FD : F.FieldChain) {
326 if (first)
327 first = false;
328 else
329 os << '.';
330 os << *FD;
331 }
332 os << "')";
333 }
334
335 // Generate a report for this bug.
336 auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
337 R->addRange(ArgRange);
338
339 if (ArgEx)
341 // FIXME: enhance track back for uninitialized value for arbitrary
342 // memregions
343 C.emitReport(std::move(R));
344 }
345 return true;
346 }
347 }
348
349 return false;
350}
351
352ProgramStateRef CallAndMessageChecker::checkFunctionPointerCall(
353 const CallExpr *CE, CheckerContext &C, ProgramStateRef State) const {
354
355 const Expr *Callee = CE->getCallee()->IgnoreParens();
356 const LocationContext *LCtx = C.getLocationContext();
357 SVal L = State->getSVal(Callee, LCtx);
358
359 if (L.isUndef()) {
360 if (!ChecksEnabled[CK_FunctionPointer]) {
361 C.addSink(State);
362 return nullptr;
363 }
364 emitBadCall(CallUndefBug, C, Callee);
365 return nullptr;
366 }
367
368 ProgramStateRef StNonNull, StNull;
369 std::tie(StNonNull, StNull) = State->assume(L.castAs<DefinedOrUnknownSVal>());
370
371 if (StNull && !StNonNull) {
372 if (!ChecksEnabled[CK_FunctionPointer]) {
373 C.addSink(StNull);
374 return nullptr;
375 }
376 emitBadCall(CallNullBug, C, Callee);
377 return nullptr;
378 }
379
380 return StNonNull;
381}
382
383ProgramStateRef CallAndMessageChecker::checkParameterCount(
384 const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const {
385
386 // If we have a function or block declaration, we can make sure we pass
387 // enough parameters.
388 unsigned Params = Call.parameters().size();
389 if (Call.getNumArgs() >= Params)
390 return State;
391
392 if (!ChecksEnabled[CK_ParameterCount]) {
393 C.addSink(State);
394 return nullptr;
395 }
396
397 ExplodedNode *N = C.generateErrorNode();
398 if (!N)
399 return nullptr;
400
401 SmallString<512> Str;
402 llvm::raw_svector_ostream os(Str);
404 os << "Function ";
405 } else {
406 assert(isa<BlockCall>(Call));
407 os << "Block ";
408 }
409 os << "taking " << Params << " argument" << (Params == 1 ? "" : "s")
410 << " is called with fewer (" << Call.getNumArgs() << ")";
411
412 C.emitReport(
413 std::make_unique<PathSensitiveBugReport>(CallFewArgsBug, os.str(), N));
414 return nullptr;
415}
416
417ProgramStateRef CallAndMessageChecker::checkCXXMethodCall(
418 const CXXInstanceCall *CC, CheckerContext &C, ProgramStateRef State) const {
419
420 SVal V = CC->getCXXThisVal();
421 if (V.isUndef()) {
422 if (!ChecksEnabled[CK_CXXThisMethodCall]) {
423 C.addSink(State);
424 return nullptr;
425 }
426 emitBadCall(CXXCallUndefBug, C, CC->getCXXThisExpr());
427 return nullptr;
428 }
429
430 ProgramStateRef StNonNull, StNull;
431 std::tie(StNonNull, StNull) = State->assume(V.castAs<DefinedOrUnknownSVal>());
432
433 if (StNull && !StNonNull) {
434 if (!ChecksEnabled[CK_CXXThisMethodCall]) {
435 C.addSink(StNull);
436 return nullptr;
437 }
438 emitBadCall(CXXCallNullBug, C, CC->getCXXThisExpr());
439 return nullptr;
440 }
441
442 return StNonNull;
443}
444
446CallAndMessageChecker::checkCXXDeallocation(const CXXDeallocatorCall *DC,
447 CheckerContext &C,
448 ProgramStateRef State) const {
449 const CXXDeleteExpr *DE = DC->getOriginExpr();
450 assert(DE);
451 SVal Arg = C.getSVal(DE->getArgument());
452 if (!Arg.isUndef())
453 return State;
454
455 if (!ChecksEnabled[CK_CXXDeallocationArg]) {
456 C.addSink(State);
457 return nullptr;
458 }
459
460 StringRef Desc;
461 ExplodedNode *N = C.generateErrorNode();
462 if (!N)
463 return nullptr;
464 if (DE->isArrayFormAsWritten())
465 Desc = "Argument to 'delete[]' is uninitialized";
466 else
467 Desc = "Argument to 'delete' is uninitialized";
468 auto R = std::make_unique<PathSensitiveBugReport>(CXXDeleteUndefBug, Desc, N);
470 C.emitReport(std::move(R));
471 return nullptr;
472}
473
474ProgramStateRef CallAndMessageChecker::checkArgInitializedness(
475 const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const {
476
477 const Decl *D = Call.getDecl();
478
479 // Don't check for uninitialized field values in arguments if the
480 // caller has a body that is available and we have the chance to inline it.
481 // This is a hack, but is a reasonable compromise betweens sometimes warning
482 // and sometimes not depending on if we decide to inline a function.
483 const bool checkUninitFields =
484 !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));
485
486 const BugType &BT = isa<ObjCMethodCall>(Call) ? MsgArgBug : CallArgBug;
487
488 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
489 for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) {
490 const ParmVarDecl *ParamDecl = nullptr;
491 if (FD && i < FD->getNumParams())
492 ParamDecl = FD->getParamDecl(i);
493 if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i),
494 Call.getArgExpr(i), i, checkUninitFields, Call, BT,
495 ParamDecl))
496 return nullptr;
497 }
498 return State;
499}
500
501void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
502 CheckerContext &C) const {
503 ProgramStateRef State = C.getState();
504
505 if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()))
506 State = checkFunctionPointerCall(CE, C, State);
507
508 if (!State)
509 return;
510
511 if (Call.getDecl())
512 State = checkParameterCount(Call, C, State);
513
514 if (!State)
515 return;
516
517 if (const auto *CC = dyn_cast<CXXInstanceCall>(&Call))
518 State = checkCXXMethodCall(CC, C, State);
519
520 if (!State)
521 return;
522
523 if (const auto *DC = dyn_cast<CXXDeallocatorCall>(&Call))
524 State = checkCXXDeallocation(DC, C, State);
525
526 if (!State)
527 return;
528
529 State = checkArgInitializedness(Call, C, State);
530
531 // If we make it here, record our assumptions about the callee.
532 C.addTransition(State);
533}
534
535void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
536 CheckerContext &C) const {
537 SVal recVal = msg.getReceiverSVal();
538 if (recVal.isUndef()) {
539 if (!ChecksEnabled[CK_UndefReceiver]) {
540 C.addSink();
541 return;
542 }
543 if (ExplodedNode *N = C.generateErrorNode()) {
544 const BugType *BT = nullptr;
545 switch (msg.getMessageKind()) {
546 case OCM_Message:
547 BT = &MsgUndefBug;
548 break;
550 BT = &ObjCPropUndefBug;
551 break;
552 case OCM_Subscript:
553 BT = &ObjCSubscriptUndefBug;
554 break;
555 }
556 assert(BT && "Unknown message kind.");
557
558 auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
559 const ObjCMessageExpr *ME = msg.getOriginExpr();
560 R->addRange(ME->getReceiverRange());
561
562 // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet.
563 if (const Expr *ReceiverE = ME->getInstanceReceiver())
564 bugreporter::trackExpressionValue(N, ReceiverE, *R);
565 C.emitReport(std::move(R));
566 }
567 return;
568 }
569}
570
571void CallAndMessageChecker::checkObjCMessageNil(const ObjCMethodCall &msg,
572 CheckerContext &C) const {
573 HandleNilReceiver(C, C.getState(), msg);
574}
575
576void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
577 const ObjCMethodCall &msg,
578 ExplodedNode *N) const {
579 if (!ChecksEnabled[CK_NilReceiver]) {
580 C.addSink();
581 return;
582 }
583
584 const ObjCMessageExpr *ME = msg.getOriginExpr();
585
586 QualType ResTy = msg.getResultType();
587
588 SmallString<200> buf;
589 llvm::raw_svector_ostream os(buf);
590 os << "The receiver of message '";
591 ME->getSelector().print(os);
592 os << "' is nil";
593 if (ResTy->isReferenceType()) {
594 os << ", which results in forming a null reference";
595 } else {
596 os << " and returns a value of type '";
597 msg.getResultType().print(os, C.getLangOpts());
598 os << "' that will be garbage";
599 }
600
601 auto report =
602 std::make_unique<PathSensitiveBugReport>(MsgRetBug, os.str(), N);
603 report->addRange(ME->getReceiverRange());
604 // FIXME: This won't track "self" in messages to super.
605 if (const Expr *receiver = ME->getInstanceReceiver()) {
606 bugreporter::trackExpressionValue(N, receiver, *report);
607 }
608 C.emitReport(std::move(report));
609}
610
611static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
612 return (triple.getVendor() == llvm::Triple::Apple &&
613 (triple.isiOS() || triple.isWatchOS() ||
614 !triple.isMacOSXVersionLT(10,5)));
615}
616
617void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
618 ProgramStateRef state,
619 const ObjCMethodCall &Msg) const {
620 ASTContext &Ctx = C.getASTContext();
621
622 // Check the return type of the message expression. A message to nil will
623 // return different values depending on the return type and the architecture.
624 QualType RetTy = Msg.getResultType();
625 CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
626 const LocationContext *LCtx = C.getLocationContext();
627
628 if (CanRetTy->isStructureOrClassType()) {
629 // Structure returns are safe since the compiler zeroes them out.
630 SVal V = C.getSValBuilder().makeZeroVal(RetTy);
631 C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V));
632 return;
633 }
634
635 // Other cases: check if sizeof(return type) > sizeof(void*)
636 if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap()
637 .isConsumedExpr(Msg.getOriginExpr())) {
638 // Compute: sizeof(void *) and sizeof(return type)
639 const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
640 const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
641
642 if (CanRetTy.getTypePtr()->isReferenceType()||
643 (voidPtrSize < returnTypeSize &&
645 (Ctx.FloatTy == CanRetTy ||
646 Ctx.DoubleTy == CanRetTy ||
647 Ctx.LongDoubleTy == CanRetTy ||
648 Ctx.LongLongTy == CanRetTy ||
649 Ctx.UnsignedLongLongTy == CanRetTy)))) {
650 if (ExplodedNode *N = C.generateErrorNode(state))
651 emitNilReceiverBug(C, Msg, N);
652 return;
653 }
654
655 // Handle the safe cases where the return value is 0 if the
656 // receiver is nil.
657 //
658 // FIXME: For now take the conservative approach that we only
659 // return null values if we *know* that the receiver is nil.
660 // This is because we can have surprises like:
661 //
662 // ... = [[NSScreens screens] objectAtIndex:0];
663 //
664 // What can happen is that [... screens] could return nil, but
665 // it most likely isn't nil. We should assume the semantics
666 // of this case unless we have *a lot* more knowledge.
667 //
668 SVal V = C.getSValBuilder().makeZeroVal(RetTy);
669 C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V));
670 return;
671 }
672
673 C.addTransition(state);
674}
675
676void ento::registerCallAndMessageChecker(CheckerManager &Mgr) {
677 CallAndMessageChecker *Chk = Mgr.registerChecker<CallAndMessageChecker>();
678
679#define QUERY_CHECKER_OPTION(OPTION) \
680 Chk->ChecksEnabled[CallAndMessageChecker::CK_##OPTION] = \
681 Mgr.getAnalyzerOptions().getCheckerBooleanOption( \
682 Mgr.getCurrentCheckerName(), #OPTION);
683
684 QUERY_CHECKER_OPTION(FunctionPointer)
686 QUERY_CHECKER_OPTION(CXXThisMethodCall)
687 QUERY_CHECKER_OPTION(CXXDeallocationArg)
688 QUERY_CHECKER_OPTION(ArgInitializedness)
689 QUERY_CHECKER_OPTION(ArgPointeeInitializedness)
690 QUERY_CHECKER_OPTION(NilReceiver)
691 QUERY_CHECKER_OPTION(UndefReceiver)
692}
693
694bool ento::shouldRegisterCallAndMessageChecker(const CheckerManager &) {
695 return true;
696}
#define V(N, I)
#define QUERY_CHECKER_OPTION(OPTION)
static bool supportsNilWithFloatRet(const llvm::Triple &triple)
static void describeUninitializedArgumentInCall(const CallEvent &Call, int ArgumentNumber, llvm::raw_svector_ostream &Os)
Defines the clang::Expr interface and subclasses for C++ expressions.
unsigned ParameterCount
Number of parameters, if this is "(", "[" or "<".
__device__ __2f16 float __ockl_bool s
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
CanQualType FloatTy
CanQualType DoubleTy
CanQualType LongDoubleTy
CanQualType VoidPtrTy
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType VoidTy
CanQualType UnsignedLongLongTy
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:895
CanQualType LongLongTy
bool isArrayFormAsWritten() const
Definition ExprCXX.h:2653
Expr * getCallee()
Definition Expr.h:3024
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition DeclBase.h:1087
This represents one expression.
Definition Expr.h:112
bool isGLValue() const
Definition Expr.h:287
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3081
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2797
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition ExprObjC.h:1265
Selector getSelector() const
Definition ExprObjC.cpp:289
SourceRange getReceiverRange() const
Source range of the receiver.
Definition ExprObjC.cpp:273
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8351
field_range fields() const
Definition Decl.h:4515
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool isStructureType() const
Definition Type.cpp:678
bool isPointerType() const
Definition TypeBase.h:8515
bool isReferenceType() const
Definition TypeBase.h:8539
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
const RecordType * getAsStructureType() const
Definition Type.cpp:768
QualType getType() const
Definition Decl.h:723
StringRef getDescription() const
Definition BugType.h:58
const CXXDeleteExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
Definition CallEvent.h:1229
virtual SVal getCXXThisVal() const
Returns the value of the implicit 'this' object.
virtual const Expr * getCXXThisExpr() const
Returns the expression representing the implicit 'this' object.
Definition CallEvent.h:713
Represents an abstract call to a function or method along a particular path.
Definition CallEvent.h:153
QualType getResultType() const
Returns the result type, adjusted for references.
Definition CallEvent.cpp:70
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
Definition Checker.h:553
const void * getStore() const
It might return null.
LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const
const FieldRegion * getFieldRegion(const FieldDecl *FD, const SubRegion *SuperRegion)
getFieldRegion - Retrieve or create the memory region associated with a specified FieldDecl.
Represents any expression that calls an Objective-C method.
Definition CallEvent.h:1261
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
bool isSetter() const
Returns true if this property access or subscript is a setter (has the form of an assignment).
Definition CallEvent.h:1333
const ObjCMessageExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
Definition CallEvent.h:1287
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
bool isUndef() const
Definition SVals.h:107
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition SVals.h:83
virtual SVal getBinding(Store store, Loc loc, QualType T=QualType())=0
Return the value bound to specified location in a given state.
virtual QualType getValueType() const =0
Defines the clang::TargetInfo interface.
const Expr * getDerefExpr(const Stmt *S)
Given that expression S represents a pointer that would be dereferenced, try to find a sub-expression...
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
Definition StoreRef.h:27
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
unsigned long uint64_t