[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