diff options
Diffstat (limited to 'clang/lib/AST/ByteCode/Compiler.cpp')
-rw-r--r-- | clang/lib/AST/ByteCode/Compiler.cpp | 209 |
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)) |