mypy: address issues parsing const/volatile/*/& items

This commit is contained in:
Dustin Spicuzza 2022-01-02 21:52:36 -05:00
parent 83aa34d06e
commit f29c1d5a30
2 changed files with 42 additions and 11 deletions

View File

@ -602,7 +602,7 @@ class CxxParser:
raise self._parse_error(None) raise self._parse_error(None)
mods.validate(var_ok=False, meth_ok=False, msg="") mods.validate(var_ok=False, meth_ok=False, msg="")
dtype = self._parse_cv_ptr(parsed_type, nonptr_fn=True) dtype = self._parse_cv_ptr_or_fn(parsed_type, nonptr_fn=True)
self._next_token_must_be(PhonyEnding.type) self._next_token_must_be(PhonyEnding.type)
except CxxParseError: except CxxParseError:
dtype = None dtype = None
@ -1220,6 +1220,7 @@ class CxxParser:
) )
self.visitor.on_class_field(class_state, f) self.visitor.on_class_field(class_state, f)
else: else:
assert pqname is not None
v = Variable( v = Variable(
pqname, dtype, default, doxygen=doxygen, template=template, **props pqname, dtype, default, doxygen=doxygen, template=template, **props
) )
@ -1757,7 +1758,7 @@ class CxxParser:
else: else:
# method must not have multiple segments except for operator # method must not have multiple segments except for operator
if len(pqname.segments) > 1: if len(pqname.segments) > 1:
if not pqname.segments[0].name == "operator": if getattr(pqname.segments[0], "name", None) != "operator":
raise self._parse_error(None) raise self._parse_error(None)
self.visitor.on_class_method(state, method) self.visitor.on_class_method(state, method)
@ -1827,6 +1828,9 @@ class CxxParser:
assert tok.type == "[" assert tok.type == "["
if isinstance(dtype, (Reference, MoveReference)):
raise CxxParseError("arrays of references are illegal", tok)
toks = self._consume_balanced_tokens(tok) toks = self._consume_balanced_tokens(tok)
otok = self.lex.token_if("[") otok = self.lex.token_if("[")
if otok: if otok:
@ -1843,9 +1847,20 @@ class CxxParser:
def _parse_cv_ptr( def _parse_cv_ptr(
self, self,
dtype: typing.Union[Array, FunctionType, Pointer, Type], dtype: DecoratedType,
nonptr_fn: bool = False,
) -> DecoratedType: ) -> DecoratedType:
dtype_or_fn = self._parse_cv_ptr_or_fn(dtype)
if isinstance(dtype_or_fn, FunctionType):
raise CxxParseError("unexpected function type")
return dtype_or_fn
def _parse_cv_ptr_or_fn(
self,
dtype: typing.Union[
Array, Pointer, MoveReference, Reference, Type, FunctionType
],
nonptr_fn: bool = False,
) -> typing.Union[Array, Pointer, MoveReference, Reference, Type, FunctionType]:
# nonptr_fn is for parsing function types directly in template specialization # nonptr_fn is for parsing function types directly in template specialization
while True: while True:
@ -1854,10 +1869,16 @@ class CxxParser:
break break
if tok.type == "*": if tok.type == "*":
if isinstance(dtype, (Reference, MoveReference)):
raise self._parse_error(tok)
dtype = Pointer(dtype) dtype = Pointer(dtype)
elif tok.type == "const": elif tok.type == "const":
if not isinstance(dtype, (Pointer, Type)):
raise self._parse_error(tok)
dtype.const = True dtype.const = True
elif tok.type == "volatile": elif tok.type == "volatile":
if not isinstance(dtype, (Pointer, Type)):
raise self._parse_error(tok)
dtype.volatile = True dtype.volatile = True
elif nonptr_fn: elif nonptr_fn:
# remove any inner grouping parens # remove any inner grouping parens
@ -1870,9 +1891,11 @@ class CxxParser:
self.lex.return_tokens(toks[1:-1]) self.lex.return_tokens(toks[1:-1])
fn_params, vararg = self._parse_parameters() fn_params, vararg = self._parse_parameters()
dtype = FunctionType(dtype, fn_params, vararg)
assert not isinstance(dtype, FunctionType)
dtype = dtype_fn = FunctionType(dtype, fn_params, vararg)
if self.lex.token_if("ARROW"): if self.lex.token_if("ARROW"):
self._parse_trailing_return_type(dtype) self._parse_trailing_return_type(dtype_fn)
else: else:
msvc_convention = None msvc_convention = None
@ -1892,11 +1915,14 @@ class CxxParser:
aptok = self.lex.token_if("[", "(") aptok = self.lex.token_if("[", "(")
if aptok: if aptok:
if aptok.type == "[": if aptok.type == "[":
assert not isinstance(dtype, FunctionType)
dtype = self._parse_array_type(aptok, dtype) dtype = self._parse_array_type(aptok, dtype)
elif aptok.type == "(": elif aptok.type == "(":
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
assert not isinstance(dtype, FunctionType)
dtype = FunctionType( dtype = FunctionType(
dtype, fn_params, vararg, msvc_convention=msvc_convention dtype, fn_params, vararg, msvc_convention=msvc_convention
) )
@ -1909,11 +1935,13 @@ class CxxParser:
# -> this could return some weird results for invalid code, but # -> this could return some weird results for invalid code, but
# we don't support that anyways so it's fine? # we don't support that anyways so it's fine?
self.lex.return_tokens(toks[1:-1]) self.lex.return_tokens(toks[1:-1])
dtype = self._parse_cv_ptr(dtype) dtype = self._parse_cv_ptr_or_fn(dtype, nonptr_fn)
break break
tok = self.lex.token_if("&", "DBL_AMP") tok = self.lex.token_if("&", "DBL_AMP")
if tok: if tok:
assert not isinstance(dtype, (Reference, MoveReference))
if tok.type == "&": if tok.type == "&":
dtype = Reference(dtype) dtype = Reference(dtype)
else: else:
@ -1922,7 +1950,7 @@ class CxxParser:
# peek at the next token and see if it's a paren. If so, it might # peek at the next token and see if it's a paren. If so, it might
# be a nasty function pointer # be a nasty function pointer
if self.lex.token_peek_if("("): if self.lex.token_peek_if("("):
dtype = self._parse_cv_ptr(dtype, nonptr_fn) dtype = self._parse_cv_ptr_or_fn(dtype, nonptr_fn)
return dtype return dtype
@ -2147,6 +2175,9 @@ class CxxParser:
if op: if op:
raise self._parse_error(None) raise self._parse_error(None)
if not dtype:
raise CxxParseError("appear to be parsing a field without a type")
self._parse_field(mods, dtype, pqname, template, doxygen, location, is_typedef) self._parse_field(mods, dtype, pqname, template, doxygen, location, is_typedef)
return False return False

View File

@ -193,7 +193,7 @@ class TemplateArgument:
#: If this argument is a type, it is stored here as a DecoratedType, #: If this argument is a type, it is stored here as a DecoratedType,
#: otherwise it's stored as an unparsed set of values #: otherwise it's stored as an unparsed set of values
arg: typing.Union["DecoratedType", Value] arg: typing.Union["DecoratedType", "FunctionType", Value]
param_pack: bool = False param_pack: bool = False
@ -297,7 +297,7 @@ class Reference:
A lvalue (``&``) reference A lvalue (``&``) reference
""" """
ref_to: typing.Union[Array, Pointer, Type] ref_to: typing.Union[Array, FunctionType, Pointer, Type]
@dataclass @dataclass
@ -306,7 +306,7 @@ class MoveReference:
An rvalue (``&&``) reference An rvalue (``&&``) reference
""" """
moveref_to: typing.Union[Array, Pointer, Type] moveref_to: typing.Union[Array, FunctionType, Pointer, Type]
#: A type or function type that is decorated with various things #: A type or function type that is decorated with various things