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: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include <google/protobuf/compiler/cpp/message_field.h>
36
37 #include <google/protobuf/io/printer.h>
38 #include <google/protobuf/compiler/cpp/field.h>
39 #include <google/protobuf/compiler/cpp/helpers.h>
40
41 #include <google/protobuf/stubs/strutil.h>
42
43 namespace google {
44 namespace protobuf {
45 namespace compiler {
46 namespace cpp {
47
48 namespace {
ReinterpretCast(const std::string & type,const std::string & expression,bool implicit_weak_field)49 std::string ReinterpretCast(const std::string& type,
50 const std::string& expression,
51 bool implicit_weak_field) {
52 if (implicit_weak_field) {
53 return "reinterpret_cast< " + type + " >(" + expression + ")";
54 } else {
55 return expression;
56 }
57 }
58
SetMessageVariables(const FieldDescriptor * descriptor,const Options & options,bool implicit_weak,std::map<std::string,std::string> * variables)59 void SetMessageVariables(const FieldDescriptor* descriptor,
60 const Options& options, bool implicit_weak,
61 std::map<std::string, std::string>* variables) {
62 SetCommonFieldVariables(descriptor, variables, options);
63 (*variables)["type"] = FieldMessageTypeName(descriptor, options);
64 (*variables)["casted_member"] = ReinterpretCast(
65 (*variables)["type"] + "*", (*variables)["field"], implicit_weak);
66 (*variables)["casted_member_const"] =
67 ReinterpretCast("const " + (*variables)["type"] + "&",
68 "*" + (*variables)["field"], implicit_weak);
69 (*variables)["type_default_instance"] =
70 QualifiedDefaultInstanceName(descriptor->message_type(), options);
71 (*variables)["type_default_instance_ptr"] = ReinterpretCast(
72 "const ::PROTOBUF_NAMESPACE_ID::MessageLite*",
73 QualifiedDefaultInstancePtr(descriptor->message_type(), options),
74 implicit_weak);
75 (*variables)["type_reference_function"] =
76 implicit_weak ? (" ::" + (*variables)["proto_ns"] +
77 "::internal::StrongReference(reinterpret_cast<const " +
78 (*variables)["type"] + "&>(\n" +
79 (*variables)["type_default_instance"] + "));\n")
80 : "";
81 // NOTE: Escaped here to unblock proto1->proto2 migration.
82 // TODO(liujisi): Extend this to apply for other conflicting methods.
83 (*variables)["release_name"] =
84 SafeFunctionName(descriptor->containing_type(), descriptor, "release_");
85 (*variables)["full_name"] = descriptor->full_name();
86 }
87
88 } // namespace
89
90 // ===================================================================
91
MessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options,MessageSCCAnalyzer * scc_analyzer)92 MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
93 const Options& options,
94 MessageSCCAnalyzer* scc_analyzer)
95 : FieldGenerator(descriptor, options),
96 implicit_weak_field_(
97 IsImplicitWeakField(descriptor, options, scc_analyzer)),
98 has_required_fields_(
99 scc_analyzer->HasRequiredFields(descriptor->message_type())) {
100 SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
101 }
102
~MessageFieldGenerator()103 MessageFieldGenerator::~MessageFieldGenerator() {}
104
GeneratePrivateMembers(io::Printer * printer) const105 void MessageFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
106 Formatter format(printer, variables_);
107 if (implicit_weak_field_) {
108 format("::$proto_ns$::MessageLite* $name$_;\n");
109 } else {
110 format("$type$* $name$_;\n");
111 }
112 }
113
GenerateAccessorDeclarations(io::Printer * printer) const114 void MessageFieldGenerator::GenerateAccessorDeclarations(
115 io::Printer* printer) const {
116 Formatter format(printer, variables_);
117 if (IsFieldStripped(descriptor_, options_)) {
118 format(
119 "$deprecated_attr$const $type$& ${1$$name$$}$() const { "
120 "__builtin_trap(); }\n"
121 "PROTOBUF_NODISCARD $deprecated_attr$$type$* "
122 "${1$$release_name$$}$() { "
123 "__builtin_trap(); }\n"
124 "$deprecated_attr$$type$* ${1$mutable_$name$$}$() { "
125 "__builtin_trap(); }\n"
126 "$deprecated_attr$void ${1$set_allocated_$name$$}$"
127 "($type$* $name$) { __builtin_trap(); }\n"
128 "$deprecated_attr$void "
129 "${1$unsafe_arena_set_allocated_$name$$}$(\n"
130 " $type$* $name$) { __builtin_trap(); }\n"
131 "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$() { "
132 "__builtin_trap(); }\n",
133 descriptor_);
134 return;
135 }
136 format(
137 "$deprecated_attr$const $type$& ${1$$name$$}$() const;\n"
138 "PROTOBUF_NODISCARD $deprecated_attr$$type$* "
139 "${1$$release_name$$}$();\n"
140 "$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n"
141 "$deprecated_attr$void ${1$set_allocated_$name$$}$"
142 "($type$* $name$);\n",
143 descriptor_);
144 if (!IsFieldStripped(descriptor_, options_)) {
145 format(
146 "private:\n"
147 "const $type$& ${1$_internal_$name$$}$() const;\n"
148 "$type$* ${1$_internal_mutable_$name$$}$();\n"
149 "public:\n",
150 descriptor_);
151 }
152 format(
153 "$deprecated_attr$void "
154 "${1$unsafe_arena_set_allocated_$name$$}$(\n"
155 " $type$* $name$);\n"
156 "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n",
157 descriptor_);
158 }
159
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const160 void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
161 io::Printer* printer) const {}
162
GenerateInlineAccessorDefinitions(io::Printer * printer) const163 void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
164 io::Printer* printer) const {
165 Formatter format(printer, variables_);
166 format(
167 "inline const $type$& $classname$::_internal_$name$() const {\n"
168 "$type_reference_function$"
169 " const $type$* p = $casted_member$;\n"
170 " return p != nullptr ? *p : reinterpret_cast<const $type$&>(\n"
171 " $type_default_instance$);\n"
172 "}\n"
173 "inline const $type$& $classname$::$name$() const {\n"
174 "$annotate_get$"
175 " // @@protoc_insertion_point(field_get:$full_name$)\n"
176 " return _internal_$name$();\n"
177 "}\n");
178
179 format(
180 "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
181 " $type$* $name$) {\n"
182 "$maybe_prepare_split_message$"
183 // If we're not on an arena, free whatever we were holding before.
184 // (If we are on arena, we can just forget the earlier pointer.)
185 " if (GetArenaForAllocation() == nullptr) {\n"
186 " delete reinterpret_cast<::$proto_ns$::MessageLite*>($field$);\n"
187 " }\n");
188 if (implicit_weak_field_) {
189 format(
190 " $field$ = reinterpret_cast<::$proto_ns$::MessageLite*>($name$);\n");
191 } else {
192 format(" $field$ = $name$;\n");
193 }
194 if (!variables_.at("set_hasbit").empty() ||
195 !variables_.at("clear_hasbit").empty()) {
196 format(
197 " if ($name$) {\n"
198 " $set_hasbit$\n"
199 " } else {\n"
200 " $clear_hasbit$\n"
201 " }\n");
202 }
203 format(
204 "$annotate_set$"
205 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
206 ":$full_name$)\n"
207 "}\n");
208 format(
209 "inline $type$* $classname$::$release_name$() {\n"
210 "$type_reference_function$"
211 "$annotate_release$"
212 "$maybe_prepare_split_message$"
213 " $clear_hasbit$\n"
214 " $type$* temp = $casted_member$;\n"
215 " $field$ = nullptr;\n"
216 "#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE\n"
217 " auto* old = reinterpret_cast<::$proto_ns$::MessageLite*>(temp);\n"
218 " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
219 " if (GetArenaForAllocation() == nullptr) { delete old; }\n"
220 "#else // PROTOBUF_FORCE_COPY_IN_RELEASE\n"
221 " if (GetArenaForAllocation() != nullptr) {\n"
222 " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
223 " }\n"
224 "#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE\n"
225 " return temp;\n"
226 "}\n"
227 "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
228 "$annotate_release$"
229 " // @@protoc_insertion_point(field_release:$full_name$)\n"
230 "$type_reference_function$"
231 "$maybe_prepare_split_message$"
232 " $clear_hasbit$\n"
233 " $type$* temp = $casted_member$;\n"
234 " $field$ = nullptr;\n"
235 " return temp;\n"
236 "}\n");
237
238 format(
239 "inline $type$* $classname$::_internal_mutable_$name$() {\n"
240 "$type_reference_function$"
241 " $set_hasbit$\n"
242 " if ($field$ == nullptr) {\n"
243 " auto* p = CreateMaybeMessage<$type$>(GetArenaForAllocation());\n");
244 if (implicit_weak_field_) {
245 format(" $field$ = reinterpret_cast<::$proto_ns$::MessageLite*>(p);\n");
246 } else {
247 format(" $field$ = p;\n");
248 }
249 format(
250 " }\n"
251 " return $casted_member$;\n"
252 "}\n"
253 "inline $type$* $classname$::mutable_$name$() {\n"
254 // TODO(b/122856539): add tests to make sure all write accessors are able
255 // to prepare split message allocation.
256 "$maybe_prepare_split_message$"
257 " $type$* _msg = _internal_mutable_$name$();\n"
258 "$annotate_mutable$"
259 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
260 " return _msg;\n"
261 "}\n");
262
263 // We handle the most common case inline, and delegate less common cases to
264 // the slow fallback function.
265 format(
266 "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
267 " ::$proto_ns$::Arena* message_arena = GetArenaForAllocation();\n");
268 format(
269 "$maybe_prepare_split_message$"
270 " if (message_arena == nullptr) {\n");
271 if (IsCrossFileMessage(descriptor_)) {
272 format(
273 " delete reinterpret_cast< ::$proto_ns$::MessageLite*>($field$);\n");
274 } else {
275 format(" delete $field$;\n");
276 }
277 format(
278 " }\n"
279 " if ($name$) {\n");
280 if (IsCrossFileMessage(descriptor_)) {
281 // We have to read the arena through the virtual method, because the type
282 // isn't defined in this file.
283 format(
284 " ::$proto_ns$::Arena* submessage_arena =\n"
285 " ::$proto_ns$::Arena::InternalGetOwningArena(\n"
286 " reinterpret_cast<::$proto_ns$::MessageLite*>("
287 "$name$));\n");
288 } else {
289 format(
290 " ::$proto_ns$::Arena* submessage_arena =\n"
291 " ::$proto_ns$::Arena::InternalGetOwningArena("
292 "$name$);\n");
293 }
294 format(
295 " if (message_arena != submessage_arena) {\n"
296 " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n"
297 " message_arena, $name$, submessage_arena);\n"
298 " }\n"
299 " $set_hasbit$\n"
300 " } else {\n"
301 " $clear_hasbit$\n"
302 " }\n");
303 if (implicit_weak_field_) {
304 format(" $field$ = reinterpret_cast<MessageLite*>($name$);\n");
305 } else {
306 format(" $field$ = $name$;\n");
307 }
308 format(
309 "$annotate_set$"
310 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
311 "}\n");
312 }
313
GenerateInternalAccessorDeclarations(io::Printer * printer) const314 void MessageFieldGenerator::GenerateInternalAccessorDeclarations(
315 io::Printer* printer) const {
316 Formatter format(printer, variables_);
317 if (implicit_weak_field_) {
318 format(
319 "static const ::$proto_ns$::MessageLite& $name$("
320 "const $classname$* msg);\n"
321 "static ::$proto_ns$::MessageLite* mutable_$name$("
322 "$classname$* msg);\n");
323 } else {
324 format("static const $type$& $name$(const $classname$* msg);\n");
325 }
326 }
327
GenerateInternalAccessorDefinitions(io::Printer * printer) const328 void MessageFieldGenerator::GenerateInternalAccessorDefinitions(
329 io::Printer* printer) const {
330 // In theory, these accessors could be inline in _Internal. However, in
331 // practice, the linker is then not able to throw them out making implicit
332 // weak dependencies not work at all.
333 Formatter format(printer, variables_);
334 if (implicit_weak_field_) {
335 // These private accessors are used by MergeFrom and
336 // MergePartialFromCodedStream, and their purpose is to provide access to
337 // the field without creating a strong dependency on the message type.
338 format(
339 "const ::$proto_ns$::MessageLite& $classname$::_Internal::$name$(\n"
340 " const $classname$* msg) {\n"
341 " if (msg->$field$ != nullptr) {\n"
342 " return *msg->$field$;\n"
343 " } else {\n"
344 " return *$type_default_instance_ptr$;\n"
345 " }\n"
346 "}\n");
347 format(
348 "::$proto_ns$::MessageLite*\n"
349 "$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
350 if (HasHasbit(descriptor_)) {
351 format(" msg->$set_hasbit$\n");
352 }
353 if (descriptor_->real_containing_oneof() == nullptr) {
354 format(" if (msg->$field$ == nullptr) {\n");
355 } else {
356 format(
357 " if (!msg->_internal_has_$name$()) {\n"
358 " msg->clear_$oneof_name$();\n"
359 " msg->set_has_$name$();\n");
360 }
361 format(
362 " msg->$field$ = $type_default_instance_ptr$->New(\n"
363 " msg->GetArenaForAllocation());\n"
364 " }\n"
365 " return msg->$field$;\n"
366 "}\n");
367 } else {
368 // This inline accessor directly returns member field and is used in
369 // Serialize such that AFDO profile correctly captures access information to
370 // message fields under serialize.
371 format(
372 "const $type$&\n"
373 "$classname$::_Internal::$name$(const $classname$* msg) {\n"
374 " return *msg->$field$;\n"
375 "}\n");
376 }
377 }
378
GenerateClearingCode(io::Printer * printer) const379 void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
380 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
381
382 Formatter format(printer, variables_);
383 if (!HasHasbit(descriptor_)) {
384 // If we don't have has-bits, message presence is indicated only by ptr !=
385 // nullptr. Thus on clear, we need to delete the object.
386 format(
387 "if (GetArenaForAllocation() == nullptr && $field$ != nullptr) {\n"
388 " delete $field$;\n"
389 "}\n"
390 "$field$ = nullptr;\n");
391 } else {
392 format("if ($field$ != nullptr) $field$->Clear();\n");
393 }
394 }
395
GenerateMessageClearingCode(io::Printer * printer) const396 void MessageFieldGenerator::GenerateMessageClearingCode(
397 io::Printer* printer) const {
398 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
399
400 Formatter format(printer, variables_);
401 if (!HasHasbit(descriptor_)) {
402 // If we don't have has-bits, message presence is indicated only by ptr !=
403 // nullptr. Thus on clear, we need to delete the object.
404 format(
405 "if (GetArenaForAllocation() == nullptr && $field$ != nullptr) {\n"
406 " delete $field$;\n"
407 "}\n"
408 "$field$ = nullptr;\n");
409 } else {
410 format(
411 "$DCHK$($field$ != nullptr);\n"
412 "$field$->Clear();\n");
413 }
414 }
415
GenerateMergingCode(io::Printer * printer) const416 void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
417 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
418
419 Formatter format(printer, variables_);
420 if (implicit_weak_field_) {
421 format(
422 "_Internal::mutable_$name$(_this)->CheckTypeAndMergeFrom(\n"
423 " _Internal::$name$(&from));\n");
424 } else {
425 format(
426 "_this->_internal_mutable_$name$()->$type$::MergeFrom(\n"
427 " from._internal_$name$());\n");
428 }
429 }
430
GenerateSwappingCode(io::Printer * printer) const431 void MessageFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
432 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
433
434 Formatter format(printer, variables_);
435 format("swap($field$, other->$field$);\n");
436 }
437
GenerateDestructorCode(io::Printer * printer) const438 void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
439 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
440
441 Formatter format(printer, variables_);
442 if (options_.opensource_runtime) {
443 // TODO(gerbens) Remove this when we don't need to destruct default
444 // instances. In google3 a default instance will never get deleted so we
445 // don't need to worry about that but in opensource protobuf default
446 // instances are deleted in shutdown process and we need to take special
447 // care when handling them.
448 format("if (this != internal_default_instance()) ");
449 }
450 if (ShouldSplit(descriptor_, options_)) {
451 format("delete $cached_split_ptr$->$name$_;\n");
452 return;
453 }
454 format("delete $field$;\n");
455 }
456
GenerateCopyConstructorCode(io::Printer * printer) const457 void MessageFieldGenerator::GenerateCopyConstructorCode(
458 io::Printer* printer) const {
459 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
460
461 Formatter format(printer, variables_);
462 format(
463 "if (from._internal_has_$name$()) {\n"
464 " _this->$field$ = new $type$(*from.$field$);\n"
465 "}\n");
466 }
467
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const468 void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
469 io::Printer* printer) const {
470 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
471
472 Formatter format(printer, variables_);
473 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
474 format(
475 "target = ::$proto_ns$::internal::WireFormatLite::\n"
476 " InternalWrite$declared_type$($number$, _Internal::$name$(this),\n"
477 " _Internal::$name$(this).GetCachedSize(), target, stream);\n");
478 } else {
479 format(
480 "target = stream->EnsureSpace(target);\n"
481 "target = ::$proto_ns$::internal::WireFormatLite::\n"
482 " InternalWrite$declared_type$(\n"
483 " $number$, _Internal::$name$(this), target, stream);\n");
484 }
485 }
486
GenerateByteSize(io::Printer * printer) const487 void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const {
488 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
489
490 Formatter format(printer, variables_);
491 format(
492 "total_size += $tag_size$ +\n"
493 " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
494 " *$field$);\n");
495 }
496
GenerateIsInitialized(io::Printer * printer) const497 void MessageFieldGenerator::GenerateIsInitialized(io::Printer* printer) const {
498 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
499
500 if (!has_required_fields_) return;
501
502 Formatter format(printer, variables_);
503 format(
504 "if (_internal_has_$name$()) {\n"
505 " if (!$field$->IsInitialized()) return false;\n"
506 "}\n");
507 }
508
GenerateConstexprAggregateInitializer(io::Printer * printer) const509 void MessageFieldGenerator::GenerateConstexprAggregateInitializer(
510 io::Printer* printer) const {
511 Formatter format(printer, variables_);
512 format("/*decltype($field$)*/nullptr");
513 }
514
GenerateCopyAggregateInitializer(io::Printer * printer) const515 void MessageFieldGenerator::GenerateCopyAggregateInitializer(
516 io::Printer* printer) const {
517 Formatter format(printer, variables_);
518 format("decltype($field$){nullptr}");
519 }
520
GenerateAggregateInitializer(io::Printer * printer) const521 void MessageFieldGenerator::GenerateAggregateInitializer(
522 io::Printer* printer) const {
523 Formatter format(printer, variables_);
524 if (ShouldSplit(descriptor_, options_)) {
525 format("decltype(Impl_::Split::$name$_){nullptr}");
526 return;
527 }
528 format("decltype($field$){nullptr}");
529 }
530
531 // ===================================================================
532
MessageOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options,MessageSCCAnalyzer * scc_analyzer)533 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
534 const FieldDescriptor* descriptor, const Options& options,
535 MessageSCCAnalyzer* scc_analyzer)
536 : MessageFieldGenerator(descriptor, options, scc_analyzer) {
537 SetCommonOneofFieldVariables(descriptor, &variables_);
538 }
539
~MessageOneofFieldGenerator()540 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
541
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const542 void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions(
543 io::Printer* printer) const {
544 Formatter format(printer, variables_);
545 format(
546 "void $classname$::set_allocated_$name$($type$* $name$) {\n"
547 " ::$proto_ns$::Arena* message_arena = GetArenaForAllocation();\n"
548 " clear_$oneof_name$();\n"
549 " if ($name$) {\n");
550 if (descriptor_->file() != descriptor_->message_type()->file()) {
551 // We have to read the arena through the virtual method, because the type
552 // isn't defined in this file.
553 format(
554 " ::$proto_ns$::Arena* submessage_arena =\n"
555 " ::$proto_ns$::Arena::InternalGetOwningArena(\n"
556 " reinterpret_cast<::$proto_ns$::MessageLite*>("
557 "$name$));\n");
558 } else {
559 format(
560 " ::$proto_ns$::Arena* submessage_arena =\n"
561 " ::$proto_ns$::Arena::InternalGetOwningArena($name$);\n");
562 }
563 format(
564 " if (message_arena != submessage_arena) {\n"
565 " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n"
566 " message_arena, $name$, submessage_arena);\n"
567 " }\n"
568 " set_has_$name$();\n"
569 " $field$ = $name$;\n"
570 " }\n"
571 "$annotate_set$"
572 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
573 "}\n");
574 }
575
GenerateInlineAccessorDefinitions(io::Printer * printer) const576 void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions(
577 io::Printer* printer) const {
578 Formatter format(printer, variables_);
579 format(
580 "inline $type$* $classname$::$release_name$() {\n"
581 "$annotate_release$"
582 " // @@protoc_insertion_point(field_release:$full_name$)\n"
583 "$type_reference_function$"
584 " if (_internal_has_$name$()) {\n"
585 " clear_has_$oneof_name$();\n"
586 " $type$* temp = $casted_member$;\n"
587 " if (GetArenaForAllocation() != nullptr) {\n"
588 " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
589 " }\n"
590 " $field$ = nullptr;\n"
591 " return temp;\n"
592 " } else {\n"
593 " return nullptr;\n"
594 " }\n"
595 "}\n");
596
597 format(
598 "inline const $type$& $classname$::_internal_$name$() const {\n"
599 "$type_reference_function$"
600 " return _internal_has_$name$()\n"
601 " ? $casted_member_const$\n"
602 " : reinterpret_cast< $type$&>($type_default_instance$);\n"
603 "}\n"
604 "inline const $type$& $classname$::$name$() const {\n"
605 "$annotate_get$"
606 " // @@protoc_insertion_point(field_get:$full_name$)\n"
607 " return _internal_$name$();\n"
608 "}\n"
609 "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
610 "$annotate_release$"
611 " // @@protoc_insertion_point(field_unsafe_arena_release"
612 ":$full_name$)\n"
613 "$type_reference_function$"
614 " if (_internal_has_$name$()) {\n"
615 " clear_has_$oneof_name$();\n"
616 " $type$* temp = $casted_member$;\n"
617 " $field$ = nullptr;\n"
618 " return temp;\n"
619 " } else {\n"
620 " return nullptr;\n"
621 " }\n"
622 "}\n"
623 "inline void $classname$::unsafe_arena_set_allocated_$name$"
624 "($type$* $name$) {\n"
625 // We rely on the oneof clear method to free the earlier contents of
626 // this oneof. We can directly use the pointer we're given to set the
627 // new value.
628 " clear_$oneof_name$();\n"
629 " if ($name$) {\n"
630 " set_has_$name$();\n");
631 if (implicit_weak_field_) {
632 format(
633 " $field$ = "
634 "reinterpret_cast<::$proto_ns$::MessageLite*>($name$);\n");
635 } else {
636 format(" $field$ = $name$;\n");
637 }
638 format(
639 " }\n"
640 "$annotate_set$"
641 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
642 "$full_name$)\n"
643 "}\n"
644 "inline $type$* $classname$::_internal_mutable_$name$() {\n"
645 "$type_reference_function$"
646 " if (!_internal_has_$name$()) {\n"
647 " clear_$oneof_name$();\n"
648 " set_has_$name$();\n");
649 if (implicit_weak_field_) {
650 format(
651 " $field$ = "
652 "reinterpret_cast<::$proto_ns$::MessageLite*>(CreateMaybeMessage< "
653 "$type$ >(GetArenaForAllocation()));\n");
654 } else {
655 format(
656 " $field$ = CreateMaybeMessage< $type$ "
657 ">(GetArenaForAllocation());\n");
658 }
659 format(
660 " }\n"
661 " return $casted_member$;\n"
662 "}\n"
663 "inline $type$* $classname$::mutable_$name$() {\n"
664 " $type$* _msg = _internal_mutable_$name$();\n"
665 "$annotate_mutable$"
666 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
667 " return _msg;\n"
668 "}\n");
669 }
670
GenerateClearingCode(io::Printer * printer) const671 void MessageOneofFieldGenerator::GenerateClearingCode(
672 io::Printer* printer) const {
673 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
674
675 Formatter format(printer, variables_);
676 format(
677 "if (GetArenaForAllocation() == nullptr) {\n"
678 " delete $field$;\n"
679 "}\n");
680 }
681
GenerateMessageClearingCode(io::Printer * printer) const682 void MessageOneofFieldGenerator::GenerateMessageClearingCode(
683 io::Printer* printer) const {
684 GenerateClearingCode(printer);
685 }
686
GenerateSwappingCode(io::Printer * printer) const687 void MessageOneofFieldGenerator::GenerateSwappingCode(
688 io::Printer* printer) const {
689 // Don't print any swapping code. Swapping the union will swap this field.
690 }
691
GenerateDestructorCode(io::Printer * printer) const692 void MessageOneofFieldGenerator::GenerateDestructorCode(
693 io::Printer* printer) const {
694 // We inherit from MessageFieldGenerator, so we need to override the default
695 // behavior.
696 }
697
GenerateConstructorCode(io::Printer * printer) const698 void MessageOneofFieldGenerator::GenerateConstructorCode(
699 io::Printer* printer) const {
700 // Don't print any constructor code. The field is in a union. We allocate
701 // space only when this field is used.
702 }
703
GenerateIsInitialized(io::Printer * printer) const704 void MessageOneofFieldGenerator::GenerateIsInitialized(
705 io::Printer* printer) const {
706 if (!has_required_fields_) return;
707
708 Formatter format(printer, variables_);
709 format(
710 "if (_internal_has_$name$()) {\n"
711 " if (!$field$->IsInitialized()) return false;\n"
712 "}\n");
713 }
714
715 // ===================================================================
716
RepeatedMessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options,MessageSCCAnalyzer * scc_analyzer)717 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
718 const FieldDescriptor* descriptor, const Options& options,
719 MessageSCCAnalyzer* scc_analyzer)
720 : FieldGenerator(descriptor, options),
721 implicit_weak_field_(
722 IsImplicitWeakField(descriptor, options, scc_analyzer)),
723 has_required_fields_(
724 scc_analyzer->HasRequiredFields(descriptor->message_type())) {
725 SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
726 }
727
~RepeatedMessageFieldGenerator()728 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
729
GeneratePrivateMembers(io::Printer * printer) const730 void RepeatedMessageFieldGenerator::GeneratePrivateMembers(
731 io::Printer* printer) const {
732 Formatter format(printer, variables_);
733 if (implicit_weak_field_) {
734 format("::$proto_ns$::WeakRepeatedPtrField< $type$ > $name$_;\n");
735 } else {
736 format("::$proto_ns$::RepeatedPtrField< $type$ > $name$_;\n");
737 }
738 }
739
GenerateAccessorDeclarations(io::Printer * printer) const740 void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations(
741 io::Printer* printer) const {
742 Formatter format(printer, variables_);
743 if (IsFieldStripped(descriptor_, options_)) {
744 format(
745 "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index) { "
746 "__builtin_trap(); }\n"
747 "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
748 " ${1$mutable_$name$$}$() { __builtin_trap(); }\n"
749 "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const { "
750 "__builtin_trap(); }\n"
751 "$deprecated_attr$$type$* ${1$add_$name$$}$() { "
752 "__builtin_trap(); }\n"
753 "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
754 " ${1$$name$$}$() const { __builtin_trap(); }\n",
755 descriptor_);
756 return;
757 }
758 format(
759 "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index);\n"
760 "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
761 " ${1$mutable_$name$$}$();\n",
762 descriptor_);
763 if (!IsFieldStripped(descriptor_, options_)) {
764 format(
765 "private:\n"
766 "const $type$& ${1$_internal_$name$$}$(int index) const;\n"
767 "$type$* ${1$_internal_add_$name$$}$();\n"
768 "public:\n",
769 descriptor_);
770 }
771 format(
772 "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const;\n"
773 "$deprecated_attr$$type$* ${1$add_$name$$}$();\n"
774 "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
775 " ${1$$name$$}$() const;\n",
776 descriptor_);
777 }
778
GenerateInlineAccessorDefinitions(io::Printer * printer) const779 void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
780 io::Printer* printer) const {
781 Formatter format(printer, variables_);
782 format.Set("weak", implicit_weak_field_ ? ".weak" : "");
783
784 format(
785 "inline $type$* $classname$::mutable_$name$(int index) {\n"
786 "$annotate_mutable$"
787 // TODO(dlj): move insertion points
788 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
789 "$type_reference_function$"
790 " return $field$$weak$.Mutable(index);\n"
791 "}\n"
792 "inline ::$proto_ns$::RepeatedPtrField< $type$ >*\n"
793 "$classname$::mutable_$name$() {\n"
794 "$annotate_mutable_list$"
795 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
796 "$type_reference_function$"
797 " return &$field$$weak$;\n"
798 "}\n");
799
800 if (options_.safe_boundary_check) {
801 format(
802 "inline const $type$& $classname$::_internal_$name$(int index) const "
803 "{\n"
804 " return $field$$weak$.InternalCheckedGet(index,\n"
805 " reinterpret_cast<const $type$&>($type_default_instance$));\n"
806 "}\n");
807 } else {
808 format(
809 "inline const $type$& $classname$::_internal_$name$(int index) const "
810 "{\n"
811 "$type_reference_function$"
812 " return $field$$weak$.Get(index);\n"
813 "}\n");
814 }
815
816 format(
817 "inline const $type$& $classname$::$name$(int index) const {\n"
818 "$annotate_get$"
819 " // @@protoc_insertion_point(field_get:$full_name$)\n"
820 " return _internal_$name$(index);\n"
821 "}\n"
822 "inline $type$* $classname$::_internal_add_$name$() {\n"
823 " return $field$$weak$.Add();\n"
824 "}\n"
825 "inline $type$* $classname$::add_$name$() {\n"
826 " $type$* _add = _internal_add_$name$();\n"
827 "$annotate_add_mutable$"
828 " // @@protoc_insertion_point(field_add:$full_name$)\n"
829 " return _add;\n"
830 "}\n");
831
832 format(
833 "inline const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
834 "$classname$::$name$() const {\n"
835 "$annotate_list$"
836 " // @@protoc_insertion_point(field_list:$full_name$)\n"
837 "$type_reference_function$"
838 " return $field$$weak$;\n"
839 "}\n");
840 }
841
GenerateClearingCode(io::Printer * printer) const842 void RepeatedMessageFieldGenerator::GenerateClearingCode(
843 io::Printer* printer) const {
844 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
845
846 Formatter format(printer, variables_);
847 format("$field$.Clear();\n");
848 }
849
GenerateMergingCode(io::Printer * printer) const850 void RepeatedMessageFieldGenerator::GenerateMergingCode(
851 io::Printer* printer) const {
852 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
853
854 Formatter format(printer, variables_);
855 format("_this->$field$.MergeFrom(from.$field$);\n");
856 }
857
GenerateSwappingCode(io::Printer * printer) const858 void RepeatedMessageFieldGenerator::GenerateSwappingCode(
859 io::Printer* printer) const {
860 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
861
862 Formatter format(printer, variables_);
863 format("$field$.InternalSwap(&other->$field$);\n");
864 }
865
GenerateConstructorCode(io::Printer * printer) const866 void RepeatedMessageFieldGenerator::GenerateConstructorCode(
867 io::Printer* printer) const {
868 // Not needed for repeated fields.
869 }
870
GenerateDestructorCode(io::Printer * printer) const871 void RepeatedMessageFieldGenerator::GenerateDestructorCode(
872 io::Printer* printer) const {
873 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
874
875 Formatter format(printer, variables_);
876 if (implicit_weak_field_) {
877 format("$field$.~WeakRepeatedPtrField();\n");
878 } else {
879 format("$field$.~RepeatedPtrField();\n");
880 }
881 }
882
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const883 void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
884 io::Printer* printer) const {
885 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
886
887 Formatter format(printer, variables_);
888 if (implicit_weak_field_) {
889 format(
890 "for (auto it = this->$field$.pointer_begin(),\n"
891 " end = this->$field$.pointer_end(); it < end; ++it) {\n");
892 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
893 format(
894 " target = ::$proto_ns$::internal::WireFormatLite::\n"
895 " InternalWrite$declared_type$($number$, "
896 "**it, (**it).GetCachedSize(), target, stream);\n");
897 } else {
898 format(
899 " target = stream->EnsureSpace(target);\n"
900 " target = ::$proto_ns$::internal::WireFormatLite::\n"
901 " InternalWrite$declared_type$($number$, **it, target, "
902 "stream);\n");
903 }
904 format("}\n");
905 } else {
906 format(
907 "for (unsigned i = 0,\n"
908 " n = static_cast<unsigned>(this->_internal_$name$_size());"
909 " i < n; i++) {\n");
910 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
911 format(
912 " const auto& repfield = this->_internal_$name$(i);\n"
913 " target = ::$proto_ns$::internal::WireFormatLite::\n"
914 " InternalWrite$declared_type$($number$, "
915 "repfield, repfield.GetCachedSize(), target, stream);\n"
916 "}\n");
917 } else {
918 format(
919 " target = stream->EnsureSpace(target);\n"
920 " target = ::$proto_ns$::internal::WireFormatLite::\n"
921 " InternalWrite$declared_type$($number$, "
922 "this->_internal_$name$(i), target, stream);\n"
923 "}\n");
924 }
925 }
926 }
927
GenerateByteSize(io::Printer * printer) const928 void RepeatedMessageFieldGenerator::GenerateByteSize(
929 io::Printer* printer) const {
930 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
931
932 Formatter format(printer, variables_);
933 format(
934 "total_size += $tag_size$UL * this->_internal_$name$_size();\n"
935 "for (const auto& msg : this->$field$) {\n"
936 " total_size +=\n"
937 " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(msg);\n"
938 "}\n");
939 }
940
GenerateIsInitialized(io::Printer * printer) const941 void RepeatedMessageFieldGenerator::GenerateIsInitialized(
942 io::Printer* printer) const {
943 GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
944
945 if (!has_required_fields_) return;
946
947 Formatter format(printer, variables_);
948 if (implicit_weak_field_) {
949 format(
950 "if (!::$proto_ns$::internal::AllAreInitializedWeak($field$.weak))\n"
951 " return false;\n");
952 } else {
953 format(
954 "if (!::$proto_ns$::internal::AllAreInitialized($field$))\n"
955 " return false;\n");
956 }
957 }
958
959 } // namespace cpp
960 } // namespace compiler
961 } // namespace protobuf
962 } // namespace google
963