@@ -2148,4 +2148,114 @@ TEST_F(DebugLineBasicFixture, LookupAddressRangeWithStmtSequenceOffset) {
21482148 EXPECT_EQ (Rows[1 ], 3u );
21492149 }
21502150}
2151+
2152+ // / Test that HighPC is now inclusive in Sequence containsPC checks.
2153+ //
2154+ // / With the old exclusive HighPC logic, lookups at the last row's address would
2155+ // / fail. With the new inclusive HighPC logic, lookups at the HighPC address
2156+ // / should succeed.
2157+ TEST_F (DebugLineBasicFixture, HighPCInclusiveLookup) {
2158+ if (!setupGenerator ())
2159+ GTEST_SKIP ();
2160+
2161+ // Create a line table with a sequence that covers addresses [0x1000, 0x1010]
2162+ // We'll test lookups at various addresses including the HighPC (0x1010)
2163+ LineTable < = Gen->addLineTable ();
2164+
2165+ // Set address to 0x1000 and create first row
2166+ LT.addExtendedOpcode (9 , DW_LNE_set_address, {{0x1000U , LineTable::Quad}});
2167+ LT.addStandardOpcode (DW_LNS_copy, {});
2168+
2169+ // Advance to 0x1008 and create second row
2170+ LT.addStandardOpcode (DW_LNS_advance_pc, {{0x8 , LineTable::ULEB}});
2171+ LT.addStandardOpcode (DW_LNS_copy, {});
2172+
2173+ // Advance to 0x1010 and create third row (this will be the HighPC)
2174+ LT.addStandardOpcode (DW_LNS_advance_pc, {{0x8 , LineTable::ULEB}});
2175+ LT.addStandardOpcode (DW_LNS_copy, {});
2176+
2177+ // End the sequence - this makes HighPC = 0x1010
2178+ LT.addExtendedOpcode (1 , DW_LNE_end_sequence, {});
2179+
2180+ generate ();
2181+
2182+ // Parse the line table
2183+ auto ExpectedLineTable = Line.getOrParseLineTable (LineData, 0 , *Context,
2184+ nullptr , RecordRecoverable);
2185+ ASSERT_THAT_EXPECTED (ExpectedLineTable, Succeeded ());
2186+ const auto *Table = *ExpectedLineTable;
2187+
2188+ // Verify we have one sequence with the expected address range
2189+ ASSERT_EQ (Table->Sequences .size (), 1u );
2190+ const auto &Seq = Table->Sequences [0 ];
2191+ EXPECT_EQ (Seq.LowPC , 0x1000U );
2192+ EXPECT_EQ (Seq.HighPC , 0x1011U );
2193+
2194+ auto LastRow = Table->Rows .back ();
2195+
2196+ // Lookup the last Row - this is the key test for inclusive HighPC
2197+ // With the old exclusive logic, this would return UnknownRowIndex
2198+ // With the new inclusive logic, this should succeed
2199+ {
2200+ uint32_t RowIndex = Table->lookupAddress (
2201+ {LastRow.Address .Address , object::SectionedAddress::UndefSection});
2202+ // EXPECT_NE(RowIndex, Table->UnknownRowIndex) << "Lookup at HighPC found no
2203+ // row";
2204+ EXPECT_EQ (RowIndex, Table->Rows .size () - 2 )
2205+ << " Lookup at HighPC should find the second to the last row" ;
2206+ }
2207+ }
2208+
2209+ // / Test that a sequence with only one row works correctly with inclusive
2210+ // / HighPC. This is an important edge case where LowPC == HighPC, and the
2211+ // / inclusive HighPC logic should still allow lookups at that single address.
2212+ TEST_F (DebugLineBasicFixture, SingleInstSequenceInclusiveHighPC) {
2213+ if (!setupGenerator ())
2214+ GTEST_SKIP ();
2215+
2216+ // Create a line table with a sequence that has only one row
2217+ // This creates a sequence where LowPC == HighPC
2218+ LineTable < = Gen->addLineTable ();
2219+
2220+ // Set address to 0x3000 and create the only row
2221+ LT.addExtendedOpcode (9 , DW_LNE_set_address, {{0x3000U , LineTable::Quad}});
2222+ LT.addStandardOpcode (DW_LNS_copy, {});
2223+
2224+ // End the sequence immediately - this makes LowPC == HighPC == 0x3000
2225+ LT.addExtendedOpcode (1 , DW_LNE_end_sequence, {});
2226+
2227+ generate ();
2228+
2229+ // Parse the line table
2230+ auto ExpectedLineTable = Line.getOrParseLineTable (LineData, 0 , *Context,
2231+ nullptr , RecordRecoverable);
2232+ ASSERT_THAT_EXPECTED (ExpectedLineTable, Succeeded ());
2233+ const auto *Table = *ExpectedLineTable;
2234+
2235+ // Verify we have one sequence with LowPC == HighPC
2236+ ASSERT_EQ (Table->Sequences .size (), 1u );
2237+ const auto &Seq = Table->Sequences [0 ];
2238+ EXPECT_EQ (Seq.LowPC , 0x3000U );
2239+ EXPECT_EQ (Seq.HighPC , 0x3001U );
2240+
2241+ // Verify we have exactly one row (plus the end_sequence row)
2242+ EXPECT_EQ (Table->Rows .size (), 2u );
2243+ EXPECT_EQ (Table->Rows [0 ].Address .Address , 0x3000U );
2244+ EXPECT_TRUE (Table->Rows [1 ].EndSequence );
2245+
2246+ auto LastRow = Table->Rows .back ();
2247+
2248+ // Lookup the last Row - this is the key test for inclusive HighPC
2249+ // With the old exclusive logic, this would return UnknownRowIndex
2250+ // With the new inclusive logic, this should succeed
2251+ {
2252+ uint32_t RowIndex = Table->lookupAddress (
2253+ {LastRow.Address .Address , object::SectionedAddress::UndefSection});
2254+ // EXPECT_NE(RowIndex, Table->UnknownRowIndex) << "Lookup at HighPC found no
2255+ // row";
2256+ EXPECT_EQ (RowIndex, Table->Rows .size () - 2 )
2257+ << " Lookup at HighPC should find the last row" ;
2258+ }
2259+ }
2260+
21512261} // end anonymous namespace
0 commit comments