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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits