diff --git a/docs/conf.py b/docs/conf.py index 871bff5f..b380fad2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -46,16 +46,16 @@ # General information about the project. project = u'pygccxml' -copyright = u'2014-2015, Insight Software Consortium' +copyright = u'2014-2016, Insight Software Consortium' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '1.7.5' +version = '1.7.6' # The full version, including alpha/beta/rc tags. -release = '1.7.5' +release = '1.7.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/history.rst b/docs/history.rst index db6e1313..adf8286f 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -11,6 +11,11 @@ to python 3 (keeping it compatible with python 2). In Mai 2014, Michka Popoff and the Insight Software Consortium revived pygccxml by setting up a git repositery on github, hosted along with gccxml. +Version 1.7.6 +------------- + +1. Fix problem with argument without names when building declaration string (#55) + Version 1.7.5 ------------- diff --git a/pygccxml/__init__.py b/pygccxml/__init__.py index a0979c4f..0ff2061b 100644 --- a/pygccxml/__init__.py +++ b/pygccxml/__init__.py @@ -40,4 +40,4 @@ # TODO: # 1. Add "explicit" property for constructors -__version__ = '1.7.5' +__version__ = '1.7.6' diff --git a/pygccxml/declarations/algorithm.py b/pygccxml/declarations/algorithm.py index a42d7ce5..d37cfedb 100644 --- a/pygccxml/declarations/algorithm.py +++ b/pygccxml/declarations/algorithm.py @@ -124,13 +124,24 @@ def full_name(decl, with_defaults=True): raise RuntimeError("Unable to generate full name for None object!") if with_defaults: if not decl.cache.full_name: - decl.cache.full_name = full_name_from_declaration_path( - declaration_path(decl)) + path = declaration_path(decl) + if path == [""]: + # Declarations without names are allowed (for examples class + # or struct instances). In this case set an empty name.. + decl.cache.full_name = "" + else: + decl.cache.full_name = full_name_from_declaration_path(path) return decl.cache.full_name else: if not decl.cache.full_partial_name: - decl.cache.full_partial_name = full_name_from_declaration_path( - partial_declaration_path(decl)) + path = partial_declaration_path(decl) + if path == [""]: + # Declarations without names are allowed (for examples class + # or struct instances). In this case set an empty name. + decl.cache.full_partial_name = "" + else: + decl.cache.full_partial_name = \ + full_name_from_declaration_path(path) return decl.cache.full_partial_name diff --git a/setup.py b/setup.py index d8927cdf..0a95582e 100644 --- a/setup.py +++ b/setup.py @@ -7,14 +7,14 @@ from setuptools import setup setup(name="pygccxml", - version="1.7.5", + version="1.7.6", author="Roman Yakovenko", author_email="roman yakovenko at gmail com", maintainer="Michka Popoff and the Insight Software Consortium", maintainer_email="castxml@public.kitware.com", description="Python package for easy C++ declarations navigation.", url="https://github.com/gccxml/pygccxml", - download_url="https://github.com/gccxml/pygccxml/archive/v1.7.5.tar.gz", + download_url="https://github.com/gccxml/pygccxml/archive/v1.7.6.tar.gz", license="Boost", keywords="C++, declaration parser, CastXML, gccxml", packages=["pygccxml", diff --git a/unittests/data/test_argument_without_name.hpp b/unittests/data/test_argument_without_name.hpp new file mode 100644 index 00000000..ff993b3f --- /dev/null +++ b/unittests/data/test_argument_without_name.hpp @@ -0,0 +1,18 @@ +// Copyright 2014-2016 Insight Software Consortium. +// Copyright 2004-2009 Roman Yakovenko. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Demonstrate some code where a struct without name is passed to a +// templated function. See bug #55 + +template +void +function(type &var) {}; + +int main() +{ + // Create foo, a struct with no name + struct { } foo; + function(foo); +} diff --git a/unittests/test_all.py b/unittests/test_all.py index f5472692..1e739811 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -71,6 +71,7 @@ import test_cpp_standards import unnamed_classes_tester import test_map_gcc5 +import test_argument_without_name testers = [ # , demangled_tester # failing right now @@ -134,7 +135,8 @@ test_copy_constructor, test_cpp_standards, unnamed_classes_tester, - test_map_gcc5 + test_map_gcc5, + test_argument_without_name ] if 'posix' in os.name: diff --git a/unittests/test_argument_without_name.py b/unittests/test_argument_without_name.py new file mode 100644 index 00000000..d288a47c --- /dev/null +++ b/unittests/test_argument_without_name.py @@ -0,0 +1,56 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2009 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import unittest +import parser_test_case + +from pygccxml import parser +from pygccxml import declarations + + +class tester_t(parser_test_case.parser_test_case_t): + + def __init__(self, *args): + parser_test_case.parser_test_case_t.__init__(self, *args) + self.header = "test_argument_without_name.hpp" + self.config.cflags = "-std=c++11" + + def test_argument_without_name(self): + + """ + Test passing an object without name to a templated function. + + The test was failing when building the declaration string. + The declaration string will be 'void (*)( & )'. If the passed + object had a name the result would then be 'void (*)(Name & )'. + + See bug #55 + + """ + + if self.config.xml_generator == "gccxml": + return + + decls = parser.parse([self.header], self.config) + global_ns = declarations.get_global_namespace(decls) + + criteria = declarations.calldef_matcher(name="function") + free_funcs = declarations.matcher.find(criteria, global_ns) + for free_func in free_funcs: + decl_string = free_func.create_decl_string(with_defaults=False) + self.assertEqual(decl_string, "void (*)( & )") + + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(tester_t)) + return suite + + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run(create_suite()) + +if __name__ == "__main__": + run_suite() diff --git a/unittests/test_map_gcc5.py b/unittests/test_map_gcc5.py index 35dfe44d..ba91cf13 100644 --- a/unittests/test_map_gcc5.py +++ b/unittests/test_map_gcc5.py @@ -1,4 +1,5 @@ # Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2009 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt @@ -21,7 +22,9 @@ def test_map_gcc5(self): """ The code in test_map_gcc5.hpp was breaking pygccxml. - Test that case (gcc5 + castxml + c++11). See issue #45 + Test that case (gcc5 + castxml + c++11). + + See issue #45 and #55 """ @@ -29,7 +32,19 @@ def test_map_gcc5(self): return decls = parser.parse([self.header], self.config) - self.global_ns = declarations.get_global_namespace(decls) + global_ns = declarations.get_global_namespace(decls) + + # This calldef is defined with gcc > 4.9 (maybe earlier, not tested) + # and -std=c++11. Calling create_decl_string is failing with gcc. + # With clang the calldef does not exist so the matcher + # will just return an empty list, letting the test pass. + # See the test_argument_without_name.py for an equivalent test, + # which is not depending on the presence of the _M_clone_node + # method in the stl_tree.h file. + criteria = declarations.calldef_matcher(name="_M_clone_node") + free_funcs = declarations.matcher.find(criteria, global_ns) + for free_funcs in free_funcs: + free_funcs.create_decl_string(with_defaults=False) def create_suite():