aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/PlistDiagnostics.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-06-15 17:48:49 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-06-15 17:48:49 +0000
commit9b414d3e2d0cb84512b55a3275a98490b090162a (patch)
treea9e89bf09e843286a73c99a9e18520c48ad725b0 /lib/Frontend/PlistDiagnostics.cpp
parentc722ea4fbf886d6460b256b5e819a4ee751d5fff (diff)
Break Frontend's dependency on Rewrite, Checker and CodeGen in shared library configuration
Currently, all AST consumers are located in the Frontend library, meaning that in a shared library configuration, Frontend has a dependency on Rewrite, Checker and CodeGen. This is suboptimal for clients which only wish to make use of the frontend. CodeGen in particular introduces a large number of unwanted dependencies. This patch breaks the dependency by moving all AST consumers with dependencies on Rewrite, Checker and/or CodeGen to their respective libraries. The patch therefore introduces dependencies in the other direction (i.e. from Rewrite, Checker and CodeGen to Frontend). After applying this patch, Clang builds correctly using CMake and shared libraries ("cmake -DBUILD_SHARED_LIBS=ON"). N.B. This patch includes file renames which are indicated in the patch body. Changes in this revision of the patch: - Fixed some copy-paste mistakes in the header files - Modified certain aspects of the coding to comply with the LLVM Coding Standards git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106010 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/PlistDiagnostics.cpp')
-rw-r--r--lib/Frontend/PlistDiagnostics.cpp471
1 files changed, 0 insertions, 471 deletions
diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp
deleted file mode 100644
index 5706a07e5a..0000000000
--- a/lib/Frontend/PlistDiagnostics.cpp
+++ /dev/null
@@ -1,471 +0,0 @@
-//===--- PlistDiagnostics.cpp - Plist Diagnostics for Paths -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the PlistDiagnostics object.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/PathDiagnosticClients.h"
-#include "clang/Checker/BugReporter/PathDiagnostic.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Lex/Preprocessor.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-using namespace clang;
-using llvm::cast;
-
-typedef llvm::DenseMap<FileID, unsigned> FIDMap;
-
-namespace clang {
- class Preprocessor;
-}
-
-namespace {
-struct CompareDiagnostics {
- // Compare if 'X' is "<" than 'Y'.
- bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const {
- // First compare by location
- const FullSourceLoc &XLoc = X->getLocation().asLocation();
- const FullSourceLoc &YLoc = Y->getLocation().asLocation();
- if (XLoc < YLoc)
- return true;
- if (XLoc != YLoc)
- return false;
-
- // Next, compare by bug type.
- llvm::StringRef XBugType = X->getBugType();
- llvm::StringRef YBugType = Y->getBugType();
- if (XBugType < YBugType)
- return true;
- if (XBugType != YBugType)
- return false;
-
- // Next, compare by bug description.
- llvm::StringRef XDesc = X->getDescription();
- llvm::StringRef YDesc = Y->getDescription();
- if (XDesc < YDesc)
- return true;
- if (XDesc != YDesc)
- return false;
-
- // FIXME: Further refine by comparing PathDiagnosticPieces?
- return false;
- }
-};
-}
-
-namespace {
- class PlistDiagnostics : public PathDiagnosticClient {
- std::vector<const PathDiagnostic*> BatchedDiags;
- const std::string OutputFile;
- const LangOptions &LangOpts;
- llvm::OwningPtr<PathDiagnosticClient> SubPD;
- bool flushed;
- public:
- PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
- PathDiagnosticClient *subPD);
-
- ~PlistDiagnostics() { FlushDiagnostics(NULL); }
-
- void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
-
- void HandlePathDiagnostic(const PathDiagnostic* D);
-
- virtual llvm::StringRef getName() const {
- return "PlistDiagnostics";
- }
-
- PathGenerationScheme getGenerationScheme() const;
- bool supportsLogicalOpControlFlow() const { return true; }
- bool supportsAllBlockEdges() const { return true; }
- virtual bool useVerboseDescription() const { return false; }
- };
-} // end anonymous namespace
-
-PlistDiagnostics::PlistDiagnostics(const std::string& output,
- const LangOptions &LO,
- PathDiagnosticClient *subPD)
- : OutputFile(output), LangOpts(LO), SubPD(subPD), flushed(false) {}
-
-PathDiagnosticClient*
-clang::CreatePlistDiagnosticClient(const std::string& s, const Preprocessor &PP,
- PathDiagnosticClient *subPD) {
- return new PlistDiagnostics(s, PP.getLangOptions(), subPD);
-}
-
-PathDiagnosticClient::PathGenerationScheme
-PlistDiagnostics::getGenerationScheme() const {
- if (const PathDiagnosticClient *PD = SubPD.get())
- return PD->getGenerationScheme();
-
- return Extensive;
-}
-
-static void AddFID(FIDMap &FIDs, llvm::SmallVectorImpl<FileID> &V,
- const SourceManager* SM, SourceLocation L) {
-
- FileID FID = SM->getFileID(SM->getInstantiationLoc(L));
- FIDMap::iterator I = FIDs.find(FID);
- if (I != FIDs.end()) return;
- FIDs[FID] = V.size();
- V.push_back(FID);
-}
-
-static unsigned GetFID(const FIDMap& FIDs, const SourceManager &SM,
- SourceLocation L) {
- FileID FID = SM.getFileID(SM.getInstantiationLoc(L));
- FIDMap::const_iterator I = FIDs.find(FID);
- assert(I != FIDs.end());
- return I->second;
-}
-
-static llvm::raw_ostream& Indent(llvm::raw_ostream& o, const unsigned indent) {
- for (unsigned i = 0; i < indent; ++i) o << ' ';
- return o;
-}
-
-static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
- const LangOptions &LangOpts,
- SourceLocation L, const FIDMap &FM,
- unsigned indent, bool extend = false) {
-
- FullSourceLoc Loc(SM.getInstantiationLoc(L), const_cast<SourceManager&>(SM));
-
- // Add in the length of the token, so that we cover multi-char tokens.
- unsigned offset =
- extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0;
-
- Indent(o, indent) << "<dict>\n";
- Indent(o, indent) << " <key>line</key><integer>"
- << Loc.getInstantiationLineNumber() << "</integer>\n";
- Indent(o, indent) << " <key>col</key><integer>"
- << Loc.getInstantiationColumnNumber() + offset << "</integer>\n";
- Indent(o, indent) << " <key>file</key><integer>"
- << GetFID(FM, SM, Loc) << "</integer>\n";
- Indent(o, indent) << "</dict>\n";
-}
-
-static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
- const LangOptions &LangOpts,
- const PathDiagnosticLocation &L, const FIDMap& FM,
- unsigned indent, bool extend = false) {
- EmitLocation(o, SM, LangOpts, L.asLocation(), FM, indent, extend);
-}
-
-static void EmitRange(llvm::raw_ostream& o, const SourceManager &SM,
- const LangOptions &LangOpts,
- PathDiagnosticRange R, const FIDMap &FM,
- unsigned indent) {
- Indent(o, indent) << "<array>\n";
- EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1);
- EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, !R.isPoint);
- Indent(o, indent) << "</array>\n";
-}
-
-static llvm::raw_ostream& EmitString(llvm::raw_ostream& o,
- const std::string& s) {
- o << "<string>";
- for (std::string::const_iterator I=s.begin(), E=s.end(); I!=E; ++I) {
- char c = *I;
- switch (c) {
- default: o << c; break;
- case '&': o << "&amp;"; break;
- case '<': o << "&lt;"; break;
- case '>': o << "&gt;"; break;
- case '\'': o << "&apos;"; break;
- case '\"': o << "&quot;"; break;
- }
- }
- o << "</string>";
- return o;
-}
-
-static void ReportControlFlow(llvm::raw_ostream& o,
- const PathDiagnosticControlFlowPiece& P,
- const FIDMap& FM,
- const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent) {
-
- Indent(o, indent) << "<dict>\n";
- ++indent;
-
- Indent(o, indent) << "<key>kind</key><string>control</string>\n";
-
- // Emit edges.
- Indent(o, indent) << "<key>edges</key>\n";
- ++indent;
- Indent(o, indent) << "<array>\n";
- ++indent;
- for (PathDiagnosticControlFlowPiece::const_iterator I=P.begin(), E=P.end();
- I!=E; ++I) {
- Indent(o, indent) << "<dict>\n";
- ++indent;
- Indent(o, indent) << "<key>start</key>\n";
- EmitRange(o, SM, LangOpts, I->getStart().asRange(), FM, indent+1);
- Indent(o, indent) << "<key>end</key>\n";
- EmitRange(o, SM, LangOpts, I->getEnd().asRange(), FM, indent+1);
- --indent;
- Indent(o, indent) << "</dict>\n";
- }
- --indent;
- Indent(o, indent) << "</array>\n";
- --indent;
-
- // Output any helper text.
- const std::string& s = P.getString();
- if (!s.empty()) {
- Indent(o, indent) << "<key>alternate</key>";
- EmitString(o, s) << '\n';
- }
-
- --indent;
- Indent(o, indent) << "</dict>\n";
-}
-
-static void ReportEvent(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
- const FIDMap& FM,
- const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent) {
-
- Indent(o, indent) << "<dict>\n";
- ++indent;
-
- Indent(o, indent) << "<key>kind</key><string>event</string>\n";
-
- // Output the location.
- FullSourceLoc L = P.getLocation().asLocation();
-
- Indent(o, indent) << "<key>location</key>\n";
- EmitLocation(o, SM, LangOpts, L, FM, indent);
-
- // Output the ranges (if any).
- PathDiagnosticPiece::range_iterator RI = P.ranges_begin(),
- RE = P.ranges_end();
-
- if (RI != RE) {
- Indent(o, indent) << "<key>ranges</key>\n";
- Indent(o, indent) << "<array>\n";
- ++indent;
- for (; RI != RE; ++RI)
- EmitRange(o, SM, LangOpts, *RI, FM, indent+1);
- --indent;
- Indent(o, indent) << "</array>\n";
- }
-
- // Output the text.
- assert(!P.getString().empty());
- Indent(o, indent) << "<key>extended_message</key>\n";
- Indent(o, indent);
- EmitString(o, P.getString()) << '\n';
-
- // Output the short text.
- // FIXME: Really use a short string.
- Indent(o, indent) << "<key>message</key>\n";
- EmitString(o, P.getString()) << '\n';
-
- // Finish up.
- --indent;
- Indent(o, indent); o << "</dict>\n";
-}
-
-static void ReportMacro(llvm::raw_ostream& o,
- const PathDiagnosticMacroPiece& P,
- const FIDMap& FM, const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent) {
-
- for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end();
- I!=E; ++I) {
-
- switch ((*I)->getKind()) {
- default:
- break;
- case PathDiagnosticPiece::Event:
- ReportEvent(o, cast<PathDiagnosticEventPiece>(**I), FM, SM, LangOpts,
- indent);
- break;
- case PathDiagnosticPiece::Macro:
- ReportMacro(o, cast<PathDiagnosticMacroPiece>(**I), FM, SM, LangOpts,
- indent);
- break;
- }
- }
-}
-
-static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
- const FIDMap& FM, const SourceManager &SM,
- const LangOptions &LangOpts) {
-
- unsigned indent = 4;
-
- switch (P.getKind()) {
- case PathDiagnosticPiece::ControlFlow:
- ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
- LangOpts, indent);
- break;
- case PathDiagnosticPiece::Event:
- ReportEvent(o, cast<PathDiagnosticEventPiece>(P), FM, SM, LangOpts,
- indent);
- break;
- case PathDiagnosticPiece::Macro:
- ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
- indent);
- break;
- }
-}
-
-void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
- if (!D)
- return;
-
- if (D->empty()) {
- delete D;
- return;
- }
-
- // We need to flatten the locations (convert Stmt* to locations) because
- // the referenced statements may be freed by the time the diagnostics
- // are emitted.
- const_cast<PathDiagnostic*>(D)->flattenLocations();
- BatchedDiags.push_back(D);
-}
-
-void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
- *FilesMade) {
-
- if (flushed)
- return;
-
- flushed = true;
-
- // Sort the diagnostics so that they are always emitted in a deterministic
- // order.
- if (!BatchedDiags.empty())
- std::sort(BatchedDiags.begin(), BatchedDiags.end(), CompareDiagnostics());
-
- // Build up a set of FIDs that we use by scanning the locations and
- // ranges of the diagnostics.
- FIDMap FM;
- llvm::SmallVector<FileID, 10> Fids;
- const SourceManager* SM = 0;
-
- if (!BatchedDiags.empty())
- SM = &(*BatchedDiags.begin())->begin()->getLocation().getManager();
-
- for (std::vector<const PathDiagnostic*>::iterator DI = BatchedDiags.begin(),
- DE = BatchedDiags.end(); DI != DE; ++DI) {
-
- const PathDiagnostic *D = *DI;
-
- for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I!=E; ++I) {
- AddFID(FM, Fids, SM, I->getLocation().asLocation());
-
- for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(),
- RE=I->ranges_end(); RI!=RE; ++RI) {
- AddFID(FM, Fids, SM, RI->getBegin());
- AddFID(FM, Fids, SM, RI->getEnd());
- }
- }
- }
-
- // Open the file.
- std::string ErrMsg;
- llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg);
- if (!ErrMsg.empty()) {
- llvm::errs() << "warning: could not creat file: " << OutputFile << '\n';
- return;
- }
-
- // Write the plist header.
- o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
- "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
- "<plist version=\"1.0\">\n";
-
- // Write the root object: a <dict> containing...
- // - "files", an <array> mapping from FIDs to file names
- // - "diagnostics", an <array> containing the path diagnostics
- o << "<dict>\n"
- " <key>files</key>\n"
- " <array>\n";
-
- for (llvm::SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end();
- I!=E; ++I) {
- o << " ";
- EmitString(o, SM->getFileEntryForID(*I)->getName()) << '\n';
- }
-
- o << " </array>\n"
- " <key>diagnostics</key>\n"
- " <array>\n";
-
- for (std::vector<const PathDiagnostic*>::iterator DI=BatchedDiags.begin(),
- DE = BatchedDiags.end(); DI!=DE; ++DI) {
-
- o << " <dict>\n"
- " <key>path</key>\n";
-
- const PathDiagnostic *D = *DI;
- // Create an owning smart pointer for 'D' just so that we auto-free it
- // when we exit this method.
- llvm::OwningPtr<PathDiagnostic> OwnedD(const_cast<PathDiagnostic*>(D));
-
- o << " <array>\n";
-
- for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I != E; ++I)
- ReportDiag(o, *I, FM, *SM, LangOpts);
-
- o << " </array>\n";
-
- // Output the bug type and bug category.
- o << " <key>description</key>";
- EmitString(o, D->getDescription()) << '\n';
- o << " <key>category</key>";
- EmitString(o, D->getCategory()) << '\n';
- o << " <key>type</key>";
- EmitString(o, D->getBugType()) << '\n';
-
- // Output the location of the bug.
- o << " <key>location</key>\n";
- EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2);
-
- // Output the diagnostic to the sub-diagnostic client, if any.
- if (SubPD) {
- SubPD->HandlePathDiagnostic(OwnedD.take());
- llvm::SmallVector<std::string, 1> SubFilesMade;
- SubPD->FlushDiagnostics(SubFilesMade);
-
- if (!SubFilesMade.empty()) {
- o << " <key>" << SubPD->getName() << "_files</key>\n";
- o << " <array>\n";
- for (size_t i = 0, n = SubFilesMade.size(); i < n ; ++i)
- o << " <string>" << SubFilesMade[i] << "</string>\n";
- o << " </array>\n";
- }
- }
-
- // Close up the entry.
- o << " </dict>\n";
- }
-
- o << " </array>\n";
-
- // Finish.
- o << "</dict>\n</plist>";
-
- if (FilesMade)
- FilesMade->push_back(OutputFile);
-
- BatchedDiags.clear();
-}