Skip to content

Commit becfa6a

Browse files
committed
Merge branch 'hotfix/v1.9.1'
2 parents c1b521e + daa290a commit becfa6a

8 files changed

+187
-29
lines changed

CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
Changes
22
=======
33

4+
Version 1.9.1
5+
-------------
6+
7+
1. Fix bug in the ```find_noncopyable_vars``` method which wrongly returned
8+
member variables of pointer type (#84)
9+
10+
2. Fix bug in the ```smart_pointer_traits.value_type``` and
11+
```auto_pointer_traits.value_type``` methods which didn't find the expected
12+
```value_type``` declaration (#85)
13+
14+
3. Fix bug in the ```smart_pointer_traits.is_smart_pointer``` and
15+
```auto_pointer_traits.is_smart_pointer``` methods which didn't properly
16+
work (#85)
17+
418
Version 1.9.0
519
-------------
620

pygccxml/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@
4141
# TODO:
4242
# 1. Add "explicit" property for constructors
4343

44-
__version__ = '1.9.0'
44+
__version__ = '1.9.1'

pygccxml/declarations/smart_pointer_traits.py

+27-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from . import class_declaration_traits
1010
from . import class_traits
1111
from . import traits_impl_details
12+
from . import runtime_errors
1213

1314

1415
class internal_type_traits(object):
@@ -17,8 +18,8 @@ class internal_type_traits(object):
1718
# TODO: add exists function
1819
@staticmethod
1920
def get_by_name(type_, name):
20-
if class_declaration_traits.is_my_case(type_):
21-
cls = class_traits.declaration_class(type_)
21+
if class_traits.is_my_case(type_):
22+
cls = class_traits.get_declaration(type_)
2223
return type_traits.remove_declarated(
2324
cls.typedef(name, recursive=False).decl_type)
2425
elif class_declaration_traits.is_my_case(type_):
@@ -72,7 +73,10 @@ def value_type(type_):
7273
'Type "%s" is not an instantiation of \
7374
boost::shared_ptr or std::shared_ptr' %
7475
type_.decl_string)
75-
return internal_type_traits.get_by_name(type_, "value_type")
76+
try:
77+
return internal_type_traits.get_by_name(type_, "element_type")
78+
except runtime_errors.declaration_not_found_t:
79+
return _search_in_bases(type_)
7680

7781

7882
class auto_ptr_traits(object):
@@ -103,4 +107,23 @@ def value_type(type_):
103107
raise TypeError(
104108
'Type "%s" is not instantiation of std::auto_ptr' %
105109
type_.decl_string)
106-
return internal_type_traits.get_by_name(type_, "element_type")
110+
try:
111+
return internal_type_traits.get_by_name(type_, "element_type")
112+
except runtime_errors.declaration_not_found_t:
113+
return _search_in_bases(type_)
114+
115+
116+
def _search_in_bases(type_):
117+
"""Implementation detail."""
118+
found = False
119+
for base_type in type_.declaration.bases:
120+
try:
121+
found = internal_type_traits.get_by_name(
122+
base_type.related_class, "element_type")
123+
except runtime_errors.declaration_not_found_t:
124+
pass
125+
if found:
126+
return found
127+
raise RuntimeError(
128+
("Unable to find 'element_type' declaration '%s'"
129+
"in type '%s'.") % type_.decl_string)

pygccxml/declarations/type_traits_classes.py

+18-14
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def find_copy_constructor(type_):
152152
return None
153153

154154

155-
def find_noncopyable_vars(type_, already_visited_cls_vars=None):
155+
def find_noncopyable_vars(class_type, already_visited_cls_vars=None):
156156
"""
157157
Returns list of all `noncopyable` variables.
158158
@@ -161,18 +161,19 @@ def find_noncopyable_vars(type_, already_visited_cls_vars=None):
161161
whatever variables pointing to classes have been found.
162162
163163
Args:
164-
type_ (declarations.class_t): the class to be searched.
164+
class_type (declarations.class_t): the class to be searched.
165165
already_visited_cls_vars (list): optional list of vars that should not
166166
be checked a second time, to prevent infinite recursions.
167167
168168
Returns:
169169
list: list of all `noncopyable` variables.
170170
171171
"""
172-
assert isinstance(type_, class_declaration.class_t)
172+
173+
assert isinstance(class_type, class_declaration.class_t)
173174

174175
logger = utils.loggers.cxx_parser
175-
mvars = type_.variables(
176+
mvars = class_type.variables(
176177
lambda v: not v.type_qualifiers.has_static,
177178
recursive=False,
178179
allow_empty=True)
@@ -187,25 +188,28 @@ def find_noncopyable_vars(type_, already_visited_cls_vars=None):
187188

188189
for mvar in mvars:
189190

190-
type_ = type_traits.remove_reference(mvar.decl_type)
191+
var_type = type_traits.remove_reference(mvar.decl_type)
191192

192-
if type_traits.is_const(type_):
193-
no_const = type_traits.remove_const(type_)
193+
if type_traits.is_const(var_type):
194+
no_const = type_traits.remove_const(var_type)
194195
if type_traits.is_fundamental(no_const) or is_enum(no_const):
195196
logger.debug(
196197
(message + "- fundamental or enum"),
197-
type_.decl_string)
198+
var_type.decl_string)
198199
noncopyable_vars.append(mvar)
199200
if is_class(no_const):
200-
logger.debug((message + " - class"), type_.decl_string)
201+
logger.debug((message + " - class"), var_type.decl_string)
201202
noncopyable_vars.append(mvar)
202203
if type_traits.is_array(no_const):
203-
logger.debug((message + " - array"), type_.decl_string)
204+
logger.debug((message + " - array"), var_type.decl_string)
204205
noncopyable_vars.append(mvar)
205206

206-
if class_traits.is_my_case(type_):
207+
if type_traits.is_pointer(var_type):
208+
continue
209+
210+
if class_traits.is_my_case(var_type):
207211

208-
cls = class_traits.get_declaration(type_)
212+
cls = class_traits.get_declaration(var_type)
209213

210214
# Exclude classes that have already been visited.
211215
if cls in already_visited_cls_vars:
@@ -215,12 +219,12 @@ def find_noncopyable_vars(type_, already_visited_cls_vars=None):
215219
if is_noncopyable(cls, already_visited_cls_vars):
216220
logger.debug(
217221
(message + " - class that is not copyable"),
218-
type_.decl_string)
222+
var_type.decl_string)
219223
noncopyable_vars.append(mvar)
220224

221225
logger.debug((
222226
"__contains_noncopyable_mem_var - %s - FALSE - doesn't " +
223-
"contain noncopyable members"), type_.decl_string)
227+
"contain noncopyable members"), class_type.decl_string)
224228

