1894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===//
2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
3894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//                     The LLVM Compiler Infrastructure
4894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
5894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// This file is distributed under the University of Illinois Open Source
6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// License. See LICENSE.TXT for details.
7894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
9894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
10894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// This file declares the SMDiagnostic and SourceMgr classes.  This
11894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// provides a simple substrate for diagnostics, #include handling, and other low
12894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// level things for simple parsers.
13894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
15894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#ifndef SUPPORT_SOURCEMGR_H
17894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#define SUPPORT_SOURCEMGR_H
18894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
19894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/SMLoc.h"
20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
21894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <string>
22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <vector>
23894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <cassert>
24894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
25894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumannamespace llvm {
26894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  class MemoryBuffer;
27894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  class SourceMgr;
28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  class SMDiagnostic;
2919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  class Twine;
30894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  class raw_ostream;
31894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
32894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// SourceMgr - This owns the files read by a parser, handles include stacks,
33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// and handles diagnostic wrangling.
34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanclass SourceMgr {
35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanpublic:
36894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// DiagHandlerTy - Clients that want to handle their own diagnostics in a
37894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// custom way can register a function pointer+context as a diagnostic
38894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// handler.  It gets called each time PrintMessage is invoked.
3919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context);
40894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanprivate:
41894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  struct SrcBuffer {
42894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// Buffer - The memory buffer for the file.
43894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    MemoryBuffer *Buffer;
44894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
45894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// IncludeLoc - This is the location of the parent include, or null if at
46894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// the top level.
47894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SMLoc IncludeLoc;
48894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  };
49894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
50894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// Buffers - This is all of the buffers that we are reading from.
51894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  std::vector<SrcBuffer> Buffers;
52894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
53894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // IncludeDirectories - This is the list of directories we should search for
54894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // include files in.
55894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  std::vector<std::string> IncludeDirectories;
56894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
57894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// LineNoCache - This is a cache for line number queries, its implementation
58894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// is really private to SourceMgr.cpp.
59894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  mutable void *LineNoCache;
60894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
61894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DiagHandlerTy DiagHandler;
62894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  void *DiagContext;
63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
64894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SourceMgr(const SourceMgr&);    // DO NOT IMPLEMENT
65894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  void operator=(const SourceMgr&); // DO NOT IMPLEMENT
66894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanpublic:
67894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SourceMgr() : LineNoCache(0), DiagHandler(0), DiagContext(0) {}
68894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ~SourceMgr();
69894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
70894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  void setIncludeDirs(const std::vector<std::string> &Dirs) {
71894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    IncludeDirectories = Dirs;
72894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
73894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
74894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// setDiagHandler - Specify a diagnostic handler to be invoked every time
7519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// PrintMessage is called. Ctx is passed into the handler when it is invoked.
7619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0) {
77894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    DiagHandler = DH;
78894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    DiagContext = Ctx;
79894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
80894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
8119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  DiagHandlerTy getDiagHandler() const { return DiagHandler; }
8219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void *getDiagContext() const { return DiagContext; }
8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
84894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const SrcBuffer &getBufferInfo(unsigned i) const {
85894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(i < Buffers.size() && "Invalid Buffer ID!");
86894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return Buffers[i];
87894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
88894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
89894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const MemoryBuffer *getMemoryBuffer(unsigned i) const {
90894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(i < Buffers.size() && "Invalid Buffer ID!");
91894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return Buffers[i].Buffer;
92894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
93894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
94894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SMLoc getParentIncludeLoc(unsigned i) const {
95894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(i < Buffers.size() && "Invalid Buffer ID!");
96894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return Buffers[i].IncludeLoc;
97894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
98894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
99894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// AddNewSourceBuffer - Add a new source buffer to this source manager.  This
100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// takes ownership of the memory buffer.
101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) {
102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SrcBuffer NB;
103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    NB.Buffer = F;
104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    NB.IncludeLoc = IncludeLoc;
105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Buffers.push_back(NB);
106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return Buffers.size()-1;
107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// AddIncludeFile - Search for a file with the specified name in the current
110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// directory or in one of the IncludeDirs.  If no file is found, this returns
111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// ~0, otherwise it returns the buffer ID of the stacked file.
11219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// The full path to the included file can be found in IncludedFile.
11319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc,
11419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                          std::string &IncludedFile);
115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// FindBufferContainingLoc - Return the ID of the buffer containing the
117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// specified location, returning -1 if not found.
118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  int FindBufferContainingLoc(SMLoc Loc) const;
119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// FindLineNumber - Find the line number for the specified location in the
121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// specified file.  This is not a fast method.
122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const;
123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// PrintMessage - Emit a message about the specified location with the
125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// specified string.
126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ///
127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// @param Type - If non-null, the kind of message (e.g., "error") which is
128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// prefixed to the message.
129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// @param ShowLine - Should the diagnostic show the source line.
13019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void PrintMessage(SMLoc Loc, const Twine &Msg, const char *Type,
131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                    bool ShowLine = true) const;
132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// GetMessage - Return an SMDiagnostic at the specified location with the
135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// specified string.
136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ///
137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// @param Type - If non-null, the kind of message (e.g., "error") which is
138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// prefixed to the message.
139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// @param ShowLine - Should the diagnostic show the source line.
140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SMDiagnostic GetMessage(SMLoc Loc,
14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                          const Twine &Msg, const char *Type,
142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                          bool ShowLine = true) const;
143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
14419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// PrintIncludeStack - Prints the names of included files and the line of the
14519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// file they were included from.  A diagnostic handler can use this before
14619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// printing its custom formatted message.
14719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  ///
14819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// @param IncludeLoc - The line of the include.
14919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// @param OS the raw_ostream to print on.
150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const;
151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman};
152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// SMDiagnostic - Instances of this class encapsulate one diagnostic report,
155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// allowing printing to a raw_ostream as a caret diagnostic.
156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanclass SMDiagnostic {
157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const SourceMgr *SM;
158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SMLoc Loc;
159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  std::string Filename;
160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  int LineNo, ColumnNo;
161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  std::string Message, LineContents;
162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned ShowLine : 1;
163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanpublic:
165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Null diagnostic.
166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SMDiagnostic() : SM(0), LineNo(0), ColumnNo(0), ShowLine(0) {}
167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Diagnostic with no location (e.g. file not found, command line arg error).
16819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SMDiagnostic(const std::string &filename, const std::string &Msg)
169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1),
17019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      Message(Msg), ShowLine(false) {}
171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Diagnostic with a location.
173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SMDiagnostic(const SourceMgr &sm, SMLoc L, const std::string &FN,
174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman               int Line, int Col,
175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman               const std::string &Msg, const std::string &LineStr,
176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman               bool showline = true)
177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    : SM(&sm), Loc(L), Filename(FN), LineNo(Line), ColumnNo(Col), Message(Msg),
178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      LineContents(LineStr), ShowLine(showline) {}
179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const SourceMgr *getSourceMgr() const { return SM; }
181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SMLoc getLoc() const { return Loc; }
18219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const std::string &getFilename() const { return Filename; }
183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  int getLineNo() const { return LineNo; }
184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  int getColumnNo() const { return ColumnNo; }
185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const std::string &getMessage() const { return Message; }
186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const std::string &getLineContents() const { return LineContents; }
187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  bool getShowLine() const { return ShowLine; }
188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  void Print(const char *ProgName, raw_ostream &S) const;
190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman};
191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}  // end llvm namespace
193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
195