fix #49 for anonymous unions (#50)

* fix #49 for anonymous unions

* fix formatting

* fix mypy and tests

* fix for structs

* fix formatting
This commit is contained in:
Tomaž Šuštar 2023-06-14 19:31:10 +02:00 committed by GitHub
parent 9bf99db87b
commit 3938d0ffef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 111 additions and 3 deletions

View File

@ -952,7 +952,7 @@ class CxxParser:
self.visitor.on_enum(self.state, enum)
# Finish it up
self._finish_class_or_enum(enum.typename, is_typedef, mods)
self._finish_class_or_enum(enum.typename, is_typedef, mods, "enum")
def _parse_enumerator_list(self) -> typing.List[Enumerator]:
"""
@ -1131,7 +1131,12 @@ class CxxParser:
self.visitor.on_class_start(state)
def _finish_class_decl(self, state: ClassBlockState) -> None:
self._finish_class_or_enum(state.class_decl.typename, state.typedef, state.mods)
self._finish_class_or_enum(
state.class_decl.typename,
state.typedef,
state.mods,
state.class_decl.classkey,
)
def _process_access_specifier(
self, tok: LexToken, doxygen: typing.Optional[str]
@ -2473,6 +2478,7 @@ class CxxParser:
name: PQName,
is_typedef: bool,
mods: ParsedTypeModifiers,
classkey: typing.Optional[str],
) -> None:
parsed_type = Type(name)
@ -2481,6 +2487,23 @@ class CxxParser:
self._consume_gcc_attribute(tok)
if not is_typedef and self.lex.token_if(";"):
# if parent scope is a class, add the anonymous
# union or struct to the parent fields
if isinstance(self.state, ClassBlockState):
class_state = self.state
access = self._current_access
assert access is not None
if (
classkey is not None
and classkey in ["union", "struct"]
and isinstance(name.segments[-1], AnonymousName)
):
f = Field(
type=Type(name),
access=access,
)
self.visitor.on_class_field(class_state, f)
return
while True:

View File

@ -1633,6 +1633,83 @@ def test_class_anon_struct_as_classvar() -> None:
)
def test_class_anon_struct_as_unnamed_classvar() -> None:
content = """
struct AnonHolderClass {
struct {
int x;
int y;
};
int z;
};
"""
data = parse_string(content, cleandoc=True)
assert data == ParsedData(
namespace=NamespaceScope(
classes=[
ClassScope(
class_decl=ClassDecl(
typename=PQName(
segments=[NameSpecifier(name="AnonHolderClass")],
classkey="struct",
)
),
classes=[
ClassScope(
class_decl=ClassDecl(
typename=PQName(
segments=[AnonymousName(id=1)], classkey="struct"
),
access="public",
),
fields=[
Field(
access="public",
type=Type(
typename=PQName(
segments=[FundamentalSpecifier(name="int")]
)
),
name="x",
),
Field(
access="public",
type=Type(
typename=PQName(
segments=[FundamentalSpecifier(name="int")]
)
),
name="y",
),
],
)
],
fields=[
Field(
access="public",
type=Type(
typename=PQName(
segments=[AnonymousName(id=1)], classkey="struct"
)
),
),
Field(
access="public",
type=Type(
typename=PQName(
segments=[FundamentalSpecifier(name="int")]
)
),
name="z",
),
],
)
]
)
)
def test_initializer_with_initializer_list_1() -> None:
content = """
struct ComplexInit : SomeBase {

View File

@ -138,6 +138,14 @@ def test_union_anon_in_struct() -> None:
)
],
fields=[
Field(
access="public",
type=Type(
typename=PQName(
segments=[AnonymousName(id=1)], classkey="union"
)
),
),
Field(
access="public",
type=Type(
@ -146,7 +154,7 @@ def test_union_anon_in_struct() -> None:
)
),
name="z",
)
),
],
)
]