]> granicus.if.org Git - clang/commitdiff
Make changes to SDiagsWriter to make it work in combination with the ARC migrator:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 7 Dec 2011 05:52:12 +0000 (05:52 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 7 Dec 2011 05:52:12 +0000 (05:52 +0000)
-Allow it to be used with multiple BeginSourceFile/EndSourceFile calls; for this introduce
 a "finish" callback method in the DiagnosticConsumer. SDiagsWriter finishes up the serialization
 file inside this method.
-Make it independent of any particular DiagnosticsEngine; make it use the SourceManager of the
 Diagnostic object.
-Ignore null source ranges.

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

include/clang/Basic/Diagnostic.h
include/clang/Frontend/ChainedDiagnosticConsumer.h
include/clang/Frontend/SerializedDiagnosticPrinter.h
lib/Frontend/CompilerInstance.cpp
lib/Frontend/SerializedDiagnosticPrinter.cpp
test/ARCMT/check-with-serialized-diag.m [new file with mode: 0644]
test/Misc/serialized-diags-single-issue.c

index 78af10ce68cab0e502a4713c9bb59ef883d521ba..6fd81b05ba5eea4fda8aa8741314fc930febb8c9 100644 (file)
@@ -1078,6 +1078,10 @@ public:
   /// objects made available via \see BeginSourceFile() are inaccessible.
   virtual void EndSourceFile() {}
 
+  /// \brief Callback to inform the diagnostic client that processing of all
+  /// source files has ended.
+  virtual void finish() {}
+
   /// IncludeInDiagnosticCounts - This method (whose default implementation
   /// returns true) indicates whether the diagnostics handled by this
   /// DiagnosticConsumer should be included in the number of diagnostics
index f20cf6fcf4f2fc7b199f4eaae40e1b38e59159d1..b47fac52179e3e8144c7f3be4bcd7c4ac56c01cf 100644 (file)
@@ -42,6 +42,11 @@ public:
     Primary->EndSourceFile();
   }
 
+  virtual void finish() {
+    Secondary->finish();
+    Primary->finish();
+  }
+
   virtual bool IncludeInDiagnosticCounts() const {
     return Primary->IncludeInDiagnosticCounts();
   }
index af4390fb12889566632e13069425db39994e7292..c4f2322141ee08ef0d9474c50b29319fd3001b82 100644 (file)
@@ -52,8 +52,7 @@ enum RecordIDs {
 /// This allows wrapper tools for Clang to get diagnostics from Clang
 /// (via libclang) without needing to parse Clang's command line output.
 ///
-DiagnosticConsumer *create(llvm::raw_ostream *OS,
-                           DiagnosticsEngine &Diags);
+DiagnosticConsumer *create(llvm::raw_ostream *OS);
 
 } // end serialized_diags namespace
 } // end clang namespace
index 7b3fe7876bef6fdffb8a024f4758577276e90531..4463fa7f2c13b6c2e1b86cbbabea610c18bf8f25 100644 (file)
@@ -170,7 +170,7 @@ static void SetupSerializedDiagnostics(const DiagnosticOptions &DiagOpts,
   }
   
   DiagnosticConsumer *SerializedConsumer =
-    clang::serialized_diags::create(OS.take(), Diags);
+    clang::serialized_diags::create(OS.take());
 
   
   Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(),
@@ -660,6 +660,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
     }
   }
 
