diff --git a/lib/AST/DiagnosticBridge.cpp b/lib/AST/DiagnosticBridge.cpp index f1f650aaf190a..35f8b095e50ae 100644 --- a/lib/AST/DiagnosticBridge.cpp +++ b/lib/AST/DiagnosticBridge.cpp @@ -77,6 +77,13 @@ static void addQueueDiagnostic(void *queuedDiagnostics, documentationPath.size(), highlightRanges.data(), highlightRanges.size() / 2); + + // TODO: A better way to do this would be to pass the notes as an + // argument to `swift_ASTGen_addQueuedDiagnostic` but that requires + // bridging of `Note` structure and new serialization. + for (auto *childNote : info.ChildDiagnosticInfo) { + addQueueDiagnostic(queuedDiagnostics, *childNote, SM); + } } void DiagnosticBridge::enqueueDiagnostic(SourceManager &SM, diff --git a/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift b/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift index 0a911139e0064..a689a3c24b0ed 100644 --- a/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift +++ b/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift @@ -339,13 +339,20 @@ public func addQueuedDiagnostic( } } - let category: DiagnosticCategory? = categoryName.map { categoryNamePtr in + let category: DiagnosticCategory? = categoryName.flatMap { categoryNamePtr in let categoryNameBuffer = UnsafeBufferPointer( start: categoryNamePtr, count: categoryLength ) let categoryName = String(decoding: categoryNameBuffer, as: UTF8.self) + // If the data comes from serialized diagnostics, it's possible that + // the category name is empty because StringRef() is serialized into + // an empty string. + guard !categoryName.isEmpty else { + return nil + } + let documentationURL = documentationPath.map { documentationPathPtr in let documentationPathBuffer = UnsafeBufferPointer( start: documentationPathPtr, diff --git a/test/diagnostics/pretty-printed-diagnostics.swift b/test/diagnostics/pretty-printed-diagnostics.swift index 01a93656a1278..222cd441329a8 100644 --- a/test/diagnostics/pretty-printed-diagnostics.swift +++ b/test/diagnostics/pretty-printed-diagnostics.swift @@ -66,6 +66,9 @@ foo(b: 1, a: 2) +// Test for child notes attached directly to a "primary" error/warning diagnostic +func test(a: Int) {} +func test(a: Int) {} // Test fallback for non-ASCII characters. // CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:11 @@ -85,3 +88,9 @@ foo(b: // CHECK: [[#LINE]] | foo(b: 1, a: 2) // CHECK: | `- error: argument 'a' must precede argument 'b' // CHECK: [[#LINE+1]] | + +// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:6 +// CHECK: [[#LINE-1]] | func test(a: Int) {} +// CHECK: | `- note: 'test(a:)' previously declared here +// CHECK: [[#LINE]] | func test(a: Int) {} +// CHECL: [[#LINE+1]] | `- error: invalid redeclaration of 'test(a:)'