/usr/include/clang/Basic/SourceManager.h is in libclang-dev 3.0-6ubuntu3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 | //===--- SourceManager.h - Track and cache source files ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the SourceManager interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SOURCEMANAGER_H
#define LLVM_CLANG_SOURCEMANAGER_H
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/MemoryBuffer.h"
#include <map>
#include <vector>
#include <cassert>
namespace clang {
class DiagnosticsEngine;
class SourceManager;
class FileManager;
class FileEntry;
class LineTableInfo;
class LangOptions;
class ASTWriter;
class ASTReader;
/// There are three different types of locations in a file: a spelling
/// location, an expansion location, and a presumed location.
///
/// Given an example of:
/// #define min(x, y) x < y ? x : y
///
/// and then later on a use of min:
/// #line 17
/// return min(a, b);
///
/// The expansion location is the line in the source code where the macro
/// was expanded (the return statement), the spelling location is the
/// location in the source where the macro was originally defined,
/// and the presumed location is where the line directive states that
/// the line is 17, or any other line.
/// SrcMgr - Public enums and private classes that are part of the
/// SourceManager implementation.
///
namespace SrcMgr {
/// CharacteristicKind - This is used to represent whether a file or directory
/// holds normal user code, system code, or system code which is implicitly
/// 'extern "C"' in C++ mode. Entire directories can be tagged with this
/// (this is maintained by DirectoryLookup and friends) as can specific
/// FileInfos when a #pragma system_header is seen or various other cases.
///
enum CharacteristicKind {
C_User, C_System, C_ExternCSystem
};
/// ContentCache - One instance of this struct is kept for every file
/// loaded or used. This object owns the MemoryBuffer object.
class ContentCache {
enum CCFlags {
/// \brief Whether the buffer is invalid.
InvalidFlag = 0x01,
/// \brief Whether the buffer should not be freed on destruction.
DoNotFreeFlag = 0x02
};
/// Buffer - The actual buffer containing the characters from the input
/// file. This is owned by the ContentCache object.
/// The bits indicate indicates whether the buffer is invalid.
mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer;
public:
/// Reference to the file entry representing this ContentCache.
/// This reference does not own the FileEntry object.
/// It is possible for this to be NULL if
/// the ContentCache encapsulates an imaginary text buffer.
const FileEntry *OrigEntry;
/// \brief References the file which the contents were actually loaded from.
/// Can be different from 'Entry' if we overridden the contents of one file
/// with the contents of another file.
const FileEntry *ContentsEntry;
/// SourceLineCache - A bump pointer allocated array of offsets for each
/// source line. This is lazily computed. This is owned by the
/// SourceManager BumpPointerAllocator object.
unsigned *SourceLineCache;
/// NumLines - The number of lines in this ContentCache. This is only valid
/// if SourceLineCache is non-null.
unsigned NumLines;
/// getBuffer - Returns the memory buffer for the associated content.
///
/// \param Diag Object through which diagnostics will be emitted if the
/// buffer cannot be retrieved.
///
/// \param Loc If specified, is the location that invalid file diagnostics
/// will be emitted at.
///
/// \param Invalid If non-NULL, will be set \c true if an error occurred.
const llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag,
const SourceManager &SM,
SourceLocation Loc = SourceLocation(),
bool *Invalid = 0) const;
/// getSize - Returns the size of the content encapsulated by this
/// ContentCache. This can be the size of the source file or the size of an
/// arbitrary scratch buffer. If the ContentCache encapsulates a source
/// file this size is retrieved from the file's FileEntry.
unsigned getSize() const;
/// getSizeBytesMapped - Returns the number of bytes actually mapped for
/// this ContentCache. This can be 0 if the MemBuffer was not actually
/// expanded.
unsigned getSizeBytesMapped() const;
/// Returns the kind of memory used to back the memory buffer for
/// this content cache. This is used for performance analysis.
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const;
void setBuffer(const llvm::MemoryBuffer *B) {
assert(!Buffer.getPointer() && "MemoryBuffer already set.");
Buffer.setPointer(B);
Buffer.setInt(false);
}
/// \brief Get the underlying buffer, returning NULL if the buffer is not
/// yet available.
const llvm::MemoryBuffer *getRawBuffer() const {
return Buffer.getPointer();
}
/// \brief Replace the existing buffer (which will be deleted)
/// with the given buffer.
void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false);
/// \brief Determine whether the buffer itself is invalid.
bool isBufferInvalid() const {
return Buffer.getInt() & InvalidFlag;
}
/// \brief Determine whether the buffer should be freed.
bool shouldFreeBuffer() const {
return (Buffer.getInt() & DoNotFreeFlag) == 0;
}
ContentCache(const FileEntry *Ent = 0)
: Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent),
SourceLineCache(0), NumLines(0) {}
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
: Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt),
SourceLineCache(0), NumLines(0) {}
~ContentCache();
/// The copy ctor does not allow copies where source object has either
/// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
/// is not transferred, so this is a logical error.
ContentCache(const ContentCache &RHS)
: Buffer(0, false), SourceLineCache(0)
{
OrigEntry = RHS.OrigEntry;
ContentsEntry = RHS.ContentsEntry;
assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0 &&
"Passed ContentCache object cannot own a buffer.");
NumLines = RHS.NumLines;
}
private:
// Disable assignments.
ContentCache &operator=(const ContentCache& RHS);
};
/// FileInfo - Information about a FileID, basically just the logical file
/// that it represents and include stack information.
///
/// Each FileInfo has include stack information, indicating where it came
/// from. This information encodes the #include chain that a token was
/// expanded from. The main include file has an invalid IncludeLoc.
///
/// FileInfos contain a "ContentCache *", with the contents of the file.
///
class FileInfo {
/// IncludeLoc - The location of the #include that brought in this file.
/// This is an invalid SLOC for the main file (top of the #include chain).
unsigned IncludeLoc; // Really a SourceLocation
/// \brief Number of FileIDs (files and macros) that were created during
/// preprocessing of this #include, including this SLocEntry.
/// Zero means the preprocessor didn't provide such info for this SLocEntry.
unsigned NumCreatedFIDs;
/// Data - This contains the ContentCache* and the bits indicating the
/// characteristic of the file and whether it has #line info, all bitmangled
/// together.
uintptr_t Data;
friend class clang::SourceManager;
friend class clang::ASTWriter;
friend class clang::ASTReader;
public:
/// get - Return a FileInfo object.
static FileInfo get(SourceLocation IL, const ContentCache *Con,
CharacteristicKind FileCharacter) {
FileInfo X;
X.IncludeLoc = IL.getRawEncoding();
X.NumCreatedFIDs = 0;
X.Data = (uintptr_t)Con;
assert((X.Data & 7) == 0 &&"ContentCache pointer insufficiently aligned");
assert((unsigned)FileCharacter < 4 && "invalid file character");
X.Data |= (unsigned)FileCharacter;
return X;
}
SourceLocation getIncludeLoc() const {
return SourceLocation::getFromRawEncoding(IncludeLoc);
}
const ContentCache* getContentCache() const {
return reinterpret_cast<const ContentCache*>(Data & ~7UL);
}
/// getCharacteristic - Return whether this is a system header or not.
CharacteristicKind getFileCharacteristic() const {
return (CharacteristicKind)(Data & 3);
}
/// hasLineDirectives - Return true if this FileID has #line directives in
/// it.
bool hasLineDirectives() const { return (Data & 4) != 0; }
/// setHasLineDirectives - Set the flag that indicates that this FileID has
/// line table entries associated with it.
void setHasLineDirectives() {
Data |= 4;
}
};
/// ExpansionInfo - Each ExpansionInfo encodes the expansion location - where
/// the token was ultimately expanded, and the SpellingLoc - where the actual
/// character data for the token came from.
class ExpansionInfo {
// Really these are all SourceLocations.
/// SpellingLoc - Where the spelling for the token can be found.
unsigned SpellingLoc;
/// ExpansionLocStart/ExpansionLocEnd - In a macro expansion, these
/// indicate the start and end of the expansion. In object-like macros,
/// these will be the same. In a function-like macro expansion, the start
/// will be the identifier and the end will be the ')'. Finally, in
/// macro-argument instantitions, the end will be 'SourceLocation()', an
/// invalid location.
unsigned ExpansionLocStart, ExpansionLocEnd;
public:
SourceLocation getSpellingLoc() const {
return SourceLocation::getFromRawEncoding(SpellingLoc);
}
SourceLocation getExpansionLocStart() const {
return SourceLocation::getFromRawEncoding(ExpansionLocStart);
}
SourceLocation getExpansionLocEnd() const {
SourceLocation EndLoc =
SourceLocation::getFromRawEncoding(ExpansionLocEnd);
return EndLoc.isInvalid() ? getExpansionLocStart() : EndLoc;
}
std::pair<SourceLocation,SourceLocation> getExpansionLocRange() const {
return std::make_pair(getExpansionLocStart(), getExpansionLocEnd());
}
bool isMacroArgExpansion() const {
// Note that this needs to return false for default constructed objects.
return getExpansionLocStart().isValid() &&
SourceLocation::getFromRawEncoding(ExpansionLocEnd).isInvalid();
}
/// create - Return a ExpansionInfo for an expansion. Start and End specify
/// the expansion range (where the macro is expanded), and SpellingLoc
/// specifies the spelling location (where the characters from the token
/// come from). All three can refer to normal File SLocs or expansion
/// locations.
static ExpansionInfo create(SourceLocation SpellingLoc,
SourceLocation Start, SourceLocation End) {
ExpansionInfo X;
X.SpellingLoc = SpellingLoc.getRawEncoding();
X.ExpansionLocStart = Start.getRawEncoding();
X.ExpansionLocEnd = End.getRawEncoding();
return X;
}
/// createForMacroArg - Return a special ExpansionInfo for the expansion of
/// a macro argument into a function-like macro's body. ExpansionLoc
/// specifies the expansion location (where the macro is expanded). This
/// doesn't need to be a range because a macro is always expanded at
/// a macro parameter reference, and macro parameters are always exactly
/// one token. SpellingLoc specifies the spelling location (where the
/// characters from the token come from). ExpansionLoc and SpellingLoc can
/// both refer to normal File SLocs or expansion locations.
///
/// Given the code:
/// \code
/// #define F(x) f(x)
/// F(42);
/// \endcode
///
/// When expanding '\c F(42)', the '\c x' would call this with an
/// SpellingLoc pointing at '\c 42' anad an ExpansionLoc pointing at its
/// location in the definition of '\c F'.
static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc,
SourceLocation ExpansionLoc) {
// We store an intentionally invalid source location for the end of the
// expansion range to mark that this is a macro argument ion rather than
// a normal one.
return create(SpellingLoc, ExpansionLoc, SourceLocation());
}
};
/// SLocEntry - This is a discriminated union of FileInfo and
/// ExpansionInfo. SourceManager keeps an array of these objects, and
/// they are uniquely identified by the FileID datatype.
class SLocEntry {
unsigned Offset; // low bit is set for expansion info.
union {
FileInfo File;
ExpansionInfo Expansion;
};
public:
unsigned getOffset() const { return Offset >> 1; }
bool isExpansion() const { return Offset & 1; }
bool isFile() const { return !isExpansion(); }
const FileInfo &getFile() const {
assert(isFile() && "Not a file SLocEntry!");
return File;
}
const ExpansionInfo &getExpansion() const {
assert(isExpansion() && "Not a macro expansion SLocEntry!");
return Expansion;
}
static SLocEntry get(unsigned Offset, const FileInfo &FI) {
SLocEntry E;
E.Offset = Offset << 1;
E.File = FI;
return E;
}
static SLocEntry get(unsigned Offset, const ExpansionInfo &Expansion) {
SLocEntry E;
E.Offset = (Offset << 1) | 1;
E.Expansion = Expansion;
return E;
}
};
} // end SrcMgr namespace.
/// \brief External source of source location entries.
class ExternalSLocEntrySource {
public:
virtual ~ExternalSLocEntrySource();
/// \brief Read the source location entry with index ID, which will always be
/// less than -1.
///
/// \returns true if an error occurred that prevented the source-location
/// entry from being loaded.
virtual bool ReadSLocEntry(int ID) = 0;
};
/// IsBeforeInTranslationUnitCache - This class holds the cache used by
/// isBeforeInTranslationUnit. The cache structure is complex enough to be
/// worth breaking out of SourceManager.
class IsBeforeInTranslationUnitCache {
/// L/R QueryFID - These are the FID's of the cached query. If these match up
/// with a subsequent query, the result can be reused.
FileID LQueryFID, RQueryFID;
/// \brief True if LQueryFID was created before RQueryFID. This is used
/// to compare macro expansion locations.
bool IsLQFIDBeforeRQFID;
/// CommonFID - This is the file found in common between the two #include
/// traces. It is the nearest common ancestor of the #include tree.
FileID CommonFID;
/// L/R CommonOffset - This is the offset of the previous query in CommonFID.
/// Usually, this represents the location of the #include for QueryFID, but if
/// LQueryFID is a parent of RQueryFID (or vise versa) then these can be a
/// random token in the parent.
unsigned LCommonOffset, RCommonOffset;
public:
/// isCacheValid - Return true if the currently cached values match up with
/// the specified LHS/RHS query. If not, we can't use the cache.
bool isCacheValid(FileID LHS, FileID RHS) const {
return LQueryFID == LHS && RQueryFID == RHS;
}
/// getCachedResult - If the cache is valid, compute the result given the
/// specified offsets in the LHS/RHS FID's.
bool getCachedResult(unsigned LOffset, unsigned ROffset) const {
// If one of the query files is the common file, use the offset. Otherwise,
// use the #include loc in the common file.
if (LQueryFID != CommonFID) LOffset = LCommonOffset;
if (RQueryFID != CommonFID) ROffset = RCommonOffset;
// It is common for multiple macro expansions to be "included" from the same
// location (expansion location), in which case use the order of the FileIDs
// to determine which came first. This will also take care the case where
// one of the locations points at the inclusion/expansion point of the other
// in which case its FileID will come before the other.
if (LOffset == ROffset &&
(LQueryFID != CommonFID || RQueryFID != CommonFID))
return IsLQFIDBeforeRQFID;
return LOffset < ROffset;
}
// Set up a new query.
void setQueryFIDs(FileID LHS, FileID RHS, bool isLFIDBeforeRFID) {
assert(LHS != RHS);
LQueryFID = LHS;
RQueryFID = RHS;
IsLQFIDBeforeRQFID = isLFIDBeforeRFID;
}
void clear() {
LQueryFID = RQueryFID = FileID();
IsLQFIDBeforeRQFID = false;
}
void setCommonLoc(FileID commonFID, unsigned lCommonOffset,
unsigned rCommonOffset) {
CommonFID = commonFID;
LCommonOffset = lCommonOffset;
RCommonOffset = rCommonOffset;
}
};
/// \brief This class handles loading and caching of source files into memory.
///
/// This object owns the MemoryBuffer objects for all of the loaded
/// files and assigns unique FileID's for each unique #include chain.
///
/// The SourceManager can be queried for information about SourceLocation
/// objects, turning them into either spelling or expansion locations. Spelling
/// locations represent where the bytes corresponding to a token came from and
/// expansion locations represent where the location is in the user's view. In
/// the case of a macro expansion, for example, the spelling location indicates
/// where the expanded token came from and the expansion location specifies
/// where it was expanded.
class SourceManager : public llvm::RefCountedBase<SourceManager> {
/// \brief DiagnosticsEngine object.
DiagnosticsEngine &Diag;
FileManager &FileMgr;
mutable llvm::BumpPtrAllocator ContentCacheAlloc;
/// FileInfos - Memoized information about all of the files tracked by this
/// SourceManager. This set allows us to merge ContentCache entries based
/// on their FileEntry*. All ContentCache objects will thus have unique,
/// non-null, FileEntry pointers.
llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos;
/// \brief True if the ContentCache for files that are overriden by other
/// files, should report the original file name. Defaults to true.
bool OverridenFilesKeepOriginalName;
/// \brief Files that have been overriden with the contents from another file.
llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles;
/// MemBufferInfos - Information about various memory buffers that we have
/// read in. All FileEntry* within the stored ContentCache objects are NULL,
/// as they do not refer to a file.
std::vector<SrcMgr::ContentCache*> MemBufferInfos;
/// \brief The table of SLocEntries that are local to this module.
///
/// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid
/// expansion.
std::vector<SrcMgr::SLocEntry> LocalSLocEntryTable;
/// \brief The table of SLocEntries that are loaded from other modules.
///
/// Negative FileIDs are indexes into this table. To get from ID to an index,
/// use (-ID - 2).
std::vector<SrcMgr::SLocEntry> LoadedSLocEntryTable;
/// \brief The starting offset of the next local SLocEntry.
///
/// This is LocalSLocEntryTable.back().Offset + the size of that entry.
unsigned NextLocalOffset;
/// \brief The starting offset of the latest batch of loaded SLocEntries.
///
/// This is LoadedSLocEntryTable.back().Offset, except that that entry might
/// not have been loaded, so that value would be unknown.
unsigned CurrentLoadedOffset;
/// \brief The highest possible offset is 2^31-1, so CurrentLoadedOffset
/// starts at 2^31.
static const unsigned MaxLoadedOffset = 1U << 31U;
/// \brief A bitmap that indicates whether the entries of LoadedSLocEntryTable
/// have already been loaded from the external source.
///
/// Same indexing as LoadedSLocEntryTable.
std::vector<bool> SLocEntryLoaded;
/// \brief An external source for source location entries.
ExternalSLocEntrySource *ExternalSLocEntries;
/// LastFileIDLookup - This is a one-entry cache to speed up getFileID.
/// LastFileIDLookup records the last FileID looked up or created, because it
/// is very common to look up many tokens from the same file.
mutable FileID LastFileIDLookup;
/// LineTable - This holds information for #line directives. It is referenced
/// by indices from SLocEntryTable.
LineTableInfo *LineTable;
/// LastLineNo - These ivars serve as a cache used in the getLineNumber
/// method which is used to speedup getLineNumber calls to nearby locations.
mutable FileID LastLineNoFileIDQuery;
mutable SrcMgr::ContentCache *LastLineNoContentCache;
mutable unsigned LastLineNoFilePos;
mutable unsigned LastLineNoResult;
/// MainFileID - The file ID for the main source file of the translation unit.
FileID MainFileID;
/// \brief The file ID for the precompiled preamble there is one.
FileID PreambleFileID;
// Statistics for -print-stats.
mutable unsigned NumLinearScans, NumBinaryProbes;
// Cache results for the isBeforeInTranslationUnit method.
mutable IsBeforeInTranslationUnitCache IsBeforeInTUCache;
// Cache for the "fake" buffer used for error-recovery purposes.
mutable llvm::MemoryBuffer *FakeBufferForRecovery;
/// \brief Lazily computed map of macro argument chunks to their expanded
/// source location.
typedef std::map<unsigned, SourceLocation> MacroArgsMap;
mutable llvm::DenseMap<FileID, MacroArgsMap *> MacroArgsCacheMap;
// SourceManager doesn't support copy construction.
explicit SourceManager(const SourceManager&);
void operator=(const SourceManager&);
public:
SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr);
~SourceManager();
void clearIDTables();
DiagnosticsEngine &getDiagnostics() const { return Diag; }
FileManager &getFileManager() const { return FileMgr; }
/// \brief Set true if the SourceManager should report the original file name
/// for contents of files that were overriden by other files.Defaults to true.
void setOverridenFilesKeepOriginalName(bool value) {
OverridenFilesKeepOriginalName = value;
}
/// createMainFileIDForMembuffer - Create the FileID for a memory buffer
/// that will represent the FileID for the main source. One example
/// of when this would be used is when the main source is read from STDIN.
FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
assert(MainFileID.isInvalid() && "MainFileID already set!");
MainFileID = createFileIDForMemBuffer(Buffer);
return MainFileID;
}
//===--------------------------------------------------------------------===//
// MainFileID creation and querying methods.
//===--------------------------------------------------------------------===//
/// getMainFileID - Returns the FileID of the main source file.
FileID getMainFileID() const { return MainFileID; }
/// createMainFileID - Create the FileID for the main source file.
FileID createMainFileID(const FileEntry *SourceFile) {
assert(MainFileID.isInvalid() && "MainFileID already set!");
MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User);
return MainFileID;
}
/// \brief Set the file ID for the precompiled preamble.
void setPreambleFileID(FileID Preamble) {
assert(PreambleFileID.isInvalid() && "PreambleFileID already set!");
PreambleFileID = Preamble;
}
/// \brief Get the file ID for the precompiled preamble if there is one.
FileID getPreambleFileID() const { return PreambleFileID; }
//===--------------------------------------------------------------------===//
// Methods to create new FileID's and macro expansions.
//===--------------------------------------------------------------------===//
/// createFileID - Create a new FileID that represents the specified file
/// being #included from the specified IncludePosition. This translates NULL
/// into standard input.
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
int LoadedID = 0, unsigned LoadedOffset = 0) {
const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
assert(IR && "getOrCreateContentCache() cannot return NULL");
return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset);
}
/// createFileIDForMemBuffer - Create a new FileID that represents the
/// specified memory buffer. This does no caching of the buffer and takes
/// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once.
FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer,
int LoadedID = 0, unsigned LoadedOffset = 0) {
return createFileID(createMemBufferContentCache(Buffer), SourceLocation(),
SrcMgr::C_User, LoadedID, LoadedOffset);
}
/// createMacroArgExpansionLoc - Return a new SourceLocation that encodes the
/// fact that a token from SpellingLoc should actually be referenced from
/// ExpansionLoc, and that it represents the expansion of a macro argument
/// into the function-like macro body.
SourceLocation createMacroArgExpansionLoc(SourceLocation Loc,
SourceLocation ExpansionLoc,
unsigned TokLength);
/// createExpansionLoc - Return a new SourceLocation that encodes the fact
/// that a token from SpellingLoc should actually be referenced from
/// ExpansionLoc.
SourceLocation createExpansionLoc(SourceLocation Loc,
SourceLocation ExpansionLocStart,
SourceLocation ExpansionLocEnd,
unsigned TokLength,
int LoadedID = 0,
unsigned LoadedOffset = 0);
/// \brief Retrieve the memory buffer associated with the given file.
///
/// \param Invalid If non-NULL, will be set \c true if an error
/// occurs while retrieving the memory buffer.
const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File,
bool *Invalid = 0);
/// \brief Override the contents of the given source file by providing an
/// already-allocated buffer.
///
/// \param SourceFile the source file whose contents will be overriden.
///
/// \param Buffer the memory buffer whose contents will be used as the
/// data in the given source file.
///
/// \param DoNotFree If true, then the buffer will not be freed when the
/// source manager is destroyed.
void overrideFileContents(const FileEntry *SourceFile,
const llvm::MemoryBuffer *Buffer,
bool DoNotFree = false);
/// \brief Override the the given source file with another one.
///
/// \param SourceFile the source file which will be overriden.
///
/// \param NewFile the file whose contents will be used as the
/// data instead of the contents of the given source file.
void overrideFileContents(const FileEntry *SourceFile,
const FileEntry *NewFile);
//===--------------------------------------------------------------------===//
// FileID manipulation methods.
//===--------------------------------------------------------------------===//
/// getBuffer - Return the buffer for the specified FileID. If there is an
/// error opening this buffer the first time, this manufactures a temporary
/// buffer and returns a non-empty error string.
const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc,
bool *Invalid = 0) const {
bool MyInvalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
if (MyInvalid || !Entry.isFile()) {
if (Invalid)
*Invalid = true;
return getFakeBufferForRecovery();
}
return Entry.getFile().getContentCache()->getBuffer(Diag, *this, Loc,
Invalid);
}
const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const {
bool MyInvalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
if (MyInvalid || !Entry.isFile()) {
if (Invalid)
*Invalid = true;
return getFakeBufferForRecovery();
}
return Entry.getFile().getContentCache()->getBuffer(Diag, *this,
SourceLocation(),
Invalid);
}
/// getFileEntryForID - Returns the FileEntry record for the provided FileID.
const FileEntry *getFileEntryForID(FileID FID) const {
bool MyInvalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
if (MyInvalid || !Entry.isFile())
return 0;
return Entry.getFile().getContentCache()->OrigEntry;
}
/// Returns the FileEntry record for the provided SLocEntry.
const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const
{
return sloc.getFile().getContentCache()->OrigEntry;
}
/// getBufferData - Return a StringRef to the source buffer data for the
/// specified FileID.
///
/// \param FID The file ID whose contents will be returned.
/// \param Invalid If non-NULL, will be set true if an error occurred.
StringRef getBufferData(FileID FID, bool *Invalid = 0) const;
/// \brief Get the number of FileIDs (files and macros) that were created
/// during preprocessing of \arg FID, including it.
unsigned getNumCreatedFIDsForFileID(FileID FID) const {
bool Invalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
if (Invalid || !Entry.isFile())
return 0;
return Entry.getFile().NumCreatedFIDs;
}
/// \brief Set the number of FileIDs (files and macros) that were created
/// during preprocessing of \arg FID, including it.
void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs) const {
bool Invalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
if (Invalid || !Entry.isFile())
return;
assert(Entry.getFile().NumCreatedFIDs == 0 && "Already set!");
const_cast<SrcMgr::FileInfo &>(Entry.getFile()).NumCreatedFIDs = NumFIDs;
}
//===--------------------------------------------------------------------===//
// SourceLocation manipulation methods.
//===--------------------------------------------------------------------===//
/// getFileID - Return the FileID for a SourceLocation. This is a very
/// hot method that is used for all SourceManager queries that start with a
/// SourceLocation object. It is responsible for finding the entry in
/// SLocEntryTable which contains the specified location.
///
FileID getFileID(SourceLocation SpellingLoc) const {
unsigned SLocOffset = SpellingLoc.getOffset();
// If our one-entry cache covers this offset, just return it.
if (isOffsetInFileID(LastFileIDLookup, SLocOffset))
return LastFileIDLookup;
return getFileIDSlow(SLocOffset);
}
/// getLocForStartOfFile - Return the source location corresponding to the
/// first byte of the specified file.
SourceLocation getLocForStartOfFile(FileID FID) const {
bool Invalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
if (Invalid || !Entry.isFile())
return SourceLocation();
unsigned FileOffset = Entry.getOffset();
return SourceLocation::getFileLoc(FileOffset);
}
/// \brief Returns the include location if \arg FID is a #include'd file
/// otherwise it returns an invalid location.
SourceLocation getIncludeLoc(FileID FID) const {
bool Invalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
if (Invalid || !Entry.isFile())
return SourceLocation();
return Entry.getFile().getIncludeLoc();
}
/// getExpansionLoc - Given a SourceLocation object, return the expansion
/// location referenced by the ID.
SourceLocation getExpansionLoc(SourceLocation Loc) const {
// Handle the non-mapped case inline, defer to out of line code to handle
// expansions.
if (Loc.isFileID()) return Loc;
return getExpansionLocSlowCase(Loc);
}
/// \brief Given \arg Loc, if it is a macro location return the expansion
/// location or the spelling location, depending on if it comes from a
/// macro argument or not.
SourceLocation getFileLoc(SourceLocation Loc) const {
if (Loc.isFileID()) return Loc;
return getFileLocSlowCase(Loc);
}
/// getImmediateExpansionRange - Loc is required to be an expansion location.
/// Return the start/end of the expansion information.
std::pair<SourceLocation,SourceLocation>
getImmediateExpansionRange(SourceLocation Loc) const;
/// getExpansionRange - Given a SourceLocation object, return the range of
/// tokens covered by the expansion the ultimate file.
std::pair<SourceLocation,SourceLocation>
getExpansionRange(SourceLocation Loc) const;
/// getSpellingLoc - Given a SourceLocation object, return the spelling
/// location referenced by the ID. This is the place where the characters
/// that make up the lexed token can be found.
SourceLocation getSpellingLoc(SourceLocation Loc) const {
// Handle the non-mapped case inline, defer to out of line code to handle
// expansions.
if (Loc.isFileID()) return Loc;
return getSpellingLocSlowCase(Loc);
}
/// getImmediateSpellingLoc - Given a SourceLocation object, return the
/// spelling location referenced by the ID. This is the first level down
/// towards the place where the characters that make up the lexed token can be
/// found. This should not generally be used by clients.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const;
/// getDecomposedLoc - Decompose the specified location into a raw FileID +
/// Offset pair. The first element is the FileID, the second is the
/// offset from the start of the buffer of the location.
std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const {
FileID FID = getFileID(Loc);
return std::make_pair(FID, Loc.getOffset()-getSLocEntry(FID).getOffset());
}
/// getDecomposedExpansionLoc - Decompose the specified location into a raw
/// FileID + Offset pair. If the location is an expansion record, walk
/// through it until we find the final location expanded.
std::pair<FileID, unsigned>
getDecomposedExpansionLoc(SourceLocation Loc) const {
FileID FID = getFileID(Loc);
const SrcMgr::SLocEntry *E = &getSLocEntry(FID);
unsigned Offset = Loc.getOffset()-E->getOffset();
if (Loc.isFileID())
return std::make_pair(FID, Offset);
return getDecomposedExpansionLocSlowCase(E);
}
/// getDecomposedSpellingLoc - Decompose the specified location into a raw
/// FileID + Offset pair. If the location is an expansion record, walk
/// through it until we find its spelling record.
std::pair<FileID, unsigned>
getDecomposedSpellingLoc(SourceLocation Loc) const {
FileID FID = getFileID(Loc);
const SrcMgr::SLocEntry *E = &getSLocEntry(FID);
unsigned Offset = Loc.getOffset()-E->getOffset();
if (Loc.isFileID())
return std::make_pair(FID, Offset);
return getDecomposedSpellingLocSlowCase(E, Offset);
}
/// getFileOffset - This method returns the offset from the start
/// of the file that the specified SourceLocation represents. This is not very
/// meaningful for a macro ID.
unsigned getFileOffset(SourceLocation SpellingLoc) const {
return getDecomposedLoc(SpellingLoc).second;
}
/// isMacroArgExpansion - This method tests whether the given source location
/// represents a macro argument's expansion into the function-like macro
/// definition. Such source locations only appear inside of the expansion
/// locations representing where a particular function-like macro was
/// expanded.
bool isMacroArgExpansion(SourceLocation Loc) const;
/// \brief Returns true if \arg Loc is inside the [\arg Start, +\arg Length)
/// chunk of the source location address space.
/// If it's true and \arg RelativeOffset is non-null, it will be set to the
/// relative offset of \arg Loc inside the chunk.
bool isInSLocAddrSpace(SourceLocation Loc,
SourceLocation Start, unsigned Length,
unsigned *RelativeOffset = 0) const {
assert(((Start.getOffset() < NextLocalOffset &&
Start.getOffset()+Length <= NextLocalOffset) ||
(Start.getOffset() >= CurrentLoadedOffset &&
Start.getOffset()+Length < MaxLoadedOffset)) &&
"Chunk is not valid SLoc address space");
unsigned LocOffs = Loc.getOffset();
unsigned BeginOffs = Start.getOffset();
unsigned EndOffs = BeginOffs + Length;
if (LocOffs >= BeginOffs && LocOffs < EndOffs) {
if (RelativeOffset)
*RelativeOffset = LocOffs - BeginOffs;
return true;
}
return false;
}
/// \brief Return true if both \arg LHS and \arg RHS are in the local source
/// location address space or the loaded one. If it's true and
/// \arg RelativeOffset is non-null, it will be set to the offset of \arg RHS
/// relative to \arg LHS.
bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS,
int *RelativeOffset) const {
unsigned LHSOffs = LHS.getOffset(), RHSOffs = RHS.getOffset();
bool LHSLoaded = LHSOffs >= CurrentLoadedOffset;
bool RHSLoaded = RHSOffs >= CurrentLoadedOffset;
if (LHSLoaded == RHSLoaded) {
if (RelativeOffset)
*RelativeOffset = RHSOffs - LHSOffs;
return true;
}
return false;
}
//===--------------------------------------------------------------------===//
// Queries about the code at a SourceLocation.
//===--------------------------------------------------------------------===//
/// getCharacterData - Return a pointer to the start of the specified location
/// in the appropriate spelling MemoryBuffer.
///
/// \param Invalid If non-NULL, will be set \c true if an error occurs.
const char *getCharacterData(SourceLocation SL, bool *Invalid = 0) const;
/// getColumnNumber - Return the column # for the specified file position.
/// This is significantly cheaper to compute than the line number. This
/// returns zero if the column number isn't known. This may only be called
/// on a file sloc, so you must choose a spelling or expansion location
/// before calling this method.
unsigned getColumnNumber(FileID FID, unsigned FilePos,
bool *Invalid = 0) const;
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;
unsigned getExpansionColumnNumber(SourceLocation Loc,
bool *Invalid = 0) const;
unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;
/// getLineNumber - Given a SourceLocation, return the spelling line number
/// for the position indicated. This requires building and caching a table of
/// line offsets for the MemoryBuffer, so this is not cheap: use only when
/// about to emit a diagnostic.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const;
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
/// Return the filename or buffer identifier of the buffer the location is in.
/// Note that this name does not respect #line directives. Use getPresumedLoc
/// for normal clients.
const char *getBufferName(SourceLocation Loc, bool *Invalid = 0) const;
/// getFileCharacteristic - return the file characteristic of the specified
/// source location, indicating whether this is a normal file, a system
/// header, or an "implicit extern C" system header.
///
/// This state can be modified with flags on GNU linemarker directives like:
/// # 4 "foo.h" 3
/// which changes all source locations in the current file after that to be
/// considered to be from a system header.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const;
/// getPresumedLoc - This method returns the "presumed" location of a
/// SourceLocation specifies. A "presumed location" can be modified by #line
/// or GNU line marker directives. This provides a view on the data that a
/// user should see in diagnostics, for example.
///
/// Note that a presumed location is always given as the expansion point of
/// an expansion location, not at the spelling location.
///
/// \returns The presumed location of the specified SourceLocation. If the
/// presumed location cannot be calculate (e.g., because \p Loc is invalid
/// or the file containing \p Loc has changed on disk), returns an invalid
/// presumed location.
PresumedLoc getPresumedLoc(SourceLocation Loc) const;
/// isFromSameFile - Returns true if both SourceLocations correspond to
/// the same file.
bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
return getFileID(Loc1) == getFileID(Loc2);
}
/// isFromMainFile - Returns true if the file of provided SourceLocation is
/// the main file.
bool isFromMainFile(SourceLocation Loc) const {
return getFileID(Loc) == getMainFileID();
}
/// isInSystemHeader - Returns if a SourceLocation is in a system header.
bool isInSystemHeader(SourceLocation Loc) const {
return getFileCharacteristic(Loc) != SrcMgr::C_User;
}
/// isInExternCSystemHeader - Returns if a SourceLocation is in an "extern C"
/// system header.
bool isInExternCSystemHeader(SourceLocation Loc) const {
return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem;
}
/// \brief The size of the SLocEnty that \arg FID represents.
unsigned getFileIDSize(FileID FID) const;
/// \brief Given a specific FileID, returns true if \arg Loc is inside that
/// FileID chunk and sets relative offset (offset of \arg Loc from beginning
/// of FileID) to \arg relativeOffset.
bool isInFileID(SourceLocation Loc, FileID FID,
unsigned *RelativeOffset = 0) const {
unsigned Offs = Loc.getOffset();
if (isOffsetInFileID(FID, Offs)) {
if (RelativeOffset)
*RelativeOffset = Offs - getSLocEntry(FID).getOffset();
return true;
}
return false;
}
//===--------------------------------------------------------------------===//
// Line Table Manipulation Routines
//===--------------------------------------------------------------------===//
/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
///
unsigned getLineTableFilenameID(StringRef Str);
/// AddLineNote - Add a line note to the line table for the FileID and offset
/// specified by Loc. If FilenameID is -1, it is considered to be
/// unspecified.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID);
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID,
bool IsFileEntry, bool IsFileExit,
bool IsSystemHeader, bool IsExternCHeader);
/// \brief Determine if the source manager has a line table.
bool hasLineTable() const { return LineTable != 0; }
/// \brief Retrieve the stored line table.
LineTableInfo &getLineTable();
//===--------------------------------------------------------------------===//
// Queries for performance analysis.
//===--------------------------------------------------------------------===//
/// Return the total amount of physical memory allocated by the
/// ContentCache allocator.
size_t getContentCacheSize() const {
return ContentCacheAlloc.getTotalMemory();
}
struct MemoryBufferSizes {
const size_t malloc_bytes;
const size_t mmap_bytes;
MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
: malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
};
/// Return the amount of memory used by memory buffers, breaking down
/// by heap-backed versus mmap'ed memory.
MemoryBufferSizes getMemoryBufferSizes() const;
// Return the amount of memory used for various side tables and
// data structures in the SourceManager.
size_t getDataStructureSizes() const;
//===--------------------------------------------------------------------===//
// Other miscellaneous methods.
//===--------------------------------------------------------------------===//
/// \brief Get the source location for the given file:line:col triplet.
///
/// If the source file is included multiple times, the source location will
/// be based upon the first inclusion.
SourceLocation translateFileLineCol(const FileEntry *SourceFile,
unsigned Line, unsigned Col) const;
/// \brief Get the FileID for the given file.
///
/// If the source file is included multiple times, the FileID will be the
/// first inclusion.
FileID translateFile(const FileEntry *SourceFile) const;
/// \brief Get the source location in \arg FID for the given line:col.
/// Returns null location if \arg FID is not a file SLocEntry.
SourceLocation translateLineCol(FileID FID,
unsigned Line, unsigned Col) const;
/// \brief If \arg Loc points inside a function macro argument, the returned
/// location will be the macro location in which the argument was expanded.
/// If a macro argument is used multiple times, the expanded location will
/// be at the first expansion of the argument.
/// e.g.
/// MY_MACRO(foo);
/// ^
/// Passing a file location pointing at 'foo', will yield a macro location
/// where 'foo' was expanded into.
SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const;
/// \brief Determines the order of 2 source locations in the translation unit.
///
/// \returns true if LHS source location comes before RHS, false otherwise.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;
/// \brief Comparison function class.
class LocBeforeThanCompare : public std::binary_function<SourceLocation,
SourceLocation, bool> {
SourceManager &SM;
public:
explicit LocBeforeThanCompare(SourceManager &SM) : SM(SM) { }
bool operator()(SourceLocation LHS, SourceLocation RHS) const {
return SM.isBeforeInTranslationUnit(LHS, RHS);
}
};
/// \brief Determines the order of 2 source locations in the "source location
/// address space".
bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {
return isBeforeInSLocAddrSpace(LHS, RHS.getOffset());
}
/// \brief Determines the order of a source location and a source location
/// offset in the "source location address space".
///
/// Note that we always consider source locations loaded from
bool isBeforeInSLocAddrSpace(SourceLocation LHS, unsigned RHS) const {
unsigned LHSOffset = LHS.getOffset();
bool LHSLoaded = LHSOffset >= CurrentLoadedOffset;
bool RHSLoaded = RHS >= CurrentLoadedOffset;
if (LHSLoaded == RHSLoaded)
return LHSOffset < RHS;
return LHSLoaded;
}
// Iterators over FileInfos.
typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>
::const_iterator fileinfo_iterator;
fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); }
fileinfo_iterator fileinfo_end() const { return FileInfos.end(); }
bool hasFileInfo(const FileEntry *File) const {
return FileInfos.find(File) != FileInfos.end();
}
/// PrintStats - Print statistics to stderr.
///
void PrintStats() const;
/// \brief Get the number of local SLocEntries we have.
unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); }
/// \brief Get a local SLocEntry. This is exposed for indexing.
const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index,
bool *Invalid = 0) const {
assert(Index < LocalSLocEntryTable.size() && "Invalid index");
return LocalSLocEntryTable[Index];
}
/// \brief Get the number of loaded SLocEntries we have.
unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();}
/// \brief Get a loaded SLocEntry. This is exposed for indexing.
const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, bool *Invalid=0) const {
assert(Index < LoadedSLocEntryTable.size() && "Invalid index");
if (!SLocEntryLoaded[Index])
ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2));
return LoadedSLocEntryTable[Index];
}
const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = 0) const {
return getSLocEntryByID(FID.ID);
}
unsigned getNextLocalOffset() const { return NextLocalOffset; }
void setExternalSLocEntrySource(ExternalSLocEntrySource *Source) {
assert(LoadedSLocEntryTable.empty() &&
"Invalidating existing loaded entries");
ExternalSLocEntries = Source;
}
/// \brief Allocate a number of loaded SLocEntries, which will be actually
/// loaded on demand from the external source.
///
/// NumSLocEntries will be allocated, which occupy a total of TotalSize space
/// in the global source view. The lowest ID and the base offset of the
/// entries will be returned.
std::pair<int, unsigned>
AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize);
/// \brief Returns true if \arg Loc came from a PCH/Module.
bool isLoadedSourceLocation(SourceLocation Loc) const {
return Loc.getOffset() >= CurrentLoadedOffset;
}
/// \brief Returns true if \arg Loc did not come from a PCH/Module.
bool isLocalSourceLocation(SourceLocation Loc) const {
return Loc.getOffset() < NextLocalOffset;
}
private:
const llvm::MemoryBuffer *getFakeBufferForRecovery() const;
/// \brief Get the entry with the given unwrapped FileID.
const SrcMgr::SLocEntry &getSLocEntryByID(int ID) const {
assert(ID != -1 && "Using FileID sentinel value");
if (ID < 0)
return getLoadedSLocEntryByID(ID);
return getLocalSLocEntry(static_cast<unsigned>(ID));
}
const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID) const {
return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2));
}
/// createExpansionLoc - Implements the common elements of storing an
/// expansion info struct into the SLocEntry table and producing a source
/// location that refers to it.
SourceLocation createExpansionLocImpl(const SrcMgr::ExpansionInfo &Expansion,
unsigned TokLength,
int LoadedID = 0,
unsigned LoadedOffset = 0);
/// isOffsetInFileID - Return true if the specified FileID contains the
/// specified SourceLocation offset. This is a very hot method.
inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const {
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID);
// If the entry is after the offset, it can't contain it.
if (SLocOffset < Entry.getOffset()) return false;
// If this is the very last entry then it does.
if (FID.ID == -2)
return true;
// If it is the last local entry, then it does if the location is local.
if (static_cast<unsigned>(FID.ID+1) == LocalSLocEntryTable.size()) {
return SLocOffset < NextLocalOffset;
}
// Otherwise, the entry after it has to not include it. This works for both
// local and loaded entries.
return SLocOffset < getSLocEntry(FileID::get(FID.ID+1)).getOffset();
}
/// createFileID - Create a new fileID for the specified ContentCache and
/// include position. This works regardless of whether the ContentCache
/// corresponds to a file or some other input source.
FileID createFileID(const SrcMgr::ContentCache* File,
SourceLocation IncludePos,
SrcMgr::CharacteristicKind DirCharacter,
int LoadedID, unsigned LoadedOffset);
const SrcMgr::ContentCache *
getOrCreateContentCache(const FileEntry *SourceFile);
/// createMemBufferContentCache - Create a new ContentCache for the specified
/// memory buffer.
const SrcMgr::ContentCache*
createMemBufferContentCache(const llvm::MemoryBuffer *Buf);
FileID getFileIDSlow(unsigned SLocOffset) const;
FileID getFileIDLocal(unsigned SLocOffset) const;
FileID getFileIDLoaded(unsigned SLocOffset) const;
SourceLocation getExpansionLocSlowCase(SourceLocation Loc) const;
SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const;
SourceLocation getFileLocSlowCase(SourceLocation Loc) const;
std::pair<FileID, unsigned>
getDecomposedExpansionLocSlowCase(const SrcMgr::SLocEntry *E) const;
std::pair<FileID, unsigned>
getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
unsigned Offset) const;
void computeMacroArgsCache(MacroArgsMap *&MacroArgsCache, FileID FID) const;
friend class ASTReader;
friend class ASTWriter;
};
} // end namespace clang
#endif
|