From dfa1093f255eee629d7f55ef1e4634445783178b Mon Sep 17 00:00:00 2001 From: Renaud Durlin Date: Sat, 11 Jul 2015 19:03:04 +0200 Subject: [PATCH] Improve parsing of friend declaration --- cpp/ast.py | 17 +++++++++++++---- cpp/find_warnings.py | 8 +++++--- test/typedef2.h | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 test/typedef2.h diff --git a/cpp/ast.py b/cpp/ast.py index 9dade56..32d959e 100644 --- a/cpp/ast.py +++ b/cpp/ast.py @@ -1390,10 +1390,19 @@ def handle_private(self): self.visibility = VISIBILITY_PRIVATE def handle_friend(self): - tokens = self._get_tokens_up_to(tokenize.SYNTAX, ';') - assert tokens - t0 = tokens[0] - return Friend(t0.start, t0.end, tokens, self.namespace_stack) + tokens, last = self._get_var_tokens_up_to(tokenize.SYNTAX, '(', ';') + if last.name == '(': + tokens.append(last) + self._add_back_tokens(tokens) + token = self._get_next_token() + result = self._generate_one(token) + else: + if tokens[0].name == 'class': + tokens = tokens[1:] + result = self.converter.to_type(tokens)[0] + + assert result + return Friend(result.start, result.end, result, self.namespace_stack) def handle_static_cast(self): pass diff --git a/cpp/find_warnings.py b/cpp/find_warnings.py index ec5e1e5..786be4e 100644 --- a/cpp/find_warnings.py +++ b/cpp/find_warnings.py @@ -375,9 +375,11 @@ def _add_template_use(name, types, namespace): _add_template_use('', alias.templated_types, node.namespace) elif isinstance(node, ast.Friend): - if node.expr and node.expr[0].name == 'class': - name = ''.join([n.name for n in node.expr[1:]]) - _add_reference(name, node.namespace) + expr = node.expr + if isinstance(expr, ast.Type): + _add_reference(expr.name, node.namespace) + elif isinstance(expr, ast.Function): + _process_function(expr) elif isinstance(node, ast.Class) and node.body is not None: if node.body: ast_seq.append(node.body) diff --git a/test/typedef2.h b/test/typedef2.h new file mode 100644 index 0000000..856a175 --- /dev/null +++ b/test/typedef2.h @@ -0,0 +1,16 @@ +class Bar; +class Barr; +class Baz; + +namespace A { + class B; + class C; +} + +class Foo { + friend class A::B; + friend A::C; + friend class Bar; + friend Barr; + friend void fn(Baz* baz); +};