33#include "llvm/ADT/STLExtras.h"
34#include "llvm/Support/ErrorHandling.h"
43 :
public Checker<eval::Call, check::DeadSymbols, check::RegionChanges,
46 bool isBoolConversionMethod(
const CallEvent &
Call)
const;
50 bool ModelSmartPtrDereference =
false;
51 bool evalCall(
const CallEvent &
Call, CheckerContext &
C)
const;
52 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &
C)
const;
56 ArrayRef<const MemRegion *> ExplicitRegions,
57 ArrayRef<const MemRegion *> Regions,
58 const LocationContext *LCtx,
const CallEvent *
Call)
const;
59 void printState(raw_ostream &Out,
ProgramStateRef State,
const char *NL,
60 const char *Sep)
const override;
64 void handleReset(
const CallEvent &
Call, CheckerContext &
C)
const;
65 void handleRelease(
const CallEvent &
Call, CheckerContext &
C)
const;
66 void handleSwapMethod(
const CallEvent &
Call, CheckerContext &
C)
const;
67 void handleGet(
const CallEvent &
Call, CheckerContext &
C)
const;
68 bool handleAssignOp(
const CallEvent &
Call, CheckerContext &
C)
const;
69 bool handleMoveCtr(
const CallEvent &
Call, CheckerContext &
C,
70 const MemRegion *ThisRegion)
const;
71 bool updateMovedSmartPointers(CheckerContext &
C,
const MemRegion *ThisRegion,
72 const MemRegion *OtherSmartPtrRegion,
73 const CallEvent &
Call)
const;
74 void handleBoolConversion(
const CallEvent &
Call, CheckerContext &
C)
const;
75 bool handleComparisionOp(
const CallEvent &
Call, CheckerContext &
C)
const;
76 bool handleOstreamOperator(
const CallEvent &
Call, CheckerContext &
C)
const;
78 CheckerContext &
C)
const;
79 std::pair<SVal, ProgramStateRef> retrieveOrConjureInnerPtrVal(
83 using SmartPtrMethodHandlerFn =
84 void (SmartPtrModeling::*)(
const CallEvent &
Call, CheckerContext &)
const;
85 CallDescriptionMap<SmartPtrMethodHandlerFn> SmartPtrMethodHandlers{
86 {{CDM::CXXMethod, {
"reset"}}, &SmartPtrModeling::handleReset},
87 {{CDM::CXXMethod, {
"release"}}, &SmartPtrModeling::handleRelease},
88 {{CDM::CXXMethod, {
"swap"}, 1}, &SmartPtrModeling::handleSwapMethod},
89 {{CDM::CXXMethod, {
"get"}}, &SmartPtrModeling::handleGet}};
90 const CallDescription StdSwapCall{CDM::SimpleFunc, {
"std",
"swap"}, 2};
91 const CallDescriptionSet MakeUniqueVariants{
92 {CDM::SimpleFunc, {
"std",
"make_unique"}},
93 {CDM::SimpleFunc, {
"std",
"make_unique_for_overwrite"}}};
102 if (!RD || !RD->getDeclContext()->isStdNamespace())
104 if (RD->getDeclName().isIdentifier())
105 return llvm::is_contained(Names, RD->getName());
125 const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(
Call.getDecl());
126 if (!MethodDecl || !MethodDecl->getParent())
136 StringRef Name = RD->
getName();
137 return Name ==
"shared_ptr" || Name ==
"unique_ptr" || Name ==
"weak_ptr";
147 const auto *InnerPointVal = State->get<TrackedRegionMap>(ThisRegion);
148 return InnerPointVal &&
156static TrackedRegionMapTy
158 TrackedRegionMapTy::Factory &RegionMapFactory,
162 for (
const auto &E : RegionMap) {
163 if (E.first->isSubRegionOf(Region))
164 RegionMap = RegionMapFactory.remove(RegionMap, E.first);
171 const SVal *RegionInnerPointerVal) {
172 if (RegionInnerPointerVal) {
173 State = State->set<TrackedRegionMap>(Region, *RegionInnerPointerVal);
175 State = State->remove<TrackedRegionMap>(Region);
184 const auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
188 auto TemplateArgs = TSD->getTemplateArgs().asArray();
189 if (TemplateArgs.empty())
191 auto InnerValueType = TemplateArgs[0].getAsType();
192 return C.getASTContext().getPointerType(InnerValueType.getCanonicalType());
200 const auto *FD = dyn_cast_or_null<FunctionDecl>(
Call.getDecl());
201 if (!FD || !FD->getPrimaryTemplate())
203 const auto &TemplateArgs = FD->getTemplateSpecializationArgs()->asArray();
204 if (TemplateArgs.size() == 0)
206 auto ValueType = TemplateArgs[0].getAsType();
207 return C.getASTContext().getPointerType(ValueType.getCanonicalType());
213 const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(
Call.getDecl());
214 if (!MethodDecl || !MethodDecl->getParent())
230bool SmartPtrModeling::isBoolConversionMethod(
const CallEvent &
Call)
const {
235 const auto *CD = dyn_cast_or_null<CXXConversionDecl>(
Call.getDecl());
236 return CD && CD->getConversionType()->isBooleanType();
247 return Call.getDecl() &&
Call.getDecl()->getDeclContext()->isStdNamespace();
253 const auto *FC = dyn_cast<SimpleFunctionCall>(&
Call);
260 if (OOK != clang::OO_LessLess)
273bool SmartPtrModeling::evalCall(
const CallEvent &
Call,
274 CheckerContext &
C)
const {
281 if (handleComparisionOp(
Call,
C))
285 return handleOstreamOperator(
Call,
C);
289 assert(
Call.getNumArgs() == 2 &&
"std::swap should have two arguments");
290 const Expr *FirstArg =
Call.getArgExpr(0);
293 return handleSwap(State,
Call.getArgSVal(0),
Call.getArgSVal(1),
C);
297 if (!ModelSmartPtrDereference)
300 const std::optional<SVal> ThisRegionOpt =
301 Call.getReturnValueUnderConstruction();
305 const auto PtrVal =
C.getSValBuilder().getConjuredHeapSymbolVal(
306 Call.getCFGElementRef(),
C.getLocationContext(),
309 const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();
310 State = State->set<TrackedRegionMap>(ThisRegion, PtrVal);
311 State = State->assume(PtrVal,
true);
329 auto &Engine = State->getStateManager().getOwningEngine();
330 State = Engine.updateObjectsUnderConstruction(
331 *ThisRegionOpt,
nullptr, State,
C.getLocationContext(),
332 Call.getConstructionContext(), {});
336 C.addTransition(State);
343 if (isBoolConversionMethod(
Call)) {
344 const MemRegion *ThisR =
347 if (ModelSmartPtrDereference) {
352 handleBoolConversion(
Call,
C);
362 C.addTransition(State->BindExpr(
363 Call.getOriginExpr(),
C.getLocationContext(),
364 C.getSValBuilder().makeZeroVal(
Call.getResultType())));
370 if (!ModelSmartPtrDereference)
373 if (
const auto *CC = dyn_cast<CXXConstructorCall>(&
Call)) {
374 if (CC->getDecl()->isCopyConstructor())
377 const MemRegion *ThisRegion = CC->getCXXThisVal().getAsRegion();
383 if (CC->getDecl()->isMoveConstructor())
384 return handleMoveCtr(
Call,
C, ThisRegion);
386 if (
Call.getNumArgs() == 0) {
387 auto NullVal =
C.getSValBuilder().makeNullWithType(ThisType);
388 State = State->set<TrackedRegionMap>(ThisRegion, NullVal);
391 State,
C.getNoteTag([ThisRegion](PathSensitiveBugReport &BR,
392 llvm::raw_ostream &
OS) {
393 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
394 !BR.isInteresting(ThisRegion))
396 OS <<
"Default constructed smart pointer";
397 checkAndPrettyPrintRegion(OS, ThisRegion);
401 const auto *TrackingExpr =
Call.getArgExpr(0);
402 assert(TrackingExpr->getType()->isPointerType() &&
403 "Adding a non pointer value to TrackedRegionMap");
404 auto ArgVal =
Call.getArgSVal(0);
405 State = State->set<TrackedRegionMap>(ThisRegion, ArgVal);
407 C.addTransition(State,
C.getNoteTag([ThisRegion, TrackingExpr,
408 ArgVal](PathSensitiveBugReport &BR,
409 llvm::raw_ostream &
OS) {
410 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
411 !BR.isInteresting(ThisRegion))
413 bugreporter::trackExpressionValue(BR.getErrorNode(), TrackingExpr, BR);
414 OS <<
"Smart pointer";
415 checkAndPrettyPrintRegion(OS, ThisRegion);
416 if (ArgVal.isZeroConstant())
417 OS <<
" is constructed using a null value";
419 OS <<
" is constructed";
425 if (handleAssignOp(
Call,
C))
428 const SmartPtrMethodHandlerFn *Handler = SmartPtrMethodHandlers.lookup(
Call);
431 (this->**Handler)(
Call,
C);
433 return C.isDifferent();
436std::pair<SVal, ProgramStateRef> SmartPtrModeling::retrieveOrConjureInnerPtrVal(
438 QualType
Type, CheckerContext &
C)
const {
439 const auto *Ptr = State->get<TrackedRegionMap>(ThisRegion);
441 return {*Ptr, State};
442 auto Val =
C.getSValBuilder().conjureSymbolVal(Elem,
C.getLocationContext(),
443 Type,
C.blockCount());
444 State = State->set<TrackedRegionMap>(ThisRegion, Val);
448bool SmartPtrModeling::handleComparisionOp(
const CallEvent &
Call,
449 CheckerContext &
C)
const {
450 const auto *FC = dyn_cast<SimpleFunctionCall>(&
Call);
453 const FunctionDecl *FD = FC->getDecl();
457 if (!(OOK == OO_EqualEqual || OOK == OO_ExclaimEqual || OOK == OO_Less ||
458 OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||
459 OOK == OO_Spaceship))
470 SVal S) -> std::pair<SVal, ProgramStateRef> {
471 if (S.isZeroConstant()) {
474 const MemRegion *Reg = S.getAsRegion();
476 "this pointer of std::unique_ptr should be obtainable as MemRegion");
478 return retrieveOrConjureInnerPtrVal(State, Reg, Elem,
Type,
C);
482 SVal Second =
Call.getArgSVal(1);
483 const auto *FirstExpr =
Call.getArgExpr(0);
484 const auto *SecondExpr =
Call.getArgExpr(1);
486 const auto *ResultExpr =
Call.getOriginExpr();
487 const auto *LCtx =
C.getLocationContext();
488 auto &Bldr =
C.getSValBuilder();
491 SVal FirstPtrVal, SecondPtrVal;
492 std::tie(FirstPtrVal, State) =
493 makeSValFor(State, FirstExpr,
Call.getCFGElementRef(),
First);
494 std::tie(SecondPtrVal, State) =
495 makeSValFor(State, SecondExpr,
Call.getCFGElementRef(), Second);
498 auto RetVal = Bldr.evalBinOp(State, BOK, FirstPtrVal, SecondPtrVal,
499 Call.getResultType());
501 if (OOK != OO_Spaceship) {
503 std::tie(TrueState, FalseState) =
504 State->assume(*RetVal.getAs<DefinedOrUnknownSVal>());
507 TrueState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(
true)));
510 FalseState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(
false)));
512 C.addTransition(State->BindExpr(ResultExpr, LCtx, RetVal));
517bool SmartPtrModeling::handleOstreamOperator(
const CallEvent &
Call,
518 CheckerContext &
C)
const {
528 const auto StreamVal =
Call.getArgSVal(0);
529 const MemRegion *StreamThisRegion = StreamVal.getAsRegion();
530 if (!StreamThisRegion)
533 State->invalidateRegions({StreamThisRegion},
Call.getCFGElementRef(),
534 C.blockCount(),
C.getLocationContext(),
false);
536 State->BindExpr(
Call.getOriginExpr(),
C.getLocationContext(), StreamVal);
537 C.addTransition(State);
541void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper,
542 CheckerContext &
C)
const {
545 TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();
546 for (
auto E : TrackedRegions) {
547 const MemRegion *Region = E.first;
551 State = State->remove<TrackedRegionMap>(Region);
553 C.addTransition(State);
556void SmartPtrModeling::printState(raw_ostream &Out,
ProgramStateRef State,
557 const char *NL,
const char *Sep)
const {
558 TrackedRegionMapTy RS = State->get<TrackedRegionMap>();
561 Out << Sep <<
"Smart ptr regions :" << NL;
563 I.first->dumpToStream(Out);
575 ArrayRef<const MemRegion *> ExplicitRegions,
576 ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
577 const CallEvent *
Call)
const {
578 TrackedRegionMapTy RegionMap = State->get<TrackedRegionMap>();
579 TrackedRegionMapTy::Factory &RegionMapFactory =
580 State->get_context<TrackedRegionMap>();
581 for (
const auto *Region : Regions)
584 return State->set<TrackedRegionMap>(RegionMap);
588 SymbolReaper &SR)
const {
590 TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();
591 for (SVal Val : llvm::make_second_range(TrackedRegions)) {
598void SmartPtrModeling::handleReset(
const CallEvent &
Call,
599 CheckerContext &
C)
const {
601 const auto *IC = dyn_cast<CXXInstanceCall>(&
Call);
605 const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
609 assert(
Call.getArgExpr(0)->getType()->isPointerType() &&
610 "Adding a non pointer value to TrackedRegionMap");
611 State = State->set<TrackedRegionMap>(ThisRegion,
Call.getArgSVal(0));
612 const auto *TrackingExpr =
Call.getArgExpr(0);
614 State,
C.getNoteTag([ThisRegion, TrackingExpr](PathSensitiveBugReport &BR,
615 llvm::raw_ostream &
OS) {
616 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
617 !BR.isInteresting(ThisRegion))
619 bugreporter::trackExpressionValue(BR.getErrorNode(), TrackingExpr, BR);
620 OS <<
"Smart pointer";
621 checkAndPrettyPrintRegion(OS, ThisRegion);
622 OS <<
" reset using a null value";
628void SmartPtrModeling::handleRelease(
const CallEvent &
Call,
629 CheckerContext &
C)
const {
631 const auto *IC = dyn_cast<CXXInstanceCall>(&
Call);
635 const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
639 const auto *InnerPointVal = State->get<TrackedRegionMap>(ThisRegion);
642 State = State->BindExpr(
Call.getOriginExpr(),
C.getLocationContext(),
647 auto ValueToUpdate =
C.getSValBuilder().makeNullWithType(ThisType);
648 State = State->set<TrackedRegionMap>(ThisRegion, ValueToUpdate);
650 C.addTransition(State,
C.getNoteTag([ThisRegion](PathSensitiveBugReport &BR,
651 llvm::raw_ostream &
OS) {
652 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
653 !BR.isInteresting(ThisRegion))
656 OS <<
"Smart pointer";
657 checkAndPrettyPrintRegion(OS, ThisRegion);
658 OS <<
" is released and set to null";
664void SmartPtrModeling::handleSwapMethod(
const CallEvent &
Call,
665 CheckerContext &
C)
const {
667 const auto *IC = dyn_cast<CXXInstanceCall>(&
Call);
671 auto State =
C.getState();
672 handleSwap(State, IC->getCXXThisVal(),
Call.getArgSVal(0),
C);
676 SVal Second, CheckerContext &
C)
const {
677 const MemRegion *FirstThisRegion =
First.getAsRegion();
678 if (!FirstThisRegion)
680 const MemRegion *SecondThisRegion = Second.
getAsRegion();
681 if (!SecondThisRegion)
684 const auto *FirstInnerPtrVal = State->get<TrackedRegionMap>(FirstThisRegion);
685 const auto *SecondInnerPtrVal =
686 State->get<TrackedRegionMap>(SecondThisRegion);
691 C.addTransition(State,
C.getNoteTag([FirstThisRegion, SecondThisRegion](
692 PathSensitiveBugReport &BR,
693 llvm::raw_ostream &
OS) {
694 if (&BR.getBugType() != smartptr::getNullDereferenceBugType())
696 if (BR.isInteresting(FirstThisRegion) &&
697 !BR.isInteresting(SecondThisRegion)) {
698 BR.markInteresting(SecondThisRegion);
699 BR.markNotInteresting(FirstThisRegion);
703 BR.markInteresting(FirstThisRegion);
704 BR.markNotInteresting(SecondThisRegion);
712void SmartPtrModeling::handleGet(
const CallEvent &
Call,
713 CheckerContext &
C)
const {
715 const auto *IC = dyn_cast<CXXInstanceCall>(&
Call);
719 const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
723 SVal InnerPointerVal;
724 std::tie(InnerPointerVal, State) = retrieveOrConjureInnerPtrVal(
725 State, ThisRegion,
Call.getCFGElementRef(),
Call.getResultType(),
C);
726 State = State->BindExpr(
Call.getOriginExpr(),
C.getLocationContext(),
729 C.addTransition(State);
732bool SmartPtrModeling::handleAssignOp(
const CallEvent &
Call,
733 CheckerContext &
C)
const {
735 const auto *OC = dyn_cast<CXXMemberOperatorCall>(&
Call);
741 const MemRegion *ThisRegion = OC->getCXXThisVal().getAsRegion();
747 const MemRegion *OtherSmartPtrRegion = OC->getArgSVal(0).getAsRegion();
749 if (!OtherSmartPtrRegion) {
750 bool AssignedNull =
Call.getArgSVal(0).isZeroConstant();
753 auto NullVal =
C.getSValBuilder().makeNullWithType(ThisType);
754 State = State->set<TrackedRegionMap>(ThisRegion, NullVal);
755 C.addTransition(State,
C.getNoteTag([ThisRegion](PathSensitiveBugReport &BR,
756 llvm::raw_ostream &
OS) {
757 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
758 !BR.isInteresting(ThisRegion))
760 OS <<
"Smart pointer";
761 checkAndPrettyPrintRegion(OS, ThisRegion);
762 OS <<
" is assigned to null";
767 return updateMovedSmartPointers(
C, ThisRegion, OtherSmartPtrRegion,
Call);
770bool SmartPtrModeling::handleMoveCtr(
const CallEvent &
Call, CheckerContext &
C,
771 const MemRegion *ThisRegion)
const {
772 const auto *OtherSmartPtrRegion =
Call.getArgSVal(0).getAsRegion();
773 if (!OtherSmartPtrRegion)
776 return updateMovedSmartPointers(
C, ThisRegion, OtherSmartPtrRegion,
Call);
779bool SmartPtrModeling::updateMovedSmartPointers(
780 CheckerContext &
C,
const MemRegion *ThisRegion,
781 const MemRegion *OtherSmartPtrRegion,
const CallEvent &
Call)
const {
784 const auto *OtherInnerPtr = State->get<TrackedRegionMap>(OtherSmartPtrRegion);
786 State = State->set<TrackedRegionMap>(ThisRegion, *OtherInnerPtr);
788 auto NullVal =
C.getSValBuilder().makeNullWithType(ThisType);
789 State = State->set<TrackedRegionMap>(OtherSmartPtrRegion, NullVal);
790 bool IsArgValNull = OtherInnerPtr->isZeroConstant();
794 C.getNoteTag([ThisRegion, OtherSmartPtrRegion, IsArgValNull](
795 PathSensitiveBugReport &BR, llvm::raw_ostream &
OS) {
796 if (&BR.getBugType() != smartptr::getNullDereferenceBugType())
798 if (BR.isInteresting(OtherSmartPtrRegion)) {
799 OS <<
"Smart pointer";
800 checkAndPrettyPrintRegion(OS, OtherSmartPtrRegion);
801 OS <<
" is null after being moved to";
802 checkAndPrettyPrintRegion(OS, ThisRegion);
805 OS <<
"A null pointer value is moved to";
806 checkAndPrettyPrintRegion(OS, ThisRegion);
807 BR.markInteresting(OtherSmartPtrRegion);
815 auto NullVal =
C.getSValBuilder().makeNullWithType(ThisType);
816 State = State->remove<TrackedRegionMap>(ThisRegion);
817 State = State->set<TrackedRegionMap>(OtherSmartPtrRegion, NullVal);
818 C.addTransition(State,
C.getNoteTag([OtherSmartPtrRegion,
819 ThisRegion](PathSensitiveBugReport &BR,
820 llvm::raw_ostream &
OS) {
821 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
822 !BR.isInteresting(OtherSmartPtrRegion))
824 OS <<
"Smart pointer";
825 checkAndPrettyPrintRegion(OS, OtherSmartPtrRegion);
826 OS <<
" is null after; previous value moved to";
827 checkAndPrettyPrintRegion(OS, ThisRegion);
834void SmartPtrModeling::handleBoolConversion(
const CallEvent &
Call,
835 CheckerContext &
C)
const {
838 const Expr *CallExpr =
Call.getOriginExpr();
839 const MemRegion *ThisRegion =
844 SVal InnerPointerVal;
845 if (
const auto *InnerValPtr = State->get<TrackedRegionMap>(ThisRegion)) {
846 InnerPointerVal = *InnerValPtr;
851 if (InnerPointerType.isNull())
854 InnerPointerVal =
C.getSValBuilder().conjureSymbolVal(
855 Call, InnerPointerType,
C.blockCount());
856 State = State->set<TrackedRegionMap>(ThisRegion, InnerPointerVal);
859 if (State->isNull(InnerPointerVal).isConstrainedTrue()) {
860 State = State->BindExpr(CallExpr,
C.getLocationContext(),
861 C.getSValBuilder().makeTruthVal(
false));
863 C.addTransition(State);
865 }
else if (State->isNonNull(InnerPointerVal).isConstrainedTrue()) {
866 State = State->BindExpr(CallExpr,
C.getLocationContext(),
867 C.getSValBuilder().makeTruthVal(
true));
869 C.addTransition(State);
873 State->BindExpr(CallExpr,
C.getLocationContext(),
874 C.getSValBuilder().makeZeroVal(
Call.getResultType())));
878 std::tie(NotNullState, NullState) =
879 State->assume(InnerPointerVal.
castAs<DefinedOrUnknownSVal>());
881 auto NullVal =
C.getSValBuilder().makeNullWithType(ThisType);
883 NullState = NullState->set<TrackedRegionMap>(ThisRegion, NullVal);
885 NullState = NullState->BindExpr(CallExpr,
C.getLocationContext(),
886 C.getSValBuilder().makeTruthVal(
false));
887 C.addTransition(NullState,
C.getNoteTag(
888 [ThisRegion](PathSensitiveBugReport &BR,
889 llvm::raw_ostream &
OS) {
890 OS <<
"Assuming smart pointer";
891 checkAndPrettyPrintRegion(OS, ThisRegion);
896 NotNullState->BindExpr(CallExpr,
C.getLocationContext(),
897 C.getSValBuilder().makeTruthVal(
true));
901 [ThisRegion](PathSensitiveBugReport &BR, llvm::raw_ostream &
OS) {
902 OS <<
"Assuming smart pointer";
903 checkAndPrettyPrintRegion(OS, ThisRegion);
904 OS <<
" is non-null";
911void ento::registerSmartPtrModeling(CheckerManager &Mgr) {
913 Checker->ModelSmartPtrDereference =
915 Checker,
"ModelSmartPtrDereference");
918bool ento::shouldRegisterSmartPtrModeling(
const CheckerManager &mgr) {
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.
Represents a C++ struct/union/class.
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.
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.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool contains(const CallEvent &Call) const
bool matches(const CallEvent &Call) const
Returns true if the CallEvent is a call to a function that matches the CallDescription.
Represents an abstract call to a function or method along a particular path.
const AnalyzerOptions & getAnalyzerOptions() const
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
const LangOptions & getLangOpts() const
Simple checker classes that implement one frontend (i.e.
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
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
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.
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.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, bool IsBinary)
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
CFGBlock::ConstCFGElementRef ConstCFGElementRef
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ Type
The name was classified as a type.
U cast(CodeGen::Address addr)
Diagnostic wrappers for TextAPI types for error reporting.