[lldb] Fix a crash when two diagnostics are on the same column or in … (#112451)
…reverse order The second inner loop (only) was missing the check for offset > column. Also this patch sorts the diagnostics before printing them.
This commit is contained in:
parent
1de15c15bc
commit
889e6ad24b
@ -77,11 +77,7 @@ void RenderDiagnosticDetails(Stream &stream,
|
|||||||
spacer = "";
|
spacer = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print a line with caret indicator(s) below the lldb prompt + command.
|
// Partition the diagnostics.
|
||||||
const size_t padding = *offset_in_command;
|
|
||||||
stream << std::string(padding, ' ');
|
|
||||||
|
|
||||||
size_t offset = 1;
|
|
||||||
std::vector<DiagnosticDetail> remaining_details, other_details,
|
std::vector<DiagnosticDetail> remaining_details, other_details,
|
||||||
hidden_details;
|
hidden_details;
|
||||||
for (const DiagnosticDetail &detail : details) {
|
for (const DiagnosticDetail &detail : details) {
|
||||||
@ -98,10 +94,31 @@ void RenderDiagnosticDetails(Stream &stream,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &loc = *detail.source_location;
|
|
||||||
remaining_details.push_back(detail);
|
remaining_details.push_back(detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the diagnostics.
|
||||||
|
auto sort = [](auto &ds) {
|
||||||
|
llvm::sort(ds.begin(), ds.end(), [](auto &d1, auto &d2) {
|
||||||
|
auto l1 = d1.source_location.value_or(DiagnosticDetail::SourceLocation{});
|
||||||
|
auto l2 = d2.source_location.value_or(DiagnosticDetail::SourceLocation{});
|
||||||
|
return std::pair(l1.line, l2.column) < std::pair(l1.line, l2.column);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
sort(remaining_details);
|
||||||
|
sort(other_details);
|
||||||
|
sort(hidden_details);
|
||||||
|
|
||||||
|
// Print a line with caret indicator(s) below the lldb prompt + command.
|
||||||
|
const size_t padding = *offset_in_command;
|
||||||
|
stream << std::string(padding, ' ');
|
||||||
|
size_t offset = 1;
|
||||||
|
for (const DiagnosticDetail &detail : remaining_details) {
|
||||||
|
auto &loc = *detail.source_location;
|
||||||
|
|
||||||
if (offset > loc.column)
|
if (offset > loc.column)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
stream << std::string(loc.column - offset, ' ') << cursor;
|
stream << std::string(loc.column - offset, ' ') << cursor;
|
||||||
for (unsigned i = 0; i + 1 < loc.length; ++i)
|
for (unsigned i = 0; i + 1 < loc.length; ++i)
|
||||||
stream << underline;
|
stream << underline;
|
||||||
@ -121,7 +138,8 @@ void RenderDiagnosticDetails(Stream &stream,
|
|||||||
for (auto &remaining_detail :
|
for (auto &remaining_detail :
|
||||||
llvm::ArrayRef(remaining_details).drop_back(1)) {
|
llvm::ArrayRef(remaining_details).drop_back(1)) {
|
||||||
uint16_t column = remaining_detail.source_location->column;
|
uint16_t column = remaining_detail.source_location->column;
|
||||||
stream << std::string(column - offset, ' ') << vbar;
|
if (offset <= column)
|
||||||
|
stream << std::string(column - offset, ' ') << vbar;
|
||||||
offset = column + 1;
|
offset = column + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,12 +16,45 @@ std::string Render(std::vector<DiagnosticDetail> details) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_F(ErrorDisplayTest, RenderStatus) {
|
TEST_F(ErrorDisplayTest, RenderStatus) {
|
||||||
DiagnosticDetail::SourceLocation inline_loc;
|
using SourceLocation = DiagnosticDetail::SourceLocation;
|
||||||
inline_loc.in_user_input = true;
|
|
||||||
{
|
{
|
||||||
|
SourceLocation inline_loc;
|
||||||
|
inline_loc.in_user_input = true;
|
||||||
std::string result =
|
std::string result =
|
||||||
Render({DiagnosticDetail{inline_loc, eSeverityError, "foo", ""}});
|
Render({DiagnosticDetail{inline_loc, eSeverityError, "foo", ""}});
|
||||||
ASSERT_TRUE(StringRef(result).contains("error:"));
|
ASSERT_TRUE(StringRef(result).contains("error:"));
|
||||||
ASSERT_TRUE(StringRef(result).contains("foo"));
|
ASSERT_TRUE(StringRef(result).contains("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Test that diagnostics on the same column can be handled and all
|
||||||
|
// three errors are diagnosed.
|
||||||
|
SourceLocation loc1 = {FileSpec{"a.c"}, 13, 11, 0, false, true};
|
||||||
|
SourceLocation loc2 = {FileSpec{"a.c"}, 13, 13, 0, false, true};
|
||||||
|
std::string result =
|
||||||
|
Render({DiagnosticDetail{loc1, eSeverityError, "1", "1"},
|
||||||
|
DiagnosticDetail{loc1, eSeverityError, "2", "2"},
|
||||||
|
DiagnosticDetail{loc2, eSeverityError, "3", "3"}});
|
||||||
|
ASSERT_TRUE(StringRef(result).contains("error: 1"));
|
||||||
|
ASSERT_TRUE(StringRef(result).contains("error: 2"));
|
||||||
|
ASSERT_TRUE(StringRef(result).contains("error: 3"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Test that diagnostics in reverse order are emitted correctly.
|
||||||
|
SourceLocation loc1 = {FileSpec{"a.c"}, 1, 20, 0, false, true};
|
||||||
|
SourceLocation loc2 = {FileSpec{"a.c"}, 2, 10, 0, false, true};
|
||||||
|
std::string result =
|
||||||
|
Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"},
|
||||||
|
DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}});
|
||||||
|
ASSERT_LT(StringRef(result).find("Y"), StringRef(result).find("X"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Test that diagnostics in reverse order are emitted correctly.
|
||||||
|
SourceLocation loc1 = {FileSpec{"a.c"}, 2, 10, 0, false, true};
|
||||||
|
SourceLocation loc2 = {FileSpec{"a.c"}, 1, 20, 0, false, true};
|
||||||
|
std::string result =
|
||||||
|
Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"},
|
||||||
|
DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}});
|
||||||
|
ASSERT_LT(StringRef(result).find("Y"), StringRef(result).find("X"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user