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