Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1700,8 +1700,11 @@ void DWARFASTParserClang::GetUniqueTypeNameAndDeclaration(
// For C++, we rely solely upon the one definition rule that says
// only one thing can exist at a given decl context. We ignore the
// file and line that things are declared on.
if (!die.IsValid() || !Language::LanguageIsCPlusPlus(language) ||
unique_typename.IsEmpty())
// FIXME: Rust pretends to be C++ for now, so use C++ name qualification rules
if (!Language::LanguageIsCPlusPlus(language) &&
language != lldb::eLanguageTypeRust)
return;
if (!die.IsValid() || unique_typename.IsEmpty())
return;
decl_declaration.Clear();
std::string qualified_name;
Expand Down
69 changes: 69 additions & 0 deletions lldb/test/API/lang/rust/enum-variant-same-name/RustEnumValue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Helper library to traverse data emitted for Rust enums """
from lldbsuite.test.lldbtest import *

DISCRIMINANT_MEMBER_NAME = "$discr$"
VALUE_MEMBER_NAME = "value"


class RustEnumValue:
def __init__(self, value: lldb.SBValue):
self.value = value

def getAllVariantTypes(self):
result = []
for i in range(self._inner().GetNumChildren()):
result.append(self.getVariantByIndex(i).GetDisplayTypeName())
return result

def _inner(self) -> lldb.SBValue:
return self.value.GetChildAtIndex(0)

def getVariantByIndex(self, index):
return (
self._inner()
.GetChildAtIndex(index)
.GetChildMemberWithName(VALUE_MEMBER_NAME)
)

@staticmethod
def _getDiscriminantValueAsUnsigned(discr_sbvalue: lldb.SBValue):
byte_size = discr_sbvalue.GetType().GetByteSize()
error = lldb.SBError()

# when discriminant is u16 Clang emits 'unsigned char'
# and LLDB seems to treat it as character type disalowing to call GetValueAsUnsigned
if byte_size == 1:
return discr_sbvalue.GetData().GetUnsignedInt8(error, 0)
elif byte_size == 2:
return discr_sbvalue.GetData().GetUnsignedInt16(error, 0)
elif byte_size == 4:
return discr_sbvalue.GetData().GetUnsignedInt32(error, 0)
elif byte_size == 8:
return discr_sbvalue.GetData().GetUnsignedInt64(error, 0)
else:
return discr_sbvalue.GetValueAsUnsigned()

def getCurrentVariantIndex(self):
default_index = 0
for i in range(self._inner().GetNumChildren()):
variant: lldb.SBValue = self._inner().GetChildAtIndex(i)
discr = variant.GetChildMemberWithName(DISCRIMINANT_MEMBER_NAME)
if discr.IsValid():
discr_unsigned_value = RustEnumValue._getDiscriminantValueAsUnsigned(
discr
)
if variant.GetName() == f"$variant${discr_unsigned_value}":
return discr_unsigned_value
else:
default_index = i
return default_index

def getFields(self):
result = []
for i in range(self._inner().GetNumChildren()):
type: lldb.SBType = self._inner().GetType()
result.append(type.GetFieldAtIndex(i).GetName())
return result

def getCurrentValue(self) -> lldb.SBValue:
return self.getVariantByIndex(self.getCurrentVariantIndex())
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Test that lldb recognizes enum variant emitted by Rust compiler """
import logging

import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from RustEnumValue import RustEnumValue


class TestRustEnumStructs(TestBase):
def setUp(self):
TestBase.setUp(self)
src_dir = self.getSourceDir()
yaml_path = os.path.join(src_dir, "main.yaml")
obj_path = self.getBuildArtifact("main.o")
self.yaml2obj(yaml_path, obj_path)
self.dbg.CreateTarget(obj_path)

def getFromGlobal(self, name):
values = self.target().FindGlobalVariables(name, 1)
self.assertEqual(values.GetSize(), 1)
return RustEnumValue(values[0])

def test_enum_instance(self):
# static ENUM_INSTANCE: A = A::A(B::B(10));
value = self.getFromGlobal("ENUM_INSTANCE").getCurrentValue()
self.assertEqual(value.GetType().GetDisplayTypeName(), "main::A::A")

value_b = RustEnumValue(value.GetChildAtIndex(0))
self.assertEqual(
value_b.getCurrentValue()
.GetChildAtIndex(0)
.GetData()
.GetUnsignedInt8(lldb.SBError(), 0),
10,
)
15 changes: 15 additions & 0 deletions lldb/test/API/lang/rust/enum-variant-same-name/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/// Command:
/// rustc -g --emit=obj --crate-type=bin -C panic=abort -C link-arg=-nostdlib main.rs && obj2yaml main.o -o main.yaml

pub enum A {
A(B),
}

pub enum B {
B(u8),
}

static ENUM_INSTANCE: A = A::A(B::B(10));

pub fn main() {
}
Loading
Loading