/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/ItaniumCXXABI.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===------- ItaniumCXXABI.cpp - AST support for the Itanium C++ ABI ------===// |
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 | | // |
9 | | // This provides C++ AST support targeting the Itanium C++ ABI, which is |
10 | | // documented at: |
11 | | // http://www.codesourcery.com/public/cxx-abi/abi.html |
12 | | // http://www.codesourcery.com/public/cxx-abi/abi-eh.html |
13 | | // |
14 | | // It also supports the closely-related ARM C++ ABI, documented at: |
15 | | // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf |
16 | | // |
17 | | //===----------------------------------------------------------------------===// |
18 | | |
19 | | #include "CXXABI.h" |
20 | | #include "clang/AST/ASTContext.h" |
21 | | #include "clang/AST/DeclCXX.h" |
22 | | #include "clang/AST/Mangle.h" |
23 | | #include "clang/AST/MangleNumberingContext.h" |
24 | | #include "clang/AST/RecordLayout.h" |
25 | | #include "clang/AST/Type.h" |
26 | | #include "clang/Basic/TargetInfo.h" |
27 | | #include "llvm/ADT/FoldingSet.h" |
28 | | #include "llvm/ADT/iterator.h" |
29 | | |
30 | | using namespace clang; |
31 | | |
32 | | namespace { |
33 | | |
34 | | /// According to Itanium C++ ABI 5.1.2: |
35 | | /// the name of an anonymous union is considered to be |
36 | | /// the name of the first named data member found by a pre-order, |
37 | | /// depth-first, declaration-order walk of the data members of |
38 | | /// the anonymous union. |
39 | | /// If there is no such data member (i.e., if all of the data members |
40 | | /// in the union are unnamed), then there is no way for a program to |
41 | | /// refer to the anonymous union, and there is therefore no need to mangle its name. |
42 | | /// |
43 | | /// Returns the name of anonymous union VarDecl or nullptr if it is not found. |
44 | 6 | static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) { |
45 | 6 | const RecordType *RT = VD.getType()->getAs<RecordType>(); |
46 | 6 | assert(RT && "type of VarDecl is expected to be RecordType."); |
47 | 6 | assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union."); |
48 | 6 | if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) { |
49 | 5 | return FD->getIdentifier(); |
50 | 5 | } |
51 | | |
52 | 1 | return nullptr; |
53 | 1 | } |
54 | | |
55 | | /// The name of a decomposition declaration. |
56 | | struct DecompositionDeclName { |
57 | | using BindingArray = ArrayRef<const BindingDecl*>; |
58 | | |
59 | | /// Representative example of a set of bindings with these names. |
60 | | BindingArray Bindings; |
61 | | |
62 | | /// Iterators over the sequence of identifiers in the name. |
63 | | struct Iterator |
64 | | : llvm::iterator_adaptor_base<Iterator, BindingArray::const_iterator, |
65 | | std::random_access_iterator_tag, |
66 | | const IdentifierInfo *> { |
67 | 2 | Iterator(BindingArray::const_iterator It) : iterator_adaptor_base(It) {} |
68 | 1 | const IdentifierInfo *operator*() const { |
69 | 1 | return (*this->I)->getIdentifier(); |
70 | 1 | } |
71 | | }; |
72 | 1 | Iterator begin() const { return Iterator(Bindings.begin()); } |
73 | 1 | Iterator end() const { return Iterator(Bindings.end()); } |
74 | | }; |
75 | | } |
76 | | |
77 | | namespace llvm { |
78 | 144 | template<typename T> bool isDenseMapKeyEmpty(T V) { |
79 | 144 | return llvm::DenseMapInfo<T>::isEqual( |
80 | 144 | V, llvm::DenseMapInfo<T>::getEmptyKey()); |
81 | 144 | } |
82 | 6 | template<typename T> bool isDenseMapKeyTombstone(T V) { |
83 | 6 | return llvm::DenseMapInfo<T>::isEqual( |
84 | 6 | V, llvm::DenseMapInfo<T>::getTombstoneKey()); |
85 | 6 | } |
86 | | |
87 | | template<typename T> |
88 | 72 | Optional<bool> areDenseMapKeysEqualSpecialValues(T LHS, T RHS) { |
89 | 72 | bool LHSEmpty = isDenseMapKeyEmpty(LHS); |
90 | 72 | bool RHSEmpty = isDenseMapKeyEmpty(RHS); |
91 | 72 | if (LHSEmpty || RHSEmpty7 ) |
92 | 69 | return LHSEmpty && RHSEmpty65 ; |
93 | | |
94 | 3 | bool LHSTombstone = isDenseMapKeyTombstone(LHS); |
95 | 3 | bool RHSTombstone = isDenseMapKeyTombstone(RHS); |
96 | 3 | if (LHSTombstone || RHSTombstone) |
97 | 3 | return LHSTombstone && RHSTombstone0 ; |
98 | | |
99 | 0 | return None; |
100 | 0 | } |
101 | | |
102 | | template<> |
103 | | struct DenseMapInfo<DecompositionDeclName> { |
104 | | using ArrayInfo = llvm::DenseMapInfo<ArrayRef<const BindingDecl*>>; |
105 | 5 | static DecompositionDeclName getEmptyKey() { |
106 | 5 | return {ArrayInfo::getEmptyKey()}; |
107 | 5 | } |
108 | 3 | static DecompositionDeclName getTombstoneKey() { |
109 | 3 | return {ArrayInfo::getTombstoneKey()}; |
110 | 3 | } |
111 | 1 | static unsigned getHashValue(DecompositionDeclName Key) { |
112 | 1 | assert(!isEqual(Key, getEmptyKey()) && !isEqual(Key, getTombstoneKey())); |
113 | 1 | return llvm::hash_combine_range(Key.begin(), Key.end()); |
114 | 1 | } |
115 | 72 | static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) { |
116 | 72 | if (Optional<bool> Result = areDenseMapKeysEqualSpecialValues( |
117 | 72 | LHS.Bindings, RHS.Bindings)) |
118 | 72 | return *Result; |
119 | | |
120 | 0 | return LHS.Bindings.size() == RHS.Bindings.size() && |
121 | 0 | std::equal(LHS.begin(), LHS.end(), RHS.begin()); |
122 | 0 | } |
123 | | }; |
124 | | } |
125 | | |
126 | | namespace { |
127 | | |
128 | | /// Keeps track of the mangled names of lambda expressions and block |
129 | | /// literals within a particular context. |
130 | | class ItaniumNumberingContext : public MangleNumberingContext { |
131 | | ItaniumMangleContext *Mangler; |
132 | | llvm::StringMap<unsigned> LambdaManglingNumbers; |
133 | | unsigned BlockManglingNumber = 0; |
134 | | llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers; |
135 | | llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers; |
136 | | llvm::DenseMap<DecompositionDeclName, unsigned> |
137 | | DecompsitionDeclManglingNumbers; |
138 | | |
139 | | public: |
140 | 29.3k | ItaniumNumberingContext(ItaniumMangleContext *Mangler) : Mangler(Mangler) {} |
141 | | |
142 | 4.40k | unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { |
143 | 4.40k | const CXXRecordDecl *Lambda = CallOperator->getParent(); |
144 | 4.40k | assert(Lambda->isLambda()); |
145 | | |
146 | | // Computation of the <lambda-sig> is non-trivial and subtle. Rather than |
147 | | // duplicating it here, just mangle the <lambda-sig> directly. |
148 | 4.40k | llvm::SmallString<128> LambdaSig; |
149 | 4.40k | llvm::raw_svector_ostream Out(LambdaSig); |
150 | 4.40k | Mangler->mangleLambdaSig(Lambda, Out); |
151 | | |
152 | 4.40k | return ++LambdaManglingNumbers[LambdaSig]; |
153 | 4.40k | } |
154 | | |
155 | 293 | unsigned getManglingNumber(const BlockDecl *BD) override { |
156 | 293 | return ++BlockManglingNumber; |
157 | 293 | } |
158 | | |
159 | 4.08k | unsigned getStaticLocalNumber(const VarDecl *VD) override { |
160 | 4.08k | return 0; |
161 | 4.08k | } |
162 | | |
163 | | /// Variable decls are numbered by identifier. |
164 | 4.08k | unsigned getManglingNumber(const VarDecl *VD, unsigned) override { |
165 | 4.08k | if (auto *DD = dyn_cast<DecompositionDecl>(VD)) { |
166 | 1 | DecompositionDeclName Name{DD->bindings()}; |
167 | 1 | return ++DecompsitionDeclManglingNumbers[Name]; |
168 | 1 | } |
169 | | |
170 | 4.08k | const IdentifierInfo *Identifier = VD->getIdentifier(); |
171 | 4.08k | if (!Identifier) { |
172 | | // VarDecl without an identifier represents an anonymous union |
173 | | // declaration. |
174 | 6 | Identifier = findAnonymousUnionVarDeclName(*VD); |
175 | 6 | } |
176 | 4.08k | return ++VarManglingNumbers[Identifier]; |
177 | 4.08k | } |
178 | | |
179 | 29.2k | unsigned getManglingNumber(const TagDecl *TD, unsigned) override { |
180 | 29.2k | return ++TagManglingNumbers[TD->getIdentifier()]; |
181 | 29.2k | } |
182 | | }; |
183 | | |
184 | | class ItaniumCXXABI : public CXXABI { |
185 | | private: |
186 | | std::unique_ptr<MangleContext> Mangler; |
187 | | protected: |
188 | | ASTContext &Context; |
189 | | public: |
190 | | ItaniumCXXABI(ASTContext &Ctx) |
191 | 61.9k | : Mangler(Ctx.createMangleContext()), Context(Ctx) {} |
192 | | |
193 | | MemberPointerInfo |
194 | 801 | getMemberPointerInfo(const MemberPointerType *MPT) const override { |
195 | 801 | const TargetInfo &Target = Context.getTargetInfo(); |
196 | 801 | TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0); |
197 | 801 | MemberPointerInfo MPI; |
198 | 801 | MPI.Width = Target.getTypeWidth(PtrDiff); |
199 | 801 | MPI.Align = Target.getTypeAlign(PtrDiff); |
200 | 801 | MPI.HasPadding = false; |
201 | 801 | if (MPT->isMemberFunctionPointer()) |
202 | 672 | MPI.Width *= 2; |
203 | 801 | return MPI; |
204 | 801 | } |
205 | | |
206 | 2.08M | CallingConv getDefaultMethodCallConv(bool isVariadic) const override { |
207 | 2.08M | const llvm::Triple &T = Context.getTargetInfo().getTriple(); |
208 | 2.08M | if (!isVariadic && T.isWindowsGNUEnvironment()2.07M && |
209 | 7.32k | T.getArch() == llvm::Triple::x86) |
210 | 4.05k | return CC_X86ThisCall; |
211 | 2.08M | return Context.getTargetInfo().getDefaultCallingConv(); |
212 | 2.08M | } |
213 | | |
214 | | // We cheat and just check that the class has a vtable pointer, and that it's |
215 | | // only big enough to have a vtable pointer and nothing more (or less). |
216 | 1.88k | bool isNearlyEmpty(const CXXRecordDecl *RD) const override { |
217 | | |
218 | | // Check that the class has a vtable pointer. |
219 | 1.88k | if (!RD->isDynamicClass()) |
220 | 507 | return false; |
221 | | |
222 | 1.37k | const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); |
223 | 1.37k | CharUnits PointerSize = |
224 | 1.37k | Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); |
225 | 1.37k | return Layout.getNonVirtualSize() == PointerSize; |
226 | 1.37k | } |
227 | | |
228 | | const CXXConstructorDecl * |
229 | 0 | getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { |
230 | 0 | return nullptr; |
231 | 0 | } |
232 | | |
233 | | void addCopyConstructorForExceptionObject(CXXRecordDecl *RD, |
234 | 0 | CXXConstructorDecl *CD) override {} |
235 | | |
236 | | void addTypedefNameForUnnamedTagDecl(TagDecl *TD, |
237 | 145 | TypedefNameDecl *DD) override {} |
238 | | |
239 | 740k | TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { |
240 | 740k | return nullptr; |
241 | 740k | } |
242 | | |
243 | | void addDeclaratorForUnnamedTagDecl(TagDecl *TD, |
244 | 8.37k | DeclaratorDecl *DD) override {} |
245 | | |
246 | 740k | DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { |
247 | 740k | return nullptr; |
248 | 740k | } |
249 | | |
250 | | std::unique_ptr<MangleNumberingContext> |
251 | 29.3k | createMangleNumberingContext() const override { |
252 | 29.3k | return std::make_unique<ItaniumNumberingContext>( |
253 | 29.3k | cast<ItaniumMangleContext>(Mangler.get())); |
254 | 29.3k | } |
255 | | }; |
256 | | } |
257 | | |
258 | 61.9k | CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) { |
259 | 61.9k | return new ItaniumCXXABI(Ctx); |
260 | 61.9k | } |