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 @@ -222,8 +222,8 @@ /// Visitor that tries to report interesting diagnostics from conditions. class ConditionBRVisitor final : public BugReporterVisitor { // FIXME: constexpr initialization isn't supported by MSVC2013. - static const char *const GenericTrueMessage; - static const char *const GenericFalseMessage; + static llvm::StringLiteral GenericTrueMessage; + static llvm::StringLiteral GenericFalseMessage; public: void Profile(llvm::FoldingSetNodeID &ID) const override { Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -180,21 +180,41 @@ RLCV->getStore() == RightNode->getState()->getStore(); } -static Optional -getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N) { +static Optional getSValForVar(const Expr *CondVarExpr, + const ExplodedNode *N) { ProgramStateRef State = N->getState(); const LocationContext *LCtx = N->getLocationContext(); + assert(CondVarExpr); + CondVarExpr = CondVarExpr->IgnoreImpCasts(); + // The declaration of the value may rely on a pointer so take its l-value. - if (const auto *DRE = dyn_cast_or_null(CondVarExpr)) { - if (const auto *VD = dyn_cast_or_null(DRE->getDecl())) { - SVal DeclSVal = State->getSVal(State->getLValue(VD, LCtx)); - if (auto DeclCI = DeclSVal.getAs()) - return &DeclCI->getValue(); - } - } + if (const auto *DRE = dyn_cast(CondVarExpr)) + if (const auto *VD = dyn_cast(DRE->getDecl())) + return State->getSVal(State->getLValue(VD, LCtx)); + + if (const auto *ME = dyn_cast(CondVarExpr)) + if (const auto *FD = dyn_cast(ME->getMemberDecl())) + if (auto FieldL = State->getSVal(ME, LCtx).getAs()) + return State->getRawSVal(*FieldL, FD->getType()); + + return None; +} + +static Optional +getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N) { + + if (Optional V = getSValForVar(CondVarExpr, N)) + if (auto DeclCI = V->getAs()) + return &DeclCI->getValue(); + return None; +} - return {}; +static bool isInterestingExpr(const Expr *E, const ExplodedNode *N, + const BugReport *B) { + if (Optional V = getSValForVar(E, N)) + return B->getInterestingnessKind(*V).hasValue(); + return false; } /// \return name of the macro inside the location \p Loc. @@ -2494,17 +2514,11 @@ const LocationContext *LCtx = N->getLocationContext(); PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx); + auto event = std::make_shared(Loc, Out.str()); - if (const auto *DR = dyn_cast(CondVarExpr)) { - if (const auto *VD = dyn_cast(DR->getDecl())) { - const ProgramState *state = N->getState().get(); - if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { - if (report.isInteresting(R)) - event->setPrunable(false); - } - } - } + if (isInterestingExpr(CondVarExpr, N, &report)) + event->setPrunable(false); return event; } @@ -2532,16 +2546,10 @@ return std::make_shared(Loc, Out.str()); auto event = std::make_shared(Loc, Out.str()); - const ProgramState *state = N->getState().get(); - if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { - if (report.isInteresting(R)) - event->setPrunable(false); - else { - SVal V = state->getSVal(R); - if (report.isInteresting(V)) - event->setPrunable(false); - } - } + + if (isInterestingExpr(DRE, N, &report)) + event->setPrunable(false); + return std::move(event); } @@ -2566,7 +2574,10 @@ if (!IsAssuming) return std::make_shared(Loc, Out.str()); - return std::make_shared(Loc, Out.str()); + auto event = std::make_shared(Loc, Out.str()); + if (isInterestingExpr(ME, N, &report)) + event->setPrunable(false); + return event; } bool ConditionBRVisitor::printValue(const Expr *CondVarExpr, raw_ostream &Out, @@ -2606,9 +2617,9 @@ return true; } -const char *const ConditionBRVisitor::GenericTrueMessage = +llvm::StringLiteral ConditionBRVisitor::GenericTrueMessage = "Assuming the condition is true"; -const char *const ConditionBRVisitor::GenericFalseMessage = +llvm::StringLiteral ConditionBRVisitor::GenericFalseMessage = "Assuming the condition is false"; bool ConditionBRVisitor::isPieceMessageGeneric( Index: clang/test/Analysis/track-control-dependency-conditions.cpp =================================================================== --- clang/test/Analysis/track-control-dependency-conditions.cpp +++ clang/test/Analysis/track-control-dependency-conditions.cpp @@ -459,6 +459,35 @@ } // end of namespace unimportant_write_before_collapse_point +namespace collapse_point_not_in_condition_as_field { + +[[noreturn]] void halt(); +struct IntWrapper { + int b; + IntWrapper(); + + void check() { + if (!b) // tracking-note{{Assuming field 'b' is not equal to 0}} + // tracking-note@-1{{Taking false branch}} + halt(); + return; + } +}; + +void f(IntWrapper i) { + int *x = 0; // expected-note{{'x' initialized to a null pointer value}} + + i.check(); // tracking-note{{Calling 'IntWrapper::check'}} + // tracking-note@-1{{Returning from 'IntWrapper::check'}} + if (i.b) // expected-note{{Field 'b' is not equal to 0}} + // expected-note@-1{{Taking true branch}} + // debug-note@-2{{Tracking condition 'i.b'}} + *x = 5; // expected-warning{{Dereference of null pointer}} + // expected-note@-1{{Dereference of null pointer}} +} + +} // end of namespace collapse_point_not_in_condition_as_field + namespace dont_track_assertlike_conditions { extern void __assert_fail (__const char *__assertion, __const char *__file,