xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/Interp/Record.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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