@@ -203,68 +203,6 @@ static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
203203 S.Note (VD->getLocation (), diag::note_declared_at);
204204}
205205
206- static bool CheckActive (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
207- AccessKinds AK) {
208- if (Ptr.isActive ())
209- return true ;
210-
211- assert (Ptr.inUnion ());
212- assert (Ptr.isField () && Ptr.getField ());
213-
214- Pointer U = Ptr.getBase ();
215- Pointer C = Ptr;
216- while (!U.isRoot () && !U.isActive ()) {
217- // A little arbitrary, but this is what the current interpreter does.
218- // See the AnonymousUnion test in test/AST/ByteCode/unions.cpp.
219- // GCC's output is more similar to what we would get without
220- // this condition.
221- if (U.getRecord () && U.getRecord ()->isAnonymousUnion ())
222- break ;
223-
224- C = U;
225- U = U.getBase ();
226- }
227- assert (C.isField ());
228-
229- // Consider:
230- // union U {
231- // struct {
232- // int x;
233- // int y;
234- // } a;
235- // }
236- //
237- // When activating x, we will also activate a. If we now try to read
238- // from y, we will get to CheckActive, because y is not active. In that
239- // case, our U will be a (not a union). We return here and let later code
240- // handle this.
241- if (!U.getFieldDesc ()->isUnion ())
242- return true ;
243-
244- // Get the inactive field descriptor.
245- assert (!C.isActive ());
246- const FieldDecl *InactiveField = C.getField ();
247- assert (InactiveField);
248-
249- // Find the active field of the union.
250- const Record *R = U.getRecord ();
251- assert (R && R->isUnion () && " Not a union" );
252-
253- const FieldDecl *ActiveField = nullptr ;
254- for (const Record::Field &F : R->fields ()) {
255- const Pointer &Field = U.atField (F.Offset );
256- if (Field.isActive ()) {
257- ActiveField = Field.getField ();
258- break ;
259- }
260- }
261-
262- const SourceInfo &Loc = S.Current ->getSource (OpPC);
263- S.FFDiag (Loc, diag::note_constexpr_access_inactive_union_member)
264- << AK << InactiveField << !ActiveField << ActiveField;
265- return false ;
266- }
267-
268206static bool CheckTemporary (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
269207 AccessKinds AK) {
270208 if (auto ID = Ptr.getDeclID ()) {
@@ -376,7 +314,68 @@ bool CheckBCPResult(InterpState &S, const Pointer &Ptr) {
376314
377315 if (const Expr *Base = Ptr.getDeclDesc ()->asExpr ())
378316 return isa<StringLiteral>(Base);
317+ return false ;
318+ }
319+
320+ bool CheckActive (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
321+ AccessKinds AK) {
322+ if (Ptr.isActive ())
323+ return true ;
379324
325+ assert (Ptr.inUnion ());
326+ assert (Ptr.isField () && Ptr.getField ());
327+
328+ Pointer U = Ptr.getBase ();
329+ Pointer C = Ptr;
330+ while (!U.isRoot () && !U.isActive ()) {
331+ // A little arbitrary, but this is what the current interpreter does.
332+ // See the AnonymousUnion test in test/AST/ByteCode/unions.cpp.
333+ // GCC's output is more similar to what we would get without
334+ // this condition.
335+ if (U.getRecord () && U.getRecord ()->isAnonymousUnion ())
336+ break ;
337+
338+ C = U;
339+ U = U.getBase ();
340+ }
341+ assert (C.isField ());
342+
343+ // Consider:
344+ // union U {
345+ // struct {
346+ // int x;
347+ // int y;
348+ // } a;
349+ // }
350+ //
351+ // When activating x, we will also activate a. If we now try to read
352+ // from y, we will get to CheckActive, because y is not active. In that
353+ // case, our U will be a (not a union). We return here and let later code
354+ // handle this.
355+ if (!U.getFieldDesc ()->isUnion ())
356+ return true ;
357+
358+ // Get the inactive field descriptor.
359+ assert (!C.isActive ());
360+ const FieldDecl *InactiveField = C.getField ();
361+ assert (InactiveField);
362+
363+ // Find the active field of the union.
364+ const Record *R = U.getRecord ();
365+ assert (R && R->isUnion () && " Not a union" );
366+
367+ const FieldDecl *ActiveField = nullptr ;
368+ for (const Record::Field &F : R->fields ()) {
369+ const Pointer &Field = U.atField (F.Offset );
370+ if (Field.isActive ()) {
371+ ActiveField = Field.getField ();
372+ break ;
373+ }
374+ }
375+
376+ const SourceInfo &Loc = S.Current ->getSource (OpPC);
377+ S.FFDiag (Loc, diag::note_constexpr_access_inactive_union_member)
378+ << AK << InactiveField << !ActiveField << ActiveField;
380379 return false ;
381380}
382381
@@ -1358,6 +1357,11 @@ static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
13581357 return false ;
13591358}
13601359
1360+ static bool checkDestructor (InterpState &S, CodePtr OpPC, const Function *Func,
1361+ const Pointer &ThisPtr) {
1362+ return CheckActive (S, OpPC, ThisPtr, AK_Destroy);
1363+ }
1364+
13611365static void compileFunction (InterpState &S, const Function *Func) {
13621366 Compiler<ByteCodeEmitter>(S.getContext (), S.P )
13631367 .compileFunc (Func->getDecl (), const_cast <Function *>(Func));
@@ -1443,13 +1447,15 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
14431447 } else {
14441448 if (!CheckInvoke (S, OpPC, ThisPtr))
14451449 return cleanup ();
1446- if (!Func->isConstructor () &&
1450+ if (!Func->isConstructor () && !Func-> isDestructor () &&
14471451 !CheckActive (S, OpPC, ThisPtr, AK_MemberCall))
14481452 return false ;
14491453 }
14501454
14511455 if (Func->isConstructor () && !checkConstructor (S, OpPC, Func, ThisPtr))
14521456 return false ;
1457+ if (Func->isDestructor () && !checkDestructor (S, OpPC, Func, ThisPtr))
1458+ return false ;
14531459 }
14541460
14551461 if (!Func->isFullyCompiled ())
0 commit comments