225229
return noncopyable_vars
226230

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2014-2017 Insight Software Consortium.
2+
// Copyright 2004-2009 Roman Yakovenko.
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// See http://www.boost.org/LICENSE_1_0.txt
5+
6+
struct abstract{
7+
virtual void do_smth() = 0;
8+
};
9+
10+
struct holder{
11+
abstract* ptr1;
12+
abstract* const ptr2;
13+
};

unittests/test_all.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
from . import test_castxml_wrong_epic
8383
from . import test_elaborated_types
8484
from . import test_order
85+
from . import test_find_noncopyable_vars
8586

8687
testers = [
8788
# , demangled_tester # failing right now
@@ -154,7 +155,8 @@
154155
test_non_copyable_recursive,
155156
test_castxml_wrong_epic,
156157
test_elaborated_types,
157-
test_order
158+
test_order,
159+
test_find_noncopyable_vars
158160
]
159161

160162
if platform.system() != 'Windows':
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright 2014-2017 Insight Software Consortium.
2+
# Copyright 2004-2009 Roman Yakovenko.
3+
# Distributed under the Boost Software License, Version 1.0.
4+
# See http://www.boost.org/LICENSE_1_0.txt
5+
6+
import unittest
7+
8+
from . import parser_test_case
9+
10+
from pygccxml import parser
11+
from pygccxml import declarations
12+
13+
14+
class Test(parser_test_case.parser_test_case_t):
15+
16+
def __init__(self, *args):
17+
parser_test_case.parser_test_case_t.__init__(self, *args)
18+
self.header = "find_noncopyable_vars.hpp"
19+
decls = parser.parse([self.header], self.config)
20+
self.global_ns = declarations.get_global_namespace(decls)
21+
22+
def test(self):
23+
"""
24+
Test the find_noncopyable_vars function
25+
26+
"""
27+
28+
# The ptr1 variable in the holder struct can be copied,
29+
# but not the ptr2 variable
30+
holder = self.global_ns.class_("holder")
31+
nc_vars = declarations.find_noncopyable_vars(holder)
32+
self.assertEqual(len(nc_vars), 1)
33+
self.assertEqual(nc_vars[0].name, "ptr2")
34+
self.assertTrue(declarations.is_pointer(nc_vars[0].decl_type))
35+
self.assertTrue(declarations.is_const(nc_vars[0].decl_type))
36+
37+
38+
def create_suite():
39+
suite = unittest.TestSuite()
40+
suite.addTest(unittest.makeSuite(Test))
41+
return suite
42+
43+
44+
def run_suite():
45+
unittest.TextTestRunner(verbosity=2).run(create_suite())
46+
47+
48+
if __name__ == "__main__":
49+
run_suite()

