Skip to content

Commit 9dcc730

Browse files
praetorian20iMichka
authored andcommitted
Fix unqualified integral const in default arguments for CastXML
CastXML, prior to XML output versin 1.137, didn't modify integral constant names used in default arguments for functions, it simply used the same text present in the source file. This causes compilation failures in bindings generated by pyplusplus in case of code such as the following: struct st { static int const DEFAULT = 0; void fun(int arg=DEFAULT); }; In this case, CastXML produced `DEFAULT` as the default value while GCCXML qualifies the name and sets the default value to `st::DEFAULT`. Consequently, pyplusplus refers to the default value as `DEFAULT`, which fails compilation because the name needs to be fully qualified as `st::DEFAULT`. This fix produces the desired qualified output from pygccxml with both GCCXML and CastXML. As of XML output version 1.137, CastXML now produces fully qualified names for default arguments. Change-Id: Ie22ae5e7e058743efcd986a44797005be8e9c891 Cherry-picked from the develop branch
1 parent 5ccfcaa commit 9dcc730

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

pygccxml/parser/patcher.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Distributed under the Boost Software License, Version 1.0.
44
# See http://www.boost.org/LICENSE_1_0.txt
55

6+
import re
67
from pygccxml import utils
78
from pygccxml import declarations
89

@@ -106,6 +107,27 @@ def __fix_invalid_integral(self, func, arg):
106107
arg.default_value))
107108
else:
108109
parent = parent.parent
110+
111+
# check if we have an unqualified integral constant
112+
# only do patching in cases where we have a bare variable name
113+
c_var = re.compile("[a-z_][a-z0-9_]*", re.IGNORECASE)
114+
m = c_var.match(arg.default_value)
115+
if m:
116+
parent = func.parent
117+
while parent:
118+
try:
119+
found = parent.variable(arg.default_value,
120+
recursive=False)
121+
except declarations.matcher.declaration_not_found_t:
122+
# ignore exceptions if a match is not found
123+
found = None
124+
if found:
125+
if declarations.is_fundamental(arg.type):
126+
return "%s" % self.__join_names(
127+
found.parent.decl_string,
128+
arg.default_value)
129+
parent = parent.parent
130+
109131
return arg.default_value
110132

111133
def __find_enum(self, scope, default_value):

unittests/data/patcher.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,20 @@ namespace osg{
6262

6363
}
6464

65+
namespace ns1{
66+
67+
static int const DEFAULT_1 = 0;
68+
struct st1{
69+
static long const DEFAULT_2 = 10;
70+
void fun1( int arg1=DEFAULT_1, long=DEFAULT_2 );
71+
};
72+
73+
}
74+
75+
static int const DEFAULT_1 = 20;
76+
int fun2( int arg1=DEFAULT_1, int arg2=ns1::DEFAULT_1, long arg3=::ns1::st1::DEFAULT_2 );
77+
78+
6579
/*struct default_arg_t{};*/
6680
/*default_arg_t create_default_argument();*/
6781
/*void double_call( default_arg_t x=create_default_argument() );*/

unittests/patcher_tester.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,60 @@ def test_numeric_patcher(self):
7070
self.assertEqual(
7171
fix_numeric.arguments[0].default_value, "0ffffffff")
7272

73+
def test_unqualified_integral_patcher(self):
74+
if 32 != self.architecture and "CastXML" not in utils.xml_generator:
75+
# For this check to be removed, patcher_tester_64bit.xml
76+
# will need to be updated for GCCXML
77+
return
78+
79+
ns1 = self.global_ns.namespace("ns1")
80+
st1 = ns1.class_("st1")
81+
fun1 = st1.member_function("fun1")
82+
if "CastXML" in utils.xml_generator:
83+
if utils.xml_output_version >= 1.137:
84+
val1 = "ns1::DEFAULT_1"
85+
val2 = "ns1::st1::DEFAULT_2"
86+
else:
87+
val1 = "::ns1::DEFAULT_1"
88+
val2 = "::ns1::st1::DEFAULT_2"
89+
self.assertEqual(
90+
fun1.arguments[0].default_value, val1)
91+
self.assertEqual(
92+
fun1.arguments[1].default_value, val2)
93+
else:
94+
self.assertEqual(
95+
fun1.arguments[0].default_value,
96+
"ns1::DEFAULT_1")
97+
self.assertEqual(
98+
fun1.arguments[1].default_value,
99+
"ns1::st1::DEFAULT_2")
100+
101+
fun2 = self.global_ns.free_fun("fun2")
102+
self.assertEqual(
103+
fun2.arguments[0].default_value,
104+
"::DEFAULT_1")
105+
if "CastXML" in utils.xml_generator:
106+
if utils.xml_output_version >= 1.137:
107+
val1 = "ns1::DEFAULT_1"
108+
val2 = "ns1::st1::DEFAULT_2"
109+
else:
110+
# Before XML output version 1.137, the following two
111+
# were unpatched and were identical to the text in
112+
# matcher.hpp
113+
val1 = "ns1::DEFAULT_1"
114+
val2 = "::ns1::st1::DEFAULT_2"
115+
self.assertEqual(
116+
fun2.arguments[1].default_value, val1)
117+
self.assertEqual(
118+
fun2.arguments[2].default_value, val2)
119+
else:
120+
self.assertEqual(
121+
fun2.arguments[1].default_value,
122+
"ns1::DEFAULT_1")
123+
self.assertEqual(
124+
fun2.arguments[2].default_value,
125+
"ns1::st1::DEFAULT_2")
126+
73127
def test_unnamed_enum_patcher(self):
74128
fix_unnamed = self.global_ns.free_fun("fix_unnamed")
75129
if ("CastXML" in utils.xml_generator and

0 commit comments

Comments
 (0)