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/cpp_message_field.h>
36 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
37 #include <google/protobuf/io/printer.h>
38
39 #include <google/protobuf/stubs/strutil.h>
40
41 namespace google {
42 namespace protobuf {
43 namespace compiler {
44 namespace cpp {
45
46 namespace {
ReinterpretCast(const std::string & type,const std::string & expression,bool implicit_weak_field)47 std::string ReinterpretCast(const std::string& type,
48 const std::string& expression,
49 bool implicit_weak_field) {
50 if (implicit_weak_field) {
51 return "reinterpret_cast< " + type + " >(" + expression + ")";
52 } else {
53 return expression;
54 }
55 }
56
SetMessageVariables(const FieldDescriptor * descriptor,const Options & options,bool implicit_weak,std::map<std::string,std::string> * variables)57 void SetMessageVariables(const FieldDescriptor* descriptor,
58 const Options& options, bool implicit_weak,
59 std::map<std::string, std::string>* variables) {
60 SetCommonFieldVariables(descriptor, variables, options);
61 (*variables)["type"] = FieldMessageTypeName(descriptor, options);
62 (*variables)["casted_member"] = ReinterpretCast(
63 (*variables)["type"] + "*", (*variables)["name"] + "_", implicit_weak);
64 (*variables)["type_default_instance"] =
65 QualifiedDefaultInstanceName(descriptor->message_type(), options);
66 (*variables)["type_default_instance_ptr"] =
67 QualifiedDefaultInstancePtr(descriptor->message_type(), options);
68 (*variables)["type_reference_function"] =
69 implicit_weak ? (" ::" + (*variables)["proto_ns"] +
70 "::internal::StrongReference(" +
71 (*variables)["type_default_instance"] + ");\n")
72 : "";
73 // NOTE: Escaped here to unblock proto1->proto2 migration.
74 // TODO(liujisi): Extend this to apply for other conflicting methods.
75 (*variables)["release_name"] =
76 SafeFunctionName(descriptor->containing_type(), descriptor, "release_");
77 (*variables)["full_name"] = descriptor->full_name();
78 }
79
80 } // namespace
81
82 // ===================================================================
83
MessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options,MessageSCCAnalyzer * scc_analyzer)84 MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
85 const Options& options,
86 MessageSCCAnalyzer* scc_analyzer)
87 : FieldGenerator(descriptor, options),
88 implicit_weak_field_(
89 IsImplicitWeakField(descriptor, options, scc_analyzer)) {
90 SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
91 }
92
~MessageFieldGenerator()93 MessageFieldGenerator::~MessageFieldGenerator() {}
94
GeneratePrivateMembers(io::Printer * printer) const95 void MessageFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
96 Formatter format(printer, variables_);
97 if (implicit_weak_field_) {
98 format("::$proto_ns$::MessageLite* $name$_;\n");
99 } else {
100 format("$type$* $name$_;\n");
101 }
102 }
103
GenerateAccessorDeclarations(io::Printer * printer) const104 void MessageFieldGenerator::GenerateAccessorDeclarations(
105 io::Printer* printer) const {
106 Formatter format(printer, variables_);
107 if (!IsFieldUsed(descriptor_, options_)) {
108 format(
109 "$deprecated_attr$const $type$& ${1$$name$$}$() const { "
110 "__builtin_trap(); }\n"
111 "$deprecated_attr$$type$* ${1$$release_name$$}$() { "
112 "__builtin_trap(); }\n"
113 "$deprecated_attr$$type$* ${1$mutable_$name$$}$() { "
114 "__builtin_trap(); }\n"
115 "$deprecated_attr$void ${1$set_allocated_$name$$}$"
116 "($type$* $name$) { __builtin_trap(); }\n",
117 descriptor_);
118 if (SupportsArenas(descriptor_)) {
119 format(
120 "$deprecated_attr$void "
121 "${1$unsafe_arena_set_allocated_$name$$}$(\n"
122 " $type$* $name$) { __builtin_trap(); }\n"
123 "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$() { "
124 "__builtin_trap(); }\n",
125 descriptor_);
126 }
127 return;
128 }
129 format(
130 "$deprecated_attr$const $type$& ${1$$name$$}$() const;\n"
131 "$deprecated_attr$$type$* ${1$$release_name$$}$();\n"
132 "$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n"
133 "$deprecated_attr$void ${1$set_allocated_$name$$}$"
134 "($type$* $name$);\n",
135 descriptor_);
136 if (IsFieldUsed(descriptor_, options_)) {
137 format(
138 "private:\n"
139 "const $type$& ${1$_internal_$name$$}$() const;\n"
140 "$type$* ${1$_internal_mutable_$name$$}$();\n"
141 "public:\n",
142 descriptor_);
143 }
144 if (SupportsArenas(descriptor_)) {
145 format(
146 "$deprecated_attr$void "
147 "${1$unsafe_arena_set_allocated_$name$$}$(\n"
148 " $type$* $name$);\n"
149 "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n",
150 descriptor_);
151 }
152 }
153
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const154 void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
155 io::Printer* printer) const {
156 }
157
GenerateInlineAccessorDefinitions(io::Printer * printer) const158 void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
159 io::Printer* printer) const {
160 Formatter format(printer, variables_);
161 format(
162 "inline const $type$& $classname$::_internal_$name$() const {\n"
163 "$type_reference_function$"
164 " const $type$* p = $casted_member$;\n"
165 " return p != nullptr ? *p : *reinterpret_cast<const $type$*>(\n"
166 " &$type_default_instance$);\n"
167 "}\n"
168 "inline const $type$& $classname$::$name$() const {\n"
169 "$annotate_accessor$"
170 " // @@protoc_insertion_point(field_get:$full_name$)\n"
171 " return _internal_$name$();\n"
172 "}\n");
173
174 if (SupportsArenas(descriptor_)) {
175 format(
176 "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
177 " $type$* $name$) {\n"
178 "$annotate_accessor$"
179 // If we're not on an arena, free whatever we were holding before.
180 // (If we are on arena, we can just forget the earlier pointer.)
181 " if (GetArena() == nullptr) {\n"
182 " delete reinterpret_cast<::$proto_ns$::MessageLite*>($name$_);\n"
183 " }\n");
184 if (implicit_weak_field_) {
185 format(
186 " $name$_ = "
187 "reinterpret_cast<::$proto_ns$::MessageLite*>($name$);\n");
188 } else {
189 format(" $name$_ = $name$;\n");
190 }
191 format(
192 " if ($name$) {\n"
193 " $set_hasbit$\n"
194 " } else {\n"
195 " $clear_hasbit$\n"
196 " }\n"
197 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
198 ":$full_name$)\n"
199 "}\n");
200 format(
201 "inline $type$* $classname$::$release_name$() {\n"
202 "$type_reference_function$"
203 " $clear_hasbit$\n"
204 " $type$* temp = $casted_member$;\n"
205 " $name$_ = nullptr;\n"
206 " if (GetArena() != nullptr) {\n"
207 " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
208 " }\n"
209 " return temp;\n"
210 "}\n"
211 "inline $type$* $classname$::unsafe_arena_release_$name$() {\n");
212 } else {
213 format("inline $type$* $classname$::$release_name$() {\n");
214 }
215 format(
216 "$annotate_accessor$"
217 " // @@protoc_insertion_point(field_release:$full_name$)\n"
218 "$type_reference_function$"
219 " $clear_hasbit$\n"
220 " $type$* temp = $casted_member$;\n"
221 " $name$_ = nullptr;\n"
222 " return temp;\n"
223 "}\n");
224
225 format(
226 "inline $type$* $classname$::_internal_mutable_$name$() {\n"
227 "$type_reference_function$"
228 " $set_hasbit$\n"
229 " if ($name$_ == nullptr) {\n"
230 " auto* p = CreateMaybeMessage<$type$>(GetArena());\n");
231 if (implicit_weak_field_) {
232 format(" $name$_ = reinterpret_cast<::$proto_ns$::MessageLite*>(p);\n");
233 } else {
234 format(" $name$_ = p;\n");
235 }
236 format(
237 " }\n"
238 " return $casted_member$;\n"
239 "}\n"
240 "inline $type$* $classname$::mutable_$name$() {\n"
241 "$annotate_accessor$"
242 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
243 " return _internal_mutable_$name$();\n"
244 "}\n");
245
246 // We handle the most common case inline, and delegate less common cases to
247 // the slow fallback function.
248 format(
249 "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
250 "$annotate_accessor$"
251 " ::$proto_ns$::Arena* message_arena = GetArena();\n");
252 format(" if (message_arena == nullptr) {\n");
253 if (IsCrossFileMessage(descriptor_)) {
254 format(
255 " delete reinterpret_cast< ::$proto_ns$::MessageLite*>($name$_);\n");
256 } else {
257 format(" delete $name$_;\n");
258 }
259 format(
260 " }\n"
261 " if ($name$) {\n");
262 if (SupportsArenas(descriptor_->message_type()) &&
263 IsCrossFileMessage(descriptor_)) {
264 // We have to read the arena through the virtual method, because the type
265 // isn't defined in this file.
266 format(
267 " ::$proto_ns$::Arena* submessage_arena =\n"
268 " "
269 "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n");
270 } else if (!SupportsArenas(descriptor_->message_type())) {
271 format(" ::$proto_ns$::Arena* submessage_arena = nullptr;\n");
272 } else {
273 format(
274 " ::$proto_ns$::Arena* submessage_arena =\n"
275 " ::$proto_ns$::Arena::GetArena($name$);\n");
276 }
277 format(
278 " if (message_arena != submessage_arena) {\n"
279 " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n"
280 " message_arena, $name$, submessage_arena);\n"
281 " }\n"
282 " $set_hasbit$\n"
283 " } else {\n"
284 " $clear_hasbit$\n"
285 " }\n");
286 if (implicit_weak_field_) {
287 format(" $name$_ = reinterpret_cast<MessageLite*>($name$);\n");
288 } else {
289 format(" $name$_ = $name$;\n");
290 }
291 format(
292 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
293 "}\n");
294 }
295
GenerateInternalAccessorDeclarations(io::Printer * printer) const296 void MessageFieldGenerator::GenerateInternalAccessorDeclarations(
297 io::Printer* printer) const {
298 Formatter format(printer, variables_);
299 if (implicit_weak_field_) {
300 format(
301 "static const ::$proto_ns$::MessageLite& $name$("
302 "const $classname$* msg);\n"
303 "static ::$proto_ns$::MessageLite* mutable_$name$("
304 "$classname$* msg);\n");
305 } else {
306 format("static const $type$& $name$(const $classname$* msg);\n");
307 }
308 }
309
GenerateInternalAccessorDefinitions(io::Printer * printer) const310 void MessageFieldGenerator::GenerateInternalAccessorDefinitions(
311 io::Printer* printer) const {
312 // In theory, these accessors could be inline in _Internal. However, in
313 // practice, the linker is then not able to throw them out making implicit
314 // weak dependencies not work at all.
315 Formatter format(printer, variables_);
316 if (implicit_weak_field_) {
317 // These private accessors are used by MergeFrom and
318 // MergePartialFromCodedStream, and their purpose is to provide access to
319 // the field without creating a strong dependency on the message type.
320 format(
321 "const ::$proto_ns$::MessageLite& $classname$::_Internal::$name$(\n"
322 " const $classname$* msg) {\n"
323 " if (msg->$name$_ != nullptr) {\n"
324 " return *msg->$name$_;\n"
325 " } else if ($type_default_instance_ptr$ != nullptr) {\n"
326 " return *reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
327 " $type_default_instance_ptr$);\n"
328 " } else {\n"
329 " return "
330 "*::$proto_ns$::internal::ImplicitWeakMessage::default_instance();\n"
331 " }\n"
332 "}\n");
333 if (SupportsArenas(descriptor_)) {
334 format(
335 "::$proto_ns$::MessageLite*\n"
336 "$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
337 if (HasFieldPresence(descriptor_->file())) {
338 format(" msg->$set_hasbit$\n");
339 }
340 format(
341 " if (msg->$name$_ == nullptr) {\n"
342 " if ($type_default_instance_ptr$ == nullptr) {\n"
343 " msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n"
344 " ::$proto_ns$::internal::ImplicitWeakMessage>(\n"
345 " msg->GetArena());\n"
346 " } else {\n"
347 " msg->$name$_ = reinterpret_cast<const "
348 "::$proto_ns$::MessageLite*>(\n"
349 " $type_default_instance_ptr$)->New(msg->GetArena());\n"
350 " }\n"
351 " }\n"
352 " return msg->$name$_;\n"
353 "}\n");
354 } else {
355 format(
356 "::$proto_ns$::MessageLite*\n"
357 "$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
358 if (HasFieldPresence(descriptor_->file())) {
359 format(" msg->$set_hasbit$\n");
360 }
361 format(
362 " if (msg->$name$_ == nullptr) {\n"
363 " if ($type_default_instance_ptr$ == nullptr) {\n"
364 " msg->$name$_ = "
365 "new ::$proto_ns$::internal::ImplicitWeakMessage;\n"
366 " } else {\n"
367 " msg->$name$_ = "
368 "reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
369 " $type_default_instance_ptr$)->New();\n"
370 " }\n"
371 " }\n"
372 " return msg->$name$_;\n"
373 "}\n");
374 }
375 } else {
376 // This inline accessor directly returns member field and is used in
377 // Serialize such that AFDO profile correctly captures access information to
378 // message fields under serialize.
379 format(
380 "const $type$&\n"
381 "$classname$::_Internal::$name$(const $classname$* msg) {\n"
382 " return *msg->$field_member$;\n"
383 "}\n");
384 }
385 }
386
GenerateClearingCode(io::Printer * printer) const387 void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
388 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
389
390 Formatter format(printer, variables_);
391 if (!HasFieldPresence(descriptor_->file())) {
392 // If we don't have has-bits, message presence is indicated only by ptr !=
393 // NULL. Thus on clear, we need to delete the object.
394 format(
395 "if (GetArena() == nullptr && $name$_ != nullptr) {\n"
396 " delete $name$_;\n"
397 "}\n"
398 "$name$_ = nullptr;\n");
399 } else {
400 format("if ($name$_ != nullptr) $name$_->Clear();\n");
401 }
402 }
403
GenerateMessageClearingCode(io::Printer * printer) const404 void MessageFieldGenerator::GenerateMessageClearingCode(
405 io::Printer* printer) const {
406 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
407
408 Formatter format(printer, variables_);
409 if (!HasFieldPresence(descriptor_->file())) {
410 // If we don't have has-bits, message presence is indicated only by ptr !=
411 // NULL. Thus on clear, we need to delete the object.
412 format(
413 "if (GetArena() == nullptr && $name$_ != nullptr) {\n"
414 " delete $name$_;\n"
415 "}\n"
416 "$name$_ = nullptr;\n");
417 } else {
418 format(
419 "$DCHK$($name$_ != nullptr);\n"
420 "$name$_->Clear();\n");
421 }
422 }
423
GenerateMergingCode(io::Printer * printer) const424 void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
425 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
426
427 Formatter format(printer, variables_);
428 if (implicit_weak_field_) {
429 format(
430 "_Internal::mutable_$name$(this)->CheckTypeAndMergeFrom(\n"
431 " _Internal::$name$(&from));\n");
432 } else {
433 format(
434 "_internal_mutable_$name$()->$type$::MergeFrom(from._internal_$name$())"
435 ";\n");
436 }
437 }
438
GenerateSwappingCode(io::Printer * printer) const439 void MessageFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
440 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
441
442 Formatter format(printer, variables_);
443 format("swap($name$_, other->$name$_);\n");
444 }
445
GenerateDestructorCode(io::Printer * printer) const446 void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
447 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
448
449 Formatter format(printer, variables_);
450 if (options_.opensource_runtime) {
451 // TODO(gerbens) Remove this when we don't need to destruct default
452 // instances. In google3 a default instance will never get deleted so we
453 // don't need to worry about that but in opensource protobuf default
454 // instances are deleted in shutdown process and we need to take special
455 // care when handling them.
456 format("if (this != internal_default_instance()) ");
457 }
458 format("delete $name$_;\n");
459 }
460
GenerateConstructorCode(io::Printer * printer) const461 void MessageFieldGenerator::GenerateConstructorCode(
462 io::Printer* printer) const {
463 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
464
465 Formatter format(printer, variables_);
466 format("$name$_ = nullptr;\n");
467 }
468
GenerateCopyConstructorCode(io::Printer * printer) const469 void MessageFieldGenerator::GenerateCopyConstructorCode(
470 io::Printer* printer) const {
471 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
472
473 Formatter format(printer, variables_);
474 format(
475 "if (from._internal_has_$name$()) {\n"
476 " $name$_ = new $type$(*from.$name$_);\n"
477 "} else {\n"
478 " $name$_ = nullptr;\n"
479 "}\n");
480 }
481
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const482 void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
483 io::Printer* printer) const {
484 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
485
486 Formatter format(printer, variables_);
487 format(
488 "target = stream->EnsureSpace(target);\n"
489 "target = ::$proto_ns$::internal::WireFormatLite::\n"
490 " InternalWrite$declared_type$(\n"
491 " $number$, _Internal::$name$(this), target, stream);\n");
492 }
493
GenerateByteSize(io::Printer * printer) const494 void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const {
495 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
496
497 Formatter format(printer, variables_);
498 format(
499 "total_size += $tag_size$ +\n"
500 " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
501 " *$field_member$);\n");
502 }
503
504 // ===================================================================
505
MessageOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options,MessageSCCAnalyzer * scc_analyzer)506 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
507 const FieldDescriptor* descriptor, const Options& options,
508 MessageSCCAnalyzer* scc_analyzer)
509 : MessageFieldGenerator(descriptor, options, scc_analyzer) {
510 SetCommonOneofFieldVariables(descriptor, &variables_);
511 }
512
~MessageOneofFieldGenerator()513 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
514
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const515 void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions(
516 io::Printer* printer) const {
517 Formatter format(printer, variables_);
518 format(
519 "void $classname$::set_allocated_$name$($type$* $name$) {\n"
520 "$annotate_accessor$"
521 " ::$proto_ns$::Arena* message_arena = GetArena();\n"
522 " clear_$oneof_name$();\n"
523 " if ($name$) {\n");
524 if (SupportsArenas(descriptor_->message_type()) &&
525 descriptor_->file() != descriptor_->message_type()->file()) {
526 // We have to read the arena through the virtual method, because the type
527 // isn't defined in this file.
528 format(
529 " ::$proto_ns$::Arena* submessage_arena =\n"
530 " "
531 "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n");
532 } else if (!SupportsArenas(descriptor_->message_type())) {
533 format(" ::$proto_ns$::Arena* submessage_arena = nullptr;\n");
534 } else {
535 format(
536 " ::$proto_ns$::Arena* submessage_arena =\n"
537 " ::$proto_ns$::Arena::GetArena($name$);\n");
538 }
539 format(
540 " if (message_arena != submessage_arena) {\n"
541 " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n"
542 " message_arena, $name$, submessage_arena);\n"
543 " }\n"
544 " set_has_$name$();\n"
545 " $field_member$ = $name$;\n"
546 " }\n"
547 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
548 "}\n");
549 }
550
GenerateInlineAccessorDefinitions(io::Printer * printer) const551 void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions(
552 io::Printer* printer) const {
553 Formatter format(printer, variables_);
554 format(
555 "inline $type$* $classname$::$release_name$() {\n"
556 "$annotate_accessor$"
557 " // @@protoc_insertion_point(field_release:$full_name$)\n"
558 " if (_internal_has_$name$()) {\n"
559 " clear_has_$oneof_name$();\n"
560 " $type$* temp = $field_member$;\n");
561 if (SupportsArenas(descriptor_)) {
562 format(
563 " if (GetArena() != nullptr) {\n"
564 " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
565 " }\n");
566 }
567 format(
568 " $field_member$ = nullptr;\n"
569 " return temp;\n"
570 " } else {\n"
571 " return nullptr;\n"
572 " }\n"
573 "}\n");
574
575 format(
576 "inline const $type$& $classname$::_internal_$name$() const {\n"
577 " return _internal_has_$name$()\n"
578 " ? *$field_member$\n"
579 " : *reinterpret_cast< $type$*>(&$type_default_instance$);\n"
580 "}\n"
581 "inline const $type$& $classname$::$name$() const {\n"
582 "$annotate_accessor$"
583 " // @@protoc_insertion_point(field_get:$full_name$)\n"
584 " return _internal_$name$();\n"
585 "}\n");
586
587 if (SupportsArenas(descriptor_)) {
588 format(
589 "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
590 "$annotate_accessor$"
591 " // @@protoc_insertion_point(field_unsafe_arena_release"
592 ":$full_name$)\n"
593 " if (_internal_has_$name$()) {\n"
594 " clear_has_$oneof_name$();\n"
595 " $type$* temp = $field_member$;\n"
596 " $field_member$ = nullptr;\n"
597 " return temp;\n"
598 " } else {\n"
599 " return nullptr;\n"
600 " }\n"
601 "}\n"
602 "inline void $classname$::unsafe_arena_set_allocated_$name$"
603 "($type$* $name$) {\n"
604 "$annotate_accessor$"
605 // We rely on the oneof clear method to free the earlier contents of
606 // this oneof. We can directly use the pointer we're given to set the
607 // new value.
608 " clear_$oneof_name$();\n"
609 " if ($name$) {\n"
610 " set_has_$name$();\n"
611 " $field_member$ = $name$;\n"
612 " }\n"
613 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
614 "$full_name$)\n"
615 "}\n");
616 }
617
618 format(
619 "inline $type$* $classname$::_internal_mutable_$name$() {\n"
620 " if (!_internal_has_$name$()) {\n"
621 " clear_$oneof_name$();\n"
622 " set_has_$name$();\n"
623 " $field_member$ = CreateMaybeMessage< $type$ >(GetArena());\n"
624 " }\n"
625 " return $field_member$;\n"
626 "}\n"
627 "inline $type$* $classname$::mutable_$name$() {\n"
628 "$annotate_accessor$"
629 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
630 " return _internal_mutable_$name$();\n"
631 "}\n");
632 }
633
GenerateClearingCode(io::Printer * printer) const634 void MessageOneofFieldGenerator::GenerateClearingCode(
635 io::Printer* printer) const {
636 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
637
638 Formatter format(printer, variables_);
639 if (SupportsArenas(descriptor_)) {
640 format(
641 "if (GetArena() == nullptr) {\n"
642 " delete $field_member$;\n"
643 "}\n");
644 } else {
645 format("delete $field_member$;\n");
646 }
647 }
648
GenerateMessageClearingCode(io::Printer * printer) const649 void MessageOneofFieldGenerator::GenerateMessageClearingCode(
650 io::Printer* printer) const {
651 GenerateClearingCode(printer);
652 }
653
GenerateSwappingCode(io::Printer * printer) const654 void MessageOneofFieldGenerator::GenerateSwappingCode(
655 io::Printer* printer) const {
656 // Don't print any swapping code. Swapping the union will swap this field.
657 }
658
GenerateDestructorCode(io::Printer * printer) const659 void MessageOneofFieldGenerator::GenerateDestructorCode(
660 io::Printer* printer) const {
661 // We inherit from MessageFieldGenerator, so we need to override the default
662 // behavior.
663 }
664
GenerateConstructorCode(io::Printer * printer) const665 void MessageOneofFieldGenerator::GenerateConstructorCode(
666 io::Printer* printer) const {
667 // Don't print any constructor code. The field is in a union. We allocate
668 // space only when this field is used.
669 }
670
671 // ===================================================================
672
RepeatedMessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options,MessageSCCAnalyzer * scc_analyzer)673 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
674 const FieldDescriptor* descriptor, const Options& options,
675 MessageSCCAnalyzer* scc_analyzer)
676 : FieldGenerator(descriptor, options),
677 implicit_weak_field_(
678 IsImplicitWeakField(descriptor, options, scc_analyzer)) {
679 SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
680 }
681
~RepeatedMessageFieldGenerator()682 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
683
GeneratePrivateMembers(io::Printer * printer) const684 void RepeatedMessageFieldGenerator::GeneratePrivateMembers(
685 io::Printer* printer) const {
686 Formatter format(printer, variables_);
687 if (implicit_weak_field_) {
688 format("::$proto_ns$::WeakRepeatedPtrField< $type$ > $name$_;\n");
689 } else {
690 format("::$proto_ns$::RepeatedPtrField< $type$ > $name$_;\n");
691 }
692 }
693
GenerateAccessorDeclarations(io::Printer * printer) const694 void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations(
695 io::Printer* printer) const {
696 Formatter format(printer, variables_);
697 if (!IsFieldUsed(descriptor_, options_)) {
698 format(
699 "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index) { "
700 "__builtin_trap(); }\n"
701 "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
702 " ${1$mutable_$name$$}$() { __builtin_trap(); }\n"
703 "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const { "
704 "__builtin_trap(); }\n"
705 "$deprecated_attr$$type$* ${1$add_$name$$}$() { "
706 "__builtin_trap(); }\n"
707 "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
708 " ${1$$name$$}$() const { __builtin_trap(); }\n",
709 descriptor_);
710 return;
711 }
712 format(
713 "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index);\n"
714 "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
715 " ${1$mutable_$name$$}$();\n",
716 descriptor_);
717 if (IsFieldUsed(descriptor_, options_)) {
718 format(
719 "private:\n"
720 "const $type$& ${1$_internal_$name$$}$(int index) const;\n"
721 "$type$* ${1$_internal_add_$name$$}$();\n"
722 "public:\n",
723 descriptor_);
724 }
725 format(
726 "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const;\n"
727 "$deprecated_attr$$type$* ${1$add_$name$$}$();\n"
728 "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
729 " ${1$$name$$}$() const;\n",
730 descriptor_);
731 }
732
GenerateInlineAccessorDefinitions(io::Printer * printer) const733 void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
734 io::Printer* printer) const {
735 Formatter format(printer, variables_);
736 format.Set("weak", implicit_weak_field_ ? ".weak" : "");
737
738 format(
739 "inline $type$* $classname$::mutable_$name$(int index) {\n"
740 "$annotate_accessor$"
741 // TODO(dlj): move insertion points
742 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
743 "$type_reference_function$"
744 " return $name$_$weak$.Mutable(index);\n"
745 "}\n"
746 "inline ::$proto_ns$::RepeatedPtrField< $type$ >*\n"
747 "$classname$::mutable_$name$() {\n"
748 "$annotate_accessor$"
749 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
750 "$type_reference_function$"
751 " return &$name$_$weak$;\n"
752 "}\n");
753
754 if (options_.safe_boundary_check) {
755 format(
756 "inline const $type$& $classname$::_internal_$name$(int index) const "
757 "{\n"
758 " return $name$_$weak$.InternalCheckedGet(index,\n"
759 " *reinterpret_cast<const $type$*>(&$type_default_instance$));\n"
760 "}\n");
761 } else {
762 format(
763 "inline const $type$& $classname$::_internal_$name$(int index) const "
764 "{\n"
765 "$type_reference_function$"
766 " return $name$_$weak$.Get(index);\n"
767 "}\n");
768 }
769
770 format(
771 "inline const $type$& $classname$::$name$(int index) const {\n"
772 "$annotate_accessor$"
773 " // @@protoc_insertion_point(field_get:$full_name$)\n"
774 " return _internal_$name$(index);\n"
775 "}\n"
776 "inline $type$* $classname$::_internal_add_$name$() {\n"
777 " return $name$_$weak$.Add();\n"
778 "}\n"
779 "inline $type$* $classname$::add_$name$() {\n"
780 "$annotate_accessor$"
781 " // @@protoc_insertion_point(field_add:$full_name$)\n"
782 " return _internal_add_$name$();\n"
783 "}\n");
784
785 format(
786 "inline const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
787 "$classname$::$name$() const {\n"
788 "$annotate_accessor$"
789 " // @@protoc_insertion_point(field_list:$full_name$)\n"
790 "$type_reference_function$"
791 " return $name$_$weak$;\n"
792 "}\n");
793 }
794
GenerateClearingCode(io::Printer * printer) const795 void RepeatedMessageFieldGenerator::GenerateClearingCode(
796 io::Printer* printer) const {
797 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
798
799 Formatter format(printer, variables_);
800 format("$name$_.Clear();\n");
801 }
802
GenerateMergingCode(io::Printer * printer) const803 void RepeatedMessageFieldGenerator::GenerateMergingCode(
804 io::Printer* printer) const {
805 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
806
807 Formatter format(printer, variables_);
808 format("$name$_.MergeFrom(from.$name$_);\n");
809 }
810
GenerateSwappingCode(io::Printer * printer) const811 void RepeatedMessageFieldGenerator::GenerateSwappingCode(
812 io::Printer* printer) const {
813 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
814
815 Formatter format(printer, variables_);
816 format("$name$_.InternalSwap(&other->$name$_);\n");
817 }
818
GenerateConstructorCode(io::Printer * printer) const819 void RepeatedMessageFieldGenerator::GenerateConstructorCode(
820 io::Printer* printer) const {
821 // Not needed for repeated fields.
822 }
823
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const824 void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
825 io::Printer* printer) const {
826 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
827
828 Formatter format(printer, variables_);
829 if (implicit_weak_field_) {
830 format(
831 "for (auto it = this->$name$_.pointer_begin(),\n"
832 " end = this->$name$_.pointer_end(); it < end; ++it) {\n"
833 " target = stream->EnsureSpace(target);\n"
834 " target = ::$proto_ns$::internal::WireFormatLite::\n"
835 " InternalWrite$declared_type$($number$, **it, target, stream);\n"
836 "}\n");
837 } else {
838 format(
839 "for (unsigned int i = 0,\n"
840 " n = static_cast<unsigned int>(this->_internal_$name$_size()); i < "
841 "n; i++) "
842 "{\n"
843 " target = stream->EnsureSpace(target);\n"
844 " target = ::$proto_ns$::internal::WireFormatLite::\n"
845 " InternalWrite$declared_type$($number$, "
846 "this->_internal_$name$(i), target, stream);\n"
847 "}\n");
848 }
849 }
850
GenerateByteSize(io::Printer * printer) const851 void RepeatedMessageFieldGenerator::GenerateByteSize(
852 io::Printer* printer) const {
853 GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
854
855 Formatter format(printer, variables_);
856 format(
857 "total_size += $tag_size$UL * this->_internal_$name$_size();\n"
858 "for (const auto& msg : this->$name$_) {\n"
859 " total_size +=\n"
860 " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(msg);\n"
861 "}\n");
862 }
863
864 } // namespace cpp
865 } // namespace compiler
866 } // namespace protobuf
867 } // namespace google
868