diff options
author | Timm Baeder <tbaeder@redhat.com> | 2025-04-16 09:00:52 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-16 09:00:52 +0200 |
commit | 05eafd9f2b14f2e8d2d95f46465c5cc53aafbc56 (patch) | |
tree | 6ea23b52dc5aacfb296dd56955174b08bf92092a /clang/lib | |
parent | a56f966417bc53051fa39e3db6fcc95f9abf0b5c (diff) | |
download | llvm-05eafd9f2b14f2e8d2d95f46465c5cc53aafbc56.zip llvm-05eafd9f2b14f2e8d2d95f46465c5cc53aafbc56.tar.gz llvm-05eafd9f2b14f2e8d2d95f46465c5cc53aafbc56.tar.bz2 |
[clang][bytecode] Explicitly mark constexpr-unknown variables as such (#135806)
Instead of trying to figure out what's constexpr-unknown later on.
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ByteCode/Compiler.cpp | 24 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Compiler.h | 12 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Descriptor.h | 1 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Disasm.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Interp.cpp | 9 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Program.cpp | 2 |
6 files changed, 32 insertions, 18 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 2e22c85..afd8d09 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -4293,7 +4293,8 @@ bool Compiler<Emitter>::emitConst(const APSInt &Value, const Expr *E) { template <class Emitter> unsigned Compiler<Emitter>::allocateLocalPrimitive( - DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl) { + DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl, + bool IsConstexprUnknown) { // Make sure we don't accidentally register the same decl twice. if (const auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { @@ -4307,6 +4308,7 @@ unsigned Compiler<Emitter>::allocateLocalPrimitive( // or isa<MaterializeTemporaryExpr>(). Descriptor *D = P.createDescriptor(Src, Ty, nullptr, Descriptor::InlineDescMD, IsConst, isa<const Expr *>(Src)); + D->IsConstexprUnknown = IsConstexprUnknown; Scope::Local Local = this->createLocal(D); if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) Locals.insert({VD, Local}); @@ -4320,7 +4322,8 @@ unsigned Compiler<Emitter>::allocateLocalPrimitive( template <class Emitter> std::optional<unsigned> Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty, - const ValueDecl *ExtendingDecl) { + const ValueDecl *ExtendingDecl, + bool IsConstexprUnknown) { // Make sure we don't accidentally register the same decl twice. if ([[maybe_unused]] const auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { @@ -4349,6 +4352,7 @@ Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty, IsTemporary, /*IsMutable=*/false, Init); if (!D) return std::nullopt; + D->IsConstexprUnknown = IsConstexprUnknown; Scope::Local Local = this->createLocal(D); if (Key) @@ -4460,9 +4464,10 @@ bool Compiler<Emitter>::visitExpr(const Expr *E, bool DestroyToplevelScope) { } template <class Emitter> -VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD) { +VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD, + bool IsConstexprUnknown) { - auto R = this->visitVarDecl(VD, /*Toplevel=*/true); + auto R = this->visitVarDecl(VD, /*Toplevel=*/true, IsConstexprUnknown); if (R.notCreated()) return R; @@ -4550,7 +4555,8 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD, template <class Emitter> VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, - bool Toplevel) { + bool Toplevel, + bool IsConstexprUnknown) { // We don't know what to do with these, so just return false. if (VD->getType().isNull()) return false; @@ -4620,7 +4626,8 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, if (VarT) { unsigned Offset = this->allocateLocalPrimitive( - VD, *VarT, VD->getType().isConstQualified()); + VD, *VarT, VD->getType().isConstQualified(), nullptr, + IsConstexprUnknown); if (Init) { // If this is a toplevel declaration, create a scope for the // initializer. @@ -4636,7 +4643,8 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, } } } else { - if (std::optional<unsigned> Offset = this->allocateLocal(VD)) { + if (std::optional<unsigned> Offset = this->allocateLocal( + VD, VD->getType(), nullptr, IsConstexprUnknown)) { if (!Init) return true; @@ -6461,7 +6469,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) { // In case we need to re-visit a declaration. auto revisit = [&](const VarDecl *VD) -> bool { - auto VarState = this->visitDecl(VD); + auto VarState = this->visitDecl(VD, /*IsConstexprUnknown=*/true); if (VarState.notCreated()) return true; diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 8589573..a3090a8 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -286,8 +286,10 @@ protected: /// intact. bool delegate(const Expr *E); /// Creates and initializes a variable from the given decl. - VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false); - VarCreationState visitDecl(const VarDecl *VD); + VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false, + bool IsConstexprUnknown = false); + VarCreationState visitDecl(const VarDecl *VD, + bool IsConstexprUnknown = false); /// Visit an APValue. bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E); bool visitAPValueInitializer(const APValue &Val, const Expr *E, QualType T); @@ -303,12 +305,14 @@ protected: /// Creates a local primitive value. unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst, - const ValueDecl *ExtendingDecl = nullptr); + const ValueDecl *ExtendingDecl = nullptr, + bool IsConstexprUnknown = false); /// Allocates a space storing a local given its type. std::optional<unsigned> allocateLocal(DeclTy &&Decl, QualType Ty = QualType(), - const ValueDecl *ExtendingDecl = nullptr); + const ValueDecl *ExtendingDecl = nullptr, + bool IsConstexprUnknown = false); std::optional<unsigned> allocateTemporary(const Expr *E); private: diff --git a/clang/lib/AST/ByteCode/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h index 9acabfd..a0705cc 100644 --- a/clang/lib/AST/ByteCode/Descriptor.h +++ b/clang/lib/AST/ByteCode/Descriptor.h @@ -168,6 +168,7 @@ public: const bool IsArray = false; /// Flag indicating if this is a dummy descriptor. bool IsDummy = false; + bool IsConstexprUnknown = false; /// Storage management methods. const BlockCtorFn CtorFn = nullptr; diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp index d4c9ce6..4bdf0f0 100644 --- a/clang/lib/AST/ByteCode/Disasm.cpp +++ b/clang/lib/AST/ByteCode/Disasm.cpp @@ -376,6 +376,8 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const { if (isDummy()) OS << " dummy"; + if (IsConstexprUnknown) + OS << " constexpr-unknown"; } /// Dump descriptor, including all valid offsets. diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 3e1f36d..4625154 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -299,15 +299,14 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC, TYPE_SWITCH(Ty, S.Stk.discard<T>()); } -// FIXME: Instead of using this fairly expensive test, we should -// just mark constexpr-unknown values when creating them. bool isConstexprUnknown(const Pointer &P) { if (!P.isBlockPointer()) return false; + if (P.isDummy()) - return false; - const VarDecl *VD = P.block()->getDescriptor()->asVarDecl(); - return VD && VD->hasLocalStorage() && !isa<ParmVarDecl>(VD); + return isa_and_nonnull<ParmVarDecl>(P.getDeclDesc()->asValueDecl()); + + return P.getDeclDesc()->IsConstexprUnknown; } bool CheckBCPResult(InterpState &S, const Pointer &Ptr) { diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index c83f557..fdb7b96 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -156,7 +156,7 @@ unsigned Program::getOrCreateDummy(const DeclTy &D) { if (const auto *E = dyn_cast<const Expr *>(D)) { QT = E->getType(); } else { - const ValueDecl *VD = cast<ValueDecl>(cast<const Decl *>(D)); + const auto *VD = cast<ValueDecl>(cast<const Decl *>(D)); IsWeak = VD->isWeak(); QT = VD->getType(); if (const auto *RT = QT->getAs<ReferenceType>()) |