summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/Interp/ByteCodeExprGen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/Interp/ByteCodeExprGen.cpp')
-rw-r--r--clang/lib/AST/Interp/ByteCodeExprGen.cpp41
1 files changed, 34 insertions, 7 deletions
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 01ec31e4077f..00c4a9f16130 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -262,7 +262,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
return this->discard(SubExpr);
std::optional<PrimType> FromT = classify(SubExpr->getType());
- std::optional<PrimType> ToT = classifyPrim(CE->getType());
+ std::optional<PrimType> ToT = classify(CE->getType());
if (!FromT || !ToT)
return false;
@@ -1251,6 +1251,15 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr(
return this->emitConst(Size.getQuantity(), E);
}
+ if (Kind == UETT_VectorElements) {
+ if (const auto *VT = E->getTypeOfArgument()->getAs<VectorType>())
+ return this->emitConst(VT->getNumElements(), E);
+
+ // FIXME: Apparently we need to catch the fact that a sizeless vector type
+ // has been passed and diagnose that (at run time).
+ assert(E->getTypeOfArgument()->isSizelessVectorType());
+ }
+
return false;
}
@@ -1258,10 +1267,30 @@ template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
// 'Base.Member'
const Expr *Base = E->getBase();
+ const ValueDecl *Member = E->getMemberDecl();
if (DiscardResult)
return this->discard(Base);
+ // MemberExprs are almost always lvalues, in which case we don't need to
+ // do the load. But sometimes they aren't.
+ const auto maybeLoadValue = [&]() -> bool {
+ if (E->isGLValue())
+ return true;
+ if (std::optional<PrimType> T = classify(E))
+ return this->emitLoadPop(*T, E);
+ return false;
+ };
+
+ if (const auto *VD = dyn_cast<VarDecl>(Member)) {
+ // I am almost confident in saying that a var decl must be static
+ // and therefore registered as a global variable. But this will probably
+ // turn out to be wrong some time in the future, as always.
+ if (auto GlobalIndex = P.getGlobal(VD))
+ return this->emitGetPtrGlobal(*GlobalIndex, E) && maybeLoadValue();
+ return false;
+ }
+
if (Initializing) {
if (!this->delegate(Base))
return false;
@@ -1271,16 +1300,14 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
}
// Base above gives us a pointer on the stack.
- // TODO: Implement non-FieldDecl members.
- const ValueDecl *Member = E->getMemberDecl();
if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
const RecordDecl *RD = FD->getParent();
const Record *R = getRecord(RD);
const Record::Field *F = R->getField(FD);
// Leave a pointer to the field on the stack.
if (F->Decl->getType()->isReferenceType())
- return this->emitGetFieldPop(PT_Ptr, F->Offset, E);
- return this->emitGetPtrField(F->Offset, E);
+ return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue();
+ return this->emitGetPtrField(F->Offset, E) && maybeLoadValue();
}
return false;
@@ -1615,7 +1642,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
return false;
if (!this->emitLoad(*LT, E))
return false;
- if (*LT != *LHSComputationT) {
+ if (LT != LHSComputationT) {
if (!this->emitCast(*LT, *LHSComputationT, E))
return false;
}
@@ -1671,7 +1698,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
}
// And now cast from LHSComputationT to ResultT.
- if (*ResultT != *LHSComputationT) {
+ if (ResultT != LHSComputationT) {
if (!this->emitCast(*LHSComputationT, *ResultT, E))
return false;
}