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