Skip to content

Commit df90df1

Browse files
committed
Memberpointers
1 parent 5c40db1 commit df90df1

26 files changed

+692
-29
lines changed

clang/lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ add_clang_library(clangAST
8787
Interp/Record.cpp
8888
Interp/Source.cpp
8989
Interp/State.cpp
90+
Interp/MemberPointer.cpp
9091
Interp/InterpShared.cpp
9192
ItaniumCXXABI.cpp
9293
ItaniumMangle.cpp

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 93 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,35 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
100100
return this->emitMemcpy(CE);
101101
}
102102

103+
case CK_DerivedToBaseMemberPointer: {
104+
assert(classifyPrim(CE->getType()) == PT_MemberPtr);
105+
assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr);
106+
const auto *FromMP = SubExpr->getType()->getAs<MemberPointerType>();
107+
const auto *ToMP = CE->getType()->getAs<MemberPointerType>();
108+
109+
unsigned DerivedOffset = collectBaseOffset(QualType(ToMP->getClass(), 0),
110+
QualType(FromMP->getClass(), 0));
111+
112+
if (!this->visit(SubExpr))
113+
return false;
114+
115+
return this->emitGetMemberPtrBasePop(DerivedOffset, CE);
116+
}
117+
118+
case CK_BaseToDerivedMemberPointer: {
119+
assert(classifyPrim(CE) == PT_MemberPtr);
120+
assert(classifyPrim(SubExpr) == PT_MemberPtr);
121+
const auto *FromMP = SubExpr->getType()->getAs<MemberPointerType>();
122+
const auto *ToMP = CE->getType()->getAs<MemberPointerType>();
123+
124+
unsigned DerivedOffset = collectBaseOffset(QualType(FromMP->getClass(), 0),
125+
QualType(ToMP->getClass(), 0));
126+
127+
if (!this->visit(SubExpr))
128+
return false;
129+
return this->emitGetMemberPtrBasePop(-DerivedOffset, CE);
130+
}
131+
103132
case CK_UncheckedDerivedToBase:
104133
case CK_DerivedToBase: {
105134
if (!this->visit(SubExpr))
@@ -187,7 +216,8 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
187216
return this->emitCastFloatingIntegral(*ToT, CE);
188217
}
189218

190-
case CK_NullToPointer: {
219+
case CK_NullToPointer:
220+
case CK_NullToMemberPointer: {
191221
if (DiscardResult)
192222
return true;
193223

@@ -326,7 +356,8 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
326356
return this->emitCast(*FromT, *ToT, CE);
327357
}
328358

329-
case CK_PointerToBoolean: {
359+
case CK_PointerToBoolean:
360+
case CK_MemberPointerToBoolean: {
330361
PrimType PtrT = classifyPrim(SubExpr->getType());
331362

332363
// Just emit p != nullptr for this.
@@ -534,8 +565,23 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
534565
BO->isComparisonOp())
535566
return this->emitComplexComparison(LHS, RHS, BO);
536567

537-
if (BO->isPtrMemOp())
538-
return this->visit(RHS);
568+
if (BO->isPtrMemOp()) {
569+
if (!this->visit(LHS))
570+
return false;
571+
572+
if (!this->visit(RHS))
573+
return false;
574+
575+
if (!this->emitToMemberPtr(BO))
576+
return false;
577+
578+
if (classifyPrim(BO) == PT_MemberPtr)
579+
return true;
580+
581+
if (!this->emitCastMemberPtrPtr(BO))
582+
return false;
583+
return DiscardResult ? this->emitPopPtr(BO) : true;
584+
}
539585

540586
// Typecheck the args.
541587
std::optional<PrimType> LT = classify(LHS->getType());
@@ -2756,6 +2802,8 @@ bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
27562802
return this->emitNullPtr(nullptr, E);
27572803
case PT_FnPtr:
27582804
return this->emitNullFnPtr(nullptr, E);
2805+
case PT_MemberPtr:
2806+
return this->emitNullMemberPtr(nullptr, E);
27592807
case PT_Float: {
27602808
return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E);
27612809
}
@@ -2858,6 +2906,7 @@ bool ByteCodeExprGen<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
28582906
return this->emitConstBool(Value, E);
28592907
case PT_Ptr:
28602908
case PT_FnPtr:
2909+
case PT_MemberPtr:
28612910
case PT_Float:
28622911
case PT_IntAP:
28632912
case PT_IntAPS:
@@ -3281,10 +3330,28 @@ bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
32813330
}
32823331
}
32833332

3333+
std::optional<unsigned> CalleeOffset;
32843334
// Add the (optional, implicit) This pointer.
32853335
if (const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) {
3286-
if (!this->visit(MC->getImplicitObjectArgument()))
3287-
return false;
3336+
if (!FuncDecl && classifyPrim(E->getCallee()) == PT_MemberPtr) {
3337+
// If we end up creating a CallPtr op for this, we need the base of the
3338+
// member pointer as the instance pointer, and later extract the function
3339+
// decl as the function pointer.
3340+
const Expr *Callee = E->getCallee();
3341+
CalleeOffset =
3342+
this->allocateLocalPrimitive(Callee, PT_MemberPtr, true, false);
3343+
if (!this->visit(Callee))
3344+
return false;
3345+
if (!this->emitSetLocal(PT_MemberPtr, *CalleeOffset, E))
3346+
return false;
3347+
if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))
3348+
return false;
3349+
if (!this->emitGetMemberPtrBase(E))
3350+
return false;
3351+
} else {
3352+
if (!this->visit(MC->getImplicitObjectArgument()))
3353+
return false;
3354+
}
32883355
}
32893356

