@@ -122,82 +122,71 @@ static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) {
122
122
return CGF.CGM .CreateRuntimeFunction (FTy, " _ZSt9terminatev" );
123
123
}
124
124
125
- // CopyObject - Utility to copy an object. Calls copy constructor as necessary.
126
- // DestPtr is casted to the right type.
127
- static void CopyObject (CodeGenFunction &CGF, const Expr *E,
128
- llvm::Value *DestPtr, llvm::Value *ExceptionPtrPtr) {
129
- QualType ObjectType = E->getType ();
130
-
131
- // Store the throw exception in the exception object.
132
- if (!CGF.hasAggregateLLVMType (ObjectType)) {
133
- llvm::Value *Value = CGF.EmitScalarExpr (E);
134
- const llvm::Type *ValuePtrTy = Value->getType ()->getPointerTo ();
135
-
136
- CGF.Builder .CreateStore (Value,
137
- CGF.Builder .CreateBitCast (DestPtr, ValuePtrTy));
138
- } else {
139
- const llvm::Type *Ty = CGF.ConvertType (ObjectType)->getPointerTo ();
140
- const CXXRecordDecl *RD =
141
- cast<CXXRecordDecl>(ObjectType->getAs <RecordType>()->getDecl ());
142
-
143
- llvm::Value *This = CGF.Builder .CreateBitCast (DestPtr, Ty);
144
- if (RD->hasTrivialCopyConstructor ()) {
145
- CGF.EmitAggExpr (E, This, false );
146
- } else if (CXXConstructorDecl *CopyCtor
147
- = RD->getCopyConstructor (CGF.getContext (), 0 )) {
148
- llvm::Value *CondPtr = 0 ;
149
- if (CGF.Exceptions ) {
150
- CodeGenFunction::EHCleanupBlock Cleanup (CGF);
151
- llvm::Constant *FreeExceptionFn = getFreeExceptionFn (CGF);
152
-
153
- llvm::BasicBlock *CondBlock = CGF.createBasicBlock (" cond.free" );
154
- llvm::BasicBlock *Cont = CGF.createBasicBlock (" cont" );
155
- CondPtr = CGF.CreateTempAlloca (llvm::Type::getInt1Ty (CGF.getLLVMContext ()),
156
- " doEHfree" );
157
-
158
- CGF.Builder .CreateCondBr (CGF.Builder .CreateLoad (CondPtr),
159
- CondBlock, Cont);
160
- CGF.EmitBlock (CondBlock);
161
-
162
- // Load the exception pointer.
163
- llvm::Value *ExceptionPtr = CGF.Builder .CreateLoad (ExceptionPtrPtr);
164
- CGF.Builder .CreateCall (FreeExceptionFn, ExceptionPtr);
165
-
166
- CGF.EmitBlock (Cont);
167
- }
168
-
169
- if (CondPtr)
170
- CGF.Builder .CreateStore (llvm::ConstantInt::getTrue (CGF.getLLVMContext ()),
171
- CondPtr);
172
-
173
- llvm::Value *Src = CGF.EmitLValue (E).getAddress ();
174
-
175
- if (CondPtr)
176
- CGF.Builder .CreateStore (llvm::ConstantInt::getFalse (CGF.getLLVMContext ()),
177
- CondPtr);
178
-
179
- llvm::BasicBlock *TerminateHandler = CGF.getTerminateHandler ();
180
- llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest ();
181
- CGF.setInvokeDest (TerminateHandler);
182
-
183
- // Stolen from EmitClassAggrMemberwiseCopy
184
- llvm::Value *Callee = CGF.CGM .GetAddrOfCXXConstructor (CopyCtor,
185
- Ctor_Complete);
186
- CallArgList CallArgs;
187
- CallArgs.push_back (std::make_pair (RValue::get (This),
188
- CopyCtor->getThisType (CGF.getContext ())));
189
-
190
- // Push the Src ptr.
191
- CallArgs.push_back (std::make_pair (RValue::get (Src),
192
- CopyCtor->getParamDecl (0 )->getType ()));
193
- const FunctionProtoType *FPT
194
- = CopyCtor->getType ()->getAs <FunctionProtoType>();
195
- CGF.EmitCall (CGF.CGM .getTypes ().getFunctionInfo (CallArgs, FPT),
196
- Callee, ReturnValueSlot (), CallArgs, CopyCtor);
197
- CGF.setInvokeDest (PrevLandingPad);
198
- } else
199
- llvm_unreachable (" uncopyable object" );
125
+ // Emits an exception expression into the given location. This
126
+ // differs from EmitAnyExprToMem only in that, if a final copy-ctor
127
+ // call is required, an exception within that copy ctor causes
128
+ // std::terminate to be invoked.
129
+ static void EmitAnyExprToExn (CodeGenFunction &CGF, const Expr *E,
130
+ llvm::Value *ExnLoc) {
131
+ // We want to release the allocated exception object if this
132
+ // expression throws. We do this by pushing an EH-only cleanup
133
+ // block which, furthermore, deactivates itself after the expression
134
+ // is complete.
135
+ llvm::AllocaInst *ShouldFreeVar =
136
+ CGF.CreateTempAlloca (llvm::Type::getInt1Ty (CGF.getLLVMContext ()),
137
+ " should-free-exnobj.var" );
138
+ CGF.InitTempAlloca (ShouldFreeVar,
139
+ llvm::ConstantInt::getFalse (CGF.getLLVMContext ()));
140
+
141
+ // A variable holding the exception pointer. This is necessary
142
+ // because the throw expression does not necessarily dominate the
143
+ // cleanup, for example if it appears in a conditional expression.
144
+ llvm::AllocaInst *ExnLocVar =
145
+ CGF.CreateTempAlloca (ExnLoc->getType (), " exnobj.var" );
146
+
147
+ llvm::BasicBlock *SavedInvokeDest = CGF.getInvokeDest ();
148
+ {
149
+ CodeGenFunction::EHCleanupBlock Cleanup (CGF);
150
+ llvm::BasicBlock *FreeBB = CGF.createBasicBlock (" free-exnobj" );
151
+ llvm::BasicBlock *DoneBB = CGF.createBasicBlock (" free-exnobj.done" );
152
+
153
+ llvm::Value *ShouldFree = CGF.Builder .CreateLoad (ShouldFreeVar,
154
+ " should-free-exnobj" );
155
+ CGF.Builder .CreateCondBr (ShouldFree, FreeBB, DoneBB);
156
+ CGF.EmitBlock (FreeBB);
157
+ llvm::Value *ExnLocLocal = CGF.Builder .CreateLoad (ExnLocVar, " exnobj" );
158
+ CGF.Builder .CreateCall (getFreeExceptionFn (CGF), ExnLocLocal);
159
+ CGF.EmitBlock (DoneBB);
200
160
}
161
+ llvm::BasicBlock *Cleanup = CGF.getInvokeDest ();
162
+
163
+ CGF.Builder .CreateStore (ExnLoc, ExnLocVar);
164
+ CGF.Builder .CreateStore (llvm::ConstantInt::getTrue (CGF.getLLVMContext ()),
165
+ ShouldFreeVar);
166
+
167
+ // __cxa_allocate_exception returns a void*; we need to cast this
168
+ // to the appropriate type for the object.
169
+ const llvm::Type *Ty = CGF.ConvertType (E->getType ())->getPointerTo ();
170
+ llvm::Value *TypedExnLoc = CGF.Builder .CreateBitCast (ExnLoc, Ty);
171
+
172
+ // FIXME: this isn't quite right! If there's a final unelided call
173
+ // to a copy constructor, then according to [except.terminate]p1 we
174
+ // must call std::terminate() if that constructor throws, because
175
+ // technically that copy occurs after the exception expression is
176
+ // evaluated but before the exception is caught. But the best way
177
+ // to handle that is to teach EmitAggExpr to do the final copy
178
+ // differently if it can't be elided.
179
+ CGF.EmitAnyExprToMem (E, TypedExnLoc, /* Volatile*/ false );
180
+
181
+ CGF.Builder .CreateStore (llvm::ConstantInt::getFalse (CGF.getLLVMContext ()),
182
+ ShouldFreeVar);
183
+
184
+ // Pop the cleanup block if it's still the top of the cleanup stack.
185
+ // Otherwise, temporaries have been created and our cleanup will get
186
+ // properly removed in time.
187
+ // TODO: this is not very resilient.
188
+ if (CGF.getInvokeDest () == Cleanup)
189
+ CGF.setInvokeDest (SavedInvokeDest);
201
190
}
202
191
203
192
// CopyObject - Utility to copy an object. Calls copy constructor as necessary.
@@ -278,17 +267,24 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) {
278
267
llvm::ConstantInt::get (SizeTy, TypeSize),
279
268
" exception" );
280
269
281
- llvm::Value *ExceptionPtrPtr =
282
- CreateTempAlloca (ExceptionPtr->getType (), " exception.ptr" );
283
- Builder.CreateStore (ExceptionPtr, ExceptionPtrPtr);
284
-
285
-
286
- CopyObject (*this , E->getSubExpr (), ExceptionPtr, ExceptionPtrPtr);
270
+ EmitAnyExprToExn (*this , E->getSubExpr (), ExceptionPtr);
287
271
288
272
// Now throw the exception.
289
273
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy (getLLVMContext ());
290
274
llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor (ThrowType);
291
- llvm::Constant *Dtor = llvm::Constant::getNullValue (Int8PtrTy);
275
+
276
+ // The address of the destructor. If the exception type has a
277
+ // trivial destructor (or isn't a record), we just pass null.
278
+ llvm::Constant *Dtor = 0 ;
279
+ if (const RecordType *RecordTy = ThrowType->getAs <RecordType>()) {
280
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl ());
281
+ if (!Record->hasTrivialDestructor ()) {
282
+ CXXDestructorDecl *DtorD = Record->getDestructor (getContext ());
283
+ Dtor = CGM.GetAddrOfCXXDestructor (DtorD, Dtor_Complete);
284
+ Dtor = llvm::ConstantExpr::getBitCast (Dtor, Int8PtrTy);
285
+ }
286
+ }
287
+ if (!Dtor) Dtor = llvm::Constant::getNullValue (Int8PtrTy);
292
288
293
289
if (getInvokeDest ()) {
294
290
llvm::BasicBlock *Cont = createBasicBlock (" invoke.cont" );
0 commit comments