Skip to content

Commit 54201e5

Browse files
committed
Merge branch 'hotfix/v1.7.5'
2 parents e02c689 + 52ad762 commit 54201e5

File tree

14 files changed

+222
-68
lines changed

14 files changed

+222
-68
lines changed

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ pygccxml
77
.. image:: https://coveralls.io/repos/gccxml/pygccxml/badge.svg?branch=master
88
:target: https://coveralls.io/r/gccxml/pygccxml?branch=master
99
:alt: Code coverage status
10-
.. image:: https://readthedocs.io/projects/pygccxml/badge/?version=master
11-
:target: https://readthedocs.io/projects/pygccxml/?badge=master
10+
.. image:: https://readthedocs.org/projects/pygccxml/badge/?version=master
11+
:target: http://pygccxml.readthedocs.io/en/master/?badge=master
1212
:alt: Documentation status
1313
.. image:: https://www.quantifiedcode.com/api/v1/project/117af14ef32a455fb7b3762e21083fb3/snapshot/origin:master:HEAD/badge.svg
1414
:target: https://www.quantifiedcode.com/app/project/117af14ef32a455fb7b3762e21083fb3?branch=origin%2Fmaster&tab=basics

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@
5353
# built documents.
5454
#
5555
# The short X.Y version.
56-
version = '1.7.4'
56+
version = '1.7.5'
5757
# The full version, including alpha/beta/rc tags.
58-
release = '1.7.4'
58+
release = '1.7.5'
5959

6060
# The language for content autogenerated by Sphinx. Refer to documentation
6161
# for a list of supported languages.

docs/history.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,22 @@ to python 3 (keeping it compatible with python 2).
1111
In Mai 2014, Michka Popoff and the Insight Software Consortium revived pygccxml
1212
by setting up a git repositery on github, hosted along with gccxml.
1313

14+
Version 1.7.5
15+
-------------
16+
17+
1. Improve error message when no castxml or gccxml is found.
18+
19+
2. Fix compilation of tests with c++11.
20+
21+
3. Fix patching of enums in default arguments for C++03.
22+
23+
4. Version numbers are still tagged with the v prefix (1.7.4 was correctly tagged),
24+
as this is recommended by GitHub. The version number in the __init__.py and
25+
setup.py files are without v prefix, because this is what pip requires.
26+
27+
Thanks to the following people for their contribution to this release:
28+
Ashish Sadanandan
29+
1430
Version 1.7.4
1531
-------------
1632

pygccxml/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@
4040
# TODO:
4141
# 1. Add "explicit" property for constructors
4242

43-
__version__ = '1.7.4'
43+
__version__ = '1.7.5'

pygccxml/parser/config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,9 +450,11 @@ def create_compiler_path(xml_generator, compiler_path):
450450
if platform.system() != 'Windows':
451451
# On windows there is no need for the compiler path
452452
p = subprocess.Popen(
453-
['which', 'clang++'], stdout=subprocess.PIPE)
453+
['which', 'clang++'], stdout=subprocess.PIPE,
454+
stderr=subprocess.PIPE)
454455
compiler_path = p.stdout.read().decode("utf-8").rstrip()
455456
p.stdout.close()
457+
p.stderr.close()
456458
# No clang found; use gcc
457459
if compiler_path == '':
458460
compiler_path = '/usr/bin/c++'

pygccxml/parser/patcher.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010

1111
class default_argument_patcher_t(object):
1212

13-
def __init__(self, enums):
13+
def __init__(self, enums, cxx_std):
1414
object.__init__(self)
1515
self.__enums = enums
16+
self.__cxx_std = cxx_std
1617

1718
def __call__(self, decl):
1819
for arg in decl.arguments:
@@ -54,8 +55,12 @@ def __is_unqualified_enum(self, func, arg):
5455
def __fix_unqualified_enum(self, func, arg):
5556
type_ = declarations.remove_reference(declarations.remove_cv(arg.type))
5657
enum_type = declarations.enum_declaration(type_)
58+
if self.__cxx_std.is_cxx11_or_greater:
59+
qualifier_decl_string = enum_type.decl_string
60+
else:
61+
qualifier_decl_string = enum_type.parent.decl_string
5762
return self.__join_names(
58-
enum_type.parent.decl_string,
63+
qualifier_decl_string,
5964
arg.default_value.split('::')[-1])
6065

6166
def __is_invalid_integral(self, func, arg):
@@ -92,19 +97,25 @@ def __fix_invalid_integral(self, func, arg):
9297
pass
9398