+  // Notify the diagnostic client that all files were processed.
+  getDiagnostics().getClient()->finish();
+
   if (getDiagnosticOpts().ShowCarets) {
     // We can have multiple diagnostics sharing one diagnostic client.
     // Get the total number of warnings/errors from the client.
index c773f81ce3bf5e52bedcad0cc4dcb0810d4ede64..04184f7f4b04900e8faa8f973285979ae3a2d1c9 100644 (file)
@@ -47,9 +47,8 @@ typedef llvm::SmallVectorImpl<uint64_t> RecordDataImpl;
   
 class SDiagsWriter : public DiagnosticConsumer {
 public:  
-  SDiagsWriter(DiagnosticsEngine &diags, llvm::raw_ostream *os) 
-    : LangOpts(0), Stream(Buffer), OS(os), Diags(diags),
-      inNonNoteDiagnostic(false)
+  explicit SDiagsWriter(llvm::raw_ostream *os) 
+    : LangOpts(0), Stream(Buffer), OS(os), inNonNoteDiagnostic(false)
   { 
     EmitPreamble();
   }
@@ -59,13 +58,13 @@ public:
   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                         const Diagnostic &Info);
   
-  void EndSourceFile();
-  
   void BeginSourceFile(const LangOptions &LO,
                        const Preprocessor *PP) {
     LangOpts = &LO;
   }
-  
+
+  virtual void finish();
+
   DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
     // It makes no sense to clone this.
     return 0;
@@ -82,7 +81,7 @@ private:
   void EmitMetaBlock();
   
   /// \brief Emit a record for a CharSourceRange.
-  void EmitCharSourceRange(CharSourceRange R);
+  void EmitCharSourceRange(CharSourceRange R, SourceManager &SM);
   
   /// \brief Emit the string information for the category for a diagnostic.
   unsigned getEmitCategory(unsigned DiagID);
@@ -92,14 +91,16 @@ private:
                                  const Diagnostic &Info);
   
   /// \brief Emit (lazily) the file string and retrieved the file identifier.
-  unsigned getEmitFile(SourceLocation Loc);
+  unsigned getEmitFile(SourceLocation Loc, SourceManager &SM);
   
   /// \brief Add SourceLocation information the specified record.
   void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
+                      SourceManager &SM,
                       unsigned TokSize = 0);
 
   /// \brief Add CharSourceRange information the specified record.
-  void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record);
+  void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record,
+                                  SourceManager &SM);
 
   /// \brief The version of the diagnostics file.
   enum { Version = 1 };
@@ -115,9 +116,6 @@ private:
   /// \brief The name of the diagnostics file.
   llvm::OwningPtr<llvm::raw_ostream> OS;
   
-  /// \brief The DiagnosticsEngine tied to all diagnostic locations.
-  DiagnosticsEngine &Diags;
-  
   /// \brief The set of constructed record abbreviations.
   AbbreviationMap Abbrevs;
 
@@ -147,8 +145,8 @@ private:
 
 namespace clang {
 namespace serialized_diags {
-DiagnosticConsumer *create(llvm::raw_ostream *OS, DiagnosticsEngine &Diags) {
-  return new SDiagsWriter(Diags, OS);
+DiagnosticConsumer *create(llvm::raw_ostream *OS) {
+  return new SDiagsWriter(OS);
 }
 } // end namespace serialized_diags
 } // end namespace clang
@@ -192,6 +190,7 @@ static void EmitRecordID(unsigned ID, const char *Name,
 
 void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
                                   RecordDataImpl &Record,
+                                  SourceManager &SM,
                                   unsigned TokSize) {
   if (Loc.isInvalid()) {
     // Emit a "sentinel" location.
@@ -202,28 +201,26 @@ void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
     return;
   }
 
-  SourceManager &SM = Diags.getSourceManager();
   Loc = SM.getSpellingLoc(Loc);
-  Record.push_back(getEmitFile(Loc));
+  Record.push_back(getEmitFile(Loc, SM));
   Record.push_back(SM.getSpellingLineNumber(Loc));
   Record.push_back(SM.getSpellingColumnNumber(Loc)+TokSize);
   Record.push_back(SM.getFileOffset(Loc));
 }
 
 void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
-                                              RecordDataImpl &Record) {
-  AddLocToRecord(Range.getBegin(), Record);
+                                              RecordDataImpl &Record,
+                                              SourceManager &SM) {
+  AddLocToRecord(Range.getBegin(), Record, SM);
   unsigned TokSize = 0;
   if (Range.isTokenRange())
     TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
-                                        Diags.getSourceManager(),
-                                        *LangOpts);
+                                        SM, *LangOpts);
   
-  AddLocToRecord(Range.getEnd(), Record, TokSize);
+  AddLocToRecord(Range.getEnd(), Record, SM, TokSize);
 }
 
