@@ -53,19 +53,133 @@ bool CIRGenFunction::isConstructorDelegationValid(
53
53
return true ;
54
54
}
55
55
56
+ static void emitLValueForAnyFieldInitialization (CIRGenFunction &cgf,
57
+ CXXCtorInitializer *memberInit,
58
+ LValue &lhs) {
59
+ FieldDecl *field = memberInit->getAnyMember ();
60
+ if (memberInit->isIndirectMemberInitializer ()) {
61
+ // If we are initializing an anonymous union field, drill down to the field.
62
+ IndirectFieldDecl *indirectField = memberInit->getIndirectMember ();
63
+ for (const auto *nd : indirectField->chain ()) {
64
+ auto *fd = cast<clang::FieldDecl>(nd);
65
+ lhs = cgf.emitLValueForFieldInitialization (lhs, fd, fd->getName ());
66
+ }
67
+ } else {
68
+ lhs = cgf.emitLValueForFieldInitialization (lhs, field, field->getName ());
69
+ }
70
+ }
71
+
72
+ static void emitMemberInitializer (CIRGenFunction &cgf,
73
+ const CXXRecordDecl *classDecl,
74
+ CXXCtorInitializer *memberInit,
75
+ const CXXConstructorDecl *constructor,
76
+ FunctionArgList &args) {
77
+ assert (memberInit->isAnyMemberInitializer () &&
78
+ " Mush have member initializer!" );
79
+ assert (memberInit->getInit () && " Must have initializer!" );
80
+
81
+ assert (!cir::MissingFeatures::generateDebugInfo ());
82
+
83
+ // non-static data member initializers
84
+ FieldDecl *field = memberInit->getAnyMember ();
85
+ QualType fieldType = field->getType ();
86
+
87
+ mlir::Value thisPtr = cgf.loadCXXThis ();
88
+ QualType recordTy = cgf.getContext ().getTypeDeclType (classDecl);
89
+
90
+ // If a base constructor is being emitted, create an LValue that has the
91
+ // non-virtual alignment.
92
+ LValue lhs = (cgf.curGD .getCtorType () == Ctor_Base)
93
+ ? cgf.makeNaturalAlignPointeeAddrLValue (thisPtr, recordTy)
94
+ : cgf.makeNaturalAlignAddrLValue (thisPtr, recordTy);
95
+
96
+ emitLValueForAnyFieldInitialization (cgf, memberInit, lhs);
97
+
98
+ // Special case: If we are in a copy or move constructor, and we are copying
99
+ // an array off PODs or classes with trivial copy constructors, ignore the AST
100
+ // and perform the copy we know is equivalent.
101
+ // FIXME: This is hacky at best... if we had a bit more explicit information
102
+ // in the AST, we could generalize it more easily.
103
+ const ConstantArrayType *array =
104
+ cgf.getContext ().getAsConstantArrayType (fieldType);
105
+ if (array && constructor->isDefaulted () &&
106
+ constructor->isCopyOrMoveConstructor ()) {
107
+ QualType baseElementTy = cgf.getContext ().getBaseElementType (array);
108
+ // NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,
109
+ // whereas ClangIR wants to represent all object construction explicitly.
110
+ if (!baseElementTy->isRecordType ()) {
111
+ cgf.cgm .errorNYI (memberInit->getSourceRange (),
112
+ " emitMemberInitializer: array of non-record type" );
113
+ return ;
114
+ }
115
+ }
116
+
117
+ cgf.emitInitializerForField (field, lhs, memberInit->getInit ());
118
+ }
119
+
56
120
// / This routine generates necessary code to initialize base classes and
57
121
// / non-static data members belonging to this constructor.
58
122
void CIRGenFunction::emitCtorPrologue (const CXXConstructorDecl *cd,
59
123
CXXCtorType ctorType,
60
124
FunctionArgList &args) {
61
- if (cd->isDelegatingConstructor ())
62
- return emitDelegatingCXXConstructorCall (cd, args);
125
+ if (cd->isDelegatingConstructor ()) {
126
+ emitDelegatingCXXConstructorCall (cd, args);
127
+ return ;
128
+ }
129
+
130
+ // If there are no member initializers, we can just return.
131
+ if (cd->getNumCtorInitializers () == 0 )
132
+ return ;
63
133
64
- if (cd->getNumCtorInitializers () != 0 ) {
65
- // There's much more to do here.
66
- cgm.errorNYI (cd->getSourceRange (), " emitCtorPrologue: any initializer" );
134
+ const CXXRecordDecl *classDecl = cd->getParent ();
135
+
136
+ // This code doesn't use range-based iteration because we may need to emit
137
+ // code between the virtual base initializers and the non-virtual base or
138
+ // between the non-virtual base initializers and the member initializers.
139
+ CXXConstructorDecl::init_const_iterator b = cd->init_begin (),
140
+ e = cd->init_end ();
141
+
142
+ // Virtual base initializers first, if any. They aren't needed if:
143
+ // - This is a base ctor variant
144
+ // - There are no vbases
145
+ // - The class is abstract, so a complete object of it cannot be constructed
146
+ //
147
+ // The check for an abstract class is necessary because sema may not have
148
+ // marked virtual base destructors referenced.
149
+ bool constructVBases = ctorType != Ctor_Base &&
150
+ classDecl->getNumVBases () != 0 &&
151
+ !classDecl->isAbstract ();
152
+ if (constructVBases) {
153
+ cgm.errorNYI (cd->getSourceRange (), " emitCtorPrologue: virtual base" );
67
154
return ;
68
155
}
156
+
157
+ if ((*b)->isBaseInitializer ()) {
158
+ cgm.errorNYI (cd->getSourceRange (),
159
+ " emitCtorPrologue: non-virtual base initializer" );
160
+ return ;
161
+ }
162
+
163
+ if (classDecl->isDynamicClass ()) {
164
+ cgm.errorNYI (cd->getSourceRange (),
165
+ " emitCtorPrologue: initialize vtable pointers" );
166
+ return ;
167
+ }
168
+
169
+ // Finally, initialize class members.
170
+ FieldConstructionScope fcs (*this , loadCXXThisAddress ());
171
+ // Classic codegen uses a special class to attempt to replace member
172
+ // initializers with memcpy. We could possibly defer that to the
173
+ // lowering or optimization phases to keep the memory accesses more
174
+ // explicit. For now, we don't insert memcpy at all.
175
+ assert (!cir::MissingFeatures::ctorMemcpyizer ());
176
+ for (; b != e; b++) {
177
+ CXXCtorInitializer *member = (*b);
178
+ assert (!member->isBaseInitializer ());
179
+ assert (member->isAnyMemberInitializer () &&
180
+ " Delegating initializer on non-delegating constructor" );
181
+ emitMemberInitializer (*this , cd->getParent (), member, cd, args);
182
+ }
69
183
}
70
184
71
185
Address CIRGenFunction::loadCXXThisAddress () {
@@ -84,6 +198,33 @@ Address CIRGenFunction::loadCXXThisAddress() {
84
198
return Address (loadCXXThis (), cxxThisAlignment);
85
199
}
86
200
201
+ void CIRGenFunction::emitInitializerForField (FieldDecl *field, LValue lhs,
202
+ Expr *init) {
203
+ QualType fieldType = field->getType ();
204
+ switch (getEvaluationKind (fieldType)) {
205
+ case cir::TEK_Scalar:
206
+ if (lhs.isSimple ())
207
+ emitExprAsInit (init, field, lhs, false );
208
+ else
209
+ cgm.errorNYI (field->getSourceRange (),
210
+ " emitInitializerForField: non-simple scalar" );
211
+ break ;
212
+ case cir::TEK_Complex:
213
+ cgm.errorNYI (field->getSourceRange (), " emitInitializerForField: complex" );
214
+ break ;
215
+ case cir::TEK_Aggregate: {
216
+ cgm.errorNYI (field->getSourceRange (), " emitInitializerForField: aggregate" );
217
+ break ;
218
+ }
219
+ }
220
+
221
+ // Ensure that we destroy this object if an exception is thrown later in the
222
+ // constructor.
223
+ QualType::DestructionKind dtorKind = fieldType.isDestructedType ();
224
+ (void )dtorKind;
225
+ assert (!cir::MissingFeatures::requiresCleanups ());
226
+ }
227
+
87
228
void CIRGenFunction::emitDelegateCXXConstructorCall (
88
229
const CXXConstructorDecl *ctor, CXXCtorType ctorType,
89
230
const FunctionArgList &args, SourceLocation loc) {
0 commit comments