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(Base.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(Base->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 (Base->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 (Base->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

1316 Packed = D->hasAttr();

1317

1318

1319 if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) {

1321 }

1322

1323

1324

1325

1326

1327 if (D->hasAttr()) {

1328 assert(

1329 D->hasAttr() &&

1330 "Having both mac68k and natural alignment on a decl is not allowed.");

1331 IsMac68kAlign = true;

1335 } else {

1336 if (D->hasAttr())

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(Type.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 && isAIXLayout(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 D->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 (External.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 (recordUsesEBO(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 (Base.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() && D->getDefinition())

3329

3331

3332 D = D->getDefinition();

3333 assert(D && "Cannot get layout of forward declarations!");

3334 assert(D->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 (getTargetInfo().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() && D->getDefinition())

3530 D = D->getDefinition();

3531 assert(D && 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 && isMsLayout(C)) {

3623 OS << '(' << *RD << " vtable pointer)\n";

3624 } else if (HasOwnVFPtr) {

3626

3627 OS << '(' << *RD << " vftable pointer)\n";

3628 }

3629

3630

3633 assert(Base.getType()->isDependentType() &&

3634 "Cannot layout class with dependent bases.");

3635 if (Base.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.