@@ -202,68 +202,6 @@ static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
202202 S.Note (VD->getLocation (), diag::note_declared_at);
203203}
204204
205- static bool CheckActive (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
206- AccessKinds AK) {
207- if (Ptr.isActive ())
208- return true ;
209-
210- assert (Ptr.inUnion ());
211- assert (Ptr.isField () && Ptr.getField ());
212-
213- Pointer U = Ptr.getBase ();
214- Pointer C = Ptr;
215- while (!U.isRoot () && !U.isActive ()) {
216- // A little arbitrary, but this is what the current interpreter does.
217- // See the AnonymousUnion test in test/AST/ByteCode/unions.cpp.
218- // GCC's output is more similar to what we would get without
219- // this condition.
220- if (U.getRecord () && U.getRecord ()->isAnonymousUnion ())
221- break ;
222-
223- C = U;
224- U = U.getBase ();
225- }
226- assert (C.isField ());
227-
228- // Consider:
229- // union U {
230- // struct {
231- // int x;
232- // int y;
233- // } a;
234- // }
235- //
236- // When activating x, we will also activate a. If we now try to read
237- // from y, we will get to CheckActive, because y is not active. In that
238- // case, our U will be a (not a union). We return here and let later code
239- // handle this.
240- if (!U.getFieldDesc ()->isUnion ())
241- return true ;
242-
243- // Get the inactive field descriptor.
244- assert (!C.isActive ());
245- const FieldDecl *InactiveField = C.getField ();
246- assert (InactiveField);
247-
248- // Find the active field of the union.
249- const Record *R = U.getRecord ();
250- assert (R && R->isUnion () && " Not a union" );
251-
252- const FieldDecl *ActiveField = nullptr ;
253- for (const Record::Field &F : R->fields ()) {
254- const Pointer &Field = U.atField (F.Offset );
255- if (Field.isActive ()) {
256- ActiveField = Field.getField ();
257- break ;
258- }
259- }
260-
261- const SourceInfo &Loc = S.Current ->getSource (OpPC);
262- S.FFDiag (Loc, diag::note_constexpr_access_inactive_union_member)
263- << AK << InactiveField << !ActiveField << ActiveField;
264- return false ;
265- }
266-
267205static bool CheckTemporary (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
268206 AccessKinds AK) {
269207 if (auto ID = Ptr.getDeclID ()) {
@@ -375,7 +313,68 @@ bool CheckBCPResult(InterpState &S, const Pointer &Ptr) {
375313
376314 if (const Expr *Base = Ptr.getDeclDesc ()->asExpr ())
377315 return isa<StringLiteral>(Base);
316+ return false ;
317+ }
318+
319+ bool CheckActive (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
320+ AccessKinds AK) {
321+ if (Ptr.isActive ())
322+ return true ;
378323
324+ assert (Ptr.inUnion ());
325+ assert (Ptr.isField () && Ptr.getField ());
326+
327+ Pointer U = Ptr.getBase ();
328+ Pointer C = Ptr;
329+ while (!U.isRoot () && !U.isActive ()) {
330+ // A little arbitrary, but this is what the current interpreter does.
331+ // See the AnonymousUnion test in test/AST/ByteCode/unions.cpp.
332+ // GCC's output is more similar to what we would get without
333+ // this condition.
334+ if (U.getRecord () && U.getRecord ()->isAnonymousUnion ())
335+ break ;
336+
337+ C = U;
338+ U = U.getBase ();
339+ }
340+ assert (C.isField ());
341+
342+ // Consider:
343+ // union U {
344+ // struct {
345+ // int x;
346+ // int y;
347+ // } a;
348+ // }
349+ //
350+ // When activating x, we will also activate a. If we now try to read
351+ // from y, we will get to CheckActive, because y is not active. In that
352+ // case, our U will be a (not a union). We return here and let later code
353+ // handle this.
354+ if (!U.getFieldDesc ()->isUnion ())
355+ return true ;
356+
357+ // Get the inactive field descriptor.
358+ assert (!C.isActive ());
359+ const FieldDecl *InactiveField = C.getField ();
360+ assert (InactiveField);
361+
362+ // Find the active field of the union.
363+ const Record *R = U.getRecord ();
364+ assert (R && R->isUnion () && " Not a union" );
365+
366+ const FieldDecl *ActiveField = nullptr ;
367+ for (const Record::Field &F : R->fields ()) {
368+ const Pointer &Field = U.atField (F.Offset );
369+ if (Field.isActive ()) {
370+ ActiveField = Field.getField ();
371+ break ;
372+ }
373+ }
374+
375+ const SourceInfo &Loc = S.Current ->getSource (OpPC);
376+ S.FFDiag (Loc, diag::note_constexpr_access_inactive_union_member)
377+ << AK << InactiveField << !ActiveField << ActiveField;
379378 return false ;
380379}
381380
@@ -1355,6 +1354,11 @@ static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
13551354 return false ;
13561355}
13571356
1357+ static bool checkDestructor (InterpState &S, CodePtr OpPC, const Function *Func,
1358+ const Pointer &ThisPtr) {
1359+ return CheckActive (S, OpPC, ThisPtr, AK_Destroy);
1360+ }
1361+
13581362bool CallVar (InterpState &S, CodePtr OpPC, const Function *Func,
13591363 uint32_t VarArgSize) {
13601364 if (Func->hasThisPointer ()) {
@@ -1433,13 +1437,15 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
14331437 } else {
14341438 if (!CheckInvoke (S, OpPC, ThisPtr))
14351439 return cleanup ();
1436- if (!Func->isConstructor () &&
1440+ if (!Func->isConstructor () && !Func-> isDestructor () &&
14371441 !CheckActive (S, OpPC, ThisPtr, AK_MemberCall))
14381442 return false ;
14391443 }
14401444
14411445 if (Func->isConstructor () && !checkConstructor (S, OpPC, Func, ThisPtr))
14421446 return false ;
1447+ if (Func->isDestructor () && !checkDestructor (S, OpPC, Func, ThisPtr))
1448+ return false ;
14431449 }
14441450
14451451 if (!CheckCallable (S, OpPC, Func))
0 commit comments