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->getOriginalDecl()->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 (SmallVectorImpl<const FieldDecl *>::iterator
326 DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){
327 if (first)
328 first = false;
329 else
330 os << '.';
331 os << **DI;
332 }
333 os << "')";
334 }
335
336 // Generate a report for this bug.
337 auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
338 R->addRange(ArgRange);
339
340 if (ArgEx)
342 // FIXME: enhance track back for uninitialized value for arbitrary
343 // memregions
344 C.emitReport(std::move(R));
345 }
346 return true;
347 }
348 }
349
350 return false;
351}
352
353ProgramStateRef CallAndMessageChecker::checkFunctionPointerCall(
354 const CallExpr *CE, CheckerContext &C, ProgramStateRef State) const {
355
356 const Expr *Callee = CE->getCallee()->IgnoreParens();
357 const LocationContext *LCtx = C.getLocationContext();
358 SVal L = State->getSVal(Callee, LCtx);
359
360 if (L.isUndef()) {
361 if (!ChecksEnabled[CK_FunctionPointer]) {
362 C.addSink(State);
363 return nullptr;
364 }
365 emitBadCall(CallUndefBug, C, Callee);
366 return nullptr;
367 }
368
369 ProgramStateRef StNonNull, StNull;
370 std::tie(StNonNull, StNull) = State->assume(L.castAs<DefinedOrUnknownSVal>());
371
372 if (StNull && !StNonNull) {
373 if (!ChecksEnabled[CK_FunctionPointer]) {
374 C.addSink(StNull);
375 return nullptr;
376 }
377 emitBadCall(CallNullBug, C, Callee);
378 return nullptr;
379 }
380
381 return StNonNull;
382}
383
384ProgramStateRef CallAndMessageChecker::checkParameterCount(
385 const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const {
386
387 // If we have a function or block declaration, we can make sure we pass
388 // enough parameters.
389 unsigned Params = Call.parameters().size();
390 if (Call.getNumArgs() >= Params)
391 return State;
392
393 if (!ChecksEnabled[CK_ParameterCount]) {
394 C.addSink(State);
395 return nullptr;
396 }
397
398 ExplodedNode *N = C.generateErrorNode();
399 if (!N)
400 return nullptr;
401
402 SmallString<512> Str;
403 llvm::raw_svector_ostream os(Str);
405 os << "Function ";
406 } else {
407 assert(isa<BlockCall>(Call));
408 os << "Block ";
409 }
410 os << "taking " << Params << " argument" << (Params == 1 ? "" : "s")
411 << " is called with fewer (" << Call.getNumArgs() << ")";
412
413 C.emitReport(
414 std::make_unique<PathSensitiveBugReport>(CallFewArgsBug, os.str(), N));
415 return nullptr;
416}
417
418ProgramStateRef CallAndMessageChecker::checkCXXMethodCall(
419 const CXXInstanceCall *CC, CheckerContext &C, ProgramStateRef State) const {
420
421 SVal V = CC->getCXXThisVal();
422 if (V.isUndef()) {
423 if (!ChecksEnabled[CK_CXXThisMethodCall]) {
424 C.addSink(State);
425 return nullptr;
426 }
427 emitBadCall(CXXCallUndefBug, C, CC->getCXXThisExpr());
428 return nullptr;
429 }
430
431 ProgramStateRef StNonNull, StNull;
432 std::tie(StNonNull, StNull) = State->assume(V.castAs<DefinedOrUnknownSVal>());
433
434 if (StNull && !StNonNull) {
435 if (!ChecksEnabled[CK_CXXThisMethodCall]) {
436 C.addSink(StNull);
437 return nullptr;
438 }
439 emitBadCall(CXXCallNullBug, C, CC->getCXXThisExpr());
440 return nullptr;
441 }
442
443 return StNonNull;
444}
445
447CallAndMessageChecker::checkCXXDeallocation(const CXXDeallocatorCall *DC,
448 CheckerContext &C,
449 ProgramStateRef State) const {
450 const CXXDeleteExpr *DE = DC->getOriginExpr();
451 assert(DE);
452 SVal Arg = C.getSVal(DE->getArgument());
453 if (!Arg.isUndef())
454 return State;
455
456 if (!ChecksEnabled[CK_CXXDeallocationArg]) {
457 C.addSink(State);
458 return nullptr;
459 }
460
461 StringRef Desc;
462 ExplodedNode *N = C.generateErrorNode();
463 if (!N)
464 return nullptr;
465 if (DE->isArrayFormAsWritten())
466 Desc = "Argument to 'delete[]' is uninitialized";
467 else
468 Desc = "Argument to 'delete' is uninitialized";
469 auto R = std::make_unique<PathSensitiveBugReport>(CXXDeleteUndefBug, Desc, N);
471 C.emitReport(std::move(R));
472 return nullptr;
473}
474
475ProgramStateRef CallAndMessageChecker::checkArgInitializedness(
476 const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const {
477
478 const Decl *D = Call.getDecl();
479
480 // Don't check for uninitialized field values in arguments if the
481 // caller has a body that is available and we have the chance to inline it.
482 // This is a hack, but is a reasonable compromise betweens sometimes warning
483 // and sometimes not depending on if we decide to inline a function.
484 const bool checkUninitFields =
485 !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));
486
487 const BugType &BT = isa<ObjCMethodCall>(Call) ? MsgArgBug : CallArgBug;
488
489 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
490 for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) {
491 const ParmVarDecl *ParamDecl = nullptr;
492 if (FD && i < FD->getNumParams())
493 ParamDecl = FD->getParamDecl(i);
494 if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i),
495 Call.getArgExpr(i), i, checkUninitFields, Call, BT,
496 ParamDecl))
497 return nullptr;
498 }
499 return State;
500}
501
502void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
503 CheckerContext &C) const {
504 ProgramStateRef State = C.getState();
505
506 if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()))
507 State = checkFunctionPointerCall(CE, C, State);
508
509 if (!State)
510 return;
511
512 if (Call.getDecl())
513 State = checkParameterCount(Call, C, State);
514
515 if (!State)
516 return;
517
518 if (const auto *CC = dyn_cast<CXXInstanceCall>(&Call))
519 State = checkCXXMethodCall(CC, C, State);
520
521 if (!State)
522 return;
523
524 if (const auto *DC = dyn_cast<CXXDeallocatorCall>(&Call))
525 State = checkCXXDeallocation(DC, C, State);
526
527 if (!State)
528 return;
529
530 State = checkArgInitializedness(Call, C, State);
531
532 // If we make it here, record our assumptions about the callee.
533 C.addTransition(State);
534}
535
536void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
537 CheckerContext &C) const {
538 SVal recVal = msg.getReceiverSVal();
539 if (recVal.isUndef()) {
540 if (!ChecksEnabled[CK_UndefReceiver]) {
541 C.addSink();
542 return;
543 }
544 if (ExplodedNode *N = C.generateErrorNode()) {
545 const BugType *BT = nullptr;
546 switch (msg.getMessageKind()) {
547 case OCM_Message:
548 BT = &MsgUndefBug;
549 break;
551 BT = &ObjCPropUndefBug;
552 break;
553 case OCM_Subscript:
554 BT = &ObjCSubscriptUndefBug;
555 break;
556 }
557 assert(BT && "Unknown message kind.");
558
559 auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
560 const ObjCMessageExpr *ME = msg.getOriginExpr();
561 R->addRange(ME->getReceiverRange());
562
563 // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet.
564 if (const Expr *ReceiverE = ME->getInstanceReceiver())
565 bugreporter::trackExpressionValue(N, ReceiverE, *R);
566 C.emitReport(std::move(R));
567 }
568 return;
569 }
570}
571
572void CallAndMessageChecker::checkObjCMessageNil(const ObjCMethodCall &msg,
573 CheckerContext &C) const {
574 HandleNilReceiver(C, C.getState(), msg);
575}
576
577void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
578 const ObjCMethodCall &msg,
579 ExplodedNode *N) const {
580 if (!ChecksEnabled[CK_NilReceiver]) {
581 C.addSink();
582 return;
583 }
584
585 const ObjCMessageExpr *ME = msg.getOriginExpr();
586
587 QualType ResTy = msg.getResultType();
588
589 SmallString<200> buf;
590 llvm::raw_svector_ostream os(buf);
591 os << "The receiver of message '";
592 ME->getSelector().print(os);
593 os << "' is nil";
594 if (ResTy->isReferenceType()) {
595 os << ", which results in forming a null reference";
596 } else {
597 os << " and returns a value of type '";
598 msg.getResultType().print(os, C.getLangOpts());
599 os << "' that will be garbage";
600 }
601
602 auto report =
603 std::make_unique<PathSensitiveBugReport>(MsgRetBug, os.str(), N);
604 report->addRange(ME->getReceiverRange());
605 // FIXME: This won't track "self" in messages to super.
606 if (const Expr *receiver = ME->getInstanceReceiver()) {
607 bugreporter::trackExpressionValue(N, receiver, *report);
608 }
609 C.emitReport(std::move(report));
610}
611
612static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
613 return (triple.getVendor() == llvm::Triple::Apple &&
614 (triple.isiOS() || triple.isWatchOS() ||
615 !triple.isMacOSXVersionLT(10,5)));
616}
617
618void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
619 ProgramStateRef state,
620 const ObjCMethodCall &Msg) const {
621 ASTContext &Ctx = C.getASTContext();
622
623 // Check the return type of the message expression. A message to nil will
624 // return different values depending on the return type and the architecture.
625 QualType RetTy = Msg.getResultType();
626 CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
627 const LocationContext *LCtx = C.getLocationContext();
628
629 if (CanRetTy->isStructureOrClassType()) {
630 // Structure returns are safe since the compiler zeroes them out.
631 SVal V = C.getSValBuilder().makeZeroVal(RetTy);
632 C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V));
633 return;
634 }
635
636 // Other cases: check if sizeof(return type) > sizeof(void*)
637 if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap()
638 .isConsumedExpr(Msg.getOriginExpr())) {
639 // Compute: sizeof(void *) and sizeof(return type)
640 const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
641 const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
642
643 if (CanRetTy.getTypePtr()->isReferenceType()||
644 (voidPtrSize < returnTypeSize &&
646 (Ctx.FloatTy == CanRetTy ||
647 Ctx.DoubleTy == CanRetTy ||
648 Ctx.LongDoubleTy == CanRetTy ||
649 Ctx.LongLongTy == CanRetTy ||
650 Ctx.UnsignedLongLongTy == CanRetTy)))) {
651 if (ExplodedNode *N = C.generateErrorNode(state))
652 emitNilReceiverBug(C, Msg, N);
653 return;
654 }
655
656 // Handle the safe cases where the return value is 0 if the
657 // receiver is nil.
658 //
659 // FIXME: For now take the conservative approach that we only
660 // return null values if we *know* that the receiver is nil.
661 // This is because we can have surprises like:
662 //
663 // ... = [[NSScreens screens] objectAtIndex:0];
664 //
665 // What can happen is that [... screens] could return nil, but
666 // it most likely isn't nil. We should assume the semantics
667 // of this case unless we have *a lot* more knowledge.
668 //
669 SVal V = C.getSValBuilder().makeZeroVal(RetTy);
670 C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V));
671 return;
672 }
673
674 C.addTransition(state);
675}
676
677void ento::registerCallAndMessageChecker(CheckerManager &Mgr) {
678 CallAndMessageChecker *Chk = Mgr.registerChecker<CallAndMessageChecker>();
679
680#define QUERY_CHECKER_OPTION(OPTION) \
681 Chk->ChecksEnabled[CallAndMessageChecker::CK_##OPTION] = \
682 Mgr.getAnalyzerOptions().getCheckerBooleanOption( \
683 Mgr.getCurrentCheckerName(), #OPTION);
684
685 QUERY_CHECKER_OPTION(FunctionPointer)
687 QUERY_CHECKER_OPTION(CXXThisMethodCall)
688 QUERY_CHECKER_OPTION(CXXDeallocationArg)
689 QUERY_CHECKER_OPTION(ArgInitializedness)
690 QUERY_CHECKER_OPTION(ArgPointeeInitializedness)
691 QUERY_CHECKER_OPTION(NilReceiver)
692 QUERY_CHECKER_OPTION(UndefReceiver)
693}
694
695bool ento::shouldRegisterCallAndMessageChecker(const CheckerManager &) {
696 return true;
697}
#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
CanQualType FloatTy
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
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:856
CanQualType LongLongTy
bool isArrayFormAsWritten() const
Definition ExprCXX.h:2647
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:2794
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition ExprObjC.h:1268
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:8358
field_range fields() const
Definition Decl.h:4512
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:334
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:8522
bool isReferenceType() const
Definition TypeBase.h:8546
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:722
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:1218
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:702
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:1250
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:1322
const ObjCMessageExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
Definition CallEvent.h:1276
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