sepavloff created this revision. sepavloff added a reviewer: rsmith. sepavloff requested review of this revision. Herald added a project: clang.
Class LValue keeps result of lvalue evaluation. In some analyses it is also necessary to have access to the original expression. This change adds new member to LValue to keep the expression and initializes this member when an lvalue is evaluated using LValueExprEvaluator. With this change LHS expression becomes available in HandleUnionActiveMemberChange and it becomes possible to fix PR45879. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D103395 Files: clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/constant-expression-cxx2a.cpp Index: clang/test/SemaCXX/constant-expression-cxx2a.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ 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 Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ 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<const Expr *>(); 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<ObjCSelectorExpr>(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->isRValue() && E->getType()->hasPointerRepresentation()); - return PointerExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); + return PointerExprEvaluator(Info, Result, InvalidBaseOK).evaluate(E); } bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
Index: clang/test/SemaCXX/constant-expression-cxx2a.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ 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 Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ 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<const Expr *>(); 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<ObjCSelectorExpr>(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->isRValue() && E->getType()->hasPointerRepresentation()); - return PointerExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); + return PointerExprEvaluator(Info, Result, InvalidBaseOK).evaluate(E); } bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits