aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/Compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode/Compiler.cpp')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp209
1 files changed, 117 insertions, 92 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index ea473730..63ac536 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -25,34 +25,6 @@ using APSInt = llvm::APSInt;
namespace clang {
namespace interp {
-static bool refersToUnion(const Expr *E) {
- for (;;) {
- if (const auto *ME = dyn_cast<MemberExpr>(E)) {
- if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
- FD && FD->getParent()->isUnion())
- return true;
- E = ME->getBase();
- continue;
- }
-
- if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
- E = ASE->getBase()->IgnoreImplicit();
- continue;
- }
-
- if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E);
- ICE && (ICE->getCastKind() == CK_NoOp ||
- ICE->getCastKind() == CK_DerivedToBase ||
- ICE->getCastKind() == CK_UncheckedDerivedToBase)) {
- E = ICE->getSubExpr();
- continue;
- }
-
- break;
- }
- return false;
-}
-
static std::optional<bool> getBoolValue(const Expr *E) {
if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);
CE && CE->hasAPValueResult() &&
@@ -237,7 +209,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (SubExpr->getType().isVolatileQualified())
return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE);
- std::optional<PrimType> SubExprT = classify(SubExpr->getType());
+ OptPrimType SubExprT = classify(SubExpr->getType());
// Prepare storage for the result.
if (!Initializing && !SubExprT) {
std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
@@ -388,7 +360,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
const Descriptor *Desc = nullptr;
const QualType PointeeType = CE->getType()->getPointeeType();
if (!PointeeType.isNull()) {
- if (std::optional<PrimType> T = classify(PointeeType))
+ if (OptPrimType T = classify(PointeeType))
Desc = P.createDescriptor(SubExpr, *T);
else
Desc = P.createDescriptor(SubExpr, PointeeType.getTypePtr(),
@@ -436,7 +408,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
PrimType T = classifyPrim(IntType);
QualType PtrType = CE->getType();
const Descriptor *Desc;
- if (std::optional<PrimType> T = classify(PtrType->getPointeeType()))
+ if (OptPrimType T = classify(PtrType->getPointeeType()))
Desc = P.createDescriptor(SubExpr, *T);
else if (PtrType->getPointeeType()->isVoidType())
Desc = nullptr;
@@ -473,12 +445,12 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, CE);
}
QualType SubExprTy = SubExpr->getType();
- std::optional<PrimType> FromT = classify(SubExprTy);
+ OptPrimType FromT = classify(SubExprTy);
// Casts from integer/vector to vector.
if (CE->getType()->isVectorType())
return this->emitBuiltinBitCast(CE);
- std::optional<PrimType> ToT = classify(CE->getType());
+ OptPrimType ToT = classify(CE->getType());
if (!FromT || !ToT)
return false;
@@ -504,7 +476,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_IntegralToBoolean:
case CK_FixedPointToBoolean: {
// HLSL uses this to cast to one-element vectors.
- std::optional<PrimType> FromT = classify(SubExpr->getType());
+ OptPrimType FromT = classify(SubExpr->getType());
if (!FromT)
return false;
@@ -517,8 +489,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_BooleanToSignedIntegral:
case CK_IntegralCast: {
- std::optional<PrimType> FromT = classify(SubExpr->getType());
- std::optional<PrimType> ToT = classify(CE->getType());
+ OptPrimType FromT = classify(SubExpr->getType());
+ OptPrimType ToT = classify(CE->getType());
if (!FromT || !ToT)
return false;
@@ -688,7 +660,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_HLSLVectorTruncation: {
assert(SubExpr->getType()->isVectorType());
- if (std::optional<PrimType> ResultT = classify(CE)) {
+ if (OptPrimType ResultT = classify(CE)) {
assert(!DiscardResult);
// Result must be either a float or integer. Take the first element.
if (!this->visit(SubExpr))
@@ -872,9 +844,9 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
}
// Typecheck the args.
- std::optional<PrimType> LT = classify(LHS);
- std::optional<PrimType> RT = classify(RHS);
- std::optional<PrimType> T = classify(BO->getType());
+ OptPrimType LT = classify(LHS);
+ OptPrimType RT = classify(RHS);
+ OptPrimType T = classify(BO->getType());
// Special case for C++'s three-way/spaceship operator <=>, which
// returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't
@@ -995,8 +967,8 @@ bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
(!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))
return false;
- std::optional<PrimType> LT = classify(LHS);
- std::optional<PrimType> RT = classify(RHS);
+ OptPrimType LT = classify(LHS);
+ OptPrimType RT = classify(RHS);
if (!LT || !RT)
return false;
@@ -1068,7 +1040,7 @@ bool Compiler<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
BinaryOperatorKind Op = E->getOpcode();
const Expr *LHS = E->getLHS();
const Expr *RHS = E->getRHS();
- std::optional<PrimType> T = classify(E->getType());
+ OptPrimType T = classify(E->getType());
if (Op == BO_LOr) {
// Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE.
@@ -1648,7 +1620,7 @@ bool Compiler<Emitter>::VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *E) {
QualType QT = E->getType();
- if (std::optional<PrimType> T = classify(QT))
+ if (OptPrimType T = classify(QT))
return this->visitZeroInitializer(*T, QT, E);
if (QT->isRecordType()) {
@@ -1734,7 +1706,7 @@ bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
if (!Success)
return false;
- std::optional<PrimType> IndexT = classify(Index->getType());
+ OptPrimType IndexT = classify(Index->getType());
// In error-recovery cases, the index expression has a dependent type.
if (!IndexT)
return this->emitError(E);
@@ -1776,7 +1748,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
}
// Primitive values.
- if (std::optional<PrimType> T = classify(QT)) {
+ if (OptPrimType T = classify(QT)) {
assert(!DiscardResult);
if (Inits.size() == 0)
return this->visitZeroInitializer(*T, QT, E);
@@ -1840,7 +1812,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
FToInit = cast<CXXParenListInitExpr>(E)->getInitializedFieldInUnion();
const Record::Field *FieldToInit = R->getField(FToInit);
- if (std::optional<PrimType> T = classify(Init)) {
+ if (OptPrimType T = classify(Init)) {
if (!initPrimitiveField(FieldToInit, Init, *T, /*Activate=*/true))
return false;
} else {
@@ -1859,7 +1831,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
R->getField(InitIndex)->isUnnamedBitField())
++InitIndex;
- if (std::optional<PrimType> T = classify(Init)) {
+ if (OptPrimType T = classify(Init)) {
const Record::Field *FieldToInit = R->getField(InitIndex);
if (!initPrimitiveField(FieldToInit, Init, *T))
return false;
@@ -1899,7 +1871,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
if (!this->emitCheckArraySize(NumElems, E))
return false;
- std::optional<PrimType> InitT = classify(CAT->getElementType());
+ OptPrimType InitT = classify(CAT->getElementType());
unsigned ElementIndex = 0;
for (const Expr *Init : Inits) {
if (const auto *EmbedS =
@@ -2013,7 +1985,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
/// this.
template <class Emitter>
bool Compiler<Emitter>::visitArrayElemInit(unsigned ElemIndex, const Expr *Init,
- std::optional<PrimType> InitT) {
+ OptPrimType InitT) {
if (InitT) {
// Visit the primitive element like normal.
if (!this->visit(Init))
@@ -2042,7 +2014,7 @@ bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,
unsigned ArgIndex = 0;
for (const Expr *Arg : Args) {
- if (std::optional<PrimType> T = classify(Arg)) {
+ if (OptPrimType T = classify(Arg)) {
if (!this->visit(Arg))
return false;
} else {
@@ -2097,7 +2069,7 @@ bool Compiler<Emitter>::VisitSubstNonTypeTemplateParmExpr(
template <class Emitter>
bool Compiler<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
- std::optional<PrimType> T = classify(E->getType());
+ OptPrimType T = classify(E->getType());
if (T && E->hasAPValueResult()) {
// Try to emit the APValue directly, without visiting the subexpr.
// This will only fail if we can't emit the APValue, so won't emit any
@@ -2292,7 +2264,7 @@ bool Compiler<Emitter>::VisitMemberExpr(const MemberExpr *E) {
const auto maybeLoadValue = [&]() -> bool {
if (E->isGLValue())
return true;
- if (std::optional<PrimType> T = classify(E))
+ if (OptPrimType T = classify(E))
return this->emitLoadPop(*T, E);
return false;
};
@@ -2357,7 +2329,7 @@ bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
// Investigate compiling this to a loop.
const Expr *SubExpr = E->getSubExpr();
size_t Size = E->getArraySize().getZExtValue();
- std::optional<PrimType> SubExprT = classify(SubExpr);
+ OptPrimType SubExprT = classify(SubExpr);
// So, every iteration, we execute an assignment here
// where the LHS is on the stack (the target array)
@@ -2589,8 +2561,8 @@ bool Compiler<Emitter>::VisitFloatCompoundAssignOperator(
QualType LHSType = LHS->getType();
QualType LHSComputationType = E->getComputationLHSType();
QualType ResultType = E->getComputationResultType();
- std::optional<PrimType> LT = classify(LHSComputationType);
- std::optional<PrimType> RT = classify(ResultType);
+ OptPrimType LT = classify(LHSComputationType);
+ OptPrimType RT = classify(ResultType);
assert(ResultType->isFloatingType());
@@ -2659,8 +2631,8 @@ bool Compiler<Emitter>::VisitPointerCompoundAssignOperator(
BinaryOperatorKind Op = E->getOpcode();
const Expr *LHS = E->getLHS();
const Expr *RHS = E->getRHS();
- std::optional<PrimType> LT = classify(LHS->getType());
- std::optional<PrimType> RT = classify(RHS->getType());
+ OptPrimType LT = classify(LHS->getType());
+ OptPrimType RT = classify(RHS->getType());
if (Op != BO_AddAssign && Op != BO_SubAssign)
return false;
@@ -2698,11 +2670,10 @@ bool Compiler<Emitter>::VisitCompoundAssignOperator(
const Expr *LHS = E->getLHS();
const Expr *RHS = E->getRHS();
- std::optional<PrimType> LHSComputationT =
- classify(E->getComputationLHSType());
- std::optional<PrimType> LT = classify(LHS->getType());
- std::optional<PrimType> RT = classify(RHS->getType());
- std::optional<PrimType> ResultT = classify(E->getType());
+ OptPrimType LHSComputationT = classify(E->getComputationLHSType());
+ OptPrimType LT = classify(LHS->getType());
+ OptPrimType RT = classify(RHS->getType());
+ OptPrimType ResultT = classify(E->getType());
if (!Ctx.getLangOpts().CPlusPlus14)
return this->visit(RHS) && this->visit(LHS) && this->emitError(E);
@@ -2837,7 +2808,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
// When we're initializing a global variable *or* the storage duration of
// the temporary is explicitly static, create a global variable.
- std::optional<PrimType> SubExprT = classify(SubExpr);
+ OptPrimType SubExprT = classify(SubExpr);
bool IsStatic = E->getStorageDuration() == SD_Static;
if (IsStatic) {
std::optional<unsigned> GlobalIndex = P.createGlobal(E);
@@ -2931,7 +2902,7 @@ bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
return this->visitInitializer(Init) && this->emitFinishInit(E);
}
- std::optional<PrimType> T = classify(E->getType());
+ OptPrimType T = classify(E->getType());
if (E->isFileScope()) {
// Avoid creating a variable if this is a primitive RValue anyway.
if (T && !E->isLValue())
@@ -3014,7 +2985,7 @@ bool Compiler<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
continue;
++CaptureInitIt;
- if (std::optional<PrimType> T = classify(Init)) {
+ if (OptPrimType T = classify(Init)) {
if (!this->visit(Init))
return false;
@@ -3061,21 +3032,21 @@ bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(
const CXXReinterpretCastExpr *E) {
const Expr *SubExpr = E->getSubExpr();
- std::optional<PrimType> FromT = classify(SubExpr);
- std::optional<PrimType> ToT = classify(E);
+ OptPrimType FromT = classify(SubExpr);
+ OptPrimType ToT = classify(E);
if (!FromT || !ToT)
return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, E);
if (FromT == PT_Ptr || ToT == PT_Ptr) {
// Both types could be PT_Ptr because their expressions are glvalues.
- std::optional<PrimType> PointeeFromT;
+ OptPrimType PointeeFromT;
if (SubExpr->getType()->isPointerOrReferenceType())
PointeeFromT = classify(SubExpr->getType()->getPointeeType());
else
PointeeFromT = classify(SubExpr->getType());
- std::optional<PrimType> PointeeToT;
+ OptPrimType PointeeToT;
if (E->getType()->isPointerOrReferenceType())
PointeeToT = classify(E->getType()->getPointeeType());
else
@@ -3344,7 +3315,7 @@ bool Compiler<Emitter>::VisitCXXScalarValueInitExpr(
if (DiscardResult || Ty->isVoidType())
return true;
- if (std::optional<PrimType> T = classify(Ty))
+ if (OptPrimType T = classify(Ty))
return this->visitZeroInitializer(*T, Ty, E);
if (const auto *CT = Ty->getAs<ComplexType>()) {
@@ -3457,7 +3428,7 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
assert(classifyPrim(E->getType()) == PT_Ptr);
const Expr *Init = E->getInitializer();
QualType ElementType = E->getAllocatedType();
- std::optional<PrimType> ElemT = classify(ElementType);
+ OptPrimType ElemT = classify(ElementType);
unsigned PlacementArgs = E->getNumPlacementArgs();
const FunctionDecl *OperatorNew = E->getOperatorNew();
const Expr *PlacementDest = nullptr;
@@ -3645,7 +3616,7 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
if (!this->emitStorePop(InitT, E))
return false;
} else if (DynamicInit) {
- if (std::optional<PrimType> InitT = classify(DynamicInit)) {
+ if (OptPrimType InitT = classify(DynamicInit)) {
if (!this->visit(DynamicInit))
return false;
if (!this->emitStorePop(*InitT, E))
@@ -4154,7 +4125,7 @@ bool Compiler<Emitter>::visitInitializer(const Expr *E) {
}
template <class Emitter> bool Compiler<Emitter>::visitBool(const Expr *E) {
- std::optional<PrimType> T = classify(E->getType());
+ OptPrimType T = classify(E->getType());
if (!T) {
// Convert complex values to bool.
if (E->getType()->isAnyComplexType()) {
@@ -4309,7 +4280,7 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
QualType ElemType = AT->getElementType();
size_t NumElems = cast<ConstantArrayType>(AT)->getZExtSize();
- if (std::optional<PrimType> ElemT = classify(ElemType)) {
+ if (OptPrimType ElemT = classify(ElemType)) {
for (size_t I = 0; I != NumElems; ++I) {
if (!this->visitZeroInitializer(*ElemT, ElemType, E))
return false;
@@ -4602,7 +4573,7 @@ bool Compiler<Emitter>::visitExpr(const Expr *E, bool DestroyToplevelScope) {
}
// Expressions with a primitive return type.
- if (std::optional<PrimType> T = classify(E)) {
+ if (OptPrimType T = classify(E)) {
if (!visit(E))
return false;
@@ -4679,7 +4650,7 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,
if (!this->visitVarDecl(VD, /*Toplevel=*/true))
return false;
- std::optional<PrimType> VarT = classify(VD->getType());
+ OptPrimType VarT = classify(VD->getType());
if (Context::shouldBeGloballyIndexed(VD)) {
auto GlobalIndex = P.getGlobal(VD);
assert(GlobalIndex); // visitVarDecl() didn't return false.
@@ -4736,7 +4707,7 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
return VarCreationState::NotCreated();
const Expr *Init = VD->getInit();
- std::optional<PrimType> VarT = classify(VD->getType());
+ OptPrimType VarT = classify(VD->getType());
if (Init && Init->isValueDependent())
return false;
@@ -4868,7 +4839,7 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
const Record::Field *RF = R->getField(I);
QualType FieldType = RF->Decl->getType();
- if (std::optional<PrimType> PT = classify(FieldType)) {
+ if (OptPrimType PT = classify(FieldType)) {
if (!this->visitAPValue(F, *PT, E))
return false;
if (!this->emitInitField(*PT, RF->Offset, E))
@@ -4898,7 +4869,7 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
QualType ElemType = ArrType->getElementType();
for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) {
const APValue &Elem = Val.getArrayInitializedElt(A);
- if (std::optional<PrimType> ElemT = classify(ElemType)) {
+ if (OptPrimType ElemT = classify(ElemType)) {
if (!this->visitAPValue(Elem, *ElemT, E))
return false;
if (!this->emitInitElem(*ElemT, A, E))
@@ -4958,7 +4929,7 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
}
QualType ReturnType = E->getType();
- std::optional<PrimType> ReturnT = classify(E);
+ OptPrimType ReturnT = classify(E);
// Non-primitive return type. Prepare storage.
if (!Initializing && !ReturnT && !ReturnType->isVoidType()) {
@@ -5032,7 +5003,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
BlockScope<Emitter> CallScope(this, ScopeKind::Call);
QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
- std::optional<PrimType> T = classify(ReturnType);
+ OptPrimType T = classify(ReturnType);
bool HasRVO = !ReturnType->isVoidType() && !T;
if (HasRVO) {
@@ -5402,6 +5373,53 @@ bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {
return true;
}
+static bool hasTrivialDefaultCtorParent(const FieldDecl *FD) {
+ assert(FD);
+ assert(FD->getParent()->isUnion());
+ const auto *CXXRD = dyn_cast<CXXRecordDecl>(FD->getParent());
+ return !CXXRD || CXXRD->hasTrivialDefaultConstructor();
+}
+
+template <class Emitter> bool Compiler<Emitter>::refersToUnion(const Expr *E) {
+ for (;;) {
+ if (const auto *ME = dyn_cast<MemberExpr>(E)) {
+ if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
+ FD && FD->getParent()->isUnion() && hasTrivialDefaultCtorParent(FD))
+ return true;
+ E = ME->getBase();
+ continue;
+ }
+
+ if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
+ E = ASE->getBase()->IgnoreImplicit();
+ continue;
+ }
+
+ if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E);
+ ICE && (ICE->getCastKind() == CK_NoOp ||
+ ICE->getCastKind() == CK_DerivedToBase ||
+ ICE->getCastKind() == CK_UncheckedDerivedToBase)) {
+ E = ICE->getSubExpr();
+ continue;
+ }
+
+ if (const auto *This = dyn_cast<CXXThisExpr>(E)) {
+ const auto *ThisRecord =
+ This->getType()->getPointeeType()->getAsRecordDecl();
+ if (!ThisRecord->isUnion())
+ return false;
+ // Otherwise, always activate if we're in the ctor.
+ if (const auto *Ctor =
+ dyn_cast_if_present<CXXConstructorDecl>(CompilingFunction))
+ return Ctor->getParent() == ThisRecord;
+ return false;
+ }
+
+ break;
+ }
+ return false;
+}
+
template <class Emitter>
bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS,
bool EvaluateConditionDecl) {
@@ -5933,17 +5951,16 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
if (InitExpr->getType().isNull())
return false;
- if (std::optional<PrimType> T = this->classify(InitExpr)) {
+ if (OptPrimType T = this->classify(InitExpr)) {
+ if (Activate && !this->emitActivateThisField(FieldOffset, InitExpr))
+ return false;
+
if (!this->visit(InitExpr))
return false;
bool BitField = F->isBitField();
- if (BitField && Activate)
- return this->emitInitThisBitFieldActivate(*T, F, FieldOffset, InitExpr);
if (BitField)
return this->emitInitThisBitField(*T, F, FieldOffset, InitExpr);
- if (Activate)
- return this->emitInitThisFieldActivate(*T, FieldOffset, InitExpr);
return this->emitInitThisField(*T, FieldOffset, InitExpr);
}
// Non-primitive case. Get a pointer to the field-to-initialize
@@ -6189,7 +6206,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
return this->VisitVectorUnaryOperator(E);
if (SubExpr->getType()->isFixedPointType())
return this->VisitFixedPointUnaryOperator(E);
- std::optional<PrimType> T = classify(SubExpr->getType());
+ OptPrimType T = classify(SubExpr->getType());
switch (E->getOpcode()) {
case UO_PostInc: { // x++
@@ -6375,6 +6392,9 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
if (!this->visit(SubExpr))
return false;
+ if (!this->emitCheckNull(E))
+ return false;
+
if (classifyPrim(SubExpr) == PT_Ptr)
return this->emitNarrowPtr(E);
return true;
@@ -6412,7 +6432,7 @@ bool Compiler<Emitter>::VisitComplexUnaryOperator(const UnaryOperator *E) {
if (DiscardResult)
return this->discard(SubExpr);
- std::optional<PrimType> ResT = classify(E);
+ OptPrimType ResT = classify(E);
auto prepareResult = [=]() -> bool {
if (!ResT && !Initializing) {
std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
@@ -6634,7 +6654,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
if (std::optional<unsigned> Index = P.getOrCreateGlobal(D)) {
if (!this->emitGetPtrGlobal(*Index, E))
return false;
- if (std::optional<PrimType> T = classify(E->getType())) {
+ if (OptPrimType T = classify(E->getType())) {
if (!this->visitAPValue(TPOD->getValue(), *T, E))
return false;
return this->emitInitGlobal(*T, *Index, E);
@@ -6670,6 +6690,11 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
}
// Function parameters.
if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
+ if (Ctx.getLangOpts().CPlusPlus && !Ctx.getLangOpts().CPlusPlus11 &&
+ !D->getType()->isIntegralOrEnumerationType()) {
+ return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),
+ /*InitializerFailed=*/false, E);
+ }
if (auto It = this->Params.find(PVD); It != this->Params.end()) {
if (IsReference || !It->second.IsPtr)
return this->emitGetParam(classifyPrim(E), It->second.Offset, E);
@@ -7128,7 +7153,7 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
const Expr *SubExpr = E->getSubExpr();
QualType FromType = SubExpr->getType();
QualType ToType = E->getType();
- std::optional<PrimType> ToT = classify(ToType);
+ OptPrimType ToT = classify(ToType);
assert(!ToType->isReferenceType());
@@ -7149,7 +7174,7 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
if (SubExpr->isGLValue() || FromType->isVectorType()) {
if (!this->visit(SubExpr))
return false;
- } else if (std::optional<PrimType> FromT = classify(SubExpr)) {
+ } else if (OptPrimType FromT = classify(SubExpr)) {
unsigned TempOffset =
allocateLocalPrimitive(SubExpr, *FromT, /*IsConst=*/true);
if (!this->visit(SubExpr))