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
26namespace clang {
27
28//===----------------------------------------------------------------------===//
29// Line Table Implementation
30//===----------------------------------------------------------------------===//
31
32struct 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
52  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)
66inline bool operator<(const LineEntry &lhs, const LineEntry &rhs) {
67  // FIXME: should check the other field?
68  return lhs.FileOffset < rhs.FileOffset;
69}
70
71inline bool operator<(const LineEntry &E, unsigned Offset) {
72  return E.FileOffset < Offset;
73}
74
75inline 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.
80class 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
94public:
95  void clear() {
96    FilenameIDs.clear();
97    FilenamesByID.clear();
98    LineEntries.clear();
99  }
100
101  unsigned getLineTableFilenameID(StringRef Str);
102
103  StringRef getFilename(unsigned ID) const {
104    assert(ID < FilenamesByID.size() && "Invalid FilenameID");
105    return FilenamesByID[ID]->getKey();
106  }
107
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
123  iterator begin() { return LineEntries.begin(); }
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