xref: /aosp_15_r20/external/cronet/third_party/protobuf/src/google/protobuf/compiler/cpp/primitive_field.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: [email protected] (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/compiler/cpp/primitive_field.h>
36 
37 #include <google/protobuf/io/printer.h>
38 #include <google/protobuf/wire_format.h>
39 #include <google/protobuf/stubs/strutil.h>
40 #include <google/protobuf/compiler/cpp/helpers.h>
41 
42 namespace google {
43 namespace protobuf {
44 namespace compiler {
45 namespace cpp {
46 
47 using internal::WireFormatLite;
48 
49 namespace {
50 
51 // For encodings with fixed sizes, returns that size in bytes.  Otherwise
52 // returns -1.
FixedSize(FieldDescriptor::Type type)53 int FixedSize(FieldDescriptor::Type type) {
54   switch (type) {
55     case FieldDescriptor::TYPE_INT32:
56       return -1;
57     case FieldDescriptor::TYPE_INT64:
58       return -1;
59     case FieldDescriptor::TYPE_UINT32:
60       return -1;
61     case FieldDescriptor::TYPE_UINT64:
62       return -1;
63     case FieldDescriptor::TYPE_SINT32:
64       return -1;
65     case FieldDescriptor::TYPE_SINT64:
66       return -1;
67     case FieldDescriptor::TYPE_FIXED32:
68       return WireFormatLite::kFixed32Size;
69     case FieldDescriptor::TYPE_FIXED64:
70       return WireFormatLite::kFixed64Size;
71     case FieldDescriptor::TYPE_SFIXED32:
72       return WireFormatLite::kSFixed32Size;
73     case FieldDescriptor::TYPE_SFIXED64:
74       return WireFormatLite::kSFixed64Size;
75     case FieldDescriptor::TYPE_FLOAT:
76       return WireFormatLite::kFloatSize;
77     case FieldDescriptor::TYPE_DOUBLE:
78       return WireFormatLite::kDoubleSize;
79 
80     case FieldDescriptor::TYPE_BOOL:
81       return WireFormatLite::kBoolSize;
82     case FieldDescriptor::TYPE_ENUM:
83       return -1;
84 
85     case FieldDescriptor::TYPE_STRING:
86       return -1;
87     case FieldDescriptor::TYPE_BYTES:
88       return -1;
89     case FieldDescriptor::TYPE_GROUP:
90       return -1;
91     case FieldDescriptor::TYPE_MESSAGE:
92       return -1;
93 
94       // No default because we want the compiler to complain if any new
95       // types are added.
96   }
97   GOOGLE_LOG(FATAL) << "Can't get here.";
98   return -1;
99 }
100 
SetPrimitiveVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables,const Options & options)101 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
102                            std::map<std::string, std::string>* variables,
103                            const Options& options) {
104   SetCommonFieldVariables(descriptor, variables, options);
105   (*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type());
106   (*variables)["default"] = DefaultValue(options, descriptor);
107   (*variables)["cached_byte_size_name"] = MakeVarintCachedSizeName(descriptor);
108   bool cold = ShouldSplit(descriptor, options);
109   (*variables)["cached_byte_size_field"] =
110       MakeVarintCachedSizeFieldName(descriptor, cold);
111   (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
112   int fixed_size = FixedSize(descriptor->type());
113   if (fixed_size != -1) {
114     (*variables)["fixed_size"] = StrCat(fixed_size);
115   }
116   (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name(
117       static_cast<FieldDescriptorProto_Type>(descriptor->type()));
118   (*variables)["full_name"] = descriptor->full_name();
119 }
120 
121 }  // namespace
122 
123 // ===================================================================
124 
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)125 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
126     const FieldDescriptor* descriptor, const Options& options)
127     : FieldGenerator(descriptor, options) {
128   SetPrimitiveVariables(descriptor, &variables_, options);
129 }
130 
~PrimitiveFieldGenerator()131 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
132 
GeneratePrivateMembers(io::Printer * printer) const133 void PrimitiveFieldGenerator::GeneratePrivateMembers(
134     io::Printer* printer) const {
135   Formatter format(printer, variables_);
136   format("$type$ $name$_;\n");
137 }
138 
GenerateAccessorDeclarations(io::Printer * printer) const139 void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
140     io::Printer* printer) const {
141   Formatter format(printer, variables_);
142   format(
143       "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
144       "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
145       "private:\n"
146       "$type$ ${1$_internal_$name$$}$() const;\n"
147       "void ${1$_internal_set_$name$$}$($type$ value);\n"
148       "public:\n",
149       descriptor_);
150 }
151 
GenerateInlineAccessorDefinitions(io::Printer * printer) const152 void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
153     io::Printer* printer) const {
154   Formatter format(printer, variables_);
155   format(
156       "inline $type$ $classname$::_internal_$name$() const {\n"
157       "  return $field$;\n"
158       "}\n"
159       "inline $type$ $classname$::$name$() const {\n"
160       "$annotate_get$"
161       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
162       "  return _internal_$name$();\n"
163       "}\n"
164       "inline void $classname$::_internal_set_$name$($type$ value) {\n"
165       "  $set_hasbit$\n"
166       "  $field$ = value;\n"
167       "}\n"
168       "inline void $classname$::set_$name$($type$ value) {\n"
169       "$maybe_prepare_split_message$"
170       "  _internal_set_$name$(value);\n"
171       "$annotate_set$"
172       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
173       "}\n");
174 }
175 
GenerateClearingCode(io::Printer * printer) const176 void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
177   Formatter format(printer, variables_);
178   format("$field$ = $default$;\n");
179 }
180 
GenerateMergingCode(io::Printer * printer) const181 void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
182   Formatter format(printer, variables_);
183   format("_this->_internal_set_$name$(from._internal_$name$());\n");
184 }
185 
GenerateSwappingCode(io::Printer * printer) const186 void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
187   Formatter format(printer, variables_);
188   format("swap($field$, other->$field$);\n");
189 }
190 
GenerateCopyConstructorCode(io::Printer * printer) const191 void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
192     io::Printer* printer) const {
193   Formatter format(printer, variables_);
194   format("_this->$field$ = from.$field$;\n");
195 }
196 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const197 void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
198     io::Printer* printer) const {
199   Formatter format(printer, variables_);
200   format(
201       "target = stream->EnsureSpace(target);\n"
202       "target = "
203       "::_pbi::WireFormatLite::Write$declared_type$ToArray("
204       "$number$, this->_internal_$name$(), target);\n");
205 }
206 
GenerateByteSize(io::Printer * printer) const207 void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
208   Formatter format(printer, variables_);
209   int fixed_size = FixedSize(descriptor_->type());
210   if (fixed_size == -1) {
211     if (internal::WireFormat::TagSize(descriptor_->number(),
212                                       descriptor_->type()) == 1) {
213       // Adding one is very common and it turns out it can be done for
214       // free inside of WireFormatLite, so we can save an instruction here.
215       format(
216           "total_size += ::_pbi::WireFormatLite::"
217           "$declared_type$SizePlusOne(this->_internal_$name$());\n");
218     } else {
219       format(
220           "total_size += $tag_size$ +\n"
221           "  ::_pbi::WireFormatLite::$declared_type$Size(\n"
222           "    this->_internal_$name$());\n");
223     }
224   } else {
225     format("total_size += $tag_size$ + $fixed_size$;\n");
226   }
227 }
228 
GenerateConstexprAggregateInitializer(io::Printer * printer) const229 void PrimitiveFieldGenerator::GenerateConstexprAggregateInitializer(
230     io::Printer* printer) const {
231   Formatter format(printer, variables_);
232   format("/*decltype($field$)*/$default$");
233 }
234 
GenerateAggregateInitializer(io::Printer * printer) const235 void PrimitiveFieldGenerator::GenerateAggregateInitializer(
236     io::Printer* printer) const {
237   Formatter format(printer, variables_);
238   if (ShouldSplit(descriptor_, options_)) {
239     format("decltype(Impl_::Split::$name$_){$default$}");
240     return;
241   }
242   format("decltype($field$){$default$}");
243 }
244 
GenerateCopyAggregateInitializer(io::Printer * printer) const245 void PrimitiveFieldGenerator::GenerateCopyAggregateInitializer(
246     io::Printer* printer) const {
247   Formatter format(printer, variables_);
248   format("decltype($field$){}");
249 }
250 
251 // ===================================================================
252 
PrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)253 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
254     const FieldDescriptor* descriptor, const Options& options)
255     : PrimitiveFieldGenerator(descriptor, options) {
256   SetCommonOneofFieldVariables(descriptor, &variables_);
257 }
258 
~PrimitiveOneofFieldGenerator()259 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
260 
GenerateInlineAccessorDefinitions(io::Printer * printer) const261 void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions(
262     io::Printer* printer) const {
263   Formatter format(printer, variables_);
264   format(
265       "inline $type$ $classname$::_internal_$name$() const {\n"
266       "  if (_internal_has_$name$()) {\n"
267       "    return $field$;\n"
268       "  }\n"
269       "  return $default$;\n"
270       "}\n"
271       "inline void $classname$::_internal_set_$name$($type$ value) {\n"
272       "  if (!_internal_has_$name$()) {\n"
273       "    clear_$oneof_name$();\n"
274       "    set_has_$name$();\n"
275       "  }\n"
276       "  $field$ = value;\n"
277       "}\n"
278       "inline $type$ $classname$::$name$() const {\n"
279       "$annotate_get$"
280       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
281       "  return _internal_$name$();\n"
282       "}\n"
283       "inline void $classname$::set_$name$($type$ value) {\n"
284       "  _internal_set_$name$(value);\n"
285       "$annotate_set$"
286       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
287       "}\n");
288 }
289 
GenerateClearingCode(io::Printer * printer) const290 void PrimitiveOneofFieldGenerator::GenerateClearingCode(
291     io::Printer* printer) const {
292   Formatter format(printer, variables_);
293   format("$field$ = $default$;\n");
294 }
295 
GenerateSwappingCode(io::Printer * printer) const296 void PrimitiveOneofFieldGenerator::GenerateSwappingCode(
297     io::Printer* printer) const {
298   // Don't print any swapping code. Swapping the union will swap this field.
299 }
300 
GenerateConstructorCode(io::Printer * printer) const301 void PrimitiveOneofFieldGenerator::GenerateConstructorCode(
302     io::Printer* printer) const {
303   Formatter format(printer, variables_);
304   format("$ns$::_$classname$_default_instance_.$field$ = $default$;\n");
305 }
306 
307 // ===================================================================
308 
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)309 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
310     const FieldDescriptor* descriptor, const Options& options)
311     : FieldGenerator(descriptor, options) {
312   SetPrimitiveVariables(descriptor, &variables_, options);
313 
314   if (descriptor->is_packed()) {
315     variables_["packed_reader"] = "ReadPackedPrimitive";
316     variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
317   } else {
318     variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
319     variables_["repeated_reader"] = "ReadRepeatedPrimitive";
320   }
321 }
322 
~RepeatedPrimitiveFieldGenerator()323 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
324 
GeneratePrivateMembers(io::Printer * printer) const325 void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers(
326     io::Printer* printer) const {
327   Formatter format(printer, variables_);
328   format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
329   if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
330       HasGeneratedMethods(descriptor_->file(), options_)) {
331     format("mutable std::atomic<int> $cached_byte_size_name$;\n");
332   }
333 }
334 
GenerateAccessorDeclarations(io::Printer * printer) const335 void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations(
336     io::Printer* printer) const {
337   Formatter format(printer, variables_);
338   format(
339       "private:\n"
340       "$type$ ${1$_internal_$name$$}$(int index) const;\n"
341       "const ::$proto_ns$::RepeatedField< $type$ >&\n"
342       "    ${1$_internal_$name$$}$() const;\n"
343       "void ${1$_internal_add_$name$$}$($type$ value);\n"
344       "::$proto_ns$::RepeatedField< $type$ >*\n"
345       "    ${1$_internal_mutable_$name$$}$();\n"
346       "public:\n"
347       "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
348       "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
349       "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
350       "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n"
351       "    ${1$$name$$}$() const;\n"
352       "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n"
353       "    ${1$mutable_$name$$}$();\n",
354       descriptor_);
355 }
356 
GenerateInlineAccessorDefinitions(io::Printer * printer) const357 void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
358     io::Printer* printer) const {
359   Formatter format(printer, variables_);
360   format(
361       "inline $type$ $classname$::_internal_$name$(int index) const {\n"
362       "  return $field$.Get(index);\n"
363       "}\n"
364       "inline $type$ $classname$::$name$(int index) const {\n"
365       "$annotate_get$"
366       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
367       "  return _internal_$name$(index);\n"
368       "}\n"
369       "inline void $classname$::set_$name$(int index, $type$ value) {\n"
370       "$annotate_set$"
371       "  $field$.Set(index, value);\n"
372       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
373       "}\n"
374       "inline void $classname$::_internal_add_$name$($type$ value) {\n"
375       "  $field$.Add(value);\n"
376       "}\n"
377       "inline void $classname$::add_$name$($type$ value) {\n"
378       "  _internal_add_$name$(value);\n"
379       "$annotate_add$"
380       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
381       "}\n"
382       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
383       "$classname$::_internal_$name$() const {\n"
384       "  return $field$;\n"
385       "}\n"
386       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
387       "$classname$::$name$() const {\n"
388       "$annotate_list$"
389       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
390       "  return _internal_$name$();\n"
391       "}\n"
392       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
393       "$classname$::_internal_mutable_$name$() {\n"
394       "  return &$field$;\n"
395       "}\n"
396       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
397       "$classname$::mutable_$name$() {\n"
398       "$annotate_mutable_list$"
399       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
400       "  return _internal_mutable_$name$();\n"
401       "}\n");
402 }
403 
GenerateClearingCode(io::Printer * printer) const404 void RepeatedPrimitiveFieldGenerator::GenerateClearingCode(
405     io::Printer* printer) const {
406   Formatter format(printer, variables_);
407   format("$field$.Clear();\n");
408 }
409 
GenerateMergingCode(io::Printer * printer) const410 void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(
411     io::Printer* printer) const {
412   Formatter format(printer, variables_);
413   format("_this->$field$.MergeFrom(from.$field$);\n");
414 }
415 
GenerateSwappingCode(io::Printer * printer) const416 void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
417     io::Printer* printer) const {
418   Formatter format(printer, variables_);
419   format("$field$.InternalSwap(&other->$field$);\n");
420 }
421 
GenerateDestructorCode(io::Printer * printer) const422 void RepeatedPrimitiveFieldGenerator::GenerateDestructorCode(
423     io::Printer* printer) const {
424   Formatter format(printer, variables_);
425   format("$field$.~RepeatedField();\n");
426 }
427 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const428 void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
429     io::Printer* printer) const {
430   Formatter format(printer, variables_);
431   if (descriptor_->is_packed()) {
432     if (FixedSize(descriptor_->type()) == -1) {
433       format(
434           "{\n"
435           "  int byte_size = "
436           "$cached_byte_size_field$.load(std::memory_order_relaxed);\n"
437           "  if (byte_size > 0) {\n"
438           "    target = stream->Write$declared_type$Packed(\n"
439           "        $number$, _internal_$name$(), byte_size, target);\n"
440           "  }\n"
441           "}\n");
442     } else {
443       format(
444           "if (this->_internal_$name$_size() > 0) {\n"
445           "  target = stream->WriteFixedPacked($number$, _internal_$name$(), "
446           "target);\n"
447           "}\n");
448     }
449   } else {
450     format(
451         "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
452         "  target = stream->EnsureSpace(target);\n"
453         "  target = ::_pbi::WireFormatLite::"
454         "Write$declared_type$ToArray($number$, this->_internal_$name$(i), "
455         "target);\n"
456         "}\n");
457   }
458 }
459 
GenerateByteSize(io::Printer * printer) const460 void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
461     io::Printer* printer) const {
462   Formatter format(printer, variables_);
463   format("{\n");
464   format.Indent();
465   int fixed_size = FixedSize(descriptor_->type());
466   if (fixed_size == -1) {
467     format(
468         "size_t data_size = ::_pbi::WireFormatLite::\n"
469         "  $declared_type$Size(this->$field$);\n");
470   } else {
471     format(
472         "unsigned int count = static_cast<unsigned "
473         "int>(this->_internal_$name$_size());\n"
474         "size_t data_size = $fixed_size$UL * count;\n");
475   }
476 
477   if (descriptor_->is_packed()) {
478     format(
479         "if (data_size > 0) {\n"
480         "  total_size += $tag_size$ +\n"
481         "    "
482         "::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n"
483         "}\n");
484     if (FixedSize(descriptor_->type()) == -1) {
485       format(
486           "int cached_size = ::_pbi::ToCachedSize(data_size);\n"
487           "$cached_byte_size_field$.store(cached_size,\n"
488           "                                std::memory_order_relaxed);\n");
489     }
490     format("total_size += data_size;\n");
491   } else {
492     format(
493         "total_size += $tag_size$ *\n"
494         "              "
495         "::_pbi::FromIntSize(this->_internal_$name$_size());\n"
496         "total_size += data_size;\n");
497   }
498   format.Outdent();
499   format("}\n");
500 }
501 
GenerateConstexprAggregateInitializer(io::Printer * printer) const502 void RepeatedPrimitiveFieldGenerator::GenerateConstexprAggregateInitializer(
503     io::Printer* printer) const {
504   Formatter format(printer, variables_);
505   format("/*decltype($field$)*/{}");
506   if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
507       HasGeneratedMethods(descriptor_->file(), options_)) {
508     format("\n, /*decltype($cached_byte_size_field$)*/{0}");
509   }
510 }
511 
GenerateAggregateInitializer(io::Printer * printer) const512 void RepeatedPrimitiveFieldGenerator::GenerateAggregateInitializer(
513     io::Printer* printer) const {
514   Formatter format(printer, variables_);
515   format("decltype($field$){arena}");
516   if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
517       HasGeneratedMethods(descriptor_->file(), options_)) {
518     // std::atomic has no move constructor, which prevents explicit aggregate
519     // initialization pre-C++17.
520     format("\n, /*decltype($cached_byte_size_field$)*/{0}");
521   }
522 }
523 
GenerateCopyAggregateInitializer(io::Printer * printer) const524 void RepeatedPrimitiveFieldGenerator::GenerateCopyAggregateInitializer(
525     io::Printer* printer) const {
526 
527   Formatter format(printer, variables_);
528   format("decltype($field$){from.$field$}");
529   if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
530       HasGeneratedMethods(descriptor_->file(), options_)) {
531     // std::atomic has no move constructor.
532     format("\n, /*decltype($cached_byte_size_field$)*/{0}");
533   }
534 }
535 
536 }  // namespace cpp
537 }  // namespace compiler
538 }  // namespace protobuf
539 }  // namespace google
540