[PATCH] D103395: PR45879: Keep evaluated expression in LValue object
Serge Pavlov via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 13 02:50:32 PST 2022
sepavloff added a comment.
P1330R0 (https://wg21.link/P1330R0) allowed changing the active member of a union in constexpr expressions. To implement it the Constant Evaluator starting from
https://github.com/llvm/llvm-project/commit/31c69a3d6363463c08b86914c0c8cfc5c929c37e checks if an assignment changes active member of a union. This is why a change proposed for union only affects compilation of code that does not contain unions at all. The issue is in the assignment treatment.
The check is made by the function `HandleUnionActiveMemberChange`, which is called from `VisitBinAssign` and `HandleFunctionCall`, they handle builtin and trivial assignment operators respectively. The check is made according to the rule specified in the standard (http://eel.is/c++draft/class.union#general-6), which is based on syntactic form. Constant evaluator on the other hand uses objects of class `APValue` and related `LValue` to make the evaluations. In some cases it is not possible to get `Expr` used for the evaluation.
Consider slightly modified test case provided in the bug report:
struct Base { int m; };
struct Derived : Base {};
constexpr int func_01(int x) {
Base v1{1};
Derived v2{x};
v1 = v2;
return v1.m;
}
constexpr int k = func_01(0);
When Constant Evaluator evaluates the expression `v1 = v2`, it eventually calls `LValueExprEvaluator::handleCallExpr` as this expression is a call of assignment operator. This is a method call, so the function evaluates the object reference, an `LValue`, which represents `v1` as `ValueDecl`. Then `HandleFunctionCall` is called, provided with the `LValue` for `v1` and an expression for `v2`. This function calls `HandleUnionActiveMemberChange`, which checks if the assignment changes an union active member.
`HandleUnionActiveMemberChange` makes the check according to the standard, so it needs `v1` in the form of expression. However, `v1` is represented by `LValue` in `HandleFunctionCall`, which contains `ValueDecl` and the original expression is unavailable. It makes the check impossible.
To make the check `HandleUnionActiveMemberChange` must be provided by the expression representing `v1`. A simple solution proposed here is to keep the original expression in `LValue`. It is set when `LValue` is evaluated when by `LValueExprEvaluator` in its method `Evaluate`. If the evaluation produces `LValue` based on something other than an expression, the reference to the original method remains in that `LValue` and may be used when the original expression is required.
The obtained solution is low-invasive. Actually only the changes in `LValueExprEvaluator::Evaluate` and `Lvalue::set` are essential for maintaining expression reference in `LValue`, and the change in `HandleUnionActiveMemberChange` is the only usage of it.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D103395/new/
https://reviews.llvm.org/D103395
More information about the cfe-commits
mailing list