BugReporter.h revision 686775deca8b8685eb90801495880e3abdd844c2
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===---  BugReporter.h - Generate PathDiagnostics --------------*- C++ -*-===//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//  This file defines BugReporter, a utility class for generating
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//  PathDiagnostics for analyses based on GRState.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef LLVM_CLANG_GR_BUGREPORTER
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define LLVM_CLANG_GR_BUGREPORTER
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Basic/SourceLocation.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/FoldingSet.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/ImmutableList.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/ImmutableSet.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/SmallSet.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace clang {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ASTContext;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Diagnostic;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Stmt;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ParentMap;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ento {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PathDiagnostic;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PathDiagnosticPiece;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PathDiagnosticClient;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExplodedNode;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExplodedGraph;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BugReporter;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BugReporterContext;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExprEngine;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GRState;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BugType;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Interface for individual bug reports.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BugReporterVisitor : public llvm::FoldingSetNode {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BugReporterVisitor();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PathDiagnosticPiece* VisitNode(const ExplodedNode* N,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const ExplodedNode* PrevN,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         BugReporterContext& BRC) = 0;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool isOwnedByReporterContext() { return true; }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FIXME: Combine this with RangedBugReport and remove RangedBugReport.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BugReport : public BugReporterVisitor {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)protected:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BugType& BT;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string ShortDescription;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string Description;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ExplodedNode *ErrorNode;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable SourceRange R;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)protected:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class BugReporter;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class BugReportEquivClass;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Profile(llvm::FoldingSetNodeID& hash) const {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash.AddPointer(&BT);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash.AddInteger(getLocation().getRawEncoding());
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash.AddString(Description);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class NodeResolver {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~NodeResolver() {}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual const ExplodedNode*
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            getOriginalNode(const ExplodedNode* N) = 0;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : BT(bt), Description(desc), ErrorNode(errornode) {}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BugReport(BugType& bt, StringRef shortDesc, StringRef desc,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const ExplodedNode *errornode)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : BT(bt), ShortDescription(shortDesc), Description(desc),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ErrorNode(errornode) {}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BugReport();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool isOwnedByReporterContext() { return false; }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BugType& getBugType() const { return BT; }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BugType& getBugType() { return BT; }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIXME: Perhaps this should be moved into a subclass?
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ExplodedNode* getErrorNode() const { return ErrorNode; }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIXME: Do we need this?  Maybe getLocation() should return a ProgramPoint
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // object.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIXME: If we do need it, we can probably just make it private to
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BugReporter.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Stmt* getStmt() const;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const StringRef getDescription() const { return Description; }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const StringRef getShortDescription() const {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ShortDescription.empty() ? Description : ShortDescription;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIXME: Is this needed?
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::make_pair((const char**)0,(const char**)0);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIXME: Perhaps move this into a subclass.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PathDiagnosticPiece* getEndPath(BugReporterContext& BRC,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const ExplodedNode* N);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// getLocation - Return the "definitive" location of the reported bug.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///  While a bug can span an entire path, usually there is a specific
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///  location that can be used to identify where the key issue occurred.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///  This location is used by clients rendering diagnostics.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual SourceLocation getLocation() const;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef const SourceRange *ranges_iterator;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// getRanges - Returns the source ranges associated with this bug.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::pair<ranges_iterator, ranges_iterator> getRanges() const;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PathDiagnosticPiece* VisitNode(const ExplodedNode* N,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const ExplodedNode* PrevN,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         BugReporterContext& BR);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void registerInitialVisitors(BugReporterContext& BRC,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const ExplodedNode* N) {}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BugTypes (collections of related reports).
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BugReportEquivClass : public llvm::FoldingSetNode {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // List of *owned* BugReport objects.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::list<BugReport*> Reports;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class BugReporter;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddReport(BugReport* R) { Reports.push_back(R); }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BugReportEquivClass(BugReport* R) { Reports.push_back(R); }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~BugReportEquivClass();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Profile(llvm::FoldingSetNodeID& ID) const {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(!Reports.empty());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*Reports.begin())->Profile(ID);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class iterator {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::list<BugReport*>::iterator impl;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iterator(std::list<BugReport*>::iterator i) : impl(i) {}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iterator& operator++() { ++impl; return *this; }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool operator==(const iterator& I) const { return I.impl == impl; }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool operator!=(const iterator& I) const { return I.impl != impl; }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BugReport* operator*() const { return *impl; }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BugReport* operator->() const { return *impl; }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class const_iterator {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::list<BugReport*>::const_iterator impl;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const_iterator(std::list<BugReport*>::const_iterator i) : impl(i) {}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const_iterator& operator++() { ++impl; return *this; }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool operator==(const const_iterator& I) const { return I.impl == impl; }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool operator!=(const const_iterator& I) const { return I.impl != impl; }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BugReport* operator*() const { return *impl; }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BugReport* operator->() const { return *impl; }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iterator begin() { return iterator(Reports.begin()); }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iterator end() { return iterator(Reports.end()); }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const_iterator begin() const { return const_iterator(Reports.begin()); }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const_iterator end() const { return const_iterator(Reports.end()); }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Specialized subclasses of BugReport.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FIXME: Collapse this with the default BugReport class.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RangedBugReport : public BugReport {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SmallVector<SourceRange, 4> Ranges;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RangedBugReport(BugType& D, StringRef description,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  ExplodedNode *errornode)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : BugReport(D, description, errornode) {}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RangedBugReport(BugType& D, StringRef shortDescription,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  StringRef description, ExplodedNode *errornode)
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  : BugReport(D, shortDescription, description, errornode) {}
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ~RangedBugReport();
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // FIXME: Move this out of line.
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void addRange(SourceRange R) {
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    assert(R.isValid());
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Ranges.push_back(R);
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual std::pair<ranges_iterator, ranges_iterator> getRanges() const {
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return std::make_pair(Ranges.begin(), Ranges.end());
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void Profile(llvm::FoldingSetNodeID& hash) const {
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BugReport::Profile(hash);
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (SmallVectorImpl<SourceRange>::const_iterator I =
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          Ranges.begin(), E = Ranges.end(); I != E; ++I) {
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const SourceRange range = *I;
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!range.isValid())
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        continue;
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      hash.AddInteger(range.getBegin().getRawEncoding());
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      hash.AddInteger(range.getEnd().getRawEncoding());
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class EnhancedBugReport : public RangedBugReport {
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public:
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef void (*VisitorCreator)(BugReporterContext &BRcC, const void *data,
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 const ExplodedNode *N);
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private:
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::vector<std::pair<VisitorCreator, const void*> > Creators;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Creators creators;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnhancedBugReport(BugType& D, StringRef description,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ExplodedNode *errornode)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   : RangedBugReport(D, description, errornode) {}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnhancedBugReport(BugType& D, StringRef shortDescription,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   StringRef description, ExplodedNode *errornode)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : RangedBugReport(D, shortDescription, description, errornode) {}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ~EnhancedBugReport() {}
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void registerInitialVisitors(BugReporterContext& BRC, const ExplodedNode* N) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (Creators::iterator I = creators.begin(), E = creators.end(); I!=E; ++I)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      I->first(BRC, I->second, N);
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void addVisitorCreator(VisitorCreator creator, const void *data) {
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    creators.push_back(std::make_pair(creator, data));
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BugReporter and friends.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class BugReporterData {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BugReporterData();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Diagnostic& getDiagnostic() = 0;
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual PathDiagnosticClient* getPathDiagnosticClient() = 0;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ASTContext& getASTContext() = 0;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual SourceManager& getSourceManager() = 0;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BugReporter {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Kind { BaseBRKind, GRBugReporterKind };
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)private:
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef llvm::ImmutableSet<BugType*> BugTypesTy;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BugTypesTy::Factory F;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BugTypesTy BugTypes;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Kind kind;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BugReporterData& D;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FlushReport(BugReportEquivClass& EQ);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  llvm::FoldingSet<BugReportEquivClass> EQClasses;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)protected:
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k),
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            D(d) {}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public:
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind),
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    D(d) {}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BugReporter();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FlushReports();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Kind getKind() const { return kind; }
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Diagnostic& getDiagnostic() {
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return D.getDiagnostic();
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathDiagnosticClient* getPathDiagnosticClient() {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return D.getPathDiagnosticClient();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  typedef BugTypesTy::iterator iterator;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iterator begin() { return BugTypes.begin(); }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iterator end() { return BugTypes.end(); }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EQClasses_iterator EQClasses_end() { return EQClasses.end(); }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASTContext& getContext() { return D.getASTContext(); }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SourceManager& getSourceManager() { return D.getSourceManager(); }
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void GeneratePathDiagnostic(PathDiagnostic& pathDiagnostic,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SmallVectorImpl<BugReport *> &bugReports) {}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Register(BugType *BT);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitReport(BugReport *R);
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void EmitBasicReport(StringRef BugName, StringRef BugStr,
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       SourceLocation Loc,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       SourceRange* RangeBeg, unsigned NumRanges);
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitBasicReport(StringRef BugName, StringRef BugCategory,
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       StringRef BugStr, SourceLocation Loc,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       SourceRange* RangeBeg, unsigned NumRanges);
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitBasicReport(StringRef BugName, StringRef BugStr,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       SourceLocation Loc) {
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EmitBasicReport(BugName, BugStr, Loc, 0, 0);
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void EmitBasicReport(StringRef BugName, StringRef BugCategory,
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       StringRef BugStr, SourceLocation Loc) {
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitBasicReport(StringRef BugName, StringRef BugStr,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       SourceLocation Loc, SourceRange R) {
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EmitBasicReport(BugName, BugStr, Loc, &R, 1);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitBasicReport(StringRef BugName, StringRef Category,
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       StringRef BugStr, SourceLocation Loc,
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       SourceRange R) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool classof(const BugReporter* R) { return true; }
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)private:
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  llvm::StringMap<BugType *> StrBugTypes;
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// \brief Returns a BugType that is associated with the given name and
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /// category.
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BugType *getBugTypeForName(StringRef name, StringRef category);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FIXME: Get rid of GRBugReporter.  It's the wrong abstraction.
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GRBugReporter : public BugReporter {
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExprEngine& Eng;
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  llvm::SmallSet<SymbolRef, 10> NotableSymbols;
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public:
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GRBugReporter(BugReporterData& d, ExprEngine& eng)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : BugReporter(d, GRBugReporterKind), Eng(eng) {}
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~GRBugReporter();
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// getEngine - Return the analysis engine used to analyze a given
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ///  function or method.
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExprEngine &getEngine() { return Eng; }
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /// getGraph - Get the exploded graph created by the analysis engine
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ///  for the analyzed method or function.
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExplodedGraph &getGraph();
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// getStateManager - Return the state manager used by the analysis
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ///  engine.
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GRStateManager &getStateManager();
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic,
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     SmallVectorImpl<BugReport*> &bugReports);
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void addNotableSymbol(SymbolRef Sym) {
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotableSymbols.insert(Sym);
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool isNotable(SymbolRef Sym) const {
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return (bool) NotableSymbols.count(Sym);
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// classof - Used by isa<>, cast<>, and dyn_cast<>.
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static bool classof(const BugReporter* R) {
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return R->getKind() == GRBugReporterKind;
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class BugReporterContext {
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GRBugReporter &BR;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Not the most efficient data structure, but we use an ImmutableList for the
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Callbacks because it is safe to make additions to list during iteration.
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  llvm::ImmutableList<BugReporterVisitor*>::Factory F;
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  llvm::ImmutableList<BugReporterVisitor*> Callbacks;
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public:
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BugReporterContext(GRBugReporter& br) : BR(br), Callbacks(F.getEmptyList()) {}
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~BugReporterContext();
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void addVisitor(BugReporterVisitor* visitor);
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef llvm::ImmutableList<BugReporterVisitor*>::iterator visitor_iterator;
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  visitor_iterator visitor_begin() { return Callbacks.begin(); }
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  visitor_iterator visitor_end() { return Callbacks.end(); }
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GRBugReporter& getBugReporter() { return BR; }
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExplodedGraph &getGraph() { return BR.getGraph(); }
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void addNotableSymbol(SymbolRef Sym) {
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // FIXME: For now forward to GRBugReporter.
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BR.addNotableSymbol(Sym);
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool isNotable(SymbolRef Sym) const {
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // FIXME: For now forward to GRBugReporter.
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return BR.isNotable(Sym);
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GRStateManager& getStateManager() {
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return BR.getStateManager();
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SValBuilder& getSValBuilder() {
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return getStateManager().getSValBuilder();
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASTContext& getASTContext() {
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return BR.getContext();
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SourceManager& getSourceManager() {
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return BR.getSourceManager();
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual BugReport::NodeResolver& getNodeResolver() = 0;
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DiagBugReport : public RangedBugReport {
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::list<std::string> Strs;
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FullSourceLoc L;
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public:
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DiagBugReport(BugType& D, StringRef desc, FullSourceLoc l) :
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RangedBugReport(D, desc, 0), L(l) {}
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~DiagBugReport() {}
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // FIXME: Move out-of-line (virtual function).
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SourceLocation getLocation() const { return L; }
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void addString(StringRef s) { Strs.push_back(s); }
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  typedef std::list<std::string>::const_iterator str_iterator;
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  str_iterator str_begin() const { return Strs.begin(); }
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  str_iterator str_end() const { return Strs.end(); }
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace bugreporter {
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const Stmt *GetDerefExpr(const ExplodedNode *N);
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const Stmt *GetDenomExpr(const ExplodedNode *N);
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const Stmt *GetCalleeExpr(const ExplodedNode *N);
491const Stmt *GetRetValExpr(const ExplodedNode *N);
492
493void registerTrackNullOrUndefValue(BugReporterContext& BRC, const void *stmt,
494                                   const ExplodedNode* N);
495
496void registerFindLastStore(BugReporterContext& BRC, const void *memregion,
497                           const ExplodedNode *N);
498
499void registerNilReceiverVisitor(BugReporterContext &BRC);
500
501void registerVarDeclsLastStore(BugReporterContext &BRC, const void *stmt,
502                               const ExplodedNode *N);
503
504} // end namespace clang::bugreporter
505
506//===----------------------------------------------------------------------===//
507
508} // end GR namespace
509
510} // end clang namespace
511
512#endif
513