aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/Diagnostic.h8
-rw-r--r--include/clang/Frontend/ASTUnit.h18
-rw-r--r--lib/Frontend/ASTUnit.cpp56
-rw-r--r--test/Index/Inputs/preamble.h7
-rw-r--r--test/Index/preamble.c4
5 files changed, 74 insertions, 19 deletions
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index c67de985a0..4371bdda0a 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -398,6 +398,10 @@ public:
unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; }
unsigned getNumWarnings() const { return NumWarnings; }
+ void setNumWarnings(unsigned NumWarnings) {
+ this->NumWarnings = NumWarnings;
+ }
+
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
@@ -943,7 +947,9 @@ public:
Diagnostic::Level getLevel() const { return Level; }
const FullSourceLoc &getLocation() const { return Loc; }
llvm::StringRef getMessage() const { return Message; }
-
+
+ void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
+
typedef std::vector<CharSourceRange>::const_iterator range_iterator;
range_iterator range_begin() const { return Ranges.begin(); }
range_iterator range_end() const { return Ranges.end(); }
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index b9db4beafd..ad622c55e6 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -149,7 +149,23 @@ private:
/// the main file when it has been padded for use with the precompiled
/// preamble.
llvm::MemoryBuffer *SavedMainFileBuffer;
-
+
+ /// \brief The number of warnings that occurred while parsing the preamble.
+ ///
+ /// This value will be used to restore the state of the \c Diagnostic object
+ /// when re-using the precompiled preamble. Note that only the
+ /// number of warnings matters, since we will not save the preamble
+ /// when any errors are present.
+ unsigned NumWarningsInPreamble;
+
+ /// \brief The number of diagnostics that were stored when parsing
+ /// the precompiled preamble.
+ ///
+ /// This value is used to determine how many of the stored
+ /// diagnostics should be retained when reparsing in the presence of
+ /// a precompiled preamble.
+ unsigned NumStoredDiagnosticsInPreamble;
+
/// \brief The group of timers associated with this translation unit.
llvm::OwningPtr<llvm::TimerGroup> TimerGroup;
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index d7597bcf5b..b36a338c19 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -381,9 +381,11 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
// Clear out old caches and data.
TopLevelDecls.clear();
- StoredDiagnostics.clear();
CleanTemporaryFiles();
PreprocessedEntitiesByFile.clear();
+
+ if (!OverrideMainBuffer)
+ StoredDiagnostics.clear();
// Capture any diagnostics that would otherwise be dropped.
CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
@@ -409,6 +411,17 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
// 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) {
+ FullSourceLoc Loc(StoredDiagnostics[I].getLocation(),
+ getSourceManager());
+ StoredDiagnostics[I].setLocation(Loc);
+ }
}
llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
@@ -430,11 +443,9 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
Act->EndSourceFile();
// Remove the overridden buffer we used for the preamble.
- if (OverrideMainBuffer) {
+ if (OverrideMainBuffer)
PreprocessorOpts.eraseRemappedFile(
PreprocessorOpts.remapped_file_buffer_end() - 1);
- PreprocessorOpts.DisablePCHValidation = true;
- }
Clang.takeDiagnosticClient();
@@ -627,7 +638,7 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
NewPreamble.second.first) == 0) {
// The preamble has not changed. We may be able to re-use the precompiled
// preamble.
-
+
// Check that none of the files used by the preamble have changed.
bool AnyFileChanged = false;
@@ -687,7 +698,19 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
}
if (!AnyFileChanged) {
- // Okay! Re-use the precompiled preamble.
+ // Okay! We can re-use the precompiled preamble.
+
+ // Set the state of the diagnostic object to mimic its state
+ // after parsing the preamble.
+ getDiagnostics().Reset();
+ getDiagnostics().setNumWarnings(NumWarningsInPreamble);
+ if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble)
+ StoredDiagnostics.erase(
+ StoredDiagnostics.begin() + NumStoredDiagnosticsInPreamble,
+ StoredDiagnostics.end());
+
+ // Create a version of the main file buffer that is padded to
+ // buffer size we reserved when creating the preamble.
return CreatePaddedMainFileBuffer(NewPreamble.first,
CreatedPreambleBuffer,
PreambleReservedSize,
@@ -718,6 +741,13 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
else
PreambleReservedSize *= 2;
+ // Save the preamble text for later; we'll need to compare against it for
+ // subsequent reparses.
+ Preamble.assign(NewPreamble.first->getBufferStart(),
+ NewPreamble.first->getBufferStart()
+ + NewPreamble.second.first);
+ PreambleEndsAtStartOfLine = NewPreamble.second.second;
+
llvm::MemoryBuffer *PreambleBuffer
= llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
FrontendOpts.Inputs[0].second);
@@ -726,13 +756,6 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
' ', PreambleReservedSize - Preamble.size() - 1);
const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
-
- // Save the preamble text for later; we'll need to compare against it for
- // subsequent reparses.
- Preamble.assign(NewPreamble.first->getBufferStart(),
- NewPreamble.first->getBufferStart()
- + NewPreamble.second.first);
- PreambleEndsAtStartOfLine = NewPreamble.second.second;
// Remap the main source file to the preamble buffer.
llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
@@ -786,7 +809,7 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
// Capture any diagnostics that would otherwise be dropped.
CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
- Clang.getDiagnostics(),
+ getDiagnostics(),
StoredDiagnostics);
// Create a file manager object to provide access to and cache the filesystem.
@@ -833,6 +856,8 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
// Keep track of the preamble we precompiled.
PreambleFile = FrontendOpts.OutputFile;
+ NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
+ NumWarningsInPreamble = getDiagnostics().getNumWarnings();
// Keep track of all of the files that the source manager knows about,
// so we can verify whether they have changed or not.
@@ -1003,7 +1028,8 @@ bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
OverrideMainBuffer = BuildPrecompiledPreamble();
// Clear out the diagnostics state.
- getDiagnostics().Reset();
+ if (!OverrideMainBuffer)
+ getDiagnostics().Reset();
// Parse the sources
bool Result = Parse(OverrideMainBuffer);
diff --git a/test/Index/Inputs/preamble.h b/test/Index/Inputs/preamble.h
index e588c12ddc..b59c234e17 100644
--- a/test/Index/Inputs/preamble.h
+++ b/test/Index/Inputs/preamble.h
@@ -1 +1,6 @@
-int bar(int);
+inline int bar(int i) {
+ int *ptr = 0;
+ float *ptr1;
+ ptr = ptr1;
+ return 0;
+}
diff --git a/test/Index/preamble.c b/test/Index/preamble.c
index f6d878b9eb..e1a64c2fbe 100644
--- a/test/Index/preamble.c
+++ b/test/Index/preamble.c
@@ -3,6 +3,8 @@
int wibble(int);
// RUN: %clang -x c-header -o %t.pch %S/Inputs/prefix.h
-// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -I %S/Inputs -include %t %s | FileCheck %s
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -I %S/Inputs -include %t %s 2> %t.stderr.txt | FileCheck %s
+// RUN: FileCheck -check-prefix CHECK-DIAG %s < %t.stderr.txt
// CHECK: preamble.c:3:5: FunctionDecl=wibble:3:5 Extent=[3:5 - 3:16]
// CHECK: preamble.c:3:15: ParmDecl=:3:15 (Definition) Extent=[3:12 - 3:16]
+// CHECK-DIAG: preamble.h:4:7:{4:9-4:13}: warning: incompatible pointer types assigning to 'int *' from 'float *'