summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-05-07 06:43:30 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-05-07 06:43:30 +0000
commitb5a317fbf67a711f5cebad6b5c21324be103fa6c (patch)
tree83a71b577c595cf5969715e1e992eb42fb0f21bf /clang/test
parentfac095caba2550c7a49cdd9c0b921c07185dd587 (diff)
downloadbcm5719-llvm-b5a317fbf67a711f5cebad6b5c21324be103fa6c.tar.gz
bcm5719-llvm-b5a317fbf67a711f5cebad6b5c21324be103fa6c.zip
Non-zero-length bit-fields make a class non-empty.
This implements the rule intended by the standard (see LWG 2358) and the rule intended by the Itanium C++ ABI (see https://github.com/itanium-cxx-abi/cxx-abi/pull/51), and makes Clang match the behavior of GCC, ICC, and MSVC. A pedantic reading of both the standard and the ABI indicate that Clang is currently technically correct, but that's not worth much when it's clear that the wording is wrong in both those places. This is an ABI break for classes that derive from a class that is empty other than one or more unnamed non-zero-length bit-fields. Such cases are expected to be rare, but -fclang-abi-compat=6 restores the old behavior just in case. Differential Revision: https://reviews.llvm.org/D45174 llvm-svn: 331620
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/Layout/ms-x86-pack-and-align.cpp24
-rw-r--r--clang/test/Layout/v6-empty.cpp20
-rw-r--r--clang/test/SemaCXX/type-traits.cpp2
3 files changed, 34 insertions, 12 deletions
diff --git a/clang/test/Layout/ms-x86-pack-and-align.cpp b/clang/test/Layout/ms-x86-pack-and-align.cpp
index 958ee195814..ccf8fac38e8 100644
--- a/clang/test/Layout/ms-x86-pack-and-align.cpp
+++ b/clang/test/Layout/ms-x86-pack-and-align.cpp
@@ -188,12 +188,12 @@ struct YA {
__declspec(align(32)) char : 1;
};
// CHECK: *** Dumping AST Record Layout
-// CHECK-NEXT: 0 | struct YA (empty)
+// CHECK-NEXT: 0 | struct YA
// CHECK-NEXT:0:0-0 | char
// CHECK-NEXT: | [sizeof=32, align=32
// CHECK-NEXT: | nvsize=32, nvalign=32]
// CHECK-X64: *** Dumping AST Record Layout
-// CHECK-X64-NEXT: 0 | struct YA (empty)
+// CHECK-X64-NEXT: 0 | struct YA
// CHECK-X64-NEXT:0:0-0 | char
// CHECK-X64-NEXT: | [sizeof=32, align=32
// CHECK-X64-NEXT: | nvsize=32, nvalign=32]
@@ -206,14 +206,14 @@ struct YB {
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct YB
// CHECK-NEXT: 0 | char a
-// CHECK-NEXT: 1 | struct YA b (empty)
+// CHECK-NEXT: 1 | struct YA b
// CHECK-NEXT:1:0-0 | char
// CHECK-NEXT: | [sizeof=33, align=1
// CHECK-NEXT: | nvsize=33, nvalign=1]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YB
// CHECK-X64-NEXT: 0 | char a
-// CHECK-X64-NEXT: 1 | struct YA b (empty)
+// CHECK-X64-NEXT: 1 | struct YA b
// CHECK-X64-NEXT:1:0-0 | char
// CHECK-X64-NEXT: | [sizeof=33, align=1
// CHECK-X64-NEXT: | nvsize=33, nvalign=1]
@@ -223,12 +223,12 @@ struct YC {
__declspec(align(32)) char : 1;
};
// CHECK: *** Dumping AST Record Layout
-// CHECK-NEXT: 0 | struct YC (empty)
+// CHECK-NEXT: 0 | struct YC
// CHECK-NEXT:0:0-0 | char
// CHECK-NEXT: | [sizeof=32, align=32
// CHECK-NEXT: | nvsize=32, nvalign=32]
// CHECK-X64: *** Dumping AST Record Layout
-// CHECK-X64-NEXT: 0 | struct YC (empty)
+// CHECK-X64-NEXT: 0 | struct YC
// CHECK-X64-NEXT: 0:0-0 | char
// CHECK-X64-NEXT: | [sizeof=8, align=32
// CHECK-X64-NEXT: | nvsize=8, nvalign=32]
@@ -241,14 +241,14 @@ struct YD {
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct YD
// CHECK-NEXT: 0 | char a
-// CHECK-NEXT: 1 | struct YC b (empty)
+// CHECK-NEXT: 1 | struct YC b
// CHECK-NEXT:1:0-0 | char
// CHECK-NEXT: | [sizeof=33, align=1
// CHECK-NEXT: | nvsize=33, nvalign=1]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YD
// CHECK-X64-NEXT: 0 | char a
-// CHECK-X64-NEXT: 1 | struct YC b (empty)
+// CHECK-X64-NEXT: 1 | struct YC b
// CHECK-X64-NEXT:1:0-0 | char
// CHECK-X64-NEXT: | [sizeof=9, align=1
// CHECK-X64-NEXT: | nvsize=9, nvalign=1]
@@ -258,12 +258,12 @@ struct YE {
__declspec(align(32)) char : 1;
};
// CHECK: *** Dumping AST Record Layout
-// CHECK-NEXT: 0 | struct YE (empty)
+// CHECK-NEXT: 0 | struct YE
// CHECK-NEXT: 0:0-0 | char
// CHECK-NEXT: | [sizeof=4, align=32
// CHECK-NEXT: | nvsize=4, nvalign=32]
// CHECK-X64: *** Dumping AST Record Layout
-// CHECK-X64-NEXT: 0 | struct YE (empty)
+// CHECK-X64-NEXT: 0 | struct YE
// CHECK-X64-NEXT: 0:0-0 | char
// CHECK-X64-NEXT: | [sizeof=4, align=32
// CHECK-X64-NEXT: | nvsize=4, nvalign=32]
@@ -276,14 +276,14 @@ struct YF {
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct YF
// CHECK-NEXT: 0 | char a
-// CHECK-NEXT: 1 | struct YE b (empty)
+// CHECK-NEXT: 1 | struct YE b
// CHECK-NEXT:1:0-0 | char
// CHECK-NEXT: | [sizeof=5, align=1
// CHECK-NEXT: | nvsize=5, nvalign=1]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YF
// CHECK-X64-NEXT: 0 | char a
-// CHECK-X64-NEXT: 1 | struct YE b (empty)
+// CHECK-X64-NEXT: 1 | struct YE b
// CHECK-X64-NEXT:1:0-0 | char
// CHECK-X64-NEXT: | [sizeof=5, align=1
// CHECK-X64-NEXT: | nvsize=5, nvalign=1]
diff --git a/clang/test/Layout/v6-empty.cpp b/clang/test/Layout/v6-empty.cpp
new file mode 100644
index 00000000000..d43db8dc32e
--- /dev/null
+++ b/clang/test/Layout/v6-empty.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -fclang-abi-compat=6 -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V6
+// RUN: %clang_cc1 -fsyntax-only -fclang-abi-compat=7 -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V7
+
+// In Clang 6 and before, we determined that Nonempty was empty, so we
+// applied EBO to it.
+struct Nonempty { int : 4; };
+struct A : Nonempty { int n; };
+int k = sizeof(A);
+
+// CHECK:*** Dumping AST Record Layout
+// CHECK: 0 | struct A
+// CHECK-V6-NEXT: 0 | struct Nonempty (base) (empty)
+// CHECK-V7-NEXT: 0 | struct Nonempty (base){{$}}
+// CHECK-NEXT: 0:0-3 | int
+// CHECK-V6-NEXT: 0 | int n
+// CHECK-V7-NEXT: 4 | int n
+// CHECK-V6-NEXT: | [sizeof=4, dsize=4, align=4,
+// CHECK-V6-NEXT: | nvsize=4, nvalign=4]
+// CHECK-V7-NEXT: | [sizeof=8, dsize=8, align=4,
+// CHECK-V7-NEXT: | nvsize=8, nvalign=4]
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index a25f4bd6b2e..1ab35dfc1a4 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -262,6 +262,7 @@ void is_pod()
typedef Empty EmptyAr[10];
struct Bit0 { int : 0; };
struct Bit0Cons { int : 0; Bit0Cons(); };
+struct AnonBitOnly { int : 3; };
struct BitOnly { int x : 3; };
struct DerivesVirt : virtual POD {};
@@ -287,6 +288,7 @@ void is_empty()
{ int arr[F(__is_empty(EmptyAr))]; }
{ int arr[F(__is_empty(HasRef))]; }
{ int arr[F(__is_empty(HasVirt))]; }
+ { int arr[F(__is_empty(AnonBitOnly))]; }
{ int arr[F(__is_empty(BitOnly))]; }
{ int arr[F(__is_empty(void))]; }
{ int arr[F(__is_empty(IntArNB))]; }
OpenPOWER on IntegriCloud