forked from OSchip/llvm-project
Extend ConditionBRVisitor to handle condition variable assignments.
llvm-svn: 147526
This commit is contained in:
parent
279c77b677
commit
5799cddde0
|
@ -160,6 +160,12 @@ public:
|
|||
BugReporterContext &BRC,
|
||||
const LocationContext *LC);
|
||||
|
||||
PathDiagnosticPiece *VisitConditionVariable(StringRef LhsString,
|
||||
const Expr *CondVarExpr,
|
||||
const bool tookTrue,
|
||||
BugReporterContext &BRC,
|
||||
const LocationContext *LC);
|
||||
|
||||
bool patternMatch(const Expr *Ex,
|
||||
llvm::raw_ostream &Out,
|
||||
BugReporterContext &BRC);
|
||||
|
|
|
@ -604,18 +604,26 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
|
|||
shouldInvert = !isVarLHS && isVarRHS;
|
||||
}
|
||||
|
||||
BinaryOperator::Opcode Op = BExpr->getOpcode();
|
||||
|
||||
if (BinaryOperator::isAssignmentOp(Op)) {
|
||||
// For assignment operators, all that we care about is that the LHS
|
||||
// evaluates to "true" or "false".
|
||||
return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
|
||||
BRC, LC);
|
||||
}
|
||||
|
||||
// For non-assignment operations, we require that we can understand
|
||||
// both the LHS and RHS.
|
||||
if (LhsString.empty() || RhsString.empty())
|
||||
return 0;
|
||||
|
||||
// Should we invert the strings if the LHS is not a variable name?
|
||||
|
||||
llvm::SmallString<256> buf;
|
||||
llvm::raw_svector_ostream Out(buf);
|
||||
Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
|
||||
|
||||
// Do we need to invert the opcode?
|
||||
BinaryOperator::Opcode Op = BExpr->getOpcode();
|
||||
|
||||
if (shouldInvert)
|
||||
switch (Op) {
|
||||
default: break;
|
||||
|
@ -655,6 +663,33 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
|
|||
return new PathDiagnosticEventPiece(Loc, Out.str());
|
||||
}
|
||||
|
||||
PathDiagnosticPiece *
|
||||
ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
|
||||
const Expr *CondVarExpr,
|
||||
const bool tookTrue,
|
||||
BugReporterContext &BRC,
|
||||
const LocationContext *LC) {
|
||||
llvm::SmallString<256> buf;
|
||||
llvm::raw_svector_ostream Out(buf);
|
||||
Out << "Assuming " << LhsString << " is ";
|
||||
|
||||
QualType Ty = CondVarExpr->getType();
|
||||
|
||||
if (Ty->isPointerType())
|
||||
Out << (tookTrue ? "not null" : "null");
|
||||
else if (Ty->isObjCObjectPointerType())
|
||||
Out << (tookTrue ? "not nil" : "nil");
|
||||
else if (Ty->isBooleanType())
|
||||
Out << (tookTrue ? "true" : "false");
|
||||
else if (Ty->isIntegerType())
|
||||
Out << (tookTrue ? "non-zero" : "zero");
|
||||
else
|
||||
return 0;
|
||||
|
||||
PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LC);
|
||||
return new PathDiagnosticEventPiece(Loc, Out.str());
|
||||
}
|
||||
|
||||
PathDiagnosticPiece *
|
||||
ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
|
||||
const DeclRefExpr *DR,
|
||||
|
|
|
@ -50,6 +50,14 @@ void test_assumptions(int a, int b)
|
|||
*p = 0xDEADBEEF;
|
||||
}
|
||||
|
||||
int *bar_cond_assign();
|
||||
int test_cond_assign() {
|
||||
int *p;
|
||||
if (p = bar_cond_assign())
|
||||
return 1;
|
||||
return *p;
|
||||
}
|
||||
|
||||
// CHECK: <?xml version="1.0" encoding="UTF-8"?>
|
||||
// CHECK: <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
// CHECK: <plist version="1.0">
|
||||
|
@ -975,6 +983,212 @@ void test_assumptions(int a, int b)
|
|||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>path</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>kind</key><string>control</string>
|
||||
// CHECK: <key>edges</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>start</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>55</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>55</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: <key>end</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>kind</key><string>control</string>
|
||||
// CHECK: <key>edges</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>start</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: <key>end</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>7</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>7</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>kind</key><string>event</string>
|
||||
// CHECK: <key>location</key>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>7</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <key>ranges</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>7</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>7</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </array>
|
||||
// CHECK: <key>extended_message</key>
|
||||
// CHECK: <string>Assuming 'p' is null</string>
|
||||
// CHECK: <key>message</key>
|
||||
// CHECK: <string>Assuming 'p' is null</string>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>kind</key><string>control</string>
|
||||
// CHECK: <key>edges</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>start</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>7</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>56</integer>
|
||||
// CHECK: <key>col</key><integer>7</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: <key>end</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>58</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>58</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>kind</key><string>control</string>
|
||||
// CHECK: <key>edges</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>start</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>58</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>58</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: <key>end</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>58</integer>
|
||||
// CHECK: <key>col</key><integer>10</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>58</integer>
|
||||
// CHECK: <key>col</key><integer>11</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>kind</key><string>event</string>
|
||||
// CHECK: <key>location</key>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>58</integer>
|
||||
// CHECK: <key>col</key><integer>10</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <key>ranges</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>58</integer>
|
||||
// CHECK: <key>col</key><integer>11</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>58</integer>
|
||||
// CHECK: <key>col</key><integer>11</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </array>
|
||||
// CHECK: <key>extended_message</key>
|
||||
// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string>
|
||||
// CHECK: <key>message</key>
|
||||
// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</string>
|
||||
// CHECK: <key>category</key><string>Logic error</string>
|
||||
// CHECK: <key>type</key><string>Dereference of null pointer</string>
|
||||
// CHECK: <key>location</key>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>58</integer>
|
||||
// CHECK: <key>col</key><integer>10</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </array>
|
||||
// CHECK: </dict>
|
||||
// CHECK: </plist>
|
||||
|
|
Loading…
Reference in New Issue