[BUG] Issue with the newly added "identifier : const = value " functionality
HALL9kv0 opened this issue · comments
Describe the bug
The identifier : const = value functionality is not consistent. 1) Doesn't work at all in global/namespace scope (might be a feature, not a bug) and 2) it results in a g++ error when trying to initialize an std::array, even though it is used inside the main scope (probably a bug).
To Reproduce
A) The following works:
N : const int =2;
main: () -> int = {
arr: std::array<int,N> =();
}
B) This one also works:
main: () -> int = {
N : const =2;
}
C) The following results to a cppfront error :
N : const =2;
main: () -> int = {
arr: std::array<int,N> =();
}
error: namespace scope objects must have a concrete type, not a deduced type
D) Then when I make the declaration inside the main function scope, it compiles to cpp but we get a g++ error.
main: () -> int = {
N : const =2;
arr: std::array<int,N> =();
}
error: the value of ‘N’ is not usable in a constant expression
7 | arr: std::array<int,N> =();
| ~~~~~~~~~~^~
main.cpp2:5:6: note: ‘int N’ is not const
5 | N : const =2;
| ^
main.cpp2:7:29: note: in template argument for type ‘long unsigned int’
7 | arr: std::array<int,N> =();
and the cpp file is :
[[nodiscard]] auto main() -> int{
auto N {2};
std::array<int,cpp2::move(N)> arr {};
}
Command lines including which C++ compiler you are using:
cppfront -p main.cpp2 && g++ -std=c++23 main.cpp
Expected result
The auto N {2};
to be a const in the cpp file.
As a user, I expected to be able to write N: const =2 in the global/namespace scope also, and to be able to use it to initialize the std::array.
If I'm not mistaken, case D is indeed a bug, but case C is a feature, as namespace objects cannot have a deduced type.
Should we have an exception to the rule regarding the C case, when the expression is const/constexpr?
Just to expand on case D) above, this Cpp2:
main: () -> int = {
a: const _ = 1;
b: const = 2;
}
lowers to:
[[nodiscard]] auto main() -> int{
auto const a {1};
auto b {2};
}
Repro on Godbolt
From my closed pr (referring to case D):
d0836be suppresses the error, but returning a default object drops the pc_qualifiers.
Due to cppfront's being a backtracking parser, it does the hokey pokey, entering and exiting parse sections until it's successful, and with my adjustment of defaulting to return the built up type_id node all the time, the parser gets thrown off in the instances where it is just testing waters by trying to parse a type id. It would be nice to convert cppfront to a predictive parser (nothing in the grammar stands out as an obstacle), but at this stage, that would be quite the undertaking.
The identifier : const = value functionality is not consistent. 1) Doesn't work at all in global/namespace scope (might be a feature, not a bug)
Correct, as the error message says, no deduced type at global/namespace scope. You get the same error for N := 2
.
Thanks! These are not really related to the const
change, they are about other rules:
C) The following results to a cppfront error :
N : const =2; main: () -> int = { arr: std::array<int,N> =(); }
error: namespace scope objects must have a concrete type, not a deduced type
Correct, this is as intended. Namespace-scope objects cannot have deduced types (for various reasons including order independence), and writing just const
still requests to deduce the type.
D) Then when I make the declaration inside the main function scope, it compiles to cpp but we get a g++ error.
main: () -> int = { N : const =2; arr: std::array<int,N> =(); }
Correct, this one is just because you can't use a run-time object as a compile-time template argument. The fix is easy though... just as in Cpp1 you'd have to write constexpr
on the declaration of N
, in Cpp2 you change =
to ==
(pronounced "is always equal to") which does the same thing and emits constexpr
, and then you don't need the const
because it's implied by ==
. This code works fine:
main: () = {
N :== 2;
arr: std::array<int,N> =();
}
Thanks again for the good questions!
@hsutter #1138 (comment) is still a separate issue.
Reopening for this (thanks Neil, and Greg for remind me):
main: () -> int = { a: const _ = 1; b: const = 2; }lowers to:
[[nodiscard]] auto main() -> int{ auto const a {1}; auto b {2}; }
Now that's fixed too, thanks!