25
25
#include " llvm/ADT/SmallVector.h"
26
26
#include " llvm/ADT/iterator.h"
27
27
#include " llvm/Support/PointerLikeTypeTraits.h"
28
+ #include < algorithm>
28
29
#include < cassert>
29
30
#include < cstddef>
30
31
#include < cstdint>
31
32
#include < iterator>
33
+ #include < new>
32
34
#include < optional>
33
35
#include < utility>
34
36
@@ -326,45 +328,65 @@ struct LazyOffsetPtr {
326
328
// /
327
329
// / If the low bit is clear, a pointer to the AST node. If the low
328
330
// / bit is set, the upper 63 bits are the offset.
329
- mutable uint64_t Ptr = 0 ;
331
+ static constexpr size_t DataSize = std::max(sizeof (uint64_t ), sizeof (T *));
332
+ alignas (uint64_t ) alignas(T *) mutable unsigned char Data[DataSize] = {};
333
+
334
+ unsigned char GetLSB () const {
335
+ return Data[llvm::sys::IsBigEndianHost ? DataSize - 1 : 0 ];
336
+ }
337
+
338
+ template <typename U> U &As (bool New) const {
339
+ unsigned char *Obj =
340
+ Data + (llvm::sys::IsBigEndianHost ? DataSize - sizeof (U) : 0 );
341
+ if (New)
342
+ return *new (Obj) U;
343
+ return *std::launder (reinterpret_cast <U *>(Obj));
344
+ }
345
+
346
+ T *&GetPtr () const { return As<T *>(false ); }
347
+ uint64_t &GetU64 () const { return As<uint64_t >(false ); }
348
+ void SetPtr (T *Ptr ) const { As<T *>(true ) = Ptr ; }
349
+ void SetU64 (uint64_t U64) const { As<uint64_t >(true ) = U64; }
330
350
331
351
public:
332
352
LazyOffsetPtr () = default;
333
- explicit LazyOffsetPtr (T *Ptr ) : Ptr( reinterpret_cast < uint64_t > (Ptr )) { }
353
+ explicit LazyOffsetPtr (T *Ptr ) : Data() { SetPtr (Ptr ); }
334
354
335
- explicit LazyOffsetPtr (uint64_t Offset) : Ptr((Offset << 1 ) | 0x01 ) {
355
+ explicit LazyOffsetPtr (uint64_t Offset) : Data( ) {
336
356
assert ((Offset << 1 >> 1 ) == Offset && " Offsets must require < 63 bits" );
337
357
if (Offset == 0 )
338
- Ptr = 0 ;
358
+ SetPtr (nullptr );
359
+ else
360
+ SetU64 ((Offset << 1 ) | 0x01 );
339
361
}
340
362
341
363
LazyOffsetPtr &operator =(T *Ptr ) {
342
- this -> Ptr = reinterpret_cast < uint64_t > (Ptr );
364
+ SetPtr (Ptr );
343
365
return *this ;
344
366
}
345
367
346
368
LazyOffsetPtr &operator =(uint64_t Offset) {
347
369
assert ((Offset << 1 >> 1 ) == Offset && " Offsets must require < 63 bits" );
348
370
if (Offset == 0 )
349
- Ptr = 0 ;
371
+ SetPtr ( nullptr ) ;
350
372
else
351
- Ptr = ( Offset << 1 ) | 0x01 ;
373
+ SetU64 (( Offset << 1 ) | 0x01 ) ;
352
374
353
375
return *this ;
354
376
}
355
377
356
378
// / Whether this pointer is non-NULL.
357
379
// /
358
380
// / This operation does not require the AST node to be deserialized.
359
- explicit operator bool () const { return Ptr != 0 ; }
381
+ explicit operator bool () const { return isOffset () || GetPtr () != nullptr ; }
360
382
361
383
// / Whether this pointer is non-NULL.
362
384
// /
363
385
// / This operation does not require the AST node to be deserialized.
364
- bool isValid () const { return Ptr != 0 ; }
386
+ bool isValid () const { return isOffset () || GetPtr () != nullptr ; }
365
387
366
388
// / Whether this pointer is currently stored as an offset.
367
- bool isOffset () const { return Ptr & 0x01 ; }
389
+ bool isOffset () const { return GetLSB () & 0x01 ; }
368
390
369
391
// / Retrieve the pointer to the AST node that this lazy pointer points to.
370
392
// /
@@ -375,17 +397,17 @@ struct LazyOffsetPtr {
375
397
if (isOffset ()) {
376
398
assert (Source &&
377
399
" Cannot deserialize a lazy pointer without an AST source" );
378
- Ptr = reinterpret_cast < uint64_t > ((Source->*Get)(OffsT (Ptr >> 1 )));
400
+ SetPtr ((Source->*Get)(OffsT (GetU64 () >> 1 )));
379
401
}
380
- return reinterpret_cast <T*>( Ptr );
402
+ return GetPtr ( );
381
403
}
382
404
383
405
// / Retrieve the address of the AST node pointer. Deserializes the pointee if
384
406
// / necessary.
385
407
T **getAddressOfPointer (ExternalASTSource *Source) const {
386
408
// Ensure the integer is in pointer form.
387
409
(void )get (Source);
388
- return reinterpret_cast <T**>(& Ptr );
410
+ return & GetPtr ( );
389
411
}
390
412
};
391
413
0 commit comments