@@ -129,68 +129,6 @@ static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
129129 S.Note (VD->getLocation (), diag::note_declared_at);
130130}
131131
132- static bool CheckActive (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
133- AccessKinds AK) {
134- if (Ptr.isActive ())
135- return true ;
136-
137- assert (Ptr.inUnion ());
138- assert (Ptr.isField () && Ptr.getField ());
139-
140- Pointer U = Ptr.getBase ();
141- Pointer C = Ptr;
142- while (!U.isRoot () && !U.isActive ()) {
143- // A little arbitrary, but this is what the current interpreter does.
144- // See the AnonymousUnion test in test/AST/ByteCode/unions.cpp.
145- // GCC's output is more similar to what we would get without
146- // this condition.
147- if (U.getRecord () && U.getRecord ()->isAnonymousUnion ())
148- break ;
149-
150- C = U;
151- U = U.getBase ();
152- }
153- assert (C.isField ());
154-
155- // Consider:
156- // union U {
157- // struct {
158- // int x;
159- // int y;
160- // } a;
161- // }
162- //
163- // When activating x, we will also activate a. If we now try to read
164- // from y, we will get to CheckActive, because y is not active. In that
165- // case, our U will be a (not a union). We return here and let later code
166- // handle this.
167- if (!U.getFieldDesc ()->isUnion ())
168- return true ;
169-
170- // Get the inactive field descriptor.
171- assert (!C.isActive ());
172- const FieldDecl *InactiveField = C.getField ();
173- assert (InactiveField);
174-
175- // Find the active field of the union.
176- const Record *R = U.getRecord ();
177- assert (R && R->isUnion () && " Not a union" );
178-
179- const FieldDecl *ActiveField = nullptr ;
180- for (const Record::Field &F : R->fields ()) {
181- const Pointer &Field = U.atField (F.Offset );
182- if (Field.isActive ()) {
183- ActiveField = Field.getField ();
184- break ;
185- }
186- }
187-
188- const SourceInfo &Loc = S.Current ->getSource (OpPC);
189- S.FFDiag (Loc, diag::note_constexpr_access_inactive_union_member)
190- << AK << InactiveField << !ActiveField << ActiveField;
191- return false ;
192- }
193-
194132static bool CheckTemporary (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
195133 AccessKinds AK) {
196134 if (auto ID = Ptr.getDeclID ()) {
@@ -290,6 +228,68 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
290228 TYPE_SWITCH (Ty, S.Stk .discard <T>());
291229}
292230
231+ bool CheckActive (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
232+ AccessKinds AK) {
233+ if (Ptr.isActive ())
234+ return true ;
235+
236+ assert (Ptr.inUnion ());
237+ assert (Ptr.isField () && Ptr.getField ());
238+
239+ Pointer U = Ptr.getBase ();
240+ Pointer C = Ptr;
241+ while (!U.isRoot () && !U.isActive ()) {
242+ // A little arbitrary, but this is what the current interpreter does.
243+ // See the AnonymousUnion test in test/AST/ByteCode/unions.cpp.
244+ // GCC's output is more similar to what we would get without
245+ // this condition.
246+ if (U.getRecord () && U.getRecord ()->isAnonymousUnion ())
247+ break ;
248+
249+ C = U;
250+ U = U.getBase ();
251+ }
252+ assert (C.isField ());
253+
254+ // Consider:
255+ // union U {
256+ // struct {
257+ // int x;
258+ // int y;
259+ // } a;
260+ // }
261+ //
262+ // When activating x, we will also activate a. If we now try to read
263+ // from y, we will get to CheckActive, because y is not active. In that
264+ // case, our U will be a (not a union). We return here and let later code
265+ // handle this.
266+ if (!U.getFieldDesc ()->isUnion ())
267+ return true ;
268+
269+ // Get the inactive field descriptor.
270+ assert (!C.isActive ());
271+ const FieldDecl *InactiveField = C.getField ();
272+ assert (InactiveField);
273+
274+ // Find the active field of the union.
275+ const Record *R = U.getRecord ();
276+ assert (R && R->isUnion () && " Not a union" );
277+
278+ const FieldDecl *ActiveField = nullptr ;
279+ for (const Record::Field &F : R->fields ()) {
280+ const Pointer &Field = U.atField (F.Offset );
281+ if (Field.isActive ()) {
282+ ActiveField = Field.getField ();
283+ break ;
284+ }
285+ }
286+
287+ const SourceInfo &Loc = S.Current ->getSource (OpPC);
288+ S.FFDiag (Loc, diag::note_constexpr_access_inactive_union_member)
289+ << AK << InactiveField << !ActiveField << ActiveField;
290+ return false ;
291+ }
292+
293293bool CheckExtern (InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
294294 if (!Ptr.isExtern ())
295295 return true ;
@@ -1265,6 +1265,11 @@ static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
12651265 return false ;
12661266}
12671267
1268+ static bool checkDestructor (InterpState &S, CodePtr OpPC, const Function *Func,
1269+ const Pointer &ThisPtr) {
1270+ return CheckActive (S, OpPC, ThisPtr, AK_Destroy);
1271+ }
1272+
12681273bool CallVar (InterpState &S, CodePtr OpPC, const Function *Func,
12691274 uint32_t VarArgSize) {
12701275 if (Func->hasThisPointer ()) {
@@ -1347,6 +1352,8 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
13471352
13481353 if (Func->isConstructor () && !checkConstructor (S, OpPC, Func, ThisPtr))
13491354 return false ;
1355+ if (Func->isDestructor () && !checkDestructor (S, OpPC, Func, ThisPtr))
1356+ return false ;
13501357 }
13511358
13521359 if (!CheckCallable (S, OpPC, Func))
0 commit comments