summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGClass.cpp
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2013-07-22 13:51:44 +0000
committerReid Kleckner <reid@kleckner.net>2013-07-22 13:51:44 +0000
commite7de47efbec4f33a9d5e111e19eca14c5f79c19a (patch)
tree8d93edb55a0401eda6df42d0279ec6b37284b188 /clang/lib/CodeGen/CGClass.cpp
parentf6ce2b5f2e6ab7a01b61f68393c1bf6bd9a49909 (diff)
downloadbcm5719-llvm-e7de47efbec4f33a9d5e111e19eca14c5f79c19a.tar.gz
bcm5719-llvm-e7de47efbec4f33a9d5e111e19eca14c5f79c19a.zip
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches. Prior to this change, clang was considering ?1 to be the complete destructor and the base destructor, which was wrong. This lead to crashes when clang tried to emit two LLVM functions with the same name. In this ABI, TUs with non-inline dtors might not emit a complete destructor. They are emitted as inline thunks in TUs that need them, and they always delegate to the base dtors of the complete class and its virtual bases. This change uses the DeferredDecls machinery to emit complete dtors as needed. Currently in clang try body destructors can catch exceptions thrown by virtual base destructors. In the Microsoft C++ ABI, clang may not have the destructor definition, in which case clang won't wrap the virtual virtual base destructor calls in a try-catch. Diagnosing this in user code is TODO. Finally, for classes that don't use virtual inheritance, MSVC always calls the base destructor (?1) directly. This is a useful code size optimization that avoids emitting lots of extra thunks or aliases. Implementing it also means our existing tests continue to pass, and is consistent with MSVC's output. We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but it will require further testing. Reviewers: rjmccall CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1066 llvm-svn: 186828
Diffstat (limited to 'clang/lib/CodeGen/CGClass.cpp')
-rw-r--r--clang/lib/CodeGen/CGClass.cpp11
1 files changed, 8 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 2bb44552e26..dd75523d14a 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1265,16 +1265,19 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// If this is the complete variant, just invoke the base variant;
// the epilogue will destruct the virtual bases. But we can't do
// this optimization if the body is a function-try-block, because
- // we'd introduce *two* handler blocks.
+ // we'd introduce *two* handler blocks. In the Microsoft ABI, we
+ // always delegate because we might not have a definition in this TU.
switch (DtorType) {
case Dtor_Deleting: llvm_unreachable("already handled deleting case");
case Dtor_Complete:
+ assert((Body || getTarget().getCXXABI().isMicrosoft()) &&
+ "can't emit a dtor without a body for non-Microsoft ABIs");
+
// Enter the cleanup scopes for virtual bases.
EnterDtorCleanups(Dtor, Dtor_Complete);
- if (!isTryBody &&
- CGM.getTarget().getCXXABI().hasDestructorVariants()) {
+ if (!isTryBody) {
EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
/*Delegating=*/false, LoadCXXThis());
break;
@@ -1282,6 +1285,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// Fallthrough: act like we're in the base variant.
case Dtor_Base:
+ assert(Body);
+
// Enter the cleanup scopes for fields and non-virtual bases.
EnterDtorCleanups(Dtor, Dtor_Base);
OpenPOWER on IntegriCloud