@@ -203,68 +203,6 @@ static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
203
203
S.Note (VD->getLocation (), diag::note_declared_at);
204
204
}
205
205
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
-
268
206
static bool CheckTemporary (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
269
207
AccessKinds AK) {
270
208
if (auto ID = Ptr.getDeclID ()) {
@@ -376,7 +314,68 @@ bool CheckBCPResult(InterpState &S, const Pointer &Ptr) {
376
314
377
315
if (const Expr *Base = Ptr.getDeclDesc ()->asExpr ())
378
316
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 ;
379
324
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;
380
379
return false ;
381
380
}
382
381
@@ -1358,6 +1357,11 @@ static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
1358
1357
return false ;
1359
1358
}
1360
1359
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
+
1361
1365
static void compileFunction (InterpState &S, const Function *Func) {
1362
1366
Compiler<ByteCodeEmitter>(S.getContext (), S.P )
1363
1367
.compileFunc (Func->getDecl (), const_cast <Function *>(Func));
@@ -1443,13 +1447,15 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
1443
1447
} else {
1444
1448
if (!CheckInvoke (S, OpPC, ThisPtr))
1445
1449
return cleanup ();
1446
- if (!Func->isConstructor () &&
1450
+ if (!Func->isConstructor () && !Func-> isDestructor () &&
1447
1451
!CheckActive (S, OpPC, ThisPtr, AK_MemberCall))
1448
1452
return false ;
1449
1453
}
1450
1454
1451
1455
if (Func->isConstructor () && !checkConstructor (S, OpPC, Func, ThisPtr))
1452
1456
return false ;
1457
+ if (Func->isDestructor () && !checkDestructor (S, OpPC, Func, ThisPtr))
1458
+ return false ;
1453
1459
}
1454
1460
1455
1461
if (!Func->isFullyCompiled ())
0 commit comments