[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
Mon Sep 21 06:36:11 PDT 2026
https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223422
>From daebac3119f7e5275ff18a9e2b88356c12557285 Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Mon, 14 Sep 2026 13:31:19 +0000
Subject: [PATCH] [CIR][CodeGen][NFC] Extract the Itanium RTTI flags and
predicates
Both CodeGens carry identical copies of the Itanium C++ ABI type_info flag
values and of the AST predicates that compute them. They come out of
ItaniumCXXABI.cpp, so they join computeOffsetHint in ItaniumCXXABIUtils.h.
The three flag sets get names (PointerTypeInfoFlags, VMIClassTypeInfoFlags,
BaseClassTypeInfoFlags) now that they live in a public header.
CIR's copy was equivalent modulo naming and integer literal spelling. The
flag block was marked "TODO(cir): Will be removed after sharing them with
the classical codegen" and canUseSingleInheritance "TODO(cir): this can
unified with LLVM codegen".
No functional change intended.
---
.../clang/CodeGenUtils/ItaniumCXXABIUtils.h | 73 +++++-
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 206 +----------------
clang/lib/CodeGen/ItaniumCXXABI.cpp | 213 +-----------------
clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp | 128 +++++++++++
4 files changed, 218 insertions(+), 402 deletions(-)
diff --git a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h
index 45b358ad343bb..9d6a20ef82ab3 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,77 @@
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,
+};
+
+/// Flags for abi::__vmi_class_type_info.
+enum VMIClassTypeInfoFlags {
+ /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
+ VMI_NonDiamondRepeat = 0x1,
+
+ /// VMI_DiamondShaped - Class is diamond shaped.
+ VMI_DiamondShaped = 0x2
+};
+
+/// Flags for abi::__base_class_type_info.
+enum BaseClassTypeInfoFlags {
+ /// BCTI_Virtual - Base class is virtual.
+ BCTI_Virtual = 0x1,
+
+ /// BCTI_Public - Base class is public.
+ BCTI_Public = 0x2
+};
+
+/// 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.
+bool canUseSingleInheritance(const CXXRecordDecl *RD);
+
/// 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);
+/// Compute the value of the flags member in abi::__vmi_class_type_info.
+unsigned computeVMIClassTypeInfoFlags(const CXXRecordDecl *RD);
+
+/// 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 59461a6c6de4a..576269b2d7424 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -622,52 +622,8 @@ class CIRGenItaniumRTTIBuilder {
};
} // namespace
-// 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.
- VMI_NonDiamondRepeat = 0x1,
-
- /// VMI_DiamondShaped - Class is diamond shaped.
- VMI_DiamondShaped = 0x2
-};
-
-// Base class type info flags.
-enum {
- /// BCTI_Virtual - Base class is virtual.
- BCTI_Virtual = 0x1,
-
- /// BCTI_Public - Base class is public.
- BCTI_Public = 0x2
-};
-
/// Given a builtin type, returns whether the type
/// info for that type is defined in the standard library.
/// TODO(cir): this can unified with LLVM codegen
@@ -859,148 +815,6 @@ static bool shouldUseExternalRttiDescriptor(CIRGenModule &cgm, QualType ty) {
return false;
}
-/// Contains virtual and non-virtual bases seen when traversing a class
-/// hierarchy.
-struct SeenBases {
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> nonVirtualBases;
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> virtualBases;
-};
-
-/// Compute the value of the flags member in abi::__vmi_class_type_info.
-///
-static unsigned computeVmiClassTypeInfoFlags(const CXXBaseSpecifier *base,
- SeenBases &bases) {
-
- unsigned flags = 0;
- auto *baseDecl = base->getType()->castAsCXXRecordDecl();
-
- if (base->isVirtual()) {
- // Mark the virtual base as seen.
- if (!bases.virtualBases.insert(baseDecl).second) {
- // If this virtual base has been seen before, then the class is diamond
- // shaped.
- flags |= VMI_DiamondShaped;
- } else {
- if (bases.nonVirtualBases.count(baseDecl))
- flags |= VMI_NonDiamondRepeat;
- }
- } else {
- // Mark the non-virtual base as seen.
- if (!bases.nonVirtualBases.insert(baseDecl).second) {
- // If this non-virtual base has been seen before, then the class has non-
- // diamond shaped repeated inheritance.
- flags |= VMI_NonDiamondRepeat;
- } else {
- if (bases.virtualBases.count(baseDecl))
- flags |= VMI_NonDiamondRepeat;
- }
- }
-
- // Walk all bases.
- for (const auto &bs : baseDecl->bases())
- flags |= computeVmiClassTypeInfoFlags(&bs, bases);
-
- return flags;
-}
-
-static unsigned computeVmiClassTypeInfoFlags(const CXXRecordDecl *rd) {
- unsigned flags = 0;
- SeenBases bases;
-
- // Walk all bases.
- for (const auto &bs : rd->bases())
- flags |= computeVmiClassTypeInfoFlags(&bs, bases);
-
- return flags;
-}
-
-// 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.
-// TODO(cir): this can unified with LLVM codegen
-static bool canUseSingleInheritance(const CXXRecordDecl *rd) {
- // Check the number of bases.
- if (rd->getNumBases() != 1)
- return false;
-
- // Get the base.
- CXXRecordDecl::base_class_const_iterator base = rd->bases_begin();
-
- // Check that the base is not virtual.
- if (base->isVirtual())
- return false;
-
- // Check that the base is public.
- if (base->getAccessSpecifier() != AS_public)
- return false;
-
- // Check that the class is dynamic iff the base is.
- auto *baseDecl = base->getType()->castAsCXXRecordDecl();
- return baseDecl->isEmpty() ||
- 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 =
@@ -1069,7 +883,7 @@ const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) {
return classTypeInfo;
}
- if (canUseSingleInheritance(rd)) {
+ if (CodeGenUtils::canUseSingleInheritance(rd)) {
return siClassTypeInfo;
}
@@ -1114,7 +928,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()) {
@@ -1283,7 +1097,7 @@ void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc,
// __flags is a word with flags describing details about the class
// structure, which may be referenced by using the __flags_masks
// enumeration. These flags refer to both direct and indirect bases.
- unsigned flags = computeVmiClassTypeInfoFlags(rd);
+ unsigned flags = CodeGenUtils::computeVMIClassTypeInfoFlags(rd);
fields.push_back(cir::IntAttr::get(unsignedIntLTy, flags));
// Itanium C++ ABI 2.9.5p6c:
@@ -1350,9 +1164,9 @@ void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc,
// The low-order byte of __offset_flags contains flags, as given by the
// masks from the enumeration __offset_flags_masks.
if (base.isVirtual())
- offsetFlags |= BCTI_Virtual;
+ offsetFlags |= CodeGenUtils::BCTI_Virtual;
if (base.getAccessSpecifier() == AS_public)
- offsetFlags |= BCTI_Public;
+ offsetFlags |= CodeGenUtils::BCTI_Public;
fields.push_back(cir::IntAttr::get(offsetFlagsLTy, offsetFlags));
}
@@ -1379,7 +1193,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);
@@ -1402,11 +1217,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);
@@ -1563,7 +1379,7 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(
break;
}
- if (canUseSingleInheritance(rd)) {
+ if (CodeGenUtils::canUseSingleInheritance(rd)) {
buildSIClassTypeInfo(loc, rd);
} else {
buildVMIClassTypeInfo(loc, rd);
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 218bf6a98cc68..b52157781fb96 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3544,49 +3544,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.
- VMI_NonDiamondRepeat = 0x1,
-
- /// VMI_DiamondShaped - Class is diamond shaped.
- VMI_DiamondShaped = 0x2
- };
-
- // Base class type info flags.
- enum {
- /// BCTI_Virtual - Base class is virtual.
- BCTI_Virtual = 0x1,
-
- /// BCTI_Public - Base class is public.
- BCTI_Public = 0x2
- };
-
/// BuildTypeInfo - Build the RTTI type info struct for the given type, or
/// link to an existing RTTI descriptor if one already exists.
llvm::Constant *BuildTypeInfo(QualType Ty);
@@ -3859,71 +3816,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.
-static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
- // Check the number of bases.
- if (RD->getNumBases() != 1)
- return false;
-
- // Get the base.
- CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
-
- // Check that the base is not virtual.
- if (Base->isVirtual())
- return false;
-
- // Check that the base is public.
- if (Base->getAccessSpecifier() != AS_public)
- return false;
-
- // Check that the class is dynamic iff the base is.
- auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
- if (!BaseDecl->isEmpty() &&
- BaseDecl->isDynamicClass() != RD->isDynamicClass())
- return false;
-
- return true;
-}
-
void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
llvm::Constant *StorageAddress) {
// abi::__class_type_info.
@@ -4000,7 +3892,7 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
if (!RD->hasDefinition() || !RD->getNumBases()) {
VTableName = ClassTypeInfo;
- } else if (CanUseSingleInheritance(RD)) {
+ } else if (CodeGenUtils::canUseSingleInheritance(RD)) {
VTableName = SIClassTypeInfo;
} else {
VTableName = VMIClassTypeInfo;
@@ -4096,7 +3988,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()) {
@@ -4288,7 +4180,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
break;
}
- if (CanUseSingleInheritance(RD))
+ if (CodeGenUtils::canUseSingleInheritance(RD))
BuildSIClassTypeInfo(RD);
else
BuildVMIClassTypeInfo(RD);
@@ -4420,64 +4312,6 @@ void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
Fields.push_back(BaseTypeInfo);
}
-namespace {
- /// SeenBases - Contains virtual and non-virtual bases seen when traversing
- /// a class hierarchy.
- struct SeenBases {
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
- };
-}
-
-/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
-/// abi::__vmi_class_type_info.
-///
-static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
- SeenBases &Bases) {
-
- unsigned Flags = 0;
-
- auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
- if (Base->isVirtual()) {
- // Mark the virtual base as seen.
- if (!Bases.VirtualBases.insert(BaseDecl).second) {
- // If this virtual base has been seen before, then the class is diamond
- // shaped.
- Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
- } else {
- if (Bases.NonVirtualBases.count(BaseDecl))
- Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
- }
- } else {
- // Mark the non-virtual base as seen.
- if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
- // If this non-virtual base has been seen before, then the class has non-
- // diamond shaped repeated inheritance.
- Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
- } else {
- if (Bases.VirtualBases.count(BaseDecl))
- Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
- }
- }
-
- // Walk all bases.
- for (const auto &I : BaseDecl->bases())
- Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
-
- return Flags;
-}
-
-static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
- unsigned Flags = 0;
- SeenBases Bases;
-
- // Walk all bases.
- for (const auto &I : RD->bases())
- Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
-
- return Flags;
-}
-
/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
/// classes with bases that do not satisfy the abi::__si_class_type_info
/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
@@ -4489,7 +4323,7 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
// __flags is a word with flags describing details about the class
// structure, which may be referenced by using the __flags_masks
// enumeration. These flags refer to both direct and indirect bases.
- unsigned Flags = ComputeVMIClassTypeInfoFlags(RD);
+ unsigned Flags = CodeGenUtils::computeVMIClassTypeInfoFlags(RD);
Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
// Itanium C++ ABI 2.9.5p6c:
@@ -4556,50 +4390,21 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
// The low-order byte of __offset_flags contains flags, as given by the
// masks from the enumeration __offset_flags_masks.
if (Base.isVirtual())
- OffsetFlags |= BCTI_Virtual;
+ OffsetFlags |= CodeGenUtils::BCTI_Virtual;
if (Base.getAccessSpecifier() == AS_public)
- OffsetFlags |= BCTI_Public;
+ OffsetFlags |= CodeGenUtils::BCTI_Public;
Fields.push_back(llvm::ConstantInt::getSigned(OffsetFlagsLTy, OffsetFlags));
}
}
-/// 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);
@@ -4622,11 +4427,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..2f22ab69d4c5a 100644
--- a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp
+++ b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp
@@ -61,4 +61,132 @@ CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src,
return Offset;
}
+bool canUseSingleInheritance(const CXXRecordDecl *RD) {
+ // Check the number of bases.
+ if (RD->getNumBases() != 1)
+ return false;
+
+ // Get the base.
+ CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
+
+ // Check that the base is not virtual.
+ if (Base->isVirtual())
+ return false;
+
+ // Check that the base is public.
+ if (Base->getAccessSpecifier() != AS_public)
+ return false;
+
+ // Check that the class is dynamic iff the base is.
+ auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
+ return BaseDecl->isEmpty() ||
+ BaseDecl->isDynamicClass() == RD->isDynamicClass();
+}
+
+namespace {
+/// Contains virtual and non-virtual bases seen when traversing a class
+/// hierarchy.
+struct SeenBases {
+ llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
+};
+} // namespace
+
+static unsigned computeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
+ SeenBases &Bases) {
+ unsigned Flags = 0;
+
+ auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
+ if (Base->isVirtual()) {
+ // Mark the virtual base as seen.
+ if (!Bases.VirtualBases.insert(BaseDecl).second) {
+ // If this virtual base has been seen before, then the class is diamond
+ // shaped.
+ Flags |= VMI_DiamondShaped;
+ } else {
+ if (Bases.NonVirtualBases.count(BaseDecl))
+ Flags |= VMI_NonDiamondRepeat;
+ }
+ } else {
+ // Mark the non-virtual base as seen.
+ if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
+ // If this non-virtual base has been seen before, then the class has non-
+ // diamond shaped repeated inheritance.
+ Flags |= VMI_NonDiamondRepeat;
+ } else {
+ if (Bases.VirtualBases.count(BaseDecl))
+ Flags |= VMI_NonDiamondRepeat;
+ }
+ }
+
+ // Walk all bases.
+ for (const auto &I : BaseDecl->bases())
+ Flags |= computeVMIClassTypeInfoFlags(&I, Bases);
+
+ return Flags;
+}
+
+unsigned computeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
+ unsigned Flags = 0;
+ SeenBases Bases;
+
+ // Walk all bases.
+ for (const auto &I : RD->bases())
+ Flags |= computeVMIClassTypeInfoFlags(&I, Bases);
+
+ return Flags;
+}
+
+/// 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