https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/216537

>From 0f6c6cab1229c44c22da28361fad540b94fcac68 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Sun, 16 Aug 2026 08:13:46 +0200
Subject: [PATCH] [clang][bytecode] Check for invalid RecordDecls in
 Pointer::toAPValue()

We can't pass forward declarations to ASTContext::getRecordLayout().
---
 clang/lib/AST/ByteCode/Pointer.cpp | 29 +++++++++++++++++++++--------
 clang/test/AST/ByteCode/cxx23.cpp  | 22 ++++++++++++++++++++++
 2 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Pointer.cpp 
b/clang/lib/AST/ByteCode/Pointer.cpp
index 4f36d20b352cb..38314312c7e79 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -170,6 +170,11 @@ Pointer &Pointer::operator=(Pointer &&P) {
   return *this;
 }
 
+static bool validRecordDecl(const RecordDecl *D) {
+  D = D->getDefinition();
+  return D && !D->isInvalidDecl() && D->isCompleteDefinition();
+}
+
 APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
   llvm::SmallVector<APValue::LValuePathEntry, 5> Path;
 
@@ -222,11 +227,9 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const 
{
 
   CharUnits Offset = CharUnits::Zero();
 
-  auto getFieldOffset = [&](const FieldDecl *FD) -> CharUnits {
-    // This shouldn't happen, but if it does, don't crash inside
-    // getASTRecordLayout.
-    if (FD->getParent()->isInvalidDecl())
-      return CharUnits::Zero();
+  auto getFieldOffset = [&](const FieldDecl *FD) -> std::optional<CharUnits> {
+    if (!validRecordDecl(FD->getParent()))
+      return std::nullopt;
     const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(FD->getParent());
     unsigned FieldIndex = FD->getFieldIndex();
     return ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex));
@@ -254,8 +257,12 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const 
{
         const auto *Dcl = Desc->asDecl();
         Path.push_back(APValue::LValuePathEntry({Dcl, /*IsVirtual=*/false}));
 
-        if (const auto *FD = dyn_cast_if_present<FieldDecl>(Dcl))
-          Offset += getFieldOffset(FD);
+        if (const auto *FD = dyn_cast_if_present<FieldDecl>(Dcl)) {
+          if (std::optional<CharUnits> FieldOffset = getFieldOffset(FD))
+            Offset += *FieldOffset;
+          else
+            return APValue();
+        }
 
         Ptr = Ptr.getBase();
       }
@@ -287,12 +294,18 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) 
const {
         bool IsVirtual = false;
         if (const auto *FD = dyn_cast<FieldDecl>(BaseOrMember)) {
           Ptr = Ptr.getBase();
-          Offset += getFieldOffset(FD);
+          if (std::optional<CharUnits> FieldOffset = getFieldOffset(FD))
+            Offset += *FieldOffset;
+          else
+            return APValue();
         } else if (const auto *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
           IsVirtual = Ptr.isVirtualBaseClass();
           Ptr = Ptr.getBase();
           const Record *BaseRecord = Ptr.getRecord();
 
+          if (!validRecordDecl(BaseRecord->getDecl()))
+            return APValue();
+
           const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(
               cast<CXXRecordDecl>(BaseRecord->getDecl()));
           if (IsVirtual)
diff --git a/clang/test/AST/ByteCode/cxx23.cpp 
b/clang/test/AST/ByteCode/cxx23.cpp
index 5607ec9b59cb5..e0e72fafd4d03 100644
--- a/clang/test/AST/ByteCode/cxx23.cpp
+++ b/clang/test/AST/ByteCode/cxx23.cpp
@@ -667,4 +667,26 @@ namespace BrokenExplicitInstanceParam {
   static_assert( (&decltype(b)::operator())(1) == 1); // expected-error {{not 
an integral constant expression}}
 }
 
+namespace InvalidRecord {
+  struct S {
+    S();
+  };
+
+  template <typename T> void F(S &, T...);
+
+  struct SS {
+    template <typename T> SS(T &val) { __builtin_dump_struct(&val, F, s); }
+    S s;
+  };
+
+  template <typename T> S foo(const T &t) { return SS(t).s; }
+
+  struct A {
+    S s;
+  };
+
+  struct B : A; // all-error {{expected '{' after base class list}}
+
+  static_assert(foo(B{1, 2, 3}), "");
+}
 #endif

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to