Skip to content

Commit af0def5

Browse files
committed
Merge pull request #35 from praetorian20/cv_qual_arrays
Fixes for cv-qualified arrays
2 parents 04c6f55 + b714e5b commit af0def5

File tree

5 files changed

+190
-897
lines changed

5 files changed

+190
-897
lines changed

pygccxml/declarations/type_traits.py

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -284,19 +284,46 @@ def remove_reference(type):
284284
def is_const(type):
285285
"""returns True, if type represents C++ const type, False otherwise"""
286286
nake_type = remove_alias(type)
287-
return isinstance(nake_type, cpptypes.const_t)
287+
if isinstance(nake_type, cpptypes.const_t):
288+
return True
289+
elif isinstance(nake_type, cpptypes.volatile_t):
290+
return is_const(nake_type.base)
291+
elif isinstance(nake_type, cpptypes.array_t):
292+
return is_const(nake_type.base)
293+
return False
288294

289295

290-
def remove_const(type):
296+
def remove_const(type_):
291297
"""removes const from the type definition
292298
293299
If type is not const type, it will be returned as is
294300
"""
295301

296-
nake_type = remove_alias(type)
302+
nake_type = remove_alias(type_)
297303
if not is_const(nake_type):
298-
return type
304+
return type_
299305
else:
306+
# Handling for const and volatile qualified types. There is a
307+
# difference in behavior between GCCXML and CastXML for cv-qual arrays.
308+
# GCCXML produces the following nesting of types:
309+
# -> volatile_t(const_t(array_t))
310+
# while CastXML produces the following nesting:
311+
# -> array_t(volatile_t(const_t))
312+
# For both cases, we must unwrap the types, remove const_t, and add
313+
# back the outer layers
314+
if isinstance(nake_type, cpptypes.array_t):
315+
is_v = is_volatile(nake_type)
316+
if is_v:
317+
result_type = nake_type.base.base.base
318+
else:
319+
result_type = nake_type.base.base
320+
if is_v:
321+
result_type = cpptypes.volatile_t(result_type)
322+
return cpptypes.array_t(result_type, nake_type.size)
323+
324+
elif isinstance(nake_type, cpptypes.volatile_t):
325+
return cpptypes.volatile_t(nake_type.base.base)
326+
300327
return nake_type.base
301328

302329

@@ -322,7 +349,13 @@ def is_same(type1, type2):
322349
def is_volatile(type):
323350
"""returns True, if type represents C++ volatile type, False otherwise"""
324351
nake_type = remove_alias(type)
325-
return isinstance(nake_type, cpptypes.volatile_t)
352+
if isinstance(nake_type, cpptypes.volatile_t):
353+
return True
354+
elif isinstance(nake_type, cpptypes.const_t):
355+
return is_volatile(nake_type.base)
356+
elif isinstance(nake_type, cpptypes.array_t):
357+
return is_volatile(nake_type.base)
358+
return False
326359

327360

328361
def remove_volatile(type):
@@ -334,6 +367,16 @@ def remove_volatile(type):
334367
if not is_volatile(nake_type):
335368
return type
336369
else:
370+
if isinstance(nake_type, cpptypes.array_t):
371+
is_c = is_const(nake_type)
372+
if is_c:
373+
base_type = nake_type.base.base.base
374+
else:
375+
base_type = nake_type.base.base
376+
result_type = base_type
377+
if is_c:
378+
result_type = cpptypes.const_t(result_type)
379+
return cpptypes.array_t(result_type, nake_type.size)
337380
return nake_type.base
338381

339382

@@ -344,12 +387,12 @@ def remove_cv(type):
344387
if not is_const(nake_type) and not is_volatile(nake_type):
345388
return type
346389
result = nake_type
347-
if is_const(nake_type):
348-
result = nake_type.base
390+
if is_const(result):
391+
result = remove_const(result)
349392
if is_volatile(result):
350-
result = result.base
393+
result = remove_volatile(result)
351394
if is_const(result):
352-
result = result.base
395+
result = remove_const(result)
353396
return result
354397

355398

unittests/array_bug_tester.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,65 @@ def test4(self):
5555
'::xyz[2][3]' == aaaa_type.decl_string,
5656
aaaa_type.decl_string)
5757

