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