Index: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1271,7 +1271,22 @@ BugReporterContext &BRC) { const Expr *Cond = nullptr; + // In the code below, Term is a CFG terminator and Cond is a branch condition + // expression upon which the decision is made on this terminator. + // + // For example, in "if (x == 0)", the "if (x == 0)" statement is a terminator, + // and "x == 0" is the respective condition. + // + // Another example: in "if (x && y)", we've got two terminators and two + // conditions due to short-circuit nature of operator "&&": + // 1. The "if (x && y)" statement is a terminator, + // and "y" is the respective condition. + // 2. Also "x && ..." is another terminator, + // and "x" is its condition. + switch (Term->getStmtClass()) { + // FIXME: Stmt::SwitchStmtClass is worth handling, however it is a bit + // more tricky because there are more than two branches to account for. default: return nullptr; case Stmt::IfStmtClass: @@ -1280,6 +1295,24 @@ case Stmt::ConditionalOperatorClass: Cond = cast(Term)->getCond(); break; + case Stmt::BinaryOperatorClass: + // When we encounter a logical operator (&& or ||) as a CFG terminator, + // then the condition is actually its LHS; otheriwse, we'd encounter + // the parent, such as if-statement, as a terminator. + const auto *BO = cast(Term); + assert(BO->isLogicalOp() && + "CFG terminator is not a short-circuit operator!"); + Cond = BO->getLHS(); + break; + } + + // 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. + while (const auto *InnerBO = dyn_cast(Cond)) { + if (!InnerBO->isLogicalOp()) + break; + Cond = InnerBO->getRHS()->IgnoreParens(); } assert(Cond); Index: cfe/trunk/test/Analysis/conditional-path-notes.c =================================================================== --- cfe/trunk/test/Analysis/conditional-path-notes.c +++ cfe/trunk/test/Analysis/conditional-path-notes.c @@ -64,11 +64,12 @@ } } -void testNonDiagnosableBranchLogical(int a, int b) { +void testDiagnosableBranchLogical(int a, int b) { if (a && b) { - // expected-note@-1 {{Assuming the condition is true}} + // expected-note@-1 {{Assuming 'a' is not equal to 0}} // expected-note@-2 {{Left side of '&&' is true}} - // expected-note@-3 {{Taking true branch}} + // expected-note@-3 {{Assuming 'b' is not equal to 0}} + // expected-note@-4 {{Taking true branch}} *(volatile int *)0 = 1; // expected-warning{{Dereference of null pointer}} // expected-note@-1 {{Dereference of null pointer}} } @@ -1343,6 +1344,35 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line68 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line68 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line68 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Assuming 'a' is not equal to 0 +// CHECK-NEXT: message +// CHECK-NEXT: Assuming 'a' is not equal to 0 +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -1377,45 +1407,11 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line68 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line68 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line68 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line68 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: // CHECK-NEXT: line68 -// CHECK-NEXT: col7 +// CHECK-NEXT: col12 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: ranges @@ -1423,7 +1419,7 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line68 -// CHECK-NEXT: col7 +// CHECK-NEXT: col12 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1435,9 +1431,9 @@ // CHECK-NEXT: // CHECK-NEXT: depth0 // CHECK-NEXT: extended_message -// CHECK-NEXT: Assuming the condition is true +// CHECK-NEXT: Assuming 'b' is not equal to 0 // CHECK-NEXT: message -// CHECK-NEXT: Assuming the condition is true +// CHECK-NEXT: Assuming 'b' is not equal to 0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: kindcontrol @@ -1448,24 +1444,24 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line68 -// CHECK-NEXT: col7 +// CHECK-NEXT: col12 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line68 -// CHECK-NEXT: col7 +// CHECK-NEXT: col12 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line72 +// CHECK-NEXT: line73 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line72 +// CHECK-NEXT: line73 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1481,12 +1477,12 @@ // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line72 +// CHECK-NEXT: line73 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line72 +// CHECK-NEXT: line73 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1494,12 +1490,12 @@ // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line72 +// CHECK-NEXT: line73 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line72 +// CHECK-NEXT: line73 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1511,7 +1507,7 @@ // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line72 +// CHECK-NEXT: line73 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1519,12 +1515,12 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line72 +// CHECK-NEXT: line73 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line72 +// CHECK-NEXT: line73 // CHECK-NEXT: col26 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1542,13 +1538,13 @@ // CHECK-NEXT: typeDereference of null pointer // CHECK-NEXT: check_namecore.NullDereference // CHECK-NEXT: -// CHECK-NEXT: issue_hash_content_of_line_in_contextebd0bb32bbdcaa2a806ff1984974c07a +// CHECK-NEXT: issue_hash_content_of_line_in_contexta2b345c9681d9dd3aa15d12810759cb9 // CHECK-NEXT: issue_context_kindfunction -// CHECK-NEXT: issue_contexttestNonDiagnosableBranchLogical -// CHECK-NEXT: issue_hash_function_offset5 +// CHECK-NEXT: issue_contexttestDiagnosableBranchLogical +// CHECK-NEXT: issue_hash_function_offset6 // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line72 +// CHECK-NEXT: line73 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1564,12 +1560,12 @@ // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line78 +// CHECK-NEXT: line79 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line78 +// CHECK-NEXT: line79 // CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1577,12 +1573,12 @@ // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line80 +// CHECK-NEXT: line81 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line80 +// CHECK-NEXT: line81 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1598,12 +1594,12 @@ // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line80 +// CHECK-NEXT: line81 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line80 +// CHECK-NEXT: line81 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1611,12 +1607,12 @@ // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line80 +// CHECK-NEXT: line81 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line80 +// CHECK-NEXT: line81 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1628,7 +1624,7 @@ // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line80 +// CHECK-NEXT: line81 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1636,12 +1632,12 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line80 +// CHECK-NEXT: line81 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line80 +// CHECK-NEXT: line81 // CHECK-NEXT: col26 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1665,7 +1661,7 @@ // CHECK-NEXT: issue_hash_function_offset3 // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line80 +// CHECK-NEXT: line81 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: Index: cfe/trunk/test/Analysis/edges-new.mm =================================================================== --- cfe/trunk/test/Analysis/edges-new.mm +++ cfe/trunk/test/Analysis/edges-new.mm @@ -7655,45 +7655,11 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line263 -// CHECK-NEXT: col19 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line263 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line263 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line263 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: // CHECK-NEXT: line263 -// CHECK-NEXT: col7 +// CHECK-NEXT: col19 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: ranges @@ -7701,7 +7667,7 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line263 -// CHECK-NEXT: col7 +// CHECK-NEXT: col19 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -7713,9 +7679,9 @@ // CHECK-NEXT: // CHECK-NEXT: depth0 // CHECK-NEXT: extended_message -// CHECK-NEXT: Assuming the condition is true +// CHECK-NEXT: Assuming 'coin' is not equal to 0 // CHECK-NEXT: message -// CHECK-NEXT: Assuming the condition is true +// CHECK-NEXT: Assuming 'coin' is not equal to 0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: kindcontrol @@ -7726,12 +7692,12 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line263 -// CHECK-NEXT: col7 +// CHECK-NEXT: col19 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line263 -// CHECK-NEXT: col7 +// CHECK-NEXT: col22 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -8000,45 +7966,11 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line263 -// CHECK-NEXT: col19 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line263 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line263 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line263 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: // CHECK-NEXT: line263 -// CHECK-NEXT: col7 +// CHECK-NEXT: col19 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: ranges @@ -8046,7 +7978,7 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line263 -// CHECK-NEXT: col7 +// CHECK-NEXT: col19 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -8058,9 +7990,9 @@ // CHECK-NEXT: // CHECK-NEXT: depth0 // CHECK-NEXT: extended_message -// CHECK-NEXT: Assuming the condition is false +// CHECK-NEXT: Assuming 'coin' is 0 // CHECK-NEXT: message -// CHECK-NEXT: Assuming the condition is false +// CHECK-NEXT: Assuming 'coin' is 0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: kindcontrol @@ -8071,12 +8003,12 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line263 -// CHECK-NEXT: col7 +// CHECK-NEXT: col19 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line263 -// CHECK-NEXT: col7 +// CHECK-NEXT: col22 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: