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
41
42
43 bool IsVirtual;
44
45
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
80 assert(FieldOffsets.count(FD) &&
81 "Field does not have an external offset");
82 return FieldOffsets[FD];
83 }
84
86 auto Known = BaseOffsets.find(RD);
87 if (Known == BaseOffsets.end())
88 return false;
89 BaseOffset = Known->second;
90 return true;
91 }
92
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 {
107
108
110
111
112 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
113 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
114 EmptyClassOffsetsMapTy EmptyClassOffsets;
115
116
117
119
120
121
122 void ComputeEmptySubobjectSizes();
123
125
126 void UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
127 CharUnits Offset, bool PlacingEmptyBase);
128
129 void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
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
144 assert(FieldOffset % CharWidth == 0 &&
145 "Field offset not at char boundary!");
146
148 }
149
150protected:
151 bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
153
154 bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
156
157 bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
160 bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
162
163public:
164
165
166
167 CharUnits SizeOfLargestEmptySubobject;
168
171 ComputeEmptySubobjectSizes();
172 }
173
174
175
176
177
178 bool CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
180
181
182
184};
185
186void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
187
189 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
190
193 if (BaseDecl->isEmpty()) {
194
195 EmptySize = Layout.getSize();
196 } else {
197
199 }
200
201 if (EmptySize > SizeOfLargestEmptySubobject)
202 SizeOfLargestEmptySubobject = EmptySize;
203 }
204
205
209
210
211 if (!RT)
212 continue;
213
217 if (MemberDecl->isEmpty()) {
218
219 EmptySize = Layout.getSize();
220 } else {
221
223 }
224
225 if (EmptySize > SizeOfLargestEmptySubobject)
226 SizeOfLargestEmptySubobject = EmptySize;
227 }
228}
229
230bool
231EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
233
235 return true;
236
237 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
238 if (I == EmptyClassOffsets.end())
239 return true;
240
241 const ClassVectorTy &Classes = I->second;
242 if (!llvm::is_contained(Classes, RD))
243 return true;
244
245
246 return false;
247}
248
249void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,
251
253 return;
254
255
256
257 ClassVectorTy &Classes = EmptyClassOffsets[Offset];
258 if (llvm::is_contained(Classes, RD))
259 return;
260
261 Classes.push_back(RD);
262
263
264 if (Offset > MaxEmptyClassOffset)
265 MaxEmptyClassOffset = Offset;
266}
267
268bool
269EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
271
272
273 if (!AnyEmptySubobjectsBeyondOffset(Offset))
274 return true;
275
276 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
277 return false;
278
279
281 for (const BaseSubobjectInfo *Base : Info->Bases) {
282 if (Base->IsVirtual)
283 continue;
284
286
287 if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))
288 return false;
289 }
290
291 if (Info->PrimaryVirtualBaseInfo) {
292 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
293
294 if (Info == PrimaryVirtualBaseInfo->Derived) {
295 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
296 return false;
297 }
298 }
299
300
301 for (const FieldDecl *Field : Info->Class->fields()) {
302 if (Field->isBitField())
303 continue;
304
306 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
307 return false;
308 }
309
310 return true;
311}
312
313void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
315 bool PlacingEmptyBase) {
316 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
317
318
319
320
321
322 return;
323 }
324
325 AddSubobjectAtOffset(Info->Class, Offset);
326
327
329 for (const BaseSubobjectInfo *Base : Info->Bases) {
330 if (Base->IsVirtual)
331 continue;
332
334 UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);
335 }
336
337 if (Info->PrimaryVirtualBaseInfo) {
338 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
339
340 if (Info == PrimaryVirtualBaseInfo->Derived)
341 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
342 PlacingEmptyBase);
343 }
344
345
346 for (const FieldDecl *Field : Info->Class->fields()) {
347 if (Field->isBitField())
348 continue;
349
351 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingEmptyBase);
352 }
353}
354
355bool EmptySubobjectMap::CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
357
358
359 if (SizeOfLargestEmptySubobject.isZero())
360 return true;
361
362 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
363 return false;
364
365
366
367 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
368 return true;
369}
370
371bool
372EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
375
376
377 if (!AnyEmptySubobjectsBeyondOffset(Offset))
378 return true;
379
380 if (!CanPlaceSubobjectAtOffset(RD, Offset))
381 return false;
382
384
385
387 if (Base.isVirtual())
388 continue;
389
390 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
391
393 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
394 return false;
395 }
396
397 if (RD == Class) {
398
400 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
401
403 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
404 return false;
405 }
406 }
407
408
410 if (Field->isBitField())
411 continue;
412
414 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
415 return false;
416 }
417
418 return true;
419}
420
421bool
422EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
424
425
426 if (!AnyEmptySubobjectsBeyondOffset(Offset))
427 return true;
428
431 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
432
433
437 if (!RT)
438 return true;
439
442
444 CharUnits ElementOffset = Offset;
445 for (uint64_t I = 0; I != NumElements; ++I) {
446
447
448 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
449 return true;
450
451 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
452 return false;
453
454 ElementOffset += Layout.getSize();
455 }
456 }
457
458 return true;
459}
460
461bool EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,
463 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
464 return false;
465
466
467
468 UpdateEmptyFieldSubobjects(FD, Offset, FD->hasAttr());
469 return true;
470}
471
472void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
474 bool PlacingOverlappingField) {
475
476
477
478
479
480
481
482
483
484
485 if (!PlacingOverlappingField && Offset >= SizeOfLargestEmptySubobject)
486 return;
487
488 AddSubobjectAtOffset(RD, Offset);
489
491
492
494 if (Base.isVirtual())
495 continue;
496
497 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
498
500 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset,
501 PlacingOverlappingField);
502 }
503
504 if (RD == Class) {
505
507 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
508
510 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset,
511 PlacingOverlappingField);
512 }
513 }
514
515
517 if (Field->isBitField())
518 continue;
519
521 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingOverlappingField);
522 }
523}
524
525void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
526 const FieldDecl *FD, CharUnits Offset, bool PlacingOverlappingField) {
529 UpdateEmptyFieldSubobjects(RD, RD, Offset, PlacingOverlappingField);
530 return;
531 }
532
533
537 if (!RT)
538 return;
539
542
544 CharUnits ElementOffset = Offset;
545
546 for (uint64_t I = 0; I != NumElements; ++I) {
547
548
549
550
551
552 if (!PlacingOverlappingField &&
553 ElementOffset >= SizeOfLargestEmptySubobject)
554 return;
555
556 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
557 PlacingOverlappingField);
558 ElementOffset += Layout.getSize();
559 }
560 }
561}
562
564
565class ItaniumRecordLayoutBuilder {
566protected:
567
569
571
572 EmptySubobjectMap *EmptySubobjects;
573
574
576
577
579
580
582
583
585
586
588
590
591
592
593 LLVM_PREFERRED_TYPE(bool)
594 unsigned UseExternalLayout : 1;
595
596
597
598 LLVM_PREFERRED_TYPE(bool)
599 unsigned InferAlignment : 1;
600
601
602 LLVM_PREFERRED_TYPE(bool)
603 unsigned Packed : 1;
604
605 LLVM_PREFERRED_TYPE(bool)
606 unsigned IsUnion : 1;
607
608 LLVM_PREFERRED_TYPE(bool)
609 unsigned IsMac68kAlign : 1;
610
611 LLVM_PREFERRED_TYPE(bool)
612 unsigned IsNaturalAlign : 1;
613
614 LLVM_PREFERRED_TYPE(bool)
615 unsigned IsMsStruct : 1;
616
617
618
619
620
621 unsigned char UnfilledBitsInLastUnit;
622
623
624
625 unsigned char LastBitfieldStorageUnitSize;
626
627
628
630
631
633
637
638
639
641
642
643
645
646
647
648 bool PrimaryBaseIsVirtual;
649
650
651
652 bool HasOwnVFPtr;
653
654
655 bool HasPackedField;
656
657
658
659
660
661 bool HandledFirstNonOverlappingEmptyField;
662
663 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
664
665
666 BaseOffsetsMapTy Bases;
667
668
670
671
672
674
675
676
678
679
680
682
683
685
686 ItaniumRecordLayoutBuilder(const ASTContext &Context,
687 EmptySubobjectMap *EmptySubobjects)
688 : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
690 UnpackedAlignment(CharUnits::One()),
691 UnadjustedAlignment(CharUnits::One()), UseExternalLayout(false),
693 IsMac68kAlign(false),
694 IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX()),
695 IsMsStruct(false), UnfilledBitsInLastUnit(0),
696 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(CharUnits::Zero()),
698 NonVirtualAlignment(CharUnits::One()),
699 PreferredNVAlignment(CharUnits::One()),
700 PaddedFieldSize(CharUnits::Zero()), PrimaryBase(nullptr),
701 PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), HasPackedField(false),
702 HandledFirstNonOverlappingEmptyField(false),
703 FirstNearlyEmptyVBase(nullptr) {}
704
708
710 void LayoutField(const FieldDecl *D, bool InsertExtraPadding);
711 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
712 bool FieldPacked, const FieldDecl *D);
713 void LayoutBitField(const FieldDecl *D);
714
717 }
718
719
720 llvm::SpecificBumpPtrAllocator BaseSubobjectInfoAllocator;
721
722 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
723 BaseSubobjectInfoMapTy;
724
725
726
728
729
730
731 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
732
733
734
735 void ComputeBaseSubobjectInfo(const CXXRecordDecl *RD);
736
737
738
739 BaseSubobjectInfo *ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
740 bool IsVirtual,
741 BaseSubobjectInfo *Derived);
742
743
744 void DeterminePrimaryBase(const CXXRecordDecl *RD);
745
746 void SelectPrimaryVBase(const CXXRecordDecl *RD);
747
748 void EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign);
749
750
751
752 void LayoutNonVirtualBases(const CXXRecordDecl *RD);
753
754
755 void LayoutNonVirtualBase(const BaseSubobjectInfo *Base);
756
757 void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
759
760
763
764
765 void LayoutVirtualBase(const BaseSubobjectInfo *Base);
766
767
768
769 CharUnits LayoutBase(const BaseSubobjectInfo *Base);
770
771
772 void InitializeLayout(const Decl *D);
773
774
775
776 void FinishLayout(const NamedDecl *D);
777
778 void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
780 void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {
781 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
782 }
783 void UpdateAlignment(CharUnits NewAlignment) {
784 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
785 }
786
787
788
789
790
791
793 uint64_t ComputedOffset);
794
795 void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
796 uint64_t UnpackedOffset, unsigned UnpackedAlign,
798
800
804 }
805 uint64_t getSizeInBits() const { return Size; }
806
808 void setSize(uint64_t NewSize) { Size = NewSize; }
809
810 CharUnits getAlignment() const { return Alignment; }
811
813 assert(DataSize % Context.getCharWidth() == 0);
815 }
816 uint64_t getDataSizeInBits() const { return DataSize; }
817
818 void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
819 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
820
821 ItaniumRecordLayoutBuilder(const ItaniumRecordLayoutBuilder &) = delete;
822 void operator=(const ItaniumRecordLayoutBuilder &) = delete;
823};
824}
825
826void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
827 for (const auto &I : RD->bases()) {
828 assert(!I.getType()->isDependentType() &&
829 "Cannot layout class with dependent bases.");
830
832
833
835
836
837 if (!IndirectPrimaryBases.count(Base)) {
838 PrimaryBase = Base;
839 PrimaryBaseIsVirtual = true;
840 return;
841 }
842
843
844 if (!FirstNearlyEmptyVBase)
845 FirstNearlyEmptyVBase = Base;
846 }
847
848 SelectPrimaryVBase(Base);
849 if (PrimaryBase)
850 return;
851 }
852}
853
854
855void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
856
858 return;
859
860
861
863
864
865
866
867 for (const auto &I : RD->bases()) {
868
869 if (I.isVirtual())
870 continue;
871
873
874 if (Base->isDynamicClass()) {
875
876 PrimaryBase = Base;
877 PrimaryBaseIsVirtual = false;
878 return;
879 }
880 }
881
882
883
884
885
887 SelectPrimaryVBase(RD);
888 if (PrimaryBase)
889 return;
890 }
891
892
893 if (FirstNearlyEmptyVBase) {
894 PrimaryBase = FirstNearlyEmptyVBase;
895 PrimaryBaseIsVirtual = true;
896 return;
897 }
898
899 assert(!PrimaryBase && "Should not get here with a primary base!");
900}
901
902BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
903 const CXXRecordDecl *RD, bool IsVirtual, BaseSubobjectInfo *Derived) {
904 BaseSubobjectInfo *Info;
905
906 if (IsVirtual) {
907
909 if (InfoSlot) {
910 assert(InfoSlot->Class == RD && "Wrong class for virtual base info!");
911 return InfoSlot;
912 }
913
914
915 InfoSlot = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
916 Info = InfoSlot;
917 } else {
918 Info = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
919 }
920
921 Info->Class = RD;
922 Info->IsVirtual = IsVirtual;
923 Info->Derived = nullptr;
924 Info->PrimaryVirtualBaseInfo = nullptr;
925
926 const CXXRecordDecl *PrimaryVirtualBase = nullptr;
927 BaseSubobjectInfo *PrimaryVirtualBaseInfo = nullptr;
928
929
933
935 assert(PrimaryVirtualBase && "Didn't have a primary virtual base!");
936
937
938 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
939
940 if (PrimaryVirtualBaseInfo) {
941 if (PrimaryVirtualBaseInfo->Derived) {
942
943
944
945 PrimaryVirtualBase = nullptr;
946 } else {
947
948 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
949 PrimaryVirtualBaseInfo->Derived = Info;
950 }
951 }
952 }
953 }
954
955
956 for (const auto &I : RD->bases()) {
957 bool IsVirtual = I.isVirtual();
958
959 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
960
961 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
962 }
963
964 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
965
966
967 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
968 assert(PrimaryVirtualBaseInfo &&
969 "Did not create a primary virtual base!");
970
971
972 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
973 PrimaryVirtualBaseInfo->Derived = Info;
974 }
975
976 return Info;
977}
978
979void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
981 for (const auto &I : RD->bases()) {
982 bool IsVirtual = I.isVirtual();
983
984 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
985
986
987 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
988 nullptr);
989
990 if (IsVirtual) {
991
993 "Did not add virtual base!");
994 } else {
995
996 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
997 "Non-virtual base already exists!");
998 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
999 }
1000 }
1001}
1002
1003void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
1006
1007
1008 if (!MaxFieldAlignment.isZero()) {
1009 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1010 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1011 }
1012
1013
1014 setSize(getSize().alignTo(BaseAlign));
1015
1016
1017 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
1018}
1019
1020void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
1022
1023 DeterminePrimaryBase(RD);
1024
1025
1026 ComputeBaseSubobjectInfo(RD);
1027
1028
1029 if (PrimaryBase) {
1030 if (PrimaryBaseIsVirtual) {
1031
1032
1033 BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
1034 PrimaryBaseInfo->Derived = nullptr;
1035
1036
1037 IndirectPrimaryBases.insert(PrimaryBase);
1038
1039 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1040 "vbase already visited!");
1041 VisitedVirtualBases.insert(PrimaryBase);
1042
1043 LayoutVirtualBase(PrimaryBaseInfo);
1044 } else {
1045 BaseSubobjectInfo *PrimaryBaseInfo =
1046 NonVirtualBaseInfo.lookup(PrimaryBase);
1047 assert(PrimaryBaseInfo &&
1048 "Did not find base info for non-virtual primary base!");
1049
1050 LayoutNonVirtualBase(PrimaryBaseInfo);
1051 }
1052
1053
1054
1056 assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
1061 EnsureVTablePointerAlignment(PtrAlign);
1062 HasOwnVFPtr = true;
1063
1064 assert(!IsUnion && "Unions cannot be dynamic classes.");
1065 HandledFirstNonOverlappingEmptyField = true;
1066
1067 setSize(getSize() + PtrWidth);
1068 setDataSize(getSize());
1069 }
1070
1071
1072 for (const auto &I : RD->bases()) {
1073
1074
1075 if (I.isVirtual())
1076 continue;
1077
1078 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1079
1080
1081
1082
1083 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1084 continue;
1085
1086
1087 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.lookup(BaseDecl);
1088 assert(BaseInfo && "Did not find base info for non-virtual base!");
1089
1090 LayoutNonVirtualBase(BaseInfo);
1091 }
1092}
1093
1094void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1095 const BaseSubobjectInfo *Base) {
1096
1098
1099
1100 assert(!Bases.count(Base->Class) && "base offset already exists!");
1101 Bases.insert(std::make_pair(Base->Class, Offset));
1102
1103 AddPrimaryVirtualBaseOffsets(Base, Offset);
1104}
1105
1106void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1107 const BaseSubobjectInfo *Info, CharUnits Offset) {
1108
1109 if (!Info->Class->getNumVBases())
1110 return;
1111
1112
1113 if (Info->PrimaryVirtualBaseInfo) {
1114 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1115 "Primary virtual base is not virtual!");
1116 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1117
1118 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1119 "primary vbase offset already exists!");
1120 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1122
1123
1124 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1125 }
1126 }
1127
1128
1130 for (const BaseSubobjectInfo *Base : Info->Bases) {
1131 if (Base->IsVirtual)
1132 continue;
1133
1135 AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
1136 }
1137}
1138
1139void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1142 bool PrimaryBaseIsVirtual;
1143
1144 if (MostDerivedClass == RD) {
1145 PrimaryBase = this->PrimaryBase;
1146 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1147 } else {
1151 }
1152
1154 assert(.getType()->isDependentType() &&
1155 "Cannot layout class with dependent bases.");
1156
1157 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1158
1159 if (Base.isVirtual()) {
1160 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1161 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1162
1163
1164 if (!IndirectPrimaryBase) {
1165
1166 if (!VisitedVirtualBases.insert(BaseDecl).second)
1167 continue;
1168
1169 const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
1170 assert(BaseInfo && "Did not find virtual base info!");
1171 LayoutVirtualBase(BaseInfo);
1172 }
1173 }
1174 }
1175
1177
1178 continue;
1179 }
1180
1181 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1182 }
1183}
1184
1185void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1186 const BaseSubobjectInfo *Base) {
1187 assert(->Derived && "Trying to lay out a primary virtual base!");
1188
1189
1191
1192
1193 assert(!VBases.count(Base->Class) && "vbase offset already exists!");
1194 VBases.insert(std::make_pair(Base->Class,
1196
1197 AddPrimaryVirtualBaseOffsets(Base, Offset);
1198}
1199
1201ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
1202 assert(!IsUnion && "Unions cannot have base classes.");
1203
1206
1207
1208 bool HasExternalLayout = false;
1209 if (UseExternalLayout) {
1210 if (Base->IsVirtual)
1211 HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
1212 else
1213 HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
1214 }
1215
1216 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](CharUnits UnpackedAlign) {
1217
1218
1219 return (Packed && ((Context.getLangOpts().getClangABICompat() <=
1224 : UnpackedAlign;
1225 };
1226
1230 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1232 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1233
1234 const bool DefaultsToAIXPowerAlignment =
1236 if (DefaultsToAIXPowerAlignment) {
1237
1238
1239
1240
1241 if (->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1242
1243
1244 HandledFirstNonOverlappingEmptyField = true;
1245 } else if (!IsNaturalAlign) {
1246 UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1247 PreferredBaseAlign = BaseAlign;
1248 }
1249 }
1250
1251 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1252 ? UnpackedBaseAlign
1253 : UnpackedPreferredBaseAlign;
1254
1255 if (Base->Class->isEmpty() &&
1258 setSize(std::max(getSize(), Layout.getSize()));
1259
1261 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1262
1264 }
1265
1266
1267
1268 if (!MaxFieldAlignment.isZero()) {
1269 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1270 PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);
1271 UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);
1272 }
1273
1275 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
1276 if (!HasExternalLayout) {
1277
1278 Offset = getDataSize().alignTo(AlignTo);
1279
1280
1281 while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))
1282 Offset += AlignTo;
1283 } else {
1284 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
1285 (void)Allowed;
1286 assert(Allowed && "Base subobject externally placed at overlapping offset");
1287
1288 if (InferAlignment && Offset < getDataSize().alignTo(AlignTo)) {
1289
1290
1292 InferAlignment = false;
1293 }
1294 }
1295
1296 if (->Class->isEmpty()) {
1297
1299
1300 setSize(std::max(getSize(), getDataSize()));
1301 } else
1302 setSize(std::max(getSize(), Offset + Layout.getSize()));
1303
1304
1305 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1306
1307 return Offset;
1308}
1309
1310void ItaniumRecordLayoutBuilder::InitializeLayout(const Decl *D) {
1311 if (const RecordDecl *RD = dyn_cast(D)) {
1312 IsUnion = RD->isUnion();
1313 IsMsStruct = RD->isMsStruct(Context);
1314 }
1315
1317
1318
1319 if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) {
1321 }
1322
1323
1324
1325
1326
1328 assert(
1329 ->hasAttr() &&
1330 "Having both mac68k and natural alignment on a decl is not allowed.");
1331 IsMac68kAlign = true;
1335 } else {
1337 IsNaturalAlign = true;
1338
1339 if (const MaxFieldAlignmentAttr *MFAA = D->getAttr())
1341
1344 }
1345
1346 HandledFirstNonOverlappingEmptyField =
1348
1349
1350 if (const RecordDecl *RD = dyn_cast(D))
1352 UseExternalLayout = Source->layoutRecordType(
1355
1356
1357 if (UseExternalLayout) {
1361 } else {
1362
1363 InferAlignment = true;
1364 }
1365 }
1366 }
1367}
1368
1369void ItaniumRecordLayoutBuilder::Layout(const RecordDecl *D) {
1370 InitializeLayout(D);
1371 LayoutFields(D);
1372
1373
1374
1375 FinishLayout(D);
1376}
1377
1378void ItaniumRecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
1379 InitializeLayout(RD);
1380
1381
1382 LayoutNonVirtualBases(RD);
1383
1384 LayoutFields(RD);
1385
1388 NonVirtualAlignment = Alignment;
1389 PreferredNVAlignment = PreferredAlignment;
1390
1391
1392 LayoutVirtualBases(RD, RD);
1393
1394
1395
1396 FinishLayout(RD);
1397
1398#ifndef NDEBUG
1399
1401 if (Base.isVirtual())
1402 continue;
1403
1404 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1405
1406 assert(Bases.count(BaseDecl) && "Did not find base offset!");
1407 }
1408
1409
1411 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1412
1413 assert(VBases.count(BaseDecl) && "Did not find base offset!");
1414 }
1415#endif
1416}
1417
1418void ItaniumRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
1421
1423
1424
1425
1427 setSize(getDataSize());
1428 }
1429
1430 InitializeLayout(D);
1431
1432 for (const ObjCIvarDecl *IVD = D->all_declared_ivar_begin(); IVD;
1433 IVD = IVD->getNextIvar())
1434 LayoutField(IVD, false);
1435
1436
1437
1438 FinishLayout(D);
1439}
1440
1441void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
1442
1443
1444 bool InsertExtraPadding = D->mayInsertExtraPadding(true);
1445 bool HasFlexibleArrayMember = D->hasFlexibleArrayMember();
1446 for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) {
1447 LayoutField(*I, InsertExtraPadding &&
1448 (std::next(I) != End || !HasFlexibleArrayMember));
1449 }
1450}
1451
1452
1457 return llvm::alignTo(Size, CharAlignment);
1458}
1459
1460void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1461 uint64_t StorageUnitSize,
1462 bool FieldPacked,
1464 assert(Context.getLangOpts().CPlusPlus &&
1465 "Can only have wide bit-fields in C++!");
1466
1467
1468
1469
1470
1471 QualType IntegralPODTypes[] = {
1474 };
1475
1477 for (const QualType &QT : IntegralPODTypes) {
1479
1480 if (Size > FieldSize)
1481 break;
1482
1484 }
1485 assert(.isNull() && "Did not find a type!");
1486
1488
1489
1490 UnfilledBitsInLastUnit = 0;
1491 LastBitfieldStorageUnitSize = 0;
1492
1494 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1495
1496 if (IsUnion) {
1498 Context);
1499 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1500 FieldOffset = 0;
1501 } else {
1502
1503
1504 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.toBits(TypeAlign));
1505
1506 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1507
1508 setDataSize(
1510 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1511 }
1512
1513
1514 FieldOffsets.push_back(FieldOffset);
1515
1516 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1517 Context.toBits(TypeAlign), FieldPacked, D);
1518
1519
1520 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1521
1522
1523 UpdateAlignment(TypeAlign);
1524}
1525
1528}
1529
1530void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
1531 bool FieldPacked = Packed || D->hasAttr();
1532 uint64_t FieldSize = D->getBitWidthValue();
1535 unsigned FieldAlign = FieldInfo.Align;
1537
1538
1539
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 if (IsMsStruct) {
1597
1598 FieldAlign = StorageUnitSize;
1599
1600
1601
1602
1603 if (LastBitfieldStorageUnitSize != StorageUnitSize ||
1604 UnfilledBitsInLastUnit < FieldSize) {
1605
1606 if (!LastBitfieldStorageUnitSize && !FieldSize)
1607 FieldAlign = 1;
1608
1609 UnfilledBitsInLastUnit = 0;
1610 LastBitfieldStorageUnitSize = 0;
1611 }
1612 }
1613
1616
1617
1621 FieldSize <= 32) {
1622
1623
1624 StorageUnitSize = 32;
1625
1626 if (!AlignIsRequired)
1627 FieldAlign = 32;
1628 }
1629
1630 if (FieldAlign < StorageUnitSize) {
1631
1632
1633 FieldAlign = StorageUnitSize;
1634 }
1635 }
1636
1637
1638
1639
1640 if (FieldSize > StorageUnitSize && (Context)) {
1641 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);
1642 return;
1643 }
1644
1645
1647 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1648
1649
1651
1652 if (FieldSize == 0 &&
1654
1655 if (!IsUnion && FieldOffset == 0 &&
1657 FieldAlign = 1;
1658 else {
1659
1660
1661 unsigned ZeroLengthBitfieldBoundary =
1663 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1664 }
1665
1666 } else {
1667 FieldAlign = 1;
1668 }
1669 }
1670
1671
1672 unsigned UnpackedFieldAlign = FieldAlign;
1673
1674
1675 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1676 FieldAlign = 1;
1677
1678
1680 if (ExplicitFieldAlign) {
1681 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1682 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1683 }
1684
1685
1686
1687 unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment);
1688 if (!MaxFieldAlignment.isZero() && FieldSize) {
1689 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1690 if (FieldPacked)
1691 FieldAlign = UnpackedFieldAlign;
1692 else
1693 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1694 }
1695
1696
1697
1698 if (IsMsStruct && IsUnion) {
1699 FieldAlign = UnpackedFieldAlign = 1;
1700 }
1701
1702
1703
1704
1705 uint64_t UnpaddedFieldOffset = FieldOffset;
1706 uint64_t UnpackedFieldOffset = FieldOffset;
1707
1708
1709
1710
1711 if (IsMsStruct) {
1712
1713
1714
1715
1716 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1717 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1718 UnpackedFieldOffset =
1719 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1720 UnfilledBitsInLastUnit = 0;
1721 }
1722
1723 } else {
1724
1725 bool AllowPadding = MaxFieldAlignment.isZero();
1726
1727
1728 if (FieldSize == 0 ||
1729 (AllowPadding &&
1730 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
1731 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1732 } else if (ExplicitFieldAlign &&
1733 (MaxFieldAlignmentInBits == 0 ||
1734 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1736
1737
1738 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1739 }
1740
1741
1742 if (FieldSize == 0 ||
1743 (AllowPadding &&
1744 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1745 StorageUnitSize))
1746 UnpackedFieldOffset =
1747 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1748 else if (ExplicitFieldAlign &&
1749 (MaxFieldAlignmentInBits == 0 ||
1750 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1752 UnpackedFieldOffset =
1753 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1754 }
1755
1756
1757
1758 if (UseExternalLayout)
1759 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1760
1761
1762 FieldOffsets.push_back(FieldOffset);
1763
1764
1765
1766
1767
1768 if (!IsMsStruct &&
1770 ->getIdentifier())
1771 FieldAlign = UnpackedFieldAlign = 1;
1772
1773
1774
1775
1776 if (isAIXLayout(Context) && !FieldSize) {
1777 if (FieldPacked)
1778 FieldAlign = 1;
1779 if (!MaxFieldAlignment.isZero()) {
1780 UnpackedFieldAlign =
1781 std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1782 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1783 }
1784 }
1785
1786
1787 if (!UseExternalLayout)
1788 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1789 UnpackedFieldAlign, FieldPacked, D);
1790
1791
1792
1793
1794 if (IsUnion) {
1795
1796
1798 if (IsMsStruct) {
1799 RoundedFieldSize = (FieldSize ? StorageUnitSize
1801
1802
1803
1804 } else {
1806 }
1807 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1808
1809
1810
1811 } else if (IsMsStruct && FieldSize) {
1812
1813
1814 if (!UnfilledBitsInLastUnit) {
1815 setDataSize(FieldOffset + StorageUnitSize);
1816 UnfilledBitsInLastUnit = StorageUnitSize;
1817 }
1818 UnfilledBitsInLastUnit -= FieldSize;
1819 LastBitfieldStorageUnitSize = StorageUnitSize;
1820
1821
1822
1823
1824 } else {
1825 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1827 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1828 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1829
1830
1831
1832
1833 LastBitfieldStorageUnitSize = 0;
1834 }
1835
1836
1837 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1838
1839
1840 UnadjustedAlignment =
1844}
1845
1846void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
1847 bool InsertExtraPadding) {
1848 auto *FieldClass = D->getType()->getAsCXXRecordDecl();
1849 bool IsOverlappingEmptyField =
1850 D->isPotentiallyOverlapping() && FieldClass->isEmpty();
1851
1853 (IsUnion || IsOverlappingEmptyField) ? CharUnits::Zero() : getDataSize();
1854
1855 const bool DefaultsToAIXPowerAlignment =
1857 bool FoundFirstNonOverlappingEmptyFieldForAIX = false;
1858 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1860 "The first non-overlapping empty field should have been handled.");
1861
1862 if (!IsOverlappingEmptyField) {
1863 FoundFirstNonOverlappingEmptyFieldForAIX = true;
1864
1865
1866
1867
1868
1869
1870 HandledFirstNonOverlappingEmptyField = !IsUnion;
1871 }
1872 }
1873
1874 if (D->isBitField()) {
1875 LayoutBitField(D);
1876 return;
1877 }
1878
1879 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1880
1881 UnfilledBitsInLastUnit = 0;
1882 LastBitfieldStorageUnitSize = 0;
1883
1885
1889
1890
1891
1893
1894 auto setDeclInfo = [&](bool IsIncompleteArrayType) {
1896 FieldAlign = TI.Align;
1897
1898
1899 EffectiveFieldSize = FieldSize =
1901 AlignRequirement = TI.AlignRequirement;
1902 };
1903
1904 if (D->getType()->isIncompleteArrayType()) {
1905 setDeclInfo(true );
1906 } else {
1907 setDeclInfo(false );
1908
1909
1910
1911 if (D->isPotentiallyOverlapping()) {
1913 EffectiveFieldSize =
1915 }
1916
1917 if (IsMsStruct) {
1918
1919
1920
1921
1922
1926
1927 if (!llvm::isPowerOf2_64(TypeSize.getQuantity())) {
1928 assert(
1930 "Non PowerOf2 size in MSVC mode");
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1951 }
1952 if (TypeSize > FieldAlign &&
1953 llvm::isPowerOf2_64(TypeSize.getQuantity()))
1954 FieldAlign = TypeSize;
1955 }
1956 }
1957 }
1958
1959 bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() ||
1960 FieldClass->hasAttr() ||
1961 Context.getLangOpts().getClangABICompat() <=
1964 Target.isOSAIX())) ||
1966
1967
1968
1969
1970
1971 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
1972
1973
1974
1977 FieldPacked);
1978 };
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989 CharUnits PreferredAlign = FieldAlign;
1990 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
1991 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
1992 auto performBuiltinTypeAlignmentUpgrade = [&](const BuiltinType *BTy) {
1993 if (BTy->getKind() == BuiltinType::Double ||
1994 BTy->getKind() == BuiltinType::LongDouble) {
1996 "No need to upgrade the alignment value.");
1998 }
1999 };
2000
2001 const Type *BaseTy = D->getType()->getBaseElementTypeUnsafe();
2003 performBuiltinTypeAlignmentUpgrade(
2004 CTy->getElementType()->castAs<BuiltinType>());
2006 performBuiltinTypeAlignmentUpgrade(BTy);
2009 assert(RD && "Expected non-null RecordDecl.");
2012 }
2013 }
2014
2015
2016
2017 CharUnits UnpackedFieldAlign = FieldAlign;
2019 CharUnits UnpackedFieldOffset = FieldOffset;
2020 CharUnits OriginalFieldAlign = UnpackedFieldAlign;
2021
2024 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2025 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
2026 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
2027
2028
2029 if (!MaxFieldAlignment.isZero()) {
2030 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2031 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
2032 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
2033 }
2034
2035
2036 if (!FieldPacked)
2037 FieldAlign = UnpackedFieldAlign;
2038 if (DefaultsToAIXPowerAlignment)
2039 UnpackedFieldAlign = PreferredAlign;
2040 if (FieldPacked) {
2041 PreferredAlign = PackedFieldAlign;
2042 FieldAlign = PackedFieldAlign;
2043 }
2044
2046 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
2047
2048 FieldOffset = FieldOffset.alignTo(AlignTo);
2049 UnpackedFieldOffset = UnpackedFieldOffset.alignTo(UnpackedFieldAlign);
2050
2051 if (UseExternalLayout) {
2053 updateExternalFieldOffset(D, Context.toBits(FieldOffset)));
2054
2055 if (!IsUnion && EmptySubobjects) {
2056
2057 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
2058 (void)Allowed;
2059 assert(Allowed && "Externally-placed field cannot be placed here");
2060 }
2061 } else {
2062 if (!IsUnion && EmptySubobjects) {
2063
2064 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
2065
2066
2069 FieldOffset = getDataSize().alignTo(AlignTo);
2070 else
2071 FieldOffset += AlignTo;
2072 }
2073 }
2074 }
2075
2076
2077 FieldOffsets.push_back(Context.toBits(FieldOffset));
2078
2079 if (!UseExternalLayout)
2080 CheckFieldPadding(Context.toBits(FieldOffset), UnpaddedFieldOffset,
2081 Context.toBits(UnpackedFieldOffset),
2082 Context.toBits(UnpackedFieldAlign), FieldPacked, D);
2083
2084 if (InsertExtraPadding) {
2086 CharUnits ExtraSizeForAsan = ASanAlignment;
2087 if (FieldSize % ASanAlignment)
2088 ExtraSizeForAsan +=
2090 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2091 }
2092
2093
2094 if (!IsOverlappingEmptyField) {
2095 uint64_t EffectiveFieldSizeInBits = Context.toBits(EffectiveFieldSize);
2096 if (IsUnion)
2097 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2098 else
2099 setDataSize(FieldOffset + EffectiveFieldSize);
2100
2101 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2102 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2103 } else {
2104 setSize(std::max(getSizeInBits(),
2105 (uint64_t)Context.toBits(FieldOffset + FieldSize)));
2106 }
2107
2108
2109 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2110 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2111
2112
2113
2114 if (const RecordDecl *RD = D->getParent()) {
2115
2116 if (RD->hasAttr() || !MaxFieldAlignment.isZero())
2117 if (FieldAlign < OriginalFieldAlign)
2118 if (D->getType()->isRecordType()) {
2119
2120
2121
2122 if (FieldOffset % OriginalFieldAlign != 0)
2125 }
2126 }
2127
2128 if (Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2130}
2131
2132void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
2133
2134 if (Context.getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2135 if (const CXXRecordDecl *RD = dyn_cast(D)) {
2136
2137
2138
2139 if (RD->isEmpty())
2141 }
2142 else
2144 }
2145
2146
2147
2148 setSize(std::max(getSizeInBits(), (uint64_t)Context.toBits(PaddedFieldSize)));
2149
2150
2151
2152 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2153 uint64_t UnpackedSizeInBits =
2154 llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment));
2155
2156 uint64_t RoundedSize = llvm::alignTo(
2157 getSizeInBits(),
2159 ? Alignment
2160 : PreferredAlignment));
2161
2162 if (UseExternalLayout) {
2163
2164
2165
2166 if (InferAlignment && External.Size < RoundedSize) {
2169 InferAlignment = false;
2170 }
2172 return;
2173 }
2174
2175
2176 setSize(RoundedSize);
2177
2179 if (const RecordDecl *RD = dyn_cast(D)) {
2180
2181 if (getSizeInBits() > UnpaddedSize) {
2182 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2183 bool InBits = true;
2184 if (PadSize % CharBitNum == 0) {
2185 PadSize = PadSize / CharBitNum;
2186 InBits = false;
2187 }
2190 << PadSize
2191 << (InBits ? 1 : 0);
2192 }
2193
2194 const auto *CXXRD = dyn_cast(RD);
2195
2196
2197
2198
2199
2200
2201
2202 if (Packed && UnpackedAlignment <= Alignment &&
2203 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
2204 (!CXXRD || CXXRD->isPOD() ||
2205 Context.getLangOpts().getClangABICompat() <=
2209 }
2210}
2211
2212void ItaniumRecordLayoutBuilder::UpdateAlignment(
2214 CharUnits PreferredNewAlignment) {
2215
2216
2217 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2218 return;
2219
2220 if (NewAlignment > Alignment) {
2221 assert(llvm::isPowerOf2_64(NewAlignment.getQuantity()) &&
2222 "Alignment not a power of 2");
2223 Alignment = NewAlignment;
2224 }
2225
2226 if (UnpackedNewAlignment > UnpackedAlignment) {
2227 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.getQuantity()) &&
2228 "Alignment not a power of 2");
2229 UnpackedAlignment = UnpackedNewAlignment;
2230 }
2231
2232 if (PreferredNewAlignment > PreferredAlignment) {
2233 assert(llvm::isPowerOf2_64(PreferredNewAlignment.getQuantity()) &&
2234 "Alignment not a power of 2");
2235 PreferredAlignment = PreferredNewAlignment;
2236 }
2237}
2238
2240ItaniumRecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
2241 uint64_t ComputedOffset) {
2242 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
2243
2244 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2245
2246
2249 InferAlignment = false;
2250 }
2251
2252
2253 return ExternalFieldOffset;
2254}
2255
2256
2257
2258
2259
2260
2262 switch (Tag) {
2264 return 0;
2266 return 1;
2268 return 2;
2269 default: llvm_unreachable("Invalid tag kind for field padding diagnostic!");
2270 }
2271}
2272
2273void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2274 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2275 unsigned UnpackedAlign, bool isPacked, const FieldDecl *D) {
2276
2277
2278 if (isa(D))
2279 return;
2280
2281
2282
2284 return;
2285
2287
2288
2289 if (!IsUnion && Offset > UnpaddedOffset) {
2290 unsigned PadSize = Offset - UnpaddedOffset;
2291 bool InBits = true;
2292 if (PadSize % CharBitNum == 0) {
2293 PadSize = PadSize / CharBitNum;
2294 InBits = false;
2295 }
2296 if (D->getIdentifier()) {
2297 auto Diagnostic = D->isBitField() ? diag::warn_padded_struct_bitfield
2298 : diag::warn_padded_struct_field;
2302 << (InBits ? 1 : 0)
2303 << D->getIdentifier();
2304 } else {
2305 auto Diagnostic = D->isBitField() ? diag::warn_padded_struct_anon_bitfield
2306 : diag::warn_padded_struct_anon_field;
2310 << (InBits ? 1 : 0);
2311 }
2312 }
2313 if (isPacked && Offset != UnpackedOffset) {
2314 HasPackedField = true;
2315 }
2316}
2317
2320
2322 return nullptr;
2323
2324
2325
2326
2328 return nullptr;
2329
2330
2331
2336 return nullptr;
2337
2338 bool allowInlineFunctions =
2340
2342 if (!MD->isVirtual())
2343 continue;
2344
2345 if (MD->isPureVirtual())
2346 continue;
2347
2348
2349
2350 if (MD->isImplicit())
2351 continue;
2352
2353 if (MD->isInlineSpecified() || MD->isConstexpr())
2354 continue;
2355
2356 if (MD->hasInlineBody())
2357 continue;
2358
2359
2360 if (!MD->isUserProvided())
2361 continue;
2362
2363
2364 if (!allowInlineFunctions) {
2367 continue;
2368 }
2369
2371
2372
2373
2374 if (Context.getLangOpts().CUDAIsDevice) {
2375
2376 if (!MD->hasAttr())
2377 continue;
2378 } else {
2379
2380 if (!MD->hasAttr() && MD->hasAttr())
2381 continue;
2382 }
2383 }
2384
2385
2386
2387
2388 if (MD->hasAttr() && !RD->hasAttr() &&
2390 return nullptr;
2391
2392
2393 return MD;
2394 }
2395
2396 return nullptr;
2397}
2398
2400 unsigned DiagID) {
2402}
2403
2404
2405
2406
2410 return false;
2411
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431 return RD->isPOD();
2432
2434
2435
2436
2437
2438
2439
2441 }
2442
2443 llvm_unreachable("bad tail-padding use kind");
2444}
2445
2447
2451
2453}
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
2545namespace {
2546struct MicrosoftRecordLayoutBuilder {
2547 struct ElementInfo {
2550 };
2551 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2552 MicrosoftRecordLayoutBuilder(const ASTContext &Context,
2553 EmptySubobjectMap *EmptySubobjects)
2554 : Context(Context), EmptySubobjects(EmptySubobjects) {}
2555
2556private:
2557 MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) = delete;
2558 void operator=(const MicrosoftRecordLayoutBuilder &) = delete;
2559public:
2562
2563 void initializeLayout(const RecordDecl *RD);
2564
2565
2566
2567 void initializeCXXLayout(const CXXRecordDecl *RD);
2568 void layoutNonVirtualBases(const CXXRecordDecl *RD);
2569 void layoutNonVirtualBase(const CXXRecordDecl *RD,
2575
2576
2577 void layoutFields(const RecordDecl *RD);
2578 void layoutField(const FieldDecl *FD);
2579 void layoutBitField(const FieldDecl *FD);
2580
2581
2582 void layoutZeroWidthBitField(const FieldDecl *FD);
2583 void layoutVirtualBases(const CXXRecordDecl *RD);
2584 void finalizeLayout(const RecordDecl *RD);
2585
2586
2587 ElementInfo getAdjustedElementInfo(const ASTRecordLayout &Layout);
2588
2589
2590
2591 ElementInfo getAdjustedElementInfo(const FieldDecl *FD);
2592
2593 void placeFieldAtOffset(CharUnits FieldOffset) {
2594 FieldOffsets.push_back(Context.toBits(FieldOffset));
2595 }
2596
2597 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2598 FieldOffsets.push_back(FieldOffset);
2599 }
2600
2601 void computeVtorDispSet(
2602 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2605 EmptySubobjectMap *EmptySubobjects;
2606
2607
2609
2611
2613
2615
2617
2618
2620
2621
2622
2624
2626
2628
2629 ElementInfo PointerInfo;
2630
2632
2634
2636
2637 BaseOffsetsMapTy Bases;
2638
2640
2641
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(
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(
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 (auto RT =
2714 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2716 }
2717
2718 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2719 }
2720
2721 if (!MaxFieldAlignment.isZero())
2722 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2723 if (FD->hasAttr())
2725 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2726 return Info;
2727}
2728
2729void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
2730
2732 initializeLayout(RD);
2733 layoutFields(RD);
2734 DataSize = Size = Size.alignTo(Alignment);
2735 RequiredAlignment = std::max(
2737 finalizeLayout(RD);
2738}
2739
2740void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
2741
2743 initializeLayout(RD);
2744 initializeCXXLayout(RD);
2745 layoutNonVirtualBases(RD);
2746 layoutFields(RD);
2747 injectVBPtr(RD);
2748 injectVFPtr(RD);
2749 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2750 Alignment = std::max(Alignment, PointerInfo.Alignment);
2751 auto RoundingAlignment = Alignment;
2752 if (!MaxFieldAlignment.isZero())
2753 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2754 if (!UseExternalLayout)
2755 Size = Size.alignTo(RoundingAlignment);
2756 NonVirtualSize = Size;
2757 RequiredAlignment = std::max(
2759 layoutVirtualBases(RD);
2760 finalizeLayout(RD);
2761}
2762
2763void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
2764 IsUnion = RD->isUnion();
2767
2768
2769
2773
2775
2776 if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct)
2778
2779
2780 if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr()){
2781 unsigned PackedAlignment = MFAA->getAlignment();
2782 if (PackedAlignment <=
2785 }
2786
2787 if (RD->hasAttr())
2789
2790
2791 UseExternalLayout = false;
2793 UseExternalLayout = Source->layoutRecordType(
2796}
2797
2798void
2799MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) {
2800 EndsWithZeroSizedObject = false;
2801 LeadsWithZeroSizedBase = false;
2802 HasOwnVFPtr = false;
2803 HasVBPtr = false;
2804 PrimaryBase = nullptr;
2805 SharedVBPtrBase = nullptr;
2806
2807
2812
2813 if (!MaxFieldAlignment.isZero())
2814 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2815}
2816
2817void
2818MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) {
2819
2820
2821
2822
2823
2824
2826 bool HasPolymorphicBaseClass = false;
2827
2829 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2830 HasPolymorphicBaseClass |= BaseDecl->isPolymorphic();
2832
2833 if (Base.isVirtual()) {
2834 HasVBPtr = true;
2835 continue;
2836 }
2837
2838 if (!SharedVBPtrBase && BaseLayout.hasVBPtr()) {
2839 SharedVBPtrBase = BaseDecl;
2840 HasVBPtr = true;
2841 }
2842
2844 continue;
2845
2846 if (!PrimaryBase) {
2847 PrimaryBase = BaseDecl;
2849 }
2850
2851 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2852 }
2853
2855 if (!HasPolymorphicBaseClass)
2856
2857
2858 HasOwnVFPtr = true;
2859 else if (!PrimaryBase) {
2860
2861
2863 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2864 M->size_overridden_methods() == 0) {
2865 HasOwnVFPtr = true;
2866 break;
2867 }
2868 }
2869 }
2870 }
2871
2872
2873 bool CheckLeadingLayout = !PrimaryBase;
2874
2876 if (Base.isVirtual())
2877 continue;
2878 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2880
2883 continue;
2884 }
2885
2886
2887 if (CheckLeadingLayout) {
2888 CheckLeadingLayout = false;
2890 }
2891
2892 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2894 }
2895
2896 if (!HasVBPtr)
2898 else if (SharedVBPtrBase) {
2900 VBPtrOffset = Bases[SharedVBPtrBase] + Layout.getVBPtrOffset();
2901 }
2902}
2903
2905 if (!isa(RD))
2906 return false;
2907 if (RD->hasAttr())
2908 return true;
2909 if (auto *LVA = RD->getAttr())
2910
2911 if (LVA->getVersion() <= LangOptions::MSVC2015)
2912 return false;
2913
2914
2915
2916 return false;
2917}
2918
2919void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2923
2924
2925
2930 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2932
2933
2934 bool FoundBase = false;
2935 if (UseExternalLayout) {
2936 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2937 if (BaseOffset > Size) {
2938 Size = BaseOffset;
2939 }
2940 }
2941
2942 if (!FoundBase) {
2943 if (MDCUsesEBO && BaseDecl->isEmpty() &&
2946 } else {
2947
2948 BaseOffset = Size = Size.alignTo(Info.Alignment);
2949 }
2950 }
2951 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2953 DataSize = Size;
2954 PreviousBaseLayout = &BaseLayout;
2955}
2956
2957void MicrosoftRecordLayoutBuilder::layoutFields(const RecordDecl *RD) {
2958 LastFieldIsNonZeroWidthBitfield = false;
2960 layoutField(Field);
2961}
2962
2963void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {
2965 layoutBitField(FD);
2966 return;
2967 }
2968 LastFieldIsNonZeroWidthBitfield = false;
2969 ElementInfo Info = getAdjustedElementInfo(FD);
2970 Alignment = std::max(Alignment, Info.Alignment);
2971
2974 FieldClass->isEmpty() &&
2975 FieldClass->fields().empty();
2977
2978 if (UseExternalLayout) {
2979 FieldOffset =
2981 } else if (IsUnion) {
2983 } else if (EmptySubobjects) {
2984 if (!IsOverlappingEmptyField)
2985 FieldOffset = DataSize.alignTo(Info.Alignment);
2986
2987 while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {
2989 bool HasBases = ParentClass && (!ParentClass->bases().empty() ||
2990 !ParentClass->vbases().empty());
2992 HasBases) {
2993
2994
2995 FieldOffset = DataSize.alignTo(Info.Alignment);
2996 } else {
2997 FieldOffset += Info.Alignment;
2998 }
2999 }
3000 } else {
3001 FieldOffset = Size.alignTo(Info.Alignment);
3002 }
3003 placeFieldAtOffset(FieldOffset);
3004
3005 if (!IsOverlappingEmptyField)
3006 DataSize = std::max(DataSize, FieldOffset + Info.Size);
3007
3008 Size = std::max(Size, FieldOffset + Info.Size);
3009}
3010
3011void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
3013 if (Width == 0) {
3014 layoutZeroWidthBitField(FD);
3015 return;
3016 }
3017 ElementInfo Info = getAdjustedElementInfo(FD);
3018
3019
3020 if (Width > Context.toBits(Info.Size))
3021 Width = Context.toBits(Info.Size);
3022
3023
3024
3025 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
3026 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
3027 placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField);
3028 RemainingBitsInField -= Width;
3029 return;
3030 }
3031 LastFieldIsNonZeroWidthBitfield = true;
3032 CurrentBitfieldSize = Info.Size;
3033 if (UseExternalLayout) {
3034 auto FieldBitOffset = External.getExternalFieldOffset(FD);
3035 placeFieldAtBitOffset(FieldBitOffset);
3037 llvm::alignDown(FieldBitOffset, Context.toBits(Info.Alignment)) +
3038 Context.toBits(Info.Size));
3039 Size = std::max(Size, NewSize);
3040 Alignment = std::max(Alignment, Info.Alignment);
3041 } else if (IsUnion) {
3043 Size = std::max(Size, Info.Size);
3044
3045 } else {
3046
3047 CharUnits FieldOffset = Size.alignTo(Info.Alignment);
3048 placeFieldAtOffset(FieldOffset);
3049 Size = FieldOffset + Info.Size;
3050 Alignment = std::max(Alignment, Info.Alignment);
3051 RemainingBitsInField = Context.toBits(Info.Size) - Width;
3052 }
3053 DataSize = Size;
3054}
3055
3056void
3057MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) {
3058
3059
3060 if (!LastFieldIsNonZeroWidthBitfield) {
3062
3063
3064 return;
3065 }
3066 LastFieldIsNonZeroWidthBitfield = false;
3067 ElementInfo Info = getAdjustedElementInfo(FD);
3068 if (IsUnion) {
3070 Size = std::max(Size, Info.Size);
3071
3072 } else {
3073
3074 CharUnits FieldOffset = Size.alignTo(Info.Alignment);
3075 placeFieldAtOffset(FieldOffset);
3076 Size = FieldOffset;
3077 Alignment = std::max(Alignment, Info.Alignment);
3078 }
3079 DataSize = Size;
3080}
3081
3082void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) {
3083 if (!HasVBPtr || SharedVBPtrBase)
3084 return;
3085
3086 CharUnits InjectionSite = VBPtrOffset;
3087
3088 VBPtrOffset = VBPtrOffset.alignTo(PointerInfo.Alignment);
3089
3090 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3091
3092
3093 if (UseExternalLayout) {
3094
3095
3096 if (Size < FieldStart)
3097 Size = FieldStart;
3098 return;
3099 }
3100
3101
3102 CharUnits Offset = (FieldStart - InjectionSite)
3103 .alignTo(std::max(RequiredAlignment, Alignment));
3104 Size += Offset;
3105 for (uint64_t &FieldOffset : FieldOffsets)
3106 FieldOffset += Context.toBits(Offset);
3107 for (BaseOffsetsMapTy::value_type &Base : Bases)
3108 if (Base.second >= InjectionSite)
3109 Base.second += Offset;
3110}
3111
3112void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) {
3113 if (!HasOwnVFPtr)
3114 return;
3115
3116
3118 PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment));
3119
3120
3121 if (HasVBPtr)
3122 VBPtrOffset += Offset;
3123
3124 if (UseExternalLayout) {
3125
3126
3127 if (Size.isZero())
3128 Size += Offset;
3129 return;
3130 }
3131
3132 Size += Offset;
3133
3134
3135
3136 for (uint64_t &FieldOffset : FieldOffsets)
3137 FieldOffset += Context.toBits(Offset);
3138 for (BaseOffsetsMapTy::value_type &Base : Bases)
3139 Base.second += Offset;
3140}
3141
3142void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
3143 if (!HasVBPtr)
3144 return;
3145
3147 CharUnits VtorDispAlignment = VtorDispSize;
3148
3149 if (!MaxFieldAlignment.isZero())
3150 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3151
3152
3153
3155 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3157 RequiredAlignment =
3159 }
3160 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3161
3163 computeVtorDispSet(HasVtorDispSet, RD);
3164
3167 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3169 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3170
3171
3172
3173
3174
3177 HasVtordisp) {
3178 Size = Size.alignTo(VtorDispAlignment) + VtorDispSize;
3179 Alignment = std::max(VtorDispAlignment, Alignment);
3180 }
3181
3182 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3184
3185
3186 if (UseExternalLayout) {
3187 if (.getExternalVBaseOffset(BaseDecl, BaseOffset))
3188 BaseOffset = Size;
3189 } else
3190 BaseOffset = Size.alignTo(Info.Alignment);
3191
3192 assert(BaseOffset >= Size && "base offset already allocated");
3193
3194 VBases.insert(std::make_pair(BaseDecl,
3197 PreviousBaseLayout = &BaseLayout;
3198 }
3199}
3200
3201void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
3202
3203
3204 DataSize = Size;
3205 if (!RequiredAlignment.isZero()) {
3206 Alignment = std::max(Alignment, RequiredAlignment);
3207 auto RoundingAlignment = Alignment;
3208 if (!MaxFieldAlignment.isZero())
3209 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3210 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3211 Size = Size.alignTo(RoundingAlignment);
3212 }
3213 if (Size.isZero()) {
3214 if ((RD) || !cast(RD)->isEmpty()) {
3215 EndsWithZeroSizedObject = true;
3216 LeadsWithZeroSizedBase = true;
3217 }
3218
3219
3220 if (RequiredAlignment >= MinEmptyStructSize)
3221 Size = Alignment;
3222 else
3223 Size = MinEmptyStructSize;
3224 }
3225
3226 if (UseExternalLayout) {
3230 }
3231}
3232
3233
3234
3235static bool
3237 BasesWithOverriddenMethods,
3239 if (BasesWithOverriddenMethods.count(RD))
3240 return true;
3241
3242
3244 if (.isVirtual() &&
3246 Base.getType()->getAsCXXRecordDecl()))
3247 return true;
3248 return false;
3249}
3250
3251void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3252 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3254
3255
3258 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
3261 HasVtordispSet.insert(BaseDecl);
3262 }
3263 return;
3264 }
3265
3266
3267
3269 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
3272 if (bi.second.hasVtorDisp())
3273 HasVtordispSet.insert(bi.first);
3274 }
3275
3276
3277
3280 return;
3281
3282
3283
3284 assert(RD->getMSVtorDispMode() == MSVtorDispMode::ForVBaseOverride);
3285
3286
3287
3288
3291
3293 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3294 !isa(MD) && !MD->isPureVirtual())
3295 Work.insert(MD);
3296 while (!Work.empty()) {
3299
3300 if (MethodRange.begin() == MethodRange.end())
3301 BasesWithOverriddenMethods.insert(MD->getParent());
3302 else
3303 Work.insert(MethodRange.begin(), MethodRange.end());
3304
3305 Work.erase(MD);
3306 }
3307
3308
3310 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
3311 if (!HasVtordispSet.count(BaseDecl) &&
3313 HasVtordispSet.insert(BaseDecl);
3314 }
3315}
3316
3317
3318
3319
3322
3323
3324
3325
3326
3327 if (D->hasExternalLexicalStorage() && ->getDefinition())
3329
3331
3333 assert(D && "Cannot get layout of forward declarations!");
3334 assert(->isInvalidDecl() && "Cannot get layout of invalid decl!");
3335 assert(D->isCompleteDefinition() && "Cannot layout type before complete!");
3336
3337
3338
3339
3341 if (Entry) return *Entry;
3342
3344
3346 if (const auto *RD = dyn_cast(D)) {
3347 EmptySubobjectMap EmptySubobjects(*this, RD);
3348 MicrosoftRecordLayoutBuilder Builder(*this, &EmptySubobjects);
3349 Builder.cxxLayout(RD);
3351 *this, Builder.Size, Builder.Alignment, Builder.Alignment,
3352 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3353 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3354 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3355 Builder.Alignment, Builder.Alignment, CharUnits::Zero(),
3356 Builder.PrimaryBase, false, Builder.SharedVBPtrBase,
3357 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3358 Builder.Bases, Builder.VBases);
3359 } else {
3360 MicrosoftRecordLayoutBuilder Builder(*this, nullptr);
3361 Builder.layout(D);
3363 *this, Builder.Size, Builder.Alignment, Builder.Alignment,
3364 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3365 Builder.FieldOffsets);
3366 }
3367 } else {
3368 if (const auto *RD = dyn_cast(D)) {
3369 EmptySubobjectMap EmptySubobjects(*this, RD);
3370 ItaniumRecordLayoutBuilder Builder(*this, &EmptySubobjects);
3371 Builder.Layout(RD);
3372
3373
3374
3375
3376 bool skipTailPadding =
3378
3379
3381 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3383 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3385 *this, Builder.getSize(), Builder.Alignment,
3386 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3387
3388 Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(),
3390 NonVirtualSize, Builder.NonVirtualAlignment,
3391 Builder.PreferredNVAlignment,
3392 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3393 Builder.PrimaryBaseIsVirtual, nullptr, false, false, Builder.Bases,
3394 Builder.VBases);
3395 } else {
3396 ItaniumRecordLayoutBuilder Builder(*this, nullptr);
3397 Builder.Layout(D);
3398
3400 *this, Builder.getSize(), Builder.Alignment,
3401 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3402
3403 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3404 }
3405 }
3406
3407 ASTRecordLayouts[D] = NewEntry;
3408
3410 llvm::outs() << "\n*** Dumping AST Record Layout\n";
3412 }
3413
3414 return *NewEntry;
3415}
3416
3418 if (().getCXXABI().hasKeyFunctions())
3419 return nullptr;
3420
3421 assert(RD->getDefinition() && "Cannot get key function for forward decl!");
3423
3424
3425
3426
3427
3428
3432
3433
3435 KeyFunctions[RD] = const_cast<Decl*>(Result);
3436
3437 return cast_or_null(Result);
3438}
3439
3442 "not working with method declaration from class definition");
3443
3444
3445
3446
3447 const auto &Map = KeyFunctions;
3448 auto I = Map.find(Method->getParent());
3449
3450
3451 if (I == Map.end()) return;
3452
3453
3454
3455
3458
3459 KeyFunctions.erase(Method->getParent());
3460 }
3461}
3462
3466}
3467
3469 uint64_t OffsetInBits;
3470 if (const FieldDecl *FD = dyn_cast(VD)) {
3472 } else {
3474
3475 OffsetInBits = 0;
3477 OffsetInBits += ::getFieldOffset(*this, cast(ND));
3478 }
3479
3480 return OffsetInBits;
3481}
3482
3488
3489
3490
3491
3492
3493
3494
3498 else
3500
3501
3502
3503
3504
3505
3506 unsigned Index = 0;
3507
3508 for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
3509 IVD; IVD = IVD->getNextIvar()) {
3510 if (Ivar == IVD)
3511 break;
3512 ++Index;
3513 }
3514 assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!");
3515
3517}
3518
3519
3520
3521
3522
3523
3527
3528 if (D->hasExternalLexicalStorage() && ->getDefinition())
3531 assert(D && ->isInvalidDecl() && D->isThisDeclarationADefinition() &&
3532 "Invalid interface decl!");
3533
3534
3538 return *Entry;
3539
3540
3541 if (Impl) {
3543
3544
3545
3546
3547 if (SynthCount == 0)
3548 return getObjCLayout(D, nullptr);
3549 }
3550
3551 ItaniumRecordLayoutBuilder Builder(*this, nullptr);
3552 Builder.Layout(D);
3553
3555 *this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3556 Builder.UnadjustedAlignment,
3557
3558 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3559
3560 ObjCLayouts[Key] = NewEntry;
3561
3562 return *NewEntry;
3563}
3564
3566 CharUnits Offset, unsigned IndentLevel) {
3567 OS << llvm::format("%10" PRId64 " | ", (int64_t)Offset.getQuantity());
3568 OS.indent(IndentLevel * 2);
3569}
3570
3572 unsigned Begin, unsigned Width,
3573 unsigned IndentLevel) {
3575 {
3576 llvm::raw_svector_ostream BufferOS(Buffer);
3577 BufferOS << Offset.getQuantity() << ':';
3578 if (Width == 0) {
3579 BufferOS << '-';
3580 } else {
3581 BufferOS << Begin << '-' << (Begin + Width - 1);
3582 }
3583 }
3584
3585 OS << llvm::right_justify(Buffer, 10) << " | ";
3586 OS.indent(IndentLevel * 2);
3587}
3588
3590 OS << " | ";
3591 OS.indent(IndentLevel * 2);
3592}
3593
3597 unsigned IndentLevel,
3598 const char* Description,
3599 bool PrintSizeInfo,
3600 bool IncludeVirtualBases) {
3602 auto CXXRD = dyn_cast(RD);
3603
3605 OS << C.getTypeDeclType(const_cast<RecordDecl *>(RD));
3606 if (Description)
3607 OS << ' ' << Description;
3608 if (CXXRD && CXXRD->isEmpty())
3609 OS << " (empty)";
3610 OS << '\n';
3611
3612 IndentLevel++;
3613
3614
3615 if (CXXRD) {
3617 bool HasOwnVFPtr = Layout.hasOwnVFPtr();
3618 bool HasOwnVBPtr = Layout.hasOwnVBPtr();
3619
3620
3621 if (CXXRD->isDynamicClass() && !PrimaryBase && (C)) {
3623 OS << '(' << *RD << " vtable pointer)\n";
3624 } else if (HasOwnVFPtr) {
3626
3627 OS << '(' << *RD << " vftable pointer)\n";
3628 }
3629
3630
3633 assert(.getType()->isDependentType() &&
3634 "Cannot layout class with dependent bases.");
3635 if (.isVirtual())
3636 Bases.push_back(Base.getType()->getAsCXXRecordDecl());
3637 }
3638
3639
3640 llvm::stable_sort(
3643 });
3644
3645
3649 Base == PrimaryBase ? "(primary base)" : "(base)",
3650 false,
3651 false);
3652 }
3653
3654
3655 if (HasOwnVBPtr) {
3657 OS << '(' << *RD << " vbtable pointer)\n";
3658 }
3659 }
3660
3661
3663 uint64_t LocalFieldOffsetInBits =
3666 Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3667
3668
3669 if (auto RT = Field->getType()->getAs<RecordType>()) {
3671 Field->getName().data(),
3672 false,
3673 true);
3674 continue;
3675 }
3676
3677 if (Field->isBitField()) {
3678 uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset);
3679 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3680 unsigned Width = Field->getBitWidthValue();
3682 } else {
3683 PrintOffset(OS, FieldOffset, IndentLevel);
3684 }
3685 const QualType &FieldType = C.getLangOpts().DumpRecordLayoutsCanonical
3686 ? Field->getType().getCanonicalType()
3687 : Field->getType();
3688 OS << FieldType << ' ' << *Field << '\n';
3689 }
3690
3691
3692 if (CXXRD && IncludeVirtualBases) {
3695
3697 assert(Base.isVirtual() && "Found non-virtual class!");
3698 const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();
3699
3701
3702 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3704 OS << "(vtordisp for vbase " << *VBase << ")\n";
3705 }
3706
3709 "(primary virtual base)" : "(virtual base)",
3710 false,
3711 false);
3712 }
3713 }
3714
3715 if (!PrintSizeInfo) return;
3716
3722 if (C.getTargetInfo().defaultsToAIXPowerAlignment())
3724
3725 if (CXXRD) {
3726 OS << ",\n";
3730 if (C.getTargetInfo().defaultsToAIXPowerAlignment())
3731 OS << ", preferrednvalign="
3733 }
3734 OS << "]\n";
3735}
3736
3738 bool Simple) const {
3739 if (!Simple) {
3741 true,
3742 true);
3743 return;
3744 }
3745
3746
3747
3748
3749
3750
3751
3752
3755 OS << "\nLayout: ";
3756 OS << "<ASTRecordLayout\n";
3757 OS << " Size:" << toBits(Info.getSize()) << "\n";
3761 if (Target->defaultsToAIXPowerAlignment())
3763 << "\n";
3764 if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) {
3765 OS << " BaseOffsets: [";
3767 for (auto I : CXXRD->bases()) {
3768 if (I.isVirtual())
3769 continue;
3771 OS << ", ";
3772 Base = I.getType()->getAsCXXRecordDecl();
3773 OS << Info.CXXInfo->BaseOffsets[Base].getQuantity();
3774 }
3775 OS << "]>\n";
3776 OS << " VBaseOffsets: [";
3778 for (auto I : CXXRD->vbases()) {
3779 if (VBase)
3780 OS << ", ";
3781 VBase = I.getType()->getAsCXXRecordDecl();
3782 OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();
3783 }
3784 OS << "]>\n";
3785 }
3786 OS << " FieldOffsets: [";
3787 for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) {
3788 if (i)
3789 OS << ", ";
3791 }
3792 OS << "]>\n";
3793}
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
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)
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...
static bool isAIXLayout(const ASTContext &Context)
static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel)
static uint64_t roundUpSizeToCharAlignment(uint64_t Size, const ASTContext &Context)
static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel)
static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
Get diagnostic select index for tag kind for field padding diagnostic message.
static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, const ASTContext &C, CharUnits Offset, unsigned IndentLevel, const char *Description, bool PrintSizeInfo, bool IncludeVirtualBases)
static bool isMsLayout(const ASTContext &Context)
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
static bool RequiresVtordisp(const llvm::SmallPtrSetImpl< const CXXRecordDecl * > &BasesWithOverriddenMethods, const CXXRecordDecl *RD)
static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset, unsigned Begin, unsigned Width, unsigned IndentLevel)
static bool recordUsesEBO(const RecordDecl *RD)
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.
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple=false) const
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...
const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const
Get or compute information about the layout of the specified Objective-C implementation.
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
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.
unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const
bool isNearlyEmpty(const CXXRecordDecl *RD) const
const TargetInfo * getAuxTargetInfo() const
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.
void setNonKeyFunction(const CXXMethodDecl *method)
Observe that the given method cannot be a key function.
TypeInfoChars getTypeInfoInChars(const Type *T) const
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID, const ObjCImplementationDecl *ID, const ObjCIvarDecl *Ivar) const
Get the offset of an ObjCIvarDecl in bits.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
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.
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...
This class is used for builtin types like 'int'.
Represents a base class of a C++ class.
A set of all the primary bases for a 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.
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.
Complex values, per C99 6.2.5p11.
Represents the canonical version of C arrays with a specified constant size.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Decl - This represents one declaration (or definition), e.g.
Decl * getMostRecentDecl()
Retrieve the most recent declaration that declares the same entity as this declaration (which may be ...
unsigned getMaxAlignment() const
getMaxAlignment - return the maximum alignment specified by attributes on this decl,...
bool isInvalidDecl() const
SourceLocation getLocation() const
A little helper class used to produce diagnostics.
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.
Abstract interface for external sources of AST nodes.
virtual void CompleteType(TagDecl *Tag)
Gives the external AST source an opportunity to complete an incomplete type.
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
@ Ver6
Attempt to be ABI-compatible with code generated by Clang 6.0.x (SVN r321711).
@ Ver15
Attempt to be ABI-compatible with code generated by Clang 15.0.x.
This represents a decl that may have a name.
bool isExternallyVisible() const
ObjCContainerDecl - Represents a container for method declarations.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
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 * 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,...
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
Encodes a location in the source.
The basic abstraction for the target C++ ABI.
TailPaddingUseRules getTailPaddingUseRules() const
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
bool canKeyFunctionBeInline() const
Can an out-of-line inline function serve as a key function?
@ 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.
virtual bool hasPS4DLLImportExport() 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.
The base class of the type hierarchy.
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 * getAs() const
Member-template getAs'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Defines the clang::TargetInfo interface.
bool Zero(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
@ 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.
TagTypeKind
The kind of a tag type.
@ Interface
The "__interface" keyword.
@ Struct
The "struct" keyword.
@ Class
The "class" keyword.
const FunctionProtoType * T
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
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.
@ None
The alignment was not explicit in code.
@ RequiredByTypedef
The alignment comes from an alignment attribute on a typedef.
@ RequiredByRecord
The alignment comes from an alignment attribute on a record type.
@ 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.
All virtual base related information about a given record decl.