 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
77.1% |
185 / 240 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
93.3% |
224 / 240 |
| |
|
Line Coverage: |
89.8% |
406 / 452 |
| |
 |
|
 |
1 : //===--- CGExprCXX.cpp - Emit LLVM Code for C++ expressions ---------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This contains code dealing with code generation of C++ expressions
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "CodeGenFunction.h"
15 : using namespace clang;
16 : using namespace CodeGen;
17 :
18 : RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD,
19 : llvm::Value *Callee,
20 : ReturnValueSlot ReturnValue,
21 : llvm::Value *This,
22 : llvm::Value *VTT,
23 : CallExpr::const_arg_iterator ArgBeg,
24 1175: CallExpr::const_arg_iterator ArgEnd) {
25 : assert(MD->isInstance() &&
1175: branch 1 taken
0: branch 2 not taken
26 1175: "Trying to emit a member call expr on a static method!");
27 :
28 1175: const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
29 :
30 1175: CallArgList Args;
31 :
32 : // Push the this ptr.
33 : Args.push_back(std::make_pair(RValue::get(This),
34 1175: MD->getThisType(getContext())));
35 :
36 : // If there is a VTT parameter, emit it.
84: branch 0 taken
1091: branch 1 taken
37 1175: if (VTT) {
38 84: QualType T = getContext().getPointerType(getContext().VoidPtrTy);
39 84: Args.push_back(std::make_pair(RValue::get(VTT), T));
40 : }
41 :
42 : // And the rest of the call args
43 1175: EmitCallArgs(Args, FPT, ArgBeg, ArgEnd);
44 :
45 1175: QualType ResultType = FPT->getResultType();
46 : return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args,
47 : FPT->getCallConv(),
48 : FPT->getNoReturnAttr()), Callee,
49 1175: ReturnValue, Args, MD);
50 : }
51 :
52 : /// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given
53 : /// expr can be devirtualized.
54 30: static bool canDevirtualizeMemberFunctionCalls(const Expr *Base) {
17: branch 1 taken
13: branch 2 taken
55 30: if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
17: branch 2 taken
0: branch 3 not taken
56 17: if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
57 : // This is a record decl. We know the type and can devirtualize it.
58 17: return VD->getType()->isRecordType();
59 : }
60 :
61 0: return false;
62 : }
63 :
64 : // We can always devirtualize calls on temporary object expressions.
1: branch 1 taken
12: branch 2 taken
65 13: if (isa<CXXConstructExpr>(Base))
66 1: return true;
67 :
68 : // And calls on bound temporaries.
2: branch 1 taken
10: branch 2 taken
69 12: if (isa<CXXBindTemporaryExpr>(Base))
70 2: return true;
71 :
72 : // Check if this is a call expr that returns a record type.
2: branch 1 taken
8: branch 2 taken
73 10: if (const CallExpr *CE = dyn_cast<CallExpr>(Base))
74 2: return CE->getCallReturnType()->isRecordType();
75 :
76 : // We can't devirtualize the call.
77 8: return false;
78 : }
79 :
80 : RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
81 269: ReturnValueSlot ReturnValue) {
10: branch 3 taken
259: branch 4 taken
82 269: if (isa<BinaryOperator>(CE->getCallee()->IgnoreParens()))
83 10: return EmitCXXMemberPointerCallExpr(CE, ReturnValue);
84 :
85 259: const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()->IgnoreParens());
86 259: const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
87 :
2: branch 1 taken
257: branch 2 taken
88 259: if (MD->isStatic()) {
89 : // The method is static, emit it as we would a regular call.
90 2: llvm::Value *Callee = CGM.GetAddrOfFunction(MD);
91 : return EmitCall(getContext().getPointerType(MD->getType()), Callee,
92 2: ReturnValue, CE->arg_begin(), CE->arg_end());
93 : }
94 :
95 257: const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
96 :
97 : const llvm::Type *Ty =
98 : CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
99 257: FPT->isVariadic());
100 : llvm::Value *This;
101 :
51: branch 1 taken
206: branch 2 taken
102 257: if (ME->isArrow())
103 51: This = EmitScalarExpr(ME->getBase());
104 : else {
105 206: LValue BaseLV = EmitLValue(ME->getBase());
106 206: This = BaseLV.getAddress();
107 : }
108 :
0: branch 1 not taken
257: branch 2 taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
257: branch 7 taken
109 257: if (MD->isCopyAssignment() && MD->isTrivial()) {
110 : // We don't like to generate the trivial copy assignment operator when
111 : // it isn't necessary; just produce the proper effect here.
112 0: llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress();
113 0: EmitAggregateCopy(This, RHS, CE->getType());
114 0: return RValue::get(This);
115 : }
116 :
117 : // C++ [class.virtual]p12:
118 : // Explicit qualification with the scope operator (5.1) suppresses the
119 : // virtual call mechanism.
120 : //
121 : // We also don't emit a virtual call if the base expression has a record type
122 : // because then we know what the type is.
123 : llvm::Value *Callee;
3: branch 0 taken
254: branch 1 taken
124 257: if (const CXXDestructorDecl *Destructor
125 257: = dyn_cast<CXXDestructorDecl>(MD)) {
2: branch 1 taken
1: branch 2 taken
126 3: if (Destructor->isTrivial())
127 2: return RValue::get(0);
1: branch 1 taken
0: branch 2 not taken
1: branch 4 taken
0: branch 5 not taken
1: branch 8 taken
0: branch 9 not taken
1: branch 10 taken
0: branch 11 not taken
128 1: if (MD->isVirtual() && !ME->hasQualifier() &&
129 : !canDevirtualizeMemberFunctionCalls(ME->getBase())) {
130 1: Callee = BuildVirtualCall(Destructor, Dtor_Complete, This, Ty);
131 : } else {
132 0: Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty);
133 : }
30: branch 1 taken
224: branch 2 taken
28: branch 4 taken
2: branch 5 taken
20: branch 8 taken
8: branch 9 taken
20: branch 10 taken
234: branch 11 taken
134 254: } else if (MD->isVirtual() && !ME->hasQualifier() &&
135 : !canDevirtualizeMemberFunctionCalls(ME->getBase())) {
136 20: Callee = BuildVirtualCall(MD, This, Ty);
137 : } else {
138 234: Callee = CGM.GetAddrOfFunction(MD, Ty);
139 : }
140 :
141 : return EmitCXXMemberCall(MD, Callee, ReturnValue, This, /*VTT=*/0,
142 255: CE->arg_begin(), CE->arg_end());
143 : }
144 :
145 : RValue
146 : CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
147 10: ReturnValueSlot ReturnValue) {
148 : const BinaryOperator *BO =
149 10: cast<BinaryOperator>(E->getCallee()->IgnoreParens());
150 10: const Expr *BaseExpr = BO->getLHS();
151 10: const Expr *MemFnExpr = BO->getRHS();
152 :
153 : const MemberPointerType *MPT =
154 10: MemFnExpr->getType()->getAs<MemberPointerType>();
155 : const FunctionProtoType *FPT =
156 10: MPT->getPointeeType()->getAs<FunctionProtoType>();
157 : const CXXRecordDecl *RD =
158 10: cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
159 :
160 : const llvm::FunctionType *FTy =
161 : CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
162 10: FPT->isVariadic());
163 :
164 10: const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
165 :
166 : // Get the member function pointer.
167 10: llvm::Value *MemFnPtr = CreateMemTemp(MemFnExpr->getType(), "mem.fn");
168 10: EmitAggExpr(MemFnExpr, MemFnPtr, /*VolatileDest=*/false);
169 :
170 : // Emit the 'this' pointer.
171 : llvm::Value *This;
172 :
6: branch 1 taken
4: branch 2 taken
173 10: if (BO->getOpcode() == BinaryOperator::PtrMemI)
174 6: This = EmitScalarExpr(BaseExpr);
175 : else
176 4: This = EmitLValue(BaseExpr).getAddress();
177 :
178 : // Adjust it.
179 10: llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1);
180 10: Adj = Builder.CreateLoad(Adj, "mem.fn.adj");
181 :
182 10: llvm::Value *Ptr = Builder.CreateBitCast(This, Int8PtrTy, "ptr");
183 10: Ptr = Builder.CreateGEP(Ptr, Adj, "adj");
184 :
185 10: This = Builder.CreateBitCast(Ptr, This->getType(), "this");
186 :
187 10: llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr");
188 :
189 10: const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
190 :
191 10: llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn");
192 :
193 : // If the LSB in the function pointer is 1, the function pointer points to
194 : // a virtual function.
195 : llvm::Value *IsVirtual
196 : = Builder.CreateAnd(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1),
197 10: "and");
198 :
199 : IsVirtual = Builder.CreateTrunc(IsVirtual,
200 10: llvm::Type::getInt1Ty(VMContext));
201 :
202 10: llvm::BasicBlock *FnVirtual = createBasicBlock("fn.virtual");
203 10: llvm::BasicBlock *FnNonVirtual = createBasicBlock("fn.nonvirtual");
204 10: llvm::BasicBlock *FnEnd = createBasicBlock("fn.end");
205 :
206 10: Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
207 10: EmitBlock(FnVirtual);
208 :
209 : const llvm::Type *VtableTy =
210 10: FTy->getPointerTo()->getPointerTo();
211 :
212 10: llvm::Value *Vtable = Builder.CreateBitCast(This, VtableTy->getPointerTo());
213 10: Vtable = Builder.CreateLoad(Vtable);
214 :
215 10: Vtable = Builder.CreateBitCast(Vtable, Int8PtrTy);
216 : llvm::Value *VtableOffset =
217 10: Builder.CreateSub(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1));
218 :
219 10: Vtable = Builder.CreateGEP(Vtable, VtableOffset, "fn");
220 10: Vtable = Builder.CreateBitCast(Vtable, VtableTy);
221 :
222 10: llvm::Value *VirtualFn = Builder.CreateLoad(Vtable, "virtualfn");
223 :
224 10: EmitBranch(FnEnd);
225 10: EmitBlock(FnNonVirtual);
226 :
227 : // If the function is not virtual, just load the pointer.
228 10: llvm::Value *NonVirtualFn = Builder.CreateLoad(FnPtr, "fn");
229 10: NonVirtualFn = Builder.CreateIntToPtr(NonVirtualFn, FTy->getPointerTo());
230 :
231 10: EmitBlock(FnEnd);
232 :
233 10: llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
234 10: Callee->reserveOperandSpace(2);
235 10: Callee->addIncoming(VirtualFn, FnVirtual);
236 10: Callee->addIncoming(NonVirtualFn, FnNonVirtual);
237 :
238 10: CallArgList Args;
239 :
240 : QualType ThisType =
241 10: getContext().getPointerType(getContext().getTagDeclType(RD));
242 :
243 : // Push the this ptr.
244 10: Args.push_back(std::make_pair(RValue::get(This), ThisType));
245 :
246 : // And the rest of the call args
247 10: EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end());
248 10: const FunctionType *BO_FPT = BO->getType()->getAs<FunctionProtoType>();
249 : return EmitCall(CGM.getTypes().getFunctionInfo(Args, BO_FPT), Callee,
250 10: ReturnValue, Args);
251 : }
252 :
253 : RValue
254 : CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
255 : const CXXMethodDecl *MD,
256 36: ReturnValueSlot ReturnValue) {
257 : assert(MD->isInstance() &&
36: branch 1 taken
0: branch 2 not taken
258 36: "Trying to emit a member call expr on a static method!");
259 :
15: branch 1 taken
21: branch 2 taken
260 36: if (MD->isCopyAssignment()) {
261 15: const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MD->getDeclContext());
7: branch 1 taken
8: branch 2 taken
262 15: if (ClassDecl->hasTrivialCopyAssignment()) {
263 : assert(!ClassDecl->hasUserDeclaredCopyAssignment() &&
7: branch 1 taken
0: branch 2 not taken
264 7: "EmitCXXOperatorMemberCallExpr - user declared copy assignment");
265 7: llvm::Value *This = EmitLValue(E->getArg(0)).getAddress();
266 7: llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress();
267 7: QualType Ty = E->getType();
268 7: EmitAggregateCopy(This, Src, Ty);
269 7: return RValue::get(This);
270 : }
271 : }
272 :
273 29: const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
274 : const llvm::Type *Ty =
275 : CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
276 29: FPT->isVariadic());
277 :
278 29: llvm::Value *This = EmitLValue(E->getArg(0)).getAddress();
279 :
280 : llvm::Value *Callee;
1: branch 1 taken
28: branch 2 taken
1: branch 5 taken
0: branch 6 not taken
1: branch 7 taken
28: branch 8 taken
281 29: if (MD->isVirtual() && !canDevirtualizeMemberFunctionCalls(E->getArg(0)))
282 1: Callee = BuildVirtualCall(MD, This, Ty);
283 : else
284 28: Callee = CGM.GetAddrOfFunction(MD, Ty);
285 :
286 : return EmitCXXMemberCall(MD, Callee, ReturnValue, This, /*VTT=*/0,
287 29: E->arg_begin() + 1, E->arg_end());
288 : }
289 :
290 : void
291 : CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
292 792: const CXXConstructExpr *E) {
0: branch 0 not taken
792: branch 1 taken
293 792: assert(Dest && "Must have a destination!");
294 792: const CXXConstructorDecl *CD = E->getConstructor();
295 : const ConstantArrayType *Array =
296 792: getContext().getAsConstantArrayType(E->getType());
297 : // For a copy constructor, even if it is trivial, must fall thru so
298 : // its argument is code-gen'ed.
671: branch 1 taken
121: branch 2 taken
299 792: if (!CD->isCopyConstructor()) {
300 671: QualType InitType = E->getType();
27: branch 0 taken
644: branch 1 taken
301 671: if (Array)
302 27: InitType = getContext().getBaseElementType(Array);
303 : const CXXRecordDecl *RD =
304 671: cast<CXXRecordDecl>(InitType->getAs<RecordType>()->getDecl());
55: branch 1 taken
616: branch 2 taken
305 671: if (RD->hasTrivialConstructor())
306 55: return;
307 : }
308 : // Code gen optimization to eliminate copy constructor and return
309 : // its first argument instead.
737: branch 2 taken
0: branch 3 not taken
42: branch 5 taken
695: branch 6 taken
42: branch 7 taken
695: branch 8 taken
310 737: if (getContext().getLangOptions().ElideConstructors && E->isElidable()) {
311 42: const Expr *Arg = E->getArg(0);
312 :
40: branch 1 taken
2: branch 2 taken
313 42: if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
314 : assert((ICE->getCastKind() == CastExpr::CK_NoOp ||
315 : ICE->getCastKind() == CastExpr::CK_ConstructorConversion ||
316 : ICE->getCastKind() == CastExpr::CK_UserDefinedConversion) &&
14: branch 1 taken
26: branch 2 taken
1: branch 4 taken
13: branch 5 taken
1: branch 7 taken
0: branch 8 not taken
317 40: "Unknown implicit cast kind in constructor elision");
318 40: Arg = ICE->getSubExpr();
319 : }
320 :
5: branch 1 taken
37: branch 2 taken
321 42: if (const CXXFunctionalCastExpr *FCE = dyn_cast<CXXFunctionalCastExpr>(Arg))
322 5: Arg = FCE->getSubExpr();
323 :
16: branch 0 taken
26: branch 1 taken
324 42: if (const CXXBindTemporaryExpr *BindExpr =
325 42: dyn_cast<CXXBindTemporaryExpr>(Arg))
326 16: Arg = BindExpr->getSubExpr();
327 :
328 42: EmitAggExpr(Arg, Dest, false);
329 42: return;
330 : }
27: branch 0 taken
668: branch 1 taken
331 695: if (Array) {
332 27: QualType BaseElementTy = getContext().getBaseElementType(Array);
333 27: const llvm::Type *BasePtr = ConvertType(BaseElementTy);
334 27: BasePtr = llvm::PointerType::getUnqual(BasePtr);
335 : llvm::Value *BaseAddrPtr =
336 27: Builder.CreateBitCast(Dest, BasePtr);
337 :
338 : EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr,
339 27: E->arg_begin(), E->arg_end());
340 : }
341 : else
342 : // Call the constructor.
343 : EmitCXXConstructorCall(CD,
344 : E->isBaseInitialization()? Ctor_Base : Ctor_Complete,
345 : Dest,
258: branch 3 taken
410: branch 4 taken
346 668: E->arg_begin(), E->arg_end());
347 : }
348 :
349 50: static CharUnits CalculateCookiePadding(ASTContext &Ctx, QualType ElementType) {
350 50: const RecordType *RT = ElementType->getAs<RecordType>();
16: branch 0 taken
34: branch 1 taken
351 50: if (!RT)
352 16: return CharUnits::Zero();
353 :
354 34: const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
0: branch 0 not taken
34: branch 1 taken
355 34: if (!RD)
356 0: return CharUnits::Zero();
357 :
358 : // Check if the class has a trivial destructor.
6: branch 1 taken
28: branch 2 taken
359 34: if (RD->hasTrivialDestructor()) {
360 : // Check if the usual deallocation function takes two arguments.
361 6: const CXXMethodDecl *UsualDeallocationFunction = 0;
362 :
363 : DeclarationName OpName =
364 6: Ctx.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
365 : DeclContext::lookup_const_iterator Op, OpEnd;
0: branch 3 not taken
6: branch 4 taken
366 6: for (llvm::tie(Op, OpEnd) = RD->lookup(OpName);
367 : Op != OpEnd; ++Op) {
368 0: const CXXMethodDecl *Delete = cast<CXXMethodDecl>(*Op);
369 :
0: branch 1 not taken
0: branch 2 not taken
370 0: if (Delete->isUsualDeallocationFunction()) {
371 0: UsualDeallocationFunction = Delete;
372 0: break;
373 : }
374 : }
375 :
376 : // No usual deallocation function, we don't need a cookie.
6: branch 0 taken
0: branch 1 not taken
377 6: if (!UsualDeallocationFunction)
378 6: return CharUnits::Zero();
379 :
380 : // The usual deallocation function doesn't take a size_t argument, so we
381 : // don't need a cookie.
0: branch 1 not taken
0: branch 2 not taken
382 0: if (UsualDeallocationFunction->getNumParams() == 1)
383 0: return CharUnits::Zero();
384 :
385 : assert(UsualDeallocationFunction->getNumParams() == 2 &&
0: branch 1 not taken
0: branch 2 not taken
386 0: "Unexpected deallocation function type!");
387 : }
388 :
389 : // Padding is the maximum of sizeof(size_t) and alignof(ElementType)
390 : return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
391 28: Ctx.getTypeAlignInChars(ElementType));
392 : }
393 :
394 77: static CharUnits CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) {
39: branch 1 taken
38: branch 2 taken
395 77: if (!E->isArray())
396 39: return CharUnits::Zero();
397 :
398 : // No cookie is required if the new operator being used is
399 : // ::operator new[](size_t, void*).
400 38: const FunctionDecl *OperatorNew = E->getOperatorNew();
38: branch 3 taken
0: branch 4 not taken
401 38: if (OperatorNew->getDeclContext()->getLookupContext()->isFileContext()) {
0: branch 1 not taken
38: branch 2 taken
402 38: if (OperatorNew->getNumParams() == 2) {
403 : CanQualType ParamType =
404 0: Ctx.getCanonicalType(OperatorNew->getParamDecl(1)->getType());
405 :
0: branch 1 not taken
0: branch 2 not taken
406 0: if (ParamType == Ctx.VoidPtrTy)
407 0: return CharUnits::Zero();
408 : }
409 : }
410 :
411 38: return CalculateCookiePadding(Ctx, E->getAllocatedType());
412 : }
413 :
414 : static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
415 : const CXXNewExpr *E,
416 58: llvm::Value *& NumElements) {
417 58: QualType Type = E->getAllocatedType();
418 58: CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(Type);
419 58: const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
420 :
39: branch 1 taken
19: branch 2 taken
421 58: if (!E->isArray())
422 39: return llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity());
423 :
424 19: CharUnits CookiePadding = CalculateCookiePadding(CGF.getContext(), E);
425 :
426 19: Expr::EvalResult Result;
16: branch 3 taken
3: branch 4 taken
16: branch 5 taken
0: branch 6 not taken
16: branch 8 taken
0: branch 9 not taken
16: branch 10 taken
3: branch 11 taken
427 19: if (E->getArraySize()->Evaluate(Result, CGF.getContext()) &&
428 : !Result.HasSideEffects && Result.Val.isInt()) {
429 :
430 : CharUnits AllocSize =
431 16: Result.Val.getInt().getZExtValue() * TypeSize + CookiePadding;
432 :
433 : NumElements =
434 16: llvm::ConstantInt::get(SizeTy, Result.Val.getInt().getZExtValue());
435 :
436 16: return llvm::ConstantInt::get(SizeTy, AllocSize.getQuantity());
437 : }
438 :
439 : // Emit the array size expression.
440 3: NumElements = CGF.EmitScalarExpr(E->getArraySize());
441 :
442 : // Multiply with the type size.
443 : llvm::Value *V =
444 : CGF.Builder.CreateMul(NumElements,
445 : llvm::ConstantInt::get(SizeTy,
446 3: TypeSize.getQuantity()));
447 :
448 : // And add the cookie padding if necessary.
1: branch 1 taken
2: branch 2 taken
449 3: if (!CookiePadding.isZero())
450 : V = CGF.Builder.CreateAdd(V,
451 1: llvm::ConstantInt::get(SizeTy, CookiePadding.getQuantity()));
452 :
453 3: return V;
454 : }
455 :
456 : static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
457 : llvm::Value *NewPtr,
458 58: llvm::Value *NumElements) {
19: branch 1 taken
39: branch 2 taken
459 58: if (E->isArray()) {
13: branch 1 taken
6: branch 2 taken
460 19: if (CXXConstructorDecl *Ctor = E->getConstructor())
461 : CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
462 : E->constructor_arg_begin(),
463 13: E->constructor_arg_end());
464 19: return;
465 : }
466 :
467 39: QualType AllocType = E->getAllocatedType();
468 :
25: branch 1 taken
14: branch 2 taken
469 39: if (CXXConstructorDecl *Ctor = E->getConstructor()) {
470 : CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
471 : E->constructor_arg_begin(),
472 25: E->constructor_arg_end());
473 :
474 25: return;
475 : }
476 :
477 : // We have a POD type.
3: branch 1 taken
11: branch 2 taken
478 14: if (E->getNumConstructorArgs() == 0)
479 3: return;
480 :
481 : assert(E->getNumConstructorArgs() == 1 &&
11: branch 1 taken
0: branch 2 not taken
482 11: "Can only have one argument to initializer of POD type.");
483 :
484 11: const Expr *Init = E->getConstructorArg(0);
485 :
9: branch 1 taken
2: branch 2 taken
486 11: if (!CGF.hasAggregateLLVMType(AllocType))
487 : CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
488 9: AllocType.isVolatileQualified(), AllocType);
1: branch 2 taken
1: branch 3 taken
489 2: else if (AllocType->isAnyComplexType())
490 : CGF.EmitComplexExprIntoAddr(Init, NewPtr,
491 1: AllocType.isVolatileQualified());
492 : else
493 1: CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
494 : }
495 :
496 58: llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
497 58: QualType AllocType = E->getAllocatedType();
498 58: FunctionDecl *NewFD = E->getOperatorNew();
499 58: const FunctionProtoType *NewFTy = NewFD->getType()->getAs<FunctionProtoType>();
500 :
501 58: CallArgList NewArgs;
502 :
503 : // The allocation size is the first argument.
504 58: QualType SizeTy = getContext().getSizeType();
505 :
506 58: llvm::Value *NumElements = 0;
507 58: llvm::Value *AllocSize = EmitCXXNewAllocSize(*this, E, NumElements);
508 :
509 58: NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy));
510 :
511 : // Emit the rest of the arguments.
512 : // FIXME: Ideally, this should just use EmitCallArgs.
513 58: CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin();
514 :
515 : // First, use the types from the function type.
516 : // We start at 1 here because the first argument (the allocation size)
517 : // has already been emitted.
19: branch 2 taken
58: branch 3 taken
518 154: for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) {
519 19: QualType ArgType = NewFTy->getArgType(i);
520 :
521 : assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
522 : getTypePtr() ==
523 : getContext().getCanonicalType(NewArg->getType()).getTypePtr() &&
19: branch 9 taken
0: branch 10 not taken
524 19: "type mismatch in call argument!");
525 :
526 : NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
527 19: ArgType));
528 :
529 : }
530 :
531 : // Either we've emitted all the call args, or we have a call to a
532 : // variadic function.
533 : assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) &&
1: branch 2 taken
57: branch 3 taken
1: branch 5 taken
0: branch 6 not taken
534 58: "Extra arguments in non-variadic function!");
535 :
536 : // If we still have any arguments, emit them using the type of the argument.
2: branch 3 taken
58: branch 4 taken
537 60: for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end();
538 : NewArg != NewArgEnd; ++NewArg) {
539 2: QualType ArgType = NewArg->getType();
540 : NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
541 2: ArgType));
542 : }
543 :
544 : // Emit the call to new.
545 : RValue RV =
546 : EmitCall(CGM.getTypes().getFunctionInfo(NewArgs, NewFTy),
547 58: CGM.GetAddrOfFunction(NewFD), ReturnValueSlot(), NewArgs, NewFD);
548 :
549 : // If an allocation function is declared with an empty exception specification
550 : // it returns null to indicate failure to allocate storage. [expr.new]p13.
551 : // (We don't need to check for null when there's no new initializer and
552 : // we're allocating a POD type).
553 : bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() &&
10: branch 1 taken
48: branch 2 taken
7: branch 5 taken
3: branch 6 taken
6: branch 8 taken
1: branch 9 taken
554 58: !(AllocType->isPODType() && !E->hasInitializer());
555 :
556 58: llvm::BasicBlock *NewNull = 0;
557 58: llvm::BasicBlock *NewNotNull = 0;
558 58: llvm::BasicBlock *NewEnd = 0;
559 :
560 58: llvm::Value *NewPtr = RV.getScalarVal();
561 :
9: branch 0 taken
49: branch 1 taken
562 58: if (NullCheckResult) {
563 9: NewNull = createBasicBlock("new.null");
564 9: NewNotNull = createBasicBlock("new.notnull");
565 9: NewEnd = createBasicBlock("new.end");
566 :
567 : llvm::Value *IsNull =
568 : Builder.CreateICmpEQ(NewPtr,
569 : llvm::Constant::getNullValue(NewPtr->getType()),
570 9: "isnull");
571 :
572 9: Builder.CreateCondBr(IsNull, NewNull, NewNotNull);
573 9: EmitBlock(NewNotNull);
574 : }
575 :
576 58: CharUnits CookiePadding = CalculateCookiePadding(getContext(), E);
10: branch 1 taken
48: branch 2 taken
577 58: if (!CookiePadding.isZero()) {
578 : CharUnits CookieOffset =
579 10: CookiePadding - getContext().getTypeSizeInChars(SizeTy);
580 :
581 : llvm::Value *NumElementsPtr =
582 10: Builder.CreateConstInBoundsGEP1_64(NewPtr, CookieOffset.getQuantity());
583 :
584 : NumElementsPtr = Builder.CreateBitCast(NumElementsPtr,
585 10: ConvertType(SizeTy)->getPointerTo());
586 10: Builder.CreateStore(NumElements, NumElementsPtr);
587 :
588 : // Now add the padding to the new ptr.
589 : NewPtr = Builder.CreateConstInBoundsGEP1_64(NewPtr,
590 10: CookiePadding.getQuantity());
591 : }
592 :
593 58: NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));
594 :
595 58: EmitNewInitializer(*this, E, NewPtr, NumElements);
596 :
9: branch 0 taken
49: branch 1 taken
597 58: if (NullCheckResult) {
598 9: Builder.CreateBr(NewEnd);
599 9: NewNotNull = Builder.GetInsertBlock();
600 9: EmitBlock(NewNull);
601 9: Builder.CreateBr(NewEnd);
602 9: EmitBlock(NewEnd);
603 :
604 9: llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType());
605 9: PHI->reserveOperandSpace(2);
606 9: PHI->addIncoming(NewPtr, NewNotNull);
607 9: PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull);
608 :
609 9: NewPtr = PHI;
610 : }
611 :
612 58: return NewPtr;
613 : }
614 :
615 : static std::pair<llvm::Value *, llvm::Value *>
616 : GetAllocatedObjectPtrAndNumElements(CodeGenFunction &CGF,
617 16: llvm::Value *Ptr, QualType DeleteTy) {
618 16: QualType SizeTy = CGF.getContext().getSizeType();
619 16: const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
620 :
621 16: CharUnits DeleteTypeAlign = CGF.getContext().getTypeAlignInChars(DeleteTy);
622 : CharUnits CookiePadding =
623 : std::max(CGF.getContext().getTypeSizeInChars(SizeTy),
624 16: DeleteTypeAlign);
16: branch 1 taken
0: branch 2 not taken
625 16: assert(!CookiePadding.isZero() && "CookiePadding should not be 0.");
626 :
627 16: const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
628 : CharUnits CookieOffset =
629 16: CookiePadding - CGF.getContext().getTypeSizeInChars(SizeTy);
630 :
631 16: llvm::Value *AllocatedObjectPtr = CGF.Builder.CreateBitCast(Ptr, Int8PtrTy);
632 : AllocatedObjectPtr =
633 : CGF.Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr,
634 16: -CookiePadding.getQuantity());
635 :
636 : llvm::Value *NumElementsPtr =
637 : CGF.Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr,
638 16: CookieOffset.getQuantity());
639 : NumElementsPtr =
640 16: CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo());
641 :
642 16: llvm::Value *NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
643 : NumElements =
644 16: CGF.Builder.CreateIntCast(NumElements, SizeLTy, /*isSigned=*/false);
645 :
646 16: return std::make_pair(AllocatedObjectPtr, NumElements);
647 : }
648 :
649 : void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
650 : llvm::Value *Ptr,
651 41: QualType DeleteTy) {
652 : const FunctionProtoType *DeleteFTy =
653 41: DeleteFD->getType()->getAs<FunctionProtoType>();
654 :
655 41: CallArgList DeleteArgs;
656 :
657 : // Check if we need to pass the size to the delete operator.
658 41: llvm::Value *Size = 0;
659 41: QualType SizeTy;
1: branch 1 taken
40: branch 2 taken
660 41: if (DeleteFTy->getNumArgs() == 2) {
661 1: SizeTy = DeleteFTy->getArgType(1);
662 1: CharUnits DeleteTypeSize = getContext().getTypeSizeInChars(DeleteTy);
663 : Size = llvm::ConstantInt::get(ConvertType(SizeTy),
664 1: DeleteTypeSize.getQuantity());
665 : }
666 :
12: branch 1 taken
29: branch 2 taken
8: branch 6 taken
4: branch 7 taken
8: branch 8 taken
33: branch 9 taken
667 41: if (DeleteFD->getOverloadedOperator() == OO_Array_Delete &&
668 : !CalculateCookiePadding(getContext(), DeleteTy).isZero()) {
669 : // We need to get the number of elements in the array from the cookie.
670 : llvm::Value *AllocatedObjectPtr;
671 : llvm::Value *NumElements;
672 : llvm::tie(AllocatedObjectPtr, NumElements) =
673 8: GetAllocatedObjectPtrAndNumElements(*this, Ptr, DeleteTy);
674 :
675 : // Multiply the size with the number of elements.
0: branch 0 not taken
8: branch 1 taken
676 8: if (Size)
677 0: Size = Builder.CreateMul(NumElements, Size);
678 :
679 8: Ptr = AllocatedObjectPtr;
680 : }
681 :
682 41: QualType ArgTy = DeleteFTy->getArgType(0);
683 41: llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));
684 41: DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy));
685 :
1: branch 0 taken
40: branch 1 taken
686 41: if (Size)
687 1: DeleteArgs.push_back(std::make_pair(RValue::get(Size), SizeTy));
688 :
689 : // Emit the call to delete.
690 : EmitCall(CGM.getTypes().getFunctionInfo(DeleteArgs, DeleteFTy),
691 : CGM.GetAddrOfFunction(DeleteFD), ReturnValueSlot(),
692 41: DeleteArgs, DeleteFD);
693 41: }
694 :
695 20: void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
696 :
697 : // Get at the argument before we performed the implicit conversion
698 : // to void*.
699 20: const Expr *Arg = E->getArgument();
20: branch 1 taken
20: branch 2 taken
700 60: while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
20: branch 1 taken
0: branch 2 not taken
20: branch 6 taken
0: branch 7 not taken
20: branch 8 taken
0: branch 9 not taken
701 20: if (ICE->getCastKind() != CastExpr::CK_UserDefinedConversion &&
702 : ICE->getType()->isVoidPointerType())
703 20: Arg = ICE->getSubExpr();
704 : else
705 0: break;
706 : }
707 :
708 20: QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType();
709 :
710 20: llvm::Value *Ptr = EmitScalarExpr(Arg);
711 :
712 : // Null check the pointer.
713 20: llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull");
714 20: llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end");
715 :
716 : llvm::Value *IsNull =
717 : Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()),
718 20: "isnull");
719 :
720 20: Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);
721 20: EmitBlock(DeleteNotNull);
722 :
723 20: bool ShouldCallDelete = true;
724 :
725 : // Call the destructor if necessary.
14: branch 2 taken
6: branch 3 taken
726 20: if (const RecordType *RT = DeleteTy->getAs<RecordType>()) {
14: branch 2 taken
0: branch 3 not taken
727 14: if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
11: branch 1 taken
3: branch 2 taken
728 14: if (!RD->hasTrivialDestructor()) {
729 11: const CXXDestructorDecl *Dtor = RD->getDestructor(getContext());
8: branch 1 taken
3: branch 2 taken
730 11: if (E->isArrayForm()) {
731 : llvm::Value *AllocatedObjectPtr;
732 : llvm::Value *NumElements;
733 : llvm::tie(AllocatedObjectPtr, NumElements) =
734 8: GetAllocatedObjectPtrAndNumElements(*this, Ptr, DeleteTy);
735 :
736 8: EmitCXXAggrDestructorCall(Dtor, NumElements, Ptr);
0: branch 1 not taken
3: branch 2 taken
737 3: } else if (Dtor->isVirtual()) {
738 : const llvm::Type *Ty =
739 : CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor),
740 0: /*isVariadic=*/false);
741 :
742 0: llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
743 : EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, /*VTT=*/0,
744 0: 0, 0);
745 :
746 : // The dtor took care of deleting the object.
747 0: ShouldCallDelete = false;
748 : } else
749 3: EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr);
750 : }
751 : }
752 : }
753 :
20: branch 0 taken
0: branch 1 not taken
754 20: if (ShouldCallDelete)
755 20: EmitDeleteCall(E->getOperatorDelete(), Ptr, DeleteTy);
756 :
757 20: EmitBlock(DeleteEnd);
758 20: }
759 :
760 68: llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
761 68: QualType Ty = E->getType();
762 68: const llvm::Type *LTy = ConvertType(Ty)->getPointerTo();
763 :
67: branch 1 taken
1: branch 2 taken
764 68: if (E->isTypeOperand()) {
765 : llvm::Constant *TypeInfo =
766 67: CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand());
767 67: return Builder.CreateBitCast(TypeInfo, LTy);
768 : }
769 :
770 1: Expr *subE = E->getExprOperand();
771 1: Ty = subE->getType();
772 1: CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
773 1: Ty = CanTy.getUnqualifiedType().getNonReferenceType();
1: branch 2 taken
0: branch 3 not taken
774 1: if (const RecordType *RT = Ty->getAs<RecordType>()) {
775 1: const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
0: branch 1 not taken
1: branch 2 taken
776 1: if (RD->isPolymorphic()) {
777 : // FIXME: if subE is an lvalue do
778 0: LValue Obj = EmitLValue(subE);
779 0: llvm::Value *This = Obj.getAddress();
780 0: LTy = LTy->getPointerTo()->getPointerTo();
781 0: llvm::Value *V = Builder.CreateBitCast(This, LTy);
782 : // We need to do a zero check for *p, unless it has NonNullAttr.
783 : // FIXME: PointerType->hasAttr<NonNullAttr>()
784 0: bool CanBeZero = false;
0: branch 2 not taken
0: branch 3 not taken
785 0: if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE->IgnoreParens()))
0: branch 1 not taken
0: branch 2 not taken
786 0: if (UO->getOpcode() == UnaryOperator::Deref)
787 0: CanBeZero = true;
0: branch 0 not taken
0: branch 1 not taken
788 0: if (CanBeZero) {
789 0: llvm::BasicBlock *NonZeroBlock = createBasicBlock();
790 0: llvm::BasicBlock *ZeroBlock = createBasicBlock();
791 :
792 0: llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
793 : Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
794 0: NonZeroBlock, ZeroBlock);
795 0: EmitBlock(ZeroBlock);
796 : /// Call __cxa_bad_typeid
797 0: const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
798 : const llvm::FunctionType *FTy;
799 0: FTy = llvm::FunctionType::get(ResultType, false);
800 0: llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
801 0: Builder.CreateCall(F)->setDoesNotReturn();
802 0: Builder.CreateUnreachable();
803 0: EmitBlock(NonZeroBlock);
804 : }
805 0: V = Builder.CreateLoad(V, "vtable");
806 0: V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL);
807 0: V = Builder.CreateLoad(V);
808 0: return V;
809 : }
810 : }
811 1: return Builder.CreateBitCast(CGM.GetAddrOfRTTIDescriptor(Ty), LTy);
812 : }
813 :
814 : llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V,
815 9: const CXXDynamicCastExpr *DCE) {
816 9: QualType SrcTy = DCE->getSubExpr()->getType();
817 9: QualType DestTy = DCE->getTypeAsWritten();
818 9: QualType InnerType = DestTy->getPointeeType();
819 :
820 9: const llvm::Type *LTy = ConvertType(DCE->getType());
821 :
822 9: bool CanBeZero = false;
823 9: bool ToVoid = false;
824 9: bool ThrowOnBad = false;
8: branch 2 taken
1: branch 3 taken
825 9: if (DestTy->isPointerType()) {
826 : // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this
827 8: CanBeZero = true;
2: branch 2 taken
6: branch 3 taken
828 8: if (InnerType->isVoidType())
829 2: ToVoid = true;
830 : } else {
831 1: LTy = LTy->getPointerTo();
832 1: ThrowOnBad = true;
833 : }
834 :
1: branch 2 taken
8: branch 3 taken
0: branch 6 not taken
1: branch 7 taken
8: branch 8 taken
1: branch 9 taken
835 9: if (SrcTy->isPointerType() || SrcTy->isReferenceType())
836 8: SrcTy = SrcTy->getPointeeType();
837 9: SrcTy = SrcTy.getUnqualifiedType();
838 :
1: branch 2 taken
8: branch 3 taken
1: branch 6 taken
0: branch 7 not taken
9: branch 8 taken
0: branch 9 not taken
839 9: if (DestTy->isPointerType() || DestTy->isReferenceType())
840 9: DestTy = DestTy->getPointeeType();
841 9: DestTy = DestTy.getUnqualifiedType();
842 :
843 9: llvm::BasicBlock *ContBlock = createBasicBlock();
844 9: llvm::BasicBlock *NullBlock = 0;
845 9: llvm::BasicBlock *NonZeroBlock = 0;
8: branch 0 taken
1: branch 1 taken
846 9: if (CanBeZero) {
847 8: NonZeroBlock = createBasicBlock();
848 8: NullBlock = createBasicBlock();
849 8: Builder.CreateCondBr(Builder.CreateIsNotNull(V), NonZeroBlock, NullBlock);
850 8: EmitBlock(NonZeroBlock);
851 : }
852 :
853 9: llvm::BasicBlock *BadCastBlock = 0;
854 :
855 9: const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
856 :
857 : // See if this is a dynamic_cast(void*)
2: branch 0 taken
7: branch 1 taken
858 9: if (ToVoid) {
859 2: llvm::Value *This = V;
860 2: V = Builder.CreateBitCast(This, PtrDiffTy->getPointerTo()->getPointerTo());
861 2: V = Builder.CreateLoad(V, "vtable");
862 2: V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL);
863 2: V = Builder.CreateLoad(V, "offset to top");
864 2: This = Builder.CreateBitCast(This, llvm::Type::getInt8PtrTy(VMContext));
865 2: V = Builder.CreateInBoundsGEP(This, V);
866 2: V = Builder.CreateBitCast(V, LTy);
867 : } else {
868 : /// Call __dynamic_cast
869 7: const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext);
870 : const llvm::FunctionType *FTy;
871 7: std::vector<const llvm::Type*> ArgTys;
872 : const llvm::Type *PtrToInt8Ty
873 7: = llvm::Type::getInt8Ty(VMContext)->getPointerTo();
874 7: ArgTys.push_back(PtrToInt8Ty);
875 7: ArgTys.push_back(PtrToInt8Ty);
876 7: ArgTys.push_back(PtrToInt8Ty);
877 7: ArgTys.push_back(PtrDiffTy);
878 7: FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
879 :
880 : // FIXME: Calculate better hint.
881 7: llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL);
882 :
7: branch 2 taken
0: branch 3 not taken
883 7: assert(SrcTy->isRecordType() && "Src type must be record type!");
7: branch 2 taken
0: branch 3 not taken
884 7: assert(DestTy->isRecordType() && "Dest type must be record type!");
885 :
886 : llvm::Value *SrcArg
887 7: = CGM.GetAddrOfRTTIDescriptor(SrcTy.getUnqualifiedType());
888 : llvm::Value *DestArg
889 7: = CGM.GetAddrOfRTTIDescriptor(DestTy.getUnqualifiedType());
890 :
891 7: V = Builder.CreateBitCast(V, PtrToInt8Ty);
892 : V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"),
893 7: V, SrcArg, DestArg, hint);
894 7: V = Builder.CreateBitCast(V, LTy);
895 :
1: branch 0 taken
6: branch 1 taken
896 7: if (ThrowOnBad) {
897 1: BadCastBlock = createBasicBlock();
898 :
899 1: Builder.CreateCondBr(Builder.CreateIsNotNull(V), ContBlock, BadCastBlock);
900 1: EmitBlock(BadCastBlock);
901 : /// Call __cxa_bad_cast
902 1: ResultType = llvm::Type::getVoidTy(VMContext);
903 : const llvm::FunctionType *FBadTy;
904 1: FBadTy = llvm::FunctionType::get(ResultType, false);
905 1: llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast");
906 1: Builder.CreateCall(F)->setDoesNotReturn();
907 1: Builder.CreateUnreachable();
908 7: }
909 : }
910 :
8: branch 0 taken
1: branch 1 taken
911 9: if (CanBeZero) {
912 8: Builder.CreateBr(ContBlock);
913 8: EmitBlock(NullBlock);
914 8: Builder.CreateBr(ContBlock);
915 : }
916 9: EmitBlock(ContBlock);
8: branch 0 taken
1: branch 1 taken
917 9: if (CanBeZero) {
918 8: llvm::PHINode *PHI = Builder.CreatePHI(LTy);
919 8: PHI->reserveOperandSpace(2);
920 8: PHI->addIncoming(V, NonZeroBlock);
921 8: PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock);
922 8: V = PHI;
923 : }
924 :
925 9: return V;
926 : }
Generated: 2010-02-10 01:31 by zcov