]> granicus.if.org Git - clang/commitdiff
Serialized diagnostic severity levels should be stable.
authorJordan Rose <jordan_rose@apple.com>
Mon, 3 Mar 2014 18:29:52 +0000 (18:29 +0000)
committerJordan Rose <jordan_rose@apple.com>
Mon, 3 Mar 2014 18:29:52 +0000 (18:29 +0000)
Serialized diagnostics were accidentally using the AST diagnostic level values
rather than a dedicated stable enum, so the addition of "remark" broke the
reading of existing serialized diagnostics files. I've added a .dia file
generated from Xcode 5's Clang to make sure we don't break this in the future.

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

include/clang/Frontend/SerializedDiagnosticPrinter.h
lib/Frontend/SerializedDiagnosticPrinter.cpp
test/Misc/Inputs/serialized-diags-stable.dia [new file with mode: 0644]
test/Misc/serialized-diags-stable.c [new file with mode: 0644]
tools/libclang/CXLoadedDiagnostic.cpp

index 117771d15791e613d3eb20346a83fd66f695f6ce..4dda1fa4b655be6f2f9528bfe06cd2804eecfa90 100644 (file)
@@ -46,6 +46,19 @@ enum RecordIDs {
   RECORD_LAST = RECORD_FIXIT
 };
 
+/// A stable version of DiagnosticIDs::Level.
+///
+/// Do not change the order of values in this enum, and please increment the
+/// serialized diagnostics version number when you add to it.
+enum Level {
+  Ignored = 0,
+  Note,
+  Warning,
+  Error,
+  Fatal,
+  Remark
+};
+
 /// \brief Returns a DiagnosticConsumer that serializes diagnostics to
 ///  a bitcode file.
 ///
index 6514321f228dce1f122dbbd76ffc7620bd770dcf..bed52b5361bfdb728482b3a0a82eeddb5b0ff5ca 100644 (file)
@@ -174,7 +174,7 @@ private:
                                   const SourceManager &SM);
 
   /// \brief The version of the diagnostics file.
-  enum { Version = 1 };
+  enum { Version = 2 };
 
   /// \brief Language options, which can differ from one clone of this client
   /// to another.
@@ -566,6 +566,21 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                           &Info);
 }
 
+static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) {
+  switch (Level) {
+#define CASE(X) case DiagnosticsEngine::X: return serialized_diags::X;
+  CASE(Ignored)
+  CASE(Note)
+  CASE(Remark)
+  CASE(Warning)
+  CASE(Error)
+  CASE(Fatal)
+#undef CASE
+  }
+
+  llvm_unreachable("invalid diagnostic level");
+}
+
 void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
                                          PresumedLoc PLoc,
                                          DiagnosticsEngine::Level Level,
@@ -579,7 +594,7 @@ void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
   // Emit the RECORD_DIAG record.
   Record.clear();
   Record.push_back(RECORD_DIAG);
-  Record.push_back(Level);
+  Record.push_back(getStableLevel(Level));
   AddLocToRecord(Loc, SM, PLoc, Record);
 
   if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
diff --git a/test/Misc/Inputs/serialized-diags-stable.dia b/test/Misc/Inputs/serialized-diags-stable.dia
new file mode 100644 (file)
index 0000000..acdaad2
Binary files /dev/null and b/test/Misc/Inputs/serialized-diags-stable.dia differ
diff --git a/test/Misc/serialized-diags-stable.c b/test/Misc/serialized-diags-stable.c
new file mode 100644 (file)
index 0000000..29b85f4
--- /dev/null
@@ -0,0 +1,20 @@
+// RUN: rm -f %t
+// RUN: not %clang -Wall -fsyntax-only %s --serialize-diagnostics %t.dia > /dev/null 2>&1
+// RUN: c-index-test -read-diagnostics %t.dia 2>&1 | FileCheck %s
+
+// RUN: c-index-test -read-diagnostics %S/Inputs/serialized-diags-stable.dia 2>&1 | FileCheck %s
+
+int foo() {
+  // CHECK: serialized-diags-stable.c:[[@LINE+2]]:1: warning: control reaches end of non-void function [-Wreturn-type] [Semantic Issue]
+  // CHECK-NEXT: Number FIXITs = 0
+}
+
+// CHECK: serialized-diags-stable.c:[[@LINE+5]]:13: error: redefinition of 'bar' as different kind of symbol [] [Semantic Issue]
+// CHECK-NEXT: Number FIXITs = 0
+// CHECK-NEXT: +-/Volumes/Lore/llvm-public/clang/test/Misc/serialized-diags-stable.c:[[@LINE+2]]:6: note: previous definition is here [] []
+// CHECK-NEXT: Number FIXITs = 0
+void bar() {}
+typedef int bar;
+
+
+// CHECK-LABEL: Number of diagnostics: 2
index e82ff95da15026fbeee46d5cc76a3d7c56fe83ee..86db08b1230fc1f0b10776e61ec0b9b5721e717a 100644 (file)
@@ -67,13 +67,19 @@ CXLoadedDiagnostic::~CXLoadedDiagnostic() {}
 //===----------------------------------------------------------------------===//
 
 CXDiagnosticSeverity CXLoadedDiagnostic::getSeverity() const {
-  // FIXME: possibly refactor with logic in CXStoredDiagnostic.
-  switch (severity) {
-    case DiagnosticsEngine::Ignored: return CXDiagnostic_Ignored;
-    case DiagnosticsEngine::Note:    return CXDiagnostic_Note;
-    case DiagnosticsEngine::Warning: return CXDiagnostic_Warning;
-    case DiagnosticsEngine::Error:   return CXDiagnostic_Error;
-    case DiagnosticsEngine::Fatal:   return CXDiagnostic_Fatal;
+  // FIXME: Fail more softly if the diagnostic level is unknown?
+  assert(severity == static_cast<serialized_diags::Level>(severity) &&
+         "unknown serialized diagnostic level");
+
+  switch (static_cast<serialized_diags::Level>(severity)) {
+#define CASE(X) case serialized_diags::X: return CXDiagnostic_##X;
+  CASE(Ignored)
+  CASE(Note)
+  CASE(Warning)
+  CASE(Error)
+  CASE(Fatal)
+  CASE(Remark)
+#undef CASE
   }
   
   llvm_unreachable("Invalid diagnostic level");
@@ -175,7 +181,7 @@ void CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,
 // Deserialize diagnostics.
 //===----------------------------------------------------------------------===//
 
-enum { MaxSupportedVersion = 1 };
+enum { MaxSupportedVersion = 2 };
 typedef SmallVector<uint64_t, 64> RecordData;
 enum LoadResult { Failure = 1, Success = 0 };
 enum StreamResult { Read_EndOfStream,