aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/ASTUnit.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-02-18 18:08:43 +0000
committerDouglas Gregor <dgregor@apple.com>2010-02-18 18:08:43 +0000
commita88084b78fd4ca5d3d858c14b02414f8cc399f02 (patch)
tree8d45285d7831d594f76f9a0a1edaa4436b090ac5 /lib/Frontend/ASTUnit.cpp
parent8b6765fb563a5b03d128d8f53b9b3986128a3405 (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.cpp69
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);
}