[PATCH] D155175: [Clang] Fix consteval propagation for aggregates and defaulted constructors
Corentin Jabot via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 14 06:17:44 PDT 2023
cor3ntin added a comment.
In D155175#4498788 <https://reviews.llvm.org/D155175#4498788>, @efriedma wrote:
> Do we need CodeGen testcases here for full coverage? The testcases from the issue passed with -fsyntax-only.
>
> --------
>
> With this patch, the following cases produce errors that don't really make sense to me:
>
> consteval int f(int x) {
> return x;
> }
> struct SS {
> int y;
> int x = f(this->y);
> constexpr SS(int yy) : y(yy) {}
> };
> SS s = {1};
>
>
>
> <stdin>:6:13: error: call to consteval function 'f' is not a constant expression
> 6 | int x = f(this->y);
> | ^
> <stdin>:7:15: note: in the default initializer of 'x'
> 7 | constexpr SS(int yy) : y(yy) {}
> | ^
> <stdin>:6:5: note: declared here
> 6 | int x = f(this->y);
> | ^
> <stdin>:6:15: note: use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function
> 6 | int x = f(this->y);
> | ^
> 1 error generated.
This seems reasonable, it's equivalent to `constexpr SS(int yy) : y(yy), x(f(y)) {}` = which is not a valid call of a consteval function. And the constructor is neither defaulted, nor templated, so escalation does not happen.
I agree that "use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function" isn't amazing but it's preexisting
https://godbolt.org/z/sa78bzsed
> consteval int f(int x) {
> return x;
> }
> struct SS {
> int y;
> int x = f(this->y);
> consteval SS(int yy) : y(yy) {}
> };
> SS s = {1};
>
> <stdin>:6:13: error: cannot take address of consteval function 'f' outside of an immediate invocation
> 6 | int x = f(this->y);
> | ^
> <stdin>:1:15: note: declared here
> 1 | consteval int f(int x) {
> | ^
> 1 error generated.
Yup, this is not great - I think it's unrelated the degradation of error message was introduced between 15 and 16, I probably want to investigate in a separate patch, not sure yet.
> Somehow the following is accepted, though:
>
> consteval int f(int x) {
> return x;
> }
> struct SS {
> int y;
> int x = f(this->y);
> template<typename T> constexpr SS(T yy) : y(yy) {}
> };
> SS s = {1};
Yes, this is bad. Thanks for finding it.
It compiles because 1 is a constant and somehow it ends up evaluating f(1) instead of f(y) - replacing 1 by a reference to a local variable produce the expected behavior. Investigating.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D155175/new/
https://reviews.llvm.org/D155175
More information about the cfe-commits
mailing list