diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1534,6 +1534,7 @@ APValue::LValueBase Base; CharUnits Offset; SubobjectDesignator Designator; + const Expr *LExpr = nullptr; bool IsNullPtr : 1; bool InvalidBase : 1; @@ -1542,6 +1543,7 @@ const CharUnits &getLValueOffset() const { return Offset; } SubobjectDesignator &getLValueDesignator() { return Designator; } const SubobjectDesignator &getLValueDesignator() const { return Designator;} + const Expr *getExpr() const { return LExpr; } bool isNullPointer() const { return IsNullPtr;} unsigned getLValueCallIndex() const { return Base.getCallIndex(); } @@ -1579,6 +1581,8 @@ Offset = CharUnits::fromQuantity(0); InvalidBase = BInvalid; Designator = SubobjectDesignator(getType(B)); + if (!LExpr) + LExpr = B.dyn_cast(); IsNullPtr = false; } @@ -6077,8 +6081,11 @@ if (!handleTrivialCopy(Info, MD->getParamDecl(0), Args[0], RHSValue, MD->getParent()->isUnion())) return false; + const Expr *LHS = This->getExpr(); + if (!LHS) + return false; if (Info.getLangOpts().CPlusPlus20 && MD->isTrivial() && - !HandleUnionActiveMemberChange(Info, Args[0], *This)) + !HandleUnionActiveMemberChange(Info, LHS, *This)) return false; if (!handleAssignment(Info, Args[0], *This, MD->getThisType(), RHSValue)) @@ -8039,6 +8046,11 @@ LValueExprEvaluator(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) : LValueExprEvaluatorBaseTy(Info, Result, InvalidBaseOK) {} + bool evaluate(const Expr *E) { + Result.LExpr = E; + return Visit(E); + } + bool VisitVarDecl(const Expr *E, const VarDecl *VD); bool VisitUnaryPreIncDec(const UnaryOperator *UO); @@ -8100,7 +8112,7 @@ assert(!E->isValueDependent()); assert(E->isGLValue() || E->getType()->isFunctionType() || E->getType()->isVoidType() || isa(E)); - return LValueExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); + return LValueExprEvaluator(Info, Result, InvalidBaseOK).evaluate(E); } bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { @@ -8571,6 +8583,8 @@ : ExprEvaluatorBaseTy(info), Result(Result), InvalidBaseOK(InvalidBaseOK) {} + bool evaluate(const Expr *E) { return Visit(E); } + bool Success(const APValue &V, const Expr *E) { Result.setFrom(Info.Ctx, V); return true; @@ -8680,7 +8694,7 @@ bool InvalidBaseOK) { assert(!E->isValueDependent()); assert(E->isPRValue() && E->getType()->hasPointerRepresentation()); - return PointerExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); + return PointerExprEvaluator(Info, Result, InvalidBaseOK).evaluate(E); } bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -1447,3 +1447,11 @@ constexpr bool b = [a = S(), b = S()] { return a.p == b.p; }(); static_assert(!b); } + +namespace PR45879 { +struct Base { + int m; +}; +struct Derived : Base {}; +constexpr int k = ((Base{} = Derived{}), 0); +} // namespace PR45879