[PATCH] D43908: [RecordLayout] Only assert that fundamental type sizes are power of two on MSVC

Martin Storsjö via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 1 12:27:51 PST 2018


This revision was automatically updated to reflect the committed changes.
Closed by commit rL326476: [RecordLayout] Only assert that fundamental type sizes are power of two on MSVC (authored by mstorsjo, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D43908?vs=136471&id=136583#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D43908

Files:
  cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
  cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
  cfe/trunk/test/CodeGen/ms_struct-long-double.c


Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
@@ -759,6 +759,10 @@
   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', "
Index: cfe/trunk/test/CodeGen/ms_struct-long-double.c
===================================================================
--- cfe/trunk/test/CodeGen/ms_struct-long-double.c
+++ cfe/trunk/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
Index: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
@@ -1752,10 +1752,32 @@
       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;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D43908.136583.patch
Type: text/x-patch
Size: 4222 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180301/0daa625d/attachment.bin>


More information about the llvm-commits mailing list