https://github.com/cmtice updated https://github.com/llvm/llvm-project/pull/145055
>From e9079e6357b933e84603997edb8d0cd27a515989 Mon Sep 17 00:00:00 2001 From: Caroline Tice <cmt...@google.com> Date: Fri, 20 Jun 2025 08:33:14 -0700 Subject: [PATCH 1/3] [LLDB] Update DIL to pass current 'frame var' tests. As a preliminary to making DIL the default implementation for 'frame var', ran check-lldb forcing 'frame var' to always use DIL, and discovered a few failing tests. This fixes most of them. The only two remaining failing tests (once the smart pointer PR is committed) are TestVarPath.py, which fails a test case using a negative array subscript, as DIL does not yet parse negative numbers; and TestDAP_evaluate.py, which now passes a test case that the test says should fail (still investigating this). Changes in this PR: - Sets correct VariableSP, as well as returning ValueObjectSP (needed for several watchpoint tests). - Update error messages, when looking up members, to match what the rest of LLDB expects. Also update appropriate DIL tests to expect the updated error messages. - Update DIL parser to look for and accept "(anonymous namespace)::" at the front of a variable name. --- lldb/source/Target/StackFrame.cpp | 1 + lldb/source/ValueObject/DILEval.cpp | 10 ++--- lldb/source/ValueObject/DILParser.cpp | 39 ++++++++++++++++--- .../MemberOf/TestFrameVarDILMemberOf.py | 2 +- .../TestFrameVarDILMemberOfAnonymousMember.py | 10 ++--- 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index ab5cd0b27c789..f5a80efc821d5 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -562,6 +562,7 @@ ValueObjectSP StackFrame::DILGetValueForVariableExpressionPath( return ValueObjectConstResult::Create(nullptr, std::move(error)); } + var_sp = (*valobj_or_error)->GetVariable(); return *valobj_or_error; } diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp index c8cb54aa18a93..2c4d355a2c6b8 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -356,8 +356,8 @@ Interpreter::Visit(const MemberOfNode *node) { if (!m_use_synthetic || !field_obj) { std::string errMsg = llvm::formatv( - "no member named '{0}' in {1}", node->GetFieldName(), - base->GetCompilerType().GetFullyUnqualifiedType().TypeDescription()); + "\"{0}\" is not a member of \"({1}) {2}\"", node->GetFieldName(), + base->GetTypeName().AsCString("<invalid type>"), base->GetName()); return llvm::make_error<DILDiagnosticError>( m_expr, errMsg, node->GetLocation(), node->GetFieldName().size()); } @@ -376,9 +376,9 @@ Interpreter::Visit(const MemberOfNode *node) { CompilerType base_type = base->GetCompilerType(); if (node->GetIsArrow() && base->IsPointerType()) base_type = base_type.GetPointeeType(); - std::string errMsg = - llvm::formatv("no member named '{0}' in {1}", node->GetFieldName(), - base_type.GetFullyUnqualifiedType().TypeDescription()); + std::string errMsg = llvm::formatv( + "\"{0}\" is not a member of \"({1}) {2}\"", node->GetFieldName(), + base->GetTypeName().AsCString("<invalid type>"), base->GetName()); return llvm::make_error<DILDiagnosticError>( m_expr, errMsg, node->GetLocation(), node->GetFieldName().size()); } diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp index 9667885734f21..37d5bd30fa61f 100644 --- a/lldb/source/ValueObject/DILParser.cpp +++ b/lldb/source/ValueObject/DILParser.cpp @@ -178,11 +178,40 @@ ASTNodeUP DILParser::ParsePrimaryExpression() { } if (CurToken().Is(Token::l_paren)) { - m_dil_lexer.Advance(); - auto expr = ParseExpression(); - Expect(Token::r_paren); - m_dil_lexer.Advance(); - return expr; + // Check in case this is an anonynmous namespace + if (m_dil_lexer.LookAhead(1).Is(Token::identifier) && + (m_dil_lexer.LookAhead(1).GetSpelling() == "anonymous") && + m_dil_lexer.LookAhead(2).Is(Token::identifier) && + (m_dil_lexer.LookAhead(2).GetSpelling() == "namespace") && + m_dil_lexer.LookAhead(3).Is(Token::r_paren) && + m_dil_lexer.LookAhead(4).Is(Token::coloncolon)) { + m_dil_lexer.Advance(4); + + std::string identifier = "(anonymous namespace)"; + Expect(Token::coloncolon); + // Save the source location for the diagnostics message. + uint32_t loc = CurToken().GetLocation(); + m_dil_lexer.Advance(); + assert( + (CurToken().Is(Token::identifier) || CurToken().Is(Token::l_paren)) && + "Expected an identifier or anonymous namespeace, but not found."); + std::string identifier2 = ParseNestedNameSpecifier(); + if (identifier2.empty()) { + // There was only an identifer, no more levels of nesting. Or there + // was an invalid expression starting with a left parenthesis. + Expect(Token::identifier); + identifier2 = CurToken().GetSpelling(); + m_dil_lexer.Advance(); + } + identifier = identifier + "::" + identifier2; + return std::make_unique<IdentifierNode>(loc, identifier); + } else { + m_dil_lexer.Advance(); + auto expr = ParseExpression(); + Expect(Token::r_paren); + m_dil_lexer.Advance(); + return expr; + } } BailOut(llvm::formatv("Unexpected token: {0}", CurToken()), diff --git a/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py b/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py index bb16c1f82489d..c204b75941a2f 100644 --- a/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py +++ b/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py @@ -32,7 +32,7 @@ def test_frame_var(self): self.expect_var_path("sp->r", type="int &") self.expect("frame variable 'sp->foo'", error=True, - substrs=["no member named 'foo' in 'Sx *'"]) + substrs=["\"foo\" is not a member of \"(Sx *) sp\""]) self.expect("frame variable 'sp.x'", error=True, substrs=["member reference type 'Sx *' is a " diff --git a/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py b/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py index 1bde4706da90f..eb6261aefb5c8 100644 --- a/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py +++ b/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py @@ -28,7 +28,7 @@ def test_frame_var(self): self.expect_var_path("a.y", value="2") self.expect("frame variable 'b.x'", error=True, - substrs=["no member named 'x' in 'B'"]) + substrs=["\"x\" is not a member of \"(B) b\""]) #self.expect_var_path("b.y", value="0") self.expect_var_path("b.z", value="3") self.expect_var_path("b.w", value="4") @@ -44,18 +44,18 @@ def test_frame_var(self): self.expect_var_path("d.w", value="10") self.expect("frame variable 'e.x'", error=True, - substrs=["no member named 'x' in 'E'"]) + substrs=["\"x\" is not a member of \"(E) e\""]) self.expect("frame variable 'f.x'", error=True, - substrs=["no member named 'x' in 'F'"]) + substrs=["\"x\" is not a member of \"(F) f\""]) self.expect_var_path("f.named_field.x", value="12") self.expect_var_path("unnamed_derived.y", value="2") self.expect_var_path("unnamed_derived.z", value="13") self.expect("frame variable 'derb.x'", error=True, - substrs=["no member named 'x' in 'DerivedB'"]) + substrs=["\"x\" is not a member of \"(DerivedB) derb\""]) self.expect("frame variable 'derb.y'", error=True, - substrs=["no member named 'y' in 'DerivedB'"]) + substrs=["\"y\" is not a member of \"(DerivedB) derb\""]) self.expect_var_path("derb.w", value="14") self.expect_var_path("derb.k", value="15") self.expect_var_path("derb.a.x", value="1") >From e7ae837e44baa64fd5fe73d34ee2b0d968ab3e08 Mon Sep 17 00:00:00 2001 From: Caroline Tice <cmt...@google.com> Date: Fri, 20 Jun 2025 08:49:31 -0700 Subject: [PATCH 2/3] Fix clang-format issues. --- .../MemberOf/TestFrameVarDILMemberOf.py | 18 ++++++---- .../TestFrameVarDILMemberOfAnonymousMember.py | 35 +++++++++++++------ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py b/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py index c204b75941a2f..2fb6a49058cf7 100644 --- a/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py +++ b/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py @@ -31,12 +31,18 @@ def test_frame_var(self): self.expect_var_path("sp->x", value="1") self.expect_var_path("sp->r", type="int &") - self.expect("frame variable 'sp->foo'", error=True, - substrs=["\"foo\" is not a member of \"(Sx *) sp\""]) - - self.expect("frame variable 'sp.x'", error=True, - substrs=["member reference type 'Sx *' is a " - "pointer; did you mean to use '->'"]) + self.expect( + "frame variable 'sp->foo'", + error=True, + substrs=["\"foo\" is not a member of \"(Sx *) sp\""], + ) + + self.expect( + "frame variable 'sp.x'", + error=True, + substrs=["member reference type 'Sx *' is a " + "pointer; did you mean to use '->'"], + ) # Test for record typedefs. self.expect_var_path("sa.x", value="3") diff --git a/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py b/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py index eb6261aefb5c8..3124133833946 100644 --- a/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py +++ b/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py @@ -27,8 +27,11 @@ def test_frame_var(self): self.expect_var_path("a.x", value="1") self.expect_var_path("a.y", value="2") - self.expect("frame variable 'b.x'", error=True, - substrs=["\"x\" is not a member of \"(B) b\""]) + self.expect( + "frame variable 'b.x'", + error=True, + substrs=["\"x\" is not a member of \"(B) b\""], + ) #self.expect_var_path("b.y", value="0") self.expect_var_path("b.z", value="3") self.expect_var_path("b.w", value="4") @@ -43,19 +46,31 @@ def test_frame_var(self): self.expect_var_path("d.z", value="9") self.expect_var_path("d.w", value="10") - self.expect("frame variable 'e.x'", error=True, - substrs=["\"x\" is not a member of \"(E) e\""]) - self.expect("frame variable 'f.x'", error=True, - substrs=["\"x\" is not a member of \"(F) f\""]) + self.expect( + "frame variable 'e.x'", + error=True, + substrs=["\"x\" is not a member of \"(E) e\""], + ) + self.expect( + "frame variable 'f.x'", + error=True, + substrs=["\"x\" is not a member of \"(F) f\""], + ) self.expect_var_path("f.named_field.x", value="12") self.expect_var_path("unnamed_derived.y", value="2") self.expect_var_path("unnamed_derived.z", value="13") - self.expect("frame variable 'derb.x'", error=True, - substrs=["\"x\" is not a member of \"(DerivedB) derb\""]) - self.expect("frame variable 'derb.y'", error=True, - substrs=["\"y\" is not a member of \"(DerivedB) derb\""]) + self.expect( + "frame variable 'derb.x'", + error=True, + substrs=["\"x\" is not a member of \"(DerivedB) derb\""], + ) + self.expect( + "frame variable 'derb.y'", + error=True, + substrs=["\"y\" is not a member of \"(DerivedB) derb\""], + ) self.expect_var_path("derb.w", value="14") self.expect_var_path("derb.k", value="15") self.expect_var_path("derb.a.x", value="1") >From f7fbde01b9d21e70597a079813115ebe713f55ab Mon Sep 17 00:00:00 2001 From: Caroline Tice <cmt...@google.com> Date: Fri, 20 Jun 2025 09:07:33 -0700 Subject: [PATCH 3/3] Fix more clang-format issues. --- .../var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py | 7 ++++--- .../TestFrameVarDILMemberOfAnonymousMember.py | 10 +++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py b/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py index 2fb6a49058cf7..cf0c63bcda549 100644 --- a/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py +++ b/lldb/test/API/commands/frame/var-dil/basics/MemberOf/TestFrameVarDILMemberOf.py @@ -34,14 +34,15 @@ def test_frame_var(self): self.expect( "frame variable 'sp->foo'", error=True, - substrs=["\"foo\" is not a member of \"(Sx *) sp\""], + substrs=['"foo" is not a member of "(Sx *) sp"'], ) self.expect( "frame variable 'sp.x'", error=True, - substrs=["member reference type 'Sx *' is a " - "pointer; did you mean to use '->'"], + substrs=[ + "member reference type 'Sx *' is a pointer; did you mean to use '->'"] + , ) # Test for record typedefs. diff --git a/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py b/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py index 3124133833946..856b3a069eec8 100644 --- a/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py +++ b/lldb/test/API/commands/frame/var-dil/basics/MemberOfAnonymousMember/TestFrameVarDILMemberOfAnonymousMember.py @@ -30,7 +30,7 @@ def test_frame_var(self): self.expect( "frame variable 'b.x'", error=True, - substrs=["\"x\" is not a member of \"(B) b\""], + substrs=['"x" is not a member of "(B) b"'], ) #self.expect_var_path("b.y", value="0") self.expect_var_path("b.z", value="3") @@ -49,12 +49,12 @@ def test_frame_var(self): self.expect( "frame variable 'e.x'", error=True, - substrs=["\"x\" is not a member of \"(E) e\""], + substrs=['"x" is not a member of "(E) e"'], ) self.expect( "frame variable 'f.x'", error=True, - substrs=["\"x\" is not a member of \"(F) f\""], + substrs=['"x" is not a member of "(F) f"'], ) self.expect_var_path("f.named_field.x", value="12") @@ -64,12 +64,12 @@ def test_frame_var(self): self.expect( "frame variable 'derb.x'", error=True, - substrs=["\"x\" is not a member of \"(DerivedB) derb\""], + substrs=['"x" is not a member of "(DerivedB) derb"'], ) self.expect( "frame variable 'derb.y'", error=True, - substrs=["\"y\" is not a member of \"(DerivedB) derb\""], + substrs=['"y" is not a member of "(DerivedB) derb"'], ) self.expect_var_path("derb.w", value="14") self.expect_var_path("derb.k", value="15") _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits