[llvm-branch-commits] [clang] [CIR][CodeGen][NFC] Extract the Itanium RTTI flags and predicates (PR #223422)

Henrich Lauko via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Sep 29 03:25:23 PDT 2026


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

>From 23f5e2f4e15d7c9d333991cf90aeef40cd896e9d 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

Both CodeGens carry the same abi::__pbase_type_info flag values, the same
containsIncompleteClassType predicate and the same extractPBaseFlags that
computes the flags from a QualType. They come out of ItaniumCXXABI.cpp, so
they join computeOffsetHint in ItaniumCXXABIUtils.h. The flag set gets a
name, PointerTypeInfoFlags, now that it lives in a public header.

CIR's copies were equivalent modulo naming. The __vmi_class_type_info and
__base_class_type_info flags and canUseSingleInheritance stay behind for
the next two patches.

No functional change intended.
---
 .../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