[llvm-branch-commits] [clang] [CIR][CodeGen][NFC] Share isEmptyFieldForLayout and isEmptyRecordForLayout (PR #223424)

Henrich Lauko via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Sep 29 04:26:21 PDT 2026


https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223424

>From 92e9dbf7ddda11055f859e773cf6580fbaa8bc18 Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Tue, 29 Sep 2026 09:56:08 +0000
Subject: [PATCH] [CIR][CodeGen][NFC] Share isEmptyFieldForLayout and
 isEmptyRecordForLayout

Deduplicates `isEmptyFieldForLayout` and `isEmptyRecordForLayout` between CIR
and classic CodeGen into a new `RecordLayoutUtils.h`. `ABIInfoImpl.h` and CIR's
`TargetInfo.h` re-export them with using-declarations, so the ~30 unqualified
callers are untouched.

Assisted-by: Claude Code (Claude Fable 5.1).
---
 .../clang/CodeGenUtils/RecordLayoutUtils.h    | 34 ++++++++++++++
 clang/lib/CIR/CodeGen/TargetInfo.cpp          | 34 --------------
 clang/lib/CIR/CodeGen/TargetInfo.h            | 12 ++---
 clang/lib/CodeGen/ABIInfoImpl.cpp             | 33 --------------
 clang/lib/CodeGen/ABIInfoImpl.h               | 12 ++---
 clang/lib/CodeGenUtils/CMakeLists.txt         |  1 +
 clang/lib/CodeGenUtils/RecordLayoutUtils.cpp  | 45 +++++++++++++++++++
 7 files changed, 86 insertions(+), 85 deletions(-)
 create mode 100644 clang/include/clang/CodeGenUtils/RecordLayoutUtils.h
 create mode 100644 clang/lib/CodeGenUtils/RecordLayoutUtils.cpp

diff --git a/clang/include/clang/CodeGenUtils/RecordLayoutUtils.h b/clang/include/clang/CodeGenUtils/RecordLayoutUtils.h
new file mode 100644
index 0000000000000..77f14fee5a3b4
--- /dev/null
+++ b/clang/include/clang/CodeGenUtils/RecordLayoutUtils.h
@@ -0,0 +1,34 @@
+//===--- RecordLayoutUtils.h - Shared record layout queries -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file holds the AST queries about record layout that both classic
+// CodeGen and CIR CodeGen need while lowering a record to its target type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGENUTILS_RECORDLAYOUTUTILS_H
+#define LLVM_CLANG_CODEGENUTILS_RECORDLAYOUTUTILS_H
+
+#include "clang/AST/ASTContext.h"
+
+namespace clang::CodeGenUtils {
+
+/// Return true iff the field is "empty", that is, either a zero-width
+/// bit-field or an \ref isEmptyRecordForLayout.
+bool isEmptyFieldForLayout(const ASTContext &Ctx, const FieldDecl *FD);
+
+/// Return true iff a structure contains only empty base classes (per \ref
+/// isEmptyRecordForLayout) and fields (per \ref isEmptyFieldForLayout).  Note,
+/// C++ record fields are considered empty if the [[no_unique_address]]
+/// attribute would have made them empty, so this is not the same as \ref
+/// isEmptyRecord.
+bool isEmptyRecordForLayout(const ASTContext &Ctx, QualType T);
+
+} // namespace clang::CodeGenUtils
+
+#endif // LLVM_CLANG_CODEGENUTILS_RECORDLAYOUTUTILS_H
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index cede4941b4473..57bc5f167e460 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -11,40 +11,6 @@
 using namespace clang;
 using namespace clang::CIRGen;
 
-bool clang::CIRGen::isEmptyRecordForLayout(const ASTContext &context,
-                                           QualType t) {
-  const auto *rd = t->getAsRecordDecl();
-  if (!rd)
-    return false;
-
-  // If this is a C++ record, check the bases first.
-  if (const CXXRecordDecl *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
-    if (cxxrd->isDynamicClass())
-      return false;
-
-    for (const auto &i : cxxrd->bases())
-      if (!isEmptyRecordForLayout(context, i.getType()))
-        return false;
-  }
-
-  for (const auto *i : rd->fields())
-    if (!isEmptyFieldForLayout(context, i))
-      return false;
-
-  return true;
-}
-
-bool clang::CIRGen::isEmptyFieldForLayout(const ASTContext &context,
-                                          const FieldDecl *fd) {
-  if (fd->isZeroLengthBitField())
-    return true;
-
-  if (fd->isUnnamedBitField())
-    return false;
-
-  return isEmptyRecordForLayout(context, fd->getType());
-}
-
 bool clang::CIRGen::isEmptyRecordForABI(const ASTContext &context, QualType t) {
   const auto *rd = t->getAsRecordDecl();
   if (!rd)
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h
index 5f380026e025d..e094fa53561f5 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.h
+++ b/clang/lib/CIR/CodeGen/TargetInfo.h
@@ -21,21 +21,15 @@
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIROpsEnums.h"
+#include "clang/CodeGenUtils/RecordLayoutUtils.h"
 
 #include <memory>
 #include <utility>
 
 namespace clang::CIRGen {
 
-/// isEmptyFieldForLayout - Return true if the field is "empty", that is,
-/// either a zero-width bit-field or an isEmptyRecordForLayout.
-bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd);
-
-/// isEmptyRecordForLayout - Return true if a structure contains only empty
-/// base classes (per  isEmptyRecordForLayout) and fields (per
-/// isEmptyFieldForLayout). Note, C++ record fields are considered empty
-/// if the [[no_unique_address]] attribute would have made them empty.
-bool isEmptyRecordForLayout(const ASTContext &context, QualType t);
+using CodeGenUtils::isEmptyFieldForLayout;
+using CodeGenUtils::isEmptyRecordForLayout;
 
 /// isEmptyFieldForABI - Return true if the field is "empty", that is, it is a
 /// zero-width bit-field or an (array of) empty record(s).  An unnamed
diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp
index 887a645a4783a..23b6b7e8200da 100644
--- a/clang/lib/CodeGen/ABIInfoImpl.cpp
+++ b/clang/lib/CodeGen/ABIInfoImpl.cpp
@@ -302,39 +302,6 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
   return true;
 }
 
-bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context,
-                                    const FieldDecl *FD) {
-  if (FD->isZeroLengthBitField())
-    return true;
-
-  if (FD->isUnnamedBitField())
-    return false;
-
-  return isEmptyRecordForLayout(Context, FD->getType());
-}
-
-bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) {
-  const auto *RD = T->getAsRecordDecl();
-  if (!RD)
-    return false;
-
-  // If this is a C++ record, check the bases first.
-  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
-    if (CXXRD->isDynamicClass())
-      return false;
-
-    for (const auto &I : CXXRD->bases())
-      if (!isEmptyRecordForLayout(Context, I.getType()))
-        return false;
-  }
-
-  for (const auto *I : RD->fields())
-    if (!isEmptyFieldForLayout(Context, I))
-      return false;
-
-  return true;
-}
-
 const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {
   const auto *RD = T->getAsRecordDecl();
   if (!RD)
diff --git a/clang/lib/CodeGen/ABIInfoImpl.h b/clang/lib/CodeGen/ABIInfoImpl.h
index d9d79c6a55ddb..89ea2219096a2 100644
--- a/clang/lib/CodeGen/ABIInfoImpl.h
+++ b/clang/lib/CodeGen/ABIInfoImpl.h
@@ -11,6 +11,7 @@
 
 #include "ABIInfo.h"
 #include "CGCXXABI.h"
+#include "clang/CodeGenUtils/RecordLayoutUtils.h"
 
 namespace clang::CodeGen {
 
@@ -120,15 +121,8 @@ bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays,
 bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
                    bool AsIfNoUniqueAddr = false);
 
-/// isEmptyFieldForLayout - Return true iff the field is "empty", that is,
-/// either a zero-width bit-field or an \ref isEmptyRecordForLayout.
-bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD);
-
-/// isEmptyRecordForLayout - Return true iff a structure contains only empty
-/// base classes (per \ref isEmptyRecordForLayout) and fields (per
-/// \ref isEmptyFieldForLayout). Note, C++ record fields are considered empty
-/// if the [[no_unique_address]] attribute would have made them empty.
-bool isEmptyRecordForLayout(const ASTContext &Context, QualType T);
+using CodeGenUtils::isEmptyFieldForLayout;
+using CodeGenUtils::isEmptyRecordForLayout;
 
 /// isSingleElementStruct - Determine if a structure is a "single
 /// element struct", i.e. it has exactly one non-empty field or
