]> granicus.if.org Git - clang/commitdiff
When using a precompiled preamble, save the diagnostics produced when
authorDouglas Gregor <dgregor@apple.com>
Mon, 2 Aug 2010 20:51:39 +0000 (20:51 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 2 Aug 2010 20:51:39 +0000 (20:51 +0000)
creating the preamble and "replay" them when reusing the
preamble. Also, fix a thinko in the copying of the preamble when
building the precompiled preamble.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110061 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Diagnostic.h
include/clang/Frontend/ASTUnit.h
lib/Frontend/ASTUnit.cpp
test/Index/Inputs/preamble.h
test/Index/preamble.c

index c67de985a023a2e877eccc422c63c1a5d1c6b5b2..4371bdda0a8602bf0dd421856d19418b9faebcb3 100644 (file)
@@ -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(); }
index b9db4beafd46c991754bb9e91c7ecaa0fa87418e..ad622c55e65cc3b7b1cff3eeff53c3adc09b119b 100644 (file)
@@ -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;  
   
index d7597bcf5b182e9968b6c57de97f6f9893444d29..b36a338c196da7342bcd844cd6fa93d3426dcf1e 100644 (file)
@@ -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);  
index e588c12ddcb5e937990f91be9b0417c59012139c..b59c234e1732f812b192f1db8949359efc977cb9 100644 (file)
@@ -1 +1,6 @@
-int bar(int);
+inline int bar(int i) {
+  int *ptr = 0;
+  float *ptr1;
+  ptr = ptr1;
+  return 0;
+}
index f6d878b9eb98c83ef1633707c9c013cb4eaaee47..e1a64c2fbe186f0510f4e01406529f0ac59fdb64 100644 (file)
@@ -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 *'