https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/102464
createGlobal fails e.g. if the type isn't complete. >From b945bf23c12fc54c6a256507c815fee19fbac655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Thu, 8 Aug 2024 15:08:46 +0200 Subject: [PATCH] [clang][Interp] Fall back to dummy pointers if createGlobal() fails createGlobal fails e.g. if the type isn't complete. --- clang/lib/AST/Interp/Compiler.cpp | 18 +++++++++++------- clang/lib/AST/Interp/Compiler.h | 11 ++++++----- clang/test/AST/Interp/records.cpp | 10 ++++++++++ 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp index 11fe2acf2d7b95..165fabbfe3d73b 100644 --- a/clang/lib/AST/Interp/Compiler.cpp +++ b/clang/lib/AST/Interp/Compiler.cpp @@ -3617,7 +3617,7 @@ VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD) { auto R = this->visitVarDecl(VD, /*Toplevel=*/true); - if (R.notCreated()) + if (R.notCreated() || R.dummyCreated()) return R; if (R) @@ -3709,7 +3709,7 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve // This case is EvalEmitter-only. If we won't create any instructions for the // initializer anyway, don't bother creating the variable in the first place. if (!this->isActive()) - return VarCreationState::NotCreated(); + return VarCreationState::NotCreated; const Expr *Init = VD->getInit(); std::optional<PrimType> VarT = classify(VD->getType()); @@ -3759,12 +3759,16 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve return Init && checkDecl() && initGlobal(*GlobalIndex); } - std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init); + if (std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init)) + return !Init || (checkDecl() && initGlobal(*GlobalIndex)); - if (!GlobalIndex) - return false; + if (std::optional<unsigned> I = P.getOrCreateDummy(VD)) { + if (!this->emitGetPtrGlobal(*I, VD)) + return false; + return VarCreationState::DummyCreated; + } - return !Init || (checkDecl() && initGlobal(*GlobalIndex)); + return false; } else { InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD)); @@ -5240,7 +5244,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) { auto revisit = [&](const VarDecl *VD) -> bool { auto VarState = this->visitDecl(VD); - if (VarState.notCreated()) + if (VarState.notCreated() || VarState.dummyCreated()) return true; if (!VarState) return false; diff --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h index 244a600d061f49..4888e499bd6d43 100644 --- a/clang/lib/AST/Interp/Compiler.h +++ b/clang/lib/AST/Interp/Compiler.h @@ -89,13 +89,14 @@ struct InitLink { /// State encapsulating if a the variable creation has been successful, /// unsuccessful, or no variable has been created at all. struct VarCreationState { - std::optional<bool> S = std::nullopt; + enum SS { Failure = 0, Success = 1, NotCreated, DummyCreated } S; VarCreationState() = default; - VarCreationState(bool b) : S(b) {} - static VarCreationState NotCreated() { return VarCreationState(); } + VarCreationState(SS b) : S(b) {} + VarCreationState(bool b) : S(b ? Success : Failure) {} - operator bool() const { return S && *S; } - bool notCreated() const { return !S; } + operator bool() const { return S == Success; } + bool notCreated() const { return S == NotCreated; } + bool dummyCreated() const { return S == DummyCreated; } }; /// Compilation context for expressions. diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 479c0487fecae0..48c07e2953ebf9 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1576,3 +1576,13 @@ namespace ctorOverrider { constexpr Covariant1 cb; } #endif + +namespace IncompleteStaticStructMember { + struct Foo; + struct Bar { + static const Foo x; + static const Foo y; + }; + static_assert(&Bar::x != nullptr, ""); // both-warning {{always true}} + static_assert(&Bar::x != &Bar::y, ""); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits