aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-05-03 22:58:43 +0000
committerDouglas Gregor <dgregor@apple.com>2013-05-03 22:58:43 +0000
commita4a90cabfa15c900016a7cfaea51a6d4e8ebf4db (patch)
treea2768593ef7b8977d9cacad5b95ae8812ec9ad88 /lib
parentdd08a0c178329ec16cb9e494e6880f3991708b93 (diff)
When building a module, forward diagnostics to the outer diagnostic consumer.
Previously, we would clone the current diagnostic consumer to produce a new diagnostic consumer to use when building a module. The problem here is that we end up losing diagnostics for important diagnostic consumers, such as serialized diagnostics (where we'd end up with two diagnostic consumers writing the same output file). With forwarding, the diagnostics from all of the different modules being built get forwarded to the one serialized-diagnostic consumer and are emitted in a sane way. Fixes <rdar://problem/13663996>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181067 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Basic/Diagnostic.cpp22
-rw-r--r--lib/Frontend/ASTMerge.cpp7
-rw-r--r--lib/Frontend/ASTUnit.cpp28
-rw-r--r--lib/Frontend/CompilerInstance.cpp7
-rw-r--r--lib/Frontend/VerifyDiagnosticConsumer.cpp12
-rw-r--r--lib/Lex/ModuleMap.cpp5
6 files changed, 69 insertions, 12 deletions
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 4a5b191aab..5eff86c2b8 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -972,6 +972,28 @@ bool DiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; }
void IgnoringDiagConsumer::anchor() { }
+ForwardingDiagnosticConsumer::~ForwardingDiagnosticConsumer() {}
+
+void ForwardingDiagnosticConsumer::HandleDiagnostic(
+ DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) {
+ Target.HandleDiagnostic(DiagLevel, Info);
+}
+
+void ForwardingDiagnosticConsumer::clear() {
+ DiagnosticConsumer::clear();
+ Target.clear();
+}
+
+bool ForwardingDiagnosticConsumer::IncludeInDiagnosticCounts() const {
+ return Target.IncludeInDiagnosticCounts();
+}
+
+DiagnosticConsumer *
+ForwardingDiagnosticConsumer::clone(DiagnosticsEngine &Diags) const {
+ return new ForwardingDiagnosticConsumer(Target);
+}
+
PartialDiagnostic::StorageAllocator::StorageAllocator() {
for (unsigned I = 0; I != NumCached; ++I)
FreeList[I] = Cached + I;
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index bfb30836d8..b6c644eba7 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -34,7 +34,7 @@ bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI,
void ASTMergeAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
CI.getDiagnostics().getClient()->BeginSourceFile(
- CI.getASTContext().getLangOpts());
+ CI.getASTContext().getLangOpts());
CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
&CI.getASTContext());
IntrusiveRefCntPtr<DiagnosticIDs>
@@ -42,8 +42,9 @@ void ASTMergeAction::ExecuteAction() {
for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
IntrusiveRefCntPtr<DiagnosticsEngine>
Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(),
- CI.getDiagnostics().getClient(),
- /*ShouldOwnClient=*/false));
+ new ForwardingDiagnosticConsumer(
+ *CI.getDiagnostics().getClient()),
+ /*ShouldOwnClient=*/true));
ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags,
CI.getFileSystemOpts(), false);
if (!Unit)
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index c1115aedbf..1b4e5a0b39 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -236,6 +236,11 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
}
ASTUnit::~ASTUnit() {
+ // If we loaded from an AST file, balance out the BeginSourceFile call.
+ if (MainFileIsAST && getDiagnostics().getClient()) {
+ getDiagnostics().getClient()->EndSourceFile();
+ }
+
clearFileLevelDecls();
// Clean up the temporary files and the preamble file.
@@ -581,14 +586,22 @@ private:
}
};
+ /// \brief Diagnostic consumer that saves each diagnostic it is given.
class StoredDiagnosticConsumer : public DiagnosticConsumer {
SmallVectorImpl<StoredDiagnostic> &StoredDiags;
-
+ SourceManager *SourceMgr;
+
public:
explicit StoredDiagnosticConsumer(
SmallVectorImpl<StoredDiagnostic> &StoredDiags)
- : StoredDiags(StoredDiags) { }
-
+ : StoredDiags(StoredDiags), SourceMgr(0) { }
+
+ virtual void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP = 0) {
+ if (PP)
+ SourceMgr = &PP->getSourceManager();
+ }
+
virtual void HandleDiagnostic(DiagnosticsEngine::Level Level,
const Diagnostic &Info);
@@ -635,7 +648,11 @@ void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level,
// Default implementation (Warnings/errors count).
DiagnosticConsumer::HandleDiagnostic(Level, Info);
- StoredDiags.push_back(StoredDiagnostic(Level, Info));
+ // Only record the diagnostic if it's part of the source manager we know
+ // about. This effectively drops diagnostics from modules we're building.
+ // FIXME: In the long run, ee don't want to drop source managers from modules.
+ if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr)
+ StoredDiags.push_back(StoredDiagnostic(Level, Info));
}
ASTDeserializationListener *ASTUnit::getDeserializationListener() {
@@ -835,6 +852,9 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
ReaderPtr->InitializeSema(*AST->TheSema);
AST->Reader = ReaderPtr;
+ // Tell the diagnostic client that we have started a source file.
+ AST->getDiagnostics().getClient()->BeginSourceFile(Context.getLangOpts(),&PP);
+
return AST.take();
}
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index df06a816e8..027e99a29d 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -868,9 +868,11 @@ static void compileModule(CompilerInstance &ImportingInstance,
// module.
CompilerInstance Instance;
Instance.setInvocation(&*Invocation);
- Instance.createDiagnostics(&ImportingInstance.getDiagnosticClient(),
+
+ Instance.createDiagnostics(new ForwardingDiagnosticConsumer(
+ ImportingInstance.getDiagnosticClient()),
/*ShouldOwnClient=*/true,
- /*ShouldCloneClient=*/true);
+ /*ShouldCloneClient=*/false);
// Note that this module is part of the module build stack, so that we
// can detect cycles in the module graph.
@@ -892,6 +894,7 @@ static void compileModule(CompilerInstance &ImportingInstance,
llvm::CrashRecoveryContext CRC;
CompileModuleMapData Data = { Instance, CreateModuleAction };
CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize);
+
// Delete the temporary module map file.
// FIXME: Even though we're executing under crash protection, it would still
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 4f05aef94f..91aa52b771 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -111,8 +111,13 @@ void VerifyDiagnosticConsumer::EndSourceFile() {
void VerifyDiagnosticConsumer::HandleDiagnostic(
DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
- if (Info.hasSourceManager())
+ if (Info.hasSourceManager()) {
+ // If this diagnostic is for a different source manager, ignore it.
+ if (SrcManager && &Info.getSourceManager() != SrcManager)
+ return;
+
setSourceManager(Info.getSourceManager());
+ }
#ifndef NDEBUG
// Debug build tracks unparsed files for possible
@@ -476,6 +481,11 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP,
SourceRange Comment) {
SourceManager &SM = PP.getSourceManager();
+
+ // If this comment is for a different source manager, ignore it.
+ if (SrcManager && &SM != SrcManager)
+ return false;
+
SourceLocation CommentBegin = Comment.getBegin();
const char *CommentRaw = SM.getCharacterData(CommentBegin);
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index 1458a73a7d..3e7a44c0e3 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -83,7 +83,7 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
return Context;
}
-ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
+ModuleMap::ModuleMap(FileManager &FileMgr, DiagnosticConsumer &DC,
const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo)
: LangOpts(LangOpts), Target(Target), HeaderInfo(HeaderInfo),
@@ -92,7 +92,8 @@ ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
new DiagnosticsEngine(DiagIDs, new DiagnosticOptions));
- Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
+ Diags->setClient(new ForwardingDiagnosticConsumer(DC),
+ /*ShouldOwnClient=*/true);
SourceMgr = new SourceManager(*Diags, FileMgr);
}