diff options
-rw-r--r-- | include/clang/Basic/Diagnostic.h | 4 | ||||
-rw-r--r-- | include/clang/Frontend/ChainedDiagnosticConsumer.h | 5 | ||||
-rw-r--r-- | include/clang/Frontend/SerializedDiagnosticPrinter.h | 3 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/SerializedDiagnosticPrinter.cpp | 58 | ||||
-rw-r--r-- | test/ARCMT/check-with-serialized-diag.m | 48 | ||||
-rw-r--r-- | test/Misc/serialized-diags-single-issue.c | 19 |
7 files changed, 109 insertions, 33 deletions
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 78af10ce68..6fd81b05ba 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -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 diff --git a/include/clang/Frontend/ChainedDiagnosticConsumer.h b/include/clang/Frontend/ChainedDiagnosticConsumer.h index f20cf6fcf4..b47fac5217 100644 --- a/include/clang/Frontend/ChainedDiagnosticConsumer.h +++ b/include/clang/Frontend/ChainedDiagnosticConsumer.h @@ -42,6 +42,11 @@ public: Primary->EndSourceFile(); } + virtual void finish() { + Secondary->finish(); + Primary->finish(); + } + virtual bool IncludeInDiagnosticCounts() const { return Primary->IncludeInDiagnosticCounts(); } diff --git a/include/clang/Frontend/SerializedDiagnosticPrinter.h b/include/clang/Frontend/SerializedDiagnosticPrinter.h index af4390fb12..c4f2322141 100644 --- a/include/clang/Frontend/SerializedDiagnosticPrinter.h +++ b/include/clang/Frontend/SerializedDiagnosticPrinter.h @@ -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 diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 7b3fe7876b..4463fa7f2c 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -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. diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp index c773f81ce3..04184f7f4b 100644 --- a/lib/Frontend/SerializedDiagnosticPrinter.cpp +++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp @@ -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 index 0000000000..57742d92c5 --- /dev/null +++ b/test/ARCMT/check-with-serialized-diag.m @@ -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 diff --git a/test/Misc/serialized-diags-single-issue.c b/test/Misc/serialized-diags-single-issue.c index c24531617e..27f8b8b602 100644 --- a/test/Misc/serialized-diags-single-issue.c +++ b/test/Misc/serialized-diags-single-issue.c @@ -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 |