diff --git a/cxxheaderparser/parser.py b/cxxheaderparser/parser.py index 20e678f..6f4d833 100644 --- a/cxxheaderparser/parser.py +++ b/cxxheaderparser/parser.py @@ -1503,7 +1503,6 @@ class CxxParser: param = self._parse_parameter(None, Parameter) params.append(param) - tok = self._next_token_must_be(",", ")") if tok.value == ")": break @@ -1812,6 +1811,11 @@ class CxxParser: else: dtype = MoveReference(dtype) + # peek at the next token and see if it's a paren. If so, it might + # be a nasty function pointer + if self.lex.token_peek_if("("): + dtype = self._parse_cv_ptr(dtype, nonptr_fn) + return dtype # Applies to variables and return values diff --git a/tests/test_fn.py b/tests/test_fn.py index c8d974a..651f922 100644 --- a/tests/test_fn.py +++ b/tests/test_fn.py @@ -3,10 +3,13 @@ from cxxheaderparser.types import ( Array, AutoSpecifier, + ClassDecl, Function, FunctionType, FundamentalSpecifier, + MoveReference, NameSpecifier, + Operator, PQName, Parameter, Pointer, @@ -20,6 +23,7 @@ from cxxheaderparser.types import ( Value, ) from cxxheaderparser.simple import ( + ClassScope, NamespaceScope, parse_string, ParsedData, @@ -857,3 +861,135 @@ def test_inline_volatile_fn(): ] ) ) + + +def test_method_w_reference(): + content = """ + struct StreamBuffer + { + StreamBuffer &operator<<(std::ostream &(*fn)(std::ostream &)) + { + return *this; + } + }; + + """ + data = parse_string(content, cleandoc=True) + + assert data == ParsedData( + namespace=NamespaceScope( + classes=[ + ClassScope( + class_decl=ClassDecl( + typename=PQName( + segments=[NameSpecifier(name="StreamBuffer")], + classkey="struct", + ) + ), + methods=[ + Operator( + return_type=Reference( + ref_to=Type( + typename=PQName( + segments=[NameSpecifier(name="StreamBuffer")] + ) + ) + ), + name=PQName(segments=[NameSpecifier(name="operator<<")]), + parameters=[ + Parameter( + type=Pointer( + ptr_to=FunctionType( + return_type=Reference( + ref_to=Type( + typename=PQName( + segments=[ + NameSpecifier(name="std"), + NameSpecifier( + name="ostream" + ), + ] + ) + ) + ), + parameters=[ + Parameter( + type=Reference( + ref_to=Type( + typename=PQName( + segments=[ + NameSpecifier( + name="std" + ), + NameSpecifier( + name="ostream" + ), + ] + ) + ) + ) + ) + ], + ) + ), + name="fn", + ) + ], + has_body=True, + access="public", + operator="<<", + ) + ], + ) + ] + ) + ) + + +def test_fn_w_mvreference(): + content = """ + void fn1(int && (*)(int)); + + """ + 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="fn1")]), + parameters=[ + Parameter( + type=Pointer( + ptr_to=FunctionType( + return_type=MoveReference( + moveref_to=Type( + typename=PQName( + segments=[ + FundamentalSpecifier(name="int") + ] + ) + ) + ), + parameters=[ + Parameter( + type=Type( + typename=PQName( + segments=[ + FundamentalSpecifier(name="int") + ] + ) + ) + ) + ], + ) + ) + ) + ], + ) + ] + ) + )