diff --git a/src/google/protobuf/compiler/cpp/enum.cc b/src/google/protobuf/compiler/cpp/enum.cc index f889a0c4f023d..4caecc98749b6 100644 --- a/src/google/protobuf/compiler/cpp/enum.cc +++ b/src/google/protobuf/compiler/cpp/enum.cc @@ -319,14 +319,23 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* p) const { for (int j = 0; j < enum_->value_count(); ++j) { const auto* value = enum_->value(j); + const bool deprecated = value->options().deprecated(); p->Emit( { Sub("VALUE", EnumValueName(enum_->value(j))).AnnotatedAs(value), - {"DEPRECATED", - value->options().deprecated() ? "[[deprecated]]" : ""}, + {"DEPRECATED", deprecated ? "[[deprecated]]" : ""}, + // The alias initializer references the deprecated enumerator, so + // wrap it to avoid triggering -Wdeprecated-declarations in code the + // user does not control. See protocolbuffers/protobuf#18205. + {"IGNORE_DEPRECATION_START", + deprecated ? "PROTOBUF_IGNORE_DEPRECATION_START" : ""}, + {"IGNORE_DEPRECATION_STOP", + deprecated ? "PROTOBUF_IGNORE_DEPRECATION_STOP" : ""}, }, R"cc( + $IGNORE_DEPRECATION_START$ $DEPRECATED $static constexpr $Enum_$ $VALUE$ = $Msg_Enum$_$VALUE$; + $IGNORE_DEPRECATION_STOP$ )cc"); } diff --git a/src/google/protobuf/compiler/cpp/generator_unittest.cc b/src/google/protobuf/compiler/cpp/generator_unittest.cc index 06d3717e475de..e58ed4d57a848 100644 --- a/src/google/protobuf/compiler/cpp/generator_unittest.cc +++ b/src/google/protobuf/compiler/cpp/generator_unittest.cc @@ -376,6 +376,52 @@ TEST_F(CppGeneratorTest, CtypeOnExtensionTest) { "extensions"); } +TEST_F(CppGeneratorTest, DeprecatedNestedEnumValueImportIsNotSelfWarning) { + // The class-scoped alias for a deprecated nested enum value initializes + // itself from the deprecated enumerator, which would otherwise trigger + // -Wdeprecated-declarations in code the user does not control. The alias + // must be wrapped in the deprecation-suppression macros. + // Regression test for protocolbuffers/protobuf#18205. + CreateTempFile("foo.proto", R"schema( + syntax = "proto3"; + message Result { + enum Status { + UNSET = 0; + OK = 1 [deprecated = true]; + FAILED = 2; + } + })schema"); + + RunProtoc( + "protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectFileContentContainsSubstring( + "foo.pb.h", + "PROTOBUF_IGNORE_DEPRECATION_START\n" + " [[deprecated]] static constexpr Status OK = Result_Status_OK;\n" + " PROTOBUF_IGNORE_DEPRECATION_STOP"); +} + +TEST_F(CppGeneratorTest, NonDeprecatedEnumValueImportHasNoSuppression) { + // Enums without deprecated values must not emit suppression macros. + CreateTempFile("foo.proto", R"schema( + syntax = "proto3"; + message Result { + enum Status { + UNSET = 0; + OK = 1; + } + })schema"); + + RunProtoc( + "protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectFileContentNotContainsSubstring("foo.pb.h", + "PROTOBUF_IGNORE_DEPRECATION_START"); +} + } // namespace } // namespace cpp