[llvm-branch-commits] [clang] [CIR][CodeGen][NFC] Share the Itanium __pbase_type_info flags and predicates (PR #223422)
Henrich Lauko via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Sep 29 04:22:27 PDT 2026
https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223422
>From 9cc1da38b389a29f2bcaf04a010629fd71cd325b Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Tue, 29 Sep 2026 09:55:22 +0000
Subject: [PATCH] [CIR][CodeGen][NFC] Share the Itanium __pbase_type_info flags
and predicates
Deduplicates the `__pbase_type_info` flags, `containsIncompleteClassType` and
`extractPBaseFlags` between CIR and classic CodeGen into `ItaniumCXXABIUtils.h`.
---
.../clang/CodeGenUtils/ItaniumCXXABIUtils.h | 47 ++++++++-
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 96 ++----------------
clang/lib/CodeGen/ItaniumCXXABI.cpp | 99 +------------------
clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp | 52 ++++++++++
4 files changed, 106 insertions(+), 188 deletions(-)
diff --git a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h
index 45b358ad343bb..fb125e796aa19 100644
--- a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h
+++ b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
//
-// This file holds the Itanium C++ ABI queries that both classic CodeGen and
-// CIR CodeGen need while lowering ABI constructs whose encoding the ABI
-// specifies in terms of the AST.
+// This file holds the Itanium C++ ABI type_info flag values, together with
+// the queries that both classic CodeGen and CIR CodeGen need while lowering
+// ABI constructs whose encoding the ABI specifies in terms of the AST.
//
//===----------------------------------------------------------------------===//
@@ -19,10 +19,51 @@
namespace clang::CodeGenUtils {
+/// Flags for abi::__pbase_type_info.
+enum PointerTypeInfoFlags {
+ /// PTI_Const - Type has const qualifier.
+ PTI_Const = 0x1,
+
+ /// PTI_Volatile - Type has volatile qualifier.
+ PTI_Volatile = 0x2,
+
+ /// PTI_Restrict - Type has restrict qualifier.
+ PTI_Restrict = 0x4,
+
+ /// PTI_Incomplete - Type is incomplete.
+ PTI_Incomplete = 0x8,
+
+ /// PTI_ContainingClassIncomplete - Containing class is incomplete.
+ /// (in pointer to member).
+ PTI_ContainingClassIncomplete = 0x10,
+
+ /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
+ // PTI_TransactionSafe = 0x20,
+
+ /// PTI_Noexcept - Pointee is noexcept function (C++1z).
+ PTI_Noexcept = 0x40,
+};
+
/// Compute the src2dst_offset hint as described in the Itanium C++ ABI [2.9.7].
CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src,
const CXXRecordDecl *Dst);
+/// Returns whether the given type contains an incomplete class type. This is
+/// true if
+///
+/// * The given type is an incomplete class type.
+/// * The given type is a pointer type whose pointee type contains an
+/// incomplete class type.
+/// * The given type is a member pointer type whose class is an incomplete
+/// class type.
+/// * The given type is a member pointer type whose pointee type contains an
+/// incomplete class type.
+bool containsIncompleteClassType(QualType Ty);
+
+/// Compute the flags for a __pbase_type_info, and remove the corresponding
+/// pieces from \p Type.
+unsigned extractPBaseFlags(const ASTContext &Ctx, QualType &Type);
+
} // namespace clang::CodeGenUtils
#endif // LLVM_CLANG_CODEGENUTILS_ITANIUMCXXABIUTILS_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 827f000ae573d..a4acd242eee1a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -641,31 +641,6 @@ class CIRGenItaniumRTTIBuilder {
// TODO(cir): Will be removed after sharing them with the classical codegen
namespace {
-// Pointer type info flags.
-enum {
- /// PTI_Const - Type has const qualifier.
- PTI_Const = 0x1,
-
- /// PTI_Volatile - Type has volatile qualifier.
- PTI_Volatile = 0x2,
-
- /// PTI_Restrict - Type has restrict qualifier.
- PTI_Restrict = 0x4,
-
- /// PTI_Incomplete - Type is incomplete.
- PTI_Incomplete = 0x8,
-
- /// PTI_ContainingClassIncomplete - Containing class is incomplete.
- /// (in pointer to member).
- PTI_ContainingClassIncomplete = 0x10,
-
- /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
- // PTI_TransactionSafe = 0x20,
-
- /// PTI_Noexcept - Pointee is noexcept function (C++1z).
- PTI_Noexcept = 0x40,
-};
-
// VMI type info flags.
enum {
/// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
@@ -956,67 +931,6 @@ static bool canUseSingleInheritance(const CXXRecordDecl *rd) {
baseDecl->isDynamicClass() == rd->isDynamicClass();
}
-/// IsIncompleteClassType - Returns whether the given record type is incomplete.
-static bool isIncompleteClassType(const RecordType *recordTy) {
- return !recordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();
-}
-
-/// Returns whether the given type contains an
-/// incomplete class type. This is true if
-///
-/// * The given type is an incomplete class type.
-/// * The given type is a pointer type whose pointee type contains an
-/// incomplete class type.
-/// * The given type is a member pointer type whose class is an incomplete
-/// class type.
-/// * The given type is a member pointer type whoise pointee type contains an
-/// incomplete class type.
-/// is an indirect or direct pointer to an incomplete class type.
-static bool containsIncompleteClassType(QualType ty) {
- if (const auto *recordTy = dyn_cast<RecordType>(ty)) {
- if (isIncompleteClassType(recordTy))
- return true;
- }
-
- if (const auto *pointerTy = dyn_cast<PointerType>(ty))
- return containsIncompleteClassType(pointerTy->getPointeeType());
-
- if (const auto *memberPointerTy = dyn_cast<MemberPointerType>(ty)) {
- // Check if the class type is incomplete.
- if (!memberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
- return true;
-
- return containsIncompleteClassType(memberPointerTy->getPointeeType());
- }
-
- return false;
-}
-
-static unsigned extractPBaseFlags(const ASTContext &ctx, QualType &ty) {
- unsigned flags = 0;
-
- if (ty.isConstQualified())
- flags |= PTI_Const;
- if (ty.isVolatileQualified())
- flags |= PTI_Volatile;
- if (ty.isRestrictQualified())
- flags |= PTI_Restrict;
-
- ty = ty.getUnqualifiedType();
-
- if (containsIncompleteClassType(ty))
- flags |= PTI_Incomplete;
-
- if (const auto *proto = ty->getAs<FunctionProtoType>()) {
- if (proto->isNothrow()) {
- flags |= PTI_Noexcept;
- ty = ctx.getFunctionTypeWithExceptionSpec(ty, EST_None);
- }
- }
-
- return flags;
-}
-
const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) {
// abi::__class_type_info.
static const char *const classTypeInfo =
@@ -1130,7 +1044,7 @@ static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm,
// generated for the incomplete type that will not resolve to the final
// complete class RTTI (because the latter need not exist), possibly by
// making it a local static object.
- if (containsIncompleteClassType(ty))
+ if (CodeGenUtils::containsIncompleteClassType(ty))
return cir::GlobalLinkageKind::InternalLinkage;
switch (ty->getLinkage()) {
@@ -1395,7 +1309,8 @@ void CIRGenItaniumRTTIBuilder::buildPointerTypeInfo(mlir::Location loc,
// __noexcept_mask = 0x40
// };
// };
- const unsigned int flags = extractPBaseFlags(cgm.getASTContext(), ty);
+ const unsigned int flags =
+ CodeGenUtils::extractPBaseFlags(cgm.getASTContext(), ty);
mlir::Type unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy);
mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags);
@@ -1418,11 +1333,12 @@ void CIRGenItaniumRTTIBuilder::buildPointerToMemberTypeInfo(
// };
QualType pointeeTy = ty->getPointeeType();
- unsigned flags = extractPBaseFlags(cgm.getASTContext(), pointeeTy);
+ unsigned flags =
+ CodeGenUtils::extractPBaseFlags(cgm.getASTContext(), pointeeTy);
const auto *rd = ty->getMostRecentCXXRecordDecl();
if (!rd->hasDefinition())
- flags |= PTI_ContainingClassIncomplete;
+ flags |= CodeGenUtils::PTI_ContainingClassIncomplete;
mlir::Type unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy);
mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags);
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 6dbf3fbbb0b12..f97871a3a2523 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3545,31 +3545,6 @@ class ItaniumRTTIBuilder {
ItaniumRTTIBuilder(const ItaniumCXXABI &ABI)
: CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {}
- // Pointer type info flags.
- enum {
- /// PTI_Const - Type has const qualifier.
- PTI_Const = 0x1,
-
- /// PTI_Volatile - Type has volatile qualifier.
- PTI_Volatile = 0x2,
-
- /// PTI_Restrict - Type has restrict qualifier.
- PTI_Restrict = 0x4,
-
- /// PTI_Incomplete - Type is incomplete.
- PTI_Incomplete = 0x8,
-
- /// PTI_ContainingClassIncomplete - Containing class is incomplete.
- /// (in pointer to member).
- PTI_ContainingClassIncomplete = 0x10,
-
- /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
- //PTI_TransactionSafe = 0x20,
-
- /// PTI_Noexcept - Pointee is noexcept function (C++1z).
- PTI_Noexcept = 0x40,
- };
-
// VMI type info flags.
enum {
/// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
@@ -3862,43 +3837,6 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
return false;
}
-/// IsIncompleteClassType - Returns whether the given record type is incomplete.
-static bool IsIncompleteClassType(const RecordType *RecordTy) {
- return !RecordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();
-}
-
-/// ContainsIncompleteClassType - Returns whether the given type contains an
-/// incomplete class type. This is true if
-///
-/// * The given type is an incomplete class type.
-/// * The given type is a pointer type whose pointee type contains an
-/// incomplete class type.
-/// * The given type is a member pointer type whose class is an incomplete
-/// class type.
-/// * The given type is a member pointer type whoise pointee type contains an
-/// incomplete class type.
-/// is an indirect or direct pointer to an incomplete class type.
-static bool ContainsIncompleteClassType(QualType Ty) {
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- if (IsIncompleteClassType(RecordTy))
- return true;
- }
-
- if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
- return ContainsIncompleteClassType(PointerTy->getPointeeType());
-
- if (const MemberPointerType *MemberPointerTy =
- dyn_cast<MemberPointerType>(Ty)) {
- // Check if the class type is incomplete.
- if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
- return true;
-
- return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
- }
-
- return false;
-}
-
// CanUseSingleInheritance - Return whether the given record decl has a "single,
// public, non-virtual base at offset zero (i.e. the derived class is dynamic
// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
@@ -4100,7 +4038,7 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
// generated for the incomplete type that will not resolve to the final
// complete class RTTI (because the latter need not exist), possibly by
// making it a local static object.
- if (ContainsIncompleteClassType(Ty))
+ if (CodeGenUtils::containsIncompleteClassType(Ty))
return llvm::GlobalValue::InternalLinkage;
switch (Ty->getLinkage()) {
@@ -4584,42 +4522,13 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
}
}
-/// Compute the flags for a __pbase_type_info, and remove the corresponding
-/// pieces from \p Type.
-static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type) {
- unsigned Flags = 0;
-
- if (Type.isConstQualified())
- Flags |= ItaniumRTTIBuilder::PTI_Const;
- if (Type.isVolatileQualified())
- Flags |= ItaniumRTTIBuilder::PTI_Volatile;
- if (Type.isRestrictQualified())
- Flags |= ItaniumRTTIBuilder::PTI_Restrict;
- Type = Type.getUnqualifiedType();
-
- // Itanium C++ ABI 2.9.5p7:
- // When the abi::__pbase_type_info is for a direct or indirect pointer to an
- // incomplete class type, the incomplete target type flag is set.
- if (ContainsIncompleteClassType(Type))
- Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
-
- if (auto *Proto = Type->getAs<FunctionProtoType>()) {
- if (Proto->isNothrow()) {
- Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
- Type = Ctx.getFunctionTypeWithExceptionSpec(Type, EST_None);
- }
- }
-
- return Flags;
-}
-
/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
/// used for pointer types.
void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
// Itanium C++ ABI 2.9.5p7:
// __flags is a flag word describing the cv-qualification and other
// attributes of the type pointed to
- unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
+ unsigned Flags = CodeGenUtils::extractPBaseFlags(CGM.getContext(), PointeeTy);
llvm::Type *UnsignedIntLTy =
CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
@@ -4642,11 +4551,11 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
// Itanium C++ ABI 2.9.5p7:
// __flags is a flag word describing the cv-qualification and other
// attributes of the type pointed to.
- unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
+ unsigned Flags = CodeGenUtils::extractPBaseFlags(CGM.getContext(), PointeeTy);
const auto *RD = Ty->getMostRecentCXXRecordDecl();
if (!RD->hasDefinition())
- Flags |= PTI_ContainingClassIncomplete;
+ Flags |= CodeGenUtils::PTI_ContainingClassIncomplete;
llvm::Type *UnsignedIntLTy =
CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
diff --git a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp
index 9640bd23cca54..1073be5a76acf 100644
--- a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp
+++ b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp
@@ -61,4 +61,56 @@ CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src,
return Offset;
}
+/// Returns whether the given record type is incomplete.
+static bool isIncompleteClassType(const RecordType *RecordTy) {
+ return !RecordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();
+}
+
+bool containsIncompleteClassType(QualType Ty) {
+ if (const auto *RecordTy = dyn_cast<RecordType>(Ty)) {
+ if (isIncompleteClassType(RecordTy))
+ return true;
+ }
+
+ if (const auto *PointerTy = dyn_cast<PointerType>(Ty))
+ return containsIncompleteClassType(PointerTy->getPointeeType());
+
+ if (const auto *MemberPointerTy = dyn_cast<MemberPointerType>(Ty)) {
+ // Check if the class type is incomplete.
+ if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
+ return true;
+
+ return containsIncompleteClassType(MemberPointerTy->getPointeeType());
+ }
+
+ return false;
+}
+
+unsigned extractPBaseFlags(const ASTContext &Ctx, QualType &Type) {
+ unsigned Flags = 0;
+
+ if (Type.isConstQualified())
+ Flags |= PTI_Const;
+ if (Type.isVolatileQualified())
+ Flags |= PTI_Volatile;
+ if (Type.isRestrictQualified())
+ Flags |= PTI_Restrict;
+ Type = Type.getUnqualifiedType();
+
+ // Itanium C++ ABI 2.9.5p7:
+ // When the abi::__pbase_type_info is for a direct or indirect pointer to an
+ // incomplete class type, the incomplete target type flag is set.
+ if (containsIncompleteClassType(Type))
+ Flags |= PTI_Incomplete;
+
+ if (auto *Proto = Type->getAs<FunctionProtoType>()) {
+ if (Proto->isNothrow()) {
+ Flags |= PTI_Noexcept;
+ Type = Ctx.getFunctionTypeWithExceptionSpec(Type, EST_None);
+ }
+ }
+
+ return Flags;
+}
+
} // namespace clang::CodeGenUtils
More information about the llvm-branch-commits
mailing list