File: | tools/clang/lib/CodeGen/CGCXXABI.cpp |
Warning: | line 50, column 25 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===----- CGCXXABI.cpp - Interface to C++ ABIs ---------------------------===// | |||
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 an abstract class for C++ code generation. Concrete subclasses | |||
10 | // of this implement code generation for specific C++ ABIs. | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #include "CGCXXABI.h" | |||
15 | #include "CGCleanup.h" | |||
16 | ||||
17 | using namespace clang; | |||
18 | using namespace CodeGen; | |||
19 | ||||
20 | CGCXXABI::~CGCXXABI() { } | |||
21 | ||||
22 | void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { | |||
23 | DiagnosticsEngine &Diags = CGF.CGM.getDiags(); | |||
24 | unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, | |||
25 | "cannot yet compile %0 in this ABI"); | |||
26 | Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()), | |||
27 | DiagID) | |||
28 | << S; | |||
29 | } | |||
30 | ||||
31 | llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) { | |||
32 | return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T)); | |||
33 | } | |||
34 | ||||
35 | llvm::Type * | |||
36 | CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { | |||
37 | return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); | |||
38 | } | |||
39 | ||||
40 | CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( | |||
41 | CodeGenFunction &CGF, const Expr *E, Address This, | |||
42 | llvm::Value *&ThisPtrForCall, | |||
43 | llvm::Value *MemPtr, const MemberPointerType *MPT) { | |||
44 | ErrorUnsupportedABI(CGF, "calls through member pointers"); | |||
45 | ||||
46 | ThisPtrForCall = This.getPointer(); | |||
47 | const FunctionProtoType *FPT = | |||
48 | MPT->getPointeeType()->getAs<FunctionProtoType>(); | |||
| ||||
49 | const CXXRecordDecl *RD = | |||
50 | cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); | |||
| ||||
51 | llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( | |||
52 | CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); | |||
53 | llvm::Constant *FnPtr = llvm::Constant::getNullValue(FTy->getPointerTo()); | |||
54 | return CGCallee::forDirect(FnPtr, FPT); | |||
55 | } | |||
56 | ||||
57 | llvm::Value * | |||
58 | CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, | |||
59 | Address Base, llvm::Value *MemPtr, | |||
60 | const MemberPointerType *MPT) { | |||
61 | ErrorUnsupportedABI(CGF, "loads of member pointers"); | |||
62 | llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType()) | |||
63 | ->getPointerTo(Base.getAddressSpace()); | |||
64 | return llvm::Constant::getNullValue(Ty); | |||
65 | } | |||
66 | ||||
67 | llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, | |||
68 | const CastExpr *E, | |||
69 | llvm::Value *Src) { | |||
70 | ErrorUnsupportedABI(CGF, "member function pointer conversions"); | |||
71 | return GetBogusMemberPointer(E->getType()); | |||
72 | } | |||
73 | ||||
74 | llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E, | |||
75 | llvm::Constant *Src) { | |||
76 | return GetBogusMemberPointer(E->getType()); | |||
77 | } | |||
78 | ||||
79 | llvm::Value * | |||
80 | CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, | |||
81 | llvm::Value *L, | |||
82 | llvm::Value *R, | |||
83 | const MemberPointerType *MPT, | |||
84 | bool Inequality) { | |||
85 | ErrorUnsupportedABI(CGF, "member function pointer comparison"); | |||
86 | return CGF.Builder.getFalse(); | |||
87 | } | |||
88 | ||||
89 | llvm::Value * | |||
90 | CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, | |||
91 | llvm::Value *MemPtr, | |||
92 | const MemberPointerType *MPT) { | |||
93 | ErrorUnsupportedABI(CGF, "member function pointer null testing"); | |||
94 | return CGF.Builder.getFalse(); | |||
95 | } | |||
96 | ||||
97 | llvm::Constant * | |||
98 | CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { | |||
99 | return GetBogusMemberPointer(QualType(MPT, 0)); | |||
100 | } | |||
101 | ||||
102 | llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { | |||
103 | return GetBogusMemberPointer(CGM.getContext().getMemberPointerType( | |||
104 | MD->getType(), MD->getParent()->getTypeForDecl())); | |||
105 | } | |||
106 | ||||
107 | llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, | |||
108 | CharUnits offset) { | |||
109 | return GetBogusMemberPointer(QualType(MPT, 0)); | |||
110 | } | |||
111 | ||||
112 | llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) { | |||
113 | return GetBogusMemberPointer(MPT); | |||
114 | } | |||
115 | ||||
116 | bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) { | |||
117 | // Fake answer. | |||
118 | return true; | |||
119 | } | |||
120 | ||||
121 | void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { | |||
122 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); | |||
123 | ||||
124 | // FIXME: I'm not entirely sure I like using a fake decl just for code | |||
125 | // generation. Maybe we can come up with a better way? | |||
126 | auto *ThisDecl = ImplicitParamDecl::Create( | |||
127 | CGM.getContext(), nullptr, MD->getLocation(), | |||
128 | &CGM.getContext().Idents.get("this"), MD->getThisType(), | |||
129 | ImplicitParamDecl::CXXThis); | |||
130 | params.push_back(ThisDecl); | |||
131 | CGF.CXXABIThisDecl = ThisDecl; | |||
132 | ||||
133 | // Compute the presumed alignment of 'this', which basically comes | |||
134 | // down to whether we know it's a complete object or not. | |||
135 | auto &Layout = CGF.getContext().getASTRecordLayout(MD->getParent()); | |||
136 | if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case | |||
137 | MD->getParent()->hasAttr<FinalAttr>() || | |||
138 | !isThisCompleteObject(CGF.CurGD)) { | |||
139 | CGF.CXXABIThisAlignment = Layout.getAlignment(); | |||
140 | } else { | |||
141 | CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment(); | |||
142 | } | |||
143 | } | |||
144 | ||||
145 | llvm::Value *CGCXXABI::loadIncomingCXXThis(CodeGenFunction &CGF) { | |||
146 | return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)), | |||
147 | "this"); | |||
148 | } | |||
149 | ||||
150 | void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr) { | |||
151 | /// Initialize the 'this' slot. | |||
152 | assert(getThisDecl(CGF) && "no 'this' variable for function")((getThisDecl(CGF) && "no 'this' variable for function" ) ? static_cast<void> (0) : __assert_fail ("getThisDecl(CGF) && \"no 'this' variable for function\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/CodeGen/CGCXXABI.cpp" , 152, __PRETTY_FUNCTION__)); | |||
153 | CGF.CXXABIThisValue = ThisPtr; | |||
154 | } | |||
155 | ||||
156 | void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, | |||
157 | RValue RV, QualType ResultType) { | |||
158 | CGF.EmitReturnOfRValue(RV, ResultType); | |||
159 | } | |||
160 | ||||
161 | CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { | |||
162 | if (!requiresArrayCookie(expr)) | |||
163 | return CharUnits::Zero(); | |||
164 | return getArrayCookieSizeImpl(expr->getAllocatedType()); | |||
165 | } | |||
166 | ||||
167 | CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) { | |||
168 | // BOGUS | |||
169 | return CharUnits::Zero(); | |||
170 | } | |||
171 | ||||
172 | Address CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, | |||
173 | Address NewPtr, | |||
174 | llvm::Value *NumElements, | |||
175 | const CXXNewExpr *expr, | |||
176 | QualType ElementType) { | |||
177 | // Should never be called. | |||
178 | ErrorUnsupportedABI(CGF, "array cookie initialization"); | |||
179 | return Address::invalid(); | |||
180 | } | |||
181 | ||||
182 | bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, | |||
183 | QualType elementType) { | |||
184 | // If the class's usual deallocation function takes two arguments, | |||
185 | // it needs a cookie. | |||
186 | if (expr->doesUsualArrayDeleteWantSize()) | |||
187 | return true; | |||
188 | ||||
189 | return elementType.isDestructedType(); | |||
190 | } | |||
191 | ||||
192 | bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { | |||
193 | // If the class's usual deallocation function takes two arguments, | |||
194 | // it needs a cookie. | |||
195 | if (expr->doesUsualArrayDeleteWantSize()) | |||
196 | return true; | |||
197 | ||||
198 | return expr->getAllocatedType().isDestructedType(); | |||
199 | } | |||
200 | ||||
201 | void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, | |||
202 | const CXXDeleteExpr *expr, QualType eltTy, | |||
203 | llvm::Value *&numElements, | |||
204 | llvm::Value *&allocPtr, CharUnits &cookieSize) { | |||
205 | // Derive a char* in the same address space as the pointer. | |||
206 | ptr = CGF.Builder.CreateElementBitCast(ptr, CGF.Int8Ty); | |||
207 | ||||
208 | // If we don't need an array cookie, bail out early. | |||
209 | if (!requiresArrayCookie(expr, eltTy)) { | |||
210 | allocPtr = ptr.getPointer(); | |||
211 | numElements = nullptr; | |||
212 | cookieSize = CharUnits::Zero(); | |||
213 | return; | |||
214 | } | |||
215 | ||||
216 | cookieSize = getArrayCookieSizeImpl(eltTy); | |||
217 | Address allocAddr = | |||
218 | CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); | |||
219 | allocPtr = allocAddr.getPointer(); | |||
220 | numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); | |||
221 | } | |||
222 | ||||
223 | llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, | |||
224 | Address ptr, | |||
225 | CharUnits cookieSize) { | |||
226 | ErrorUnsupportedABI(CGF, "reading a new[] cookie"); | |||
227 | return llvm::ConstantInt::get(CGF.SizeTy, 0); | |||
228 | } | |||
229 | ||||
230 | /// Returns the adjustment, in bytes, required for the given | |||
231 | /// member-pointer operation. Returns null if no adjustment is | |||
232 | /// required. | |||
233 | llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) { | |||
234 | assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||((E->getCastKind() == CK_DerivedToBaseMemberPointer || E-> getCastKind() == CK_BaseToDerivedMemberPointer) ? static_cast <void> (0) : __assert_fail ("E->getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/CodeGen/CGCXXABI.cpp" , 235, __PRETTY_FUNCTION__)) | |||
235 | E->getCastKind() == CK_BaseToDerivedMemberPointer)((E->getCastKind() == CK_DerivedToBaseMemberPointer || E-> getCastKind() == CK_BaseToDerivedMemberPointer) ? static_cast <void> (0) : __assert_fail ("E->getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/CodeGen/CGCXXABI.cpp" , 235, __PRETTY_FUNCTION__)); | |||
236 | ||||
237 | QualType derivedType; | |||
238 | if (E->getCastKind() == CK_DerivedToBaseMemberPointer) | |||
239 | derivedType = E->getSubExpr()->getType(); | |||
240 | else | |||
241 | derivedType = E->getType(); | |||
242 | ||||
243 | const CXXRecordDecl *derivedClass = | |||
244 | derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl(); | |||
245 | ||||
246 | return CGM.GetNonVirtualBaseClassOffset(derivedClass, | |||
247 | E->path_begin(), | |||
248 | E->path_end()); | |||
249 | } | |||
250 | ||||
251 | CharUnits CGCXXABI::getMemberPointerPathAdjustment(const APValue &MP) { | |||
252 | // TODO: Store base specifiers in APValue member pointer paths so we can | |||
253 | // easily reuse CGM.GetNonVirtualBaseClassOffset(). | |||
254 | const ValueDecl *MPD = MP.getMemberPointerDecl(); | |||
255 | CharUnits ThisAdjustment = CharUnits::Zero(); | |||
256 | ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath(); | |||
257 | bool DerivedMember = MP.isMemberPointerToDerivedMember(); | |||
258 | const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext()); | |||
259 | for (unsigned I = 0, N = Path.size(); I != N; ++I) { | |||
260 | const CXXRecordDecl *Base = RD; | |||
261 | const CXXRecordDecl *Derived = Path[I]; | |||
262 | if (DerivedMember) | |||
263 | std::swap(Base, Derived); | |||
264 | ThisAdjustment += | |||
265 | getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base); | |||
266 | RD = Path[I]; | |||
267 | } | |||
268 | if (DerivedMember) | |||
269 | ThisAdjustment = -ThisAdjustment; | |||
270 | return ThisAdjustment; | |||
271 | } | |||
272 | ||||
273 | llvm::BasicBlock * | |||
274 | CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, | |||
275 | const CXXRecordDecl *RD) { | |||
276 | if (CGM.getTarget().getCXXABI().hasConstructorVariants()) | |||
277 | llvm_unreachable("shouldn't be called in this ABI")::llvm::llvm_unreachable_internal("shouldn't be called in this ABI" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/CodeGen/CGCXXABI.cpp" , 277); | |||
278 | ||||
279 | ErrorUnsupportedABI(CGF, "complete object detection in ctor"); | |||
280 | return nullptr; | |||
281 | } | |||
282 | ||||
283 | void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, | |||
284 | const CXXDestructorDecl *Dtor, | |||
285 | CXXDtorType DT) const { | |||
286 | // Assume the base C++ ABI has no special rules for destructor variants. | |||
287 | CGM.setDLLImportDLLExport(GV, Dtor); | |||
288 | } | |||
289 | ||||
290 | llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage( | |||
291 | GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { | |||
292 | // Delegate back to CGM by default. | |||
293 | return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, | |||
294 | /*IsConstantVariable=*/false); | |||
295 | } | |||
296 | ||||
297 | bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) { | |||
298 | return false; | |||
299 | } | |||
300 | ||||
301 | llvm::CallInst * | |||
302 | CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF, | |||
303 | llvm::Value *Exn) { | |||
304 | // Just call std::terminate and ignore the violating exception. | |||
305 | return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn()); | |||
306 | } | |||
307 | ||||
308 | CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() { | |||
309 | return CatchTypeInfo{nullptr, 0}; | |||
310 | } | |||
311 | ||||
312 | std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) { | |||
313 | return std::vector<CharUnits>(); | |||
314 | } |