r202471 - [ASTUnit] Don't let the preamble diagnostics out-live the CompilerInstance that created them,
Argyrios Kyrtzidis
akyrtzi at gmail.com
Thu Feb 27 23:11:01 PST 2014
Author: akirtzidis
Date: Fri Feb 28 01:11:01 2014
New Revision: 202471
URL: http://llvm.org/viewvc/llvm-project?rev=202471&view=rev
Log:
[ASTUnit] Don't let the preamble diagnostics out-live the CompilerInstance that created them,
this is inherently unsafe.
Instead get the diagnostic info into a SourceManager-independent form.
Modified:
cfe/trunk/include/clang/Frontend/ASTUnit.h
cfe/trunk/lib/Frontend/ASTUnit.cpp
Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=202471&r1=202470&r2=202471&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Fri Feb 28 01:11:01 2014
@@ -64,6 +64,24 @@ class ASTDeserializationListener;
/// \brief Utility class for loading a ASTContext from an AST file.
///
class ASTUnit : public ModuleLoader {
+public:
+ struct StandaloneFixIt {
+ std::pair<unsigned, unsigned> RemoveRange;
+ std::pair<unsigned, unsigned> InsertFromRange;
+ std::string CodeToInsert;
+ bool BeforePreviousInsertions;
+ };
+
+ struct StandaloneDiagnostic {
+ unsigned ID;
+ DiagnosticsEngine::Level Level;
+ std::string Message;
+ std::string Filename;
+ unsigned LocOffset;
+ std::vector<std::pair<unsigned, unsigned> > Ranges;
+ std::vector<StandaloneFixIt> FixIts;
+ };
+
private:
IntrusiveRefCntPtr<LangOptions> LangOpts;
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
@@ -136,7 +154,7 @@ private:
std::string OriginalSourceFile;
/// \brief The set of diagnostics produced when creating the preamble.
- SmallVector<StoredDiagnostic, 4> PreambleDiagnostics;
+ SmallVector<StandaloneDiagnostic, 4> PreambleDiagnostics;
/// \brief The set of diagnostics produced when creating this
/// translation unit.
@@ -295,9 +313,9 @@ private:
const char **ArgBegin, const char **ArgEnd,
ASTUnit &AST, bool CaptureDiagnostics);
- void TranslateStoredDiagnostics(ASTReader *MMan, StringRef ModName,
+ void TranslateStoredDiagnostics(FileManager &FileMgr,
SourceManager &SrcMan,
- const SmallVectorImpl<StoredDiagnostic> &Diags,
+ const SmallVectorImpl<StandaloneDiagnostic> &Diags,
SmallVectorImpl<StoredDiagnostic> &Out);
void clearFileLevelDecls();
Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=202471&r1=202470&r2=202471&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Fri Feb 28 01:11:01 2014
@@ -1159,9 +1159,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *
if (OverrideMainBuffer) {
std::string ModName = getPreambleFile(this);
- TranslateStoredDiagnostics(Clang->getModuleManager().getPtr(), ModName,
- getSourceManager(), PreambleDiagnostics,
- StoredDiagnostics);
+ TranslateStoredDiagnostics(getFileManager(), getSourceManager(),
+ PreambleDiagnostics, StoredDiagnostics);
}
if (!Act->Execute())
@@ -1329,6 +1328,53 @@ bool operator==(const ASTUnit::PreambleF
}
} // namespace clang
+static std::pair<unsigned, unsigned>
+makeStandaloneRange(CharSourceRange Range, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ CharSourceRange FileRange = Lexer::makeFileCharRange(Range, SM, LangOpts);
+ unsigned Offset = SM.getFileOffset(FileRange.getBegin());
+ unsigned EndOffset = SM.getFileOffset(FileRange.getEnd());
+ return std::make_pair(Offset, EndOffset);
+}
+
+static void makeStandaloneFixIt(const SourceManager &SM,
+ const LangOptions &LangOpts,
+ const FixItHint &InFix,
+ ASTUnit::StandaloneFixIt &OutFix) {
+ OutFix.RemoveRange = makeStandaloneRange(InFix.RemoveRange, SM, LangOpts);
+ OutFix.InsertFromRange = makeStandaloneRange(InFix.InsertFromRange, SM,
+ LangOpts);
+ OutFix.CodeToInsert = InFix.CodeToInsert;
+ OutFix.BeforePreviousInsertions = InFix.BeforePreviousInsertions;
+}
+
+static void makeStandaloneDiagnostic(const LangOptions &LangOpts,
+ const StoredDiagnostic &InDiag,
+ ASTUnit::StandaloneDiagnostic &OutDiag) {
+ OutDiag.ID = InDiag.getID();
+ OutDiag.Level = InDiag.getLevel();
+ OutDiag.Message = InDiag.getMessage();
+ OutDiag.LocOffset = 0;
+ if (InDiag.getLocation().isInvalid())
+ return;
+ const SourceManager &SM = InDiag.getLocation().getManager();
+ SourceLocation FileLoc = SM.getFileLoc(InDiag.getLocation());
+ OutDiag.Filename = SM.getFilename(FileLoc);
+ if (OutDiag.Filename.empty())
+ return;
+ OutDiag.LocOffset = SM.getFileOffset(FileLoc);
+ for (StoredDiagnostic::range_iterator
+ I = InDiag.range_begin(), E = InDiag.range_end(); I != E; ++I) {
+ OutDiag.Ranges.push_back(makeStandaloneRange(*I, SM, LangOpts));
+ }
+ for (StoredDiagnostic::fixit_iterator
+ I = InDiag.fixit_begin(), E = InDiag.fixit_end(); I != E; ++I) {
+ ASTUnit::StandaloneFixIt Fix;
+ makeStandaloneFixIt(SM, LangOpts, *I, Fix);
+ OutDiag.FixIts.push_back(Fix);
+ }
+}
+
/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
/// the source file.
///
@@ -1589,6 +1635,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBuff
checkAndRemoveNonDriverDiags(StoredDiagnostics);
TopLevelDecls.clear();
TopLevelDeclsInPreamble.clear();
+ PreambleDiagnostics.clear();
// Create a file manager object to provide access to and cache the filesystem.
Clang->setFileManager(new FileManager(Clang->getFileSystemOpts()));
@@ -1609,8 +1656,21 @@ llvm::MemoryBuffer *ASTUnit::getMainBuff
}
Act->Execute();
+
+ // Transfer any diagnostics generated when parsing the preamble into the set
+ // of preamble diagnostics.
+ for (stored_diag_iterator
+ I = stored_diag_afterDriver_begin(),
+ E = stored_diag_end(); I != E; ++I) {
+ StandaloneDiagnostic Diag;
+ makeStandaloneDiagnostic(Clang->getLangOpts(), *I, Diag);
+ PreambleDiagnostics.push_back(Diag);
+ }
+
Act->EndSourceFile();
+ checkAndRemoveNonDriverDiags(StoredDiagnostics);
+
if (!Act->hasEmittedPreamblePCH()) {
// The preamble PCH failed (e.g. there was a module loading fatal error),
// so no precompiled header was generated. Forget that we even tried.
@@ -1624,13 +1684,6 @@ llvm::MemoryBuffer *ASTUnit::getMainBuff
return 0;
}
- // Transfer any diagnostics generated when parsing the preamble into the set
- // of preamble diagnostics.
- PreambleDiagnostics.clear();
- PreambleDiagnostics.insert(PreambleDiagnostics.end(),
- stored_diag_afterDriver_begin(), stored_diag_end());
- checkAndRemoveNonDriverDiags(StoredDiagnostics);
-
// Keep track of the preamble we precompiled.
setPreambleFile(this, FrontendOpts.OutputFile);
NumWarningsInPreamble = getDiagnostics().getNumWarnings();
@@ -2545,68 +2598,57 @@ bool ASTUnit::serialize(raw_ostream &OS)
typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap;
-static void TranslateSLoc(SourceLocation &L, SLocRemap &Remap) {
- unsigned Raw = L.getRawEncoding();
- const unsigned MacroBit = 1U << 31;
- L = SourceLocation::getFromRawEncoding((Raw & MacroBit) |
- ((Raw & ~MacroBit) + Remap.find(Raw & ~MacroBit)->second));
-}
-
void ASTUnit::TranslateStoredDiagnostics(
- ASTReader *MMan,
- StringRef ModName,
+ FileManager &FileMgr,
SourceManager &SrcMgr,
- const SmallVectorImpl<StoredDiagnostic> &Diags,
+ const SmallVectorImpl<StandaloneDiagnostic> &Diags,
SmallVectorImpl<StoredDiagnostic> &Out) {
- // The stored diagnostic has the old source manager in it; update
- // the locations to refer into the new source manager. We also need to remap
- // all the locations to the new view. This includes the diag location, any
- // associated source ranges, and the source ranges of associated fix-its.
+ // Map the standalone diagnostic into the new source manager. We also need to
+ // remap all the locations to the new view. This includes the diag location,
+ // any associated source ranges, and the source ranges of associated fix-its.
// FIXME: There should be a cleaner way to do this.
SmallVector<StoredDiagnostic, 4> Result;
Result.reserve(Diags.size());
- assert(MMan && "Don't have a module manager");
- serialization::ModuleFile *Mod = MMan->ModuleMgr.lookup(ModName);
- assert(Mod && "Don't have preamble module");
- SLocRemap &Remap = Mod->SLocRemap;
for (unsigned I = 0, N = Diags.size(); I != N; ++I) {
// Rebuild the StoredDiagnostic.
- const StoredDiagnostic &SD = Diags[I];
- SourceLocation L = SD.getLocation();
- TranslateSLoc(L, Remap);
+ const StandaloneDiagnostic &SD = Diags[I];
+ if (SD.Filename.empty())
+ continue;
+ const FileEntry *FE = FileMgr.getFile(SD.Filename);
+ if (!FE)
+ continue;
+ FileID FID = SrcMgr.translateFile(FE);
+ SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID);
+ if (FileLoc.isInvalid())
+ continue;
+ SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset);
FullSourceLoc Loc(L, SrcMgr);
SmallVector<CharSourceRange, 4> Ranges;
- Ranges.reserve(SD.range_size());
- for (StoredDiagnostic::range_iterator I = SD.range_begin(),
- E = SD.range_end();
- I != E; ++I) {
- SourceLocation BL = I->getBegin();
- TranslateSLoc(BL, Remap);
- SourceLocation EL = I->getEnd();
- TranslateSLoc(EL, Remap);
- Ranges.push_back(CharSourceRange(SourceRange(BL, EL), I->isTokenRange()));
+ Ranges.reserve(SD.Ranges.size());
+ for (std::vector<std::pair<unsigned, unsigned> >::const_iterator
+ I = SD.Ranges.begin(), E = SD.Ranges.end(); I != E; ++I) {
+ SourceLocation BL = FileLoc.getLocWithOffset((*I).first);
+ SourceLocation EL = FileLoc.getLocWithOffset((*I).second);
+ Ranges.push_back(CharSourceRange::getCharRange(BL, EL));
}
SmallVector<FixItHint, 2> FixIts;
- FixIts.reserve(SD.fixit_size());
- for (StoredDiagnostic::fixit_iterator I = SD.fixit_begin(),
- E = SD.fixit_end();
+ FixIts.reserve(SD.FixIts.size());
+ for (std::vector<StandaloneFixIt>::const_iterator
+ I = SD.FixIts.begin(), E = SD.FixIts.end();
I != E; ++I) {
FixIts.push_back(FixItHint());
FixItHint &FH = FixIts.back();
FH.CodeToInsert = I->CodeToInsert;
- SourceLocation BL = I->RemoveRange.getBegin();
- TranslateSLoc(BL, Remap);
- SourceLocation EL = I->RemoveRange.getEnd();
- TranslateSLoc(EL, Remap);
- FH.RemoveRange = CharSourceRange(SourceRange(BL, EL),
- I->RemoveRange.isTokenRange());
+ SourceLocation BL = FileLoc.getLocWithOffset(I->RemoveRange.first);
+ SourceLocation EL = FileLoc.getLocWithOffset(I->RemoveRange.second);
+ FH.RemoveRange = CharSourceRange::getCharRange(BL, EL);
}
- Result.push_back(StoredDiagnostic(SD.getLevel(), SD.getID(),
- SD.getMessage(), Loc, Ranges, FixIts));
+ Result.push_back(StoredDiagnostic(SD.Level, SD.ID,
+ SD.Message, Loc, Ranges, FixIts));
}
Result.swap(Out);
}
More information about the cfe-commits
mailing list