parent
a67c9c4afe
commit
92f8e72779
@ -359,6 +359,15 @@ class CxxParser:
|
|||||||
# Various
|
# Various
|
||||||
#
|
#
|
||||||
|
|
||||||
|
_msvc_conventions = {
|
||||||
|
"__cdecl",
|
||||||
|
"__clrcall",
|
||||||
|
"__stdcall",
|
||||||
|
"__fastcall",
|
||||||
|
"__thiscall",
|
||||||
|
"__vectorcall",
|
||||||
|
}
|
||||||
|
|
||||||
def _parse_namespace(
|
def _parse_namespace(
|
||||||
self, tok: LexToken, doxygen: typing.Optional[str], inline: bool = False
|
self, tok: LexToken, doxygen: typing.Optional[str], inline: bool = False
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -1655,6 +1664,7 @@ class CxxParser:
|
|||||||
destructor: bool,
|
destructor: bool,
|
||||||
is_friend: bool,
|
is_friend: bool,
|
||||||
is_typedef: bool,
|
is_typedef: bool,
|
||||||
|
msvc_convention: typing.Optional[LexToken],
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Assumes the caller has already consumed the return type and name, this consumes the
|
Assumes the caller has already consumed the return type and name, this consumes the
|
||||||
@ -1670,6 +1680,8 @@ class CxxParser:
|
|||||||
raise self._parse_error(None)
|
raise self._parse_error(None)
|
||||||
|
|
||||||
props = dict.fromkeys(mods.both.keys(), True)
|
props = dict.fromkeys(mods.both.keys(), True)
|
||||||
|
if msvc_convention:
|
||||||
|
props["msvc_convention"] = msvc_convention.value
|
||||||
|
|
||||||
state = self.state
|
state = self.state
|
||||||
state.location = location
|
state.location = location
|
||||||
@ -1758,6 +1770,7 @@ class CxxParser:
|
|||||||
fn.vararg,
|
fn.vararg,
|
||||||
fn.has_trailing_return,
|
fn.has_trailing_return,
|
||||||
noexcept=fn.noexcept,
|
noexcept=fn.noexcept,
|
||||||
|
msvc_convention=fn.msvc_convention,
|
||||||
)
|
)
|
||||||
|
|
||||||
typedef = Typedef(fntype, pqname.segments[0].name, self._current_access)
|
typedef = Typedef(fntype, pqname.segments[0].name, self._current_access)
|
||||||
@ -1823,6 +1836,10 @@ class CxxParser:
|
|||||||
self._parse_trailing_return_type(dtype)
|
self._parse_trailing_return_type(dtype)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
msvc_convention = self.lex.token_if_val(*self._msvc_conventions)
|
||||||
|
if msvc_convention:
|
||||||
|
msvc_convention = msvc_convention.value
|
||||||
|
|
||||||
# Check to see if this is a grouping paren or something else
|
# Check to see if this is a grouping paren or something else
|
||||||
if not self.lex.token_peek_if("*", "&"):
|
if not self.lex.token_peek_if("*", "&"):
|
||||||
self.lex.return_token(tok)
|
self.lex.return_token(tok)
|
||||||
@ -1840,7 +1857,9 @@ class CxxParser:
|
|||||||
fn_params, vararg = self._parse_parameters()
|
fn_params, vararg = self._parse_parameters()
|
||||||
# the type we already have is the return type of the function pointer
|
# the type we already have is the return type of the function pointer
|
||||||
|
|
||||||
dtype = FunctionType(dtype, fn_params, vararg)
|
dtype = FunctionType(
|
||||||
|
dtype, fn_params, vararg, msvc_convention=msvc_convention
|
||||||
|
)
|
||||||
|
|
||||||
# the inner tokens must either be a * or a pqname that ends
|
# the inner tokens must either be a * or a pqname that ends
|
||||||
# with ::* (member function pointer)
|
# with ::* (member function pointer)
|
||||||
@ -1975,6 +1994,7 @@ class CxxParser:
|
|||||||
constructor = False
|
constructor = False
|
||||||
destructor = False
|
destructor = False
|
||||||
op = None
|
op = None
|
||||||
|
msvc_convention = None
|
||||||
|
|
||||||
# If we have a leading (, that's either an obnoxious grouping
|
# If we have a leading (, that's either an obnoxious grouping
|
||||||
# paren or it's a constructor
|
# paren or it's a constructor
|
||||||
@ -2021,6 +2041,8 @@ class CxxParser:
|
|||||||
self.lex.return_tokens(toks[1:-1])
|
self.lex.return_tokens(toks[1:-1])
|
||||||
|
|
||||||
if dtype:
|
if dtype:
|
||||||
|
msvc_convention = self.lex.token_if_val(*self._msvc_conventions)
|
||||||
|
|
||||||
tok = self.lex.token_if_in_set(self._pqname_start_tokens)
|
tok = self.lex.token_if_in_set(self._pqname_start_tokens)
|
||||||
if tok:
|
if tok:
|
||||||
pqname, op = self._parse_pqname(tok, fn_ok=True)
|
pqname, op = self._parse_pqname(tok, fn_ok=True)
|
||||||
@ -2046,7 +2068,10 @@ class CxxParser:
|
|||||||
destructor,
|
destructor,
|
||||||
is_friend,
|
is_friend,
|
||||||
is_typedef,
|
is_typedef,
|
||||||
|
msvc_convention,
|
||||||
)
|
)
|
||||||
|
elif msvc_convention:
|
||||||
|
raise self._parse_error(msvc_convention)
|
||||||
|
|
||||||
# anything else is a field/variable
|
# anything else is a field/variable
|
||||||
if is_friend:
|
if is_friend:
|
||||||
|
@ -238,6 +238,14 @@ class FunctionType:
|
|||||||
|
|
||||||
noexcept: typing.Optional[Value] = None
|
noexcept: typing.Optional[Value] = None
|
||||||
|
|
||||||
|
#: Only set if an MSVC calling convention (__stdcall, etc) is explictly
|
||||||
|
#: specified.
|
||||||
|
#:
|
||||||
|
#: .. note:: If your code contains things like WINAPI, you will need to
|
||||||
|
#: use a preprocessor to transform it to the appropriate
|
||||||
|
#: calling convention
|
||||||
|
msvc_convention: typing.Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Type:
|
class Type:
|
||||||
@ -487,6 +495,14 @@ class Function:
|
|||||||
throw: typing.Optional[Value] = None
|
throw: typing.Optional[Value] = None
|
||||||
noexcept: typing.Optional[Value] = None
|
noexcept: typing.Optional[Value] = None
|
||||||
|
|
||||||
|
#: Only set if an MSVC calling convention (__stdcall, etc) is explictly
|
||||||
|
#: specified.
|
||||||
|
#:
|
||||||
|
#: .. note:: If your code contains things like WINAPI, you will need to
|
||||||
|
#: use a preprocessor to transform it to the appropriate
|
||||||
|
#: calling convention
|
||||||
|
msvc_convention: typing.Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Method(Function):
|
class Method(Function):
|
||||||
|
@ -20,6 +20,7 @@ from cxxheaderparser.types import (
|
|||||||
TemplateTypeParam,
|
TemplateTypeParam,
|
||||||
Token,
|
Token,
|
||||||
Type,
|
Type,
|
||||||
|
Typedef,
|
||||||
Value,
|
Value,
|
||||||
)
|
)
|
||||||
from cxxheaderparser.simple import (
|
from cxxheaderparser.simple import (
|
||||||
@ -993,3 +994,54 @@ def test_fn_w_mvreference():
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_msvc_conventions():
|
||||||
|
content = """
|
||||||
|
void __cdecl fn();
|
||||||
|
typedef const char* (__stdcall *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
|
||||||
|
"""
|
||||||
|
data = parse_string(content, cleandoc=True)
|
||||||
|
|
||||||
|
assert data == ParsedData(
|
||||||
|
namespace=NamespaceScope(
|
||||||
|
functions=[
|
||||||
|
Function(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
||||||
|
parameters=[],
|
||||||
|
msvc_convention="__cdecl",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
typedefs=[
|
||||||
|
Typedef(
|
||||||
|
type=Pointer(
|
||||||
|
ptr_to=FunctionType(
|
||||||
|
return_type=Pointer(
|
||||||
|
ptr_to=Type(
|
||||||
|
typename=PQName(
|
||||||
|
segments=[FundamentalSpecifier(name="char")]
|
||||||
|
),
|
||||||
|
const=True,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
parameters=[
|
||||||
|
Parameter(
|
||||||
|
type=Type(
|
||||||
|
typename=PQName(
|
||||||
|
segments=[NameSpecifier(name="HDC")]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
name="theDeviceContext",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
msvc_convention="__stdcall",
|
||||||
|
)
|
||||||
|
),
|
||||||
|
name="wglGetExtensionsStringARB_t",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user