clang: lib/AST/RecordLayoutBuilder.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
20#include "llvm/Support/Format.h"
21#include "llvm/Support/MathExtras.h"
22
23using namespace clang;
24
25namespace {
26
27
28
29
30
31
32
33
34
35
36
37
38struct BaseSubobjectInfo {
39
40 const CXXRecordDecl *Class;
41
42
43 bool IsVirtual;
44
45
46 SmallVector<BaseSubobjectInfo*, 4> Bases;
47
48
49
50 BaseSubobjectInfo *PrimaryVirtualBaseInfo;
51
52
53 const BaseSubobjectInfo *Derived;
54};
55
56
57
58
59struct ExternalLayout {
60 ExternalLayout() = default;
61
62
64
65
67
68
69 llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
70
71
72 llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
73
74
75 llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
76
77
78
79 uint64_t getExternalFieldOffset(const FieldDecl *FD) {
80 assert(FieldOffsets.count(FD) &&
81 "Field does not have an external offset");
82 return FieldOffsets[FD];
83 }
84
85 bool getExternalNVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) {
86 auto Known = BaseOffsets.find(RD);
87 if (Known == BaseOffsets.end())
88 return false;
89 BaseOffset = Known->second;
90 return true;
91 }
92
93 bool getExternalVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) {
94 auto Known = VirtualBaseOffsets.find(RD);
95 if (Known == VirtualBaseOffsets.end())
96 return false;
97 BaseOffset = Known->second;
98 return true;
99 }
100};
101
102
103
104class EmptySubobjectMap {
105 const ASTContext &Context;
107
108
109 const CXXRecordDecl *Class;
110
111
112 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
113 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
114 EmptyClassOffsetsMapTy EmptyClassOffsets;
115
116
117
118 CharUnits MaxEmptyClassOffset;
119
120
121
122 void ComputeEmptySubobjectSizes();
123
124 void AddSubobjectAtOffset(const CXXRecordDecl *RD, CharUnits Offset);
125
126 void UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
127 CharUnits Offset, bool PlacingEmptyBase);
128
129 void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
130 const CXXRecordDecl *Class, CharUnits Offset,
131 bool PlacingOverlappingField);
132 void UpdateEmptyFieldSubobjects(const FieldDecl *FD, CharUnits Offset,
133 bool PlacingOverlappingField);
134
135
136
137 bool AnyEmptySubobjectsBeyondOffset(CharUnits Offset) const {
138 return Offset <= MaxEmptyClassOffset;
139 }
140
141 CharUnits getFieldOffset(const ASTRecordLayout &Layout,
142 const FieldDecl *Field) const {
144 assert(FieldOffset % CharWidth == 0 &&
145 "Field offset not at char boundary!");
146
147 return Context.toCharUnitsFromBits(FieldOffset);
148 }
149
150protected:
151 bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
152 CharUnits Offset) const;
153
154 bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
155 CharUnits Offset);
156
157 bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
158 const CXXRecordDecl *Class,
159 CharUnits Offset) const;
160 bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
161 CharUnits Offset) const;
162
163public:
164
165
166
167 CharUnits SizeOfLargestEmptySubobject;
168
169 EmptySubobjectMap(const ASTContext &Context, const CXXRecordDecl *Class)
170 : Context(Context), CharWidth(Context.getCharWidth()), Class(Class) {
171 ComputeEmptySubobjectSizes();
172 }
173
174
175
176
177
178 bool CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
179 CharUnits Offset);
180
181
182
183 bool CanPlaceFieldAtOffset(const FieldDecl *FD, CharUnits Offset);
184};
185
186void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
187
188 for (const CXXBaseSpecifier &Base : Class->bases()) {
189 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
190 assert(BaseDecl != Class && "Class cannot inherit from itself.");
191
192 CharUnits EmptySize;
193 const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
194 if (BaseDecl->isEmpty()) {
195
196 EmptySize = Layout.getSize();
197 } else {
198
200 }
201
202 if (EmptySize > SizeOfLargestEmptySubobject)
203 SizeOfLargestEmptySubobject = EmptySize;
204 }
205
206
207 for (const FieldDecl *FD : Class->fields()) {
208
209 const auto *MemberDecl =
211 if (!MemberDecl)
212 continue;
213
214 CharUnits EmptySize;
215 const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl);
216 if (MemberDecl->isEmpty()) {
217
218 EmptySize = Layout.getSize();
219 } else {
220
222 }
223
224 if (EmptySize > SizeOfLargestEmptySubobject)
225 SizeOfLargestEmptySubobject = EmptySize;
226 }
227}
228
229bool
230EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
231 CharUnits Offset) const {
232
234 return true;
235
236 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
237 if (I == EmptyClassOffsets.end())
238 return true;
239
240 const ClassVectorTy &Classes = I->second;
241 if (!llvm::is_contained(Classes, RD))
242 return true;
243
244
245 return false;
246}
247
248void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,
249 CharUnits Offset) {
250
252 return;
253
254
255
256 ClassVectorTy &Classes = EmptyClassOffsets[Offset];
257 if (llvm::is_contained(Classes, RD))
258 return;
259
260 Classes.push_back(RD);
261
262
263 if (Offset > MaxEmptyClassOffset)
264 MaxEmptyClassOffset = Offset;
265}
266
267bool
268EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
269 CharUnits Offset) {
270
271
272 if (!AnyEmptySubobjectsBeyondOffset(Offset))
273 return true;
274
275 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
276 return false;
277
278
279 const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
280 for (const BaseSubobjectInfo *Base : Info->Bases) {
281 if (Base->IsVirtual)
282 continue;
283
285
286 if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))
287 return false;
288 }
289
290 if (Info->PrimaryVirtualBaseInfo) {
291 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
292
293 if (Info == PrimaryVirtualBaseInfo->Derived) {
294 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
295 return false;
296 }
297 }
298
299
300 for (const FieldDecl *Field : Info->Class->fields()) {
301 if (Field->isBitField())
302 continue;
303
304 CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
305 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
306 return false;
307 }
308
309 return true;
310}
311
312void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
313 CharUnits Offset,
314 bool PlacingEmptyBase) {
315 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
316
317
318
319
320
321 return;
322 }
323
324 AddSubobjectAtOffset(Info->Class, Offset);
325
326
327 const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
328 for (const BaseSubobjectInfo *Base : Info->Bases) {
329 if (Base->IsVirtual)
330 continue;
331
333 UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);
334 }
335
336 if (Info->PrimaryVirtualBaseInfo) {
337 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
338
339 if (Info == PrimaryVirtualBaseInfo->Derived)
340 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
341 PlacingEmptyBase);
342 }
343
344
345 for (const FieldDecl *Field : Info->Class->fields()) {
346 if (Field->isBitField())
347 continue;
348
349 CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
350 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingEmptyBase);
351 }
352}
353
354bool EmptySubobjectMap::CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
355 CharUnits Offset) {
356
357
358 if (SizeOfLargestEmptySubobject.isZero())
359 return true;
360
361 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
362 return false;
363
364
365
366 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
367 return true;
368}
369
370bool
371EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
372 const CXXRecordDecl *Class,
373 CharUnits Offset) const {
374
375
376 if (!AnyEmptySubobjectsBeyondOffset(Offset))
377 return true;
378
379 if (!CanPlaceSubobjectAtOffset(RD, Offset))
380 return false;
381
383
384
385 for (const CXXBaseSpecifier &Base : RD->bases()) {
386 if (Base.isVirtual())
387 continue;
388
389 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
390
392 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
393 return false;
394 }
395
396 if (RD == Class) {
397
398 for (const CXXBaseSpecifier &Base : RD->vbases()) {
399 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
400
402 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
403 return false;
404 }
405 }
406
407
408 for (const FieldDecl *Field : RD->fields()) {
409 if (Field->isBitField())
410 continue;
411
412 CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
413 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
414 return false;
415 }
416
417 return true;
418}
419
420bool
421EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
422 CharUnits Offset) const {
423
424
425 if (!AnyEmptySubobjectsBeyondOffset(Offset))
426 return true;
427
430 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
431
432
436 if (!RD)
437 return true;
438
440
442 CharUnits ElementOffset = Offset;
443 for (uint64_t I = 0; I != NumElements; ++I) {
444
445
446 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
447 return true;
448
449 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
450 return false;
451
452 ElementOffset += Layout.getSize();
453 }
454 }
455
456 return true;
457}
458
459bool EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,
460 CharUnits Offset) {
461 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
462 return false;
463
464
465
466 UpdateEmptyFieldSubobjects(FD, Offset, FD->hasAttr());
467 return true;
468}
469
470void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
471 const CXXRecordDecl *RD, const CXXRecordDecl *Class, CharUnits Offset,
472 bool PlacingOverlappingField) {
473
474
475
476
477
478
479
480
481
482
483 if (!PlacingOverlappingField && Offset >= SizeOfLargestEmptySubobject)
484 return;
485
486 AddSubobjectAtOffset(RD, Offset);
487
489
490
491 for (const CXXBaseSpecifier &Base : RD->bases()) {
492 if (Base.isVirtual())
493 continue;
494
495 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
496
498 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset,
499 PlacingOverlappingField);
500 }
501
502 if (RD == Class) {
503
504 for (const CXXBaseSpecifier &Base : RD->vbases()) {
505 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
506
508 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset,
509 PlacingOverlappingField);
510 }
511 }
512
513
514 for (const FieldDecl *Field : RD->fields()) {
515 if (Field->isBitField())
516 continue;
517
518 CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
519 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingOverlappingField);
520 }
521}
522
523void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
524 const FieldDecl *FD, CharUnits Offset, bool PlacingOverlappingField) {
527 UpdateEmptyFieldSubobjects(RD, RD, Offset, PlacingOverlappingField);
528 return;
529 }
530
531
535 if (!RD)
536 return;
537
539
541 CharUnits ElementOffset = Offset;
542
543 for (uint64_t I = 0; I != NumElements; ++I) {
544
545
546
547
548
549 if (!PlacingOverlappingField &&
550 ElementOffset >= SizeOfLargestEmptySubobject)
551 return;
552
553 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
554 PlacingOverlappingField);
555 ElementOffset += Layout.getSize();
556 }
557 }
558}
559
560typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy;
561
562class ItaniumRecordLayoutBuilder {
563protected:
564
565 friend class clang::ASTContext;
566
567 const ASTContext &Context;
568
569 EmptySubobjectMap *EmptySubobjects;
570
571
573
574
575 CharUnits Alignment;
576
577
578 CharUnits PreferredAlignment;
579
580
581 CharUnits UnpackedAlignment;
582
583
584 CharUnits UnadjustedAlignment;
585
586 SmallVector<uint64_t, 16> FieldOffsets;
587
588
589
590 LLVM_PREFERRED_TYPE(bool)
591 unsigned UseExternalLayout : 1;
592
593
594
595 LLVM_PREFERRED_TYPE(bool)
596 unsigned InferAlignment : 1;
597
598
599 LLVM_PREFERRED_TYPE(bool)
601
602 LLVM_PREFERRED_TYPE(bool)
603 unsigned IsUnion : 1;
604
605 LLVM_PREFERRED_TYPE(bool)
606 unsigned IsMac68kAlign : 1;
607
608 LLVM_PREFERRED_TYPE(bool)
609 unsigned IsNaturalAlign : 1;
610
611 LLVM_PREFERRED_TYPE(bool)
612 unsigned IsMsStruct : 1;
613
614
615
616
617
618 unsigned char UnfilledBitsInLastUnit;
619
620
621
622 unsigned char LastBitfieldStorageUnitSize;
623
624
625
626 CharUnits MaxFieldAlignment;
627
628
630
631 CharUnits NonVirtualSize;
632 CharUnits NonVirtualAlignment;
633 CharUnits PreferredNVAlignment;
634
635
636
637 CharUnits PaddedFieldSize;
638
639
640
641 const CXXRecordDecl *PrimaryBase;
642
643
644
645 bool PrimaryBaseIsVirtual;
646
647
648
649 bool HasOwnVFPtr;
650
651
652 bool HasPackedField;
653
654
655
656
657
658 bool HandledFirstNonOverlappingEmptyField;
659
660 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
661
662
663 BaseOffsetsMapTy Bases;
664
665
667
668
669
670 CXXIndirectPrimaryBaseSet IndirectPrimaryBases;
671
672
673
674 const CXXRecordDecl *FirstNearlyEmptyVBase;
675
676
677
678 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
679
680
682
683 ItaniumRecordLayoutBuilder(const ASTContext &Context,
684 EmptySubobjectMap *EmptySubobjects)
685 : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
686 Alignment(CharUnits::One()), PreferredAlignment(CharUnits::One()),
687 UnpackedAlignment(CharUnits::One()),
688 UnadjustedAlignment(CharUnits::One()), UseExternalLayout(false),
690 IsMac68kAlign(false),
691 IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX()),
692 IsMsStruct(false), UnfilledBitsInLastUnit(0),
693 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(CharUnits::Zero()),
694 DataSize(0), NonVirtualSize(CharUnits::Zero()),
695 NonVirtualAlignment(CharUnits::One()),
696 PreferredNVAlignment(CharUnits::One()),
697 PaddedFieldSize(CharUnits::Zero()), PrimaryBase(nullptr),
698 PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), HasPackedField(false),
699 HandledFirstNonOverlappingEmptyField(false),
700 FirstNearlyEmptyVBase(nullptr) {}
701
702 void Layout(const RecordDecl *D);
703 void Layout(const CXXRecordDecl *D);
704 void Layout(const ObjCInterfaceDecl *D);
705
706 void LayoutFields(const RecordDecl *D);
707 void LayoutField(const FieldDecl *D, bool InsertExtraPadding);
708 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
709 bool FieldPacked, const FieldDecl *D);
710 void LayoutBitField(const FieldDecl *D);
711
712 TargetCXXABI getCXXABI() const {
714 }
715
716
717 llvm::SpecificBumpPtrAllocator BaseSubobjectInfoAllocator;
718
719 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
720 BaseSubobjectInfoMapTy;
721
722
723
724 BaseSubobjectInfoMapTy VirtualBaseInfo;
725
726
727
728 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
729
730
731
732 void ComputeBaseSubobjectInfo(const CXXRecordDecl *RD);
733
734
735
736 BaseSubobjectInfo *ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
737 bool IsVirtual,
738 BaseSubobjectInfo *Derived);
739
740
741 void DeterminePrimaryBase(const CXXRecordDecl *RD);
742
743 void SelectPrimaryVBase(const CXXRecordDecl *RD);
744
745 void EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign);
746
747
748
749 void LayoutNonVirtualBases(const CXXRecordDecl *RD);
750
751
752 void LayoutNonVirtualBase(const BaseSubobjectInfo *Base);
753
754 void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
755 CharUnits Offset);
756
757
758 void LayoutVirtualBases(const CXXRecordDecl *RD,
759 const CXXRecordDecl *MostDerivedClass);
760
761
762 void LayoutVirtualBase(const BaseSubobjectInfo *Base);
763
764
765
766 CharUnits LayoutBase(const BaseSubobjectInfo *Base);
767
768
769 void InitializeLayout(const Decl *D);
770
771
772
773 void FinishLayout(const NamedDecl *D);
774
775 void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
776 CharUnits PreferredAlignment);
777 void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {
778 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
779 }
780 void UpdateAlignment(CharUnits NewAlignment) {
781 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
782 }
783
784
785
786
787
788
789 uint64_t updateExternalFieldOffset(const FieldDecl *Field,
790 uint64_t ComputedOffset);
791
793 uint64_t UnpackedOffset, unsigned UnpackedAlign,
794 bool isPacked, const FieldDecl *D);
795
796 DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
797
798 CharUnits getSize() const {
801 }
802 uint64_t getSizeInBits() const { return Size; }
803
804 void setSize(CharUnits NewSize) { Size = Context.toBits(NewSize); }
805 void setSize(uint64_t NewSize) { Size = NewSize; }
806
807 CharUnits getAlignment() const { return Alignment; }
808
809 CharUnits getDataSize() const {
810 assert(DataSize % Context.getCharWidth() == 0);
812 }
813 uint64_t getDataSizeInBits() const { return DataSize; }
814
815 void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
816 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
817
818 ItaniumRecordLayoutBuilder(const ItaniumRecordLayoutBuilder &) = delete;
819 void operator=(const ItaniumRecordLayoutBuilder &) = delete;
820};
821}
822
823void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
824 for (const auto &I : RD->bases()) {
825 assert(!I.getType()->isDependentType() &&
826 "Cannot layout class with dependent bases.");
827
828 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
829
830
831 if (I.isVirtual() && Context.isNearlyEmpty(Base)) {
832
833
834 if (!IndirectPrimaryBases.count(Base)) {
835 PrimaryBase = Base;
836 PrimaryBaseIsVirtual = true;
837 return;
838 }
839
840
841 if (!FirstNearlyEmptyVBase)
842 FirstNearlyEmptyVBase = Base;
843 }
844
845 SelectPrimaryVBase(Base);
846 if (PrimaryBase)
847 return;
848 }
849}
850
851
852void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
853
855 return;
856
857
858
860
861
862
863
864 for (const auto &I : RD->bases()) {
865
866 if (I.isVirtual())
867 continue;
868
869 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
870
871 if (Base->isDynamicClass()) {
872
873 PrimaryBase = Base;
874 PrimaryBaseIsVirtual = false;
875 return;
876 }
877 }
878
879
880
881
882
884 SelectPrimaryVBase(RD);
885 if (PrimaryBase)
886 return;
887 }
888
889
890 if (FirstNearlyEmptyVBase) {
891 PrimaryBase = FirstNearlyEmptyVBase;
892 PrimaryBaseIsVirtual = true;
893 return;
894 }
895
896 assert(!PrimaryBase && "Should not get here with a primary base!");
897}
898
899BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
900 const CXXRecordDecl *RD, bool IsVirtual, BaseSubobjectInfo *Derived) {
901 BaseSubobjectInfo *Info;
902
903 if (IsVirtual) {
904
905 BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
906 if (InfoSlot) {
907 assert(InfoSlot->Class == RD && "Wrong class for virtual base info!");
908 return InfoSlot;
909 }
910
911
912 InfoSlot = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
913 Info = InfoSlot;
914 } else {
915 Info = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
916 }
917
918 Info->Class = RD;
919 Info->IsVirtual = IsVirtual;
920 Info->Derived = nullptr;
921 Info->PrimaryVirtualBaseInfo = nullptr;
922
923 const CXXRecordDecl *PrimaryVirtualBase = nullptr;
924 BaseSubobjectInfo *PrimaryVirtualBaseInfo = nullptr;
925
926
930
932 assert(PrimaryVirtualBase && "Didn't have a primary virtual base!");
933
934
935 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
936
937 if (PrimaryVirtualBaseInfo) {
938 if (PrimaryVirtualBaseInfo->Derived) {
939
940
941
942 PrimaryVirtualBase = nullptr;
943 } else {
944
945 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
946 PrimaryVirtualBaseInfo->Derived = Info;
947 }
948 }
949 }
950 }
951
952
953 for (const auto &I : RD->bases()) {
954 bool IsVirtual = I.isVirtual();
955
956 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
957
958 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
959 }
960
961 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
962
963
964 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
965 assert(PrimaryVirtualBaseInfo &&
966 "Did not create a primary virtual base!");
967
968
969 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
970 PrimaryVirtualBaseInfo->Derived = Info;
971 }
972
973 return Info;
974}
975
976void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
977 const CXXRecordDecl *RD) {
978 for (const auto &I : RD->bases()) {
979 bool IsVirtual = I.isVirtual();
980
981 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
982
983
984 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
985 nullptr);
986
987 if (IsVirtual) {
988
989 assert(VirtualBaseInfo.count(BaseDecl) &&
990 "Did not add virtual base!");
991 } else {
992
993 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
994 "Non-virtual base already exists!");
995 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
996 }
997 }
998}
999
1000void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
1001 CharUnits UnpackedBaseAlign) {
1003
1004
1005 if (!MaxFieldAlignment.isZero()) {
1006 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1007 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1008 }
1009
1010
1011 setSize(getSize().alignTo(BaseAlign));
1012
1013
1014 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
1015}
1016
1017void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
1018 const CXXRecordDecl *RD) {
1019
1020 DeterminePrimaryBase(RD);
1021
1022
1023 ComputeBaseSubobjectInfo(RD);
1024
1025
1026 if (PrimaryBase) {
1027 if (PrimaryBaseIsVirtual) {
1028
1029
1030 BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
1031 PrimaryBaseInfo->Derived = nullptr;
1032
1033
1034 IndirectPrimaryBases.insert(PrimaryBase);
1035
1036 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1037 "vbase already visited!");
1038 VisitedVirtualBases.insert(PrimaryBase);
1039
1040 LayoutVirtualBase(PrimaryBaseInfo);
1041 } else {
1042 BaseSubobjectInfo *PrimaryBaseInfo =
1043 NonVirtualBaseInfo.lookup(PrimaryBase);
1044 assert(PrimaryBaseInfo &&
1045 "Did not find base info for non-virtual primary base!");
1046
1047 LayoutNonVirtualBase(PrimaryBaseInfo);
1048 }
1049
1050
1051
1053 assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
1058 EnsureVTablePointerAlignment(PtrAlign);
1059 HasOwnVFPtr = true;
1060
1061 assert(!IsUnion && "Unions cannot be dynamic classes.");
1062 HandledFirstNonOverlappingEmptyField = true;
1063
1064 setSize(getSize() + PtrWidth);
1065 setDataSize(getSize());
1066 }
1067
1068
1069 for (const auto &I : RD->bases()) {
1070
1071
1072 if (I.isVirtual())
1073 continue;
1074
1075 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1076
1077
1078
1079
1080 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1081 continue;
1082
1083
1084 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.lookup(BaseDecl);
1085 assert(BaseInfo && "Did not find base info for non-virtual base!");
1086
1087 LayoutNonVirtualBase(BaseInfo);
1088 }
1089}
1090
1091void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1092 const BaseSubobjectInfo *Base) {
1093
1094 CharUnits Offset = LayoutBase(Base);
1095
1096
1097 assert(!Bases.count(Base->Class) && "base offset already exists!");
1098 Bases.insert(std::make_pair(Base->Class, Offset));
1099
1100 AddPrimaryVirtualBaseOffsets(Base, Offset);
1101}
1102
1103void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1104 const BaseSubobjectInfo *Info, CharUnits Offset) {
1105
1107 return;
1108
1109
1110 if (Info->PrimaryVirtualBaseInfo) {
1111 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1112 "Primary virtual base is not virtual!");
1113 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1114
1115 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1116 "primary vbase offset already exists!");
1117 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1118 ASTRecordLayout::VBaseInfo(Offset, false)));
1119
1120
1121 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1122 }
1123 }
1124
1125
1126 const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
1127 for (const BaseSubobjectInfo *Base : Info->Bases) {
1128 if (Base->IsVirtual)
1129 continue;
1130
1132 AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
1133 }
1134}
1135
1136void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1137 const CXXRecordDecl *RD, const CXXRecordDecl *MostDerivedClass) {
1138 const CXXRecordDecl *PrimaryBase;
1139 bool PrimaryBaseIsVirtual;
1140
1141 if (MostDerivedClass == RD) {
1142 PrimaryBase = this->PrimaryBase;
1143 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1144 } else {
1148 }
1149
1150 for (const CXXBaseSpecifier &Base : RD->bases()) {
1151 assert(.getType()->isDependentType() &&
1152 "Cannot layout class with dependent bases.");
1153
1154 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1155
1156 if (Base.isVirtual()) {
1157 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1158 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1159
1160
1161 if (!IndirectPrimaryBase) {
1162
1163 if (!VisitedVirtualBases.insert(BaseDecl).second)
1164 continue;
1165
1166 const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
1167 assert(BaseInfo && "Did not find virtual base info!");
1168 LayoutVirtualBase(BaseInfo);
1169 }
1170 }
1171 }
1172
1174
1175 continue;
1176 }
1177
1178 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1179 }
1180}
1181
1182void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1183 const BaseSubobjectInfo *Base) {
1184 assert(->Derived && "Trying to lay out a primary virtual base!");
1185
1186
1187 CharUnits Offset = LayoutBase(Base);
1188
1189
1190 assert(!VBases.count(Base->Class) && "vbase offset already exists!");
1191 VBases.insert(std::make_pair(Base->Class,
1192 ASTRecordLayout::VBaseInfo(Offset, false)));
1193
1194 AddPrimaryVirtualBaseOffsets(Base, Offset);
1195}
1196
1197CharUnits
1198ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
1199 assert(!IsUnion && "Unions cannot have base classes.");
1200
1202 CharUnits Offset;
1203
1204
1205 bool HasExternalLayout = false;
1206 if (UseExternalLayout) {
1207 if (Base->IsVirtual)
1208 HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
1209 else
1210 HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
1211 }
1212
1213 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](CharUnits UnpackedAlign) {
1214
1215
1216 return (Packed && ((Context.getLangOpts().getClangABICompat() <=
1217 LangOptions::ClangABI::Ver6) ||
1221 : UnpackedAlign;
1222 };
1223
1226 CharUnits BaseAlign =
1227 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1228 CharUnits PreferredBaseAlign =
1229 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1230
1231 const bool DefaultsToAIXPowerAlignment =
1233 if (DefaultsToAIXPowerAlignment) {
1234
1235
1236
1237
1238 if (->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1239
1240
1241 HandledFirstNonOverlappingEmptyField = true;
1242 } else if (!IsNaturalAlign) {
1243 UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1244 PreferredBaseAlign = BaseAlign;
1245 }
1246 }
1247
1248 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1249 ? UnpackedBaseAlign
1250 : UnpackedPreferredBaseAlign;
1251
1252 if (Base->Class->isEmpty() &&
1254 EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) {
1255 setSize(std::max(getSize(), Layout.getSize()));
1256
1258 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1259
1261 }
1262
1263
1264
1265 if (!MaxFieldAlignment.isZero()) {
1266 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1267 PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);
1268 UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);
1269 }
1270
1271 CharUnits AlignTo =
1272 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
1273 if (!HasExternalLayout) {
1274
1275 Offset = getDataSize().alignTo(AlignTo);
1276
1277
1278 while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))
1279 Offset += AlignTo;
1280 } else {
1281 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
1282 (void)Allowed;
1283 assert(Allowed && "Base subobject externally placed at overlapping offset");
1284
1285 if (InferAlignment && Offset < getDataSize().alignTo(AlignTo)) {
1286
1287
1289 InferAlignment = false;
1290 }
1291 }
1292
1293 if (->Class->isEmpty()) {
1294
1296
1297 setSize(std::max(getSize(), getDataSize()));
1298 } else
1299 setSize(std::max(getSize(), Offset + Layout.getSize()));
1300
1301
1302 UnadjustedAlignment = std::max(UnadjustedAlignment, BaseAlign);
1303 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1304
1305 return Offset;
1306}
1307
1308void ItaniumRecordLayoutBuilder::InitializeLayout(const Decl *D) {
1309 if (const RecordDecl *RD = dyn_cast(D)) {
1310 IsUnion = RD->isUnion();
1311 IsMsStruct = RD->isMsStruct(Context);
1312 }
1313
1315
1316
1317 if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) {
1319 }
1320
1321
1322
1323
1324
1325 if (D->hasAttr()) {
1326 assert(
1327 !D->hasAttr() &&
1328 "Having both mac68k and natural alignment on a decl is not allowed.");
1329 IsMac68kAlign = true;
1333 } else {
1334 if (D->hasAttr())
1335 IsNaturalAlign = true;
1336
1337 if (const MaxFieldAlignmentAttr *MFAA = D->getAttr())
1339
1342 }
1343
1344 HandledFirstNonOverlappingEmptyField =
1346
1347
1348 if (const RecordDecl *RD = dyn_cast(D))
1350 UseExternalLayout = Source->layoutRecordType(
1353
1354
1355 if (UseExternalLayout) {
1359 } else {
1360
1361 InferAlignment = true;
1362 }
1363 }
1364 }
1365}
1366
1367void ItaniumRecordLayoutBuilder::Layout(const RecordDecl *D) {
1368 InitializeLayout(D);
1369 LayoutFields(D);
1370
1371
1372
1373 FinishLayout(D);
1374}
1375
1376void ItaniumRecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
1377 InitializeLayout(RD);
1378
1379
1380 LayoutNonVirtualBases(RD);
1381
1382 LayoutFields(RD);
1383
1386 NonVirtualAlignment = Alignment;
1387 PreferredNVAlignment = PreferredAlignment;
1388
1389
1390 LayoutVirtualBases(RD, RD);
1391
1392
1393
1394 FinishLayout(RD);
1395
1396#ifndef NDEBUG
1397
1398 for (const CXXBaseSpecifier &Base : RD->bases()) {
1399 if (Base.isVirtual())
1400 continue;
1401
1402 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1403
1404 assert(Bases.count(BaseDecl) && "Did not find base offset!");
1405 }
1406
1407
1408 for (const CXXBaseSpecifier &Base : RD->vbases()) {
1409 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1410
1411 assert(VBases.count(BaseDecl) && "Did not find base offset!");
1412 }
1413#endif
1414}
1415
1416void ItaniumRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
1417 if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
1419
1421
1422
1423
1425 setSize(getDataSize());
1426 }
1427
1428 InitializeLayout(D);
1429
1432 LayoutField(IVD, false);
1433
1434
1435
1436 FinishLayout(D);
1437}
1438
1439void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
1440
1441
1445 LayoutField(*I, InsertExtraPadding &&
1446 (std::next(I) != End || !HasFlexibleArrayMember));
1447 }
1448}
1449
1450
1454 uint64_t CharAlignment = Context.getTargetInfo().getCharAlign();
1455 return llvm::alignTo(Size, CharAlignment);
1456}
1457
1458void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1459 uint64_t StorageUnitSize,
1460 bool FieldPacked,
1461 const FieldDecl *D) {
1462 assert(Context.getLangOpts().CPlusPlus &&
1463 "Can only have wide bit-fields in C++!");
1464
1465
1466
1467
1468
1469 QualType IntegralPODTypes[] = {
1473 };
1474
1475 QualType Type;
1478 for (const QualType &QT : IntegralPODTypes) {
1480
1481 if (Size > FieldSize || Size > MaxSize)
1482 break;
1483
1485 }
1486 assert(.isNull() && "Did not find a type!");
1487
1489
1490
1491 UnfilledBitsInLastUnit = 0;
1492 LastBitfieldStorageUnitSize = 0;
1493
1495 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1496
1497 if (IsUnion) {
1499 Context);
1500 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1501 FieldOffset = 0;
1502 } else {
1503
1504
1505 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.toBits(TypeAlign));
1506
1507 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1508
1509 setDataSize(
1511 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1512 }
1513
1514
1515 FieldOffsets.push_back(FieldOffset);
1516
1517 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1518 Context.toBits(TypeAlign), FieldPacked, D);
1519
1520
1521 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1522
1523
1524 UnadjustedAlignment = std::max(UnadjustedAlignment, TypeAlign);
1525 UpdateAlignment(TypeAlign);
1526}
1527
1529 return Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX;
1530}
1531
1532void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
1533 bool FieldPacked = Packed || D->hasAttr();
1537 unsigned FieldAlign = FieldInfo.Align;
1539 unsigned char PaddingInLastUnit = 0;
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599 if (IsMsStruct) {
1600
1601 FieldAlign = StorageUnitSize;
1602
1603
1604
1605
1606 if (LastBitfieldStorageUnitSize != StorageUnitSize ||
1607 UnfilledBitsInLastUnit < FieldSize) {
1608
1609 if (!LastBitfieldStorageUnitSize && !FieldSize)
1610 FieldAlign = 1;
1611
1612 PaddingInLastUnit = UnfilledBitsInLastUnit;
1613 UnfilledBitsInLastUnit = 0;
1614 LastBitfieldStorageUnitSize = 0;
1615 }
1616 }
1617
1620
1621
1625 FieldSize <= 32) {
1626
1627
1628 StorageUnitSize = 32;
1629
1630 if (!AlignIsRequired)
1631 FieldAlign = 32;
1632 }
1633
1634 if (FieldAlign < StorageUnitSize) {
1635
1636
1637 FieldAlign = StorageUnitSize;
1638 }
1639 }
1640
1641
1642
1643
1644 if (FieldSize > StorageUnitSize && (Context)) {
1645 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);
1646 return;
1647 }
1648
1649
1651 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1652
1653
1655
1656 if (FieldSize == 0 &&
1658
1659 if (!IsUnion && FieldOffset == 0 &&
1661 FieldAlign = 1;
1662 else {
1663
1664
1665 unsigned ZeroLengthBitfieldBoundary =
1667 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1668 }
1669
1670 } else {
1671 FieldAlign = 1;
1672 }
1673 }
1674
1675
1676 unsigned UnpackedFieldAlign = FieldAlign;
1677
1678
1679 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1680 FieldAlign = 1;
1681
1682
1684 if (ExplicitFieldAlign) {
1685 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1686 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1687 }
1688
1689
1690
1691 unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment);
1692 if (!MaxFieldAlignment.isZero() && FieldSize) {
1693 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1694 if (FieldPacked)
1695 FieldAlign = UnpackedFieldAlign;
1696 else
1697 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1698 }
1699
1700
1701
1702 if (IsMsStruct && IsUnion) {
1703 FieldAlign = UnpackedFieldAlign = 1;
1704 }
1705
1706
1707
1708
1709 uint64_t UnpaddedFieldOffset = FieldOffset - PaddingInLastUnit;
1710 uint64_t UnpackedFieldOffset = FieldOffset;
1711
1712
1713
1714
1715 if (IsMsStruct) {
1716
1717
1718
1719
1720 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1721 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1722 UnpackedFieldOffset =
1723 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1724 UnfilledBitsInLastUnit = 0;
1725 }
1726
1727 } else {
1728
1729 bool AllowPadding = MaxFieldAlignment.isZero();
1730
1731
1732 if (FieldSize == 0 ||
1733 (AllowPadding &&
1734 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
1735 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1736 } else if (ExplicitFieldAlign &&
1737 (MaxFieldAlignmentInBits == 0 ||
1738 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1740
1741
1742 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1743 }
1744
1745
1746 if (FieldSize == 0 ||
1747 (AllowPadding &&
1748 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1749 StorageUnitSize))
1750 UnpackedFieldOffset =
1751 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1752 else if (ExplicitFieldAlign &&
1753 (MaxFieldAlignmentInBits == 0 ||
1754 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1756 UnpackedFieldOffset =
1757 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1758 }
1759
1760
1761
1762 if (UseExternalLayout)
1763 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1764
1765
1766 FieldOffsets.push_back(FieldOffset);
1767
1768
1769
1770
1771
1772 if (!IsMsStruct &&
1775 FieldAlign = UnpackedFieldAlign = 1;
1776
1777
1778
1779
1780 if (isAIXLayout(Context) && !FieldSize) {
1781 if (FieldPacked)
1782 FieldAlign = 1;
1783 if (!MaxFieldAlignment.isZero()) {
1784 UnpackedFieldAlign =
1785 std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1786 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1787 }
1788 }
1789
1790
1791 if (!UseExternalLayout)
1792 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1793 UnpackedFieldAlign, FieldPacked, D);
1794
1795
1796
1797
1798 if (IsUnion) {
1799
1800
1802 if (IsMsStruct) {
1803 RoundedFieldSize = (FieldSize ? StorageUnitSize
1805
1806
1807
1808 } else {
1810 }
1811 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1812
1813
1814
1815 } else if (IsMsStruct && FieldSize) {
1816
1817
1818 if (!UnfilledBitsInLastUnit) {
1819 setDataSize(FieldOffset + StorageUnitSize);
1820 UnfilledBitsInLastUnit = StorageUnitSize;
1821 }
1822 UnfilledBitsInLastUnit -= FieldSize;
1823 LastBitfieldStorageUnitSize = StorageUnitSize;
1824
1825
1826
1827
1828 } else {
1829 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1831 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1832 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1833
1834
1835
1836
1837 LastBitfieldStorageUnitSize = 0;
1838 }
1839
1840
1841 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1842
1843
1844 UnadjustedAlignment =
1848}
1849
1850void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
1851 bool InsertExtraPadding) {
1853 bool IsOverlappingEmptyField =
1855
1856 CharUnits FieldOffset =
1857 (IsUnion || IsOverlappingEmptyField) ? CharUnits::Zero() : getDataSize();
1858
1859 const bool DefaultsToAIXPowerAlignment =
1861 bool FoundFirstNonOverlappingEmptyFieldForAIX = false;
1862 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1864 "The first non-overlapping empty field should have been handled.");
1865
1866 if (!IsOverlappingEmptyField) {
1867 FoundFirstNonOverlappingEmptyFieldForAIX = true;
1868
1869
1870
1871
1872
1873
1874 HandledFirstNonOverlappingEmptyField = !IsUnion;
1875 }
1876 }
1877
1879 LayoutBitField(D);
1880 return;
1881 }
1882
1883 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1884
1885 UnfilledBitsInLastUnit = 0;
1886 LastBitfieldStorageUnitSize = 0;
1887
1889
1891 CharUnits FieldSize;
1892 CharUnits FieldAlign;
1893
1894
1895
1896 CharUnits EffectiveFieldSize;
1897
1898 auto setDeclInfo = [&](bool IsIncompleteArrayType) {
1900 FieldAlign = TI.Align;
1901
1902
1903 EffectiveFieldSize = FieldSize =
1905 AlignRequirement = TI.AlignRequirement;
1906 };
1907
1909 setDeclInfo(true );
1910 } else {
1911 setDeclInfo(false );
1912
1913
1914
1916 const ASTRecordLayout &Layout = Context.getASTRecordLayout(FieldClass);
1917 EffectiveFieldSize =
1919 }
1920
1921 if (IsMsStruct) {
1922
1923
1924
1925
1926
1928 if (const BuiltinType *BTy = T->getAs()) {
1930
1931 if (!llvm::isPowerOf2_64(TypeSize.getQuantity())) {
1932 assert(
1934 "Non PowerOf2 size in MSVC mode");
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1955 }
1956 if (TypeSize > FieldAlign &&
1957 llvm::isPowerOf2_64(TypeSize.getQuantity()))
1958 FieldAlign = TypeSize;
1959 }
1960 }
1961 }
1962
1963 bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() ||
1964 FieldClass->hasAttr() ||
1965 Context.getLangOpts().getClangABICompat() <=
1966 LangOptions::ClangABI::Ver15 ||
1968 Target.isOSAIX())) ||
1969 D->hasAttr();
1970
1971
1972
1973
1974
1975 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
1976
1977
1978
1979 return AlignRequirement == AlignRequirementKind::RequiredByTypedef ||
1980 (AlignRequirement == AlignRequirementKind::RequiredByRecord &&
1981 FieldPacked);
1982 };
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993 CharUnits PreferredAlign = FieldAlign;
1994 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
1995 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
1996 auto performBuiltinTypeAlignmentUpgrade = [&](const BuiltinType *BTy) {
1997 if (BTy->getKind() == BuiltinType::Double ||
1998 BTy->getKind() == BuiltinType::LongDouble) {
2000 "No need to upgrade the alignment value.");
2002 }
2003 };
2004
2006 if (const ComplexType *CTy = BaseTy->getAs()) {
2007 performBuiltinTypeAlignmentUpgrade(
2008 CTy->getElementType()->castAs());
2009 } else if (const BuiltinType *BTy = BaseTy->getAs()) {
2010 performBuiltinTypeAlignmentUpgrade(BTy);
2011 } else if (const RecordType *RT = BaseTy->getAsCanonical()) {
2012 const RecordDecl *RD = RT->getDecl();
2013 const ASTRecordLayout &FieldRecord = Context.getASTRecordLayout(RD);
2015 }
2016 }
2017
2018
2019
2020 CharUnits UnpackedFieldAlign = FieldAlign;
2022 CharUnits UnpackedFieldOffset = FieldOffset;
2023 CharUnits OriginalFieldAlign = UnpackedFieldAlign;
2024
2025 CharUnits MaxAlignmentInChars =
2027 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2028 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
2029 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
2030
2031
2032 if (!MaxFieldAlignment.isZero()) {
2033 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2034 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
2035 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
2036 }
2037
2038
2039 if (!FieldPacked)
2040 FieldAlign = UnpackedFieldAlign;
2041 if (DefaultsToAIXPowerAlignment)
2042 UnpackedFieldAlign = PreferredAlign;
2043 if (FieldPacked) {
2044 PreferredAlign = PackedFieldAlign;
2045 FieldAlign = PackedFieldAlign;
2046 }
2047
2048 CharUnits AlignTo =
2049 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
2050
2051 FieldOffset = FieldOffset.alignTo(AlignTo);
2052 UnpackedFieldOffset = UnpackedFieldOffset.alignTo(UnpackedFieldAlign);
2053
2054 if (UseExternalLayout) {
2056 updateExternalFieldOffset(D, Context.toBits(FieldOffset)));
2057
2058 if (!IsUnion && EmptySubobjects) {
2059
2060 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
2061 (void)Allowed;
2062 assert(Allowed && "Externally-placed field cannot be placed here");
2063 }
2064 } else {
2065 if (!IsUnion && EmptySubobjects) {
2066
2067 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
2068
2069
2072 FieldOffset = getDataSize().alignTo(AlignTo);
2073 else
2074 FieldOffset += AlignTo;
2075 }
2076 }
2077 }
2078
2079
2080 FieldOffsets.push_back(Context.toBits(FieldOffset));
2081
2082 if (!UseExternalLayout)
2084 Context.toBits(UnpackedFieldOffset),
2085 Context.toBits(UnpackedFieldAlign), FieldPacked, D);
2086
2087 if (InsertExtraPadding) {
2089 CharUnits ExtraSizeForAsan = ASanAlignment;
2091 ExtraSizeForAsan += ASanAlignment - (FieldSize % ASanAlignment);
2092 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2093 }
2094
2095
2096 if (!IsOverlappingEmptyField) {
2097 uint64_t EffectiveFieldSizeInBits = Context.toBits(EffectiveFieldSize);
2098 if (IsUnion)
2099 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2100 else
2101 setDataSize(FieldOffset + EffectiveFieldSize);
2102
2103 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2104 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2105 } else {
2106 setSize(std::max(getSizeInBits(),
2107 (uint64_t)Context.toBits(FieldOffset + FieldSize)));
2108 }
2109
2110
2111 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2112 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2113
2114
2115
2116 if (const RecordDecl *RD = D->getParent()) {
2117
2118 if (RD->hasAttr() || !MaxFieldAlignment.isZero())
2119 if (FieldAlign < OriginalFieldAlign)
2121
2122
2123
2124 if (!FieldOffset.isMultipleOf(OriginalFieldAlign))
2128 }
2129 }
2130
2131 if (Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2133}
2134
2135void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
2136
2137 if (Context.getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2138 if (const CXXRecordDecl *RD = dyn_cast(D)) {
2139
2140
2141
2142 if (RD->isEmpty())
2144 }
2145 else
2147 }
2148
2149
2150
2151 setSize(std::max(getSizeInBits(), (uint64_t)Context.toBits(PaddedFieldSize)));
2152
2153
2154
2155 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2156 uint64_t UnpackedSizeInBits =
2157 llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment));
2158
2159 uint64_t RoundedSize = llvm::alignTo(
2160 getSizeInBits(),
2162 ? Alignment
2163 : PreferredAlignment));
2164
2165 if (UseExternalLayout) {
2166
2167
2168
2169 if (InferAlignment && External.Size < RoundedSize) {
2172 InferAlignment = false;
2173 }
2175 return;
2176 }
2177
2178
2179 setSize(RoundedSize);
2180
2182 if (const RecordDecl *RD = dyn_cast(D)) {
2183
2184 if (getSizeInBits() > UnpaddedSize) {
2185 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2186 bool InBits = true;
2187 if (PadSize % CharBitNum == 0) {
2188 PadSize = PadSize / CharBitNum;
2189 InBits = false;
2190 }
2193 << (InBits ? 1 : 0);
2194 }
2195
2196 const auto *CXXRD = dyn_cast(RD);
2197
2198
2199
2200
2201
2202
2203
2204 if (Packed && UnpackedAlignment <= Alignment &&
2205 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
2206 (!CXXRD || CXXRD->isPOD() ||
2207 Context.getLangOpts().getClangABICompat() <=
2208 LangOptions::ClangABI::Ver15))
2211 }
2212}
2213
2214void ItaniumRecordLayoutBuilder::UpdateAlignment(
2215 CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
2216 CharUnits PreferredNewAlignment) {
2217
2218
2219 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2220 return;
2221
2222 if (NewAlignment > Alignment) {
2223 assert(llvm::isPowerOf2_64(NewAlignment.getQuantity()) &&
2224 "Alignment not a power of 2");
2225 Alignment = NewAlignment;
2226 }
2227
2228 if (UnpackedNewAlignment > UnpackedAlignment) {
2229 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.getQuantity()) &&
2230 "Alignment not a power of 2");
2231 UnpackedAlignment = UnpackedNewAlignment;
2232 }
2233
2234 if (PreferredNewAlignment > PreferredAlignment) {
2235 assert(llvm::isPowerOf2_64(PreferredNewAlignment.getQuantity()) &&
2236 "Alignment not a power of 2");
2237 PreferredAlignment = PreferredNewAlignment;
2238 }
2239}
2240
2242ItaniumRecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
2243 uint64_t ComputedOffset) {
2244 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
2245
2246 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2247
2248
2251 InferAlignment = false;
2252 }
2253
2254
2255 return ExternalFieldOffset;
2256}
2257
2258
2259
2260
2261
2262
2264 switch (Tag) {
2266 return 0;
2268 return 1;
2270 return 2;
2271 default: llvm_unreachable("Invalid tag kind for field padding diagnostic!");
2272 }
2273}
2274
2276 uint64_t Offset, uint64_t UnpaddedOffset,
2278
2279
2281 return;
2282
2283
2284
2286 return;
2287
2288 unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
2289
2290
2291 if (!IsUnion && Offset > UnpaddedOffset) {
2292 unsigned PadSize = Offset - UnpaddedOffset;
2293 bool InBits = true;
2294 if (PadSize % CharBitNum == 0) {
2295 PadSize = PadSize / CharBitNum;
2296 InBits = false;
2297 }
2300 : diag::warn_padded_struct_field;
2301 Context.getDiagnostics().Report(D->getLocation(),
2304 << Context.getCanonicalTagType(D->getParent()) << PadSize
2305 << (InBits ? 1 : 0)
2307 } else {
2309 : diag::warn_padded_struct_anon_field;
2310 Context.getDiagnostics().Report(D->getLocation(),
2313 << Context.getCanonicalTagType(D->getParent()) << PadSize
2314 << (InBits ? 1 : 0);
2315 }
2316 }
2317}
2318
2319void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2320 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2321 unsigned UnpackedAlign, bool isPacked, const FieldDecl *D) {
2323 if (isPacked && Offset != UnpackedOffset) {
2324 HasPackedField = true;
2325 }
2326}
2327
2330
2332 return nullptr;
2333
2334
2335
2336
2338 return nullptr;
2339
2340
2341
2346 return nullptr;
2347
2348 bool allowInlineFunctions =
2349 Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline();
2350
2352 if (!MD->isVirtual())
2353 continue;
2354
2355 if (MD->isPureVirtual())
2356 continue;
2357
2358
2359
2360 if (MD->isImplicit())
2361 continue;
2362
2363 if (MD->isInlineSpecified() || MD->isConstexpr())
2364 continue;
2365
2366 if (MD->hasInlineBody())
2367 continue;
2368
2369
2370 if (!MD->isUserProvided())
2371 continue;
2372
2373
2374 if (!allowInlineFunctions) {
2377 continue;
2378 }
2379
2380 if (Context.getLangOpts().CUDA) {
2381
2382
2383
2384 if (Context.getLangOpts().CUDAIsDevice) {
2385
2386 if (!MD->hasAttr())
2387 continue;
2388 } else {
2389
2390 if (!MD->hasAttr() && MD->hasAttr())
2391 continue;
2392 }
2393 }
2394
2395
2396
2397
2398 if (MD->hasAttr() && !RD->hasAttr() &&
2399 !Context.getTargetInfo().hasPS4DLLImportExport())
2400 return nullptr;
2401
2402
2403 return MD;
2404 }
2405
2406 return nullptr;
2407}
2408
2409DiagnosticBuilder ItaniumRecordLayoutBuilder::Diag(SourceLocation Loc,
2410 unsigned DiagID) {
2412}
2413
2414
2415
2416
2420 return false;
2421
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441 return RD->isPOD();
2442
2444
2445
2446
2447
2448
2449
2451 }
2452
2453 llvm_unreachable("bad tail-padding use kind");
2454}
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546namespace {
2547struct MicrosoftRecordLayoutBuilder {
2548 struct ElementInfo {
2549 CharUnits Size;
2550 CharUnits Alignment;
2551 };
2552 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2553 MicrosoftRecordLayoutBuilder(const ASTContext &Context,
2554 EmptySubobjectMap *EmptySubobjects)
2555 : Context(Context), EmptySubobjects(EmptySubobjects),
2556 RemainingBitsInField(0) {}
2557
2558private:
2559 MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) = delete;
2560 void operator=(const MicrosoftRecordLayoutBuilder &) = delete;
2561public:
2562 void layout(const RecordDecl *RD);
2563 void cxxLayout(const CXXRecordDecl *RD);
2564
2565 void initializeLayout(const RecordDecl *RD);
2566
2567
2568
2569 void initializeCXXLayout(const CXXRecordDecl *RD);
2570 void layoutNonVirtualBases(const CXXRecordDecl *RD);
2571 void layoutNonVirtualBase(const CXXRecordDecl *RD,
2572 const CXXRecordDecl *BaseDecl,
2573 const ASTRecordLayout &BaseLayout,
2574 const ASTRecordLayout *&PreviousBaseLayout);
2575 void injectVFPtr(const CXXRecordDecl *RD);
2576 void injectVBPtr(const CXXRecordDecl *RD);
2577
2578
2579 void layoutFields(const RecordDecl *RD);
2580 void layoutField(const FieldDecl *FD);
2581 void layoutBitField(const FieldDecl *FD);
2582
2583
2584 void layoutZeroWidthBitField(const FieldDecl *FD);
2585 void layoutVirtualBases(const CXXRecordDecl *RD);
2586 void finalizeLayout(const RecordDecl *RD);
2587
2588
2589 ElementInfo getAdjustedElementInfo(const ASTRecordLayout &Layout);
2590
2591
2592
2593 ElementInfo getAdjustedElementInfo(const FieldDecl *FD);
2594
2595 void placeFieldAtOffset(CharUnits FieldOffset) {
2596 FieldOffsets.push_back(Context.toBits(FieldOffset));
2597 }
2598
2599 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2600 FieldOffsets.push_back(FieldOffset);
2601 }
2602
2603 void computeVtorDispSet(
2604 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2605 const CXXRecordDecl *RD) const;
2606 const ASTContext &Context;
2607 EmptySubobjectMap *EmptySubobjects;
2608
2609
2610 CharUnits Size;
2611
2612 CharUnits NonVirtualSize;
2613
2614 CharUnits DataSize;
2615
2616 CharUnits Alignment;
2617
2618 CharUnits MaxFieldAlignment;
2619
2620
2621 CharUnits RequiredAlignment;
2622
2623
2624
2625 CharUnits CurrentBitfieldSize;
2626
2627 CharUnits VBPtrOffset;
2628
2629 CharUnits MinEmptyStructSize;
2630
2631 ElementInfo PointerInfo;
2632
2633 const CXXRecordDecl *PrimaryBase;
2634
2635 const CXXRecordDecl *SharedVBPtrBase;
2636
2637 SmallVector<uint64_t, 16> FieldOffsets;
2638
2639 BaseOffsetsMapTy Bases;
2640
2642
2643 unsigned RemainingBitsInField;
2644 bool IsUnion : 1;
2645
2646
2647 bool LastFieldIsNonZeroWidthBitfield : 1;
2648
2649 bool HasOwnVFPtr : 1;
2650
2651 bool HasVBPtr : 1;
2652
2653
2654
2655 bool EndsWithZeroSizedObject : 1;
2656
2657
2658 bool LeadsWithZeroSizedBase : 1;
2659
2660
2661 bool UseExternalLayout : 1;
2662
2663
2664
2666};
2667}
2668
2669MicrosoftRecordLayoutBuilder::ElementInfo
2670MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2671 const ASTRecordLayout &Layout) {
2672 ElementInfo Info;
2674
2675 if (!MaxFieldAlignment.isZero())
2676 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2677
2679
2680
2681
2682 Alignment = std::max(Alignment, Info.Alignment);
2683 RequiredAlignment = std::max(RequiredAlignment, Layout.getRequiredAlignment());
2686 return Info;
2687}
2688
2689MicrosoftRecordLayoutBuilder::ElementInfo
2690MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2691 const FieldDecl *FD) {
2692
2693
2694 auto TInfo =
2696 ElementInfo Info{TInfo.Width, TInfo.Align};
2697
2698 CharUnits FieldRequiredAlignment =
2700
2702 FieldRequiredAlignment = std::max(
2704
2706
2707
2708 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2709 else {
2710 if (const auto *RT = FD->getType()
2715 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2717 }
2718
2719 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2720 }
2721
2722 if (!MaxFieldAlignment.isZero())
2723 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2724 if (FD->hasAttr())
2726 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2727 return Info;
2728}
2729
2730void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
2731
2733 initializeLayout(RD);
2734 layoutFields(RD);
2735 DataSize = Size = Size.alignTo(Alignment);
2736 RequiredAlignment = std::max(
2738 finalizeLayout(RD);
2739}
2740
2741void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
2742
2744 initializeLayout(RD);
2745 initializeCXXLayout(RD);
2746 layoutNonVirtualBases(RD);
2747 layoutFields(RD);
2748 injectVBPtr(RD);
2749 injectVFPtr(RD);
2750 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2751 Alignment = std::max(Alignment, PointerInfo.Alignment);
2752 auto RoundingAlignment = Alignment;
2753 if (!MaxFieldAlignment.isZero())
2754 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2755 if (!UseExternalLayout)
2756 Size = Size.alignTo(RoundingAlignment);
2757 NonVirtualSize = Size;
2758 RequiredAlignment = std::max(
2760 layoutVirtualBases(RD);
2761 finalizeLayout(RD);
2762}
2763
2764void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
2765 IsUnion = RD->isUnion();
2768
2769
2770
2773 : CharUnits::Zero();
2774
2776
2777 if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct)
2779
2780
2781 if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr()){
2782 unsigned PackedAlignment = MFAA->getAlignment();
2783 if (PackedAlignment <=
2786 }
2787
2788 if (RD->hasAttr())
2790
2791
2792 UseExternalLayout = false;
2794 UseExternalLayout = Source->layoutRecordType(
2797
2800 if (Location.isValid())
2802 diag::err_itanium_layout_unimplemented);
2803 }
2804}
2805
2806void
2807MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) {
2808 EndsWithZeroSizedObject = false;
2809 LeadsWithZeroSizedBase = false;
2810 HasOwnVFPtr = false;
2811 HasVBPtr = false;
2812 PrimaryBase = nullptr;
2813 SharedVBPtrBase = nullptr;
2814
2815
2820
2821 if (!MaxFieldAlignment.isZero())
2822 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2823}
2824
2825void
2826MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) {
2827
2828
2829
2830
2831
2832
2833 const ASTRecordLayout *PreviousBaseLayout = nullptr;
2834 bool HasPolymorphicBaseClass = false;
2835
2836 for (const CXXBaseSpecifier &Base : RD->bases()) {
2837 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2838 HasPolymorphicBaseClass |= BaseDecl->isPolymorphic();
2839 const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
2840
2841 if (Base.isVirtual()) {
2842 HasVBPtr = true;
2843 continue;
2844 }
2845
2846 if (!SharedVBPtrBase && BaseLayout.hasVBPtr()) {
2847 SharedVBPtrBase = BaseDecl;
2848 HasVBPtr = true;
2849 }
2850
2852 continue;
2853
2854 if (!PrimaryBase) {
2855 PrimaryBase = BaseDecl;
2857 }
2858
2859 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2860 }
2861
2863 if (!HasPolymorphicBaseClass)
2864
2865
2866 HasOwnVFPtr = true;
2867 else if (!PrimaryBase) {
2868
2869
2870 for (CXXMethodDecl *M : RD->methods()) {
2871 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2872 M->size_overridden_methods() == 0) {
2873 HasOwnVFPtr = true;
2874 break;
2875 }
2876 }
2877 }
2878 }
2879
2880
2881 bool CheckLeadingLayout = !PrimaryBase;
2882
2883 for (const CXXBaseSpecifier &Base : RD->bases()) {
2884 if (Base.isVirtual())
2885 continue;
2886 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2887 const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
2888
2891 continue;
2892 }
2893
2894
2895 if (CheckLeadingLayout) {
2896 CheckLeadingLayout = false;
2898 }
2899
2900 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2902 }
2903
2904 if (!HasVBPtr)
2906 else if (SharedVBPtrBase) {
2907 const ASTRecordLayout &Layout = Context.getASTRecordLayout(SharedVBPtrBase);
2908 VBPtrOffset = Bases[SharedVBPtrBase] + Layout.getVBPtrOffset();
2909 }
2910}
2911
2914 return false;
2915 if (RD->hasAttr())
2916 return true;
2917 if (auto *LVA = RD->getAttr())
2918
2920 return false;
2921
2922
2923
2924 return false;
2925}
2926
2927void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2928 const CXXRecordDecl *RD, const CXXRecordDecl *BaseDecl,
2929 const ASTRecordLayout &BaseLayout,
2930 const ASTRecordLayout *&PreviousBaseLayout) {
2931
2932
2933
2938 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2939 CharUnits BaseOffset;
2940
2941
2942 bool FoundBase = false;
2943 if (UseExternalLayout) {
2944 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2945 if (BaseOffset > Size) {
2946 Size = BaseOffset;
2947 }
2948 }
2949
2950 if (!FoundBase) {
2951 if (MDCUsesEBO && BaseDecl->isEmpty() &&
2954 } else {
2955
2956 BaseOffset = Size = Size.alignTo(Info.Alignment);
2957 }
2958 }
2959 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2961 DataSize = Size;
2962 PreviousBaseLayout = &BaseLayout;
2963}
2964
2965void MicrosoftRecordLayoutBuilder::layoutFields(const RecordDecl *RD) {
2966 LastFieldIsNonZeroWidthBitfield = false;
2967 for (const FieldDecl *Field : RD->fields())
2968 layoutField(Field);
2969}
2970
2971void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {
2973 layoutBitField(FD);
2974 return;
2975 }
2976 LastFieldIsNonZeroWidthBitfield = false;
2977 ElementInfo Info = getAdjustedElementInfo(FD);
2978 Alignment = std::max(Alignment, Info.Alignment);
2979
2982 FieldClass->isEmpty() &&
2983 FieldClass->fields().empty();
2985
2986 if (UseExternalLayout) {
2987 FieldOffset =
2989 } else if (IsUnion) {
2991 } else if (EmptySubobjects) {
2992 if (!IsOverlappingEmptyField)
2993 FieldOffset = DataSize.alignTo(Info.Alignment);
2994
2995 while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {
2997 bool HasBases = ParentClass && (!ParentClass->bases().empty() ||
2998 !ParentClass->vbases().empty());
3000 HasBases) {
3001
3002
3003 FieldOffset = DataSize.alignTo(Info.Alignment);
3004 } else {
3005 FieldOffset += Info.Alignment;
3006 }
3007 }
3008 } else {
3009 FieldOffset = Size.alignTo(Info.Alignment);
3010 }
3011
3012 uint64_t UnpaddedFielddOffsetInBits =
3013 Context.toBits(DataSize) - RemainingBitsInField;
3014
3016 UnpaddedFielddOffsetInBits, FD);
3017
3018 RemainingBitsInField = 0;
3019
3020 placeFieldAtOffset(FieldOffset);
3021
3022 if (!IsOverlappingEmptyField)
3023 DataSize = std::max(DataSize, FieldOffset + Info.Size);
3024
3025 Size = std::max(Size, FieldOffset + Info.Size);
3026}
3027
3028void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
3030 if (Width == 0) {
3031 layoutZeroWidthBitField(FD);
3032 return;
3033 }
3034 ElementInfo Info = getAdjustedElementInfo(FD);
3035
3036
3037 if (Width > Context.toBits(Info.Size))
3038 Width = Context.toBits(Info.Size);
3039
3040
3041
3042 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
3043 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
3044 placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField);
3045 RemainingBitsInField -= Width;
3046 return;
3047 }
3048 LastFieldIsNonZeroWidthBitfield = true;
3049 CurrentBitfieldSize = Info.Size;
3050 if (UseExternalLayout) {
3051 auto FieldBitOffset = External.getExternalFieldOffset(FD);
3052 placeFieldAtBitOffset(FieldBitOffset);
3054 llvm::alignDown(FieldBitOffset, Context.toBits(Info.Alignment)) +
3055 Context.toBits(Info.Size));
3056 Size = std::max(Size, NewSize);
3057 Alignment = std::max(Alignment, Info.Alignment);
3058 } else if (IsUnion) {
3060 Size = std::max(Size, Info.Size);
3061
3062 } else {
3063
3064 CharUnits FieldOffset = Size.alignTo(Info.Alignment);
3065 uint64_t UnpaddedFieldOffsetInBits =
3066 Context.toBits(DataSize) - RemainingBitsInField;
3067 placeFieldAtOffset(FieldOffset);
3068 Size = FieldOffset + Info.Size;
3069 Alignment = std::max(Alignment, Info.Alignment);
3070 RemainingBitsInField = Context.toBits(Info.Size) - Width;
3072 UnpaddedFieldOffsetInBits, FD);
3073 }
3074 DataSize = Size;
3075}
3076
3077void
3078MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) {
3079
3080
3081 if (!LastFieldIsNonZeroWidthBitfield) {
3083
3084
3085 return;
3086 }
3087 LastFieldIsNonZeroWidthBitfield = false;
3088 ElementInfo Info = getAdjustedElementInfo(FD);
3089 if (IsUnion) {
3091 Size = std::max(Size, Info.Size);
3092
3093 } else {
3094
3095 CharUnits FieldOffset = Size.alignTo(Info.Alignment);
3096 uint64_t UnpaddedFieldOffsetInBits =
3097 Context.toBits(DataSize) - RemainingBitsInField;
3098 placeFieldAtOffset(FieldOffset);
3099 RemainingBitsInField = 0;
3100 Size = FieldOffset;
3101 Alignment = std::max(Alignment, Info.Alignment);
3103 UnpaddedFieldOffsetInBits, FD);
3104 }
3105 DataSize = Size;
3106}
3107
3108void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) {
3109 if (!HasVBPtr || SharedVBPtrBase)
3110 return;
3111
3112 CharUnits InjectionSite = VBPtrOffset;
3113
3114 VBPtrOffset = VBPtrOffset.alignTo(PointerInfo.Alignment);
3115
3116 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3117
3118
3119 if (UseExternalLayout) {
3120
3121
3122 if (Size < FieldStart)
3123 Size = FieldStart;
3124 return;
3125 }
3126
3127
3128 CharUnits Offset = (FieldStart - InjectionSite)
3129 .alignTo(std::max(RequiredAlignment, Alignment));
3130 Size += Offset;
3131 for (uint64_t &FieldOffset : FieldOffsets)
3132 FieldOffset += Context.toBits(Offset);
3133 for (BaseOffsetsMapTy::value_type &Base : Bases)
3134 if (Base.second >= InjectionSite)
3135 Base.second += Offset;
3136}
3137
3138void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) {
3139 if (!HasOwnVFPtr)
3140 return;
3141
3142
3143 CharUnits Offset =
3144 PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment));
3145
3146
3147 if (HasVBPtr)
3148 VBPtrOffset += Offset;
3149
3150 if (UseExternalLayout) {
3151
3152
3153 if (Size.isZero())
3154 Size += Offset;
3155 return;
3156 }
3157
3158 Size += Offset;
3159
3160
3161
3162 for (uint64_t &FieldOffset : FieldOffsets)
3163 FieldOffset += Context.toBits(Offset);
3164 for (BaseOffsetsMapTy::value_type &Base : Bases)
3165 Base.second += Offset;
3166}
3167
3168void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
3169 if (!HasVBPtr)
3170 return;
3171
3173 CharUnits VtorDispAlignment = VtorDispSize;
3174
3175 if (!MaxFieldAlignment.isZero())
3176 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3177
3178
3179
3180 for (const CXXBaseSpecifier &VBase : RD->vbases()) {
3181 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3182 const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
3183 RequiredAlignment =
3185 }
3186 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3187
3188 llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
3189 computeVtorDispSet(HasVtorDispSet, RD);
3190
3191 const ASTRecordLayout *PreviousBaseLayout = nullptr;
3192 for (const CXXBaseSpecifier &VBase : RD->vbases()) {
3193 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3194 const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
3195 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3196
3197
3198
3199
3200
3203 HasVtordisp) {
3204 Size = Size.alignTo(VtorDispAlignment) + VtorDispSize;
3205 Alignment = std::max(VtorDispAlignment, Alignment);
3206 }
3207
3208 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3209 CharUnits BaseOffset;
3210
3211
3212 if (UseExternalLayout) {
3213 if (.getExternalVBaseOffset(BaseDecl, BaseOffset))
3214 BaseOffset = Size;
3215 } else
3216 BaseOffset = Size.alignTo(Info.Alignment);
3217
3218 assert(BaseOffset >= Size && "base offset already allocated");
3219
3220 VBases.insert(std::make_pair(BaseDecl,
3221 ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
3223 PreviousBaseLayout = &BaseLayout;
3224 }
3225}
3226
3227void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
3228 uint64_t UnpaddedSizeInBits = Context.toBits(DataSize);
3229 UnpaddedSizeInBits -= RemainingBitsInField;
3230
3231
3232
3233 if (Size.isZero())
3234 UnpaddedSizeInBits += 8;
3235
3236
3237
3238 DataSize = Size;
3239 if (!RequiredAlignment.isZero()) {
3240 Alignment = std::max(Alignment, RequiredAlignment);
3241 auto RoundingAlignment = Alignment;
3242 if (!MaxFieldAlignment.isZero())
3243 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3244 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3245 Size = Size.alignTo(RoundingAlignment);
3246 }
3247 if (Size.isZero()) {
3249 EndsWithZeroSizedObject = true;
3250 LeadsWithZeroSizedBase = true;
3251 }
3252
3253
3254 if (RequiredAlignment >= MinEmptyStructSize)
3255 Size = Alignment;
3256 else
3257 Size = MinEmptyStructSize;
3258 }
3259
3260 if (UseExternalLayout) {
3264 return;
3265 }
3268
3269 if (SizeInBits > UnpaddedSizeInBits) {
3270 unsigned int PadSize = SizeInBits - UnpaddedSizeInBits;
3271 bool InBits = true;
3272 if (PadSize % CharBitNum == 0) {
3273 PadSize = PadSize / CharBitNum;
3274 InBits = false;
3275 }
3276
3278 diag::warn_padded_struct_size)
3280 << (InBits ? 1 : 0);
3281 }
3282}
3283
3284
3285
3286static bool
3288 BasesWithOverriddenMethods,
3290 if (BasesWithOverriddenMethods.count(RD))
3291 return true;
3292
3293
3295 if (.isVirtual() &&
3297 Base.getType()->getAsCXXRecordDecl()))
3298 return true;
3299 return false;
3300}
3301
3302void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3303 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3304 const CXXRecordDecl *RD) const {
3305
3306
3308 for (const CXXBaseSpecifier &Base : RD->vbases()) {
3309 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
3310 const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
3312 HasVtordispSet.insert(BaseDecl);
3313 }
3314 return;
3315 }
3316
3317
3318
3319 for (const CXXBaseSpecifier &Base : RD->bases()) {
3320 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
3321 const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
3323 if (bi.second.hasVtorDisp())
3324 HasVtordispSet.insert(bi.first);
3325 }
3326
3327
3328
3331 return;
3332
3333
3334
3335 assert(RD->getMSVtorDispMode() == MSVtorDispMode::ForVBaseOverride);
3336
3337
3338
3339
3340 llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
3341 llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
3342
3343 for (const CXXMethodDecl *MD : RD->methods())
3344 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3346 Work.insert(MD);
3347 while (!Work.empty()) {
3348 const CXXMethodDecl *MD = *Work.begin();
3350
3351 if (MethodRange.begin() == MethodRange.end())
3352 BasesWithOverriddenMethods.insert(MD->getParent());
3353 else
3354 Work.insert_range(MethodRange);
3355
3356 Work.erase(MD);
3357 }
3358
3359
3360 for (const CXXBaseSpecifier &Base : RD->vbases()) {
3361 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
3362 if (!HasVtordispSet.count(BaseDecl) &&
3364 HasVtordispSet.insert(BaseDecl);
3365 }
3366}
3367
3372
3373
3374
3375
3380
3382
3383
3384
3385
3386
3388 assert(D && "Cannot get layout of forward declarations!");
3389 assert(!D->isInvalidDecl() && "Cannot get layout of invalid decl!");
3391
3392
3393
3394
3396 if (Entry) return *Entry;
3397
3399
3400 if (getTargetInfo().hasMicrosoftRecordLayout()) {
3401 if (const auto *RD = dyn_cast(D)) {
3402 EmptySubobjectMap EmptySubobjects(*this, RD);
3403 MicrosoftRecordLayoutBuilder Builder(*this, &EmptySubobjects);
3404 Builder.cxxLayout(RD);
3406 *this, Builder.Size, Builder.Alignment, Builder.Alignment,
3407 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3408 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3409 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3410 Builder.Alignment, Builder.Alignment, CharUnits::Zero(),
3411 Builder.PrimaryBase, false, Builder.SharedVBPtrBase,
3412 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3413 Builder.Bases, Builder.VBases);
3414 } else {
3415 MicrosoftRecordLayoutBuilder Builder(*this, nullptr);
3416 Builder.layout(D);
3418 *this, Builder.Size, Builder.Alignment, Builder.Alignment,
3419 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3420 Builder.FieldOffsets);
3421 }
3422 } else {
3423 if (const auto *RD = dyn_cast(D)) {
3424 EmptySubobjectMap EmptySubobjects(*this, RD);
3425 ItaniumRecordLayoutBuilder Builder(*this, &EmptySubobjects);
3426 Builder.Layout(RD);
3427
3428
3429
3430
3431 bool skipTailPadding =
3433
3434
3436 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3438 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3440 *this, Builder.getSize(), Builder.Alignment,
3441 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3442
3443 Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(),
3445 NonVirtualSize, Builder.NonVirtualAlignment,
3446 Builder.PreferredNVAlignment,
3447 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3448 Builder.PrimaryBaseIsVirtual, nullptr, false, false, Builder.Bases,
3449 Builder.VBases);
3450 } else {
3451 ItaniumRecordLayoutBuilder Builder(*this, nullptr);
3452 Builder.Layout(D);
3453
3455 *this, Builder.getSize(), Builder.Alignment,
3456 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3457
3458 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3459 }
3460 }
3461
3462 ASTRecordLayouts[D] = NewEntry;
3463
3464 constexpr uint64_t MaxStructSizeInBytes = 1ULL << 60;
3466 if (static_cast<uint64_t>(StructSize.getQuantity()) >= MaxStructSizeInBytes) {
3468 << D->getName() << MaxStructSizeInBytes;
3469 }
3470
3472 llvm::outs() << "\n*** Dumping AST Record Layout\n";
3474 }
3475
3476 return *NewEntry;
3477}
3478
3480 if (().getCXXABI().hasKeyFunctions())
3481 return nullptr;
3482
3483 assert(RD->getDefinition() && "Cannot get key function for forward decl!");
3485
3486
3487
3488
3489
3490
3494
3495
3497 KeyFunctions[RD] = const_cast<Decl*>(Result);
3498
3499 return cast_or_null(Result);
3500}
3501
3504 "not working with method declaration from class definition");
3505
3506
3507
3508
3509 const auto &Map = KeyFunctions;
3510 auto I = Map.find(Method->getParent());
3511
3512
3513 if (I == Map.end()) return;
3514
3515
3516
3517
3520
3521 KeyFunctions.erase(Method->getParent());
3522 }
3523}
3524
3529
3531 uint64_t OffsetInBits;
3532 if (const FieldDecl *FD = dyn_cast(VD)) {
3534 } else {
3536
3537 OffsetInBits = 0;
3540 }
3541
3542 return OffsetInBits;
3543}
3544
3550
3551
3552
3553
3554
3555
3556 unsigned Index = 0;
3557
3560 if (Ivar == IVD)
3561 break;
3562 ++Index;
3563 }
3564 assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!");
3565
3567}
3568
3569
3570
3571
3572
3573
3576
3578 getExternalSource()->CompleteType(const_cast<ObjCInterfaceDecl*>(D));
3581 "Invalid interface decl!");
3582
3583
3585 return *Entry;
3586
3587 ItaniumRecordLayoutBuilder Builder(*this, nullptr);
3588 Builder.Layout(D);
3589
3591 *this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3592 Builder.UnadjustedAlignment,
3593
3594 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3595
3596 ObjCLayouts[D] = NewEntry;
3597
3598 return *NewEntry;
3599}
3600
3603 OS << llvm::format("%10" PRId64 " | ", (int64_t)Offset.getQuantity());
3605}
3606
3608 unsigned Begin, unsigned Width,
3611 {
3612 llvm::raw_svector_ostream BufferOS(Buffer);
3613 BufferOS << Offset.getQuantity() << ':';
3614 if (Width == 0) {
3615 BufferOS << '-';
3616 } else {
3617 BufferOS << Begin << '-' << (Begin + Width - 1);
3618 }
3619 }
3620
3621 OS << llvm::right_justify(Buffer, 10) << " | ";
3623}
3624
3629
3634 const char* Description,
3635 bool PrintSizeInfo,
3636 bool IncludeVirtualBases) {
3638 auto CXXRD = dyn_cast(RD);
3639
3641 OS << C.getCanonicalTagType(const_cast<RecordDecl *>(RD));
3642 if (Description)
3643 OS << ' ' << Description;
3644 if (CXXRD && CXXRD->isEmpty())
3645 OS << " (empty)";
3646 OS << '\n';
3647
3649
3650
3651 if (CXXRD) {
3653 bool HasOwnVFPtr = Layout.hasOwnVFPtr();
3654 bool HasOwnVBPtr = Layout.hasOwnVBPtr();
3655
3656
3657 if (CXXRD->isDynamicClass() && !PrimaryBase &&
3658 .getTargetInfo().hasMicrosoftRecordLayout()) {
3660 OS << '(' << *RD << " vtable pointer)\n";
3661 } else if (HasOwnVFPtr) {
3663
3664 OS << '(' << *RD << " vftable pointer)\n";
3665 }
3666
3667
3670 assert(.getType()->isDependentType() &&
3671 "Cannot layout class with dependent bases.");
3672 if (.isVirtual())
3673 Bases.push_back(Base.getType()->getAsCXXRecordDecl());
3674 }
3675
3676
3677 llvm::stable_sort(
3680 });
3681
3682
3686 Base == PrimaryBase ? "(primary base)" : "(base)",
3687 false,
3688 false);
3689 }
3690
3691
3692 if (HasOwnVBPtr) {
3694 OS << '(' << *RD << " vbtable pointer)\n";
3695 }
3696 }
3697
3698
3700 uint64_t LocalFieldOffsetInBits =
3703 Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3704
3705
3706 if (const auto *RD = Field->getType()->getAsRecordDecl()) {
3708 Field->getName().data(),
3709 false,
3710 true);
3711 continue;
3712 }
3713
3714 if (Field->isBitField()) {
3715 uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset);
3716 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3717 unsigned Width = Field->getBitWidthValue();
3719 } else {
3721 }
3722 const QualType &FieldType = C.getLangOpts().DumpRecordLayoutsCanonical
3723 ? Field->getType().getCanonicalType()
3724 : Field->getType();
3725 OS << FieldType << ' ' << *Field << '\n';
3726 }
3727
3728
3729 if (CXXRD && IncludeVirtualBases) {
3732
3734 assert(Base.isVirtual() && "Found non-virtual class!");
3735 const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();
3736
3738
3739 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3741 OS << "(vtordisp for vbase " << *VBase << ")\n";
3742 }
3743
3746 "(primary virtual base)" : "(virtual base)",
3747 false,
3748 false);
3749 }
3750 }
3751
3752 if (!PrintSizeInfo) return;
3753
3756 if (CXXRD && .getTargetInfo().hasMicrosoftRecordLayout())
3759 if (C.getTargetInfo().defaultsToAIXPowerAlignment())
3761
3762 if (CXXRD) {
3763 OS << ",\n";
3767 if (C.getTargetInfo().defaultsToAIXPowerAlignment())
3768 OS << ", preferrednvalign="
3770 }
3771 OS << "]\n";
3772}
3773
3775 bool Simple) const {
3776 if (!Simple) {
3778 true,
3779 true);
3780 return;
3781 }
3782
3783
3784
3785
3786
3787
3788
3789
3792 OS << "\nLayout: ";
3793 OS << "<ASTRecordLayout\n";
3794 OS << " Size:" << toBits(Info.getSize()) << "\n";
3795 if (().hasMicrosoftRecordLayout())
3798 if (Target->defaultsToAIXPowerAlignment())
3800 << "\n";
3801 if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) {
3802 OS << " BaseOffsets: [";
3804 for (auto I : CXXRD->bases()) {
3805 if (I.isVirtual())
3806 continue;
3808 OS << ", ";
3809 Base = I.getType()->getAsCXXRecordDecl();
3810 OS << Info.CXXInfo->BaseOffsets[Base].getQuantity();
3811 }
3812 OS << "]>\n";
3813 OS << " VBaseOffsets: [";
3815 for (auto I : CXXRD->vbases()) {
3816 if (VBase)
3817 OS << ", ";
3818 VBase = I.getType()->getAsCXXRecordDecl();
3819 OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();
3820 }
3821 OS << "]>\n";
3822 }
3823 OS << " FieldOffsets: [";
3824 for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) {
3825 if (i)
3826 OS << ", ";
3828 }
3829 OS << "]>\n";
3830}
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
unsigned IndentLevel
The indent level of this token. Copied from the surrounding line.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target)
llvm::MachO::Target Target
static const CXXMethodDecl * computeKeyFunction(ASTContext &Context, const CXXRecordDecl *RD)
Definition RecordLayoutBuilder.cpp:2328
static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD)
Does the target C++ ABI require us to skip over the tail-padding of the given class (considering it a...
Definition RecordLayoutBuilder.cpp:2417
static bool isAIXLayout(const ASTContext &Context)
Definition RecordLayoutBuilder.cpp:1528
static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel)
Definition RecordLayoutBuilder.cpp:3625
static uint64_t roundUpSizeToCharAlignment(uint64_t Size, const ASTContext &Context)
Definition RecordLayoutBuilder.cpp:1452
static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel)
Definition RecordLayoutBuilder.cpp:3601
static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
Get diagnostic select index for tag kind for field padding diagnostic message.
Definition RecordLayoutBuilder.cpp:2263
static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, const ASTContext &C, CharUnits Offset, unsigned IndentLevel, const char *Description, bool PrintSizeInfo, bool IncludeVirtualBases)
Definition RecordLayoutBuilder.cpp:3630
static void CheckFieldPadding(const ASTContext &Context, bool IsUnion, uint64_t Offset, uint64_t UnpaddedOffset, const FieldDecl *D)
Definition RecordLayoutBuilder.cpp:2275
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
Definition RecordLayoutBuilder.cpp:3525
static bool RequiresVtordisp(const llvm::SmallPtrSetImpl< const CXXRecordDecl * > &BasesWithOverriddenMethods, const CXXRecordDecl *RD)
Definition RecordLayoutBuilder.cpp:3287
static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset, unsigned Begin, unsigned Width, unsigned IndentLevel)
Definition RecordLayoutBuilder.cpp:3607
static bool recordUsesEBO(const RecordDecl *RD)
Definition RecordLayoutBuilder.cpp:2912
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
Definition RecordLayoutBuilder.cpp:3530
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
Definition RecordLayoutBuilder.cpp:3377
void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple=false) const
Definition RecordLayoutBuilder.cpp:3774
bool defaultsToMsStruct() const
Return whether unannotated records are treated as if they have [[gnu::ms_struct]].
Definition RecordLayoutBuilder.cpp:3368
const CXXMethodDecl * getCurrentKeyFunction(const CXXRecordDecl *RD)
Get our current best idea for the key function of the given record decl, or nullptr if there isn't on...
Definition RecordLayoutBuilder.cpp:3479
uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID, const ObjCIvarDecl *Ivar) const
Get the offset of an ObjCIvarDecl in bits.
Definition RecordLayoutBuilder.cpp:3545
void setNonKeyFunction(const CXXMethodDecl *method)
Observe that the given method cannot be a key function.
Definition RecordLayoutBuilder.cpp:3502
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
Definition RecordLayoutBuilder.cpp:3377
const LangOptions & getLangOpts() const
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool isNearlyEmpty(const CXXRecordDecl *RD) const
friend class CXXRecordDecl
CanQualType UnsignedLongTy
TypeInfo getTypeInfo(const Type *T) const
Get the size and alignment of the specified complete type in bits.
bool isAlignmentRequired(const Type *T) const
Determine if the alignment the type has was required using an alignment attribute.
TypeInfoChars getTypeInfoInChars(const Type *T) const
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType UnsignedInt128Ty
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedCharTy
CanQualType UnsignedIntTy
CanQualType UnsignedLongLongTy
CanQualType UnsignedShortTy
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
CanQualType getCanonicalTagType(const TagDecl *TD) const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool endsWithZeroSizedObject() const
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
CharUnits getAlignment() const
getAlignment - Get the record alignment in characters.
CharUnits getPreferredAlignment() const
getPreferredFieldAlignment - Get the record preferred alignment in characters.
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
CharUnits getSize() const
getSize - Get the record size in characters.
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
bool hasVBPtr() const
hasVBPtr - Does this class have a virtual function table pointer.
bool leadsWithZeroSizedBase() const
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualAlignment() const
getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an object, which is the alignmen...
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
CharUnits getDataSize() const
getDataSize() - Get the record data size, which is the record size without tail padding,...
CharUnits getRequiredAlignment() const
CharUnits getSizeOfLargestEmptySubobject() const
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getPreferredNVAlignment() const
getPreferredNVAlignment - Get the preferred non-virtual alignment (in chars) of an object,...
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool hasExtendableVFPtr() const
hasVFPtr - Does this class have a virtual function table pointer that can be extended by a derived cl...
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Represents a base class of a C++ class.
Represents a static or instance method of a struct/union/class.
overridden_method_range overridden_methods() const
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this class.
bool hasUserDeclaredDestructor() const
Determine whether this class has a user-declared destructor.
method_range methods() const
CXXRecordDecl * getDefinition() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
base_class_range vbases()
bool isDynamicClass() const
bool isCXX11StandardLayout() const
Determine whether this class was standard-layout per C++11 [class]p7, specifically using the C++11 ru...
bool hasUserDeclaredConstructor() const
Determine whether this class has any user-declared constructors.
bool isPOD() const
Whether this class is a POD-type (C++ [class]p4)
MSVtorDispMode getMSVtorDispMode() const
Controls when vtordisps will be emitted if this record is used as a virtual base.
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
bool isTrivial() const
Determine whether this class is considered trivial.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
bool isMultipleOf(CharUnits N) const
Test whether this is a multiple of the other value.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
Decl - This represents one declaration (or definition), e.g.
unsigned getMaxAlignment() const
getMaxAlignment - return the maximum alignment specified by attributes on this decl,...
bool isInvalidDecl() const
SourceLocation getLocation() const
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine a...
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
Represents a function declaration or definition.
bool isInlineSpecified() const
Determine whether the "inline" keyword was specified for this function.
Represents a field injected from an anonymous union/struct into the parent scope.
ArrayRef< NamedDecl * > chain() const
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
Represents an ObjC class declaration.
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
ObjCInterfaceDecl * getSuperClass() const
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getNextIvar()
ObjCIvarDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
A (possibly-)qualified type.
Represents a struct/union/class.
bool isMsStruct(const ASTContext &C) const
Get whether or not this is an ms_struct which can be turned on with an attribute, pragma,...
bool hasFlexibleArrayMember() const
field_iterator field_end() const
field_range fields() const
bool mayInsertExtraPadding(bool EmitRemark=false) const
Whether we are allowed to insert extra padding between fields.
RecordDecl * getMostRecentDecl()
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
field_iterator field_begin() const
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
TagKind getTagKind() const
The basic abstraction for the target C++ ABI.
TailPaddingUseRules getTailPaddingUseRules() const
@ AlwaysUseTailPadding
The tail-padding of a base class is always theoretically available, even if it's POD.
@ UseTailPaddingUnlessPOD11
Only allocate objects in the tail padding of a base class if the base class is not POD according to t...
@ UseTailPaddingUnlessPOD03
Only allocate objects in the tail padding of a base class if the base class is not POD according to t...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool useLeadingZeroLengthBitfield() const
Check whether zero length bitfield alignment is respected if they are leading members.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
unsigned getLargestOverSizedBitfieldContainer() const
virtual bool defaultsToAIXPowerAlignment() const
Whether target defaults to the power alignment rules of AIX.
unsigned getCharAlign() const
unsigned getZeroLengthBitfieldBoundary() const
Get the fixed alignment value in bits for a member that follows a zero length bitfield.
bool useExplicitBitFieldAlignment() const
Check whether explicit bitfield alignment attributes should be.
uint64_t getPointerAlign(LangAS AddrSpace) const
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
unsigned getCharWidth() const
bool useZeroLengthBitfieldAlignment() const
Check whether zero length bitfields should force alignment of the next member.
bool useBitFieldTypeAlignment() const
Check whether the alignment of bit-field types is respected when laying out structures.
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * getAs() const
Member-template getAs'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
LazyOffsetPtr< Decl, GlobalDeclID, &ExternalASTSource::GetExternalDecl > LazyDeclPtr
A lazy pointer to a declaration.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ External
External linkage, which indicates that the entity can be referred to from other translation units.
@ Result
The result type of a method or function.
const FunctionProtoType * T
TagTypeKind
The kind of a tag type.
@ Interface
The "__interface" keyword.
@ Struct
The "struct" keyword.
@ Class
The "class" keyword.
@ Type
The name was classified as a type.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
bool isValid() const
Whether this pointer is non-NULL.
bool isOffset() const
Whether this pointer is currently stored as an offset.
T * get(ExternalASTSource *Source) const
Retrieve the pointer to the AST node that this lazy pointer points to.