diff --git a/cxxheaderparser/parser.py b/cxxheaderparser/parser.py index 7cea0ea..fc658cc 100644 --- a/cxxheaderparser/parser.py +++ b/cxxheaderparser/parser.py @@ -901,11 +901,17 @@ def _consume_attribute(self, tok: LexToken) -> None: raise CxxParseError("internal error") def _consume_gcc_attribute( - self, tok: LexToken, doxygen: typing.Optional[str] = None + self, tok: typing.Optional[LexToken], doxygen: typing.Optional[str] = None ) -> None: - tok1 = self._next_token_must_be("(") - tok2 = self._next_token_must_be("(") - self._consume_balanced_tokens(tok1, tok2) + while True: + tok1 = self._next_token_must_be("(") + tok2 = self._next_token_must_be("(") + self._consume_balanced_tokens(tok1, tok2) + + # Apparently you can have multiple attributes chained together? + tok = self.lex.token_if("__attribute__") + if tok is None: + break def _consume_declspec( self, tok: LexToken, doxygen: typing.Optional[str] = None @@ -2676,6 +2682,11 @@ def _parse_declarations( # if it returns True then it handled the end of the statement break + # Sometimes attributes come after a function + atok = self.lex.token_if("__attribute__") + if atok: + self._consume_gcc_attribute(atok) + # Unset the doxygen, location doxygen = None diff --git a/tests/test_attributes.py b/tests/test_attributes.py index 4f1da84..ae988b4 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -231,3 +231,34 @@ def test_declspec_template() -> None: ] ) ) + + +def test_multiple_attributes() -> None: + content = """ + extern const unsigned short int **__ctype_b_loc (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); + """ + data = parse_string(content, cleandoc=True) + + assert data == ParsedData( + namespace=NamespaceScope( + functions=[ + Function( + return_type=Pointer( + ptr_to=Pointer( + ptr_to=Type( + typename=PQName( + segments=[ + FundamentalSpecifier(name="unsigned short int") + ] + ), + const=True, + ) + ) + ), + name=PQName(segments=[NameSpecifier(name="__ctype_b_loc")]), + parameters=[], + extern=True, + ) + ] + ) + )