cppfront icon indicating copy to clipboard operation
cppfront copied to clipboard

[BUG] Issue with the newly added "identifier : const = value " functionality

Open HALL9kv0 opened this issue 1 year ago • 3 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?

HALL9kv0 avatar Jun 23 '24 19:06 HALL9kv0

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

bluetarpmedia avatar Jun 23 '24 23:06 bluetarpmedia

From my closed pr (referring to case D): https://github.com/hsutter/cppfront/commit/d0836be2bff6a65d6ffb081a3d4cb14ccc49c25f 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.

sookach avatar Jun 24 '24 17:06 sookach

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.

gregmarr avatar Jul 03 '24 19:07 gregmarr

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 avatar Jul 12 '24 16:07 hsutter

@hsutter https://github.com/hsutter/cppfront/issues/1138#issuecomment-2185361702 is still a separate issue.

gregmarr avatar Jul 12 '24 16:07 gregmarr

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}; 
}

hsutter avatar Jul 12 '24 17:07 hsutter

Now that's fixed too, thanks!

hsutter avatar Jul 12 '24 17:07 hsutter