[cfe-commits] r116285 - in /cfe/trunk: include/clang/Frontend/ASTUnit.h lib/Frontend/ASTUnit.cpp test/Index/complete-driver-errors.c tools/libclang/CIndexDiagnostic.cpp
Douglas Gregor
dgregor at apple.com
Mon Oct 11 17:50:20 PDT 2010
Author: dgregor
Date: Mon Oct 11 19:50:20 2010
New Revision: 116285
URL: http://llvm.org/viewvc/llvm-project?rev=116285&view=rev
Log:
When we load an ASTUnit from command-line arguments, hold on to the
diagnostics produced by the driver itself. Previously, we were
allowing these to either be dropped or to slip through to stderr.
Fixes <rdar://problem/7595339>.
Added:
cfe/trunk/test/Index/complete-driver-errors.c
Modified:
cfe/trunk/include/clang/Frontend/ASTUnit.h
cfe/trunk/lib/Frontend/ASTUnit.cpp
cfe/trunk/tools/libclang/CIndexDiagnostic.cpp
Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=116285&r1=116284&r2=116285&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Mon Oct 11 19:50:20 2010
@@ -115,6 +115,13 @@
/// translation unit.
llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
+ /// \brief The number of stored diagnostics that come from the driver
+ /// itself.
+ ///
+ /// Diagnostics that come from the driver are retained from one parse to
+ /// the next.
+ unsigned NumStoredDiagnosticsFromDriver;
+
/// \brief Temporary files that should be removed when the ASTUnit is
/// destroyed.
llvm::SmallVector<llvm::sys::Path, 4> TemporaryFiles;
@@ -483,6 +490,19 @@
unsigned NumRemappedFiles = 0,
bool CaptureDiagnostics = false);
+private:
+ /// \brief Helper function for \c LoadFromCompilerInvocation() and
+ /// \c LoadFromCommandLine(), which loads an AST from a compiler invocation.
+ ///
+ /// \param PrecompilePreamble Whether to precompile the preamble of this
+ /// translation unit, to improve the performance of reparsing.
+ ///
+ /// \returns \c true if a catastrophic failure occurred (which means that the
+ /// \c ASTUnit itself is invalid), or \c false otherwise.
+ bool LoadFromCompilerInvocation(bool PrecompilePreamble);
+
+public:
+
/// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
/// CompilerInvocation object.
///
Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=116285&r1=116284&r2=116285&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Mon Oct 11 19:50:20 2010
@@ -52,7 +52,8 @@
ASTUnit::ASTUnit(bool _MainFileIsAST)
: CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
- CompleteTranslationUnit(true), ConcurrencyCheckValue(CheckUnlocked),
+ CompleteTranslationUnit(true), NumStoredDiagnosticsFromDriver(0),
+ ConcurrencyCheckValue(CheckUnlocked),
PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
ShouldCacheCodeCompletionResults(false),
NumTopLevelDeclsAtLastCompletionCache(0),
@@ -714,7 +715,9 @@
PreprocessedEntitiesByFile.clear();
if (!OverrideMainBuffer) {
- StoredDiagnostics.clear();
+ StoredDiagnostics.erase(
+ StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
+ StoredDiagnostics.end());
TopLevelDeclsInPreamble.clear();
}
@@ -737,19 +740,21 @@
PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
PreprocessorOpts.DisablePCHValidation = true;
- // Keep track of the override buffer;
- SavedMainFileBuffer = OverrideMainBuffer;
-
// The stored diagnostic has the old source manager in it; update
// the locations to refer into the new source manager. Since we've
// been careful to make sure that the source manager's state
// before and after are identical, so that we can reuse the source
// location itself.
- for (unsigned I = 0, N = StoredDiagnostics.size(); I != N; ++I) {
+ for (unsigned I = NumStoredDiagnosticsFromDriver,
+ N = StoredDiagnostics.size();
+ I < N; ++I) {
FullSourceLoc Loc(StoredDiagnostics[I].getLocation(),
getSourceManager());
StoredDiagnostics[I].setLocation(Loc);
}
+
+ // Keep track of the override buffer;
+ SavedMainFileBuffer = OverrideMainBuffer;
} else {
PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
PreprocessorOpts.PrecompiledPreambleBytes.second = false;
@@ -1201,7 +1206,9 @@
// Clear out old caches and data.
getDiagnostics().Reset();
ProcessWarningOptions(getDiagnostics(), Clang.getDiagnosticOpts());
- StoredDiagnostics.clear();
+ StoredDiagnostics.erase(
+ StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
+ StoredDiagnostics.end());
TopLevelDecls.clear();
TopLevelDeclsInPreamble.clear();
@@ -1306,6 +1313,41 @@
return 0;
}
+bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
+ if (!Invocation)
+ return true;
+
+ // We'll manage file buffers ourselves.
+ Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;
+ Invocation->getFrontendOpts().DisableFree = false;
+
+ if (getenv("LIBCLANG_TIMING"))
+ TimerGroup.reset(
+ new llvm::TimerGroup(Invocation->getFrontendOpts().Inputs[0].second));
+
+
+ llvm::MemoryBuffer *OverrideMainBuffer = 0;
+ // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble.
+ if (PrecompilePreamble && !Invocation->getLangOpts().CPlusPlus) {
+ PreambleRebuildCounter = 1;
+ OverrideMainBuffer
+ = getMainBufferWithPrecompiledPreamble(*Invocation);
+ }
+
+ llvm::Timer *ParsingTimer = 0;
+ if (TimerGroup.get()) {
+ ParsingTimer = new llvm::Timer("Initial parse", *TimerGroup);
+ ParsingTimer->startTimer();
+ Timers.push_back(ParsingTimer);
+ }
+
+ bool Failed = Parse(OverrideMainBuffer);
+ if (ParsingTimer)
+ ParsingTimer->stopTimer();
+
+ return Failed;
+}
+
ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
bool OnlyLocalDecls,
@@ -1329,33 +1371,8 @@
AST->CompleteTranslationUnit = CompleteTranslationUnit;
AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
AST->Invocation.reset(CI);
- CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
-
- if (getenv("LIBCLANG_TIMING"))
- AST->TimerGroup.reset(
- new llvm::TimerGroup(CI->getFrontendOpts().Inputs[0].second));
-
-
- llvm::MemoryBuffer *OverrideMainBuffer = 0;
- // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble.
- if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) {
- AST->PreambleRebuildCounter = 1;
- OverrideMainBuffer
- = AST->getMainBufferWithPrecompiledPreamble(*AST->Invocation);
- }
- llvm::Timer *ParsingTimer = 0;
- if (AST->TimerGroup.get()) {
- ParsingTimer = new llvm::Timer("Initial parse", *AST->TimerGroup);
- ParsingTimer->startTimer();
- AST->Timers.push_back(ParsingTimer);
- }
-
- bool Failed = AST->Parse(OverrideMainBuffer);
- if (ParsingTimer)
- ParsingTimer->stopTimer();
-
- return Failed? 0 : AST.take();
+ return AST->LoadFromCompilerInvocation(PrecompilePreamble)? 0 : AST.take();
}
ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
@@ -1387,41 +1404,50 @@
// also want to force it to use clang.
Args.push_back("-fsyntax-only");
- // FIXME: We shouldn't have to pass in the path info.
- driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
- "a.out", false, false, *Diags);
-
- // Don't check that inputs exist, they have been remapped.
- TheDriver.setCheckInputsExist(false);
-
- llvm::OwningPtr<driver::Compilation> C(
- TheDriver.BuildCompilation(Args.size(), Args.data()));
-
- // We expect to get back exactly one command job, if we didn't something
- // failed.
- const driver::JobList &Jobs = C->getJobs();
- if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
- llvm::SmallString<256> Msg;
- llvm::raw_svector_ostream OS(Msg);
- C->PrintJob(OS, C->getJobs(), "; ", true);
- Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
- return 0;
- }
-
- const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
- if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
- Diags->Report(diag::err_fe_expected_clang_command);
- return 0;
- }
+ llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
+
+ llvm::OwningPtr<CompilerInvocation> CI;
+ {
+ CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
+ *Diags,
+ StoredDiagnostics);
+
+ // FIXME: We shouldn't have to pass in the path info.
+ driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
+ "a.out", false, false, *Diags);
+
+ // Don't check that inputs exist, they have been remapped.
+ TheDriver.setCheckInputsExist(false);
+
+ llvm::OwningPtr<driver::Compilation> C(
+ TheDriver.BuildCompilation(Args.size(), Args.data()));
+
+ // We expect to get back exactly one command job, if we didn't something
+ // failed.
+ const driver::JobList &Jobs = C->getJobs();
+ if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
+ llvm::SmallString<256> Msg;
+ llvm::raw_svector_ostream OS(Msg);
+ C->PrintJob(OS, C->getJobs(), "; ", true);
+ Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
+ return 0;
+ }
- const driver::ArgStringList &CCArgs = Cmd->getArguments();
- llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
- CompilerInvocation::CreateFromArgs(*CI,
- const_cast<const char **>(CCArgs.data()),
- const_cast<const char **>(CCArgs.data()) +
- CCArgs.size(),
- *Diags);
+ const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
+ if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
+ Diags->Report(diag::err_fe_expected_clang_command);
+ return 0;
+ }
+ const driver::ArgStringList &CCArgs = Cmd->getArguments();
+ CI.reset(new CompilerInvocation);
+ CompilerInvocation::CreateFromArgs(*CI,
+ const_cast<const char **>(CCArgs.data()),
+ const_cast<const char **>(CCArgs.data()) +
+ CCArgs.size(),
+ *Diags);
+ }
+
// Override any files that need remapping
for (unsigned I = 0; I != NumRemappedFiles; ++I)
CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
@@ -1430,11 +1456,19 @@
// Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
- CI->getFrontendOpts().DisableFree = false;
- return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
- CaptureDiagnostics, PrecompilePreamble,
- CompleteTranslationUnit,
- CacheCodeCompletionResults);
+ // Create the AST unit.
+ llvm::OwningPtr<ASTUnit> AST;
+ AST.reset(new ASTUnit(false));
+ AST->Diagnostics = Diags;
+ AST->CaptureDiagnostics = CaptureDiagnostics;
+ AST->OnlyLocalDecls = OnlyLocalDecls;
+ AST->CompleteTranslationUnit = CompleteTranslationUnit;
+ AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
+ AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
+ AST->NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
+ AST->StoredDiagnostics.swap(StoredDiagnostics);
+ AST->Invocation.reset(CI.take());
+ return AST->LoadFromCompilerInvocation(PrecompilePreamble)? 0 : AST.take();
}
bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
@@ -1832,6 +1866,9 @@
// If the main file has been overridden due to the use of a preamble,
// make that override happen and introduce the preamble.
+ StoredDiagnostics.insert(StoredDiagnostics.end(),
+ this->StoredDiagnostics.begin(),
+ this->StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver);
if (OverrideMainBuffer) {
PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
@@ -1843,12 +1880,14 @@
// The stored diagnostics have the old source manager. Copy them
// to our output set of stored diagnostics, updating the source
// manager to the one we were given.
- for (unsigned I = 0, N = this->StoredDiagnostics.size(); I != N; ++I) {
+ for (unsigned I = NumStoredDiagnosticsFromDriver,
+ N = this->StoredDiagnostics.size();
+ I < N; ++I) {
StoredDiagnostics.push_back(this->StoredDiagnostics[I]);
FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SourceMgr);
StoredDiagnostics[I].setLocation(Loc);
}
-
+
OwnedBuffers.push_back(OverrideMainBuffer);
} else {
PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
Added: cfe/trunk/test/Index/complete-driver-errors.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-driver-errors.c?rev=116285&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-driver-errors.c (added)
+++ cfe/trunk/test/Index/complete-driver-errors.c Mon Oct 11 19:50:20 2010
@@ -0,0 +1,23 @@
+int *blah = 1;
+
+int
+
+// Test driver errors with code completion
+// RUN: c-index-test -code-completion-at=%s:4:1 -std= %s 2> %t | FileCheck -check-prefix=CHECK-RESULTS %s
+// RUN: FileCheck -check-prefix=CHECK-DIAGS %s < %t
+// CHECK-RESULTS: NotImplemented:{TypedText const} (30)
+// CHECK-RESULTS: NotImplemented:{TypedText restrict} (30)
+// CHECK-RESULTS: NotImplemented:{TypedText volatile} (30)
+
+// Test driver errors with parsing
+// RUN: c-index-test -test-load-source all -std= %s 2> %t | FileCheck -check-prefix=CHECK-LOAD %s
+// RUN: FileCheck -check-prefix=CHECK-DIAGS %s < %t
+// CHECK-LOAD: complete-driver-errors.c:1:6: VarDecl=blah:1:6
+
+// CHECK-DIAGS: error: invalid value '' in '-std='
+// CHECK-DIAGS: complete-driver-errors.c:1:6:{1:13-1:14}: warning: incompatible integer to pointer conversion initializing 'int *' with an expression of type 'int'
+// Test driver errors with code completion and precompiled preamble
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:4:1 -std= %s 2> %t | FileCheck -check-prefix=CHECK-RESULTS %s
+// RUN: FileCheck -check-prefix=CHECK-DIAGS %s < %t
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source all -std= %s 2> %t | FileCheck -check-prefix=CHECK-LOAD %s
+// RUN: FileCheck -check-prefix=CHECK-DIAGS %s < %t
Modified: cfe/trunk/tools/libclang/CIndexDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexDiagnostic.cpp?rev=116285&r1=116284&r2=116285&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexDiagnostic.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexDiagnostic.cpp Mon Oct 11 19:50:20 2010
@@ -56,10 +56,6 @@
CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
- // Ignore diagnostics that should be ignored.
- if (Severity == CXDiagnostic_Ignored)
- return createCXString("");
-
llvm::SmallString<256> Str;
llvm::raw_svector_ostream Out(Str);
@@ -101,9 +97,9 @@
if (PrintedRange)
Out << ":";
}
+
+ Out << " ";
}
-
- Out << " ";
}
/* Print warning/error/etc. */
More information about the cfe-commits
mailing list