diff --git a/clang/lib/CodeGenUtils/CMakeLists.txt b/clang/lib/CodeGenUtils/CMakeLists.txt
index 5839e8f2e1fe5..f46ac572a0ce9 100644
--- a/clang/lib/CodeGenUtils/CMakeLists.txt
+++ b/clang/lib/CodeGenUtils/CMakeLists.txt
@@ -11,6 +11,7 @@ add_clang_library(clangCodeGenUtils
   FunctionUtils.cpp
   ItaniumCXXABIUtils.cpp
   ModuleUtils.cpp
+  RecordLayoutUtils.cpp
 
   LINK_LIBS
   clangAST
diff --git a/clang/lib/CodeGenUtils/RecordLayoutUtils.cpp b/clang/lib/CodeGenUtils/RecordLayoutUtils.cpp
new file mode 100644
index 0000000000000..3b8d433dc8759
--- /dev/null
+++ b/clang/lib/CodeGenUtils/RecordLayoutUtils.cpp
@@ -0,0 +1,45 @@
+//===--- RecordLayoutUtils.cpp - Shared record layout queries -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGenUtils/RecordLayoutUtils.h"
+
+namespace clang::CodeGenUtils {
+
+bool isEmptyFieldForLayout(const ASTContext &Ctx, const FieldDecl *FD) {
+  if (FD->isZeroLengthBitField())
+    return true;
+
+  if (FD->isUnnamedBitField())
+    return false;
+
+  return isEmptyRecordForLayout(Ctx, FD->getType());
+}
+
+bool isEmptyRecordForLayout(const ASTContext &Ctx, QualType T) {
+  const auto *RD = T->getAsRecordDecl();
+  if (!RD)
+    return false;
+
+  // If this is a C++ record, check the bases first.
+  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+    if (CXXRD->isDynamicClass())
+      return false;
+
+    for (const auto &I : CXXRD->bases())
+      if (!isEmptyRecordForLayout(Ctx, I.getType()))
+        return false;
+  }
+
+  for (const auto *I : RD->fields())
+    if (!isEmptyFieldForLayout(Ctx, I))
+      return false;
+
+  return true;
+}
+
+} // namespace clang::CodeGenUtils



More information about the llvm-branch-commits mailing list