[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