On Thu, 30 May 2019 at 04:31, Stephan Bergmann via cfe-commits < cfe-commits@lists.llvm.org> wrote:
> On 22/05/2019 01:15, Richard Smith via cfe-commits wrote: > > Author: rsmith > > Date: Tue May 21 16:15:20 2019 > > New Revision: 361329 > > > > URL: http://llvm.org/viewvc/llvm-project?rev=361329&view=rev > > Log: > > [c++20] P1330R0: permit simple-assignments that change the active member > > of a union within constant expression evaluation. > [...] > > --- cfe/trunk/lib/AST/ExprConstant.cpp (original) > > +++ cfe/trunk/lib/AST/ExprConstant.cpp Tue May 21 16:15:20 2019 > [...]> @@ -4888,6 +4916,159 @@ static bool HandleDynamicCast(EvalInfo & > [...] > > +/// Handle a builtin simple-assignment or a call to a trivial assignment > > +/// operator whose left-hand side might involve a union member access. > If it > > +/// does, implicitly start the lifetime of any accessed union elements > per > > +/// C++20 [class.union]5. > > +static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr > *LHSExpr, > > + const LValue &LHS) { > > + if (LHS.InvalidBase || LHS.Designator.Invalid) > > + return false; > > + > > + llvm::SmallVector<std::pair<unsigned, const FieldDecl*>, 4> > UnionPathLengths; > > + // C++ [class.union]p5: > > + // define the set S(E) of subexpressions of E as follows: > > + const Expr *E = LHSExpr; > > + unsigned PathLength = LHS.Designator.Entries.size(); > > + while (E) { > > + // -- If E is of the form A.B, S(E) contains the elements of > S(A)... > > + if (auto *ME = dyn_cast<MemberExpr>(E)) { > > + auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()); > > + if (!FD) > > + break; > > + > > + // ... and also contains A.B if B names a union member > > + if (FD->getParent()->isUnion()) > > + UnionPathLengths.push_back({PathLength - 1, FD}); > > + > > + E = ME->getBase(); > > + --PathLength; > > + assert(declaresSameEntity(FD, > > + LHS.Designator.Entries[PathLength] > > + .getAsBaseOrMember().getPointer())); > > + > > + // -- If E is of the form A[B] and is interpreted as a built-in > array > > + // subscripting operator, S(E) is [S(the array operand, if > any)]. > > + } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) { > > + // Step over an ArrayToPointerDecay implicit cast. > > + auto *Base = ASE->getBase()->IgnoreImplicit(); > > + if (!Base->getType()->isArrayType()) > > + break; > > + > > + E = Base; > > + --PathLength; > > + > > + } else if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) { > > + // Step over a derived-to-base conversion. > > + if (ICE->getCastKind() == CK_NoOp) > > + continue; > > + if (ICE->getCastKind() != CK_DerivedToBase && > > + ICE->getCastKind() != CK_UncheckedDerivedToBase) > > + break; > > + for (const CXXBaseSpecifier *Elt : ICE->path()) { > > + --PathLength; > > + assert(declaresSameEntity(Elt->getType()->getAsCXXRecordDecl(), > > + LHS.Designator.Entries[PathLength] > > + > .getAsBaseOrMember().getPointer())); > > the above assert fires for the below test.cc with `clang++ -std=c++2a > -fsyntax-only test.cc`: > > > struct S1 { int n; }; > > struct S2: S1 {}; > > struct S3: S2 {}; > > void f() { > > S3 s; > > s.n = 0; > > } > Thanks for the great testcase, fixed in r362147.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits