diff --git a/src/google/protobuf/compiler/cpp/field.cc b/src/google/protobuf/compiler/cpp/field.cc index a8a73ecd677aa..8c357cfbaff92 100644 --- a/src/google/protobuf/compiler/cpp/field.cc +++ b/src/google/protobuf/compiler/cpp/field.cc @@ -43,6 +43,8 @@ std::vector FieldVars(const FieldDescriptor* field, const Options& opts) { // This will eventually be renamed to "field", once the existing "field" // variable is replaced with "field_" everywhere. {"name", FieldName(field)}, + // Same as above, but represents internal use. + {"name_internal", FieldName(field)}, {"index", field->index()}, {"number", field->number()}, diff --git a/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc b/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc index ffcf3dce90926..8924bef438c8b 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc @@ -174,7 +174,7 @@ void CordFieldGenerator::GenerateInlineAccessorDefinitions( io::Printer* printer) const { auto v = printer->WithVars(variables_); printer->Emit(R"cc( - inline const ::absl::Cord& $classname$::_internal_$name$() const { + inline const ::absl::Cord& $classname$::_internal_$name_internal$() const { return $field$; } )cc"); @@ -183,18 +183,20 @@ void CordFieldGenerator::GenerateInlineAccessorDefinitions( ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_get$; // @@protoc_insertion_point(field_get:$full_name$) - return _internal_$name$(); + return _internal_$name_internal$(); } )cc"); printer->Emit(R"cc( - inline void $classname$::_internal_set_$name$(const ::absl::Cord& value) { + inline void $classname$::_internal_set_$name_internal$( + const ::absl::Cord& value) { $set_hasbit$; $field$ = value; } )cc"); printer->Emit(R"cc( inline void $classname$::set_$name$(const ::absl::Cord& value) { - $PrepareSplitMessageForWrite$ _internal_set_$name$(value); + $PrepareSplitMessageForWrite$; + _internal_set_$name_internal$(value); $annotate_set$; // @@protoc_insertion_point(field_set:$full_name$) } @@ -209,7 +211,7 @@ void CordFieldGenerator::GenerateInlineAccessorDefinitions( } )cc"); printer->Emit(R"cc( - inline ::absl::Cord* $classname$::_internal_mutable_$name$() { + inline ::absl::Cord* $classname$::_internal_mutable_$name_internal$() { $set_hasbit$; return &$field$; } @@ -333,7 +335,7 @@ void CordOneofFieldGenerator::GenerateInlineAccessorDefinitions( io::Printer* printer) const { auto v = printer->WithVars(variables_); printer->Emit(R"cc( - inline const ::absl::Cord& $classname$::_internal_$name$() const { + inline const ::absl::Cord& $classname$::_internal_$name_internal$() const { if ($has_field$) { return *$field$; } @@ -345,14 +347,14 @@ void CordOneofFieldGenerator::GenerateInlineAccessorDefinitions( ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_get$; // @@protoc_insertion_point(field_get:$full_name$) - return _internal_$name$(); + return _internal_$name_internal$(); } )cc"); printer->Emit(R"cc( inline void $classname$::set_$name$(const ::absl::Cord& value) { if ($not_has_field$) { clear_$oneof_name$(); - set_has_$name$(); + set_has_$name_internal$(); $field$ = new ::absl::Cord; ::$proto_ns$::Arena* arena = GetArena(); if (arena != nullptr) { @@ -368,7 +370,7 @@ void CordOneofFieldGenerator::GenerateInlineAccessorDefinitions( inline void $classname$::set_$name$(::absl::string_view value) { if ($not_has_field$) { clear_$oneof_name$(); - set_has_$name$(); + set_has_$name_internal$(); $field$ = new ::absl::Cord; ::$proto_ns$::Arena* arena = GetArena(); if (arena != nullptr) { @@ -381,10 +383,10 @@ void CordOneofFieldGenerator::GenerateInlineAccessorDefinitions( } )cc"); printer->Emit(R"cc( - inline ::absl::Cord* $classname$::_internal_mutable_$name$() { + inline ::absl::Cord* $classname$::_internal_mutable_$name_internal$() { if ($not_has_field$) { clear_$oneof_name$(); - set_has_$name$(); + set_has_$name_internal$(); $field$ = new ::absl::Cord; ::$proto_ns$::Arena* arena = GetArena(); if (arena != nullptr) { diff --git a/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc b/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc index 1b5287960a0ef..8f3a7f1d56650 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc @@ -167,7 +167,7 @@ void SingularEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { inline $Enum$ $Msg$::$name$() const { $annotate_get$; // @@protoc_insertion_point(field_get:$pkg.Msg.field$) - return _internal_$name$(); + return _internal_$name_internal$(); } )cc"); @@ -178,13 +178,13 @@ void SingularEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { $assert_valid$; if ($not_has_field$) { clear_$oneof_name$(); - set_has_$name$(); + set_has_$name_internal$(); } $field_$ = value; $annotate_set$; // @@protoc_insertion_point(field_set:$pkg.Msg.field$) } - inline $Enum$ $Msg$::_internal_$name$() const { + inline $Enum$ $Msg$::_internal_$name_internal$() const { if ($has_field$) { return static_cast<$Enum$>($field_$); } @@ -195,16 +195,16 @@ void SingularEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { p->Emit(R"cc( inline void $Msg$::set_$name$($Enum$ value) { $PrepareSplitMessageForWrite$; - _internal_set_$name$(value); + _internal_set_$name_internal$(value); $set_hasbit$; $annotate_set$; // @@protoc_insertion_point(field_set:$pkg.Msg.field$) } - inline $Enum$ $Msg$::_internal_$name$() const { + inline $Enum$ $Msg$::_internal_$name_internal$() const { $TsanDetectConcurrentRead$; return static_cast<$Enum$>($field_$); } - inline void $Msg$::_internal_set_$name$($Enum$ value) { + inline void $Msg$::_internal_set_$name_internal$($Enum$ value) { $TsanDetectConcurrentMutation$; $assert_valid$; $field_$ = value; @@ -400,13 +400,13 @@ void RepeatedEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { inline $Enum$ $Msg$::$name$(int index) const { $annotate_get$; // @@protoc_insertion_point(field_get:$pkg.Msg.field$) - return static_cast<$Enum$>(_internal_$name$().Get(index)); + return static_cast<$Enum$>(_internal_$name_internal$().Get(index)); } )cc"); p->Emit(R"cc( inline void $Msg$::set_$name$(int index, $Enum$ value) { $assert_valid$; - _internal_mutable_$name$()->Set(index, value); + _internal_mutable_$name_internal$()->Set(index, value); $annotate_set$ // @@protoc_insertion_point(field_set:$pkg.Msg.field$) } @@ -415,7 +415,7 @@ void RepeatedEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { inline void $Msg$::add_$name$($Enum$ value) { $assert_valid$; $TsanDetectConcurrentMutation$; - _internal_mutable_$name$()->Add(value); + _internal_mutable_$name_internal$()->Add(value); $annotate_add$ // @@protoc_insertion_point(field_add:$pkg.Msg.field$) } @@ -425,7 +425,7 @@ void RepeatedEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_list$; // @@protoc_insertion_point(field_list:$pkg.Msg.field$) - return _internal_$name$(); + return _internal_$name_internal$(); } )cc"); p->Emit(R"cc( @@ -434,16 +434,17 @@ void RepeatedEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { $annotate_mutable_list$; // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$) $TsanDetectConcurrentMutation$; - return _internal_mutable_$name$(); + return _internal_mutable_$name_internal$(); } )cc"); if (should_split()) { p->Emit(R"cc( - inline const $pb$::RepeatedField& $Msg$::_internal_$name$() const { + inline const $pb$::RepeatedField& $Msg$::_internal_$name_internal$() + const { $TsanDetectConcurrentRead$; return *$field_$; } - inline $pb$::RepeatedField* $Msg$::_internal_mutable_$name$() { + inline $pb$::RepeatedField* $Msg$::_internal_mutable_$name_internal$() { $TsanDetectConcurrentRead$; $PrepareSplitMessageForWrite$; if ($field_$.IsDefault()) { @@ -455,11 +456,12 @@ void RepeatedEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { )cc"); } else { p->Emit(R"cc( - inline const $pb$::RepeatedField& $Msg$::_internal_$name$() const { + inline const $pb$::RepeatedField& $Msg$::_internal_$name_internal$() + const { $TsanDetectConcurrentRead$; return $field_$; } - inline $pb$::RepeatedField* $Msg$::_internal_mutable_$name$() { + inline $pb$::RepeatedField* $Msg$::_internal_mutable_$name_internal$() { $TsanDetectConcurrentRead$; return &$field_$; } diff --git a/src/google/protobuf/compiler/cpp/field_generators/map_field.cc b/src/google/protobuf/compiler/cpp/field_generators/map_field.cc index 13bcd63fe00ae..79690963a0960 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/map_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/map_field.cc @@ -215,7 +215,7 @@ void Map::GenerateAccessorDeclarations(io::Printer* p) const { void Map::GenerateInlineAccessorDefinitions(io::Printer* p) const { p->Emit(R"cc( - inline const $Map$& $Msg$::_internal_$name$() const { + inline const $Map$& $Msg$::_internal_$name_internal$() const { $TsanDetectConcurrentRead$; return $field_$.GetMap(); } @@ -224,11 +224,11 @@ void Map::GenerateInlineAccessorDefinitions(io::Printer* p) const { inline const $Map$& $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_get$; // @@protoc_insertion_point(field_map:$pkg.Msg.field$) - return _internal_$name$(); + return _internal_$name_internal$(); } )cc"); p->Emit(R"cc( - inline $Map$* $Msg$::_internal_mutable_$name$() { + inline $Map$* $Msg$::_internal_mutable_$name_internal$() { $PrepareSplitMessageForWrite$; $TsanDetectConcurrentMutation$; return $field_$.MutableMap(); @@ -238,7 +238,7 @@ void Map::GenerateInlineAccessorDefinitions(io::Printer* p) const { inline $Map$* $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_mutable$; // @@protoc_insertion_point(field_mutable_map:$pkg.Msg.field$) - return _internal_mutable_$name$(); + return _internal_mutable_$name_internal$(); } )cc"); } diff --git a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc index b2b20dec3e0e0..318cf4c598e4d 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc @@ -198,7 +198,7 @@ void SingularMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { }}, }, R"cc( - inline const $Submsg$& $Msg$::_internal_$name$() const { + inline const $Submsg$& $Msg$::_internal_$name_internal$() const { $TsanDetectConcurrentRead$; $StrongRef$; const $Submsg$* p = $cast_field_$; @@ -207,7 +207,7 @@ void SingularMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { inline const $Submsg$& $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_get$; // @@protoc_insertion_point(field_get:$pkg.Msg.field$) - return _internal_$name$(); + return _internal_$name_internal$(); } inline void $Msg$::unsafe_arena_set_allocated_$name$($Submsg$* value) { $TsanDetectConcurrentMutation$; @@ -256,7 +256,7 @@ void SingularMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { $field_$ = nullptr; return temp; } - inline $Submsg$* $Msg$::_internal_mutable_$name$() { + inline $Submsg$* $Msg$::_internal_mutable_$name_internal$() { $TsanDetectConcurrentMutation$; $StrongRef$; if ($field_$ == nullptr) { @@ -270,7 +270,7 @@ void SingularMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { //~ able to prepare split message allocation. $PrepareSplitMessageForWrite$; $set_hasbit$; - $Submsg$* _msg = _internal_mutable_$name$(); + $Submsg$* _msg = _internal_mutable_$name_internal$(); $annotate_mutable$; // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$) return _msg; @@ -539,7 +539,7 @@ void OneofMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { } )cc"); p->Emit(R"cc( - inline const $Submsg$& $Msg$::_internal_$name$() const { + inline const $Submsg$& $Msg$::_internal_$name_internal$() const { $StrongRef$; return $has_field$ ? *$cast_field_$ : reinterpret_cast<$Submsg$&>($kDefault$); } @@ -548,7 +548,7 @@ void OneofMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { inline const $Submsg$& $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_get$; // @@protoc_insertion_point(field_get:$pkg.Msg.field$) - return _internal_$name$(); + return _internal_$name_internal$(); } )cc"); p->Emit(R"cc( @@ -573,7 +573,7 @@ void OneofMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { // set the new value. clear_$oneof_name$(); if (value) { - set_has_$name$(); + set_has_$name_internal$(); $field_$ = $weak_cast$(value); } $annotate_set$; @@ -581,11 +581,11 @@ void OneofMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { } )cc"); p->Emit(R"cc( - inline $Submsg$* $Msg$::_internal_mutable_$name$() { + inline $Submsg$* $Msg$::_internal_mutable_$name_internal$() { $StrongRef$; if ($not_has_field$) { clear_$oneof_name$(); - set_has_$name$(); + set_has_$name_internal$(); $field_$ = $weak_cast$($superclass$::DefaultConstruct<$Submsg$>(GetArena())); } @@ -594,7 +594,7 @@ void OneofMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { )cc"); p->Emit(R"cc( inline $Submsg$* $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND { - $Submsg$* _msg = _internal_mutable_$name$(); + $Submsg$* _msg = _internal_mutable_$name_internal$(); $annotate_mutable$; // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$) return _msg; @@ -745,7 +745,7 @@ void RepeatedMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { $annotate_mutable$; // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$) $StrongRef$; - return _internal_mutable_$name$()->Mutable(index); + return _internal_mutable_$name_internal$()->Mutable(index); } )cc"); p->Emit(R"cc( @@ -755,7 +755,7 @@ void RepeatedMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$) $StrongRef$; $TsanDetectConcurrentMutation$; - return _internal_mutable_$name$(); + return _internal_mutable_$name_internal$(); } )cc"); p->Emit( @@ -774,13 +774,13 @@ void RepeatedMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { $annotate_get$; // @@protoc_insertion_point(field_get:$pkg.Msg.field$) $StrongRef$; - return _internal_$name$().$Get$(index$GetExtraArg$); + return _internal_$name_internal$().$Get$(index$GetExtraArg$); } )cc"); p->Emit(R"cc( inline $Submsg$* $Msg$::add_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND { $TsanDetectConcurrentMutation$; - $Submsg$* _add = _internal_mutable_$name$()->Add(); + $Submsg$* _add = _internal_mutable_$name_internal$()->Add(); $annotate_add_mutable$; // @@protoc_insertion_point(field_add:$pkg.Msg.field$) return _add; @@ -792,19 +792,19 @@ void RepeatedMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { $annotate_list$; // @@protoc_insertion_point(field_list:$pkg.Msg.field$) $StrongRef$; - return _internal_$name$(); + return _internal_$name_internal$(); } )cc"); if (should_split()) { p->Emit(R"cc( inline const $pb$::$Weak$RepeatedPtrField<$Submsg$>& - $Msg$::_internal$_weak$_$name$() const { + $Msg$::_internal$_weak$_$name_internal$() const { $TsanDetectConcurrentRead$; return *$field_$; } inline $pb$::$Weak$RepeatedPtrField<$Submsg$>* - $Msg$::_internal_mutable$_weak$_$name$() { + $Msg$::_internal_mutable$_weak$_$name_internal$() { $TsanDetectConcurrentRead$; $PrepareSplitMessageForWrite$; if ($field_$.IsDefault()) { @@ -817,12 +817,12 @@ void RepeatedMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { } else { p->Emit(R"cc( inline const $pb$::$Weak$RepeatedPtrField<$Submsg$>& - $Msg$::_internal$_weak$_$name$() const { + $Msg$::_internal$_weak$_$name_internal$() const { $TsanDetectConcurrentRead$; return $field_$; } inline $pb$::$Weak$RepeatedPtrField<$Submsg$>* - $Msg$::_internal_mutable$_weak$_$name$() { + $Msg$::_internal_mutable$_weak$_$name_internal$() { $TsanDetectConcurrentRead$; return &$field_$; } @@ -830,12 +830,13 @@ void RepeatedMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { } if (is_weak()) { p->Emit(R"cc( - inline const $pb$::RepeatedPtrField<$Submsg$>& $Msg$::_internal_$name$() - const { - return _internal_weak_$name$().weak; + inline const $pb$::RepeatedPtrField<$Submsg$>& + $Msg$::_internal_$name_internal$() const { + return _internal_weak_$name_internal$().weak; } - inline $pb$::RepeatedPtrField<$Submsg$>* $Msg$::_internal_mutable_$name$() { - return &_internal_mutable_weak_$name$()->weak; + inline $pb$::RepeatedPtrField<$Submsg$>* + $Msg$::_internal_mutable_$name_internal$() { + return &_internal_mutable_weak_$name_internal$()->weak; } )cc"); } diff --git a/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc b/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc index eaa00a17a8494..e0e1ff3ca4fcb 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc @@ -190,7 +190,7 @@ void SingularPrimitive::GenerateInlineAccessorDefinitions( inline $Type$ $Msg$::$name$() const { $annotate_get$; // @@protoc_insertion_point(field_get:$pkg.Msg.field$) - return _internal_$name$(); + return _internal_$name_internal$(); } )cc"); @@ -200,13 +200,13 @@ void SingularPrimitive::GenerateInlineAccessorDefinitions( $PrepareSplitMessageForWrite$; if ($not_has_field$) { clear_$oneof_name$(); - set_has_$name$(); + set_has_$name_internal$(); } $field_$ = value; $annotate_set$; // @@protoc_insertion_point(field_set:$pkg.Msg.field$) } - inline $Type$ $Msg$::_internal_$name$() const { + inline $Type$ $Msg$::_internal_$name_internal$() const { if ($has_field$) { return $field_$; } @@ -217,16 +217,16 @@ void SingularPrimitive::GenerateInlineAccessorDefinitions( p->Emit(R"cc( inline void $Msg$::set_$name$($Type$ value) { $PrepareSplitMessageForWrite$; - _internal_set_$name$(value); + _internal_set_$name_internal$(value); $set_hasbit$; $annotate_set$; // @@protoc_insertion_point(field_set:$pkg.Msg.field$) } - inline $Type$ $Msg$::_internal_$name$() const { + inline $Type$ $Msg$::_internal_$name_internal$() const { $TsanDetectConcurrentRead$; return $field_$; } - inline void $Msg$::_internal_set_$name$($Type$ value) { + inline void $Msg$::_internal_set_$name_internal$($Type$ value) { $TsanDetectConcurrentMutation$; $field_$ = value; } @@ -469,20 +469,20 @@ void RepeatedPrimitive::GenerateInlineAccessorDefinitions( inline $Type$ $Msg$::$name$(int index) const { $annotate_get$; // @@protoc_insertion_point(field_get:$pkg.Msg.field$) - return _internal_$name$().Get(index); + return _internal_$name_internal$().Get(index); } )cc"); p->Emit(R"cc( inline void $Msg$::set_$name$(int index, $Type$ value) { $annotate_set$; - _internal_mutable_$name$()->Set(index, value); + _internal_mutable_$name_internal$()->Set(index, value); // @@protoc_insertion_point(field_set:$pkg.Msg.field$) } )cc"); p->Emit(R"cc( inline void $Msg$::add_$name$($Type$ value) { $TsanDetectConcurrentMutation$; - _internal_mutable_$name$()->Add(value); + _internal_mutable_$name_internal$()->Add(value); $annotate_add$; // @@protoc_insertion_point(field_add:$pkg.Msg.field$) } @@ -492,7 +492,7 @@ void RepeatedPrimitive::GenerateInlineAccessorDefinitions( ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_list$; // @@protoc_insertion_point(field_list:$pkg.Msg.field$) - return _internal_$name$(); + return _internal_$name_internal$(); } )cc"); p->Emit(R"cc( @@ -501,18 +501,18 @@ void RepeatedPrimitive::GenerateInlineAccessorDefinitions( $annotate_mutable_list$; // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$) $TsanDetectConcurrentMutation$; - return _internal_mutable_$name$(); + return _internal_mutable_$name_internal$(); } )cc"); if (should_split()) { p->Emit(R"cc( - inline const $pb$::RepeatedField<$Type$>& $Msg$::_internal_$name$() - const { + inline const $pb$::RepeatedField<$Type$>& + $Msg$::_internal_$name_internal$() const { $TsanDetectConcurrentRead$; return *$field_$; } - inline $pb$::RepeatedField<$Type$>* $Msg$::_internal_mutable_$name$() { + inline $pb$::RepeatedField<$Type$>* $Msg$::_internal_mutable_$name_internal$() { $TsanDetectConcurrentRead$; $PrepareSplitMessageForWrite$; if ($field_$.IsDefault()) { @@ -524,12 +524,12 @@ void RepeatedPrimitive::GenerateInlineAccessorDefinitions( )cc"); } else { p->Emit(R"cc( - inline const $pb$::RepeatedField<$Type$>& $Msg$::_internal_$name$() - const { + inline const $pb$::RepeatedField<$Type$>& + $Msg$::_internal_$name_internal$() const { $TsanDetectConcurrentRead$; return $field_$; } - inline $pb$::RepeatedField<$Type$>* $Msg$::_internal_mutable_$name$() { + inline $pb$::RepeatedField<$Type$>* $Msg$::_internal_mutable_$name_internal$() { $TsanDetectConcurrentRead$; return &$field_$; } diff --git a/src/google/protobuf/compiler/cpp/field_generators/string_field.cc b/src/google/protobuf/compiler/cpp/field_generators/string_field.cc index 7464d81a2bcf8..cd1049eea24df 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/string_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/string_field.cc @@ -300,7 +300,7 @@ void UpdateHasbitSet(io::Printer* p, bool is_oneof) { if ($not_has_field$) { clear_$oneof_name$(); - set_has_$name$(); + set_has_$name_internal$(); $field_$.InitDefault(); } )cc"); @@ -312,7 +312,7 @@ void ArgsForSetter(io::Printer* p, bool inlined) { return; } p->Emit( - "GetArena(), _internal_$name$_donated(), " + "GetArena(), _internal_$name_internal$_donated(), " "&$donating_states_word$, $mask_for_undonate$, this"); } @@ -342,7 +342,7 @@ void SingularString::ReleaseImpl(io::Printer* p) const { } $clear_hasbit$; - return $field_$.Release(GetArena(), _internal_$name$_donated()); + return $field_$.Release(GetArena(), _internal_$name_internal$_donated()); )cc"); return; } @@ -377,7 +377,7 @@ void SingularString::SetAllocatedImpl(io::Printer* p) const { clear_$oneof_name$(); } if (value != nullptr) { - set_has_$name$(); + set_has_$name_internal$(); $field_$.InitAllocated(value, GetArena()); } )cc"); @@ -451,7 +451,7 @@ void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const { $annotate_get$; // @@protoc_insertion_point(field_get:$pkg.Msg.field$) $if_IsDefault$; - return _internal_$name$(); + return _internal_$name_internal$(); } template inline PROTOBUF_ALWAYS_INLINE void $Msg$::set_$name$(Arg_&& arg, @@ -465,24 +465,24 @@ void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const { } inline std::string* $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND { $PrepareSplitMessageForWrite$; - std::string* _s = _internal_mutable_$name$(); + std::string* _s = _internal_mutable_$name_internal$(); $annotate_mutable$; // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$) return _s; } - inline const std::string& $Msg$::_internal_$name$() const { + inline const std::string& $Msg$::_internal_$name_internal$() const { $TsanDetectConcurrentRead$; $check_hasbit$; return $field_$.Get(); } - inline void $Msg$::_internal_set_$name$(const std::string& value) { + inline void $Msg$::_internal_set_$name_internal$(const std::string& value) { $TsanDetectConcurrentMutation$; $update_hasbit$; //~ Don't use $Set$ here; we always want the std::string variant //~ regardless of whether this is a `bytes` field. $field_$.Set(value, $set_args$); } - inline std::string* $Msg$::_internal_mutable_$name$() { + inline std::string* $Msg$::_internal_mutable_$name_internal$() { $TsanDetectConcurrentMutation$; $update_hasbit$; return $field_$.Mutable($lazy_args$, $set_args$); @@ -505,7 +505,7 @@ void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const { if (is_inlined()) { p->Emit(R"cc( - inline bool $Msg$::_internal_$name$_donated() const { + inline bool $Msg$::_internal_$name_internal$_donated() const { return $inlined_string_donated$; } )cc"); @@ -871,7 +871,7 @@ void RepeatedString::GenerateInlineAccessorDefinitions(io::Printer* p) const { inline std::string* $Msg$::add_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND { $TsanDetectConcurrentMutation$; - std::string* _s = _internal_mutable_$name$()->Add(); + std::string* _s = _internal_mutable_$name_internal$()->Add(); $annotate_add_mutable$; // @@protoc_insertion_point(field_add_mutable:$pkg.Msg.field$) return _s; @@ -880,72 +880,73 @@ void RepeatedString::GenerateInlineAccessorDefinitions(io::Printer* p) const { ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_get$; // @@protoc_insertion_point(field_get:$pkg.Msg.field$) - return _internal_$name$().$Get$(index$GetExtraArg$); + return _internal_$name_internal$().$Get$(index$GetExtraArg$); } inline std::string* $Msg$::mutable_$name$(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_mutable$; // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$) - return _internal_mutable_$name$()->Mutable(index); + return _internal_mutable_$name_internal$()->Mutable(index); } inline void $Msg$::set_$name$(int index, const std::string& value) { - _internal_mutable_$name$()->Mutable(index)->assign(value); + _internal_mutable_$name_internal$()->Mutable(index)->assign(value); $annotate_set$; // @@protoc_insertion_point(field_set:$pkg.Msg.field$) } inline void $Msg$::set_$name$(int index, std::string&& value) { - _internal_mutable_$name$()->Mutable(index)->assign(std::move(value)); + _internal_mutable_$name_internal$()->Mutable(index)->assign(std::move(value)); $annotate_set$; // @@protoc_insertion_point(field_set:$pkg.Msg.field$) } inline void $Msg$::set_$name$(int index, const char* value) { $DCHK$(value != nullptr); - _internal_mutable_$name$()->Mutable(index)->assign(value); + _internal_mutable_$name_internal$()->Mutable(index)->assign(value); $annotate_set$; // @@protoc_insertion_point(field_set_char:$pkg.Msg.field$) } inline void $Msg$::set_$name$(int index, const $byte$* value, std::size_t size) { - _internal_mutable_$name$()->Mutable(index)->assign( + _internal_mutable_$name_internal$()->Mutable(index)->assign( reinterpret_cast(value), size); $annotate_set$; // @@protoc_insertion_point(field_set_pointer:$pkg.Msg.field$) } inline void $Msg$::set_$name$(int index, absl::string_view value) { - _internal_mutable_$name$()->Mutable(index)->assign(value.data(), - value.size()); + _internal_mutable_$name_internal$()->Mutable(index)->assign( + value.data(), value.size()); $annotate_set$; // @@protoc_insertion_point(field_set_string_piece:$pkg.Msg.field$) } inline void $Msg$::add_$name$(const std::string& value) { $TsanDetectConcurrentMutation$; - _internal_mutable_$name$()->Add()->assign(value); + _internal_mutable_$name_internal$()->Add()->assign(value); $annotate_add$; // @@protoc_insertion_point(field_add:$pkg.Msg.field$) } inline void $Msg$::add_$name$(std::string&& value) { $TsanDetectConcurrentMutation$; - _internal_mutable_$name$()->Add(std::move(value)); + _internal_mutable_$name_internal$()->Add(std::move(value)); $annotate_add$; // @@protoc_insertion_point(field_add:$pkg.Msg.field$) } inline void $Msg$::add_$name$(const char* value) { $DCHK$(value != nullptr); $TsanDetectConcurrentMutation$; - _internal_mutable_$name$()->Add()->assign(value); + _internal_mutable_$name_internal$()->Add()->assign(value); $annotate_add$; // @@protoc_insertion_point(field_add_char:$pkg.Msg.field$) } inline void $Msg$::add_$name$(const $byte$* value, std::size_t size) { $TsanDetectConcurrentMutation$; - _internal_mutable_$name$()->Add()->assign( + _internal_mutable_$name_internal$()->Add()->assign( reinterpret_cast(value), size); $annotate_add$; // @@protoc_insertion_point(field_add_pointer:$pkg.Msg.field$) } inline void $Msg$::add_$name$(absl::string_view value) { $TsanDetectConcurrentMutation$; - _internal_mutable_$name$()->Add()->assign(value.data(), value.size()); + _internal_mutable_$name_internal$()->Add()->assign(value.data(), + value.size()); $annotate_add$; // @@protoc_insertion_point(field_add_string_piece:$pkg.Msg.field$) } @@ -953,24 +954,25 @@ void RepeatedString::GenerateInlineAccessorDefinitions(io::Printer* p) const { $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_list$; // @@protoc_insertion_point(field_list:$pkg.Msg.field$) - return _internal_$name$(); + return _internal_$name_internal$(); } inline ::$proto_ns$::RepeatedPtrField* $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND { $annotate_mutable_list$; // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$) $TsanDetectConcurrentMutation$; - return _internal_mutable_$name$(); + return _internal_mutable_$name_internal$(); } )cc"); if (ShouldSplit(descriptor_, options_)) { p->Emit(R"cc( inline const $pb$::RepeatedPtrField& - $Msg$::_internal_$name$() const { + $Msg$::_internal_$name_internal$() const { $TsanDetectConcurrentRead$; return *$field_$; } - inline $pb$::RepeatedPtrField* $Msg$::_internal_mutable_$name$() { + inline $pb$::RepeatedPtrField* + $Msg$::_internal_mutable_$name_internal$() { $TsanDetectConcurrentRead$; $PrepareSplitMessageForWrite$; if ($field_$.IsDefault()) { @@ -984,12 +986,12 @@ void RepeatedString::GenerateInlineAccessorDefinitions(io::Printer* p) const { } else { p->Emit(R"cc( inline const ::$proto_ns$::RepeatedPtrField& - $Msg$::_internal_$name$() const { + $Msg$::_internal_$name_internal$() const { $TsanDetectConcurrentRead$; return $field_$; } inline ::$proto_ns$::RepeatedPtrField* - $Msg$::_internal_mutable_$name$() { + $Msg$::_internal_mutable_$name_internal$() { $TsanDetectConcurrentRead$; return &$field_$; } diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc index 2372b36364fa6..cbd5aa9d5e281 100644 --- a/src/google/protobuf/compiler/cpp/message.cc +++ b/src/google/protobuf/compiler/cpp/message.cc @@ -29,6 +29,7 @@ #include "absl/log/absl_log.h" #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" +#include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" @@ -1060,7 +1061,7 @@ void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field, } if (HasInternalHasMethod(field)) { p->Emit(R"cc( - inline bool $classname$::_internal_has_$name$() const { + inline bool $classname$::_internal_has_$name_internal$() const { return $has_field$; } )cc"); @@ -1068,7 +1069,7 @@ void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field, // set_has_$name$() for oneof fields is always private; hence should not be // annotated. p->Emit(R"cc( - inline void $classname$::set_has_$name$() { + inline void $classname$::set_has_$name_internal$() { $oneof_case$[$oneof_index$] = k$field_name$; } )cc"); @@ -1120,22 +1121,81 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field, )cc"); } +namespace { + +class AccessorVerifier { + public: + using SourceLocation = io::Printer::SourceLocation; + + AccessorVerifier(const FieldDescriptor* field) : field_(field) {} + ~AccessorVerifier() { + ABSL_CHECK(!needs_annotate_) << Error(SourceLocation::current()); + } + + void operator()(absl::string_view label, io::Printer::SourceLocation loc) { + if (label == "name" || label == "release_name") { + // All accessors use $name$ or $release_name$ when constructing the + // function name. We hook into those to determine that an accessor is + // starting. + ABSL_CHECK(!needs_annotate_) << Error(loc); + loc_ = loc; + needs_annotate_ = true; + } else if (absl::StartsWith(label, "annotate")) { + // All annotation labels start with `annotate`. Eg `annotate_get`. + ABSL_CHECK(needs_annotate_) << Error(loc); + loc_ = loc; + needs_annotate_ = false; + } + } + + private: + std::string Error(SourceLocation loc) const { + return absl::StrFormat("Field %s printed from %s:%d (prev %s:%d)\n", + field_->full_name(), loc.file_name(), loc.line(), + loc_.file_name(), loc_.line()); + } + + bool needs_annotate_ = false; + // We keep these fields for error reporting. + const FieldDescriptor* field_; + // On error, we report two locations: the current one and the last one. This + // can help determine where the bug is. For example, if we see "name" twice in + // a row, the bug is likely in the "last" one and not the current one because + // it means the previous accessor didn't add the required code. + SourceLocation loc_; +}; + +} // namespace + void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* p) { p->Emit("// $classname$\n\n"); for (auto field : FieldRange(descriptor_)) { + // We use a print listener to verify that the field generators properly add + // the right annotations. This is only a verification step aimed to prevent + // bugs where we have lack of test coverage. Note that this will verify the + // annotations even when the particular feature is not on because we look at + // the substitution variables, not the substitution result. + // The check is a state machine that verifies that every substitution for + // `name` is followed by one and only one for needed annotations. False + // positives are accessors that are using $name$ for an internal name. For + // those you can use $name_internal$ which is the same substitution but not + // tracked by the verifier. + const auto accessor_verifier = + p->WithSubstitutionListener(AccessorVerifier(field)); + PrintFieldComment(Formatter{p}, field, options_); auto v = p->WithVars(FieldVars(field, options_)); auto t = p->WithVars(MakeTrackerCalls(field, options_)); if (field->is_repeated()) { p->Emit(R"cc( - inline int $classname$::_internal_$name$_size() const { - return _internal_$name$().size(); + inline int $classname$::_internal_$name_internal$_size() const { + return _internal_$name_internal$().size(); } inline int $classname$::$name$_size() const { $annotate_size$; - return _internal_$name$_size(); + return _internal_$name_internal$_size(); } )cc"); } else if (field->real_containing_oneof()) { diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index 7b036ff75484f..49252c37ec61a 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -1295,8 +1295,8 @@ inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* va // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::set_file_to_generate(int index, absl::string_view value) { - _internal_mutable_file_to_generate()->Mutable(index)->assign(value.data(), - value.size()); + _internal_mutable_file_to_generate()->Mutable(index)->assign( + value.data(), value.size()); // @@protoc_insertion_point(field_set_string_piece:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::add_file_to_generate(const std::string& value) { @@ -1323,7 +1323,8 @@ inline void CodeGeneratorRequest::add_file_to_generate(const char* value, std::s } inline void CodeGeneratorRequest::add_file_to_generate(absl::string_view value) { PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); - _internal_mutable_file_to_generate()->Add()->assign(value.data(), value.size()); + _internal_mutable_file_to_generate()->Add()->assign(value.data(), + value.size()); // @@protoc_insertion_point(field_add_string_piece:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline const ::google::protobuf::RepeatedPtrField& diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 765de53a7674d..9409875173066 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -10783,8 +10783,8 @@ inline void FileDescriptorProto::set_dependency(int index, const char* value, // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency) } inline void FileDescriptorProto::set_dependency(int index, absl::string_view value) { - _internal_mutable_dependency()->Mutable(index)->assign(value.data(), - value.size()); + _internal_mutable_dependency()->Mutable(index)->assign( + value.data(), value.size()); // @@protoc_insertion_point(field_set_string_piece:google.protobuf.FileDescriptorProto.dependency) } inline void FileDescriptorProto::add_dependency(const std::string& value) { @@ -10811,7 +10811,8 @@ inline void FileDescriptorProto::add_dependency(const char* value, std::size_t s } inline void FileDescriptorProto::add_dependency(absl::string_view value) { PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); - _internal_mutable_dependency()->Add()->assign(value.data(), value.size()); + _internal_mutable_dependency()->Add()->assign(value.data(), + value.size()); // @@protoc_insertion_point(field_add_string_piece:google.protobuf.FileDescriptorProto.dependency) } inline const ::google::protobuf::RepeatedPtrField& @@ -10871,8 +10872,8 @@ inline ::google::protobuf::RepeatedField<::int32_t>* FileDescriptorProto::mutabl PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); return _internal_mutable_public_dependency(); } -inline const ::google::protobuf::RepeatedField<::int32_t>& FileDescriptorProto::_internal_public_dependency() - const { +inline const ::google::protobuf::RepeatedField<::int32_t>& +FileDescriptorProto::_internal_public_dependency() const { PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); return _impl_.public_dependency_; } @@ -10916,8 +10917,8 @@ inline ::google::protobuf::RepeatedField<::int32_t>* FileDescriptorProto::mutabl PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); return _internal_mutable_weak_dependency(); } -inline const ::google::protobuf::RepeatedField<::int32_t>& FileDescriptorProto::_internal_weak_dependency() - const { +inline const ::google::protobuf::RepeatedField<::int32_t>& +FileDescriptorProto::_internal_weak_dependency() const { PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); return _impl_.weak_dependency_; } @@ -12192,8 +12193,8 @@ inline void DescriptorProto::set_reserved_name(int index, const char* value, // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name) } inline void DescriptorProto::set_reserved_name(int index, absl::string_view value) { - _internal_mutable_reserved_name()->Mutable(index)->assign(value.data(), - value.size()); + _internal_mutable_reserved_name()->Mutable(index)->assign( + value.data(), value.size()); // @@protoc_insertion_point(field_set_string_piece:google.protobuf.DescriptorProto.reserved_name) } inline void DescriptorProto::add_reserved_name(const std::string& value) { @@ -12220,7 +12221,8 @@ inline void DescriptorProto::add_reserved_name(const char* value, std::size_t si } inline void DescriptorProto::add_reserved_name(absl::string_view value) { PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); - _internal_mutable_reserved_name()->Add()->assign(value.data(), value.size()); + _internal_mutable_reserved_name()->Add()->assign(value.data(), + value.size()); // @@protoc_insertion_point(field_add_string_piece:google.protobuf.DescriptorProto.reserved_name) } inline const ::google::protobuf::RepeatedPtrField& @@ -13847,8 +13849,8 @@ inline void EnumDescriptorProto::set_reserved_name(int index, const char* value, // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.reserved_name) } inline void EnumDescriptorProto::set_reserved_name(int index, absl::string_view value) { - _internal_mutable_reserved_name()->Mutable(index)->assign(value.data(), - value.size()); + _internal_mutable_reserved_name()->Mutable(index)->assign( + value.data(), value.size()); // @@protoc_insertion_point(field_set_string_piece:google.protobuf.EnumDescriptorProto.reserved_name) } inline void EnumDescriptorProto::add_reserved_name(const std::string& value) { @@ -13875,7 +13877,8 @@ inline void EnumDescriptorProto::add_reserved_name(const char* value, std::size_ } inline void EnumDescriptorProto::add_reserved_name(absl::string_view value) { PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); - _internal_mutable_reserved_name()->Add()->assign(value.data(), value.size()); + _internal_mutable_reserved_name()->Add()->assign(value.data(), + value.size()); // @@protoc_insertion_point(field_add_string_piece:google.protobuf.EnumDescriptorProto.reserved_name) } inline const ::google::protobuf::RepeatedPtrField& @@ -16489,7 +16492,8 @@ inline ::google::protobuf::RepeatedField* FieldOptions::mutable_targets() PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); return _internal_mutable_targets(); } -inline const ::google::protobuf::RepeatedField& FieldOptions::_internal_targets() const { +inline const ::google::protobuf::RepeatedField& FieldOptions::_internal_targets() + const { PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); return _impl_.targets_; } @@ -18572,8 +18576,8 @@ inline ::google::protobuf::RepeatedField<::int32_t>* SourceCodeInfo_Location::mu PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); return _internal_mutable_path(); } -inline const ::google::protobuf::RepeatedField<::int32_t>& SourceCodeInfo_Location::_internal_path() - const { +inline const ::google::protobuf::RepeatedField<::int32_t>& +SourceCodeInfo_Location::_internal_path() const { PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); return _impl_.path_; } @@ -18617,8 +18621,8 @@ inline ::google::protobuf::RepeatedField<::int32_t>* SourceCodeInfo_Location::mu PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); return _internal_mutable_span(); } -inline const ::google::protobuf::RepeatedField<::int32_t>& SourceCodeInfo_Location::_internal_span() - const { +inline const ::google::protobuf::RepeatedField<::int32_t>& +SourceCodeInfo_Location::_internal_span() const { PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); return _impl_.span_; } @@ -18817,8 +18821,8 @@ inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, co // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, absl::string_view value) { - _internal_mutable_leading_detached_comments()->Mutable(index)->assign(value.data(), - value.size()); + _internal_mutable_leading_detached_comments()->Mutable(index)->assign( + value.data(), value.size()); // @@protoc_insertion_point(field_set_string_piece:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } inline void SourceCodeInfo_Location::add_leading_detached_comments(const std::string& value) { @@ -18845,7 +18849,8 @@ inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* v } inline void SourceCodeInfo_Location::add_leading_detached_comments(absl::string_view value) { PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); - _internal_mutable_leading_detached_comments()->Add()->assign(value.data(), value.size()); + _internal_mutable_leading_detached_comments()->Add()->assign(value.data(), + value.size()); // @@protoc_insertion_point(field_add_string_piece:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } inline const ::google::protobuf::RepeatedPtrField& @@ -18962,8 +18967,8 @@ inline ::google::protobuf::RepeatedField<::int32_t>* GeneratedCodeInfo_Annotatio PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); return _internal_mutable_path(); } -inline const ::google::protobuf::RepeatedField<::int32_t>& GeneratedCodeInfo_Annotation::_internal_path() - const { +inline const ::google::protobuf::RepeatedField<::int32_t>& +GeneratedCodeInfo_Annotation::_internal_path() const { PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); return _impl_.path_; } diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc index 621d1ed07994e..ef4445a05e731 100644 --- a/src/google/protobuf/io/printer.cc +++ b/src/google/protobuf/io/printer.cc @@ -30,6 +30,7 @@ #include "absl/strings/string_view.h" #include "absl/strings/strip.h" #include "absl/types/optional.h" +#include "absl/types/source_location.h" #include "absl/types/span.h" #include "absl/types/variant.h" @@ -547,6 +548,9 @@ void Printer::PrintImpl(absl::string_view format, // If we get this far, we can conclude the chunk is a substitution // variable; we rename the `chunk` variable to make this clear below. absl::string_view var = chunk.text; + if (substitution_listener_ != nullptr) { + substitution_listener_(var, opts.loc.value_or(SourceLocation())); + } if (opts.use_curly_brace_substitutions && absl::ConsumePrefix(&var, "{")) { if (!Validate(var.size() == 1u, opts, diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h index e2bcc55dd4f1e..471cf0b47222c 100644 --- a/src/google/protobuf/io/printer.h +++ b/src/google/protobuf/io/printer.h @@ -24,6 +24,7 @@ #include "absl/cleanup/cleanup.h" #include "absl/container/flat_hash_map.h" +#include "absl/functional/any_invocable.h" #include "absl/functional/function_ref.h" #include "absl/log/absl_check.h" #include "absl/meta/type_traits.h" @@ -655,6 +656,18 @@ class PROTOBUF_EXPORT Printer { void FormatInternal(absl::Span args, const Map& vars, absl::string_view format); + // Injects a substitution listener for the lifetime of the RAII object + // returned. + // While the listener is active it will receive a callback on each + // substitution label found. + // This can be used to add basic verification on top of emit routines. + auto WithSubstitutionListener( + absl::AnyInvocable listener) { + ABSL_CHECK(substitution_listener_ == nullptr); + substitution_listener_ = std::move(listener); + return absl::MakeCleanup([this] { substitution_listener_ = nullptr; }); + } + private: struct PrintOptions; struct Format; @@ -753,6 +766,11 @@ class PROTOBUF_EXPORT Printer { std::function(absl::string_view)>> annotation_lookups_; + // If set, we invoke this when we do a label substitution. This can be used to + // verify consistency of the generated code while we generate it. + absl::AnyInvocable + substitution_listener_; + // A map from variable name to [start, end) offsets in the output buffer. // // This stores the data looked up by GetSubstitutionRange(). diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc index 5e72f2d0952e5..081f4a531fc11 100644 --- a/src/google/protobuf/io/printer_unittest.cc +++ b/src/google/protobuf/io/printer_unittest.cc @@ -610,6 +610,35 @@ TEST_F(PrinterTest, EmitConsumeAfter) { "};\n"); } +TEST_F(PrinterTest, EmitWithSubstituionListener) { + std::vector seen; + Printer printer(output()); + const auto emit = [&] { + printer.Emit( + { + {"class", "Foo"}, + Printer::Sub{"var", "int x;"}.WithSuffix(";"), + }, + R"cc( + void $class$::foo() { $var$; } + void $class$::set_foo() { $var$; } + )cc"); + }; + emit(); + EXPECT_THAT(seen, ElementsAre()); + { + auto listener = printer.WithSubstitutionListener( + [&](auto label, auto loc) { seen.emplace_back(label); }); + emit(); + } + EXPECT_THAT(seen, ElementsAre("class", "var", "class", "var")); + + // Still works after the listener is disconnected. + seen.clear(); + emit(); + EXPECT_THAT(seen, ElementsAre()); +} + TEST_F(PrinterTest, EmitConditionalFunctionCall) { { Printer printer(output());