BugReporter.h revision 62059e809596a419e6fc3e751b2f0b57b7cc51e7
161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// BugReporter.h - Generate PathDiagnostics  ----------*- C++ -*--//
261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//
361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//                     The LLVM Compiler Infrastructure
461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//
561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// This file is distributed under the University of Illinois Open Source
661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// License. See LICENSE.TXT for details.
761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//
861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//===----------------------------------------------------------------------===//
961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//
1061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//  This file defines BugReporter, a utility class for generating
114adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek//  PathDiagnostics for analyses based on GRState.
1261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//
1361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//===----------------------------------------------------------------------===//
1461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
1561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER
1661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#define LLVM_CLANG_ANALYSIS_BUGREPORTER
1761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
18e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek#include "clang/Basic/Diagnostic.h"
19d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek#include "clang/Basic/SourceLocation.h"
204adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek#include "clang/Analysis/PathSensitive/GRState.h"
2161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
2261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "llvm/ADT/SmallPtrSet.h"
23f377fc85488f4799ced714ac60e65a0e3f8f69cbTed Kremenek#include "llvm/ADT/SmallSet.h"
24cb61292aeafc1dc1bc4064fb3d2733717d1d50e5Ted Kremenek#include <vector>
25e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek#include <list>
26e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
2761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremeneknamespace clang {
2861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
2961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekclass PathDiagnostic;
3061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekclass PathDiagnosticPiece;
3161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekclass PathDiagnosticClient;
3261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekclass ASTContext;
3361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekclass Diagnostic;
3450a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenekclass BugReporter;
3550a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenekclass GRExprEngine;
364adc81e540b874bafa15715fd2c5cb662463debdTed Kremenekclass GRState;
37d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenekclass Stmt;
3895cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenekclass BugReport;
391a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenekclass ParentMap;
4050a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek
4150a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenekclass BugType {
4261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekpublic:
4350a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek  BugType() {}
4450a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek  virtual ~BugType();
4561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
4661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek  virtual const char* getName() const = 0;
4750a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek  virtual const char* getDescription() const { return getName(); }
488c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  virtual const char* getCategory() const { return ""; }
49072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek
50072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek  virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
51072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek    return std::pair<const char**, const char**>(0, 0);
52072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek  }
5350a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek
5450a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek  virtual void EmitWarnings(BugReporter& BR) {}
554adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek  virtual void GetErrorNodes(std::vector<ExplodedNode<GRState>*>& Nodes) {}
5695cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek
5795cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek  virtual bool isCached(BugReport& R) = 0;
5895cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek};
5995cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek
6095cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenekclass BugTypeCacheLocation : public BugType {
61d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  llvm::SmallSet<ProgramPoint,10> CachedErrors;
6295cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenekpublic:
6395cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek  BugTypeCacheLocation() {}
6495cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek  virtual ~BugTypeCacheLocation() {}
6595cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek  virtual bool isCached(BugReport& R);
6676d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek  bool isCached(ProgramPoint P);
6750a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek};
6861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
6995cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek
7050a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenekclass BugReport {
7195cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek  BugType& Desc;
724adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek  ExplodedNode<GRState> *EndNode;
73bb77e9b908658b354b058509d3801f3aed052becTed Kremenek  SourceRange R;
7450a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenekpublic:
754adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek  BugReport(BugType& D, ExplodedNode<GRState> *n) : Desc(D), EndNode(n) {}
7650a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek  virtual ~BugReport();
7750a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek
7850a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek  const BugType& getBugType() const { return Desc; }
7995cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek  BugType& getBugType() { return Desc; }
80d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
814adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek  ExplodedNode<GRState>* getEndNode() const { return EndNode; }
82d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
83bb77e9b908658b354b058509d3801f3aed052becTed Kremenek  Stmt* getStmt(BugReporter& BR) const;
8450a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek
8550a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek  const char* getName() const { return getBugType().getName(); }
864d35dacf85fc9fb257baa1a846abef2361a1c426Ted Kremenek
874d35dacf85fc9fb257baa1a846abef2361a1c426Ted Kremenek  virtual const char* getDescription() const {
884d35dacf85fc9fb257baa1a846abef2361a1c426Ted Kremenek    return getBugType().getDescription();
894d35dacf85fc9fb257baa1a846abef2361a1c426Ted Kremenek  }
9061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
918c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  virtual const char* getCategory() const {
928c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek    return getBugType().getCategory();
938c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  }
948c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek
95072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek  virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
96072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek    return getBugType().getExtraDescriptiveText();
97072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek  }
98072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek
99bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek  virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1004adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek                                          ExplodedNode<GRState>* N);
101d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
102d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  virtual FullSourceLoc getLocation(SourceManager& Mgr);
103f1ae705460552655fe7275327804444c62e86baeTed Kremenek
104bb77e9b908658b354b058509d3801f3aed052becTed Kremenek  virtual void getRanges(BugReporter& BR,const SourceRange*& beg,
105bb77e9b908658b354b058509d3801f3aed052becTed Kremenek                         const SourceRange*& end);
1066837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek
1074adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek  virtual PathDiagnosticPiece* VisitNode(ExplodedNode<GRState>* N,
1084adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek                                         ExplodedNode<GRState>* PrevN,
1094adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek                                         ExplodedGraph<GRState>& G,
1108dd564630c901d6d62dd2ffd4110b613d0055078Ted Kremenek                                         BugReporter& BR);
1116837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek};
1126837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek
113d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenekclass RangedBugReport : public BugReport {
1145e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek  std::vector<SourceRange> Ranges;
11522bda887aacd0e591978541a799aa43835652ec9Ted Kremenek  const char* desc;
1165e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenekpublic:
1174adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek  RangedBugReport(BugType& D, ExplodedNode<GRState> *n,
11822bda887aacd0e591978541a799aa43835652ec9Ted Kremenek                  const char* description = 0)
11922bda887aacd0e591978541a799aa43835652ec9Ted Kremenek    : BugReport(D, n), desc(description) {}
120d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
1215e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek  virtual ~RangedBugReport();
12222bda887aacd0e591978541a799aa43835652ec9Ted Kremenek
12322bda887aacd0e591978541a799aa43835652ec9Ted Kremenek  virtual const char* getDescription() const {
12422bda887aacd0e591978541a799aa43835652ec9Ted Kremenek    return desc ? desc : BugReport::getDescription();
12522bda887aacd0e591978541a799aa43835652ec9Ted Kremenek  }
1265e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek
1275e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek  void addRange(SourceRange R) { Ranges.push_back(R); }
1285e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek
12922bda887aacd0e591978541a799aa43835652ec9Ted Kremenek
130bb77e9b908658b354b058509d3801f3aed052becTed Kremenek  virtual void getRanges(BugReporter& BR,const SourceRange*& beg,
131bb77e9b908658b354b058509d3801f3aed052becTed Kremenek                         const SourceRange*& end) {
1325e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek
1335e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek    if (Ranges.empty()) {
1345e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek      beg = NULL;
1355e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek      end = NULL;
1365e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek    }
1375e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek    else {
1385e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek      beg = &Ranges[0];
1395e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek      end = beg + Ranges.size();
1405e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek    }
1415e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek  }
1425e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek};
1435e55cda64f4452fa65d83f66390c7126a8b248bbTed Kremenek
144c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenekclass BugReporterData {
145c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenekpublic:
146c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  virtual ~BugReporterData();
147c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  virtual Diagnostic& getDiagnostic() = 0;
148c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  virtual PathDiagnosticClient* getPathDiagnosticClient() = 0;
149c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  virtual ASTContext& getContext() = 0;
150c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  virtual SourceManager& getSourceManager() = 0;
1517032f460fc9828f386056e75933da5af61e88638Ted Kremenek  virtual CFG* getCFG() = 0;
152c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  virtual ParentMap& getParentMap() = 0;
1537032f460fc9828f386056e75933da5af61e88638Ted Kremenek  virtual LiveVariables* getLiveVariables() = 0;
154c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek};
155c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek
15661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekclass BugReporter {
157c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenekpublic:
158c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  enum Kind { BaseBRKind, GRBugReporterKind };
159c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek
160c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenekprotected:
161c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  Kind kind;
162c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  BugReporterData& D;
163c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek
164c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  BugReporter(BugReporterData& d, Kind k) : kind(k), D(d) {}
16561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
16661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekpublic:
167c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  BugReporter(BugReporterData& d) : kind(BaseBRKind), D(d) {}
168c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  virtual ~BugReporter();
16950a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek
170c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  Kind getKind() const { return kind; }
17161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
172c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  Diagnostic& getDiagnostic() {
173c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    return D.getDiagnostic();
174c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
17550a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek
176c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  PathDiagnosticClient* getPathDiagnosticClient() {
177c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    return D.getPathDiagnosticClient();
178c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
17961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
180c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  ASTContext& getContext() {
181c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    return D.getContext();
182c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
18361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
184c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  SourceManager& getSourceManager() {
185e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek    return D.getSourceManager();
186c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
187c9fa2f7bcc3061aa8bcdbe0df26d2c7cf7281539Ted Kremenek
1887032f460fc9828f386056e75933da5af61e88638Ted Kremenek  CFG* getCFG() {
189c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    return D.getCFG();
190c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
191c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek
192c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  ParentMap& getParentMap() {
193c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    return D.getParentMap();
194c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
195c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek
1967032f460fc9828f386056e75933da5af61e88638Ted Kremenek  LiveVariables* getLiveVariables() {
197c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    return D.getLiveVariables();
198c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
199c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek
200c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  virtual void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R) {}
20161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
202c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  void EmitWarning(BugReport& R);
20350a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek
20457202071e477530e9348bc76671ee369b2399b92Ted Kremenek  void EmitBasicReport(const char* BugName, const char* BugStr,
2058f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek                       SourceLocation Loc,
2068f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek                       SourceRange* RangeBeg, unsigned NumRanges);
2078f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek
2088c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  void EmitBasicReport(const char* BugName, const char* BugCategory,
2098c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                       const char* BugStr, SourceLocation Loc,
2108c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                       SourceRange* RangeBeg, unsigned NumRanges);
2118c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek
2128c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek
2138f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek  void EmitBasicReport(const char* BugName, const char* BugStr,
2148f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek                       SourceLocation Loc) {
2158f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek    EmitBasicReport(BugName, BugStr, Loc, 0, 0);
2168f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek  }
2178f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek
21862059e809596a419e6fc3e751b2f0b57b7cc51e7Ted Kremenek  void EmitBasicReport(const char* BugName, const char* BugCategory,
21962059e809596a419e6fc3e751b2f0b57b7cc51e7Ted Kremenek                       const char* BugStr, SourceLocation Loc) {
22062059e809596a419e6fc3e751b2f0b57b7cc51e7Ted Kremenek    EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0);
22162059e809596a419e6fc3e751b2f0b57b7cc51e7Ted Kremenek  }
22262059e809596a419e6fc3e751b2f0b57b7cc51e7Ted Kremenek
2238f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek  void EmitBasicReport(const char* BugName, const char* BugStr,
2248f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek                       SourceLocation Loc, SourceRange R) {
2258f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek    EmitBasicReport(BugName, BugStr, Loc, &R, 1);
2268f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek  }
22757202071e477530e9348bc76671ee369b2399b92Ted Kremenek
2288c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  void EmitBasicReport(const char* BugName, const char* Category,
2298c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                       const char* BugStr, SourceLocation Loc, SourceRange R) {
2308c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek    EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1);
2318c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  }
2328c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek
233c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  static bool classof(const BugReporter* R) { return true; }
234c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek};
235f377fc85488f4799ced714ac60e65a0e3f8f69cbTed Kremenek
236c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenekclass GRBugReporter : public BugReporter {
237c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  GRExprEngine& Eng;
238c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  llvm::SmallSet<SymbolID, 10> NotableSymbols;
239c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenekpublic:
240bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek
241c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  GRBugReporter(BugReporterData& d, GRExprEngine& eng)
242c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    : BugReporter(d, GRBugReporterKind), Eng(eng) {}
2431a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
244c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  virtual ~GRBugReporter();
245c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek
246cfdf9b4edf1172728be97d1ae2d95171975f812bTed Kremenek  /// getEngine - Return the analysis engine used to analyze a given
247cfdf9b4edf1172728be97d1ae2d95171975f812bTed Kremenek  ///  function or method.
248c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  GRExprEngine& getEngine() {
249c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    return Eng;
250c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
251c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek
252cfdf9b4edf1172728be97d1ae2d95171975f812bTed Kremenek  /// getGraph - Get the exploded graph created by the analysis engine
253cfdf9b4edf1172728be97d1ae2d95171975f812bTed Kremenek  ///  for the analyzed method or function.
2544adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek  ExplodedGraph<GRState>& getGraph();
25561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
256cfdf9b4edf1172728be97d1ae2d95171975f812bTed Kremenek  /// getStateManager - Return the state manager used by the analysis
257cfdf9b4edf1172728be97d1ae2d95171975f812bTed Kremenek  ///  engine.
2584adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek  GRStateManager& getStateManager();
259f377fc85488f4799ced714ac60e65a0e3f8f69cbTed Kremenek
260c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  virtual void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R);
261c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek
262c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  void addNotableSymbol(SymbolID Sym) {
263c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    NotableSymbols.insert(Sym);
264c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
265c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek
266c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  bool isNotable(SymbolID Sym) const {
267c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    return (bool) NotableSymbols.count(Sym);
268c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
269cfdf9b4edf1172728be97d1ae2d95171975f812bTed Kremenek
270cfdf9b4edf1172728be97d1ae2d95171975f812bTed Kremenek  /// classof - Used by isa<>, cast<>, and dyn_cast<>.
271c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  static bool classof(const BugReporter* R) {
272c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek    return R->getKind() == GRBugReporterKind;
273c095997b853270d8adb6fe55209a4dbc42803d16Ted Kremenek  }
27461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek};
27561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
276e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
277e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenekclass DiagBugReport : public RangedBugReport {
278e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  std::list<std::string> Strs;
279e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  FullSourceLoc L;
280e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  const char* description;
281e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenekpublic:
282e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  DiagBugReport(const char* desc, BugType& D, FullSourceLoc l) :
283e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  RangedBugReport(D, NULL), L(l), description(desc) {}
284e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
285e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  virtual ~DiagBugReport() {}
286e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  virtual FullSourceLoc getLocation(SourceManager&) { return L; }
287e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
288e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  virtual const char* getDescription() const {
289e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek    return description;
290e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  }
291e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
292e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  void addString(const std::string& s) { Strs.push_back(s); }
293e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
294e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  typedef std::list<std::string>::const_iterator str_iterator;
295e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  str_iterator str_begin() const { return Strs.begin(); }
296e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  str_iterator str_end() const { return Strs.end(); }
297e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek};
298e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
299e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenekclass DiagCollector : public DiagnosticClient {
300e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  std::list<DiagBugReport> Reports;
301e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  BugType& D;
302e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenekpublic:
303e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  DiagCollector(BugType& d) : D(d) {}
304e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
305e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  virtual ~DiagCollector() {}
306e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
307e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  virtual void HandleDiagnostic(Diagnostic &Diags,
308e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek                                Diagnostic::Level DiagLevel,
309e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek                                FullSourceLoc Pos,
310e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek                                diag::kind ID,
311e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek                                const std::string *Strs,
312e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek                                unsigned NumStrs,
313e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek                                const SourceRange *Ranges,
314e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek                                unsigned NumRanges) {
315e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
316e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek    // FIXME: Use a map from diag::kind to BugType, instead of having just
317e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek    //  one BugType.
318e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
319e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek    Reports.push_back(DiagBugReport(Diags.getDescription(ID), D, Pos));
320e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek    DiagBugReport& R = Reports.back();
321e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
322e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek    for ( ; NumRanges ; --NumRanges, ++Ranges)
323e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek      R.addRange(*Ranges);
324e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
325e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek    for ( ; NumStrs ; --NumStrs, ++Strs)
326e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek      R.addString(*Strs);
327e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  }
328e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
329e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  // Iterators.
330e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
331e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  typedef std::list<DiagBugReport>::iterator iterator;
332e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  iterator begin() { return Reports.begin(); }
333e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek  iterator end() { return Reports.end(); }
334e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek};
335e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
336db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenekclass SimpleBugType : public BugTypeCacheLocation {
337584def7364f51e35bfcaf5c3c64673096533addaTed Kremenek  const char* name;
3388c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  const char* category;
339584def7364f51e35bfcaf5c3c64673096533addaTed Kremenek  const char* desc;
340db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenekpublic:
3418c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  SimpleBugType(const char* n) : name(n), category(""), desc(0) {}
3428c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  SimpleBugType(const char* n, const char* c, const char* d)
3438c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek    : name(n), category(c), desc(d) {}
344db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
345db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek  virtual const char* getName() const { return name; }
3468c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  virtual const char* getDescription() const { return desc ? desc : name; }
3478c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  virtual const char* getCategory() const { return category; }
348db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek};
349db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
35061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} // end clang namespace
35161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
35261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#endif
353