Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot compile c++ generated code #8484

Closed
Eddie-cz opened this issue Apr 13, 2021 · 17 comments
Closed

cannot compile c++ generated code #8484

Eddie-cz opened this issue Apr 13, 2021 · 17 comments

Comments

@Eddie-cz
Copy link
Contributor

Version: 3.15.8
Language: C++
Windows 10, MSVC 16.9.3 with clang-cl compiler (LLVM 11.1)

Message definition:
syntax = "proto3";
message StringMsg
{
string value = 1;
}

Compilation of generated pb.cc fails for this message with "error : variable does not have a constant initializer".
Compiles with repeated modifier.

Variable is:
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT StringMsgDefaultTypeInternal StringMsg_default_instance;

@TeBoring
Copy link
Contributor

Do you see if there is a constexpr constructor for StringMsgDefaultTypeInternal in .pb.cc?

@TeBoring
Copy link
Contributor

Could you also paste the full error log?

@Eddie-cz
Copy link
Contributor Author

Eddie-cz commented Apr 22, 2021

There is constexpr constructor, code compiles fine with msvc compiler, only clang-cl (both 11.1 or 12.0) thinks this message variable doesn't satisfy constinit restrictions introduced by PROTOBUF_CONSTINIT (guess it has problems with string type).
Should I put repeated modifier for that string param, or manualy remove PROTOBUF_CONSTINIT from pb.cc, it compiles fine.
Log:
etherCATMessages.pb.cc(114,79): error : variable does not have a constant initializer
etherCATMessages.pb.cc(114,31): message : required by 'require_constant_initialization' attribute here
protobuf\3.15.8\include\google/protobuf/port_def.inc(571,30): message : expanded from macro 'PROTOBUF_CONSTINIT'

@TeBoring
Copy link
Contributor

https://godbolt.org/z/75rfhqY4E
I cannot reproduce it in the godbolt. Could you help advice a reproduce?

@TeBoring
Copy link
Contributor

https://godbolt.org/z/j9nv47n5P
Still no error

@Eddie-cz
Copy link
Contributor Author

Eddie-cz commented Apr 26, 2021

Issue is isolated to
PROTOBUF_CONSTINIT google::protobuf::internal::ArenaStringPtr sptr(&google::protobuf::internal::fixed_address_empty_string);
Same error as described above. To reproduce, you must define your ExplicitlyConstructed<std::string> empty_string variable; in different compilation unit, in this case in different dll, same as it's for protobuf variables. When I test your code in one compilation unit, it's ok, problem is with protobuf dll usage.

@ngg
Copy link
Contributor

ngg commented May 26, 2021

We ran into the same problem.
If I try to compile libprotobuf into a dll, and compile the protoc executable that uses this dll with clang-cl, then I get an error like this from plugin.pb.cc:

error: variable does not have a constant initializer
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT VersionDefaultTypeInternal _Version_default_instance_;

I tried using protobuf 3.15.2 and 3.17.1

@sbenzaquen
Copy link
Contributor

It seems to be an interaction between __declspec(dllimport) and constant initialization.
I can't test with clang-cl, so my tests below are with MSVC.

If I write:

__declspec(dllimport) extern int x;
auto& p = x;

then p is dynamically initialized (at least in the latest MSVC)
If the symbol is not dllimport, then p is constant initialized as expected.

I think what's happening is that clang is following this behavior but since it also supports the [[clang::require_constant_initialization]] attribute it is failing there because it is indeed not constant initialized.

We might want to disable the attribute in clang-for-windows.
The attribute is not required for correctness. It is there mostly to make sure we really are constant initialized in the platforms that support it for code size efficiency.

@ngg
Copy link
Contributor

ngg commented May 26, 2021

I also checked that if I compile with clang in C++20 mode, then constinit is used, and the same error still appears.
I did not check what happens with MSVC, but if C++20 is enabled (using /std:c++latest) and constinit is used then I think it wouldn't compile either. (clang seems to be right, this is not supposed to work as constantly initialized on Windows)

@sbenzaquen
Copy link
Contributor

I don't know about that.

This works fine:

__declspec(dllimport) extern int x;
constexpr auto& p = x;

So it can do constant initialization for it, but it just chooses not to when constexpr is not there.
tbh, I don't know enough about the semantics of dllexport/dllimport.

@kelteseth
Copy link

I can confirm this issue with clang 12 on Windows.

manualy remove PROTOBUF_CONSTINIT from pb.cc, it compiles fine.

This fixes the problem for me

@mmurrian
Copy link

We might want to disable the attribute in clang-for-windows.

That was my solution. I changed line 571 of port_def.inc to:
#if !defined(_MSC_VER) && __has_cpp_attribute(clang::require_constant_initialization)

Same problem on Visual Studio 2019, clang-cl, Windows.

@Eddie-cz
Copy link
Contributor Author

Will make pull request as suggested by mmurrian, kinda suprised multiple versions were released in last 6 month and nobody was concerned with fact that library is producing not compilable code under msvc clang-cl environment.

@acozzette
Copy link
Member

acozzette commented Sep 22, 2021

This should be fixed now with #8993.

@martenrichter
Copy link

martenrichter commented Jul 9, 2022

I am currently trying to build libquiche for windows with a cmake build and clang as compiler.
The patch seems to be removed from the repository.
And I am getting:
....webtransport\third_party\quiche\quiche\quic\core\proto\cached_network_parameters.pb.cc(40,127): error : variable does not have a constant initializer [...webtransport\build\gquiche.vcxproj] ....third_party\quiche\quiche\quic\core\proto\cached_network_parameters.pb.cc(40,31): message : required by 'require_constant_initialization' attribute here [...webtransport\build\gquiche.vcxproj] C:\vcpkg\installed\x64-windows\include\google/protobuf/port_def.inc(651,30): message : expanded from macro 'PROTOBUF_CONSTINIT' [...webtransport\build\gquiche.vcxproj]
If I patch port_def.inc analog to the previous patch:
#elif !defined(_MSC_VER) && __has_cpp_attribute(clang::require_constant_initialization) && \ ((defined(__APPLE__) && __clang_major__ >= 13) || \ (!defined(__APPLE__) && __clang_major__ >= 12))
it is fixed again.
Can you consider adding this check again?

@Eddie-cz
Copy link
Contributor Author

Eddie-cz commented Jul 9, 2022

Yey, this is getting ridiculous more and more. I made another pull request, it is not approved yet. #10232

@martenrichter
Copy link

@Eddie-cz: Thanks for making the new PR, it much better then mine, and yes using protocol buffers on windows is pretty complicated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants