1
+ #include < cstdint>
2
+
3
+ std::int16_t s16;
4
+ std::uint16_t u16 ;
5
+ std::int32_t s32;
6
+ std::uint32_t u32 ;
7
+ std::int64_t s64;
8
+ std::uint64_t u64 ;
9
+
10
+ struct MemberFunctionPointerTest {
11
+ void mf15 (std::int32_t l1) {}
12
+ void mf15 (std::uint32_t l1) {}
13
+ void mf16 (std::int32_t l1) {}
14
+ };
15
+
16
+ void test_pointer_to_member_functions () {
17
+ MemberFunctionPointerTest l1;
18
+ MemberFunctionPointerTest *l6 = &l1;
19
+
20
+ // mf15 is overload independent when used as a member function pointer
21
+ void (MemberFunctionPointerTest::*l2)(std::int32_t ) =
22
+ &MemberFunctionPointerTest::mf15;
23
+ (l1.*l2)(s16); // COMPLIANT - widening of id-expression
24
+ (l1.*l2)(s32); // COMPLIANT - type match
25
+ (l1.*l2)(s64); // NON_COMPLIANT - narrowing
26
+ (l1.*l2)(u16 ); // NON_COMPLIANT - wrong sign
27
+ (l1.*l2)(u32 ); // NON_COMPLIANT - wrong sign
28
+ (l1.*l2)(u64 ); // NON_COMPLIANT - wrong sign and narrowing
29
+
30
+ (l6->*l2)(s16); // COMPLIANT - is widening of id-expression
31
+ (l6->*l2)(s32); // COMPLIANT - type match
32
+ (l6->*l2)(s64); // NON_COMPLIANT - narrowing
33
+ (l6->*l2)(u16 ); // NON_COMPLIANT - wrong sign
34
+ (l6->*l2)(u32 ); // NON_COMPLIANT - wrong sign
35
+ (l6->*l2)(u64 ); // NON_COMPLIANT - wrong sign and narrowing
36
+
37
+ // mf16 is overload independent when used as a member function pointer
38
+ void (MemberFunctionPointerTest::*l3)(std::int32_t ) =
39
+ &MemberFunctionPointerTest::mf16;
40
+ (l1.*l3)(s16); // COMPLIANT - widening of id-expression
41
+ (l1.*l3)(s32); // COMPLIANT - type match
42
+ (l1.*l3)(s64); // NON_COMPLIANT - narrowing
43
+ (l1.*l3)(u16 ); // NON_COMPLIANT - wrong sign
44
+ (l1.*l3)(u32 ); // NON_COMPLIANT - wrong sign
45
+ (l1.*l3)(u64 ); // NON_COMPLIANT - wrong sign and narrowing
46
+
47
+ (l6->*l3)(s16); // COMPLIANT - widening of id-expression
48
+ (l6->*l3)(s32); // COMPLIANT - type match
49
+ (l6->*l3)(s64); // NON_COMPLIANT - narrowing
50
+ (l6->*l3)(u16 ); // NON_COMPLIANT - wrong sign
51
+ (l6->*l3)(u32 ); // NON_COMPLIANT - wrong sign
52
+ (l6->*l3)(u64 ); // NON_COMPLIANT - wrong sign and narrowing
53
+
54
+ // Direct calls for comparison
55
+
56
+ // mf15 is not overload-independent, so it should only be compliant
57
+ // where an exact type of an overload is used
58
+ l1.mf15 (s16); // NON_COMPLIANT - widening not allowed
59
+ l1.mf15 (s32); // COMPLIANT - exact type match
60
+ l1.mf15 (u16 ); // NON_COMPLIANT - widening not allowed
61
+ l1.mf15 (u32 ); // COMPLIANT - exact type match
62
+
63
+ // A qualified call to mf16 is overload-independent
64
+ l1.mf16 (s16); // COMPLIANT - widening of id-expression
65
+ l1.mf16 (s32); // COMPLIANT - exact type match
66
+ l1.mf16 (u16 ); // NON_COMPLIANT
67
+ l1.mf16 (u32 ); // NON_COMPLIANT
68
+ }
69
+
70
+ // Test static member function pointers - should be overload-independent
71
+ struct StaticMemberFunctionPointerTest {
72
+ static void mf19 (std::int32_t l1) {}
73
+ static void mf19 (std::uint32_t l1) {}
74
+ static void mf20 (std::int32_t l1) {}
75
+ };
76
+
77
+ void test_static_member_function_pointers () {
78
+ // Static member function pointers - overload-independent
79
+ void (*l1)(std::int32_t ) = &StaticMemberFunctionPointerTest::mf19;
80
+ l1 (s16); // COMPLIANT - widening of id-expression
81
+ l1 (s32); // COMPLIANT - type match
82
+ l1 (s64); // NON_COMPLIANT - narrowing
83
+ l1 (u16 ); // NON_COMPLIANT - wrong sign
84
+ l1 (u32 ); // NON_COMPLIANT - wrong sign
85
+ l1 (u64 ); // NON_COMPLIANT - wrong sign and narrowing
86
+
87
+ void (*l2)(std::int32_t ) = &StaticMemberFunctionPointerTest::mf20;
88
+ l2 (s16); // COMPLIANT - widening of id-expression
89
+ l2 (s32); // COMPLIANT - type match
90
+ l2 (s64); // NON_COMPLIANT - narrowing
91
+ l2 (u16 ); // NON_COMPLIANT - wrong sign
92
+ l2 (u32 ); // NON_COMPLIANT - wrong sign
93
+ l2 (u64 ); // NON_COMPLIANT - wrong sign and narrowing
94
+
95
+ // Direct calls for comparison - not overload-independent
96
+ StaticMemberFunctionPointerTest::mf19 (
97
+ s16); // NON_COMPLIANT - widening not allowed
98
+ StaticMemberFunctionPointerTest::mf19 (s32); // COMPLIANT - exact type match
99
+ StaticMemberFunctionPointerTest::mf19 (
100
+ u16 ); // NON_COMPLIANT - widening not allowed
101
+ StaticMemberFunctionPointerTest::mf19 (u32 ); // COMPLIANT - exact type match
102
+
103
+ StaticMemberFunctionPointerTest::mf20 (
104
+ s16); // COMPLIANT - widening of id-expression
105
+ StaticMemberFunctionPointerTest::mf20 (s32); // COMPLIANT - exact type match
106
+ StaticMemberFunctionPointerTest::mf20 (u16 ); // NON_COMPLIANT
107
+ StaticMemberFunctionPointerTest::mf20 (u32 ); // NON_COMPLIANT
108
+ }
109
+
110
+ // Test member data pointers - not function calls, but test assignment to them
111
+ struct MemberDataPointerTest {
112
+ std::int64_t m1;
113
+ std::int64_t m2 : 10 ;
114
+ };
115
+
116
+ void test_member_data_pointers () {
117
+ MemberDataPointerTest l1;
118
+
119
+ // Member data pointer assignments - follow normal assignment rules
120
+ std::int64_t MemberDataPointerTest::*l2 = &MemberDataPointerTest::m1;
121
+
122
+ l1.*l2 = s16; // COMPLIANT - widening conversion allowed
123
+ l1.*l2 = s32; // COMPLIANT - widening conversion allowed
124
+ l1.*l2 = s64; // COMPLIANT
125
+ l1.*l2 = u16 ; // NON_COMPLIANT - signedness violation
126
+ l1.*l2 = u32 ; // NON_COMPLIANT - different signedness/size
127
+ l1.*l2 = u64 ; // NON_COMPLIANT - different signedness
128
+ }
0 commit comments