clang: lib/AST/RecordLayoutBuilder.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

20#include "llvm/Support/Format.h"

21#include "llvm/Support/MathExtras.h"

22

23using namespace clang;

24

25namespace {

26

27

28

29

30

31

32

33

34

35

36

37

38struct BaseSubobjectInfo {

39

40 const CXXRecordDecl *Class;

41

42

43 bool IsVirtual;

44

45

46 SmallVector<BaseSubobjectInfo*, 4> Bases;

47

48

49

50 BaseSubobjectInfo *PrimaryVirtualBaseInfo;

51

52

53 const BaseSubobjectInfo *Derived;

54};

55

56

57

58

59struct ExternalLayout {

60 ExternalLayout() = default;

61

62

64

65

67

68

69 llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;

70

71

72 llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;

73

74

75 llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;

76

77

78

79 uint64_t getExternalFieldOffset(const FieldDecl *FD) {

80 assert(FieldOffsets.count(FD) &&

81 "Field does not have an external offset");

82 return FieldOffsets[FD];

83 }

84

85 bool getExternalNVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) {

86 auto Known = BaseOffsets.find(RD);

87 if (Known == BaseOffsets.end())

88 return false;

89 BaseOffset = Known->second;

90 return true;

91 }

92

93 bool getExternalVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) {

94 auto Known = VirtualBaseOffsets.find(RD);

95 if (Known == VirtualBaseOffsets.end())

96 return false;

97 BaseOffset = Known->second;

98 return true;

99 }

100};

101

102

103

104class EmptySubobjectMap {

105 const ASTContext &Context;

107

108

109 const CXXRecordDecl *Class;

110

111

112 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;

113 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;

114 EmptyClassOffsetsMapTy EmptyClassOffsets;

115

116

117

118 CharUnits MaxEmptyClassOffset;

119

120

121

122 void ComputeEmptySubobjectSizes();

123

124 void AddSubobjectAtOffset(const CXXRecordDecl *RD, CharUnits Offset);

125

126 void UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,

127 CharUnits Offset, bool PlacingEmptyBase);

128

129 void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,

130 const CXXRecordDecl *Class, CharUnits Offset,

131 bool PlacingOverlappingField);

132 void UpdateEmptyFieldSubobjects(const FieldDecl *FD, CharUnits Offset,

133 bool PlacingOverlappingField);

134

135

136

137 bool AnyEmptySubobjectsBeyondOffset(CharUnits Offset) const {

138 return Offset <= MaxEmptyClassOffset;

139 }

140

141 CharUnits getFieldOffset(const ASTRecordLayout &Layout,

142 const FieldDecl *Field) const {

144 assert(FieldOffset % CharWidth == 0 &&

145 "Field offset not at char boundary!");

146

147 return Context.toCharUnitsFromBits(FieldOffset);

148 }

149

150protected:

151 bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,

152 CharUnits Offset) const;

153

154 bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,

155 CharUnits Offset);

156

157 bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,

158 const CXXRecordDecl *Class,

159 CharUnits Offset) const;

160 bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,

161 CharUnits Offset) const;

162

163public:

164

165

166

167 CharUnits SizeOfLargestEmptySubobject;

168

169 EmptySubobjectMap(const ASTContext &Context, const CXXRecordDecl *Class)

170 : Context(Context), CharWidth(Context.getCharWidth()), Class(Class) {

171 ComputeEmptySubobjectSizes();

172 }

173

174

175

176

177

178 bool CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,

179 CharUnits Offset);

180

181

182

183 bool CanPlaceFieldAtOffset(const FieldDecl *FD, CharUnits Offset);

184};

185

186void EmptySubobjectMap::ComputeEmptySubobjectSizes() {

187

188 for (const CXXBaseSpecifier &Base : Class->bases()) {

189 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

190 assert(BaseDecl != Class && "Class cannot inherit from itself.");

191

192 CharUnits EmptySize;

193 const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);

194 if (BaseDecl->isEmpty()) {

195

196 EmptySize = Layout.getSize();

197 } else {

198

200 }

201

202 if (EmptySize > SizeOfLargestEmptySubobject)

203 SizeOfLargestEmptySubobject = EmptySize;

204 }

205

206

207 for (const FieldDecl *FD : Class->fields()) {

208

209 const auto *MemberDecl =

211 if (!MemberDecl)

212 continue;

213

214 CharUnits EmptySize;

215 const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl);

216 if (MemberDecl->isEmpty()) {

217

218 EmptySize = Layout.getSize();

219 } else {

220

222 }

223

224 if (EmptySize > SizeOfLargestEmptySubobject)

225 SizeOfLargestEmptySubobject = EmptySize;

226 }

227}

228

229bool

230EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,

231 CharUnits Offset) const {

232

234 return true;

235

236 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);

237 if (I == EmptyClassOffsets.end())

238 return true;

239

240 const ClassVectorTy &Classes = I->second;

241 if (!llvm::is_contained(Classes, RD))

242 return true;

243

244

245 return false;

246}

247

248void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,

249 CharUnits Offset) {

250

252 return;

253

254

255

256 ClassVectorTy &Classes = EmptyClassOffsets[Offset];

257 if (llvm::is_contained(Classes, RD))

258 return;

259

260 Classes.push_back(RD);

261

262

263 if (Offset > MaxEmptyClassOffset)

264 MaxEmptyClassOffset = Offset;

265}

266

267bool

268EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,

269 CharUnits Offset) {

270

271

272 if (!AnyEmptySubobjectsBeyondOffset(Offset))

273 return true;

274

275 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))

276 return false;

277

278

279 const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);

280 for (const BaseSubobjectInfo *Base : Info->Bases) {

281 if (Base->IsVirtual)

282 continue;

283

285

286 if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))

287 return false;

288 }

289

290 if (Info->PrimaryVirtualBaseInfo) {

291 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;

292

293 if (Info == PrimaryVirtualBaseInfo->Derived) {

294 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))

295 return false;

296 }

297 }

298

299

300 for (const FieldDecl *Field : Info->Class->fields()) {

301 if (Field->isBitField())

302 continue;

303

304 CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);

305 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))

306 return false;

307 }

308

309 return true;

310}

311

312void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,

313 CharUnits Offset,

314 bool PlacingEmptyBase) {

315 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {

316

317

318

319

320

321 return;

322 }

323

324 AddSubobjectAtOffset(Info->Class, Offset);

325

326

327 const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);

328 for (const BaseSubobjectInfo *Base : Info->Bases) {

329 if (Base->IsVirtual)

330 continue;

331

333 UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);

334 }

335

336 if (Info->PrimaryVirtualBaseInfo) {

337 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;

338

339 if (Info == PrimaryVirtualBaseInfo->Derived)

340 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,

341 PlacingEmptyBase);

342 }

343

344

345 for (const FieldDecl *Field : Info->Class->fields()) {

346 if (Field->isBitField())

347 continue;

348

349 CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);

350 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingEmptyBase);

351 }

352}

353

354bool EmptySubobjectMap::CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,

355 CharUnits Offset) {

356

357

358 if (SizeOfLargestEmptySubobject.isZero())

359 return true;

360

361 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))

362 return false;

363

364

365

366 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());

367 return true;

368}

369

370bool

371EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,

372 const CXXRecordDecl *Class,

373 CharUnits Offset) const {

374

375

376 if (!AnyEmptySubobjectsBeyondOffset(Offset))

377 return true;

378

379 if (!CanPlaceSubobjectAtOffset(RD, Offset))

380 return false;

381

383

384

385 for (const CXXBaseSpecifier &Base : RD->bases()) {

386 if (Base.isVirtual())

387 continue;

388

389 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

390

392 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))

393 return false;

394 }

395

396 if (RD == Class) {

397

398 for (const CXXBaseSpecifier &Base : RD->vbases()) {

399 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();

400

402 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))

403 return false;

404 }

405 }

406

407

408 for (const FieldDecl *Field : RD->fields()) {

409 if (Field->isBitField())

410 continue;

411

412 CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);

413 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))

414 return false;

415 }

416

417 return true;

418}

419

420bool

421EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,

422 CharUnits Offset) const {

423

424

425 if (!AnyEmptySubobjectsBeyondOffset(Offset))

426 return true;

427

430 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);

431

432

436 if (!RD)

437 return true;

438

440

442 CharUnits ElementOffset = Offset;

443 for (uint64_t I = 0; I != NumElements; ++I) {

444

445

446 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))

447 return true;

448

449 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))

450 return false;

451

452 ElementOffset += Layout.getSize();

453 }

454 }

455

456 return true;

457}

458

459bool EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,

460 CharUnits Offset) {

461 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))

462 return false;

463

464

465

466 UpdateEmptyFieldSubobjects(FD, Offset, FD->hasAttr());

467 return true;

468}

469

470void EmptySubobjectMap::UpdateEmptyFieldSubobjects(

471 const CXXRecordDecl *RD, const CXXRecordDecl *Class, CharUnits Offset,

472 bool PlacingOverlappingField) {

473

474

475

476

477

478

479

480

481

482

483 if (!PlacingOverlappingField && Offset >= SizeOfLargestEmptySubobject)

484 return;

485

486 AddSubobjectAtOffset(RD, Offset);

487

489

490

491 for (const CXXBaseSpecifier &Base : RD->bases()) {

492 if (Base.isVirtual())

493 continue;

494

495 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

496

498 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset,

499 PlacingOverlappingField);

500 }

501

502 if (RD == Class) {

503

504 for (const CXXBaseSpecifier &Base : RD->vbases()) {

505 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();

506

508 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset,

509 PlacingOverlappingField);

510 }

511 }

512

513

514 for (const FieldDecl *Field : RD->fields()) {

515 if (Field->isBitField())

516 continue;

517

518 CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);

519 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingOverlappingField);

520 }

521}

522

523void EmptySubobjectMap::UpdateEmptyFieldSubobjects(

524 const FieldDecl *FD, CharUnits Offset, bool PlacingOverlappingField) {

527 UpdateEmptyFieldSubobjects(RD, RD, Offset, PlacingOverlappingField);

528 return;

529 }

530

531

535 if (!RD)

536 return;

537

539

541 CharUnits ElementOffset = Offset;

542

543 for (uint64_t I = 0; I != NumElements; ++I) {

544

545

546

547

548

549 if (!PlacingOverlappingField &&

550 ElementOffset >= SizeOfLargestEmptySubobject)

551 return;

552

553 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,

554 PlacingOverlappingField);

555 ElementOffset += Layout.getSize();

556 }

557 }

558}

559

560typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy;

561

562class ItaniumRecordLayoutBuilder {

563protected:

564

565 friend class clang::ASTContext;

566

567 const ASTContext &Context;

568

569 EmptySubobjectMap *EmptySubobjects;

570

571

573

574

575 CharUnits Alignment;

576

577

578 CharUnits PreferredAlignment;

579

580

581 CharUnits UnpackedAlignment;

582

583

584 CharUnits UnadjustedAlignment;

585

586 SmallVector<uint64_t, 16> FieldOffsets;

587

588

589

590 LLVM_PREFERRED_TYPE(bool)

591 unsigned UseExternalLayout : 1;

592

593

594

595 LLVM_PREFERRED_TYPE(bool)

596 unsigned InferAlignment : 1;

597

598

599 LLVM_PREFERRED_TYPE(bool)

601

602 LLVM_PREFERRED_TYPE(bool)

603 unsigned IsUnion : 1;

604

605 LLVM_PREFERRED_TYPE(bool)

606 unsigned IsMac68kAlign : 1;

607

608 LLVM_PREFERRED_TYPE(bool)

609 unsigned IsNaturalAlign : 1;

610

611 LLVM_PREFERRED_TYPE(bool)

612 unsigned IsMsStruct : 1;

613

614

615

616

617

618 unsigned char UnfilledBitsInLastUnit;

619

620

621

622 unsigned char LastBitfieldStorageUnitSize;

623

624

625

626 CharUnits MaxFieldAlignment;

627

628

630

631 CharUnits NonVirtualSize;

632 CharUnits NonVirtualAlignment;

633 CharUnits PreferredNVAlignment;

634

635

636

637 CharUnits PaddedFieldSize;

638

639

640

641 const CXXRecordDecl *PrimaryBase;

642

643

644

645 bool PrimaryBaseIsVirtual;

646

647

648

649 bool HasOwnVFPtr;

650

651

652 bool HasPackedField;

653

654

655

656

657

658 bool HandledFirstNonOverlappingEmptyField;

659

660 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;

661

662

663 BaseOffsetsMapTy Bases;

664

665

667

668

669

670 CXXIndirectPrimaryBaseSet IndirectPrimaryBases;

671

672

673

674 const CXXRecordDecl *FirstNearlyEmptyVBase;

675

676

677

678 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;

679

680

682

683 ItaniumRecordLayoutBuilder(const ASTContext &Context,

684 EmptySubobjectMap *EmptySubobjects)

685 : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),

686 Alignment(CharUnits::One()), PreferredAlignment(CharUnits::One()),

687 UnpackedAlignment(CharUnits::One()),

688 UnadjustedAlignment(CharUnits::One()), UseExternalLayout(false),

690 IsMac68kAlign(false),

691 IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX()),

692 IsMsStruct(false), UnfilledBitsInLastUnit(0),

693 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(CharUnits::Zero()),

694 DataSize(0), NonVirtualSize(CharUnits::Zero()),

695 NonVirtualAlignment(CharUnits::One()),

696 PreferredNVAlignment(CharUnits::One()),

697 PaddedFieldSize(CharUnits::Zero()), PrimaryBase(nullptr),

698 PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), HasPackedField(false),

699 HandledFirstNonOverlappingEmptyField(false),

700 FirstNearlyEmptyVBase(nullptr) {}

701

702 void Layout(const RecordDecl *D);

703 void Layout(const CXXRecordDecl *D);

704 void Layout(const ObjCInterfaceDecl *D);

705

706 void LayoutFields(const RecordDecl *D);

707 void LayoutField(const FieldDecl *D, bool InsertExtraPadding);

708 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,

709 bool FieldPacked, const FieldDecl *D);

710 void LayoutBitField(const FieldDecl *D);

711

712 TargetCXXABI getCXXABI() const {

714 }

715

716

717 llvm::SpecificBumpPtrAllocator BaseSubobjectInfoAllocator;

718

719 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>

720 BaseSubobjectInfoMapTy;

721

722

723

724 BaseSubobjectInfoMapTy VirtualBaseInfo;

725

726

727

728 BaseSubobjectInfoMapTy NonVirtualBaseInfo;

729

730

731

732 void ComputeBaseSubobjectInfo(const CXXRecordDecl *RD);

733

734

735

736 BaseSubobjectInfo *ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,

737 bool IsVirtual,

738 BaseSubobjectInfo *Derived);

739

740

741 void DeterminePrimaryBase(const CXXRecordDecl *RD);

742

743 void SelectPrimaryVBase(const CXXRecordDecl *RD);

744

745 void EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign);

746

747

748

749 void LayoutNonVirtualBases(const CXXRecordDecl *RD);

750

751

752 void LayoutNonVirtualBase(const BaseSubobjectInfo *Base);

753

754 void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,

755 CharUnits Offset);

756

757

758 void LayoutVirtualBases(const CXXRecordDecl *RD,

759 const CXXRecordDecl *MostDerivedClass);

760

761

762 void LayoutVirtualBase(const BaseSubobjectInfo *Base);

763

764

765

766 CharUnits LayoutBase(const BaseSubobjectInfo *Base);

767

768

769 void InitializeLayout(const Decl *D);

770

771

772

773 void FinishLayout(const NamedDecl *D);

774

775 void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment,

776 CharUnits PreferredAlignment);

777 void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {

778 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);

779 }

780 void UpdateAlignment(CharUnits NewAlignment) {

781 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);

782 }

783

784

785

786

787

788

789 uint64_t updateExternalFieldOffset(const FieldDecl *Field,

790 uint64_t ComputedOffset);

791

793 uint64_t UnpackedOffset, unsigned UnpackedAlign,

794 bool isPacked, const FieldDecl *D);

795

796 DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);

797

798 CharUnits getSize() const {

801 }

802 uint64_t getSizeInBits() const { return Size; }

803

804 void setSize(CharUnits NewSize) { Size = Context.toBits(NewSize); }

805 void setSize(uint64_t NewSize) { Size = NewSize; }

806

807 CharUnits getAlignment() const { return Alignment; }

808

809 CharUnits getDataSize() const {

810 assert(DataSize % Context.getCharWidth() == 0);

812 }

813 uint64_t getDataSizeInBits() const { return DataSize; }

814

815 void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }

816 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }

817

818 ItaniumRecordLayoutBuilder(const ItaniumRecordLayoutBuilder &) = delete;

819 void operator=(const ItaniumRecordLayoutBuilder &) = delete;

820};

821}

822

823void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {

824 for (const auto &I : RD->bases()) {

825 assert(!I.getType()->isDependentType() &&

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

827

828 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();

829

830

831 if (I.isVirtual() && Context.isNearlyEmpty(Base)) {

832

833

834 if (!IndirectPrimaryBases.count(Base)) {

835 PrimaryBase = Base;

836 PrimaryBaseIsVirtual = true;

837 return;

838 }

839

840

841 if (!FirstNearlyEmptyVBase)

842 FirstNearlyEmptyVBase = Base;

843 }

844

845 SelectPrimaryVBase(Base);

846 if (PrimaryBase)

847 return;

848 }

849}

850

851

852void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {

853

855 return;

856

857

858

860

861

862

863

864 for (const auto &I : RD->bases()) {

865

866 if (I.isVirtual())

867 continue;

868

869 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();

870

871 if (Base->isDynamicClass()) {

872

873 PrimaryBase = Base;

874 PrimaryBaseIsVirtual = false;

875 return;

876 }

877 }

878

879

880

881

882

884 SelectPrimaryVBase(RD);

885 if (PrimaryBase)

886 return;

887 }

888

889

890 if (FirstNearlyEmptyVBase) {

891 PrimaryBase = FirstNearlyEmptyVBase;

892 PrimaryBaseIsVirtual = true;

893 return;

894 }

895

896 assert(!PrimaryBase && "Should not get here with a primary base!");

897}

898

899BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(

900 const CXXRecordDecl *RD, bool IsVirtual, BaseSubobjectInfo *Derived) {

901 BaseSubobjectInfo *Info;

902

903 if (IsVirtual) {

904

905 BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];

906 if (InfoSlot) {

907 assert(InfoSlot->Class == RD && "Wrong class for virtual base info!");

908 return InfoSlot;

909 }

910

911

912 InfoSlot = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;

913 Info = InfoSlot;

914 } else {

915 Info = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;

916 }

917

918 Info->Class = RD;

919 Info->IsVirtual = IsVirtual;

920 Info->Derived = nullptr;

921 Info->PrimaryVirtualBaseInfo = nullptr;

922

923 const CXXRecordDecl *PrimaryVirtualBase = nullptr;

924 BaseSubobjectInfo *PrimaryVirtualBaseInfo = nullptr;

925

926

930

932 assert(PrimaryVirtualBase && "Didn't have a primary virtual base!");

933

934

935 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);

936

937 if (PrimaryVirtualBaseInfo) {

938 if (PrimaryVirtualBaseInfo->Derived) {

939

940

941

942 PrimaryVirtualBase = nullptr;

943 } else {

944

945 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;

946 PrimaryVirtualBaseInfo->Derived = Info;

947 }

948 }

949 }

950 }

951

952

953 for (const auto &I : RD->bases()) {

954 bool IsVirtual = I.isVirtual();

955

956 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();

957

958 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));

959 }

960

961 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {

962

963

964 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);

965 assert(PrimaryVirtualBaseInfo &&

966 "Did not create a primary virtual base!");

967

968

969 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;

970 PrimaryVirtualBaseInfo->Derived = Info;

971 }

972

973 return Info;

974}

975

976void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(

977 const CXXRecordDecl *RD) {

978 for (const auto &I : RD->bases()) {

979 bool IsVirtual = I.isVirtual();

980

981 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();

982

983

984 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,

985 nullptr);

986

987 if (IsVirtual) {

988

989 assert(VirtualBaseInfo.count(BaseDecl) &&

990 "Did not add virtual base!");

991 } else {

992

993 assert(!NonVirtualBaseInfo.count(BaseDecl) &&

994 "Non-virtual base already exists!");

995 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));

996 }

997 }

998}

999

1000void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(

1001 CharUnits UnpackedBaseAlign) {

1003

1004

1005 if (!MaxFieldAlignment.isZero()) {

1006 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);

1007 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);

1008 }

1009

1010

1011 setSize(getSize().alignTo(BaseAlign));

1012

1013

1014 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);

1015}

1016

1017void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(

1018 const CXXRecordDecl *RD) {

1019

1020 DeterminePrimaryBase(RD);

1021

1022

1023 ComputeBaseSubobjectInfo(RD);

1024

1025

1026 if (PrimaryBase) {

1027 if (PrimaryBaseIsVirtual) {

1028

1029

1030 BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);

1031 PrimaryBaseInfo->Derived = nullptr;

1032

1033

1034 IndirectPrimaryBases.insert(PrimaryBase);

1035

1036 assert(!VisitedVirtualBases.count(PrimaryBase) &&

1037 "vbase already visited!");

1038 VisitedVirtualBases.insert(PrimaryBase);

1039

1040 LayoutVirtualBase(PrimaryBaseInfo);

1041 } else {

1042 BaseSubobjectInfo *PrimaryBaseInfo =

1043 NonVirtualBaseInfo.lookup(PrimaryBase);

1044 assert(PrimaryBaseInfo &&

1045 "Did not find base info for non-virtual primary base!");

1046

1047 LayoutNonVirtualBase(PrimaryBaseInfo);

1048 }

1049

1050

1051

1053 assert(DataSize == 0 && "Vtable pointer must be at offset zero!");

1058 EnsureVTablePointerAlignment(PtrAlign);

1059 HasOwnVFPtr = true;

1060

1061 assert(!IsUnion && "Unions cannot be dynamic classes.");

1062 HandledFirstNonOverlappingEmptyField = true;

1063

1064 setSize(getSize() + PtrWidth);

1065 setDataSize(getSize());

1066 }

1067

1068

1069 for (const auto &I : RD->bases()) {

1070

1071

1072 if (I.isVirtual())

1073 continue;

1074

1075 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();

1076

1077

1078

1079

1080 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)

1081 continue;

1082

1083

1084 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.lookup(BaseDecl);

1085 assert(BaseInfo && "Did not find base info for non-virtual base!");

1086

1087 LayoutNonVirtualBase(BaseInfo);

1088 }

1089}

1090

1091void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(

1092 const BaseSubobjectInfo *Base) {

1093

1094 CharUnits Offset = LayoutBase(Base);

1095

1096

1097 assert(!Bases.count(Base->Class) && "base offset already exists!");

1098 Bases.insert(std::make_pair(Base->Class, Offset));

1099

1100 AddPrimaryVirtualBaseOffsets(Base, Offset);

1101}

1102

1103void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(

1104 const BaseSubobjectInfo *Info, CharUnits Offset) {

1105

1107 return;

1108

1109

1110 if (Info->PrimaryVirtualBaseInfo) {

1111 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&

1112 "Primary virtual base is not virtual!");

1113 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {

1114

1115 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&

1116 "primary vbase offset already exists!");

1117 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,

1118 ASTRecordLayout::VBaseInfo(Offset, false)));

1119

1120

1121 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);

1122 }

1123 }

1124

1125

1126 const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);

1127 for (const BaseSubobjectInfo *Base : Info->Bases) {

1128 if (Base->IsVirtual)

1129 continue;

1130

1132 AddPrimaryVirtualBaseOffsets(Base, BaseOffset);

1133 }

1134}

1135

1136void ItaniumRecordLayoutBuilder::LayoutVirtualBases(

1137 const CXXRecordDecl *RD, const CXXRecordDecl *MostDerivedClass) {

1138 const CXXRecordDecl *PrimaryBase;

1139 bool PrimaryBaseIsVirtual;

1140

1141 if (MostDerivedClass == RD) {

1142 PrimaryBase = this->PrimaryBase;

1143 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;

1144 } else {

1148 }

1149

1150 for (const CXXBaseSpecifier &Base : RD->bases()) {

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

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

1153

1154 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

1155

1156 if (Base.isVirtual()) {

1157 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {

1158 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);

1159

1160

1161 if (!IndirectPrimaryBase) {

1162

1163 if (!VisitedVirtualBases.insert(BaseDecl).second)

1164 continue;

1165

1166 const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);

1167 assert(BaseInfo && "Did not find virtual base info!");

1168 LayoutVirtualBase(BaseInfo);

1169 }

1170 }

1171 }

1172

1174

1175 continue;

1176 }

1177

1178 LayoutVirtualBases(BaseDecl, MostDerivedClass);

1179 }

1180}

1181

1182void ItaniumRecordLayoutBuilder::LayoutVirtualBase(

1183 const BaseSubobjectInfo *Base) {

1184 assert(Base->Derived && "Trying to lay out a primary virtual base!");

1185

1186

1187 CharUnits Offset = LayoutBase(Base);

1188

1189

1190 assert(!VBases.count(Base->Class) && "vbase offset already exists!");

1191 VBases.insert(std::make_pair(Base->Class,

1192 ASTRecordLayout::VBaseInfo(Offset, false)));

1193

1194 AddPrimaryVirtualBaseOffsets(Base, Offset);

1195}

1196

1197CharUnits

1198ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {

1199 assert(!IsUnion && "Unions cannot have base classes.");

1200

1202 CharUnits Offset;

1203

1204

1205 bool HasExternalLayout = false;

1206 if (UseExternalLayout) {

1207 if (Base->IsVirtual)

1208 HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);

1209 else

1210 HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);

1211 }

1212

1213 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](CharUnits UnpackedAlign) {

1214

1215

1216 return (Packed && ((Context.getLangOpts().getClangABICompat() <=

1217 LangOptions::ClangABI::Ver6) ||

1221 : UnpackedAlign;

1222 };

1223

1226 CharUnits BaseAlign =

1227 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);

1228 CharUnits PreferredBaseAlign =

1229 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);

1230

1231 const bool DefaultsToAIXPowerAlignment =

1233 if (DefaultsToAIXPowerAlignment) {

1234

1235

1236

1237

1238 if (Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {

1239

1240

1241 HandledFirstNonOverlappingEmptyField = true;

1242 } else if (!IsNaturalAlign) {

1243 UnpackedPreferredBaseAlign = UnpackedBaseAlign;

1244 PreferredBaseAlign = BaseAlign;

1245 }

1246 }

1247

1248 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment

1249 ? UnpackedBaseAlign

1250 : UnpackedPreferredBaseAlign;

1251

1252 if (Base->Class->isEmpty() &&

1254 EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) {

1255 setSize(std::max(getSize(), Layout.getSize()));

1256

1258 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);

1259

1261 }

1262

1263

1264

1265 if (!MaxFieldAlignment.isZero()) {

1266 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);

1267 PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);

1268 UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);

1269 }

1270

1271 CharUnits AlignTo =

1272 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;

1273 if (!HasExternalLayout) {

1274

1275 Offset = getDataSize().alignTo(AlignTo);

1276

1277

1278 while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))

1279 Offset += AlignTo;

1280 } else {

1281 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);

1282 (void)Allowed;

1283 assert(Allowed && "Base subobject externally placed at overlapping offset");

1284

1285 if (InferAlignment && Offset < getDataSize().alignTo(AlignTo)) {

1286

1287

1289 InferAlignment = false;

1290 }

1291 }

1292

1293 if (Base->Class->isEmpty()) {

1294

1296

1297 setSize(std::max(getSize(), getDataSize()));

1298 } else

1299 setSize(std::max(getSize(), Offset + Layout.getSize()));

1300

1301

1302 UnadjustedAlignment = std::max(UnadjustedAlignment, BaseAlign);

1303 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);

1304

1305 return Offset;

1306}

1307

1308void ItaniumRecordLayoutBuilder::InitializeLayout(const Decl *D) {

1309 if (const RecordDecl *RD = dyn_cast(D)) {

1310 IsUnion = RD->isUnion();

1311 IsMsStruct = RD->isMsStruct(Context);

1312 }

1313

1315

1316

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

1319 }

1320

1321

1322

1323

1324

1325 if (D->hasAttr()) {

1326 assert(

1327 !D->hasAttr() &&

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

1329 IsMac68kAlign = true;

1333 } else {

1334 if (D->hasAttr())

1335 IsNaturalAlign = true;

1336

1337 if (const MaxFieldAlignmentAttr *MFAA = D->getAttr())

1339

1342 }

1343

1344 HandledFirstNonOverlappingEmptyField =

1346

1347

1348 if (const RecordDecl *RD = dyn_cast(D))

1350 UseExternalLayout = Source->layoutRecordType(

1353

1354

1355 if (UseExternalLayout) {

1359 } else {

1360

1361 InferAlignment = true;

1362 }

1363 }

1364 }

1365}

1366

1367void ItaniumRecordLayoutBuilder::Layout(const RecordDecl *D) {

1368 InitializeLayout(D);

1369 LayoutFields(D);

1370

1371

1372

1373 FinishLayout(D);

1374}

1375

1376void ItaniumRecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {

1377 InitializeLayout(RD);

1378

1379

1380 LayoutNonVirtualBases(RD);

1381

1382 LayoutFields(RD);

1383

1386 NonVirtualAlignment = Alignment;

1387 PreferredNVAlignment = PreferredAlignment;

1388

1389

1390 LayoutVirtualBases(RD, RD);

1391

1392

1393

1394 FinishLayout(RD);

1395

1396#ifndef NDEBUG

1397

1398 for (const CXXBaseSpecifier &Base : RD->bases()) {

1399 if (Base.isVirtual())

1400 continue;

1401

1402 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

1403

1404 assert(Bases.count(BaseDecl) && "Did not find base offset!");

1405 }

1406

1407

1408 for (const CXXBaseSpecifier &Base : RD->vbases()) {

1409 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

1410

1411 assert(VBases.count(BaseDecl) && "Did not find base offset!");

1412 }

1413#endif

1414}

1415

1416void ItaniumRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {

1417 if (ObjCInterfaceDecl *SD = D->getSuperClass()) {

1419

1421

1422

1423

1425 setSize(getDataSize());

1426 }

1427

1428 InitializeLayout(D);

1429

1432 LayoutField(IVD, false);

1433

1434

1435

1436 FinishLayout(D);

1437}

1438

1439void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {

1440

1441

1445 LayoutField(*I, InsertExtraPadding &&

1446 (std::next(I) != End || !HasFlexibleArrayMember));

1447 }

1448}

1449

1450

1454 uint64_t CharAlignment = Context.getTargetInfo().getCharAlign();

1455 return llvm::alignTo(Size, CharAlignment);

1456}

1457

1458void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,

1459 uint64_t StorageUnitSize,

1460 bool FieldPacked,

1461 const FieldDecl *D) {

1462 assert(Context.getLangOpts().CPlusPlus &&

1463 "Can only have wide bit-fields in C++!");

1464

1465

1466

1467

1468

1469 QualType IntegralPODTypes[] = {

1473 };

1474

1475 QualType Type;

1478 for (const QualType &QT : IntegralPODTypes) {

1480

1481 if (Size > FieldSize || Size > MaxSize)

1482 break;

1483

1485 }

1486 assert(Type.isNull() && "Did not find a type!");

1487

1489

1490

1491 UnfilledBitsInLastUnit = 0;

1492 LastBitfieldStorageUnitSize = 0;

1493

1495 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;

1496

1497 if (IsUnion) {

1499 Context);

1500 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));

1501 FieldOffset = 0;

1502 } else {

1503

1504

1505 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.toBits(TypeAlign));

1506

1507 uint64_t NewSizeInBits = FieldOffset + FieldSize;

1508

1509 setDataSize(

1511 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;

1512 }

1513

1514

1515 FieldOffsets.push_back(FieldOffset);

1516

1517 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,

1518 Context.toBits(TypeAlign), FieldPacked, D);

1519

1520

1521 setSize(std::max(getSizeInBits(), getDataSizeInBits()));

1522

1523

1524 UnadjustedAlignment = std::max(UnadjustedAlignment, TypeAlign);

1525 UpdateAlignment(TypeAlign);

1526}

1527

1529 return Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX;

1530}

1531

1532void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {

1533 bool FieldPacked = Packed || D->hasAttr();

1537 unsigned FieldAlign = FieldInfo.Align;

1539 unsigned char PaddingInLastUnit = 0;

1540

1541

1542

1543

1544

1545

1546

1547

1548

1549

1550

1551

1552

1553

1554

1555

1556

1557

1558

1559

1560

1561

1562

1563

1564

1565

1566

1567

1568

1569

1570

1571

1572

1573

1574

1575

1576

1577

1578

1579

1580

1581

1582

1583

1584

1585

1586

1587

1588

1589

1590

1591

1592

1593

1594

1595

1596

1597

1598

1599 if (IsMsStruct) {

1600

1601 FieldAlign = StorageUnitSize;

1602

1603

1604

1605

1606 if (LastBitfieldStorageUnitSize != StorageUnitSize ||

1607 UnfilledBitsInLastUnit < FieldSize) {

1608

1609 if (!LastBitfieldStorageUnitSize && !FieldSize)

1610 FieldAlign = 1;

1611

1612 PaddingInLastUnit = UnfilledBitsInLastUnit;

1613 UnfilledBitsInLastUnit = 0;

1614 LastBitfieldStorageUnitSize = 0;

1615 }

1616 }

1617

1620

1621

1625 FieldSize <= 32) {

1626

1627

1628 StorageUnitSize = 32;

1629

1630 if (!AlignIsRequired)

1631 FieldAlign = 32;

1632 }

1633

1634 if (FieldAlign < StorageUnitSize) {

1635

1636

1637 FieldAlign = StorageUnitSize;

1638 }

1639 }

1640

1641

1642

1643

1644 if (FieldSize > StorageUnitSize && isAIXLayout(Context)) {

1645 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);

1646 return;

1647 }

1648

1649

1651 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);

1652

1653

1655

1656 if (FieldSize == 0 &&

1658

1659 if (!IsUnion && FieldOffset == 0 &&

1661 FieldAlign = 1;

1662 else {

1663

1664

1665 unsigned ZeroLengthBitfieldBoundary =

1667 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);

1668 }

1669

1670 } else {

1671 FieldAlign = 1;

1672 }

1673 }

1674

1675

1676 unsigned UnpackedFieldAlign = FieldAlign;

1677

1678

1679 if (!IsMsStruct && FieldPacked && FieldSize != 0)

1680 FieldAlign = 1;

1681

1682

1684 if (ExplicitFieldAlign) {

1685 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);

1686 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);

1687 }

1688

1689

1690

1691 unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment);

1692 if (!MaxFieldAlignment.isZero() && FieldSize) {

1693 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);

1694 if (FieldPacked)

1695 FieldAlign = UnpackedFieldAlign;

1696 else

1697 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);

1698 }

1699

1700

1701

1702 if (IsMsStruct && IsUnion) {

1703 FieldAlign = UnpackedFieldAlign = 1;

1704 }

1705

1706

1707

1708

1709 uint64_t UnpaddedFieldOffset = FieldOffset - PaddingInLastUnit;

1710 uint64_t UnpackedFieldOffset = FieldOffset;

1711

1712

1713

1714

1715 if (IsMsStruct) {

1716

1717

1718

1719

1720 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {

1721 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);

1722 UnpackedFieldOffset =

1723 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);

1724 UnfilledBitsInLastUnit = 0;

1725 }

1726

1727 } else {

1728

1729 bool AllowPadding = MaxFieldAlignment.isZero();

1730

1731

1732 if (FieldSize == 0 ||

1733 (AllowPadding &&

1734 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {

1735 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);

1736 } else if (ExplicitFieldAlign &&

1737 (MaxFieldAlignmentInBits == 0 ||

1738 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&

1740

1741

1742 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);

1743 }

1744

1745

1746 if (FieldSize == 0 ||

1747 (AllowPadding &&

1748 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >

1749 StorageUnitSize))

1750 UnpackedFieldOffset =

1751 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);

1752 else if (ExplicitFieldAlign &&

1753 (MaxFieldAlignmentInBits == 0 ||

1754 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&

1756 UnpackedFieldOffset =

1757 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);

1758 }

1759

1760

1761

1762 if (UseExternalLayout)

1763 FieldOffset = updateExternalFieldOffset(D, FieldOffset);

1764

1765

1766 FieldOffsets.push_back(FieldOffset);

1767

1768

1769

1770

1771

1772 if (!IsMsStruct &&

1775 FieldAlign = UnpackedFieldAlign = 1;

1776

1777

1778

1779

1780 if (isAIXLayout(Context) && !FieldSize) {

1781 if (FieldPacked)

1782 FieldAlign = 1;

1783 if (!MaxFieldAlignment.isZero()) {

1784 UnpackedFieldAlign =

1785 std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);

1786 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);

1787 }

1788 }

