From ad2fb01cb68dc17594d2a923da90f5e01e127cdf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timm=20B=C3=A4der?= Date: Mon, 31 Oct 2022 15:48:15 +0100 Subject: [PATCH] [clang][Interp] Fix dereferencing arrays with no offset applied A pointer to an array and a pointer to the first element of the array are not the same in the interpreter, so handle this specially in deref(). Differential Revision: https://reviews.llvm.org/D137082 --- clang/lib/AST/Interp/Pointer.h | 8 ++++++++ clang/test/AST/Interp/arrays.cpp | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index 1462d01..489884a 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -225,6 +225,10 @@ public: 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 @@ public: /// 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 index cd8d374..3c0eaef 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -42,6 +42,21 @@ constexpr int getElement(const int *Arr, int index) { 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, ""); -- 2.7.4