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