clang 24.0.0git
ItaniumCXXABIUtils.cpp
Go to the documentation of this file.
1//===--- ItaniumCXXABIUtils.cpp - Shared Itanium C++ ABI queries ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
12
13namespace clang::CodeGenUtils {
14
16 const CXXRecordDecl *Dst) {
17 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18 /*DetectVirtual=*/false);
19
20 // If Dst is not derived from Src we can skip the whole computation below and
21 // return that Src is not a public base of Dst. Record all inheritance paths.
22 if (!Dst->isDerivedFrom(Src, Paths))
23 return CharUnits::fromQuantity(-2ULL);
24
25 unsigned NumPublicPaths = 0;
26 CharUnits Offset;
27
28 // Now walk all possible inheritance paths.
29 for (const CXXBasePath &Path : Paths) {
30 if (Path.Access != AS_public) // Ignore non-public inheritance.
31 continue;
32
33 ++NumPublicPaths;
34
35 for (const CXXBasePathElement &PathElement : Path) {
36 // If the path contains a virtual base class we can't give any hint.
37 // -1: no hint.
38 if (PathElement.Base->isVirtual())
39 return CharUnits::fromQuantity(-1ULL);
40
41 if (NumPublicPaths > 1) // Won't use offsets, skip computation.
42 continue;
43
44 // Accumulate the base class offsets.
45 const ASTRecordLayout &L = Ctx.getASTRecordLayout(PathElement.Class);
46 Offset += L.getBaseClassOffset(
47 PathElement.Base->getType()->getAsCXXRecordDecl());
48 }
49 }
50
51 // -2: Src is not a public base of Dst.
52 if (NumPublicPaths == 0)
53 return CharUnits::fromQuantity(-2ULL);
54
55 // -3: Src is a multiple public base type but never a virtual base type.
56 if (NumPublicPaths > 1)
57 return CharUnits::fromQuantity(-3ULL);
58
59 // Otherwise, the Src type is a unique public nonvirtual base type of Dst.
60 // Return the offset of Src from the origin of Dst.
61 return Offset;
62}
63
65 // Check the number of bases.
66 if (RD->getNumBases() != 1)
67 return false;
68
69 // Get the base.
71
72 // Check that the base is not virtual.
73 if (Base->isVirtual())
74 return false;
75
76 // Check that the base is public.
77 if (Base->getAccessSpecifier() != AS_public)
78 return false;
79
80 // Check that the class is dynamic iff the base is.
81 auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
82 return BaseDecl->isEmpty() ||
83 BaseDecl->isDynamicClass() == RD->isDynamicClass();
84}
85
86namespace {
87/// Contains virtual and non-virtual bases seen when traversing a class
88/// hierarchy.
89struct SeenBases {
92};
93} // namespace
94
96 SeenBases &Bases) {
97 unsigned Flags = 0;
98
99 auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
100 if (Base->isVirtual()) {
101 // Mark the virtual base as seen.
102 if (!Bases.VirtualBases.insert(BaseDecl).second) {
103 // If this virtual base has been seen before, then the class is diamond
104 // shaped.
105 Flags |= VMI_DiamondShaped;
106 } else {
107 if (Bases.NonVirtualBases.count(BaseDecl))
108 Flags |= VMI_NonDiamondRepeat;
109 }
110 } else {
111 // Mark the non-virtual base as seen.
112 if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
113 // If this non-virtual base has been seen before, then the class has non-
114 // diamond shaped repeated inheritance.
115 Flags |= VMI_NonDiamondRepeat;
116 } else {
117 if (Bases.VirtualBases.count(BaseDecl))
118 Flags |= VMI_NonDiamondRepeat;
119 }
120 }
121
122 // Walk all bases.
123 for (const auto &I : BaseDecl->bases())
124 Flags |= computeVMIClassTypeInfoFlags(&I, Bases);
125
126 return Flags;
127}
128
130 unsigned Flags = 0;
131 SeenBases Bases;
132
133 // Walk all bases.
134 for (const auto &I : RD->bases())
135 Flags |= computeVMIClassTypeInfoFlags(&I, Bases);
136
137 return Flags;
138}
139
140/// Returns whether the given record type is incomplete.
141static bool isIncompleteClassType(const RecordType *RecordTy) {
142 return !RecordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();
143}
144
146 if (const auto *RecordTy = dyn_cast<RecordType>(Ty)) {
147 if (isIncompleteClassType(RecordTy))
148 return true;
149 }
150
151 if (const auto *PointerTy = dyn_cast<PointerType>(Ty))
152 return containsIncompleteClassType(PointerTy->getPointeeType());
153
154 if (const auto *MemberPointerTy = dyn_cast<MemberPointerType>(Ty)) {
155 // Check if the class type is incomplete.
156 if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
157 return true;
158
159 return containsIncompleteClassType(MemberPointerTy->getPointeeType());
160 }
161
162 return false;
163}
164
166 unsigned Flags = 0;
167
168 if (Type.isConstQualified())
169 Flags |= PTI_Const;
170 if (Type.isVolatileQualified())
171 Flags |= PTI_Volatile;
172 if (Type.isRestrictQualified())
173 Flags |= PTI_Restrict;
174 Type = Type.getUnqualifiedType();
175
176 // Itanium C++ ABI 2.9.5p7:
177 // When the abi::__pbase_type_info is for a direct or indirect pointer to an
178 // incomplete class type, the incomplete target type flag is set.
180 Flags |= PTI_Incomplete;
181
182 if (auto *Proto = Type->getAs<FunctionProtoType>()) {
183 if (Proto->isNothrow()) {
184 Flags |= PTI_Noexcept;
186 }
187 }
188
189 return Flags;
190}
191
192} // namespace clang::CodeGenUtils
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getFunctionTypeWithExceptionSpec(QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) const
Get a function type and produce the equivalent function type with the specified exception specificati...
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
base_class_range bases()
Definition DeclCXX.h:609
unsigned getNumBases() const
Retrieves the number of base classes of this class.
Definition DeclCXX.h:603
base_class_iterator bases_begin()
Definition DeclCXX.h:616
const CXXBaseSpecifier * base_class_const_iterator
Iterator that traverses the base classes of a class.
Definition DeclCXX.h:521
bool isDynamicClass() const
Definition DeclCXX.h:575
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:58
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5416
A (possibly-)qualified type.
Definition TypeBase.h:938
The base class of the type hierarchy.
Definition TypeBase.h:1879
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
unsigned extractPBaseFlags(const ASTContext &Ctx, QualType &Type)
Compute the flags for a __pbase_type_info, and remove the corresponding pieces from Type.
@ VMI_NonDiamondRepeat
VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
@ VMI_DiamondShaped
VMI_DiamondShaped - Class is diamond shaped.
bool containsIncompleteClassType(QualType Ty)
Returns whether the given type contains an incomplete class type.
bool canUseSingleInheritance(const CXXRecordDecl *RD)
Return whether the given record decl has a "single, public, non-virtual base at offset zero (i....
static bool isIncompleteClassType(const RecordType *RecordTy)
Returns whether the given record type is incomplete.
unsigned computeVMIClassTypeInfoFlags(const CXXRecordDecl *RD)
Compute the value of the flags member in abi::__vmi_class_type_info.
CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src, const CXXRecordDecl *Dst)
Compute the src2dst_offset hint as described in the Itanium C++ ABI [2.9.7].
@ PTI_Restrict
PTI_Restrict - Type has restrict qualifier.
@ PTI_Const
PTI_Const - Type has const qualifier.
@ PTI_Noexcept
PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
@ PTI_Volatile
PTI_Volatile - Type has volatile qualifier.
@ PTI_Incomplete
PTI_Incomplete - Type is incomplete.
@ AS_public
Definition Specifiers.h:128
@ EST_None
no exception specification
Represents an element in a path from a derived class to a base class.