We need to use uintptr_t, not uint64_t. getAddressOfPointer returns a pointer to the Ptr field. When dereferenced on a 32-bit big endian platform, this will be the first (invalid) 32 bits, not the actual 32 bits containing the pointer value. This leads to bad things. Ref: #1255 Upstream-URL: https://github.com/llvm/llvm-project/issues/111993 --- clang/include/clang/AST/ExternalASTSource.h.old 2024-06-15 17:21:32.000000000 +0000 +++ clang/include/clang/AST/ExternalASTSource.h 2024-10-10 16:54:58.013411406 +0000 @@ -326,25 +326,25 @@ /// /// If the low bit is clear, a pointer to the AST node. If the low /// bit is set, the upper 63 bits are the offset. - mutable uint64_t Ptr = 0; + mutable uintptr_t Ptr = 0; public: LazyOffsetPtr() = default; - explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast(Ptr)) {} + explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast(Ptr)) {} - explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { - assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); + explicit LazyOffsetPtr(uintptr_t Offset) : Ptr((Offset << 1) | 0x01) { + assert((Offset << 1 >> 1) == Offset && "Offsets must fit in addressable bits"); if (Offset == 0) Ptr = 0; } LazyOffsetPtr &operator=(T *Ptr) { - this->Ptr = reinterpret_cast(Ptr); + this->Ptr = reinterpret_cast(Ptr); return *this; } - LazyOffsetPtr &operator=(uint64_t Offset) { - assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); + LazyOffsetPtr &operator=(uintptr_t Offset) { + assert((Offset << 1 >> 1) == Offset && "Offsets must fit in addressable bits"); if (Offset == 0) Ptr = 0; else @@ -375,7 +375,7 @@ if (isOffset()) { assert(Source && "Cannot deserialize a lazy pointer without an AST source"); - Ptr = reinterpret_cast((Source->*Get)(Ptr >> 1)); + Ptr = reinterpret_cast((Source->*Get)(Ptr >> 1)); } return reinterpret_cast(Ptr); }