1789

1790

1791 if (!UseExternalLayout)

1792 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,

1793 UnpackedFieldAlign, FieldPacked, D);

1794

1795

1796

1797

1798 if (IsUnion) {

1799

1800

1802 if (IsMsStruct) {

1803 RoundedFieldSize = (FieldSize ? StorageUnitSize

1805

1806

1807

1808 } else {

1810 }

1811 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));

1812

1813

1814

1815 } else if (IsMsStruct && FieldSize) {

1816

1817

1818 if (!UnfilledBitsInLastUnit) {

1819 setDataSize(FieldOffset + StorageUnitSize);

1820 UnfilledBitsInLastUnit = StorageUnitSize;

1821 }

1822 UnfilledBitsInLastUnit -= FieldSize;

1823 LastBitfieldStorageUnitSize = StorageUnitSize;

1824

1825

1826

1827

1828 } else {

1829 uint64_t NewSizeInBits = FieldOffset + FieldSize;

1831 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));

1832 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;

1833

1834

1835

1836

1837 LastBitfieldStorageUnitSize = 0;

1838 }

1839

1840

1841 setSize(std::max(getSizeInBits(), getDataSizeInBits()));

1842

1843

1844 UnadjustedAlignment =

1848}

1849

1850void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,

1851 bool InsertExtraPadding) {

1853 bool IsOverlappingEmptyField =

1855

1856 CharUnits FieldOffset =

1857 (IsUnion || IsOverlappingEmptyField) ? CharUnits::Zero() : getDataSize();

1858

1859 const bool DefaultsToAIXPowerAlignment =

1861 bool FoundFirstNonOverlappingEmptyFieldForAIX = false;

1862 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {

1864 "The first non-overlapping empty field should have been handled.");

1865

1866 if (!IsOverlappingEmptyField) {

1867 FoundFirstNonOverlappingEmptyFieldForAIX = true;

1868

1869

1870

1871

1872

1873

1874 HandledFirstNonOverlappingEmptyField = !IsUnion;

1875 }

1876 }

1877

1879 LayoutBitField(D);

1880 return;

1881 }

1882

1883 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;

1884

1885 UnfilledBitsInLastUnit = 0;

1886 LastBitfieldStorageUnitSize = 0;

1887

1889

1891 CharUnits FieldSize;

1892 CharUnits FieldAlign;

1893

1894

1895

1896 CharUnits EffectiveFieldSize;

1897

1898 auto setDeclInfo = [&](bool IsIncompleteArrayType) {

1900 FieldAlign = TI.Align;

1901

1902

1903 EffectiveFieldSize = FieldSize =

1905 AlignRequirement = TI.AlignRequirement;

1906 };

1907

1909 setDeclInfo(true );

1910 } else {

1911 setDeclInfo(false );

1912

1913

1914

1916 const ASTRecordLayout &Layout = Context.getASTRecordLayout(FieldClass);

1917 EffectiveFieldSize =

1919 }

1920

1921 if (IsMsStruct) {

1922

1923

1924

1925

1926

1928 if (const BuiltinType *BTy = T->getAs()) {

1930

1931 if (!llvm::isPowerOf2_64(TypeSize.getQuantity())) {

1932 assert(

1934 "Non PowerOf2 size in MSVC mode");

1935

1936

1937

1938

1939

1940

1941

1942

1943

1944

1945

1946

1947

1948

1949

1950

1951

1952

1955 }

1956 if (TypeSize > FieldAlign &&

1957 llvm::isPowerOf2_64(TypeSize.getQuantity()))

1958 FieldAlign = TypeSize;

1959 }

1960 }

1961 }

1962

1963 bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() ||

1964 FieldClass->hasAttr() ||

1965 Context.getLangOpts().getClangABICompat() <=

1966 LangOptions::ClangABI::Ver15 ||

1968 Target.isOSAIX())) ||

1969 D->hasAttr();

1970

1971

1972

1973

1974

1975 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {

1976

1977

1978

1979 return AlignRequirement == AlignRequirementKind::RequiredByTypedef ||

1980 (AlignRequirement == AlignRequirementKind::RequiredByRecord &&

1981 FieldPacked);

1982 };

1983

1984

1985

1986

1987

1988

1989

1990

1991

1992

1993 CharUnits PreferredAlign = FieldAlign;

1994 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&

1995 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {

1996 auto performBuiltinTypeAlignmentUpgrade = [&](const BuiltinType *BTy) {

1997 if (BTy->getKind() == BuiltinType::Double ||

1998 BTy->getKind() == BuiltinType::LongDouble) {

2000 "No need to upgrade the alignment value.");

2002 }

2003 };

2004

2006 if (const ComplexType *CTy = BaseTy->getAs()) {

2007 performBuiltinTypeAlignmentUpgrade(

2008 CTy->getElementType()->castAs());

2009 } else if (const BuiltinType *BTy = BaseTy->getAs()) {

2010 performBuiltinTypeAlignmentUpgrade(BTy);

2011 } else if (const RecordType *RT = BaseTy->getAsCanonical()) {

2012 const RecordDecl *RD = RT->getDecl();

2013 const ASTRecordLayout &FieldRecord = Context.getASTRecordLayout(RD);

2015 }

2016 }

2017

2018

2019

2020 CharUnits UnpackedFieldAlign = FieldAlign;

2022 CharUnits UnpackedFieldOffset = FieldOffset;

2023 CharUnits OriginalFieldAlign = UnpackedFieldAlign;

2024

2025 CharUnits MaxAlignmentInChars =

2027 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);

2028 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);

2029 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);

2030

2031

2032 if (!MaxFieldAlignment.isZero()) {

2033 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);

2034 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);

2035 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);

2036 }

2037

2038

2039 if (!FieldPacked)

2040 FieldAlign = UnpackedFieldAlign;

2041 if (DefaultsToAIXPowerAlignment)

2042 UnpackedFieldAlign = PreferredAlign;

2043 if (FieldPacked) {

2044 PreferredAlign = PackedFieldAlign;

2045 FieldAlign = PackedFieldAlign;

2046 }

2047

2048 CharUnits AlignTo =

2049 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;

2050

2051 FieldOffset = FieldOffset.alignTo(AlignTo);

2052 UnpackedFieldOffset = UnpackedFieldOffset.alignTo(UnpackedFieldAlign);

2053

2054 if (UseExternalLayout) {

2056 updateExternalFieldOffset(D, Context.toBits(FieldOffset)));

2057

2058 if (!IsUnion && EmptySubobjects) {

2059

2060 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);

2061 (void)Allowed;

2062 assert(Allowed && "Externally-placed field cannot be placed here");

2063 }

2064 } else {

2065 if (!IsUnion && EmptySubobjects) {

2066

2067 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {

2068

2069

2072 FieldOffset = getDataSize().alignTo(AlignTo);

2073 else

2074 FieldOffset += AlignTo;

2075 }

2076 }

2077 }

2078

2079

2080 FieldOffsets.push_back(Context.toBits(FieldOffset));

2081

2082 if (!UseExternalLayout)

2084 Context.toBits(UnpackedFieldOffset),

2085 Context.toBits(UnpackedFieldAlign), FieldPacked, D);

2086

2087 if (InsertExtraPadding) {

2089 CharUnits ExtraSizeForAsan = ASanAlignment;

2091 ExtraSizeForAsan += ASanAlignment - (FieldSize % ASanAlignment);

2092 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;

2093 }

2094

2095

2096 if (!IsOverlappingEmptyField) {

2097 uint64_t EffectiveFieldSizeInBits = Context.toBits(EffectiveFieldSize);

2098 if (IsUnion)

2099 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));

2100 else

2101 setDataSize(FieldOffset + EffectiveFieldSize);

2102

2103 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);

2104 setSize(std::max(getSizeInBits(), getDataSizeInBits()));

2105 } else {

2106 setSize(std::max(getSizeInBits(),

2107 (uint64_t)Context.toBits(FieldOffset + FieldSize)));

2108 }

2109

2110

2111 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);

2112 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);

2113

2114

2115

2116 if (const RecordDecl *RD = D->getParent()) {

2117

2118 if (RD->hasAttr() || !MaxFieldAlignment.isZero())

2119 if (FieldAlign < OriginalFieldAlign)

2121

2122

2123

2124 if (!FieldOffset.isMultipleOf(OriginalFieldAlign))

2128 }

2129 }

2130

2131 if (Packed && !FieldPacked && PackedFieldAlign < FieldAlign)

2133}

2134

2135void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {

2136

2137 if (Context.getLangOpts().CPlusPlus && getSizeInBits() == 0) {

2138 if (const CXXRecordDecl *RD = dyn_cast(D)) {

2139

2140

2141

2142 if (RD->isEmpty())

2144 }

2145 else

2147 }

2148

2149

2150

2151 setSize(std::max(getSizeInBits(), (uint64_t)Context.toBits(PaddedFieldSize)));

2152

2153

2154

2155 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;

2156 uint64_t UnpackedSizeInBits =

2157 llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment));

2158

2159 uint64_t RoundedSize = llvm::alignTo(

2160 getSizeInBits(),

2162 ? Alignment

2163 : PreferredAlignment));

2164

2165 if (UseExternalLayout) {

2166

2167

2168

2169 if (InferAlignment && External.Size < RoundedSize) {

2172 InferAlignment = false;

2173 }

2175 return;

2176 }

2177

2178

2179 setSize(RoundedSize);

2180

2182 if (const RecordDecl *RD = dyn_cast(D)) {

2183

2184 if (getSizeInBits() > UnpaddedSize) {

2185 unsigned PadSize = getSizeInBits() - UnpaddedSize;

2186 bool InBits = true;

2187 if (PadSize % CharBitNum == 0) {

2188 PadSize = PadSize / CharBitNum;

2189 InBits = false;

2190 }

2193 << (InBits ? 1 : 0);

2194 }

2195

2196 const auto *CXXRD = dyn_cast(RD);

2197

2198

2199

2200

2201

2202

2203

2204 if (Packed && UnpackedAlignment <= Alignment &&

2205 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&

2206 (!CXXRD || CXXRD->isPOD() ||

2207 Context.getLangOpts().getClangABICompat() <=

2208 LangOptions::ClangABI::Ver15))

2211 }

2212}

2213

2214void ItaniumRecordLayoutBuilder::UpdateAlignment(

2215 CharUnits NewAlignment, CharUnits UnpackedNewAlignment,

2216 CharUnits PreferredNewAlignment) {

2217

2218

2219 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))

2220 return;

2221

2222 if (NewAlignment > Alignment) {

2223 assert(llvm::isPowerOf2_64(NewAlignment.getQuantity()) &&

2224 "Alignment not a power of 2");

2225 Alignment = NewAlignment;

2226 }

2227

2228 if (UnpackedNewAlignment > UnpackedAlignment) {

2229 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.getQuantity()) &&

2230 "Alignment not a power of 2");

2231 UnpackedAlignment = UnpackedNewAlignment;

2232 }

2233

2234 if (PreferredNewAlignment > PreferredAlignment) {

2235 assert(llvm::isPowerOf2_64(PreferredNewAlignment.getQuantity()) &&

2236 "Alignment not a power of 2");

2237 PreferredAlignment = PreferredNewAlignment;

2238 }

2239}

2240

2242ItaniumRecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,

2243 uint64_t ComputedOffset) {

2244 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);

2245

2246 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {

2247

2248

2251 InferAlignment = false;

2252 }

2253

2254

2255 return ExternalFieldOffset;

2256}

2257

2258

2259

2260

2261

2262

2264 switch (Tag) {

2266 return 0;

2268 return 1;

2270 return 2;

2271 default: llvm_unreachable("Invalid tag kind for field padding diagnostic!");

2272 }

2273}

2274

2276 uint64_t Offset, uint64_t UnpaddedOffset,

2278

2279

2281 return;

2282

2283

2284

2286 return;

2287

2288 unsigned CharBitNum = Context.getTargetInfo().getCharWidth();

2289

2290

2291 if (!IsUnion && Offset > UnpaddedOffset) {

2292 unsigned PadSize = Offset - UnpaddedOffset;

2293 bool InBits = true;

2294 if (PadSize % CharBitNum == 0) {

2295 PadSize = PadSize / CharBitNum;

2296 InBits = false;

2297 }

2300 : diag::warn_padded_struct_field;

2301 Context.getDiagnostics().Report(D->getLocation(),

2304 << Context.getCanonicalTagType(D->getParent()) << PadSize

2305 << (InBits ? 1 : 0)

2307 } else {

2309 : diag::warn_padded_struct_anon_field;

2310 Context.getDiagnostics().Report(D->getLocation(),

2313 << Context.getCanonicalTagType(D->getParent()) << PadSize

2314 << (InBits ? 1 : 0);

2315 }

2316 }

2317}

2318

2319void ItaniumRecordLayoutBuilder::CheckFieldPadding(

2320 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,

2321 unsigned UnpackedAlign, bool isPacked, const FieldDecl *D) {

2323 if (isPacked && Offset != UnpackedOffset) {

2324 HasPackedField = true;

2325 }

2326}

2327

2330

2332 return nullptr;

2333

2334

2335

2336

2338 return nullptr;

2339

2340

2341

2346 return nullptr;

2347

2348 bool allowInlineFunctions =

2349 Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline();

2350

2352 if (!MD->isVirtual())

2353 continue;

2354

2355 if (MD->isPureVirtual())

2356 continue;

2357

2358

2359

2360 if (MD->isImplicit())

2361 continue;

2362

2363 if (MD->isInlineSpecified() || MD->isConstexpr())

2364 continue;

2365

2366 if (MD->hasInlineBody())

2367 continue;

2368

2369

2370 if (!MD->isUserProvided())

2371 continue;

2372

2373

2374 if (!allowInlineFunctions) {

2377 continue;

2378 }

2379

2380 if (Context.getLangOpts().CUDA) {

2381

2382

2383

2384 if (Context.getLangOpts().CUDAIsDevice) {

2385

2386 if (!MD->hasAttr())

2387 continue;

2388 } else {

2389

2390 if (!MD->hasAttr() && MD->hasAttr())

2391 continue;

2392 }

2393 }

2394

2395

2396

2397

2398 if (MD->hasAttr() && !RD->hasAttr() &&

2399 !Context.getTargetInfo().hasPS4DLLImportExport())

2400 return nullptr;

2401

2402

2403 return MD;

2404 }

2405

2406 return nullptr;

2407}

2408

2409DiagnosticBuilder ItaniumRecordLayoutBuilder::Diag(SourceLocation Loc,

2410 unsigned DiagID) {

2412}

2413

2414

2415

2416

2420 return false;

2421

2423

2424

2425

2426

2427

2428

2429

2430

2431

2432

2433

2434

2435

2436

2437

2438

2439

2440

2441 return RD->isPOD();

2442

2444

2445

2446

2447

2448

2449

2451 }

2452

2453 llvm_unreachable("bad tail-padding use kind");

2454}

2455

2456

2457

2458

2459

2460

2461

2462

2463

2464

2465

2466

2467

2468

2469

2470

2471

2472

2473

2474

2475

2476

2477

2478

2479

2480

2481

2482

2483

2484

2485

2486

2487

2488

2489

2490

2491

2492

2493

2494

2495

2496

2497

2498

2499

2500

2501

2502

2503

2504

2505

2506

2507

2508

2509

2510

2511

2512

2513

2514

2515

2516

2517

2518

2519

2520

2521

2522

2523

2524

2525

2526

2527

2528

2529

2530

2531

2532

2533

2534

2535

2536

2537

2538

2539

2540

2541

2542

2543

2544

2545

2546namespace {

2547struct MicrosoftRecordLayoutBuilder {

2548 struct ElementInfo {

2549 CharUnits Size;

2550 CharUnits Alignment;

2551 };

2552 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;

2553 MicrosoftRecordLayoutBuilder(const ASTContext &Context,

2554 EmptySubobjectMap *EmptySubobjects)

2555 : Context(Context), EmptySubobjects(EmptySubobjects),

2556 RemainingBitsInField(0) {}

2557

2558private:

2559 MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) = delete;

2560 void operator=(const MicrosoftRecordLayoutBuilder &) = delete;

2561public:

2562 void layout(const RecordDecl *RD);

2563 void cxxLayout(const CXXRecordDecl *RD);

2564

2565 void initializeLayout(const RecordDecl *RD);

2566

2567

2568

2569 void initializeCXXLayout(const CXXRecordDecl *RD);

2570 void layoutNonVirtualBases(const CXXRecordDecl *RD);

2571 void layoutNonVirtualBase(const CXXRecordDecl *RD,

2572 const CXXRecordDecl *BaseDecl,

2573 const ASTRecordLayout &BaseLayout,

2574 const ASTRecordLayout *&PreviousBaseLayout);

2575 void injectVFPtr(const CXXRecordDecl *RD);

2576 void injectVBPtr(const CXXRecordDecl *RD);

2577

2578

2579 void layoutFields(const RecordDecl *RD);

2580 void layoutField(const FieldDecl *FD);

2581 void layoutBitField(const FieldDecl *FD);

2582

2583

2584 void layoutZeroWidthBitField(const FieldDecl *FD);

2585 void layoutVirtualBases(const CXXRecordDecl *RD);

2586 void finalizeLayout(const RecordDecl *RD);

2587

2588

2589 ElementInfo getAdjustedElementInfo(const ASTRecordLayout &Layout);

2590

2591

2592

2593 ElementInfo getAdjustedElementInfo(const FieldDecl *FD);

2594

2595 void placeFieldAtOffset(CharUnits FieldOffset) {

2596 FieldOffsets.push_back(Context.toBits(FieldOffset));

2597 }

2598

2599 void placeFieldAtBitOffset(uint64_t FieldOffset) {

2600 FieldOffsets.push_back(FieldOffset);

2601 }

2602

2603 void computeVtorDispSet(

2604 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,

2605 const CXXRecordDecl *RD) const;

2606 const ASTContext &Context;

2607 EmptySubobjectMap *EmptySubobjects;

2608

2609

2610 CharUnits Size;

2611

2612 CharUnits NonVirtualSize;

2613

2614 CharUnits DataSize;

2615

2616 CharUnits Alignment;

2617

2618 CharUnits MaxFieldAlignment;

2619

2620

2621 CharUnits RequiredAlignment;

2622

2623

2624

2625 CharUnits CurrentBitfieldSize;

2626

2627 CharUnits VBPtrOffset;

2628

2629 CharUnits MinEmptyStructSize;

2630

2631 ElementInfo PointerInfo;

2632

2633 const CXXRecordDecl *PrimaryBase;

2634

2635 const CXXRecordDecl *SharedVBPtrBase;

2636

2637 SmallVector<uint64_t, 16> FieldOffsets;

2638

2639 BaseOffsetsMapTy Bases;

2640

2642

2643 unsigned RemainingBitsInField;

2644 bool IsUnion : 1;

2645

2646

2647 bool LastFieldIsNonZeroWidthBitfield : 1;

2648

2649 bool HasOwnVFPtr : 1;

2650

2651 bool HasVBPtr : 1;

2652

2653

2654

2655 bool EndsWithZeroSizedObject : 1;

2656

2657

2658 bool LeadsWithZeroSizedBase : 1;

2659

2660

2661 bool UseExternalLayout : 1;

2662

2663

2664

2666};

2667}

2668

2669MicrosoftRecordLayoutBuilder::ElementInfo

2670MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(

2671 const ASTRecordLayout &Layout) {

2672 ElementInfo Info;

2674

2675 if (!MaxFieldAlignment.isZero())

2676 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);

2677

2679

2680

2681

2682 Alignment = std::max(Alignment, Info.Alignment);

2683 RequiredAlignment = std::max(RequiredAlignment, Layout.getRequiredAlignment());

2686 return Info;

2687}

2688

2689MicrosoftRecordLayoutBuilder::ElementInfo

2690MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(

2691 const FieldDecl *FD) {

2692

2693

2694 auto TInfo =

2696 ElementInfo Info{TInfo.Width, TInfo.Align};

2697

2698 CharUnits FieldRequiredAlignment =

2700

2702 FieldRequiredAlignment = std::max(

2704

2706

2707

2708 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);

2709 else {

2710 if (const auto *RT = FD->getType()

2715 FieldRequiredAlignment = std::max(FieldRequiredAlignment,

2717 }

2718

2719 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);

2720 }

2721

2722 if (!MaxFieldAlignment.isZero())

2723 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);

2724 if (FD->hasAttr())

2726 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);

2727 return Info;

2728}

2729

2730void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {

2731

2733 initializeLayout(RD);

2734 layoutFields(RD);

2735 DataSize = Size = Size.alignTo(Alignment);

2736 RequiredAlignment = std::max(

2738 finalizeLayout(RD);

2739}

2740

2741void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {

2742

2744 initializeLayout(RD);

2745 initializeCXXLayout(RD);

2746 layoutNonVirtualBases(RD);

2747 layoutFields(RD);

2748 injectVBPtr(RD);

2749 injectVFPtr(RD);

2750 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))

2751 Alignment = std::max(Alignment, PointerInfo.Alignment);

2752 auto RoundingAlignment = Alignment;

2753 if (!MaxFieldAlignment.isZero())

2754 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);

2755 if (!UseExternalLayout)

2756 Size = Size.alignTo(RoundingAlignment);

2757 NonVirtualSize = Size;

2758 RequiredAlignment = std::max(

2760 layoutVirtualBases(RD);

2761 finalizeLayout(RD);

2762}

2763

2764void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {

2765 IsUnion = RD->isUnion();

2768

2769

2770

2773 : CharUnits::Zero();

2774

2776

2777 if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct)

2779

2780

2781 if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr()){

2782 unsigned PackedAlignment = MFAA->getAlignment();

2783 if (PackedAlignment <=

2786 }

2787

2788 if (RD->hasAttr())

2790

2791

2792 UseExternalLayout = false;

2794 UseExternalLayout = Source->layoutRecordType(

2797

2800 if (Location.isValid())

2802 diag::err_itanium_layout_unimplemented);

2803 }

2804}

2805

2806void

2807MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) {

2808 EndsWithZeroSizedObject = false;

2809 LeadsWithZeroSizedBase = false;

2810 HasOwnVFPtr = false;

2811 HasVBPtr = false;

2812 PrimaryBase = nullptr;

2813 SharedVBPtrBase = nullptr;

2814

2815

2820

2821 if (!MaxFieldAlignment.isZero())

2822 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);

2823}

2824

2825void

2826MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) {

2827

2828

2829

2830

2831

2832

2833 const ASTRecordLayout *PreviousBaseLayout = nullptr;

2834 bool HasPolymorphicBaseClass = false;

2835

2836 for (const CXXBaseSpecifier &Base : RD->bases()) {

2837 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

2838 HasPolymorphicBaseClass |= BaseDecl->isPolymorphic();

2839 const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);

2840

2841 if (Base.isVirtual()) {

2842 HasVBPtr = true;

2843 continue;

2844 }

2845

2846 if (!SharedVBPtrBase && BaseLayout.hasVBPtr()) {

2847 SharedVBPtrBase = BaseDecl;

2848 HasVBPtr = true;

2849 }

2850

2852 continue;

2853

2854 if (!PrimaryBase) {

2855 PrimaryBase = BaseDecl;

2857 }

2858

2859 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);

2860 }

2861

2863 if (!HasPolymorphicBaseClass)

2864

2865

2866 HasOwnVFPtr = true;

2867 else if (!PrimaryBase) {

2868

2869

2870 for (CXXMethodDecl *M : RD->methods()) {

2871 if (MicrosoftVTableContext::hasVtableSlot(M) &&

2872 M->size_overridden_methods() == 0) {

2873 HasOwnVFPtr = true;

2874 break;

2875 }

2876 }

2877 }

2878 }

2879

2880

2881 bool CheckLeadingLayout = !PrimaryBase;

2882

2883 for (const CXXBaseSpecifier &Base : RD->bases()) {

2884 if (Base.isVirtual())

2885 continue;

2886 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

2887 const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);

2888

2891 continue;

2892 }

2893

2894

2895 if (CheckLeadingLayout) {

2896 CheckLeadingLayout = false;

2898 }

2899

2900 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);

2902 }

2903

2904 if (!HasVBPtr)

2906 else if (SharedVBPtrBase) {

2907 const ASTRecordLayout &Layout = Context.getASTRecordLayout(SharedVBPtrBase);

2908 VBPtrOffset = Bases[SharedVBPtrBase] + Layout.getVBPtrOffset();

2909 }

2910}

2911

2914 return false;

2915 if (RD->hasAttr())

2916 return true;

2917 if (auto *LVA = RD->getAttr())

2918

2920 return false;

2921

2922

2923

2924 return false;

2925}

2926

2927void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(

2928 const CXXRecordDecl *RD, const CXXRecordDecl *BaseDecl,

2929 const ASTRecordLayout &BaseLayout,

2930 const ASTRecordLayout *&PreviousBaseLayout) {

2931

2932

2933

2938 ElementInfo Info = getAdjustedElementInfo(BaseLayout);

2939 CharUnits BaseOffset;

2940

2941

2942 bool FoundBase = false;

2943 if (UseExternalLayout) {

2944 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);

2945 if (BaseOffset > Size) {

2946 Size = BaseOffset;

2947 }

2948 }

2949

2950 if (!FoundBase) {

2951 if (MDCUsesEBO && BaseDecl->isEmpty() &&

2954 } else {

2955

2956 BaseOffset = Size = Size.alignTo(Info.Alignment);

2957 }

2958 }

2959 Bases.insert(std::make_pair(BaseDecl, BaseOffset));

2961 DataSize = Size;

2962 PreviousBaseLayout = &BaseLayout;

2963}

2964

2965void MicrosoftRecordLayoutBuilder::layoutFields(const RecordDecl *RD) {

2966 LastFieldIsNonZeroWidthBitfield = false;

2967 for (const FieldDecl *Field : RD->fields())

2968 layoutField(Field);

2969}

2970

2971void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {

2973 layoutBitField(FD);

2974 return;

2975 }

2976 LastFieldIsNonZeroWidthBitfield = false;

2977 ElementInfo Info = getAdjustedElementInfo(FD);

2978 Alignment = std::max(Alignment, Info.Alignment);

2979

2982 FieldClass->isEmpty() &&

2983 FieldClass->fields().empty();

2985

2986 if (UseExternalLayout) {

2987 FieldOffset =

2989 } else if (IsUnion) {

2991 } else if (EmptySubobjects) {

2992 if (!IsOverlappingEmptyField)

2993 FieldOffset = DataSize.alignTo(Info.Alignment);

2994

2995 while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {

2997 bool HasBases = ParentClass && (!ParentClass->bases().empty() ||

2998 !ParentClass->vbases().empty());

3000 HasBases) {

3001

3002

3003 FieldOffset = DataSize.alignTo(Info.Alignment);

3004 } else {

3005 FieldOffset += Info.Alignment;

3006 }

3007 }

3008 } else {

3009 FieldOffset = Size.alignTo(Info.Alignment);

3010 }

3011

3012 uint64_t UnpaddedFielddOffsetInBits =

3013 Context.toBits(DataSize) - RemainingBitsInField;

3014

3016 UnpaddedFielddOffsetInBits, FD);

3017

3018 RemainingBitsInField = 0;

3019

3020 placeFieldAtOffset(FieldOffset);

3021

3022 if (!IsOverlappingEmptyField)

3023 DataSize = std::max(DataSize, FieldOffset + Info.Size);

3024

3025 Size = std::max(Size, FieldOffset + Info.Size);

3026}

3027

3028void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {

3030 if (Width == 0) {

3031 layoutZeroWidthBitField(FD);

3032 return;

3033 }

3034 ElementInfo Info = getAdjustedElementInfo(FD);

3035

3036

3037 if (Width > Context.toBits(Info.Size))

3038 Width = Context.toBits(Info.Size);

3039

3040

3041

3042 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&

3043 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {

3044 placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField);

3045 RemainingBitsInField -= Width;

3046 return;

3047 }

3048 LastFieldIsNonZeroWidthBitfield = true;

3049 CurrentBitfieldSize = Info.Size;

3050 if (UseExternalLayout) {

3051 auto FieldBitOffset = External.getExternalFieldOffset(FD);

3052 placeFieldAtBitOffset(FieldBitOffset);

3054 llvm::alignDown(FieldBitOffset, Context.toBits(Info.Alignment)) +

3055 Context.toBits(Info.Size));

3056 Size = std::max(Size, NewSize);

3057 Alignment = std::max(Alignment, Info.Alignment);

3058 } else if (IsUnion) {

3060 Size = std::max(Size, Info.Size);

3061

3062 } else {

3063

3064 CharUnits FieldOffset = Size.alignTo(Info.Alignment);

3065 uint64_t UnpaddedFieldOffsetInBits =

3066 Context.toBits(DataSize) - RemainingBitsInField;

3067 placeFieldAtOffset(FieldOffset);

3068 Size = FieldOffset + Info.Size;

3069 Alignment = std::max(Alignment, Info.Alignment);

3070 RemainingBitsInField = Context.toBits(Info.Size) - Width;

3072 UnpaddedFieldOffsetInBits, FD);

3073 }

3074 DataSize = Size;

3075}

3076

3077void

3078MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) {

3079

3080

3081 if (!LastFieldIsNonZeroWidthBitfield) {

3083

3084

3085 return;

3086 }

3087 LastFieldIsNonZeroWidthBitfield = false;

3088 ElementInfo Info = getAdjustedElementInfo(FD);

3089 if (IsUnion) {

3091 Size = std::max(Size, Info.Size);

3092

3093 } else {

3094

3095 CharUnits FieldOffset = Size.alignTo(Info.Alignment);

3096 uint64_t UnpaddedFieldOffsetInBits =

3097 Context.toBits(DataSize) - RemainingBitsInField;

3098 placeFieldAtOffset(FieldOffset);

3099 RemainingBitsInField = 0;

3100 Size = FieldOffset;

3101 Alignment = std::max(Alignment, Info.Alignment);

3103 UnpaddedFieldOffsetInBits, FD);

3104 }

3105 DataSize = Size;

3106}

3107

3108void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) {

3109 if (!HasVBPtr || SharedVBPtrBase)

3110 return;

3111

3112 CharUnits InjectionSite = VBPtrOffset;

3113

3114 VBPtrOffset = VBPtrOffset.alignTo(PointerInfo.Alignment);

3115

3116 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;

3117

3118

3119 if (UseExternalLayout) {

3120

3121

3122 if (Size < FieldStart)

3123 Size = FieldStart;

3124 return;

3125 }

3126

3127

3128 CharUnits Offset = (FieldStart - InjectionSite)

3129 .alignTo(std::max(RequiredAlignment, Alignment));

3130 Size += Offset;

3131 for (uint64_t &FieldOffset : FieldOffsets)

3132 FieldOffset += Context.toBits(Offset);

3133 for (BaseOffsetsMapTy::value_type &Base : Bases)

3134 if (Base.second >= InjectionSite)

3135 Base.second += Offset;

3136}

3137

3138void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) {

3139 if (!HasOwnVFPtr)

3140 return;

3141

3142

3143 CharUnits Offset =

3144 PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment));

3145

3146

3147 if (HasVBPtr)

3148 VBPtrOffset += Offset;

3149

3150 if (UseExternalLayout) {

3151

3152

3153 if (Size.isZero())

3154 Size += Offset;

3155 return;

3156 }

3157

3158 Size += Offset;

3159

3160

3161

3162 for (uint64_t &FieldOffset : FieldOffsets)

3163 FieldOffset += Context.toBits(Offset);

3164 for (BaseOffsetsMapTy::value_type &Base : Bases)

3165 Base.second += Offset;

3166}

3167

3168void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {

3169 if (!HasVBPtr)

3170 return;

3171

3173 CharUnits VtorDispAlignment = VtorDispSize;

3174

3175 if (!MaxFieldAlignment.isZero())

3176 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);

3177

3178

3179

3180 for (const CXXBaseSpecifier &VBase : RD->vbases()) {

3181 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();

3182 const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);

3183 RequiredAlignment =

3185 }

3186 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);

3187

3188 llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;

3189 computeVtorDispSet(HasVtorDispSet, RD);

3190

3191 const ASTRecordLayout *PreviousBaseLayout = nullptr;

3192 for (const CXXBaseSpecifier &VBase : RD->vbases()) {

3193 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();

3194 const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);

3195 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);

3196

3197

3198

3199

3200

3203 HasVtordisp) {

3204 Size = Size.alignTo(VtorDispAlignment) + VtorDispSize;

3205 Alignment = std::max(VtorDispAlignment, Alignment);

3206 }

3207

3208 ElementInfo Info = getAdjustedElementInfo(BaseLayout);

3209 CharUnits BaseOffset;

3210

3211

3212 if (UseExternalLayout) {

3213 if (External.getExternalVBaseOffset(BaseDecl, BaseOffset))

3214 BaseOffset = Size;

3215 } else

3216 BaseOffset = Size.alignTo(Info.Alignment);

3217

3218 assert(BaseOffset >= Size && "base offset already allocated");

3219

3220 VBases.insert(std::make_pair(BaseDecl,

3221 ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));

3223 PreviousBaseLayout = &BaseLayout;

3224 }

3225}

3226

3227void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {

3228 uint64_t UnpaddedSizeInBits = Context.toBits(DataSize);

3229 UnpaddedSizeInBits -= RemainingBitsInField;

3230

3231

3232

3233 if (Size.isZero())

3234 UnpaddedSizeInBits += 8;

3235

3236

3237

3238 DataSize = Size;

3239 if (!RequiredAlignment.isZero()) {

3240 Alignment = std::max(Alignment, RequiredAlignment);

3241 auto RoundingAlignment = Alignment;

3242 if (!MaxFieldAlignment.isZero())

3243 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);

3244 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);

3245 Size = Size.alignTo(RoundingAlignment);

3246 }

3247 if (Size.isZero()) {

3249 EndsWithZeroSizedObject = true;

3250 LeadsWithZeroSizedBase = true;

3251 }

3252

3253

3254 if (RequiredAlignment >= MinEmptyStructSize)

3255 Size = Alignment;

3256 else

3257 Size = MinEmptyStructSize;

3258 }

3259

3260 if (UseExternalLayout) {

3264 return;

3265 }

3268

3269 if (SizeInBits > UnpaddedSizeInBits) {

3270 unsigned int PadSize = SizeInBits - UnpaddedSizeInBits;

3271 bool InBits = true;

3272 if (PadSize % CharBitNum == 0) {

3273 PadSize = PadSize / CharBitNum;

3274 InBits = false;

3275 }

3276

3278 diag::warn_padded_struct_size)

3280 << (InBits ? 1 : 0);

3281 }

3282}

3283

3284

3285

3286static bool

3288 BasesWithOverriddenMethods,

3290 if (BasesWithOverriddenMethods.count(RD))

3291 return true;

3292

3293

3295 if (Base.isVirtual() &&

3297 Base.getType()->getAsCXXRecordDecl()))

3298 return true;

3299 return false;

3300}

3301

3302void MicrosoftRecordLayoutBuilder::computeVtorDispSet(

3303 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,

3304 const CXXRecordDecl *RD) const {

3305

3306

3308 for (const CXXBaseSpecifier &Base : RD->vbases()) {

3309 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

3310 const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);

3312 HasVtordispSet.insert(BaseDecl);

3313 }

3314 return;

3315 }

3316

3317

3318

3319 for (const CXXBaseSpecifier &Base : RD->bases()) {

3320 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

3321 const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);

3323 if (bi.second.hasVtorDisp())

3324 HasVtordispSet.insert(bi.first);

3325 }

3326

3327

3328

3331 return;

3332

3333

3334

3335 assert(RD->getMSVtorDispMode() == MSVtorDispMode::ForVBaseOverride);

3336

3337

3338

3339

3340 llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;

3341 llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;

3342

3343 for (const CXXMethodDecl *MD : RD->methods())

3344 if (MicrosoftVTableContext::hasVtableSlot(MD) &&

3346 Work.insert(MD);

3347 while (!Work.empty()) {

3348 const CXXMethodDecl *MD = *Work.begin();

3350

3351 if (MethodRange.begin() == MethodRange.end())

3352 BasesWithOverriddenMethods.insert(MD->getParent());

3353 else

3354 Work.insert_range(MethodRange);

3355

3356 Work.erase(MD);

3357 }

3358

3359

3360 for (const CXXBaseSpecifier &Base : RD->vbases()) {

3361 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

3362 if (!HasVtordispSet.count(BaseDecl) &&

3364 HasVtordispSet.insert(BaseDecl);

3365 }

3366}

3367

3372

3373

3374

3375

3380

3382

3383

3384

3385

3386

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

3389 assert(!D->isInvalidDecl() && "Cannot get layout of invalid decl!");

3391

3392

3393

3394

3396 if (Entry) return *Entry;

3397

3399

3400 if (getTargetInfo().hasMicrosoftRecordLayout()) {

3401 if (const auto *RD = dyn_cast(D)) {

3402 EmptySubobjectMap EmptySubobjects(*this, RD);

3403 MicrosoftRecordLayoutBuilder Builder(*this, &EmptySubobjects);

3404 Builder.cxxLayout(RD);

3406 *this, Builder.Size, Builder.Alignment, Builder.Alignment,

3407 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,

3408 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,

3409 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,

3410 Builder.Alignment, Builder.Alignment, CharUnits::Zero(),

3411 Builder.PrimaryBase, false, Builder.SharedVBPtrBase,

3412 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,

3413 Builder.Bases, Builder.VBases);

3414 } else {

3415 MicrosoftRecordLayoutBuilder Builder(*this, nullptr);

3416 Builder.layout(D);

3418 *this, Builder.Size, Builder.Alignment, Builder.Alignment,

3419 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,

3420 Builder.FieldOffsets);

3421 }

3422 } else {

3423 if (const auto *RD = dyn_cast(D)) {

3424 EmptySubobjectMap EmptySubobjects(*this, RD);

3425 ItaniumRecordLayoutBuilder Builder(*this, &EmptySubobjects);

3426 Builder.Layout(RD);

3427

3428

3429

3430

3431 bool skipTailPadding =

3433

3434

3436 skipTailPadding ? Builder.getSize() : Builder.getDataSize();

3438 skipTailPadding ? DataSize : Builder.NonVirtualSize;

3440 *this, Builder.getSize(), Builder.Alignment,

3441 Builder.PreferredAlignment, Builder.UnadjustedAlignment,

3442

3443 Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(),

3445 NonVirtualSize, Builder.NonVirtualAlignment,

3446 Builder.PreferredNVAlignment,

3447 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,

3448 Builder.PrimaryBaseIsVirtual, nullptr, false, false, Builder.Bases,

3449 Builder.VBases);

3450 } else {

3451 ItaniumRecordLayoutBuilder Builder(*this, nullptr);

3452 Builder.Layout(D);

3453

3455 *this, Builder.getSize(), Builder.Alignment,

3456 Builder.PreferredAlignment, Builder.UnadjustedAlignment,

3457

3458 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);

3459 }

3460 }

3461

3462 ASTRecordLayouts[D] = NewEntry;

3463

3464 constexpr uint64_t MaxStructSizeInBytes = 1ULL << 60;

3466 if (static_cast<uint64_t>(StructSize.getQuantity()) >= MaxStructSizeInBytes) {

3468 << D->getName() << MaxStructSizeInBytes;

3469 }

3470

3472 llvm::outs() << "\n*** Dumping AST Record Layout\n";

3474 }

3475

3476 return *NewEntry;

3477}

3478

3480 if (getTargetInfo().getCXXABI().hasKeyFunctions())

3481 return nullptr;

3482

3483 assert(RD->getDefinition() && "Cannot get key function for forward decl!");

3485

3486

3487

3488

3489

3490

3494

3495

3497 KeyFunctions[RD] = const_cast<Decl*>(Result);

3498

3499 return cast_or_null(Result);

3500}

3501

3504 "not working with method declaration from class definition");

3505

3506

3507

3508

3509 const auto &Map = KeyFunctions;

3510 auto I = Map.find(Method->getParent());

3511

3512

3513 if (I == Map.end()) return;

3514

3515

3516

3517

3520

3521 KeyFunctions.erase(Method->getParent());

3522 }

3523}

3524

3529

3531 uint64_t OffsetInBits;

3532 if (const FieldDecl *FD = dyn_cast(VD)) {

3534 } else {

3536

3537 OffsetInBits = 0;

3540 }

3541

3542 return OffsetInBits;

3543}

3544

3550

3551

3552

3553

3554

3555

3556 unsigned Index = 0;

3557

3560 if (Ivar == IVD)

3561 break;

3562 ++Index;

3563 }

3564 assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!");

3565

3567}

3568

3569

3570

3571

3572

3573

3576

3578 getExternalSource()->CompleteType(const_cast<ObjCInterfaceDecl*>(D));

3581 "Invalid interface decl!");

3582

3583

3585 return *Entry;

3586

3587 ItaniumRecordLayoutBuilder Builder(*this, nullptr);

3588 Builder.Layout(D);

3589

3591 *this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,

3592 Builder.UnadjustedAlignment,

3593

3594 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);

3595

3596 ObjCLayouts[D] = NewEntry;

3597

3598 return *NewEntry;

3599}

3600

3603 OS << llvm::format("%10" PRId64 " | ", (int64_t)Offset.getQuantity());

3605}

3606

3608 unsigned Begin, unsigned Width,

3611 {

3612 llvm::raw_svector_ostream BufferOS(Buffer);

3613 BufferOS << Offset.getQuantity() << ':';

3614 if (Width == 0) {

3615 BufferOS << '-';

3616 } else {

3617 BufferOS << Begin << '-' << (Begin + Width - 1);

3618 }

3619 }

3620

3621 OS << llvm::right_justify(Buffer, 10) << " | ";

3623}

3624

3629

3634 const char* Description,

3635 bool PrintSizeInfo,

3636 bool IncludeVirtualBases) {

3638 auto CXXRD = dyn_cast(RD);

3639

3641 OS << C.getCanonicalTagType(const_cast<RecordDecl *>(RD));

3642 if (Description)

3643 OS << ' ' << Description;

3644 if (CXXRD && CXXRD->isEmpty())

3645 OS << " (empty)";

3646 OS << '\n';

3647

3649

3650

3651 if (CXXRD) {

3653 bool HasOwnVFPtr = Layout.hasOwnVFPtr();

3654 bool HasOwnVBPtr = Layout.hasOwnVBPtr();

3655

3656

3657 if (CXXRD->isDynamicClass() && !PrimaryBase &&

3658 C.getTargetInfo().hasMicrosoftRecordLayout()) {

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

3661 } else if (HasOwnVFPtr) {

3663

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

3665 }

3666

3667

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

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

3672 if (Base.isVirtual())

3673 Bases.push_back(Base.getType()->getAsCXXRecordDecl());

3674 }

3675

3676

3677 llvm::stable_sort(

3680 });

3681

3682

3686 Base == PrimaryBase ? "(primary base)" : "(base)",

3687 false,

3688 false);

3689 }

3690

3691

3692 if (HasOwnVBPtr) {

3694 OS << '(' << *RD << " vbtable pointer)\n";

3695 }

3696 }

3697

3698

3700 uint64_t LocalFieldOffsetInBits =

3703 Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits);

3704

3705

3706 if (const auto *RD = Field->getType()->getAsRecordDecl()) {

3708 Field->getName().data(),

3709 false,

3710 true);

3711 continue;

3712 }

3713

3714 if (Field->isBitField()) {

3715 uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset);

3716 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;

3717 unsigned Width = Field->getBitWidthValue();

3719 } else {

3721 }

3722 const QualType &FieldType = C.getLangOpts().DumpRecordLayoutsCanonical

3723 ? Field->getType().getCanonicalType()

3724 : Field->getType();

3725 OS << FieldType << ' ' << *Field << '\n';

3726 }

3727

3728

3729 if (CXXRD && IncludeVirtualBases) {

3732

3734 assert(Base.isVirtual() && "Found non-virtual class!");

3735 const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();

3736

3738

3739 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {

3741 OS << "(vtordisp for vbase " << *VBase << ")\n";

3742 }

3743

3746 "(primary virtual base)" : "(virtual base)",

3747 false,

3748 false);

3749 }

3750 }

3751

3752 if (!PrintSizeInfo) return;

3753

3756 if (CXXRD && C.getTargetInfo().hasMicrosoftRecordLayout())

3759 if (C.getTargetInfo().defaultsToAIXPowerAlignment())

3761

3762 if (CXXRD) {

3763 OS << ",\n";

3767 if (C.getTargetInfo().defaultsToAIXPowerAlignment())

3768 OS << ", preferrednvalign="

3770 }

3771 OS << "]\n";

3772}

3773

3775 bool Simple) const {

3776 if (!Simple) {

3778 true,

3779 true);

3780 return;

3781 }

3782

3783

3784

3785

3786

3787

3788

3789

3792 OS << "\nLayout: ";

3793 OS << "<ASTRecordLayout\n";

3794 OS << " Size:" << toBits(Info.getSize()) << "\n";

3795 if (getTargetInfo().hasMicrosoftRecordLayout())

3798 if (Target->defaultsToAIXPowerAlignment())

3800 << "\n";

3801 if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) {

3802 OS << " BaseOffsets: [";

3804 for (auto I : CXXRD->bases()) {

3805 if (I.isVirtual())

3806 continue;

3808 OS << ", ";

3809 Base = I.getType()->getAsCXXRecordDecl();

3810 OS << Info.CXXInfo->BaseOffsets[Base].getQuantity();

3811 }

3812 OS << "]>\n";

3813 OS << " VBaseOffsets: [";

3815 for (auto I : CXXRD->vbases()) {

3816 if (VBase)

3817 OS << ", ";

3818 VBase = I.getType()->getAsCXXRecordDecl();

3819 OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();

3820 }

3821 OS << "]>\n";

3822 }

3823 OS << " FieldOffsets: [";

3824 for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) {

3825 if (i)

3826 OS << ", ";

3828 }

3829 OS << "]>\n";

3830}

Defines the clang::ASTContext interface.

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

unsigned IndentLevel

The indent level of this token. Copied from the surrounding line.

static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)

Produce a diagnostic highlighting some portion of a literal.

static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target)

llvm::MachO::Target Target

static const CXXMethodDecl * computeKeyFunction(ASTContext &Context, const CXXRecordDecl *RD)

Definition RecordLayoutBuilder.cpp:2328

static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD)

Does the target C++ ABI require us to skip over the tail-padding of the given class (considering it a...

Definition RecordLayoutBuilder.cpp:2417

static bool isAIXLayout(const ASTContext &Context)

Definition RecordLayoutBuilder.cpp:1528

static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel)

Definition RecordLayoutBuilder.cpp:3625

static uint64_t roundUpSizeToCharAlignment(uint64_t Size, const ASTContext &Context)

Definition RecordLayoutBuilder.cpp:1452

static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel)

Definition RecordLayoutBuilder.cpp:3601

static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)

Get diagnostic select index for tag kind for field padding diagnostic message.

Definition RecordLayoutBuilder.cpp:2263

static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, const ASTContext &C, CharUnits Offset, unsigned IndentLevel, const char *Description, bool PrintSizeInfo, bool IncludeVirtualBases)

Definition RecordLayoutBuilder.cpp:3630

static void CheckFieldPadding(const ASTContext &Context, bool IsUnion, uint64_t Offset, uint64_t UnpaddedOffset, const FieldDecl *D)

Definition RecordLayoutBuilder.cpp:2275

static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)

Definition RecordLayoutBuilder.cpp:3525

static bool RequiresVtordisp(const llvm::SmallPtrSetImpl< const CXXRecordDecl * > &BasesWithOverriddenMethods, const CXXRecordDecl *RD)

Definition RecordLayoutBuilder.cpp:3287

static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset, unsigned Begin, unsigned Width, unsigned IndentLevel)

Definition RecordLayoutBuilder.cpp:3607

static bool recordUsesEBO(const RecordDecl *RD)

Definition RecordLayoutBuilder.cpp:2912

uint64_t getFieldOffset(const ValueDecl *FD) const

Get the offset of a FieldDecl or IndirectFieldDecl, in bits.

Definition RecordLayoutBuilder.cpp:3530

const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const

Get or compute information about the layout of the specified record (struct/union/class) D,...

Definition RecordLayoutBuilder.cpp:3377

void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple=false) const

Definition RecordLayoutBuilder.cpp:3774

bool defaultsToMsStruct() const

Return whether unannotated records are treated as if they have [[gnu::ms_struct]].

Definition RecordLayoutBuilder.cpp:3368

const CXXMethodDecl * getCurrentKeyFunction(const CXXRecordDecl *RD)

Get our current best idea for the key function of the given record decl, or nullptr if there isn't on...

Definition RecordLayoutBuilder.cpp:3479

uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID, const ObjCIvarDecl *Ivar) const

Get the offset of an ObjCIvarDecl in bits.

Definition RecordLayoutBuilder.cpp:3545

void setNonKeyFunction(const CXXMethodDecl *method)

Observe that the given method cannot be a key function.

Definition RecordLayoutBuilder.cpp:3502

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

const ConstantArrayType * getAsConstantArrayType(QualType T) const

CharUnits getTypeAlignInChars(QualType T) const

Return the ABI-specified alignment of a (complete) type T, in characters.

const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const

Get or compute information about the layout of the specified record (struct/union/class) D,...

Definition RecordLayoutBuilder.cpp:3377

const LangOptions & getLangOpts() const

const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const

Get or compute information about the layout of the specified Objective-C interface.

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

bool isNearlyEmpty(const CXXRecordDecl *RD) const

friend class CXXRecordDecl

CanQualType UnsignedLongTy

TypeInfo getTypeInfo(const Type *T) const

Get the size and alignment of the specified complete type in bits.

bool isAlignmentRequired(const Type *T) const

Determine if the alignment the type has was required using an alignment attribute.

TypeInfoChars getTypeInfoInChars(const Type *T) const

int64_t toBits(CharUnits CharSize) const

Convert a size in characters to a size in bits.

uint64_t getTypeSize(QualType T) const

Return the size of the specified (complete) type T, in bits.

CanQualType UnsignedInt128Ty

CharUnits getTypeSizeInChars(QualType T) const

Return the size of the specified (complete) type T, in characters.

CanQualType UnsignedCharTy

CanQualType UnsignedIntTy

CanQualType UnsignedLongLongTy

CanQualType UnsignedShortTy

DiagnosticsEngine & getDiagnostics() const

const TargetInfo & getTargetInfo() const

CharUnits toCharUnitsFromBits(int64_t BitSize) const

Convert a size in bits to a size in characters.

ExternalASTSource * getExternalSource() const

Retrieve a pointer to the external AST source associated with this AST context, if any.

uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const

Return number of constant array elements.

CanQualType getCanonicalTagType(const TagDecl *TD) const

uint64_t getCharWidth() const

Return the size of the character type, in bits.

ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...

bool endsWithZeroSizedObject() const

bool hasOwnVFPtr() const

hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...

CharUnits getAlignment() const

getAlignment - Get the record alignment in characters.

CharUnits getPreferredAlignment() const

getPreferredFieldAlignment - Get the record preferred alignment in characters.

bool hasOwnVBPtr() const

hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...

llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy

CharUnits getSize() const

getSize - Get the record size in characters.

unsigned getFieldCount() const

getFieldCount - Get the number of fields in the layout.

bool hasVBPtr() const

hasVBPtr - Does this class have a virtual function table pointer.

bool leadsWithZeroSizedBase() const

uint64_t getFieldOffset(unsigned FieldNo) const

getFieldOffset - Get the offset of the given field index, in bits.

CharUnits getNonVirtualAlignment() const

getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an object, which is the alignmen...

CharUnits getVBPtrOffset() const

getVBPtrOffset - Get the offset for virtual base table pointer.

CharUnits getDataSize() const

getDataSize() - Get the record data size, which is the record size without tail padding,...

CharUnits getRequiredAlignment() const

CharUnits getSizeOfLargestEmptySubobject() const

CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const

getBaseClassOffset - Get the offset, in chars, for the given base class.

CharUnits getPreferredNVAlignment() const

getPreferredNVAlignment - Get the preferred non-virtual alignment (in chars) of an object,...

CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const

getVBaseClassOffset - Get the offset, in chars, for the given base class.

const VBaseOffsetsMapTy & getVBaseOffsetsMap() const

const CXXRecordDecl * getPrimaryBase() const

getPrimaryBase - Get the primary base for this record.

bool hasExtendableVFPtr() const

hasVFPtr - Does this class have a virtual function table pointer that can be extended by a derived cl...

bool isPrimaryBaseVirtual() const

isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.

CharUnits getNonVirtualSize() const

getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...

Represents a base class of a C++ class.

Represents a static or instance method of a struct/union/class.

overridden_method_range overridden_methods() const

const CXXRecordDecl * getParent() const

Return the parent of this method declaration, which is the class in which this method is defined.

Represents a C++ struct/union/class.

void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const

Get the indirect primary bases for this class.

bool hasUserDeclaredDestructor() const

Determine whether this class has a user-declared destructor.

method_range methods() const

CXXRecordDecl * getDefinition() const

bool isPolymorphic() const

Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...

TemplateSpecializationKind getTemplateSpecializationKind() const

Determine whether this particular class is a specialization or instantiation of a class template or m...

base_class_range vbases()

bool isDynamicClass() const

bool isCXX11StandardLayout() const

Determine whether this class was standard-layout per C++11 [class]p7, specifically using the C++11 ru...

bool hasUserDeclaredConstructor() const

Determine whether this class has any user-declared constructors.

bool isPOD() const

Whether this class is a POD-type (C++ [class]p4)

MSVtorDispMode getMSVtorDispMode() const

Controls when vtordisps will be emitted if this record is used as a virtual base.

bool isEmpty() const

Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).

bool isTrivial() const

Determine whether this class is considered trivial.

unsigned getNumVBases() const

Retrieves the number of virtual base classes of this class.

CharUnits - This is an opaque type for sizes expressed in character units.

bool isZero() const

isZero - Test whether the quantity equals zero.

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

static CharUnits One()

One - Construct a CharUnits quantity of one.

bool isMultipleOf(CharUnits N) const

Test whether this is a multiple of the other value.

static CharUnits fromQuantity(QuantityType Quantity)

fromQuantity - Construct a CharUnits quantity from a raw integer type.

CharUnits alignTo(const CharUnits &Align) const

alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...

static CharUnits Zero()

Zero - Construct a CharUnits quantity of zero.

lookup_result lookup(DeclarationName Name) const

lookup - Find the declarations (if any) with the given Name in this context.

bool hasExternalLexicalStorage() const

Whether this DeclContext has external storage containing additional declarations that are lexically i...

Decl - This represents one declaration (or definition), e.g.

unsigned getMaxAlignment() const

getMaxAlignment - return the maximum alignment specified by attributes on this decl,...

bool isInvalidDecl() const

SourceLocation getLocation() const

A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine a...

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

Represents a member of a struct/union/class.

bool isBitField() const

Determines whether this field is a bitfield.

unsigned getBitWidthValue() const

Computes the bit width of this field, if this is a bit field.

unsigned getFieldIndex() const

Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...

const RecordDecl * getParent() const

Returns the parent of this field declaration, which is the struct in which this field is defined.

bool isPotentiallyOverlapping() const

Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...

Represents a function declaration or definition.

bool isInlineSpecified() const

Determine whether the "inline" keyword was specified for this function.

Represents a field injected from an anonymous union/struct into the parent scope.

ArrayRef< NamedDecl * > chain() const

This represents a decl that may have a name.

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

bool isExternallyVisible() const

Represents an ObjC class declaration.

ObjCIvarDecl * all_declared_ivar_begin()

all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...

bool isThisDeclarationADefinition() const

Determine whether this particular declaration of this class is actually also a definition.

ObjCInterfaceDecl * getSuperClass() const

ObjCInterfaceDecl * getDefinition()

Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...

ObjCIvarDecl - Represents an ObjC instance variable.

ObjCInterfaceDecl * getContainingInterface()

Return the class interface that this ivar is logically contained in; this is either the interface whe...

ObjCIvarDecl * getNextIvar()

ObjCIvarDecl * getCanonicalDecl() override

Retrieves the canonical declaration of this field.

A (possibly-)qualified type.

Represents a struct/union/class.

bool isMsStruct(const ASTContext &C) const

Get whether or not this is an ms_struct which can be turned on with an attribute, pragma,...

bool hasFlexibleArrayMember() const

field_iterator field_end() const

field_range fields() const

bool mayInsertExtraPadding(bool EmitRemark=false) const

Whether we are allowed to insert extra padding between fields.

RecordDecl * getMostRecentDecl()

RecordDecl * getDefinition() const

Returns the RecordDecl that actually defines this struct/union/class.

field_iterator field_begin() const

bool isCompleteDefinition() const

Return true if this decl has its body fully specified.

TagKind getTagKind() const

The basic abstraction for the target C++ ABI.

TailPaddingUseRules getTailPaddingUseRules() const

@ AlwaysUseTailPadding

The tail-padding of a base class is always theoretically available, even if it's POD.

@ UseTailPaddingUnlessPOD11

Only allocate objects in the tail padding of a base class if the base class is not POD according to t...

@ UseTailPaddingUnlessPOD03

Only allocate objects in the tail padding of a base class if the base class is not POD according to t...

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

bool useLeadingZeroLengthBitfield() const

Check whether zero length bitfield alignment is respected if they are leading members.

uint64_t getPointerWidth(LangAS AddrSpace) const

Return the width of pointers on this target, for the specified address space.

unsigned getLargestOverSizedBitfieldContainer() const

virtual bool defaultsToAIXPowerAlignment() const

Whether target defaults to the power alignment rules of AIX.

unsigned getCharAlign() const

unsigned getZeroLengthBitfieldBoundary() const

Get the fixed alignment value in bits for a member that follows a zero length bitfield.

bool useExplicitBitFieldAlignment() const

Check whether explicit bitfield alignment attributes should be.

uint64_t getPointerAlign(LangAS AddrSpace) const

TargetCXXABI getCXXABI() const

Get the C++ ABI currently in use.

unsigned getCharWidth() const

bool useZeroLengthBitfieldAlignment() const

Check whether zero length bitfields should force alignment of the next member.

bool useBitFieldTypeAlignment() const

Check whether the alignment of bit-field types is respected when laying out structures.

bool isIncompleteArrayType() const

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

const Type * getBaseElementTypeUnsafe() const

Get the base element type of this type, potentially discarding type qualifiers.

const T * getAsCanonical() const

If this type is canonically the specified type, return its canonical type cast to that specified type...

const T * getAs() const

Member-template getAs'.

const Type * getUnqualifiedDesugaredType() const

Return the specified type with any "sugar" removed from the type, removing any typedefs,...

bool isRecordType() const

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

Defines the clang::TargetInfo interface.

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

LazyOffsetPtr< Decl, GlobalDeclID, &ExternalASTSource::GetExternalDecl > LazyDeclPtr

A lazy pointer to a declaration.

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

@ External

External linkage, which indicates that the entity can be referred to from other translation units.

@ Result

The result type of a method or function.

const FunctionProtoType * T

TagTypeKind

The kind of a tag type.

@ Interface

The "__interface" keyword.

@ Struct

The "struct" keyword.

@ Class

The "class" keyword.

@ Type

The name was classified as a type.

TemplateSpecializationKind

Describes the kind of template specialization that a particular template specialization declaration r...

@ TSK_ExplicitInstantiationDefinition

This template specialization was instantiated from a template due to an explicit instantiation defini...

@ TSK_ExplicitInstantiationDeclaration

This template specialization was instantiated from a template due to an explicit instantiation declar...

@ TSK_ImplicitInstantiation

This template specialization was implicitly instantiated from a template.

U cast(CodeGen::Address addr)

@ Class

The "class" keyword introduces the elaborated-type-specifier.

bool isValid() const

Whether this pointer is non-NULL.

bool isOffset() const

Whether this pointer is currently stored as an offset.

T * get(ExternalASTSource *Source) const

Retrieve the pointer to the AST node that this lazy pointer points to.