From 311aec6aa2fb8274ff4c1ad5e843b86028f2a264 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 10 Jan 2017 22:53:38 +0100 Subject: [PATCH 1/8] Use new syntax for super hash calls This fixes the following error with pypy 5.6.0 (2.7.12) File "../pygccxml/pygccxml/declarations/calldef.py", line 233, in __hash__ hash(self.return_type) ^ TypeError: unbound method __hash__() must be called with super instance as first argument (got free_function_t instance instead) The cpython implementation was OK with this, though the syntax is dubious. The new way of writing this is better as it clearly defines what is called in the class tree. Some of the calls may even be unnecessary, but I am leaving them as-is for the moment. Cherry-picked from the develop branch --- pygccxml/declarations/calldef.py | 4 ++-- pygccxml/declarations/calldef_members.py | 2 +- pygccxml/declarations/cpptypes.py | 2 +- pygccxml/declarations/enumeration.py | 2 +- pygccxml/declarations/scopedef.py | 2 +- pygccxml/declarations/typedef.py | 2 +- pygccxml/declarations/variable.py | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index 7174abc9..51683e5d 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -264,12 +264,12 @@ def __eq__(self, other): def __hash__(self): if "GCC" in utils.xml_generator: - return (super.__hash__(self) ^ + return (super(calldef_t, self).__hash__() ^ hash(self.return_type) ^ hash(self.demangled_name)) elif "CastXML" in utils.xml_generator: # No demangled name with castxml. Use the normal name. - return (super.__hash__(self) ^ + return (super(calldef_t, self).__hash__() ^ hash(self.return_type) ^ hash(self.name)) diff --git a/pygccxml/declarations/calldef_members.py b/pygccxml/declarations/calldef_members.py index 3c76e62b..fb37f69b 100644 --- a/pygccxml/declarations/calldef_members.py +++ b/pygccxml/declarations/calldef_members.py @@ -64,7 +64,7 @@ def __eq__(self, other): and self.has_const == other.has_const def __hash__(self): - return super.__hash__(self) + return super(member_calldef_t, self).__hash__() @property def virtuality(self): diff --git a/pygccxml/declarations/cpptypes.py b/pygccxml/declarations/cpptypes.py index cbb97268..55ba39e2 100644 --- a/pygccxml/declarations/cpptypes.py +++ b/pygccxml/declarations/cpptypes.py @@ -935,7 +935,7 @@ def __eq__(self, other): and self.has_mutable == other.has_mutable def __hash__(self): - return super.__hash__(self) + return super(type_qualifiers_t, self).__hash__() def __ne__(self, other): return not self.__eq__(other) diff --git a/pygccxml/declarations/enumeration.py b/pygccxml/declarations/enumeration.py index c841f180..3cf3a119 100644 --- a/pygccxml/declarations/enumeration.py +++ b/pygccxml/declarations/enumeration.py @@ -47,7 +47,7 @@ def __eq__(self, other): return self.values == other.values def __hash__(self): - return super.__hash__(self) + return super(enumeration_t, self).__hash__(self) def _get__cmp__items(self): """implementation details""" diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index 82217bb8..84c704ef 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -228,7 +228,7 @@ def __eq__(self, other): # return self_decls == other_decls def __hash__(self): - return super.__hash__(self) + return super(scopedef_t, self).__hash__() def _get_declarations_impl(self): raise NotImplementedError() diff --git a/pygccxml/declarations/typedef.py b/pygccxml/declarations/typedef.py index c0b1bc2c..5871a2bf 100644 --- a/pygccxml/declarations/typedef.py +++ b/pygccxml/declarations/typedef.py @@ -44,7 +44,7 @@ def __eq__(self, other): return self.decl_type == other.decl_type def __hash__(self): - return super.__hash__(self) + return super(typedef_t, self).__hash__(self) @property def type(self): diff --git a/pygccxml/declarations/variable.py b/pygccxml/declarations/variable.py index 334c8485..575c9e0c 100644 --- a/pygccxml/declarations/variable.py +++ b/pygccxml/declarations/variable.py @@ -61,7 +61,7 @@ def __eq__(self, other): and self.bits == other.bits def __hash__(self): - return super.__hash__(self) + return super(variable_t, self).__hash__() @property def type(self): From 53843a7a52572faf6512ef900a6edb28efa83a6f Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 17 Feb 2017 21:36:41 +0100 Subject: [PATCH 2/8] Remove unexpected arguments --- pygccxml/declarations/enumeration.py | 2 +- pygccxml/declarations/typedef.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pygccxml/declarations/enumeration.py b/pygccxml/declarations/enumeration.py index 3cf3a119..a6a3f397 100644 --- a/pygccxml/declarations/enumeration.py +++ b/pygccxml/declarations/enumeration.py @@ -47,7 +47,7 @@ def __eq__(self, other): return self.values == other.values def __hash__(self): - return super(enumeration_t, self).__hash__(self) + return super(enumeration_t, self).__hash__() def _get__cmp__items(self): """implementation details""" diff --git a/pygccxml/declarations/typedef.py b/pygccxml/declarations/typedef.py index 5871a2bf..acf193dd 100644 --- a/pygccxml/declarations/typedef.py +++ b/pygccxml/declarations/typedef.py @@ -44,7 +44,7 @@ def __eq__(self, other): return self.decl_type == other.decl_type def __hash__(self): - return super(typedef_t, self).__hash__(self) + return super(typedef_t, self).__hash__() @property def type(self): From 886e9a8eb8d23de323b6ed7be030fc69eaabb9a9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 17 Feb 2017 21:39:28 +0100 Subject: [PATCH 3/8] Document changes for v1.8.5 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc59c632..356e504e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Changes ======= +Version 1.8.5 +------------- + +1. Fix multiple calls to __hash__() (#70) + Version 1.8.4 ------------- From 91456e41de6b884496660c67b6128573648aadf3 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 17 Feb 2017 21:41:30 +0100 Subject: [PATCH 4/8] Bump version number to v1.8.5 --- pygccxml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/__init__.py b/pygccxml/__init__.py index a3ab22fc..c1b97c2c 100644 --- a/pygccxml/__init__.py +++ b/pygccxml/__init__.py @@ -40,4 +40,4 @@ # TODO: # 1. Add "explicit" property for constructors -__version__ = '1.8.4' +__version__ = '1.8.5' From e697d33c3310a2ccb7ff500a51a17ae49f45dae9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 18 Feb 2017 12:36:27 +0100 Subject: [PATCH 5/8] Cleanup static - extern type_qualifiers logic for CastXML CastXML is more robust than GCC-XML at defining static and extern qualifiers. Static and extern are now no more treated as equivalents in the type_qualifiers class. A bunch of tests have been added to test the new behaviour. The old behaviour is kept for GCC-XML (static == extern). --- pygccxml/declarations/cpptypes.py | 10 +-- pygccxml/parser/scanner.py | 11 +++- unittests/data/declarations_variables.hpp | 9 ++- unittests/declarations_tester.py | 75 +++++++++++++++++++---- 4 files changed, 87 insertions(+), 18 deletions(-) diff --git a/pygccxml/declarations/cpptypes.py b/pygccxml/declarations/cpptypes.py index 55ba39e2..9ac8490f 100644 --- a/pygccxml/declarations/cpptypes.py +++ b/pygccxml/declarations/cpptypes.py @@ -924,14 +924,16 @@ class type_qualifiers_t(object): """contains additional information about type: mutable, static, extern""" - def __init__(self, has_static=False, has_mutable=False): + def __init__(self, has_static=False, has_mutable=False, has_extern=False): self._has_static = has_static + self._has_extern = has_extern self._has_mutable = has_mutable def __eq__(self, other): if not isinstance(other, type_qualifiers_t): return False return self.has_static == other.has_static \ + and self.has_extern == other.has_extern \ and self.has_mutable == other.has_mutable def __hash__(self): @@ -944,6 +946,7 @@ def __lt__(self, other): if not isinstance(other, type_qualifiers_t): return object.__lt__(self, other) return self.has_static < other.has_static \ + and self.has_extern < other.has_extern \ and self.has_mutable < other.has_mutable @property @@ -956,12 +959,11 @@ def has_static(self, has_static): @property def has_extern(self): - """synonym to static""" - return self.has_static + return self._has_extern @has_extern.setter def has_extern(self, has_extern): - self.has_static = has_extern + self._has_extern = has_extern @property def has_mutable(self): diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 6f22c334..85f4e455 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -556,7 +556,16 @@ def __read_typedef(self, attrs): def __read_variable(self, attrs): type_qualifiers = declarations.type_qualifiers_t() type_qualifiers.has_mutable = attrs.get(XML_AN_MUTABLE, False) - type_qualifiers.has_static = attrs.get(XML_AN_EXTERN, False) + if "GCC-XML" in utils.xml_generator: + # Old behaviour with gccxml. Will be dropped when gccxml + # is removed. + type_qualifiers.has_static = attrs.get(XML_AN_EXTERN, False) + # With gccxml both were equivalent (at least this was the old + # behaviour in pygccxml) + type_qualifiers.has_extern = type_qualifiers.has_static + else: + type_qualifiers.has_static = attrs.get(XML_AN_STATIC, False) + type_qualifiers.has_extern = attrs.get(XML_AN_EXTERN, False) bits = attrs.get(XML_AN_BITS) if bits: bits = int(bits) diff --git a/unittests/data/declarations_variables.hpp b/unittests/data/declarations_variables.hpp index ec608f55..a9d5c0eb 100644 --- a/unittests/data/declarations_variables.hpp +++ b/unittests/data/declarations_variables.hpp @@ -11,8 +11,8 @@ namespace declarations{ namespace variables{ const long unsigned int initialized = 10122004; int array[255]; -//TODO: explain why such variables is not peeked -extern int static_var; +static int static_var; +extern int extern_var; struct struct_variables_t{ mutable int m_mutable; @@ -22,6 +22,11 @@ struct struct_variables_holder_t{ struct_variables_t m_struct_variables; }; +struct struct_static_variables_t{ + static const int ssv_static_var; + static const int ssv_static_var_value = 1; +}; + } } #endif//__declarations_variables_hpp__ diff --git a/unittests/declarations_tester.py b/unittests/declarations_tester.py index 5d523259..584a093d 100644 --- a/unittests/declarations_tester.py +++ b/unittests/declarations_tester.py @@ -56,25 +56,78 @@ def test_variables(self): declarations.const_t, declarations.long_unsigned_int_t) - static_var = initialized = self.global_ns.variable(name='static_var') + m_mutable = self.global_ns.variable(name="m_mutable") + self.assertFalse( + m_mutable.type_qualifiers.has_static, + "m_mutable must not have static type qualifier") + + if "GCC-XML" in utils.xml_generator: + # Old GCC-XML behaviour. Can be dropped once GCC-XML is removed. + static_var = self.global_ns.variable(name="extern_var") + self.assertTrue( + static_var.type_qualifiers.has_static, + "static_var must have static type qualifier") + self.assertFalse( + static_var.type_qualifiers.has_mutable, + "static_var must not have mutable type qualifier") + return + + # CastXML only tests -------------- + + self.assertTrue( + m_mutable.type_qualifiers.has_mutable, + "m_mutable must have mutable type qualifier") + + # External static variable + extern_var = self.global_ns.variable(name="extern_var") + self.assertTrue( + extern_var.type_qualifiers.has_extern, + "extern_var must have extern type qualifier") + self.assertFalse( + extern_var.type_qualifiers.has_static, + "extern_var must not have a static type qualifier") + self.assertFalse( + extern_var.type_qualifiers.has_mutable, + "static_var must not have mutable type qualifier") + + # Static variable + static_var = self.global_ns.variable(name="static_var") self.assertTrue( static_var.type_qualifiers.has_static, "static_var must have static type qualifier") - self.assertTrue( - not static_var.type_qualifiers.has_mutable, + self.assertFalse( + static_var.type_qualifiers.has_extern, + "static_var must not have an extern type qualifier") + self.assertFalse( + static_var.type_qualifiers.has_mutable, "static_var must not have mutable type qualifier") + ssv_static_var = self.global_ns.variable(name="ssv_static_var") + self.assertTrue( + ssv_static_var.type_qualifiers.has_static, + "ssv_static_var must have static type qualifier") + self.assertFalse( + ssv_static_var.type_qualifiers.has_extern, + "ssv_static_var must not have an extern type qualifier") + self.assertFalse( + ssv_static_var.type_qualifiers.has_mutable, + "ssv_static_var must not have mutable type qualifier") + + ssv_static_var_value = self.global_ns.variable( + name="ssv_static_var_value") + self.assertTrue( + ssv_static_var_value.type_qualifiers.has_static, + "ssv_static_var_value must have static type qualifier") + self.assertFalse( + ssv_static_var_value.type_qualifiers.has_extern, + "ssv_static_var_value must not have an extern type qualifier") + self.assertFalse( + ssv_static_var_value.type_qualifiers.has_mutable, + "ssv_static_var_value must not have mutable type qualifier") + if 'PDB' in utils.xml_generator: return # TODO find out work around - m_mutable = initialized = self.global_ns.variable(name='m_mutable') - self.assertTrue( - not m_mutable.type_qualifiers.has_static, - "m_mutable must not have static type qualifier") - # TODO: "There is bug in GCCXML: doesn't write mutable qualifier." - # self.assertTrue( m_mutable.type_qualifiers.has_mutable - # , "static_var must have mutable type qualifier" ) - def test_calldef_free_functions(self): ns = self.global_ns.namespace('calldef') From d3780a9f53e682e437cef82acc2b2d362c5dceb9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 19 Feb 2017 22:38:22 +0100 Subject: [PATCH 6/8] Add new test for is_noncopyable ... when used on classes having static const members. --- unittests/data/non_copyable_classes.hpp | 18 ++++++++++++++++++ unittests/non_copyable_classes_tester.py | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/unittests/data/non_copyable_classes.hpp b/unittests/data/non_copyable_classes.hpp index 1d3dafef..6e5b1aac 100644 --- a/unittests/data/non_copyable_classes.hpp +++ b/unittests/data/non_copyable_classes.hpp @@ -106,6 +106,24 @@ class MainFoo5 : Foo5 { char b; }; +// ----------------------------------------------- Member with static qualifiers + +// Foo6 is a base class (with a static const variable foo) +class Foo6 { + private: + Foo6(); + protected: + static const int foo1; +}; + +// Use the base class: this class is copyable, it has a public ctor, and +// the base class does not contain non-copyable members (because of the static +// qualifier) +class MainFoo6 : Foo6 { + public: + MainFoo6(); +}; + } #endif//__non_copyable_classes_hpp__ diff --git a/unittests/non_copyable_classes_tester.py b/unittests/non_copyable_classes_tester.py index 01fba939..ac68b353 100644 --- a/unittests/non_copyable_classes_tester.py +++ b/unittests/non_copyable_classes_tester.py @@ -7,6 +7,7 @@ from pygccxml import parser from pygccxml import declarations +from pygccxml import utils class Test(parser_test_case.parser_test_case_t): @@ -52,6 +53,12 @@ def test(self): main_foo_5 = self.global_ns.class_('MainFoo5') self.assertTrue(declarations.is_noncopyable(main_foo_5)) + if "CastXML" in utils.xml_generator: + # CastXML only test + # MainFoo6 is copyable + main_foo_6 = self.global_ns.class_('MainFoo6') + self.assertFalse(declarations.is_noncopyable(main_foo_6)) + def create_suite(): suite = unittest.TestSuite() From 8653705798bea652bd2f33fe4248468340c50165 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 20 Feb 2017 21:28:35 +0100 Subject: [PATCH 7/8] declaration_xxx_traits.get_declaration now removes pointer types This makes sure that when declarations.is_noncopyable is called on a pointer_t, the is_noncopyable does not fail and correctly extracts the class declaration using get_declaration. --- pygccxml/declarations/type_traits_classes.py | 1 + unittests/data/type_traits.hpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/pygccxml/declarations/type_traits_classes.py b/pygccxml/declarations/type_traits_classes.py index 3b672848..ab3f2d7b 100644 --- a/pygccxml/declarations/type_traits_classes.py +++ b/pygccxml/declarations/type_traits_classes.py @@ -56,6 +56,7 @@ class declaration_xxx_traits(object): - get reference to the declaration """ sequence = [ + type_traits.remove_pointer, type_traits.remove_alias, type_traits.remove_cv, type_traits.remove_declarated] diff --git a/unittests/data/type_traits.hpp b/unittests/data/type_traits.hpp index 8408bf31..4f3e9ed4 100644 --- a/unittests/data/type_traits.hpp +++ b/unittests/data/type_traits.hpp @@ -191,6 +191,7 @@ namespace yes{ typedef detail::g_t g_t; typedef detail::const_container const_container_t; typedef detail::const_item const_item_t; + typedef detail::const_item *const_item_t_ptr; } namespace no{ @@ -200,6 +201,7 @@ namespace no{ typedef std::set< std::string > string_set_type; typedef std::multimap< std::string, std::string > s2s_multimap_type; typedef detail::vertex vertex_type; + typedef detail::vertex *vertex_type_ptr; } } From 5b070652268b1dfe004074c74bf43e5360fc10e8 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 22 Feb 2017 22:02:44 +0100 Subject: [PATCH 8/8] Update changelog --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 356e504e..5bd91075 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,13 @@ Changes Version 1.8.5 ------------- -1. Fix multiple calls to __hash__() (#70) +1. Fix multiple calls to ``` __hash__()``` (#70) + +2. ```Static``` and ```extern``` qualifiers are now no more treated as equivalents + in the type_qualifiers class (for ```CastXML```). + The old behaviour is kept for ```GCC-XML``` (```static == extern```). + +3. Fix for ```declarations.is_noncopyable``` when used on a ```pointer_t```. Version 1.8.4 -------------