diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -225,6 +225,10 @@ return Offset - Base - Adjust; } + /// Whether this array refers to an array, but not + /// to the first element. + bool isArrayRoot() const { return inArray() && Offset == Base; } + /// Checks if the innermost field is an array. bool inArray() const { return getFieldDesc()->IsArray; } /// Checks if the structure is a primitive array. @@ -306,6 +310,10 @@ /// Dereferences the pointer, if it's live. template T &deref() const { assert(isLive() && "Invalid pointer"); + if (isArrayRoot()) + return *reinterpret_cast(Pointee->rawData() + Base + + sizeof(InitMap *)); + return *reinterpret_cast(Pointee->rawData() + Offset); } diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -42,6 +42,21 @@ return *(Arr + index); } +constexpr int derefPtr(const int *d) { + return *d; +} +static_assert(derefPtr(data) == 5, ""); + +constexpr int storePtr() { + int b[] = {1,2,3,4}; + int *c = b; + + *c = 4; + return *c; +} +static_assert(storePtr() == 4, ""); + + static_assert(getElement(data, 1) == 4, ""); static_assert(getElement(data, 4) == 1, "");