diff options
author | Tom Stellard <tstellar@redhat.com> | 2018-05-30 18:19:45 +0000 |
---|---|---|
committer | Tom Stellard <tstellar@redhat.com> | 2018-05-30 18:19:45 +0000 |
commit | 06815bf8ab3afe8af486b911869b47978a753ab2 (patch) | |
tree | c6ae0210a3b16e69e0d04ab60be9d471ecae11aa | |
parent | ba3c53d060a8c1943297a14b3b770e90cf9afd65 (diff) | |
download | llvm-06815bf8ab3afe8af486b911869b47978a753ab2.zip llvm-06815bf8ab3afe8af486b911869b47978a753ab2.tar.gz llvm-06815bf8ab3afe8af486b911869b47978a753ab2.tar.bz2 |
Merging r326476:
------------------------------------------------------------------------
r326476 | mstorsjo | 2018-03-01 12:22:57 -0800 (Thu, 01 Mar 2018) | 7 lines
[RecordLayout] Only assert that fundamental type sizes are power of two on MSVC
Make types with sizes that aren't a power of two an error (that can
be disabled) in structs with ms_struct layout, except on mingw where
the situation is quite likely to occur and GCC handles it silently.
Differential Revision: https://reviews.llvm.org/D43908
------------------------------------------------------------------------
llvm-svn: 333571
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 30 | ||||
-rw-r--r-- | clang/test/CodeGen/ms_struct-long-double.c | 17 |
3 files changed, 47 insertions, 4 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ec624a0..9d17bda 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -759,6 +759,10 @@ def warn_cxx_ms_struct : Warning<"ms_struct may not produce Microsoft-compatible layouts for classes " "with base classes or virtual functions">, DefaultError, InGroup<IncompatibleMSStruct>; +def warn_npot_ms_struct : + Warning<"ms_struct may not produce Microsoft-compatible layouts with fundamental " + "data types with sizes that aren't a power of two">, + DefaultError, InGroup<IncompatibleMSStruct>; def err_section_conflict : Error<"%0 causes a section type conflict with %1">; def err_no_base_classes : Error<"invalid use of '__super', %0 has no base classes">; def err_invalid_super_scope : Error<"invalid use of '__super', " diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 240e7f6..de38bc9 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1751,10 +1751,32 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, QualType T = Context.getBaseElementType(D->getType()); if (const BuiltinType *BTy = T->getAs<BuiltinType>()) { CharUnits TypeSize = Context.getTypeSizeInChars(BTy); - assert( - (llvm::isPowerOf2_64(TypeSize.getQuantity()) || - Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) && - "Non PowerOf2 size outside of GNU mode"); + + if (!llvm::isPowerOf2_64(TypeSize.getQuantity())) { + assert( + !Context.getTargetInfo().getTriple().isWindowsMSVCEnvironment() && + "Non PowerOf2 size in MSVC mode"); + // Base types with sizes that aren't a power of two don't work + // with the layout rules for MS structs. This isn't an issue in + // MSVC itself since there are no such base data types there. + // On e.g. x86_32 mingw and linux, long double is 12 bytes though. + // Any structs involving that data type obviously can't be ABI + // compatible with MSVC regardless of how it is laid out. + + // Since ms_struct can be mass enabled (via a pragma or via the + // -mms-bitfields command line parameter), this can trigger for + // structs that don't actually need MSVC compatibility, so we + // need to be able to sidestep the ms_struct layout for these types. + + // Since the combination of -mms-bitfields together with structs + // like max_align_t (which contains a long double) for mingw is + // quite comon (and GCC handles it silently), just handle it + // silently there. For other targets that have ms_struct enabled + // (most probably via a pragma or attribute), trigger a diagnostic + // that defaults to an error. + if (!Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) + Diag(D->getLocation(), diag::warn_npot_ms_struct); + } if (TypeSize > FieldAlign && llvm::isPowerOf2_64(TypeSize.getQuantity())) FieldAlign = TypeSize; diff --git a/clang/test/CodeGen/ms_struct-long-double.c b/clang/test/CodeGen/ms_struct-long-double.c new file mode 100644 index 0000000..9b3ea79 --- /dev/null +++ b/clang/test/CodeGen/ms_struct-long-double.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -emit-llvm-only -triple i686-windows-gnu -fdump-record-layouts %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm-only -triple i686-linux -fdump-record-layouts -Wno-incompatible-ms-struct %s | FileCheck %s +// RUN: not %clang_cc1 -emit-llvm-only -triple i686-linux -fdump-record-layouts %s 2>&1 | FileCheck %s -check-prefix=ERROR + +struct ldb_struct { + char c; + long double ldb; +} __attribute__((__ms_struct__)); + +struct ldb_struct a; + +// CHECK: 0 | struct ldb_struct +// CHECK-NEXT: 0 | char c +// CHECK-NEXT: 4 | long double ldb +// CHECK-NEXT: | [sizeof=16, align=4] + +// ERROR: error: ms_struct may not produce Microsoft-compatible layouts with fundamental data types with sizes that aren't a power of two |