49 #include "llvm/ADT/ArrayRef.h" 50 #include "llvm/ADT/None.h" 51 #include "llvm/ADT/Optional.h" 52 #include "llvm/ADT/STLExtras.h" 53 #include "llvm/ADT/SmallPtrSet.h" 54 #include "llvm/ADT/SmallString.h" 55 #include "llvm/ADT/SmallVector.h" 56 #include "llvm/ADT/StringExtras.h" 57 #include "llvm/ADT/StringRef.h" 58 #include "llvm/Support/Casting.h" 59 #include "llvm/Support/ErrorHandling.h" 60 #include "llvm/Support/raw_ostream.h" 67 using namespace clang;
97 const Expr *bugreporter::getDerefExpr(
const Stmt *S) {
98 const auto *E = dyn_cast<
Expr>(S);
103 if (
const auto *CE = dyn_cast<CastExpr>(E)) {
104 if (CE->getCastKind() == CK_LValueToRValue) {
108 E = CE->getSubExpr();
109 }
else if (
const auto *B = dyn_cast<BinaryOperator>(E)) {
118 }
else if (
const auto *U = dyn_cast<UnaryOperator>(E)) {
119 if (U->getOpcode() == UO_Deref || U->getOpcode() == UO_AddrOf ||
120 (U->isIncrementDecrementOp() && U->getType()->isPointerType())) {
131 else if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
133 }
else if (
const auto *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
134 E = IvarRef->getBase();
135 }
else if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(E)) {
137 }
else if (
const auto *PE = dyn_cast<ParenExpr>(E)) {
138 E = PE->getSubExpr();
139 }
else if (
const auto *FE = dyn_cast<FullExpr>(E)) {
140 E = FE->getSubExpr();
150 if (
const auto *CE = dyn_cast<ImplicitCastExpr>(E))
151 if (CE->getCastKind() == CK_LValueToRValue)
152 E = CE->getSubExpr();
166 const ExplodedNode *RightNode, SVal RightVal) {
167 if (LeftVal == RightVal)
170 const auto LLCV = LeftVal.getAs<nonloc::LazyCompoundVal>();
174 const auto RLCV = RightVal.getAs<nonloc::LazyCompoundVal>();
178 return LLCV->getRegion() == RLCV->getRegion() &&
179 LLCV->getStore() == LeftNode->getState()->getStore() &&
180 RLCV->getStore() == RightNode->getState()->getStore();
184 const ExplodedNode *N) {
195 if (
const auto *DRE = dyn_cast<DeclRefExpr>(CondVarExpr))
196 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
197 return State->getSVal(State->getLValue(VD, LCtx));
199 if (
const auto *ME = dyn_cast<MemberExpr>(CondVarExpr))
200 if (
const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
201 if (
auto FieldL = State->getSVal(ME, LCtx).getAs<Loc>())
202 return State->getRawSVal(*FieldL, FD->getType());
211 if (
auto CI =
V->getAs<nonloc::ConcreteInt>())
212 return &CI->getValue();
217 const ExplodedNode *N,
218 const PathSensitiveBugReport *B) {
222 if (!B->getErrorNode()->getStackFrame()->isParentOf(N->getStackFrame()))
227 return *K == bugreporter::TrackingKind::Condition;
233 const PathSensitiveBugReport *B) {
235 return B->getInterestingnessKind(*V).hasValue();
241 BugReporterContext &BRC) {
244 BRC.getSourceManager(),
245 BRC.getASTContext().getLangOpts());
266 const ExplodedNode *N,
269 ProgramStateManager &Mgr = N->getState()->getStateManager();
276 if (
auto PS = N->getLocationAs<
PostStmt>())
278 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(
279 N->getSVal(BO->getLHS()).getAsRegion()))
283 SVal ValueAtN = N->getState()->getSVal(RegionOfInterest);
284 if (!Mgr.getSValBuilder()
285 .areEqual(State, ValueAtN, ValueAfter)
286 .isConstrainedTrue() &&
287 (!ValueAtN.isUndef() || !ValueAfter.isUndef()))
298 const ExplodedNode *,
299 PathSensitiveBugReport &) {
303 void BugReporterVisitor::finalizeVisitor(BugReporterContext &,
304 const ExplodedNode *,
305 PathSensitiveBugReport &) {}
308 BugReporterVisitor::getDefaultEndPath(
const BugReporterContext &BRC,
309 const ExplodedNode *EndPathNode,
310 const PathSensitiveBugReport &BR) {
311 PathDiagnosticLocation L = BR.getLocation();
312 const auto &Ranges = BR.getRanges();
316 auto P = std::make_shared<PathDiagnosticEventPiece>(
317 L, BR.getDescription(), Ranges.begin() == Ranges.end());
335 const SubRegion *RegionOfInterest;
336 MemRegionManager &MmrMgr;
339 bugreporter::TrackingKind TKind;
344 static const unsigned DEREFERENCE_LIMIT = 2;
354 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingRegion;
355 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
360 NoStoreFuncVisitor(
const SubRegion *R, bugreporter::TrackingKind TKind)
361 : RegionOfInterest(R), MmrMgr(*R->getMemRegionManager()),
362 SM(MmrMgr.getContext().getSourceManager()),
363 PP(MmrMgr.getContext().getPrintingPolicy()), TKind(TKind) {}
365 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
368 ID.AddPointer(RegionOfInterest);
371 void *getTag()
const {
373 return static_cast<void *
>(&Tag);
377 BugReporterContext &BR,
378 PathSensitiveBugReport &R)
override;
389 const MemRegion *R,
const RegionVector &Vec = {},
395 bool isRegionOfInterestModifiedInFrame(
const ExplodedNode *N) {
398 if (!FramesModifyingCalculated.count(SCtx))
399 findModifyingFrames(N);
400 return FramesModifyingRegion.count(SCtx);
405 void findModifyingFrames(
const ExplodedNode *N);
412 maybeEmitNote(PathSensitiveBugReport &R,
const CallEvent &Call,
413 const ExplodedNode *N,
const RegionVector &FieldChain,
414 const MemRegion *MatchedRegion, StringRef FirstElement,
415 bool FirstIsReferenceType,
unsigned IndirectionLevel);
419 bool prettyPrintRegionName(StringRef FirstElement,
bool FirstIsReferenceType,
420 const MemRegion *MatchedRegion,
421 const RegionVector &FieldChain,
422 int IndirectionLevel,
423 llvm::raw_svector_ostream &os);
426 static StringRef prettyPrintFirstElement(StringRef FirstElement,
427 bool MoreItemsExpected,
428 int IndirectionLevel,
429 llvm::raw_svector_ostream &os);
439 const char *IvarBind =
"Ivar";
440 if (!Parent || !Parent->
hasBody())
443 hasOperatorName(
"="),
444 hasLHS(ignoringParenImpCasts(
450 if (IvarRef->isFreeIvar())
453 const Expr *
Base = IvarRef->getBase();
454 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(Base))
455 Base = ICE->getSubExpr();
457 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Base))
458 if (
const auto *
ID = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
471 RuntimeDefinition RD = Call->getRuntimeDefinition();
472 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl()))
473 return FD->parameters();
474 if (
const auto *MD = dyn_cast_or_null<ObjCMethodDecl>(RD.getDecl()))
475 return MD->parameters();
477 return Call->parameters();
493 NoStoreFuncVisitor::findRegionOfInterestInRecord(
498 if (depth == DEREFERENCE_LIMIT)
501 if (
const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
502 if (!RDX->hasDefinition())
507 if (
const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
508 for (
const auto II : RDX->bases())
509 if (
const RecordDecl *RRD = II.getType()->getAsRecordDecl())
511 findRegionOfInterestInRecord(RRD,
State, R, Vec, depth))
516 const FieldRegion *FR = MmrMgr.getFieldRegion(I, cast<SubRegion>(R));
517 const SVal
V =
State->getSVal(FR);
518 const MemRegion *VR = V.getAsRegion();
520 RegionVector VecF = Vec;
523 if (RegionOfInterest == VR)
528 findRegionOfInterestInRecord(RRD,
State, FR, VecF, depth + 1))
537 findRegionOfInterestInRecord(RRD,
State, VR, VecF, depth + 1))
545 NoStoreFuncVisitor::VisitNode(
const ExplodedNode *N, BugReporterContext &BR,
546 PathSensitiveBugReport &R) {
554 if (!CallExitLoc || isRegionOfInterestModifiedInFrame(N))
557 CallEventRef<> Call =
558 BR.getStateManager().getCallEventManager().getCaller(SCtx, State);
562 if (
const auto *MC = dyn_cast<ObjCMethodCall>(Call)) {
563 if (
const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest)) {
564 const MemRegion *SelfRegion = MC->getReceiverSVal().getAsRegion();
565 if (RegionOfInterest->isSubRegionOf(SelfRegion) &&
568 return maybeEmitNote(R, *Call, N, {}, SelfRegion,
"self",
573 if (
const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
574 const MemRegion *ThisR = CCall->getCXXThisVal().getAsRegion();
575 if (RegionOfInterest->isSubRegionOf(ThisR) &&
576 !CCall->getDecl()->isImplicit())
577 return maybeEmitNote(R, *Call, N, {}, ThisR,
"this",
586 for (
unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) {
588 SVal
V = Call->getArgSVal(I);
592 int IndirectionLevel = 1;
594 while (
const MemRegion *MR = V.getAsRegion()) {
596 return maybeEmitNote(R, *Call, N, {}, MR, ParamName,
597 ParamIsReferenceType, IndirectionLevel);
605 findRegionOfInterestInRecord(RD, State, MR))
606 return maybeEmitNote(R, *Call, N, *
P, RegionOfInterest, ParamName,
607 ParamIsReferenceType, IndirectionLevel);
609 V = State->getSVal(MR, PT);
618 void NoStoreFuncVisitor::findModifyingFrames(
const ExplodedNode *N) {
621 SVal ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
629 LastReturnState =
State;
630 ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
633 FramesModifyingCalculated.insert(N->getLocationContext()->getStackFrame());
638 auto p = FramesModifyingRegion.insert(SCtx);
646 if (
auto CE = N->getLocationAs<
CallEnter>())
647 if (CE->getCalleeContext() == OriginalSCtx)
650 N = N->getFirstPred();
655 ", which participates in a condition later";
658 PathSensitiveBugReport &R,
const CallEvent &Call,
const ExplodedNode *N,
659 const RegionVector &FieldChain,
const MemRegion *MatchedRegion,
660 StringRef FirstElement,
bool FirstIsReferenceType,
661 unsigned IndirectionLevel) {
671 if (Call.isInSystemHeader()) {
679 if (!N->getStackFrame()->getCFG()->isLinear())
680 R.markInvalid(getTag(),
nullptr);
684 PathDiagnosticLocation L =
690 if (!L.hasValidLocation())
694 llvm::raw_svector_ostream os(sbuf);
695 os <<
"Returning without writing to '";
698 if (!prettyPrintRegionName(FirstElement, FirstIsReferenceType, MatchedRegion,
699 FieldChain, IndirectionLevel, os))
703 if (TKind == bugreporter::TrackingKind::Condition)
705 return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
708 bool NoStoreFuncVisitor::prettyPrintRegionName(StringRef FirstElement,
709 bool FirstIsReferenceType,
710 const MemRegion *MatchedRegion,
711 const RegionVector &FieldChain,
712 int IndirectionLevel,
713 llvm::raw_svector_ostream &os) {
715 if (FirstIsReferenceType)
718 RegionVector RegionSequence;
721 assert(RegionOfInterest->isSubRegionOf(MatchedRegion));
722 const MemRegion *R = RegionOfInterest;
723 while (R != MatchedRegion) {
724 RegionSequence.push_back(R);
725 R = cast<SubRegion>(R)->getSuperRegion();
727 std::reverse(RegionSequence.begin(), RegionSequence.end());
728 RegionSequence.append(FieldChain.begin(), FieldChain.end());
731 for (
const MemRegion *R : RegionSequence) {
735 if (isa<CXXBaseObjectRegion>(R) || isa<CXXTempObjectRegion>(R))
739 Sep = prettyPrintFirstElement(FirstElement,
741 IndirectionLevel, os);
746 if (!isa<DeclRegion>(R))
749 const auto *DR = cast<DeclRegion>(R);
750 Sep = DR->getValueType()->isAnyPointerType() ?
"->" :
".";
751 DR->getDecl()->getDeclName().print(os, PP);
755 prettyPrintFirstElement(FirstElement,
756 false, IndirectionLevel, os);
760 StringRef NoStoreFuncVisitor::prettyPrintFirstElement(
761 StringRef FirstElement,
bool MoreItemsExpected,
int IndirectionLevel,
762 llvm::raw_svector_ostream &os) {
765 if (IndirectionLevel > 0 && MoreItemsExpected) {
770 if (IndirectionLevel > 0 && MoreItemsExpected)
773 for (
int i = 0; i < IndirectionLevel; i++)
777 if (IndirectionLevel > 0 && MoreItemsExpected)
792 const SubRegion *RegionOfInterest;
793 const SVal ValueAtDereference;
797 bool WasModified =
false;
800 MacroNullReturnSuppressionVisitor(
const SubRegion *R,
const SVal
V)
801 : RegionOfInterest(R), ValueAtDereference(V) {}
804 BugReporterContext &BRC,
805 PathSensitiveBugReport &BR)
override {
809 auto BugPoint = BR.getErrorNode()->getLocation().getAs<
StmtPoint>();
814 if (
auto Loc = matchAssignment(N)) {
819 BR.markInvalid(getTag(), MacroName.c_str());
829 static void addMacroVisitorIfNecessary(
830 const ExplodedNode *N,
const MemRegion *R,
831 bool EnableNullFPSuppression, PathSensitiveBugReport &BR,
833 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
834 if (EnableNullFPSuppression &&
835 Options.ShouldSuppressNullReturnPaths && V.getAs<Loc>())
836 BR.addVisitor(std::make_unique<MacroNullReturnSuppressionVisitor>(
837 R->getAs<SubRegion>(), V));
840 void* getTag()
const {
842 return static_cast<void *
>(&Tag);
845 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
846 ID.AddPointer(getTag());
853 const Stmt *S = N->getStmtForDiagnostics();
855 auto *LCtx = N->getLocationContext();
859 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
860 if (
const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
861 if (
const Expr *RHS = VD->getInit())
862 if (RegionOfInterest->isSubRegionOf(
863 State->getLValue(VD, LCtx).getAsRegion()))
864 return RHS->getBeginLoc();
865 }
else if (
const auto *BO = dyn_cast<BinaryOperator>(S)) {
866 const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
867 const Expr *RHS = BO->getRHS();
868 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) {
895 bool EnableNullFPSuppression;
896 bool ShouldInvalidate =
true;
898 bugreporter::TrackingKind TKind;
903 : CalleeSFC(Frame), EnableNullFPSuppression(Suppressed),
904 Options(Options), TKind(TKind) {}
906 static void *getTag() {
908 return static_cast<void *
>(&Tag);
911 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
912 ID.AddPointer(ReturnVisitor::getTag());
913 ID.AddPointer(CalleeSFC);
914 ID.AddBoolean(EnableNullFPSuppression);
924 static void addVisitorIfNecessary(
const ExplodedNode *
Node,
const Stmt *S,
925 PathSensitiveBugReport &BR,
926 bool InEnableNullFPSuppression,
927 bugreporter::TrackingKind TKind) {
935 const bool BypassCXXNewExprEval = isa<CXXNewExpr>(S);
943 if (CEE->getCalleeContext()->getCallSite() == S)
947 Node = Node->getFirstPred();
956 if (!BypassCXXNewExprEval)
959 if (SP->getStmt() == S && CurrentSFC == PredSFC)
962 CurrentSFC = PredSFC;
963 }
while (Node->getStackFrame() == CurrentSFC);
966 while (Node && Node->getLocation().getAs<
PostStmt>())
967 Node = Node->getFirstPred();
982 SVal RetVal = Node->getSVal(S);
985 if (cast<Expr>(S)->isGLValue())
987 RetVal = State->getSVal(*LValue);
992 bool EnableNullFPSuppression =
false;
993 if (InEnableNullFPSuppression &&
994 Options.ShouldSuppressNullReturnPaths)
996 EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
998 BR.addVisitor(std::make_unique<ReturnVisitor>(CalleeContext,
999 EnableNullFPSuppression,
1004 BugReporterContext &BRC,
1005 PathSensitiveBugReport &BR) {
1007 if (N->getLocationContext() != CalleeSFC)
1021 SVal
V = State->getSVal(
Ret, CalleeSFC);
1022 if (V.isUnknownOrUndef())
1028 const Expr *RetE =
Ret->getRetValue();
1029 assert(RetE &&
"Tracking a return value for a void function");
1034 if ((LValue = V.getAs<Loc>())) {
1035 SVal RValue = State->getRawSVal(*LValue, RetE->
getType());
1036 if (RValue.getAs<DefinedSVal>())
1042 if (V.getAs<nonloc::LazyCompoundVal>() ||
1043 V.getAs<nonloc::CompoundVal>())
1049 bugreporter::trackExpressionValue(
1050 N, RetE, BR, TKind, EnableNullFPSuppression);
1054 llvm::raw_svector_ostream Out(Msg);
1056 bool WouldEventBeMeaningless =
false;
1058 if (State->isNull(V).isConstrainedTrue()) {
1059 if (V.getAs<Loc>()) {
1064 if (EnableNullFPSuppression &&
1065 Options.ShouldAvoidSuppressingNullArgumentPaths)
1066 Mode = MaybeUnsuppress;
1069 Out <<
"Returning nil";
1071 Out <<
"Returning null pointer";
1074 Out <<
"Returning zero";
1078 if (
auto CI = V.getAs<nonloc::ConcreteInt>()) {
1079 Out <<
"Returning the value " << CI->getValue();
1086 if (N->getCFG().size() == 3)
1087 WouldEventBeMeaningless =
true;
1090 Out <<
"Returning pointer";
1092 Out <<
"Returning value";
1097 if (
const MemRegion *MR = LValue->getAsRegion()) {
1098 if (MR->canPrintPretty()) {
1099 Out <<
" (reference to ";
1100 MR->printPretty(Out);
1106 if (
const auto *DR = dyn_cast<DeclRefExpr>(RetE))
1107 if (
const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
1108 Out <<
" (loaded from '" << *DD <<
"')";
1111 PathDiagnosticLocation L(
Ret, BRC.getSourceManager(), CalleeSFC);
1112 if (!L.isValid() || !L.asLocation().isValid())
1115 if (TKind == bugreporter::TrackingKind::Condition)
1118 auto EventPiece = std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
1122 if (WouldEventBeMeaningless)
1123 EventPiece->setPrunable(
true);
1125 BR.markInteresting(CalleeSFC);
1131 BugReporterContext &BRC,
1132 PathSensitiveBugReport &BR) {
1133 assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
1140 if (CE->getCalleeContext() != CalleeSFC)
1148 ProgramStateManager &StateMgr = BRC.getStateManager();
1152 CallEventRef<> Call = CallMgr.
getCaller(CalleeSFC, State);
1153 for (
unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
1158 const Expr *ArgE = Call->getArgExpr(I);
1163 if (!State->isNull(*ArgV).isConstrainedTrue())
1166 if (trackExpressionValue(N, ArgE, BR, TKind, EnableNullFPSuppression))
1167 ShouldInvalidate =
false;
1178 BugReporterContext &BRC,
1179 PathSensitiveBugReport &BR)
override {
1182 return visitNodeInitial(N, BRC, BR);
1183 case MaybeUnsuppress:
1184 return visitNodeMaybeUnsuppress(N, BRC, BR);
1189 llvm_unreachable(
"Invalid visit mode!");
1192 void finalizeVisitor(BugReporterContext &,
const ExplodedNode *,
1193 PathSensitiveBugReport &BR)
override {
1194 if (EnableNullFPSuppression && ShouldInvalidate)
1195 BR.markInvalid(ReturnVisitor::getTag(), CalleeSFC);
1205 void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
1207 ID.AddPointer(&tag);
1210 ID.AddInteger(static_cast<int>(TKind));
1211 ID.AddBoolean(EnableNullFPSuppression);
1228 const MemSpaceRegion *VarSpace = VR->getMemorySpace();
1229 const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
1234 assert(VR->getDecl()->isStaticLocal() &&
"non-static stackless VarRegion");
1238 assert(VR->getDecl()->hasLocalStorage());
1245 const MemRegion *R, SVal
V,
const DeclStmt *DS) {
1246 if (R->canPrintPretty()) {
1251 if (V.getAs<loc::ConcreteInt>()) {
1253 if (R->isBoundable()) {
1254 if (
const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1255 if (TR->getValueType()->isObjCObjectPointerType()) {
1256 os << action <<
"nil";
1262 os << action <<
"a null pointer value";
1264 }
else if (
auto CVal = V.getAs<nonloc::ConcreteInt>()) {
1265 os << action << CVal->getValue();
1268 if (isa<VarRegion>(R)) {
1270 if (VD->getInit()) {
1271 os << (R->canPrintPretty() ?
"initialized" :
"Initializing")
1272 <<
" to a garbage value";
1274 os << (R->canPrintPretty() ?
"declared" :
"Declaring")
1275 <<
" without an initial value";
1279 os << (R->canPrintPretty() ?
"initialized" :
"Initialized")
1287 const VarRegion *VR,
1289 const auto *Param = cast<ParmVarDecl>(VR->getDecl());
1293 if (V.getAs<loc::ConcreteInt>()) {
1294 if (Param->getType()->isObjCObjectPointerType())
1295 os <<
"nil object reference";
1297 os <<
"null pointer value";
1298 }
else if (V.isUndef()) {
1299 os <<
"uninitialized value";
1300 }
else if (
auto CI = V.getAs<nonloc::ConcreteInt>()) {
1301 os <<
"the value " << CI->getValue();
1307 unsigned Idx = Param->getFunctionScopeIndex() + 1;
1308 os <<
" via " << Idx << llvm::getOrdinalSuffix(Idx) <<
" parameter";
1309 if (VR->canPrintPretty()) {
1311 VR->printPretty(os);
1317 const MemRegion *R, SVal
V) {
1318 if (V.getAs<loc::ConcreteInt>()) {
1320 if (R->isBoundable()) {
1321 if (
const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1322 if (TR->getValueType()->isObjCObjectPointerType()) {
1323 os <<
"nil object reference stored";
1329 if (R->canPrintPretty())
1330 os <<
"Null pointer value stored";
1332 os <<
"Storing null pointer value";
1335 }
else if (V.isUndef()) {
1336 if (R->canPrintPretty())
1337 os <<
"Uninitialized value stored";
1339 os <<
"Storing uninitialized value";
1341 }
else if (
auto CV = V.getAs<nonloc::ConcreteInt>()) {
1342 if (R->canPrintPretty())
1343 os <<
"The value " << CV->getValue() <<
" is assigned";
1345 os <<
"Assigning " << CV->getValue();
1348 if (R->canPrintPretty())
1349 os <<
"Value assigned";
1351 os <<
"Assigning value";
1354 if (R->canPrintPretty()) {
1361 FindLastStoreBRVisitor::VisitNode(
const ExplodedNode *Succ,
1362 BugReporterContext &BRC,
1363 PathSensitiveBugReport &BR) {
1367 const ExplodedNode *StoreSite =
nullptr;
1368 const ExplodedNode *Pred = Succ->getFirstPred();
1369 const Expr *InitE =
nullptr;
1370 bool IsParam =
false;
1373 if (
const auto *VR = dyn_cast<VarRegion>(R)) {
1376 InitE = VR->getDecl()->getInit();
1383 const MemRegion *FieldReg = (
const MemRegion *)PIP->getLocationValue();
1384 if (FieldReg == R) {
1386 InitE = PIP->getInitializer()->getInit();
1396 if (Succ->getState()->getSVal(R) !=
V)
1401 if (!PS || PS->getLocationValue() != R)
1411 if (BO->isAssignmentOp())
1412 InitE = BO->getRHS();
1419 if (
const auto *VR = dyn_cast<VarRegion>(R)) {
1421 if (
const auto *Param = dyn_cast<ParmVarDecl>(VR->getDecl())) {
1422 ProgramStateManager &StateMgr = BRC.getStateManager();
1425 CallEventRef<> Call = CallMgr.
getCaller(CE->getCalleeContext(),
1427 InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
1430 assert(isa<ImplicitParamDecl>(VR->getDecl()));
1431 InitE = cast<ObjCMessageExpr>(CE->getCalleeContext()->getCallSite())
1440 if (
const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R))
1441 InitE = TmpR->getExpr();
1455 bugreporter::trackExpressionValue(
1456 StoreSite, InitE, BR, TKind, EnableNullFPSuppression);
1459 if (TKind == TrackingKind::Condition &&
1460 !OriginSFC->isParentOf(StoreSite->getStackFrame()))
1465 llvm::raw_svector_ostream os(sbuf);
1468 const Stmt *S = PS->getStmt();
1469 const char *action =
nullptr;
1470 const auto *DS = dyn_cast<
DeclStmt>(S);
1471 const auto *VR = dyn_cast<VarRegion>(R);
1474 action = R->canPrintPretty() ?
"initialized to " :
1476 }
else if (isa<BlockExpr>(S)) {
1477 action = R->canPrintPretty() ?
"captured by block as " :
1478 "Captured by block as ";
1482 SVal
V = StoreSite->getSVal(S);
1483 if (
const auto *BDR =
1484 dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
1485 if (
const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
1486 if (
auto KV = State->getSVal(OriginalR).getAs<KnownSVal>())
1487 BR.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
1488 *KV, OriginalR, EnableNullFPSuppression, TKind, OriginSFC));
1496 }
else if (StoreSite->getLocation().getAs<
CallEnter>()) {
1497 if (
const auto *VR = dyn_cast<VarRegion>(R))
1501 if (os.str().empty())
1504 if (TKind == bugreporter::TrackingKind::Condition)
1509 PathDiagnosticLocation L;
1511 L = PathDiagnosticLocation(InitE, BRC.getSourceManager(),
1514 if (!L.isValid() || !L.asLocation().isValid())
1517 if (!L.isValid() || !L.asLocation().isValid())
1520 return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1527 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
1529 ID.AddPointer(&tag);
1530 ID.AddBoolean(Assumption);
1536 const char *TrackConstraintBRVisitor::getTag() {
1537 return "TrackConstraintBRVisitor";
1540 bool TrackConstraintBRVisitor::isUnderconstrained(
const ExplodedNode *N)
const {
1542 return N->getState()->isNull(Constraint).isUnderconstrained();
1543 return (
bool)N->getState()->assume(Constraint, !Assumption);
1547 const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) {
1548 const ExplodedNode *PrevN = N->getFirstPred();
1554 if (!IsTrackingTurnedOn)
1555 if (!isUnderconstrained(N))
1556 IsTrackingTurnedOn =
true;
1557 if (!IsTrackingTurnedOn)
1562 if (isUnderconstrained(PrevN)) {
1568 assert(!isUnderconstrained(N));
1573 llvm::raw_svector_ostream os(sbuf);
1575 if (Constraint.getAs<Loc>()) {
1576 os <<
"Assuming pointer value is ";
1577 os << (Assumption ?
"non-null" :
"null");
1580 if (os.str().empty())
1585 PathDiagnosticLocation L =
1590 auto X = std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1591 X->setTag(getTag());
1592 return std::move(
X);
1602 SuppressInlineDefensiveChecksVisitor::
1603 SuppressInlineDefensiveChecksVisitor(DefinedSVal
Value,
const ExplodedNode *N)
1606 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
1607 if (!Options.ShouldSuppressInlinedDefensiveChecks)
1610 assert(N->getState()->isNull(
V).isConstrainedTrue() &&
1611 "The visitor only tracks the cases where V is constrained to 0");
1614 void SuppressInlineDefensiveChecksVisitor::Profile(
1615 llvm::FoldingSetNodeID &
ID)
const {
1621 const char *SuppressInlineDefensiveChecksVisitor::getTag() {
1622 return "IDCVisitor";
1626 SuppressInlineDefensiveChecksVisitor::VisitNode(
const ExplodedNode *Succ,
1627 BugReporterContext &BRC,
1628 PathSensitiveBugReport &BR) {
1629 const ExplodedNode *Pred = Succ->getFirstPred();
1634 if (!IsTrackingTurnedOn)
1635 if (Succ->getState()->isNull(
V).isConstrainedTrue())
1636 IsTrackingTurnedOn =
true;
1637 if (!IsTrackingTurnedOn)
1642 if (!Pred->getState()->isNull(
V).isConstrainedTrue()) {
1645 assert(Succ->getState()->isNull(
V).isConstrainedTrue());
1649 const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
1650 if (CurLC != ReportLC && !CurLC->
isParentOf(ReportLC)) {
1651 BR.markInvalid(
"Suppress IDC", CurLC);
1659 auto BugPoint = BR.getErrorNode()->getLocation().getAs<
StmtPoint>();
1665 const Stmt *CurTerminatorStmt =
nullptr;
1667 CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
1669 const Stmt *CurStmt = SP->getStmt();
1673 CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
1679 if (!CurTerminatorStmt)
1689 BR.markInvalid(
"Suppress Macro IDC", CurLC);
1714 const ExplodedNode *Origin;
1716 llvm::SmallSet<const CFGBlock *, 32> VisitedBlocks;
1719 TrackControlDependencyCondBRVisitor(
const ExplodedNode *O)
1720 : Origin(O), ControlDeps(&O->getCFG()) {}
1722 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
1728 BugReporterContext &BRC,
1729 PathSensitiveBugReport &BR)
override;
1733 static std::shared_ptr<PathDiagnosticEventPiece>
1735 const ExplodedNode *N,
1736 BugReporterContext &BRC) {
1738 if (BRC.getAnalyzerOptions().AnalysisDiagOpt ==
PD_NONE ||
1739 !BRC.getAnalyzerOptions().ShouldTrackConditionsDebug)
1744 BRC.getSourceManager(),
1745 BRC.getASTContext().getLangOpts());
1747 return std::make_shared<PathDiagnosticEventPiece>(
1749 Cond, BRC.getSourceManager(), N->getLocationContext()),
1750 (Twine() +
"Tracking condition '" + ConditionText +
"'").str());
1778 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ElseCond))
1779 if (BinOp->isLogicalOp())
1786 TrackControlDependencyCondBRVisitor::VisitNode(
const ExplodedNode *N,
1787 BugReporterContext &BRC,
1788 PathSensitiveBugReport &BR) {
1790 if (Origin->getStackFrame() != N->getStackFrame())
1796 if (!VisitedBlocks.insert(NB).second)
1802 if (!OriginB || !NB)
1808 if (ControlDeps.isControlDependent(OriginB, NB)) {
1818 if (BR.addTrackedCondition(N)) {
1819 bugreporter::trackExpressionValue(
1820 N, Condition, BR, bugreporter::TrackingKind::Condition,
1835 const ExplodedNode *N) {
1836 if (
const auto *DR = dyn_cast<DeclRefExpr>(E)) {
1837 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1838 if (!VD->getType()->isReferenceType())
1840 ProgramStateManager &StateMgr = N->getState()->getStateManager();
1841 MemRegionManager &MRMgr = StateMgr.getRegionManager();
1842 return MRMgr.getVarRegion(VD, N->getLocationContext());
1857 static const Expr *peelOffOuterExpr(
const Expr *Ex,
1858 const ExplodedNode *N) {
1860 if (
const auto *FE = dyn_cast<FullExpr>(Ex))
1861 return peelOffOuterExpr(FE->getSubExpr(), N);
1862 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
1863 return peelOffOuterExpr(OVE->getSourceExpr(), N);
1864 if (
const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
1866 if (PropRef && PropRef->isMessagingGetter()) {
1867 const Expr *GetterMessageSend =
1868 POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
1870 return peelOffOuterExpr(GetterMessageSend, N);
1875 if (
const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
1878 const ExplodedNode *NI = N;
1882 const CFGBlock *srcBlk = BE->getSrc();
1885 bool TookTrueBranch = (*(srcBlk->
succ_begin()) == BE->getDst());
1887 return peelOffOuterExpr(CO->getTrueExpr(), N);
1889 return peelOffOuterExpr(CO->getFalseExpr(), N);
1893 NI = NI->getFirstPred();
1897 if (
auto *BO = dyn_cast<BinaryOperator>(Ex))
1899 return peelOffOuterExpr(SubEx, N);
1901 if (
auto *UO = dyn_cast<UnaryOperator>(Ex)) {
1902 if (UO->getOpcode() == UO_LNot)
1903 return peelOffOuterExpr(UO->getSubExpr(), N);
1913 if (UO->getOpcode() == UO_AddrOf && UO->getSubExpr()->isLValue())
1914 if (
const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr()))
1915 return peelOffOuterExpr(DerefEx, N);
1923 static const ExplodedNode* findNodeForExpression(
const ExplodedNode *N,
1924 const Expr *Inner) {
1926 if (N->getStmtForDiagnostics() == Inner)
1928 N = N->getFirstPred();
1933 bool bugreporter::trackExpressionValue(
const ExplodedNode *InputNode,
1935 PathSensitiveBugReport &report,
1936 bugreporter::TrackingKind TKind,
1937 bool EnableNullFPSuppression) {
1939 if (!E || !InputNode)
1942 const Expr *Inner = peelOffOuterExpr(E, InputNode);
1943 const ExplodedNode *LVNode = findNodeForExpression(InputNode, Inner);
1955 if (LVState->getAnalysisManager().getAnalyzerOptions().ShouldTrackConditions)
1956 report.addVisitor(std::make_unique<TrackControlDependencyCondBRVisitor>(
1962 if (
const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
1963 trackExpressionValue(
1964 LVNode, Receiver, report, TKind, EnableNullFPSuppression);
1967 if (
const auto *Arr = dyn_cast<ArraySubscriptExpr>(Inner))
1968 trackExpressionValue(
1969 LVNode, Arr->getIdx(), report, TKind,
false);
1974 SVal LVal = LVNode->getSVal(Inner);
1977 bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
1982 if (RR && !LVIsNull)
1983 if (
auto KV = LVal.getAs<KnownSVal>())
1984 report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
1985 *KV, RR, EnableNullFPSuppression, TKind, SFC));
1991 const MemRegion *R = (RR && LVIsNull) ? RR :
1992 LVNode->getSVal(Inner).getAsRegion();
1997 SVal
V = LVState->getRawSVal(loc::MemRegionVal(R));
1999 std::make_unique<NoStoreFuncVisitor>(cast<SubRegion>(R), TKind));
2001 MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
2002 LVNode, R, EnableNullFPSuppression, report, V);
2004 report.markInteresting(V, TKind);
2005 report.addVisitor(std::make_unique<UndefOrNullArgVisitor>(R));
2008 if (V.getAsLocSymbol(
true))
2009 if (LVState->isNull(V).isConstrainedTrue())
2010 report.addVisitor(std::make_unique<TrackConstraintBRVisitor>(
2011 V.castAs<DefinedSVal>(),
false));
2014 if (
auto DV = V.getAs<DefinedSVal>())
2015 if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() &&
2016 EnableNullFPSuppression)
2018 std::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV,
2021 if (
auto KV = V.getAs<KnownSVal>())
2022 report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
2023 *KV, R, EnableNullFPSuppression, TKind, SFC));
2030 SVal
V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
2032 ReturnVisitor::addVisitorIfNecessary(
2033 LVNode, Inner, report, EnableNullFPSuppression, TKind);
2036 if (
auto L = V.getAs<loc::MemRegionVal>()) {
2041 bool CanDereference =
true;
2042 if (
const auto *SR = L->getRegionAs<SymbolicRegion>()) {
2043 if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
2044 CanDereference =
false;
2045 }
else if (L->getRegionAs<AllocaRegion>())
2046 CanDereference =
false;
2053 RVal = LVState->getRawSVal(L.getValue(), Inner->
getType());
2054 else if (CanDereference)
2055 RVal = LVState->getSVal(L->getRegion());
2057 if (CanDereference) {
2059 std::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
2061 if (
auto KV = RVal.getAs<KnownSVal>())
2062 report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
2063 *KV, L->getRegion(), EnableNullFPSuppression, TKind, SFC));
2066 const MemRegion *RegionRVal = RVal.getAsRegion();
2067 if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
2068 report.markInteresting(RegionRVal, TKind);
2069 report.addVisitor(std::make_unique<TrackConstraintBRVisitor>(
2070 loc::MemRegionVal(RegionRVal),
false));
2080 const Expr *NilReceiverBRVisitor::getNilReceiver(
const Stmt *S,
2081 const ExplodedNode *N) {
2085 if (
const Expr *Receiver = ME->getInstanceReceiver()) {
2087 SVal
V = N->getSVal(Receiver);
2088 if (state->isNull(V).isConstrainedTrue())
2095 NilReceiverBRVisitor::VisitNode(
const ExplodedNode *N, BugReporterContext &BRC,
2096 PathSensitiveBugReport &BR) {
2101 const Stmt *S = P->getStmt();
2102 const Expr *Receiver = getNilReceiver(S, N);
2107 llvm::raw_svector_ostream
OS(Buf);
2109 if (
const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
2111 ME->getSelector().print(OS);
2112 OS <<
"' not called";
2115 OS <<
"No method is called";
2117 OS <<
" because the receiver is nil";
2122 bugreporter::trackExpressionValue(
2123 N, Receiver, BR, bugreporter::TrackingKind::Thorough,
2126 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
2127 N->getLocationContext());
2128 return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
2137 const char *ConditionBRVisitor::getTag() {
return "ConditionBRVisitor"; }
2140 ConditionBRVisitor::VisitNode(
const ExplodedNode *N, BugReporterContext &BRC,
2141 PathSensitiveBugReport &BR) {
2142 auto piece = VisitNodeImpl(N, BRC, BR);
2144 piece->setTag(getTag());
2145 if (
auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
2146 ev->setPrunable(
true,
false);
2152 ConditionBRVisitor::VisitNodeImpl(
const ExplodedNode *N,
2153 BugReporterContext &BRC,
2154 PathSensitiveBugReport &BR) {
2156 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &Tags =
2162 const CFGBlock *SrcBlock = BE->getSrc();
2169 N->getFirstPred()->getLocation().getTag();
2170 if (PreviousNodeTag == Tags.first || PreviousNodeTag == Tags.second)
2173 return VisitTerminator(Term, N, SrcBlock, BE->getDst(), BR, BRC);
2180 if (CurrentNodeTag != Tags.first && CurrentNodeTag != Tags.second)
2183 bool TookTrue = CurrentNodeTag == Tags.first;
2184 return VisitTrueTest(cast<Expr>(PS->getStmt()), BRC, BR, N, TookTrue);
2191 const Stmt *Term,
const ExplodedNode *N,
const CFGBlock *srcBlk,
2192 const CFGBlock *dstBlk, PathSensitiveBugReport &R,
2193 BugReporterContext &BRC) {
2194 const Expr *Cond =
nullptr;
2214 case Stmt::IfStmtClass:
2215 Cond = cast<IfStmt>(Term)->getCond();
2217 case Stmt::ConditionalOperatorClass:
2218 Cond = cast<ConditionalOperator>(Term)->getCond();
2220 case Stmt::BinaryOperatorClass:
2224 const auto *BO = cast<BinaryOperator>(Term);
2225 assert(BO->isLogicalOp() &&
2226 "CFG terminator is not a short-circuit operator!");
2227 Cond = BO->getLHS();
2236 while (
const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
2237 if (!InnerBO->isLogicalOp())
2244 const bool TookTrue = *(srcBlk->
succ_begin()) == dstBlk;
2245 return VisitTrueTest(Cond, BRC, R, N, TookTrue);
2249 ConditionBRVisitor::VisitTrueTest(
const Expr *Cond, BugReporterContext &BRC,
2250 PathSensitiveBugReport &R,
2251 const ExplodedNode *N,
bool TookTrue) {
2261 !BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) ||
2262 CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef();
2266 const Expr *CondTmp = Cond;
2267 bool TookTrueTmp = TookTrue;
2274 case Stmt::BinaryOperatorClass:
2275 if (
auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
2276 BRC, R, N, TookTrueTmp, IsAssuming))
2279 case Stmt::DeclRefExprClass:
2280 if (
auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
2281 BRC, R, N, TookTrueTmp, IsAssuming))
2284 case Stmt::MemberExprClass:
2285 if (
auto P = VisitTrueTest(Cond, cast<MemberExpr>(CondTmp),
2286 BRC, R, N, TookTrueTmp, IsAssuming))
2289 case Stmt::UnaryOperatorClass: {
2290 const auto *UO = cast<UnaryOperator>(CondTmp);
2291 if (UO->getOpcode() == UO_LNot) {
2292 TookTrueTmp = !TookTrueTmp;
2293 CondTmp = UO->getSubExpr();
2309 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2310 if (!Loc.isValid() || !Loc.asLocation().isValid())
2313 return std::make_shared<PathDiagnosticEventPiece>(
2314 Loc, TookTrue ? GenericTrueMessage : GenericFalseMessage);
2317 bool ConditionBRVisitor::patternMatch(
const Expr *Ex,
2318 const Expr *ParentEx,
2320 BugReporterContext &BRC,
2321 PathSensitiveBugReport &report,
2322 const ExplodedNode *N,
2324 bool IsSameFieldName) {
2325 const Expr *OriginalExpr = Ex;
2328 if (isa<GNUNullExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
2329 isa<CXXBoolLiteralExpr>(Ex) || isa<IntegerLiteral>(Ex) ||
2330 isa<FloatingLiteral>(Ex)) {
2337 const LangOptions &LO = BRC.getASTContext().getLangOpts();
2347 if (
const auto *DR = dyn_cast<DeclRefExpr>(Ex)) {
2348 const bool quotes = isa<VarDecl>(DR->getDecl());
2352 const ProgramState *
state = N->getState().get();
2353 if (
const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
2354 LCtx).getAsRegion()) {
2355 if (report.isInteresting(R))
2358 const ProgramState *state = N->getState().get();
2359 SVal
V = state->getSVal(R);
2360 if (report.isInteresting(V))
2365 Out << DR->getDecl()->getDeclName().getAsString();
2371 if (
const auto *IL = dyn_cast<IntegerLiteral>(Ex)) {
2374 if (IL->getValue() == 0) {
2380 if (IL->getValue() == 0) {
2386 Out << IL->getValue();
2390 if (
const auto *ME = dyn_cast<MemberExpr>(Ex)) {
2391 if (!IsSameFieldName)
2392 Out <<
"field '" << ME->getMemberDecl()->getName() <<
'\'';
2397 BRC.getSourceManager(), BRC.getASTContext().getLangOpts(), 0)
2406 PathSensitiveBugReport &R,
const ExplodedNode *N,
bool TookTrue,
2408 bool shouldInvert =
false;
2413 bool IsSameFieldName =
false;
2423 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
2424 const bool isVarLHS = patternMatch(BExpr->
getLHS(), BExpr, OutLHS, BRC, R,
2425 N, shouldPrune, IsSameFieldName);
2426 const bool isVarRHS = patternMatch(BExpr->
getRHS(), BExpr, OutRHS, BRC, R,
2427 N, shouldPrune, IsSameFieldName);
2429 shouldInvert = !isVarLHS && isVarRHS;
2437 return VisitConditionVariable(LhsString, BExpr->
getLHS(), BRC, R, N,
2443 if (LhsString.empty() || RhsString.empty() ||
2449 llvm::raw_svector_ostream Out(buf);
2450 Out << (IsAssuming ?
"Assuming " :
"")
2451 << (shouldInvert ? RhsString : LhsString) <<
" is ";
2457 case BO_LT: Op = BO_GT;
break;
2458 case BO_GT: Op = BO_LT;
break;
2459 case BO_LE: Op = BO_GE;
break;
2460 case BO_GE: Op = BO_LE;
break;
2465 case BO_EQ: Op = BO_NE;
break;
2466 case BO_NE: Op = BO_EQ;
break;
2467 case BO_LT: Op = BO_GE;
break;
2468 case BO_GT: Op = BO_LE;
break;
2469 case BO_LE: Op = BO_GT;
break;
2470 case BO_GE: Op = BO_LT;
break;
2480 Out <<
"not equal to ";
2487 Out << (shouldInvert ? LhsString : RhsString);
2496 std::string Message = Out.str();
2497 Message[0] = toupper(Message[0]);
2501 PathDiagnosticLocation Loc;
2502 if (!shouldInvert) {
2503 if (LhsME && LhsME->getMemberLoc().isValid())
2504 Loc = PathDiagnosticLocation(LhsME->getMemberLoc(),
SM);
2506 Loc = PathDiagnosticLocation(BExpr->
getLHS(),
SM, LCtx);
2508 if (RhsME && RhsME->getMemberLoc().isValid())
2509 Loc = PathDiagnosticLocation(RhsME->getMemberLoc(),
SM);
2511 Loc = PathDiagnosticLocation(BExpr->
getRHS(),
SM, LCtx);
2514 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Message);
2517 PathDiagnosticLocation Loc(Cond, SM, LCtx);
2518 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Message);
2519 if (shouldPrune.hasValue())
2520 event->setPrunable(shouldPrune.getValue());
2525 StringRef LhsString,
const Expr *CondVarExpr, BugReporterContext &BRC,
2526 PathSensitiveBugReport &report,
const ExplodedNode *N,
bool TookTrue) {
2531 llvm::raw_svector_ostream Out(buf);
2532 Out <<
"Assuming " << LhsString <<
" is ";
2534 if (!printValue(CondVarExpr, Out, N, TookTrue,
true))
2538 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
2543 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2546 event->setPrunable(
false);
2553 PathSensitiveBugReport &report,
const ExplodedNode *N,
bool TookTrue,
2560 llvm::raw_svector_ostream Out(Buf);
2562 Out << (IsAssuming ?
"Assuming '" :
"'") << VD->getDeclName() <<
"' is ";
2564 if (!printValue(DRE, Out, N, TookTrue, IsAssuming))
2574 PathDiagnosticLocation Loc(DRE, BRC.getSourceManager(), LCtx);
2575 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2578 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2579 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2582 event->setPrunable(
false);
2584 return std::move(event);
2589 PathSensitiveBugReport &report,
const ExplodedNode *N,
bool TookTrue,
2592 llvm::raw_svector_ostream Out(Buf);
2594 Out << (IsAssuming ?
"Assuming field '" :
"Field '")
2597 if (!printValue(ME, Out, N, TookTrue, IsAssuming))
2601 PathDiagnosticLocation Loc;
2605 Loc = PathDiagnosticLocation(ME->
getMemberLoc(), BRC.getSourceManager());
2607 Loc = PathDiagnosticLocation(Cond, BRC.getSourceManager(), LCtx);
2609 if (!Loc.isValid() || !Loc.asLocation().isValid())
2617 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2619 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2621 event->setPrunable(
false);
2625 bool ConditionBRVisitor::printValue(
const Expr *CondVarExpr, raw_ostream &Out,
2626 const ExplodedNode *N,
bool TookTrue,
2631 Out << (TookTrue ?
"non-null" :
"null");
2636 Out << (TookTrue ?
"non-nil" :
"nil");
2647 if (IsAssuming || !IntValue.hasValue()) {
2649 Out << (TookTrue ?
"true" :
"false");
2651 Out << (TookTrue ?
"not equal to 0" :
"0");
2654 Out << (IntValue.getValue()->getBoolValue() ?
"true" :
"false");
2656 Out << *IntValue.getValue();
2662 constexpr llvm::StringLiteral ConditionBRVisitor::GenericTrueMessage;
2663 constexpr llvm::StringLiteral ConditionBRVisitor::GenericFalseMessage;
2665 bool ConditionBRVisitor::isPieceMessageGeneric(
2666 const PathDiagnosticPiece *Piece) {
2667 return Piece->getString() == GenericTrueMessage ||
2668 Piece->getString() == GenericFalseMessage;
2675 void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
2676 BugReporterContext &BRC,
const ExplodedNode *N,
2677 PathSensitiveBugReport &BR) {
2681 const Decl *D = N->getLocationContext()->getDecl();
2688 if (Options.ShouldSuppressFromCXXStandardLibrary) {
2689 BR.markInvalid(getTag(),
nullptr);
2698 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
2700 if (CD->
getName() ==
"list") {
2701 BR.markInvalid(getTag(),
nullptr);
2708 if (
const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
2710 if (CD->
getName() ==
"__independent_bits_engine") {
2711 BR.markInvalid(getTag(),
nullptr);
2729 if (CD->
getName() ==
"basic_string") {
2730 BR.markInvalid(getTag(),
nullptr);
2737 if (CD->
getName() ==
"shared_ptr") {
2738 BR.markInvalid(getTag(),
nullptr);
2751 if (SM.
getFilename(Loc).endswith(
"sys/queue.h")) {
2752 BR.markInvalid(getTag(),
nullptr);
2763 UndefOrNullArgVisitor::VisitNode(
const ExplodedNode *N, BugReporterContext &BRC,
2764 PathSensitiveBugReport &BR) {
2775 CallEventRef<> Call = CEMgr.
getCaller(CEnter->getCalleeContext(),
State);
2779 for (
const auto ParamDecl : parms) {
2780 const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
2784 if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts()))
2788 assert(ParamDecl &&
"Formal parameter has no decl?");
2803 SVal BoundVal = State->getSVal(R);
2804 if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
2805 BR.markInteresting(CEnter->getCalleeContext());
2816 FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor()
2817 : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {}
2819 void FalsePositiveRefutationBRVisitor::finalizeVisitor(
2820 BugReporterContext &BRC,
const ExplodedNode *EndPathNode,
2821 PathSensitiveBugReport &BR) {
2823 VisitNode(EndPathNode, BRC, BR);
2826 llvm::SMTSolverRef RefutationSolver = llvm::CreateZ3Solver();
2830 for (
const auto &I : Constraints) {
2832 auto RangeIt = I.second.begin();
2835 RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
2837 while ((++RangeIt) != I.second.end()) {
2838 Constraints = RefutationSolver->mkOr(
2840 RangeIt->From(), RangeIt->To(),
2844 RefutationSolver->addConstraint(Constraints);
2849 if (!isSat.hasValue())
2852 if (!isSat.getValue())
2853 BR.markInvalid(
"Infeasible constraints", EndPathNode->getLocationContext());
2857 const ExplodedNode *N, BugReporterContext &, PathSensitiveBugReport &) {
2860 ConstraintRangeTy::Factory &
CF =
2861 N->getState()->get_context<ConstraintRange>();
2864 for (
auto const &C : NewCs) {
2866 if (!Constraints.contains(Sym)) {
2867 Constraints = CF.add(Constraints, Sym, C.second);
2874 void FalsePositiveRefutationBRVisitor::Profile(
2875 llvm::FoldingSetNodeID &
ID)
const {
2877 ID.AddPointer(&Tag);
2884 int NoteTag::Kind = 0;
2886 void TagVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
2888 ID.AddPointer(&Tag);
2892 BugReporterContext &BRC,
2893 PathSensitiveBugReport &R) {
2895 const NoteTag *T = dyn_cast_or_null<NoteTag>(PP.
getTag());
2900 PathDiagnosticLocation Loc =
2902 auto Piece = std::make_shared<PathDiagnosticEventPiece>(Loc, *Msg);
2903 Piece->setPrunable(T->isPrunable());
ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC property.
Indicates that the tracked object is a CF object.
Defines the clang::ASTContext interface.
static ArrayRef< ParmVarDecl * > getCallParameters(CallEventRef<> Call)
Get parameters associated with runtime definition in order to get the correct parameter name...
This is a discriminated union of FileInfo and ExpansionInfo.
A (possibly-)qualified type.
static bool isPointerToConst(QualType Ty)
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
static StringRef getMacroName(SourceLocation Loc, BugReporterContext &BRC)
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
succ_iterator succ_begin()
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
static llvm::StringLiteral WillBeUsedForACondition
Stmt - This represents one statement.
internal::Matcher< Stmt > StatementMatcher
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher< Decl >, void(internal::HasDeclarationSupportedTypes)> hasDeclaration(const internal::Matcher< Decl > &InnerMatcher)
Matches a node if the declaration associated with that node matches the given matcher.
C Language Family Type Representation.
Defines the SourceManager interface.
static CharSourceRange getTokenRange(SourceRange R)
Decl - This represents one declaration (or definition), e.g.
Represents a point when we begin processing an inlined call.
Manages the lifetime of CallEvent objects.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher. ...
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded...
llvm::ImmutableMap< SymbolRef, RangeSet > ConstraintRangeTy
unsigned succ_size() const
static bool isAtStartOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroBegin=nullptr)
Returns true if the given MacroID location points at the first token of the macro expansion...
Represents a variable declaration or definition.
const internal::VariadicDynCastAllOfMatcher< Stmt, BinaryOperator > binaryOperator
Matches binary operator expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, ObjCIvarRefExpr > objcIvarRefExpr
Matches a reference to an ObjCIvar.
Describes how types, statements, expressions, and declarations should be printed. ...
Represents a parameter to a function.
Defines the clang::Expr interface and subclasses for C++ expressions.
bool isParentOf(const LocationContext *LC) const
Represents a struct/union/class.
const SymExpr * SymbolRef
SourceLocation getBegin() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
field_range fields() const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a member of a struct/union/class.
Represents a program point after a store evaluation.
bool isReferenceType() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
bool isAssignmentOp() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Represents a point when we start the call exit sequence (for inlined call).
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
StringRef getOpcodeStr() const
static bool isInStdNamespace(const Decl *D)
Returns true if the root namespace of the given declaration is the 'std' C++ namespace.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
const LocationContext * getParent() const
A builtin binary operation expression such as "x + y" or "x <= y".
static bool wasRegionOfInterestModifiedAt(const SubRegion *RegionOfInterest, const ExplodedNode *N, SVal ValueAfter)
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
static const Expr * peelOffPointerArithmetic(const BinaryOperator *B)
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
static const MemRegion * getLocationRegionIfReference(const Expr *E, const ExplodedNode *N)
static Optional< const llvm::APSInt * > getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N)
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
static bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal, const ExplodedNode *RightNode, SVal RightVal)
Comparing internal representations of symbolic values (via SVal::operator==()) is a valid way to chec...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
static bool isAssertlikeBlock(const CFGBlock *B, ASTContext &Context)
const Stmt * getCallSite() const
Represents a single basic block in a source-level CFG.
static bool potentiallyWritesIntoIvar(const Decl *Parent, const ObjCIvarDecl *Ivar)
Represents a point when we finish the call exit sequence (for inlined call).
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroEnd=nullptr)
Returns true if the given MacroID location points at the last token of the macro expansion.
This represents one expression.
Stmt * getTerminatorCondition(bool StripParens=true)
static Optional< SVal > getSValForVar(const Expr *CondVarExpr, const ExplodedNode *N)
Represents a character-granular source range.
CFGBlock * getBlock(Stmt *S)
Returns the CFGBlock the specified Stmt* appears in.
const Expr * getLastCondition() const
CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)
Gets an outside caller given a callee context.
bool inTopFrame() const override
Return true if the current LocationContext has no caller context.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
static std::pair< const ProgramPointTag *, const ProgramPointTag * > geteagerlyAssumeBinOpBifurcationTags()
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
An expression that sends a message to the given Objective-C object or class.
SourceLocation getMemberLoc() const
getMemberLoc - Return the location of the "member", in X->F, it is the location of 'F'...
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const ExpansionInfo & getExpansion() const
SourceLocation getEndLoc() const LLVM_READONLY
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
bool isConstQualified() const
Determine whether this type is const-qualified.
bool isComparisonOp() const
Maps string IDs to AST nodes matched by parts of a matcher.
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
QualType getCanonicalType() const
Encodes a location in the source.
static std::shared_ptr< PathDiagnosticEventPiece > constructDebugPieceForTrackedCondition(const Expr *Cond, const ExplodedNode *N, BugReporterContext &BRC)
static bool isCallStmt(const Stmt *S)
Returns true if this is a statement is a function or method call of some kind.
static bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
ProgramPoints can be "tagged" as representing points specific to a given analysis entity...
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
ASTContext & getASTContext() const LLVM_READONLY
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Represents a static or instance method of a struct/union/class.
bool isAnyPointerType() const
bool isObjCObjectPointerType() const
static void showBRDiagnostics(const char *action, llvm::raw_svector_ostream &os, const MemRegion *R, SVal V, const DeclStmt *DS)
Show diagnostics for initializing or declaring a region R with a bad value.
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
static bool isFunctionMacroExpansion(SourceLocation Loc, const SourceManager &SM)
ast_type_traits::DynTypedNode Node
bool isInevitablySinking() const
Returns true if the block would eventually end with a sink (a noreturn node).
Dataflow Directional Tag Classes.
static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &os, const MemRegion *R, SVal V)
Show default diagnostics for storing bad region.
bool isValid() const
Return true if this is a valid SourceLocation object.
Parameter for Objective-C 'self' argument.
static bool isVarAnInterestingCondition(const Expr *CondVarExpr, const ExplodedNode *N, const PathSensitiveBugReport *B)
StmtClass getStmtClass() const
bool isBooleanType() const
const Decl * getSingleDecl() const
const ProgramPointTag * getTag() const
Stmt * getTerminatorStmt()
static void showBRParamDiagnostics(llvm::raw_svector_ostream &os, const VarRegion *VR, SVal V)
Display diagnostics for passing bad region as a parameter.
static bool isInterestingExpr(const Expr *E, const ExplodedNode *N, const PathSensitiveBugReport *B)
static CharSourceRange getAsCharRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Given a token range, produce a corresponding CharSourceRange that is not a token range.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
const LocationContext * getLocationContext() const
static bool isAdditiveOp(Opcode Opc)
const StackFrameContext * getStackFrame() const
Stores options for the analyzer from the command line.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
ObjCIvarRefExpr - A reference to an ObjC instance variable.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Defines the clang::SourceLocation class and associated facilities.
Represents a C++ struct/union/class.
ObjCIvarDecl - Represents an ObjC instance variable.
static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR)
Returns true if N represents the DeclStmt declaring and initializing VR.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
FullSourceLoc getSpellingLoc() const
A SourceLocation and its associated SourceManager.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A reference to a declared variable, function, enum, etc.
bool isFunctionMacroExpansion() const
bool isPointerType() const
A trivial tuple used to represent a source range.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
static bool isInterestingLValueExpr(const Expr *Ex)
Returns true if nodes for the given expression kind are always kept around.
This class handles loading and caching of source files into memory.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point...
static llvm::SMTExprRef getRangeExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)