Skip to content

Commit dd5df27

Browse files
authored
[lldb] Make semantics of SupportFile equivalence explicit (llvm#97126)
This is an improved attempt to improve the semantics of SupportFile equivalence, taking into account the feedback from llvm#95606. Pavel's comment about the lack of a concise name because the concept isn't trivial made me realize that I don't want to abstract this concept away behind a helper function. Instead, I opted for a rather verbose enum that forces the caller to consider exactly what kind of comparison is appropriate for every call.
1 parent 668ee3f commit dd5df27

File tree

9 files changed

+146
-22
lines changed

9 files changed

+146
-22
lines changed

lldb/include/lldb/Utility/SupportFile.h

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,37 @@ class SupportFile {
3030

3131
virtual ~SupportFile() = default;
3232

33-
/// Return true if both SupportFiles have the same FileSpec and, if both have
34-
/// a valid Checksum, the Checksum is the same.
35-
bool operator==(const SupportFile &other) const {
36-
if (m_checksum && other.m_checksum)
37-
return m_file_spec == other.m_file_spec && m_checksum == other.m_checksum;
38-
return m_file_spec == other.m_file_spec;
39-
}
33+
enum SupportFileEquality : uint8_t {
34+
eEqualFileSpec = (1u << 1),
35+
eEqualChecksum = (1u << 2),
36+
eEqualChecksumIfSet = (1u << 3),
37+
eEqualFileSpecAndChecksum = eEqualFileSpec | eEqualChecksum,
38+
eEqualFileSpecAndChecksumIfSet = eEqualFileSpec | eEqualChecksumIfSet,
39+
};
40+
41+
bool Equal(const SupportFile &other,
42+
SupportFileEquality equality = eEqualFileSpecAndChecksum) const {
43+
assert(!(equality & eEqualChecksum & eEqualChecksumIfSet) &&
44+
"eEqualChecksum and eEqualChecksumIfSet are mutually exclusive");
45+
46+
if (equality & eEqualFileSpec) {
47+
if (m_file_spec != other.m_file_spec)
48+
return false;
49+
}
4050

41-
bool operator!=(const SupportFile &other) const { return !(*this == other); }
51+
if (equality & eEqualChecksum) {
52+
if (m_checksum != other.m_checksum)
53+
return false;
54+
}
55+
56+
if (equality & eEqualChecksumIfSet) {
57+
if (m_checksum && other.m_checksum)
58+
if (m_checksum != other.m_checksum)
59+
return false;
60+
}
61+
62+
return true;
63+
}
4264

4365
/// Return the file name only. Useful for resolving breakpoints by file name.
4466
const FileSpec &GetSpecOnly() const { return m_file_spec; };

lldb/source/Breakpoint/BreakpointResolver.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,9 @@ void BreakpointResolver::SetSCMatchesByLine(
222222
auto worklist_begin = std::partition(
223223
all_scs.begin(), all_scs.end(), [&](const SymbolContext &sc) {
224224
if (sc.line_entry.GetFile() == match.line_entry.GetFile() ||
225-
*sc.line_entry.original_file_sp ==
226-
*match.line_entry.original_file_sp) {
225+
sc.line_entry.original_file_sp->Equal(
226+
*match.line_entry.original_file_sp,
227+
SupportFile::eEqualFileSpecAndChecksumIfSet)) {
227228
// When a match is found, keep track of the smallest line number.
228229
closest_line = std::min(closest_line, sc.line_entry.line);
229230
return false;

lldb/source/Commands/CommandObjectSource.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,13 +747,17 @@ class CommandObjectSourceList : public CommandObjectParsed {
747747

748748
bool operator==(const SourceInfo &rhs) const {
749749
return function == rhs.function &&
750-
*line_entry.original_file_sp == *rhs.line_entry.original_file_sp &&
750+
line_entry.original_file_sp->Equal(
751+
*rhs.line_entry.original_file_sp,
752+
SupportFile::eEqualFileSpecAndChecksumIfSet) &&
751753
line_entry.line == rhs.line_entry.line;
752754
}
753755

754756
bool operator!=(const SourceInfo &rhs) const {
755757
return function != rhs.function ||
756-
*line_entry.original_file_sp != *rhs.line_entry.original_file_sp ||
758+
!line_entry.original_file_sp->Equal(
759+
*rhs.line_entry.original_file_sp,
760+
SupportFile::eEqualFileSpecAndChecksumIfSet) ||
757761
line_entry.line != rhs.line_entry.line;
758762
}
759763

lldb/source/Symbol/LineEntry.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,8 @@ AddressRange LineEntry::GetSameLineContiguousAddressRange(
199199
next_line_sc.line_entry.range.GetByteSize() == 0)
200200
break;
201201

202-
if (*original_file_sp == *next_line_sc.line_entry.original_file_sp &&
202+
if (original_file_sp->Equal(*next_line_sc.line_entry.original_file_sp,
203+
SupportFile::eEqualFileSpecAndChecksumIfSet) &&
203204
(next_line_sc.line_entry.line == 0 ||
204205
line == next_line_sc.line_entry.line)) {
205206
// Include any line 0 entries - they indicate that this is compiler-

lldb/source/Symbol/LineTable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ void LineTable::Dump(Stream *s, Target *target, Address::DumpStyle style,
360360
SupportFileSP prev_file;
361361
for (size_t idx = 0; idx < count; ++idx) {
362362
ConvertEntryAtIndexToLineEntry(idx, line_entry);
363-
line_entry.Dump(s, target, *prev_file != *line_entry.original_file_sp,
363+
line_entry.Dump(s, target, !prev_file->Equal(*line_entry.original_file_sp),
364364
style, fallback_style, show_line_ranges);
365365
s->EOL();
366366
prev_file = line_entry.original_file_sp;

lldb/source/Target/ThreadPlanStepOverRange.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,9 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
220220
StackFrameSP frame_sp = thread.GetStackFrameAtIndex(0);
221221
sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
222222
if (sc.line_entry.IsValid()) {
223-
if (*sc.line_entry.original_file_sp !=
224-
*m_addr_context.line_entry.original_file_sp &&
223+
if (!sc.line_entry.original_file_sp->Equal(
224+
*m_addr_context.line_entry.original_file_sp,
225+
SupportFile::eEqualFileSpecAndChecksumIfSet) &&
225226
sc.comp_unit == m_addr_context.comp_unit &&
226227
sc.function == m_addr_context.function) {
227228
// Okay, find the next occurrence of this file in the line table:
@@ -244,8 +245,9 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
244245
LineEntry prev_line_entry;
245246
if (line_table->GetLineEntryAtIndex(entry_idx - 1,
246247
prev_line_entry) &&
247-
*prev_line_entry.original_file_sp ==
248-
*line_entry.original_file_sp) {
248+
prev_line_entry.original_file_sp->Equal(
249+
*line_entry.original_file_sp,
250+
SupportFile::eEqualFileSpecAndChecksumIfSet)) {
249251
SymbolContext prev_sc;
250252
Address prev_address =
251253
prev_line_entry.range.GetBaseAddress();
@@ -279,8 +281,9 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
279281
if (next_line_function != m_addr_context.function)
280282
break;
281283

282-
if (*next_line_entry.original_file_sp ==
283-
*m_addr_context.line_entry.original_file_sp) {
284+
if (next_line_entry.original_file_sp->Equal(
285+
*m_addr_context.line_entry.original_file_sp,
286+
SupportFile::eEqualFileSpecAndChecksumIfSet)) {
284287
const bool abort_other_plans = false;
285288
const RunMode stop_other_threads = RunMode::eAllThreads;
286289
lldb::addr_t cur_pc = thread.GetStackFrameAtIndex(0)

lldb/source/Target/ThreadPlanStepRange.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,9 @@ bool ThreadPlanStepRange::InRange() {
120120
frame->GetSymbolContext(eSymbolContextEverything));
121121
if (m_addr_context.line_entry.IsValid() &&
122122
new_context.line_entry.IsValid()) {
123-
if (*m_addr_context.line_entry.original_file_sp ==
124-
*new_context.line_entry.original_file_sp) {
123+
if (m_addr_context.line_entry.original_file_sp->Equal(
124+
*new_context.line_entry.original_file_sp,
125+
SupportFile::eEqualFileSpecAndChecksumIfSet)) {
125126
if (m_addr_context.line_entry.line == new_context.line_entry.line) {
126127
m_addr_context = new_context;
127128
const bool include_inlined_functions =

lldb/unittests/Utility/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ add_lldb_unittest(UtilityTests
3636
StringListTest.cpp
3737
StructuredDataTest.cpp
3838
SubsystemRAIITest.cpp
39+
SupportFileTest.cpp
3940
TildeExpressionResolverTest.cpp
4041
TimeoutTest.cpp
4142
TimerTest.cpp
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//===-- SupportFileTest.cpp
2+
//--------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "gtest/gtest.h"
11+
12+
#include "lldb/Utility/Checksum.h"
13+
#include "lldb/Utility/FileSpec.h"
14+
#include "lldb/Utility/SupportFile.h"
15+
16+
using namespace lldb_private;
17+
18+
static llvm::MD5::MD5Result hash1 = {
19+
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
20+
21+
static llvm::MD5::MD5Result hash2 = {
22+
{8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7}};
23+
24+
TEST(SupportFileTest, TestDefaultConstructor) {
25+
SupportFile support_file;
26+
27+
EXPECT_EQ(support_file.GetSpecOnly(), FileSpec());
28+
EXPECT_EQ(support_file.GetChecksum(), Checksum());
29+
}
30+
31+
TEST(SupportFileTest, TestConstructor) {
32+
FileSpec file_spec("/foo/bar");
33+
Checksum checksum(hash1);
34+
SupportFile support_file(file_spec, checksum);
35+
36+
EXPECT_EQ(support_file.GetSpecOnly(), file_spec);
37+
EXPECT_EQ(support_file.GetChecksum(), checksum);
38+
}
39+
40+
TEST(SupportFileTest, TestEqual) {
41+
auto EQ = [&](const SupportFile &LHS, const SupportFile &RHS,
42+
SupportFile::SupportFileEquality equality) -> bool {
43+
EXPECT_EQ(LHS.Equal(RHS, equality), RHS.Equal(LHS, equality));
44+
return LHS.Equal(RHS, equality);
45+
};
46+
47+
FileSpec foo_bar("/foo/bar");
48+
Checksum checksum_foo_bar(hash1);
49+
50+
FileSpec bar_baz("/bar/baz");
51+
Checksum checksum_bar_baz(hash2);
52+
53+
// The canonical support file we're comparing against.
54+
SupportFile support_file(foo_bar, checksum_foo_bar);
55+
56+
// Support file A is identical.
57+
SupportFile support_file_a(foo_bar, checksum_foo_bar);
58+
EXPECT_TRUE(EQ(support_file, support_file_a, SupportFile::eEqualFileSpec));
59+
EXPECT_TRUE(EQ(support_file, support_file_a, SupportFile::eEqualChecksum));
60+
EXPECT_TRUE(
61+
EQ(support_file, support_file_a, SupportFile::eEqualFileSpecAndChecksum));
62+
EXPECT_TRUE(EQ(support_file, support_file_a,
63+
SupportFile::eEqualFileSpecAndChecksumIfSet));
64+
65+
// Support file C is has the same path but no checksum.
66+
SupportFile support_file_b(foo_bar);
67+
EXPECT_TRUE(EQ(support_file, support_file_b, SupportFile::eEqualFileSpec));
68+
EXPECT_FALSE(EQ(support_file, support_file_b, SupportFile::eEqualChecksum));
69+
EXPECT_FALSE(
70+
EQ(support_file, support_file_b, SupportFile::eEqualFileSpecAndChecksum));
71+
EXPECT_TRUE(EQ(support_file, support_file_b,
72+
SupportFile::eEqualFileSpecAndChecksumIfSet));
73+
74+
// Support file D has a different path and checksum.
75+
SupportFile support_file_c(bar_baz, checksum_bar_baz);
76+
EXPECT_FALSE(EQ(support_file, support_file_c, SupportFile::eEqualFileSpec));
77+
EXPECT_FALSE(EQ(support_file, support_file_c,
78+
SupportFile::eEqualFileSpecAndChecksumIfSet));
79+
EXPECT_FALSE(EQ(support_file, support_file_c, SupportFile::eEqualChecksum));
80+
EXPECT_FALSE(
81+
EQ(support_file, support_file_c, SupportFile::eEqualFileSpecAndChecksum));
82+
83+
// Support file E has a different path but the same checksum.
84+
SupportFile support_file_d(bar_baz, checksum_foo_bar);
85+
EXPECT_FALSE(EQ(support_file, support_file_d, SupportFile::eEqualFileSpec));
86+
EXPECT_FALSE(EQ(support_file, support_file_d,
87+
SupportFile::eEqualFileSpecAndChecksumIfSet));
88+
EXPECT_TRUE(EQ(support_file, support_file_d, SupportFile::eEqualChecksum));
89+
EXPECT_FALSE(
90+
EQ(support_file, support_file_d, SupportFile::eEqualFileSpecAndChecksum));
91+
}

0 commit comments

Comments
 (0)