58+
def test5(self):
59+
code = 'char const arr[4] = {};'
60+
src_reader = parser.source_reader_t(self.config)
61+
global_ns = declarations.get_global_namespace(
62+
src_reader.read_string(code))
63+
arr_type = global_ns.variable('arr').decl_type
64+
if self.config.xml_generator == "gccxml":
65+
self.assertTrue(
66+
'char[4] const' == arr_type.decl_string,
67+
arr_type.decl_string)
68+
else:
69+
self.assertTrue(
70+
'char const[4]' == arr_type.decl_string,
71+
arr_type.decl_string)
72+
self.assertTrue(
73+
declarations.is_array(arr_type))
74+
self.assertTrue(
75+
declarations.is_const(arr_type))
76+
77+
def test6(self):
78+
code = 'char volatile arr[4] = {};'
79+
src_reader = parser.source_reader_t(self.config)
80+
global_ns = declarations.get_global_namespace(
81+
src_reader.read_string(code))
82+
arr_type = global_ns.variable('arr').decl_type
83+
if self.config.xml_generator == "gccxml":
84+
self.assertTrue(
85+
'char[4] volatile' == arr_type.decl_string,
86+
arr_type.decl_string)
87+
else:
88+
self.assertTrue(
89+
'char volatile[4]' == arr_type.decl_string,
90+
arr_type.decl_string)
91+
self.assertTrue(
92+
declarations.is_array(arr_type))
93+
self.assertTrue(
94+
declarations.is_volatile(arr_type))
95+
96+
def test7(self):
97+
code = 'char const volatile arr[4] = {};'
98+
src_reader = parser.source_reader_t(self.config)
99+
global_ns = declarations.get_global_namespace(
100+
src_reader.read_string(code))
101+
arr_type = global_ns.variable('arr').decl_type
102+
if self.config.xml_generator == "gccxml":
103+
self.assertTrue(
104+
'char[4] const volatile' == arr_type.decl_string,
105+
arr_type.decl_string)
106+
else:
107+
self.assertTrue(
108+
'char const volatile[4]' == arr_type.decl_string,
109+
arr_type.decl_string)
110+
self.assertTrue(
111+
declarations.is_array(arr_type))
112+
self.assertTrue(
113+
declarations.is_const(arr_type))
114+
self.assertTrue(
115+
declarations.is_volatile(arr_type))
116+
58117

59118
def create_suite():
60119
suite = unittest.TestSuite()

unittests/data/type_traits_gccxml.hpp renamed to unittests/data/type_traits.hpp

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
typedef BASE volatile NAME##_volatile_t; \
2020
typedef BASE const volatile NAME##_const_volatile_t;
2121

