forked from OSchip/llvm-project
Make changes to SDiagsWriter to make it work in combination with the ARC migrator:
-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. llvm-svn: 146020
This commit is contained in:
parent
2b0b43cf56
commit
7910d7b72a
|
@ -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
|
||||
|
|
|
@ -42,6 +42,11 @@ public:
|
|||
Primary->EndSourceFile();
|
||||
}
|
||||
|
||||
virtual void finish() {
|
||||
Secondary->finish();
|
||||
Primary->finish();
|
||||
}
|
||||
|
||||
virtual bool IncludeInDiagnosticCounts() const {
|
||||
return Primary->IncludeInDiagnosticCounts();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
|
@ -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"
|
||||
// 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
|
||||
|
|
Loading…
Reference in New Issue