Merge pull request #30 from robotpy/fix-12
Support __declspec (and other attributes) when parsing a name
This commit is contained in:
commit
bcc57c72c0
@ -614,6 +614,23 @@ class CxxParser:
|
|||||||
# Attributes
|
# 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(
|
def _consume_gcc_attribute(
|
||||||
self, tok: LexToken, doxygen: typing.Optional[str] = None
|
self, tok: LexToken, doxygen: typing.Optional[str] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -627,8 +644,6 @@ class CxxParser:
|
|||||||
tok = self._next_token_must_be("(")
|
tok = self._next_token_must_be("(")
|
||||||
self._consume_balanced_tokens(tok)
|
self._consume_balanced_tokens(tok)
|
||||||
|
|
||||||
_attribute_specifier_seq_start_types = ("DBL_LBRACKET", "alignas")
|
|
||||||
|
|
||||||
def _consume_attribute_specifier_seq(
|
def _consume_attribute_specifier_seq(
|
||||||
self, tok: LexToken, doxygen: typing.Optional[str] = None
|
self, tok: LexToken, doxygen: typing.Optional[str] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -1361,16 +1376,10 @@ class CxxParser:
|
|||||||
if tok:
|
if tok:
|
||||||
classkey = f"{classkey} {tok.value}"
|
classkey = f"{classkey} {tok.value}"
|
||||||
|
|
||||||
tok = self.lex.token_if(
|
# Sometimes there's an embedded attribute
|
||||||
"alignas", "__attribute__", "__declspec", "DBL_LBRACKET"
|
tok = self.lex.token_if(*self._attribute_start_tokens)
|
||||||
)
|
|
||||||
if tok:
|
if tok:
|
||||||
if tok.type == "__attribute__":
|
self._consume_attribute(tok)
|
||||||
self._consume_gcc_attribute(tok)
|
|
||||||
elif tok.type == "__declspec":
|
|
||||||
self._consume_declspec(tok)
|
|
||||||
else:
|
|
||||||
self._consume_attribute_specifier_seq(tok)
|
|
||||||
|
|
||||||
tok = self.lex.token_if("NAME", "DBL_COLON")
|
tok = self.lex.token_if("NAME", "DBL_COLON")
|
||||||
if not tok:
|
if not tok:
|
||||||
@ -1898,6 +1907,7 @@ class CxxParser:
|
|||||||
pqname: typing.Optional[PQName] = None
|
pqname: typing.Optional[PQName] = None
|
||||||
|
|
||||||
_pqname_start_tokens = self._pqname_start_tokens
|
_pqname_start_tokens = self._pqname_start_tokens
|
||||||
|
_attribute_start = self._attribute_start_tokens
|
||||||
|
|
||||||
# This loop parses until it finds two pqname or ptr/ref
|
# This loop parses until it finds two pqname or ptr/ref
|
||||||
while True:
|
while True:
|
||||||
@ -1926,6 +1936,8 @@ class CxxParser:
|
|||||||
vars["mutable"] = tok
|
vars["mutable"] = tok
|
||||||
elif tok_type == "volatile":
|
elif tok_type == "volatile":
|
||||||
volatile = True
|
volatile = True
|
||||||
|
elif tok_type in _attribute_start:
|
||||||
|
self._consume_attribute(tok)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -5,8 +5,10 @@ from cxxheaderparser.types import (
|
|||||||
EnumDecl,
|
EnumDecl,
|
||||||
Enumerator,
|
Enumerator,
|
||||||
Field,
|
Field,
|
||||||
|
FriendDecl,
|
||||||
Function,
|
Function,
|
||||||
FundamentalSpecifier,
|
FundamentalSpecifier,
|
||||||
|
Method,
|
||||||
NameSpecifier,
|
NameSpecifier,
|
||||||
PQName,
|
PQName,
|
||||||
Pointer,
|
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",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user