protocolbuffers / protocolbuffers/protobuf

proto defined enums conflicts with globally defined variables using protoc cpp

Open
#8,953 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

c++ help wanted protoc
Dominant language
C++
Stars
72k
Forks
16.3k
Avg merge
1d 17h
Merged PRs (30d)
140

Description

What version of protobuf and what language are you using?
Version: master/v3.11.1 proto3 syntax.
Language: C++

What operating system (Linux, Windows, ...) and version?
Windows 10 Enterprise (v1909)

What runtime / compiler are you using (e.g., python version or gcc version)
vs2019 (v142), SDK 10.0.18362
What did you do?
Steps to reproduce the behavior:

Using globally defined names in enums in proto files conflicts with each other resulting in build errors. Here is an example:
Using the following enum type:

enum AlarmSeverityProto {
  SEVERITY_INFO = 0;
  SEVERITY_WARNING = 1;
  SEVERITY_ERROR = 2;
}

conflicts with a globally defined variable (SEVERITY_ERROR) defined in winerror.h which is included in one of the following header files:

#include <grpc/grpc.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>

Investigating the proto ph.h header file generated:

...
PROTOBUF_NAMESPACE_CLOSE
namespace NOV {
namespace Valhall {
namespace AlarmHandling {

enum AlarmSeverityProto : int {
  SEVERITY_INFO = 0,
  SEVERITY_WARNING = 1,
  SEVERITY_ERROR = 2,
  AlarmSeverityProto_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(),
  AlarmSeverityProto_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max()
};
bool AlarmSeverityProto_IsValid(int value);
constexpr AlarmSeverityProto AlarmSeverityProto_MIN = SEVERITY_INFO;
constexpr AlarmSeverityProto AlarmSeverityProto_MAX = SEVERITY_ERROR;
...
}}}

I can see that in the line constexpr AlarmSeverityProto AlarmSeverityProto_MAX = SEVERITY_ERROR;, SEVERITY_ERROR gets resolved to the global defined variable in winerror.h. I think this is weird behaviour as I would think the compiler would instead use the one defined in the namespace 🤷

Currently I have found 2 workarounds for this bug:

  1. Do a #undef SEVERITY_ERROR before including the grpc/proto core header files mentioned above.
  2. Insert the namespace of the enum in line constexpr AlarmSeverityProto AlarmSeverityProto_MAX = SEVERITY_ERROR; as the following constexpr AlarmSeverityProto AlarmSeverityProto_MAX = AlarmSeverityProto::SEVERITY_ERROR;

What did you expect to see

Expected it to use its own namespace defined enum instead of the global one.

What did you see instead?

It uses the global defined one.

Anything else we should know about your project / environment
Here is the error message I receive:
protolib_build_error.txt

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the conflict with the shown proto enum and the grpc/grpcpp headers on Windows, then inspect the generated header at the AlarmSeverityProto_MAX definition. The issue is done when generated C++ refers to the enum's own SEVERITY_ERROR value and the project builds without requiring a winerror.h workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, grpc
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.