[libclang] When getting a source location from a file:line:col triplet
check whether the requested location points inside the precompiled preamble,
in which case the returned source location will be a "loaded" one.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140060 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 38cc994..68c98fe 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -1324,7 +1324,8 @@
/// 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) {
+ unsigned Line,
+ unsigned Col) const {
assert(SourceFile && "Null source file!");
assert(Line && Col && "Line and column should start from 1!");
@@ -1439,7 +1440,8 @@
/// \brief Get the source location in \arg FID for the given line:col.
/// Returns null location if \arg FID is not a file SLocEntry.
SourceLocation SourceManager::translateLineCol(FileID FID,
- unsigned Line, unsigned Col) {
+ unsigned Line,
+ unsigned Col) const {
if (FID.isInvalid())
return SourceLocation();
@@ -1496,7 +1498,8 @@
/// 0 -> SourceLocation()
/// 100 -> Expanded macro arg location
/// 110 -> SourceLocation()
-void SourceManager::computeMacroArgsCache(ContentCache *Content, FileID FID) {
+void SourceManager::computeMacroArgsCache(ContentCache *Content,
+ FileID FID) const {
assert(!Content->MacroArgsCache);
assert(!FID.isInvalid());
@@ -1575,7 +1578,8 @@
/// ^
/// Passing a file location pointing at 'foo', will yield a macro location
/// where 'foo' was expanded into.
-SourceLocation SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) {
+SourceLocation
+SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const {
if (Loc.isInvalid() || !Loc.isFileID())
return Loc;
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 6f9b437..53e0412 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -1200,7 +1200,7 @@
if (Preamble.size() == NewPreamble.second.first &&
PreambleEndsAtStartOfLine == NewPreamble.second.second &&
NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
- memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
+ memcmp(Preamble.getBufferStart(), NewPreamble.first->getBufferStart(),
NewPreamble.second.first) == 0) {
// The preamble has not changed. We may be able to re-use the precompiled
// preamble.
@@ -1332,7 +1332,9 @@
// Save the preamble text for later; we'll need to compare against it for
// subsequent reparses.
- Preamble.assign(NewPreamble.first->getBufferStart(),
+ StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].second;
+ Preamble.assign(FileMgr->getFile(MainFilename),
+ NewPreamble.first->getBufferStart(),
NewPreamble.first->getBufferStart()
+ NewPreamble.second.first);
PreambleEndsAtStartOfLine = NewPreamble.second.second;
@@ -2396,3 +2398,41 @@
}
Result.swap(Out);
}
+
+SourceLocation ASTUnit::getLocation(const FileEntry *File,
+ unsigned Line, unsigned Col) const {
+ const SourceManager &SM = getSourceManager();
+ SourceLocation Loc;
+ if (!Preamble.empty() && Line <= Preamble.getNumLines())
+ Loc = SM.translateLineCol(SM.getPreambleFileID(), Line, Col);
+ else
+ Loc = SM.translateFileLineCol(File, Line, Col);
+
+ return SM.getMacroArgExpandedLocation(Loc);
+}
+
+SourceLocation ASTUnit::getLocation(const FileEntry *File,
+ unsigned Offset) const {
+ const SourceManager &SM = getSourceManager();
+ SourceLocation FileLoc;
+ if (!Preamble.empty() && Offset < Preamble.size())
+ FileLoc = SM.getLocForStartOfFile(SM.getPreambleFileID());
+ else
+ FileLoc = SM.translateFileLineCol(File, 1, 1);
+
+ return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));
+}
+
+void ASTUnit::PreambleData::countLines() const {
+ NumLines = 0;
+ if (empty())
+ return;
+
+ for (std::vector<char>::const_iterator
+ I = Buffer.begin(), E = Buffer.end(); I != E; ++I) {
+ if (*I == '\n')
+ ++NumLines;
+ }
+ if (Buffer.back() != '\n')
+ ++NumLines;
+}
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 92798c8..924864c 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -539,11 +539,8 @@
FileManager &FileMgr,
SourceManager &SourceMgr,
const FrontendOptions &Opts) {
- // Figure out where to get and map in the main file, unless it's already
- // been created (e.g., by a precompiled preamble).
- if (!SourceMgr.getMainFileID().isInvalid()) {
- // Do nothing: the main file has already been set.
- } else if (InputFile != "-") {
+ // Figure out where to get and map in the main file.
+ if (InputFile != "-") {
const FileEntry *File = FileMgr.getFile(InputFile);
if (!File) {
Diags.Report(diag::err_fe_error_reading) << InputFile;
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 0f3cad5..02d7eea 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2508,23 +2508,15 @@
if (DeserializationListener)
DeserializationListener->ReaderInitialized(this);
- // If this AST file is a precompiled preamble, then set the main file ID of
- // the source manager to the file source file from which the preamble was
- // built. This is the only valid way to use a precompiled preamble.
+ // If this AST file is a precompiled preamble, then set the preamble file ID
+ // of the source manager to the file source file from which the preamble was
+ // built.
if (Type == MK_Preamble) {
- if (OriginalFileID.isInvalid()) {
- SourceLocation Loc
- = SourceMgr.getLocation(FileMgr.getFile(getOriginalSourceFile()), 1, 1);
- if (Loc.isValid())
- OriginalFileID = SourceMgr.getDecomposedLoc(Loc).first;
- }
- else {
+ if (!OriginalFileID.isInvalid()) {
OriginalFileID = FileID::get(ModuleMgr.getPrimaryModule().SLocEntryBaseID
+ OriginalFileID.getOpaqueValue() - 1);
+ SourceMgr.setPreambleFileID(OriginalFileID);
}
-
- if (!OriginalFileID.isInvalid())
- SourceMgr.SetPreambleFileID(OriginalFileID);
}
return Success;