Skip to content

Commit f72cbc1

Browse files
committed
[lldb] Fix a crash when two diagnostics are on the same column or in reverse order
The second inner loop (only) was missing the check for offset > column. Also this patch sorts the diagnostics before printing them.
1 parent 9b8dbe2 commit f72cbc1

File tree

2 files changed

+51
-9
lines changed

2 files changed

+51
-9
lines changed

lldb/source/Utility/DiagnosticsRendering.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,7 @@ void RenderDiagnosticDetails(Stream &stream,
7777
spacer = "";
7878
}
7979

80-
// Print a line with caret indicator(s) below the lldb prompt + command.
81-
const size_t padding = *offset_in_command;
82-
stream << std::string(padding, ' ');
83-
84-
size_t offset = 1;
80+
// Partition the diagnostics.
8581
std::vector<DiagnosticDetail> remaining_details, other_details,
8682
hidden_details;
8783
for (const DiagnosticDetail &detail : details) {
@@ -98,10 +94,31 @@ void RenderDiagnosticDetails(Stream &stream,
9894
continue;
9995
}
10096

101-
auto &loc = *detail.source_location;
10297
remaining_details.push_back(detail);
98+
}
99+
100+
// Sort the diagnostics.
101+
auto sort = [](auto &ds) {
102+
llvm::sort(ds.begin(), ds.end(), [](auto &d1, auto &d2) {
103+
auto l1 = d1.source_location.value_or(DiagnosticDetail::SourceLocation{});
104+
auto l2 = d2.source_location.value_or(DiagnosticDetail::SourceLocation{});
105+
return std::pair(l1.line, l2.column) < std::pair(l1.line, l2.column);
106+
});
107+
};
108+
sort(remaining_details);
109+
sort(other_details);
110+
sort(hidden_details);
111+
112+
// Print a line with caret indicator(s) below the lldb prompt + command.
113+
const size_t padding = *offset_in_command;
114+
stream << std::string(padding, ' ');
115+
size_t offset = 1;
116+
for (const DiagnosticDetail &detail : remaining_details) {
117+
auto &loc = *detail.source_location;
118+
103119
if (offset > loc.column)
104120
continue;
121+
105122
stream << std::string(loc.column - offset, ' ') << cursor;
106123
for (unsigned i = 0; i + 1 < loc.length; ++i)
107124
stream << underline;
@@ -121,7 +138,8 @@ void RenderDiagnosticDetails(Stream &stream,
121138
for (auto &remaining_detail :
122139
llvm::ArrayRef(remaining_details).drop_back(1)) {
123140
uint16_t column = remaining_detail.source_location->column;
124-
stream << std::string(column - offset, ' ') << vbar;
141+
if (offset <= column)
142+
stream << std::string(column - offset, ' ') << vbar;
125143
offset = column + 1;
126144
}
127145

lldb/unittests/Utility/DiagnosticsRenderingTest.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,36 @@ std::string Render(std::vector<DiagnosticDetail> details) {
1616
} // namespace
1717

1818
TEST_F(ErrorDisplayTest, RenderStatus) {
19-
DiagnosticDetail::SourceLocation inline_loc;
20-
inline_loc.in_user_input = true;
2119
{
20+
DiagnosticDetail::SourceLocation inline_loc;
21+
inline_loc.in_user_input = true;
2222
std::string result =
2323
Render({DiagnosticDetail{inline_loc, eSeverityError, "foo", ""}});
2424
ASSERT_TRUE(StringRef(result).contains("error:"));
2525
ASSERT_TRUE(StringRef(result).contains("foo"));
2626
}
27+
28+
{
29+
DiagnosticDetail::SourceLocation loc1 = {FileSpec{"a.c"}, 13, 11, 0,
30+
false, true};
31+
DiagnosticDetail::SourceLocation loc2 = {FileSpec{"a.c"}, 13, 13, 0,
32+
false, true};
33+
std::string result =
34+
Render({DiagnosticDetail{loc1, eSeverityError, "1", "1"},
35+
DiagnosticDetail{loc1, eSeverityError, "2", "3"},
36+
DiagnosticDetail{loc2, eSeverityError, "3", "3"}});
37+
ASSERT_TRUE(StringRef(result).contains("error: 1"));
38+
ASSERT_TRUE(StringRef(result).contains("error: 3"));
39+
ASSERT_TRUE(StringRef(result).contains("error: 2"));
40+
}
41+
{
42+
DiagnosticDetail::SourceLocation loc1 = {FileSpec{"a.c"}, 1, 20, 0,
43+
false, true};
44+
DiagnosticDetail::SourceLocation loc2 = {FileSpec{"a.c"}, 2, 10, 0,
45+
false, true};
46+
std::string result =
47+
Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"},
48+
DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}});
49+
ASSERT_LT(StringRef(result).find("Y"), StringRef(result).find("X"));
50+
}
2751
}

0 commit comments

Comments
 (0)