Index: clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -345,12 +345,10 @@ namespace bugreporter { -/// Attempts to add visitors to trace a null or undefined value back to its -/// point of origin, whether it is a symbol constrained to null or an explicit -/// assignment. -/// +/// Attempts to add visitors to track expression back to its point of origin. +///// /// \param N A node "downstream" from the evaluation of the statement. -/// \param S The statement whose value is null or undefined. +/// \param E The expression which we are finding /// \param R The bug report to which visitors should be attached. /// \param EnableNullFPSuppression Whether we should employ false positive /// suppression (inlined defensive checks, returned null). @@ -358,11 +356,11 @@ /// \return Whether or not the function was able to add visitors for this /// statement. Note that returning \c true does not actually imply /// that any visitors were added. -bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, - bool EnableNullFPSuppression = true); +bool trackExpression(const ExplodedNode *N, const Expr *E, BugReport &R, + bool EnableNullFPSuppression = true); const Expr *getDerefExpr(const Stmt *S); -const Stmt *GetDenomExpr(const ExplodedNode *N); +const Expr *GetDenomExpr(const ExplodedNode *N); const Stmt *GetRetValExpr(const ExplodedNode *N); bool isDeclRefExprToReference(const Expr *E); Index: clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -214,7 +214,7 @@ auto R = llvm::make_unique(*BT, Msg, N); R->addRange(Range); - bugreporter::trackNullOrUndefValue(N, E, *R); + bugreporter::trackExpression(N, E, *R); C.emitReport(std::move(R)); } @@ -578,7 +578,7 @@ auto report = llvm::make_unique(BT, OS.str(), N); report->addRange(Call.getArgSourceRange(0)); - bugreporter::trackNullOrUndefValue(N, Call.getArgExpr(0), *report); + bugreporter::trackExpression(N, Call.getArgExpr(0), *report); C.emitReport(std::move(report)); return; } Index: clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -553,7 +553,8 @@ BuiltinBug *BT = static_cast(BT_Null.get()); auto Report = llvm::make_unique(*BT, WarningMsg, N); Report->addRange(S->getSourceRange()); - bugreporter::trackNullOrUndefValue(N, S, *Report); + if (const auto *Ex = dyn_cast(S)) + bugreporter::trackExpression(N, Ex, *Report); C.emitReport(std::move(Report)); } } Index: clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -108,7 +108,7 @@ R->addRange(BadE->getSourceRange()); if (BadE->isGLValue()) BadE = bugreporter::getDerefExpr(BadE); - bugreporter::trackNullOrUndefValue(N, BadE, *R); + bugreporter::trackExpression(N, BadE, *R); } C.emitReport(std::move(R)); } @@ -186,7 +186,7 @@ auto R = llvm::make_unique(*BT, Os.str(), N); R->addRange(ArgRange); if (ArgEx) { - bugreporter::trackNullOrUndefValue(N, ArgEx, *R); + bugreporter::trackExpression(N, ArgEx, *R); } C.emitReport(std::move(R)); } @@ -262,7 +262,7 @@ R->addRange(ArgRange); if (ArgEx) - bugreporter::trackNullOrUndefValue(N, ArgEx, *R); + bugreporter::trackExpression(N, ArgEx, *R); C.emitReport(std::move(R)); } return true; @@ -305,7 +305,7 @@ R->addRange(ArgRange); if (ArgEx) - bugreporter::trackNullOrUndefValue(N, ArgEx, *R); + bugreporter::trackExpression(N, ArgEx, *R); // FIXME: enhance track back for uninitialized value for arbitrary // memregions C.emitReport(std::move(R)); @@ -365,7 +365,7 @@ Desc = "Argument to 'delete' is uninitialized"; BugType *BT = BT_cxx_delete_undef.get(); auto R = llvm::make_unique(*BT, Desc, N); - bugreporter::trackNullOrUndefValue(N, DE, *R); + bugreporter::trackExpression(N, DE, *R); C.emitReport(std::move(R)); return; } @@ -494,7 +494,7 @@ // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet. if (const Expr *ReceiverE = ME->getInstanceReceiver()) - bugreporter::trackNullOrUndefValue(N, ReceiverE, *R); + bugreporter::trackExpression(N, ReceiverE, *R); C.emitReport(std::move(R)); } return; @@ -535,7 +535,7 @@ report->addRange(ME->getReceiverRange()); // FIXME: This won't track "self" in messages to super. if (const Expr *receiver = ME->getInstanceReceiver()) { - bugreporter::trackNullOrUndefValue(N, receiver, *report); + bugreporter::trackExpression(N, receiver, *report); } C.emitReport(std::move(report)); } Index: clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -177,7 +177,7 @@ auto report = llvm::make_unique( *BT_null, buf.empty() ? BT_null->getDescription() : StringRef(buf), N); - bugreporter::trackNullOrUndefValue(N, bugreporter::getDerefExpr(S), *report); + bugreporter::trackExpression(N, bugreporter::getDerefExpr(S), *report); for (SmallVectorImpl::iterator I = Ranges.begin(), E = Ranges.end(); I!=E; ++I) @@ -197,8 +197,7 @@ auto report = llvm::make_unique(*BT_undef, BT_undef->getDescription(), N); - bugreporter::trackNullOrUndefValue(N, bugreporter::getDerefExpr(S), - *report); + bugreporter::trackExpression(N, bugreporter::getDerefExpr(S), *report); C.emitReport(std::move(report)); } return; Index: clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp @@ -41,7 +41,7 @@ auto R = llvm::make_unique(*BT, Msg, N); R->addVisitor(std::move(Visitor)); - bugreporter::trackNullOrUndefValue(N, bugreporter::GetDenomExpr(N), *R); + bugreporter::trackExpression(N, bugreporter::GetDenomExpr(N), *R); C.emitReport(std::move(R)); } } Index: clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp @@ -192,7 +192,7 @@ *BTAttrNonNull, "Null pointer passed as an argument to a 'nonnull' parameter", ErrorNode); if (ArgE) - bugreporter::trackNullOrUndefValue(ErrorNode, ArgE, *R); + bugreporter::trackExpression(ErrorNode, ArgE, *R); return R; } @@ -208,9 +208,7 @@ const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE); if (!ArgEDeref) ArgEDeref = ArgE; - bugreporter::trackNullOrUndefValue(ErrorNode, - ArgEDeref, - *R); + bugreporter::trackExpression(ErrorNode, ArgEDeref, *R); } return R; Index: clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp @@ -174,7 +174,8 @@ if (Error == ErrorKind::NilAssignedToNonnull || Error == ErrorKind::NilPassedToNonnull || Error == ErrorKind::NilReturnedToNonnull) - bugreporter::trackNullOrUndefValue(N, ValueExpr, *R); + if (const auto *Ex = dyn_cast(ValueExpr)) + bugreporter::trackExpression(N, Ex, *R); } BR.emitReport(std::move(R)); } Index: clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp @@ -49,7 +49,7 @@ "for @synchronized")); auto report = llvm::make_unique(*BT_undef, BT_undef->getDescription(), N); - bugreporter::trackNullOrUndefValue(N, Ex, *report); + bugreporter::trackExpression(N, Ex, *report); C.emitReport(std::move(report)); } return; @@ -73,7 +73,7 @@ "(no synchronization will occur)")); auto report = llvm::make_unique(*BT_null, BT_null->getDescription(), N); - bugreporter::trackNullOrUndefValue(N, Ex, *report); + bugreporter::trackExpression(N, Ex, *report); C.emitReport(std::move(report)); return; Index: clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp @@ -87,7 +87,7 @@ auto Report = llvm::make_unique(BT, BT.getDescription(), N); Report->addRange(RetE->getSourceRange()); - bugreporter::trackNullOrUndefValue(N, TrackingE ? TrackingE : RetE, *Report); + bugreporter::trackExpression(N, TrackingE ? TrackingE : RetE, *Report); C.emitReport(std::move(Report)); } Index: clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -98,7 +98,7 @@ // Emit the bug report. auto R = llvm::make_unique(*BT, BT->getDescription(), N); - bugreporter::trackNullOrUndefValue(N, Ex, *R); + bugreporter::trackExpression(N, Ex, *R); R->addRange(Ex->getSourceRange()); Ctx.emitReport(std::move(R)); Index: clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp @@ -174,10 +174,10 @@ auto report = llvm::make_unique(*BT, OS.str(), N); if (Ex) { report->addRange(Ex->getSourceRange()); - bugreporter::trackNullOrUndefValue(N, Ex, *report); + bugreporter::trackExpression(N, Ex, *report); } else - bugreporter::trackNullOrUndefValue(N, B, *report); + bugreporter::trackExpression(N, B, *report); C.emitReport(std::move(report)); } Index: clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp @@ -55,7 +55,7 @@ // Generate a report for this bug. auto R = llvm::make_unique(*BT, BT->getName(), N); R->addRange(A->getIdx()->getSourceRange()); - bugreporter::trackNullOrUndefValue(N, A->getIdx(), *R); + bugreporter::trackExpression(N, A->getIdx(), *R); C.emitReport(std::move(R)); } Index: clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp @@ -112,7 +112,7 @@ auto R = llvm::make_unique(*BT, OS.str(), N); if (ex) { R->addRange(ex->getSourceRange()); - bugreporter::trackNullOrUndefValue(N, ex, *R); + bugreporter::trackExpression(N, ex, *R); } C.emitReport(std::move(R)); } Index: clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -314,7 +314,7 @@ auto report = llvm::make_unique(*BT_mallocZero, os.str(), N); report->addRange(arg->getSourceRange()); - bugreporter::trackNullOrUndefValue(N, arg, *report); + bugreporter::trackExpression(N, arg, *report); C.emitReport(std::move(report)); return true; Index: clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -74,7 +74,7 @@ auto report = llvm::make_unique(*BT, os.str(), N); report->addVisitor(std::move(Visitor)); report->addRange(SizeE->getSourceRange()); - bugreporter::trackNullOrUndefValue(N, SizeE, *report); + bugreporter::trackExpression(N, SizeE, *report); C.emitReport(std::move(report)); } Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -160,7 +160,7 @@ return E; } -const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) { +const Expr *bugreporter::GetDenomExpr(const ExplodedNode *N) { const Stmt *S = N->getLocationAs()->getStmt(); if (const auto *BE = dyn_cast(S)) return BE->getRHS(); @@ -884,7 +884,7 @@ RetE = RetE->IgnoreParenCasts(); // If we're returning 0, we should track where that 0 came from. - bugreporter::trackNullOrUndefValue(N, RetE, BR, EnableNullFPSuppression); + bugreporter::trackExpression(N, RetE, BR, EnableNullFPSuppression); // Build an appropriate message based on the return value. SmallString<64> Msg; @@ -979,8 +979,7 @@ if (!State->isNull(*ArgV).isConstrainedTrue()) continue; - if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, - EnableNullFPSuppression)) + if (bugreporter::trackExpression(N, ArgE, BR, EnableNullFPSuppression)) ShouldInvalidate = false; // If we /can't/ track the null pointer, we should err on the side of @@ -1258,8 +1257,8 @@ V.getAs() || V.getAs()) { if (!IsParam) InitE = InitE->IgnoreParenCasts(); - bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, - EnableNullFPSuppression); + bugreporter::trackExpression(StoreSite, InitE, BR, + EnableNullFPSuppression); } ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(), BR, EnableNullFPSuppression); @@ -1588,14 +1587,14 @@ return N; } -bool bugreporter::trackNullOrUndefValue(const ExplodedNode *InputNode, - const Stmt *InputS, - BugReport &report, - bool EnableNullFPSuppression) { - if (!InputS || !InputNode || !isa(InputS)) +bool bugreporter::trackExpression(const ExplodedNode *InputNode, + const Expr *E, + BugReport &report, + bool EnableNullFPSuppression) { + if (!E || !InputNode) return false; - const Expr *Inner = peelOffOuterExpr(cast(InputS), InputNode); + const Expr *Inner = peelOffOuterExpr(E, InputNode); const ExplodedNode *LVNode = findNodeForExpression(InputNode, Inner); if (!LVNode) return false; @@ -1606,7 +1605,7 @@ // At this point in the path, the receiver should be live since we are at the // message send expr. If it is nil, start tracking it. if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode)) - trackNullOrUndefValue(LVNode, Receiver, report, EnableNullFPSuppression); + trackExpression(LVNode, Receiver, report, EnableNullFPSuppression); // See if the expression we're interested refers to a variable. // If so, we can track both its contents and constraints on its value. @@ -1751,8 +1750,8 @@ // The receiver was nil, and hence the method was skipped. // Register a BugReporterVisitor to issue a message telling us how // the receiver was null. - bugreporter::trackNullOrUndefValue(N, Receiver, BR, - /*EnableNullFPSuppression*/ false); + bugreporter::trackExpression(N, Receiver, BR, + /*EnableNullFPSuppression*/ false); // Issue a message saying that the method was skipped. PathDiagnosticLocation L(Receiver, BRC.getSourceManager(), N->getLocationContext());