BugReporterVisitors.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. // BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines a set of BugReporter "visitors" which can be used to
  11. // enhance the diagnostics reported for a bug.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
  15. #include "clang/AST/Expr.h"
  16. #include "clang/AST/ExprObjC.h"
  17. #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
  18. #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
  19. #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
  20. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  21. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  22. using namespace clang;
  23. using namespace ento;
  24. //===----------------------------------------------------------------------===//
  25. // Utility functions.
  26. //===----------------------------------------------------------------------===//
  27. const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) {
  28. // Pattern match for a few useful cases (do something smarter later):
  29. // a[0], p->f, *p
  30. const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
  31. if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) {
  32. if (U->getOpcode() == UO_Deref)
  33. return U->getSubExpr()->IgnoreParenCasts();
  34. }
  35. else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
  36. return ME->getBase()->IgnoreParenCasts();
  37. }
  38. else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) {
  39. return AE->getBase();
  40. }
  41. return NULL;
  42. }
  43. const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
  44. const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
  45. if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
  46. return BE->getRHS();
  47. return NULL;
  48. }
  49. const Stmt *bugreporter::GetCalleeExpr(const ExplodedNode *N) {
  50. // Callee is checked as a PreVisit to the CallExpr.
  51. const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
  52. if (const CallExpr *CE = dyn_cast<CallExpr>(S))
  53. return CE->getCallee();
  54. return NULL;
  55. }
  56. const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
  57. const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
  58. if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
  59. return RS->getRetValue();
  60. return NULL;
  61. }
  62. //===----------------------------------------------------------------------===//
  63. // Definitions for bug reporter visitors.
  64. //===----------------------------------------------------------------------===//
  65. PathDiagnosticPiece*
  66. BugReporterVisitor::getEndPath(BugReporterContext &BRC,
  67. const ExplodedNode *EndPathNode,
  68. BugReport &BR) {
  69. return 0;
  70. }
  71. PathDiagnosticPiece*
  72. BugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC,
  73. const ExplodedNode *EndPathNode,
  74. BugReport &BR) {
  75. const ProgramPoint &PP = EndPathNode->getLocation();
  76. PathDiagnosticLocation L;
  77. if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&PP)) {
  78. const CFGBlock *block = BE->getBlock();
  79. if (block->getBlockID() == 0) {
  80. L = PathDiagnosticLocation(
  81. EndPathNode->getLocationContext()->getDecl()->getBodyRBrace(),
  82. BRC.getSourceManager());
  83. }
  84. }
  85. if (!L.isValid()) {
  86. const Stmt *S = BR.getStmt();
  87. if (!S)
  88. return NULL;
  89. L = PathDiagnosticLocation(S, BRC.getSourceManager());
  90. }
  91. BugReport::ranges_iterator Beg, End;
  92. llvm::tie(Beg, End) = BR.getRanges();
  93. // Only add the statement itself as a range if we didn't specify any
  94. // special ranges for this report.
  95. PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L,
  96. BR.getDescription(),
  97. Beg == End);
  98. for (; Beg != End; ++Beg)
  99. P->addRange(*Beg);
  100. return P;
  101. }
  102. void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
  103. static int tag = 0;
  104. ID.AddPointer(&tag);
  105. ID.AddPointer(R);
  106. ID.Add(V);
  107. }
  108. PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N,
  109. const ExplodedNode *PrevN,
  110. BugReporterContext &BRC,
  111. BugReport &BR) {
  112. if (satisfied)
  113. return NULL;
  114. if (!StoreSite) {
  115. const ExplodedNode *Node = N, *Last = NULL;
  116. for ( ; Node ; Last = Node, Node = Node->getFirstPred()) {
  117. if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
  118. if (const PostStmt *P = Node->getLocationAs<PostStmt>())
  119. if (const DeclStmt *DS = P->getStmtAs<DeclStmt>())
  120. if (DS->getSingleDecl() == VR->getDecl()) {
  121. Last = Node;
  122. break;
  123. }
  124. }
  125. if (Node->getState()->getSVal(R) != V)
  126. break;
  127. }
  128. if (!Node || !Last) {
  129. satisfied = true;
  130. return NULL;
  131. }
  132. StoreSite = Last;
  133. }
  134. if (StoreSite != N)
  135. return NULL;
  136. satisfied = true;
  137. llvm::SmallString<256> sbuf;
  138. llvm::raw_svector_ostream os(sbuf);
  139. if (const PostStmt *PS = N->getLocationAs<PostStmt>()) {
  140. if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) {
  141. if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
  142. os << "Variable '" << VR->getDecl() << "' ";
  143. }
  144. else
  145. return NULL;
  146. if (isa<loc::ConcreteInt>(V)) {
  147. bool b = false;
  148. if (R->isBoundable()) {
  149. if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
  150. if (TR->getValueType()->isObjCObjectPointerType()) {
  151. os << "initialized to nil";
  152. b = true;
  153. }
  154. }
  155. }
  156. if (!b)
  157. os << "initialized to a null pointer value";
  158. }
  159. else if (isa<nonloc::ConcreteInt>(V)) {
  160. os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue();
  161. }
  162. else if (V.isUndef()) {
  163. if (isa<VarRegion>(R)) {
  164. const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
  165. if (VD->getInit())
  166. os << "initialized to a garbage value";
  167. else
  168. os << "declared without an initial value";
  169. }
  170. }
  171. }
  172. }
  173. if (os.str().empty()) {
  174. if (isa<loc::ConcreteInt>(V)) {
  175. bool b = false;
  176. if (R->isBoundable()) {
  177. if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
  178. if (TR->getValueType()->isObjCObjectPointerType()) {
  179. os << "nil object reference stored to ";
  180. b = true;
  181. }
  182. }
  183. }
  184. if (!b)
  185. os << "Null pointer value stored to ";
  186. }
  187. else if (V.isUndef()) {
  188. os << "Uninitialized value stored to ";
  189. }
  190. else if (isa<nonloc::ConcreteInt>(V)) {
  191. os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
  192. << " is assigned to ";
  193. }
  194. else
  195. return NULL;
  196. if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
  197. os << '\'' << VR->getDecl() << '\'';
  198. }
  199. else
  200. return NULL;
  201. }
  202. // FIXME: Refactor this into BugReporterContext.
  203. const Stmt *S = 0;
  204. ProgramPoint P = N->getLocation();
  205. if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
  206. const CFGBlock *BSrc = BE->getSrc();
  207. S = BSrc->getTerminatorCondition();
  208. }
  209. else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
  210. S = PS->getStmt();
  211. }
  212. if (!S)
  213. return NULL;
  214. // Construct a new PathDiagnosticPiece.
  215. PathDiagnosticLocation L(S, BRC.getSourceManager());
  216. return new PathDiagnosticEventPiece(L, os.str());
  217. }
  218. void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
  219. static int tag = 0;
  220. ID.AddPointer(&tag);
  221. ID.AddBoolean(Assumption);
  222. ID.Add(Constraint);
  223. }
  224. PathDiagnosticPiece *
  225. TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
  226. const ExplodedNode *PrevN,
  227. BugReporterContext &BRC,
  228. BugReport &BR) {
  229. if (isSatisfied)
  230. return NULL;
  231. // Check if in the previous state it was feasible for this constraint
  232. // to *not* be true.
  233. if (PrevN->getState()->assume(Constraint, !Assumption)) {
  234. isSatisfied = true;
  235. // As a sanity check, make sure that the negation of the constraint
  236. // was infeasible in the current state. If it is feasible, we somehow
  237. // missed the transition point.
  238. if (N->getState()->assume(Constraint, !Assumption))
  239. return NULL;
  240. // We found the transition point for the constraint. We now need to
  241. // pretty-print the constraint. (work-in-progress)
  242. std::string sbuf;
  243. llvm::raw_string_ostream os(sbuf);
  244. if (isa<Loc>(Constraint)) {
  245. os << "Assuming pointer value is ";
  246. os << (Assumption ? "non-null" : "null");
  247. }
  248. if (os.str().empty())
  249. return NULL;
  250. // FIXME: Refactor this into BugReporterContext.
  251. const Stmt *S = 0;
  252. ProgramPoint P = N->getLocation();
  253. if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
  254. const CFGBlock *BSrc = BE->getSrc();
  255. S = BSrc->getTerminatorCondition();
  256. }
  257. else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
  258. S = PS->getStmt();
  259. }
  260. if (!S)
  261. return NULL;
  262. // Construct a new PathDiagnosticPiece.
  263. PathDiagnosticLocation L(S, BRC.getSourceManager());
  264. return new PathDiagnosticEventPiece(L, os.str());
  265. }
  266. return NULL;
  267. }
  268. BugReporterVisitor *
  269. bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N,
  270. const Stmt *S) {
  271. if (!S || !N)
  272. return 0;
  273. ProgramStateManager &StateMgr = N->getState()->getStateManager();
  274. // Walk through nodes until we get one that matches the statement
  275. // exactly.
  276. while (N) {
  277. const ProgramPoint &pp = N->getLocation();
  278. if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) {
  279. if (ps->getStmt() == S)
  280. break;
  281. }
  282. N = *N->pred_begin();
  283. }
  284. if (!N)
  285. return 0;
  286. const ProgramState *state = N->getState();
  287. // Walk through lvalue-to-rvalue conversions.
  288. if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S)) {
  289. if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
  290. const VarRegion *R =
  291. StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
  292. // What did we load?
  293. SVal V = state->getSVal(loc::MemRegionVal(R));
  294. if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)
  295. || V.isUndef()) {
  296. return new FindLastStoreBRVisitor(V, R);
  297. }
  298. }
  299. }
  300. SVal V = state->getSValAsScalarOrLoc(S);
  301. // Uncomment this to find cases where we aren't properly getting the
  302. // base value that was dereferenced.
  303. // assert(!V.isUnknownOrUndef());
  304. // Is it a symbolic value?
  305. if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) {
  306. const SubRegion *R = cast<SubRegion>(L->getRegion());
  307. while (R && !isa<SymbolicRegion>(R)) {
  308. R = dyn_cast<SubRegion>(R->getSuperRegion());
  309. }
  310. if (R) {
  311. assert(isa<SymbolicRegion>(R));
  312. return new TrackConstraintBRVisitor(loc::MemRegionVal(R), false);
  313. }
  314. }
  315. return 0;
  316. }
  317. BugReporterVisitor *
  318. FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N,
  319. const MemRegion *R) {
  320. assert(R && "The memory region is null.");
  321. const ProgramState *state = N->getState();
  322. SVal V = state->getSVal(R);
  323. if (V.isUnknown())
  324. return 0;
  325. return new FindLastStoreBRVisitor(V, R);
  326. }
  327. PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
  328. const ExplodedNode *PrevN,
  329. BugReporterContext &BRC,
  330. BugReport &BR) {
  331. const PostStmt *P = N->getLocationAs<PostStmt>();
  332. if (!P)
  333. return 0;
  334. const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
  335. if (!ME)
  336. return 0;
  337. const Expr *Receiver = ME->getInstanceReceiver();
  338. if (!Receiver)
  339. return 0;
  340. const ProgramState *state = N->getState();
  341. const SVal &V = state->getSVal(Receiver);
  342. const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
  343. if (!DV)
  344. return 0;
  345. state = state->assume(*DV, true);
  346. if (state)
  347. return 0;
  348. // The receiver was nil, and hence the method was skipped.
  349. // Register a BugReporterVisitor to issue a message telling us how
  350. // the receiver was null.
  351. BR.addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Receiver));
  352. // Issue a message saying that the method was skipped.
  353. PathDiagnosticLocation L(Receiver, BRC.getSourceManager());
  354. return new PathDiagnosticEventPiece(L, "No method actually called "
  355. "because the receiver is nil");
  356. }
  357. // Registers every VarDecl inside a Stmt with a last store visitor.
  358. void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
  359. const Stmt *S) {
  360. const ExplodedNode *N = BR.getErrorNode();
  361. std::deque<const Stmt *> WorkList;
  362. WorkList.push_back(S);
  363. while (!WorkList.empty()) {
  364. const Stmt *Head = WorkList.front();
  365. WorkList.pop_front();
  366. const ProgramState *state = N->getState();
  367. ProgramStateManager &StateMgr = state->getStateManager();
  368. if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
  369. if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
  370. const VarRegion *R =
  371. StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
  372. // What did we load?
  373. SVal V = state->getSVal(S);
  374. if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
  375. // Register a new visitor with the BugReport.
  376. BR.addVisitor(new FindLastStoreBRVisitor(V, R));
  377. }
  378. }
  379. }
  380. for (Stmt::const_child_iterator I = Head->child_begin();
  381. I != Head->child_end(); ++I)
  382. WorkList.push_back(*I);
  383. }
  384. }
  385. //===----------------------------------------------------------------------===//
  386. // Visitor that tries to report interesting diagnostics from conditions.
  387. //===----------------------------------------------------------------------===//
  388. PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N,
  389. const ExplodedNode *Prev,
  390. BugReporterContext &BRC,
  391. BugReport &BR) {
  392. const ProgramPoint &progPoint = N->getLocation();
  393. const ProgramState *CurrentState = N->getState();
  394. const ProgramState *PrevState = Prev->getState();
  395. // Compare the GDMs of the state, because that is where constraints
  396. // are managed. Note that ensure that we only look at nodes that
  397. // were generated by the analyzer engine proper, not checkers.
  398. if (CurrentState->getGDM().getRoot() ==
  399. PrevState->getGDM().getRoot())
  400. return 0;
  401. // If an assumption was made on a branch, it should be caught
  402. // here by looking at the state transition.
  403. if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) {
  404. const CFGBlock *srcBlk = BE->getSrc();
  405. if (const Stmt *term = srcBlk->getTerminator())
  406. return VisitTerminator(term, CurrentState, PrevState,
  407. srcBlk, BE->getDst(), BRC);
  408. return 0;
  409. }
  410. if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) {
  411. // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
  412. // violation.
  413. const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
  414. cast<GRBugReporter>(BRC.getBugReporter()).
  415. getEngine().getEagerlyAssumeTags();
  416. const ProgramPointTag *tag = PS->getTag();
  417. if (tag == tags.first)
  418. return VisitTrueTest(cast<Expr>(PS->getStmt()), true, BRC);
  419. if (tag == tags.second)
  420. return VisitTrueTest(cast<Expr>(PS->getStmt()), false, BRC);
  421. return 0;
  422. }
  423. return 0;
  424. }
  425. PathDiagnosticPiece *
  426. ConditionBRVisitor::VisitTerminator(const Stmt *Term,
  427. const ProgramState *CurrentState,
  428. const ProgramState *PrevState,
  429. const CFGBlock *srcBlk,
  430. const CFGBlock *dstBlk,
  431. BugReporterContext &BRC) {
  432. const Expr *Cond = 0;
  433. switch (Term->getStmtClass()) {
  434. default:
  435. return 0;
  436. case Stmt::IfStmtClass:
  437. Cond = cast<IfStmt>(Term)->getCond();
  438. break;
  439. case Stmt::ConditionalOperatorClass:
  440. Cond = cast<ConditionalOperator>(Term)->getCond();
  441. break;
  442. }
  443. assert(Cond);
  444. assert(srcBlk->succ_size() == 2);
  445. const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
  446. return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()),
  447. tookTrue, BRC);
  448. }
  449. PathDiagnosticPiece *
  450. ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
  451. bool tookTrue,
  452. BugReporterContext &BRC) {
  453. const Expr *Ex = Cond;
  454. while (true) {
  455. Ex = Ex->IgnoreParens();
  456. switch (Ex->getStmtClass()) {
  457. default:
  458. return 0;
  459. case Stmt::BinaryOperatorClass:
  460. return VisitTrueTest(Cond, cast<BinaryOperator>(Cond), tookTrue, BRC);
  461. case Stmt::DeclRefExprClass:
  462. return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC);
  463. case Stmt::UnaryOperatorClass: {
  464. const UnaryOperator *UO = cast<UnaryOperator>(Ex);
  465. if (UO->getOpcode() == UO_LNot) {
  466. tookTrue = !tookTrue;
  467. Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext());
  468. continue;
  469. }
  470. return 0;
  471. }
  472. }
  473. }
  474. }
  475. bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
  476. BugReporterContext &BRC) {
  477. const Expr *OriginalExpr = Ex;
  478. Ex = Ex->IgnoreParenCasts();
  479. if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
  480. const bool quotes = isa<VarDecl>(DR->getDecl());
  481. if (quotes)
  482. Out << '\'';
  483. Out << DR->getDecl()->getDeclName().getAsString();
  484. if (quotes)
  485. Out << '\'';
  486. return quotes;
  487. }
  488. if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
  489. QualType OriginalTy = OriginalExpr->getType();
  490. if (OriginalTy->isPointerType()) {
  491. if (IL->getValue() == 0) {
  492. Out << "null";
  493. return false;
  494. }
  495. }
  496. else if (OriginalTy->isObjCObjectPointerType()) {
  497. if (IL->getValue() == 0) {
  498. Out << "nil";
  499. return false;
  500. }
  501. }
  502. Out << IL->getValue();
  503. return false;
  504. }
  505. return false;
  506. }
  507. PathDiagnosticPiece *
  508. ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
  509. const BinaryOperator *BExpr,
  510. const bool tookTrue,
  511. BugReporterContext &BRC) {
  512. bool shouldInvert = false;
  513. llvm::SmallString<128> LhsString, RhsString;
  514. {
  515. llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
  516. const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC);
  517. const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC);
  518. shouldInvert = !isVarLHS && isVarRHS;
  519. }
  520. if (LhsString.empty() || RhsString.empty())
  521. return 0;
  522. // Should we invert the strings if the LHS is not a variable name?
  523. llvm::SmallString<256> buf;
  524. llvm::raw_svector_ostream Out(buf);
  525. Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
  526. // Do we need to invert the opcode?
  527. BinaryOperator::Opcode Op = BExpr->getOpcode();
  528. if (shouldInvert)
  529. switch (Op) {
  530. default: break;
  531. case BO_LT: Op = BO_GT; break;
  532. case BO_GT: Op = BO_LT; break;
  533. case BO_LE: Op = BO_GE; break;
  534. case BO_GE: Op = BO_LE; break;
  535. }
  536. if (!tookTrue)
  537. switch (Op) {
  538. case BO_EQ: Op = BO_NE; break;
  539. case BO_NE: Op = BO_EQ; break;
  540. case BO_LT: Op = BO_GE; break;
  541. case BO_GT: Op = BO_LE; break;
  542. case BO_LE: Op = BO_GT; break;
  543. case BO_GE: Op = BO_LT; break;
  544. default:
  545. return 0;
  546. }
  547. switch (BExpr->getOpcode()) {
  548. case BO_EQ:
  549. Out << "equal to ";
  550. break;
  551. case BO_NE:
  552. Out << "not equal to ";
  553. break;
  554. default:
  555. Out << BinaryOperator::getOpcodeStr(Op) << ' ';
  556. break;
  557. }
  558. Out << (shouldInvert ? LhsString : RhsString);
  559. PathDiagnosticLocation Loc(Cond, BRC.getSourceManager());
  560. return new PathDiagnosticEventPiece(Loc, Out.str());
  561. }
  562. PathDiagnosticPiece *
  563. ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
  564. const DeclRefExpr *DR,
  565. const bool tookTrue,
  566. BugReporterContext &BRC) {
  567. const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
  568. if (!VD)
  569. return 0;
  570. llvm::SmallString<256> Buf;
  571. llvm::raw_svector_ostream Out(Buf);
  572. Out << "Assuming '";
  573. VD->getDeclName().printName(Out);
  574. Out << "' is ";
  575. QualType VDTy = VD->getType();
  576. if (VDTy->isPointerType())
  577. Out << (tookTrue ? "non-null" : "null");
  578. else if (VDTy->isObjCObjectPointerType())
  579. Out << (tookTrue ? "non-nil" : "nil");
  580. else if (VDTy->isScalarType())
  581. Out << (tookTrue ? "not equal to 0" : "0");
  582. else
  583. return 0;
  584. PathDiagnosticLocation Loc(Cond, BRC.getSourceManager());
  585. return new PathDiagnosticEventPiece(Loc, Out.str());
  586. }