diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-02-18 18:08:43 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-02-18 18:08:43 +0000 |
commit | a88084b78fd4ca5d3d858c14b02414f8cc399f02 (patch) | |
tree | 8d45285d7831d594f76f9a0a1edaa4436b090ac5 /lib/Frontend/ASTUnit.cpp | |
parent | 8b6765fb563a5b03d128d8f53b9b3986128a3405 (diff) |
Rework how CIndex handles diagnostics. Rather than using a callback,
we attach diagnostics to translation units and code-completion
results, so they can be queried at any time.
To facilitate this, the new StoredDiagnostic class stores a diagnostic
in a serializable/deserializable form, and ASTUnit knows how to
capture diagnostics in this stored form. CIndex's CXDiagnostic is a
thin wrapper around StoredDiagnostic, providing a C interface to
stored or de-serialized diagnostics.
I've XFAIL'd one test case temporarily, because currently we end up
storing diagnostics in an ASTUnit that's never returned to the user
(because it contains errors). I'll introduce a temporary fix for this
soon; the real fix will be to allow us to return and query invalid ASTs.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96592 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/ASTUnit.cpp')
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 69 |
1 files changed, 62 insertions, 7 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index a0c4889c16..345b9ba4d3 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -90,8 +90,46 @@ public: } }; +class StoredDiagnosticClient : public DiagnosticClient { + llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags; + +public: + explicit StoredDiagnosticClient( + llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags) + : StoredDiags(StoredDiags) { } + + virtual void HandleDiagnostic(Diagnostic::Level Level, + const DiagnosticInfo &Info); +}; + +/// \brief RAII object that optionally captures diagnostics, if +/// there is no diagnostic client to capture them already. +class CaptureDroppedDiagnostics { + Diagnostic &Diags; + StoredDiagnosticClient Client; + DiagnosticClient *PreviousClient; + +public: + CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags, + llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags) + : Diags(Diags), Client(StoredDiags), PreviousClient(Diags.getClient()) + { + if (RequestCapture || Diags.getClient() == 0) + Diags.setClient(&Client); + } + + ~CaptureDroppedDiagnostics() { + Diags.setClient(PreviousClient); + } +}; + } // anonymous namespace +void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level, + const DiagnosticInfo &Info) { + StoredDiags.push_back(StoredDiagnostic(Level, Info)); +} + const std::string &ASTUnit::getOriginalSourceFileName() { return OriginalSourceFile; } @@ -105,11 +143,16 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, Diagnostic &Diags, bool OnlyLocalDecls, RemappedFile *RemappedFiles, - unsigned NumRemappedFiles) { + unsigned NumRemappedFiles, + bool CaptureDiagnostics) { llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true)); AST->OnlyLocalDecls = OnlyLocalDecls; AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager())); + // If requested, capture diagnostics in the ASTUnit. + CaptureDroppedDiagnostics Capture(CaptureDiagnostics, Diags, + AST->Diagnostics); + for (unsigned I = 0; I != NumRemappedFiles; ++I) { // Create the file entry for the file that we're mapping from. const FileEntry *FromFile @@ -231,7 +274,8 @@ public: ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, Diagnostic &Diags, - bool OnlyLocalDecls) { + bool OnlyLocalDecls, + bool CaptureDiagnostics) { // Create the compiler instance to use for building the AST. CompilerInstance Clang; llvm::OwningPtr<ASTUnit> AST; @@ -245,8 +289,13 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, // Create the target instance. Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), Clang.getTargetOpts())); - if (!Clang.hasTarget()) - goto error; + if (!Clang.hasTarget()) { + Clang.takeSourceManager(); + Clang.takeFileManager(); + Clang.takeDiagnosticClient(); + Clang.takeDiagnostics(); + return 0; + } // Inform the target of the language options. // @@ -261,10 +310,14 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, // Create the AST unit. AST.reset(new ASTUnit(false)); - AST->OnlyLocalDecls = OnlyLocalDecls; AST->OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second; + // Capture any diagnostics that would otherwise be dropped. + CaptureDroppedDiagnostics Capture(CaptureDiagnostics, + Clang.getDiagnostics(), + AST->Diagnostics); + // Create a file manager object to provide access to and cache the filesystem. Clang.setFileManager(&AST->getFileManager()); @@ -312,7 +365,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, llvm::StringRef ResourceFilesPath, bool OnlyLocalDecls, RemappedFile *RemappedFiles, - unsigned NumRemappedFiles) { + unsigned NumRemappedFiles, + bool CaptureDiagnostics) { llvm::SmallVector<const char *, 16> Args; Args.push_back("<clang>"); // FIXME: Remove dummy argument. Args.insert(Args.end(), ArgBegin, ArgEnd); @@ -363,5 +417,6 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; CI->getFrontendOpts().DisableFree = true; - return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls); + return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls, + CaptureDiagnostics); } |