[clang] [clang][Interp] Fall back to dummy pointers if createGlobal() fails (PR #102464)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 8 06:30:51 PDT 2024
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?= <tbaeder at 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, "");
+}
More information about the cfe-commits
mailing list