Skip to content

Commit 1f4c018

Browse files
author
git apple-llvm automerger
committed
Merge commit 'e541aa5ff994' from llvm.org/release/19.x into stable/20240723
2 parents ef79c35 + e541aa5 commit 1f4c018

File tree

1 file changed

+35
-13
lines changed

1 file changed

+35
-13
lines changed

clang/include/clang/AST/ExternalASTSource.h

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
#include "llvm/ADT/SmallVector.h"
2626
#include "llvm/ADT/iterator.h"
2727
#include "llvm/Support/PointerLikeTypeTraits.h"
28+
#include <algorithm>
2829
#include <cassert>
2930
#include <cstddef>
3031
#include <cstdint>
3132
#include <iterator>
33+
#include <new>
3234
#include <optional>
3335
#include <utility>
3436

@@ -331,45 +333,65 @@ struct LazyOffsetPtr {
331333
///
332334
/// If the low bit is clear, a pointer to the AST node. If the low
333335
/// bit is set, the upper 63 bits are the offset.
334-
mutable uint64_t Ptr = 0;
336+
static constexpr size_t DataSize = std::max(sizeof(uint64_t), sizeof(T *));
337+
alignas(uint64_t) alignas(T *) mutable unsigned char Data[DataSize] = {};
338+
339+
unsigned char GetLSB() const {
340+
return Data[llvm::sys::IsBigEndianHost ? DataSize - 1 : 0];
341+
}
342+
343+
template <typename U> U &As(bool New) const {
344+
unsigned char *Obj =
345+
Data + (llvm::sys::IsBigEndianHost ? DataSize - sizeof(U) : 0);
346+
if (New)
347+
return *new (Obj) U;
348+
return *std::launder(reinterpret_cast<U *>(Obj));
349+
}
350+
351+
T *&GetPtr() const { return As<T *>(false); }
352+
uint64_t &GetU64() const { return As<uint64_t>(false); }
353+
void SetPtr(T *Ptr) const { As<T *>(true) = Ptr; }
354+
void SetU64(uint64_t U64) const { As<uint64_t>(true) = U64; }
335355

336356
public:
337357
LazyOffsetPtr() = default;
338-
explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) {}
358+
explicit LazyOffsetPtr(T *Ptr) : Data() { SetPtr(Ptr); }
339359

340-
explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
360+
explicit LazyOffsetPtr(uint64_t Offset) : Data() {
341361
assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
342362
if (Offset == 0)
343-
Ptr = 0;
363+
SetPtr(nullptr);
364+
else
365+
SetU64((Offset << 1) | 0x01);
344366
}
345367

346368
LazyOffsetPtr &operator=(T *Ptr) {
347-
this->Ptr = reinterpret_cast<uint64_t>(Ptr);
369+
SetPtr(Ptr);
348370
return *this;
349371
}
350372

351373
LazyOffsetPtr &operator=(uint64_t Offset) {
352374
assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
353375
if (Offset == 0)
354-
Ptr = 0;
376+
SetPtr(nullptr);
355377
else
356-
Ptr = (Offset << 1) | 0x01;
378+
SetU64((Offset << 1) | 0x01);
357379

358380
return *this;
359381
}
360382

361383
/// Whether this pointer is non-NULL.
362384
///
363385
/// This operation does not require the AST node to be deserialized.
364-
explicit operator bool() const { return Ptr != 0; }
386+
explicit operator bool() const { return isOffset() || GetPtr() != nullptr; }
365387

366388
/// Whether this pointer is non-NULL.
367389
///
368390
/// This operation does not require the AST node to be deserialized.
369-
bool isValid() const { return Ptr != 0; }
391+
bool isValid() const { return isOffset() || GetPtr() != nullptr; }
370392

371393
/// Whether this pointer is currently stored as an offset.
372-
bool isOffset() const { return Ptr & 0x01; }
394+
bool isOffset() const { return GetLSB() & 0x01; }
373395

374396
/// Retrieve the pointer to the AST node that this lazy pointer points to.
375397
///
@@ -380,17 +402,17 @@ struct LazyOffsetPtr {
380402
if (isOffset()) {
381403
assert(Source &&
382404
"Cannot deserialize a lazy pointer without an AST source");
383-
Ptr = reinterpret_cast<uint64_t>((Source->*Get)(OffsT(Ptr >> 1)));
405+
SetPtr((Source->*Get)(OffsT(GetU64() >> 1)));
384406
}
385-
return reinterpret_cast<T*>(Ptr);
407+
return GetPtr();
386408
}
387409

388410
/// Retrieve the address of the AST node pointer. Deserializes the pointee if
389411
/// necessary.
390412
T **getAddressOfPointer(ExternalASTSource *Source) const {
391413
// Ensure the integer is in pointer form.
392414
(void)get(Source);
393-
return reinterpret_cast<T**>(&Ptr);
415+
return &GetPtr();
394416
}
395417
};
396418

0 commit comments

Comments
 (0)