diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 70e2bca2ebf16..d11d05dd709d5 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -81,16 +81,15 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { if (DiscardResult) return this->discard(SubExpr); - return dereference( - SubExpr, DerefKind::Read, - [](PrimType) { - // Value loaded - nothing to do here. - return true; - }, - [this, CE](PrimType T) { - // Pointer on stack - dereference it. - return this->emitLoadPop(T, CE); - }); + if (SubExpr->getType()->isAnyComplexType()) + return this->delegate(SubExpr); + + if (!this->visit(SubExpr)) + return false; + + if (std::optional SubExprT = classify(SubExpr->getType())) + return this->emitLoadPop(*SubExprT, CE); + return false; } case CK_UncheckedDerivedToBase: @@ -2326,134 +2325,6 @@ bool ByteCodeExprGen::visitZeroRecordInitializer(const Record *R, return true; } -template -bool ByteCodeExprGen::dereference( - const Expr *LV, DerefKind AK, llvm::function_ref Direct, - llvm::function_ref Indirect) { - if (std::optional T = classify(LV->getType())) { - if (!LV->refersToBitField()) { - // Only primitive, non bit-field types can be dereferenced directly. - if (const auto *DE = dyn_cast(LV)) { - if (!DE->getDecl()->getType()->isReferenceType()) { - if (const auto *PD = dyn_cast(DE->getDecl())) - return dereferenceParam(LV, *T, PD, AK, Direct, Indirect); - if (const auto *VD = dyn_cast(DE->getDecl())) - return dereferenceVar(LV, *T, VD, AK, Direct, Indirect); - } - } - } - - if (!visit(LV)) - return false; - return Indirect(*T); - } - - if (LV->getType()->isAnyComplexType()) - return this->delegate(LV); - - return false; -} - -template -bool ByteCodeExprGen::dereferenceParam( - const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK, - llvm::function_ref Direct, - llvm::function_ref Indirect) { - if (auto It = this->Params.find(PD); It != this->Params.end()) { - unsigned Idx = It->second.Offset; - switch (AK) { - case DerefKind::Read: - return DiscardResult ? true : this->emitGetParam(T, Idx, LV); - - case DerefKind::Write: - if (!Direct(T)) - return false; - if (!this->emitSetParam(T, Idx, LV)) - return false; - return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); - - case DerefKind::ReadWrite: - if (!this->emitGetParam(T, Idx, LV)) - return false; - if (!Direct(T)) - return false; - if (!this->emitSetParam(T, Idx, LV)) - return false; - return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); - } - return true; - } - - // If the param is a pointer, we can dereference a dummy value. - if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) { - if (auto Idx = P.getOrCreateDummy(PD)) - return this->emitGetPtrGlobal(*Idx, PD); - return false; - } - - // Value cannot be produced - try to emit pointer and do stuff with it. - return visit(LV) && Indirect(T); -} - -template -bool ByteCodeExprGen::dereferenceVar( - const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK, - llvm::function_ref Direct, - llvm::function_ref Indirect) { - auto It = Locals.find(VD); - if (It != Locals.end()) { - const auto &L = It->second; - switch (AK) { - case DerefKind::Read: - if (!this->emitGetLocal(T, L.Offset, LV)) - return false; - return DiscardResult ? this->emitPop(T, LV) : true; - - case DerefKind::Write: - if (!Direct(T)) - return false; - if (!this->emitSetLocal(T, L.Offset, LV)) - return false; - return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); - - case DerefKind::ReadWrite: - if (!this->emitGetLocal(T, L.Offset, LV)) - return false; - if (!Direct(T)) - return false; - if (!this->emitSetLocal(T, L.Offset, LV)) - return false; - return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); - } - } else if (auto Idx = P.getGlobal(VD)) { - switch (AK) { - case DerefKind::Read: - if (!this->emitGetGlobal(T, *Idx, LV)) - return false; - return DiscardResult ? this->emitPop(T, LV) : true; - - case DerefKind::Write: - if (!Direct(T)) - return false; - if (!this->emitSetGlobal(T, *Idx, LV)) - return false; - return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); - - case DerefKind::ReadWrite: - if (!this->emitGetGlobal(T, *Idx, LV)) - return false; - if (!Direct(T)) - return false; - if (!this->emitSetGlobal(T, *Idx, LV)) - return false; - return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); - } - } - - // Value cannot be produced - try to emit pointer. - return visit(LV) && Indirect(T); -} - template template bool ByteCodeExprGen::emitConst(T Value, PrimType Ty, const Expr *E) { @@ -3092,15 +2963,9 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { // We should already have a pointer when we get here. return this->delegate(SubExpr); case UO_Deref: // *x - return dereference( - SubExpr, DerefKind::Read, - [](PrimType) { - llvm_unreachable("Dereferencing requires a pointer"); - return false; - }, - [this, E](PrimType T) { - return DiscardResult ? this->emitPop(T, E) : true; - }); + if (DiscardResult) + return this->discard(SubExpr); + return this->visit(SubExpr); case UO_Not: // ~x if (!this->visit(SubExpr)) return false; diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 4c88e33b3ece4..8f7a0c2fc3c10 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -236,29 +236,6 @@ class ByteCodeExprGen : public ConstStmtVisitor, bool>, bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E); bool visitZeroRecordInitializer(const Record *R, const Expr *E); - enum class DerefKind { - /// Value is read and pushed to stack. - Read, - /// Direct method generates a value which is written. Returns pointer. - Write, - /// Direct method receives the value, pushes mutated value. Returns pointer. - ReadWrite, - }; - - /// Method to directly load a value. If the value can be fetched directly, - /// the direct handler is called. Otherwise, a pointer is left on the stack - /// and the indirect handler is expected to operate on that. - bool dereference(const Expr *LV, DerefKind AK, - llvm::function_ref Direct, - llvm::function_ref Indirect); - bool dereferenceParam(const Expr *LV, PrimType T, const ParmVarDecl *PD, - DerefKind AK, - llvm::function_ref Direct, - llvm::function_ref Indirect); - bool dereferenceVar(const Expr *LV, PrimType T, const VarDecl *PD, - DerefKind AK, llvm::function_ref Direct, - llvm::function_ref Indirect); - /// Emits an APSInt constant. bool emitConst(const llvm::APSInt &Value, PrimType Ty, const Expr *E); bool emitConst(const llvm::APSInt &Value, const Expr *E); diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 1a48b8bddced0..82bc1f240cc51 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -362,13 +362,13 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, if (Ptr.isInitialized()) return true; + if (const auto *VD = Ptr.getDeclDesc()->asVarDecl(); + VD && VD->hasGlobalStorage()) { + const SourceInfo &Loc = S.Current->getSource(OpPC); + S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD; + S.Note(VD->getLocation(), diag::note_declared_at); + } if (!S.checkingPotentialConstantExpression()) { - if (const auto *VD = Ptr.getDeclDesc()->asVarDecl(); - VD && VD->hasGlobalStorage()) { - const SourceInfo &Loc = S.Current->getSource(OpPC); - S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD; - S.Note(VD->getLocation(), diag::note_declared_at); - } S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit) << AK << /*uninitialized=*/true << S.Current->getRange(OpPC); }