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)
1611 void SuppressInlineDefensiveChecksVisitor::Profile(
1612 llvm::FoldingSetNodeID &
ID)
const {
1618 const char *SuppressInlineDefensiveChecksVisitor::getTag() {
1619 return "IDCVisitor";
1623 SuppressInlineDefensiveChecksVisitor::VisitNode(
const ExplodedNode *Succ,
1624 BugReporterContext &BRC,
1625 PathSensitiveBugReport &BR) {
1626 const ExplodedNode *Pred = Succ->getFirstPred();
1631 if (!IsTrackingTurnedOn)
1632 if (Succ->getState()->isNull(
V).isConstrainedTrue())
1633 IsTrackingTurnedOn =
true;
1634 if (!IsTrackingTurnedOn)
1639 if (!Pred->getState()->isNull(
V).isConstrainedTrue() &&
1640 Succ->getState()->isNull(
V).isConstrainedTrue()) {
1645 const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
1646 if (CurLC != ReportLC && !CurLC->
isParentOf(ReportLC)) {
1647 BR.markInvalid(
"Suppress IDC", CurLC);
1655 auto BugPoint = BR.getErrorNode()->getLocation().getAs<
StmtPoint>();
1661 const Stmt *CurTerminatorStmt =
nullptr;
1663 CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
1665 const Stmt *CurStmt = SP->getStmt();
1675 if (!CurTerminatorStmt)
1685 BR.markInvalid(
"Suppress Macro IDC", CurLC);
1710 const ExplodedNode *Origin;
1712 llvm::SmallSet<const CFGBlock *, 32> VisitedBlocks;
1715 TrackControlDependencyCondBRVisitor(
const ExplodedNode *O)
1716 : Origin(O), ControlDeps(&O->getCFG()) {}
1718 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
1724 BugReporterContext &BRC,
1725 PathSensitiveBugReport &BR)
override;
1729 static std::shared_ptr<PathDiagnosticEventPiece>
1731 const ExplodedNode *N,
1732 BugReporterContext &BRC) {
1734 if (BRC.getAnalyzerOptions().AnalysisDiagOpt ==
PD_NONE ||
1735 !BRC.getAnalyzerOptions().ShouldTrackConditionsDebug)
1740 BRC.getSourceManager(),
1741 BRC.getASTContext().getLangOpts());
1743 return std::make_shared<PathDiagnosticEventPiece>(
1745 Cond, BRC.getSourceManager(), N->getLocationContext()),
1746 (Twine() +
"Tracking condition '" + ConditionText +
"'").str());
1774 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ElseCond))
1775 if (BinOp->isLogicalOp())
1782 TrackControlDependencyCondBRVisitor::VisitNode(
const ExplodedNode *N,
1783 BugReporterContext &BRC,
1784 PathSensitiveBugReport &BR) {
1786 if (Origin->getStackFrame() != N->getStackFrame())
1792 if (!VisitedBlocks.insert(NB).second)
1798 if (!OriginB || !NB)
1804 if (ControlDeps.isControlDependent(OriginB, NB)) {
1814 if (BR.addTrackedCondition(N)) {
1815 bugreporter::trackExpressionValue(
1816 N, Condition, BR, bugreporter::TrackingKind::Condition,
1831 const ExplodedNode *N) {
1832 if (
const auto *DR = dyn_cast<DeclRefExpr>(E)) {
1833 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1834 if (!VD->getType()->isReferenceType())
1836 ProgramStateManager &StateMgr = N->getState()->getStateManager();
1837 MemRegionManager &MRMgr = StateMgr.getRegionManager();
1838 return MRMgr.getVarRegion(VD, N->getLocationContext());
1853 static const Expr *peelOffOuterExpr(
const Expr *Ex,
1854 const ExplodedNode *N) {
1856 if (
const auto *FE = dyn_cast<FullExpr>(Ex))
1857 return peelOffOuterExpr(FE->getSubExpr(), N);
1858 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
1859 return peelOffOuterExpr(OVE->getSourceExpr(), N);
1860 if (
const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
1862 if (PropRef && PropRef->isMessagingGetter()) {
1863 const Expr *GetterMessageSend =
1864 POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
1866 return peelOffOuterExpr(GetterMessageSend, N);
1871 if (
const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
1874 const ExplodedNode *NI = N;
1878 const CFGBlock *srcBlk = BE->getSrc();
1881 bool TookTrueBranch = (*(srcBlk->
succ_begin()) == BE->getDst());
1883 return peelOffOuterExpr(CO->getTrueExpr(), N);
1885 return peelOffOuterExpr(CO->getFalseExpr(), N);
1889 NI = NI->getFirstPred();
1893 if (
auto *BO = dyn_cast<BinaryOperator>(Ex))
1895 return peelOffOuterExpr(SubEx, N);
1897 if (
auto *UO = dyn_cast<UnaryOperator>(Ex)) {
1898 if (UO->getOpcode() == UO_LNot)
1899 return peelOffOuterExpr(UO->getSubExpr(), N);
1909 if (UO->getOpcode() == UO_AddrOf && UO->getSubExpr()->isLValue())
1910 if (
const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr()))
1911 return peelOffOuterExpr(DerefEx, N);
1919 static const ExplodedNode* findNodeForExpression(
const ExplodedNode *N,
1920 const Expr *Inner) {
1922 if (N->getStmtForDiagnostics() == Inner)
1924 N = N->getFirstPred();
1929 bool bugreporter::trackExpressionValue(
const ExplodedNode *InputNode,
1931 PathSensitiveBugReport &report,
1932 bugreporter::TrackingKind TKind,
1933 bool EnableNullFPSuppression) {
1935 if (!E || !InputNode)
1938 const Expr *Inner = peelOffOuterExpr(E, InputNode);
1939 const ExplodedNode *LVNode = findNodeForExpression(InputNode, Inner);
1951 if (LVState->getAnalysisManager().getAnalyzerOptions().ShouldTrackConditions)
1952 report.addVisitor(std::make_unique<TrackControlDependencyCondBRVisitor>(
1958 if (
const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
1959 trackExpressionValue(
1960 LVNode, Receiver, report, TKind, EnableNullFPSuppression);
1963 if (
const auto *Arr = dyn_cast<ArraySubscriptExpr>(Inner))
1964 trackExpressionValue(
1965 LVNode, Arr->getIdx(), report, TKind,
false);
1970 SVal LVal = LVNode->getSVal(Inner);
1973 bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
1978 if (RR && !LVIsNull)
1979 if (
auto KV = LVal.getAs<KnownSVal>())
1980 report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
1981 *KV, RR, EnableNullFPSuppression, TKind, SFC));
1987 const MemRegion *R = (RR && LVIsNull) ? RR :
1988 LVNode->getSVal(Inner).getAsRegion();
1993 SVal
V = LVState->getRawSVal(loc::MemRegionVal(R));
1995 std::make_unique<NoStoreFuncVisitor>(cast<SubRegion>(R), TKind));
1997 MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
1998 LVNode, R, EnableNullFPSuppression, report, V);
2000 report.markInteresting(V, TKind);
2001 report.addVisitor(std::make_unique<UndefOrNullArgVisitor>(R));
2004 if (V.getAsLocSymbol(
true))
2005 if (LVState->isNull(V).isConstrainedTrue())
2006 report.addVisitor(std::make_unique<TrackConstraintBRVisitor>(
2007 V.castAs<DefinedSVal>(),
false));
2010 if (
auto DV = V.getAs<DefinedSVal>())
2011 if (!DV->isZeroConstant() && EnableNullFPSuppression) {
2018 std::make_unique<SuppressInlineDefensiveChecksVisitor>(
2022 if (
auto KV = V.getAs<KnownSVal>())
2023 report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
2024 *KV, R, EnableNullFPSuppression, TKind, SFC));
2031 SVal
V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
2033 ReturnVisitor::addVisitorIfNecessary(
2034 LVNode, Inner, report, EnableNullFPSuppression, TKind);
2037 if (
auto L = V.getAs<loc::MemRegionVal>()) {
2042 bool CanDereference =
true;
2043 if (
const auto *SR = L->getRegionAs<SymbolicRegion>()) {
2044 if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
2045 CanDereference =
false;
2046 }
else if (L->getRegionAs<AllocaRegion>())
2047 CanDereference =
false;
2054 RVal = LVState->getRawSVal(L.getValue(), Inner->
getType());
2055 else if (CanDereference)
2056 RVal = LVState->getSVal(L->getRegion());
2058 if (CanDereference) {
2060 std::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
2062 if (
auto KV = RVal.getAs<KnownSVal>())
2063 report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
2064 *KV, L->getRegion(), EnableNullFPSuppression, TKind, SFC));
2067 const MemRegion *RegionRVal = RVal.getAsRegion();
2068 if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
2069 report.markInteresting(RegionRVal, TKind);
2070 report.addVisitor(std::make_unique<TrackConstraintBRVisitor>(
2071 loc::MemRegionVal(RegionRVal),
false));
2081 const Expr *NilReceiverBRVisitor::getNilReceiver(
const Stmt *S,
2082 const ExplodedNode *N) {
2086 if (
const Expr *Receiver = ME->getInstanceReceiver()) {
2088 SVal
V = N->getSVal(Receiver);
2089 if (state->isNull(V).isConstrainedTrue())
2096 NilReceiverBRVisitor::VisitNode(
const ExplodedNode *N, BugReporterContext &BRC,
2097 PathSensitiveBugReport &BR) {
2102 const Stmt *S = P->getStmt();
2103 const Expr *Receiver = getNilReceiver(S, N);
2108 llvm::raw_svector_ostream
OS(Buf);
2110 if (
const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
2112 ME->getSelector().print(OS);
2113 OS <<
"' not called";
2116 OS <<
"No method is called";
2118 OS <<
" because the receiver is nil";
2123 bugreporter::trackExpressionValue(
2124 N, Receiver, BR, bugreporter::TrackingKind::Thorough,
2127 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
2128 N->getLocationContext());
2129 return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
2138 const char *ConditionBRVisitor::getTag() {
return "ConditionBRVisitor"; }
2141 ConditionBRVisitor::VisitNode(
const ExplodedNode *N, BugReporterContext &BRC,
2142 PathSensitiveBugReport &BR) {
2143 auto piece = VisitNodeImpl(N, BRC, BR);
2145 piece->setTag(getTag());
2146 if (
auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
2147 ev->setPrunable(
true,
false);
2153 ConditionBRVisitor::VisitNodeImpl(
const ExplodedNode *N,
2154 BugReporterContext &BRC,
2155 PathSensitiveBugReport &BR) {
2157 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &Tags =
2163 const CFGBlock *SrcBlock = BE->getSrc();
2170 N->getFirstPred()->getLocation().getTag();
2171 if (PreviousNodeTag == Tags.first || PreviousNodeTag == Tags.second)
2174 return VisitTerminator(Term, N, SrcBlock, BE->getDst(), BR, BRC);
2181 if (CurrentNodeTag != Tags.first && CurrentNodeTag != Tags.second)
2184 bool TookTrue = CurrentNodeTag == Tags.first;
2185 return VisitTrueTest(cast<Expr>(PS->getStmt()), BRC, BR, N, TookTrue);
2192 const Stmt *Term,
const ExplodedNode *N,
const CFGBlock *srcBlk,
2193 const CFGBlock *dstBlk, PathSensitiveBugReport &R,
2194 BugReporterContext &BRC) {
2195 const Expr *Cond =
nullptr;
2215 case Stmt::IfStmtClass:
2216 Cond = cast<IfStmt>(Term)->getCond();
2218 case Stmt::ConditionalOperatorClass:
2219 Cond = cast<ConditionalOperator>(Term)->getCond();
2221 case Stmt::BinaryOperatorClass:
2225 const auto *BO = cast<BinaryOperator>(Term);
2226 assert(BO->isLogicalOp() &&
2227 "CFG terminator is not a short-circuit operator!");
2228 Cond = BO->getLHS();
2237 while (
const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
2238 if (!InnerBO->isLogicalOp())
2245 const bool TookTrue = *(srcBlk->
succ_begin()) == dstBlk;
2246 return VisitTrueTest(Cond, BRC, R, N, TookTrue);
2250 ConditionBRVisitor::VisitTrueTest(
const Expr *Cond, BugReporterContext &BRC,
2251 PathSensitiveBugReport &R,
2252 const ExplodedNode *N,
bool TookTrue) {
2262 !BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) ||
2263 CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef();
2267 const Expr *CondTmp = Cond;
2268 bool TookTrueTmp = TookTrue;
2275 case Stmt::BinaryOperatorClass:
2276 if (
auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
2277 BRC, R, N, TookTrueTmp, IsAssuming))
2280 case Stmt::DeclRefExprClass:
2281 if (
auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
2282 BRC, R, N, TookTrueTmp, IsAssuming))
2285 case Stmt::MemberExprClass:
2286 if (
auto P = VisitTrueTest(Cond, cast<MemberExpr>(CondTmp),
2287 BRC, R, N, TookTrueTmp, IsAssuming))
2290 case Stmt::UnaryOperatorClass: {
2291 const auto *UO = cast<UnaryOperator>(CondTmp);
2292 if (UO->getOpcode() == UO_LNot) {
2293 TookTrueTmp = !TookTrueTmp;
2294 CondTmp = UO->getSubExpr();
2310 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2311 if (!Loc.isValid() || !Loc.asLocation().isValid())
2314 return std::make_shared<PathDiagnosticEventPiece>(
2315 Loc, TookTrue ? GenericTrueMessage : GenericFalseMessage);
2318 bool ConditionBRVisitor::patternMatch(
const Expr *Ex,
2319 const Expr *ParentEx,
2321 BugReporterContext &BRC,
2322 PathSensitiveBugReport &report,
2323 const ExplodedNode *N,
2325 bool IsSameFieldName) {
2326 const Expr *OriginalExpr = Ex;
2329 if (isa<GNUNullExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
2330 isa<CXXBoolLiteralExpr>(Ex) || isa<IntegerLiteral>(Ex) ||
2331 isa<FloatingLiteral>(Ex)) {
2338 const LangOptions &LO = BRC.getASTContext().getLangOpts();
2348 if (
const auto *DR = dyn_cast<DeclRefExpr>(Ex)) {
2349 const bool quotes = isa<VarDecl>(DR->getDecl());
2353 const ProgramState *
state = N->getState().get();
2354 if (
const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
2355 LCtx).getAsRegion()) {
2356 if (report.isInteresting(R))
2359 const ProgramState *state = N->getState().get();
2360 SVal
V = state->getSVal(R);
2361 if (report.isInteresting(V))
2366 Out << DR->getDecl()->getDeclName().getAsString();
2372 if (
const auto *IL = dyn_cast<IntegerLiteral>(Ex)) {
2375 if (IL->getValue() == 0) {
2381 if (IL->getValue() == 0) {
2387 Out << IL->getValue();
2391 if (
const auto *ME = dyn_cast<MemberExpr>(Ex)) {
2392 if (!IsSameFieldName)
2393 Out <<
"field '" << ME->getMemberDecl()->getName() <<
'\'';
2398 BRC.getSourceManager(), BRC.getASTContext().getLangOpts(), 0)
2407 PathSensitiveBugReport &R,
const ExplodedNode *N,
bool TookTrue,
2409 bool shouldInvert =
false;
2414 bool IsSameFieldName =
false;
2424 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
2425 const bool isVarLHS = patternMatch(BExpr->
getLHS(), BExpr, OutLHS, BRC, R,
2426 N, shouldPrune, IsSameFieldName);
2427 const bool isVarRHS = patternMatch(BExpr->
getRHS(), BExpr, OutRHS, BRC, R,
2428 N, shouldPrune, IsSameFieldName);
2430 shouldInvert = !isVarLHS && isVarRHS;
2438 return VisitConditionVariable(LhsString, BExpr->
getLHS(), BRC, R, N,
2444 if (LhsString.empty() || RhsString.empty() ||
2450 llvm::raw_svector_ostream Out(buf);
2451 Out << (IsAssuming ?
"Assuming " :
"")
2452 << (shouldInvert ? RhsString : LhsString) <<
" is ";
2458 case BO_LT: Op = BO_GT;
break;
2459 case BO_GT: Op = BO_LT;
break;
2460 case BO_LE: Op = BO_GE;
break;
2461 case BO_GE: Op = BO_LE;
break;
2466 case BO_EQ: Op = BO_NE;
break;
2467 case BO_NE: Op = BO_EQ;
break;
2468 case BO_LT: Op = BO_GE;
break;
2469 case BO_GT: Op = BO_LE;
break;
2470 case BO_LE: Op = BO_GT;
break;
2471 case BO_GE: Op = BO_LT;
break;
2481 Out <<
"not equal to ";
2488 Out << (shouldInvert ? LhsString : RhsString);
2497 std::string Message = Out.str();
2498 Message[0] = toupper(Message[0]);
2502 PathDiagnosticLocation Loc;
2503 if (!shouldInvert) {
2504 if (LhsME && LhsME->getMemberLoc().isValid())
2505 Loc = PathDiagnosticLocation(LhsME->getMemberLoc(),
SM);
2507 Loc = PathDiagnosticLocation(BExpr->
getLHS(),
SM, LCtx);
2509 if (RhsME && RhsME->getMemberLoc().isValid())
2510 Loc = PathDiagnosticLocation(RhsME->getMemberLoc(),
SM);
2512 Loc = PathDiagnosticLocation(BExpr->
getRHS(),
SM, LCtx);
2515 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Message);
2518 PathDiagnosticLocation Loc(Cond, SM, LCtx);
2519 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Message);
2520 if (shouldPrune.hasValue())
2521 event->setPrunable(shouldPrune.getValue());
2526 StringRef LhsString,
const Expr *CondVarExpr, BugReporterContext &BRC,
2527 PathSensitiveBugReport &report,
const ExplodedNode *N,
bool TookTrue) {
2532 llvm::raw_svector_ostream Out(buf);
2533 Out <<
"Assuming " << LhsString <<
" is ";
2535 if (!printValue(CondVarExpr, Out, N, TookTrue,
true))
2539 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
2544 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2547 event->setPrunable(
false);
2554 PathSensitiveBugReport &report,
const ExplodedNode *N,
bool TookTrue,
2561 llvm::raw_svector_ostream Out(Buf);
2563 Out << (IsAssuming ?
"Assuming '" :
"'") << VD->getDeclName() <<
"' is ";
2565 if (!printValue(DRE, Out, N, TookTrue, IsAssuming))
2575 PathDiagnosticLocation Loc(DRE, BRC.getSourceManager(), LCtx);
2576 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2579 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2580 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2583 event->setPrunable(
false);
2585 return std::move(event);
2590 PathSensitiveBugReport &report,
const ExplodedNode *N,
bool TookTrue,
2593 llvm::raw_svector_ostream Out(Buf);
2595 Out << (IsAssuming ?
"Assuming field '" :
"Field '")
2598 if (!printValue(ME, Out, N, TookTrue, IsAssuming))
2602 PathDiagnosticLocation Loc;
2606 Loc = PathDiagnosticLocation(ME->
getMemberLoc(), BRC.getSourceManager());
2608 Loc = PathDiagnosticLocation(Cond, BRC.getSourceManager(), LCtx);
2610 if (!Loc.isValid() || !Loc.asLocation().isValid())
2618 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2620 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2622 event->setPrunable(
false);
2626 bool ConditionBRVisitor::printValue(
const Expr *CondVarExpr, raw_ostream &Out,
2627 const ExplodedNode *N,
bool TookTrue,
2632 Out << (TookTrue ?
"non-null" :
"null");
2637 Out << (TookTrue ?
"non-nil" :
"nil");
2648 if (IsAssuming || !IntValue.hasValue()) {
2650 Out << (TookTrue ?
"true" :
"false");
2652 Out << (TookTrue ?
"not equal to 0" :
"0");
2655 Out << (IntValue.getValue()->getBoolValue() ?
"true" :
"false");
2657 Out << *IntValue.getValue();
2663 constexpr llvm::StringLiteral ConditionBRVisitor::GenericTrueMessage;
2664 constexpr llvm::StringLiteral ConditionBRVisitor::GenericFalseMessage;
2666 bool ConditionBRVisitor::isPieceMessageGeneric(
2667 const PathDiagnosticPiece *Piece) {
2668 return Piece->getString() == GenericTrueMessage ||
2669 Piece->getString() == GenericFalseMessage;
2676 void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
2677 BugReporterContext &BRC,
const ExplodedNode *N,
2678 PathSensitiveBugReport &BR) {
2682 const Decl *D = N->getLocationContext()->getDecl();
2689 if (Options.ShouldSuppressFromCXXStandardLibrary) {
2690 BR.markInvalid(getTag(),
nullptr);
2699 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
2701 if (CD->
getName() ==
"list") {
2702 BR.markInvalid(getTag(),
nullptr);
2709 if (
const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
2711 if (CD->
getName() ==
"__independent_bits_engine") {
2712 BR.markInvalid(getTag(),
nullptr);
2730 if (CD->
getName() ==
"basic_string") {
2731 BR.markInvalid(getTag(),
nullptr);
2738 if (CD->
getName() ==
"shared_ptr") {
2739 BR.markInvalid(getTag(),
nullptr);
2752 if (SM.
getFilename(Loc).endswith(
"sys/queue.h")) {
2753 BR.markInvalid(getTag(),
nullptr);
2764 UndefOrNullArgVisitor::VisitNode(
const ExplodedNode *N, BugReporterContext &BRC,
2765 PathSensitiveBugReport &BR) {
2776 CallEventRef<> Call = CEMgr.
getCaller(CEnter->getCalleeContext(),
State);
2780 for (
const auto ParamDecl : parms) {
2781 const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
2785 if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts()))
2789 assert(ParamDecl &&
"Formal parameter has no decl?");
2804 SVal BoundVal = State->getSVal(R);
2805 if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
2806 BR.markInteresting(CEnter->getCalleeContext());
2817 FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor()
2818 : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {}
2820 void FalsePositiveRefutationBRVisitor::finalizeVisitor(
2821 BugReporterContext &BRC,
const ExplodedNode *EndPathNode,
2822 PathSensitiveBugReport &BR) {
2824 VisitNode(EndPathNode, BRC, BR);
2827 llvm::SMTSolverRef RefutationSolver = llvm::CreateZ3Solver();
2831 for (
const auto &I : Constraints) {
2833 auto RangeIt = I.second.begin();
2836 RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
2838 while ((++RangeIt) != I.second.end()) {
2839 Constraints = RefutationSolver->mkOr(
2841 RangeIt->From(), RangeIt->To(),
2845 RefutationSolver->addConstraint(Constraints);
2850 if (!isSat.hasValue())
2853 if (!isSat.getValue())
2854 BR.markInvalid(
"Infeasible constraints", EndPathNode->getLocationContext());
2858 const ExplodedNode *N, BugReporterContext &, PathSensitiveBugReport &) {
2861 ConstraintRangeTy::Factory &
CF =
2862 N->getState()->get_context<ConstraintRange>();
2865 for (
auto const &C : NewCs) {
2867 if (!Constraints.contains(Sym)) {
2868 Constraints = CF.add(Constraints, Sym, C.second);
2875 void FalsePositiveRefutationBRVisitor::Profile(
2876 llvm::FoldingSetNodeID &
ID)
const {
2878 ID.AddPointer(&Tag);
2885 int NoteTag::Kind = 0;
2887 void TagVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
2889 ID.AddPointer(&Tag);
2893 BugReporterContext &BRC,
2894 PathSensitiveBugReport &R) {
2896 const NoteTag *T = dyn_cast_or_null<NoteTag>(PP.
getTag());
2901 PathDiagnosticLocation Loc =
2903 auto Piece = std::make_shared<PathDiagnosticEventPiece>(Loc, *Msg);
2904 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()
CFGStmtMap * getCFGStmtMap()
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...
AnalysisDeclContext * getAnalysisDeclContext() const
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)