r361329 - [c++20] P1330R0: permit simple-assignments that change the active member

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Thu May 30 13:42:42 PDT 2019


On Thu, 30 May 2019 at 04:31, Stephan Bergmann via cfe-commits <
cfe-commits at 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190530/baf7a9e8/attachment.html>


More information about the cfe-commits mailing list