9499
# may be we deal with enum
100+
# CastXML qualifies the enum value with enum type, so split the
101+
# argument and use only the enum value
102+
enum_value = arg.default_value.split('::')[-1]
95103
parent = func.parent
96104
while parent:
97-
found = self.__find_enum(parent, arg.default_value)
105+
found = self.__find_enum(parent, enum_value)
98106
if found:
99107
if declarations.is_fundamental(arg.type) and ' ' in \
100108
arg.type.decl_string:
101109
template = '(%s)(%s)'
102110
else:
103111
template = '%s(%s)'
112+
if self.__cxx_std.is_cxx11_or_greater:
113+
qualifier_decl_string = found.decl_string
114+
else:
115+
qualifier_decl_string = found.parent.decl_string
104116
return template % (arg.type.decl_string,
105-
self.__join_names(
106-
found.parent.decl_string,
107-
arg.default_value))
117+
self.__join_names(qualifier_decl_string,
118+
enum_value))
108119
else:
109120
parent = parent.parent
110121

@@ -132,7 +143,7 @@ def __fix_invalid_integral(self, func, arg):
132143

133144
def __find_enum(self, scope, default_value):
134145
# this algorithm could be improved: it could take into account
135-
# 1. unnamed namespaced
146+
# 1. unnamed namespace
136147
# 2. location within files
137148

138149
for enum in self.__enums:
@@ -221,8 +232,8 @@ def __call__(self, decl):
221232
_casting_oper_patcher_ = casting_operator_patcher_t()
222233

223234

224-
def fix_calldef_decls(decls, enums):
225-
default_arg_patcher = default_argument_patcher_t(enums)
235+
def fix_calldef_decls(decls, enums, cxx_std):
236+
default_arg_patcher = default_argument_patcher_t(enums, cxx_std)
226237
# decls should be flat list of all declarations, you want to apply patch on
227238
for decl in decls:
228239
default_arg_patcher(decl)

pygccxml/parser/source_reader.py

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ def __init__(self, config, cache=None, decl_factory=None, join_decls=True):
9393
self.__join_decls = join_decls
9494
self.__search_directories = []
9595
self.__config = config
96+
self.__cxx_std = utils.cxx_standard(config.cflags)
9697
self.__search_directories.append(config.working_directory)
9798
self.__search_directories.extend(config.include_paths)
9899
if not cache:
@@ -163,30 +164,12 @@ def __create_command_line_castxml(self, source_file, xmlfile):
163164
# On mac or linux, use gcc or clang (the flag is the same)
164165
cmd.append('--castxml-cc-gnu ')
165166

