Merge pull request #30 from robotpy/fix-12

Support __declspec (and other attributes) when parsing a name
This commit is contained in:
Dustin Spicuzza 2021-11-26 10:09:11 -05:00 committed by GitHub
commit bcc57c72c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 11 deletions

View File

@ -614,6 +614,23 @@ class CxxParser:
# Attributes
#
_attribute_specifier_seq_start_types = {"DBL_LBRACKET", "alignas"}
_attribute_start_tokens = {
"__attribute__",
"__declspec",
}
_attribute_start_tokens |= _attribute_specifier_seq_start_types
def _consume_attribute(self, tok: LexToken) -> None:
if tok.type == "__attribute__":
self._consume_gcc_attribute(tok)
elif tok.type == "__declspec":
self._consume_declspec(tok)
elif tok.type in self._attribute_specifier_seq_start_types:
self._consume_attribute_specifier_seq(tok)
else:
raise CxxParseError("internal error")
def _consume_gcc_attribute(
self, tok: LexToken, doxygen: typing.Optional[str] = None
) -> None:
@ -627,8 +644,6 @@ class CxxParser:
tok = self._next_token_must_be("(")
self._consume_balanced_tokens(tok)
_attribute_specifier_seq_start_types = ("DBL_LBRACKET", "alignas")
def _consume_attribute_specifier_seq(
self, tok: LexToken, doxygen: typing.Optional[str] = None
) -> None:
@ -1361,16 +1376,10 @@ class CxxParser:
if tok:
classkey = f"{classkey} {tok.value}"
tok = self.lex.token_if(
"alignas", "__attribute__", "__declspec", "DBL_LBRACKET"
)
# Sometimes there's an embedded attribute
tok = self.lex.token_if(*self._attribute_start_tokens)
if tok:
if tok.type == "__attribute__":
self._consume_gcc_attribute(tok)
elif tok.type == "__declspec":
self._consume_declspec(tok)
else:
self._consume_attribute_specifier_seq(tok)
self._consume_attribute(tok)
tok = self.lex.token_if("NAME", "DBL_COLON")
if not tok:
@ -1898,6 +1907,7 @@ class CxxParser:
pqname: typing.Optional[PQName] = None
_pqname_start_tokens = self._pqname_start_tokens
_attribute_start = self._attribute_start_tokens
# This loop parses until it finds two pqname or ptr/ref
while True:
@ -1926,6 +1936,8 @@ class CxxParser:
vars["mutable"] = tok
elif tok_type == "volatile":
volatile = True
elif tok_type in _attribute_start:
self._consume_attribute(tok)
else:
break

View File

@ -5,8 +5,10 @@ from cxxheaderparser.types import (
EnumDecl,
Enumerator,
Field,
FriendDecl,
Function,
FundamentalSpecifier,
Method,
NameSpecifier,
PQName,
Pointer,
@ -146,3 +148,56 @@ def test_attributes_gcc_enum_packed():
]
)
)
def test_friendly_declspec():
content = """
struct D {
friend __declspec(dllexport) void my_friend();
static __declspec(dllexport) void static_declspec();
};
"""
data = parse_string(content, cleandoc=True)
assert data == ParsedData(
namespace=NamespaceScope(
classes=[
ClassScope(
class_decl=ClassDecl(
typename=PQName(
segments=[NameSpecifier(name="D")], classkey="struct"
)
),
friends=[
FriendDecl(
fn=Method(
return_type=Type(
typename=PQName(
segments=[FundamentalSpecifier(name="void")]
)
),
name=PQName(segments=[NameSpecifier(name="my_friend")]),
parameters=[],
access="public",
)
)
],
methods=[
Method(
return_type=Type(
typename=PQName(
segments=[FundamentalSpecifier(name="void")]
)
),
name=PQName(
segments=[NameSpecifier(name="static_declspec")]
),
parameters=[],
static=True,
access="public",
)
],
)
]
)
)