Index: lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1815,12 +1815,6 @@ ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { ProgramPoint progPoint = N->getLocation(); - ProgramStateRef CurrentState = N->getState(); - ProgramStateRef PreviousState = N->getFirstPred()->getState(); - - // If the constraint information does not changed there is no assumption. - if (BRC.getStateManager().haveEqualConstraints(CurrentState, PreviousState)) - return nullptr; // If an assumption was made on a branch, it should be caught // here by looking at the state transition. @@ -1889,6 +1883,8 @@ break; } + Cond = Cond->IgnoreParens(); + // However, when we encounter a logical operator as a branch condition, // then the condition is actually its RHS, because LHS would be // the condition for the logical operator terminator. @@ -1908,6 +1904,18 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, bool tookTrue, BugReporterContext &BRC, BugReport &R, const ExplodedNode *N) { + ProgramStateRef CurrentState = N->getState(); + ProgramStateRef PreviousState = N->getFirstPred()->getState(); + const LocationContext *LCtx = N->getLocationContext(); + + // If the constraint information is changed between the current and the + // previous program state we assuming the newly seen constraint information. + // If we cannot evaluate the condition (and the constraints are the same) + // the analyzer has no information about the value and just assuming it. + if (BRC.getStateManager().haveEqualConstraints(CurrentState, PreviousState) && + CurrentState->getSVal(Cond, LCtx).isValid()) + return nullptr; + // These will be modified in code below, but we need to preserve the original // values in case we want to throw the generic message. const Expr *CondTmp = Cond; @@ -1943,7 +1951,6 @@ // Condition too complex to explain? Just say something so that the user // knew we've made some path decision at this point. - const LocationContext *LCtx = N->getLocationContext(); PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); if (!Loc.isValid() || !Loc.asLocation().isValid()) return nullptr; Index: test/Analysis/diagnostics/macros.cpp =================================================================== --- test/Analysis/diagnostics/macros.cpp +++ test/Analysis/diagnostics/macros.cpp @@ -30,7 +30,8 @@ // There are no path notes on the comparison to float types. void testDoubleMacro(double d) { - if (d == DBL_MAX) { // expected-note {{Taking true branch}} + if (d == DBL_MAX) { // expected-note {{Assuming 'd' is equal to DBL_MAX}} + // expected-note@-1 {{Taking true branch}} char *p = NULL; // expected-note {{'p' initialized to a null pointer value}} *p = 7; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}} Index: test/Analysis/uninit-vals.m =================================================================== --- test/Analysis/uninit-vals.m +++ test/Analysis/uninit-vals.m @@ -164,7 +164,8 @@ // expected-note@-1{{TRUE}} testObj->origin = makePoint(0.0, 0.0); - if (testObj->size > 0) { ; } // expected-note{{Taking false branch}} + if (testObj->size > 0) { ; } // expected-note{{Assuming the condition is false}} + // expected-note@-1{{Taking false branch}} // FIXME: Assigning to 'testObj->origin' kills the default binding for the // whole region, meaning that we've forgotten that testObj->size should also @@ -218,10 +219,14 @@ // expected-note@-1{{TRUE}} testObj->origin = makeIntPoint(1, 2); - if (testObj->size > 0) { ; } // expected-note{{Taking false branch}} + if (testObj->size > 0) { ; } // expected-note{{Assuming the condition is false}} // expected-note@-1{{Taking false branch}} - // expected-note@-2{{Taking false branch}} + // expected-note@-2{{Assuming the condition is false}} // expected-note@-3{{Taking false branch}} + // expected-note@-4{{Assuming the condition is false}} + // expected-note@-5{{Taking false branch}} + // expected-note@-6{{Assuming the condition is false}} + // expected-note@-7{{Taking false branch}} // FIXME: Assigning to 'testObj->origin' kills the default binding for the // whole region, meaning that we've forgotten that testObj->size should also