hsutter / cppfront

A personal experimental C++ Syntax 2 -> Syntax 1 compiler
Other
5.23k stars 224 forks source link

[BUG] string interpolation of certain types warns about "non-portable usage of variadic functions" #1136

Closed DyXel closed 1 week ago

DyXel commented 1 week ago

Describe the bug Title. This one has different effects on different compilers.

To Reproduce Steps to reproduce the behavior:

  1. Sample code - distilled down to minimal essentials please
    
    #include <filesystem>

my_enum: @enum type = { foo; bar; }

aaa: () -> std::string = { a := my_enum::foo; return "(a)$"; }

bbb: () -> std::string = { p: std::filesystem::path = (); return "(p)$"; }

main: () = std::cout << aaa() << bbb();

2. Command lines including which C++ compiler you are using
Clang 17: `-std=c++20 -Wall -Wextra -pedantic -Werror`
MSVC: `/std:c++latest /MD /EHsc /experimental:module /W4 /WX`
4. Expected result - what you expected to happen
I would expect these to compile on all compilers, they seem to work in GCC 14. But non-GCC compilers seem unhappy about it.
3. Actual result/error
On clang I get the following:

error: cannot pass object of non-trivial type 'typename std::remove_reference<my_enum &>::type' (aka 'my_enum') through variadic function; call will abort at runtime [-Wnon-pod-varargs] 63 | return { cpp2::to_string(cpp2::move(a)) }; | ^ 1 error generated.

On MSVC I get roughly:

error C2220: the following warning is treated as an error warning C4840: non-portable use of class 'std::filesystem::path' as an argument to a variadic function note: 'std::filesystem::path::path' is non-trivial note: see declaration of 'std::filesystem::path::path' note: the constructor and destructor will not be called; a bitwise copy of the class will be passed as the argument note: see declaration of 'std::filesystem::path'


So the `@enum` case seems to fail in clang (presumably because it defines a `to_string` member function?) and the `std::filesystem::path` case seems to fail on MSVC. This latter one I have no idea whats wrong.
**Additional context**
For the `@enum` case, calling `to_string` directly seems to workaround the issue, although that mostly makes the string interpolation redundant.

Initially I thought about opening an issue for each case, but they seem very related. Also I think these have to do with the definition at `cpp2util.h:1192`.
DyXel commented 1 week ago

Addendum: Clang always fails to compile this even if you don't turn up all the warnings. If you instead use -Wno-non-pod-varargs, it compiles, but once you execute the program it says: Illegal instruction.

hsutter commented 1 week ago

Thanks! Fixed... now the first case works as expected, and the second case gives the correct "not customized" message for filesystem::path.

That said, I could see adding support for "anything you can stream with << by pushing it through a stringstream" and I've added a code comment for that, but the naive overload creates ambiguities with other overloads so I think the right thing is to change those core to_string overloads into a single function with if constexpr alternatives (as @filipsajdak did with is, thanks again Filip!) and then it should work fine... I just didn't have time to do that today.

DyXel commented 1 week ago

Thanks. I think the crashes were related to the fact that auto to_string(...) uses the old vararg stuff from C. So the compiler was right about warning for that.

For the std::filesystem::path one, I was getting very frustrated because I thought that ought to work, and in fact, the documentation says that it has operator string_type(), what is not obvious is the fact that string_type is probably not the regular std::string but std::wstring on Windows, so yeah...