1a7dea167SDimitry Andric //===--- Record.h - struct and class metadata for the VM --------*- C++ -*-===// 2a7dea167SDimitry Andric // 3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric // 9a7dea167SDimitry Andric // A record is part of a program to describe the layout and methods of a struct. 10a7dea167SDimitry Andric // 11a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 12a7dea167SDimitry Andric 13a7dea167SDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_RECORD_H 14a7dea167SDimitry Andric #define LLVM_CLANG_AST_INTERP_RECORD_H 15a7dea167SDimitry Andric 16bdd1243dSDimitry Andric #include "Descriptor.h" 17bdd1243dSDimitry Andric #include "clang/AST/Decl.h" 18bdd1243dSDimitry Andric #include "clang/AST/DeclCXX.h" 19a7dea167SDimitry Andric 20a7dea167SDimitry Andric namespace clang { 21a7dea167SDimitry Andric namespace interp { 22a7dea167SDimitry Andric class Program; 23a7dea167SDimitry Andric 24a7dea167SDimitry Andric /// Structure/Class descriptor. 25bdd1243dSDimitry Andric class Record final { 26a7dea167SDimitry Andric public: 27a7dea167SDimitry Andric /// Describes a record field. 28a7dea167SDimitry Andric struct Field { 29a7dea167SDimitry Andric const FieldDecl *Decl; 30a7dea167SDimitry Andric unsigned Offset; 31*0fca6ea1SDimitry Andric const Descriptor *Desc; 325f757f3fSDimitry Andric bool isBitField() const { return Decl->isBitField(); } 33a7dea167SDimitry Andric }; 34a7dea167SDimitry Andric 35a7dea167SDimitry Andric /// Describes a base class. 36a7dea167SDimitry Andric struct Base { 37a7dea167SDimitry Andric const RecordDecl *Decl; 38a7dea167SDimitry Andric unsigned Offset; 39*0fca6ea1SDimitry Andric const Descriptor *Desc; 40*0fca6ea1SDimitry Andric const Record *R; 41a7dea167SDimitry Andric }; 42a7dea167SDimitry Andric 43a7dea167SDimitry Andric /// Mapping from identifiers to field descriptors. 44a7dea167SDimitry Andric using FieldList = llvm::SmallVector<Field, 8>; 45a7dea167SDimitry Andric /// Mapping from identifiers to base classes. 46a7dea167SDimitry Andric using BaseList = llvm::SmallVector<Base, 8>; 47a7dea167SDimitry Andric /// List of virtual base classes. 48a7dea167SDimitry Andric using VirtualBaseList = llvm::SmallVector<Base, 2>; 49a7dea167SDimitry Andric 50a7dea167SDimitry Andric public: 51a7dea167SDimitry Andric /// Returns the underlying declaration. 52a7dea167SDimitry Andric const RecordDecl *getDecl() const { return Decl; } 53bdd1243dSDimitry Andric /// Returns the name of the underlying declaration. 54*0fca6ea1SDimitry Andric const std::string getName() const; 55a7dea167SDimitry Andric /// Checks if the record is a union. 56*0fca6ea1SDimitry Andric bool isUnion() const { return IsUnion; } 57a7dea167SDimitry Andric /// Returns the size of the record. 58a7dea167SDimitry Andric unsigned getSize() const { return BaseSize; } 59a7dea167SDimitry Andric /// Returns the full size of the record, including records. 60a7dea167SDimitry Andric unsigned getFullSize() const { return BaseSize + VirtualSize; } 61a7dea167SDimitry Andric /// Returns a field. 62a7dea167SDimitry Andric const Field *getField(const FieldDecl *FD) const; 63a7dea167SDimitry Andric /// Returns a base descriptor. 64a7dea167SDimitry Andric const Base *getBase(const RecordDecl *FD) const; 6506c3fb27SDimitry Andric /// Returns a base descriptor. 6606c3fb27SDimitry Andric const Base *getBase(QualType T) const; 67a7dea167SDimitry Andric /// Returns a virtual base descriptor. 68a7dea167SDimitry Andric const Base *getVirtualBase(const RecordDecl *RD) const; 6906c3fb27SDimitry Andric /// Returns the destructor of the record, if any. 70bdd1243dSDimitry Andric const CXXDestructorDecl *getDestructor() const { 71bdd1243dSDimitry Andric if (const auto *CXXDecl = dyn_cast<CXXRecordDecl>(Decl)) 72bdd1243dSDimitry Andric return CXXDecl->getDestructor(); 73bdd1243dSDimitry Andric return nullptr; 74bdd1243dSDimitry Andric } 75a7dea167SDimitry Andric 76a7dea167SDimitry Andric using const_field_iter = FieldList::const_iterator; 77a7dea167SDimitry Andric llvm::iterator_range<const_field_iter> fields() const { 78a7dea167SDimitry Andric return llvm::make_range(Fields.begin(), Fields.end()); 79a7dea167SDimitry Andric } 80a7dea167SDimitry Andric 81bdd1243dSDimitry Andric unsigned getNumFields() const { return Fields.size(); } 82bdd1243dSDimitry Andric const Field *getField(unsigned I) const { return &Fields[I]; } 83a7dea167SDimitry Andric 84a7dea167SDimitry Andric using const_base_iter = BaseList::const_iterator; 85a7dea167SDimitry Andric llvm::iterator_range<const_base_iter> bases() const { 86a7dea167SDimitry Andric return llvm::make_range(Bases.begin(), Bases.end()); 87a7dea167SDimitry Andric } 88a7dea167SDimitry Andric 89bdd1243dSDimitry Andric unsigned getNumBases() const { return Bases.size(); } 905f757f3fSDimitry Andric const Base *getBase(unsigned I) const { 915f757f3fSDimitry Andric assert(I < getNumBases()); 925f757f3fSDimitry Andric return &Bases[I]; 935f757f3fSDimitry Andric } 94a7dea167SDimitry Andric 95a7dea167SDimitry Andric using const_virtual_iter = VirtualBaseList::const_iterator; 96a7dea167SDimitry Andric llvm::iterator_range<const_virtual_iter> virtual_bases() const { 97a7dea167SDimitry Andric return llvm::make_range(VirtualBases.begin(), VirtualBases.end()); 98a7dea167SDimitry Andric } 99a7dea167SDimitry Andric 100bdd1243dSDimitry Andric unsigned getNumVirtualBases() const { return VirtualBases.size(); } 10106c3fb27SDimitry Andric const Base *getVirtualBase(unsigned I) const { return &VirtualBases[I]; } 102a7dea167SDimitry Andric 103*0fca6ea1SDimitry Andric void dump(llvm::raw_ostream &OS, unsigned Indentation = 0, 104*0fca6ea1SDimitry Andric unsigned Offset = 0) const; 105*0fca6ea1SDimitry Andric void dump() const { dump(llvm::errs()); } 106*0fca6ea1SDimitry Andric 107a7dea167SDimitry Andric private: 108a7dea167SDimitry Andric /// Constructor used by Program to create record descriptors. 109a7dea167SDimitry Andric Record(const RecordDecl *, BaseList &&Bases, FieldList &&Fields, 110a7dea167SDimitry Andric VirtualBaseList &&VirtualBases, unsigned VirtualSize, 111a7dea167SDimitry Andric unsigned BaseSize); 112a7dea167SDimitry Andric 113a7dea167SDimitry Andric private: 114a7dea167SDimitry Andric friend class Program; 115a7dea167SDimitry Andric 116a7dea167SDimitry Andric /// Original declaration. 117a7dea167SDimitry Andric const RecordDecl *Decl; 118a7dea167SDimitry Andric /// List of all base classes. 119a7dea167SDimitry Andric BaseList Bases; 120a7dea167SDimitry Andric /// List of all the fields in the record. 121a7dea167SDimitry Andric FieldList Fields; 122a7dea167SDimitry Andric /// List o fall virtual bases. 123a7dea167SDimitry Andric VirtualBaseList VirtualBases; 124a7dea167SDimitry Andric 125a7dea167SDimitry Andric /// Mapping from declarations to bases. 126*0fca6ea1SDimitry Andric llvm::DenseMap<const RecordDecl *, const Base *> BaseMap; 127a7dea167SDimitry Andric /// Mapping from field identifiers to descriptors. 128*0fca6ea1SDimitry Andric llvm::DenseMap<const FieldDecl *, const Field *> FieldMap; 129a7dea167SDimitry Andric /// Mapping from declarations to virtual bases. 130a7dea167SDimitry Andric llvm::DenseMap<const RecordDecl *, Base *> VirtualBaseMap; 131a7dea167SDimitry Andric /// Size of the structure. 132a7dea167SDimitry Andric unsigned BaseSize; 133a7dea167SDimitry Andric /// Size of all virtual bases. 134a7dea167SDimitry Andric unsigned VirtualSize; 135*0fca6ea1SDimitry Andric /// If this record is a union. 136*0fca6ea1SDimitry Andric bool IsUnion; 137a7dea167SDimitry Andric }; 138a7dea167SDimitry Andric 139a7dea167SDimitry Andric } // namespace interp 140a7dea167SDimitry Andric } // namespace clang 141a7dea167SDimitry Andric 142a7dea167SDimitry Andric #endif 143