File: | clang/include/clang/Basic/SourceManager.h |
Warning: | line 837, column 29 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- Refactoring.cpp - Framework for clang refactoring tools ----------===// | |||
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 | // Implements tools to support refactorings. | |||
10 | // | |||
11 | //===----------------------------------------------------------------------===// | |||
12 | ||||
13 | #include "clang/Tooling/Refactoring.h" | |||
14 | #include "clang/Basic/DiagnosticOptions.h" | |||
15 | #include "clang/Basic/FileManager.h" | |||
16 | #include "clang/Basic/SourceManager.h" | |||
17 | #include "clang/Format/Format.h" | |||
18 | #include "clang/Frontend/TextDiagnosticPrinter.h" | |||
19 | #include "clang/Lex/Lexer.h" | |||
20 | #include "clang/Rewrite/Core/Rewriter.h" | |||
21 | #include "llvm/Support/Path.h" | |||
22 | #include "llvm/Support/raw_os_ostream.h" | |||
23 | ||||
24 | namespace clang { | |||
25 | namespace tooling { | |||
26 | ||||
27 | RefactoringTool::RefactoringTool( | |||
28 | const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths, | |||
29 | std::shared_ptr<PCHContainerOperations> PCHContainerOps) | |||
30 | : ClangTool(Compilations, SourcePaths, std::move(PCHContainerOps)) {} | |||
31 | ||||
32 | std::map<std::string, Replacements> &RefactoringTool::getReplacements() { | |||
33 | return FileToReplaces; | |||
34 | } | |||
35 | ||||
36 | int RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) { | |||
37 | if (int Result = run(ActionFactory)) { | |||
38 | return Result; | |||
39 | } | |||
40 | ||||
41 | LangOptions DefaultLangOptions; | |||
42 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); | |||
43 | TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts); | |||
44 | DiagnosticsEngine Diagnostics( | |||
45 | IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), | |||
46 | &*DiagOpts, &DiagnosticPrinter, false); | |||
47 | SourceManager Sources(Diagnostics, getFiles()); | |||
48 | Rewriter Rewrite(Sources, DefaultLangOptions); | |||
49 | ||||
50 | if (!applyAllReplacements(Rewrite)) { | |||
51 | llvm::errs() << "Skipped some replacements.\n"; | |||
52 | } | |||
53 | ||||
54 | return saveRewrittenFiles(Rewrite); | |||
55 | } | |||
56 | ||||
57 | bool RefactoringTool::applyAllReplacements(Rewriter &Rewrite) { | |||
58 | bool Result = true; | |||
59 | for (const auto &Entry : groupReplacementsByFile( | |||
60 | Rewrite.getSourceMgr().getFileManager(), FileToReplaces)) | |||
61 | Result = tooling::applyAllReplacements(Entry.second, Rewrite) && Result; | |||
62 | return Result; | |||
63 | } | |||
64 | ||||
65 | int RefactoringTool::saveRewrittenFiles(Rewriter &Rewrite) { | |||
66 | return Rewrite.overwriteChangedFiles() ? 1 : 0; | |||
67 | } | |||
68 | ||||
69 | bool formatAndApplyAllReplacements( | |||
70 | const std::map<std::string, Replacements> &FileToReplaces, | |||
71 | Rewriter &Rewrite, StringRef Style) { | |||
72 | SourceManager &SM = Rewrite.getSourceMgr(); | |||
73 | FileManager &Files = SM.getFileManager(); | |||
74 | ||||
75 | bool Result = true; | |||
76 | for (const auto &FileAndReplaces : groupReplacementsByFile( | |||
77 | Rewrite.getSourceMgr().getFileManager(), FileToReplaces)) { | |||
78 | const std::string &FilePath = FileAndReplaces.first; | |||
79 | auto &CurReplaces = FileAndReplaces.second; | |||
80 | ||||
81 | const FileEntry *Entry = nullptr; | |||
| ||||
82 | if (auto File = Files.getFile(FilePath)) | |||
83 | Entry = *File; | |||
84 | ||||
85 | FileID ID = SM.getOrCreateFileID(Entry, SrcMgr::C_User); | |||
86 | StringRef Code = SM.getBufferData(ID); | |||
87 | ||||
88 | auto CurStyle = format::getStyle(Style, FilePath, "LLVM"); | |||
89 | if (!CurStyle) { | |||
90 | llvm::errs() << llvm::toString(CurStyle.takeError()) << "\n"; | |||
91 | return false; | |||
92 | } | |||
93 | ||||
94 | auto NewReplacements = | |||
95 | format::formatReplacements(Code, CurReplaces, *CurStyle); | |||
96 | if (!NewReplacements) { | |||
97 | llvm::errs() << llvm::toString(NewReplacements.takeError()) << "\n"; | |||
98 | return false; | |||
99 | } | |||
100 | Result = applyAllReplacements(*NewReplacements, Rewrite) && Result; | |||
101 | } | |||
102 | return Result; | |||
103 | } | |||
104 | ||||
105 | } // end namespace tooling | |||
106 | } // end namespace clang |
1 | //===- SourceManager.h - Track and cache source files -----------*- 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 the SourceManager interface. | |||
11 | /// | |||
12 | /// There are three different types of locations in a %file: a spelling | |||
13 | /// location, an expansion location, and a presumed location. | |||
14 | /// | |||
15 | /// Given an example of: | |||
16 | /// \code | |||
17 | /// #define min(x, y) x < y ? x : y | |||
18 | /// \endcode | |||
19 | /// | |||
20 | /// and then later on a use of min: | |||
21 | /// \code | |||
22 | /// #line 17 | |||
23 | /// return min(a, b); | |||
24 | /// \endcode | |||
25 | /// | |||
26 | /// The expansion location is the line in the source code where the macro | |||
27 | /// was expanded (the return statement), the spelling location is the | |||
28 | /// location in the source where the macro was originally defined, | |||
29 | /// and the presumed location is where the line directive states that | |||
30 | /// the line is 17, or any other line. | |||
31 | // | |||
32 | //===----------------------------------------------------------------------===// | |||
33 | ||||
34 | #ifndef LLVM_CLANG_BASIC_SOURCEMANAGER_H | |||
35 | #define LLVM_CLANG_BASIC_SOURCEMANAGER_H | |||
36 | ||||
37 | #include "clang/Basic/Diagnostic.h" | |||
38 | #include "clang/Basic/FileManager.h" | |||
39 | #include "clang/Basic/SourceLocation.h" | |||
40 | #include "llvm/ADT/ArrayRef.h" | |||
41 | #include "llvm/ADT/BitVector.h" | |||
42 | #include "llvm/ADT/DenseMap.h" | |||
43 | #include "llvm/ADT/DenseSet.h" | |||
44 | #include "llvm/ADT/IntrusiveRefCntPtr.h" | |||
45 | #include "llvm/ADT/PointerIntPair.h" | |||
46 | #include "llvm/ADT/SmallVector.h" | |||
47 | #include "llvm/ADT/StringRef.h" | |||
48 | #include "llvm/Support/Allocator.h" | |||
49 | #include "llvm/Support/Compiler.h" | |||
50 | #include "llvm/Support/MemoryBuffer.h" | |||
51 | #include <cassert> | |||
52 | #include <cstddef> | |||
53 | #include <map> | |||
54 | #include <memory> | |||
55 | #include <string> | |||
56 | #include <utility> | |||
57 | #include <vector> | |||
58 | ||||
59 | namespace clang { | |||
60 | ||||
61 | class ASTReader; | |||
62 | class ASTWriter; | |||
63 | class LineTableInfo; | |||
64 | class SourceManager; | |||
65 | ||||
66 | /// Public enums and private classes that are part of the | |||
67 | /// SourceManager implementation. | |||
68 | namespace SrcMgr { | |||
69 | ||||
70 | /// Indicates whether a file or directory holds normal user code, | |||
71 | /// system code, or system code which is implicitly 'extern "C"' in C++ mode. | |||
72 | /// | |||
73 | /// Entire directories can be tagged with this (this is maintained by | |||
74 | /// DirectoryLookup and friends) as can specific FileInfos when a \#pragma | |||
75 | /// system_header is seen or in various other cases. | |||
76 | /// | |||
77 | enum CharacteristicKind { | |||
78 | C_User, C_System, C_ExternCSystem, C_User_ModuleMap, C_System_ModuleMap | |||
79 | }; | |||
80 | ||||
81 | /// Determine whether a file / directory characteristic is for system code. | |||
82 | inline bool isSystem(CharacteristicKind CK) { | |||
83 | return CK != C_User && CK != C_User_ModuleMap; | |||
84 | } | |||
85 | ||||
86 | /// Determine whether a file characteristic is for a module map. | |||
87 | inline bool isModuleMap(CharacteristicKind CK) { | |||
88 | return CK == C_User_ModuleMap || CK == C_System_ModuleMap; | |||
89 | } | |||
90 | ||||
91 | /// One instance of this struct is kept for every file loaded or used. | |||
92 | /// | |||
93 | /// This object owns the MemoryBuffer object. | |||
94 | class alignas(8) ContentCache { | |||
95 | enum CCFlags { | |||
96 | /// Whether the buffer is invalid. | |||
97 | InvalidFlag = 0x01, | |||
98 | ||||
99 | /// Whether the buffer should not be freed on destruction. | |||
100 | DoNotFreeFlag = 0x02 | |||
101 | }; | |||
102 | ||||
103 | /// The actual buffer containing the characters from the input | |||
104 | /// file. | |||
105 | /// | |||
106 | /// This is owned by the ContentCache object. The bits indicate | |||
107 | /// whether the buffer is invalid. | |||
108 | mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer; | |||
109 | ||||
110 | public: | |||
111 | /// Reference to the file entry representing this ContentCache. | |||
112 | /// | |||
113 | /// This reference does not own the FileEntry object. | |||
114 | /// | |||
115 | /// It is possible for this to be NULL if the ContentCache encapsulates | |||
116 | /// an imaginary text buffer. | |||
117 | const FileEntry *OrigEntry; | |||
118 | ||||
119 | /// References the file which the contents were actually loaded from. | |||
120 | /// | |||
121 | /// Can be different from 'Entry' if we overridden the contents of one file | |||
122 | /// with the contents of another file. | |||
123 | const FileEntry *ContentsEntry; | |||
124 | ||||
125 | /// A bump pointer allocated array of offsets for each source line. | |||
126 | /// | |||
127 | /// This is lazily computed. This is owned by the SourceManager | |||
128 | /// BumpPointerAllocator object. | |||
129 | unsigned *SourceLineCache = nullptr; | |||
130 | ||||
131 | /// The number of lines in this ContentCache. | |||
132 | /// | |||
133 | /// This is only valid if SourceLineCache is non-null. | |||
134 | unsigned NumLines = 0; | |||
135 | ||||
136 | /// Indicates whether the buffer itself was provided to override | |||
137 | /// the actual file contents. | |||
138 | /// | |||
139 | /// When true, the original entry may be a virtual file that does not | |||
140 | /// exist. | |||
141 | unsigned BufferOverridden : 1; | |||
142 | ||||
143 | /// True if this content cache was initially created for a source file | |||
144 | /// considered to be volatile (likely to change between stat and open). | |||
145 | unsigned IsFileVolatile : 1; | |||
146 | ||||
147 | /// True if this file may be transient, that is, if it might not | |||
148 | /// exist at some later point in time when this content entry is used, | |||
149 | /// after serialization and deserialization. | |||
150 | unsigned IsTransient : 1; | |||
151 | ||||
152 | ContentCache(const FileEntry *Ent = nullptr) : ContentCache(Ent, Ent) {} | |||
153 | ||||
154 | ContentCache(const FileEntry *Ent, const FileEntry *contentEnt) | |||
155 | : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt), | |||
156 | BufferOverridden(false), IsFileVolatile(false), IsTransient(false) {} | |||
157 | ||||
158 | /// The copy ctor does not allow copies where source object has either | |||
159 | /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory | |||
160 | /// is not transferred, so this is a logical error. | |||
161 | ContentCache(const ContentCache &RHS) | |||
162 | : Buffer(nullptr, false), BufferOverridden(false), | |||
163 | IsFileVolatile(false), IsTransient(false) { | |||
164 | OrigEntry = RHS.OrigEntry; | |||
165 | ContentsEntry = RHS.ContentsEntry; | |||
166 | ||||
167 | assert(RHS.Buffer.getPointer() == nullptr &&((RHS.Buffer.getPointer() == nullptr && RHS.SourceLineCache == nullptr && "Passed ContentCache object cannot own a buffer." ) ? static_cast<void> (0) : __assert_fail ("RHS.Buffer.getPointer() == nullptr && RHS.SourceLineCache == nullptr && \"Passed ContentCache object cannot own a buffer.\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 169, __PRETTY_FUNCTION__)) | |||
168 | RHS.SourceLineCache == nullptr &&((RHS.Buffer.getPointer() == nullptr && RHS.SourceLineCache == nullptr && "Passed ContentCache object cannot own a buffer." ) ? static_cast<void> (0) : __assert_fail ("RHS.Buffer.getPointer() == nullptr && RHS.SourceLineCache == nullptr && \"Passed ContentCache object cannot own a buffer.\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 169, __PRETTY_FUNCTION__)) | |||
169 | "Passed ContentCache object cannot own a buffer.")((RHS.Buffer.getPointer() == nullptr && RHS.SourceLineCache == nullptr && "Passed ContentCache object cannot own a buffer." ) ? static_cast<void> (0) : __assert_fail ("RHS.Buffer.getPointer() == nullptr && RHS.SourceLineCache == nullptr && \"Passed ContentCache object cannot own a buffer.\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 169, __PRETTY_FUNCTION__)); | |||
170 | ||||
171 | NumLines = RHS.NumLines; | |||
172 | } | |||
173 | ||||
174 | ContentCache &operator=(const ContentCache& RHS) = delete; | |||
175 | ||||
176 | ~ContentCache(); | |||
177 | ||||
178 | /// Returns the memory buffer for the associated content. | |||
179 | /// | |||
180 | /// \param Diag Object through which diagnostics will be emitted if the | |||
181 | /// buffer cannot be retrieved. | |||
182 | /// | |||
183 | /// \param Loc If specified, is the location that invalid file diagnostics | |||
184 | /// will be emitted at. | |||
185 | /// | |||
186 | /// \param Invalid If non-NULL, will be set \c true if an error occurred. | |||
187 | const llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag, | |||
188 | FileManager &FM, | |||
189 | SourceLocation Loc = SourceLocation(), | |||
190 | bool *Invalid = nullptr) const; | |||
191 | ||||
192 | /// Returns the size of the content encapsulated by this | |||
193 | /// ContentCache. | |||
194 | /// | |||
195 | /// This can be the size of the source file or the size of an | |||
196 | /// arbitrary scratch buffer. If the ContentCache encapsulates a source | |||
197 | /// file this size is retrieved from the file's FileEntry. | |||
198 | unsigned getSize() const; | |||
199 | ||||
200 | /// Returns the number of bytes actually mapped for this | |||
201 | /// ContentCache. | |||
202 | /// | |||
203 | /// This can be 0 if the MemBuffer was not actually expanded. | |||
204 | unsigned getSizeBytesMapped() const; | |||
205 | ||||
206 | /// Returns the kind of memory used to back the memory buffer for | |||
207 | /// this content cache. This is used for performance analysis. | |||
208 | llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const; | |||
209 | ||||
210 | /// Get the underlying buffer, returning NULL if the buffer is not | |||
211 | /// yet available. | |||
212 | const llvm::MemoryBuffer *getRawBuffer() const { | |||
213 | return Buffer.getPointer(); | |||
214 | } | |||
215 | ||||
216 | /// Replace the existing buffer (which will be deleted) | |||
217 | /// with the given buffer. | |||
218 | void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false); | |||
219 | ||||
220 | /// Determine whether the buffer itself is invalid. | |||
221 | bool isBufferInvalid() const { | |||
222 | return Buffer.getInt() & InvalidFlag; | |||
223 | } | |||
224 | ||||
225 | /// Determine whether the buffer should be freed. | |||
226 | bool shouldFreeBuffer() const { | |||
227 | return (Buffer.getInt() & DoNotFreeFlag) == 0; | |||
228 | } | |||
229 | ||||
230 | // If BufStr has an invalid BOM, returns the BOM name; otherwise, returns | |||
231 | // nullptr | |||
232 | static const char *getInvalidBOM(StringRef BufStr); | |||
233 | }; | |||
234 | ||||
235 | // Assert that the \c ContentCache objects will always be 8-byte aligned so | |||
236 | // that we can pack 3 bits of integer into pointers to such objects. | |||
237 | static_assert(alignof(ContentCache) >= 8, | |||
238 | "ContentCache must be 8-byte aligned."); | |||
239 | ||||
240 | /// Information about a FileID, basically just the logical file | |||
241 | /// that it represents and include stack information. | |||
242 | /// | |||
243 | /// Each FileInfo has include stack information, indicating where it came | |||
244 | /// from. This information encodes the \#include chain that a token was | |||
245 | /// expanded from. The main include file has an invalid IncludeLoc. | |||
246 | /// | |||
247 | /// FileInfos contain a "ContentCache *", with the contents of the file. | |||
248 | /// | |||
249 | class FileInfo { | |||
250 | friend class clang::SourceManager; | |||
251 | friend class clang::ASTWriter; | |||
252 | friend class clang::ASTReader; | |||
253 | ||||
254 | /// The location of the \#include that brought in this file. | |||
255 | /// | |||
256 | /// This is an invalid SLOC for the main file (top of the \#include chain). | |||
257 | unsigned IncludeLoc; // Really a SourceLocation | |||
258 | ||||
259 | /// Number of FileIDs (files and macros) that were created during | |||
260 | /// preprocessing of this \#include, including this SLocEntry. | |||
261 | /// | |||
262 | /// Zero means the preprocessor didn't provide such info for this SLocEntry. | |||
263 | unsigned NumCreatedFIDs : 31; | |||
264 | ||||
265 | /// Whether this FileInfo has any \#line directives. | |||
266 | unsigned HasLineDirectives : 1; | |||
267 | ||||
268 | /// The content cache and the characteristic of the file. | |||
269 | llvm::PointerIntPair<const ContentCache*, 3, CharacteristicKind> | |||
270 | ContentAndKind; | |||
271 | ||||
272 | /// The filename that is used to access the file entry represented by the | |||
273 | /// content cache. | |||
274 | StringRef Filename; | |||
275 | ||||
276 | public: | |||
277 | /// Return a FileInfo object. | |||
278 | static FileInfo get(SourceLocation IL, const ContentCache *Con, | |||
279 | CharacteristicKind FileCharacter, StringRef Filename) { | |||
280 | FileInfo X; | |||
281 | X.IncludeLoc = IL.getRawEncoding(); | |||
282 | X.NumCreatedFIDs = 0; | |||
283 | X.HasLineDirectives = false; | |||
284 | X.ContentAndKind.setPointer(Con); | |||
285 | X.ContentAndKind.setInt(FileCharacter); | |||
286 | X.Filename = Filename; | |||
287 | return X; | |||
288 | } | |||
289 | ||||
290 | SourceLocation getIncludeLoc() const { | |||
291 | return SourceLocation::getFromRawEncoding(IncludeLoc); | |||
292 | } | |||
293 | ||||
294 | const ContentCache *getContentCache() const { | |||
295 | return ContentAndKind.getPointer(); | |||
296 | } | |||
297 | ||||
298 | /// Return whether this is a system header or not. | |||
299 | CharacteristicKind getFileCharacteristic() const { | |||
300 | return ContentAndKind.getInt(); | |||
301 | } | |||
302 | ||||
303 | /// Return true if this FileID has \#line directives in it. | |||
304 | bool hasLineDirectives() const { return HasLineDirectives; } | |||
305 | ||||
306 | /// Set the flag that indicates that this FileID has | |||
307 | /// line table entries associated with it. | |||
308 | void setHasLineDirectives() { | |||
309 | HasLineDirectives = true; | |||
310 | } | |||
311 | ||||
312 | /// Returns the name of the file that was used when the file was loaded from | |||
313 | /// the underlying file system. | |||
314 | StringRef getName() const { return Filename; } | |||
315 | }; | |||
316 | ||||
317 | /// Each ExpansionInfo encodes the expansion location - where | |||
318 | /// the token was ultimately expanded, and the SpellingLoc - where the actual | |||
319 | /// character data for the token came from. | |||
320 | class ExpansionInfo { | |||
321 | // Really these are all SourceLocations. | |||
322 | ||||
323 | /// Where the spelling for the token can be found. | |||
324 | unsigned SpellingLoc; | |||
325 | ||||
326 | /// In a macro expansion, ExpansionLocStart and ExpansionLocEnd | |||
327 | /// indicate the start and end of the expansion. In object-like macros, | |||
328 | /// they will be the same. In a function-like macro expansion, the start | |||
329 | /// will be the identifier and the end will be the ')'. Finally, in | |||
330 | /// macro-argument instantiations, the end will be 'SourceLocation()', an | |||
331 | /// invalid location. | |||
332 | unsigned ExpansionLocStart, ExpansionLocEnd; | |||
333 | ||||
334 | /// Whether the expansion range is a token range. | |||
335 | bool ExpansionIsTokenRange; | |||
336 | ||||
337 | public: | |||
338 | SourceLocation getSpellingLoc() const { | |||
339 | SourceLocation SpellLoc = SourceLocation::getFromRawEncoding(SpellingLoc); | |||
340 | return SpellLoc.isInvalid() ? getExpansionLocStart() : SpellLoc; | |||
341 | } | |||
342 | ||||
343 | SourceLocation getExpansionLocStart() const { | |||
344 | return SourceLocation::getFromRawEncoding(ExpansionLocStart); | |||
345 | } | |||
346 | ||||
347 | SourceLocation getExpansionLocEnd() const { | |||
348 | SourceLocation EndLoc = | |||
349 | SourceLocation::getFromRawEncoding(ExpansionLocEnd); | |||
350 | return EndLoc.isInvalid() ? getExpansionLocStart() : EndLoc; | |||
351 | } | |||
352 | ||||
353 | bool isExpansionTokenRange() const { | |||
354 | return ExpansionIsTokenRange; | |||
355 | } | |||
356 | ||||
357 | CharSourceRange getExpansionLocRange() const { | |||
358 | return CharSourceRange( | |||
359 | SourceRange(getExpansionLocStart(), getExpansionLocEnd()), | |||
360 | isExpansionTokenRange()); | |||
361 | } | |||
362 | ||||
363 | bool isMacroArgExpansion() const { | |||
364 | // Note that this needs to return false for default constructed objects. | |||
365 | return getExpansionLocStart().isValid() && | |||
366 | SourceLocation::getFromRawEncoding(ExpansionLocEnd).isInvalid(); | |||
367 | } | |||
368 | ||||
369 | bool isMacroBodyExpansion() const { | |||
370 | return getExpansionLocStart().isValid() && | |||
371 | SourceLocation::getFromRawEncoding(ExpansionLocEnd).isValid(); | |||
372 | } | |||
373 | ||||
374 | bool isFunctionMacroExpansion() const { | |||
375 | return getExpansionLocStart().isValid() && | |||
376 | getExpansionLocStart() != getExpansionLocEnd(); | |||
377 | } | |||
378 | ||||
379 | /// Return a ExpansionInfo for an expansion. | |||
380 | /// | |||
381 | /// Start and End specify the expansion range (where the macro is | |||
382 | /// expanded), and SpellingLoc specifies the spelling location (where | |||
383 | /// the characters from the token come from). All three can refer to | |||
384 | /// normal File SLocs or expansion locations. | |||
385 | static ExpansionInfo create(SourceLocation SpellingLoc, | |||
386 | SourceLocation Start, SourceLocation End, | |||
387 | bool ExpansionIsTokenRange = true) { | |||
388 | ExpansionInfo X; | |||
389 | X.SpellingLoc = SpellingLoc.getRawEncoding(); | |||
390 | X.ExpansionLocStart = Start.getRawEncoding(); | |||
391 | X.ExpansionLocEnd = End.getRawEncoding(); | |||
392 | X.ExpansionIsTokenRange = ExpansionIsTokenRange; | |||
393 | return X; | |||
394 | } | |||
395 | ||||
396 | /// Return a special ExpansionInfo for the expansion of | |||
397 | /// a macro argument into a function-like macro's body. | |||
398 | /// | |||
399 | /// ExpansionLoc specifies the expansion location (where the macro is | |||
400 | /// expanded). This doesn't need to be a range because a macro is always | |||
401 | /// expanded at a macro parameter reference, and macro parameters are | |||
402 | /// always exactly one token. SpellingLoc specifies the spelling location | |||
403 | /// (where the characters from the token come from). ExpansionLoc and | |||
404 | /// SpellingLoc can both refer to normal File SLocs or expansion locations. | |||
405 | /// | |||
406 | /// Given the code: | |||
407 | /// \code | |||
408 | /// #define F(x) f(x) | |||
409 | /// F(42); | |||
410 | /// \endcode | |||
411 | /// | |||
412 | /// When expanding '\c F(42)', the '\c x' would call this with an | |||
413 | /// SpellingLoc pointing at '\c 42' and an ExpansionLoc pointing at its | |||
414 | /// location in the definition of '\c F'. | |||
415 | static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, | |||
416 | SourceLocation ExpansionLoc) { | |||
417 | // We store an intentionally invalid source location for the end of the | |||
418 | // expansion range to mark that this is a macro argument location rather | |||
419 | // than a normal one. | |||
420 | return create(SpellingLoc, ExpansionLoc, SourceLocation()); | |||
421 | } | |||
422 | ||||
423 | /// Return a special ExpansionInfo representing a token that ends | |||
424 | /// prematurely. This is used to model a '>>' token that has been split | |||
425 | /// into '>' tokens and similar cases. Unlike for the other forms of | |||
426 | /// expansion, the expansion range in this case is a character range, not | |||
427 | /// a token range. | |||
428 | static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc, | |||
429 | SourceLocation Start, | |||
430 | SourceLocation End) { | |||
431 | return create(SpellingLoc, Start, End, false); | |||
432 | } | |||
433 | }; | |||
434 | ||||
435 | /// This is a discriminated union of FileInfo and ExpansionInfo. | |||
436 | /// | |||
437 | /// SourceManager keeps an array of these objects, and they are uniquely | |||
438 | /// identified by the FileID datatype. | |||
439 | class SLocEntry { | |||
440 | unsigned Offset : 31; | |||
441 | unsigned IsExpansion : 1; | |||
442 | union { | |||
443 | FileInfo File; | |||
444 | ExpansionInfo Expansion; | |||
445 | }; | |||
446 | ||||
447 | public: | |||
448 | SLocEntry() : Offset(), IsExpansion(), File() {} | |||
449 | ||||
450 | unsigned getOffset() const { return Offset; } | |||
451 | ||||
452 | bool isExpansion() const { return IsExpansion; } | |||
453 | bool isFile() const { return !isExpansion(); } | |||
454 | ||||
455 | const FileInfo &getFile() const { | |||
456 | assert(isFile() && "Not a file SLocEntry!")((isFile() && "Not a file SLocEntry!") ? static_cast< void> (0) : __assert_fail ("isFile() && \"Not a file SLocEntry!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 456, __PRETTY_FUNCTION__)); | |||
457 | return File; | |||
458 | } | |||
459 | ||||
460 | const ExpansionInfo &getExpansion() const { | |||
461 | assert(isExpansion() && "Not a macro expansion SLocEntry!")((isExpansion() && "Not a macro expansion SLocEntry!" ) ? static_cast<void> (0) : __assert_fail ("isExpansion() && \"Not a macro expansion SLocEntry!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 461, __PRETTY_FUNCTION__)); | |||
462 | return Expansion; | |||
463 | } | |||
464 | ||||
465 | static SLocEntry get(unsigned Offset, const FileInfo &FI) { | |||
466 | assert(!(Offset & (1u << 31)) && "Offset is too large")((!(Offset & (1u << 31)) && "Offset is too large" ) ? static_cast<void> (0) : __assert_fail ("!(Offset & (1u << 31)) && \"Offset is too large\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 466, __PRETTY_FUNCTION__)); | |||
467 | SLocEntry E; | |||
468 | E.Offset = Offset; | |||
469 | E.IsExpansion = false; | |||
470 | E.File = FI; | |||
471 | return E; | |||
472 | } | |||
473 | ||||
474 | static SLocEntry get(unsigned Offset, const ExpansionInfo &Expansion) { | |||
475 | assert(!(Offset & (1u << 31)) && "Offset is too large")((!(Offset & (1u << 31)) && "Offset is too large" ) ? static_cast<void> (0) : __assert_fail ("!(Offset & (1u << 31)) && \"Offset is too large\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 475, __PRETTY_FUNCTION__)); | |||
476 | SLocEntry E; | |||
477 | E.Offset = Offset; | |||
478 | E.IsExpansion = true; | |||
479 | E.Expansion = Expansion; | |||
480 | return E; | |||
481 | } | |||
482 | }; | |||
483 | ||||
484 | } // namespace SrcMgr | |||
485 | ||||
486 | /// External source of source location entries. | |||
487 | class ExternalSLocEntrySource { | |||
488 | public: | |||
489 | virtual ~ExternalSLocEntrySource(); | |||
490 | ||||
491 | /// Read the source location entry with index ID, which will always be | |||
492 | /// less than -1. | |||
493 | /// | |||
494 | /// \returns true if an error occurred that prevented the source-location | |||
495 | /// entry from being loaded. | |||
496 | virtual bool ReadSLocEntry(int ID) = 0; | |||
497 | ||||
498 | /// Retrieve the module import location and name for the given ID, if | |||
499 | /// in fact it was loaded from a module (rather than, say, a precompiled | |||
500 | /// header). | |||
501 | virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) = 0; | |||
502 | }; | |||
503 | ||||
504 | /// Holds the cache used by isBeforeInTranslationUnit. | |||
505 | /// | |||
506 | /// The cache structure is complex enough to be worth breaking out of | |||
507 | /// SourceManager. | |||
508 | class InBeforeInTUCacheEntry { | |||
509 | /// The FileID's of the cached query. | |||
510 | /// | |||
511 | /// If these match up with a subsequent query, the result can be reused. | |||
512 | FileID LQueryFID, RQueryFID; | |||
513 | ||||
514 | /// True if LQueryFID was created before RQueryFID. | |||
515 | /// | |||
516 | /// This is used to compare macro expansion locations. | |||
517 | bool IsLQFIDBeforeRQFID; | |||
518 | ||||
519 | /// The file found in common between the two \#include traces, i.e., | |||
520 | /// the nearest common ancestor of the \#include tree. | |||
521 | FileID CommonFID; | |||
522 | ||||
523 | /// The offset of the previous query in CommonFID. | |||
524 | /// | |||
525 | /// Usually, this represents the location of the \#include for QueryFID, but | |||
526 | /// if LQueryFID is a parent of RQueryFID (or vice versa) then these can be a | |||
527 | /// random token in the parent. | |||
528 | unsigned LCommonOffset, RCommonOffset; | |||
529 | ||||
530 | public: | |||
531 | /// Return true if the currently cached values match up with | |||
532 | /// the specified LHS/RHS query. | |||
533 | /// | |||
534 | /// If not, we can't use the cache. | |||
535 | bool isCacheValid(FileID LHS, FileID RHS) const { | |||
536 | return LQueryFID == LHS && RQueryFID == RHS; | |||
537 | } | |||
538 | ||||
539 | /// If the cache is valid, compute the result given the | |||
540 | /// specified offsets in the LHS/RHS FileID's. | |||
541 | bool getCachedResult(unsigned LOffset, unsigned ROffset) const { | |||
542 | // If one of the query files is the common file, use the offset. Otherwise, | |||
543 | // use the #include loc in the common file. | |||
544 | if (LQueryFID != CommonFID) LOffset = LCommonOffset; | |||
545 | if (RQueryFID != CommonFID) ROffset = RCommonOffset; | |||
546 | ||||
547 | // It is common for multiple macro expansions to be "included" from the same | |||
548 | // location (expansion location), in which case use the order of the FileIDs | |||
549 | // to determine which came first. This will also take care the case where | |||
550 | // one of the locations points at the inclusion/expansion point of the other | |||
551 | // in which case its FileID will come before the other. | |||
552 | if (LOffset == ROffset) | |||
553 | return IsLQFIDBeforeRQFID; | |||
554 | ||||
555 | return LOffset < ROffset; | |||
556 | } | |||
557 | ||||
558 | /// Set up a new query. | |||
559 | void setQueryFIDs(FileID LHS, FileID RHS, bool isLFIDBeforeRFID) { | |||
560 | assert(LHS != RHS)((LHS != RHS) ? static_cast<void> (0) : __assert_fail ( "LHS != RHS", "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 560, __PRETTY_FUNCTION__)); | |||
561 | LQueryFID = LHS; | |||
562 | RQueryFID = RHS; | |||
563 | IsLQFIDBeforeRQFID = isLFIDBeforeRFID; | |||
564 | } | |||
565 | ||||
566 | void clear() { | |||
567 | LQueryFID = RQueryFID = FileID(); | |||
568 | IsLQFIDBeforeRQFID = false; | |||
569 | } | |||
570 | ||||
571 | void setCommonLoc(FileID commonFID, unsigned lCommonOffset, | |||
572 | unsigned rCommonOffset) { | |||
573 | CommonFID = commonFID; | |||
574 | LCommonOffset = lCommonOffset; | |||
575 | RCommonOffset = rCommonOffset; | |||
576 | } | |||
577 | }; | |||
578 | ||||
579 | /// The stack used when building modules on demand, which is used | |||
580 | /// to provide a link between the source managers of the different compiler | |||
581 | /// instances. | |||
582 | using ModuleBuildStack = ArrayRef<std::pair<std::string, FullSourceLoc>>; | |||
583 | ||||
584 | /// This class handles loading and caching of source files into memory. | |||
585 | /// | |||
586 | /// This object owns the MemoryBuffer objects for all of the loaded | |||
587 | /// files and assigns unique FileID's for each unique \#include chain. | |||
588 | /// | |||
589 | /// The SourceManager can be queried for information about SourceLocation | |||
590 | /// objects, turning them into either spelling or expansion locations. Spelling | |||
591 | /// locations represent where the bytes corresponding to a token came from and | |||
592 | /// expansion locations represent where the location is in the user's view. In | |||
593 | /// the case of a macro expansion, for example, the spelling location indicates | |||
594 | /// where the expanded token came from and the expansion location specifies | |||
595 | /// where it was expanded. | |||
596 | class SourceManager : public RefCountedBase<SourceManager> { | |||
597 | /// DiagnosticsEngine object. | |||
598 | DiagnosticsEngine &Diag; | |||
599 | ||||
600 | FileManager &FileMgr; | |||
601 | ||||
602 | mutable llvm::BumpPtrAllocator ContentCacheAlloc; | |||
603 | ||||
604 | /// Memoized information about all of the files tracked by this | |||
605 | /// SourceManager. | |||
606 | /// | |||
607 | /// This map allows us to merge ContentCache entries based | |||
608 | /// on their FileEntry*. All ContentCache objects will thus have unique, | |||
609 | /// non-null, FileEntry pointers. | |||
610 | llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos; | |||
611 | ||||
612 | /// True if the ContentCache for files that are overridden by other | |||
613 | /// files, should report the original file name. Defaults to true. | |||
614 | bool OverridenFilesKeepOriginalName = true; | |||
615 | ||||
616 | /// True if non-system source files should be treated as volatile | |||
617 | /// (likely to change while trying to use them). Defaults to false. | |||
618 | bool UserFilesAreVolatile; | |||
619 | ||||
620 | /// True if all files read during this compilation should be treated | |||
621 | /// as transient (may not be present in later compilations using a module | |||
622 | /// file created from this compilation). Defaults to false. | |||
623 | bool FilesAreTransient = false; | |||
624 | ||||
625 | struct OverriddenFilesInfoTy { | |||
626 | /// Files that have been overridden with the contents from another | |||
627 | /// file. | |||
628 | llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles; | |||
629 | ||||
630 | /// Files that were overridden with a memory buffer. | |||
631 | llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer; | |||
632 | }; | |||
633 | ||||
634 | /// Lazily create the object keeping overridden files info, since | |||
635 | /// it is uncommonly used. | |||
636 | std::unique_ptr<OverriddenFilesInfoTy> OverriddenFilesInfo; | |||
637 | ||||
638 | OverriddenFilesInfoTy &getOverriddenFilesInfo() { | |||
639 | if (!OverriddenFilesInfo) | |||
640 | OverriddenFilesInfo.reset(new OverriddenFilesInfoTy); | |||
641 | return *OverriddenFilesInfo; | |||
642 | } | |||
643 | ||||
644 | /// Information about various memory buffers that we have read in. | |||
645 | /// | |||
646 | /// All FileEntry* within the stored ContentCache objects are NULL, | |||
647 | /// as they do not refer to a file. | |||
648 | std::vector<SrcMgr::ContentCache*> MemBufferInfos; | |||
649 | ||||
650 | /// The table of SLocEntries that are local to this module. | |||
651 | /// | |||
652 | /// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid | |||
653 | /// expansion. | |||
654 | SmallVector<SrcMgr::SLocEntry, 0> LocalSLocEntryTable; | |||
655 | ||||
656 | /// The table of SLocEntries that are loaded from other modules. | |||
657 | /// | |||
658 | /// Negative FileIDs are indexes into this table. To get from ID to an index, | |||
659 | /// use (-ID - 2). | |||
660 | mutable SmallVector<SrcMgr::SLocEntry, 0> LoadedSLocEntryTable; | |||
661 | ||||
662 | /// The starting offset of the next local SLocEntry. | |||
663 | /// | |||
664 | /// This is LocalSLocEntryTable.back().Offset + the size of that entry. | |||
665 | unsigned NextLocalOffset; | |||
666 | ||||
667 | /// The starting offset of the latest batch of loaded SLocEntries. | |||
668 | /// | |||
669 | /// This is LoadedSLocEntryTable.back().Offset, except that that entry might | |||
670 | /// not have been loaded, so that value would be unknown. | |||
671 | unsigned CurrentLoadedOffset; | |||
672 | ||||
673 | /// The highest possible offset is 2^31-1, so CurrentLoadedOffset | |||
674 | /// starts at 2^31. | |||
675 | static const unsigned MaxLoadedOffset = 1U << 31U; | |||
676 | ||||
677 | /// A bitmap that indicates whether the entries of LoadedSLocEntryTable | |||
678 | /// have already been loaded from the external source. | |||
679 | /// | |||
680 | /// Same indexing as LoadedSLocEntryTable. | |||
681 | llvm::BitVector SLocEntryLoaded; | |||
682 | ||||
683 | /// An external source for source location entries. | |||
684 | ExternalSLocEntrySource *ExternalSLocEntries = nullptr; | |||
685 | ||||
686 | /// A one-entry cache to speed up getFileID. | |||
687 | /// | |||
688 | /// LastFileIDLookup records the last FileID looked up or created, because it | |||
689 | /// is very common to look up many tokens from the same file. | |||
690 | mutable FileID LastFileIDLookup; | |||
691 | ||||
692 | /// Holds information for \#line directives. | |||
693 | /// | |||
694 | /// This is referenced by indices from SLocEntryTable. | |||
695 | std::unique_ptr<LineTableInfo> LineTable; | |||
696 | ||||
697 | /// These ivars serve as a cache used in the getLineNumber | |||
698 | /// method which is used to speedup getLineNumber calls to nearby locations. | |||
699 | mutable FileID LastLineNoFileIDQuery; | |||
700 | mutable SrcMgr::ContentCache *LastLineNoContentCache; | |||
701 | mutable unsigned LastLineNoFilePos; | |||
702 | mutable unsigned LastLineNoResult; | |||
703 | ||||
704 | /// The file ID for the main source file of the translation unit. | |||
705 | FileID MainFileID; | |||
706 | ||||
707 | /// The file ID for the precompiled preamble there is one. | |||
708 | FileID PreambleFileID; | |||
709 | ||||
710 | // Statistics for -print-stats. | |||
711 | mutable unsigned NumLinearScans = 0; | |||
712 | mutable unsigned NumBinaryProbes = 0; | |||
713 | ||||
714 | /// Associates a FileID with its "included/expanded in" decomposed | |||
715 | /// location. | |||
716 | /// | |||
717 | /// Used to cache results from and speed-up \c getDecomposedIncludedLoc | |||
718 | /// function. | |||
719 | mutable llvm::DenseMap<FileID, std::pair<FileID, unsigned>> IncludedLocMap; | |||
720 | ||||
721 | /// The key value into the IsBeforeInTUCache table. | |||
722 | using IsBeforeInTUCacheKey = std::pair<FileID, FileID>; | |||
723 | ||||
724 | /// The IsBeforeInTranslationUnitCache is a mapping from FileID pairs | |||
725 | /// to cache results. | |||
726 | using InBeforeInTUCache = | |||
727 | llvm::DenseMap<IsBeforeInTUCacheKey, InBeforeInTUCacheEntry>; | |||
728 | ||||
729 | /// Cache results for the isBeforeInTranslationUnit method. | |||
730 | mutable InBeforeInTUCache IBTUCache; | |||
731 | mutable InBeforeInTUCacheEntry IBTUCacheOverflow; | |||
732 | ||||
733 | /// Return the cache entry for comparing the given file IDs | |||
734 | /// for isBeforeInTranslationUnit. | |||
735 | InBeforeInTUCacheEntry &getInBeforeInTUCache(FileID LFID, FileID RFID) const; | |||
736 | ||||
737 | // Cache for the "fake" buffer used for error-recovery purposes. | |||
738 | mutable std::unique_ptr<llvm::MemoryBuffer> FakeBufferForRecovery; | |||
739 | ||||
740 | mutable std::unique_ptr<SrcMgr::ContentCache> FakeContentCacheForRecovery; | |||
741 | ||||
742 | /// Lazily computed map of macro argument chunks to their expanded | |||
743 | /// source location. | |||
744 | using MacroArgsMap = std::map<unsigned, SourceLocation>; | |||
745 | ||||
746 | mutable llvm::DenseMap<FileID, std::unique_ptr<MacroArgsMap>> | |||
747 | MacroArgsCacheMap; | |||
748 | ||||
749 | /// The stack of modules being built, which is used to detect | |||
750 | /// cycles in the module dependency graph as modules are being built, as | |||
751 | /// well as to describe why we're rebuilding a particular module. | |||
752 | /// | |||
753 | /// There is no way to set this value from the command line. If we ever need | |||
754 | /// to do so (e.g., if on-demand module construction moves out-of-process), | |||
755 | /// we can add a cc1-level option to do so. | |||
756 | SmallVector<std::pair<std::string, FullSourceLoc>, 2> StoredModuleBuildStack; | |||
757 | ||||
758 | public: | |||
759 | SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, | |||
760 | bool UserFilesAreVolatile = false); | |||
761 | explicit SourceManager(const SourceManager &) = delete; | |||
762 | SourceManager &operator=(const SourceManager &) = delete; | |||
763 | ~SourceManager(); | |||
764 | ||||
765 | void clearIDTables(); | |||
766 | ||||
767 | /// Initialize this source manager suitably to replay the compilation | |||
768 | /// described by \p Old. Requires that \p Old outlive \p *this. | |||
769 | void initializeForReplay(const SourceManager &Old); | |||
770 | ||||
771 | DiagnosticsEngine &getDiagnostics() const { return Diag; } | |||
772 | ||||
773 | FileManager &getFileManager() const { return FileMgr; } | |||
774 | ||||
775 | /// Set true if the SourceManager should report the original file name | |||
776 | /// for contents of files that were overridden by other files. Defaults to | |||
777 | /// true. | |||
778 | void setOverridenFilesKeepOriginalName(bool value) { | |||
779 | OverridenFilesKeepOriginalName = value; | |||
780 | } | |||
781 | ||||
782 | /// True if non-system source files should be treated as volatile | |||
783 | /// (likely to change while trying to use them). | |||
784 | bool userFilesAreVolatile() const { return UserFilesAreVolatile; } | |||
785 | ||||
786 | /// Retrieve the module build stack. | |||
787 | ModuleBuildStack getModuleBuildStack() const { | |||
788 | return StoredModuleBuildStack; | |||
789 | } | |||
790 | ||||
791 | /// Set the module build stack. | |||
792 | void setModuleBuildStack(ModuleBuildStack stack) { | |||
793 | StoredModuleBuildStack.clear(); | |||
794 | StoredModuleBuildStack.append(stack.begin(), stack.end()); | |||
795 | } | |||
796 | ||||
797 | /// Push an entry to the module build stack. | |||
798 | void pushModuleBuildStack(StringRef moduleName, FullSourceLoc importLoc) { | |||
799 | StoredModuleBuildStack.push_back(std::make_pair(moduleName.str(),importLoc)); | |||
800 | } | |||
801 | ||||
802 | //===--------------------------------------------------------------------===// | |||
803 | // MainFileID creation and querying methods. | |||
804 | //===--------------------------------------------------------------------===// | |||
805 | ||||
806 | /// Returns the FileID of the main source file. | |||
807 | FileID getMainFileID() const { return MainFileID; } | |||
808 | ||||
809 | /// Set the file ID for the main source file. | |||
810 | void setMainFileID(FileID FID) { | |||
811 | MainFileID = FID; | |||
812 | } | |||
813 | ||||
814 | /// Set the file ID for the precompiled preamble. | |||
815 | void setPreambleFileID(FileID Preamble) { | |||
816 | assert(PreambleFileID.isInvalid() && "PreambleFileID already set!")((PreambleFileID.isInvalid() && "PreambleFileID already set!" ) ? static_cast<void> (0) : __assert_fail ("PreambleFileID.isInvalid() && \"PreambleFileID already set!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 816, __PRETTY_FUNCTION__)); | |||
817 | PreambleFileID = Preamble; | |||
818 | } | |||
819 | ||||
820 | /// Get the file ID for the precompiled preamble if there is one. | |||
821 | FileID getPreambleFileID() const { return PreambleFileID; } | |||
822 | ||||
823 | //===--------------------------------------------------------------------===// | |||
824 | // Methods to create new FileID's and macro expansions. | |||
825 | //===--------------------------------------------------------------------===// | |||
826 | ||||
827 | /// Create a new FileID that represents the specified file | |||
828 | /// being \#included from the specified IncludePosition. | |||
829 | /// | |||
830 | /// This translates NULL into standard input. | |||
831 | FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, | |||
832 | SrcMgr::CharacteristicKind FileCharacter, | |||
833 | int LoadedID = 0, unsigned LoadedOffset = 0) { | |||
834 | const SrcMgr::ContentCache *IR = | |||
835 | getOrCreateContentCache(SourceFile, isSystem(FileCharacter)); | |||
836 | assert(IR && "getOrCreateContentCache() cannot return NULL")((IR && "getOrCreateContentCache() cannot return NULL" ) ? static_cast<void> (0) : __assert_fail ("IR && \"getOrCreateContentCache() cannot return NULL\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 836, __PRETTY_FUNCTION__)); | |||
837 | return createFileID(IR, SourceFile->getName(), IncludePos, FileCharacter, | |||
| ||||
838 | LoadedID, LoadedOffset); | |||
839 | } | |||
840 | ||||
841 | FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, | |||
842 | SrcMgr::CharacteristicKind FileCharacter, | |||
843 | int LoadedID = 0, unsigned LoadedOffset = 0) { | |||
844 | const SrcMgr::ContentCache *IR = getOrCreateContentCache( | |||
845 | &SourceFile.getFileEntry(), isSystem(FileCharacter)); | |||
846 | assert(IR && "getOrCreateContentCache() cannot return NULL")((IR && "getOrCreateContentCache() cannot return NULL" ) ? static_cast<void> (0) : __assert_fail ("IR && \"getOrCreateContentCache() cannot return NULL\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 846, __PRETTY_FUNCTION__)); | |||
847 | return createFileID(IR, SourceFile.getName(), IncludePos, FileCharacter, | |||
848 | LoadedID, LoadedOffset); | |||
849 | } | |||
850 | ||||
851 | /// Create a new FileID that represents the specified memory buffer. | |||
852 | /// | |||
853 | /// This does no caching of the buffer and takes ownership of the | |||
854 | /// MemoryBuffer, so only pass a MemoryBuffer to this once. | |||
855 | FileID createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer, | |||
856 | SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User, | |||
857 | int LoadedID = 0, unsigned LoadedOffset = 0, | |||
858 | SourceLocation IncludeLoc = SourceLocation()) { | |||
859 | StringRef Name = Buffer->getBufferIdentifier(); | |||
860 | return createFileID( | |||
861 | createMemBufferContentCache(Buffer.release(), /*DoNotFree*/ false), | |||
862 | Name, IncludeLoc, FileCharacter, LoadedID, LoadedOffset); | |||
863 | } | |||
864 | ||||
865 | enum UnownedTag { Unowned }; | |||
866 | ||||
867 | /// Create a new FileID that represents the specified memory buffer. | |||
868 | /// | |||
869 | /// This does not take ownership of the MemoryBuffer. The memory buffer must | |||
870 | /// outlive the SourceManager. | |||
871 | FileID createFileID(UnownedTag, const llvm::MemoryBuffer *Buffer, | |||
872 | SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User, | |||
873 | int LoadedID = 0, unsigned LoadedOffset = 0, | |||
874 | SourceLocation IncludeLoc = SourceLocation()) { | |||
875 | return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/ true), | |||
876 | Buffer->getBufferIdentifier(), IncludeLoc, | |||
877 | FileCharacter, LoadedID, LoadedOffset); | |||
878 | } | |||
879 | ||||
880 | /// Get the FileID for \p SourceFile if it exists. Otherwise, create a | |||
881 | /// new FileID for the \p SourceFile. | |||
882 | FileID getOrCreateFileID(const FileEntry *SourceFile, | |||
883 | SrcMgr::CharacteristicKind FileCharacter) { | |||
884 | FileID ID = translateFile(SourceFile); | |||
885 | return ID.isValid() ? ID : createFileID(SourceFile, SourceLocation(), | |||
886 | FileCharacter); | |||
887 | } | |||
888 | ||||
889 | /// Return a new SourceLocation that encodes the | |||
890 | /// fact that a token from SpellingLoc should actually be referenced from | |||
891 | /// ExpansionLoc, and that it represents the expansion of a macro argument | |||
892 | /// into the function-like macro body. | |||
893 | SourceLocation createMacroArgExpansionLoc(SourceLocation Loc, | |||
894 | SourceLocation ExpansionLoc, | |||
895 | unsigned TokLength); | |||
896 | ||||
897 | /// Return a new SourceLocation that encodes the fact | |||
898 | /// that a token from SpellingLoc should actually be referenced from | |||
899 | /// ExpansionLoc. | |||
900 | SourceLocation createExpansionLoc(SourceLocation Loc, | |||
901 | SourceLocation ExpansionLocStart, | |||
902 | SourceLocation ExpansionLocEnd, | |||
903 | unsigned TokLength, | |||
904 | bool ExpansionIsTokenRange = true, | |||
905 | int LoadedID = 0, | |||
906 | unsigned LoadedOffset = 0); | |||
907 | ||||
908 | /// Return a new SourceLocation that encodes that the token starting | |||
909 | /// at \p TokenStart ends prematurely at \p TokenEnd. | |||
910 | SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc, | |||
911 | SourceLocation TokenStart, | |||
912 | SourceLocation TokenEnd); | |||
913 | ||||
914 | /// Retrieve the memory buffer associated with the given file. | |||
915 | /// | |||
916 | /// \param Invalid If non-NULL, will be set \c true if an error | |||
917 | /// occurs while retrieving the memory buffer. | |||
918 | const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File, | |||
919 | bool *Invalid = nullptr); | |||
920 | ||||
921 | /// Override the contents of the given source file by providing an | |||
922 | /// already-allocated buffer. | |||
923 | /// | |||
924 | /// \param SourceFile the source file whose contents will be overridden. | |||
925 | /// | |||
926 | /// \param Buffer the memory buffer whose contents will be used as the | |||
927 | /// data in the given source file. | |||
928 | /// | |||
929 | /// \param DoNotFree If true, then the buffer will not be freed when the | |||
930 | /// source manager is destroyed. | |||
931 | void overrideFileContents(const FileEntry *SourceFile, | |||
932 | llvm::MemoryBuffer *Buffer, bool DoNotFree); | |||
933 | void overrideFileContents(const FileEntry *SourceFile, | |||
934 | std::unique_ptr<llvm::MemoryBuffer> Buffer) { | |||
935 | overrideFileContents(SourceFile, Buffer.release(), /*DoNotFree*/ false); | |||
936 | } | |||
937 | ||||
938 | /// Override the given source file with another one. | |||
939 | /// | |||
940 | /// \param SourceFile the source file which will be overridden. | |||
941 | /// | |||
942 | /// \param NewFile the file whose contents will be used as the | |||
943 | /// data instead of the contents of the given source file. | |||
944 | void overrideFileContents(const FileEntry *SourceFile, | |||
945 | const FileEntry *NewFile); | |||
946 | ||||
947 | /// Returns true if the file contents have been overridden. | |||
948 | bool isFileOverridden(const FileEntry *File) const { | |||
949 | if (OverriddenFilesInfo) { | |||
950 | if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File)) | |||
951 | return true; | |||
952 | if (OverriddenFilesInfo->OverriddenFiles.find(File) != | |||
953 | OverriddenFilesInfo->OverriddenFiles.end()) | |||
954 | return true; | |||
955 | } | |||
956 | return false; | |||
957 | } | |||
958 | ||||
959 | /// Bypass the overridden contents of a file. This creates a new FileEntry | |||
960 | /// and initializes the content cache for it. Returns nullptr if there is no | |||
961 | /// such file in the filesystem. | |||
962 | /// | |||
963 | /// This should be called before parsing has begun. | |||
964 | const FileEntry *bypassFileContentsOverride(const FileEntry &File); | |||
965 | ||||
966 | /// Specify that a file is transient. | |||
967 | void setFileIsTransient(const FileEntry *SourceFile); | |||
968 | ||||
969 | /// Specify that all files that are read during this compilation are | |||
970 | /// transient. | |||
971 | void setAllFilesAreTransient(bool Transient) { | |||
972 | FilesAreTransient = Transient; | |||
973 | } | |||
974 | ||||
975 | //===--------------------------------------------------------------------===// | |||
976 | // FileID manipulation methods. | |||
977 | //===--------------------------------------------------------------------===// | |||
978 | ||||
979 | /// Return the buffer for the specified FileID. | |||
980 | /// | |||
981 | /// If there is an error opening this buffer the first time, this | |||
982 | /// manufactures a temporary buffer and returns a non-empty error string. | |||
983 | const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc, | |||
984 | bool *Invalid = nullptr) const { | |||
985 | bool MyInvalid = false; | |||
986 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); | |||
987 | if (MyInvalid || !Entry.isFile()) { | |||
988 | if (Invalid) | |||
989 | *Invalid = true; | |||
990 | ||||
991 | return getFakeBufferForRecovery(); | |||
992 | } | |||
993 | ||||
994 | return Entry.getFile().getContentCache()->getBuffer(Diag, getFileManager(), | |||
995 | Loc, Invalid); | |||
996 | } | |||
997 | ||||
998 | const llvm::MemoryBuffer *getBuffer(FileID FID, | |||
999 | bool *Invalid = nullptr) const { | |||
1000 | bool MyInvalid = false; | |||
1001 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); | |||
1002 | if (MyInvalid || !Entry.isFile()) { | |||
1003 | if (Invalid) | |||
1004 | *Invalid = true; | |||
1005 | ||||
1006 | return getFakeBufferForRecovery(); | |||
1007 | } | |||
1008 | ||||
1009 | return Entry.getFile().getContentCache()->getBuffer( | |||
1010 | Diag, getFileManager(), SourceLocation(), Invalid); | |||
1011 | } | |||
1012 | ||||
1013 | /// Returns the FileEntry record for the provided FileID. | |||
1014 | const FileEntry *getFileEntryForID(FileID FID) const { | |||
1015 | bool MyInvalid = false; | |||
1016 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); | |||
1017 | if (MyInvalid || !Entry.isFile()) | |||
1018 | return nullptr; | |||
1019 | ||||
1020 | const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache(); | |||
1021 | if (!Content) | |||
1022 | return nullptr; | |||
1023 | return Content->OrigEntry; | |||
1024 | } | |||
1025 | ||||
1026 | /// Returns the FileEntryRef for the provided FileID. | |||
1027 | Optional<FileEntryRef> getFileEntryRefForID(FileID FID) const { | |||
1028 | bool Invalid = false; | |||
1029 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); | |||
1030 | if (Invalid || !Entry.isFile()) | |||
1031 | return None; | |||
1032 | ||||
1033 | const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache(); | |||
1034 | if (!Content || !Content->OrigEntry) | |||
1035 | return None; | |||
1036 | return FileEntryRef(Entry.getFile().getName(), *Content->OrigEntry); | |||
1037 | } | |||
1038 | ||||
1039 | /// Returns the FileEntry record for the provided SLocEntry. | |||
1040 | const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const | |||
1041 | { | |||
1042 | const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache(); | |||
1043 | if (!Content) | |||
1044 | return nullptr; | |||
1045 | return Content->OrigEntry; | |||
1046 | } | |||
1047 | ||||
1048 | /// Return a StringRef to the source buffer data for the | |||
1049 | /// specified FileID. | |||
1050 | /// | |||
1051 | /// \param FID The file ID whose contents will be returned. | |||
1052 | /// \param Invalid If non-NULL, will be set true if an error occurred. | |||
1053 | StringRef getBufferData(FileID FID, bool *Invalid = nullptr) const; | |||
1054 | ||||
1055 | /// Get the number of FileIDs (files and macros) that were created | |||
1056 | /// during preprocessing of \p FID, including it. | |||
1057 | unsigned getNumCreatedFIDsForFileID(FileID FID) const { | |||
1058 | bool Invalid = false; | |||
1059 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); | |||
1060 | if (Invalid || !Entry.isFile()) | |||
1061 | return 0; | |||
1062 | ||||
1063 | return Entry.getFile().NumCreatedFIDs; | |||
1064 | } | |||
1065 | ||||
1066 | /// Set the number of FileIDs (files and macros) that were created | |||
1067 | /// during preprocessing of \p FID, including it. | |||
1068 | void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs, | |||
1069 | bool Force = false) const { | |||
1070 | bool Invalid = false; | |||
1071 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); | |||
1072 | if (Invalid || !Entry.isFile()) | |||
1073 | return; | |||
1074 | ||||
1075 | assert((Force || Entry.getFile().NumCreatedFIDs == 0) && "Already set!")(((Force || Entry.getFile().NumCreatedFIDs == 0) && "Already set!" ) ? static_cast<void> (0) : __assert_fail ("(Force || Entry.getFile().NumCreatedFIDs == 0) && \"Already set!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1075, __PRETTY_FUNCTION__)); | |||
1076 | const_cast<SrcMgr::FileInfo &>(Entry.getFile()).NumCreatedFIDs = NumFIDs; | |||
1077 | } | |||
1078 | ||||
1079 | //===--------------------------------------------------------------------===// | |||
1080 | // SourceLocation manipulation methods. | |||
1081 | //===--------------------------------------------------------------------===// | |||
1082 | ||||
1083 | /// Return the FileID for a SourceLocation. | |||
1084 | /// | |||
1085 | /// This is a very hot method that is used for all SourceManager queries | |||
1086 | /// that start with a SourceLocation object. It is responsible for finding | |||
1087 | /// the entry in SLocEntryTable which contains the specified location. | |||
1088 | /// | |||
1089 | FileID getFileID(SourceLocation SpellingLoc) const { | |||
1090 | unsigned SLocOffset = SpellingLoc.getOffset(); | |||
1091 | ||||
1092 | // If our one-entry cache covers this offset, just return it. | |||
1093 | if (isOffsetInFileID(LastFileIDLookup, SLocOffset)) | |||
1094 | return LastFileIDLookup; | |||
1095 | ||||
1096 | return getFileIDSlow(SLocOffset); | |||
1097 | } | |||
1098 | ||||
1099 | /// Return the filename of the file containing a SourceLocation. | |||
1100 | StringRef getFilename(SourceLocation SpellingLoc) const { | |||
1101 | if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc))) | |||
1102 | return F->getName(); | |||
1103 | return StringRef(); | |||
1104 | } | |||
1105 | ||||
1106 | /// Return the source location corresponding to the first byte of | |||
1107 | /// the specified file. | |||
1108 | SourceLocation getLocForStartOfFile(FileID FID) const { | |||
1109 | bool Invalid = false; | |||
1110 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); | |||
1111 | if (Invalid || !Entry.isFile()) | |||
1112 | return SourceLocation(); | |||
1113 | ||||
1114 | unsigned FileOffset = Entry.getOffset(); | |||
1115 | return SourceLocation::getFileLoc(FileOffset); | |||
1116 | } | |||
1117 | ||||
1118 | /// Return the source location corresponding to the last byte of the | |||
1119 | /// specified file. | |||
1120 | SourceLocation getLocForEndOfFile(FileID FID) const { | |||
1121 | bool Invalid = false; | |||
1122 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); | |||
1123 | if (Invalid || !Entry.isFile()) | |||
1124 | return SourceLocation(); | |||
1125 | ||||
1126 | unsigned FileOffset = Entry.getOffset(); | |||
1127 | return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID)); | |||
1128 | } | |||
1129 | ||||
1130 | /// Returns the include location if \p FID is a \#include'd file | |||
1131 | /// otherwise it returns an invalid location. | |||
1132 | SourceLocation getIncludeLoc(FileID FID) const { | |||
1133 | bool Invalid = false; | |||
1134 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); | |||
1135 | if (Invalid || !Entry.isFile()) | |||
1136 | return SourceLocation(); | |||
1137 | ||||
1138 | return Entry.getFile().getIncludeLoc(); | |||
1139 | } | |||
1140 | ||||
1141 | // Returns the import location if the given source location is | |||
1142 | // located within a module, or an invalid location if the source location | |||
1143 | // is within the current translation unit. | |||
1144 | std::pair<SourceLocation, StringRef> | |||
1145 | getModuleImportLoc(SourceLocation Loc) const { | |||
1146 | FileID FID = getFileID(Loc); | |||
1147 | ||||
1148 | // Positive file IDs are in the current translation unit, and -1 is a | |||
1149 | // placeholder. | |||
1150 | if (FID.ID >= -1) | |||
1151 | return std::make_pair(SourceLocation(), ""); | |||
1152 | ||||
1153 | return ExternalSLocEntries->getModuleImportLoc(FID.ID); | |||
1154 | } | |||
1155 | ||||
1156 | /// Given a SourceLocation object \p Loc, return the expansion | |||
1157 | /// location referenced by the ID. | |||
1158 | SourceLocation getExpansionLoc(SourceLocation Loc) const { | |||
1159 | // Handle the non-mapped case inline, defer to out of line code to handle | |||
1160 | // expansions. | |||
1161 | if (Loc.isFileID()) return Loc; | |||
1162 | return getExpansionLocSlowCase(Loc); | |||
1163 | } | |||
1164 | ||||
1165 | /// Given \p Loc, if it is a macro location return the expansion | |||
1166 | /// location or the spelling location, depending on if it comes from a | |||
1167 | /// macro argument or not. | |||
1168 | SourceLocation getFileLoc(SourceLocation Loc) const { | |||
1169 | if (Loc.isFileID()) return Loc; | |||
1170 | return getFileLocSlowCase(Loc); | |||
1171 | } | |||
1172 | ||||
1173 | /// Return the start/end of the expansion information for an | |||
1174 | /// expansion location. | |||
1175 | /// | |||
1176 | /// \pre \p Loc is required to be an expansion location. | |||
1177 | CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const; | |||
1178 | ||||
1179 | /// Given a SourceLocation object, return the range of | |||
1180 | /// tokens covered by the expansion in the ultimate file. | |||
1181 | CharSourceRange getExpansionRange(SourceLocation Loc) const; | |||
1182 | ||||
1183 | /// Given a SourceRange object, return the range of | |||
1184 | /// tokens or characters covered by the expansion in the ultimate file. | |||
1185 | CharSourceRange getExpansionRange(SourceRange Range) const { | |||
1186 | SourceLocation Begin = getExpansionRange(Range.getBegin()).getBegin(); | |||
1187 | CharSourceRange End = getExpansionRange(Range.getEnd()); | |||
1188 | return CharSourceRange(SourceRange(Begin, End.getEnd()), | |||
1189 | End.isTokenRange()); | |||
1190 | } | |||
1191 | ||||
1192 | /// Given a CharSourceRange object, return the range of | |||
1193 | /// tokens or characters covered by the expansion in the ultimate file. | |||
1194 | CharSourceRange getExpansionRange(CharSourceRange Range) const { | |||
1195 | CharSourceRange Expansion = getExpansionRange(Range.getAsRange()); | |||
1196 | if (Expansion.getEnd() == Range.getEnd()) | |||
1197 | Expansion.setTokenRange(Range.isTokenRange()); | |||
1198 | return Expansion; | |||
1199 | } | |||
1200 | ||||
1201 | /// Given a SourceLocation object, return the spelling | |||
1202 | /// location referenced by the ID. | |||
1203 | /// | |||
1204 | /// This is the place where the characters that make up the lexed token | |||
1205 | /// can be found. | |||
1206 | SourceLocation getSpellingLoc(SourceLocation Loc) const { | |||
1207 | // Handle the non-mapped case inline, defer to out of line code to handle | |||
1208 | // expansions. | |||
1209 | if (Loc.isFileID()) return Loc; | |||
1210 | return getSpellingLocSlowCase(Loc); | |||
1211 | } | |||
1212 | ||||
1213 | /// Given a SourceLocation object, return the spelling location | |||
1214 | /// referenced by the ID. | |||
1215 | /// | |||
1216 | /// This is the first level down towards the place where the characters | |||
1217 | /// that make up the lexed token can be found. This should not generally | |||
1218 | /// be used by clients. | |||
1219 | SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const; | |||
1220 | ||||
1221 | /// Form a SourceLocation from a FileID and Offset pair. | |||
1222 | SourceLocation getComposedLoc(FileID FID, unsigned Offset) const { | |||
1223 | bool Invalid = false; | |||
1224 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); | |||
1225 | if (Invalid) | |||
1226 | return SourceLocation(); | |||
1227 | ||||
1228 | unsigned GlobalOffset = Entry.getOffset() + Offset; | |||
1229 | return Entry.isFile() ? SourceLocation::getFileLoc(GlobalOffset) | |||
1230 | : SourceLocation::getMacroLoc(GlobalOffset); | |||
1231 | } | |||
1232 | ||||
1233 | /// Decompose the specified location into a raw FileID + Offset pair. | |||
1234 | /// | |||
1235 | /// The first element is the FileID, the second is the offset from the | |||
1236 | /// start of the buffer of the location. | |||
1237 | std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const { | |||
1238 | FileID FID = getFileID(Loc); | |||
1239 | bool Invalid = false; | |||
1240 | const SrcMgr::SLocEntry &E = getSLocEntry(FID, &Invalid); | |||
1241 | if (Invalid) | |||
1242 | return std::make_pair(FileID(), 0); | |||
1243 | return std::make_pair(FID, Loc.getOffset()-E.getOffset()); | |||
1244 | } | |||
1245 | ||||
1246 | /// Decompose the specified location into a raw FileID + Offset pair. | |||
1247 | /// | |||
1248 | /// If the location is an expansion record, walk through it until we find | |||
1249 | /// the final location expanded. | |||
1250 | std::pair<FileID, unsigned> | |||
1251 | getDecomposedExpansionLoc(SourceLocation Loc) const { | |||
1252 | FileID FID = getFileID(Loc); | |||
1253 | bool Invalid = false; | |||
1254 | const SrcMgr::SLocEntry *E = &getSLocEntry(FID, &Invalid); | |||
1255 | if (Invalid) | |||
1256 | return std::make_pair(FileID(), 0); | |||
1257 | ||||
1258 | unsigned Offset = Loc.getOffset()-E->getOffset(); | |||
1259 | if (Loc.isFileID()) | |||
1260 | return std::make_pair(FID, Offset); | |||
1261 | ||||
1262 | return getDecomposedExpansionLocSlowCase(E); | |||
1263 | } | |||
1264 | ||||
1265 | /// Decompose the specified location into a raw FileID + Offset pair. | |||
1266 | /// | |||
1267 | /// If the location is an expansion record, walk through it until we find | |||
1268 | /// its spelling record. | |||
1269 | std::pair<FileID, unsigned> | |||
1270 | getDecomposedSpellingLoc(SourceLocation Loc) const { | |||
1271 | FileID FID = getFileID(Loc); | |||
1272 | bool Invalid = false; | |||
1273 | const SrcMgr::SLocEntry *E = &getSLocEntry(FID, &Invalid); | |||
1274 | if (Invalid) | |||
1275 | return std::make_pair(FileID(), 0); | |||
1276 | ||||
1277 | unsigned Offset = Loc.getOffset()-E->getOffset(); | |||
1278 | if (Loc.isFileID()) | |||
1279 | return std::make_pair(FID, Offset); | |||
1280 | return getDecomposedSpellingLocSlowCase(E, Offset); | |||
1281 | } | |||
1282 | ||||
1283 | /// Returns the "included/expanded in" decomposed location of the given | |||
1284 | /// FileID. | |||
1285 | std::pair<FileID, unsigned> getDecomposedIncludedLoc(FileID FID) const; | |||
1286 | ||||
1287 | /// Returns the offset from the start of the file that the | |||
1288 | /// specified SourceLocation represents. | |||
1289 | /// | |||
1290 | /// This is not very meaningful for a macro ID. | |||
1291 | unsigned getFileOffset(SourceLocation SpellingLoc) const { | |||
1292 | return getDecomposedLoc(SpellingLoc).second; | |||
1293 | } | |||
1294 | ||||
1295 | /// Tests whether the given source location represents a macro | |||
1296 | /// argument's expansion into the function-like macro definition. | |||
1297 | /// | |||
1298 | /// \param StartLoc If non-null and function returns true, it is set to the | |||
1299 | /// start location of the macro argument expansion. | |||
1300 | /// | |||
1301 | /// Such source locations only appear inside of the expansion | |||
1302 | /// locations representing where a particular function-like macro was | |||
1303 | /// expanded. | |||
1304 | bool isMacroArgExpansion(SourceLocation Loc, | |||
1305 | SourceLocation *StartLoc = nullptr) const; | |||
1306 | ||||
1307 | /// Tests whether the given source location represents the expansion of | |||
1308 | /// a macro body. | |||
1309 | /// | |||
1310 | /// This is equivalent to testing whether the location is part of a macro | |||
1311 | /// expansion but not the expansion of an argument to a function-like macro. | |||
1312 | bool isMacroBodyExpansion(SourceLocation Loc) const; | |||
1313 | ||||
1314 | /// Returns true if the given MacroID location points at the beginning | |||
1315 | /// of the immediate macro expansion. | |||
1316 | /// | |||
1317 | /// \param MacroBegin If non-null and function returns true, it is set to the | |||
1318 | /// begin location of the immediate macro expansion. | |||
1319 | bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, | |||
1320 | SourceLocation *MacroBegin = nullptr) const; | |||
1321 | ||||
1322 | /// Returns true if the given MacroID location points at the character | |||
1323 | /// end of the immediate macro expansion. | |||
1324 | /// | |||
1325 | /// \param MacroEnd If non-null and function returns true, it is set to the | |||
1326 | /// character end location of the immediate macro expansion. | |||
1327 | bool | |||
1328 | isAtEndOfImmediateMacroExpansion(SourceLocation Loc, | |||
1329 | SourceLocation *MacroEnd = nullptr) const; | |||
1330 | ||||
1331 | /// Returns true if \p Loc is inside the [\p Start, +\p Length) | |||
1332 | /// chunk of the source location address space. | |||
1333 | /// | |||
1334 | /// If it's true and \p RelativeOffset is non-null, it will be set to the | |||
1335 | /// relative offset of \p Loc inside the chunk. | |||
1336 | bool isInSLocAddrSpace(SourceLocation Loc, | |||
1337 | SourceLocation Start, unsigned Length, | |||
1338 | unsigned *RelativeOffset = nullptr) const { | |||
1339 | assert(((Start.getOffset() < NextLocalOffset &&((((Start.getOffset() < NextLocalOffset && Start.getOffset ()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && Start.getOffset()+Length < MaxLoadedOffset)) && "Chunk is not valid SLoc address space") ? static_cast<void > (0) : __assert_fail ("((Start.getOffset() < NextLocalOffset && Start.getOffset()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && Start.getOffset()+Length < MaxLoadedOffset)) && \"Chunk is not valid SLoc address space\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1343, __PRETTY_FUNCTION__)) | |||
1340 | Start.getOffset()+Length <= NextLocalOffset) ||((((Start.getOffset() < NextLocalOffset && Start.getOffset ()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && Start.getOffset()+Length < MaxLoadedOffset)) && "Chunk is not valid SLoc address space") ? static_cast<void > (0) : __assert_fail ("((Start.getOffset() < NextLocalOffset && Start.getOffset()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && Start.getOffset()+Length < MaxLoadedOffset)) && \"Chunk is not valid SLoc address space\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1343, __PRETTY_FUNCTION__)) | |||
1341 | (Start.getOffset() >= CurrentLoadedOffset &&((((Start.getOffset() < NextLocalOffset && Start.getOffset ()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && Start.getOffset()+Length < MaxLoadedOffset)) && "Chunk is not valid SLoc address space") ? static_cast<void > (0) : __assert_fail ("((Start.getOffset() < NextLocalOffset && Start.getOffset()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && Start.getOffset()+Length < MaxLoadedOffset)) && \"Chunk is not valid SLoc address space\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1343, __PRETTY_FUNCTION__)) | |||
1342 | Start.getOffset()+Length < MaxLoadedOffset)) &&((((Start.getOffset() < NextLocalOffset && Start.getOffset ()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && Start.getOffset()+Length < MaxLoadedOffset)) && "Chunk is not valid SLoc address space") ? static_cast<void > (0) : __assert_fail ("((Start.getOffset() < NextLocalOffset && Start.getOffset()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && Start.getOffset()+Length < MaxLoadedOffset)) && \"Chunk is not valid SLoc address space\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1343, __PRETTY_FUNCTION__)) | |||
1343 | "Chunk is not valid SLoc address space")((((Start.getOffset() < NextLocalOffset && Start.getOffset ()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && Start.getOffset()+Length < MaxLoadedOffset)) && "Chunk is not valid SLoc address space") ? static_cast<void > (0) : __assert_fail ("((Start.getOffset() < NextLocalOffset && Start.getOffset()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && Start.getOffset()+Length < MaxLoadedOffset)) && \"Chunk is not valid SLoc address space\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1343, __PRETTY_FUNCTION__)); | |||
1344 | unsigned LocOffs = Loc.getOffset(); | |||
1345 | unsigned BeginOffs = Start.getOffset(); | |||
1346 | unsigned EndOffs = BeginOffs + Length; | |||
1347 | if (LocOffs >= BeginOffs && LocOffs < EndOffs) { | |||
1348 | if (RelativeOffset) | |||
1349 | *RelativeOffset = LocOffs - BeginOffs; | |||
1350 | return true; | |||
1351 | } | |||
1352 | ||||
1353 | return false; | |||
1354 | } | |||
1355 | ||||
1356 | /// Return true if both \p LHS and \p RHS are in the local source | |||
1357 | /// location address space or the loaded one. | |||
1358 | /// | |||
1359 | /// If it's true and \p RelativeOffset is non-null, it will be set to the | |||
1360 | /// offset of \p RHS relative to \p LHS. | |||
1361 | bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS, | |||
1362 | int *RelativeOffset) const { | |||
1363 | unsigned LHSOffs = LHS.getOffset(), RHSOffs = RHS.getOffset(); | |||
1364 | bool LHSLoaded = LHSOffs >= CurrentLoadedOffset; | |||
1365 | bool RHSLoaded = RHSOffs >= CurrentLoadedOffset; | |||
1366 | ||||
1367 | if (LHSLoaded == RHSLoaded) { | |||
1368 | if (RelativeOffset) | |||
1369 | *RelativeOffset = RHSOffs - LHSOffs; | |||
1370 | return true; | |||
1371 | } | |||
1372 | ||||
1373 | return false; | |||
1374 | } | |||
1375 | ||||
1376 | //===--------------------------------------------------------------------===// | |||
1377 | // Queries about the code at a SourceLocation. | |||
1378 | //===--------------------------------------------------------------------===// | |||
1379 | ||||
1380 | /// Return a pointer to the start of the specified location | |||
1381 | /// in the appropriate spelling MemoryBuffer. | |||
1382 | /// | |||
1383 | /// \param Invalid If non-NULL, will be set \c true if an error occurs. | |||
1384 | const char *getCharacterData(SourceLocation SL, | |||
1385 | bool *Invalid = nullptr) const; | |||
1386 | ||||
1387 | /// Return the column # for the specified file position. | |||
1388 | /// | |||
1389 | /// This is significantly cheaper to compute than the line number. This | |||
1390 | /// returns zero if the column number isn't known. This may only be called | |||
1391 | /// on a file sloc, so you must choose a spelling or expansion location | |||
1392 | /// before calling this method. | |||
1393 | unsigned getColumnNumber(FileID FID, unsigned FilePos, | |||
1394 | bool *Invalid = nullptr) const; | |||
1395 | unsigned getSpellingColumnNumber(SourceLocation Loc, | |||
1396 | bool *Invalid = nullptr) const; | |||
1397 | unsigned getExpansionColumnNumber(SourceLocation Loc, | |||
1398 | bool *Invalid = nullptr) const; | |||
1399 | unsigned getPresumedColumnNumber(SourceLocation Loc, | |||
1400 | bool *Invalid = nullptr) const; | |||
1401 | ||||
1402 | /// Given a SourceLocation, return the spelling line number | |||
1403 | /// for the position indicated. | |||
1404 | /// | |||
1405 | /// This requires building and caching a table of line offsets for the | |||
1406 | /// MemoryBuffer, so this is not cheap: use only when about to emit a | |||
1407 | /// diagnostic. | |||
1408 | unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = nullptr) const; | |||
1409 | unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; | |||
1410 | unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; | |||
1411 | unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; | |||
1412 | ||||
1413 | /// Return the filename or buffer identifier of the buffer the | |||
1414 | /// location is in. | |||
1415 | /// | |||
1416 | /// Note that this name does not respect \#line directives. Use | |||
1417 | /// getPresumedLoc for normal clients. | |||
1418 | StringRef getBufferName(SourceLocation Loc, bool *Invalid = nullptr) const; | |||
1419 | ||||
1420 | /// Return the file characteristic of the specified source | |||
1421 | /// location, indicating whether this is a normal file, a system | |||
1422 | /// header, or an "implicit extern C" system header. | |||
1423 | /// | |||
1424 | /// This state can be modified with flags on GNU linemarker directives like: | |||
1425 | /// \code | |||
1426 | /// # 4 "foo.h" 3 | |||
1427 | /// \endcode | |||
1428 | /// which changes all source locations in the current file after that to be | |||
1429 | /// considered to be from a system header. | |||
1430 | SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const; | |||
1431 | ||||
1432 | /// Returns the "presumed" location of a SourceLocation specifies. | |||
1433 | /// | |||
1434 | /// A "presumed location" can be modified by \#line or GNU line marker | |||
1435 | /// directives. This provides a view on the data that a user should see | |||
1436 | /// in diagnostics, for example. | |||
1437 | /// | |||
1438 | /// Note that a presumed location is always given as the expansion point of | |||
1439 | /// an expansion location, not at the spelling location. | |||
1440 | /// | |||
1441 | /// \returns The presumed location of the specified SourceLocation. If the | |||
1442 | /// presumed location cannot be calculated (e.g., because \p Loc is invalid | |||
1443 | /// or the file containing \p Loc has changed on disk), returns an invalid | |||
1444 | /// presumed location. | |||
1445 | PresumedLoc getPresumedLoc(SourceLocation Loc, | |||
1446 | bool UseLineDirectives = true) const; | |||
1447 | ||||
1448 | /// Returns whether the PresumedLoc for a given SourceLocation is | |||
1449 | /// in the main file. | |||
1450 | /// | |||
1451 | /// This computes the "presumed" location for a SourceLocation, then checks | |||
1452 | /// whether it came from a file other than the main file. This is different | |||
1453 | /// from isWrittenInMainFile() because it takes line marker directives into | |||
1454 | /// account. | |||
1455 | bool isInMainFile(SourceLocation Loc) const; | |||
1456 | ||||
1457 | /// Returns true if the spelling locations for both SourceLocations | |||
1458 | /// are part of the same file buffer. | |||
1459 | /// | |||
1460 | /// This check ignores line marker directives. | |||
1461 | bool isWrittenInSameFile(SourceLocation Loc1, SourceLocation Loc2) const { | |||
1462 | return getFileID(Loc1) == getFileID(Loc2); | |||
1463 | } | |||
1464 | ||||
1465 | /// Returns true if the spelling location for the given location | |||
1466 | /// is in the main file buffer. | |||
1467 | /// | |||
1468 | /// This check ignores line marker directives. | |||
1469 | bool isWrittenInMainFile(SourceLocation Loc) const { | |||
1470 | return getFileID(Loc) == getMainFileID(); | |||
1471 | } | |||
1472 | ||||
1473 | /// Returns whether \p Loc is located in a <built-in> file. | |||
1474 | bool isWrittenInBuiltinFile(SourceLocation Loc) const { | |||
1475 | StringRef Filename(getPresumedLoc(Loc).getFilename()); | |||
1476 | return Filename.equals("<built-in>"); | |||
1477 | } | |||
1478 | ||||
1479 | /// Returns whether \p Loc is located in a <command line> file. | |||
1480 | bool isWrittenInCommandLineFile(SourceLocation Loc) const { | |||
1481 | StringRef Filename(getPresumedLoc(Loc).getFilename()); | |||
1482 | return Filename.equals("<command line>"); | |||
1483 | } | |||
1484 | ||||
1485 | /// Returns whether \p Loc is located in a <scratch space> file. | |||
1486 | bool isWrittenInScratchSpace(SourceLocation Loc) const { | |||
1487 | StringRef Filename(getPresumedLoc(Loc).getFilename()); | |||
1488 | return Filename.equals("<scratch space>"); | |||
1489 | } | |||
1490 | ||||
1491 | /// Returns if a SourceLocation is in a system header. | |||
1492 | bool isInSystemHeader(SourceLocation Loc) const { | |||
1493 | return isSystem(getFileCharacteristic(Loc)); | |||
1494 | } | |||
1495 | ||||
1496 | /// Returns if a SourceLocation is in an "extern C" system header. | |||
1497 | bool isInExternCSystemHeader(SourceLocation Loc) const { | |||
1498 | return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem; | |||
1499 | } | |||
1500 | ||||
1501 | /// Returns whether \p Loc is expanded from a macro in a system header. | |||
1502 | bool isInSystemMacro(SourceLocation loc) const { | |||
1503 | if (!loc.isMacroID()) | |||
1504 | return false; | |||
1505 | ||||
1506 | // This happens when the macro is the result of a paste, in that case | |||
1507 | // its spelling is the scratch memory, so we take the parent context. | |||
1508 | // There can be several level of token pasting. | |||
1509 | if (isWrittenInScratchSpace(getSpellingLoc(loc))) { | |||
1510 | do { | |||
1511 | loc = getImmediateMacroCallerLoc(loc); | |||
1512 | } while (isWrittenInScratchSpace(getSpellingLoc(loc))); | |||
1513 | return isInSystemMacro(loc); | |||
1514 | } | |||
1515 | ||||
1516 | return isInSystemHeader(getSpellingLoc(loc)); | |||
1517 | } | |||
1518 | ||||
1519 | /// The size of the SLocEntry that \p FID represents. | |||
1520 | unsigned getFileIDSize(FileID FID) const; | |||
1521 | ||||
1522 | /// Given a specific FileID, returns true if \p Loc is inside that | |||
1523 | /// FileID chunk and sets relative offset (offset of \p Loc from beginning | |||
1524 | /// of FileID) to \p relativeOffset. | |||
1525 | bool isInFileID(SourceLocation Loc, FileID FID, | |||
1526 | unsigned *RelativeOffset = nullptr) const { | |||
1527 | unsigned Offs = Loc.getOffset(); | |||
1528 | if (isOffsetInFileID(FID, Offs)) { | |||
1529 | if (RelativeOffset) | |||
1530 | *RelativeOffset = Offs - getSLocEntry(FID).getOffset(); | |||
1531 | return true; | |||
1532 | } | |||
1533 | ||||
1534 | return false; | |||
1535 | } | |||
1536 | ||||
1537 | //===--------------------------------------------------------------------===// | |||
1538 | // Line Table Manipulation Routines | |||
1539 | //===--------------------------------------------------------------------===// | |||
1540 | ||||
1541 | /// Return the uniqued ID for the specified filename. | |||
1542 | unsigned getLineTableFilenameID(StringRef Str); | |||
1543 | ||||
1544 | /// Add a line note to the line table for the FileID and offset | |||
1545 | /// specified by Loc. | |||
1546 | /// | |||
1547 | /// If FilenameID is -1, it is considered to be unspecified. | |||
1548 | void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, | |||
1549 | bool IsFileEntry, bool IsFileExit, | |||
1550 | SrcMgr::CharacteristicKind FileKind); | |||
1551 | ||||
1552 | /// Determine if the source manager has a line table. | |||
1553 | bool hasLineTable() const { return LineTable != nullptr; } | |||
1554 | ||||
1555 | /// Retrieve the stored line table. | |||
1556 | LineTableInfo &getLineTable(); | |||
1557 | ||||
1558 | //===--------------------------------------------------------------------===// | |||
1559 | // Queries for performance analysis. | |||
1560 | //===--------------------------------------------------------------------===// | |||
1561 | ||||
1562 | /// Return the total amount of physical memory allocated by the | |||
1563 | /// ContentCache allocator. | |||
1564 | size_t getContentCacheSize() const { | |||
1565 | return ContentCacheAlloc.getTotalMemory(); | |||
1566 | } | |||
1567 | ||||
1568 | struct MemoryBufferSizes { | |||
1569 | const size_t malloc_bytes; | |||
1570 | const size_t mmap_bytes; | |||
1571 | ||||
1572 | MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) | |||
1573 | : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} | |||
1574 | }; | |||
1575 | ||||
1576 | /// Return the amount of memory used by memory buffers, breaking down | |||
1577 | /// by heap-backed versus mmap'ed memory. | |||
1578 | MemoryBufferSizes getMemoryBufferSizes() const; | |||
1579 | ||||
1580 | /// Return the amount of memory used for various side tables and | |||
1581 | /// data structures in the SourceManager. | |||
1582 | size_t getDataStructureSizes() const; | |||
1583 | ||||
1584 | //===--------------------------------------------------------------------===// | |||
1585 | // Other miscellaneous methods. | |||
1586 | //===--------------------------------------------------------------------===// | |||
1587 | ||||
1588 | /// Get the source location for the given file:line:col triplet. | |||
1589 | /// | |||
1590 | /// If the source file is included multiple times, the source location will | |||
1591 | /// be based upon the first inclusion. | |||
1592 | SourceLocation translateFileLineCol(const FileEntry *SourceFile, | |||
1593 | unsigned Line, unsigned Col) const; | |||
1594 | ||||
1595 | /// Get the FileID for the given file. | |||
1596 | /// | |||
1597 | /// If the source file is included multiple times, the FileID will be the | |||
1598 | /// first inclusion. | |||
1599 | FileID translateFile(const FileEntry *SourceFile) const; | |||
1600 | ||||
1601 | /// Get the source location in \p FID for the given line:col. | |||
1602 | /// Returns null location if \p FID is not a file SLocEntry. | |||
1603 | SourceLocation translateLineCol(FileID FID, | |||
1604 | unsigned Line, unsigned Col) const; | |||
1605 | ||||
1606 | /// If \p Loc points inside a function macro argument, the returned | |||
1607 | /// location will be the macro location in which the argument was expanded. | |||
1608 | /// If a macro argument is used multiple times, the expanded location will | |||
1609 | /// be at the first expansion of the argument. | |||
1610 | /// e.g. | |||
1611 | /// MY_MACRO(foo); | |||
1612 | /// ^ | |||
1613 | /// Passing a file location pointing at 'foo', will yield a macro location | |||
1614 | /// where 'foo' was expanded into. | |||
1615 | SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const; | |||
1616 | ||||
1617 | /// Determines the order of 2 source locations in the translation unit. | |||
1618 | /// | |||
1619 | /// \returns true if LHS source location comes before RHS, false otherwise. | |||
1620 | bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const; | |||
1621 | ||||
1622 | /// Determines whether the two decomposed source location is in the | |||
1623 | /// same translation unit. As a byproduct, it also calculates the order | |||
1624 | /// of the source locations in case they are in the same TU. | |||
1625 | /// | |||
1626 | /// \returns Pair of bools the first component is true if the two locations | |||
1627 | /// are in the same TU. The second bool is true if the first is true | |||
1628 | /// and \p LOffs is before \p ROffs. | |||
1629 | std::pair<bool, bool> | |||
1630 | isInTheSameTranslationUnit(std::pair<FileID, unsigned> &LOffs, | |||
1631 | std::pair<FileID, unsigned> &ROffs) const; | |||
1632 | ||||
1633 | /// Determines the order of 2 source locations in the "source location | |||
1634 | /// address space". | |||
1635 | bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const { | |||
1636 | return isBeforeInSLocAddrSpace(LHS, RHS.getOffset()); | |||
1637 | } | |||
1638 | ||||
1639 | /// Determines the order of a source location and a source location | |||
1640 | /// offset in the "source location address space". | |||
1641 | /// | |||
1642 | /// Note that we always consider source locations loaded from | |||
1643 | bool isBeforeInSLocAddrSpace(SourceLocation LHS, unsigned RHS) const { | |||
1644 | unsigned LHSOffset = LHS.getOffset(); | |||
1645 | bool LHSLoaded = LHSOffset >= CurrentLoadedOffset; | |||
1646 | bool RHSLoaded = RHS >= CurrentLoadedOffset; | |||
1647 | if (LHSLoaded == RHSLoaded) | |||
1648 | return LHSOffset < RHS; | |||
1649 | ||||
1650 | return LHSLoaded; | |||
1651 | } | |||
1652 | ||||
1653 | /// Return true if the Point is within Start and End. | |||
1654 | bool isPointWithin(SourceLocation Location, SourceLocation Start, | |||
1655 | SourceLocation End) const { | |||
1656 | return Location == Start || Location == End || | |||
1657 | (isBeforeInTranslationUnit(Start, Location) && | |||
1658 | isBeforeInTranslationUnit(Location, End)); | |||
1659 | } | |||
1660 | ||||
1661 | // Iterators over FileInfos. | |||
1662 | using fileinfo_iterator = | |||
1663 | llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::const_iterator; | |||
1664 | ||||
1665 | fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); } | |||
1666 | fileinfo_iterator fileinfo_end() const { return FileInfos.end(); } | |||
1667 | bool hasFileInfo(const FileEntry *File) const { | |||
1668 | return FileInfos.find(File) != FileInfos.end(); | |||
1669 | } | |||
1670 | ||||
1671 | /// Print statistics to stderr. | |||
1672 | void PrintStats() const; | |||
1673 | ||||
1674 | void dump() const; | |||
1675 | ||||
1676 | /// Get the number of local SLocEntries we have. | |||
1677 | unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); } | |||
1678 | ||||
1679 | /// Get a local SLocEntry. This is exposed for indexing. | |||
1680 | const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index, | |||
1681 | bool *Invalid = nullptr) const { | |||
1682 | assert(Index < LocalSLocEntryTable.size() && "Invalid index")((Index < LocalSLocEntryTable.size() && "Invalid index" ) ? static_cast<void> (0) : __assert_fail ("Index < LocalSLocEntryTable.size() && \"Invalid index\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1682, __PRETTY_FUNCTION__)); | |||
1683 | return LocalSLocEntryTable[Index]; | |||
1684 | } | |||
1685 | ||||
1686 | /// Get the number of loaded SLocEntries we have. | |||
1687 | unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();} | |||
1688 | ||||
1689 | /// Get a loaded SLocEntry. This is exposed for indexing. | |||
1690 | const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, | |||
1691 | bool *Invalid = nullptr) const { | |||
1692 | assert(Index < LoadedSLocEntryTable.size() && "Invalid index")((Index < LoadedSLocEntryTable.size() && "Invalid index" ) ? static_cast<void> (0) : __assert_fail ("Index < LoadedSLocEntryTable.size() && \"Invalid index\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1692, __PRETTY_FUNCTION__)); | |||
1693 | if (SLocEntryLoaded[Index]) | |||
1694 | return LoadedSLocEntryTable[Index]; | |||
1695 | return loadSLocEntry(Index, Invalid); | |||
1696 | } | |||
1697 | ||||
1698 | const SrcMgr::SLocEntry &getSLocEntry(FileID FID, | |||
1699 | bool *Invalid = nullptr) const { | |||
1700 | if (FID.ID == 0 || FID.ID == -1) { | |||
1701 | if (Invalid) *Invalid = true; | |||
1702 | return LocalSLocEntryTable[0]; | |||
1703 | } | |||
1704 | return getSLocEntryByID(FID.ID, Invalid); | |||
1705 | } | |||
1706 | ||||
1707 | unsigned getNextLocalOffset() const { return NextLocalOffset; } | |||
1708 | ||||
1709 | void setExternalSLocEntrySource(ExternalSLocEntrySource *Source) { | |||
1710 | assert(LoadedSLocEntryTable.empty() &&((LoadedSLocEntryTable.empty() && "Invalidating existing loaded entries" ) ? static_cast<void> (0) : __assert_fail ("LoadedSLocEntryTable.empty() && \"Invalidating existing loaded entries\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1711, __PRETTY_FUNCTION__)) | |||
1711 | "Invalidating existing loaded entries")((LoadedSLocEntryTable.empty() && "Invalidating existing loaded entries" ) ? static_cast<void> (0) : __assert_fail ("LoadedSLocEntryTable.empty() && \"Invalidating existing loaded entries\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1711, __PRETTY_FUNCTION__)); | |||
1712 | ExternalSLocEntries = Source; | |||
1713 | } | |||
1714 | ||||
1715 | /// Allocate a number of loaded SLocEntries, which will be actually | |||
1716 | /// loaded on demand from the external source. | |||
1717 | /// | |||
1718 | /// NumSLocEntries will be allocated, which occupy a total of TotalSize space | |||
1719 | /// in the global source view. The lowest ID and the base offset of the | |||
1720 | /// entries will be returned. | |||
1721 | std::pair<int, unsigned> | |||
1722 | AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize); | |||
1723 | ||||
1724 | /// Returns true if \p Loc came from a PCH/Module. | |||
1725 | bool isLoadedSourceLocation(SourceLocation Loc) const { | |||
1726 | return Loc.getOffset() >= CurrentLoadedOffset; | |||
1727 | } | |||
1728 | ||||
1729 | /// Returns true if \p Loc did not come from a PCH/Module. | |||
1730 | bool isLocalSourceLocation(SourceLocation Loc) const { | |||
1731 | return Loc.getOffset() < NextLocalOffset; | |||
1732 | } | |||
1733 | ||||
1734 | /// Returns true if \p FID came from a PCH/Module. | |||
1735 | bool isLoadedFileID(FileID FID) const { | |||
1736 | assert(FID.ID != -1 && "Using FileID sentinel value")((FID.ID != -1 && "Using FileID sentinel value") ? static_cast <void> (0) : __assert_fail ("FID.ID != -1 && \"Using FileID sentinel value\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1736, __PRETTY_FUNCTION__)); | |||
1737 | return FID.ID < 0; | |||
1738 | } | |||
1739 | ||||
1740 | /// Returns true if \p FID did not come from a PCH/Module. | |||
1741 | bool isLocalFileID(FileID FID) const { | |||
1742 | return !isLoadedFileID(FID); | |||
1743 | } | |||
1744 | ||||
1745 | /// Gets the location of the immediate macro caller, one level up the stack | |||
1746 | /// toward the initial macro typed into the source. | |||
1747 | SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const { | |||
1748 | if (!Loc.isMacroID()) return Loc; | |||
1749 | ||||
1750 | // When we have the location of (part of) an expanded parameter, its | |||
1751 | // spelling location points to the argument as expanded in the macro call, | |||
1752 | // and therefore is used to locate the macro caller. | |||
1753 | if (isMacroArgExpansion(Loc)) | |||
1754 | return getImmediateSpellingLoc(Loc); | |||
1755 | ||||
1756 | // Otherwise, the caller of the macro is located where this macro is | |||
1757 | // expanded (while the spelling is part of the macro definition). | |||
1758 | return getImmediateExpansionRange(Loc).getBegin(); | |||
1759 | } | |||
1760 | ||||
1761 | /// \return Location of the top-level macro caller. | |||
1762 | SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const; | |||
1763 | ||||
1764 | private: | |||
1765 | friend class ASTReader; | |||
1766 | friend class ASTWriter; | |||
1767 | ||||
1768 | llvm::MemoryBuffer *getFakeBufferForRecovery() const; | |||
1769 | const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const; | |||
1770 | ||||
1771 | const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const; | |||
1772 | ||||
1773 | /// Get the entry with the given unwrapped FileID. | |||
1774 | const SrcMgr::SLocEntry &getSLocEntryByID(int ID, | |||
1775 | bool *Invalid = nullptr) const { | |||
1776 | assert(ID != -1 && "Using FileID sentinel value")((ID != -1 && "Using FileID sentinel value") ? static_cast <void> (0) : __assert_fail ("ID != -1 && \"Using FileID sentinel value\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1776, __PRETTY_FUNCTION__)); | |||
1777 | if (ID < 0) | |||
1778 | return getLoadedSLocEntryByID(ID, Invalid); | |||
1779 | return getLocalSLocEntry(static_cast<unsigned>(ID), Invalid); | |||
1780 | } | |||
1781 | ||||
1782 | const SrcMgr::SLocEntry & | |||
1783 | getLoadedSLocEntryByID(int ID, bool *Invalid = nullptr) const { | |||
1784 | return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid); | |||
1785 | } | |||
1786 | ||||
1787 | /// Implements the common elements of storing an expansion info struct into | |||
1788 | /// the SLocEntry table and producing a source location that refers to it. | |||
1789 | SourceLocation createExpansionLocImpl(const SrcMgr::ExpansionInfo &Expansion, | |||
1790 | unsigned TokLength, | |||
1791 | int LoadedID = 0, | |||
1792 | unsigned LoadedOffset = 0); | |||
1793 | ||||
1794 | /// Return true if the specified FileID contains the | |||
1795 | /// specified SourceLocation offset. This is a very hot method. | |||
1796 | inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const { | |||
1797 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID); | |||
1798 | // If the entry is after the offset, it can't contain it. | |||
1799 | if (SLocOffset < Entry.getOffset()) return false; | |||
1800 | ||||
1801 | // If this is the very last entry then it does. | |||
1802 | if (FID.ID == -2) | |||
1803 | return true; | |||
1804 | ||||
1805 | // If it is the last local entry, then it does if the location is local. | |||
1806 | if (FID.ID+1 == static_cast<int>(LocalSLocEntryTable.size())) | |||
1807 | return SLocOffset < NextLocalOffset; | |||
1808 | ||||
1809 | // Otherwise, the entry after it has to not include it. This works for both | |||
1810 | // local and loaded entries. | |||
1811 | return SLocOffset < getSLocEntryByID(FID.ID+1).getOffset(); | |||
1812 | } | |||
1813 | ||||
1814 | /// Returns the previous in-order FileID or an invalid FileID if there | |||
1815 | /// is no previous one. | |||
1816 | FileID getPreviousFileID(FileID FID) const; | |||
1817 | ||||
1818 | /// Returns the next in-order FileID or an invalid FileID if there is | |||
1819 | /// no next one. | |||
1820 | FileID getNextFileID(FileID FID) const; | |||
1821 | ||||
1822 | /// Create a new fileID for the specified ContentCache and | |||
1823 | /// include position. | |||
1824 | /// | |||
1825 | /// This works regardless of whether the ContentCache corresponds to a | |||
1826 | /// file or some other input source. | |||
1827 | FileID createFileID(const SrcMgr::ContentCache *File, StringRef Filename, | |||
1828 | SourceLocation IncludePos, | |||
1829 | SrcMgr::CharacteristicKind DirCharacter, int LoadedID, | |||
1830 | unsigned LoadedOffset); | |||
1831 | ||||
1832 | const SrcMgr::ContentCache * | |||
1833 | getOrCreateContentCache(const FileEntry *SourceFile, | |||
1834 | bool isSystemFile = false); | |||
1835 | ||||
1836 | /// Create a new ContentCache for the specified memory buffer. | |||
1837 | const SrcMgr::ContentCache * | |||
1838 | createMemBufferContentCache(const llvm::MemoryBuffer *Buf, bool DoNotFree); | |||
1839 | ||||
1840 | FileID getFileIDSlow(unsigned SLocOffset) const; | |||
1841 | FileID getFileIDLocal(unsigned SLocOffset) const; | |||
1842 | FileID getFileIDLoaded(unsigned SLocOffset) const; | |||
1843 | ||||
1844 | SourceLocation getExpansionLocSlowCase(SourceLocation Loc) const; | |||
1845 | SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const; | |||
1846 | SourceLocation getFileLocSlowCase(SourceLocation Loc) const; | |||
1847 | ||||
1848 | std::pair<FileID, unsigned> | |||
1849 | getDecomposedExpansionLocSlowCase(const SrcMgr::SLocEntry *E) const; | |||
1850 | std::pair<FileID, unsigned> | |||
1851 | getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, | |||
1852 | unsigned Offset) const; | |||
1853 | void computeMacroArgsCache(MacroArgsMap &MacroArgsCache, FileID FID) const; | |||
1854 | void associateFileChunkWithMacroArgExp(MacroArgsMap &MacroArgsCache, | |||
1855 | FileID FID, | |||
1856 | SourceLocation SpellLoc, | |||
1857 | SourceLocation ExpansionLoc, | |||
1858 | unsigned ExpansionLength) const; | |||
1859 | }; | |||
1860 | ||||
1861 | /// Comparison function object. | |||
1862 | template<typename T> | |||
1863 | class BeforeThanCompare; | |||
1864 | ||||
1865 | /// Compare two source locations. | |||
1866 | template<> | |||
1867 | class BeforeThanCompare<SourceLocation> { | |||
1868 | SourceManager &SM; | |||
1869 | ||||
1870 | public: | |||
1871 | explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {} | |||
1872 | ||||
1873 | bool operator()(SourceLocation LHS, SourceLocation RHS) const { | |||
1874 | return SM.isBeforeInTranslationUnit(LHS, RHS); | |||
1875 | } | |||
1876 | }; | |||
1877 | ||||
1878 | /// Compare two non-overlapping source ranges. | |||
1879 | template<> | |||
1880 | class BeforeThanCompare<SourceRange> { | |||
1881 | SourceManager &SM; | |||
1882 | ||||
1883 | public: | |||
1884 | explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {} | |||
1885 | ||||
1886 | bool operator()(SourceRange LHS, SourceRange RHS) const { | |||
1887 | return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin()); | |||
1888 | } | |||
1889 | }; | |||
1890 | ||||
1891 | /// SourceManager and necessary depdencies (e.g. VFS, FileManager) for a single | |||
1892 | /// in-memorty file. | |||
1893 | class SourceManagerForFile { | |||
1894 | public: | |||
1895 | /// Creates SourceManager and necessary depdencies (e.g. VFS, FileManager). | |||
1896 | /// The main file in the SourceManager will be \p FileName with \p Content. | |||
1897 | SourceManagerForFile(StringRef FileName, StringRef Content); | |||
1898 | ||||
1899 | SourceManager &get() { | |||
1900 | assert(SourceMgr)((SourceMgr) ? static_cast<void> (0) : __assert_fail ("SourceMgr" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceManager.h" , 1900, __PRETTY_FUNCTION__)); | |||
1901 | return *SourceMgr; | |||
1902 | } | |||
1903 | ||||
1904 | private: | |||
1905 | // The order of these fields are important - they should be in the same order | |||
1906 | // as they are created in `createSourceManagerForFile` so that they can be | |||
1907 | // deleted in the reverse order as they are created. | |||
1908 | std::unique_ptr<FileManager> FileMgr; | |||
1909 | std::unique_ptr<DiagnosticsEngine> Diagnostics; | |||
1910 | std::unique_ptr<SourceManager> SourceMgr; | |||
1911 | }; | |||
1912 | ||||
1913 | } // namespace clang | |||
1914 | ||||
1915 | #endif // LLVM_CLANG_BASIC_SOURCEMANAGER_H |
1 | //===- SourceLocation.h - Compact identifier for Source Files ---*- 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 the clang::SourceLocation class and associated facilities. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H |
15 | #define LLVM_CLANG_BASIC_SOURCELOCATION_H |
16 | |
17 | #include "clang/Basic/LLVM.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/Support/PointerLikeTypeTraits.h" |
20 | #include <cassert> |
21 | #include <cstdint> |
22 | #include <string> |
23 | #include <utility> |
24 | |
25 | namespace llvm { |
26 | |
27 | template <typename T> struct DenseMapInfo; |
28 | |
29 | } // namespace llvm |
30 | |
31 | namespace clang { |
32 | |
33 | class SourceManager; |
34 | |
35 | /// An opaque identifier used by SourceManager which refers to a |
36 | /// source file (MemoryBuffer) along with its \#include path and \#line data. |
37 | /// |
38 | class FileID { |
39 | /// A mostly-opaque identifier, where 0 is "invalid", >0 is |
40 | /// this module, and <-1 is something loaded from another module. |
41 | int ID = 0; |
42 | |
43 | public: |
44 | bool isValid() const { return ID != 0; } |
45 | bool isInvalid() const { return ID == 0; } |
46 | |
47 | bool operator==(const FileID &RHS) const { return ID == RHS.ID; } |
48 | bool operator<(const FileID &RHS) const { return ID < RHS.ID; } |
49 | bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; } |
50 | bool operator!=(const FileID &RHS) const { return !(*this == RHS); } |
51 | bool operator>(const FileID &RHS) const { return RHS < *this; } |
52 | bool operator>=(const FileID &RHS) const { return RHS <= *this; } |
53 | |
54 | static FileID getSentinel() { return get(-1); } |
55 | unsigned getHashValue() const { return static_cast<unsigned>(ID); } |
56 | |
57 | private: |
58 | friend class ASTWriter; |
59 | friend class ASTReader; |
60 | friend class SourceManager; |
61 | |
62 | static FileID get(int V) { |
63 | FileID F; |
64 | F.ID = V; |
65 | return F; |
66 | } |
67 | |
68 | int getOpaqueValue() const { return ID; } |
69 | }; |
70 | |
71 | /// Encodes a location in the source. The SourceManager can decode this |
72 | /// to get at the full include stack, line and column information. |
73 | /// |
74 | /// Technically, a source location is simply an offset into the manager's view |
75 | /// of the input source, which is all input buffers (including macro |
76 | /// expansions) concatenated in an effectively arbitrary order. The manager |
77 | /// actually maintains two blocks of input buffers. One, starting at offset |
78 | /// 0 and growing upwards, contains all buffers from this module. The other, |
79 | /// starting at the highest possible offset and growing downwards, contains |
80 | /// buffers of loaded modules. |
81 | /// |
82 | /// In addition, one bit of SourceLocation is used for quick access to the |
83 | /// information whether the location is in a file or a macro expansion. |
84 | /// |
85 | /// It is important that this type remains small. It is currently 32 bits wide. |
86 | class SourceLocation { |
87 | friend class ASTReader; |
88 | friend class ASTWriter; |
89 | friend class SourceManager; |
90 | |
91 | unsigned ID = 0; |
92 | |
93 | enum : unsigned { |
94 | MacroIDBit = 1U << 31 |
95 | }; |
96 | |
97 | public: |
98 | bool isFileID() const { return (ID & MacroIDBit) == 0; } |
99 | bool isMacroID() const { return (ID & MacroIDBit) != 0; } |
100 | |
101 | /// Return true if this is a valid SourceLocation object. |
102 | /// |
103 | /// Invalid SourceLocations are often used when events have no corresponding |
104 | /// location in the source (e.g. a diagnostic is required for a command line |
105 | /// option). |
106 | bool isValid() const { return ID != 0; } |
107 | bool isInvalid() const { return ID == 0; } |
108 | |
109 | private: |
110 | /// Return the offset into the manager's global input view. |
111 | unsigned getOffset() const { |
112 | return ID & ~MacroIDBit; |
113 | } |
114 | |
115 | static SourceLocation getFileLoc(unsigned ID) { |
116 | assert((ID & MacroIDBit) == 0 && "Ran out of source locations!")(((ID & MacroIDBit) == 0 && "Ran out of source locations!" ) ? static_cast<void> (0) : __assert_fail ("(ID & MacroIDBit) == 0 && \"Ran out of source locations!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 116, __PRETTY_FUNCTION__)); |
117 | SourceLocation L; |
118 | L.ID = ID; |
119 | return L; |
120 | } |
121 | |
122 | static SourceLocation getMacroLoc(unsigned ID) { |
123 | assert((ID & MacroIDBit) == 0 && "Ran out of source locations!")(((ID & MacroIDBit) == 0 && "Ran out of source locations!" ) ? static_cast<void> (0) : __assert_fail ("(ID & MacroIDBit) == 0 && \"Ran out of source locations!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 123, __PRETTY_FUNCTION__)); |
124 | SourceLocation L; |
125 | L.ID = MacroIDBit | ID; |
126 | return L; |
127 | } |
128 | |
129 | public: |
130 | /// Return a source location with the specified offset from this |
131 | /// SourceLocation. |
132 | SourceLocation getLocWithOffset(int Offset) const { |
133 | assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow")((((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow" ) ? static_cast<void> (0) : __assert_fail ("((getOffset()+Offset) & MacroIDBit) == 0 && \"offset overflow\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 133, __PRETTY_FUNCTION__)); |
134 | SourceLocation L; |
135 | L.ID = ID+Offset; |
136 | return L; |
137 | } |
138 | |
139 | /// When a SourceLocation itself cannot be used, this returns |
140 | /// an (opaque) 32-bit integer encoding for it. |
141 | /// |
142 | /// This should only be passed to SourceLocation::getFromRawEncoding, it |
143 | /// should not be inspected directly. |
144 | unsigned getRawEncoding() const { return ID; } |
145 | |
146 | /// Turn a raw encoding of a SourceLocation object into |
147 | /// a real SourceLocation. |
148 | /// |
149 | /// \see getRawEncoding. |
150 | static SourceLocation getFromRawEncoding(unsigned Encoding) { |
151 | SourceLocation X; |
152 | X.ID = Encoding; |
153 | return X; |
154 | } |
155 | |
156 | /// When a SourceLocation itself cannot be used, this returns |
157 | /// an (opaque) pointer encoding for it. |
158 | /// |
159 | /// This should only be passed to SourceLocation::getFromPtrEncoding, it |
160 | /// should not be inspected directly. |
161 | void* getPtrEncoding() const { |
162 | // Double cast to avoid a warning "cast to pointer from integer of different |
163 | // size". |
164 | return (void*)(uintptr_t)getRawEncoding(); |
165 | } |
166 | |
167 | /// Turn a pointer encoding of a SourceLocation object back |
168 | /// into a real SourceLocation. |
169 | static SourceLocation getFromPtrEncoding(const void *Encoding) { |
170 | return getFromRawEncoding((unsigned)(uintptr_t)Encoding); |
171 | } |
172 | |
173 | static bool isPairOfFileLocations(SourceLocation Start, SourceLocation End) { |
174 | return Start.isValid() && Start.isFileID() && End.isValid() && |
175 | End.isFileID(); |
176 | } |
177 | |
178 | void print(raw_ostream &OS, const SourceManager &SM) const; |
179 | std::string printToString(const SourceManager &SM) const; |
180 | void dump(const SourceManager &SM) const; |
181 | }; |
182 | |
183 | inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) { |
184 | return LHS.getRawEncoding() == RHS.getRawEncoding(); |
185 | } |
186 | |
187 | inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) { |
188 | return !(LHS == RHS); |
189 | } |
190 | |
191 | // Ordering is meaningful only if LHS and RHS have the same FileID! |
192 | // Otherwise use SourceManager::isBeforeInTranslationUnit(). |
193 | inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) { |
194 | return LHS.getRawEncoding() < RHS.getRawEncoding(); |
195 | } |
196 | inline bool operator>(const SourceLocation &LHS, const SourceLocation &RHS) { |
197 | return LHS.getRawEncoding() > RHS.getRawEncoding(); |
198 | } |
199 | inline bool operator<=(const SourceLocation &LHS, const SourceLocation &RHS) { |
200 | return LHS.getRawEncoding() <= RHS.getRawEncoding(); |
201 | } |
202 | inline bool operator>=(const SourceLocation &LHS, const SourceLocation &RHS) { |
203 | return LHS.getRawEncoding() >= RHS.getRawEncoding(); |
204 | } |
205 | |
206 | /// A trivial tuple used to represent a source range. |
207 | class SourceRange { |
208 | SourceLocation B; |
209 | SourceLocation E; |
210 | |
211 | public: |
212 | SourceRange() = default; |
213 | SourceRange(SourceLocation loc) : B(loc), E(loc) {} |
214 | SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} |
215 | |
216 | SourceLocation getBegin() const { return B; } |
217 | SourceLocation getEnd() const { return E; } |
218 | |
219 | void setBegin(SourceLocation b) { B = b; } |
220 | void setEnd(SourceLocation e) { E = e; } |
221 | |
222 | bool isValid() const { return B.isValid() && E.isValid(); } |
223 | bool isInvalid() const { return !isValid(); } |
224 | |
225 | bool operator==(const SourceRange &X) const { |
226 | return B == X.B && E == X.E; |
227 | } |
228 | |
229 | bool operator!=(const SourceRange &X) const { |
230 | return B != X.B || E != X.E; |
231 | } |
232 | |
233 | // Returns true iff other is wholly contained within this range. |
234 | bool fullyContains(const SourceRange &other) const { |
235 | return B <= other.B && E >= other.E; |
236 | } |
237 | |
238 | void print(raw_ostream &OS, const SourceManager &SM) const; |
239 | std::string printToString(const SourceManager &SM) const; |
240 | void dump(const SourceManager &SM) const; |
241 | }; |
242 | |
243 | /// Represents a character-granular source range. |
244 | /// |
245 | /// The underlying SourceRange can either specify the starting/ending character |
246 | /// of the range, or it can specify the start of the range and the start of the |
247 | /// last token of the range (a "token range"). In the token range case, the |
248 | /// size of the last token must be measured to determine the actual end of the |
249 | /// range. |
250 | class CharSourceRange { |
251 | SourceRange Range; |
252 | bool IsTokenRange = false; |
253 | |
254 | public: |
255 | CharSourceRange() = default; |
256 | CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {} |
257 | |
258 | static CharSourceRange getTokenRange(SourceRange R) { |
259 | return CharSourceRange(R, true); |
260 | } |
261 | |
262 | static CharSourceRange getCharRange(SourceRange R) { |
263 | return CharSourceRange(R, false); |
264 | } |
265 | |
266 | static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) { |
267 | return getTokenRange(SourceRange(B, E)); |
268 | } |
269 | |
270 | static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) { |
271 | return getCharRange(SourceRange(B, E)); |
272 | } |
273 | |
274 | /// Return true if the end of this range specifies the start of |
275 | /// the last token. Return false if the end of this range specifies the last |
276 | /// character in the range. |
277 | bool isTokenRange() const { return IsTokenRange; } |
278 | bool isCharRange() const { return !IsTokenRange; } |
279 | |
280 | SourceLocation getBegin() const { return Range.getBegin(); } |
281 | SourceLocation getEnd() const { return Range.getEnd(); } |
282 | SourceRange getAsRange() const { return Range; } |
283 | |
284 | void setBegin(SourceLocation b) { Range.setBegin(b); } |
285 | void setEnd(SourceLocation e) { Range.setEnd(e); } |
286 | void setTokenRange(bool TR) { IsTokenRange = TR; } |
287 | |
288 | bool isValid() const { return Range.isValid(); } |
289 | bool isInvalid() const { return !isValid(); } |
290 | }; |
291 | |
292 | /// Represents an unpacked "presumed" location which can be presented |
293 | /// to the user. |
294 | /// |
295 | /// A 'presumed' location can be modified by \#line and GNU line marker |
296 | /// directives and is always the expansion point of a normal location. |
297 | /// |
298 | /// You can get a PresumedLoc from a SourceLocation with SourceManager. |
299 | class PresumedLoc { |
300 | const char *Filename = nullptr; |
301 | FileID ID; |
302 | unsigned Line, Col; |
303 | SourceLocation IncludeLoc; |
304 | |
305 | public: |
306 | PresumedLoc() = default; |
307 | PresumedLoc(const char *FN, FileID FID, unsigned Ln, unsigned Co, |
308 | SourceLocation IL) |
309 | : Filename(FN), ID(FID), Line(Ln), Col(Co), IncludeLoc(IL) {} |
310 | |
311 | /// Return true if this object is invalid or uninitialized. |
312 | /// |
313 | /// This occurs when created with invalid source locations or when walking |
314 | /// off the top of a \#include stack. |
315 | bool isInvalid() const { return Filename == nullptr; } |
316 | bool isValid() const { return Filename != nullptr; } |
317 | |
318 | /// Return the presumed filename of this location. |
319 | /// |
320 | /// This can be affected by \#line etc. |
321 | const char *getFilename() const { |
322 | assert(isValid())((isValid()) ? static_cast<void> (0) : __assert_fail ("isValid()" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 322, __PRETTY_FUNCTION__)); |
323 | return Filename; |
324 | } |
325 | |
326 | FileID getFileID() const { |
327 | assert(isValid())((isValid()) ? static_cast<void> (0) : __assert_fail ("isValid()" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 327, __PRETTY_FUNCTION__)); |
328 | return ID; |
329 | } |
330 | |
331 | /// Return the presumed line number of this location. |
332 | /// |
333 | /// This can be affected by \#line etc. |
334 | unsigned getLine() const { |
335 | assert(isValid())((isValid()) ? static_cast<void> (0) : __assert_fail ("isValid()" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 335, __PRETTY_FUNCTION__)); |
336 | return Line; |
337 | } |
338 | |
339 | /// Return the presumed column number of this location. |
340 | /// |
341 | /// This cannot be affected by \#line, but is packaged here for convenience. |
342 | unsigned getColumn() const { |
343 | assert(isValid())((isValid()) ? static_cast<void> (0) : __assert_fail ("isValid()" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 343, __PRETTY_FUNCTION__)); |
344 | return Col; |
345 | } |
346 | |
347 | /// Return the presumed include location of this location. |
348 | /// |
349 | /// This can be affected by GNU linemarker directives. |
350 | SourceLocation getIncludeLoc() const { |
351 | assert(isValid())((isValid()) ? static_cast<void> (0) : __assert_fail ("isValid()" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 351, __PRETTY_FUNCTION__)); |
352 | return IncludeLoc; |
353 | } |
354 | }; |
355 | |
356 | class FileEntry; |
357 | |
358 | /// A SourceLocation and its associated SourceManager. |
359 | /// |
360 | /// This is useful for argument passing to functions that expect both objects. |
361 | class FullSourceLoc : public SourceLocation { |
362 | const SourceManager *SrcMgr = nullptr; |
363 | |
364 | public: |
365 | /// Creates a FullSourceLoc where isValid() returns \c false. |
366 | FullSourceLoc() = default; |
367 | |
368 | explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) |
369 | : SourceLocation(Loc), SrcMgr(&SM) {} |
370 | |
371 | bool hasManager() const { |
372 | bool hasSrcMgr = SrcMgr != nullptr; |
373 | assert(hasSrcMgr == isValid() && "FullSourceLoc has location but no manager")((hasSrcMgr == isValid() && "FullSourceLoc has location but no manager" ) ? static_cast<void> (0) : __assert_fail ("hasSrcMgr == isValid() && \"FullSourceLoc has location but no manager\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 373, __PRETTY_FUNCTION__)); |
374 | return hasSrcMgr; |
375 | } |
376 | |
377 | /// \pre This FullSourceLoc has an associated SourceManager. |
378 | const SourceManager &getManager() const { |
379 | assert(SrcMgr && "SourceManager is NULL.")((SrcMgr && "SourceManager is NULL.") ? static_cast< void> (0) : __assert_fail ("SrcMgr && \"SourceManager is NULL.\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 379, __PRETTY_FUNCTION__)); |
380 | return *SrcMgr; |
381 | } |
382 | |
383 | FileID getFileID() const; |
384 | |
385 | FullSourceLoc getExpansionLoc() const; |
386 | FullSourceLoc getSpellingLoc() const; |
387 | FullSourceLoc getFileLoc() const; |
388 | PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const; |
389 | bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const; |
390 | FullSourceLoc getImmediateMacroCallerLoc() const; |
391 | std::pair<FullSourceLoc, StringRef> getModuleImportLoc() const; |
392 | unsigned getFileOffset() const; |
393 | |
394 | unsigned getExpansionLineNumber(bool *Invalid = nullptr) const; |
395 | unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const; |
396 | |
397 | unsigned getSpellingLineNumber(bool *Invalid = nullptr) const; |
398 | unsigned getSpellingColumnNumber(bool *Invalid = nullptr) const; |
399 | |
400 | const char *getCharacterData(bool *Invalid = nullptr) const; |
401 | |
402 | unsigned getLineNumber(bool *Invalid = nullptr) const; |
403 | unsigned getColumnNumber(bool *Invalid = nullptr) const; |
404 | |
405 | const FileEntry *getFileEntry() const; |
406 | |
407 | /// Return a StringRef to the source buffer data for the |
408 | /// specified FileID. |
409 | StringRef getBufferData(bool *Invalid = nullptr) const; |
410 | |
411 | /// Decompose the specified location into a raw FileID + Offset pair. |
412 | /// |
413 | /// The first element is the FileID, the second is the offset from the |
414 | /// start of the buffer of the location. |
415 | std::pair<FileID, unsigned> getDecomposedLoc() const; |
416 | |
417 | bool isInSystemHeader() const; |
418 | |
419 | /// Determines the order of 2 source locations in the translation unit. |
420 | /// |
421 | /// \returns true if this source location comes before 'Loc', false otherwise. |
422 | bool isBeforeInTranslationUnitThan(SourceLocation Loc) const; |
423 | |
424 | /// Determines the order of 2 source locations in the translation unit. |
425 | /// |
426 | /// \returns true if this source location comes before 'Loc', false otherwise. |
427 | bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const { |
428 | assert(Loc.isValid())((Loc.isValid()) ? static_cast<void> (0) : __assert_fail ("Loc.isValid()", "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 428, __PRETTY_FUNCTION__)); |
429 | assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!")((SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!" ) ? static_cast<void> (0) : __assert_fail ("SrcMgr == Loc.SrcMgr && \"Loc comes from another SourceManager!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/clang/include/clang/Basic/SourceLocation.h" , 429, __PRETTY_FUNCTION__)); |
430 | return isBeforeInTranslationUnitThan((SourceLocation)Loc); |
431 | } |
432 | |
433 | /// Comparison function class, useful for sorting FullSourceLocs. |
434 | struct BeforeThanCompare { |
435 | bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const { |
436 | return lhs.isBeforeInTranslationUnitThan(rhs); |
437 | } |
438 | }; |
439 | |
440 | /// Prints information about this FullSourceLoc to stderr. |
441 | /// |
442 | /// This is useful for debugging. |
443 | void dump() const; |
444 | |
445 | friend bool |
446 | operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { |
447 | return LHS.getRawEncoding() == RHS.getRawEncoding() && |
448 | LHS.SrcMgr == RHS.SrcMgr; |
449 | } |
450 | |
451 | friend bool |
452 | operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { |
453 | return !(LHS == RHS); |
454 | } |
455 | }; |
456 | |
457 | } // namespace clang |
458 | |
459 | namespace llvm { |
460 | |
461 | /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and |
462 | /// DenseSets. |
463 | template <> |
464 | struct DenseMapInfo<clang::FileID> { |
465 | static clang::FileID getEmptyKey() { |
466 | return {}; |
467 | } |
468 | |
469 | static clang::FileID getTombstoneKey() { |
470 | return clang::FileID::getSentinel(); |
471 | } |
472 | |
473 | static unsigned getHashValue(clang::FileID S) { |
474 | return S.getHashValue(); |
475 | } |
476 | |
477 | static bool isEqual(clang::FileID LHS, clang::FileID RHS) { |
478 | return LHS == RHS; |
479 | } |
480 | }; |
481 | |
482 | // Teach SmallPtrSet how to handle SourceLocation. |
483 | template<> |
484 | struct PointerLikeTypeTraits<clang::SourceLocation> { |
485 | enum { NumLowBitsAvailable = 0 }; |
486 | |
487 | static void *getAsVoidPointer(clang::SourceLocation L) { |
488 | return L.getPtrEncoding(); |
489 | } |
490 | |
491 | static clang::SourceLocation getFromVoidPointer(void *P) { |
492 | return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P); |
493 | } |
494 | }; |
495 | |
496 | } // namespace llvm |
497 | |
498 | #endif // LLVM_CLANG_BASIC_SOURCELOCATION_H |