@@ -612,6 +612,87 @@ class Test5(Structure):
612612 self .assertEqual (test5 .nested .an_int , 0 )
613613 self .assertEqual (test5 .another_int , 0 )
614614
615+ #@unittest.skipIf('s390' in MACHINE, 'Test causes segfault on S390')
616+ def test_bitfield_by_value (self ):
617+ # See bpo-16576
618+
619+ # These should mirror the structures in Modules/_ctypes/_ctypes_test.c
620+
621+ class Test6 (Structure ):
622+ _fields_ = [
623+ ('A' , c_int , 1 ),
624+ ('B' , c_int , 2 ),
625+ ('C' , c_int , 3 ),
626+ ('D' , c_int , 2 ),
627+ ]
628+
629+ test6 = Test6 ()
630+ # As these are signed int fields, all are logically -1 due to sign
631+ # extension.
632+ test6 .A = 1
633+ test6 .B = 3
634+ test6 .C = 7
635+ test6 .D = 3
636+ dll = CDLL (_ctypes_test .__file__ )
637+ with self .assertRaises (TypeError ) as ctx :
638+ func = dll ._testfunc_bitfield_by_value1
639+ func .restype = c_long
640+ func .argtypes = (Test6 ,)
641+ result = func (test6 )
642+ self .assertEqual (ctx .exception .args [0 ], 'item 1 in _argtypes_ passes '
643+ 'a struct/union with a bitfield by value, which is '
644+ 'unsupported.' )
645+ # passing by reference should be OK
646+ func = dll ._testfunc_bitfield_by_reference1
647+ func .restype = c_long
648+ func .argtypes = (POINTER (Test6 ),)
649+ result = func (byref (test6 ))
650+ self .assertEqual (result , - 4 )
651+ self .assertEqual (test6 .A , 0 )
652+ self .assertEqual (test6 .B , 0 )
653+ self .assertEqual (test6 .C , 0 )
654+ self .assertEqual (test6 .D , 0 )
655+
656+ class Test7 (Structure ):
657+ _fields_ = [
658+ ('A' , c_uint , 1 ),
659+ ('B' , c_uint , 2 ),
660+ ('C' , c_uint , 3 ),
661+ ('D' , c_uint , 2 ),
662+ ]
663+ test7 = Test7 ()
664+ test7 .A = 1
665+ test7 .B = 3
666+ test7 .C = 7
667+ test7 .D = 3
668+ func = dll ._testfunc_bitfield_by_reference2
669+ func .restype = c_long
670+ func .argtypes = (POINTER (Test7 ),)
671+ result = func (byref (test7 ))
672+ self .assertEqual (result , 14 )
673+ self .assertEqual (test7 .A , 0 )
674+ self .assertEqual (test7 .B , 0 )
675+ self .assertEqual (test7 .C , 0 )
676+ self .assertEqual (test7 .D , 0 )
677+
678+ # for a union with bitfields, the union check happens first
679+ class Test8 (Union ):
680+ _fields_ = [
681+ ('A' , c_int , 1 ),
682+ ('B' , c_int , 2 ),
683+ ('C' , c_int , 3 ),
684+ ('D' , c_int , 2 ),
685+ ]
686+
687+ test8 = Test8 ()
688+ with self .assertRaises (TypeError ) as ctx :
689+ func = dll ._testfunc_bitfield_by_value2
690+ func .restype = c_long
691+ func .argtypes = (Test8 ,)
692+ result = func (test8 )
693+ self .assertEqual (ctx .exception .args [0 ], 'item 1 in _argtypes_ passes '
694+ 'a union by value, which is unsupported.' )
695+
615696class PointerMemberTestCase (unittest .TestCase ):
616697
617698 def test (self ):
0 commit comments