Skip to content

Commit

Permalink
fix #49 for anonymous unions (#50)
Browse files Browse the repository at this point in the history
* fix #49 for anonymous unions

* fix formatting

* fix mypy and tests

* fix for structs

* fix formatting
  • Loading branch information
tomazsustar authored Jun 14, 2023
1 parent 9bf99db commit 3938d0f
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 3 deletions.
27 changes: 25 additions & 2 deletions cxxheaderparser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ def _parse_enum_decl(
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]:
"""
Expand Down Expand Up @@ -1131,7 +1131,12 @@ def _parse_class_decl(
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]
Expand Down Expand Up @@ -2473,6 +2478,7 @@ def _finish_class_or_enum(
name: PQName,
is_typedef: bool,
mods: ParsedTypeModifiers,
classkey: typing.Optional[str],
) -> None:
parsed_type = Type(name)

Expand All @@ -2481,6 +2487,23 @@ def _finish_class_or_enum(
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:
Expand Down
77 changes: 77 additions & 0 deletions tests/test_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
10 changes: 9 additions & 1 deletion tests/test_union.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -146,7 +154,7 @@ def test_union_anon_in_struct() -> None:
)
),
name="z",
)
),
],
)
]
Expand Down

0 comments on commit 3938d0f

Please sign in to comment.