32903357
llvm::BitVector NonNullArgs = collectNonNullArgs(FuncDecl, Args);
@@ -3352,11 +3419,22 @@ bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
33523419
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
33533420
ArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
33543421

3355-
if (!this->visit(E->getCallee()))
3356-
return false;
3422+
// Get the callee, either from a member pointer saved in CalleeOffset,
3423+
// or by just visiting the Callee expr.
3424+
if (CalleeOffset) {
3425+
if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))
3426+
return false;
3427+
if (!this->emitGetMemberPtrDecl(E))
3428+
return false;
3429+
if (!this->emitCallPtr(ArgSize, E, E))
3430+
return false;
3431+
} else {
3432+
if (!this->visit(E->getCallee()))
3433+
return false;
33573434

3358-
if (!this->emitCallPtr(ArgSize, E, E))
3359-
return false;
3435+
if (!this->emitCallPtr(ArgSize, E, E))
3436+
return false;
3437+
}
33603438
}
33613439

33623440
// Cleanup for discarded return values.
@@ -3595,6 +3673,11 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
35953673
return false;
35963674
return DiscardResult ? this->emitPop(*T, E) : true;
35973675
case UO_AddrOf: // &x
3676+
if (E->getType()->isMemberPointerType()) {
3677+
// C++11 [expr.unary.op]p3 has very strict rules on how the address of a
3678+
// member can be formed.
3679+
return this->emitGetMemberPtr(cast<DeclRefExpr>(SubExpr)->getDecl(), E);
3680+
}
35983681
// We should already have a pointer when we get here.
35993682
return this->delegate(SubExpr);
36003683
case UO_Deref: // *x

clang/lib/AST/Interp/Context.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,12 @@ std::optional<PrimType> Context::classify(QualType T) const {
160160
if (T->isFloatingType())
161161
return PT_Float;
162162

163+
if (T->isSpecificBuiltinType(BuiltinType::BoundMember) ||
164+
T->isMemberPointerType())
165+
return PT_MemberPtr;
166+
163167
if (T->isFunctionPointerType() || T->isFunctionReferenceType() ||
164-
T->isFunctionType() || T->isSpecificBuiltinType(BuiltinType::BoundMember))
168+
T->isFunctionType())
165169
return PT_FnPtr;
166170

167171
if (T->isReferenceType() || T->isPointerType())
@@ -173,9 +177,6 @@ std::optional<PrimType> Context::classify(QualType T) const {
173177
if (const auto *DT = dyn_cast<DecltypeType>(T))
174178
return classify(DT->getUnderlyingType());
175179

176-
if (const auto *DT = dyn_cast<MemberPointerType>(T))
177-
return classify(DT->getPointeeType());
178-
179180
return std::nullopt;
180181
}
181182

@@ -288,10 +289,12 @@ unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
288289
}
289290
if (CurDecl == FinalDecl)
290291
break;
291-
292-
// break;
293292
}
294293

295294
assert(OffsetSum > 0);
296295
return OffsetSum;
297296
}
297+
298+
const Record *Context::getRecord(const RecordDecl *D) const {
299+
return P->getOrCreateRecord(D);
300+
}

clang/lib/AST/Interp/Context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ class Context final {
107107
unsigned collectBaseOffset(const RecordDecl *BaseDecl,
108108
const RecordDecl *DerivedDecl) const;
109109

110+
const Record *getRecord(const RecordDecl *D) const;
111+
110112
private:
111113
/// Runs a function.
112114
bool Run(State &Parent, const Function *Func, APValue &Result);

clang/lib/AST/Interp/Descriptor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "Floating.h"
1212
#include "FunctionPointer.h"
1313
#include "IntegralAP.h"
14+
#include "MemberPointer.h"
1415
#include "Pointer.h"
1516
#include "PrimType.h"
1617
#include "Record.h"

clang/lib/AST/Interp/Disasm.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "Integral.h"
1818
#include "IntegralAP.h"
1919
#include "InterpFrame.h"
20+
#include "MemberPointer.h"
2021
#include "Opcode.h"
2122
#include "PrimType.h"
2223
#include "Program.h"
@@ -120,6 +121,8 @@ static const char *primTypeToString(PrimType T) {
120121
return "Ptr";
121122
case PT_FnPtr:
122123
return "FnPtr";
124+
case PT_MemberPtr:
125+
return "MemberPtr";
123126
}
124127
llvm_unreachable("Unhandled PrimType");
125128
}

clang/lib/AST/Interp/Interp.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,26 @@ bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
373373
return false;
374374
}
375375

376+
bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
377+
uint32_t Offset) {
378+
uint32_t MinOffset = Ptr.getDeclDesc()->getMetadataSize();
379+
uint32_t PtrOffset = Ptr.getByteOffset();
380+
381+
// We subtract Offset from PtrOffset. The result must be at least
382+
// MinOffset.
383+
if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
384+
return true;
385+
386+
const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
387+
QualType TargetQT = E->getType()->getPointeeType();
388+
QualType MostDerivedQT = Ptr.getDeclPtr().getType();
389+
390+
S.CCEDiag(E, diag::note_constexpr_invalid_downcast)
391+
<< MostDerivedQT << TargetQT;
392+
393+
return false;
394+
}
395+
376396
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
377397
assert(Ptr.isLive() && "Pointer is not live");
378398
if (!Ptr.isConst())
@@ -493,10 +513,12 @@ bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
493513
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
494514
if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
495515
return false;
496-
if (!CheckExtern(S, OpPC, Ptr))
497-
return false;
498-
if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
499-
return false;
516+
if (!Ptr.isDummy()) {
517+
if (!CheckExtern(S, OpPC, Ptr))
518+
return false;
519+
if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
520+
return false;
521+
}
500522
return true;
501523
}
502524

0 commit comments

Comments
 (0)