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