Author: ahatanak Date: Thu May 9 19:16:37 2019 New Revision: 360404 URL: http://llvm.org/viewvc/llvm-project?rev=360404&view=rev Log: Assume `__cxa_allocate_exception` returns an under-aligned memory on Darwin if the version of libc++abi isn't new enough to include the fix in r319123
This patch resurrects r264998, which was committed to work around a bug in libc++abi that was causing _cxa_allocate_exception to return a memory that wasn't double-word aligned. http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20160328/154332.html In addition, this patch makes clang issue a warning if the type of the thrown object requires an alignment that is larger than the minimum guaranteed by the target C++ runtime. rdar://problem/49864414 Differential Revision: https://reviews.llvm.org/D61667 Added: cfe/trunk/test/SemaCXX/warn-overaligned-type-thrown.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/Basic/DiagnosticGroups.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Basic/TargetInfo.h cfe/trunk/lib/Basic/Targets/OSTargets.h cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/test/CodeGenCXX/eh.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=360404&r1=360403&r2=360404&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Thu May 9 19:16:37 2019 @@ -2166,6 +2166,13 @@ public: /// pointers and large arrays get extra alignment. CharUnits getDeclAlign(const Decl *D, bool ForAlignof = false) const; + /// Return the alignment (in bytes) of the thrown exception object. This is + /// only meaningful for targets that allocate C++ exceptions in a system + /// runtime, such as those using the Itanium C++ ABI. + CharUnits getExnObjectAlignment() const { + return toCharUnitsFromBits(Target->getExnObjectAlignment()); + } + /// Get or compute information about the layout of the specified /// record (struct/union/class) \p D, which indicates its size and field /// position information. Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=360404&r1=360403&r2=360404&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Thu May 9 19:16:37 2019 @@ -408,6 +408,7 @@ def ObjCMultipleMethodNames : DiagGroup< def ObjCFlexibleArray : DiagGroup<"objc-flexible-array">; def ObjCBoxing : DiagGroup<"objc-boxing">; def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">; +def UnderalignedExceptionObject : DiagGroup<"underaligned-exception-object">; def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">; def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">; def Packed : DiagGroup<"packed">; Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=360404&r1=360403&r2=360404&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu May 9 19:16:37 2019 @@ -6576,6 +6576,12 @@ def err_throw_incomplete : Error< "cannot throw object of incomplete type %0">; def err_throw_incomplete_ptr : Error< "cannot throw pointer to object of incomplete type %0">; +def warn_throw_underaligned_obj : Warning< + "underaligned exception object thrown">, + InGroup<UnderalignedExceptionObject>; +def note_throw_underaligned_obj : Note< + "required alignment of type %0 (%1 bytes) is larger than the supported " + "alignment of C++ exception objects on this target (%2 bytes)">; def err_return_in_constructor_handler : Error< "return in the catch of a function try block of a constructor is illegal">; def warn_cdtor_function_try_handler_mem_expr : Warning< Modified: cfe/trunk/include/clang/Basic/TargetInfo.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=360404&r1=360403&r2=360404&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TargetInfo.h (original) +++ cfe/trunk/include/clang/Basic/TargetInfo.h Thu May 9 19:16:37 2019 @@ -637,6 +637,21 @@ public: /// types for the given target. unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; } + /// Return the alignment (in bits) of the thrown exception object. This is + /// only meaningful for targets that allocate C++ exceptions in a system + /// runtime, such as those using the Itanium C++ ABI. + 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(); + } + /// Return the size of intmax_t and uintmax_t for this target, in bits. unsigned getIntMaxTWidth() const { return getTypeWidth(IntMaxType); Modified: cfe/trunk/lib/Basic/Targets/OSTargets.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/OSTargets.h?rev=360404&r1=360403&r2=360404&view=diff ============================================================================== --- cfe/trunk/lib/Basic/Targets/OSTargets.h (original) +++ cfe/trunk/lib/Basic/Targets/OSTargets.h Thu May 9 19:16:37 2019 @@ -133,6 +133,37 @@ public: /// attribute on declarations that can be dynamically replaced. bool hasProtectedVisibility() const override { return false; } + unsigned getExnObjectAlignment() const override { + // Older versions of libc++abi guarantee an alignment of only 8-bytes for + // exception objects because of a bug in __cxa_exception that was + // eventually fixed in r319123. + llvm::VersionTuple MinVersion; + const llvm::Triple &T = this->getTriple(); + + // Compute the earliest OS versions that have the fix to libc++abi. + switch (T.getOS()) { + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: // Earliest supporting version is 10.14. + MinVersion = llvm::VersionTuple(10U, 14U); + break; + case llvm::Triple::IOS: + case llvm::Triple::TvOS: // Earliest supporting version is 12.0.0. + MinVersion = llvm::VersionTuple(12U); + break; + case llvm::Triple::WatchOS: // Earliest supporting version is 5.0.0. + MinVersion = llvm::VersionTuple(5U); + break; + default: + llvm_unreachable("Unexpected OS"); + } + + unsigned Major, Minor, Micro; + T.getOSVersion(Major, Minor, Micro); + if (llvm::VersionTuple(Major, Minor, Micro) < MinVersion) + return 64; + return OSTargetInfo<Target>::getExnObjectAlignment(); + } + TargetInfo::IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final { // Darwin uses `long long` for `int_least64_t` and `int_fast64_t`. Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=360404&r1=360403&r2=360404&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original) +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Thu May 9 19:16:37 2019 @@ -154,19 +154,6 @@ public: 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); - } - void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override; void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override; @@ -1191,7 +1178,7 @@ void ItaniumCXXABI::emitThrow(CodeGenFun llvm::CallInst *ExceptionPtr = CGF.EmitNounwindRuntimeCall( AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception"); - CharUnits ExnAlign = getAlignmentOfExnObject(); + CharUnits ExnAlign = CGF.getContext().getExnObjectAlignment(); CGF.EmitAnyExprToExn(E->getSubExpr(), Address(ExceptionPtr, ExnAlign)); // Now throw the exception. Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=360404&r1=360403&r2=360404&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu May 9 19:16:37 2019 @@ -941,6 +941,21 @@ bool Sema::CheckCXXThrowOperand(SourceLo } } + // Under the Itanium C++ ABI, memory for the exception object is allocated by + // the runtime with no ability for the compiler to request additional + // alignment. Warn if the exception type requires alignment beyond the minimum + // guaranteed by the target C++ runtime. + if (Context.getTargetInfo().getCXXABI().isItaniumFamily()) { + CharUnits TypeAlign = Context.getTypeAlignInChars(Ty); + CharUnits ExnObjAlign = Context.getExnObjectAlignment(); + if (ExnObjAlign < TypeAlign) { + Diag(ThrowLoc, diag::warn_throw_underaligned_obj); + Diag(ThrowLoc, diag::note_throw_underaligned_obj) + << Ty << (unsigned)TypeAlign.getQuantity() + << (unsigned)ExnObjAlign.getQuantity(); + } + } + return false; } Modified: cfe/trunk/test/CodeGenCXX/eh.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/eh.cpp?rev=360404&r1=360403&r2=360404&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/eh.cpp (original) +++ cfe/trunk/test/CodeGenCXX/eh.cpp Thu May 9 19:16:37 2019 @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - \ -// RUN: | FileCheck %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-macosx10.13.99 -std=c++11 -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=UNALIGNED %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-macosx10.14 -std=c++11 -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ALIGNED %s struct test1_D { double d; @@ -13,7 +13,8 @@ void test1() { // CHECK: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8) // CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]] // CHECK-NEXT: [[EXN2:%.*]] = bitcast [[DSTAR]] [[EXN]] to i8* -// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[EXN2]], i8* align 8 bitcast ([[DSTAR]] @d1 to i8*), i64 8, i1 false) +// UNALIGNED-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[EXN2]], i8* align 8 bitcast ([[DSTAR]] @d1 to i8*), i64 8, i1 false) +// ALIGNED-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[EXN2]], i8* align 8 bitcast ([[DSTAR]] @d1 to i8*), i64 8, i1 false) // CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({ i8*, i8* }* @_ZTI7test1_D to i8*), i8* null) [[NR:#[0-9]+]] // CHECK-NEXT: unreachable @@ -466,7 +467,8 @@ int foo() { // 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* align 16 [[T2]], i8 0, i64 16, i1 false) + // UNALIGNED-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[T2]], i8 0, i64 16, i1 false) + // ALIGNED-NEXT: call void @llvm.memset.p0i8.i64(i8* align 16 [[T2]], i8 0, i64 16, i1 false) } } Added: cfe/trunk/test/SemaCXX/warn-overaligned-type-thrown.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-overaligned-type-thrown.cpp?rev=360404&view=auto ============================================================================== --- cfe/trunk/test/SemaCXX/warn-overaligned-type-thrown.cpp (added) +++ cfe/trunk/test/SemaCXX/warn-overaligned-type-thrown.cpp Thu May 9 19:16:37 2019 @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.99 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions -DUNDERALIGNED %s +// RUN: %clang_cc1 -triple arm64-apple-ios10 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions -DUNDERALIGNED %s +// RUN: %clang_cc1 -triple arm64-apple-tvos10 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions -DUNDERALIGNED %s +// RUN: %clang_cc1 -triple arm64-apple-watchos4 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions -DUNDERALIGNED %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple arm64-apple-ios12 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple arm64-apple-tvos12 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple arm64-apple-watchos5 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple arm-linux-gnueabi -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple aarch64-linux-gnueabi -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple mipsel-linux-gnu -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple mips64el-linux-gnu -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple wasm32-unknown-unknown -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple wasm64-unknown-unknown -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions -Wno-underaligned-exception-object -DNODIAG %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions -DNODIAG %s + +struct S0 { + S0(); + int m; +}; + +struct Overaligned1 { + Overaligned1(); + int __attribute__((aligned(16))) m; +}; + +struct __attribute__((aligned(16))) Overaligned2 { + Overaligned2(); + int m; +}; + +struct Overaligned3 { + Overaligned3(); + int __attribute__((aligned(64))) m; +}; + +void test0() { + throw S0(); +} + +void test1() { + throw Overaligned1(); +} + +void test2() { + throw Overaligned2(); +} + +void test3() { + throw Overaligned3(); +} + +#if defined(NODIAG) +// expected-no-diagnostics +#elif defined(UNDERALIGNED) +// expected-warning@-14 {{underaligned exception object thrown}} +// expected-note@-15 {{(16 bytes) is larger than the supported alignment of C++ exception objects on this target (8 bytes)}} +// expected-warning@-12 {{underaligned exception object thrown}} +// expected-note@-13 {{(16 bytes) is larger than the supported alignment of C++ exception objects on this target (8 bytes)}} +// expected-warning@-10 {{underaligned exception object thrown}} +// expected-note@-11 {{(64 bytes) is larger than the supported alignment of C++ exception objects on this target (8 bytes)}} +#else +// expected-warning@-13 {{underaligned exception object thrown}} +// expected-note@-14 {{(64 bytes) is larger than the supported alignment of C++ exception objects on this target (16 bytes)}} +#endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits