@@ -116,16 +116,93 @@ std::string CIRGenTypes::getRecordTypeName(const clang::RecordDecl *recordDecl,
116
116
return builder.getUniqueRecordName (std::string (typeName));
117
117
}
118
118
119
+ // / Return true if the specified type is already completely laid out.
120
+ bool CIRGenTypes::isRecordLayoutComplete (const Type *ty) const {
121
+ const auto it = recordDeclTypes.find (ty);
122
+ return it != recordDeclTypes.end () && it->second .isComplete ();
123
+ }
124
+
125
+ // We have multiple forms of this function that call each other, so we need to
126
+ // declare one in advance.
127
+ static bool
128
+ isSafeToConvert (QualType qt, CIRGenTypes &cgt,
129
+ llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
130
+
131
+ // / Return true if it is safe to convert the specified record decl to CIR and
132
+ // / lay it out, false if doing so would cause us to get into a recursive
133
+ // / compilation mess.
134
+ static bool
135
+ isSafeToConvert (const RecordDecl *rd, CIRGenTypes &cgt,
136
+ llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
137
+ // If we have already checked this type (maybe the same type is used by-value
138
+ // multiple times in multiple record fields, don't check again.
139
+ if (!alreadyChecked.insert (rd).second )
140
+ return true ;
141
+
142
+ const Type *key = cgt.getASTContext ().getTagDeclType (rd).getTypePtr ();
143
+
144
+ // If this type is already laid out, converting it is a noop.
145
+ if (cgt.isRecordLayoutComplete (key))
146
+ return true ;
147
+
148
+ // If this type is currently being laid out, we can't recursively compile it.
149
+ if (cgt.isRecordBeingLaidOut (key))
150
+ return false ;
151
+
152
+ // If this type would require laying out bases that are currently being laid
153
+ // out, don't do it. This includes virtual base classes which get laid out
154
+ // when a class is translated, even though they aren't embedded by-value into
155
+ // the class.
156
+ if (const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
157
+ assert (!cir::MissingFeatures::cxxSupport ());
158
+ cgt.getCGModule ().errorNYI (rd->getSourceRange (),
159
+ " isSafeToConvert: CXXRecordDecl" );
160
+ return false ;
161
+ }
162
+
163
+ // If this type would require laying out members that are currently being laid
164
+ // out, don't do it.
165
+ for (const FieldDecl *field : rd->fields ())
166
+ if (!isSafeToConvert (field->getType (), cgt, alreadyChecked))
167
+ return false ;
168
+
169
+ // If there are no problems, lets do it.
170
+ return true ;
171
+ }
172
+
173
+ // / Return true if it is safe to convert this field type, which requires the
174
+ // / record elements contained by-value to all be recursively safe to convert.
175
+ static bool
176
+ isSafeToConvert (QualType qt, CIRGenTypes &cgt,
177
+ llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
178
+ // Strip off atomic type sugar.
179
+ if (const auto *at = qt->getAs <AtomicType>())
180
+ qt = at->getValueType ();
181
+
182
+ // If this is a record, check it.
183
+ if (const auto *rt = qt->getAs <RecordType>())
184
+ return isSafeToConvert (rt->getDecl (), cgt, alreadyChecked);
185
+
186
+ // If this is an array, check the elements, which are embedded inline.
187
+ if (const auto *at = cgt.getASTContext ().getAsArrayType (qt))
188
+ return isSafeToConvert (at->getElementType (), cgt, alreadyChecked);
189
+
190
+ // Otherwise, there is no concern about transforming this. We only care about
191
+ // things that are contained by-value in a record that can have another
192
+ // record as a member.
193
+ return true ;
194
+ }
195
+
119
196
// Return true if it is safe to convert the specified record decl to CIR and lay
120
197
// it out, false if doing so would cause us to get into a recursive compilation
121
198
// mess.
122
- static bool isSafeToConvert (const RecordDecl *RD , CIRGenTypes &CGT ) {
199
+ static bool isSafeToConvert (const RecordDecl *rd , CIRGenTypes &cgt ) {
123
200
// If no records are being laid out, we can certainly do this one.
124
- if (CGT .noRecordsBeingLaidOut ())
201
+ if (cgt .noRecordsBeingLaidOut ())
125
202
return true ;
126
203
127
- assert (! cir::MissingFeatures::recursiveRecordLayout ()) ;
128
- return false ;
204
+ llvm::SmallPtrSet< const RecordDecl *, 16 > alreadyChecked ;
205
+ return isSafeToConvert (rd, cgt, alreadyChecked) ;
129
206
}
130
207
131
208
// / Lay out a tagged decl type like struct or union.
0 commit comments