@@ -25,6 +25,34 @@ using APSInt = llvm::APSInt;
2525namespace clang {
2626namespace interp {
2727
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+
2856static std::optional<bool > getBoolValue (const Expr *E) {
2957 if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);
3058 CE && CE->hasAPValueResult () &&
@@ -880,22 +908,11 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
880908 return this ->VisitPointerArithBinOp (BO);
881909 }
882910
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);
892913
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 ;
899916
900917 // For languages such as C, cast the result of one
901918 // of our comparision opcodes to T (which is usually int).
@@ -946,22 +963,6 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
946963 if (BO->getType ()->isFloatingType ())
947964 return Discard (this ->emitDivf (getFPOptions (BO), BO));
948965 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 ;
965966 case BO_And:
966967 return Discard (this ->emitBitAnd (*T, BO));
967968 case BO_Or:
@@ -1790,26 +1791,37 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
17901791 return this ->delegate (Inits[0 ]);
17911792
17921793 auto initPrimitiveField = [=](const Record::Field *FieldToInit,
1793- const Expr *Init, PrimType T) -> bool {
1794+ const Expr *Init, PrimType T,
1795+ bool Activate = false ) -> bool {
17941796 InitStackScope<Emitter> ISS (this , isa<CXXDefaultInitExpr>(Init));
17951797 InitLinkScope<Emitter> ILS (this , InitLink::Field (FieldToInit->Offset ));
17961798 if (!this ->visit (Init))
17971799 return false ;
17981800
1799- if (FieldToInit->isBitField ())
1801+ bool BitField = FieldToInit->isBitField ();
1802+ if (BitField && Activate)
1803+ return this ->emitInitBitFieldActivate (T, FieldToInit, E);
1804+ if (BitField)
18001805 return this ->emitInitBitField (T, FieldToInit, E);
1806+ if (Activate)
1807+ return this ->emitInitFieldActivate (T, FieldToInit->Offset , E);
18011808 return this ->emitInitField (T, FieldToInit->Offset , E);
18021809 };
18031810
18041811 auto initCompositeField = [=](const Record::Field *FieldToInit,
1805- const Expr *Init) -> bool {
1812+ const Expr *Init,
1813+ bool Activate = false ) -> bool {
18061814 InitStackScope<Emitter> ISS (this , isa<CXXDefaultInitExpr>(Init));
18071815 InitLinkScope<Emitter> ILS (this , InitLink::Field (FieldToInit->Offset ));
18081816
18091817 // Non-primitive case. Get a pointer to the field-to-initialize
18101818 // on the stack and recurse into visitInitializer().
18111819 if (!this ->emitGetPtrField (FieldToInit->Offset , Init))
18121820 return false ;
1821+
1822+ if (Activate && !this ->emitActivate (E))
1823+ return false ;
1824+
18131825 if (!this ->visitInitializer (Init))
18141826 return false ;
18151827 return this ->emitPopPtr (E);
@@ -1829,10 +1841,10 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
18291841
18301842 const Record::Field *FieldToInit = R->getField (FToInit);
18311843 if (std::optional<PrimType> T = classify (Init)) {
1832- if (!initPrimitiveField (FieldToInit, Init, *T))
1844+ if (!initPrimitiveField (FieldToInit, Init, *T, /* Activate= */ true ))
18331845 return false ;
18341846 } else {
1835- if (!initCompositeField (FieldToInit, Init))
1847+ if (!initCompositeField (FieldToInit, Init, /* Activate= */ true ))
18361848 return false ;
18371849 }
18381850 }
@@ -2023,7 +2035,8 @@ bool Compiler<Emitter>::visitArrayElemInit(unsigned ElemIndex, const Expr *Init,
20232035
20242036template <class Emitter >
20252037bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,
2026- const FunctionDecl *FuncDecl) {
2038+ const FunctionDecl *FuncDecl,
2039+ bool Activate) {
20272040 assert (VarScope->getKind () == ScopeKind::Call);
20282041 llvm::BitVector NonNullArgs = collectNonNullArgs (FuncDecl, Args);
20292042
@@ -2046,6 +2059,11 @@ bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,
20462059 return false ;
20472060 }
20482061
2062+ if (ArgIndex == 1 && Activate) {
2063+ if (!this ->emitActivate (Arg))
2064+ return false ;
2065+ }
2066+
20492067 if (FuncDecl && NonNullArgs[ArgIndex]) {
20502068 PrimType ArgT = classify (Arg).value_or (PT_Ptr);
20512069 if (ArgT == PT_Ptr) {
@@ -4227,10 +4245,13 @@ bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,
42274245 PrimType T = classifyPrim (D->getType ());
42284246 if (!this ->visitZeroInitializer (T, QT, E))
42294247 return false ;
4248+ if (R->isUnion ()) {
4249+ if (!this ->emitInitFieldActivate (T, Field.Offset , E))
4250+ return false ;
4251+ break ;
4252+ }
42304253 if (!this ->emitInitField (T, Field.Offset , E))
42314254 return false ;
4232- if (R->isUnion ())
4233- break ;
42344255 continue ;
42354256 }
42364257
@@ -4256,13 +4277,15 @@ bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,
42564277 } else
42574278 return false ;
42584279
4259- if (!this ->emitFinishInitPop (E))
4260- return false ;
4261-
42624280 // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
42634281 // 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 ;
42654285 break ;
4286+ }
4287+ if (!this ->emitFinishInitPop (E))
4288+ return false ;
42664289 }
42674290
42684291 for (const Record::Base &B : R->bases ()) {
@@ -4325,6 +4348,59 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
43254348 return false ;
43264349}
43274350
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+
43284404template <class Emitter >
43294405template <typename T>
43304406bool Compiler<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
@@ -5067,7 +5143,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
50675143 return false ;
50685144 }
50695145
5070- if (!this ->visitCallArgs (Args, FuncDecl))
5146+ if (!this ->visitCallArgs (Args, FuncDecl, IsAssignmentOperatorCall ))
50715147 return false ;
50725148
50735149 // Undo the argument reversal we did earlier.
@@ -5851,7 +5927,8 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
58515927 assert (!ReturnType);
58525928
58535929 auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset,
5854- const Expr *InitExpr) -> bool {
5930+ const Expr *InitExpr,
5931+ bool Activate = false ) -> bool {
58555932 // We don't know what to do with these, so just return false.
58565933 if (InitExpr->getType ().isNull ())
58575934 return false ;
@@ -5860,8 +5937,13 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
58605937 if (!this ->visit (InitExpr))
58615938 return false ;
58625939
5863- if (F->isBitField ())
5940+ bool BitField = F->isBitField ();
5941+ if (BitField && Activate)
5942+ return this ->emitInitThisBitFieldActivate (*T, F, FieldOffset, InitExpr);
5943+ if (BitField)
58645944 return this ->emitInitThisBitField (*T, F, FieldOffset, InitExpr);
5945+ if (Activate)
5946+ return this ->emitInitThisFieldActivate (*T, FieldOffset, InitExpr);
58655947 return this ->emitInitThisField (*T, FieldOffset, InitExpr);
58665948 }
58675949 // Non-primitive case. Get a pointer to the field-to-initialize
@@ -5870,6 +5952,9 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
58705952 if (!this ->emitGetPtrThisField (FieldOffset, InitExpr))
58715953 return false ;
58725954
5955+ if (Activate && !this ->emitActivate (InitExpr))
5956+ return false ;
5957+
58735958 if (!this ->visitInitializer (InitExpr))
58745959 return false ;
58755960
@@ -5880,8 +5965,9 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
58805965 const Record *R = this ->getRecord (RD);
58815966 if (!R)
58825967 return false ;
5968+ bool IsUnion = R->isUnion ();
58835969
5884- if (R-> isUnion () && Ctor->isCopyOrMoveConstructor ()) {
5970+ if (IsUnion && Ctor->isCopyOrMoveConstructor ()) {
58855971 if (R->getNumFields () == 0 )
58865972 return this ->emitRetVoid (Ctor);
58875973 // union copy and move ctors are special.
@@ -5908,7 +5994,7 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
59085994 if (const FieldDecl *Member = Init->getMember ()) {
59095995 const Record::Field *F = R->getField (Member);
59105996
5911- if (!emitFieldInitializer (F, F->Offset , InitExpr))
5997+ if (!emitFieldInitializer (F, F->Offset , InitExpr, IsUnion ))
59125998 return false ;
59135999 } else if (const Type *Base = Init->getBaseClass ()) {
59146000 const auto *BaseDecl = Base->getAsCXXRecordDecl ();
@@ -5928,11 +6014,15 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
59286014 return false ;
59296015 }
59306016
6017+ if (IsUnion && !this ->emitActivate (InitExpr))
6018+ return false ;
6019+
59316020 if (!this ->visitInitializer (InitExpr))
59326021 return false ;
59336022 if (!this ->emitFinishInitPop (InitExpr))
59346023 return false ;
59356024 } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember ()) {
6025+
59366026 assert (IFD->getChainingSize () >= 2 );
59376027
59386028 unsigned NestedFieldOffset = 0 ;
@@ -5944,12 +6034,14 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
59446034
59456035 NestedField = FieldRecord->getField (FD);
59466036 assert (NestedField);
6037+ IsUnion = IsUnion || FieldRecord->isUnion ();
59476038
59486039 NestedFieldOffset += NestedField->Offset ;
59496040 }
59506041 assert (NestedField);
59516042
5952- if (!emitFieldInitializer (NestedField, NestedFieldOffset, InitExpr))
6043+ if (!emitFieldInitializer (NestedField, NestedFieldOffset, InitExpr,
6044+ IsUnion))
59536045 return false ;
59546046
59556047 // Mark all chain links as initialized.
0 commit comments