forked from google/boringssl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompiler_test.cc
175 lines (147 loc) · 6.89 KB
/
compiler_test.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/* Copyright (c) 2017, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <limits.h>
#include <stdint.h>
#include <type_traits>
#include <gtest/gtest.h>
#include "test/test_util.h"
template <typename T>
static void CheckRepresentation(T value) {
SCOPED_TRACE(value);
// Convert to the corresponding two's-complement unsigned value. We use an
// unsigned value so the right-shift below has defined value. Right-shifts of
// negative numbers in C are implementation defined.
//
// If |T| is already unsigned, this is a no-op, as desired.
//
// If |T| is signed, conversion to unsigned is defined to repeatedly add or
// subtract (numerically, not within |T|) one more than the unsigned type's
// maximum value until it fits (this must be a power of two). This is the
// conversion we want.
using UnsignedT = typename std::make_unsigned<T>::type;
UnsignedT value_u = static_cast<UnsignedT>(value);
EXPECT_EQ(sizeof(UnsignedT), sizeof(T));
// Integers must be little-endian.
uint8_t expected[sizeof(UnsignedT)];
for (size_t i = 0; i < sizeof(UnsignedT); i++) {
expected[i] = static_cast<uint8_t>(value_u);
// Divide instead of right-shift to appease compilers that warn if |T| is a
// char. The explicit cast is also needed to appease MSVC if integer
// promotion happened.
value_u = static_cast<UnsignedT>(value_u / 256);
}
EXPECT_EQ(0u, value_u);
// Check that |value| has the expected representation.
EXPECT_EQ(Bytes(expected),
Bytes(reinterpret_cast<const uint8_t *>(&value), sizeof(value)));
}
TEST(CompilerTest, IntegerRepresentation) {
EXPECT_EQ(8, CHAR_BIT);
EXPECT_EQ(0xff, static_cast<int>(UCHAR_MAX));
// uint8_t is assumed to be unsigned char. I.e., casting to uint8_t should be
// as good as unsigned char for strict aliasing purposes.
uint8_t u8 = 0;
unsigned char *ptr = &u8;
(void)ptr;
// Sized integers have the expected size.
EXPECT_EQ(1u, sizeof(uint8_t));
EXPECT_EQ(2u, sizeof(uint16_t));
EXPECT_EQ(4u, sizeof(uint32_t));
EXPECT_EQ(8u, sizeof(uint64_t));
// size_t does not exceed uint64_t.
EXPECT_LE(sizeof(size_t), 8u);
// int must be 32-bit or larger.
EXPECT_LE(0x7fffffff, INT_MAX);
EXPECT_LE(0xffffffffu, UINT_MAX);
CheckRepresentation(static_cast<signed char>(127));
CheckRepresentation(static_cast<signed char>(1));
CheckRepresentation(static_cast<signed char>(0));
CheckRepresentation(static_cast<signed char>(-1));
CheckRepresentation(static_cast<signed char>(-42));
CheckRepresentation(static_cast<signed char>(-128));
CheckRepresentation(static_cast<int>(INT_MAX));
CheckRepresentation(static_cast<int>(0x12345678));
CheckRepresentation(static_cast<int>(1));
CheckRepresentation(static_cast<int>(0));
CheckRepresentation(static_cast<int>(-1));
CheckRepresentation(static_cast<int>(-0x12345678));
CheckRepresentation(static_cast<int>(INT_MIN));
CheckRepresentation(static_cast<unsigned>(UINT_MAX));
CheckRepresentation(static_cast<unsigned>(0x12345678));
CheckRepresentation(static_cast<unsigned>(1));
CheckRepresentation(static_cast<unsigned>(0));
CheckRepresentation(static_cast<long>(LONG_MAX));
CheckRepresentation(static_cast<long>(0x12345678));
CheckRepresentation(static_cast<long>(1));
CheckRepresentation(static_cast<long>(0));
CheckRepresentation(static_cast<long>(-1));
CheckRepresentation(static_cast<long>(-0x12345678));
CheckRepresentation(static_cast<long>(LONG_MIN));
CheckRepresentation(static_cast<unsigned long>(ULONG_MAX));
CheckRepresentation(static_cast<unsigned long>(0x12345678));
CheckRepresentation(static_cast<unsigned long>(1));
CheckRepresentation(static_cast<unsigned long>(0));
CheckRepresentation(static_cast<int16_t>(0x7fff));
CheckRepresentation(static_cast<int16_t>(0x1234));
CheckRepresentation(static_cast<int16_t>(1));
CheckRepresentation(static_cast<int16_t>(0));
CheckRepresentation(static_cast<int16_t>(-1));
CheckRepresentation(static_cast<int16_t>(-0x7fff - 1));
CheckRepresentation(static_cast<uint16_t>(0xffff));
CheckRepresentation(static_cast<uint16_t>(0x1234));
CheckRepresentation(static_cast<uint16_t>(1));
CheckRepresentation(static_cast<uint16_t>(0));
CheckRepresentation(static_cast<int32_t>(0x7fffffff));
CheckRepresentation(static_cast<int32_t>(0x12345678));
CheckRepresentation(static_cast<int32_t>(1));
CheckRepresentation(static_cast<int32_t>(0));
CheckRepresentation(static_cast<int32_t>(-1));
CheckRepresentation(static_cast<int32_t>(-0x7fffffff - 1));
CheckRepresentation(static_cast<uint32_t>(0xffffffff));
CheckRepresentation(static_cast<uint32_t>(0x12345678));
CheckRepresentation(static_cast<uint32_t>(1));
CheckRepresentation(static_cast<uint32_t>(0));
CheckRepresentation(static_cast<int64_t>(0x7fffffffffffffff));
CheckRepresentation(static_cast<int64_t>(0x123456789abcdef0));
CheckRepresentation(static_cast<int64_t>(1));
CheckRepresentation(static_cast<int64_t>(0));
CheckRepresentation(static_cast<int64_t>(-1));
CheckRepresentation(static_cast<int64_t>(-0x7fffffffffffffff - 1));
CheckRepresentation(static_cast<uint64_t>(0xffffffffffffffff));
CheckRepresentation(static_cast<uint64_t>(0x12345678abcdef0));
CheckRepresentation(static_cast<uint64_t>(1));
CheckRepresentation(static_cast<uint64_t>(0));
}
TEST(CompilerTest, PointerRepresentation) {
// Converting pointers to integers and doing arithmetic on those values are
// both defined. Converting those values back into pointers is undefined,
// but, for aliasing checks, we require that the implementation-defined
// result of that computation commutes with pointer arithmetic.
char chars[256];
for (size_t i = 0; i < sizeof(chars); i++) {
EXPECT_EQ(reinterpret_cast<uintptr_t>(chars) + i,
reinterpret_cast<uintptr_t>(chars + i));
}
int ints[256];
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(ints); i++) {
EXPECT_EQ(reinterpret_cast<uintptr_t>(ints) + i * sizeof(int),
reinterpret_cast<uintptr_t>(ints + i));
}
// nullptr must be represented by all zeros in memory. This is necessary so
// structs may be initialized by memset(0).
int *null = nullptr;
uint8_t bytes[sizeof(null)] = {0};
EXPECT_EQ(Bytes(bytes),
Bytes(reinterpret_cast<uint8_t *>(&null), sizeof(null)));
}