unittests/test_smart_pointer.py

+62-9
Original file line numberDiff line numberDiff line change
@@ -17,40 +17,93 @@ def __init__(self, *args):
1717
parser_test_case.parser_test_case_t.__init__(self, *args)
1818
self.header = "test_smart_pointer.hpp"
1919
self.config.cflags = "-std=c++11"
20+
self.global_ns = None
2021

21-
def test_smart_pointer(self):
22+
def setUp(self):
23+
if self.config.xml_generator == "gccxml":
24+
return
25+
decls = parser.parse([self.header], self.config)
26+
self.global_ns = declarations.get_global_namespace(decls)
27+
28+
def test_is_smart_pointer(self):
2229
"""
23-
Test code in the smart_pointer_traits module.
30+
Test smart_pointer_traits.is_smart_pointer method.
2431
2532
"""
2633

2734
if self.config.xml_generator == "gccxml":
2835
return
2936

30-
decls = parser.parse([self.header], self.config)
31-
global_ns = declarations.get_global_namespace(decls)
32-
3337
criteria = declarations.declaration_matcher(name="yes1")
34-
decls = declarations.matcher.find(criteria, global_ns)
38+
decls = declarations.matcher.find(criteria, self.global_ns)
3539
self.assertTrue(
3640
declarations.smart_pointer_traits.is_smart_pointer(
3741
decls[0].decl_type))
3842

43+
criteria = declarations.declaration_matcher(name="no1")
44+
decls = declarations.matcher.find(criteria, self.global_ns)
45+
self.assertFalse(
46+
declarations.smart_pointer_traits.is_smart_pointer(
47+
decls[0].decl_type))
48+
49+
criteria = declarations.declaration_matcher(name="no2")
50+
decls = declarations.matcher.find(criteria, self.global_ns)
51+
self.assertFalse(
52+
declarations.smart_pointer_traits.is_smart_pointer(
53+
decls[0].decl_type))
54+
55+
def test_is_auto_pointer(self):
56+
"""
57+
Test auto_ptr_traits.is_smart_pointer method.
58+
59+
"""
60+
61+
if self.config.xml_generator == "gccxml":
62+
return
63+
3964
criteria = declarations.declaration_matcher(name="yes2")
40-
decls = declarations.matcher.find(criteria, global_ns)
65+
decls = declarations.matcher.find(criteria, self.global_ns)
4166
self.assertTrue(
4267
declarations.auto_ptr_traits.is_smart_pointer(decls[0].decl_type))
4368

4469
criteria = declarations.declaration_matcher(name="no1")
45-
decls = declarations.matcher.find(criteria, global_ns)
70+
decls = declarations.matcher.find(criteria, self.global_ns)
4671
self.assertFalse(
4772
declarations.auto_ptr_traits.is_smart_pointer(decls[0].decl_type))
4873

4974
criteria = declarations.declaration_matcher(name="no2")
50-
decls = declarations.matcher.find(criteria, global_ns)
75+
decls = declarations.matcher.find(criteria, self.global_ns)
5176
self.assertFalse(
5277
declarations.auto_ptr_traits.is_smart_pointer(decls[0].decl_type))
5378

79+
def test_smart_pointer_value_type(self):
80+
"""
81+
Test smart_pointer_traits.value_type method.
82+
83+
"""
84+
85+
if self.config.xml_generator == "gccxml":
86+
return
87+
88+
criteria = declarations.declaration_matcher(name="yes1")
89+
decls = declarations.matcher.find(criteria, self.global_ns)
90+
vt = declarations.smart_pointer_traits.value_type(decls[0].decl_type)
91+
self.assertIsInstance(vt, declarations.int_t)
92+
93+
def test_auto_pointer_value_type(self):
94+
"""
95+
Test auto_pointer_traits.value_type method.
96+
97+
"""
98+
99+
if self.config.xml_generator == "gccxml":
100+
return
101+
102+
criteria = declarations.declaration_matcher(name="yes2")
103+
decls = declarations.matcher.find(criteria, self.global_ns)
104+
vt = declarations.auto_ptr_traits.value_type(decls[0].decl_type)
105+
self.assertIsInstance(vt, declarations.double_t)
106+
54107

55108
def create_suite():
56109
suite = unittest.TestSuite()

0 commit comments

Comments
 (0)