clang: lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
16
34#include "llvm/ADT/STLExtras.h"
35#include "llvm/Support/ErrorHandling.h"
36#include
37#include
38
39using namespace clang;
40using namespace ento;
41
42namespace {
43
44class SmartPtrModeling
45 : public Checker<eval::Call, check::DeadSymbols, check::RegionChanges,
46 check::LiveSymbols> {
47
48 bool isBoolConversionMethod(const CallEvent &Call) const;
49
50public:
51
52 bool ModelSmartPtrDereference = false;
62 const char *Sep) const override;
64
65private:
72 const MemRegion *ThisRegion) const;
74 const MemRegion *OtherSmartPtrRegion,
81 std::pair<SVal, ProgramStateRef>
85
86 using SmartPtrMethodHandlerFn =
89 {{CDM::CXXMethod, {"reset"}}, &SmartPtrModeling::handleReset},
90 {{CDM::CXXMethod, {"release"}}, &SmartPtrModeling::handleRelease},
91 {{CDM::CXXMethod, {"swap"}, 1}, &SmartPtrModeling::handleSwapMethod},
92 {{CDM::CXXMethod, {"get"}}, &SmartPtrModeling::handleGet}};
93 const CallDescription StdSwapCall{CDM::SimpleFunc, {"std", "swap"}, 2};
95 {CDM::SimpleFunc, {"std", "make_unique"}},
96 {CDM::SimpleFunc, {"std", "make_unique_for_overwrite"}}};
97};
98}
99
101
102
105 if (!RD || !RD->getDeclContext()->isStdNamespace())
106 return false;
107 if (RD->getDeclName().isIdentifier())
108 return llvm::is_contained(Names, RD->getName());
109 return false;
110}
111
112constexpr llvm::StringLiteral STD_PTR_NAMES[] = {"shared_ptr", "unique_ptr",
113 "weak_ptr"};
114
117}
118
121}
122
123
125namespace ento {
126namespace smartptr {
128 const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
129 if (!MethodDecl || !MethodDecl->getParent())
130 return false;
132}
133
136 return false;
137
139 StringRef Name = RD->getName();
140 return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
141 }
142 return false;
143}
144
147}
148
150 const auto *InnerPointVal = State->get(ThisRegion);
151 return InnerPointVal &&
153}
154}
155}
156}
157
158
159static TrackedRegionMapTy
161 TrackedRegionMapTy::Factory &RegionMapFactory,
163 if (!Region)
164 return RegionMap;
165 for (const auto &E : RegionMap) {
166 if (E.first->isSubRegionOf(Region))
167 RegionMap = RegionMapFactory.remove(RegionMap, E.first);
168 }
169 return RegionMap;
170}
171
174 const SVal *RegionInnerPointerVal) {
175 if (RegionInnerPointerVal) {
176 State = State->set(Region, *RegionInnerPointerVal);
177 } else {
178 State = State->remove(Region);
179 }
180 return State;
181}
182
185 return {};
186
187 const auto *TSD = dyn_cast(RD);
188 if (!TSD)
189 return {};
190
191 auto TemplateArgs = TSD->getTemplateArgs().asArray();
192 if (TemplateArgs.empty())
193 return {};
194 auto InnerValueType = TemplateArgs[0].getAsType();
195 return C.getASTContext().getPointerType(InnerValueType.getCanonicalType());
196}
197
198
199
200
203 const auto *FD = dyn_cast_or_null(Call.getDecl());
204 if (!FD || !FD->getPrimaryTemplate())
205 return {};
206 const auto &TemplateArgs = FD->getTemplateSpecializationArgs()->asArray();
207 if (TemplateArgs.size() == 0)
208 return {};
209 auto ValueType = TemplateArgs[0].getAsType();
210 return C.getASTContext().getPointerType(ValueType.getCanonicalType());
211}
212
213
214
216 const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
217 if (!MethodDecl || !MethodDecl->getParent())
218 return {};
219
222}
223
224
228 OS << " ";
230 }
231}
232
233bool SmartPtrModeling::isBoolConversionMethod(const CallEvent &Call) const {
234
235
236
237
238 const auto *CD = dyn_cast_or_null(Call.getDecl());
239 return CD && CD->getConversionType()->isBooleanType();
240}
241
243
247}
248
250 return Call.getDecl() && Call.getDecl()->getDeclContext()->isStdNamespace();
251}
252
255 return false;
256 const auto *FC = dyn_cast(&Call);
257 if (!FC)
258 return false;
261 return false;
263 if (OOK != clang::OO_LessLess)
264 return false;
267}
268
271 return false;
274}
275
276bool SmartPtrModeling::evalCall(const CallEvent &Call,
278
280
281
282
284 if (handleComparisionOp(Call, C))
285 return true;
286
288 return handleOstreamOperator(Call, C);
289
290 if (StdSwapCall.matches(Call)) {
291
292 assert(Call.getNumArgs() == 2 && "std::swap should have two arguments");
293 const Expr *FirstArg = Call.getArgExpr(0);
295 return false;
296 return handleSwap(State, Call.getArgSVal(0), Call.getArgSVal(1), C);
297 }
298
299 if (MakeUniqueVariants.contains(Call)) {
300 if (!ModelSmartPtrDereference)
301 return false;
302
303 const std::optional ThisRegionOpt =
304 Call.getReturnValueUnderConstruction();
305 if (!ThisRegionOpt)
306 return false;
307
308 const auto PtrVal = C.getSValBuilder().getConjuredHeapSymbolVal(
309 Call.getOriginExpr(), C.getLocationContext(),
311
312 const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();
313 State = State->set(ThisRegion, PtrVal);
314 State = State->assume(PtrVal, true);
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332 auto &Engine = State->getStateManager().getOwningEngine();
333 State = Engine.updateObjectsUnderConstruction(
334 *ThisRegionOpt, nullptr, State, C.getLocationContext(),
335 Call.getConstructionContext(), {});
336
337
338
339 C.addTransition(State);
340 return true;
341 }
342
344 return false;
345
346 if (isBoolConversionMethod(Call)) {
348 cast(&Call)->getCXXThisVal().getAsRegion();
349
350 if (ModelSmartPtrDereference) {
351
352
353
354
355 handleBoolConversion(Call, C);
356 return true;
357 } else {
359
360
361 return false;
362 }
363
364
365 C.addTransition(State->BindExpr(
366 Call.getOriginExpr(), C.getLocationContext(),
367 C.getSValBuilder().makeZeroVal(Call.getResultType())));
368
369 return true;
370 }
371 }
372
373 if (!ModelSmartPtrDereference)
374 return false;
375
376 if (const auto *CC = dyn_cast(&Call)) {
377 if (CC->getDecl()->isCopyConstructor())
378 return false;
379
380 const MemRegion *ThisRegion = CC->getCXXThisVal().getAsRegion();
381 if (!ThisRegion)
382 return false;
383
384 QualType ThisType = cast(Call.getDecl())->getThisType();
385
386 if (CC->getDecl()->isMoveConstructor())
387 return handleMoveCtr(Call, C, ThisRegion);
388
389 if (Call.getNumArgs() == 0) {
390 auto NullVal = C.getSValBuilder().makeNullWithType(ThisType);
391 State = State->set(ThisRegion, NullVal);
392
393 C.addTransition(
395 llvm::raw_ostream &OS) {
396 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
397 !BR.isInteresting(ThisRegion))
398 return;
399 OS << "Default constructed smart pointer";
400 checkAndPrettyPrintRegion(OS, ThisRegion);
401 OS << " is null";
402 }));
403 } else {
404 const auto *TrackingExpr = Call.getArgExpr(0);
405 assert(TrackingExpr->getType()->isPointerType() &&
406 "Adding a non pointer value to TrackedRegionMap");
407 auto ArgVal = Call.getArgSVal(0);
408 State = State->set(ThisRegion, ArgVal);
409
410 C.addTransition(State, C.getNoteTag([ThisRegion, TrackingExpr,
412 llvm::raw_ostream &OS) {
413 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
414 !BR.isInteresting(ThisRegion))
415 return;
416 bugreporter::trackExpressionValue(BR.getErrorNode(), TrackingExpr, BR);
417 OS << "Smart pointer";
418 checkAndPrettyPrintRegion(OS, ThisRegion);
419 if (ArgVal.isZeroConstant())
420 OS << " is constructed using a null value";
421 else
422 OS << " is constructed";
423 }));
424 }
425 return true;
426 }
427
428 if (handleAssignOp(Call, C))
429 return true;
430
431 const SmartPtrMethodHandlerFn *Handler = SmartPtrMethodHandlers.lookup(Call);
432 if (!Handler)
433 return false;
434 (this->**Handler)(Call, C);
435
436 return C.isDifferent();
437}
438
439std::pair<SVal, ProgramStateRef> SmartPtrModeling::retrieveOrConjureInnerPtrVal(
442 const auto *Ptr = State->get(ThisRegion);
443 if (Ptr)
444 return {*Ptr, State};
445 auto Val = C.getSValBuilder().conjureSymbolVal(E, C.getLocationContext(),
447 State = State->set(ThisRegion, Val);
448 return {Val, State};
449}
450
451bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
453 const auto *FC = dyn_cast(&Call);
454 if (!FC)
455 return false;
458 return false;
460 if (!(OOK == OO_EqualEqual || OOK == OO_ExclaimEqual || OOK == OO_Less ||
461 OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||
462 OOK == OO_Spaceship))
463 return false;
464
465
466
467
468
469
470
472 SVal S) -> std::pair<SVal, ProgramStateRef> {
473 if (S.isZeroConstant()) {
474 return {S, State};
475 }
476 const MemRegion *Reg = S.getAsRegion();
477 assert(Reg &&
478 "this pointer of std::unique_ptr should be obtainable as MemRegion");
480 return retrieveOrConjureInnerPtrVal(State, Reg, E, Type, C);
481 };
482
484 SVal Second = Call.getArgSVal(1);
485 const auto *FirstExpr = Call.getArgExpr(0);
486 const auto *SecondExpr = Call.getArgExpr(1);
487
488 const auto *ResultExpr = Call.getOriginExpr();
489 const auto *LCtx = C.getLocationContext();
490 auto &Bldr = C.getSValBuilder();
492
493 SVal FirstPtrVal, SecondPtrVal;
494 std::tie(FirstPtrVal, State) = makeSValFor(State, FirstExpr, First);
495 std::tie(SecondPtrVal, State) = makeSValFor(State, SecondExpr, Second);
498 auto RetVal = Bldr.evalBinOp(State, BOK, FirstPtrVal, SecondPtrVal,
499 Call.getResultType());
500
501 if (OOK != OO_Spaceship) {
503 std::tie(TrueState, FalseState) =
505 if (TrueState)
506 C.addTransition(
507 TrueState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(true)));
508 if (FalseState)
509 C.addTransition(
510 FalseState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(false)));
511 } else {
512 C.addTransition(State->BindExpr(ResultExpr, LCtx, RetVal));
513 }
514 return true;
515}
516
517bool SmartPtrModeling::handleOstreamOperator(const CallEvent &Call,
519
520
521
522
523
524
525
526
528 const auto StreamVal = Call.getArgSVal(0);
529 const MemRegion *StreamThisRegion = StreamVal.getAsRegion();
530 if (!StreamThisRegion)
531 return false;
532 State =
533 State->invalidateRegions({StreamThisRegion}, Call.getOriginExpr(),
534 C.blockCount(), C.getLocationContext(), false);
535 State =
536 State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), StreamVal);
537 C.addTransition(State);
538 return true;
539}
540
541void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper,
544
545 TrackedRegionMapTy TrackedRegions = State->get();
546 for (auto E : TrackedRegions) {
548 bool IsRegDead = !SymReaper.isLiveRegion(Region);
549
550 if (IsRegDead)
551 State = State->remove(Region);
552 }
553 C.addTransition(State);
554}
555
556void SmartPtrModeling::printState(raw_ostream &Out, ProgramStateRef State,
557 const char *NL, const char *Sep) const {
558 TrackedRegionMapTy RS = State->get();
559
560 if (!RS.isEmpty()) {
561 Out << Sep << "Smart ptr regions :" << NL;
562 for (auto I : RS) {
563 I.first->dumpToStream(Out);
565 Out << ": Null";
566 else
567 Out << ": Non Null";
568 Out << NL;
569 }
570 }
571}
572
578 TrackedRegionMapTy RegionMap = State->get();
579 TrackedRegionMapTy::Factory &RegionMapFactory =
580 State->get_context();
581 for (const auto *Region : Regions)
584 return State->set(RegionMap);
585}
586
587void SmartPtrModeling::checkLiveSymbols(ProgramStateRef State,
589
590 TrackedRegionMapTy TrackedRegions = State->get();
591 for (SVal Val : llvm::make_second_range(TrackedRegions)) {
594 }
595 }
596}
597
598void SmartPtrModeling::handleReset(const CallEvent &Call,
601 const auto *IC = dyn_cast(&Call);
602 if (!IC)
603 return;
604
605 const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
606 if (!ThisRegion)
607 return;
608
609 assert(Call.getArgExpr(0)->getType()->isPointerType() &&
610 "Adding a non pointer value to TrackedRegionMap");
611 State = State->set(ThisRegion, Call.getArgSVal(0));
612 const auto *TrackingExpr = Call.getArgExpr(0);
613 C.addTransition(
615 llvm::raw_ostream &OS) {
616 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
617 !BR.isInteresting(ThisRegion))
618 return;
619 bugreporter::trackExpressionValue(BR.getErrorNode(), TrackingExpr, BR);
620 OS << "Smart pointer";
621 checkAndPrettyPrintRegion(OS, ThisRegion);
622 OS << " reset using a null value";
623 }));
624
625
626}
627
628void SmartPtrModeling::handleRelease(const CallEvent &Call,
631 const auto *IC = dyn_cast(&Call);
632 if (!IC)
633 return;
634
635 const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
636 if (!ThisRegion)
637 return;
638
639 const auto *InnerPointVal = State->get(ThisRegion);
640
641 if (InnerPointVal) {
642 State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
643 *InnerPointVal);
644 }
645
646 QualType ThisType = cast(Call.getDecl())->getThisType();
647 auto ValueToUpdate = C.getSValBuilder().makeNullWithType(ThisType);
648 State = State->set(ThisRegion, ValueToUpdate);
649
651 llvm::raw_ostream &OS) {
652 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
653 !BR.isInteresting(ThisRegion))
654 return;
655
656 OS << "Smart pointer";
657 checkAndPrettyPrintRegion(OS, ThisRegion);
658 OS << " is released and set to null";
659 }));
660
661
662}
663
664void SmartPtrModeling::handleSwapMethod(const CallEvent &Call,
666
667 const auto *IC = dyn_cast(&Call);
668 if (!IC)
669 return;
670
671 auto State = C.getState();
672 handleSwap(State, IC->getCXXThisVal(), Call.getArgSVal(0), C);
673}
674
677 const MemRegion *FirstThisRegion = First.getAsRegion();
678 if (!FirstThisRegion)
679 return false;
681 if (!SecondThisRegion)
682 return false;
683
684 const auto *FirstInnerPtrVal = State->get(FirstThisRegion);
685 const auto *SecondInnerPtrVal =
686 State->get(SecondThisRegion);
687
690
691 C.addTransition(State, C.getNoteTag([FirstThisRegion, SecondThisRegion](
693 llvm::raw_ostream &OS) {
694 if (&BR.getBugType() != smartptr::getNullDereferenceBugType())
695 return;
696 if (BR.isInteresting(FirstThisRegion) &&
697 !BR.isInteresting(SecondThisRegion)) {
698 BR.markInteresting(SecondThisRegion);
699 BR.markNotInteresting(FirstThisRegion);
700 }
703 BR.markInteresting(FirstThisRegion);
704 BR.markNotInteresting(SecondThisRegion);
705 }
706
707 }));
708
709 return true;
710}
711
712void SmartPtrModeling::handleGet(const CallEvent &Call,
715 const auto *IC = dyn_cast(&Call);
716 if (!IC)
717 return;
718
719 const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
720 if (!ThisRegion)
721 return;
722
723 SVal InnerPointerVal;
724 std::tie(InnerPointerVal, State) = retrieveOrConjureInnerPtrVal(
725 State, ThisRegion, Call.getOriginExpr(), Call.getResultType(), C);
726 State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
727 InnerPointerVal);
728
729 C.addTransition(State);
730}
731
732bool SmartPtrModeling::handleAssignOp(const CallEvent &Call,
735 const auto *OC = dyn_cast(&Call);
736 if (!OC)
737 return false;
739 if (OOK != OO_Equal)
740 return false;
741 const MemRegion *ThisRegion = OC->getCXXThisVal().getAsRegion();
742 if (!ThisRegion)
743 return false;
744
745 QualType ThisType = cast(Call.getDecl())->getThisType();
746
747 const MemRegion *OtherSmartPtrRegion = OC->getArgSVal(0).getAsRegion();
748
749 if (!OtherSmartPtrRegion) {
750 bool AssignedNull = Call.getArgSVal(0).isZeroConstant();
751 if (!AssignedNull)
752 return false;
753 auto NullVal = C.getSValBuilder().makeNullWithType(ThisType);
754 State = State->set(ThisRegion, NullVal);
756 llvm::raw_ostream &OS) {
757 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
758 !BR.isInteresting(ThisRegion))
759 return;
760 OS << "Smart pointer";
761 checkAndPrettyPrintRegion(OS, ThisRegion);
762 OS << " is assigned to null";
763 }));
764 return true;
765 }
766
767 return updateMovedSmartPointers(C, ThisRegion, OtherSmartPtrRegion, Call);
768}
769
771 const MemRegion *ThisRegion) const {
772 const auto *OtherSmartPtrRegion = Call.getArgSVal(0).getAsRegion();
773 if (!OtherSmartPtrRegion)
774 return false;
775
776 return updateMovedSmartPointers(C, ThisRegion, OtherSmartPtrRegion, Call);
777}
778
779bool SmartPtrModeling::updateMovedSmartPointers(
783 QualType ThisType = cast(Call.getDecl())->getThisType();
784 const auto *OtherInnerPtr = State->get(OtherSmartPtrRegion);
785 if (OtherInnerPtr) {
786 State = State->set(ThisRegion, *OtherInnerPtr);
787
788 auto NullVal = C.getSValBuilder().makeNullWithType(ThisType);
789 State = State->set(OtherSmartPtrRegion, NullVal);
790 bool IsArgValNull = OtherInnerPtr->isZeroConstant();
791
792 C.addTransition(
793 State,
794 C.getNoteTag([ThisRegion, OtherSmartPtrRegion, IsArgValNull](
797 return;
799 OS << "Smart pointer";
801 OS << " is null after being moved to";
803 }
804 if (BR.isInteresting(ThisRegion) && IsArgValNull) {
805 OS << "A null pointer value is moved to";
808 }
809 }));
810 return true;
811 } else {
812
813
814
815 auto NullVal = C.getSValBuilder().makeNullWithType(ThisType);
816 State = State->remove(ThisRegion);
817 State = State->set(OtherSmartPtrRegion, NullVal);
818 C.addTransition(State, C.getNoteTag([OtherSmartPtrRegion,
820 llvm::raw_ostream &OS) {
823 return;
824 OS << "Smart pointer";
826 OS << " is null after; previous value moved to";
828 }));
829 return true;
830 }
831 return false;
832}
833
834void SmartPtrModeling::handleBoolConversion(const CallEvent &Call,
836
840 cast(&Call)->getCXXThisVal().getAsRegion();
841
842 QualType ThisType = cast(Call.getDecl())->getThisType();
843
844 SVal InnerPointerVal;
845 if (const auto *InnerValPtr = State->get(ThisRegion)) {
846 InnerPointerVal = *InnerValPtr;
847 } else {
848
849
851 if (InnerPointerType.isNull())
852 return;
853
855 InnerPointerVal = C.getSValBuilder().conjureSymbolVal(
856 CallExpr, LC, InnerPointerType, C.blockCount());
857 State = State->set(ThisRegion, InnerPointerVal);
858 }
859
860 if (State->isNull(InnerPointerVal).isConstrainedTrue()) {
861 State = State->BindExpr(CallExpr, C.getLocationContext(),
862 C.getSValBuilder().makeTruthVal(false));
863
864 C.addTransition(State);
865 return;
866 } else if (State->isNonNull(InnerPointerVal).isConstrainedTrue()) {
867 State = State->BindExpr(CallExpr, C.getLocationContext(),
868 C.getSValBuilder().makeTruthVal(true));
869
870 C.addTransition(State);
871 return;
873 C.addTransition(
874 State->BindExpr(CallExpr, C.getLocationContext(),
875 C.getSValBuilder().makeZeroVal(Call.getResultType())));
876 return;
877 } else {
879 std::tie(NotNullState, NullState) =
881
882 auto NullVal = C.getSValBuilder().makeNullWithType(ThisType);
883
884 NullState = NullState->set(ThisRegion, NullVal);
885
886 NullState = NullState->BindExpr(CallExpr, C.getLocationContext(),
887 C.getSValBuilder().makeTruthVal(false));
888 C.addTransition(NullState, C.getNoteTag(
890 llvm::raw_ostream &OS) {
891 OS << "Assuming smart pointer";
892 checkAndPrettyPrintRegion(OS, ThisRegion);
893 OS << " is null";
894 },
895 true));
896 NotNullState =
897 NotNullState->BindExpr(CallExpr, C.getLocationContext(),
898 C.getSValBuilder().makeTruthVal(true));
899 C.addTransition(
900 NotNullState,
901 C.getNoteTag(
903 OS << "Assuming smart pointer";
904 checkAndPrettyPrintRegion(OS, ThisRegion);
905 OS << " is non-null";
906 },
907 true));
908 return;
909 }
910}
911
912void ento::registerSmartPtrModeling(CheckerManager &Mgr) {
914 Checker->ModelSmartPtrDereference =
916 Checker, "ModelSmartPtrDereference");
917}
918
919bool ento::shouldRegisterSmartPtrModeling(const CheckerManager &mgr) {
921 return LO.CPlusPlus;
922}
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
static bool isStdFunctionCall(const CallEvent &Call)
static bool isStdBasicOstream(const Expr *E)
static void checkAndPrettyPrintRegion(llvm::raw_ostream &OS, const MemRegion *Region)
static QualType getInnerPointerType(CheckerContext C, const CXXRecordDecl *RD)
static ProgramStateRef updateSwappedRegion(ProgramStateRef State, const MemRegion *Region, const SVal *RegionInnerPointerVal)
static bool isStdOstreamOperatorCall(const CallEvent &Call)
static TrackedRegionMapTy removeTrackedSubregions(TrackedRegionMapTy RegionMap, TrackedRegionMapTy::Factory &RegionMapFactory, const MemRegion *Region)
static bool isPotentiallyComparisionOpCall(const CallEvent &Call)
static QualType getPointerTypeFromTemplateArg(const CallEvent &Call, CheckerContext &C)
static bool hasStdClassWithName(const CXXRecordDecl *RD, ArrayRef< llvm::StringLiteral > Names)
static bool isStdSmartPtr(const CXXRecordDecl *RD)
constexpr llvm::StringLiteral BASIC_OSTREAM_NAMES[]
constexpr llvm::StringLiteral STD_PTR_NAMES[]
C Language Family Type Representation.
bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, bool SearchInParents=false) const
Interprets an option's string value as a boolean.
Represents a C++ struct/union/class.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isStdNamespace() const
bool isInStdNamespace() const
DeclContext * getDeclContext()
bool isIdentifier() const
Predicate functions for querying what type of name this is.
This represents one expression.
Represents a function declaration or definition.
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
A (possibly-)qualified type.
Represents a struct/union/class.
StringLiteral - This represents a string literal expression, e.g.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const BugType & getBugType() const
An immutable map from CallDescriptions to arbitrary data.
An immutable set of CallDescriptions.
A CallDescription is a pattern that can be used to match calls based on the qualified name and the ar...
Represents an abstract call to a function or method along a particular path.
virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const
See CheckerManager::runCheckersForPrintState.
const AnalyzerOptions & getAnalyzerOptions() const
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
const LangOptions & getLangOpts() const
MemRegion - The root abstract class for all memory regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
virtual bool canPrintPretty() const
Returns true if this region can be printed in a user-friendly way.
BinaryOperatorKind GetBinaryOpUnsafe() const
void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind=bugreporter::TrackingKind::Thorough)
Marks a symbol as interesting.
bool isInteresting(SymbolRef sym) const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
llvm::iterator_range< symbol_iterator > symbols() const
A class responsible for cleaning up unused symbols.
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
bool isLiveRegion(const MemRegion *region)
bool isMovedFrom(ProgramStateRef State, const MemRegion *Region)
Returns true if the object is known to have been recently std::moved.
const BugType * getNullDereferenceBugType()
bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion)
Returns whether the smart pointer is null or not.
bool isStdSmartPtr(const CXXRecordDecl *RD)
bool isStdSmartPtrCall(const CallEvent &Call)
Returns true if the event call is on smart pointer.
OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, bool IsBinary)
llvm::DenseSet< SymbolRef > InvalidatedSymbols
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
Diagnostic wrappers for TextAPI types for error reporting.