Index: cfe/trunk/include/clang/Basic/TargetInfo.h =================================================================== --- cfe/trunk/include/clang/Basic/TargetInfo.h +++ cfe/trunk/include/clang/Basic/TargetInfo.h @@ -414,6 +414,19 @@ /// types for the given target. unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; } + /// Return the alignment (in bits) of the thrown exception object. + virtual unsigned getExnObjectAlignment() const { + /// Itanium says that an _Unwind_Exception has to be "double-word" + /// aligned (and thus the end of it is also so-aligned), meaning 16 + /// bytes. Of course, that was written for the actual Itanium, + /// which is a 64-bit platform. Classically, the ABI doesn't really + /// specify the alignment on other platforms, but in practice + /// libUnwind declares the struct with __attribute__((aligned)), so + /// we assume that alignment here. (It's generally 16 bytes, but + /// some targets overwrite it.) + return getDefaultAlignForAttributeAligned(); + } + /// \brief Return the size of intmax_t and uintmax_t for this target, in bits. unsigned getIntMaxTWidth() const { return getTypeWidth(IntMaxType); Index: cfe/trunk/lib/Basic/Targets.cpp =================================================================== --- cfe/trunk/lib/Basic/Targets.cpp +++ cfe/trunk/lib/Basic/Targets.cpp @@ -262,6 +262,13 @@ bool hasProtectedVisibility() const override { return false; } + + unsigned getExnObjectAlignment() const override { + // The alignment of an exception object is 8-bytes for darwin since + // libc++abi doesn't declare _Unwind_Exception with __attribute__((aligned)) + // and therefore doesn't guarantee 16-byte alignment. + return 64; + } }; Index: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp @@ -154,17 +154,9 @@ Address Ptr, QualType ElementType, const CXXDestructorDecl *Dtor) override; - /// Itanium says that an _Unwind_Exception has to be "double-word" - /// aligned (and thus the end of it is also so-aligned), meaning 16 - /// bytes. Of course, that was written for the actual Itanium, - /// which is a 64-bit platform. Classically, the ABI doesn't really - /// specify the alignment on other platforms, but in practice - /// libUnwind declares the struct with __attribute__((aligned)), so - /// we assume that alignment here. (It's generally 16 bytes, but - /// some targets overwrite it.) CharUnits getAlignmentOfExnObject() { - auto align = CGM.getContext().getTargetDefaultAlignForAttributeAligned(); - return CGM.getContext().toCharUnitsFromBits(align); + unsigned Align = CGM.getContext().getTargetInfo().getExnObjectAlignment(); + return CGM.getContext().toCharUnitsFromBits(Align); } void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override; Index: cfe/trunk/test/CodeGenCXX/eh.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/eh.cpp +++ cfe/trunk/test/CodeGenCXX/eh.cpp @@ -448,5 +448,27 @@ } } +namespace test17 { +class BaseException { +private: + int a[4]; +public: + BaseException() {}; +}; + +class DerivedException: public BaseException { +}; + +int foo() { + throw DerivedException(); + // The alignment passed to memset is 8, not 16, on Darwin. + + // CHECK: [[T0:%.*]] = call i8* @__cxa_allocate_exception(i64 16) + // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to %"class.test17::DerivedException"* + // CHECK-NEXT: [[T2:%.*]] = bitcast %"class.test17::DerivedException"* [[T1]] to i8* + // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T2]], i8 0, i64 16, i32 8, i1 false) +} +} + // CHECK: attributes [[NUW]] = { nounwind } // CHECK: attributes [[NR]] = { noreturn }