-unsigned SDiagsWriter::getEmitFile(SourceLocation Loc) {
-  SourceManager &SM = Diags.getSourceManager();
+unsigned SDiagsWriter::getEmitFile(SourceLocation Loc, SourceManager &SM) {
   assert(Loc.isValid());
   const std::pair<FileID, unsigned> &LocInfo = SM.getDecomposedLoc(Loc);
   const FileEntry *FE = SM.getFileEntryForID(LocInfo.first);
@@ -248,10 +245,11 @@ unsigned SDiagsWriter::getEmitFile(SourceLocation Loc) {
   return entry;
 }
 
-void SDiagsWriter::EmitCharSourceRange(CharSourceRange R) {
+void SDiagsWriter::EmitCharSourceRange(CharSourceRange R,
+                                       SourceManager &SM) {
   Record.clear();
   Record.push_back(RECORD_SOURCE_RANGE);
-  AddCharSourceRangeToRecord(R, Record);
+  AddCharSourceRangeToRecord(R, Record, SM);
   Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_SOURCE_RANGE), Record);
 }
 
@@ -426,6 +424,7 @@ unsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
 
 void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                     const Diagnostic &Info) {
+  SourceManager &SM = Info.getSourceManager();
 
   if (DiagLevel != DiagnosticsEngine::Note) {
     if (inNonNoteDiagnostic) {
@@ -442,7 +441,7 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
   Record.clear();
   Record.push_back(RECORD_DIAG);
   Record.push_back(DiagLevel);
-  AddLocToRecord(Info.getLocation(), Record);    
+  AddLocToRecord(Info.getLocation(), Record, SM);
   // Emit the category string lazily and get the category ID.
   Record.push_back(getEmitCategory(Info.getID()));
   // Emit the diagnostic flag string lazily and get the mapped ID.
@@ -457,7 +456,8 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
   ArrayRef<CharSourceRange> Ranges = Info.getRanges();
   for (ArrayRef<CharSourceRange>::iterator it=Ranges.begin(), ei=Ranges.end();
        it != ei; ++it) {
-    EmitCharSourceRange(*it);    
+    if (it->isValid())
+      EmitCharSourceRange(*it, SM);
   }
 
   // Emit FixIts.
@@ -467,7 +467,7 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
       continue;
     Record.clear();
     Record.push_back(RECORD_FIXIT);
-    AddCharSourceRangeToRecord(fix.RemoveRange, Record);
+    AddCharSourceRangeToRecord(fix.RemoveRange, Record, SM);
     Record.push_back(fix.CodeToInsert.size());
     Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FIXIT), Record,
                               fix.CodeToInsert);    
@@ -480,7 +480,7 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
   }
 }
 
