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