[clang] [llvm] Alisonz/tmp (PR #204233)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 16 12:55:26 PDT 2026
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff origin/main HEAD --extensions h,cpp -- clang/include/clang/Lex/TextEncodingConfig.h clang/lib/Lex/TextEncodingConfig.cpp clang/include/clang/Basic/SourceManager.h clang/include/clang/Frontend/CompilerInstance.h clang/include/clang/Lex/Preprocessor.h clang/lib/Basic/SourceManager.cpp clang/lib/Frontend/CompilerInstance.cpp clang/lib/Frontend/VerifyDiagnosticConsumer.cpp clang/lib/Lex/ModuleMap.cpp clang/lib/Lex/PPDirectives.cpp clang/lib/Lex/Preprocessor.cpp clang/lib/Serialization/ASTReader.cpp llvm/include/llvm/Support/AutoConvert.h llvm/include/llvm/Support/TextEncoding.h llvm/lib/Support/TextEncoding.cpp --diff_from_common_commit
``````````
:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h
index f7d91d612..939285fbe 100644
--- a/clang/include/clang/Basic/SourceManager.h
+++ b/clang/include/clang/Basic/SourceManager.h
@@ -924,7 +924,7 @@ public:
/// being \#included from the specified IncludePosition.
FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
- llvm::TextEncodingConverter *Converter = nullptr,
+ llvm::TextEncodingConverter *Converter = nullptr,
int LoadedID = 0,
SourceLocation::UIntTy LoadedOffset = 0);
@@ -950,7 +950,7 @@ public:
/// new FileID for the \p SourceFile.
FileID getOrCreateFileID(FileEntryRef SourceFile,
SrcMgr::CharacteristicKind FileCharacter,
- llvm::TextEncodingConverter *Converter = nullptr);
+ llvm::TextEncodingConverter *Converter = nullptr);
/// Creates an expansion SLocEntry for the substitution of an argument into a
/// function-like macro's body. Returns the start of the expansion.
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 89a0d066a..6010b4bd9 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -864,7 +864,7 @@ public:
///
/// \return True on success.
static bool InitializeSourceManager(const FrontendInputFile &Input,
- llvm::TextEncodingConverter *,
+ llvm::TextEncodingConverter *,
DiagnosticsEngine &Diags,
FileManager &FileMgr,
SourceManager &SourceMgr);
diff --git a/clang/include/clang/Lex/TextEncodingConfig.h b/clang/include/clang/Lex/TextEncodingConfig.h
index e4f659599..fdd34051e 100644
--- a/clang/include/clang/Lex/TextEncodingConfig.h
+++ b/clang/include/clang/Lex/TextEncodingConfig.h
@@ -16,18 +16,19 @@
enum ConversionAction { CA_NoConversion, CA_FromInputEncoding };
class TextEncodingConfig {
-std::unique_ptr<llvm::TextEncodingConverter> FromInputEncodingConverter;
-llvm::StringMap<std::unique_ptr<llvm::TextEncodingConverter>> FromFiletagEncodingConverters;
+ std::unique_ptr<llvm::TextEncodingConverter> FromInputEncodingConverter;
+ llvm::StringMap<std::unique_ptr<llvm::TextEncodingConverter>>
+ FromFiletagEncodingConverters;
public:
llvm::TextEncodingConverter *getConverter(ConversionAction Action) const;
static llvm::TextEncodingConverter *
- getFromFiletagEncodingConverter(TextEncodingConfig &TEC,
- llvm::StringRef FiletagEncoding);
+ getFromFiletagEncodingConverter(TextEncodingConfig &TEC,
+ llvm::StringRef FiletagEncoding);
static llvm::TextEncodingConverter *
- createAndInsertFromFiletagEncodingConverter(TextEncodingConfig &TEC,
- llvm::StringRef FiletagEncoding,
- clang::DiagnosticsEngine &Diag);
+ createAndInsertFromFiletagEncodingConverter(TextEncodingConfig &TEC,
+ llvm::StringRef FiletagEncoding,
+ clang::DiagnosticsEngine &Diag);
};
#endif
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index 25a7023b7..3bfbfc7eb 100644
--- a/clang/lib/Basic/SourceManager.cpp
+++ b/clang/lib/Basic/SourceManager.cpp
@@ -31,8 +31,8 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SmallVectorMemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -123,9 +123,9 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
IsBufferInvalid = true;
auto BufferOrError = FM.getBufferForFile(*ContentsEntry, IsFileVolatile,
- /*RequiresNullTerminator=*/true,
- /*MaybeLimit=*/std::nullopt,
- /*IsText=*/false);
+ /*RequiresNullTerminator=*/true,
+ /*MaybeLimit=*/std::nullopt,
+ /*IsText=*/false);
// If we were unable to open the file, then we are in an inconsistent
// situation where the content cache referenced a file which no longer
@@ -184,9 +184,9 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
// TODO: Reclaim memory if the buffer size exceeds the content.
auto NewBuf = std::make_unique<llvm::SmallVectorMemoryBuffer>(
std::move(UTF8Buf), Buffer->getBufferIdentifier());
- Buffer = std::move(NewBuf);
+ Buffer = std::move(NewBuf);
}
- }
+ }
#endif
}
}
@@ -594,1776 +594,1799 @@ FileID SourceManager::createFileID(FileEntryRef SourceFile,
llvm::ErrorOr<int> Ccsid = llvm::getFileTag(SourceFile.getName());
if (Ccsid && *Ccsid > 0) {
- #ifndef NDEBUG
- // Either the content cache has never been used for a FileID (and, if we are
- // being asked to use a converter, there should be no valid buffer set up for
- // it) or the conversion (or lack thereof) should be the same as that used
- // previously.
- auto [CacheConverter, CacheUsedByFileID] = IR.FileIDConverterInfo;
- if (CacheUsedByFileID)
- assert(CacheConverter == Converter);
- else
- assert(!Converter || IR.IsBufferInvalid || !IR.getBufferIfLoaded());
+#ifndef NDEBUG
+ // Either the content cache has never been used for a FileID (and, if we are
+ // being asked to use a converter, there should be no valid buffer set up
+ // for it) or the conversion (or lack thereof) should be the same as that
+ // used previously.
+ auto [CacheConverter, CacheUsedByFileID] = IR.FileIDConverterInfo;
+ if (CacheUsedByFileID)
+ assert(CacheConverter == Converter);
+ else
+ assert(!Converter || IR.IsBufferInvalid || !IR.getBufferIfLoaded());
#endif
- IR.FileIDConverterInfo.setPointerAndInt(Converter, true);
+ IR.FileIDConverterInfo.setPointerAndInt(Converter, true);
- // If this is a named pipe, immediately load the buffer to ensure subsequent
- // calls to ContentCache::getSize() are accurate.
- // Do the same if character-encoding conversion was requested.
- if (IR.ContentsEntry->isNamedPipe() || Converter)
- (void)IR.getBufferOrNone(Diag, getFileManager(), SourceLocation());
+ // If this is a named pipe, immediately load the buffer to ensure subsequent
+ // calls to ContentCache::getSize() are accurate.
+ // Do the same if character-encoding conversion was requested.
+ if (IR.ContentsEntry->isNamedPipe() || Converter)
+ (void)IR.getBufferOrNone(Diag, getFileManager(), SourceLocation());
- return createFileIDImpl(IR, SourceFile.getName(), IncludePos, FileCharacter,
- LoadedID, LoadedOffset);
-}
+ return createFileIDImpl(IR, SourceFile.getName(), IncludePos, FileCharacter,
+ LoadedID, LoadedOffset);
+ }
-/// 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 SourceManager::createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer,
- SrcMgr::CharacteristicKind FileCharacter,
- int LoadedID,
- SourceLocation::UIntTy LoadedOffset,
- SourceLocation IncludeLoc) {
- StringRef Name = Buffer->getBufferIdentifier();
- return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
- IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
-}
+ /// 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 SourceManager::createFileID(
+ std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ SrcMgr::CharacteristicKind FileCharacter, int LoadedID,
+ SourceLocation::UIntTy LoadedOffset, SourceLocation IncludeLoc) {
+ StringRef Name = Buffer->getBufferIdentifier();
+ return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)),
+ Name, IncludeLoc, FileCharacter, LoadedID,
+ LoadedOffset);
+ }
-/// Create a new FileID that represents the specified memory buffer.
-///
-/// This does not take ownership of the MemoryBuffer. The memory buffer must
-/// outlive the SourceManager.
-FileID SourceManager::createFileID(const llvm::MemoryBufferRef &Buffer,
- SrcMgr::CharacteristicKind FileCharacter,
- int LoadedID,
- SourceLocation::UIntTy LoadedOffset,
- SourceLocation IncludeLoc) {
- return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
- LoadedID, LoadedOffset, IncludeLoc);
-}
+ /// Create a new FileID that represents the specified memory buffer.
+ ///
+ /// This does not take ownership of the MemoryBuffer. The memory buffer must
+ /// outlive the SourceManager.
+ FileID SourceManager::createFileID(
+ const llvm::MemoryBufferRef &Buffer,
+ SrcMgr::CharacteristicKind FileCharacter, int LoadedID,
+ SourceLocation::UIntTy LoadedOffset, SourceLocation IncludeLoc) {
+ return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
+ LoadedID, LoadedOffset, IncludeLoc);
+ }
-/// Get the FileID for \p SourceFile if it exists. Otherwise, create a
-/// new FileID for the \p SourceFile.
-FileID
-SourceManager::getOrCreateFileID(FileEntryRef SourceFile,
- SrcMgr::CharacteristicKind FileCharacter,
- llvm::TextEncodingConverter *Converter) {
- FileID ID = translateFile(SourceFile);
- return ID.isValid() ? ID
- : createFileID(SourceFile, SourceLocation(),
- FileCharacter, Converter);
-}
+ /// Get the FileID for \p SourceFile if it exists. Otherwise, create a
+ /// new FileID for the \p SourceFile.
+ FileID SourceManager::getOrCreateFileID(
+ FileEntryRef SourceFile, SrcMgr::CharacteristicKind FileCharacter,
+ llvm::TextEncodingConverter * Converter) {
+ FileID ID = translateFile(SourceFile);
+ return ID.isValid() ? ID
+ : createFileID(SourceFile, SourceLocation(),
+ FileCharacter, Converter);
+ }
-/// 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 SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename,
- SourceLocation IncludePos,
- SrcMgr::CharacteristicKind FileCharacter,
- int LoadedID,
- SourceLocation::UIntTy LoadedOffset) {
- if (LoadedID < 0) {
- assert(LoadedID != -1 && "Loading sentinel FileID");
- unsigned Index = unsigned(-LoadedID) - 2;
- assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
- assert(!SLocEntryLoaded[Index] && "FileID already loaded");
- LoadedSLocEntryTable[Index] = SLocEntry::get(
- LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename));
- SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
- return FileID::get(LoadedID);
- }
- unsigned FileSize = File.getSize();
- llvm::ErrorOr<bool> NeedConversion = llvm::needConversion(Filename);
- if (NeedConversion && *NeedConversion) {
- // Buffer size may increase due to potential z/OS EBCDIC to UTF-8
- // conversion.
- if (std::optional<llvm::MemoryBufferRef> Buffer =
- File.getBufferOrNone(Diag, getFileManager())) {
- unsigned BufSize = Buffer->getBufferSize();
- if (BufSize > FileSize) {
- if (File.ContentsEntry.has_value())
- File.ContentsEntry->updateFileEntryBufferSize(BufSize);
- FileSize = BufSize;
+ /// 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 SourceManager::createFileIDImpl(
+ ContentCache & File, StringRef Filename, SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind FileCharacter, int LoadedID,
+ SourceLocation::UIntTy LoadedOffset) {
+ if (LoadedID < 0) {
+ assert(LoadedID != -1 && "Loading sentinel FileID");
+ unsigned Index = unsigned(-LoadedID) - 2;
+ assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
+ assert(!SLocEntryLoaded[Index] && "FileID already loaded");
+ LoadedSLocEntryTable[Index] =
+ SLocEntry::get(LoadedOffset, FileInfo::get(IncludePos, File,
+ FileCharacter, Filename));
+ SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
+ return FileID::get(LoadedID);
+ }
+ unsigned FileSize = File.getSize();
+ llvm::ErrorOr<bool> NeedConversion = llvm::needConversion(Filename);
+ if (NeedConversion && *NeedConversion) {
+ // Buffer size may increase due to potential z/OS EBCDIC to UTF-8
+ // conversion.
+ if (std::optional<llvm::MemoryBufferRef> Buffer =
+ File.getBufferOrNone(Diag, getFileManager())) {
+ unsigned BufSize = Buffer->getBufferSize();
+ if (BufSize > FileSize) {
+ if (File.ContentsEntry.has_value())
+ File.ContentsEntry->updateFileEntryBufferSize(BufSize);
+ FileSize = BufSize;
+ }
}
}
+ if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
+ NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
+ Diag.Report(IncludePos, diag::err_sloc_space_too_large);
+ noteSLocAddressSpaceUsage(Diag);
+ return FileID();
+ }
+ assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
+ LocalSLocEntryTable.push_back(SLocEntry::get(
+ NextLocalOffset,
+ FileInfo::get(IncludePos, File, FileCharacter, Filename)));
+ LocalLocOffsetTable.push_back(NextLocalOffset);
+ LastLookupStartOffset = NextLocalOffset;
+ // We do a +1 here because we want a SourceLocation that means "the end of
+ // the file", e.g. for the "no newline at the end of the file" diagnostic.
+ NextLocalOffset += FileSize + 1;
+ LastLookupEndOffset = NextLocalOffset;
+ updateSlocUsageStats();
+
+ // Set LastFileIDLookup to the newly created file. The next getFileID call
+ // is almost guaranteed to be from that file.
+ FileID FID = FileID::get(LocalSLocEntryTable.size() - 1);
+ return LastFileIDLookup = FID;
}
- if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
- NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
- Diag.Report(IncludePos, diag::err_sloc_space_too_large);
- noteSLocAddressSpaceUsage(Diag);
- return FileID();
+
+ SourceLocation SourceManager::createMacroArgExpansionLoc(
+ SourceLocation SpellingLoc, SourceLocation ExpansionLoc,
+ unsigned Length) {
+ ExpansionInfo Info =
+ ExpansionInfo::createForMacroArg(SpellingLoc, ExpansionLoc);
+ return createExpansionLocImpl(Info, Length);
}
- assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
- LocalSLocEntryTable.push_back(
- SLocEntry::get(NextLocalOffset,
- FileInfo::get(IncludePos, File, FileCharacter, Filename)));
- LocalLocOffsetTable.push_back(NextLocalOffset);
- LastLookupStartOffset = NextLocalOffset;
- // We do a +1 here because we want a SourceLocation that means "the end of the
- // file", e.g. for the "no newline at the end of the file" diagnostic.
- NextLocalOffset += FileSize + 1;
- LastLookupEndOffset = NextLocalOffset;
- updateSlocUsageStats();
- // Set LastFileIDLookup to the newly created file. The next getFileID call is
- // almost guaranteed to be from that file.
- FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
- return LastFileIDLookup = FID;
-}
+ SourceLocation SourceManager::createExpansionLoc(
+ SourceLocation SpellingLoc, SourceLocation ExpansionLocStart,
+ SourceLocation ExpansionLocEnd, unsigned Length,
+ bool ExpansionIsTokenRange, int LoadedID,
+ SourceLocation::UIntTy LoadedOffset) {
+ ExpansionInfo Info = ExpansionInfo::create(
+ SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
+ return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
+ }
-SourceLocation SourceManager::createMacroArgExpansionLoc(
- SourceLocation SpellingLoc, SourceLocation ExpansionLoc, unsigned Length) {
- ExpansionInfo Info = ExpansionInfo::createForMacroArg(SpellingLoc,
- ExpansionLoc);
- return createExpansionLocImpl(Info, Length);
-}
+ SourceLocation SourceManager::createTokenSplitLoc(SourceLocation Spelling,
+ SourceLocation TokenStart,
+ SourceLocation TokenEnd) {
+ assert(getFileID(TokenStart) == getFileID(TokenEnd) &&
+ "token spans multiple files");
+ return createExpansionLocImpl(
+ ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd),
+ TokenEnd.getOffset() - TokenStart.getOffset());
+ }
-SourceLocation SourceManager::createExpansionLoc(
- SourceLocation SpellingLoc, SourceLocation ExpansionLocStart,
- SourceLocation ExpansionLocEnd, unsigned Length,
- bool ExpansionIsTokenRange, int LoadedID,
- SourceLocation::UIntTy LoadedOffset) {
- ExpansionInfo Info = ExpansionInfo::create(
- SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
- return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
-}
+ SourceLocation SourceManager::createExpansionLocImpl(
+ const ExpansionInfo &Info, unsigned Length, int LoadedID,
+ SourceLocation::UIntTy LoadedOffset) {
+ if (LoadedID < 0) {
+ assert(LoadedID != -1 && "Loading sentinel FileID");
+ unsigned Index = unsigned(-LoadedID) - 2;
+ assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
+ assert(!SLocEntryLoaded[Index] && "FileID already loaded");
+ LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);
+ SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
+ return SourceLocation::getMacroLoc(LoadedOffset);
+ }
+ assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
+ LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
+ LocalLocOffsetTable.push_back(NextLocalOffset);
+ if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
+ NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
+ Diag.Report(diag::err_sloc_space_too_large);
+ // FIXME: call `noteSLocAddressSpaceUsage` to report details to users and
+ // use a source location from `Info` to point at an error.
+ // Currently, both cause Clang to run indefinitely, this needs to be
+ // fixed.
+ // FIXME: return an error instead of crashing. Returning invalid source
+ // locations causes compiler to run indefinitely.
+ llvm::report_fatal_error("ran out of source locations");
+ }
+ // See createFileID for that +1.
+ NextLocalOffset += Length + 1;
+ updateSlocUsageStats();
+ return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
+ }
-SourceLocation SourceManager::createTokenSplitLoc(SourceLocation Spelling,
- SourceLocation TokenStart,
- SourceLocation TokenEnd) {
- assert(getFileID(TokenStart) == getFileID(TokenEnd) &&
- "token spans multiple files");
- return createExpansionLocImpl(
- ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd),
- TokenEnd.getOffset() - TokenStart.getOffset());
-}
+ std::optional<llvm::MemoryBufferRef>
+ SourceManager::getMemoryBufferForFileOrNone(FileEntryRef File) {
+ SrcMgr::ContentCache &IR = getOrCreateContentCache(File);
+ return IR.getBufferOrNone(Diag, getFileManager(), SourceLocation());
+ }
-SourceLocation
-SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
- unsigned Length, int LoadedID,
- SourceLocation::UIntTy LoadedOffset) {
- if (LoadedID < 0) {
- assert(LoadedID != -1 && "Loading sentinel FileID");
- unsigned Index = unsigned(-LoadedID) - 2;
- assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
- assert(!SLocEntryLoaded[Index] && "FileID already loaded");
- LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);
- SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
- return SourceLocation::getMacroLoc(LoadedOffset);
- }
- assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
- LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
- LocalLocOffsetTable.push_back(NextLocalOffset);
- if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
- NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
- Diag.Report(diag::err_sloc_space_too_large);
- // FIXME: call `noteSLocAddressSpaceUsage` to report details to users and
- // use a source location from `Info` to point at an error.
- // Currently, both cause Clang to run indefinitely, this needs to be fixed.
- // FIXME: return an error instead of crashing. Returning invalid source
- // locations causes compiler to run indefinitely.
- llvm::report_fatal_error("ran out of source locations");
- }
- // See createFileID for that +1.
- NextLocalOffset += Length + 1;
- updateSlocUsageStats();
- return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
-}
+ void SourceManager::overrideFileContents(
+ FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile);
-std::optional<llvm::MemoryBufferRef>
-SourceManager::getMemoryBufferForFileOrNone(FileEntryRef File) {
- SrcMgr::ContentCache &IR = getOrCreateContentCache(File);
- return IR.getBufferOrNone(Diag, getFileManager(), SourceLocation());
-}
+ IR.setBuffer(std::move(Buffer));
+ IR.BufferOverridden = true;
-void SourceManager::overrideFileContents(
- FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
- SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile);
+ getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
+ }
- IR.setBuffer(std::move(Buffer));
- IR.BufferOverridden = true;
+ void SourceManager::overrideFileContents(const FileEntry *SourceFile,
+ FileEntryRef NewFile) {
+ assert(SourceFile->getSize() == NewFile.getSize() &&
+ "Different sizes, use the FileManager to create a virtual file with "
+ "the correct size");
+ assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
+ "This function should be called at the initialization stage, before "
+ "any parsing occurs.");
+ // FileEntryRef is not default-constructible.
+ auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
+ std::make_pair(SourceFile, NewFile));
+ if (!Pair.second)
+ Pair.first->second = NewFile;
+ }
- getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
-}
+ OptionalFileEntryRef SourceManager::bypassFileContentsOverride(
+ FileEntryRef File) {
+ assert(isFileOverridden(&File.getFileEntry()));
+ OptionalFileEntryRef BypassFile = FileMgr.getBypassFile(File);
-void SourceManager::overrideFileContents(const FileEntry *SourceFile,
- FileEntryRef NewFile) {
- assert(SourceFile->getSize() == NewFile.getSize() &&
- "Different sizes, use the FileManager to create a virtual file with "
- "the correct size");
- assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
- "This function should be called at the initialization stage, before "
- "any parsing occurs.");
- // FileEntryRef is not default-constructible.
- auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
- std::make_pair(SourceFile, NewFile));
- if (!Pair.second)
- Pair.first->second = NewFile;
-}
+ // If the file can't be found in the FS, give up.
+ if (!BypassFile)
+ return std::nullopt;
-OptionalFileEntryRef
-SourceManager::bypassFileContentsOverride(FileEntryRef File) {
- assert(isFileOverridden(&File.getFileEntry()));
- OptionalFileEntryRef BypassFile = FileMgr.getBypassFile(File);
+ (void)getOrCreateContentCache(*BypassFile);
+ return BypassFile;
+ }
- // If the file can't be found in the FS, give up.
- if (!BypassFile)
- return std::nullopt;
+ void SourceManager::setFileIsTransient(FileEntryRef File) {
+ getOrCreateContentCache(File).IsTransient = true;
+ }
- (void)getOrCreateContentCache(*BypassFile);
- return BypassFile;
-}
+ std::optional<StringRef> SourceManager::getNonBuiltinFilenameForID(FileID FID)
+ const {
+ if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
+ if (Entry->getFile().getContentCache().OrigEntry)
+ return Entry->getFile().getName();
+ return std::nullopt;
+ }
-void SourceManager::setFileIsTransient(FileEntryRef File) {
- getOrCreateContentCache(File).IsTransient = true;
-}
+ StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
+ auto B = getBufferDataOrNone(FID);
+ if (Invalid)
+ *Invalid = !B;
+ return B ? *B : "<<<<<INVALID SOURCE LOCATION>>>>>";
+ }
-std::optional<StringRef>
-SourceManager::getNonBuiltinFilenameForID(FileID FID) const {
- if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
- if (Entry->getFile().getContentCache().OrigEntry)
- return Entry->getFile().getName();
- return std::nullopt;
-}
+ std::optional<StringRef> SourceManager::getBufferDataIfLoaded(FileID FID)
+ const {
+ if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
+ return Entry->getFile().getContentCache().getBufferDataIfLoaded();
+ return std::nullopt;
+ }
-StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
- auto B = getBufferDataOrNone(FID);
- if (Invalid)
- *Invalid = !B;
- return B ? *B : "<<<<<INVALID SOURCE LOCATION>>>>>";
-}
+ std::optional<StringRef> SourceManager::getBufferDataOrNone(FileID FID)
+ const {
+ if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
+ if (auto B = Entry->getFile().getContentCache().getBufferOrNone(
+ Diag, getFileManager(), SourceLocation()))
+ return B->getBuffer();
+ return std::nullopt;
+ }
-std::optional<StringRef>
-SourceManager::getBufferDataIfLoaded(FileID FID) const {
- if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
- return Entry->getFile().getContentCache().getBufferDataIfLoaded();
- return std::nullopt;
-}
+ //===----------------------------------------------------------------------===//
+ // SourceLocation manipulation methods.
+ //===----------------------------------------------------------------------===//
+
+ /// Return the FileID for a SourceLocation.
+ ///
+ /// This is the cache-miss path of getFileID. Not as hot as that function, but
+ /// still very important. It is responsible for finding the entry in the
+ /// SLocEntry tables that contains the specified location.
+ FileID SourceManager::getFileIDSlow(SourceLocation::UIntTy SLocOffset) const {
+ if (!SLocOffset)
+ return FileID::get(0);
+
+ // Now it is time to search for the correct file. See where the SLocOffset
+ // sits in the global view and consult local or loaded buffers for it.
+ if (SLocOffset < NextLocalOffset)
+ return getFileIDLocal(SLocOffset);
+ return getFileIDLoaded(SLocOffset);
+ }
-std::optional<StringRef> SourceManager::getBufferDataOrNone(FileID FID) const {
- if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
- if (auto B = Entry->getFile().getContentCache().getBufferOrNone(
- Diag, getFileManager(), SourceLocation()))
- return B->getBuffer();
- return std::nullopt;
-}
+ /// Return the FileID for a SourceLocation with a low offset.
+ ///
+ /// This function knows that the SourceLocation is in a local buffer, not a
+ /// loaded one.
+ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset)
+ const {
+ assert(SLocOffset < NextLocalOffset && "Bad function choice");
+ assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
+ "Invalid SLocOffset");
+ assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
+ assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry");
+
+ // After the first and second level caches, I see two common sorts of
+ // behavior: 1) a lot of searched FileID's are "near" the cached file
+ // location or are "near" the cached expansion location. 2) others are just
+ // completely random and may be a very long way away.
+ //
+ // To handle this, we do a linear search for up to 8 steps to catch #1
+ // quickly then we fall back to a less cache efficient, but more scalable,
+ // binary search to find the location.
+
+ // See if this is near the file point - worst case we start scanning from
+ // the most newly created FileID.
+
+ // LessIndex - This is the lower bound of the range that we're searching.
+ // We know that the offset corresponding to the FileID is less than
+ // SLocOffset.
+ unsigned LessIndex = 0;
+ // upper bound of the search range.
+ unsigned GreaterIndex = LocalLocOffsetTable.size();
+ // Use the LastFileIDLookup to prune the search space.
+ if (LastLookupStartOffset < SLocOffset)
+ LessIndex = LastFileIDLookup.ID;
+ else
+ GreaterIndex = LastFileIDLookup.ID;
-//===----------------------------------------------------------------------===//
-// SourceLocation manipulation methods.
-//===----------------------------------------------------------------------===//
+ // Find the FileID that contains this.
+ unsigned NumProbes = 0;
+ while (true) {
+ --GreaterIndex;
+ assert(GreaterIndex < LocalLocOffsetTable.size());
+ if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
+ FileID Res = FileID::get(int(GreaterIndex));
+ // Remember it. We have good locality across FileID lookups.
+ LastFileIDLookup = Res;
+ LastLookupStartOffset = LocalLocOffsetTable[GreaterIndex];
+ LastLookupEndOffset = GreaterIndex + 1 >= LocalLocOffsetTable.size()
+ ? NextLocalOffset
+ : LocalLocOffsetTable[GreaterIndex + 1];
+ NumLinearScans += NumProbes + 1;
+ return Res;
+ }
+ if (++NumProbes == 8)
+ break;
+ }
-/// Return the FileID for a SourceLocation.
-///
-/// This is the cache-miss path of getFileID. Not as hot as that function, but
-/// still very important. It is responsible for finding the entry in the
-/// SLocEntry tables that contains the specified location.
-FileID SourceManager::getFileIDSlow(SourceLocation::UIntTy SLocOffset) const {
- if (!SLocOffset)
- return FileID::get(0);
-
- // Now it is time to search for the correct file. See where the SLocOffset
- // sits in the global view and consult local or loaded buffers for it.
- if (SLocOffset < NextLocalOffset)
- return getFileIDLocal(SLocOffset);
- return getFileIDLoaded(SLocOffset);
-}
+ while (LessIndex < GreaterIndex) {
+ ++NumBinaryProbes;
-/// Return the FileID for a SourceLocation with a low offset.
-///
-/// This function knows that the SourceLocation is in a local buffer, not a
-/// loaded one.
-FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
- assert(SLocOffset < NextLocalOffset && "Bad function choice");
- assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
- "Invalid SLocOffset");
- assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
- assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry");
-
- // After the first and second level caches, I see two common sorts of
- // behavior: 1) a lot of searched FileID's are "near" the cached file
- // location or are "near" the cached expansion location. 2) others are just
- // completely random and may be a very long way away.
- //
- // To handle this, we do a linear search for up to 8 steps to catch #1 quickly
- // then we fall back to a less cache efficient, but more scalable, binary
- // search to find the location.
-
- // See if this is near the file point - worst case we start scanning from the
- // most newly created FileID.
-
- // LessIndex - This is the lower bound of the range that we're searching.
- // We know that the offset corresponding to the FileID is less than
- // SLocOffset.
- unsigned LessIndex = 0;
- // upper bound of the search range.
- unsigned GreaterIndex = LocalLocOffsetTable.size();
- // Use the LastFileIDLookup to prune the search space.
- if (LastLookupStartOffset < SLocOffset)
- LessIndex = LastFileIDLookup.ID;
- else
- GreaterIndex = LastFileIDLookup.ID;
-
- // Find the FileID that contains this.
- unsigned NumProbes = 0;
- while (true) {
- --GreaterIndex;
- assert(GreaterIndex < LocalLocOffsetTable.size());
- if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
- FileID Res = FileID::get(int(GreaterIndex));
- // Remember it. We have good locality across FileID lookups.
- LastFileIDLookup = Res;
- LastLookupStartOffset = LocalLocOffsetTable[GreaterIndex];
- LastLookupEndOffset =
- GreaterIndex + 1 >= LocalLocOffsetTable.size()
- ? NextLocalOffset
- : LocalLocOffsetTable[GreaterIndex + 1];
- NumLinearScans += NumProbes + 1;
- return Res;
+ unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
+ if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
+ LessIndex = MiddleIndex + 1;
+ else
+ GreaterIndex = MiddleIndex;
}
- if (++NumProbes == 8)
- break;
+
+ // At this point, LessIndex is the index of the *first element greater than*
+ // SLocOffset. The element we are actually looking for is the one
+ // immediately before it.
+ LastLookupStartOffset = LocalLocOffsetTable[LessIndex - 1];
+ LastLookupEndOffset = LocalLocOffsetTable[LessIndex];
+ return LastFileIDLookup = FileID::get(LessIndex - 1);
}
- while (LessIndex < GreaterIndex) {
- ++NumBinaryProbes;
+ /// Return the FileID for a SourceLocation with a high offset.
+ ///
+ /// This function knows that the SourceLocation is in a loaded buffer, not a
+ /// local one.
+ FileID SourceManager::getFileIDLoaded(SourceLocation::UIntTy SLocOffset)
+ const {
+ if (SLocOffset < CurrentLoadedOffset) {
+ assert(0 && "Invalid SLocOffset or bad function choice");
+ return FileID();
+ }
- unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
- if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
- LessIndex = MiddleIndex + 1;
- else
- GreaterIndex = MiddleIndex;
+ return FileID::get(ExternalSLocEntries->getSLocEntryID(SLocOffset));
}
- // At this point, LessIndex is the index of the *first element greater than*
- // SLocOffset. The element we are actually looking for is the one immediately
- // before it.
- LastLookupStartOffset = LocalLocOffsetTable[LessIndex - 1];
- LastLookupEndOffset = LocalLocOffsetTable[LessIndex];
- return LastFileIDLookup = FileID::get(LessIndex - 1);
-}
+ SourceLocation SourceManager::getExpansionLocSlowCase(SourceLocation Loc)
+ const {
+ do {
+ // Note: If Loc indicates an offset into a token that came from a macro
+ // expansion (e.g. the 5th character of the token) we do not want to add
+ // this offset when going to the expansion location. The expansion
+ // location is the macro invocation, which the offset has nothing to do
+ // with. This is unlike when we get the spelling loc, because the offset
+ // directly correspond to the token whose spelling we're inspecting.
+ Loc = getSLocEntry(getFileID(Loc)).getExpansion().getExpansionLocStart();
+ } while (!Loc.isFileID());
-/// Return the FileID for a SourceLocation with a high offset.
-///
-/// This function knows that the SourceLocation is in a loaded buffer, not a
-/// local one.
-FileID SourceManager::getFileIDLoaded(SourceLocation::UIntTy SLocOffset) const {
- if (SLocOffset < CurrentLoadedOffset) {
- assert(0 && "Invalid SLocOffset or bad function choice");
- return FileID();
+ return Loc;
}
- return FileID::get(ExternalSLocEntries->getSLocEntryID(SLocOffset));
-}
-
-SourceLocation SourceManager::
-getExpansionLocSlowCase(SourceLocation Loc) const {
- do {
- // Note: If Loc indicates an offset into a token that came from a macro
- // expansion (e.g. the 5th character of the token) we do not want to add
- // this offset when going to the expansion location. The expansion
- // location is the macro invocation, which the offset has nothing to do
- // with. This is unlike when we get the spelling loc, because the offset
- // directly correspond to the token whose spelling we're inspecting.
- Loc = getSLocEntry(getFileID(Loc)).getExpansion().getExpansionLocStart();
- } while (!Loc.isFileID());
-
- return Loc;
-}
+ SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc)
+ const {
+ do {
+ const SLocEntry &Entry = getSLocEntry(getFileID(Loc));
+ Loc = Entry.getExpansion().getSpellingLoc().getLocWithOffset(
+ Loc.getOffset() - Entry.getOffset());
+ } while (!Loc.isFileID());
+ return Loc;
+ }
-SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
- do {
- const SLocEntry &Entry = getSLocEntry(getFileID(Loc));
- Loc = Entry.getExpansion().getSpellingLoc().getLocWithOffset(
- Loc.getOffset() - Entry.getOffset());
- } while (!Loc.isFileID());
- return Loc;
-}
+ SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const {
+ do {
+ const SLocEntry &Entry = getSLocEntry(getFileID(Loc));
+ const ExpansionInfo &ExpInfo = Entry.getExpansion();
+ if (ExpInfo.isMacroArgExpansion()) {
+ Loc = ExpInfo.getSpellingLoc().getLocWithOffset(Loc.getOffset() -
+ Entry.getOffset());
+ } else {
+ Loc = ExpInfo.getExpansionLocStart();
+ }
+ } while (!Loc.isFileID());
+ return Loc;
+ }
-SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const {
- do {
- const SLocEntry &Entry = getSLocEntry(getFileID(Loc));
- const ExpansionInfo &ExpInfo = Entry.getExpansion();
- if (ExpInfo.isMacroArgExpansion()) {
- Loc = ExpInfo.getSpellingLoc().getLocWithOffset(Loc.getOffset() -
- Entry.getOffset());
- } else {
- Loc = ExpInfo.getExpansionLocStart();
- }
- } while (!Loc.isFileID());
- return 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 SourceManager::getImmediateSpellingLoc(SourceLocation Loc)
+ const {
+ if (Loc.isFileID())
+ return Loc;
+ FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
+ Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc();
+ return Loc.getLocWithOffset(LocInfo.second);
+ }
-/// 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 SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{
- if (Loc.isFileID()) return Loc;
- FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
- Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc();
- return Loc.getLocWithOffset(LocInfo.second);
-}
+ /// Return the filename of the file containing a SourceLocation.
+ StringRef SourceManager::getFilename(SourceLocation SpellingLoc) const {
+ if (OptionalFileEntryRef F = getFileEntryRefForID(getFileID(SpellingLoc)))
+ return F->getName();
+ return StringRef();
+ }
-/// Return the filename of the file containing a SourceLocation.
-StringRef SourceManager::getFilename(SourceLocation SpellingLoc) const {
- if (OptionalFileEntryRef F = getFileEntryRefForID(getFileID(SpellingLoc)))
- return F->getName();
- return StringRef();
-}
+ /// getImmediateExpansionRange - Loc is required to be an expansion location.
+ /// Return the start/end of the expansion information.
+ CharSourceRange SourceManager::getImmediateExpansionRange(SourceLocation Loc)
+ const {
+ assert(Loc.isMacroID() && "Not a macro expansion loc!");
+ const ExpansionInfo &Expansion =
+ getSLocEntry(getFileID(Loc)).getExpansion();
+ return Expansion.getExpansionLocRange();
+ }
-/// getImmediateExpansionRange - Loc is required to be an expansion location.
-/// Return the start/end of the expansion information.
-CharSourceRange
-SourceManager::getImmediateExpansionRange(SourceLocation Loc) const {
- assert(Loc.isMacroID() && "Not a macro expansion loc!");
- const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion();
- return Expansion.getExpansionLocRange();
-}
+ SourceLocation SourceManager::getTopMacroCallerLoc(SourceLocation Loc) const {
+ while (isMacroArgExpansion(Loc))
+ Loc = getImmediateSpellingLoc(Loc);
+ return Loc;
+ }
-SourceLocation SourceManager::getTopMacroCallerLoc(SourceLocation Loc) const {
- while (isMacroArgExpansion(Loc))
- Loc = getImmediateSpellingLoc(Loc);
- return Loc;
-}
+ /// getExpansionRange - Given a SourceLocation object, return the range of
+ /// tokens covered by the expansion in the ultimate file.
+ CharSourceRange SourceManager::getExpansionRange(SourceLocation Loc) const {
+ if (Loc.isFileID())
+ return CharSourceRange(SourceRange(Loc, Loc), true);
+
+ CharSourceRange Res = getImmediateExpansionRange(Loc);
+
+ // Fully resolve the start and end locations to their ultimate expansion
+ // points.
+ while (!Res.getBegin().isFileID())
+ Res.setBegin(getImmediateExpansionRange(Res.getBegin()).getBegin());
+ while (!Res.getEnd().isFileID()) {
+ CharSourceRange EndRange = getImmediateExpansionRange(Res.getEnd());
+ Res.setEnd(EndRange.getEnd());
+ Res.setTokenRange(EndRange.isTokenRange());
+ }
+ return Res;
+ }
-/// getExpansionRange - Given a SourceLocation object, return the range of
-/// tokens covered by the expansion in the ultimate file.
-CharSourceRange SourceManager::getExpansionRange(SourceLocation Loc) const {
- if (Loc.isFileID())
- return CharSourceRange(SourceRange(Loc, Loc), true);
+ bool SourceManager::isMacroArgExpansion(SourceLocation Loc,
+ SourceLocation * StartLoc) const {
+ if (!Loc.isMacroID())
+ return false;
- CharSourceRange Res = getImmediateExpansionRange(Loc);
+ FileID FID = getFileID(Loc);
+ const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
+ if (!Expansion.isMacroArgExpansion())
+ return false;
- // Fully resolve the start and end locations to their ultimate expansion
- // points.
- while (!Res.getBegin().isFileID())
- Res.setBegin(getImmediateExpansionRange(Res.getBegin()).getBegin());
- while (!Res.getEnd().isFileID()) {
- CharSourceRange EndRange = getImmediateExpansionRange(Res.getEnd());
- Res.setEnd(EndRange.getEnd());
- Res.setTokenRange(EndRange.isTokenRange());
+ if (StartLoc)
+ *StartLoc = Expansion.getExpansionLocStart();
+ return true;
}
- return Res;
-}
-
-bool SourceManager::isMacroArgExpansion(SourceLocation Loc,
- SourceLocation *StartLoc) const {
- if (!Loc.isMacroID()) return false;
-
- FileID FID = getFileID(Loc);
- const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
- if (!Expansion.isMacroArgExpansion()) return false;
- if (StartLoc)
- *StartLoc = Expansion.getExpansionLocStart();
- return true;
-}
+ bool SourceManager::isMacroBodyExpansion(SourceLocation Loc) const {
+ if (!Loc.isMacroID())
+ return false;
-bool SourceManager::isMacroBodyExpansion(SourceLocation Loc) const {
- if (!Loc.isMacroID()) return false;
+ FileID FID = getFileID(Loc);
+ const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
+ return Expansion.isMacroBodyExpansion();
+ }
- FileID FID = getFileID(Loc);
- const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
- return Expansion.isMacroBodyExpansion();
-}
+ bool SourceManager::isAtStartOfImmediateMacroExpansion(
+ SourceLocation Loc, SourceLocation * MacroBegin) const {
+ assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
-bool SourceManager::isAtStartOfImmediateMacroExpansion(SourceLocation Loc,
- SourceLocation *MacroBegin) const {
- assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
+ FileIDAndOffset DecompLoc = getDecomposedLoc(Loc);
+ if (DecompLoc.second > 0)
+ return false; // Does not point at the start of expansion range.
- FileIDAndOffset DecompLoc = getDecomposedLoc(Loc);
- if (DecompLoc.second > 0)
- return false; // Does not point at the start of expansion range.
+ bool Invalid = false;
+ const SrcMgr::ExpansionInfo &ExpInfo =
+ getSLocEntry(DecompLoc.first, &Invalid).getExpansion();
+ if (Invalid)
+ return false;
+ SourceLocation ExpLoc = ExpInfo.getExpansionLocStart();
- bool Invalid = false;
- const SrcMgr::ExpansionInfo &ExpInfo =
- getSLocEntry(DecompLoc.first, &Invalid).getExpansion();
- if (Invalid)
- return false;
- SourceLocation ExpLoc = ExpInfo.getExpansionLocStart();
-
- if (ExpInfo.isMacroArgExpansion()) {
- // For macro argument expansions, check if the previous FileID is part of
- // the same argument expansion, in which case this Loc is not at the
- // beginning of the expansion.
- FileID PrevFID = getPreviousFileID(DecompLoc.first);
- if (!PrevFID.isInvalid()) {
- const SrcMgr::SLocEntry &PrevEntry = getSLocEntry(PrevFID, &Invalid);
- if (Invalid)
- return false;
- if (PrevEntry.isExpansion() &&
- PrevEntry.getExpansion().getExpansionLocStart() == ExpLoc)
- return false;
+ if (ExpInfo.isMacroArgExpansion()) {
+ // For macro argument expansions, check if the previous FileID is part of
+ // the same argument expansion, in which case this Loc is not at the
+ // beginning of the expansion.
+ FileID PrevFID = getPreviousFileID(DecompLoc.first);
+ if (!PrevFID.isInvalid()) {
+ const SrcMgr::SLocEntry &PrevEntry = getSLocEntry(PrevFID, &Invalid);
+ if (Invalid)
+ return false;
+ if (PrevEntry.isExpansion() &&
+ PrevEntry.getExpansion().getExpansionLocStart() == ExpLoc)
+ return false;
+ }
}
- }
- if (MacroBegin)
- *MacroBegin = ExpLoc;
- return true;
-}
+ if (MacroBegin)
+ *MacroBegin = ExpLoc;
+ return true;
+ }
-bool SourceManager::isAtEndOfImmediateMacroExpansion(SourceLocation Loc,
- SourceLocation *MacroEnd) const {
- assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
+ bool SourceManager::isAtEndOfImmediateMacroExpansion(
+ SourceLocation Loc, SourceLocation * MacroEnd) const {
+ assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
- FileID FID = getFileID(Loc);
- SourceLocation NextLoc = Loc.getLocWithOffset(1);
- if (isInFileID(NextLoc, FID))
- return false; // Does not point at the end of expansion range.
+ FileID FID = getFileID(Loc);
+ SourceLocation NextLoc = Loc.getLocWithOffset(1);
+ if (isInFileID(NextLoc, FID))
+ return false; // Does not point at the end of expansion range.
- bool Invalid = false;
- const SrcMgr::ExpansionInfo &ExpInfo =
- getSLocEntry(FID, &Invalid).getExpansion();
- if (Invalid)
- return false;
+ bool Invalid = false;
+ const SrcMgr::ExpansionInfo &ExpInfo =
+ getSLocEntry(FID, &Invalid).getExpansion();
+ if (Invalid)
+ return false;
- if (ExpInfo.isMacroArgExpansion()) {
- // For macro argument expansions, check if the next FileID is part of the
- // same argument expansion, in which case this Loc is not at the end of the
- // expansion.
- FileID NextFID = getNextFileID(FID);
- if (!NextFID.isInvalid()) {
- const SrcMgr::SLocEntry &NextEntry = getSLocEntry(NextFID, &Invalid);
- if (Invalid)
- return false;
- if (NextEntry.isExpansion() &&
- NextEntry.getExpansion().getExpansionLocStart() ==
- ExpInfo.getExpansionLocStart())
- return false;
+ if (ExpInfo.isMacroArgExpansion()) {
+ // For macro argument expansions, check if the next FileID is part of the
+ // same argument expansion, in which case this Loc is not at the end of
+ // the expansion.
+ FileID NextFID = getNextFileID(FID);
+ if (!NextFID.isInvalid()) {
+ const SrcMgr::SLocEntry &NextEntry = getSLocEntry(NextFID, &Invalid);
+ if (Invalid)
+ return false;
+ if (NextEntry.isExpansion() &&
+ NextEntry.getExpansion().getExpansionLocStart() ==
+ ExpInfo.getExpansionLocStart())
+ return false;
+ }
}
- }
- if (MacroEnd)
- *MacroEnd = ExpInfo.getExpansionLocEnd();
- return true;
-}
+ if (MacroEnd)
+ *MacroEnd = ExpInfo.getExpansionLocEnd();
+ return true;
+ }
-//===----------------------------------------------------------------------===//
-// Queries about the code at a SourceLocation.
-//===----------------------------------------------------------------------===//
+ //===----------------------------------------------------------------------===//
+ // Queries about the code at a SourceLocation.
+ //===----------------------------------------------------------------------===//
+
+ /// getCharacterData - Return a pointer to the start of the specified location
+ /// in the appropriate MemoryBuffer.
+ const char *SourceManager::getCharacterData(SourceLocation SL, bool *Invalid)
+ const {
+ // Note that this is a hot function in the getSpelling() path, which is
+ // heavily used by -E mode.
+ FileIDAndOffset LocInfo = getDecomposedSpellingLoc(SL);
+
+ // Note that calling 'getBuffer()' may lazily page in a source file.
+ bool CharDataInvalid = false;
+ const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid);
+ if (CharDataInvalid || !Entry.isFile()) {
+ if (Invalid)
+ *Invalid = true;
-/// getCharacterData - Return a pointer to the start of the specified location
-/// in the appropriate MemoryBuffer.
-const char *SourceManager::getCharacterData(SourceLocation SL,
- bool *Invalid) const {
- // Note that this is a hot function in the getSpelling() path, which is
- // heavily used by -E mode.
- FileIDAndOffset LocInfo = getDecomposedSpellingLoc(SL);
-
- // Note that calling 'getBuffer()' may lazily page in a source file.
- bool CharDataInvalid = false;
- const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid);
- if (CharDataInvalid || !Entry.isFile()) {
+ return "<<<<INVALID BUFFER>>>>";
+ }
+ std::optional<llvm::MemoryBufferRef> Buffer =
+ Entry.getFile().getContentCache().getBufferOrNone(
+ Diag, getFileManager(), SourceLocation());
if (Invalid)
- *Invalid = true;
-
- return "<<<<INVALID BUFFER>>>>";
+ *Invalid = !Buffer;
+ return Buffer ? Buffer->getBufferStart() + LocInfo.second
+ : "<<<<INVALID BUFFER>>>>";
}
- std::optional<llvm::MemoryBufferRef> Buffer =
- Entry.getFile().getContentCache().getBufferOrNone(Diag, getFileManager(),
- SourceLocation());
- if (Invalid)
- *Invalid = !Buffer;
- return Buffer ? Buffer->getBufferStart() + LocInfo.second
- : "<<<<INVALID BUFFER>>>>";
-}
-/// getColumnNumber - Return the column # for the specified file position.
-/// this is significantly cheaper to compute than the line number.
-unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
- bool *Invalid) const {
- std::optional<llvm::MemoryBufferRef> MemBuf = getBufferOrNone(FID);
- if (Invalid)
- *Invalid = !MemBuf;
+ /// getColumnNumber - Return the column # for the specified file position.
+ /// this is significantly cheaper to compute than the line number.
+ unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
+ bool *Invalid) const {
+ std::optional<llvm::MemoryBufferRef> MemBuf = getBufferOrNone(FID);
+ if (Invalid)
+ *Invalid = !MemBuf;
- if (!MemBuf)
- return 1;
+ if (!MemBuf)
+ return 1;
- // It is okay to request a position just past the end of the buffer.
- if (FilePos > MemBuf->getBufferSize()) {
- if (Invalid)
- *Invalid = true;
- return 1;
- }
-
- const char *Buf = MemBuf->getBufferStart();
- // See if we just calculated the line number for this FilePos and can use
- // that to lookup the start of the line instead of searching for it.
- if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache &&
- LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {
- const unsigned *SourceLineCache =
- LastLineNoContentCache->SourceLineCache.begin();
- unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
- unsigned LineEnd = SourceLineCache[LastLineNoResult];
- if (FilePos >= LineStart && FilePos < LineEnd) {
- // LineEnd is the LineStart of the next line.
- // A line ends with separator LF or CR+LF on Windows.
- // FilePos might point to the last separator,
- // but we need a column number at most 1 + the last column.
- if (FilePos + 1 == LineEnd && FilePos > LineStart) {
- if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')
- --FilePos;
+ // It is okay to request a position just past the end of the buffer.
+ if (FilePos > MemBuf->getBufferSize()) {
+ if (Invalid)
+ *Invalid = true;
+ return 1;
+ }
+
+ const char *Buf = MemBuf->getBufferStart();
+ // See if we just calculated the line number for this FilePos and can use
+ // that to lookup the start of the line instead of searching for it.
+ if (LastLineNoFileIDQuery == FID &&
+ LastLineNoContentCache->SourceLineCache &&
+ LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {
+ const unsigned *SourceLineCache =
+ LastLineNoContentCache->SourceLineCache.begin();
+ unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
+ unsigned LineEnd = SourceLineCache[LastLineNoResult];
+ if (FilePos >= LineStart && FilePos < LineEnd) {
+ // LineEnd is the LineStart of the next line.
+ // A line ends with separator LF or CR+LF on Windows.
+ // FilePos might point to the last separator,
+ // but we need a column number at most 1 + the last column.
+ if (FilePos + 1 == LineEnd && FilePos > LineStart) {
+ if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')
+ --FilePos;
+ }
+ return (FilePos - LineStart) + 1;
}
- return (FilePos - LineStart) + 1;
}
- }
- unsigned LineStart = FilePos;
- while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
- --LineStart;
- return (FilePos - LineStart) + 1;
-}
+ unsigned LineStart = FilePos;
+ while (LineStart && Buf[LineStart - 1] != '\n' &&
+ Buf[LineStart - 1] != '\r')
+ --LineStart;
+ return (FilePos - LineStart) + 1;
+ }
-// isInvalid - Return the result of calling loc.isInvalid(), and
-// if Invalid is not null, set its value to same.
-template<typename LocType>
-static bool isInvalid(LocType Loc, bool *Invalid) {
- bool MyInvalid = Loc.isInvalid();
- if (Invalid)
- *Invalid = MyInvalid;
- return MyInvalid;
-}
+ // isInvalid - Return the result of calling loc.isInvalid(), and
+ // if Invalid is not null, set its value to same.
+ template <typename LocType>
+ static bool isInvalid(LocType Loc, bool *Invalid) {
+ bool MyInvalid = Loc.isInvalid();
+ if (Invalid)
+ *Invalid = MyInvalid;
+ return MyInvalid;
+ }
-unsigned SourceManager::getColumnNumber(SourceLocation Loc,
- bool *Invalid) const {
- assert(Loc.isFileID());
- if (isInvalid(Loc, Invalid)) return 0;
- FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
- return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
-}
+ unsigned SourceManager::getColumnNumber(SourceLocation Loc, bool *Invalid)
+ const {
+ assert(Loc.isFileID());
+ if (isInvalid(Loc, Invalid))
+ return 0;
+ FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
+ return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
+ }
-unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc,
- bool *Invalid) const {
- PresumedLoc PLoc = getPresumedLoc(Loc);
- if (isInvalid(PLoc, Invalid)) return 0;
- return PLoc.getColumn();
-}
+ unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ PresumedLoc PLoc = getPresumedLoc(Loc);
+ if (isInvalid(PLoc, Invalid))
+ return 0;
+ return PLoc.getColumn();
+ }
-// Check if multi-byte word x has bytes between m and n, included. This may also
-// catch bytes equal to n + 1.
-// The returned value holds a 0x80 at each byte position that holds a match.
-// see http://graphics.stanford.edu/~seander/bithacks.html#HasBetweenInWord
-template <class T>
-static constexpr inline T likelyhasbetween(T x, unsigned char m,
- unsigned char n) {
- return ((x - ~static_cast<T>(0) / 255 * (n + 1)) & ~x &
- ((x & ~static_cast<T>(0) / 255 * 127) +
- (~static_cast<T>(0) / 255 * (127 - (m - 1))))) &
- ~static_cast<T>(0) / 255 * 128;
-}
+ // Check if multi-byte word x has bytes between m and n, included. This may
+ // also catch bytes equal to n + 1. The returned value holds a 0x80 at each
+ // byte position that holds a match. see
+ // http://graphics.stanford.edu/~seander/bithacks.html#HasBetweenInWord
+ template <class T>
+ static constexpr inline T likelyhasbetween(T x, unsigned char m,
+ unsigned char n) {
+ return ((x - ~static_cast<T>(0) / 255 * (n + 1)) & ~x &
+ ((x & ~static_cast<T>(0) / 255 * 127) +
+ (~static_cast<T>(0) / 255 * (127 - (m - 1))))) &
+ ~static_cast<T>(0) / 255 * 128;
+ }
-LineOffsetMapping LineOffsetMapping::get(llvm::MemoryBufferRef Buffer,
- llvm::BumpPtrAllocator &Alloc) {
+ LineOffsetMapping LineOffsetMapping::get(llvm::MemoryBufferRef Buffer,
+ llvm::BumpPtrAllocator & Alloc) {
- // Find the file offsets of all of the *physical* source lines. This does
- // not look at trigraphs, escaped newlines, or anything else tricky.
- SmallVector<unsigned, 256> LineOffsets;
+ // Find the file offsets of all of the *physical* source lines. This does
+ // not look at trigraphs, escaped newlines, or anything else tricky.
+ SmallVector<unsigned, 256> LineOffsets;
- // Line #1 starts at char 0.
- LineOffsets.push_back(0);
+ // Line #1 starts at char 0.
+ LineOffsets.push_back(0);
- const unsigned char *Start = (const unsigned char *)Buffer.getBufferStart();
- const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd();
- const unsigned char *Buf = Start;
+ const unsigned char *Start = (const unsigned char *)Buffer.getBufferStart();
+ const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd();
+ const unsigned char *Buf = Start;
- uint64_t Word;
+ uint64_t Word;
- // scan sizeof(Word) bytes at a time for new lines.
- // This is much faster than scanning each byte independently.
- if ((unsigned long)(End - Start) > sizeof(Word)) {
- do {
- Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
- // no new line => jump over sizeof(Word) bytes.
- auto Mask = likelyhasbetween(Word, '\n', '\r');
- if (!Mask) {
- Buf += sizeof(Word);
- continue;
- }
+ // scan sizeof(Word) bytes at a time for new lines.
+ // This is much faster than scanning each byte independently.
+ if ((unsigned long)(End - Start) > sizeof(Word)) {
+ do {
+ Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
+ // no new line => jump over sizeof(Word) bytes.
+ auto Mask = likelyhasbetween(Word, '\n', '\r');
+ if (!Mask) {
+ Buf += sizeof(Word);
+ continue;
+ }
- // At that point, Mask contains 0x80 set at each byte that holds a value
- // in [\n, \r + 1 [
+ // At that point, Mask contains 0x80 set at each byte that holds a value
+ // in [\n, \r + 1 [
+
+ // Scan for the next newline - it's very likely there's one.
+ unsigned N =
+ llvm::countr_zero(Mask) - 7; // -7 because 0x80 is the marker
+ Word >>= N;
+ Buf += N / 8 + 1;
+ unsigned char Byte = Word;
+ switch (Byte) {
+ case '\r':
+ // If this is \r\n, skip both characters.
+ if (*Buf == '\n') {
+ ++Buf;
+ }
+ [[fallthrough]];
+ case '\n':
+ LineOffsets.push_back(Buf - Start);
+ };
+ } while (Buf < End - sizeof(Word) - 1);
+ }
- // Scan for the next newline - it's very likely there's one.
- unsigned N = llvm::countr_zero(Mask) - 7; // -7 because 0x80 is the marker
- Word >>= N;
- Buf += N / 8 + 1;
- unsigned char Byte = Word;
- switch (Byte) {
- case '\r':
+ // Handle tail using a regular check.
+ while (Buf < End) {
+ if (*Buf == '\n') {
+ LineOffsets.push_back(Buf - Start + 1);
+ } else if (*Buf == '\r') {
// If this is \r\n, skip both characters.
- if (*Buf == '\n') {
+ if (Buf + 1 < End && Buf[1] == '\n') {
++Buf;
}
- [[fallthrough]];
- case '\n':
- LineOffsets.push_back(Buf - Start);
- };
- } while (Buf < End - sizeof(Word) - 1);
- }
-
- // Handle tail using a regular check.
- while (Buf < End) {
- if (*Buf == '\n') {
- LineOffsets.push_back(Buf - Start + 1);
- } else if (*Buf == '\r') {
- // If this is \r\n, skip both characters.
- if (Buf + 1 < End && Buf[1] == '\n') {
- ++Buf;
+ LineOffsets.push_back(Buf - Start + 1);
}
- LineOffsets.push_back(Buf - Start + 1);
+ ++Buf;
}
- ++Buf;
- }
-
- return LineOffsetMapping(LineOffsets, Alloc);
-}
-LineOffsetMapping::LineOffsetMapping(ArrayRef<unsigned> LineOffsets,
- llvm::BumpPtrAllocator &Alloc)
- : Storage(Alloc.Allocate<unsigned>(LineOffsets.size() + 1)) {
- Storage[0] = LineOffsets.size();
- std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
-}
+ return LineOffsetMapping(LineOffsets, Alloc);
+ }
-/// 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 SourceManager::getLineNumber(FileID FID, unsigned FilePos,
- bool *Invalid) const {
- if (FID.isInvalid()) {
- if (Invalid)
- *Invalid = true;
- return 1;
+ LineOffsetMapping::LineOffsetMapping(ArrayRef<unsigned> LineOffsets,
+ llvm::BumpPtrAllocator & Alloc)
+ : Storage(Alloc.Allocate<unsigned>(LineOffsets.size() + 1)) {
+ Storage[0] = LineOffsets.size();
+ std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
}
- const ContentCache *Content;
- if (LastLineNoFileIDQuery == FID)
- Content = LastLineNoContentCache;
- else {
- bool MyInvalid = false;
- const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
- if (MyInvalid || !Entry.isFile()) {
+ /// 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 SourceManager::getLineNumber(FileID FID, unsigned FilePos,
+ bool *Invalid) const {
+ if (FID.isInvalid()) {
if (Invalid)
*Invalid = true;
return 1;
}
- Content = &Entry.getFile().getContentCache();
- }
-
- // If this is the first use of line information for this buffer, compute the
- // SourceLineCache for it on demand.
- if (!Content->SourceLineCache) {
- std::optional<llvm::MemoryBufferRef> Buffer =
- Content->getBufferOrNone(Diag, getFileManager(), SourceLocation());
- if (Invalid)
- *Invalid = !Buffer;
- if (!Buffer)
- return 1;
-
- Content->SourceLineCache =
- LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
- } else if (Invalid)
- *Invalid = false;
-
- // Okay, we know we have a line number table. Do a binary search to find the
- // line number that this character position lands on.
- const unsigned *SourceLineCache = Content->SourceLineCache.begin();
- const unsigned *SourceLineCacheStart = SourceLineCache;
- const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end();
+ const ContentCache *Content;
+ if (LastLineNoFileIDQuery == FID)
+ Content = LastLineNoContentCache;
+ else {
+ bool MyInvalid = false;
+ const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
+ if (MyInvalid || !Entry.isFile()) {
+ if (Invalid)
+ *Invalid = true;
+ return 1;
+ }
- unsigned QueriedFilePos = FilePos+1;
+ Content = &Entry.getFile().getContentCache();
+ }
- // FIXME: I would like to be convinced that this code is worth being as
- // complicated as it is, binary search isn't that slow.
- //
- // If it is worth being optimized, then in my opinion it could be more
- // performant, simpler, and more obviously correct by just "galloping" outward
- // from the queried file position. In fact, this could be incorporated into a
- // generic algorithm such as lower_bound_with_hint.
- //
- // If someone gives me a test case where this matters, and I will do it! - DWD
-
- // If the previous query was to the same file, we know both the file pos from
- // that query and the line number returned. This allows us to narrow the
- // search space from the entire file to something near the match.
- if (LastLineNoFileIDQuery == FID) {
- if (QueriedFilePos >= LastLineNoFilePos) {
- // FIXME: Potential overflow?
- SourceLineCache = SourceLineCache+LastLineNoResult-1;
-
- // The query is likely to be nearby the previous one. Here we check to
- // see if it is within 5, 10 or 20 lines. It can be far away in cases
- // where big comment blocks and vertical whitespace eat up lines but
- // contribute no tokens.
- if (SourceLineCache+5 < SourceLineCacheEnd) {
- if (SourceLineCache[5] > QueriedFilePos)
- SourceLineCacheEnd = SourceLineCache+5;
- else if (SourceLineCache+10 < SourceLineCacheEnd) {
- if (SourceLineCache[10] > QueriedFilePos)
- SourceLineCacheEnd = SourceLineCache+10;
- else if (SourceLineCache+20 < SourceLineCacheEnd) {
- if (SourceLineCache[20] > QueriedFilePos)
- SourceLineCacheEnd = SourceLineCache+20;
+ // If this is the first use of line information for this buffer, compute the
+ // SourceLineCache for it on demand.
+ if (!Content->SourceLineCache) {
+ std::optional<llvm::MemoryBufferRef> Buffer =
+ Content->getBufferOrNone(Diag, getFileManager(), SourceLocation());
+ if (Invalid)
+ *Invalid = !Buffer;
+ if (!Buffer)
+ return 1;
+
+ Content->SourceLineCache =
+ LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
+ } else if (Invalid)
+ *Invalid = false;
+
+ // Okay, we know we have a line number table. Do a binary search to find
+ // the line number that this character position lands on.
+ const unsigned *SourceLineCache = Content->SourceLineCache.begin();
+ const unsigned *SourceLineCacheStart = SourceLineCache;
+ const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end();
+
+ unsigned QueriedFilePos = FilePos + 1;
+
+ // FIXME: I would like to be convinced that this code is worth being as
+ // complicated as it is, binary search isn't that slow.
+ //
+ // If it is worth being optimized, then in my opinion it could be more
+ // performant, simpler, and more obviously correct by just "galloping"
+ // outward from the queried file position. In fact, this could be
+ // incorporated into a generic algorithm such as lower_bound_with_hint.
+ //
+ // If someone gives me a test case where this matters, and I will do it! -
+ // DWD
+
+ // If the previous query was to the same file, we know both the file pos
+ // from that query and the line number returned. This allows us to narrow
+ // the search space from the entire file to something near the match.
+ if (LastLineNoFileIDQuery == FID) {
+ if (QueriedFilePos >= LastLineNoFilePos) {
+ // FIXME: Potential overflow?
+ SourceLineCache = SourceLineCache + LastLineNoResult - 1;
+
+ // The query is likely to be nearby the previous one. Here we check to
+ // see if it is within 5, 10 or 20 lines. It can be far away in cases
+ // where big comment blocks and vertical whitespace eat up lines but
+ // contribute no tokens.
+ if (SourceLineCache + 5 < SourceLineCacheEnd) {
+ if (SourceLineCache[5] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache + 5;
+ else if (SourceLineCache + 10 < SourceLineCacheEnd) {
+ if (SourceLineCache[10] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache + 10;
+ else if (SourceLineCache + 20 < SourceLineCacheEnd) {
+ if (SourceLineCache[20] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache + 20;
+ }
}
}
+ } else {
+ if (LastLineNoResult < Content->SourceLineCache.size())
+ SourceLineCacheEnd = SourceLineCache + LastLineNoResult + 1;
}
- } else {
- if (LastLineNoResult < Content->SourceLineCache.size())
- SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
}
- }
- const unsigned *Pos =
- std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
- unsigned LineNo = Pos-SourceLineCacheStart;
+ const unsigned *Pos =
+ std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
+ unsigned LineNo = Pos - SourceLineCacheStart;
- LastLineNoFileIDQuery = FID;
- LastLineNoContentCache = Content;
- LastLineNoFilePos = QueriedFilePos;
- LastLineNoResult = LineNo;
- return LineNo;
-}
-
-unsigned SourceManager::getLineNumber(SourceLocation Loc, bool *Invalid) const {
- assert(Loc.isFileID());
- if (isInvalid(Loc, Invalid)) return 0;
- FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
- return getLineNumber(LocInfo.first, LocInfo.second);
-}
+ LastLineNoFileIDQuery = FID;
+ LastLineNoContentCache = Content;
+ LastLineNoFilePos = QueriedFilePos;
+ LastLineNoResult = LineNo;
+ return LineNo;
+ }
-unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc,
- bool *Invalid) const {
- PresumedLoc PLoc = getPresumedLoc(Loc);
- if (isInvalid(PLoc, Invalid)) return 0;
- return PLoc.getLine();
-}
+ unsigned SourceManager::getLineNumber(SourceLocation Loc, bool *Invalid)
+ const {
+ assert(Loc.isFileID());
+ if (isInvalid(Loc, Invalid))
+ return 0;
+ FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
+ return getLineNumber(LocInfo.first, LocInfo.second);
+ }
-/// 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
-SourceManager::getFileCharacteristic(SourceLocation Loc) const {
- assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");
- FileIDAndOffset LocInfo = getDecomposedExpansionLoc(Loc);
- const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
- if (!SEntry)
- return C_User;
+ unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ PresumedLoc PLoc = getPresumedLoc(Loc);
+ if (isInvalid(PLoc, Invalid))
+ return 0;
+ return PLoc.getLine();
+ }
- const SrcMgr::FileInfo &FI = SEntry->getFile();
+ /// 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 SourceManager::getFileCharacteristic(
+ SourceLocation Loc) const {
+ assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");
+ FileIDAndOffset LocInfo = getDecomposedExpansionLoc(Loc);
+ const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
+ if (!SEntry)
+ return C_User;
+
+ const SrcMgr::FileInfo &FI = SEntry->getFile();
+
+ // If there are no #line directives in this file, just return the whole-file
+ // state.
+ if (!FI.hasLineDirectives())
+ return FI.getFileCharacteristic();
- // If there are no #line directives in this file, just return the whole-file
- // state.
- if (!FI.hasLineDirectives())
- return FI.getFileCharacteristic();
+ assert(LineTable && "Can't have linetable entries without a LineTable!");
+ // See if there is a #line directive before the location.
+ const LineEntry *Entry =
+ LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
- assert(LineTable && "Can't have linetable entries without a LineTable!");
- // See if there is a #line directive before the location.
- const LineEntry *Entry =
- LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
+ // If this is before the first line marker, use the file characteristic.
+ if (!Entry)
+ return FI.getFileCharacteristic();
- // If this is before the first line marker, use the file characteristic.
- if (!Entry)
- return FI.getFileCharacteristic();
+ return Entry->FileKind;
+ }
- return Entry->FileKind;
-}
+ /// 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.
+ StringRef SourceManager::getBufferName(SourceLocation Loc, bool *Invalid)
+ const {
+ if (isInvalid(Loc, Invalid))
+ return "<invalid loc>";
-/// 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.
-StringRef SourceManager::getBufferName(SourceLocation Loc,
- bool *Invalid) const {
- if (isInvalid(Loc, Invalid)) return "<invalid loc>";
-
- auto B = getBufferOrNone(getFileID(Loc));
- if (Invalid)
- *Invalid = !B;
- return B ? B->getBufferIdentifier() : "<invalid buffer>";
-}
+ auto B = getBufferOrNone(getFileID(Loc));
+ if (Invalid)
+ *Invalid = !B;
+ return B ? B->getBufferIdentifier() : "<invalid buffer>";
+ }
-/// 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.
-PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
- bool UseLineDirectives) const {
- if (Loc.isInvalid()) return PresumedLoc();
-
- // Presumed locations are always for expansion points.
- FileIDAndOffset LocInfo = getDecomposedExpansionLoc(Loc);
+ /// 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.
+ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
+ bool UseLineDirectives) const {
+ if (Loc.isInvalid())
+ return PresumedLoc();
+
+ // Presumed locations are always for expansion points.
+ FileIDAndOffset LocInfo = getDecomposedExpansionLoc(Loc);
- bool Invalid = false;
- const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
- if (Invalid || !Entry.isFile())
- return PresumedLoc();
-
- const SrcMgr::FileInfo &FI = Entry.getFile();
- const SrcMgr::ContentCache *C = &FI.getContentCache();
-
- // To get the source name, first consult the FileEntry (if one exists)
- // before the MemBuffer as this will avoid unnecessarily paging in the
- // MemBuffer.
- FileID FID = LocInfo.first;
- StringRef Filename;
- if (C->OrigEntry)
- Filename = C->OrigEntry->getName();
- else if (auto Buffer = C->getBufferOrNone(Diag, getFileManager()))
- Filename = Buffer->getBufferIdentifier();
-
- unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
- if (Invalid)
- return PresumedLoc();
- unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
- if (Invalid)
- return PresumedLoc();
-
- SourceLocation IncludeLoc = FI.getIncludeLoc();
-
- // If we have #line directives in this file, update and overwrite the physical
- // location info if appropriate.
- if (UseLineDirectives && FI.hasLineDirectives()) {
- assert(LineTable && "Can't have linetable entries without a LineTable!");
- // See if there is a #line directive before this. If so, get it.
- if (const LineEntry *Entry =
- LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
- // If the LineEntry indicates a filename, use it.
- if (Entry->FilenameID != -1) {
- Filename = LineTable->getFilename(Entry->FilenameID);
- // The contents of files referenced by #line are not in the
- // SourceManager
- FID = FileID::get(0);
- }
+ bool Invalid = false;
+ const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return PresumedLoc();
+
+ const SrcMgr::FileInfo &FI = Entry.getFile();
+ const SrcMgr::ContentCache *C = &FI.getContentCache();
+
+ // To get the source name, first consult the FileEntry (if one exists)
+ // before the MemBuffer as this will avoid unnecessarily paging in the
+ // MemBuffer.
+ FileID FID = LocInfo.first;
+ StringRef Filename;
+ if (C->OrigEntry)
+ Filename = C->OrigEntry->getName();
+ else if (auto Buffer = C->getBufferOrNone(Diag, getFileManager()))
+ Filename = Buffer->getBufferIdentifier();
+
+ unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
+ if (Invalid)
+ return PresumedLoc();
+ unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
+ if (Invalid)
+ return PresumedLoc();
+
+ SourceLocation IncludeLoc = FI.getIncludeLoc();
+
+ // If we have #line directives in this file, update and overwrite the
+ // physical location info if appropriate.
+ if (UseLineDirectives && FI.hasLineDirectives()) {
+ assert(LineTable && "Can't have linetable entries without a LineTable!");
+ // See if there is a #line directive before this. If so, get it.
+ if (const LineEntry *Entry =
+ LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
+ // If the LineEntry indicates a filename, use it.
+ if (Entry->FilenameID != -1) {
+ Filename = LineTable->getFilename(Entry->FilenameID);
+ // The contents of files referenced by #line are not in the
+ // SourceManager
+ FID = FileID::get(0);
+ }
- // Use the line number specified by the LineEntry. This line number may
- // be multiple lines down from the line entry. Add the difference in
- // physical line numbers from the query point and the line marker to the
- // total.
- unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
- LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
+ // Use the line number specified by the LineEntry. This line number may
+ // be multiple lines down from the line entry. Add the difference in
+ // physical line numbers from the query point and the line marker to the
+ // total.
+ unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
+ LineNo = Entry->LineNo + (LineNo - MarkerLineNo - 1);
- // Note that column numbers are not molested by line markers.
+ // Note that column numbers are not molested by line markers.
- // Handle virtual #include manipulation.
- if (Entry->IncludeOffset) {
- IncludeLoc = getLocForStartOfFile(LocInfo.first);
- IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset);
+ // Handle virtual #include manipulation.
+ if (Entry->IncludeOffset) {
+ IncludeLoc = getLocForStartOfFile(LocInfo.first);
+ IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset);
+ }
}
}
- }
-
- return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
-}
-
-/// Returns whether the PresumedLoc for a given SourceLocation is
-/// in the main file.
-///
-/// This computes the "presumed" location for a SourceLocation, then checks
-/// whether it came from a file other than the main file. This is different
-/// from isWrittenInMainFile() because it takes line marker directives into
-/// account.
-bool SourceManager::isInMainFile(SourceLocation Loc) const {
- if (Loc.isInvalid()) return false;
-
- // Presumed locations are always for expansion points.
- FileIDAndOffset LocInfo = getDecomposedExpansionLoc(Loc);
-
- const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
- if (!Entry)
- return false;
-
- const SrcMgr::FileInfo &FI = Entry->getFile();
- // Check if there is a line directive for this location.
- if (FI.hasLineDirectives())
- if (const LineEntry *Entry =
- LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
- if (Entry->IncludeOffset)
- return false;
+ return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
+ }
- return FI.getIncludeLoc().isInvalid();
-}
+ /// Returns whether the PresumedLoc for a given SourceLocation is
+ /// in the main file.
+ ///
+ /// This computes the "presumed" location for a SourceLocation, then checks
+ /// whether it came from a file other than the main file. This is different
+ /// from isWrittenInMainFile() because it takes line marker directives into
+ /// account.
+ bool SourceManager::isInMainFile(SourceLocation Loc) const {
+ if (Loc.isInvalid())
+ return false;
-/// The size of the SLocEntry that \p FID represents.
-unsigned SourceManager::getFileIDSize(FileID FID) const {
- bool Invalid = false;
- const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
- if (Invalid)
- return 0;
+ // Presumed locations are always for expansion points.
+ FileIDAndOffset LocInfo = getDecomposedExpansionLoc(Loc);
- int ID = FID.ID;
- SourceLocation::UIntTy NextOffset;
- if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size()))
- NextOffset = getNextLocalOffset();
- else if (ID+1 == -1)
- NextOffset = MaxLoadedOffset;
- else
- NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
-
- return NextOffset - Entry.getOffset() - 1;
-}
+ const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
+ if (!Entry)
+ return false;
-//===----------------------------------------------------------------------===//
-// Other miscellaneous methods.
-//===----------------------------------------------------------------------===//
+ const SrcMgr::FileInfo &FI = Entry->getFile();
-/// 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 an arbitrary inclusion.
-SourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile,
- unsigned Line,
- unsigned Col) const {
- assert(SourceFile && "Null source file!");
- assert(Line && Col && "Line and column should start from 1!");
-
- FileID FirstFID = translateFile(SourceFile);
- return translateLineCol(FirstFID, Line, Col);
-}
+ // Check if there is a line directive for this location.
+ if (FI.hasLineDirectives())
+ if (const LineEntry *Entry =
+ LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
+ if (Entry->IncludeOffset)
+ return false;
-/// Get the FileID for the given file.
-///
-/// If the source file is included multiple times, the FileID will be the
-/// first inclusion.
-FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
- assert(SourceFile && "Null source file!");
+ return FI.getIncludeLoc().isInvalid();
+ }
- // First, check the main file ID, since it is common to look for a
- // location in the main file.
- if (MainFileID.isValid()) {
+ /// The size of the SLocEntry that \p FID represents.
+ unsigned SourceManager::getFileIDSize(FileID FID) const {
bool Invalid = false;
- const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
if (Invalid)
- return FileID();
+ return 0;
+
+ int ID = FID.ID;
+ SourceLocation::UIntTy NextOffset;
+ if ((ID > 0 && unsigned(ID + 1) == local_sloc_entry_size()))
+ NextOffset = getNextLocalOffset();
+ else if (ID + 1 == -1)
+ NextOffset = MaxLoadedOffset;
+ else
+ NextOffset = getSLocEntry(FileID::get(ID + 1)).getOffset();
- if (MainSLoc.isFile()) {
- if (MainSLoc.getFile().getContentCache().OrigEntry == SourceFile)
- return MainFileID;
- }
+ return NextOffset - Entry.getOffset() - 1;
}
- // The location we're looking for isn't in the main file; look
- // through all of the local source locations.
- for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
- const SLocEntry &SLoc = getLocalSLocEntry(I);
- if (SLoc.isFile() &&
- SLoc.getFile().getContentCache().OrigEntry == SourceFile)
- return FileID::get(I);
+ //===----------------------------------------------------------------------===//
+ // Other miscellaneous methods.
+ //===----------------------------------------------------------------------===//
+
+ /// 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 an arbitrary inclusion.
+ SourceLocation SourceManager::translateFileLineCol(
+ const FileEntry *SourceFile, unsigned Line, unsigned Col) const {
+ assert(SourceFile && "Null source file!");
+ assert(Line && Col && "Line and column should start from 1!");
+
+ FileID FirstFID = translateFile(SourceFile);
+ return translateLineCol(FirstFID, Line, Col);
}
- // If that still didn't help, try the modules.
- for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
- const SLocEntry &SLoc = getLoadedSLocEntry(I);
- if (SLoc.isFile() &&
- SLoc.getFile().getContentCache().OrigEntry == SourceFile)
- return FileID::get(-int(I) - 2);
- }
+ /// Get the FileID for the given file.
+ ///
+ /// If the source file is included multiple times, the FileID will be the
+ /// first inclusion.
+ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
+ assert(SourceFile && "Null source file!");
+
+ // First, check the main file ID, since it is common to look for a
+ // location in the main file.
+ if (MainFileID.isValid()) {
+ bool Invalid = false;
+ const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);
+ if (Invalid)
+ return FileID();
- return FileID();
-}
+ if (MainSLoc.isFile()) {
+ if (MainSLoc.getFile().getContentCache().OrigEntry == SourceFile)
+ return MainFileID;
+ }
+ }
-/// Get the source location in \arg FID for the given line:col.
-/// Returns null location if \arg FID is not a file SLocEntry.
-SourceLocation SourceManager::translateLineCol(FileID FID,
- unsigned Line,
- unsigned Col) const {
- // Lines are used as a one-based index into a zero-based array. This assert
- // checks for possible buffer underruns.
- assert(Line && Col && "Line and column should start from 1!");
+ // The location we're looking for isn't in the main file; look
+ // through all of the local source locations.
+ for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
+ const SLocEntry &SLoc = getLocalSLocEntry(I);
+ if (SLoc.isFile() &&
+ SLoc.getFile().getContentCache().OrigEntry == SourceFile)
+ return FileID::get(I);
+ }
- if (FID.isInvalid())
- return SourceLocation();
+ // If that still didn't help, try the modules.
+ for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
+ const SLocEntry &SLoc = getLoadedSLocEntry(I);
+ if (SLoc.isFile() &&
+ SLoc.getFile().getContentCache().OrigEntry == SourceFile)
+ return FileID::get(-int(I) - 2);
+ }
- bool Invalid = false;
- const SLocEntry &Entry = getSLocEntry(FID, &Invalid);
- if (Invalid)
- return SourceLocation();
+ return FileID();
+ }
- if (!Entry.isFile())
- return SourceLocation();
+ /// Get the source location in \arg FID for the given line:col.
+ /// Returns null location if \arg FID is not a file SLocEntry.
+ SourceLocation SourceManager::translateLineCol(FileID FID, unsigned Line,
+ unsigned Col) const {
+ // Lines are used as a one-based index into a zero-based array. This assert
+ // checks for possible buffer underruns.
+ assert(Line && Col && "Line and column should start from 1!");
- SourceLocation FileLoc = SourceLocation::getFileLoc(Entry.getOffset());
+ if (FID.isInvalid())
+ return SourceLocation();
- if (Line == 1 && Col == 1)
- return FileLoc;
+ bool Invalid = false;
+ const SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid)
+ return SourceLocation();
- const ContentCache *Content = &Entry.getFile().getContentCache();
+ if (!Entry.isFile())
+ return SourceLocation();
- // If this is the first use of line information for this buffer, compute the
- // SourceLineCache for it on demand.
- std::optional<llvm::MemoryBufferRef> Buffer =
- Content->getBufferOrNone(Diag, getFileManager());
- if (!Buffer)
- return SourceLocation();
- if (!Content->SourceLineCache)
- Content->SourceLineCache =
- LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
+ SourceLocation FileLoc = SourceLocation::getFileLoc(Entry.getOffset());
- if (Line > Content->SourceLineCache.size()) {
- unsigned Size = Buffer->getBufferSize();
- if (Size > 0)
- --Size;
- return FileLoc.getLocWithOffset(Size);
- }
+ if (Line == 1 && Col == 1)
+ return FileLoc;
- unsigned FilePos = Content->SourceLineCache[Line - 1];
- const char *Buf = Buffer->getBufferStart() + FilePos;
- unsigned BufLength = Buffer->getBufferSize() - FilePos;
- if (BufLength == 0)
- return FileLoc.getLocWithOffset(FilePos);
+ const ContentCache *Content = &Entry.getFile().getContentCache();
- unsigned i = 0;
+ // If this is the first use of line information for this buffer, compute the
+ // SourceLineCache for it on demand.
+ std::optional<llvm::MemoryBufferRef> Buffer =
+ Content->getBufferOrNone(Diag, getFileManager());
+ if (!Buffer)
+ return SourceLocation();
+ if (!Content->SourceLineCache)
+ Content->SourceLineCache =
+ LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
+
+ if (Line > Content->SourceLineCache.size()) {
+ unsigned Size = Buffer->getBufferSize();
+ if (Size > 0)
+ --Size;
+ return FileLoc.getLocWithOffset(Size);
+ }
- // Check that the given column is valid.
- while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
- ++i;
- return FileLoc.getLocWithOffset(FilePos + i);
-}
+ unsigned FilePos = Content->SourceLineCache[Line - 1];
+ const char *Buf = Buffer->getBufferStart() + FilePos;
+ unsigned BufLength = Buffer->getBufferSize() - FilePos;
+ if (BufLength == 0)
+ return FileLoc.getLocWithOffset(FilePos);
-/// Compute a map of macro argument chunks to their expanded source
-/// location. Chunks that are not part of a macro argument will map to an
-/// invalid source location. e.g. if a file contains one macro argument at
-/// offset 100 with length 10, this is how the map will be formed:
-/// 0 -> SourceLocation()
-/// 100 -> Expanded macro arg location
-/// 110 -> SourceLocation()
-void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
- FileID FID) const {
- assert(FID.isValid());
+ unsigned i = 0;
- // Initially no macro argument chunk is present.
- MacroArgsCache.try_emplace(0);
+ // Check that the given column is valid.
+ while (i < BufLength - 1 && i < Col - 1 && Buf[i] != '\n' && Buf[i] != '\r')
+ ++i;
+ return FileLoc.getLocWithOffset(FilePos + i);
+ }
- int ID = FID.ID;
- while (true) {
- ++ID;
- // Stop if there are no more FileIDs to check.
- if (ID > 0) {
- if (unsigned(ID) >= local_sloc_entry_size())
+ /// Compute a map of macro argument chunks to their expanded source
+ /// location. Chunks that are not part of a macro argument will map to an
+ /// invalid source location. e.g. if a file contains one macro argument at
+ /// offset 100 with length 10, this is how the map will be formed:
+ /// 0 -> SourceLocation()
+ /// 100 -> Expanded macro arg location
+ /// 110 -> SourceLocation()
+ void SourceManager::computeMacroArgsCache(MacroArgsMap & MacroArgsCache,
+ FileID FID) const {
+ assert(FID.isValid());
+
+ // Initially no macro argument chunk is present.
+ MacroArgsCache.try_emplace(0);
+
+ int ID = FID.ID;
+ while (true) {
+ ++ID;
+ // Stop if there are no more FileIDs to check.
+ if (ID > 0) {
+ if (unsigned(ID) >= local_sloc_entry_size())
+ return;
+ } else if (ID == -1) {
return;
- } else if (ID == -1) {
- return;
- }
+ }
- bool Invalid = false;
- const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid);
- if (Invalid)
- return;
- if (Entry.isFile()) {
- auto& File = Entry.getFile();
- if (File.getFileCharacteristic() == C_User_ModuleMap ||
- File.getFileCharacteristic() == C_System_ModuleMap)
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid);
+ if (Invalid)
+ return;
+ if (Entry.isFile()) {
+ auto &File = Entry.getFile();
+ if (File.getFileCharacteristic() == C_User_ModuleMap ||
+ File.getFileCharacteristic() == C_System_ModuleMap)
+ continue;
+
+ SourceLocation IncludeLoc = File.getIncludeLoc();
+ bool IncludedInFID =
+ (IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) ||
+ // Predefined header doesn't have a valid include location in main
+ // file, but any files created by it should still be skipped when
+ // computing macro args expanded in the main file.
+ (FID == MainFileID && Entry.getFile().getName() == "<built-in>");
+ if (IncludedInFID) {
+ // Skip the files/macros of the #include'd file, we only care about
+ // macros that lexed macro arguments from our file.
+ if (Entry.getFile().NumCreatedFIDs)
+ ID += Entry.getFile().NumCreatedFIDs - 1 /*because of next ++ID*/;
+ continue;
+ }
+ // If file was included but not from FID, there is no more files/macros
+ // that may be "contained" in this file.
+ if (IncludeLoc.isValid())
+ return;
continue;
+ }
- SourceLocation IncludeLoc = File.getIncludeLoc();
- bool IncludedInFID =
- (IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) ||
- // Predefined header doesn't have a valid include location in main
- // file, but any files created by it should still be skipped when
- // computing macro args expanded in the main file.
- (FID == MainFileID && Entry.getFile().getName() == "<built-in>");
- if (IncludedInFID) {
- // Skip the files/macros of the #include'd file, we only care about
- // macros that lexed macro arguments from our file.
- if (Entry.getFile().NumCreatedFIDs)
- ID += Entry.getFile().NumCreatedFIDs - 1 /*because of next ++ID*/;
- continue;
+ const ExpansionInfo &ExpInfo = Entry.getExpansion();
+
+ if (ExpInfo.getExpansionLocStart().isFileID()) {
+ if (!isInFileID(ExpInfo.getExpansionLocStart(), FID))
+ return; // No more files/macros that may be "contained" in this file.
}
- // If file was included but not from FID, there is no more files/macros
- // that may be "contained" in this file.
- if (IncludeLoc.isValid())
- return;
- continue;
- }
- const ExpansionInfo &ExpInfo = Entry.getExpansion();
+ if (!ExpInfo.isMacroArgExpansion())
+ continue;
- if (ExpInfo.getExpansionLocStart().isFileID()) {
- if (!isInFileID(ExpInfo.getExpansionLocStart(), FID))
- return; // No more files/macros that may be "contained" in this file.
+ associateFileChunkWithMacroArgExp(
+ MacroArgsCache, FID, ExpInfo.getSpellingLoc(),
+ SourceLocation::getMacroLoc(Entry.getOffset()),
+ getFileIDSize(FileID::get(ID)));
}
+ }
- if (!ExpInfo.isMacroArgExpansion())
- continue;
+ void SourceManager::associateFileChunkWithMacroArgExp(
+ MacroArgsMap & MacroArgsCache, FileID FID, SourceLocation SpellLoc,
+ SourceLocation ExpansionLoc, unsigned ExpansionLength) const {
+ if (!SpellLoc.isFileID()) {
+ SourceLocation::UIntTy SpellBeginOffs = SpellLoc.getOffset();
+ SourceLocation::UIntTy SpellEndOffs = SpellBeginOffs + ExpansionLength;
+
+ // The spelling range for this macro argument expansion can span multiple
+ // consecutive FileID entries. Go through each entry contained in the
+ // spelling range and if one is itself a macro argument expansion, recurse
+ // and associate the file chunk that it represents.
+
+ // Current FileID in the spelling range.
+ auto [SpellFID, SpellRelativeOffs] = getDecomposedLoc(SpellLoc);
+ while (true) {
+ const SLocEntry &Entry = getSLocEntry(SpellFID);
+ SourceLocation::UIntTy SpellFIDBeginOffs = Entry.getOffset();
+ unsigned SpellFIDSize = getFileIDSize(SpellFID);
+ SourceLocation::UIntTy SpellFIDEndOffs =
+ SpellFIDBeginOffs + SpellFIDSize;
+ const ExpansionInfo &Info = Entry.getExpansion();
+ if (Info.isMacroArgExpansion()) {
+ unsigned CurrSpellLength;
+ if (SpellFIDEndOffs < SpellEndOffs)
+ CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
+ else
+ CurrSpellLength = ExpansionLength;
+ associateFileChunkWithMacroArgExp(
+ MacroArgsCache, FID,
+ Info.getSpellingLoc().getLocWithOffset(SpellRelativeOffs),
+ ExpansionLoc, CurrSpellLength);
+ }
- associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
- ExpInfo.getSpellingLoc(),
- SourceLocation::getMacroLoc(Entry.getOffset()),
- getFileIDSize(FileID::get(ID)));
- }
-}
+ if (SpellFIDEndOffs >= SpellEndOffs)
+ return; // we covered all FileID entries in the spelling range.
-void SourceManager::associateFileChunkWithMacroArgExp(
- MacroArgsMap &MacroArgsCache,
- FileID FID,
- SourceLocation SpellLoc,
- SourceLocation ExpansionLoc,
- unsigned ExpansionLength) const {
- if (!SpellLoc.isFileID()) {
- SourceLocation::UIntTy SpellBeginOffs = SpellLoc.getOffset();
- SourceLocation::UIntTy SpellEndOffs = SpellBeginOffs + ExpansionLength;
-
- // The spelling range for this macro argument expansion can span multiple
- // consecutive FileID entries. Go through each entry contained in the
- // spelling range and if one is itself a macro argument expansion, recurse
- // and associate the file chunk that it represents.
-
- // Current FileID in the spelling range.
- auto [SpellFID, SpellRelativeOffs] = getDecomposedLoc(SpellLoc);
- while (true) {
- const SLocEntry &Entry = getSLocEntry(SpellFID);
- SourceLocation::UIntTy SpellFIDBeginOffs = Entry.getOffset();
- unsigned SpellFIDSize = getFileIDSize(SpellFID);
- SourceLocation::UIntTy SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize;
- const ExpansionInfo &Info = Entry.getExpansion();
- if (Info.isMacroArgExpansion()) {
- unsigned CurrSpellLength;
- if (SpellFIDEndOffs < SpellEndOffs)
- CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
- else
- CurrSpellLength = ExpansionLength;
- associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
- Info.getSpellingLoc().getLocWithOffset(SpellRelativeOffs),
- ExpansionLoc, CurrSpellLength);
+ // Move to the next FileID entry in the spelling range.
+ unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
+ ExpansionLoc = ExpansionLoc.getLocWithOffset(advance);
+ ExpansionLength -= advance;
+ ++SpellFID.ID;
+ SpellRelativeOffs = 0;
}
+ }
- if (SpellFIDEndOffs >= SpellEndOffs)
- return; // we covered all FileID entries in the spelling range.
+ assert(SpellLoc.isFileID());
- // Move to the next FileID entry in the spelling range.
- unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
- ExpansionLoc = ExpansionLoc.getLocWithOffset(advance);
- ExpansionLength -= advance;
- ++SpellFID.ID;
- SpellRelativeOffs = 0;
- }
+ unsigned BeginOffs;
+ if (!isInFileID(SpellLoc, FID, &BeginOffs))
+ return;
+
+ unsigned EndOffs = BeginOffs + ExpansionLength;
+
+ // Add a new chunk for this macro argument. A previous macro argument chunk
+ // may have been lexed again, so e.g. if the map is
+ // 0 -> SourceLocation()
+ // 100 -> Expanded loc #1
+ // 110 -> SourceLocation()
+ // and we found a new macro FileID that lexed from offset 105 with length 3,
+ // the new map will be:
+ // 0 -> SourceLocation()
+ // 100 -> Expanded loc #1
+ // 105 -> Expanded loc #2
+ // 108 -> Expanded loc #1
+ // 110 -> SourceLocation()
+ //
+ // Since re-lexed macro chunks will always be the same size or less of
+ // previous chunks, we only need to find where the ending of the new macro
+ // chunk is mapped to and update the map with new begin/end mappings.
+
+ MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
+ --I;
+ SourceLocation EndOffsMappedLoc = I->second;
+ MacroArgsCache[BeginOffs] = ExpansionLoc;
+ MacroArgsCache[EndOffs] = EndOffsMappedLoc;
}
- assert(SpellLoc.isFileID());
+ void SourceManager::updateSlocUsageStats() const {
+ SourceLocation::UIntTy UsedBytes =
+ NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
+ MaxUsedSLocBytes.updateMax(UsedBytes);
+ }
- unsigned BeginOffs;
- if (!isInFileID(SpellLoc, FID, &BeginOffs))
- return;
+ /// 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 SourceManager::getMacroArgExpandedLocation(SourceLocation Loc)
+ const {
+ if (Loc.isInvalid() || !Loc.isFileID())
+ return Loc;
+
+ auto [FID, Offset] = getDecomposedLoc(Loc);
+ if (FID.isInvalid())
+ return Loc;
+
+ std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
+ if (!MacroArgsCache) {
+ MacroArgsCache = std::make_unique<MacroArgsMap>();
+ computeMacroArgsCache(*MacroArgsCache, FID);
+ }
- unsigned EndOffs = BeginOffs + ExpansionLength;
-
- // Add a new chunk for this macro argument. A previous macro argument chunk
- // may have been lexed again, so e.g. if the map is
- // 0 -> SourceLocation()
- // 100 -> Expanded loc #1
- // 110 -> SourceLocation()
- // and we found a new macro FileID that lexed from offset 105 with length 3,
- // the new map will be:
- // 0 -> SourceLocation()
- // 100 -> Expanded loc #1
- // 105 -> Expanded loc #2
- // 108 -> Expanded loc #1
- // 110 -> SourceLocation()
- //
- // Since re-lexed macro chunks will always be the same size or less of
- // previous chunks, we only need to find where the ending of the new macro
- // chunk is mapped to and update the map with new begin/end mappings.
-
- MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
- --I;
- SourceLocation EndOffsMappedLoc = I->second;
- MacroArgsCache[BeginOffs] = ExpansionLoc;
- MacroArgsCache[EndOffs] = EndOffsMappedLoc;
-}
+ assert(!MacroArgsCache->empty());
+ MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
+ // In case every element in MacroArgsCache is greater than Offset we can't
+ // decrement the iterator.
+ if (I == MacroArgsCache->begin())
+ return Loc;
-void SourceManager::updateSlocUsageStats() const {
- SourceLocation::UIntTy UsedBytes =
- NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
- MaxUsedSLocBytes.updateMax(UsedBytes);
-}
+ --I;
-/// 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
-SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const {
- if (Loc.isInvalid() || !Loc.isFileID())
- return Loc;
+ SourceLocation::UIntTy MacroArgBeginOffs = I->first;
+ SourceLocation MacroArgExpandedLoc = I->second;
+ if (MacroArgExpandedLoc.isValid())
+ return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);
- auto [FID, Offset] = getDecomposedLoc(Loc);
- if (FID.isInvalid())
return Loc;
-
- std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
- if (!MacroArgsCache) {
- MacroArgsCache = std::make_unique<MacroArgsMap>();
- computeMacroArgsCache(*MacroArgsCache, FID);
}
- assert(!MacroArgsCache->empty());
- MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
- // In case every element in MacroArgsCache is greater than Offset we can't
- // decrement the iterator.
- if (I == MacroArgsCache->begin())
- return Loc;
-
- --I;
+ FileIDAndOffset SourceManager::getDecomposedIncludedLoc(FileID FID) const {
+ if (FID.isInvalid())
+ return std::make_pair(FileID(), 0);
- SourceLocation::UIntTy MacroArgBeginOffs = I->first;
- SourceLocation MacroArgExpandedLoc = I->second;
- if (MacroArgExpandedLoc.isValid())
- return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);
+ // Uses IncludedLocMap to retrieve/cache the decomposed loc.
- return Loc;
-}
+ using DecompTy = FileIDAndOffset;
+ auto InsertOp = IncludedLocMap.try_emplace(FID);
+ DecompTy &DecompLoc = InsertOp.first->second;
+ if (!InsertOp.second)
+ return DecompLoc; // already in map.
-FileIDAndOffset SourceManager::getDecomposedIncludedLoc(FileID FID) const {
- if (FID.isInvalid())
- return std::make_pair(FileID(), 0);
+ SourceLocation UpperLoc;
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (!Invalid) {
+ if (Entry.isExpansion())
+ UpperLoc = Entry.getExpansion().getExpansionLocStart();
+ else
+ UpperLoc = Entry.getFile().getIncludeLoc();
+ }
- // Uses IncludedLocMap to retrieve/cache the decomposed loc.
+ if (UpperLoc.isValid())
+ DecompLoc = getDecomposedLoc(UpperLoc);
- using DecompTy = FileIDAndOffset;
- auto InsertOp = IncludedLocMap.try_emplace(FID);
- DecompTy &DecompLoc = InsertOp.first->second;
- if (!InsertOp.second)
- return DecompLoc; // already in map.
+ return DecompLoc;
+ }
- SourceLocation UpperLoc;
- bool Invalid = false;
- const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
- if (!Invalid) {
- if (Entry.isExpansion())
- UpperLoc = Entry.getExpansion().getExpansionLocStart();
- else
- UpperLoc = Entry.getFile().getIncludeLoc();
+ FileID SourceManager::getUniqueLoadedASTFileID(SourceLocation Loc) const {
+ assert(isLoadedSourceLocation(Loc) &&
+ "Must be a source location in a loaded PCH/Module file");
+
+ auto [FID, Ignore] = getDecomposedLoc(Loc);
+ // `LoadedSLocEntryAllocBegin` stores the sorted lowest FID of each loaded
+ // allocation. Later allocations have lower FileIDs. The call below is to
+ // find the lowest FID of a loaded allocation from any FID in the same
+ // allocation. The lowest FID is used to identify a loaded allocation.
+ const FileID *FirstFID = llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
+ std::greater<FileID>{});
+
+ assert(FirstFID &&
+ "The failure to find the first FileID of a "
+ "loaded AST from a loaded source location was unexpected.");
+ return *FirstFID;
}
- if (UpperLoc.isValid())
- DecompLoc = getDecomposedLoc(UpperLoc);
+ bool SourceManager::isInTheSameTranslationUnitImpl(
+ const FileIDAndOffset &LOffs, const FileIDAndOffset &ROffs) const {
+ // If one is local while the other is loaded.
+ if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))
+ return false;
- return DecompLoc;
-}
+ if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {
+ auto FindSLocEntryAlloc = [this](FileID FID) {
+ // Loaded FileIDs are negative, we store the lowest FileID from each
+ // allocation, later allocations have lower FileIDs.
+ return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
+ std::greater<FileID>{});
+ };
-FileID SourceManager::getUniqueLoadedASTFileID(SourceLocation Loc) const {
- assert(isLoadedSourceLocation(Loc) &&
- "Must be a source location in a loaded PCH/Module file");
-
- auto [FID, Ignore] = getDecomposedLoc(Loc);
- // `LoadedSLocEntryAllocBegin` stores the sorted lowest FID of each loaded
- // allocation. Later allocations have lower FileIDs. The call below is to find
- // the lowest FID of a loaded allocation from any FID in the same allocation.
- // The lowest FID is used to identify a loaded allocation.
- const FileID *FirstFID =
- llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater<FileID>{});
-
- assert(FirstFID &&
- "The failure to find the first FileID of a "
- "loaded AST from a loaded source location was unexpected.");
- return *FirstFID;
-}
+ // If both are loaded from different AST files.
+ if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
+ return false;
+ }
-bool SourceManager::isInTheSameTranslationUnitImpl(
- const FileIDAndOffset &LOffs, const FileIDAndOffset &ROffs) const {
- // If one is local while the other is loaded.
- if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))
+ return true;
+ }
+
+ /// Given a decomposed source location, move it up the include/expansion stack
+ /// to the parent source location within the same translation unit. If this
+ /// is possible, return the decomposed version of the parent in Loc and return
+ /// false. If Loc is a top-level entry, return true and don't modify it.
+ static bool MoveUpTranslationUnitIncludeHierarchy(FileIDAndOffset & Loc,
+ const SourceManager &SM) {
+ FileIDAndOffset UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);
+ if (UpperLoc.first.isInvalid() ||
+ !SM.isInTheSameTranslationUnitImpl(UpperLoc, Loc))
+ return true; // We reached the top.
+
+ Loc = UpperLoc;
return false;
+ }
- if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {
- auto FindSLocEntryAlloc = [this](FileID FID) {
- // Loaded FileIDs are negative, we store the lowest FileID from each
- // allocation, later allocations have lower FileIDs.
- return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
- std::greater<FileID>{});
- };
+ /// Return the cache entry for comparing the given file IDs
+ /// for isBeforeInTranslationUnit.
+ InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(
+ FileID LFID, FileID RFID) const {
+ // This is a magic number for limiting the cache size. It was
+ // experimentally derived from a small Objective-C project (where the cache
+ // filled out to ~250 items). We can make it larger if necessary.
+ // FIXME: this is almost certainly full these days. Use an LRU cache?
+ enum { MagicCacheSize = 300 };
+ IsBeforeInTUCacheKey Key(LFID, RFID);
+
+ // If the cache size isn't too large, do a lookup and if necessary default
+ // construct an entry. We can then return it to the caller for direct
+ // use. When they update the value, the cache will get automatically
+ // updated as well.
+ if (IBTUCache.size() < MagicCacheSize)
+ return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
+
+ // Otherwise, do a lookup that will not construct a new value.
+ InBeforeInTUCache::iterator I = IBTUCache.find(Key);
+ if (I != IBTUCache.end())
+ return I->second;
+
+ // Fall back to the overflow value.
+ IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
+ return IBTUCacheOverflow;
+ }
- // If both are loaded from different AST files.
- if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
+ /// Determines the order of 2 source locations in the translation unit.
+ ///
+ /// \returns true if LHS source location comes before RHS, false otherwise.
+ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
+ SourceLocation RHS) const {
+ assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");
+ if (LHS == RHS)
return false;
+
+ FileIDAndOffset LOffs = getDecomposedLoc(LHS);
+ FileIDAndOffset ROffs = getDecomposedLoc(RHS);
+
+ // getDecomposedLoc may have failed to return a valid FileID because, e.g.
+ // it is a serialized one referring to a file that was removed after we
+ // loaded the PCH.
+ if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
+ return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
+
+ std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
+ if (InSameTU.first)
+ return InSameTU.second;
+ // This case is used by libclang: clang_isBeforeInTranslationUnit
+ return LOffs.first < ROffs.first;
}
- return true;
-}
+ std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
+ FileIDAndOffset & LOffs, FileIDAndOffset & ROffs) const {
+ // If the source locations are not in the same TU, return early.
+ if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))
+ return std::make_pair(false, false);
-/// Given a decomposed source location, move it up the include/expansion stack
-/// to the parent source location within the same translation unit. If this is
-/// possible, return the decomposed version of the parent in Loc and return
-/// false. If Loc is a top-level entry, return true and don't modify it.
-static bool MoveUpTranslationUnitIncludeHierarchy(FileIDAndOffset &Loc,
- const SourceManager &SM) {
- FileIDAndOffset UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);
- if (UpperLoc.first.isInvalid() ||
- !SM.isInTheSameTranslationUnitImpl(UpperLoc, Loc))
- return true; // We reached the top.
-
- Loc = UpperLoc;
- return false;
-}
+ // If the source locations are in the same file, just compare offsets.
+ if (LOffs.first == ROffs.first)
+ return std::make_pair(true, LOffs.second < ROffs.second);
-/// Return the cache entry for comparing the given file IDs
-/// for isBeforeInTranslationUnit.
-InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
- FileID RFID) const {
- // This is a magic number for limiting the cache size. It was experimentally
- // derived from a small Objective-C project (where the cache filled
- // out to ~250 items). We can make it larger if necessary.
- // FIXME: this is almost certainly full these days. Use an LRU cache?
- enum { MagicCacheSize = 300 };
- IsBeforeInTUCacheKey Key(LFID, RFID);
-
- // If the cache size isn't too large, do a lookup and if necessary default
- // construct an entry. We can then return it to the caller for direct
- // use. When they update the value, the cache will get automatically
- // updated as well.
- if (IBTUCache.size() < MagicCacheSize)
- return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
-
- // Otherwise, do a lookup that will not construct a new value.
- InBeforeInTUCache::iterator I = IBTUCache.find(Key);
- if (I != IBTUCache.end())
- return I->second;
-
- // Fall back to the overflow value.
- IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
- return IBTUCacheOverflow;
-}
+ // If we are comparing a source location with multiple locations in the same
+ // file, we get a big win by caching the result.
+ InBeforeInTUCacheEntry &IsBeforeInTUCache =
+ getInBeforeInTUCache(LOffs.first, ROffs.first);
-/// Determines the order of 2 source locations in the translation unit.
-///
-/// \returns true if LHS source location comes before RHS, false otherwise.
-bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
- SourceLocation RHS) const {
- assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");
- if (LHS == RHS)
- return false;
+ // If we are comparing a source location with multiple locations in the same
+ // file, we get a big win by caching the result.
+ if (IsBeforeInTUCache.isCacheValid())
+ return std::make_pair(
+ true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
- FileIDAndOffset LOffs = getDecomposedLoc(LHS);
- FileIDAndOffset ROffs = getDecomposedLoc(RHS);
+ // Okay, we missed in the cache, we'll compute the answer and populate it.
+ // We need to find the common ancestor. The only way of doing this is to
+ // build the complete include chain for one and then walking up the chain
+ // of the other looking for a match.
- // getDecomposedLoc may have failed to return a valid FileID because, e.g. it
- // is a serialized one referring to a file that was removed after we loaded
- // the PCH.
- if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
- return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
+ // A location within a FileID on the path up from LOffs to the main file.
+ struct Entry {
+ FileIDAndOffset DecomposedLoc; // FileID redundant, but clearer.
+ FileID ChildFID; // Used for breaking ties. Invalid for the initial loc.
+ };
+ llvm::SmallDenseMap<FileID, Entry, 16> LChain;
- std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
- if (InSameTU.first)
- return InSameTU.second;
- // This case is used by libclang: clang_isBeforeInTranslationUnit
- return LOffs.first < ROffs.first;
-}
+ FileID LChild;
+ do {
+ LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
+ // We catch the case where LOffs is in a file included by ROffs and
+ // quit early. The other way round unfortunately remains suboptimal.
+ if (LOffs.first == ROffs.first)
+ break;
+ LChild = LOffs.first;
+ } while (!MoveUpTranslationUnitIncludeHierarchy(LOffs, *this));
+
+ FileID RChild;
+ do {
+ auto LIt = LChain.find(ROffs.first);
+ if (LIt != LChain.end()) {
+ // Compare the locations within the common file and cache them.
+ LOffs = LIt->second.DecomposedLoc;
+ LChild = LIt->second.ChildFID;
+ // The relative order of LChild and RChild is a tiebreaker when
+ // - locs expand to the same location (occurs in macro arg expansion)
+ // - one loc is a parent of the other (we consider the parent as
+ // "first") For the parent entry to be first, its invalid child file ID
+ // must compare smaller to the valid child file ID of the other entry.
+ // However loaded FileIDs are <0, so we perform *unsigned* comparison!
+ // This changes the relative order of local vs loaded FileIDs, but it
+ // doesn't matter as these are never mixed in macro expansion.
+ unsigned LChildID = LChild.ID;
+ unsigned RChildID = RChild.ID;
+ assert(((LOffs.second != ROffs.second) ||
+ (LChildID == 0 || RChildID == 0) ||
+ isInSameSLocAddrSpace(getComposedLoc(LChild, 0),
+ getComposedLoc(RChild, 0), nullptr)) &&
+ "Mixed local/loaded FileIDs with same include location?");
+ IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
+ LChildID < RChildID);
+ return std::make_pair(true, IsBeforeInTUCache.getCachedResult(
+ LOffs.second, ROffs.second));
+ }
+ RChild = ROffs.first;
+ } while (!MoveUpTranslationUnitIncludeHierarchy(ROffs, *this));
+
+ // If we found no match, the location is either in a built-ins buffer or
+ // associated with global inline asm. PR5662 and PR22576 are examples.
+
+ StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
+ StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
+
+ bool LIsBuiltins = LB == "<built-in>";
+ bool RIsBuiltins = RB == "<built-in>";
+ // Sort built-in before non-built-in.
+ if (LIsBuiltins || RIsBuiltins) {
+ if (LIsBuiltins != RIsBuiltins)
+ return std::make_pair(true, LIsBuiltins);
+ // Both are in built-in buffers, but from different files. We just claim
+ // that lower IDs come first.
+ return std::make_pair(true, LOffs.first < ROffs.first);
+ }
-std::pair<bool, bool>
-SourceManager::isInTheSameTranslationUnit(FileIDAndOffset &LOffs,
- FileIDAndOffset &ROffs) const {
- // If the source locations are not in the same TU, return early.
- if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))
- return std::make_pair(false, false);
-
- // If the source locations are in the same file, just compare offsets.
- if (LOffs.first == ROffs.first)
- return std::make_pair(true, LOffs.second < ROffs.second);
-
- // If we are comparing a source location with multiple locations in the same
- // file, we get a big win by caching the result.
- InBeforeInTUCacheEntry &IsBeforeInTUCache =
- getInBeforeInTUCache(LOffs.first, ROffs.first);
-
- // If we are comparing a source location with multiple locations in the same
- // file, we get a big win by caching the result.
- if (IsBeforeInTUCache.isCacheValid())
- return std::make_pair(
- true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
-
- // Okay, we missed in the cache, we'll compute the answer and populate it.
- // We need to find the common ancestor. The only way of doing this is to
- // build the complete include chain for one and then walking up the chain
- // of the other looking for a match.
-
- // A location within a FileID on the path up from LOffs to the main file.
- struct Entry {
- FileIDAndOffset DecomposedLoc; // FileID redundant, but clearer.
- FileID ChildFID; // Used for breaking ties. Invalid for the initial loc.
- };
- llvm::SmallDenseMap<FileID, Entry, 16> LChain;
+ bool LIsAsm = LB == "<inline asm>";
+ bool RIsAsm = RB == "<inline asm>";
+ // Sort assembler after built-ins, but before the rest.
+ if (LIsAsm || RIsAsm) {
+ if (LIsAsm != RIsAsm)
+ return std::make_pair(true, RIsAsm);
+ assert(LOffs.first == ROffs.first);
+ return std::make_pair(true, false);
+ }
- FileID LChild;
- do {
- LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
- // We catch the case where LOffs is in a file included by ROffs and
- // quit early. The other way round unfortunately remains suboptimal.
- if (LOffs.first == ROffs.first)
- break;
- LChild = LOffs.first;
- } while (!MoveUpTranslationUnitIncludeHierarchy(LOffs, *this));
-
- FileID RChild;
- do {
- auto LIt = LChain.find(ROffs.first);
- if (LIt != LChain.end()) {
- // Compare the locations within the common file and cache them.
- LOffs = LIt->second.DecomposedLoc;
- LChild = LIt->second.ChildFID;
- // The relative order of LChild and RChild is a tiebreaker when
- // - locs expand to the same location (occurs in macro arg expansion)
- // - one loc is a parent of the other (we consider the parent as "first")
- // For the parent entry to be first, its invalid child file ID must
- // compare smaller to the valid child file ID of the other entry.
- // However loaded FileIDs are <0, so we perform *unsigned* comparison!
- // This changes the relative order of local vs loaded FileIDs, but it
- // doesn't matter as these are never mixed in macro expansion.
- unsigned LChildID = LChild.ID;
- unsigned RChildID = RChild.ID;
- assert(((LOffs.second != ROffs.second) ||
- (LChildID == 0 || RChildID == 0) ||
- isInSameSLocAddrSpace(getComposedLoc(LChild, 0),
- getComposedLoc(RChild, 0), nullptr)) &&
- "Mixed local/loaded FileIDs with same include location?");
- IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
- LChildID < RChildID);
- return std::make_pair(
- true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
+ bool LIsScratch = LB == "<scratch space>";
+ bool RIsScratch = RB == "<scratch space>";
+ // Sort scratch after inline asm, but before the rest.
+ if (LIsScratch || RIsScratch) {
+ if (LIsScratch != RIsScratch)
+ return std::make_pair(true, LIsScratch);
+ return std::make_pair(true, LOffs.second < ROffs.second);
}
- RChild = ROffs.first;
- } while (!MoveUpTranslationUnitIncludeHierarchy(ROffs, *this));
-
- // If we found no match, the location is either in a built-ins buffer or
- // associated with global inline asm. PR5662 and PR22576 are examples.
-
- StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
- StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
-
- bool LIsBuiltins = LB == "<built-in>";
- bool RIsBuiltins = RB == "<built-in>";
- // Sort built-in before non-built-in.
- if (LIsBuiltins || RIsBuiltins) {
- if (LIsBuiltins != RIsBuiltins)
- return std::make_pair(true, LIsBuiltins);
- // Both are in built-in buffers, but from different files. We just claim
- // that lower IDs come first.
- return std::make_pair(true, LOffs.first < ROffs.first);
- }
-
- bool LIsAsm = LB == "<inline asm>";
- bool RIsAsm = RB == "<inline asm>";
- // Sort assembler after built-ins, but before the rest.
- if (LIsAsm || RIsAsm) {
- if (LIsAsm != RIsAsm)
- return std::make_pair(true, RIsAsm);
- assert(LOffs.first == ROffs.first);
- return std::make_pair(true, false);
- }
-
- bool LIsScratch = LB == "<scratch space>";
- bool RIsScratch = RB == "<scratch space>";
- // Sort scratch after inline asm, but before the rest.
- if (LIsScratch || RIsScratch) {
- if (LIsScratch != RIsScratch)
- return std::make_pair(true, LIsScratch);
- return std::make_pair(true, LOffs.second < ROffs.second);
- }
-
- llvm_unreachable("Unsortable locations found");
-}
-void SourceManager::PrintStats() const {
- llvm::errs() << "\n*** Source Manager Stats:\n";
- llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
- << " mem buffers mapped.\n";
- llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntries allocated ("
- << llvm::capacity_in_bytes(LocalSLocEntryTable)
- << " bytes of capacity), " << NextLocalOffset
- << "B of SLoc address space used.\n";
- llvm::errs() << LoadedSLocEntryTable.size()
- << " loaded SLocEntries allocated ("
- << llvm::capacity_in_bytes(LoadedSLocEntryTable)
- << " bytes of capacity), "
- << MaxLoadedOffset - CurrentLoadedOffset
- << "B of SLoc address space used.\n";
-
- unsigned NumLineNumsComputed = 0;
- unsigned NumFileBytesMapped = 0;
- for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
- NumLineNumsComputed += bool(I->second->SourceLineCache);
- NumFileBytesMapped += I->second->getSizeBytesMapped();
- }
- unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
-
- llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "
- << NumLineNumsComputed << " files with line #'s computed, "
- << NumMacroArgsComputed << " files with macro args computed.\n";
- llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "
- << NumBinaryProbes << " binary.\n";
-}
+ llvm_unreachable("Unsortable locations found");
+ }
-LLVM_DUMP_METHOD void SourceManager::dump() const {
- llvm::raw_ostream &out = llvm::errs();
+ void SourceManager::PrintStats() const {
+ llvm::errs() << "\n*** Source Manager Stats:\n";
+ llvm::errs() << FileInfos.size() << " files mapped, "
+ << MemBufferInfos.size() << " mem buffers mapped.\n";
+ llvm::errs() << LocalSLocEntryTable.size()
+ << " local SLocEntries allocated ("
+ << llvm::capacity_in_bytes(LocalSLocEntryTable)
+ << " bytes of capacity), " << NextLocalOffset
+ << "B of SLoc address space used.\n";
+ llvm::errs() << LoadedSLocEntryTable.size()
+ << " loaded SLocEntries allocated ("
+ << llvm::capacity_in_bytes(LoadedSLocEntryTable)
+ << " bytes of capacity), "
+ << MaxLoadedOffset - CurrentLoadedOffset
+ << "B of SLoc address space used.\n";
+
+ unsigned NumLineNumsComputed = 0;
+ unsigned NumFileBytesMapped = 0;
+ for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E;
+ ++I) {
+ NumLineNumsComputed += bool(I->second->SourceLineCache);
+ NumFileBytesMapped += I->second->getSizeBytesMapped();
+ }
+ unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
+
+ llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "
+ << NumLineNumsComputed << " files with line #'s computed, "
+ << NumMacroArgsComputed
+ << " files with macro args computed.\n";
+ llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "
+ << NumBinaryProbes << " binary.\n";
+ }
- auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,
- std::optional<SourceLocation::UIntTy> NextStart) {
- out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion")
- << " <SourceLocation " << Entry.getOffset() << ":";
- if (NextStart)
- out << *NextStart << ">\n";
- else
- out << "???\?>\n";
- if (Entry.isFile()) {
- auto &FI = Entry.getFile();
- if (FI.NumCreatedFIDs)
- out << " covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs)
- << ">\n";
- if (FI.getIncludeLoc().isValid())
- out << " included from " << FI.getIncludeLoc().getOffset() << "\n";
- auto &CC = FI.getContentCache();
- out << " for " << (CC.OrigEntry ? CC.OrigEntry->getName() : "<none>")
- << "\n";
- if (CC.BufferOverridden)
- out << " contents overridden\n";
- if (CC.ContentsEntry != CC.OrigEntry) {
- out << " contents from "
- << (CC.ContentsEntry ? CC.ContentsEntry->getName() : "<none>")
+ LLVM_DUMP_METHOD void SourceManager::dump() const {
+ llvm::raw_ostream &out = llvm::errs();
+
+ auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,
+ std::optional<SourceLocation::UIntTy> NextStart) {
+ out << "SLocEntry <FileID " << ID << "> "
+ << (Entry.isFile() ? "file" : "expansion") << " <SourceLocation "
+ << Entry.getOffset() << ":";
+ if (NextStart)
+ out << *NextStart << ">\n";
+ else
+ out << "???\?>\n";
+ if (Entry.isFile()) {
+ auto &FI = Entry.getFile();
+ if (FI.NumCreatedFIDs)
+ out << " covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs)
+ << ">\n";
+ if (FI.getIncludeLoc().isValid())
+ out << " included from " << FI.getIncludeLoc().getOffset() << "\n";
+ auto &CC = FI.getContentCache();
+ out << " for " << (CC.OrigEntry ? CC.OrigEntry->getName() : "<none>")
<< "\n";
+ if (CC.BufferOverridden)
+ out << " contents overridden\n";
+ if (CC.ContentsEntry != CC.OrigEntry) {
+ out << " contents from "
+ << (CC.ContentsEntry ? CC.ContentsEntry->getName() : "<none>")
+ << "\n";
+ }
+ } else {
+ auto &EI = Entry.getExpansion();
+ out << " spelling from " << EI.getSpellingLoc().getOffset() << "\n";
+ out << " macro " << (EI.isMacroArgExpansion() ? "arg" : "body")
+ << " range <" << EI.getExpansionLocStart().getOffset() << ":"
+ << EI.getExpansionLocEnd().getOffset() << ">\n";
}
- } else {
- auto &EI = Entry.getExpansion();
- out << " spelling from " << EI.getSpellingLoc().getOffset() << "\n";
- out << " macro " << (EI.isMacroArgExpansion() ? "arg" : "body")
- << " range <" << EI.getExpansionLocStart().getOffset() << ":"
- << EI.getExpansionLocEnd().getOffset() << ">\n";
- }
- };
+ };
- // Dump local SLocEntries.
- for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
- DumpSLocEntry(ID, LocalSLocEntryTable[ID],
- ID == NumIDs - 1 ? NextLocalOffset
- : LocalSLocEntryTable[ID + 1].getOffset());
- }
- // Dump loaded SLocEntries.
- std::optional<SourceLocation::UIntTy> NextStart;
- for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
- int ID = -(int)Index - 2;
- if (SLocEntryLoaded[Index]) {
- DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
- NextStart = LoadedSLocEntryTable[Index].getOffset();
- } else {
- NextStart = std::nullopt;
+ // Dump local SLocEntries.
+ for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs;
+ ++ID) {
+ DumpSLocEntry(ID, LocalSLocEntryTable[ID],
+ ID == NumIDs - 1 ? NextLocalOffset
+ : LocalSLocEntryTable[ID + 1].getOffset());
+ }
+ // Dump loaded SLocEntries.
+ std::optional<SourceLocation::UIntTy> NextStart;
+ for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
+ int ID = -(int)Index - 2;
+ if (SLocEntryLoaded[Index]) {
+ DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
+ NextStart = LoadedSLocEntryTable[Index].getOffset();
+ } else {
+ NextStart = std::nullopt;
+ }
}
}
-}
-void SourceManager::noteSLocAddressSpaceUsage(
- DiagnosticsEngine &Diag, std::optional<unsigned> MaxNotes) const {
- struct Info {
- // A location where this file was entered.
- SourceLocation Loc;
- // Number of times this FileEntry was entered.
- unsigned Inclusions = 0;
- // Size usage from the file itself.
- uint64_t DirectSize = 0;
- // Total size usage from the file and its macro expansions.
- uint64_t TotalSize = 0;
- };
- using UsageMap = llvm::MapVector<const FileEntry*, Info>;
-
- UsageMap Usage;
- uint64_t CountedSize = 0;
-
- auto AddUsageForFileID = [&](FileID ID) {
- // The +1 here is because getFileIDSize doesn't include the extra byte for
- // the one-past-the-end location.
- unsigned Size = getFileIDSize(ID) + 1;
-
- // Find the file that used this address space, either directly or by
- // macro expansion.
- SourceLocation FileStart = getFileLoc(getComposedLoc(ID, 0));
- FileID FileLocID = getFileID(FileStart);
- const FileEntry *Entry = getFileEntryForID(FileLocID);
-
- Info &EntryInfo = Usage[Entry];
- if (EntryInfo.Loc.isInvalid())
- EntryInfo.Loc = FileStart;
- if (ID == FileLocID) {
- ++EntryInfo.Inclusions;
- EntryInfo.DirectSize += Size;
+ void SourceManager::noteSLocAddressSpaceUsage(
+ DiagnosticsEngine & Diag, std::optional<unsigned> MaxNotes) const {
+ struct Info {
+ // A location where this file was entered.
+ SourceLocation Loc;
+ // Number of times this FileEntry was entered.
+ unsigned Inclusions = 0;
+ // Size usage from the file itself.
+ uint64_t DirectSize = 0;
+ // Total size usage from the file and its macro expansions.
+ uint64_t TotalSize = 0;
+ };
+ using UsageMap = llvm::MapVector<const FileEntry *, Info>;
+
+ UsageMap Usage;
+ uint64_t CountedSize = 0;
+
+ auto AddUsageForFileID = [&](FileID ID) {
+ // The +1 here is because getFileIDSize doesn't include the extra byte for
+ // the one-past-the-end location.
+ unsigned Size = getFileIDSize(ID) + 1;
+
+ // Find the file that used this address space, either directly or by
+ // macro expansion.
+ SourceLocation FileStart = getFileLoc(getComposedLoc(ID, 0));
+ FileID FileLocID = getFileID(FileStart);
+ const FileEntry *Entry = getFileEntryForID(FileLocID);
+
+ Info &EntryInfo = Usage[Entry];
+ if (EntryInfo.Loc.isInvalid())
+ EntryInfo.Loc = FileStart;
+ if (ID == FileLocID) {
+ ++EntryInfo.Inclusions;
+ EntryInfo.DirectSize += Size;
+ }
+ EntryInfo.TotalSize += Size;
+ CountedSize += Size;
+ };
+
+ // Loaded SLocEntries have indexes counting downwards from -2.
+ for (size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
+ AddUsageForFileID(FileID::get(-2 - Index));
+ }
+ // Local SLocEntries have indexes counting upwards from 0.
+ for (size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
+ AddUsageForFileID(FileID::get(Index));
}
- EntryInfo.TotalSize += Size;
- CountedSize += Size;
- };
- // Loaded SLocEntries have indexes counting downwards from -2.
- for (size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
- AddUsageForFileID(FileID::get(-2 - Index));
- }
- // Local SLocEntries have indexes counting upwards from 0.
- for (size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
- AddUsageForFileID(FileID::get(Index));
- }
+ // Sort the usage by size from largest to smallest. Break ties by raw source
+ // location.
+ auto SortedUsage = Usage.takeVector();
+ auto Cmp = [](const UsageMap::value_type &A,
+ const UsageMap::value_type &B) {
+ return A.second.TotalSize > B.second.TotalSize ||
+ (A.second.TotalSize == B.second.TotalSize &&
+ A.second.Loc < B.second.Loc);
+ };
+ auto SortedEnd = SortedUsage.end();
+ if (MaxNotes && SortedUsage.size() > *MaxNotes) {
+ SortedEnd = SortedUsage.begin() + *MaxNotes;
+ std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
+ }
+ std::sort(SortedUsage.begin(), SortedEnd, Cmp);
+
+ // Produce note on sloc address space usage total.
+ uint64_t LocalUsage = NextLocalOffset;
+ uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
+ int UsagePercent = static_cast<int>(
+ 100.0 * double(LocalUsage + LoadedUsage) / MaxLoadedOffset);
+ Diag.Report(diag::note_total_sloc_usage)
+ << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)
+ << UsagePercent;
+
+ // Produce notes on sloc address space usage for each file with a high
+ // usage.
+ uint64_t ReportedSize = 0;
+ for (auto &[Entry, FileInfo] :
+ llvm::make_range(SortedUsage.begin(), SortedEnd)) {
+ Diag.Report(FileInfo.Loc, diag::note_file_sloc_usage)
+ << FileInfo.Inclusions << FileInfo.DirectSize
+ << (FileInfo.TotalSize - FileInfo.DirectSize);
+ ReportedSize += FileInfo.TotalSize;
+ }
- // Sort the usage by size from largest to smallest. Break ties by raw source
- // location.
- auto SortedUsage = Usage.takeVector();
- auto Cmp = [](const UsageMap::value_type &A, const UsageMap::value_type &B) {
- return A.second.TotalSize > B.second.TotalSize ||
- (A.second.TotalSize == B.second.TotalSize &&
- A.second.Loc < B.second.Loc);
- };
- auto SortedEnd = SortedUsage.end();
- if (MaxNotes && SortedUsage.size() > *MaxNotes) {
- SortedEnd = SortedUsage.begin() + *MaxNotes;
- std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
- }
- std::sort(SortedUsage.begin(), SortedEnd, Cmp);
-
- // Produce note on sloc address space usage total.
- uint64_t LocalUsage = NextLocalOffset;
- uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
- int UsagePercent = static_cast<int>(100.0 * double(LocalUsage + LoadedUsage) /
- MaxLoadedOffset);
- Diag.Report(diag::note_total_sloc_usage)
- << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)
- << UsagePercent;
-
- // Produce notes on sloc address space usage for each file with a high usage.
- uint64_t ReportedSize = 0;
- for (auto &[Entry, FileInfo] :
- llvm::make_range(SortedUsage.begin(), SortedEnd)) {
- Diag.Report(FileInfo.Loc, diag::note_file_sloc_usage)
- << FileInfo.Inclusions << FileInfo.DirectSize
- << (FileInfo.TotalSize - FileInfo.DirectSize);
- ReportedSize += FileInfo.TotalSize;
- }
-
- // Describe any remaining usage not reported in the per-file usage.
- if (ReportedSize != CountedSize) {
- Diag.Report(diag::note_file_misc_sloc_usage)
- << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
+ // Describe any remaining usage not reported in the per-file usage.
+ if (ReportedSize != CountedSize) {
+ Diag.Report(diag::note_file_misc_sloc_usage)
+ << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
+ }
}
-}
-ExternalSLocEntrySource::~ExternalSLocEntrySource() = default;
+ ExternalSLocEntrySource::~ExternalSLocEntrySource() = default;
-/// Return the amount of memory used by memory buffers, breaking down
-/// by heap-backed versus mmap'ed memory.
-SourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const {
- size_t malloc_bytes = 0;
- size_t mmap_bytes = 0;
+ /// Return the amount of memory used by memory buffers, breaking down
+ /// by heap-backed versus mmap'ed memory.
+ SourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const {
+ size_t malloc_bytes = 0;
+ size_t mmap_bytes = 0;
- for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
- if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
- switch (MemBufferInfos[i]->getMemoryBufferKind()) {
+ for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
+ if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
+ switch (MemBufferInfos[i]->getMemoryBufferKind()) {
case llvm::MemoryBuffer::MemoryBuffer_MMap:
mmap_bytes += sized_mapped;
break;
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 7e612b83f..0d764e994 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -915,9 +915,10 @@ CompilerInstance::createOutputFileImpl(StringRef OutputPath, bool Binary,
bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input){
// Retrieve the converter to the internal charset if it exists.
llvm::TextEncodingConverter *Converter =
- hasPreprocessor() ? getPreprocessor().getTextEncodingConfig().getConverter(
- CA_FromInputEncoding)
- : nullptr;
+ hasPreprocessor()
+ ? getPreprocessor().getTextEncodingConfig().getConverter(
+ CA_FromInputEncoding)
+ : nullptr;
return InitializeSourceManager(Input, Converter, getDiagnostics(),
getFileManager(), getSourceManager());
@@ -934,7 +935,8 @@ bool CompilerInstance::InitializeSourceManager(
: Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
if (Input.isBuffer()) {
- SourceMgr.setMainFileID(SourceMgr.createFileID(Input.getBuffer(), Kind, Converter));
+ SourceMgr.setMainFileID(
+ SourceMgr.createFileID(Input.getBuffer(), Kind, Converter));
assert(SourceMgr.getMainFileID().isValid() &&
"Couldn't establish MainFileID!");
return true;
diff --git a/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp b/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 01e3b20e0..27bca6c99 100644
--- a/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -610,10 +610,10 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
}
FileID FID = SM.translateFile(*File);
- // FIXME: Figure out character-encoding converter treatment.
+ // FIXME: Figure out character-encoding converter treatment.
if (FID.isInvalid())
FID = SM.createFileID(*File, Pos, SrcMgr::C_User,
- /*Converter=*/nullptr);
+ /*Converter=*/nullptr);
if (PH.Next(Line) && Line > 0)
ExpectedLoc = SM.translateLineCol(FID, Line, 1);
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index c7c1e04b7..ea1901503 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -1473,10 +1473,10 @@ bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,
if (LocalFID.isInvalid()) {
auto FileCharacter =
IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
- // FIXME: Module map files are also textual "source files". For consistency,
- // conversion should occur.
+ // FIXME: Module map files are also textual "source files". For
+ // consistency, conversion should occur.
LocalFID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter,
- /*Converter=*/nullptr);
+ /*Converter=*/nullptr);
}
ID = LocalFID;
}
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index c5e32468b..8173723fe 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -651,7 +651,7 @@ void Preprocessor::EnterMainSourceFile() {
}
// FIXME: Figure out character-encoding converter treatment.
setPCHThroughHeaderFileID(SourceMgr.createFileID(
- *File, SourceLocation(), SrcMgr::C_User, /*Converter=*/nullptr));
+ *File, SourceLocation(), SrcMgr::C_User, /*Converter=*/nullptr));
}
// Skip tokens from the Predefines and if needed the main file.
diff --git a/clang/lib/Lex/TextEncodingConfig.cpp b/clang/lib/Lex/TextEncodingConfig.cpp
index 01c9bfcf6..c6bb7b664 100644
--- a/clang/lib/Lex/TextEncodingConfig.cpp
+++ b/clang/lib/Lex/TextEncodingConfig.cpp
@@ -32,10 +32,11 @@ TextEncodingConfig::getFromFiletagEncodingConverter(TextEncodingConfig &TEC,
}
llvm::TextEncodingConverter *
-TextEncodingConfig::createAndInsertFromFiletagEncodingConverter(TextEncodingConfig &TEC,
- StringRef FiletagEncoding,
- clang::DiagnosticsEngine &Diag) {
- llvm::TextEncodingConverter *Converter = getFromFiletagtEncodingConverter(TEC, FiletagEncoding);
+TextEncodingConfig::createAndInsertFromFiletagEncodingConverter(
+ TextEncodingConfig &TEC, StringRef FiletagEncoding,
+ clang::DiagnosticsEngine &Diag) {
+ llvm::TextEncodingConverter *Converter =
+ getFromFiletagtEncodingConverter(TEC, FiletagEncoding);
if (Converter)
return Converter;
@@ -49,10 +50,12 @@ TextEncodingConfig::createAndInsertFromFiletagEncodingConverter(TextEncodingConf
<< "Filetag encoding" << FiletagEncoding;
return nullptr;
} else {
- auto FromFiletagEncodingConverter = std::make_unique<llvm::TextEncodingConverter>(
- std::move(*ErrorOrConverter));
+ auto FromFiletagEncodingConverter =
+ std::make_unique<llvm::TextEncodingConverter>(
+ std::move(*ErrorOrConverter));
llvm::TextEncodingConverter *Result = FromFiletagEncodingConverter.get();
- TEC.FromFiletagEncodingConverters.insert_or_assign(FiletagEncoding, std::move(FromFiletagEncodingConverter));
+ TEC.FromFiletagEncodingConverters.insert_or_assign(
+ FiletagEncoding, std::move(FromFiletagEncodingConverter));
return Result;
}
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 379622e92..89684cdcc 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -2006,7 +2006,7 @@ bool ASTReader::ReadSLocEntry(int ID) {
// true and the associated handling will trigger.
FileID FID = SourceMgr.createFileID(*File, IncludeLoc, FileCharacter,
/*Converter=*/nullptr, ID,
- BaseOffset + Record[0]);
+ BaseOffset + Record[0]);
SrcMgr::FileInfo &FileInfo = SourceMgr.getSLocEntry(FID).getFile();
FileInfo.NumCreatedFIDs = Record[5];
if (Record[3])
diff --git a/llvm/include/llvm/Support/TextEncoding.h b/llvm/include/llvm/Support/TextEncoding.h
index 24a2e026e..de268bcca 100644
--- a/llvm/include/llvm/Support/TextEncoding.h
+++ b/llvm/include/llvm/Support/TextEncoding.h
@@ -156,7 +156,7 @@ public:
/// \param[in] TargetEncoding the target character encoding name
/// \return pointer to the converter or nullptr on error
TextEncodingConverter *createAndInsertConverter(StringRef SourceEncoding,
- StringRef TargetEncoding);
+ StringRef TargetEncoding);
};
} // namespace llvm
diff --git a/llvm/lib/Support/TextEncoding.cpp b/llvm/lib/Support/TextEncoding.cpp
index 2a1d19935..a5d61e1d6 100644
--- a/llvm/lib/Support/TextEncoding.cpp
+++ b/llvm/lib/Support/TextEncoding.cpp
@@ -368,7 +368,7 @@ TextEncodingConverterCache::getConverter(StringRef SourceEncoding) const {
TextEncodingConverter *
TextEncodingConverterCache::createAndInsertConverter(StringRef SourceEncoding,
- StringRef TargetEncoding) {
+ StringRef TargetEncoding) {
// Check if converter already exists
TextEncodingConverter *Converter = getConverter(SourceEncoding);
if (Converter)
``````````
</details>
https://github.com/llvm/llvm-project/pull/204233
More information about the cfe-commits
mailing list