166-
# Check for -std=xx flags passed to the compiler.
167-
# A regex could be used but this is a moving target.
168-
# See c++1z for example. It is preferable to have a defined
169-
# list of what is allowed. http://clang.llvm.org/cxx_status.html
170-
#
171-
# Version 98 and 03 are only there in the case somebody is using
172-
# these flags; this is the equivalent to not passing these flags.
173-
standards = [
174-
"-std=c++98",
175-
"-std=c++03",
176-
"-std=c++11",
177-
"-std=c++14",
178-
"-std=c++1z"]
179-
180-
std_flag = ""
181-
for standard in standards:
182-
if standard in self.__config.cflags:
183-
std_flag = " " + standard + " "
184-
185-
# A -std= flag was passed, but is not in the list
186-
if "-std=" in self.__config.cflags and std_flag == "":
187-
raise(RuntimeError("Unknown -std=c++xx flag used !"))
188-
189-
if std_flag != "":
167+
if self.__cxx_std.is_implicit:
168+
std_flag = ''
169+
else:
170+
std_flag = ' ' + self.__cxx_std.stdcxx + ' '
171+
172+
if std_flag:
190173
cmd.append(
191174
'"(" ' + self.__config.compiler_path + std_flag + '")"')
192175
else:
@@ -502,7 +485,8 @@ def __parse_xml_file(self, xml_file):
502485
# void ddd(){ typedef typename X::Y YY;}
503486
# if I will fail on this bug next time, the right way to fix it may be
504487
# different
505-
patcher.fix_calldef_decls(scanner_.calldefs(), scanner_.enums())
488+
patcher.fix_calldef_decls(scanner_.calldefs(), scanner_.enums(),
489+
self.__cxx_std)
506490
decls = [
507491
inst for inst in iter(
508492
decls.values()) if isinstance(

pygccxml/utils/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from .utils import normalize_path
1818
from .utils import find_xml_generator
1919
from .utils import get_tr1
20+
from .utils import cxx_standard
2021

2122
# Version of xml generator which was used.
2223
xml_generator = None

pygccxml/utils/utils.py

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,24 @@ def find_xml_generator(name=None):
4848

4949
if name is None:
5050
name = "gccxml"
51-
p = subprocess.Popen([command, name], stdout=subprocess.PIPE)
51+
p = subprocess.Popen([command, name], stdout=subprocess.PIPE,
52+
stderr=subprocess.PIPE)
5253
path = p.stdout.read().decode("utf-8")
5354
p.stdout.close()
55+
p.stderr.close()
5456
if path == "":
5557
name = "castxml"
56-
p = subprocess.Popen([command, name], stdout=subprocess.PIPE)
58+
p = subprocess.Popen([command, name], stdout=subprocess.PIPE,
59+
stderr=subprocess.PIPE)
5760
path = p.stdout.read().decode("utf-8")
5861
p.stdout.close()
62+
p.stderr.close()
5963
else:
60-
p = subprocess.Popen([command, name], stdout=subprocess.PIPE)
64+
p = subprocess.Popen([command, name], stdout=subprocess.PIPE,
65+
stderr=subprocess.PIPE)
6166
path = p.stdout.read().decode("utf-8")
6267
p.stdout.close()
68+
p.stderr.close()
6369
if path == "":
6470
raise(Exception(
6571
"No c++ parser found. Please install castxml or gccxml."))
@@ -346,3 +352,94 @@ def get_tr1(name):
346352
if "tr1" in name:
347353
tr1 = "tr1::"
348354
return tr1
355+
356+
357+
class cxx_standard(object):
358+
"""Helper class for parsing the C++ standard version.
359+
360+
This class holds the C++ standard version the XML generator has been
361+
configured with, and provides helpers functions for querying C++ standard
362+
version related information.
363+
"""
364+
365+
__STD_CXX = {
366+
'-std=c++98': 199711,
367+
'-std=gnu++98': 199711,
368+
'-std=c++03': 199711,
369+
'-std=gnu++03': 199711,
370+
'-std=c++0x': 201103,
371+
'-std=gnu++0x': 201103,
372+
'-std=c++11': 201103,
373+
'-std=gnu++11': 201103,
374+
'-std=c++1y': 201402,
375+
'-std=gnu++1y': 201402,
376+
'-std=c++14': 201402,
377+
'-std=gnu++14': 201402,
378+
'-std=c++1z': float('inf'),
379+
'-std=gnu++1z': float('inf'),
380+
}
381+
382+
def __init__(self, cflags):
383+
"""Class constructor that parses the XML generator's command line
384+
385+
Args:
386+
cflags (str): cflags command line arguments passed to the XML
387+
generator
388+
"""
389+
super(cxx_standard, self).__init__()
390+
391+
self._stdcxx = None
392+
self._is_implicit = False
393+
for key in cxx_standard.__STD_CXX:
394+
if key in cflags:
395+
self._stdcxx = key
396+
self._cplusplus = cxx_standard.__STD_CXX[key]
397+
398+
if not self._stdcxx:
399+
if '-std=' in cflags:
400+
raise RuntimeError('Unknown -std=c++xx flag used')
401+
402+
# Assume c++03 by default
403+
self._stdcxx = '-std=c++03'
404+
self._cplusplus = cxx_standard.__STD_CXX['-std=c++03']
405+
self._is_implicit = True
406+
407+
@property
408+
def stdcxx(self):
409+
"""Returns the -std=c++xx option passed to the constructor"""
410+
return self._stdcxx
411+
412+
@property
413+
def is_implicit(self):
414+
"""Indicates whether a -std=c++xx was specified"""
415+
return self._is_implicit
416+
417+
@property
418+
def is_cxx03(self):
419+
"""Returns true if -std=c++03 is being used"""
420+
return self._cplusplus == cxx_standard.__STD_CXX['-std=c++03']
421+
422+
@property
423+
def is_cxx11(self):
424+
"""Returns true if -std=c++11 is being used"""
425+
return self._cplusplus == cxx_standard.__STD_CXX['-std=c++11']
426+
427+
@property
428+
def is_cxx11_or_greater(self):
429+
"""Returns true if -std=c++11 or a newer standard is being used"""
430+
return self._cplusplus >= cxx_standard.__STD_CXX['-std=c++11']
431+
432+
@property
433+
def is_cxx14(self):
434+
"""Returns true if -std=c++14 is being used"""
435+
return self._cplusplus == cxx_standard.__STD_CXX['-std=c++14']
436+
437+
@property
438+
def is_cxx14_or_greater(self):
439+
"""Returns true if -std=c++14 or a newer standard is being used"""
440+
return self._cplusplus >= cxx_standard.__STD_CXX['-std=c++14']
441+
442+
@property
443+
def is_cxx1z(self):
444+
"""Returns true if -std=c++1z is being used"""
445+
return self._cplusplus == cxx_standard.__STD_CXX['-std=c++1z']

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
from setuptools import setup
88

99
setup(name="pygccxml",
10-
version="1.7.4",
10+
version="1.7.5",
1111
author="Roman Yakovenko",
1212
author_email="roman yakovenko at gmail com",
1313
maintainer="Michka Popoff and the Insight Software Consortium",
1414
maintainer_email="[email protected]",
1515
description="Python package for easy C++ declarations navigation.",
1616
url="https://github.com/gccxml/pygccxml",
17-
download_url="https://github.com/gccxml/pygccxml/archive/1.7.4.tar.gz",
17+
download_url="https://github.com/gccxml/pygccxml/archive/v1.7.5.tar.gz",
1818
license="Boost",
1919
keywords="C++, declaration parser, CastXML, gccxml",
2020
packages=["pygccxml",

0 commit comments

Comments
 (0)