@@ -25,6 +25,34 @@ using APSInt = llvm::APSInt;
25
25
namespace clang {
26
26
namespace interp {
27
27
28
+ static bool refersToUnion (const Expr *E) {
29
+ for (;;) {
30
+ if (const auto *ME = dyn_cast<MemberExpr>(E)) {
31
+ if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl ());
32
+ FD && FD->getParent ()->isUnion ())
33
+ return true ;
34
+ E = ME->getBase ();
35
+ continue ;
36
+ }
37
+
38
+ if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
39
+ E = ASE->getBase ()->IgnoreImplicit ();
40
+ continue ;
41
+ }
42
+
43
+ if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E);
44
+ ICE && (ICE->getCastKind () == CK_NoOp ||
45
+ ICE->getCastKind () == CK_DerivedToBase ||
46
+ ICE->getCastKind () == CK_UncheckedDerivedToBase)) {
47
+ E = ICE->getSubExpr ();
48
+ continue ;
49
+ }
50
+
51
+ break ;
52
+ }
53
+ return false ;
54
+ }
55
+
28
56
static std::optional<bool > getBoolValue (const Expr *E) {
29
57
if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);
30
58
CE && CE->hasAPValueResult () &&
@@ -880,22 +908,11 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
880
908
return this ->VisitPointerArithBinOp (BO);
881
909
}
882
910
883
- // Assignments require us to evalute the RHS first.
884
- if (BO->getOpcode () == BO_Assign) {
885
-
886
- if (!visit (RHS) || !visit (LHS))
887
- return false ;
888
-
889
- // We don't support assignments in C.
890
- if (!Ctx.getLangOpts ().CPlusPlus && !this ->emitInvalid (BO))
891
- return false ;
911
+ if (BO->getOpcode () == BO_Assign)
912
+ return this ->visitAssignment (LHS, RHS, BO);
892
913
893
- if (!this ->emitFlip (*LT, *RT, BO))
894
- return false ;
895
- } else {
896
- if (!visit (LHS) || !visit (RHS))
897
- return false ;
898
- }
914
+ if (!visit (LHS) || !visit (RHS))
915
+ return false ;
899
916
900
917
// For languages such as C, cast the result of one
901
918
// of our comparision opcodes to T (which is usually int).
@@ -946,22 +963,6 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
946
963
if (BO->getType ()->isFloatingType ())
947
964
return Discard (this ->emitDivf (getFPOptions (BO), BO));
948
965
return Discard (this ->emitDiv (*T, BO));
949
- case BO_Assign:
950
- if (DiscardResult)
951
- return LHS->refersToBitField () ? this ->emitStoreBitFieldPop (*T, BO)
952
- : this ->emitStorePop (*T, BO);
953
- if (LHS->refersToBitField ()) {
954
- if (!this ->emitStoreBitField (*T, BO))
955
- return false ;
956
- } else {
957
- if (!this ->emitStore (*T, BO))
958
- return false ;
959
- }
960
- // Assignments aren't necessarily lvalues in C.
961
- // Load from them in that case.
962
- if (!BO->isLValue ())
963
- return this ->emitLoadPop (*T, BO);
964
- return true ;
965
966
case BO_And:
966
967
return Discard (this ->emitBitAnd (*T, BO));
967
968
case BO_Or:
@@ -1790,26 +1791,37 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
1790
1791
return this ->delegate (Inits[0 ]);
1791
1792
1792
1793
auto initPrimitiveField = [=](const Record::Field *FieldToInit,
1793
- const Expr *Init, PrimType T) -> bool {
1794
+ const Expr *Init, PrimType T,
1795
+ bool Activate = false ) -> bool {
1794
1796
InitStackScope<Emitter> ISS (this , isa<CXXDefaultInitExpr>(Init));
1795
1797
InitLinkScope<Emitter> ILS (this , InitLink::Field (FieldToInit->Offset ));
1796
1798
if (!this ->visit (Init))
1797
1799
return false ;
1798
1800
1799
- if (FieldToInit->isBitField ())
1801
+ bool BitField = FieldToInit->isBitField ();
1802
+ if (BitField && Activate)
1803
+ return this ->emitInitBitFieldActivate (T, FieldToInit, E);
1804
+ if (BitField)
1800
1805
return this ->emitInitBitField (T, FieldToInit, E);
1806
+ if (Activate)
1807
+ return this ->emitInitFieldActivate (T, FieldToInit->Offset , E);
1801
1808
return this ->emitInitField (T, FieldToInit->Offset , E);
1802
1809
};
1803
1810
1804
1811
auto initCompositeField = [=](const Record::Field *FieldToInit,
1805
- const Expr *Init) -> bool {
1812
+ const Expr *Init,
1813
+ bool Activate = false ) -> bool {
1806
1814
InitStackScope<Emitter> ISS (this , isa<CXXDefaultInitExpr>(Init));
1807
1815
InitLinkScope<Emitter> ILS (this , InitLink::Field (FieldToInit->Offset ));
1808
1816
1809
1817
// Non-primitive case. Get a pointer to the field-to-initialize
1810
1818
// on the stack and recurse into visitInitializer().
1811
1819
if (!this ->emitGetPtrField (FieldToInit->Offset , Init))
1812
1820
return false ;
1821
+
1822
+ if (Activate && !this ->emitActivate (E))
1823
+ return false ;
1824
+
1813
1825
if (!this ->visitInitializer (Init))
1814
1826
return false ;
1815
1827
return this ->emitPopPtr (E);
@@ -1829,10 +1841,10 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
1829
1841
1830
1842
const Record::Field *FieldToInit = R->getField (FToInit);
1831
1843
if (std::optional<PrimType> T = classify (Init)) {
1832
- if (!initPrimitiveField (FieldToInit, Init, *T))
1844
+ if (!initPrimitiveField (FieldToInit, Init, *T, /* Activate= */ true ))
1833
1845
return false ;
1834
1846
} else {
1835
- if (!initCompositeField (FieldToInit, Init))
1847
+ if (!initCompositeField (FieldToInit, Init, /* Activate= */ true ))
1836
1848
return false ;
1837
1849
}
1838
1850
}
@@ -2023,7 +2035,8 @@ bool Compiler<Emitter>::visitArrayElemInit(unsigned ElemIndex, const Expr *Init,
2023
2035
2024
2036
template <class Emitter >
2025
2037
bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,
2026
- const FunctionDecl *FuncDecl) {
2038
+ const FunctionDecl *FuncDecl,
2039
+ bool Activate) {
2027
2040
assert (VarScope->getKind () == ScopeKind::Call);
2028
2041
llvm::BitVector NonNullArgs = collectNonNullArgs (FuncDecl, Args);
2029
2042
@@ -2046,6 +2059,11 @@ bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,
2046
2059
return false ;
2047
2060
}
2048
2061
2062
+ if (ArgIndex == 1 && Activate) {
2063
+ if (!this ->emitActivate (Arg))
2064
+ return false ;
2065
+ }
2066
+
2049
2067
if (FuncDecl && NonNullArgs[ArgIndex]) {
2050
2068
PrimType ArgT = classify (Arg).value_or (PT_Ptr);
2051
2069
if (ArgT == PT_Ptr) {
@@ -4227,10 +4245,13 @@ bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,
4227
4245
PrimType T = classifyPrim (D->getType ());
4228
4246
if (!this ->visitZeroInitializer (T, QT, E))
4229
4247
return false ;
4248
+ if (R->isUnion ()) {
4249
+ if (!this ->emitInitFieldActivate (T, Field.Offset , E))
4250
+ return false ;
4251
+ break ;
4252
+ }
4230
4253
if (!this ->emitInitField (T, Field.Offset , E))
4231
4254
return false ;
4232
- if (R->isUnion ())
4233
- break ;
4234
4255
continue ;
4235
4256
}
4236
4257
@@ -4256,13 +4277,15 @@ bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,
4256
4277
} else
4257
4278
return false ;
4258
4279
4259
- if (!this ->emitFinishInitPop (E))
4260
- return false ;
4261
-
4262
4280
// C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
4263
4281
// object's first non-static named data member is zero-initialized
4264
- if (R->isUnion ())
4282
+ if (R->isUnion ()) {
4283
+ if (!this ->emitFinishInitActivatePop (E))
4284
+ return false ;
4265
4285
break ;
4286
+ }
4287
+ if (!this ->emitFinishInitPop (E))
4288
+ return false ;
4266
4289
}
4267
4290
4268
4291
for (const Record::Base &B : R->bases ()) {
@@ -4325,6 +4348,59 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
4325
4348
return false ;
4326
4349
}
4327
4350
4351
+ template <class Emitter >
4352
+ bool Compiler<Emitter>::visitAssignment(const Expr *LHS, const Expr *RHS,
4353
+ const Expr *E) {
4354
+ if (!classify (E->getType ()))
4355
+ return false ;
4356
+
4357
+ if (!this ->visit (RHS))
4358
+ return false ;
4359
+ if (!this ->visit (LHS))
4360
+ return false ;
4361
+
4362
+ // We don't support assignments in C.
4363
+ if (!Ctx.getLangOpts ().CPlusPlus && !this ->emitInvalid (E))
4364
+ return false ;
4365
+
4366
+ PrimType RHT = classifyPrim (RHS);
4367
+ bool Activates = refersToUnion (LHS);
4368
+ bool BitField = LHS->refersToBitField ();
4369
+
4370
+ if (!this ->emitFlip (PT_Ptr, RHT, E))
4371
+ return false ;
4372
+
4373
+ if (DiscardResult) {
4374
+ if (BitField && Activates)
4375
+ return this ->emitStoreBitFieldActivatePop (RHT, E);
4376
+ if (BitField)
4377
+ return this ->emitStoreBitFieldPop (RHT, E);
4378
+ if (Activates)
4379
+ return this ->emitStoreActivatePop (RHT, E);
4380
+ // Otherwise, regular non-activating store.
4381
+ return this ->emitStorePop (RHT, E);
4382
+ }
4383
+
4384
+ auto maybeLoad = [&](bool Result) -> bool {
4385
+ if (!Result)
4386
+ return false ;
4387
+ // Assignments aren't necessarily lvalues in C.
4388
+ // Load from them in that case.
4389
+ if (!E->isLValue ())
4390
+ return this ->emitLoadPop (RHT, E);
4391
+ return true ;
4392
+ };
4393
+
4394
+ if (BitField && Activates)
4395
+ return maybeLoad (this ->emitStoreBitFieldActivate (RHT, E));
4396
+ if (BitField)
4397
+ return maybeLoad (this ->emitStoreBitField (RHT, E));
4398
+ if (Activates)
4399
+ return maybeLoad (this ->emitStoreActivate (RHT, E));
4400
+ // Otherwise, regular non-activating store.
4401
+ return maybeLoad (this ->emitStore (RHT, E));
4402
+ }
4403
+
4328
4404
template <class Emitter >
4329
4405
template <typename T>
4330
4406
bool Compiler<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
@@ -5067,7 +5143,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
5067
5143
return false ;
5068
5144
}
5069
5145
5070
- if (!this ->visitCallArgs (Args, FuncDecl))
5146
+ if (!this ->visitCallArgs (Args, FuncDecl, IsAssignmentOperatorCall ))
5071
5147
return false ;
5072
5148
5073
5149
// Undo the argument reversal we did earlier.
@@ -5851,7 +5927,8 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
5851
5927
assert (!ReturnType);
5852
5928
5853
5929
auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset,
5854
- const Expr *InitExpr) -> bool {
5930
+ const Expr *InitExpr,
5931
+ bool Activate = false ) -> bool {
5855
5932
// We don't know what to do with these, so just return false.
5856
5933
if (InitExpr->getType ().isNull ())
5857
5934
return false ;
@@ -5860,8 +5937,13 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
5860
5937
if (!this ->visit (InitExpr))
5861
5938
return false ;
5862
5939
5863
- if (F->isBitField ())
5940
+ bool BitField = F->isBitField ();
5941
+ if (BitField && Activate)
5942
+ return this ->emitInitThisBitFieldActivate (*T, F, FieldOffset, InitExpr);
5943
+ if (BitField)
5864
5944
return this ->emitInitThisBitField (*T, F, FieldOffset, InitExpr);
5945
+ if (Activate)
5946
+ return this ->emitInitThisFieldActivate (*T, FieldOffset, InitExpr);
5865
5947
return this ->emitInitThisField (*T, FieldOffset, InitExpr);
5866
5948
}
5867
5949
// Non-primitive case. Get a pointer to the field-to-initialize
@@ -5870,6 +5952,9 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
5870
5952
if (!this ->emitGetPtrThisField (FieldOffset, InitExpr))
5871
5953
return false ;
5872
5954
5955
+ if (Activate && !this ->emitActivate (InitExpr))
5956
+ return false ;
5957
+
5873
5958
if (!this ->visitInitializer (InitExpr))
5874
5959
return false ;
5875
5960
@@ -5880,8 +5965,9 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
5880
5965
const Record *R = this ->getRecord (RD);
5881
5966
if (!R)
5882
5967
return false ;
5968
+ bool IsUnion = R->isUnion ();
5883
5969
5884
- if (R-> isUnion () && Ctor->isCopyOrMoveConstructor ()) {
5970
+ if (IsUnion && Ctor->isCopyOrMoveConstructor ()) {
5885
5971
if (R->getNumFields () == 0 )
5886
5972
return this ->emitRetVoid (Ctor);
5887
5973
// union copy and move ctors are special.
@@ -5908,7 +5994,7 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
5908
5994
if (const FieldDecl *Member = Init->getMember ()) {
5909
5995
const Record::Field *F = R->getField (Member);
5910
5996
5911
- if (!emitFieldInitializer (F, F->Offset , InitExpr))
5997
+ if (!emitFieldInitializer (F, F->Offset , InitExpr, IsUnion ))
5912
5998
return false ;
5913
5999
} else if (const Type *Base = Init->getBaseClass ()) {
5914
6000
const auto *BaseDecl = Base->getAsCXXRecordDecl ();
@@ -5928,11 +6014,15 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
5928
6014
return false ;
5929
6015
}
5930
6016
6017
+ if (IsUnion && !this ->emitActivate (InitExpr))
6018
+ return false ;
6019
+
5931
6020
if (!this ->visitInitializer (InitExpr))
5932
6021
return false ;
5933
6022
if (!this ->emitFinishInitPop (InitExpr))
5934
6023
return false ;
5935
6024
} else if (const IndirectFieldDecl *IFD = Init->getIndirectMember ()) {
6025
+
5936
6026
assert (IFD->getChainingSize () >= 2 );
5937
6027
5938
6028
unsigned NestedFieldOffset = 0 ;
@@ -5944,12 +6034,14 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
5944
6034
5945
6035
NestedField = FieldRecord->getField (FD);
5946
6036
assert (NestedField);
6037
+ IsUnion = IsUnion || FieldRecord->isUnion ();
5947
6038
5948
6039
NestedFieldOffset += NestedField->Offset ;
5949
6040
}
5950
6041
assert (NestedField);
5951
6042
5952
- if (!emitFieldInitializer (NestedField, NestedFieldOffset, InitExpr))
6043
+ if (!emitFieldInitializer (NestedField, NestedFieldOffset, InitExpr,
6044
+ IsUnion))
5953
6045
return false ;
5954
6046
5955
6047
// Mark all chain links as initialized.
0 commit comments