From fc6297f31499b13f297ec909dd309a1e89096b26 Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Tue, 1 Apr 2014 01:38:16 +0000 Subject: [PATCH] Disable this-return optimizations when targeting iOS 5 and earlier. Clang implements the part of the ARM ABI saying that certain functions (e.g., constructors and destructors) return "this", but Apple's version of gcc and llvm-gcc did not. The libstdc++ dylib on iOS 5 was built with llvm-gcc, which means that clang cannot safely assume that code from the C++ runtime will correctly follow the ABI. It is also possible to run into this problem when linking with other libraries built with gcc or llvm-gcc. Even though there is no way to reliably detect that situation, it is most likely to come up when targeting older versions of iOS. Disabling the optimization for any code targeting iOS 5 solves the libstdc++ problem and has a reasonably good chance of fixing the issue for other older libraries as well. llvm-svn: 205272 --- clang/lib/CodeGen/CodeGenModule.cpp | 7 ++++++- clang/test/CodeGenCXX/arm.cpp | 2 +- .../constructor-destructor-return-this.cpp | 18 +++++++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 89d177fdb051..d997a79f5b23 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -775,7 +775,12 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, if (!IsIncompleteFunction) SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F); - if (getCXXABI().HasThisReturn(GD)) { + // Add the Returned attribute for "this", except for iOS 5 and earlier + // where substantial code, including the libstdc++ dylib, was compiled with + // GCC and does not actually return "this". + if (getCXXABI().HasThisReturn(GD) && + !(getTarget().getTriple().isiOS() && + getTarget().getTriple().isOSVersionLT(6))) { assert(!F->arg_empty() && F->arg_begin()->getType() ->canLosslesslyBitCastTo(F->getReturnType()) && diff --git a/clang/test/CodeGenCXX/arm.cpp b/clang/test/CodeGenCXX/arm.cpp index 2fb9c49bb707..2790199446d7 100644 --- a/clang/test/CodeGenCXX/arm.cpp +++ b/clang/test/CodeGenCXX/arm.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=thumbv7-apple-ios3.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s +// RUN: %clang_cc1 %s -triple=thumbv7-apple-ios6.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s // CHECK: @_ZZN5test74testEvE1x = internal global i32 0, align 4 // CHECK: @_ZGVZN5test74testEvE1x = internal global i32 0 diff --git a/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp b/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp index d93a0d184820..ce6ddd29f644 100644 --- a/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp +++ b/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp @@ -1,5 +1,6 @@ //RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-unknown-linux | FileCheck --check-prefix=CHECKGEN %s -//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios3.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKARM %s +//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios6.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKARM %s +//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios5.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKIOS5 %s //RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-pc-win32 -fno-rtti | FileCheck --check-prefix=CHECKMS %s // FIXME: these tests crash on the bots when run with -triple=x86_64-pc-win32 @@ -37,6 +38,11 @@ B::~B() { } // CHECKARM-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* returned %this) // CHECKARM-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* returned %this) +// CHECKIOS5-LABEL: define %class.B* @_ZN1BC2EPi(%class.B* %this, i32* %i) +// CHECKIOS5-LABEL: define %class.B* @_ZN1BC1EPi(%class.B* %this, i32* %i) +// CHECKIOS5-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* %this) +// CHECKIOS5-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* %this) + // CHECKMS-LABEL: define x86_thiscallcc %class.B* @"\01??0B@@QAE@PAH@Z"(%class.B* returned %this, i32* %i) // CHECKMS-LABEL: define x86_thiscallcc void @"\01??1B@@QAE@XZ"(%class.B* %this) @@ -63,6 +69,12 @@ C::~C() { } // CHECKARM-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* returned %this) // CHECKARM-LABEL: define void @_ZN1CD0Ev(%class.C* %this) +// CHECKIOS5-LABEL: define %class.C* @_ZN1CC2EPiPc(%class.C* %this, i32* %i, i8* %c) +// CHECKIOS5-LABEL: define %class.C* @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c) +// CHECKIOS5-LABEL: define %class.C* @_ZN1CD2Ev(%class.C* %this) +// CHECKIOS5-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* %this) +// CHECKIOS5-LABEL: define void @_ZN1CD0Ev(%class.C* %this) + // CHECKMS-LABEL: define x86_thiscallcc %class.C* @"\01??0C@@QAE@PAHPAD@Z"(%class.C* returned %this, i32* %i, i8* %c) // CHECKMS-LABEL: define x86_thiscallcc void @"\01??1C@@UAE@XZ"(%class.C* %this) @@ -85,6 +97,10 @@ D::~D() { } // CHECKARM-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* returned %this, i8** %vtt) // CHECKARM-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* returned %this) +// CHECKIOS5-LABEL: define %class.D* @_ZN1DC2Ev(%class.D* %this, i8** %vtt) +// CHECKIOS5-LABEL: define %class.D* @_ZN1DC1Ev(%class.D* %this) +// CHECKIOS5-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* %this, i8** %vtt) +// CHECKIOS5-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* %this) // CHECKMS-LABEL: define x86_thiscallcc %class.D* @"\01??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived) // CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@QAE@XZ"(%class.D* %this)