diff --git a/Modules/ThirdParty/pygccxml/src/UpdatepygccxmlFromUpstream.sh b/Modules/ThirdParty/pygccxml/src/UpdatepygccxmlFromUpstream.sh index 7a60fa4c82f..0149893bbd3 100755 --- a/Modules/ThirdParty/pygccxml/src/UpdatepygccxmlFromUpstream.sh +++ b/Modules/ThirdParty/pygccxml/src/UpdatepygccxmlFromUpstream.sh @@ -20,16 +20,16 @@ fi # Update the git tag for the version you are merging git_url="https://github.com/CastXML/pygccxml" -git_tag="v2.4.0" -upstream_sha="ce011e1bc57248d205cfda60dd51b3182acbe106" +git_tag="v3.0.2" +upstream_sha="62f600c98ec6a25fd3d264774c6fc811ec3c46e4" # # Once the merge has been done # EDIT THIS SCRIPT to change the hash tag at which to begin the # next update... # -# This merge was done on: April 9th, 2024 -git branch pygccxml-upstream b39a0bbb81bf02fc6541131b331f36254b3971d4 +# This merge was done with respect to pygccxml v3.0.2 as of : March 16th, 2025 +git branch pygccxml-upstream de4804643f66c89d38725a3ae1742071cd354efc # # Make a temp directory to handle the import of the upstream source @@ -81,8 +81,8 @@ cd .. rm -fr pygccxml-Tmp # -# checkout a new update branch off master -git checkout -b pygccxml-update master +# checkout a new update branch off main +git checkout -b pygccxml-update main # # use subtree merge to bring in upstream changes git merge -s recursive -X subtree=Modules/ThirdParty/pygccxml/src/pygccxml pygccxml-upstream diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/__init__.py b/Modules/ThirdParty/pygccxml/src/pygccxml/__init__.py index ad1e989183d..9b183bb2630 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/__init__.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/__init__.py @@ -52,5 +52,5 @@ from importlib import metadata # Begin ITK edit -__version__ = "2.4.0" +__version__ = "3.0.2" # __version__ = metadata.version("pygccxml") diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/calldef.py b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/calldef.py index d1a0cd2808b..cbfd28d23e7 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/calldef.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/calldef.py @@ -266,12 +266,24 @@ def does_throw(self, does_throw): @property def exceptions(self): - """The list of exceptions. - @type: list of :class:`declaration_t`""" + """ + The list of exceptions. + + Useless with c++17 and above as dynamich exceptions + are not allowed anymore: + https://developers.redhat.com/articles/2021/08/06/porting-your-code-c17-gcc-11#exception_specification_changes # noqa + + @type: list of :class:`declaration_t` + """ return self._exceptions @exceptions.setter def exceptions(self, exceptions): + """ + Useless with c++17 and above as dynamich exceptions + are not allowed anymore: + https://developers.redhat.com/articles/2021/08/06/porting-your-code-c17-gcc-11#exception_specification_changes # noqa + """ self._exceptions = exceptions @property diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/container_traits.py b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/container_traits.py index d4f6658edda..8778d68f302 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/container_traits.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/container_traits.py @@ -19,6 +19,16 @@ std_namespaces = ('std', 'stdext', '__gnu_cxx') +# Take into account different equivalences (with or without spaces) +string_equivalences = type_traits.string_equivalences + \ + type_traits.normalized_string_equivalences +string_equivalences = [ + v for v in string_equivalences if not v == "std::string"] +wstring_equivalences = type_traits.wstring_equivalences + \ + type_traits.normalized_wstring_equivalences +wstring_equivalences = [ + v for v in wstring_equivalences if not v == "std::wstring"] + class defaults_eraser(object): @@ -28,27 +38,17 @@ def __init__(self, unordered_maps_and_sets): def normalize(self, type_str): return type_str.replace(' ', '') - def replace_basic_string(self, cls_name): - - # Take the lists of all possible string variations - # and clean them up by replacing ::std by std. - str_eq = [ - v.replace("::std", "std") for v in - type_traits.string_equivalences] - wstr_eq = [ - v.replace("::std", "std") for v in - type_traits.wstring_equivalences] - - # Replace all the variations of strings by the smallest one. + @staticmethod + def replace_basic_string(cls_name): strings = { - "std::string": [v for v in str_eq if not v == "std::string"], - "std::wstring": [v for v in wstr_eq if not v == "std::wstring"]} + "std::string": string_equivalences, + "std::wstring": wstring_equivalences + } new_name = cls_name for short_name, long_names in strings.items(): for lname in long_names: new_name = new_name.replace(lname, short_name) - return new_name def decorated_call_prefix(self, cls_name, text, doit): @@ -99,13 +99,12 @@ def erase_recursive(self, cls_name): return self.no_end_const(cls_name) def erase_allocator(self, cls_name, default_allocator='std::allocator'): - cls_name = self.replace_basic_string(cls_name) c_name, c_args = templates.split(cls_name) if len(c_args) != 2: return value_type = c_args[0] tmpl = string.Template( - "$container< $value_type, $allocator<$value_type> >") + "$container<$value_type, $allocator<$value_type>>") tmpl = tmpl.substitute( container=c_name, value_type=value_type, @@ -116,24 +115,21 @@ def erase_allocator(self, cls_name, default_allocator='std::allocator'): c_name, [self.erase_recursive(value_type)]) def erase_container(self, cls_name, default_container_name='std::deque'): - cls_name = self.replace_basic_string(cls_name) c_name, c_args = templates.split(cls_name) if len(c_args) != 2: return value_type = c_args[0] dc_no_defaults = self.erase_recursive(c_args[1]) - if self.normalize(dc_no_defaults) != self.normalize( + if self.normalize(dc_no_defaults) == self.normalize( templates.join(default_container_name, [value_type])): - return - return templates.join( - c_name, [self.erase_recursive(value_type)]) + return templates.join( + c_name, [self.erase_recursive(value_type)]) def erase_container_compare( self, cls_name, default_container_name='std::vector', default_compare='std::less'): - cls_name = self.replace_basic_string(cls_name) c_name, c_args = templates.split(cls_name) if len(c_args) != 3: return @@ -153,14 +149,13 @@ def erase_compare_allocator( cls_name, default_compare='std::less', default_allocator='std::allocator'): - cls_name = self.replace_basic_string(cls_name) c_name, c_args = templates.split(cls_name) if len(c_args) != 3: return value_type = c_args[0] tmpl = string.Template( - "$container< $value_type, $compare<$value_type>, " + - "$allocator<$value_type> >") + "$container<$value_type, $compare<$value_type>, " + + "$allocator<$value_type>>") tmpl = tmpl.substitute( container=c_name, value_type=value_type, @@ -176,7 +171,6 @@ def erase_map_compare_allocator( cls_name, default_compare='std::less', default_allocator='std::allocator'): - cls_name = self.replace_basic_string(cls_name) c_name, c_args = templates.split(cls_name) if len(c_args) != 4: return @@ -184,14 +178,14 @@ def erase_map_compare_allocator( mapped_type = c_args[1] tmpls = [ string.Template( - "$container< $key_type, $mapped_type, $compare<$key_type>, " + - "$allocator< std::pair< const $key_type, $mapped_type> > >"), + "$container<$key_type, $mapped_type, $compare<$key_type>, " + + "$allocator>>"), string.Template( - "$container< $key_type, $mapped_type, $compare<$key_type>, " + - "$allocator< std::pair< $key_type const, $mapped_type> > >"), + "$container<$key_type, $mapped_type, $compare<$key_type>, " + + "$allocator>>"), string.Template( - "$container< $key_type, $mapped_type, $compare<$key_type>, " + - "$allocator< std::pair< $key_type, $mapped_type> > >")] + "$container<$key_type, $mapped_type, $compare<$key_type>, " + + "$allocator>>")] for tmpl in tmpls: tmpl = tmpl.substitute( container=c_name, @@ -206,7 +200,6 @@ def erase_map_compare_allocator( self.erase_recursive(mapped_type)]) def erase_hash_allocator(self, cls_name): - cls_name = self.replace_basic_string(cls_name) c_name, c_args = templates.split(cls_name) if len(c_args) < 3: return @@ -218,13 +211,13 @@ def erase_hash_allocator(self, cls_name): if len(c_args) == 3: default_hash = 'hash_compare' tmpl = ( - "$container< $value_type, $hash<$value_type, " + - "$less<$value_type> >, $allocator<$value_type> >") + "$container<$value_type, $hash<$value_type, " + + "$less<$value_type>>, $allocator<$value_type>>") elif len(c_args) == 4: default_hash = 'hash' tmpl = ( - "$container< $value_type, $hash<$value_type >, " + - "$equal_to<$value_type >, $allocator<$value_type> >") + "$container<$value_type, $hash<$value_type>, " + + "$equal_to<$value_type>, $allocator<$value_type>>") else: return @@ -244,7 +237,6 @@ def erase_hash_allocator(self, cls_name): c_name, [self.erase_recursive(value_type)]) def erase_hashmap_compare_allocator(self, cls_name): - cls_name = self.replace_basic_string(cls_name) c_name, c_args = templates.split(cls_name) if self.unordered_maps_and_sets: @@ -263,14 +255,14 @@ def erase_hashmap_compare_allocator(self, cls_name): if len(c_args) == 4: default_hash = 'hash_compare' tmpl = string.Template( - "$container< $key_type, $mapped_type, " + - "$hash<$key_type, $less<$key_type> >, " + - "$allocator< std::pair< const $key_type, $mapped_type> > >") + "$container<$key_type, $mapped_type, " + + "$hash<$key_type, $less<$key_type>>, " + + "$allocator>>") if key_type.startswith('const ') or key_type.endswith(' const'): tmpl = string.Template( - "$container< $key_type, $mapped_type, $hash<$key_type, " + - "$less<$key_type> >, $allocator< std::pair< $key_type, " + - "$mapped_type> > >") + "$container<$key_type, $mapped_type, $hash<$key_type, " + + "$less<$key_type>>, $allocator>>") elif len(c_args) == 5: default_hash = 'hash' if self.unordered_maps_and_sets: @@ -279,31 +271,31 @@ def erase_hashmap_compare_allocator(self, cls_name): "$hash<$key_type>, " + "$equal_to<$key_type>, " + "$allocator > >") + "$mapped_type>>>") if key_type.startswith('const ') or \ key_type.endswith(' const'): tmpl = string.Template( "$container<$key_type, $mapped_type, " + - "$hash<$key_type >, " + - "$equal_to<$key_type >, " + + "$hash<$key_type>, " + + "$equal_to<$key_type>, " + "$allocator > >") + "$mapped_type>>>") else: tmpl = string.Template( - "$container< $key_type, $mapped_type, " + "$container<$key_type, $mapped_type, " "$hash<$key_type >, " + "$equal_to<$key_type>, " - "$allocator< $mapped_type> >") + "$allocator<$mapped_type>>") if key_type.startswith('const ') or \ key_type.endswith(' const'): # TODO: this template is the same than above. # Make sure why this was needed and if this is # tested. There may be a const missing somewhere. tmpl = string.Template( - "$container< $key_type, $mapped_type, " + - "$hash<$key_type >, " + + "$container<$key_type, $mapped_type, " + + "$hash<$key_type>, " + "$equal_to<$key_type>, " + - "$allocator< $mapped_type > >") + "$allocator<$mapped_type>>") else: return @@ -524,6 +516,7 @@ def remove_defaults(self, type_or_string): name = type_or_string if not isinstance(type_or_string, str): name = self.class_declaration(type_or_string).name + name = defaults_eraser.replace_basic_string(name) if not self.remove_defaults_impl: return name no_defaults = self.remove_defaults_impl(name) @@ -647,14 +640,14 @@ def remove_defaults(self, type_or_string): unordered_set_traits = container_traits_impl_t( 'unordered_set', - 1, + 0, 'value_type', 'erase_hash_allocator', unordered_maps_and_sets=True) unordered_multiset_traits = container_traits_impl_t( 'unordered_multiset', - 1, + 0, 'value_type', 'erase_hash_allocator', unordered_maps_and_sets=True) diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/cpptypes.py b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/cpptypes.py index b8b1769a4fe..b2ab2e1ee6b 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/cpptypes.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/cpptypes.py @@ -9,6 +9,7 @@ from . import algorithms_cache from . import byte_info +from . import elaborated_info class type_t(byte_info.byte_info): @@ -593,10 +594,10 @@ def __init__(self, base): compound_t.__init__(self, base) def build_decl_string(self, with_defaults=True): - if hasattr(self.base.declaration, "elaborated_type_specifier"): + prefix = "" + if isinstance(self.base, type(declarated_t)) and \ + isinstance(self.base.declaration, type(elaborated_info)): prefix = self.base.declaration.elaborated_type_specifier + " " - else: - prefix = "" return prefix + self.base.build_decl_string(with_defaults) def _clone_impl(self): diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/pattern_parser.py b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/pattern_parser.py index 093e692b26f..da2479d9fcf 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/pattern_parser.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/pattern_parser.py @@ -192,11 +192,11 @@ def join(self, name, args, arg_separator=None): args = [_f for _f in args if _f] if not args: - args_str = ' ' + args_str = '' elif len(args) == 1: - args_str = ' ' + args[0] + ' ' + args_str = args[0] else: - args_str = ' ' + arg_separator.join(args) + ' ' + args_str = arg_separator.join(args) return ''.join([name, self.__begin, args_str, self.__end]) diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/traits_impl_details.py b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/traits_impl_details.py index b9fce5945b1..3d452fc8349 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/traits_impl_details.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/traits_impl_details.py @@ -50,39 +50,40 @@ def find_value_type(global_ns, value_type_str): name=value_type_str, function=lambda decl: not isinstance(decl, calldef.calldef_t), allow_empty=True) - if not found: - no_global_ns_value_type_str = value_type_str[2:] - if no_global_ns_value_type_str in cpptypes.FUNDAMENTAL_TYPES: - return cpptypes.FUNDAMENTAL_TYPES[no_global_ns_value_type_str] - elif type_traits.is_std_string(value_type_str): - string_ = global_ns.typedef('::std::string') - return type_traits.remove_declarated(string_) - elif type_traits.is_std_wstring(value_type_str): - string_ = global_ns.typedef('::std::wstring') - return type_traits.remove_declarated(string_) + + if len(found) == 1: + return found[0] + + no_global_ns_value_type_str = value_type_str[2:] + if no_global_ns_value_type_str in cpptypes.FUNDAMENTAL_TYPES: + return cpptypes.FUNDAMENTAL_TYPES[no_global_ns_value_type_str] + elif type_traits.is_std_string(value_type_str): + string_ = global_ns.typedef('::std::string') + return type_traits.remove_declarated(string_) + elif type_traits.is_std_wstring(value_type_str): + string_ = global_ns.typedef('::std::wstring') + return type_traits.remove_declarated(string_) + else: + value_type_str = no_global_ns_value_type_str + has_const = value_type_str.startswith('const ') + if has_const: + value_type_str = value_type_str[len('const '):] + has_pointer = value_type_str.endswith('*') + if has_pointer: + value_type_str = value_type_str[:-1] + found = None + if has_const or has_pointer: + found = impl_details.find_value_type( + global_ns, + value_type_str) + if not found: + return None else: - value_type_str = no_global_ns_value_type_str - has_const = value_type_str.startswith('const ') + if isinstance(found, class_declaration.class_types): + return cpptypes.declarated_t(found) if has_const: - value_type_str = value_type_str[len('const '):] - has_pointer = value_type_str.endswith('*') + return cpptypes.const_t(found) if has_pointer: - value_type_str = value_type_str[:-1] - found = None - if has_const or has_pointer: - found = impl_details.find_value_type( - global_ns, - value_type_str) - if not found: - return None - else: - if isinstance(found, class_declaration.class_types): - return cpptypes.declarated_t(found) - if has_const: - return cpptypes.const_t(found) - if has_pointer: - return cpptypes.pointer_t(found) - if len(found) == 1: - return found[0] + return cpptypes.pointer_t(found) return None diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/type_traits.py b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/type_traits.py index bc9be8dea0d..ba1292593ac 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/type_traits.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/declarations/type_traits.py @@ -480,25 +480,57 @@ def is_fundamental(type_): (cpptypes.volatile_t, cpptypes.const_t)) +def _normalize(string): + return string.replace(' ', '').replace("::std", "std") + + +def _normalize_equivalences(equivalences): + return [_normalize(eq) for eq in equivalences] + + string_equivalences = [ ( - '::std::basic_string,' - 'std::allocator>'), - '::std::basic_string', '::std::string'] + 'std::basic_string, ' + 'std::allocator>' + ), + 'std::basic_string', + 'std::string' + ] wstring_equivalences = [ ( - '::std::basic_string,' + - 'std::allocator>'), - '::std::basic_string', '::std::wstring'] + 'std::basic_string, ' + 'std::allocator>' + ), + 'std::basic_string', + 'std::wstring' + ] ostream_equivalences = [ - '::std::basic_ostream>', - '::std::basic_ostream', '::std::ostream'] + 'std::basic_ostream>', + 'std::basic_ostream', + 'std::ostream' + ] wostream_equivalences = [ - '::std::basic_ostream>', - '::std::basic_ostream', '::std::wostream'] + 'std::basic_ostream>', + 'std::basic_ostream', + 'std::wostream' + ] + + +normalized_string_equivalences = _normalize_equivalences( + string_equivalences + ) +normalized_wstring_equivalences = _normalize_equivalences( + wstring_equivalences + ) +normalized_ostream_equivalences = _normalize_equivalences( + ostream_equivalences + ) +normalized_wostream_equivalences = _normalize_equivalences( + wostream_equivalences + ) def is_std_string(type_): @@ -508,12 +540,12 @@ def is_std_string(type_): """ if isinstance(type_, str): - return type_ in string_equivalences + return _normalize(type_) in normalized_string_equivalences type_ = remove_alias(type_) type_ = remove_reference(type_) type_ = remove_cv(type_) - return type_.decl_string.replace(' ', '') in string_equivalences + return _normalize(type_.decl_string) in normalized_string_equivalences def is_std_wstring(type_): @@ -523,12 +555,12 @@ def is_std_wstring(type_): """ if isinstance(type_, str): - return type_ in wstring_equivalences + return _normalize(type_) in normalized_wstring_equivalences type_ = remove_alias(type_) type_ = remove_reference(type_) type_ = remove_cv(type_) - return type_.decl_string.replace(' ', '') in wstring_equivalences + return _normalize(type_.decl_string) in normalized_wstring_equivalences def is_std_ostream(type_): @@ -538,12 +570,12 @@ def is_std_ostream(type_): """ if isinstance(type_, str): - return type_ in ostream_equivalences + return _normalize(type_) in normalized_ostream_equivalences type_ = remove_alias(type_) type_ = remove_reference(type_) type_ = remove_cv(type_) - return type_.decl_string.replace(' ', '') in ostream_equivalences + return _normalize(type_.decl_string) in normalized_ostream_equivalences def is_std_wostream(type_): @@ -553,9 +585,9 @@ def is_std_wostream(type_): """ if isinstance(type_, str): - return type_ in wostream_equivalences + return _normalize(type_) in normalized_wostream_equivalences type_ = remove_alias(type_) type_ = remove_reference(type_) type_ = remove_cv(type_) - return type_.decl_string.replace(' ', '') in wostream_equivalences + return _normalize(type_.decl_string) in normalized_wostream_equivalences diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/parser/config.py b/Modules/ThirdParty/pygccxml/src/pygccxml/parser/config.py index e2db56d84d9..e1a1cfc6b62 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/parser/config.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/parser/config.py @@ -11,6 +11,7 @@ import os import copy import platform +import shutil import subprocess import warnings # In py3, ConfigParser was renamed to the more-standard configparser. @@ -129,16 +130,12 @@ def compiler(self, compiler): @property def xml_generator(self): - """get xml_generator (gccxml or castxml)""" + """get xml_generator""" return self.__xml_generator @xml_generator.setter def xml_generator(self, xml_generator): - """set xml_generator (gccxml or castxml)""" - if "real" in xml_generator: - # Support for gccxml.real from newer gccxml package - # Can be removed once gccxml support is dropped. - xml_generator = "gccxml" + """set xml_generator""" self.__xml_generator = xml_generator @property @@ -241,9 +238,8 @@ def raise_on_wrong_settings(self): self.__ensure_dir_exists(self.working_directory, 'working directory') for idir in self.include_paths: self.__ensure_dir_exists(idir, 'include directory') - if self.__xml_generator not in ["castxml", "gccxml"]: - msg = ('xml_generator("%s") should either be ' + - '"castxml" or "gccxml".') % self.xml_generator + if self.__xml_generator != "castxml": + msg = f"xml_generator ({self.xml_generator}) can only be 'castxml'" raise RuntimeError(msg) @@ -378,7 +374,7 @@ def load_xml_generator_configuration(configuration, **defaults): An example configuration file skeleton can be found `here `_. + tests/xml_generator.cfg>`_. """ parser = configuration @@ -456,35 +452,20 @@ def create_compiler_path(xml_generator, compiler_path): if xml_generator == 'castxml' and compiler_path is None: if platform.system() == 'Windows': # Look for msvc - compiler_path = __get_first_compiler_in_path('where', 'cl') + compiler_path = shutil.which('cl') # No msvc found; look for mingw - if compiler_path == '': - compiler_path = __get_first_compiler_in_path('where', 'mingw') + if compiler_path is None: + compiler_path = shutil.which('mingw') else: # OS X or Linux # Look for clang first, then gcc - compiler_path = __get_first_compiler_in_path('which', 'clang++') + compiler_path = shutil.which('clang++') # No clang found; use gcc - if compiler_path == '': - compiler_path = __get_first_compiler_in_path('which', 'c++') - - if compiler_path == "": - compiler_path = None + if compiler_path is None: + compiler_path = shutil.which('c++') return compiler_path -def __get_first_compiler_in_path(command, compiler_name): - p = subprocess.Popen( - [command, compiler_name], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - path = p.stdout.read().decode("utf-8").rstrip().split("\r\n")[0].rstrip() - p.wait() - p.stdout.close() - p.stderr.close() - return path - - if __name__ == '__main__': print(load_xml_generator_configuration('xml_generator.cfg').__dict__) diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/parser/project_reader.py b/Modules/ThirdParty/pygccxml/src/pygccxml/parser/project_reader.py index d7bf7c994f2..a4eaace1778 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/parser/project_reader.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/parser/project_reader.py @@ -353,7 +353,12 @@ def __parse_all_at_once(self, files): header_content.append( '#include "%s" %s' % (header, os.linesep)) - return self.read_string(''.join(header_content)) + declarations = self.read_string(''.join(header_content)) + declarations = self._join_top_namespaces(declarations, []) + for ns in declarations: + if isinstance(ns, pygccxml.declarations.namespace_t): + declarations_joiner.join_declarations(ns) + return declarations def read_string(self, content): """Parse a string containing C/C++ source code. @@ -420,15 +425,24 @@ def read_xml(self, file_configuration): def _join_top_namespaces(main_ns_list, other_ns_list): answer = main_ns_list[:] for other_ns in other_ns_list: - main_ns = pygccxml.declarations.find_declaration( + same_name_namespaces = pygccxml.declarations.find_all_declarations( answer, decl_type=pygccxml.declarations.namespace_t, - name=other_ns._name, - recursive=False) - if main_ns: - main_ns.take_parenting(other_ns) - else: + name=other_ns.name, + parent=None, # top-level only + recursive=False + ) + if len(same_name_namespaces) == 0: answer.append(other_ns) + elif len(same_name_namespaces) == 1: + same_name_namespaces[0].take_parenting(other_ns) + else: + primary_ns = same_name_namespaces[0] + for extra_ns in same_name_namespaces[1:]: + primary_ns.take_parenting(extra_ns) + answer.remove(extra_ns) + # then unify the new other_ns + primary_ns.take_parenting(other_ns) return answer @staticmethod @@ -548,11 +562,13 @@ def _relink_declarated_types(self, leaved_classes, declarated_types): if name == "rebind, void *> >": continue + if name == "type": + continue msg = [] msg.append( "Unable to find out actual class definition: '%s'." % - decl_wrapper_type.declaration._name) + name) msg.append(( "Class definition has been changed from one " + "compilation to an other.")) diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/parser/scanner.py b/Modules/ThirdParty/pygccxml/src/pygccxml/parser/scanner.py index 63f9cbd729f..538adbd60eb 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/parser/scanner.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/parser/scanner.py @@ -56,6 +56,7 @@ XML_AN_STATIC = "static" XML_AN_THROW = "throw" XML_AN_TYPE = "type" +XML_AN_ORIGINAL_TYPE = "original_type" XML_AN_VIRTUAL = "virtual" XML_AN_VOLATILE = "volatile" XML_NN_ARGUMENT = "Argument" @@ -196,6 +197,16 @@ def __init__(self, xml_file, decl_factory, config, *args): "__vr_offs", ] + # With CastXML and clang some __va_list_tag declarations are + # present in the tree + # With llvm 3.9 there is a __NSConstantString(_tag) in the tree + self.__declarations_to_skip = [ + "__va_list_tag", + "__va_list", + "__NSConstantString_tag", + "__NSConstantString" + ] + self.__xml_generator_from_xml_file = None @property @@ -284,7 +295,6 @@ def members(self): return self.__members def startElement(self, name, attrs): - try: if name not in self.__readers: return @@ -297,21 +307,10 @@ def startElement(self, name, attrs): self.__read_access(attrs) element_id = attrs.get(XML_AN_ID) - # With CastXML and clang some __va_list_tag declarations are - # present in the tree: we do not want to have these in the tree. - # With llvm 3.9 there is a __NSConstantString(_tag) in the tree - # We hide these declarations by default - rm1 = "f1" not in self.config.flags - names = [ - "__va_list_tag", - "__NSConstantString_tag", - "__NSConstantString"] - if isinstance(obj, declarations.declaration_t): - if rm1 and str(obj.name) in names: + if obj.name in self.__declarations_to_skip: return - self.__update_membership(attrs) self.__declarations[element_id] = obj if not isinstance(obj, declarations.namespace_t): @@ -558,7 +557,10 @@ def __read_argument(self, attrs): XML_AN_NAME, 'arg%d' % len( self.__inst.arguments)) - argument.decl_type = attrs[XML_AN_TYPE] + argument.decl_type = attrs.get( + XML_AN_ORIGINAL_TYPE, + attrs.get(XML_AN_TYPE) + ) argument.default_value = attrs.get(XML_AN_DEFAULT) self.__read_attributes(argument, attrs) self.__inst.arguments.append(argument) @@ -576,8 +578,8 @@ def __read_calldef(self, calldef, attrs, is_declaration): if is_declaration: self.__calldefs.append(calldef) calldef.name = attrs.get(XML_AN_NAME, '') - calldef.has_extern = attrs.get(XML_AN_EXTERN, False) - calldef.has_inline = bool(attrs.get(XML_AN_INLINE, "") == "1") + calldef.has_extern = bool(attrs.get(XML_AN_EXTERN, False)) + calldef.has_inline = bool(attrs.get(XML_AN_INLINE, False)) throw_stmt = attrs.get(XML_AN_THROW) if None is throw_stmt: calldef.does_throw = True @@ -593,9 +595,9 @@ def __read_calldef(self, calldef, attrs, is_declaration): def __read_member_function(self, calldef, attrs, is_declaration): self.__read_calldef(calldef, attrs, is_declaration) - calldef.has_const = attrs.get(XML_AN_CONST, False) + calldef.has_const = bool(attrs.get(XML_AN_CONST, False)) if is_declaration: - calldef.has_static = attrs.get(XML_AN_STATIC, False) + calldef.has_static = bool(attrs.get(XML_AN_STATIC, False)) if XML_AN_PURE_VIRTUAL in attrs: calldef.virtuality = declarations.VIRTUALITY_TYPES.PURE_VIRTUAL elif XML_AN_VIRTUAL in attrs: @@ -626,9 +628,9 @@ 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_STATIC, False) - type_qualifiers.has_extern = attrs.get(XML_AN_EXTERN, False) + type_qualifiers.has_mutable = bool(attrs.get(XML_AN_MUTABLE, False)) + type_qualifiers.has_static = bool(attrs.get(XML_AN_STATIC, False)) + type_qualifiers.has_extern = bool(attrs.get(XML_AN_EXTERN, False)) bits = attrs.get(XML_AN_BITS) if bits: bits = int(bits) @@ -652,6 +654,12 @@ def __read_class_impl(self, class_type, attrs): name = attrs.get(XML_AN_NAME, '') if '$' in name or '.' in name: name = '' + if "<" in name and " >" in name: + # Name with template. In some rare cases there + # is a space before > (and only there), so remove + # it to be consistent with the other names that + # have no space there + name = name.replace(" >", ">") if XML_AN_INCOMPLETE in attrs: decl = self.__decl_factory.create_class_declaration(name=name) else: diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/utils/__init__.py b/Modules/ThirdParty/pygccxml/src/pygccxml/utils/__init__.py index 1730aee03c2..84df5cf6c7a 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/utils/__init__.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/utils/__init__.py @@ -8,7 +8,6 @@ """ -from .utils import is_str from .utils import get_architecture from .utils import loggers from .utils import create_temp_file_name diff --git a/Modules/ThirdParty/pygccxml/src/pygccxml/utils/utils.py b/Modules/ThirdParty/pygccxml/src/pygccxml/utils/utils.py index 7a9deb5ae1d..0d1022dcf7f 100644 --- a/Modules/ThirdParty/pygccxml/src/pygccxml/utils/utils.py +++ b/Modules/ThirdParty/pygccxml/src/pygccxml/utils/utils.py @@ -7,36 +7,12 @@ import os import sys -import platform import logging import tempfile import shutil -import subprocess import warnings -def is_str(string): - """ - Python 2 and 3 compatible string checker. - - Args: - string (str | basestring): the string to check - - Returns: - bool: True or False - - """ - warnings.warn( - "The is_str function is deprecated. \ - Use isinstance(string, str) instead.", - DeprecationWarning) - - if sys.version_info[:2] >= (3, 0): - return isinstance(string, str) - - return isinstance(string, basestring) - - def find_xml_generator(name="castxml", search_path=None): """ Try to find a c++ parser (xml generator)