1 : /*
2 : * Copyright 2010 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 :
8 : #include <stdio.h>
9 :
10 : #include "native_client/src/include/portability.h"
11 : #include "native_client/src/include/checked_cast.h"
12 :
13 : #if NACL_WINDOWS
14 : extern "C" {
15 : int TestFFS();
16 :
17 : # ifdef _WIN64
18 : int TestTlsAccess();
19 : # endif
20 : }
21 : #endif
22 :
23 : using nacl::can_cast;
24 : using nacl::saturate_cast;
25 : using nacl::assert_cast;
26 :
27 :
28 : #ifdef DEBUG
29 : #define CHECK(current,expected)if((current) != (expected)) { \
30 : ++errors; \
31 : printf("ERROR: expected %d got %d\n", \
32 : static_cast<int>(expected), \
33 : static_cast<int>(current)); \
34 : } else { printf("SUCCESS: expected %d" \
35 : " got %d\n", \
36 : static_cast<int>(expected), \
37 : static_cast<int>(current)); \
38 : }
39 : #else
40 : #define CHECK(current,expected)if((current) != (expected)) { ++errors; }
41 : #endif
42 1 : int TestCheckedCastSaturate() {
43 1 : int errors = 0;
44 :
45 1 : uint32_t u32 = 0xffffffff;
46 1 : int32_t i32 = -0x12345678;
47 :
48 : uint8_t u8;
49 : int8_t i8;
50 :
51 1 : CHECK(can_cast<uint8_t>(u32), false);
52 1 : u8 = saturate_cast<uint8_t>(u32);
53 1 : CHECK(u8, 255);
54 :
55 1 : CHECK(can_cast<uint8_t>(i32), false);
56 1 : u8 = saturate_cast<uint8_t>(i32);
57 1 : CHECK(u8, 0);
58 :
59 1 : i8 = saturate_cast<int8_t>(u32);
60 1 : CHECK(i8, 127);
61 :
62 1 : i8 = saturate_cast<int8_t>(i32);
63 1 : CHECK(i8, -128);
64 :
65 1 : CHECK(can_cast<uint16_t>(u32), false);
66 1 : CHECK(can_cast<int32_t>(u32), false);
67 1 : CHECK(can_cast<uint32_t>(u32), true);
68 1 : return errors;
69 1 : }
70 :
71 0 : int TestCheckedCastFatal() {
72 0 : int errors = 0;
73 :
74 0 : uint32_t u32 = 0xffffffff;
75 0 : int32_t i32 = -0x12345678;
76 :
77 : uint8_t u8;
78 : int8_t i8;
79 :
80 0 : u8 = assert_cast<uint8_t>(u32);
81 0 : CHECK(u8, 255);
82 :
83 0 : u8 = assert_cast<uint8_t>(i32);
84 0 : CHECK(u8, 0);
85 :
86 0 : i8 = assert_cast<int8_t>(u32);
87 0 : CHECK(i8, 127);
88 :
89 0 : i8 = assert_cast<int8_t>(i32);
90 0 : CHECK(i8, -128);
91 :
92 0 : return errors;
93 0 : }
94 :
95 : template<int N>
96 : class intN_t {
97 : public:
98 : static const int bits = N;
99 : static const int max = ((1 << (bits - 1)) - 1);
100 : static const int min = -max - 1;
101 :
102 1 : intN_t() : overflow_(0), storage_(0) {}
103 :
104 1 : explicit intN_t(int32_t v) {
105 1 : storage_ = v;
106 1 : if (v > max || v < min) {
107 1 : overflow_ = 1;
108 1 : } else {
109 1 : overflow_ = 0;
110 : }
111 1 : }
112 :
113 1 : operator int() const { return storage_; }
114 :
115 1 : bool Overflow() const { return !!overflow_; }
116 :
117 : private:
118 : int32_t overflow_ : 2; // Mac compiler complains if this is 1 instead of 2
119 : int32_t storage_ : bits;
120 : };
121 :
122 : typedef intN_t<28> int28_t;
123 :
124 : namespace std {
125 : template<> struct numeric_limits<int28_t>
126 : : public numeric_limits<int> {
127 : static const bool is_specialized = true;
128 1 : static int28_t max() {return int28_t(int28_t::max);}
129 1 : static int28_t min() {return int28_t(int28_t::min);}
130 : // static const int digits = 28;
131 : };
132 : } // namespace std
133 :
134 1 : int TestCheckedCastUDT() {
135 1 : int32_t i32 = 0xf0000000;
136 1 : uint32_t u32 = 0xffffffff;
137 :
138 1 : int errors = 0;
139 :
140 1 : int28_t i28 = int28_t(0xffffffff);
141 1 : CHECK(i28.Overflow(), false);
142 :
143 1 : i28 = int28_t(0x80000000);
144 1 : CHECK(i28.Overflow(), true);
145 :
146 1 : CHECK(can_cast<int28_t>(i32), false);
147 1 : i28 = saturate_cast<int28_t>(i32);
148 1 : CHECK(i28.Overflow(), false);
149 1 : CHECK(i28, static_cast<int>(0xf8000000));
150 :
151 1 : i28 = saturate_cast<int28_t>(u32);
152 1 : CHECK(i28.Overflow(), false);
153 1 : CHECK(i28, static_cast<int>(0x07ffffff));
154 :
155 :
156 1 : return errors;
157 1 : }
158 :
159 : /******************************************************************************
160 : * main
161 : *****************************************************************************/
162 : int main(int ,
163 1 : char **) {
164 1 : int errors = 0;
165 :
166 1 : errors += TestCheckedCastSaturate();
167 1 : printf("---------- After TestCheckedSaturate errors = %d\n", errors);
168 1 : errors += TestCheckedCastUDT();
169 1 : printf("---------- After TestCheckedCastUDT errors = %d\n", errors);
170 :
171 : #if NACL_WINDOWS
172 : // this test ensures the validity of the assembly version of ffs()
173 1 : errors += TestFFS();
174 : #endif
175 :
176 1 : printf("---------- Final error count = %d\n", errors);
177 :
178 : #if NACL_WINDOWS && defined(_WIN64)
179 : errors += TestTlsAccess();
180 : #endif
181 :
182 1 : return errors;
183 1 : }
|