Skip to content

Commit c385015

Browse files
committed
Fix semantic issues with unions and undefined behavior.
1 parent 3c16f84 commit c385015

File tree

1 file changed

+24
-24
lines changed

1 file changed

+24
-24
lines changed

common/bitfield.h

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,22 @@
1111

1212
//---------------------------------------------------------
1313
// BitFieldMember<>: Used internally by ADD_BITFIELD_MEMBER macro.
14+
// All members are public to simplify compliance with sections 9.0.7 and
15+
// 9.5.1 of the C++11 standard, thereby avoiding undefined behavior.
1416
//---------------------------------------------------------
15-
template <class T, int Offset, int Bits>
16-
class BitFieldMember
17+
template <typename T, int Offset, int Bits>
18+
struct BitFieldMember
1719
{
18-
private:
1920
static_assert(Offset + Bits <= (int) sizeof(T) * 8, "Member exceeds bitfield boundaries");
2021
static_assert(Bits < (int) sizeof(T) * 8, "Can't fill entire bitfield with one member");
2122

2223
static const T Maximum = (T(1) << Bits) - 1;
2324
static const T Mask = Maximum << Offset;
24-
25-
T value;
26-
27-
public:
2825
T maximum() const { return Maximum; }
2926
T one() const { return T(1) << Offset; }
3027

28+
T value;
29+
3130
operator T() const
3231
{
3332
return (value >> Offset) & Maximum;
@@ -63,15 +62,18 @@ class BitFieldMember
6362

6463
//---------------------------------------------------------
6564
// BitFieldArray<>: Used internally by ADD_BITFIELD_ARRAY macro.
65+
// All members are public to simplify compliance with sections 9.0.7 and
66+
// 9.5.1 of the C++11 standard, thereby avoiding undefined behavior.
6667
//---------------------------------------------------------
67-
template <class T, int BaseOffset, int BitsPerItem, int NumItems>
68-
class BitFieldArray
68+
template <typename T, int BaseOffset, int BitsPerItem, int NumItems>
69+
struct BitFieldArray
6970
{
70-
private:
7171
static_assert(BaseOffset + BitsPerItem * NumItems <= (int) sizeof(T) * 8, "Array exceeds bitfield boundaries");
7272
static_assert(BitsPerItem < (int) sizeof(T) * 8, "Can't fill entire bitfield with one array element");
7373

7474
static const T Maximum = (T(1) << BitsPerItem) - 1;
75+
T maximum() const { return Maximum; }
76+
int numItems() const { return NumItems; }
7577

7678
T value;
7779

@@ -117,10 +119,6 @@ class BitFieldArray
117119
Element& operator--(int) { return *this -= 1; } // postfix form
118120
};
119121

120-
public:
121-
T maximum() const { return Maximum; }
122-
int numItems() const { return NumItems; }
123-
124122
Element operator[](int i)
125123
{
126124
assert(i >= 0 && i < NumItems); // array index must be in range
@@ -138,27 +136,29 @@ class BitFieldArray
138136
//---------------------------------------------------------
139137
// Bitfield definition macros.
140138
// For usage examples, see RWLock and LockReducedDiningPhilosophers.
139+
// All members are public to simplify compliance with sections 9.0.7 and
140+
// 9.5.1 of the C++11 standard, thereby avoiding undefined behavior.
141141
//---------------------------------------------------------
142142
#define BEGIN_BITFIELD_TYPE(typeName, T) \
143143
union typeName \
144144
{ \
145-
private: \
146-
typedef T _IntType; \
147-
T value; \
148-
public: \
149-
typeName(T v = 0) : value(v) {} \
150-
typeName& operator=(T v) { value = v; return *this; } \
151-
operator T&() { return value; } \
152-
operator T() const { return value; }
145+
struct Wrapper { T value; }; \
146+
Wrapper wrapper; \
147+
typeName(T v = 0) { wrapper.value = v; } \
148+
typeName& operator=(T v) { wrapper.value = v; return *this; } \
149+
operator T&() { return wrapper.value; } \
150+
operator T() const { return wrapper.value; } \
151+
typedef T StorageType;
153152

154153
#define ADD_BITFIELD_MEMBER(memberName, offset, bits) \
155-
BitFieldMember<_IntType, offset, bits> memberName;
154+
BitFieldMember<StorageType, offset, bits> memberName;
156155

157156
#define ADD_BITFIELD_ARRAY(memberName, offset, bits, numItems) \
158-
BitFieldArray<_IntType, offset, bits, numItems> memberName;
157+
BitFieldArray<StorageType, offset, bits, numItems> memberName;
159158

160159
#define END_BITFIELD_TYPE() \
161160
};
162161

163162

164163
#endif // __CPP11OM_BITFIELD_H__
164+

0 commit comments

Comments
 (0)