BugReporterVisitors.cpp revision 9abf1b4577b75ffcc46afbdfb55de334f68f05c0
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--//
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com//
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com//                     The LLVM Compiler Infrastructure
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com//
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// This file is distributed under the University of Illinois Open Source
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// License. See LICENSE.TXT for details.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com//
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com//===----------------------------------------------------------------------===//
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  This file defines a set of BugReporter "visitors" which can be used to
11309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org//  enhance the diagnostics reported for a bug.
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//===----------------------------------------------------------------------===//
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
15bbe50131413098bffed9186660c41f047d881596bungeman@google.com#include "clang/AST/Expr.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "clang/AST/ExprObjC.h"
1797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
188b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
198b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
22045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "llvm/ADT/SmallString.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "llvm/ADT/StringExtras.h"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "llvm/Support/raw_ostream.h"
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comusing namespace clang;
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comusing namespace ento;
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//===----------------------------------------------------------------------===//
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Utility functions.
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//===----------------------------------------------------------------------===//
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
346c14b43a840c791699747ba4cc0ed5abf2bda218reed@android.combool bugreporter::isDeclRefExprToReference(const Expr *E) {
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return DRE->getDecl()->getType()->isReferenceType();
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  }
38309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org  return false;
39309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org}
40309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org
417db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.comconst Expr *bugreporter::getDerefExpr(const Stmt *S) {
427db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com  // Pattern match for a few useful cases (do something smarter later):
437db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com  //   a[0], p->f, *p
447db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com  const Expr *E = dyn_cast<Expr>(S);
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  if (!E)
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return 0;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  E = E->IgnoreParenCasts();
4862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com
4962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com  while (true) {
5062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) {
5162900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com      assert(B->isAssignmentOp());
5262900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com      E = B->getLHS()->IgnoreParenCasts();
5362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com      continue;
5462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com    }
5562900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com    else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) {
5662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com      if (U->getOpcode() == UO_Deref)
5762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com        return U->getSubExpr()->IgnoreParenCasts();
5862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com    }
5962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com    else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
6062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com      if (ME->isArrow() || isDeclRefExprToReference(ME->getBase())) {
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return ME->getBase()->IgnoreParenCasts();
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      }
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
65353482251e61971a8cf3a60bbb6910f482be634freed@google.com      return IvarRef->getBase()->IgnoreParenCasts();
66c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) {
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      return AE->getBase();
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
70583b18a20959c9ac360316a366f4ddd9598bdf52skia.committer@gmail.com    break;
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  }
728b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
73c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org  return NULL;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
790da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com    return BE->getRHS();
8097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com  return NULL;
81a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com}
820da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com
83c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgconst Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
84c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org  const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
85c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org  if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
86c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    return RS->getRetValue();
87c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org  return NULL;
88c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
89a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com
9097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com//===----------------------------------------------------------------------===//
91a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com// Definitions for bug reporter visitors.
92a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com//===----------------------------------------------------------------------===//
93a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com
94a76de72a6036da0a6b051b14411b80941971f881bungeman@google.comPathDiagnosticPiece*
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comBugReporterVisitor::getEndPath(BugReporterContext &BRC,
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               const ExplodedNode *EndPathNode,
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               BugReport &BR) {
9834abef14a637450743e1debccdcdb5bdc2e9ba01commit-bot@chromium.org  return 0;
997db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com}
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comPathDiagnosticPiece*
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comBugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC,
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      const ExplodedNode *EndPathNode,
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      BugReport &BR) {
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  PathDiagnosticLocation L =
1067db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com    PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager());
1077db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  BugReport::ranges_iterator Beg, End;
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  llvm::tie(Beg, End) = BR.getRanges();
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  // Only add the statement itself as a range if we didn't specify any
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  // special ranges for this report.
11382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com  PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L,
11482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com      BR.getDescription(),
11582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com      Beg == End);
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  for (; Beg != End; ++Beg)
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    P->addRange(*Beg);
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  return P;
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comnamespace {
1241b27704eba15be4e9d1997faac42038493a30be5djsollen/// Emits an extra note at the return statement of an interesting stack frame.
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// The returned value is marked as an interesting value, and if it's null,
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// adds a visitor to track where it became null.
1281b27704eba15be4e9d1997faac42038493a30be5djsollen///
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// This visitor is intended to be used when another visitor discovers that an
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// interesting value comes from an inlined function call.
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass ReturnVisitor : public BugReporterVisitorImpl<ReturnVisitor> {
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  const StackFrameContext *StackFrame;
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  enum {
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Initial,
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MaybeSuppress,
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Satisfied
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  } Mode;
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  ReturnVisitor(const StackFrameContext *Frame)
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : StackFrame(Frame), Mode(Initial) {}
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  static void *getTag() {
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int Tag = 0;
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return static_cast<void *>(&Tag);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  }
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com  virtual void Profile(llvm::FoldingSetNodeID &ID) const {
149a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com    ID.AddPointer(ReturnVisitor::getTag());
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ID.AddPointer(StackFrame);
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  }
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  /// Adds a ReturnVisitor if the given statement represents a call that was
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  /// inlined.
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  ///
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  /// This will search back through the ExplodedGraph, starting from the given
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  /// node, looking for when the given statement was processed. If it turns out
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  /// the statement is a call that was inlined, we add the visitor to the
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  /// bug report, so it can print a note later.
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S,
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    BugReport &BR) {
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!CallEvent::isCallStmt(S))
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      return;
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // First, find when we processed the statement.
1667767cd87fdadeed868457a2407e8b0a50006fc4asenorblanco@chromium.org    do {
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>())
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (CEE->getCalleeContext()->getCallSite() == S)
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          break;
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      if (Optional<StmtPoint> SP = Node->getLocationAs<StmtPoint>())
171d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        if (SP->getStmt() == S)
17282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com          break;
173b757f8d20c582463999bd7aa5a48110e84945d19reed@android.com
1747767cd87fdadeed868457a2407e8b0a50006fc4asenorblanco@chromium.org      Node = Node->getFirstPred();
175d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com    } while (Node);
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // Next, step over any post-statement checks.
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (Node && Node->getLocation().getAs<PostStmt>())
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      Node = Node->getFirstPred();
1800abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
1810abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    // Finally, see if we inlined the call.
182d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    if (Node) {
183d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com      if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>()) {
184d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        const StackFrameContext *CalleeContext = CEE->getCalleeContext();
185d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        if (CalleeContext->getCallSite() == S) {
186d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com          BR.markInteresting(CalleeContext);
187d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com          BR.addVisitor(new ReturnVisitor(CalleeContext));
188d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        }
189d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com      }
190d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    }
1910abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com  }
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  /// Returns true if any counter-suppression heuristics are enabled for
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  /// ReturnVisitor.
195a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com  static bool hasCounterSuppression(AnalyzerOptions &Options) {
196a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com    return Options.shouldAvoidSuppressingNullArgumentPaths();
197a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com  }
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1995bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com  PathDiagnosticPiece *visitNodeInitial(const ExplodedNode *N,
2005bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com                                        const ExplodedNode *PrevN,
2015bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com                                        BugReporterContext &BRC,
2025bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com                                        BugReport &BR) {
2035bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    // Only print a message at the interesting return statement.
2045bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    if (N->getLocationContext() != StackFrame)
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      return 0;
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Optional<StmtPoint> SP = N->getLocationAs<StmtPoint>();
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!SP)
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      return 0;
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!Ret)
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      return 0;
2148136d58161c3fa314af42f5c65682be855dfec1breed@google.com
2158136d58161c3fa314af42f5c65682be855dfec1breed@google.com    // Okay, we're at the right return statement, but do we have the return
2168136d58161c3fa314af42f5c65682be855dfec1breed@google.com    // value available?
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ProgramStateRef State = N->getState();
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SVal V = State->getSVal(Ret, StackFrame);
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (V.isUnknownOrUndef())
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      return 0;
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // Don't print any more notes after this one.
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Mode = Satisfied;
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
225d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com    const Expr *RetE = Ret->getRetValue();
22682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    assert(RetE && "Tracking a return value for a void function");
2277767cd87fdadeed868457a2407e8b0a50006fc4asenorblanco@chromium.org
228d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com    // Handle cases where a reference is returned and then immediately used.
229d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com    Optional<Loc> LValue;
230d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com    if (RetE->isGLValue()) {
231d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com      if ((LValue = V.getAs<Loc>())) {
232d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com        SVal RValue = State->getRawSVal(*LValue, RetE->getType());
233b757f8d20c582463999bd7aa5a48110e84945d19reed@android.com        if (RValue.getAs<DefinedSVal>())
234b757f8d20c582463999bd7aa5a48110e84945d19reed@android.com          V = RValue;
235b757f8d20c582463999bd7aa5a48110e84945d19reed@android.com      }
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2380abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    // Ignore aggregate rvalues.
239a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    if (V.getAs<nonloc::LazyCompoundVal>() ||
240a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        V.getAs<nonloc::CompoundVal>())
241a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com      return 0;
242a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com
243a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    RetE = RetE->IgnoreParenCasts();
244a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com
245a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    // If we can't prove the return value is 0, just mark it interesting, and
246a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    // make sure to track it into any further inner functions.
247a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    if (State->assume(V.castAs<DefinedSVal>(), true)) {
248a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com      BR.markInteresting(V);
249a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com      ReturnVisitor::addVisitorIfNecessary(N, RetE, BR);
250a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com      return 0;
251a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    }
25297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
2530abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    // If we're returning 0, we should track where that 0 came from.
254a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    bugreporter::trackNullOrUndefValue(N, RetE, BR);
2550abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
2560abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    // Build an appropriate message based on the return value.
257900ecf2f1579d42c9d2959831787af0346320f86reed@google.com    SmallString<64> Msg;
258cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com    llvm::raw_svector_ostream Out(Msg);
259fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2600abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    if (V.getAs<Loc>()) {
2610abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      // If we are pruning null-return paths as unlikely error paths, mark the
2620abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      // report invalid. We still want to emit a path note, however, in case
263a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com      // the report is resurrected as valid later on.
264cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      ExprEngine &Eng = BRC.getBugReporter().getEngine();
2650abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      AnalyzerOptions &Options = Eng.getAnalysisManager().options;
2660abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      if (Options.shouldSuppressNullReturnPaths()) {
2670abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com        if (hasCounterSuppression(Options))
2680abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com          Mode = MaybeSuppress;
2690abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com        else
2700abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com          BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
2710abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      }
2720abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
2730abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      if (RetE->getType()->isObjCObjectPointerType())
27427e21fe577211c1c40cbf40d0385b02c69d04522skia.committer@gmail.com        Out << "Returning nil";
2750abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      else
2760abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com        Out << "Returning null pointer";
2770abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    } else {
2780abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      Out << "Returning zero";
2790abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    }
2800abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
2810abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    if (LValue) {
2820abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      if (const MemRegion *MR = LValue->getAsRegion()) {
2830abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com        if (MR->canPrintPretty()) {
2840abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com          Out << " (reference to '";
2850abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com          MR->printPretty(Out);
2860abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com          Out << "')";
2870abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com        }
2880abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      }
2890abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    } else {
2900abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      // FIXME: We should have a more generalized location printing mechanism.
2910abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetE))
2920abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com        if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
2930abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com          Out << " (loaded from '" << *DD << "')";
294fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
295cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com
296cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com    PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame);
2970abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    return new PathDiagnosticEventPiece(L, Out.str());
2980abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com  }
2990abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
3000abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com  PathDiagnosticPiece *visitNodeMaybeSuppress(const ExplodedNode *N,
3010abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com                                              const ExplodedNode *PrevN,
3020abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com                                              BugReporterContext &BRC,
3030abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com                                              BugReport &BR) {
3040abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    // Are we at the entry node for this call?
3050abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    Optional<CallEnter> CE = N->getLocationAs<CallEnter>();
3060abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    if (!CE)
3070abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      return 0;
3080abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
3090abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    if (CE->getCalleeContext() != StackFrame)
3100abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      return 0;
3110abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
3120abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    Mode = Satisfied;
3130abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
3140abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    ExprEngine &Eng = BRC.getBugReporter().getEngine();
3150abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    AnalyzerOptions &Options = Eng.getAnalysisManager().options;
3160abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    if (Options.shouldAvoidSuppressingNullArgumentPaths()) {
3170abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      // Don't automatically suppress a report if one of the arguments is
3180abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      // known to be a null pointer. Instead, start tracking /that/ null
3190abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      // value back to its origin.
3200abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      ProgramStateManager &StateMgr = BRC.getStateManager();
3210abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com      CallEventManager &CallMgr = StateMgr.getCallEventManager();
3220abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
323cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      ProgramStateRef State = N->getState();
324cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      CallEventRef<> Call = CallMgr.getCaller(StackFrame, State);
325cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
326cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        SVal ArgV = Call->getArgSVal(I);
327a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com        if (!ArgV.getAs<Loc>())
32897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com          continue;
3290abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
330a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        const Expr *ArgE = Call->getArgExpr(I);
331900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        if (!ArgE)
332cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com          continue;
333fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
334cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        // Is it possible for this argument to be non-null?
335cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        if (State->assume(ArgV.castAs<Loc>(), true))
336a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com          continue;
337cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com
338fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, /*IsArg=*/true))
339cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com          return 0;
340cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com
3410abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com        // If we /can't/ track the null pointer, we should err on the side of
3420abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com        // false negatives, and continue towards marking this report invalid.
343cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        // (We will still look at the other arguments, though.)
344a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com      }
345a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    }
346a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com
34797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    // There is no reason not to suppress this report; go ahead and do it.
348a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com    BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
349a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com    return 0;
350a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com  }
351a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com
352a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
353d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com                                 const ExplodedNode *PrevN,
354d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com                                 BugReporterContext &BRC,
355d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com                                 BugReport &BR) {
356d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    switch (Mode) {
357d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    case Initial:
358d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com      return visitNodeInitial(N, PrevN, BRC, BR);
359d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    case MaybeSuppress:
360d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com      return visitNodeMaybeSuppress(N, PrevN, BRC, BR);
361d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    case Satisfied:
362d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com      return 0;
363d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    }
364d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
365d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    llvm_unreachable("Invalid visit mode!");
366d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  }
367d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com};
368d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com} // end anonymous namespace
369d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
370d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
371d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.comvoid FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
372d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  static int tag = 0;
373d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  ID.AddPointer(&tag);
374d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  ID.AddPointer(R);
375d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  ID.Add(V);
376d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com}
377f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org
378f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.orgPathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
379f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org                                                       const ExplodedNode *Pred,
380d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com                                                       BugReporterContext &BRC,
381d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com                                                       BugReport &BR) {
382d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
383d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  if (Satisfied)
384d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    return NULL;
385d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
386d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  const ExplodedNode *StoreSite = 0;
387d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  const Expr *InitE = 0;
388d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  bool IsParam = false;
389d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
390c932c9fd77503aec47c256818dd94a8b57219a43robertphillips@google.com  // First see if we reached the declaration of the region.
391d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
392d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    if (Optional<PostStmt> P = Pred->getLocationAs<PostStmt>()) {
393d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com      if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) {
394d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        if (DS->getSingleDecl() == VR->getDecl()) {
395d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com          StoreSite = Pred;
396d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com          InitE = VR->getDecl()->getInit();
397d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        }
398d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com      }
399a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    }
400a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com  }
401d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
402cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com  // Otherwise, see if this is the store site:
403cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com  // (1) Succ has this binding and Pred does not, i.e. this is
404cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com  //     where the binding first occurred.
405cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com  // (2) Succ has this binding and is a PostStore node for this region, i.e.
406cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com  //     the same binding was re-assigned here.
407cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com  if (!StoreSite) {
408cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com    if (Succ->getState()->getSVal(R) != V)
409cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      return NULL;
410cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com
411cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com    if (Pred->getState()->getSVal(R) == V) {
412cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      Optional<PostStore> PS = Succ->getLocationAs<PostStore>();
413d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com      if (!PS || PS->getLocationValue() != R)
414d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        return NULL;
415d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    }
416d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
417d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    StoreSite = Succ;
418d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
419d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    // If this is an assignment expression, we can track the value
420d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    // being assigned.
421d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    if (Optional<PostStmt> P = Succ->getLocationAs<PostStmt>())
422d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com      if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>())
423d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        if (BO->isAssignmentOp())
424d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com          InitE = BO->getRHS();
425d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
426d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    // If this is a call entry, the variable should be a parameter.
427d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    // FIXME: Handle CXXThisRegion as well. (This is not a priority because
428d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    // 'this' should never be NULL, but this visitor isn't just for NULL and
429d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    // UndefinedVal.)
430d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
431cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
432cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl());
433045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
434045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        ProgramStateManager &StateMgr = BRC.getStateManager();
435cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        CallEventManager &CallMgr = StateMgr.getCallEventManager();
436a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org
437cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(),
438cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com                                                Succ->getState());
439cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
440848250415eddc54075f7eb8795e8db79e749c6abreed        IsParam = true;
4419be5727d96979f6a0f89b00a43c19bca97ace0fcreed@google.com      }
4429be5727d96979f6a0f89b00a43c19bca97ace0fcreed@google.com    }
4439be5727d96979f6a0f89b00a43c19bca97ace0fcreed@google.com  }
4449be5727d96979f6a0f89b00a43c19bca97ace0fcreed@google.com
445cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com  if (!StoreSite)
446a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    return NULL;
447cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com  Satisfied = true;
448cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com
449fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com  // If we have an expression that provided the value, try to track where it
450cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com  // came from.
451045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com  if (InitE) {
452045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (V.isUndef() || V.getAs<loc::ConcreteInt>()) {
453cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      if (!IsParam)
454cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        InitE = InitE->IgnoreParenCasts();
455cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam);
456fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    } else {
4570c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com      ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(),
458d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com                                           BR);
459d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    }
460d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com  }
4610c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com
4620c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com  if (!R->canPrintPretty())
4630c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com    return 0;
4640c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com
4650c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com  // Okay, we've found the binding. Emit an appropriate message.
4660c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com  SmallString<256> sbuf;
4670c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com  llvm::raw_svector_ostream os(sbuf);
4680abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com
4690c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com  if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
4700abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    const Stmt *S = PS->getStmt();
4710c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com    const char *action = 0;
4720c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com    const DeclStmt *DS = dyn_cast<DeclStmt>(S);
4730c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com    const VarRegion *VR = dyn_cast<VarRegion>(R);
4740c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com
4750abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    if (DS) {
4760c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com      action = "initialized to ";
4770abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com    } else if (isa<BlockExpr>(S)) {
4780c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com      action = "captured by block as ";
4790c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com      if (VR) {
4800c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com        // See if we can get the BlockVarRegion.
4810c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com        ProgramStateRef State = StoreSite->getState();
482cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        SVal V = State->getSVal(S, PS->getLocationContext());
483cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com        if (const BlockDataRegion *BDR =
484cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com              dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
4855bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com          if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
4865bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com            if (Optional<KnownSVal> KV =
4875bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com                State->getSVal(OriginalR).getAs<KnownSVal>())
4885bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com              BR.addVisitor(new FindLastStoreBRVisitor(*KV, OriginalR));
4895bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com          }
4905bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        }
4915bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      }
4925bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    }
4935bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com
4945bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    if (action) {
4955bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      if (!R)
4965bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        return 0;
4975bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com
4985bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      os << '\'';
4995bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      R->printPretty(os);
5005bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      os << "' ";
5015bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com
5025bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      if (V.getAs<loc::ConcreteInt>()) {
5035bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        bool b = false;
5045bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        if (R->isBoundable()) {
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (TR->getValueType()->isObjCObjectPointerType()) {
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com              os << action << "nil";
508fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com              b = true;
5095bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com            }
5105bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com          }
5115bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        }
5125bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com
5135bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        if (!b)
5145bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com          os << action << "a null pointer value";
5155bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      } else if (Optional<nonloc::ConcreteInt> CVal =
5165bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com                     V.getAs<nonloc::ConcreteInt>()) {
5175bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        os << action << CVal->getValue();
5185bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      }
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      else if (DS) {
520ce2b1afb582f0a2274f476c949cff8b0e1c72b36reed@google.com        if (V.isUndef()) {
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          if (isa<VarRegion>(R)) {
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (VD->getInit())
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com              os << "initialized to a garbage value";
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            else
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com              os << "declared without an initial value";
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          }
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        else {
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          os << "initialized here";
5315bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        }
5325bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      }
5335bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    }
5345bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com  } else if (StoreSite->getLocation().getAs<CallEnter>()) {
5355bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
5365bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl());
5375bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      os << "Passing ";
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      if (V.getAs<loc::ConcreteInt>()) {
541a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com        if (Param->getType()->isObjCObjectPointerType())
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          os << "nil object reference";
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        else
544cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com          os << "null pointer value";
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      } else if (V.isUndef()) {
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        os << "uninitialized value";
547cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      } else if (Optional<nonloc::ConcreteInt> CI =
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     V.getAs<nonloc::ConcreteInt>()) {
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        os << "the value " << CI->getValue();
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      } else {
5514516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com        os << "value";
55282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com      }
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      // Printed parameter indexes are 1-based, not 0-based.
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      unsigned Idx = Param->getFunctionScopeIndex() + 1;
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter '";
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
558a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com      R->printPretty(os);
559a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com      os << '\'';
56097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    }
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  }
5625bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com
563a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com  if (os.str().empty()) {
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (V.getAs<loc::ConcreteInt>()) {
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      bool b = false;
5661b27704eba15be4e9d1997faac42038493a30be5djsollen      if (R->isBoundable()) {
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          if (TR->getValueType()->isObjCObjectPointerType()) {
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            os << "nil object reference stored to ";
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            b = true;
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          }
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      }
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5755bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      if (!b)
5765bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        os << "Null pointer value stored to ";
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5785bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    else if (V.isUndef()) {
5795bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      os << "Uninitialized value stored to ";
5805bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    } else if (Optional<nonloc::ConcreteInt> CV =
5815bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com                   V.getAs<nonloc::ConcreteInt>()) {
5825bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      os << "The value " << CV->getValue() << " is assigned to ";
5835bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    }
5845bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    else
5855bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com      os << "Value assigned to ";
5865bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com
5875bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    os << '\'';
5885bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    R->printPretty(os);
5892fd42c471c77f54ace35c13975651e17d5b2e8c6skia.committer@gmail.com    os << '\'';
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  }
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  // Construct a new PathDiagnosticPiece.
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  ProgramPoint P = StoreSite->getLocation();
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  PathDiagnosticLocation L;
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  if (P.getAs<CallEnter>() && InitE)
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    L = PathDiagnosticLocation(InitE, BRC.getSourceManager(),
59782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                               P.getLocationContext());
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  else
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    L = PathDiagnosticLocation::create(P, BRC.getSourceManager());
6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  if (!L.isValid())
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  return new PathDiagnosticEventPiece(L, os.str());
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  static int tag = 0;
6074516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com  ID.AddPointer(&tag);
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  ID.AddBoolean(Assumption);
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  ID.Add(Constraint);
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// Return the tag associated with this visitor.  This tag will be used
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// to make all PathDiagnosticPieces created by this visitor.
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst char *TrackConstraintBRVisitor::getTag() {
61597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com  return "TrackConstraintBRVisitor";
616a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com}
617a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com
618a76de72a6036da0a6b051b14411b80941971f881bungeman@google.comPathDiagnosticPiece *
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    const ExplodedNode *PrevN,
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    BugReporterContext &BRC,
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    BugReport &BR) {
6237db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com  if (isSatisfied)
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  // Check if in the previous state it was feasible for this constraint
6270a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com  // to *not* be true.
628410780677af260e32948b02c0725ef6ad761260cbungeman  if (PrevN->getState()->assume(Constraint, !Assumption)) {
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    isSatisfied = true;
6319d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
6329d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    // As a sanity check, make sure that the negation of the constraint
6339d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    // was infeasible in the current state.  If it is feasible, we somehow
6349d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    // missed the transition point.
6357db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com    if (N->getState()->assume(Constraint, !Assumption))
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      return NULL;
6377db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com
6387db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com    // We found the transition point for the constraint.  We now need to
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // pretty-print the constraint. (work-in-progress)
6401b27704eba15be4e9d1997faac42038493a30be5djsollen    std::string sbuf;
64182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    llvm::raw_string_ostream os(sbuf);
642cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com
643cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com    if (Constraint.getAs<Loc>()) {
644cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      os << "Assuming pointer value is ";
645cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      os << (Assumption ? "non-null" : "null");
646cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com    }
647cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com
648cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com    if (os.str().empty())
649cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com      return NULL;
6507db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // Construct a new PathDiagnosticPiece.
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ProgramPoint P = N->getLocation();
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    PathDiagnosticLocation L =
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      PathDiagnosticLocation::create(P, BRC.getSourceManager());
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!L.isValid())
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      return NULL;
6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    PathDiagnosticEventPiece *X = new PathDiagnosticEventPiece(L, os.str());
6599575fb8b1d505572dd9808af1697921fe48c021ebungeman@google.com    X->setTag(getTag());
6609575fb8b1d505572dd9808af1697921fe48c021ebungeman@google.com    return X;
6619575fb8b1d505572dd9808af1697921fe48c021ebungeman@google.com  }
6629575fb8b1d505572dd9808af1697921fe48c021ebungeman@google.com
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  return NULL;
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
666fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.combool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S,
667fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                                        BugReport &report, bool IsArg) {
668fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com  if (!S || !N)
669fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    return false;
670fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com
671fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com  if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S))
672fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    S = OVE->getSourceExpr();
673fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com
674fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com  if (IsArg) {
675fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    assert(N->getLocation().getAs<CallEnter>() && "Tracking arg but not at call");
676fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com  } else {
677fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // Walk through nodes until we get one that matches the statement exactly.
6787db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com    do {
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      const ProgramPoint &pp = N->getLocation();
6804bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com      if (Optional<PostStmt> ps = pp.getAs<PostStmt>()) {
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (ps->getStmt() == S)
6827db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com          break;
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      } else if (Optional<CallExitEnd> CEE = pp.getAs<CallExitEnd>()) {
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (CEE->getCalleeContext()->getCallSite() == S)
685fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com          break;
686fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com      }
687fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com      N = N->getFirstPred();
688fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    } while (N);
689fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!N)
69182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com      return false;
6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  }
6937db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  ProgramStateRef state = N->getState();
6957db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com
6967db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com  // See if the expression we're interested refers to a variable.
6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com  // If so, we can track both its contents and constraints on its value.
6987db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com  if (const Expr *Ex = dyn_cast<Expr>(S)) {
6997db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com    // Strip off parens and casts. Note that this will never have issues with
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // C++ user-defined implicit conversions, because those have a constructor
7017db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com    // or function call inside.
7027db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com    Ex = Ex->IgnoreParenCasts();
7037db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com
7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (ExplodedGraph::isInterestingLValueExpr(Ex)) {
7057db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com      const MemRegion *R = 0;
7067db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com
7077db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com      // First check if this is a DeclRefExpr for a C++ reference type.
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      // For those, we want the location of the reference.
7097db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
7117db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com          if (VD->getType()->isReferenceType()) {
7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ProgramStateManager &StateMgr = state->getStateManager();
71382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            MemRegionManager &MRMgr = StateMgr.getRegionManager();
7147db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com            R = MRMgr.getVarRegion(VD, N->getLocationContext());
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          }
7167db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com        }
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      }
71882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
7197db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com      // For all other cases, find the location by scouring the ExplodedGraph.
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      if (!R) {
7217db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com        // Find the ExplodedNode where the lvalue (the value of 'Ex')
7227db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com        // was computed.  We need this for getting the location value.
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const ExplodedNode *LVNode = N;
7247db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com        const Expr *SearchEx = Ex;
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (const OpaqueValueExpr *OPE = dyn_cast<OpaqueValueExpr>(Ex)) {
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          SearchEx = OPE->getSourceExpr();
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
728a9d4e84c435f61be3c02d7f54acab973e8b7761creed@google.com        while (LVNode) {
72950dd41017ad121b5f40f063d813ba517668fcfbcbungeman@google.com          if (Optional<PostStmt> P = LVNode->getLocation().getAs<PostStmt>()) {
73050dd41017ad121b5f40f063d813ba517668fcfbcbungeman@google.com            if (P->getStmt() == SearchEx)
73150dd41017ad121b5f40f063d813ba517668fcfbcbungeman@google.com              break;
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          }
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          LVNode = LVNode->getFirstPred();
734a9d4e84c435f61be3c02d7f54acab973e8b7761creed@google.com        }
735ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        assert(LVNode && "Unable to find the lvalue node.");
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ProgramStateRef LVState = LVNode->getState();
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (Optional<Loc> L =
738a9d4e84c435f61be3c02d7f54acab973e8b7761creed@google.com              LVState->getSVal(Ex, LVNode->getLocationContext()).getAs<Loc>()) {
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com          R = L->getAsRegion();
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com      }
7427db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com
7437db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com      if (R) {
7447db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com        // Mark both the variable region and its contents as interesting.
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SVal V = state->getRawSVal(loc::MemRegionVal(R));
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7472e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com        // If the value matches the default for the variable region, that
7482e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com        // might mean that it's been cleared out of the state. Fall back to
749fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        // the full argument expression (with casts and such intact).
7502e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com        if (IsArg) {
7512e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com          bool UseArgValue = V.isUnknownOrUndef() || V.isZeroConstant();
7522e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com          if (!UseArgValue) {
7532e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com            const SymbolRegionValue *SRV =
7542e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com              dyn_cast_or_null<SymbolRegionValue>(V.getAsLocSymbol());
7552e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com            if (SRV)
7562e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com              UseArgValue = (SRV->getRegion() == R);
7572e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com          }
7582e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com          if (UseArgValue)
75962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com            V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
76062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com        }
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        report.markInteresting(R);
76362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com        report.markInteresting(V);
76462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com        report.addVisitor(new UndefOrNullArgVisitor(R));
7650da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com
7660da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com        if (isa<SymbolicRegion>(R)) {
76762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com          TrackConstraintBRVisitor *VI =
76862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com            new TrackConstraintBRVisitor(loc::MemRegionVal(R), false);
769a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com          report.addVisitor(VI);
77062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com        }
77162900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com
772a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        // If the contents are symbolic, find out when they became null.
77362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com        if (V.getAsLocSymbol()) {
77462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com          BugReporterVisitor *ConstraintTracker =
775a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com              new TrackConstraintBRVisitor(V.castAs<DefinedSVal>(), false);
77662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com          report.addVisitor(ConstraintTracker);
77762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com        }
778a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com
77962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com        if (Optional<KnownSVal> KV = V.getAs<KnownSVal>())
78062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com          report.addVisitor(new FindLastStoreBRVisitor(*KV, R));
781a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        return true;
782a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com      }
783410780677af260e32948b02c0725ef6ad761260cbungeman    }
784410780677af260e32948b02c0725ef6ad761260cbungeman  }
785410780677af260e32948b02c0725ef6ad761260cbungeman
78662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com  // If the expression is not an "lvalue expression", we can still
78762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com  // track the constraints on its contents.
78862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com  SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
78962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com
790f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com  // If the value came from an inlined function call, we should at least make
791f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com  // sure that function isn't pruned in our output.
79284e22d847fc84727bc220947162363ee1fe068fcreed@google.com  if (const Expr *E = dyn_cast<Expr>(S))
79384e22d847fc84727bc220947162363ee1fe068fcreed@google.com    S = E->IgnoreParenCasts();
79484e22d847fc84727bc220947162363ee1fe068fcreed@google.com  ReturnVisitor::addVisitorIfNecessary(N, S, report);
79584e22d847fc84727bc220947162363ee1fe068fcreed@google.com
79684e22d847fc84727bc220947162363ee1fe068fcreed@google.com  // Uncomment this to find cases where we aren't properly getting the
7970da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com  // base value that was dereferenced.
7980da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com  // assert(!V.isUnknownOrUndef());
79962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com  // Is it a symbolic value?
80062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com  if (Optional<loc::MemRegionVal> L = V.getAs<loc::MemRegionVal>()) {
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // At this point we are dealing with the region's LValue.
802    // However, if the rvalue is a symbolic region, we should track it as well.
803    SVal RVal = state->getSVal(L->getRegion());
804    const MemRegion *RegionRVal = RVal.getAsRegion();
805    report.addVisitor(new UndefOrNullArgVisitor(L->getRegion()));
806
807    if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
808      report.markInteresting(RegionRVal);
809      report.addVisitor(new TrackConstraintBRVisitor(
810        loc::MemRegionVal(RegionRVal), false));
811    }
812  }
813
814  return true;
815}
816
817BugReporterVisitor *
818FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N,
819                                            const MemRegion *R) {
820  assert(R && "The memory region is null.");
821
822  ProgramStateRef state = N->getState();
823  if (Optional<KnownSVal> KV = state->getSVal(R).getAs<KnownSVal>())
824    return new FindLastStoreBRVisitor(*KV, R);
825  return 0;
826}
827
828PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
829                                                     const ExplodedNode *PrevN,
830                                                     BugReporterContext &BRC,
831                                                     BugReport &BR) {
832  Optional<PostStmt> P = N->getLocationAs<PostStmt>();
833  if (!P)
834    return 0;
835  const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
836  if (!ME)
837    return 0;
838  const Expr *Receiver = ME->getInstanceReceiver();
839  if (!Receiver)
840    return 0;
841  ProgramStateRef state = N->getState();
842  const SVal &V = state->getSVal(Receiver, N->getLocationContext());
843  Optional<DefinedOrUnknownSVal> DV = V.getAs<DefinedOrUnknownSVal>();
844  if (!DV)
845    return 0;
846  state = state->assume(*DV, true);
847  if (state)
848    return 0;
849
850  // The receiver was nil, and hence the method was skipped.
851  // Register a BugReporterVisitor to issue a message telling us how
852  // the receiver was null.
853  bugreporter::trackNullOrUndefValue(N, Receiver, BR);
854  // Issue a message saying that the method was skipped.
855  PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
856                                     N->getLocationContext());
857  return new PathDiagnosticEventPiece(L, "No method is called "
858      "because the receiver is nil");
859}
860
861// Registers every VarDecl inside a Stmt with a last store visitor.
862void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
863                                                       const Stmt *S) {
864  const ExplodedNode *N = BR.getErrorNode();
865  std::deque<const Stmt *> WorkList;
866  WorkList.push_back(S);
867
868  while (!WorkList.empty()) {
869    const Stmt *Head = WorkList.front();
870    WorkList.pop_front();
871
872    ProgramStateRef state = N->getState();
873    ProgramStateManager &StateMgr = state->getStateManager();
874
875    if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
876      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
877        const VarRegion *R =
878        StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
879
880        // What did we load?
881        SVal V = state->getSVal(S, N->getLocationContext());
882
883        if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
884          // Register a new visitor with the BugReport.
885          BR.addVisitor(new FindLastStoreBRVisitor(V.castAs<KnownSVal>(), R));
886        }
887      }
888    }
889
890    for (Stmt::const_child_iterator I = Head->child_begin();
891        I != Head->child_end(); ++I)
892      WorkList.push_back(*I);
893  }
894}
895
896//===----------------------------------------------------------------------===//
897// Visitor that tries to report interesting diagnostics from conditions.
898//===----------------------------------------------------------------------===//
899
900/// Return the tag associated with this visitor.  This tag will be used
901/// to make all PathDiagnosticPieces created by this visitor.
902const char *ConditionBRVisitor::getTag() {
903  return "ConditionBRVisitor";
904}
905
906PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N,
907                                                   const ExplodedNode *Prev,
908                                                   BugReporterContext &BRC,
909                                                   BugReport &BR) {
910  PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR);
911  if (piece) {
912    piece->setTag(getTag());
913    if (PathDiagnosticEventPiece *ev=dyn_cast<PathDiagnosticEventPiece>(piece))
914      ev->setPrunable(true, /* override */ false);
915  }
916  return piece;
917}
918
919PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
920                                                       const ExplodedNode *Prev,
921                                                       BugReporterContext &BRC,
922                                                       BugReport &BR) {
923
924  ProgramPoint progPoint = N->getLocation();
925  ProgramStateRef CurrentState = N->getState();
926  ProgramStateRef PrevState = Prev->getState();
927
928  // Compare the GDMs of the state, because that is where constraints
929  // are managed.  Note that ensure that we only look at nodes that
930  // were generated by the analyzer engine proper, not checkers.
931  if (CurrentState->getGDM().getRoot() ==
932      PrevState->getGDM().getRoot())
933    return 0;
934
935  // If an assumption was made on a branch, it should be caught
936  // here by looking at the state transition.
937  if (Optional<BlockEdge> BE = progPoint.getAs<BlockEdge>()) {
938    const CFGBlock *srcBlk = BE->getSrc();
939    if (const Stmt *term = srcBlk->getTerminator())
940      return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
941    return 0;
942  }
943
944  if (Optional<PostStmt> PS = progPoint.getAs<PostStmt>()) {
945    // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
946    // violation.
947    const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
948      cast<GRBugReporter>(BRC.getBugReporter()).
949        getEngine().geteagerlyAssumeBinOpBifurcationTags();
950
951    const ProgramPointTag *tag = PS->getTag();
952    if (tag == tags.first)
953      return VisitTrueTest(cast<Expr>(PS->getStmt()), true,
954                           BRC, BR, N);
955    if (tag == tags.second)
956      return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
957                           BRC, BR, N);
958
959    return 0;
960  }
961
962  return 0;
963}
964
965PathDiagnosticPiece *
966ConditionBRVisitor::VisitTerminator(const Stmt *Term,
967                                    const ExplodedNode *N,
968                                    const CFGBlock *srcBlk,
969                                    const CFGBlock *dstBlk,
970                                    BugReport &R,
971                                    BugReporterContext &BRC) {
972  const Expr *Cond = 0;
973
974  switch (Term->getStmtClass()) {
975  default:
976    return 0;
977  case Stmt::IfStmtClass:
978    Cond = cast<IfStmt>(Term)->getCond();
979    break;
980  case Stmt::ConditionalOperatorClass:
981    Cond = cast<ConditionalOperator>(Term)->getCond();
982    break;
983  }
984
985  assert(Cond);
986  assert(srcBlk->succ_size() == 2);
987  const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
988  return VisitTrueTest(Cond, tookTrue, BRC, R, N);
989}
990
991PathDiagnosticPiece *
992ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
993                                  bool tookTrue,
994                                  BugReporterContext &BRC,
995                                  BugReport &R,
996                                  const ExplodedNode *N) {
997
998  const Expr *Ex = Cond;
999
1000  while (true) {
1001    Ex = Ex->IgnoreParenCasts();
1002    switch (Ex->getStmtClass()) {
1003      default:
1004        return 0;
1005      case Stmt::BinaryOperatorClass:
1006        return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC,
1007                             R, N);
1008      case Stmt::DeclRefExprClass:
1009        return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC,
1010                             R, N);
1011      case Stmt::UnaryOperatorClass: {
1012        const UnaryOperator *UO = cast<UnaryOperator>(Ex);
1013        if (UO->getOpcode() == UO_LNot) {
1014          tookTrue = !tookTrue;
1015          Ex = UO->getSubExpr();
1016          continue;
1017        }
1018        return 0;
1019      }
1020    }
1021  }
1022}
1023
1024bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out,
1025                                      BugReporterContext &BRC,
1026                                      BugReport &report,
1027                                      const ExplodedNode *N,
1028                                      Optional<bool> &prunable) {
1029  const Expr *OriginalExpr = Ex;
1030  Ex = Ex->IgnoreParenCasts();
1031
1032  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
1033    const bool quotes = isa<VarDecl>(DR->getDecl());
1034    if (quotes) {
1035      Out << '\'';
1036      const LocationContext *LCtx = N->getLocationContext();
1037      const ProgramState *state = N->getState().getPtr();
1038      if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
1039                                                LCtx).getAsRegion()) {
1040        if (report.isInteresting(R))
1041          prunable = false;
1042        else {
1043          const ProgramState *state = N->getState().getPtr();
1044          SVal V = state->getSVal(R);
1045          if (report.isInteresting(V))
1046            prunable = false;
1047        }
1048      }
1049    }
1050    Out << DR->getDecl()->getDeclName().getAsString();
1051    if (quotes)
1052      Out << '\'';
1053    return quotes;
1054  }
1055
1056  if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
1057    QualType OriginalTy = OriginalExpr->getType();
1058    if (OriginalTy->isPointerType()) {
1059      if (IL->getValue() == 0) {
1060        Out << "null";
1061        return false;
1062      }
1063    }
1064    else if (OriginalTy->isObjCObjectPointerType()) {
1065      if (IL->getValue() == 0) {
1066        Out << "nil";
1067        return false;
1068      }
1069    }
1070
1071    Out << IL->getValue();
1072    return false;
1073  }
1074
1075  return false;
1076}
1077
1078PathDiagnosticPiece *
1079ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
1080                                  const BinaryOperator *BExpr,
1081                                  const bool tookTrue,
1082                                  BugReporterContext &BRC,
1083                                  BugReport &R,
1084                                  const ExplodedNode *N) {
1085
1086  bool shouldInvert = false;
1087  Optional<bool> shouldPrune;
1088
1089  SmallString<128> LhsString, RhsString;
1090  {
1091    llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
1092    const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N,
1093                                       shouldPrune);
1094    const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N,
1095                                       shouldPrune);
1096
1097    shouldInvert = !isVarLHS && isVarRHS;
1098  }
1099
1100  BinaryOperator::Opcode Op = BExpr->getOpcode();
1101
1102  if (BinaryOperator::isAssignmentOp(Op)) {
1103    // For assignment operators, all that we care about is that the LHS
1104    // evaluates to "true" or "false".
1105    return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
1106                                  BRC, R, N);
1107  }
1108
1109  // For non-assignment operations, we require that we can understand
1110  // both the LHS and RHS.
1111  if (LhsString.empty() || RhsString.empty())
1112    return 0;
1113
1114  // Should we invert the strings if the LHS is not a variable name?
1115  SmallString<256> buf;
1116  llvm::raw_svector_ostream Out(buf);
1117  Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
1118
1119  // Do we need to invert the opcode?
1120  if (shouldInvert)
1121    switch (Op) {
1122      default: break;
1123      case BO_LT: Op = BO_GT; break;
1124      case BO_GT: Op = BO_LT; break;
1125      case BO_LE: Op = BO_GE; break;
1126      case BO_GE: Op = BO_LE; break;
1127    }
1128
1129  if (!tookTrue)
1130    switch (Op) {
1131      case BO_EQ: Op = BO_NE; break;
1132      case BO_NE: Op = BO_EQ; break;
1133      case BO_LT: Op = BO_GE; break;
1134      case BO_GT: Op = BO_LE; break;
1135      case BO_LE: Op = BO_GT; break;
1136      case BO_GE: Op = BO_LT; break;
1137      default:
1138        return 0;
1139    }
1140
1141  switch (Op) {
1142    case BO_EQ:
1143      Out << "equal to ";
1144      break;
1145    case BO_NE:
1146      Out << "not equal to ";
1147      break;
1148    default:
1149      Out << BinaryOperator::getOpcodeStr(Op) << ' ';
1150      break;
1151  }
1152
1153  Out << (shouldInvert ? LhsString : RhsString);
1154  const LocationContext *LCtx = N->getLocationContext();
1155  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1156  PathDiagnosticEventPiece *event =
1157    new PathDiagnosticEventPiece(Loc, Out.str());
1158  if (shouldPrune.hasValue())
1159    event->setPrunable(shouldPrune.getValue());
1160  return event;
1161}
1162
1163PathDiagnosticPiece *
1164ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
1165                                           const Expr *CondVarExpr,
1166                                           const bool tookTrue,
1167                                           BugReporterContext &BRC,
1168                                           BugReport &report,
1169                                           const ExplodedNode *N) {
1170  // FIXME: If there's already a constraint tracker for this variable,
1171  // we shouldn't emit anything here (c.f. the double note in
1172  // test/Analysis/inlining/path-notes.c)
1173  SmallString<256> buf;
1174  llvm::raw_svector_ostream Out(buf);
1175  Out << "Assuming " << LhsString << " is ";
1176
1177  QualType Ty = CondVarExpr->getType();
1178
1179  if (Ty->isPointerType())
1180    Out << (tookTrue ? "not null" : "null");
1181  else if (Ty->isObjCObjectPointerType())
1182    Out << (tookTrue ? "not nil" : "nil");
1183  else if (Ty->isBooleanType())
1184    Out << (tookTrue ? "true" : "false");
1185  else if (Ty->isIntegerType())
1186    Out << (tookTrue ? "non-zero" : "zero");
1187  else
1188    return 0;
1189
1190  const LocationContext *LCtx = N->getLocationContext();
1191  PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
1192  PathDiagnosticEventPiece *event =
1193    new PathDiagnosticEventPiece(Loc, Out.str());
1194
1195  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
1196    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1197      const ProgramState *state = N->getState().getPtr();
1198      if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
1199        if (report.isInteresting(R))
1200          event->setPrunable(false);
1201      }
1202    }
1203  }
1204
1205  return event;
1206}
1207
1208PathDiagnosticPiece *
1209ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
1210                                  const DeclRefExpr *DR,
1211                                  const bool tookTrue,
1212                                  BugReporterContext &BRC,
1213                                  BugReport &report,
1214                                  const ExplodedNode *N) {
1215
1216  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
1217  if (!VD)
1218    return 0;
1219
1220  SmallString<256> Buf;
1221  llvm::raw_svector_ostream Out(Buf);
1222
1223  Out << "Assuming '";
1224  VD->getDeclName().printName(Out);
1225  Out << "' is ";
1226
1227  QualType VDTy = VD->getType();
1228
1229  if (VDTy->isPointerType())
1230    Out << (tookTrue ? "non-null" : "null");
1231  else if (VDTy->isObjCObjectPointerType())
1232    Out << (tookTrue ? "non-nil" : "nil");
1233  else if (VDTy->isScalarType())
1234    Out << (tookTrue ? "not equal to 0" : "0");
1235  else
1236    return 0;
1237
1238  const LocationContext *LCtx = N->getLocationContext();
1239  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1240  PathDiagnosticEventPiece *event =
1241    new PathDiagnosticEventPiece(Loc, Out.str());
1242
1243  const ProgramState *state = N->getState().getPtr();
1244  if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
1245    if (report.isInteresting(R))
1246      event->setPrunable(false);
1247    else {
1248      SVal V = state->getSVal(R);
1249      if (report.isInteresting(V))
1250        event->setPrunable(false);
1251    }
1252  }
1253  return event;
1254}
1255
1256PathDiagnosticPiece *
1257LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
1258                                                    const ExplodedNode *N,
1259                                                    BugReport &BR) {
1260  const Stmt *S = BR.getStmt();
1261  if (!S)
1262    return 0;
1263
1264  // Here we suppress false positives coming from system macros. This list is
1265  // based on known issues.
1266
1267  // Skip reports within the sys/queue.h macros as we do not have the ability to
1268  // reason about data structure shapes.
1269  SourceManager &SM = BRC.getSourceManager();
1270  SourceLocation Loc = S->getLocStart();
1271  while (Loc.isMacroID()) {
1272    if (SM.isInSystemMacro(Loc) &&
1273       (SM.getFilename(SM.getSpellingLoc(Loc)).endswith("sys/queue.h"))) {
1274      BR.markInvalid(getTag(), 0);
1275      return 0;
1276    }
1277    Loc = SM.getSpellingLoc(Loc);
1278  }
1279
1280  return 0;
1281}
1282
1283PathDiagnosticPiece *
1284UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
1285                                  const ExplodedNode *PrevN,
1286                                  BugReporterContext &BRC,
1287                                  BugReport &BR) {
1288
1289  ProgramStateRef State = N->getState();
1290  ProgramPoint ProgLoc = N->getLocation();
1291
1292  // We are only interested in visiting CallEnter nodes.
1293  Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>();
1294  if (!CEnter)
1295    return 0;
1296
1297  // Check if one of the arguments is the region the visitor is tracking.
1298  CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
1299  CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
1300  unsigned Idx = 0;
1301  for (CallEvent::param_iterator I = Call->param_begin(),
1302                                 E = Call->param_end(); I != E; ++I, ++Idx) {
1303    const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
1304
1305    // Are we tracking the argument or its subregion?
1306    if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts())))
1307      continue;
1308
1309    // Check the function parameter type.
1310    const ParmVarDecl *ParamDecl = *I;
1311    assert(ParamDecl && "Formal parameter has no decl?");
1312    QualType T = ParamDecl->getType();
1313
1314    if (!(T->isAnyPointerType() || T->isReferenceType())) {
1315      // Function can only change the value passed in by address.
1316      continue;
1317    }
1318
1319    // If it is a const pointer value, the function does not intend to
1320    // change the value.
1321    if (T->getPointeeType().isConstQualified())
1322      continue;
1323
1324    // Mark the call site (LocationContext) as interesting if the value of the
1325    // argument is undefined or '0'/'NULL'.
1326    SVal BoundVal = State->getSVal(R);
1327    if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
1328      BR.markInteresting(CEnter->getCalleeContext());
1329      return 0;
1330    }
1331  }
1332  return 0;
1333}
1334