22+
2223
struct some_struct_t{
2324
void do_smth();
2425
int member;
@@ -47,9 +48,7 @@ struct incomplete_type;
4748

4849
namespace is_void{
4950
namespace yes{
50-
typedef void void_t;
51-
typedef void const void_cont_t;
52-
typedef void volatile void_volatile_t;
51+
TYPE_PERMUTATION( void, void )
5352
}
5453
namespace no{
5554
typedef void* void_ptr_t;
@@ -186,7 +185,6 @@ namespace yes{
186185
typedef detail::dd_t dd_t;
187186
typedef detail::f_t f_t;
188187
typedef detail::g_t g_t;
189-
190188
typedef detail::const_container const_container_t;
191189
typedef detail::const_item const_item_t;
192190

@@ -287,11 +285,6 @@ namespace no{
287285
namespace is_fundamental{
288286
namespace yes{
289287

290-
#define FUNDAMENTAL_TYPE_PERMUTATION( BASE, NAME ) \
291-
typedef BASE NAME##_t; \
292-
typedef BASE const NAME##_const_t; \
293-
typedef BASE volatile NAME##_volatile_t;
294-
295288
TYPE_PERMUTATION( void, void )
296289
TYPE_PERMUTATION( bool, bool )
297290
TYPE_PERMUTATION( char, char )
@@ -409,7 +402,8 @@ namespace yes{
409402
typedef const void const_void_t;
410403
typedef const incomplete_type const_incomplete_type_t;
411404
typedef int* const int_const_t;
412-
//TODO typedef const int& const_int_ref_t;
405+
typedef int* volatile const int_volatile_const_t;
406+
typedef int* const volatile int_const_volatile_t;
413407
}
414408

415409
namespace no{
@@ -421,32 +415,53 @@ namespace no{
421415
typedef void(*function_t)();
422416
typedef void (some_struct_t::*member_function_t)();
423417
typedef int int_t;
418+
typedef const int& const_int_ref_t;
424419
} }
425420

426421
namespace remove_const{
427422
namespace before{
428-
429423
typedef const void x1;
430424
typedef const incomplete_type x2;
431425
typedef int* const x3;
432426
typedef int* volatile x4;
427+
typedef void const * x5;
428+
typedef int volatile const x6;
429+
typedef int const volatile x7;
430+
431+
typedef char arr_42[42];
432+
typedef char const arr_c_42[42];
433+
typedef char volatile arr_v_42[42];
434+
typedef char const volatile arr_cv_42[42];
435+
typedef char volatile const arr_vc_42[42];
433436
}
434437

435438
namespace after{
436439
typedef void x1;
437440
typedef incomplete_type x2;
438441
typedef int* x3;
439442
typedef int* volatile x4;
443+
typedef void const * x5;
444+
typedef int volatile x6;
445+
typedef int volatile x7;
446+
447+
typedef char arr_42[42];
448+
typedef char arr_c_42[42];
449+
typedef char volatile arr_v_42[42];
450+
typedef char volatile arr_cv_42[42];
451+
typedef char volatile arr_vc_42[42];
440452
} }
441453

442454
namespace is_volatile{
443455
namespace yes{
444456

445457
typedef void * volatile vvoid_ptr_t;
446458
typedef volatile int volatile_int_t;
459+
typedef int* volatile const int_volatile_const_t;
460+
typedef int* const volatile int_const_volatile_t;
447461
}
448462

449463
namespace no{
464+
typedef void volatile * void_ptr_to_v_t;
450465
typedef int* int_ptr_t;
451466
typedef const int* const_int_ptr_t;
452467
typedef int* volatile_int_ptr_t;
@@ -463,12 +478,30 @@ namespace before{
463478
typedef void * volatile x1;
464479
typedef volatile int x2;
465480
typedef int* x3;
481+
typedef void volatile * x4;
482+
typedef int volatile const x5;
483+
typedef int const volatile x6;
484+
485+
typedef char arr_42[42];
486+
typedef char const arr_c_42[42];
487+
typedef char volatile arr_v_42[42];
488+
typedef char const volatile arr_cv_42[42];
489+
typedef char volatile const arr_vc_42[42];
466490
}
467491

468492
namespace after{
469493
typedef void * x1;
470494
typedef int x2;
471495
typedef int* x3;
496+
typedef void volatile * x4;
497+
typedef int const x5;
498+
typedef int const x6;
499+
500+
typedef char arr_42[42];
501+
typedef char const arr_c_42[42];
502+
typedef char arr_v_42[42];
503+
typedef char const arr_cv_42[42];
504+
typedef char const arr_vc_42[42];
472505
} }
473506

474507

@@ -488,6 +521,12 @@ namespace before{
488521
typedef int* const x32;
489522

490523
typedef void(*x40)();
524+
525+
typedef char arr_42[42];
526+
typedef char const arr_c_42[42];
527+
typedef char volatile arr_v_42[42];
528+
typedef char const volatile arr_cv_42[42];
529+
typedef char volatile const arr_vc_42[42];
491530
}
492531

493532
namespace after{
@@ -504,6 +543,12 @@ namespace after{
504543
typedef int* x32;
505544

506545
typedef void(*x40)();
546+
547+
typedef char arr_42[42];
548+
typedef char arr_c_42[42];
549+
typedef char arr_v_42[42];
550+
typedef char arr_cv_42[42];
551+
typedef char arr_vc_42[42];
507552
} }
508553

509554

@@ -548,9 +593,6 @@ namespace yes{
548593

549594
namespace no{
550595

551-
typedef details::const_item const_item;
552-
typedef details::const_container const_container;
553-
554596
class y{
555597
private:
556598
y(){}
@@ -567,6 +609,9 @@ namespace no{
567609
public:
568610
static singleton_t* instance();
569611
};
612+
613+
typedef details::const_item const_item;
614+
typedef details::const_container const_container;
570615
} }
571616

572617
namespace has_public_constructor{
@@ -663,6 +708,7 @@ namespace yes{
663708
const int yes2[2] = {0};
664709
const volatile int yes3[2] = {0};
665710
int yes4[2][3];
711+
int const yes5[2] = {0};
666712
}
667713

668714
namespace no{

0 commit comments

Comments
 (0)