sepavloff updated this revision to Diff 386823.
sepavloff added a comment.
Update the patch
- Use more careful check for LHS expression,
- Make a bit more precise LHS expression tracking,
- Add comments,
- Add the test from discussion.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D103395/new/
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,22 @@
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);
+
+struct sub {
+ char data;
+};
+struct main2 {
+ constexpr main2() {
+ member = {};
+ }
+ sub member;
+};
+constexpr main2 a{};
+} // namespace PR45879
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -1546,6 +1546,7 @@
APValue::LValueBase Base;
CharUnits Offset;
SubobjectDesignator Designator;
+ const Expr *LExpr = nullptr;
bool IsNullPtr : 1;
bool InvalidBase : 1;
@@ -1554,6 +1555,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(); }
@@ -1591,6 +1593,8 @@
Offset = CharUnits::fromQuantity(0);
InvalidBase = BInvalid;
Designator = SubobjectDesignator(getType(B));
+ if (const Expr *E = B.dyn_cast<const Expr *>())
+ LExpr = E;
IsNullPtr = false;
}
@@ -5893,11 +5897,17 @@
/// 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.
+/// Returns true if the assignment is OK and it may be processed further.
static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
const LValue &LHS) {
if (LHS.InvalidBase || LHS.Designator.Invalid)
return false;
+ // If no LHS expression was specified, assume the LHS cannot be an assignment
+ // to a union member.
+ if (!LHSExpr)
+ return true;
+
llvm::SmallVector<std::pair<unsigned, const FieldDecl*>, 4> UnionPathLengths;
// C++ [class.union]p5:
// define the set S(E) of subexpressions of E as follows:
@@ -6101,7 +6111,7 @@
MD->getParent()->isUnion()))
return false;
if (Info.getLangOpts().CPlusPlus20 && MD->isTrivial() &&
- !HandleUnionActiveMemberChange(Info, Args[0], *This))
+ !HandleUnionActiveMemberChange(Info, This->getExpr(), *This))
return false;
if (!handleAssignment(Info, Args[0], *This, MD->getThisType(),
RHSValue))
@@ -8058,10 +8068,20 @@
namespace {
class LValueExprEvaluator
: public LValueExprEvaluatorBase<LValueExprEvaluator> {
+ friend class LValueExprEvaluatorBase<LValueExprEvaluator>;
+ friend class ExprEvaluatorBase<LValueExprEvaluator>;
+ friend class ConstStmtVisitor<LValueExprEvaluator, bool>;
+ friend class StmtVisitorBase<llvm::make_const_ptr, LValueExprEvaluator, bool>;
public:
LValueExprEvaluator(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) :
LValueExprEvaluatorBaseTy(Info, Result, InvalidBaseOK) {}
+ bool Evaluate(const Expr *E) {
+ Result.LExpr = E;
+ return Visit(E);
+ }
+
+protected:
bool VisitVarDecl(const Expr *E, const VarDecl *VD);
bool VisitUnaryPreIncDec(const UnaryOperator *UO);
@@ -8123,7 +8143,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) {
@@ -8424,7 +8444,7 @@
// C++17 onwards require that we evaluate the RHS first.
APValue RHS;
- if (!Evaluate(RHS, this->Info, CAO->getRHS())) {
+ if (!::Evaluate(RHS, this->Info, CAO->getRHS())) {
if (!Info.noteFailure())
return false;
Success = false;
@@ -8448,7 +8468,7 @@
// C++17 onwards require that we evaluate the RHS first.
APValue NewVal;
- if (!Evaluate(NewVal, this->Info, E->getRHS())) {
+ if (!::Evaluate(NewVal, this->Info, E->getRHS())) {
if (!Info.noteFailure())
return false;
Success = false;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits