Skip to content

Commit cba8a9e

Browse files
committed
feat: improve template parameter parsing logics
1 parent d4b8fcd commit cba8a9e

2 files changed

Lines changed: 79 additions & 31 deletions

File tree

src/dwarf2cpp/models.py

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,41 @@ class TemplateParameterKind(enum.StrEnum):
197197

198198
@dataclass
199199
class TemplateParameter:
200-
name: str
201200
kind: TemplateParameterKind
202-
type: str | None = None
203-
arg: str | None = field(default=None, compare=False)
204-
pack: list["TemplateParameter"] | None = field(default_factory=list, compare=False)
201+
name: str | None = None
205202
default: str | None = None
203+
type: str | None = None
204+
value: str | None = None
205+
parameters: list["TemplateParameter"] = field(default_factory=list)
206+
207+
def to_declaration(self) -> "TemplateParameter":
208+
match self.kind:
209+
case TemplateParameterKind.TYPE:
210+
return TemplateParameter(
211+
TemplateParameterKind.TYPE,
212+
name=self.name,
213+
default=self.default,
214+
)
215+
case TemplateParameterKind.CONSTANT:
216+
return TemplateParameter(
217+
TemplateParameterKind.CONSTANT,
218+
type=self.type,
219+
name=self.name,
220+
default=self.default,
221+
)
222+
case TemplateParameterKind.TEMPLATE:
223+
return TemplateParameter(
224+
TemplateParameterKind.TEMPLATE,
225+
parameters=[p.to_declaration() for p in self.parameters],
226+
name=self.name,
227+
default=self.default,
228+
)
229+
case TemplateParameterKind.PACK:
230+
return TemplateParameter(
231+
TemplateParameterKind.PACK,
232+
parameters=[p.to_declaration() for p in self.parameters],
233+
name=self.name,
234+
)
206235

207236

208237
@dataclass
@@ -223,16 +252,10 @@ def merge(self, other: "Template") -> bool:
223252
return False
224253

225254
for p1, p2 in zip(self.parameters, other.parameters):
226-
if (
227-
p1.name != p2.name
228-
or p1.kind != p2.kind
229-
or p1.type != p2.type
230-
or p1.arg is not None
231-
or p2.arg is not None
232-
):
255+
if p1.name != p2.name or p1.kind != p2.kind:
233256
return False
234257

235258
for p1, p2 in zip(self.parameters, other.parameters):
236-
p1.default = p1.default or p2.default
259+
raise NotImplementedError
237260

238261
return True

src/dwarf2cpp/visitor.py

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -607,22 +607,22 @@ def visit_imported_declaration(self, die: DWARFDie) -> None:
607607
self._cache[die.offset] = imported_decl
608608

609609
def visit_template_type_parameter(self, die: DWARFDie) -> None:
610-
param = TemplateParameter(die.short_name, TemplateParameterKind.TYPE)
610+
param = TemplateParameter(TemplateParameterKind.TYPE, name=die.short_name)
611611

612612
# A template type parameter entry has a DW_AT_type attribute
613613
# describing the actual type by which the formal is replaced.
614614
if ty := die.find("DW_AT_type"):
615-
param.arg = get_qualified_type(ty.as_referenced_die())
615+
param.type = get_qualified_type(ty.as_referenced_die())
616616
else:
617-
param.arg = "void"
617+
param.type = "void"
618618

619619
for attribute in die.attributes:
620620
if attribute.name in {"DW_AT_name", "DW_AT_type"}:
621621
continue
622622

623623
match attribute.name:
624624
case "DW_AT_default_value":
625-
param.default = param.arg
625+
param.default = param.type
626626
case _:
627627
raise ValueError(f"Unhandled attribute {attribute.name}")
628628

@@ -632,19 +632,19 @@ def visit_template_type_parameter(self, die: DWARFDie) -> None:
632632
self._cache[die.offset] = param
633633

634634
def visit_template_value_parameter(self, die: DWARFDie) -> None:
635-
param = TemplateParameter(die.short_name, TemplateParameterKind.CONSTANT)
635+
param = TemplateParameter(TemplateParameterKind.CONSTANT, name=die.short_name)
636636
param.type = get_qualified_type(die.find("DW_AT_type").as_referenced_die())
637637

638638
if value := die.find("DW_AT_const_value"):
639-
param.arg = value.as_constant()
639+
param.value = value.as_constant()
640640

641641
for attribute in die.attributes:
642642
if attribute.name in {"DW_AT_name", "DW_AT_type", "DW_AT_const_value", "DW_AT_location"}:
643643
continue
644644

645645
match attribute.name:
646646
case "DW_AT_default_value":
647-
param.default = param.arg
647+
param.default = param.value
648648
case _:
649649
raise ValueError(f"Unhandled attribute {attribute.name}")
650650

@@ -654,7 +654,7 @@ def visit_template_value_parameter(self, die: DWARFDie) -> None:
654654
self._cache[die.offset] = param
655655

656656
def visit_GNU_template_parameter_pack(self, die: DWARFDie) -> None:
657-
param = TemplateParameter(die.short_name, TemplateParameterKind.PACK)
657+
param = TemplateParameter(TemplateParameterKind.PACK, name=die.short_name)
658658

659659
for attribute in die.attributes:
660660
if attribute.name in {"DW_AT_name"}:
@@ -664,21 +664,49 @@ def visit_GNU_template_parameter_pack(self, die: DWARFDie) -> None:
664664
case _:
665665
raise ValueError(f"Unhandled attribute {attribute.name}")
666666

667-
pack = []
667+
pack_type = None
668+
parameters = []
668669
for child in die.children:
669-
if child.tag in {"DW_TAG_template_type_parameter", "DW_TAG_template_value_parameter"}:
670+
if child.tag == "DW_TAG_template_type_parameter":
671+
assert pack_type is None, "Expected pack type to be None"
670672
self.visit(child)
671-
pack.append(self._cache[child.offset])
673+
p = self._cache[child.offset]
674+
parameters.append(p)
675+
elif child.tag == "DW_TAG_template_value_parameter":
676+
self.visit(child)
677+
p = self._cache[child.offset]
678+
if pack_type is None:
679+
assert len(parameters) == 0, "Expected no parameters"
680+
pack_type = p.type
681+
else:
682+
assert p.type == pack_type, "Expected same type"
683+
parameters.append(p)
672684
else:
673685
raise ValueError(f"Unhandled child tag {child.tag}")
674686

675-
if pack:
676-
param.pack = pack
687+
if parameters:
688+
param.parameters = parameters
677689

678690
self._cache[die.offset] = param
679691

680692
def visit_GNU_template_template_param(self, die: DWARFDie) -> None:
681-
self._cache[die.offset] = TemplateParameter(die.short_name, TemplateParameterKind.TEMPLATE)
693+
param = TemplateParameter(TemplateParameterKind.TEMPLATE, name=die.short_name)
694+
695+
for attribute in die.attributes:
696+
if attribute.name in {"DW_AT_name"}:
697+
continue
698+
699+
match attribute.name:
700+
case "DW_AT_GNU_template_name":
701+
param.type = attribute.value.as_string()
702+
case _:
703+
raise ValueError(f"Unhandled attribute {attribute.name}")
704+
705+
for child in die.children:
706+
raise ValueError(f"Unhandled child tag {child.tag}")
707+
708+
self._cache[die.offset] = param
709+
print(param)
682710

683711
def generic_visit(self, die: DWARFDie) -> None:
684712
for child in die.children:
@@ -699,12 +727,9 @@ def _register_template(self, key: str | int, lineno: int, template: Template) ->
699727

700728
# make a copy for template declaration
701729
template = copy.copy(template)
702-
for parameter in template.parameters:
703-
# declaration must not have type replacement
704-
parameter.arg = None
705-
parameter.pack = None
730+
template.parameters = [p.to_declaration() for p in template.parameters]
706731

707-
# try to merge with existing templates
732+
# try to merge with existing templates
708733
for t in templates:
709734
if t.merge(template):
710735
return None

0 commit comments

Comments
 (0)