[PATCH] D103395: PR45879: Keep evaluated expression in LValue object

Serge Pavlov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon May 31 04:09:07 PDT 2021


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) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D103395.348765.patch
Type: text/x-patch
Size: 3540 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210531/9e58ce59/attachment.bin>


More information about the cfe-commits mailing list