diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 52a54020bc468..d97a814952186 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 4293990208c77..3a304b7a070ed 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -363,8 +363,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(""), base->GetName()); return llvm::make_error( m_expr, errMsg, node->GetLocation(), node->GetFieldName().size()); } @@ -383,9 +383,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(""), base->GetName()); return llvm::make_error( m_expr, errMsg, node->GetLocation(), node->GetFieldName().size()); } diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp index 5abbfeabcea3d..eac41fab90763 100644 --- a/lldb/source/ValueObject/DILParser.cpp +++ b/lldb/source/ValueObject/DILParser.cpp @@ -183,12 +183,14 @@ ASTNodeUP DILParser::ParsePostfixExpression() { // "(" expression ")" // ASTNodeUP DILParser::ParsePrimaryExpression() { - if (CurToken().IsOneOf({Token::coloncolon, Token::identifier})) { + if (CurToken().IsOneOf( + {Token::coloncolon, Token::identifier, Token::l_paren})) { // Save the source location for the diagnostics message. uint32_t loc = CurToken().GetLocation(); - auto identifier = ParseIdExpression(); + std::string identifier = ParseIdExpression(); - return std::make_unique(loc, identifier); + if (!identifier.empty()) + return std::make_unique(loc, identifier); } if (CurToken().Is(Token::l_paren)) { @@ -232,16 +234,15 @@ std::string DILParser::ParseNestedNameSpecifier() { m_dil_lexer.LookAhead(4).Is(Token::coloncolon)) { m_dil_lexer.Advance(4); - assert( - (CurToken().Is(Token::identifier) || CurToken().Is(Token::l_paren)) && - "Expected an identifier or anonymous namespace, but not found."); + Expect(Token::coloncolon); + m_dil_lexer.Advance(); + if (!CurToken().Is(Token::identifier) && !CurToken().Is(Token::l_paren)) { + BailOut("Expected an identifier or anonymous namespace, but not found.", + CurToken().GetLocation(), CurToken().GetSpelling().length()); + } // Continue parsing the nested_namespace_specifier. std::string identifier2 = ParseNestedNameSpecifier(); - if (identifier2.empty()) { - Expect(Token::identifier); - identifier2 = CurToken().GetSpelling(); - m_dil_lexer.Advance(); - } + return "(anonymous namespace)::" + identifier2; } @@ -301,6 +302,9 @@ std::string DILParser::ParseIdExpression() { nested_name_specifier, unqualified_id); } + if (!CurToken().Is(Token::identifier)) + return ""; + // No nested_name_specifier, but with global scope -- this is also a // qualified_id production. Follow the second production rule. if (global_scope) { 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..ca6754a556d89 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,19 @@ 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=["no member named 'foo' in 'Sx *'"]) - - 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 1bde4706da90f..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 @@ -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=["no member named 'x' in '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=["no member named 'x' in 'E'"]) - self.expect("frame variable 'f.x'", error=True, - substrs=["no member named 'x' in '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=["no member named 'x' in 'DerivedB'"]) - self.expect("frame variable 'derb.y'", error=True, - substrs=["no member named 'y' in 'DerivedB'"]) + 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")