Skip to content

Commit 72fb188

Browse files
authored
[clang][Interp] Handle Pointer::toAPValue() for expr bases (llvm#101937)
No reason to return early for them anymore.
1 parent 1fec981 commit 72fb188

File tree

3 files changed

+36
-5
lines changed

3 files changed

+36
-5
lines changed

clang/lib/AST/Interp/Pointer.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "MemberPointer.h"
1717
#include "PrimType.h"
1818
#include "Record.h"
19+
#include "clang/AST/ExprCXX.h"
1920
#include "clang/AST/RecordLayout.h"
2021

2122
using namespace clang;
@@ -155,12 +156,32 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
155156
APValue::LValueBase Base;
156157
if (const auto *VD = Desc->asValueDecl())
157158
Base = VD;
158-
else if (const auto *E = Desc->asExpr())
159-
Base = E;
160-
else
159+
else if (const auto *E = Desc->asExpr()) {
160+
// Create a DynamicAlloc base of the right type.
161+
if (const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
162+
QualType AllocatedType;
163+
if (NewExpr->isArray()) {
164+
assert(Desc->isArray());
165+
APInt ArraySize(64, static_cast<uint64_t>(Desc->getNumElems()),
166+
/*IsSigned=*/false);
167+
AllocatedType =
168+
ASTCtx.getConstantArrayType(NewExpr->getAllocatedType(), ArraySize,
169+
nullptr, ArraySizeModifier::Normal, 0);
170+
} else {
171+
AllocatedType = NewExpr->getAllocatedType();
172+
}
173+
// FIXME: Suboptimal counting of dynamic allocations. Move this to Context
174+
// or InterpState?
175+
static int ReportedDynamicAllocs = 0;
176+
DynamicAllocLValue DA(ReportedDynamicAllocs++);
177+
Base = APValue::LValueBase::getDynamicAlloc(DA, AllocatedType);
178+
} else {
179+
Base = E;
180+
}
181+
} else
161182
llvm_unreachable("Invalid allocation type");
162183

163-
if (isUnknownSizeArray() || Desc->asExpr())
184+
if (isUnknownSizeArray())
164185
return APValue(Base, CharUnits::Zero(), Path,
165186
/*IsOnePastEnd=*/isOnePastEnd(), /*IsNullPtr=*/false);
166187

clang/test/AST/Interp/codegen.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ namespace BaseClassOffsets {
3232
B* b = &c;
3333
}
3434

35+
namespace ExprBase {
36+
struct A { int n; };
37+
struct B { int n; };
38+
struct C : A, B {};
39+
40+
extern const int &&t = ((B&&)C{}).n;
41+
// CHECK: @_ZGRN8ExprBase1tE_ = internal global {{.*}} zeroinitializer,
42+
// CHECK: @_ZN8ExprBase1tE = constant ptr {{.*}} @_ZGRN8ExprBase1tE_, {{.*}} 8
43+
}
44+
3545
namespace reinterpretcast {
3646
const unsigned int n = 1234;
3747
extern const int &s = reinterpret_cast<const int&>(n);

clang/test/AST/Interp/new-delete.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ namespace delete_random_things {
358358
// both-note {{delete of pointer to subobject }}
359359
static_assert((delete (new int + 1), true)); // both-error {{}} \
360360
// ref-note {{delete of pointer '&{*new int#0} + 1' that does not point to complete object}} \
361-
// expected-note {{delete of pointer '&new int + 1' that does not point to complete object}}
361+
// expected-note {{delete of pointer '&{*new int#1} + 1' that does not point to complete object}}
362362
static_assert((delete[] (new int[3] + 1), true)); // both-error {{}} \
363363
// both-note {{delete of pointer to subobject}}
364364
static_assert((delete &(int&)(int&&)0, true)); // both-error {{}} \

0 commit comments

Comments
 (0)