-void SDiagsWriter::EndSourceFile() {
+void SDiagsWriter::finish() {
   if (inNonNoteDiagnostic) {
     // Finish off any diagnostics we were in the process of emitting.
     Stream.ExitBlock();
diff --git a/test/ARCMT/check-with-serialized-diag.m b/test/ARCMT/check-with-serialized-diag.m
new file mode 100644 (file)
index 0000000..57742d9
--- /dev/null
@@ -0,0 +1,48 @@
+
+@protocol NSObject
+- (id)retain;
+- (unsigned)retainCount;
+- (oneway void)release;
+- (id)autorelease;
+@end
+
+@interface NSObject <NSObject> {}
+- (id)init;
+
++ (id)new;
++ (id)alloc;
+- (void)dealloc;
+
+- (void)finalize;
+
+- (id)copy;
+- (id)mutableCopy;
+@end
+
+@interface A : NSObject
+@end
+
+struct UnsafeS {
+  A *__unsafe_unretained unsafeObj;
+};
+
+id global_foo;
+
+void test1(A *a, struct UnsafeS *unsafeS) {
+  [unsafeS->unsafeObj retain];
+  id foo = [unsafeS->unsafeObj retain]; // no warning.
+  [global_foo retain];
+  [a retainCount];
+}
+
+// RUN: not %clang_cc1 -arcmt-check -triple x86_64-apple-darwin10 %s -serialize-diagnostic-file %t.diag
+// RUN: c-index-test -read-diagnostics %t.diag 2>&1 | FileCheck %s
+
+// CHECK: {{.*}}check-with-serialized-diag.m:32:4: error: [rewriter] it is not safe to remove 'retain' message on an __unsafe_unretained type
+// CHECK-NEXT: {{.*}}check-with-serialized-diag.m:34:4: error: [rewriter] it is not safe to remove 'retain' message on a global variable
+// CHECK-NEXT: {{.*}}check-with-serialized-diag.m:32:4: error: ARC forbids explicit message send of 'retain'
+// CHECK-NEXT: Range: {{.*}}check-with-serialized-diag.m:32:23 {{.*}}check-with-serialized-diag.m:32:29
+// CHECK-NEXT: {{.*}}check-with-serialized-diag.m:34:4: error: ARC forbids explicit message send of 'retain'
+// CHECK-NEXT: Range: {{.*}}check-with-serialized-diag.m:34:15 {{.*}}check-with-serialized-diag.m:34:21
+// CHECK-NEXT: {{.*}}check-with-serialized-diag.m:35:4: error: ARC forbids explicit message send of 'retainCount'
+// CHECK-NEXT: Range: {{.*}}check-with-serialized-diag.m:35:6 {{.*}}check-with-serialized-diag.m:35:17
index c24531617e9be2abc292a6bbee5daafd11e9bf02..27f8b8b602ff1f5db02a01d9d560ab81bd04be23 100644 (file)
@@ -13,4 +13,21 @@ void foo() {
 // CHECK: {{.*}}serialized-diags-single-issue.c:3:12: warning: variable 'voodoo' is uninitialized when used here [-Wuninitialized]
 // CHECK: Range: {{.*}}serialized-diags-single-issue.c:3:12 {{.*}}serialized-diags-single-issue.c:3:18
 // CHECK: +-{{.*}}serialized-diags-single-issue.c:2:13: note: initialize the variable 'voodoo' to silence this warning []
-// CHECK: +-FIXIT: {{.*}}serialized-diags-single-issue.c:2:13 - {{.*}}serialized-diags-single-issue.c:2:13): " = 0"
\ No newline at end of file
+// CHECK: +-FIXIT: {{.*}}serialized-diags-single-issue.c:2:13 - {{.*}}serialized-diags-single-issue.c:2:13): " = 0"
+
+// Test that we handle serializing diagnostics for multiple source files
+// RUN: %clang_cc1 -Wall -fsyntax-only %s %s -serialize-diagnostic-file %t
+// RUN: c-index-test -read-diagnostics %t 2>&1 | FileCheck -check-prefix=CHECK-MULT %s
+// RUN: rm -f %t
+
+// CHECK-MULT: {{.*}}serialized-diags-single-issue.c:3:12: warning: variable 'voodoo' is uninitialized when used here [-Wuninitialized]
+// CHECK-MULT: Range: {{.*}}serialized-diags-single-issue.c:3:12 {{.*}}serialized-diags-single-issue.c:3:18
+// CHECK-MULT: +-{{.*}}serialized-diags-single-issue.c:2:13: note: initialize the variable 'voodoo' to silence this warning []
+// CHECK-MULT: +-FIXIT: {{.*}}serialized-diags-single-issue.c:2:13 - {{.*}}serialized-diags-single-issue.c:2:13): " = 0"
+
+// CHECK-MULT: {{.*}}serialized-diags-single-issue.c:3:12: warning: variable 'voodoo' is uninitialized when used here [-Wuninitialized]
+// CHECK-MULT: Range: {{.*}}serialized-diags-single-issue.c:3:12 {{.*}}serialized-diags-single-issue.c:3:18
+// CHECK-MULT: +-{{.*}}serialized-diags-single-issue.c:2:13: note: initialize the variable 'voodoo' to silence this warning []
+// CHECK-MULT: +-FIXIT: {{.*}}serialized-diags-single-issue.c:2:13 - {{.*}}serialized-diags-single-issue.c:2:13): " = 0"
+
+// CHECK-MULT: Number of diagnostics: 2