no-unique-address.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s
  2. namespace Empty {
  3. struct A {};
  4. struct B { [[no_unique_address]] A a; char b; };
  5. static_assert(sizeof(B) == 1);
  6. // CHECK:*** Dumping AST Record Layout
  7. // CHECK: 0 | struct Empty::B
  8. // CHECK-NEXT: 0 | struct Empty::A a (empty)
  9. // CHECK-NEXT: 0 | char b
  10. // CHECK-NEXT: | [sizeof=1, dsize=1, align=1,
  11. // CHECK-NEXT: | nvsize=1, nvalign=1]
  12. struct C {};
  13. struct D {
  14. [[no_unique_address]] A a;
  15. [[no_unique_address]] C c;
  16. char d;
  17. };
  18. static_assert(sizeof(D) == 1);
  19. // CHECK:*** Dumping AST Record Layout
  20. // CHECK: 0 | struct Empty::D
  21. // CHECK-NEXT: 0 | struct Empty::A a (empty)
  22. // CHECK-NEXT: 0 | struct Empty::C c (empty)
  23. // CHECK-NEXT: 0 | char d
  24. // CHECK-NEXT: | [sizeof=1, dsize=1, align=1,
  25. // CHECK-NEXT: | nvsize=1, nvalign=1]
  26. struct E {
  27. [[no_unique_address]] A a1;
  28. [[no_unique_address]] A a2;
  29. char e;
  30. };
  31. static_assert(sizeof(E) == 2);
  32. // CHECK:*** Dumping AST Record Layout
  33. // CHECK: 0 | struct Empty::E
  34. // CHECK-NEXT: 0 | struct Empty::A a1 (empty)
  35. // CHECK-NEXT: 1 | struct Empty::A a2 (empty)
  36. // CHECK-NEXT: 0 | char e
  37. // CHECK-NEXT: | [sizeof=2, dsize=2, align=1,
  38. // CHECK-NEXT: | nvsize=2, nvalign=1]
  39. struct F {
  40. ~F();
  41. [[no_unique_address]] A a1;
  42. [[no_unique_address]] A a2;
  43. char f;
  44. };
  45. static_assert(sizeof(F) == 2);
  46. // CHECK:*** Dumping AST Record Layout
  47. // CHECK: 0 | struct Empty::F
  48. // CHECK-NEXT: 0 | struct Empty::A a1 (empty)
  49. // CHECK-NEXT: 1 | struct Empty::A a2 (empty)
  50. // CHECK-NEXT: 0 | char f
  51. // CHECK-NEXT: | [sizeof=2, dsize=1, align=1,
  52. // CHECK-NEXT: | nvsize=2, nvalign=1]
  53. struct G { [[no_unique_address]] A a; ~G(); };
  54. static_assert(sizeof(G) == 1);
  55. // CHECK:*** Dumping AST Record Layout
  56. // CHECK: 0 | struct Empty::G
  57. // CHECK-NEXT: 0 | struct Empty::A a (empty)
  58. // CHECK-NEXT: | [sizeof=1, dsize=0, align=1,
  59. // CHECK-NEXT: | nvsize=1, nvalign=1]
  60. struct H { [[no_unique_address]] A a, b; ~H(); };
  61. static_assert(sizeof(H) == 2);
  62. // CHECK:*** Dumping AST Record Layout
  63. // CHECK: 0 | struct Empty::H
  64. // CHECK-NEXT: 0 | struct Empty::A a (empty)
  65. // CHECK-NEXT: 1 | struct Empty::A b (empty)
  66. // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,
  67. // CHECK-NEXT: | nvsize=2, nvalign=1]
  68. struct OversizedEmpty : A {
  69. ~OversizedEmpty();
  70. [[no_unique_address]] A a;
  71. };
  72. static_assert(sizeof(OversizedEmpty) == 2);
  73. // CHECK:*** Dumping AST Record Layout
  74. // CHECK: 0 | struct Empty::OversizedEmpty
  75. // CHECK-NEXT: 0 | struct Empty::A (base) (empty)
  76. // CHECK-NEXT: 1 | struct Empty::A a (empty)
  77. // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,
  78. // CHECK-NEXT: | nvsize=2, nvalign=1]
  79. struct HasOversizedEmpty {
  80. [[no_unique_address]] OversizedEmpty m;
  81. };
  82. static_assert(sizeof(HasOversizedEmpty) == 2);
  83. // CHECK:*** Dumping AST Record Layout
  84. // CHECK: 0 | struct Empty::HasOversizedEmpty
  85. // CHECK-NEXT: 0 | struct Empty::OversizedEmpty m (empty)
  86. // CHECK-NEXT: 0 | struct Empty::A (base) (empty)
  87. // CHECK-NEXT: 1 | struct Empty::A a (empty)
  88. // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,
  89. // CHECK-NEXT: | nvsize=2, nvalign=1]
  90. struct EmptyWithNonzeroDSize {
  91. [[no_unique_address]] A a;
  92. int x;
  93. [[no_unique_address]] A b;
  94. int y;
  95. [[no_unique_address]] A c;
  96. };
  97. static_assert(sizeof(EmptyWithNonzeroDSize) == 12);
  98. // CHECK:*** Dumping AST Record Layout
  99. // CHECK: 0 | struct Empty::EmptyWithNonzeroDSize
  100. // CHECK-NEXT: 0 | struct Empty::A a (empty)
  101. // CHECK-NEXT: 0 | int x
  102. // CHECK-NEXT: 4 | struct Empty::A b (empty)
  103. // CHECK-NEXT: 4 | int y
  104. // CHECK-NEXT: 8 | struct Empty::A c (empty)
  105. // CHECK-NEXT: | [sizeof=12, dsize=12, align=4,
  106. // CHECK-NEXT: | nvsize=12, nvalign=4]
  107. struct EmptyWithNonzeroDSizeNonPOD {
  108. ~EmptyWithNonzeroDSizeNonPOD();
  109. [[no_unique_address]] A a;
  110. int x;
  111. [[no_unique_address]] A b;
  112. int y;
  113. [[no_unique_address]] A c;
  114. };
  115. static_assert(sizeof(EmptyWithNonzeroDSizeNonPOD) == 12);
  116. // CHECK:*** Dumping AST Record Layout
  117. // CHECK: 0 | struct Empty::EmptyWithNonzeroDSizeNonPOD
  118. // CHECK-NEXT: 0 | struct Empty::A a (empty)
  119. // CHECK-NEXT: 0 | int x
  120. // CHECK-NEXT: 4 | struct Empty::A b (empty)
  121. // CHECK-NEXT: 4 | int y
  122. // CHECK-NEXT: 8 | struct Empty::A c (empty)
  123. // CHECK-NEXT: | [sizeof=12, dsize=8, align=4,
  124. // CHECK-NEXT: | nvsize=9, nvalign=4]
  125. }
  126. namespace POD {
  127. // Cannot reuse tail padding of a PDO type.
  128. struct A { int n; char c[3]; };
  129. struct B { [[no_unique_address]] A a; char d; };
  130. static_assert(sizeof(B) == 12);
  131. // CHECK:*** Dumping AST Record Layout
  132. // CHECK: 0 | struct POD::B
  133. // CHECK-NEXT: 0 | struct POD::A a
  134. // CHECK-NEXT: 0 | int n
  135. // CHECK-NEXT: 4 | char [3] c
  136. // CHECK-NEXT: 8 | char d
  137. // CHECK-NEXT: | [sizeof=12, dsize=12, align=4,
  138. // CHECK-NEXT: | nvsize=12, nvalign=4]
  139. }
  140. namespace NonPOD {
  141. struct A { int n; char c[3]; ~A(); };
  142. struct B { [[no_unique_address]] A a; char d; };
  143. static_assert(sizeof(B) == 8);
  144. // CHECK:*** Dumping AST Record Layout
  145. // CHECK: 0 | struct NonPOD::B
  146. // CHECK-NEXT: 0 | struct NonPOD::A a
  147. // CHECK-NEXT: 0 | int n
  148. // CHECK-NEXT: 4 | char [3] c
  149. // CHECK-NEXT: 7 | char d
  150. // CHECK-NEXT: | [sizeof=8, dsize=8, align=4,
  151. // CHECK-NEXT: | nvsize=8, nvalign=4]
  152. }
  153. namespace NVSizeGreaterThanDSize {
  154. // The nvsize of an object includes the complete size of its empty subobjects
  155. // (although it's unclear why). Ensure this corner case is handled properly.
  156. struct alignas(8) A { ~A(); }; // dsize 0, nvsize 0, size 8
  157. struct B : A { char c; }; // dsize 1, nvsize 8, size 8
  158. static_assert(sizeof(B) == 8);
  159. // CHECK:*** Dumping AST Record Layout
  160. // CHECK: 0 | struct NVSizeGreaterThanDSize::B
  161. // CHECK-NEXT: 0 | struct NVSizeGreaterThanDSize::A (base) (empty)
  162. // CHECK-NEXT: 0 | char c
  163. // CHECK-NEXT: | [sizeof=8, dsize=1, align=8,
  164. // CHECK-NEXT: | nvsize=8, nvalign=8]
  165. struct V { int n; };
  166. // V is at offset 16, not offset 12, because B's tail padding is strangely not
  167. // usable for virtual bases.
  168. struct C : B, virtual V {};
  169. static_assert(sizeof(C) == 24);
  170. // CHECK:*** Dumping AST Record Layout
  171. // CHECK: 0 | struct NVSizeGreaterThanDSize::C
  172. // CHECK-NEXT: 0 | (C vtable pointer)
  173. // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::B (base)
  174. // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A (base) (empty)
  175. // CHECK-NEXT: 8 | char c
  176. // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::V (virtual base)
  177. // CHECK-NEXT: 16 | int n
  178. // CHECK-NEXT: | [sizeof=24, dsize=20, align=8,
  179. // CHECK-NEXT: | nvsize=16, nvalign=8]
  180. struct D : virtual V {
  181. [[no_unique_address]] B b;
  182. };
  183. static_assert(sizeof(D) == 24);
  184. // CHECK:*** Dumping AST Record Layout
  185. // CHECK: 0 | struct NVSizeGreaterThanDSize::D
  186. // CHECK-NEXT: 0 | (D vtable pointer)
  187. // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::B b
  188. // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A (base) (empty)
  189. // CHECK-NEXT: 8 | char c
  190. // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::V (virtual base)
  191. // CHECK-NEXT: 16 | int n
  192. // CHECK-NEXT: | [sizeof=24, dsize=20, align=8,
  193. // CHECK-NEXT: | nvsize=16, nvalign=8]
  194. struct X : virtual A { [[no_unique_address]] A a; };
  195. struct E : virtual A {
  196. [[no_unique_address]] A a;
  197. // Here, we arrange for X to hang over the end of the nvsize of E. This
  198. // should force the A vbase to be laid out at offset 24, not 16.
  199. [[no_unique_address]] X x;
  200. };
  201. static_assert(sizeof(E) == 32);
  202. // CHECK:*** Dumping AST Record Layout
  203. // CHECK: 0 | struct NVSizeGreaterThanDSize::E
  204. // CHECK-NEXT: 0 | (E vtable pointer)
  205. // CHECK-NEXT: 0 | struct NVSizeGreaterThanDSize::A a (empty)
  206. // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::X x
  207. // CHECK-NEXT: 8 | (X vtable pointer)
  208. // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A a (empty)
  209. // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::A (virtual base) (empty)
  210. // CHECK-NEXT: 24 | struct NVSizeGreaterThanDSize::A (virtual base) (empty)
  211. // CHECK-NEXT: | [sizeof=32, dsize=16, align=8,
  212. // CHECK-NEXT: | nvsize=16, nvalign=8]
  213. }
  214. namespace RepeatedVBase {
  215. struct alignas(16) A { ~A(); };
  216. struct B : A {};
  217. struct X : virtual A, virtual B {};
  218. struct Y { [[no_unique_address]] X x; char c; };
  219. static_assert(sizeof(Y) == 32);
  220. // CHECK:*** Dumping AST Record Layout
  221. // CHECK: 0 | struct RepeatedVBase::Y
  222. // CHECK-NEXT: 0 | struct RepeatedVBase::X x
  223. // CHECK-NEXT: 0 | (X vtable pointer)
  224. // CHECK-NEXT: 0 | struct RepeatedVBase::A (virtual base) (empty)
  225. // CHECK-NEXT: 16 | struct RepeatedVBase::B (virtual base) (empty)
  226. // CHECK-NEXT: 16 | struct RepeatedVBase::A (base) (empty)
  227. // CHECK-NEXT: 8 | char c
  228. // CHECK-NEXT: | [sizeof=32, dsize=9, align=16,
  229. // CHECK-NEXT: | nvsize=9, nvalign=16]
  230. }