1//===--- SourceManagerInternals.h - SourceManager Internals -----*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief Defines implementation details of the clang::SourceManager class.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_SOURCEMANAGER_INTERNALS_H
16#define LLVM_CLANG_SOURCEMANAGER_INTERNALS_H
17
18#include "clang/Basic/SourceLocation.h"
19#include "clang/Basic/SourceManager.h"
20#include "llvm/ADT/StringMap.h"
21#include <map>
22
23namespace clang {
24
25//===----------------------------------------------------------------------===//
26// Line Table Implementation
27//===----------------------------------------------------------------------===//
28
29struct LineEntry {
30  /// \brief The offset in this file that the line entry occurs at.
31  unsigned FileOffset;
32
33  /// \brief The presumed line number of this line entry: \#line 4.
34  unsigned LineNo;
35
36  /// \brief The ID of the filename identified by this line entry:
37  /// \#line 4 "foo.c".  This is -1 if not specified.
38  int FilenameID;
39
40  /// \brief Set the 0 if no flags, 1 if a system header,
41  SrcMgr::CharacteristicKind FileKind;
42
43  /// \brief The offset of the virtual include stack location,
44  /// which is manipulated by GNU linemarker directives.
45  ///
46  /// If this is 0 then there is no virtual \#includer.
47  unsigned IncludeOffset;
48
49  static LineEntry get(unsigned Offs, unsigned Line, int Filename,
50                       SrcMgr::CharacteristicKind FileKind,
51                       unsigned IncludeOffset) {
52    LineEntry E;
53    E.FileOffset = Offs;
54    E.LineNo = Line;
55    E.FilenameID = Filename;
56    E.FileKind = FileKind;
57    E.IncludeOffset = IncludeOffset;
58    return E;
59  }
60};
61
62// needed for FindNearestLineEntry (upper_bound of LineEntry)
63inline bool operator<(const LineEntry &lhs, const LineEntry &rhs) {
64  // FIXME: should check the other field?
65  return lhs.FileOffset < rhs.FileOffset;
66}
67
68inline bool operator<(const LineEntry &E, unsigned Offset) {
69  return E.FileOffset < Offset;
70}
71
72inline bool operator<(unsigned Offset, const LineEntry &E) {
73  return Offset < E.FileOffset;
74}
75
76/// \brief Used to hold and unique data used to represent \#line information.
77class LineTableInfo {
78  /// \brief Map used to assign unique IDs to filenames in \#line directives.
79  ///
80  /// This allows us to unique the filenames that
81  /// frequently reoccur and reference them with indices.  FilenameIDs holds
82  /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID
83  /// to string.
84  llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs;
85  std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID;
86
87  /// \brief Map from FileIDs to a list of line entries (sorted by the offset
88  /// at which they occur in the file).
89  std::map<FileID, std::vector<LineEntry> > LineEntries;
90public:
91  LineTableInfo() {
92  }
93
94  void clear() {
95    FilenameIDs.clear();
96    FilenamesByID.clear();
97    LineEntries.clear();
98  }
99
100  ~LineTableInfo() {}
101
102  unsigned getLineTableFilenameID(StringRef Str);
103  const char *getFilename(unsigned ID) const {
104    assert(ID < FilenamesByID.size() && "Invalid FilenameID");
105    return FilenamesByID[ID]->getKeyData();
106  }
107  unsigned getNumFilenames() const { return FilenamesByID.size(); }
108
109  void AddLineNote(FileID FID, unsigned Offset,
110                   unsigned LineNo, int FilenameID);
111  void AddLineNote(FileID FID, unsigned Offset,
112                   unsigned LineNo, int FilenameID,
113                   unsigned EntryExit, SrcMgr::CharacteristicKind FileKind);
114
115
116  /// \brief Find the line entry nearest to FID that is before it.
117  ///
118  /// If there is no line entry before \p Offset in \p FID, returns null.
119  const LineEntry *FindNearestLineEntry(FileID FID, unsigned Offset);
120
121  // Low-level access
122  typedef std::map<FileID, std::vector<LineEntry> >::iterator iterator;
123  iterator begin() { return LineEntries.begin(); }
124  iterator end() { return LineEntries.end(); }
125
126  /// \brief Add a new line entry that has already been encoded into
127  /// the internal representation of the line table.
128  void AddEntry(FileID FID, const std::vector<LineEntry> &Entries);
129};
130
131} // end namespace clang
132
133#endif
134