1+ #include < cerrno>
2+ #include < cstdint>
3+ #include < optional>
4+ #include < string>
5+
6+ void errnoSettingFunction ();
7+ void handleError ();
8+ void f ();
9+
10+ #define OK 0
11+ #define CUSTOM_ERROR 42
12+ #define ZERO_MACRO 0
13+
14+ void test_literal_zero_assignment () {
15+ errno = 0 ; // COMPLIANT
16+ }
17+
18+ void test_different_zero_literal_formats () {
19+ errno = 0 ; // COMPLIANT - decimal zero literal
20+ errno = 0x0 ; // COMPLIANT - hexadecimal zero literal
21+ errno = 00 ; // COMPLIANT - octal zero literal
22+ errno = 0b0 ; // COMPLIANT - binary zero literal
23+ }
24+
25+ void test_floating_point_zero_literals () {
26+ errno = 0.0 ; // NON_COMPLIANT - floating point literal, not integer literal
27+ errno = 0 .0f ; // NON_COMPLIANT - floating point literal, not integer literal
28+ }
29+
30+ void test_non_zero_literal_assignment () {
31+ errno = 1 ; // NON_COMPLIANT
32+ errno = 42 ; // NON_COMPLIANT
33+ errno = -1 ; // NON_COMPLIANT
34+ }
35+
36+ void test_macro_assignments () {
37+ errno = OK; // COMPLIANT - expands to literal 0
38+ errno = ZERO_MACRO; // COMPLIANT - expands to literal 0
39+ errno = CUSTOM_ERROR; // NON_COMPLIANT - expands to non-zero literal
40+ }
41+
42+ void test_variable_assignments () {
43+ std::uint32_t l1 = 0 ;
44+ const std::uint32_t l2 = 0 ;
45+ constexpr std::uint32_t l3 = 0 ;
46+ std::uint32_t l4 = 42 ;
47+ const std::uint32_t l5 = 42 ;
48+
49+ errno = l1; // NON_COMPLIANT - variable, not literal
50+ errno = l2; // NON_COMPLIANT - constant variable, not literal
51+ errno = l3; // NON_COMPLIANT - constexpr variable, not literal
52+ errno = l4; // NON_COMPLIANT - variable with non-zero value
53+ errno = l5; // NON_COMPLIANT - constant variable with non-zero value
54+ }
55+
56+ void test_standard_error_macros () {
57+ errno = EINVAL; // NON_COMPLIANT - standard error macro
58+ errno = ERANGE; // NON_COMPLIANT - standard error macro
59+ errno = EDOM; // NON_COMPLIANT - standard error macro
60+ }
61+
62+ void test_expressions () {
63+ errno = 0 + 0 ; // NON_COMPLIANT - expression, not literal
64+ errno = 1 - 1 ; // NON_COMPLIANT - expression, not literal
65+ errno = 0 * 5 ; // NON_COMPLIANT - expression, not literal
66+ errno = sizeof (int ) - sizeof (int ); // NON_COMPLIANT - expression, not literal
67+ }
68+
69+ void test_compound_assignments () {
70+ errno = 5 ; // NON_COMPLIANT - initial assignment to non-zero value
71+ errno += 0 ; // NON_COMPLIANT - compound assignment, not simple assignment
72+ errno -= 5 ; // NON_COMPLIANT - compound assignment, not simple assignment
73+ errno *= 0 ; // NON_COMPLIANT - compound assignment, not simple assignment
74+ errno /= 1 ; // NON_COMPLIANT - compound assignment, not simple assignment
75+ }
76+
77+ void test_function_return_values () {
78+ auto l1 = []() { return 0 ; };
79+ auto l2 = []() { return 42 ; };
80+
81+ errno = l1 (); // NON_COMPLIANT - function return value, not literal
82+ errno = l2 (); // NON_COMPLIANT - function return value, not literal
83+ }
84+
85+ void test_cast_expressions () {
86+ errno = static_cast <int >(0 ); // NON_COMPLIANT - cast expression
87+ errno = static_cast <int >(0.0 ); // NON_COMPLIANT - cast expression
88+ errno = (int )0 ; // NON_COMPLIANT - C-style cast
89+ errno = int (0 ); // NON_COMPLIANT - functional cast
90+ }
91+
92+ void test_reading_errno_is_allowed () {
93+ std::uint32_t l1 = errno; // COMPLIANT - reading errno is allowed
94+ if (errno != 0 ) { // COMPLIANT - reading errno is allowed
95+ handleError ();
96+ }
97+
98+ errnoSettingFunction ();
99+ std::uint32_t l2 = 0 ;
100+ if (errno != l2) { // COMPLIANT - reading errno is allowed
101+ handleError ();
102+ }
103+ }
104+
105+ void test_pointer_and_null_assignments () {
106+ label:
107+ static const int x = 0 ;
108+ errno = reinterpret_cast <int >(nullptr ); // NON_COMPLIANT - nullptr is
109+ // not an integer literal
110+ errno = reinterpret_cast <int >(&x); // NON_COMPLIANT - pointer cast to integer
111+ errno = reinterpret_cast <int >(&f); // NON_COMPLIANT - pointer cast to
112+ // integer
113+ errno = reinterpret_cast <int >(&&label); // NON_COMPLIANT - pointer
114+ // cast to integer
115+ errno = NULL ; // NON_COMPLIANT[FALSE_NEGATIVE] - NULL may expand to 0 but not
116+ // literal
117+ }
118+
119+ void test_character_literals () {
120+ errno = ' \0 ' ; // NON_COMPLIANT[FALSE_NEGATIVE] - character literal, not
121+ // integer literal
122+ errno = ' 0' ; // NON_COMPLIANT - character '0' has value 48
123+ }
124+
125+ void test_boolean_literals () {
126+ errno = false ; // NON_COMPLIANT[FALSE_NEGATIVE] - boolean literal, not integer
127+ // literal
128+ errno = true ; // NON_COMPLIANT - boolean literal with non-zero value
129+ }
0 commit comments