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.h>
36
37#include <algorithm>
38#include <cstdint>
39#include <functional>
40#include <map>
41#include <memory>
42#include <unordered_map>
43#include <utility>
44#include <vector>
45
46#include <google/protobuf/stubs/common.h>
47#include <google/protobuf/io/coded_stream.h>
48#include <google/protobuf/io/printer.h>
49#include <google/protobuf/descriptor.h>
50#include <google/protobuf/generated_message_util.h>
51#include <google/protobuf/map_entry_lite.h>
52#include <google/protobuf/wire_format.h>
53#include <google/protobuf/stubs/strutil.h>
54#include <google/protobuf/stubs/stringprintf.h>
55#include <google/protobuf/stubs/substitute.h>
56#include <google/protobuf/compiler/cpp/enum.h>
57#include <google/protobuf/compiler/cpp/extension.h>
58#include <google/protobuf/compiler/cpp/field.h>
59#include <google/protobuf/compiler/cpp/helpers.h>
60#include <google/protobuf/compiler/cpp/padding_optimizer.h>
61#include <google/protobuf/compiler/cpp/parse_function_generator.h>
62#include <google/protobuf/descriptor.pb.h>
63#include <google/protobuf/stubs/hash.h>
64
65
66// Must be included last.
67#include <google/protobuf/port_def.inc>
68
69namespace google {
70namespace protobuf {
71namespace compiler {
72namespace cpp {
73
74using internal::WireFormat;
75using internal::WireFormatLite;
76
77namespace {
78
79static constexpr int kNoHasbit = -1;
80
81// Create an expression that evaluates to
82// "for all i, (_has_bits_[i] & masks[i]) == masks[i]"
83// masks is allowed to be shorter than _has_bits_, but at least one element of
84// masks must be non-zero.
85std::string ConditionalToCheckBitmasks(
86 const std::vector<uint32_t>& masks, bool return_success = true,
87 StringPiece has_bits_var = "_impl_._has_bits_") {
88 std::vector<std::string> parts;
89 for (int i = 0; i < masks.size(); i++) {
90 if (masks[i] == 0) continue;
91 std::string m = StrCat(a: "0x", b: strings::Hex(masks[i], strings::ZERO_PAD_8));
92 // Each xor evaluates to 0 if the expected bits are present.
93 parts.push_back(
94 x: StrCat(a: "((", b: has_bits_var, c: "[", d: i, e: "] & ", f: m, g: ") ^ ", h: m, i: ")"));
95 }
96 GOOGLE_CHECK(!parts.empty());
97 // If we have multiple parts, each expected to be 0, then bitwise-or them.
98 std::string result =
99 parts.size() == 1
100 ? parts[0]
101 : StrCat(a: "(", b: Join(components: parts, delim: "\n | "), c: ")");
102 return result + (return_success ? " == 0" : " != 0");
103}
104
105void PrintPresenceCheck(const Formatter& format, const FieldDescriptor* field,
106 const std::vector<int>& has_bit_indices,
107 io::Printer* printer, int* cached_has_word_index) {
108 if (!field->options().weak()) {
109 int has_bit_index = has_bit_indices[field->index()];
110 if (*cached_has_word_index != (has_bit_index / 32)) {
111 *cached_has_word_index = (has_bit_index / 32);
112 format("cached_has_bits = $has_bits$[$1$];\n", *cached_has_word_index);
113 }
114 const std::string mask =
115 StrCat(a: strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
116 format("if (cached_has_bits & 0x$1$u) {\n", mask);
117 } else {
118 format("if (has_$1$()) {\n", FieldName(field));
119 }
120 format.Indent();
121}
122
123struct FieldOrderingByNumber {
124 inline bool operator()(const FieldDescriptor* a,
125 const FieldDescriptor* b) const {
126 return a->number() < b->number();
127 }
128};
129
130// Sort the fields of the given Descriptor by number into a new[]'d array
131// and return it.
132std::vector<const FieldDescriptor*> SortFieldsByNumber(
133 const Descriptor* descriptor) {
134 std::vector<const FieldDescriptor*> fields(descriptor->field_count());
135 for (int i = 0; i < descriptor->field_count(); i++) {
136 fields[i] = descriptor->field(index: i);
137 }
138 std::sort(first: fields.begin(), last: fields.end(), comp: FieldOrderingByNumber());
139 return fields;
140}
141
142// Functor for sorting extension ranges by their "start" field number.
143struct ExtensionRangeSorter {
144 bool operator()(const Descriptor::ExtensionRange* left,
145 const Descriptor::ExtensionRange* right) const {
146 return left->start < right->start;
147 }
148};
149
150bool IsPOD(const FieldDescriptor* field) {
151 if (field->is_repeated() || field->is_extension()) return false;
152 switch (field->cpp_type()) {
153 case FieldDescriptor::CPPTYPE_ENUM:
154 case FieldDescriptor::CPPTYPE_INT32:
155 case FieldDescriptor::CPPTYPE_INT64:
156 case FieldDescriptor::CPPTYPE_UINT32:
157 case FieldDescriptor::CPPTYPE_UINT64:
158 case FieldDescriptor::CPPTYPE_FLOAT:
159 case FieldDescriptor::CPPTYPE_DOUBLE:
160 case FieldDescriptor::CPPTYPE_BOOL:
161 return true;
162 case FieldDescriptor::CPPTYPE_STRING:
163 return false;
164 default:
165 return false;
166 }
167}
168
169// Helper for the code that emits the SharedCtor() and InternalSwap() methods.
170// Anything that is a POD or a "normal" message (represented by a pointer) can
171// be manipulated as raw bytes.
172bool CanBeManipulatedAsRawBytes(const FieldDescriptor* field,
173 const Options& options,
174 MessageSCCAnalyzer* scc_analyzer) {
175 bool ret = CanInitializeByZeroing(field);
176
177 // Non-repeated, non-lazy message fields are simply raw pointers, so we can
178 // swap them or use memset to initialize these in SharedCtor. We cannot use
179 // this in Clear, as we need to potentially delete the existing value.
180 ret =
181 ret || (!field->is_repeated() && !IsLazy(field, options, scc_analyzer) &&
182 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
183 return ret;
184}
185
186bool StrContains(const std::string& haystack, const std::string& needle) {
187 return haystack.find(str: needle) != std::string::npos;
188}
189
190// Finds runs of fields for which `predicate` is true.
191// RunMap maps from fields that start each run to the number of fields in that
192// run. This is optimized for the common case that there are very few runs in
193// a message and that most of the eligible fields appear together.
194using RunMap = std::unordered_map<const FieldDescriptor*, size_t>;
195RunMap FindRuns(const std::vector<const FieldDescriptor*>& fields,
196 const std::function<bool(const FieldDescriptor*)>& predicate) {
197 RunMap runs;
198 const FieldDescriptor* last_start = nullptr;
199
200 for (auto field : fields) {
201 if (predicate(field)) {
202 if (last_start == nullptr) {
203 last_start = field;
204 }
205
206 runs[last_start]++;
207 } else {
208 last_start = nullptr;
209 }
210 }
211 return runs;
212}
213
214// Emits an if-statement with a condition that evaluates to true if |field| is
215// considered non-default (will be sent over the wire), for message types
216// without true field presence. Should only be called if
217// !HasHasbit(field).
218bool EmitFieldNonDefaultCondition(io::Printer* printer,
219 const std::string& prefix,
220 const FieldDescriptor* field) {
221 GOOGLE_CHECK(!HasHasbit(field));
222 Formatter format(printer);
223 format.Set(key: "prefix", value: prefix);
224 format.Set(key: "name", value: FieldName(field));
225 // Merge and serialize semantics: primitive fields are merged/serialized only
226 // if non-zero (numeric) or non-empty (string).
227 if (!field->is_repeated() && !field->containing_oneof()) {
228 if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
229 format("if (!$prefix$_internal_$name$().empty()) {\n");
230 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
231 // Message fields still have has_$name$() methods.
232 format("if ($prefix$_internal_has_$name$()) {\n");
233 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT) {
234 format(
235 "static_assert(sizeof(uint32_t) == sizeof(float), \"Code assumes "
236 "uint32_t and float are the same size.\");\n"
237 "float tmp_$name$ = $prefix$_internal_$name$();\n"
238 "uint32_t raw_$name$;\n"
239 "memcpy(&raw_$name$, &tmp_$name$, sizeof(tmp_$name$));\n"
240 "if (raw_$name$ != 0) {\n");
241 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
242 format(
243 "static_assert(sizeof(uint64_t) == sizeof(double), \"Code assumes "
244 "uint64_t and double are the same size.\");\n"
245 "double tmp_$name$ = $prefix$_internal_$name$();\n"
246 "uint64_t raw_$name$;\n"
247 "memcpy(&raw_$name$, &tmp_$name$, sizeof(tmp_$name$));\n"
248 "if (raw_$name$ != 0) {\n");
249 } else {
250 format("if ($prefix$_internal_$name$() != 0) {\n");
251 }
252 format.Indent();
253 return true;
254 } else if (field->real_containing_oneof()) {
255 format("if (_internal_has_$name$()) {\n");
256 format.Indent();
257 return true;
258 }
259 return false;
260}
261
262// Does the given field have a has_$name$() method?
263bool HasHasMethod(const FieldDescriptor* field) {
264 if (!IsProto3(file: field->file())) {
265 // In proto1/proto2, every field has a has_$name$() method.
266 return true;
267 }
268 // For message types without true field presence, only fields with a message
269 // type or inside an one-of have a has_$name$() method.
270 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
271 field->has_optional_keyword() || field->real_containing_oneof();
272}
273
274// Collects map entry message type information.
275void CollectMapInfo(const Options& options, const Descriptor* descriptor,
276 std::map<std::string, std::string>* variables) {
277 GOOGLE_CHECK(IsMapEntryMessage(descriptor));
278 std::map<std::string, std::string>& vars = *variables;
279 const FieldDescriptor* key = descriptor->map_key();
280 const FieldDescriptor* val = descriptor->map_value();
281 vars["key_cpp"] = PrimitiveTypeName(options, type: key->cpp_type());
282 switch (val->cpp_type()) {
283 case FieldDescriptor::CPPTYPE_MESSAGE:
284 vars["val_cpp"] = FieldMessageTypeName(field: val, options);
285 break;
286 case FieldDescriptor::CPPTYPE_ENUM:
287 vars["val_cpp"] = ClassName(descriptor: val->enum_type(), qualified: true);
288 break;
289 default:
290 vars["val_cpp"] = PrimitiveTypeName(options, type: val->cpp_type());
291 }
292 vars["key_wire_type"] =
293 "TYPE_" + ToUpper(s: DeclaredTypeMethodName(type: key->type()));
294 vars["val_wire_type"] =
295 "TYPE_" + ToUpper(s: DeclaredTypeMethodName(type: val->type()));
296}
297
298// Does the given field have a private (internal helper only) has_$name$()
299// method?
300bool HasPrivateHasMethod(const FieldDescriptor* field) {
301 // Only for oneofs in message types with no field presence. has_$name$(),
302 // based on the oneof case, is still useful internally for generated code.
303 return IsProto3(file: field->file()) && field->real_containing_oneof();
304}
305
306// TODO(ckennelly): Cull these exclusions if/when these protos do not have
307// their methods overridden by subclasses.
308
309bool ShouldMarkClassAsFinal(const Descriptor* descriptor,
310 const Options& options) {
311 return true;
312}
313
314
315// Returns true to make the message serialize in order, decided by the following
316// factors in the order of precedence.
317// --options().message_set_wire_format() == true
318// --the message is in the allowlist (true)
319// --GOOGLE_PROTOBUF_SHUFFLE_SERIALIZE is defined (false)
320// --a ranage of message names that are allowed to stay in order (true)
321bool ShouldSerializeInOrder(const Descriptor* descriptor,
322 const Options& options) {
323 return true;
324}
325
326bool IsCrossFileMapField(const FieldDescriptor* field) {
327 if (!field->is_map()) {
328 return false;
329 }
330
331 const Descriptor* d = field->message_type();
332 const FieldDescriptor* value = d->FindFieldByNumber(number: 2);
333
334 return IsCrossFileMessage(field: value);
335}
336
337bool IsCrossFileMaybeMap(const FieldDescriptor* field) {
338 if (IsCrossFileMapField(field)) {
339 return true;
340 }
341
342 return IsCrossFileMessage(field);
343}
344
345bool IsRequired(const std::vector<const FieldDescriptor*>& v) {
346 return v.front()->is_required();
347}
348
349bool HasNonSplitOptionalString(const Descriptor* desc, const Options& options) {
350 for (const auto* field : FieldRange(desc)) {
351 if (IsString(field, options) && !field->is_repeated() &&
352 !field->real_containing_oneof() && !ShouldSplit(field, options)) {
353 return true;
354 }
355 }
356 return false;
357}
358
359// Collects neighboring fields based on a given criteria (equivalent predicate).
360template <typename Predicate>
361std::vector<std::vector<const FieldDescriptor*>> CollectFields(
362 const std::vector<const FieldDescriptor*>& fields,
363 const Predicate& equivalent) {
364 std::vector<std::vector<const FieldDescriptor*>> chunks;
365 for (auto field : fields) {
366 if (chunks.empty() || !equivalent(chunks.back().back(), field)) {
367 chunks.emplace_back();
368 }
369 chunks.back().push_back(x: field);
370 }
371 return chunks;
372}
373
374// Returns a bit mask based on has_bit index of "fields" that are typically on
375// the same chunk. It is used in a group presence check where _has_bits_ is
376// masked to tell if any thing in "fields" is present.
377uint32_t GenChunkMask(const std::vector<const FieldDescriptor*>& fields,
378 const std::vector<int>& has_bit_indices) {
379 GOOGLE_CHECK(!fields.empty());
380 int first_index_offset = has_bit_indices[fields.front()->index()] / 32;
381 uint32_t chunk_mask = 0;
382 for (auto field : fields) {
383 // "index" defines where in the _has_bits_ the field appears.
384 int index = has_bit_indices[field->index()];
385 GOOGLE_CHECK_EQ(first_index_offset, index / 32);
386 chunk_mask |= static_cast<uint32_t>(1) << (index % 32);
387 }
388 GOOGLE_CHECK_NE(0, chunk_mask);
389 return chunk_mask;
390}
391
392// Return the number of bits set in n, a non-negative integer.
393static int popcnt(uint32_t n) {
394 int result = 0;
395 while (n != 0) {
396 result += (n & 1);
397 n = n / 2;
398 }
399 return result;
400}
401
402// For a run of cold chunks, opens and closes an external if statement that
403// checks multiple has_bits words to skip bulk of cold fields.
404class ColdChunkSkipper {
405 public:
406 ColdChunkSkipper(
407 const Descriptor* descriptor, const Options& options,
408 const std::vector<std::vector<const FieldDescriptor*>>& chunks,
409 const std::vector<int>& has_bit_indices, const double cold_threshold)
410 : chunks_(chunks),
411 has_bit_indices_(has_bit_indices),
412 access_info_map_(options.access_info_map),
413 cold_threshold_(cold_threshold) {
414 SetCommonVars(options, variables: &variables_);
415 SetCommonMessageDataVariables(descriptor, variables: &variables_);
416 }
417
418 // May open an external if check for a batch of cold fields. "from" is the
419 // prefix to _has_bits_ to allow MergeFrom to use "from._has_bits_".
420 // Otherwise, it should be "".
421 void OnStartChunk(int chunk, int cached_has_word_index,
422 const std::string& from, io::Printer* printer);
423 bool OnEndChunk(int chunk, io::Printer* printer);
424
425 private:
426 bool IsColdChunk(int chunk);
427
428 int HasbitWord(int chunk, int offset) {
429 return has_bit_indices_[chunks_[chunk][offset]->index()] / 32;
430 }
431
432 const std::vector<std::vector<const FieldDescriptor*>>& chunks_;
433 const std::vector<int>& has_bit_indices_;
434 const AccessInfoMap* access_info_map_;
435 const double cold_threshold_;
436 std::map<std::string, std::string> variables_;
437 int limit_chunk_ = -1;
438};
439
440// Tuning parameters for ColdChunkSkipper.
441const double kColdRatio = 0.005;
442
443bool ColdChunkSkipper::IsColdChunk(int chunk) {
444 // Mark this variable as used until it is actually used
445 (void)cold_threshold_;
446 return false;
447}
448
449
450void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index,
451 const std::string& from,
452 io::Printer* printer) {
453 Formatter format(printer, variables_);
454 if (!access_info_map_) {
455 return;
456 } else if (chunk < limit_chunk_) {
457 // We are already inside a run of cold chunks.
458 return;
459 } else if (!IsColdChunk(chunk)) {
460 // We can't start a run of cold chunks.
461 return;
462 }
463
464 // Find the end of consecutive cold chunks.
465 limit_chunk_ = chunk;
466 while (limit_chunk_ < chunks_.size() && IsColdChunk(chunk: limit_chunk_)) {
467 limit_chunk_++;
468 }
469
470 if (limit_chunk_ <= chunk + 1) {
471 // Require at least two chunks to emit external has_bit checks.
472 limit_chunk_ = -1;
473 return;
474 }
475
476 // Emit has_bit check for each has_bit_dword index.
477 format("if (PROTOBUF_PREDICT_FALSE(");
478 int first_word = HasbitWord(chunk, offset: 0);
479 while (chunk < limit_chunk_) {
480 uint32_t mask = 0;
481 int this_word = HasbitWord(chunk, offset: 0);
482 // Generate mask for chunks on the same word.
483 for (; chunk < limit_chunk_ && HasbitWord(chunk, offset: 0) == this_word; chunk++) {
484 for (auto field : chunks_[chunk]) {
485 int hasbit_index = has_bit_indices_[field->index()];
486 // Fields on a chunk must be in the same word.
487 GOOGLE_CHECK_EQ(this_word, hasbit_index / 32);
488 mask |= 1 << (hasbit_index % 32);
489 }
490 }
491
492 if (this_word != first_word) {
493 format(" ||\n ");
494 }
495 format.Set(key: "mask", value: strings::Hex(mask, strings::ZERO_PAD_8));
496 if (this_word == cached_has_word_index) {
497 format("(cached_has_bits & 0x$mask$u) != 0");
498 } else {
499 format("($1$_impl_._has_bits_[$2$] & 0x$mask$u) != 0", from, this_word);
500 }
501 }
502 format(")) {\n");
503 format.Indent();
504}
505
506bool ColdChunkSkipper::OnEndChunk(int chunk, io::Printer* printer) {
507 Formatter format(printer, variables_);
508 if (chunk != limit_chunk_ - 1) {
509 return false;
510 }
511 format.Outdent();
512 format("}\n");
513 return true;
514}
515
516void MaySetAnnotationVariable(const Options& options,
517 StringPiece annotation_name,
518 StringPiece injector_template_prefix,
519 StringPiece injector_template_suffix,
520 std::map<std::string, std::string>* variables) {
521 if (options.field_listener_options.forbidden_field_listener_events.count(
522 x: std::string(annotation_name)))
523 return;
524 (*variables)[StrCat(a: "annotate_", b: annotation_name)] = strings::Substitute(
525 format: StrCat(a: injector_template_prefix, b: injector_template_suffix),
526 arg0: (*variables)["classtype"]);
527}
528
529void GenerateExtensionAnnotations(
530 const Descriptor* descriptor, const Options& options,
531 std::map<std::string, std::string>* variables) {
532 const std::map<std::string, std::string> accessor_annotations_to_hooks = {
533 {"annotate_extension_has", "OnHasExtension"},
534 {"annotate_extension_clear", "OnClearExtension"},
535 {"annotate_extension_repeated_size", "OnExtensionSize"},
536 {"annotate_extension_get", "OnGetExtension"},
537 {"annotate_extension_mutable", "OnMutableExtension"},
538 {"annotate_extension_set", "OnSetExtension"},
539 {"annotate_extension_release", "OnReleaseExtension"},
540 {"annotate_repeated_extension_get", "OnGetExtension"},
541 {"annotate_repeated_extension_mutable", "OnMutableExtension"},
542 {"annotate_repeated_extension_set", "OnSetExtension"},
543 {"annotate_repeated_extension_add", "OnAddExtension"},
544 {"annotate_repeated_extension_add_mutable", "OnAddMutableExtension"},
545 {"annotate_repeated_extension_list", "OnListExtension"},
546 {"annotate_repeated_extension_list_mutable", "OnMutableListExtension"},
547 };
548 for (const auto& annotation : accessor_annotations_to_hooks) {
549 (*variables)[annotation.first] = "";
550 }
551 if (!HasTracker(desc: descriptor, options)) {
552 return;
553 }
554 StringPiece tracker = (*variables)["tracker"];
555 StringPiece extensions = (*variables)["extensions"];
556 for (const auto& annotation : accessor_annotations_to_hooks) {
557 const std::string& annotation_name = annotation.first;
558 const std::string& listener_call = annotation.second;
559 if (!StrContains(haystack: annotation_name, needle: "repeated") &&
560 !StrContains(haystack: annotation_name, needle: "size") &&
561 !StrContains(haystack: annotation_name, needle: "clear")) {
562 // Primitive fields accessors.
563 // "Has" is here as users calling "has" on a repeated field is a mistake.
564 (*variables)[annotation_name] = StrCat(
565 a: " ", b: tracker, c: ".", d: listener_call,
566 e: "(this, id.number(), _proto_TypeTraits::GetPtr(id.number(), ",
567 f: extensions, g: ", id.default_value_ref()));");
568 } else if (StrContains(haystack: annotation_name, needle: "repeated") &&
569 !StrContains(haystack: annotation_name, needle: "list") &&
570 !StrContains(haystack: annotation_name, needle: "size")) {
571 // Repeated index accessors.
572 std::string str_index = "index";
573 if (StrContains(haystack: annotation_name, needle: "add")) {
574 str_index = StrCat(a: extensions, b: ".ExtensionSize(id.number()) - 1");
575 }
576 (*variables)[annotation_name] =
577 StrCat(a: " ", b: tracker, c: ".", d: listener_call,
578 e: "(this, id.number(), "
579 "_proto_TypeTraits::GetPtr(id.number(), ",
580 f: extensions, g: ", ", h: str_index, i: "));");
581 } else if (StrContains(haystack: annotation_name, needle: "list") ||
582 StrContains(haystack: annotation_name, needle: "size")) {
583 // Repeated full accessors.
584 (*variables)[annotation_name] = StrCat(
585 a: " ", b: tracker, c: ".", d: listener_call,
586 e: "(this, id.number(), _proto_TypeTraits::GetRepeatedPtr(id.number(), ",
587 f: extensions, g: "));");
588 } else {
589 // Generic accessors such as "clear".
590 // TODO(b/190614678): Generalize clear from both repeated and non repeated
591 // calls, currently their underlying memory interfaces are very different.
592 // Or think of removing clear callback as no usages are needed and no
593 // memory exist after calling clear().
594 }
595 }
596}
597
598} // anonymous namespace
599
600// ===================================================================
601
602MessageGenerator::MessageGenerator(
603 const Descriptor* descriptor,
604 const std::map<std::string, std::string>& vars, int index_in_file_messages,
605 const Options& options, MessageSCCAnalyzer* scc_analyzer)
606 : descriptor_(descriptor),
607 index_in_file_messages_(index_in_file_messages),
608 classname_(ClassName(descriptor, qualified: false)),
609 options_(options),
610 field_generators_(descriptor, options, scc_analyzer),
611 max_has_bit_index_(0),
612 max_inlined_string_index_(0),
613 num_weak_fields_(0),
614 scc_analyzer_(scc_analyzer),
615 variables_(vars) {
616 if (!message_layout_helper_) {
617 message_layout_helper_.reset(p: new PaddingOptimizer());
618 }
619 SetCommonMessageDataVariables(descriptor, variables: &variables_);
620
621 // Variables that apply to this class
622 variables_["classname"] = classname_;
623 variables_["classtype"] = QualifiedClassName(d: descriptor_, options);
624 variables_["full_name"] = descriptor_->full_name();
625 variables_["superclass"] = SuperClassName(descriptor: descriptor_, options: options_);
626 variables_["annotate_serialize"] = "";
627 variables_["annotate_deserialize"] = "";
628 variables_["annotate_reflection"] = "";
629 variables_["annotate_bytesize"] = "";
630 variables_["annotate_mergefrom"] = "";
631
632 if (HasTracker(desc: descriptor_, options: options_)) {
633 const std::string injector_template =
634 StrCat(a: " ", b: variables_["tracker"], c: ".");
635
636 MaySetAnnotationVariable(options, annotation_name: "serialize", injector_template_prefix: injector_template,
637 injector_template_suffix: "OnSerialize(this);\n", variables: &variables_);
638 MaySetAnnotationVariable(options, annotation_name: "deserialize", injector_template_prefix: injector_template,
639 injector_template_suffix: "OnDeserialize(this);\n", variables: &variables_);
640 // TODO(danilak): Ideally annotate_reflection should not exist and we need
641 // to annotate all reflective calls on our own, however, as this is a cause
642 // for side effects, i.e. reading values dynamically, we want the users know
643 // that dynamic access can happen.
644 MaySetAnnotationVariable(options, annotation_name: "reflection", injector_template_prefix: injector_template,
645 injector_template_suffix: "OnGetMetadata();\n", variables: &variables_);
646 MaySetAnnotationVariable(options, annotation_name: "bytesize", injector_template_prefix: injector_template,
647 injector_template_suffix: "OnByteSize(this);\n", variables: &variables_);
648 MaySetAnnotationVariable(options, annotation_name: "mergefrom", injector_template_prefix: injector_template,
649 injector_template_suffix: "OnMergeFrom(_this, &from);\n", variables: &variables_);
650 }
651
652 GenerateExtensionAnnotations(descriptor: descriptor_, options: options_, variables: &variables_);
653
654 SetUnknownFieldsVariable(descriptor: descriptor_, options: options_, variables: &variables_);
655
656 // Compute optimized field order to be used for layout and initialization
657 // purposes.
658 for (auto field : FieldRange(desc: descriptor_)) {
659 if (IsFieldStripped(field, options_)) {
660 continue;
661 }
662
663 if (IsWeak(field, options: options_)) {
664 num_weak_fields_++;
665 } else if (!field->real_containing_oneof()) {
666 optimized_order_.push_back(x: field);
667 }
668 }
669
670 message_layout_helper_->OptimizeLayout(fields: &optimized_order_, options: options_,
671 scc_analyzer: scc_analyzer_);
672
673 // This message has hasbits iff one or more fields need one.
674 for (auto field : optimized_order_) {
675 if (HasHasbit(field)) {
676 if (has_bit_indices_.empty()) {
677 has_bit_indices_.resize(new_size: descriptor_->field_count(), x: kNoHasbit);
678 }
679 has_bit_indices_[field->index()] = max_has_bit_index_++;
680 }
681 if (IsStringInlined(descriptor: field, options: options_)) {
682 if (inlined_string_indices_.empty()) {
683 inlined_string_indices_.resize(new_size: descriptor_->field_count(), x: kNoHasbit);
684 // The bitset[0] is for arena dtor tracking. Donating states start from
685 // bitset[1];
686 max_inlined_string_index_++;
687 }
688 inlined_string_indices_[field->index()] = max_inlined_string_index_++;
689 }
690 }
691
692 if (!has_bit_indices_.empty()) {
693 field_generators_.SetHasBitIndices(has_bit_indices_);
694 }
695
696 if (!inlined_string_indices_.empty()) {
697 field_generators_.SetInlinedStringIndices(inlined_string_indices_);
698 }
699
700 num_required_fields_ = 0;
701 for (int i = 0; i < descriptor->field_count(); i++) {
702 if (descriptor->field(index: i)->is_required()) {
703 ++num_required_fields_;
704 }
705 }
706
707 parse_function_generator_.reset(p: new ParseFunctionGenerator(
708 descriptor_, max_has_bit_index_, has_bit_indices_,
709 inlined_string_indices_, options_, scc_analyzer_, variables_));
710}
711
712MessageGenerator::~MessageGenerator() = default;
713
714size_t MessageGenerator::HasBitsSize() const {
715 return (max_has_bit_index_ + 31) / 32;
716}
717
718size_t MessageGenerator::InlinedStringDonatedSize() const {
719 return (max_inlined_string_index_ + 31) / 32;
720}
721
722int MessageGenerator::HasBitIndex(const FieldDescriptor* field) const {
723 return has_bit_indices_.empty() ? kNoHasbit
724 : has_bit_indices_[field->index()];
725}
726
727int MessageGenerator::HasByteIndex(const FieldDescriptor* field) const {
728 int hasbit = HasBitIndex(field);
729 return hasbit == kNoHasbit ? kNoHasbit : hasbit / 8;
730}
731
732int MessageGenerator::HasWordIndex(const FieldDescriptor* field) const {
733 int hasbit = HasBitIndex(field);
734 return hasbit == kNoHasbit ? kNoHasbit : hasbit / 32;
735}
736
737void MessageGenerator::AddGenerators(
738 std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
739 std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators) {
740 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
741 enum_generators->emplace_back(
742 args: new EnumGenerator(descriptor_->enum_type(index: i), variables_, options_));
743 enum_generators_.push_back(x: enum_generators->back().get());
744 }
745 for (int i = 0; i < descriptor_->extension_count(); i++) {
746 extension_generators->emplace_back(args: new ExtensionGenerator(
747 descriptor_->extension(index: i), options_, scc_analyzer_));
748 extension_generators_.push_back(x: extension_generators->back().get());
749 }
750}
751
752void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
753 Formatter format(printer, variables_);
754 // optimized_fields_ does not contain fields where
755 // field->real_containing_oneof()
756 // so we need to iterate over those as well.
757 //
758 // We place the non-oneof fields in optimized_order_, as that controls the
759 // order of the _has_bits_ entries and we want GDB's pretty printers to be
760 // able to infer these indices from the k[FIELDNAME]FieldNumber order.
761 std::vector<const FieldDescriptor*> ordered_fields;
762 ordered_fields.reserve(n: descriptor_->field_count());
763
764 ordered_fields.insert(position: ordered_fields.begin(), first: optimized_order_.begin(),
765 last: optimized_order_.end());
766 for (auto field : FieldRange(desc: descriptor_)) {
767 if (!field->real_containing_oneof() && !field->options().weak() &&
768 !IsFieldStripped(field, options_)) {
769 continue;
770 }
771 ordered_fields.push_back(x: field);
772 }
773
774 if (!ordered_fields.empty()) {
775 format("enum : int {\n");
776 for (auto field : ordered_fields) {
777 Formatter::SaveState save(&format);
778
779 std::map<std::string, std::string> vars;
780 SetCommonFieldVariables(descriptor: field, variables: &vars, options: options_);
781 format.AddMap(vars);
782 format(" ${1$$2$$}$ = $number$,\n", field, FieldConstantName(field));
783 }
784 format("};\n");
785 }
786 for (auto field : ordered_fields) {
787 PrintFieldComment(format, field);
788
789 Formatter::SaveState save(&format);
790
791 std::map<std::string, std::string> vars;
792 SetCommonFieldVariables(descriptor: field, variables: &vars, options: options_);
793 format.AddMap(vars);
794
795 if (field->is_repeated()) {
796 format("$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field,
797 !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
798 if (!IsFieldStripped(field, options_)) {
799 format(
800 "private:\n"
801 "int ${1$_internal_$name$_size$}$() const;\n"
802 "public:\n",
803 field);
804 }
805 } else if (HasHasMethod(field)) {
806 format("$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field,
807 !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
808 if (!IsFieldStripped(field, options_)) {
809 format(
810 "private:\n"
811 "bool _internal_has_$name$() const;\n"
812 "public:\n");
813 }
814 } else if (HasPrivateHasMethod(field)) {
815 if (!IsFieldStripped(field, options_)) {
816 format(
817 "private:\n"
818 "bool ${1$_internal_has_$name$$}$() const;\n"
819 "public:\n",
820 field);
821 }
822 }
823 format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field,
824 !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}");
825
826 // Generate type-specific accessor declarations.
827 field_generators_.get(field).GenerateAccessorDeclarations(printer);
828
829 format("\n");
830 }
831
832 if (descriptor_->extension_range_count() > 0) {
833 // Generate accessors for extensions.
834 // We use "_proto_TypeTraits" as a type name below because "TypeTraits"
835 // causes problems if the class has a nested message or enum type with that
836 // name and "_TypeTraits" is technically reserved for the C++ library since
837 // it starts with an underscore followed by a capital letter.
838 //
839 // For similar reason, we use "_field_type" and "_is_packed" as parameter
840 // names below, so that "field_type" and "is_packed" can be used as field
841 // names.
842 format(R"(
843template <typename _proto_TypeTraits,
844 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
845 bool _is_packed>
846inline bool HasExtension(
847 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
848 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
849$annotate_extension_has$
850 return $extensions$.Has(id.number());
851}
852
853template <typename _proto_TypeTraits,
854 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
855 bool _is_packed>
856inline void ClearExtension(
857 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
858 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
859 $extensions$.ClearExtension(id.number());
860$annotate_extension_clear$
861}
862
863template <typename _proto_TypeTraits,
864 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
865 bool _is_packed>
866inline int ExtensionSize(
867 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
868 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
869$annotate_extension_repeated_size$
870 return $extensions$.ExtensionSize(id.number());
871}
872
873template <typename _proto_TypeTraits,
874 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
875 bool _is_packed>
876inline typename _proto_TypeTraits::Singular::ConstType GetExtension(
877 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
878 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
879$annotate_extension_get$
880 return _proto_TypeTraits::Get(id.number(), $extensions$,
881 id.default_value());
882}
883
884template <typename _proto_TypeTraits,
885 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
886 bool _is_packed>
887inline typename _proto_TypeTraits::Singular::MutableType MutableExtension(
888 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
889 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
890$annotate_extension_mutable$
891 return _proto_TypeTraits::Mutable(id.number(), _field_type,
892 &$extensions$);
893}
894
895template <typename _proto_TypeTraits,
896 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
897 bool _is_packed>
898inline void SetExtension(
899 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
900 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
901 typename _proto_TypeTraits::Singular::ConstType value) {
902 _proto_TypeTraits::Set(id.number(), _field_type, value, &$extensions$);
903$annotate_extension_set$
904}
905
906template <typename _proto_TypeTraits,
907 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
908 bool _is_packed>
909inline void SetAllocatedExtension(
910 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
911 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
912 typename _proto_TypeTraits::Singular::MutableType value) {
913 _proto_TypeTraits::SetAllocated(id.number(), _field_type, value,
914 &$extensions$);
915$annotate_extension_set$
916}
917template <typename _proto_TypeTraits,
918 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
919 bool _is_packed>
920inline void UnsafeArenaSetAllocatedExtension(
921 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
922 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
923 typename _proto_TypeTraits::Singular::MutableType value) {
924 _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type,
925 value, &$extensions$);
926$annotate_extension_set$
927}
928template <typename _proto_TypeTraits,
929 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
930 bool _is_packed>
931PROTOBUF_NODISCARD inline
932 typename _proto_TypeTraits::Singular::MutableType
933 ReleaseExtension(
934 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
935 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
936$annotate_extension_release$
937 return _proto_TypeTraits::Release(id.number(), _field_type,
938 &$extensions$);
939}
940template <typename _proto_TypeTraits,
941 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
942 bool _is_packed>
943inline typename _proto_TypeTraits::Singular::MutableType
944UnsafeArenaReleaseExtension(
945 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
946 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
947$annotate_extension_release$
948 return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type,
949 &$extensions$);
950}
951
952template <typename _proto_TypeTraits,
953 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
954 bool _is_packed>
955inline typename _proto_TypeTraits::Repeated::ConstType GetExtension(
956 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
957 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
958 int index) const {
959$annotate_repeated_extension_get$
960 return _proto_TypeTraits::Get(id.number(), $extensions$, index);
961}
962
963template <typename _proto_TypeTraits,
964 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
965 bool _is_packed>
966inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension(
967 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
968 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
969 int index) {
970$annotate_repeated_extension_mutable$
971 return _proto_TypeTraits::Mutable(id.number(), index, &$extensions$);
972}
973
974template <typename _proto_TypeTraits,
975 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
976 bool _is_packed>
977inline void SetExtension(
978 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
979 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
980 int index, typename _proto_TypeTraits::Repeated::ConstType value) {
981 _proto_TypeTraits::Set(id.number(), index, value, &$extensions$);
982$annotate_repeated_extension_set$
983}
984
985template <typename _proto_TypeTraits,
986 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
987 bool _is_packed>
988inline typename _proto_TypeTraits::Repeated::MutableType AddExtension(
989 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
990 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
991 typename _proto_TypeTraits::Repeated::MutableType to_add =
992 _proto_TypeTraits::Add(id.number(), _field_type, &$extensions$);
993$annotate_repeated_extension_add_mutable$
994 return to_add;
995}
996
997template <typename _proto_TypeTraits,
998 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
999 bool _is_packed>
1000inline void AddExtension(
1001 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1002 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
1003 typename _proto_TypeTraits::Repeated::ConstType value) {
1004 _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value,
1005 &$extensions$);
1006$annotate_repeated_extension_add$
1007}
1008
1009template <typename _proto_TypeTraits,
1010 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
1011 bool _is_packed>
1012inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType&
1013GetRepeatedExtension(
1014 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1015 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
1016$annotate_repeated_extension_list$
1017 return _proto_TypeTraits::GetRepeated(id.number(), $extensions$);
1018}
1019
1020template <typename _proto_TypeTraits,
1021 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
1022 bool _is_packed>
1023inline typename _proto_TypeTraits::Repeated::RepeatedFieldType*
1024MutableRepeatedExtension(
1025 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1026 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
1027$annotate_repeated_extension_list_mutable$
1028 return _proto_TypeTraits::MutableRepeated(id.number(), _field_type,
1029 _is_packed, &$extensions$);
1030}
1031
1032)");
1033 // Generate MessageSet specific APIs for proto2 MessageSet.
1034 // For testing purposes we don't check for bridge.MessageSet, so
1035 // we don't use IsProto2MessageSet
1036 if (descriptor_->options().message_set_wire_format() &&
1037 !options_.opensource_runtime && !options_.lite_implicit_weak_fields) {
1038 // Special-case MessageSet
1039 format("GOOGLE_PROTOBUF_EXTENSION_MESSAGE_SET_ACCESSORS($classname$)\n");
1040 }
1041 }
1042
1043 for (auto oneof : OneOfRange(desc: descriptor_)) {
1044 Formatter::SaveState saver(&format);
1045 format.Set(key: "oneof_name", value: oneof->name());
1046 format.Set(key: "camel_oneof_name", value: UnderscoresToCamelCase(input: oneof->name(), cap_next_letter: true));
1047 format(
1048 "void ${1$clear_$oneof_name$$}$();\n"
1049 "$camel_oneof_name$Case $oneof_name$_case() const;\n",
1050 oneof);
1051 }
1052}
1053
1054void MessageGenerator::GenerateSingularFieldHasBits(
1055 const FieldDescriptor* field, Formatter format) {
1056 if (IsFieldStripped(field, options_)) {
1057 format(
1058 "inline bool $classname$::has_$name$() const { "
1059 "__builtin_trap(); }\n");
1060 return;
1061 }
1062 if (field->options().weak()) {
1063 format(
1064 "inline bool $classname$::has_$name$() const {\n"
1065 "$annotate_has$"
1066 " return $weak_field_map$.Has($number$);\n"
1067 "}\n");
1068 return;
1069 }
1070 if (HasHasbit(field)) {
1071 int has_bit_index = HasBitIndex(field);
1072 GOOGLE_CHECK_NE(has_bit_index, kNoHasbit);
1073
1074 format.Set(key: "has_array_index", value: has_bit_index / 32);
1075 format.Set(key: "has_mask",
1076 value: strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
1077 format(
1078 "inline bool $classname$::_internal_has_$name$() const {\n"
1079 " bool value = "
1080 "($has_bits$[$has_array_index$] & 0x$has_mask$u) != 0;\n");
1081
1082 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
1083 !IsLazy(field, options: options_, scc_analyzer: scc_analyzer_)) {
1084 // We maintain the invariant that for a submessage x, has_x() returning
1085 // true implies that x_ is not null. By giving this information to the
1086 // compiler, we allow it to eliminate unnecessary null checks later on.
1087 format(" PROTOBUF_ASSUME(!value || $field$ != nullptr);\n");
1088 }
1089
1090 format(
1091 " return value;\n"
1092 "}\n"
1093 "inline bool $classname$::has_$name$() const {\n"
1094 "$annotate_has$"
1095 " return _internal_has_$name$();\n"
1096 "}\n");
1097 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
1098 // Message fields have a has_$name$() method.
1099 if (IsLazy(field, options: options_, scc_analyzer: scc_analyzer_)) {
1100 format(
1101 "inline bool $classname$::_internal_has_$name$() const {\n"
1102 " return !$field$.IsCleared();\n"
1103 "}\n");
1104 } else {
1105 format(
1106 "inline bool $classname$::_internal_has_$name$() const {\n"
1107 " return this != internal_default_instance() "
1108 "&& $field$ != nullptr;\n"
1109 "}\n");
1110 }
1111 format(
1112 "inline bool $classname$::has_$name$() const {\n"
1113 "$annotate_has$"
1114 " return _internal_has_$name$();\n"
1115 "}\n");
1116 }
1117}
1118
1119void MessageGenerator::GenerateOneofHasBits(io::Printer* printer) {
1120 Formatter format(printer, variables_);
1121 for (auto oneof : OneOfRange(desc: descriptor_)) {
1122 format.Set(key: "oneof_name", value: oneof->name());
1123 format.Set(key: "oneof_index", value: oneof->index());
1124 format.Set(key: "cap_oneof_name", value: ToUpper(s: oneof->name()));
1125 format(
1126 "inline bool $classname$::has_$oneof_name$() const {\n"
1127 " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
1128 "}\n"
1129 "inline void $classname$::clear_has_$oneof_name$() {\n"
1130 " $oneof_case$[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
1131 "}\n");
1132 }
1133}
1134
1135void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field,
1136 const Formatter& format) {
1137 if (IsFieldStripped(field, options_)) {
1138 if (HasHasMethod(field)) {
1139 format(
1140 "inline bool $classname$::has_$name$() const { "
1141 "__builtin_trap(); }\n");
1142 }
1143 format(
1144 "inline void $classname$::set_has_$name$() { __builtin_trap(); "
1145 "}\n");
1146 return;
1147 }
1148 // Singular field in a oneof
1149 // N.B.: Without field presence, we do not use has-bits or generate
1150 // has_$name$() methods, but oneofs still have set_has_$name$().
1151 // Oneofs also have has_$name$() but only as a private helper
1152 // method, so that generated code is slightly cleaner (vs. comparing
1153 // _oneof_case_[index] against a constant everywhere).
1154 //
1155 // If has_$name$() is private, there is no need to add an internal accessor.
1156 // Only annotate public accessors.
1157 if (HasHasMethod(field)) {
1158 format(
1159 "inline bool $classname$::_internal_has_$name$() const {\n"
1160 " return $oneof_name$_case() == k$field_name$;\n"
1161 "}\n"
1162 "inline bool $classname$::has_$name$() const {\n"
1163 "$annotate_has$"
1164 " return _internal_has_$name$();\n"
1165 "}\n");
1166 } else if (HasPrivateHasMethod(field)) {
1167 format(
1168 "inline bool $classname$::_internal_has_$name$() const {\n"
1169 " return $oneof_name$_case() == k$field_name$;\n"
1170 "}\n");
1171 }
1172 // set_has_$name$() for oneof fields is always private; hence should not be
1173 // annotated.
1174 format(
1175 "inline void $classname$::set_has_$name$() {\n"
1176 " $oneof_case$[$oneof_index$] = k$field_name$;\n"
1177 "}\n");
1178}
1179
1180void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
1181 bool is_inline, Formatter format) {
1182 if (IsFieldStripped(field, options_)) {
1183 format("void $classname$::clear_$name$() { __builtin_trap(); }\n");
1184 return;
1185 }
1186
1187 // Generate clear_$name$().
1188 if (is_inline) {
1189 format("inline ");
1190 }
1191 format("void $classname$::clear_$name$() {\n");
1192
1193 format.Indent();
1194
1195 if (field->real_containing_oneof()) {
1196 // Clear this field only if it is the active field in this oneof,
1197 // otherwise ignore
1198 format("if (_internal_has_$name$()) {\n");
1199 format.Indent();
1200 field_generators_.get(field).GenerateClearingCode(printer: format.printer());
1201 format("clear_has_$oneof_name$();\n");
1202 format.Outdent();
1203 format("}\n");
1204 } else {
1205 if (ShouldSplit(field, options: options_)) {
1206 format("if (IsSplitMessageDefault()) return;\n");
1207 }
1208 field_generators_.get(field).GenerateClearingCode(printer: format.printer());
1209 if (HasHasbit(field)) {
1210 int has_bit_index = HasBitIndex(field);
1211 format.Set(key: "has_array_index", value: has_bit_index / 32);
1212 format.Set(key: "has_mask",
1213 value: strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
1214 format("$has_bits$[$has_array_index$] &= ~0x$has_mask$u;\n");
1215 }
1216 }
1217 format("$annotate_clear$");
1218 format.Outdent();
1219 format("}\n");
1220}
1221
1222void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) {
1223 Formatter format(printer, variables_);
1224 format("// $classname$\n\n");
1225
1226 for (auto field : FieldRange(desc: descriptor_)) {
1227 PrintFieldComment(format, field);
1228
1229 if (IsFieldStripped(field, options_)) {
1230 continue;
1231 }
1232
1233 std::map<std::string, std::string> vars;
1234 SetCommonFieldVariables(descriptor: field, variables: &vars, options: options_);
1235
1236 Formatter::SaveState saver(&format);
1237 format.AddMap(vars);
1238
1239 // Generate has_$name$() or $name$_size().
1240 if (field->is_repeated()) {
1241 if (IsFieldStripped(field, options_)) {
1242 format(
1243 "inline int $classname$::$name$_size() const { "
1244 "__builtin_trap(); }\n");
1245 } else {
1246 format(
1247 "inline int $classname$::_internal_$name$_size() const {\n"
1248 " return $field$$1$.size();\n"
1249 "}\n"
1250 "inline int $classname$::$name$_size() const {\n"
1251 "$annotate_size$"
1252 " return _internal_$name$_size();\n"
1253 "}\n",
1254 IsImplicitWeakField(field, options: options_, scc_analyzer: scc_analyzer_) &&
1255 field->message_type()
1256 ? ".weak"
1257 : "");
1258 }
1259 } else if (field->real_containing_oneof()) {
1260 format.Set(key: "field_name", value: UnderscoresToCamelCase(input: field->name(), cap_next_letter: true));
1261 format.Set(key: "oneof_name", value: field->containing_oneof()->name());
1262 format.Set(key: "oneof_index",
1263 value: StrCat(a: field->containing_oneof()->index()));
1264 GenerateOneofMemberHasBits(field, format);
1265 } else {
1266 // Singular field.
1267 GenerateSingularFieldHasBits(field, format);
1268 }
1269
1270 if (!IsCrossFileMaybeMap(field)) {
1271 GenerateFieldClear(field, is_inline: true, format);
1272 }
1273
1274 // Generate type-specific accessors.
1275 if (!IsFieldStripped(field, options_)) {
1276 field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
1277 }
1278
1279 format("\n");
1280 }
1281
1282 // Generate has_$name$() and clear_has_$name$() functions for oneofs.
1283 GenerateOneofHasBits(printer);
1284}
1285
1286void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
1287 Formatter format(printer, variables_);
1288 format.Set(key: "class_final",
1289 value: ShouldMarkClassAsFinal(descriptor: descriptor_, options: options_) ? "final" : "");
1290
1291 if (IsMapEntryMessage(descriptor: descriptor_)) {
1292 std::map<std::string, std::string> vars;
1293 CollectMapInfo(options: options_, descriptor: descriptor_, variables: &vars);
1294 vars["lite"] =
1295 HasDescriptorMethods(file: descriptor_->file(), options: options_) ? "" : "Lite";
1296 format.AddMap(vars);
1297 format(
1298 "class $classname$ : public "
1299 "::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
1300 " $key_cpp$, $val_cpp$,\n"
1301 " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
1302 " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> {\n"
1303 "public:\n"
1304 " typedef ::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
1305 " $key_cpp$, $val_cpp$,\n"
1306 " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
1307 " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
1308 "SuperType;\n"
1309 " $classname$();\n"
1310 " explicit PROTOBUF_CONSTEXPR $classname$(\n"
1311 " ::$proto_ns$::internal::ConstantInitialized);\n"
1312 " explicit $classname$(::$proto_ns$::Arena* arena);\n"
1313 " void MergeFrom(const $classname$& other);\n"
1314 " static const $classname$* internal_default_instance() { return "
1315 "reinterpret_cast<const "
1316 "$classname$*>(&_$classname$_default_instance_); }\n");
1317 auto utf8_check = GetUtf8CheckMode(field: descriptor_->field(index: 0), options: options_);
1318 if (descriptor_->field(index: 0)->type() == FieldDescriptor::TYPE_STRING &&
1319 utf8_check != Utf8CheckMode::kNone) {
1320 if (utf8_check == Utf8CheckMode::kStrict) {
1321 format(
1322 " static bool ValidateKey(std::string* s) {\n"
1323 " return ::$proto_ns$::internal::WireFormatLite::"
1324 "VerifyUtf8String(s->data(), static_cast<int>(s->size()), "
1325 "::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n"
1326 " }\n",
1327 descriptor_->field(index: 0)->full_name());
1328 } else {
1329 GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify);
1330 format(
1331 " static bool ValidateKey(std::string* s) {\n"
1332 "#ifndef NDEBUG\n"
1333 " ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n"
1334 " s->data(), static_cast<int>(s->size()), "
1335 "::$proto_ns$::internal::"
1336 "WireFormatLite::PARSE, \"$1$\");\n"
1337 "#else\n"
1338 " (void) s;\n"
1339 "#endif\n"
1340 " return true;\n"
1341 " }\n",
1342 descriptor_->field(index: 0)->full_name());
1343 }
1344 } else {
1345 format(" static bool ValidateKey(void*) { return true; }\n");
1346 }
1347 if (descriptor_->field(index: 1)->type() == FieldDescriptor::TYPE_STRING &&
1348 utf8_check != Utf8CheckMode::kNone) {
1349 if (utf8_check == Utf8CheckMode::kStrict) {
1350 format(
1351 " static bool ValidateValue(std::string* s) {\n"
1352 " return ::$proto_ns$::internal::WireFormatLite::"
1353 "VerifyUtf8String(s->data(), static_cast<int>(s->size()), "
1354 "::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n"
1355 " }\n",
1356 descriptor_->field(index: 1)->full_name());
1357 } else {
1358 GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify);
1359 format(
1360 " static bool ValidateValue(std::string* s) {\n"
1361 "#ifndef NDEBUG\n"
1362 " ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n"
1363 " s->data(), static_cast<int>(s->size()), "
1364 "::$proto_ns$::internal::"
1365 "WireFormatLite::PARSE, \"$1$\");\n"
1366 "#else\n"
1367 " (void) s;\n"
1368 "#endif\n"
1369 " return true;\n"
1370 " }\n",
1371 descriptor_->field(index: 1)->full_name());
1372 }
1373 } else {
1374 format(" static bool ValidateValue(void*) { return true; }\n");
1375 }
1376 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
1377 format(
1378 " using ::$proto_ns$::Message::MergeFrom;\n"
1379 ""
1380 " ::$proto_ns$::Metadata GetMetadata() const final;\n");
1381 }
1382 format(
1383 " friend struct ::$tablename$;\n"
1384 "};\n");
1385 return;
1386 }
1387
1388 format(
1389 "class $dllexport_decl $${1$$classname$$}$$ class_final$ :\n"
1390 " public $superclass$ /* @@protoc_insertion_point("
1391 "class_definition:$full_name$) */ {\n",
1392 descriptor_);
1393 format(" public:\n");
1394 format.Indent();
1395
1396 if (EnableMessageOwnedArena(desc: descriptor_, options: options_)) {
1397 format(
1398 "inline $classname$() : $classname$("
1399 "::$proto_ns$::Arena::InternalCreateMessageOwnedArena(), true) {}\n");
1400 } else if (EnableMessageOwnedArenaTrial(desc: descriptor_, options: options_)) {
1401 format(
1402 "inline $classname$() : $classname$(InMoaTrial() ? "
1403 "::$proto_ns$::Arena::InternalCreateMessageOwnedArena() : nullptr, "
1404 "InMoaTrial()) {}\n");
1405 } else {
1406 format("inline $classname$() : $classname$(nullptr) {}\n");
1407 }
1408 if (!HasSimpleBaseClass(desc: descriptor_, options: options_)) {
1409 format("~$classname$() override;\n");
1410 }
1411 format(
1412 "explicit PROTOBUF_CONSTEXPR "
1413 "$classname$(::$proto_ns$::internal::ConstantInitialized);\n"
1414 "\n"
1415 "$classname$(const $classname$& from);\n"
1416 "$classname$($classname$&& from) noexcept\n"
1417 " : $classname$() {\n"
1418 " *this = ::std::move(from);\n"
1419 "}\n"
1420 "\n"
1421 "inline $classname$& operator=(const $classname$& from) {\n"
1422 " CopyFrom(from);\n"
1423 " return *this;\n"
1424 "}\n"
1425 "inline $classname$& operator=($classname$&& from) noexcept {\n"
1426 " if (this == &from) return *this;\n"
1427 " if (GetOwningArena() == from.GetOwningArena()\n"
1428 "#ifdef PROTOBUF_FORCE_COPY_IN_MOVE\n"
1429 " && GetOwningArena() != nullptr\n"
1430 "#endif // !PROTOBUF_FORCE_COPY_IN_MOVE\n"
1431 " ) {\n"
1432 " InternalSwap(&from);\n"
1433 " } else {\n"
1434 " CopyFrom(from);\n"
1435 " }\n"
1436 " return *this;\n"
1437 "}\n"
1438 "\n");
1439
1440 if (PublicUnknownFieldsAccessors(message: descriptor_)) {
1441 format(
1442 "inline const $unknown_fields_type$& unknown_fields() const {\n"
1443 " return $unknown_fields$;\n"
1444 "}\n"
1445 "inline $unknown_fields_type$* mutable_unknown_fields() {\n"
1446 " return $mutable_unknown_fields$;\n"
1447 "}\n"
1448 "\n");
1449 }
1450
1451 // Only generate this member if it's not disabled.
1452 if (HasDescriptorMethods(file: descriptor_->file(), options: options_) &&
1453 !descriptor_->options().no_standard_descriptor_accessor()) {
1454 format(
1455 "static const ::$proto_ns$::Descriptor* descriptor() {\n"
1456 " return GetDescriptor();\n"
1457 "}\n");
1458 }
1459
1460 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
1461 // These shadow non-static methods of the same names in Message. We
1462 // redefine them here because calls directly on the generated class can be
1463 // statically analyzed -- we know what descriptor types are being requested.
1464 // It also avoids a vtable dispatch.
1465 //
1466 // We would eventually like to eliminate the methods in Message, and having
1467 // this separate also lets us track calls to the base class methods
1468 // separately.
1469 format(
1470 "static const ::$proto_ns$::Descriptor* GetDescriptor() {\n"
1471 " return default_instance().GetMetadata().descriptor;\n"
1472 "}\n"
1473 "static const ::$proto_ns$::Reflection* GetReflection() {\n"
1474 " return default_instance().GetMetadata().reflection;\n"
1475 "}\n");
1476 }
1477
1478 format(
1479 "static const $classname$& default_instance() {\n"
1480 " return *internal_default_instance();\n"
1481 "}\n");
1482
1483 // Generate enum values for every field in oneofs. One list is generated for
1484 // each oneof with an additional *_NOT_SET value.
1485 for (auto oneof : OneOfRange(desc: descriptor_)) {
1486 format("enum $1$Case {\n", UnderscoresToCamelCase(input: oneof->name(), cap_next_letter: true));
1487 format.Indent();
1488 for (auto field : FieldRange(desc: oneof)) {
1489 format("$1$ = $2$,\n", OneofCaseConstantName(field), // 1
1490 field->number()); // 2
1491 }
1492 format("$1$_NOT_SET = 0,\n", ToUpper(s: oneof->name()));
1493 format.Outdent();
1494 format(
1495 "};\n"
1496 "\n");
1497 }
1498
1499 // TODO(gerbens) make this private, while still granting other protos access.
1500 format(
1501 "static inline const $classname$* internal_default_instance() {\n"
1502 " return reinterpret_cast<const $classname$*>(\n"
1503 " &_$classname$_default_instance_);\n"
1504 "}\n"
1505 "static constexpr int kIndexInFileMessages =\n"
1506 " $1$;\n"
1507 "\n",
1508 index_in_file_messages_);
1509
1510 if (IsAnyMessage(descriptor: descriptor_, options: options_)) {
1511 format(
1512 "// implements Any -----------------------------------------------\n"
1513 "\n");
1514 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
1515 format(
1516 "bool PackFrom(const ::$proto_ns$::Message& message) {\n"
1517 " $DCHK$_NE(&message, this);\n"
1518 " return $any_metadata$.PackFrom(GetArena(), message);\n"
1519 "}\n"
1520 "bool PackFrom(const ::$proto_ns$::Message& message,\n"
1521 " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
1522 "type_url_prefix) {\n"
1523 " $DCHK$_NE(&message, this);\n"
1524 " return $any_metadata$.PackFrom(GetArena(), message, "
1525 "type_url_prefix);\n"
1526 "}\n"
1527 "bool UnpackTo(::$proto_ns$::Message* message) const {\n"
1528 " return $any_metadata$.UnpackTo(message);\n"
1529 "}\n"
1530 "static bool GetAnyFieldDescriptors(\n"
1531 " const ::$proto_ns$::Message& message,\n"
1532 " const ::$proto_ns$::FieldDescriptor** type_url_field,\n"
1533 " const ::$proto_ns$::FieldDescriptor** value_field);\n"
1534 "template <typename T, class = typename std::enable_if<"
1535 "!std::is_convertible<T, const ::$proto_ns$::Message&>"
1536 "::value>::type>\n"
1537 "bool PackFrom(const T& message) {\n"
1538 " return $any_metadata$.PackFrom<T>(GetArena(), message);\n"
1539 "}\n"
1540 "template <typename T, class = typename std::enable_if<"
1541 "!std::is_convertible<T, const ::$proto_ns$::Message&>"
1542 "::value>::type>\n"
1543 "bool PackFrom(const T& message,\n"
1544 " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
1545 "type_url_prefix) {\n"
1546 " return $any_metadata$.PackFrom<T>(GetArena(), message, "
1547 "type_url_prefix);"
1548 "}\n"
1549 "template <typename T, class = typename std::enable_if<"
1550 "!std::is_convertible<T, const ::$proto_ns$::Message&>"
1551 "::value>::type>\n"
1552 "bool UnpackTo(T* message) const {\n"
1553 " return $any_metadata$.UnpackTo<T>(message);\n"
1554 "}\n");
1555 } else {
1556 format(
1557 "template <typename T>\n"
1558 "bool PackFrom(const T& message) {\n"
1559 " return $any_metadata$.PackFrom(GetArena(), message);\n"
1560 "}\n"
1561 "template <typename T>\n"
1562 "bool PackFrom(const T& message,\n"
1563 " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
1564 "type_url_prefix) {\n"
1565 " return $any_metadata$.PackFrom(GetArena(), message, "
1566 "type_url_prefix);\n"
1567 "}\n"
1568 "template <typename T>\n"
1569 "bool UnpackTo(T* message) const {\n"
1570 " return $any_metadata$.UnpackTo(message);\n"
1571 "}\n");
1572 }
1573 format(
1574 "template<typename T> bool Is() const {\n"
1575 " return $any_metadata$.Is<T>();\n"
1576 "}\n"
1577 "static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam "
1578 "type_url,\n"
1579 " std::string* full_type_name);\n");
1580 }
1581
1582 format(
1583 "friend void swap($classname$& a, $classname$& b) {\n"
1584 " a.Swap(&b);\n"
1585 "}\n"
1586 "inline void Swap($classname$* other) {\n"
1587 " if (other == this) return;\n"
1588 "#ifdef PROTOBUF_FORCE_COPY_IN_SWAP\n"
1589 " if (GetOwningArena() != nullptr &&\n"
1590 " GetOwningArena() == other->GetOwningArena()) {\n "
1591 "#else // PROTOBUF_FORCE_COPY_IN_SWAP\n"
1592 " if (GetOwningArena() == other->GetOwningArena()) {\n"
1593 "#endif // !PROTOBUF_FORCE_COPY_IN_SWAP\n"
1594 " InternalSwap(other);\n"
1595 " } else {\n"
1596 " ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n"
1597 " }\n"
1598 "}\n"
1599 "void UnsafeArenaSwap($classname$* other) {\n"
1600 " if (other == this) return;\n"
1601 " $DCHK$(GetOwningArena() == other->GetOwningArena());\n"
1602 " InternalSwap(other);\n"
1603 "}\n");
1604
1605 format(
1606 "\n"
1607 "// implements Message ----------------------------------------------\n"
1608 "\n"
1609 "$classname$* New(::$proto_ns$::Arena* arena = nullptr) const final {\n"
1610 " return CreateMaybeMessage<$classname$>(arena);\n"
1611 "}\n");
1612
1613 // For instances that derive from Message (rather than MessageLite), some
1614 // methods are virtual and should be marked as final.
1615 format.Set(key: "full_final", value: HasDescriptorMethods(file: descriptor_->file(), options: options_)
1616 ? "final"
1617 : "");
1618
1619 if (HasGeneratedMethods(file: descriptor_->file(), options: options_)) {
1620 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
1621 if (!HasSimpleBaseClass(desc: descriptor_, options: options_)) {
1622 format(
1623 // Use Message's built-in MergeFrom and CopyFrom when the passed-in
1624 // argument is a generic Message instance, and only define the
1625 // custom MergeFrom and CopyFrom instances when the source of the
1626 // merge/copy is known to be the same class as the destination.
1627 "using $superclass$::CopyFrom;\n"
1628 "void CopyFrom(const $classname$& from);\n"
1629 ""
1630 "using $superclass$::MergeFrom;\n"
1631 "void MergeFrom("
1632 " const $classname$& from) {\n"
1633 " $classname$::MergeImpl(*this, from);\n"
1634 "}\n"
1635 "private:\n"
1636 "static void MergeImpl(::$proto_ns$::Message& to_msg, const "
1637 "::$proto_ns$::Message& from_msg);\n"
1638 "public:\n");
1639 } else {
1640 format(
1641 "using $superclass$::CopyFrom;\n"
1642 "inline void CopyFrom(const $classname$& from) {\n"
1643 " $superclass$::CopyImpl(*this, from);\n"
1644 "}\n"
1645 ""
1646 "using $superclass$::MergeFrom;\n"
1647 "void MergeFrom(const $classname$& from) {\n"
1648 " $superclass$::MergeImpl(*this, from);\n"
1649 "}\n"
1650 "public:\n");
1651 }
1652 } else {
1653 format(
1654 "void CheckTypeAndMergeFrom(const ::$proto_ns$::MessageLite& from)"
1655 " final;\n"
1656 "void CopyFrom(const $classname$& from);\n"
1657 "void MergeFrom(const $classname$& from);\n");
1658 }
1659
1660 if (!HasSimpleBaseClass(desc: descriptor_, options: options_)) {
1661 format(
1662 "PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;\n"
1663 "bool IsInitialized() const final;\n"
1664 "\n"
1665 "size_t ByteSizeLong() const final;\n");
1666
1667 parse_function_generator_->GenerateMethodDecls(printer);
1668
1669 format(
1670 "$uint8$* _InternalSerialize(\n"
1671 " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
1672 "const final;\n");
1673 }
1674 }
1675
1676 if (options_.field_listener_options.inject_field_listener_events) {
1677 format("static constexpr int _kInternalFieldNumber = $1$;\n",
1678 descriptor_->field_count());
1679 }
1680
1681 if (!HasSimpleBaseClass(desc: descriptor_, options: options_)) {
1682 format(
1683 "int GetCachedSize() const final { return "
1684 "$cached_size$.Get(); }"
1685 "\n\nprivate:\n"
1686 "void SharedCtor(::$proto_ns$::Arena* arena, bool is_message_owned);\n"
1687 "void SharedDtor();\n"
1688 "void SetCachedSize(int size) const$ full_final$;\n"
1689 "void InternalSwap($classname$* other);\n");
1690 }
1691
1692 format(
1693 // Friend AnyMetadata so that it can call this FullMessageName() method.
1694 "\nprivate:\n"
1695 "friend class ::$proto_ns$::internal::AnyMetadata;\n"
1696 "static $1$ FullMessageName() {\n"
1697 " return \"$full_name$\";\n"
1698 "}\n",
1699 options_.opensource_runtime ? "::PROTOBUF_NAMESPACE_ID::StringPiece"
1700 : "::StringPiece");
1701
1702 format(
1703 // TODO(gerbens) Make this private! Currently people are deriving from
1704 // protos to give access to this constructor, breaking the invariants
1705 // we rely on.
1706 "protected:\n"
1707 "explicit $classname$(::$proto_ns$::Arena* arena,\n"
1708 " bool is_message_owned = false);\n");
1709
1710 switch (NeedsArenaDestructor()) {
1711 case ArenaDtorNeeds::kOnDemand:
1712 format(
1713 "private:\n"
1714 "static void ArenaDtor(void* object);\n"
1715 "inline void OnDemandRegisterArenaDtor(::$proto_ns$::Arena* arena) "
1716 "override {\n"
1717 " if (arena == nullptr || ($inlined_string_donated_array$[0] & "
1718 "0x1u) "
1719 "== "
1720 "0) {\n"
1721 " return;\n"
1722 " }\n"
1723 " $inlined_string_donated_array$[0] &= 0xFFFFFFFEu;\n"
1724 " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n"
1725 "}\n");
1726 break;
1727 case ArenaDtorNeeds::kRequired:
1728 format(
1729 "private:\n"
1730 "static void ArenaDtor(void* object);\n");
1731 break;
1732 case ArenaDtorNeeds::kNone:
1733 break;
1734 }
1735
1736 format(
1737 "public:\n"
1738 "\n");
1739
1740 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
1741 if (HasGeneratedMethods(file: descriptor_->file(), options: options_)) {
1742 format(
1743 "static const ClassData _class_data_;\n"
1744 "const ::$proto_ns$::Message::ClassData*"
1745 "GetClassData() const final;\n"
1746 "\n");
1747 }
1748 format(
1749 "::$proto_ns$::Metadata GetMetadata() const final;\n"
1750 "\n");
1751 } else {
1752 format(
1753 "std::string GetTypeName() const final;\n"
1754 "\n");
1755 }
1756
1757 if (ShouldSplit(desc: descriptor_, options: options_)) {
1758 format(
1759 "private:\n"
1760 "inline bool IsSplitMessageDefault() const {\n"
1761 " return $split$ == reinterpret_cast<Impl_::Split*>(&$1$);\n"
1762 "}\n"
1763 "PROTOBUF_NOINLINE void PrepareSplitMessageForWrite();\n"
1764 "public:\n",
1765 DefaultInstanceName(descriptor: descriptor_, options: options_, /*split=*/true));
1766 }
1767
1768 format(
1769 "// nested types ----------------------------------------------------\n"
1770 "\n");
1771
1772 // Import all nested message classes into this class's scope with typedefs.
1773 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1774 const Descriptor* nested_type = descriptor_->nested_type(index: i);
1775 if (!IsMapEntryMessage(descriptor: nested_type)) {
1776 format.Set(key: "nested_full_name", value: ClassName(descriptor: nested_type, qualified: false));
1777 format.Set(key: "nested_name", value: ResolveKeyword(name: nested_type->name()));
1778 format("typedef ${1$$nested_full_name$$}$ ${1$$nested_name$$}$;\n",
1779 nested_type);
1780 }
1781 }
1782
1783 if (descriptor_->nested_type_count() > 0) {
1784 format("\n");
1785 }
1786
1787 // Import all nested enums and their values into this class's scope with
1788 // typedefs and constants.
1789 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
1790 enum_generators_[i]->GenerateSymbolImports(printer);
1791 format("\n");
1792 }
1793
1794 format(
1795 "// accessors -------------------------------------------------------\n"
1796 "\n");
1797
1798 // Generate accessor methods for all fields.
1799 GenerateFieldAccessorDeclarations(printer);
1800
1801 // Declare extension identifiers.
1802 for (int i = 0; i < descriptor_->extension_count(); i++) {
1803 extension_generators_[i]->GenerateDeclaration(printer);
1804 }
1805
1806
1807 format("// @@protoc_insertion_point(class_scope:$full_name$)\n");
1808
1809 // Generate private members.
1810 format.Outdent();
1811 format(" private:\n");
1812 format.Indent();
1813 // TODO(seongkim): Remove hack to track field access and remove this class.
1814 format("class _Internal;\n");
1815
1816 for (auto field : FieldRange(desc: descriptor_)) {
1817 // set_has_***() generated in all oneofs.
1818 if (!field->is_repeated() && !field->options().weak() &&
1819 field->real_containing_oneof()) {
1820 format("void set_has_$1$();\n", FieldName(field));
1821 }
1822 }
1823 format("\n");
1824
1825 // Generate oneof function declarations
1826 for (auto oneof : OneOfRange(desc: descriptor_)) {
1827 format(
1828 "inline bool has_$1$() const;\n"
1829 "inline void clear_has_$1$();\n\n",
1830 oneof->name());
1831 }
1832
1833 if (HasGeneratedMethods(file: descriptor_->file(), options: options_) &&
1834 !descriptor_->options().message_set_wire_format() &&
1835 num_required_fields_ > 1) {
1836 format(
1837 "// helper for ByteSizeLong()\n"
1838 "size_t RequiredFieldsByteSizeFallback() const;\n\n");
1839 }
1840
1841 if (HasGeneratedMethods(file: descriptor_->file(), options: options_)) {
1842 parse_function_generator_->GenerateDataDecls(printer);
1843 }
1844
1845 // Prepare decls for _cached_size_ and _has_bits_. Their position in the
1846 // output will be determined later.
1847
1848 bool need_to_emit_cached_size = !HasSimpleBaseClass(desc: descriptor_, options: options_);
1849 const std::string cached_size_decl =
1850 "mutable ::$proto_ns$::internal::CachedSize _cached_size_;\n";
1851
1852 const size_t sizeof_has_bits = HasBitsSize();
1853 const std::string has_bits_decl =
1854 sizeof_has_bits == 0 ? ""
1855 : StrCat(a: "::$proto_ns$::internal::HasBits<",
1856 b: sizeof_has_bits, c: "> _has_bits_;\n");
1857
1858 format(
1859 "template <typename T> friend class "
1860 "::$proto_ns$::Arena::InternalHelper;\n"
1861 "typedef void InternalArenaConstructable_;\n"
1862 "typedef void DestructorSkippable_;\n");
1863
1864 // To minimize padding, data members are divided into three sections:
1865 // (1) members assumed to align to 8 bytes
1866 // (2) members corresponding to message fields, re-ordered to optimize
1867 // alignment.
1868 // (3) members assumed to align to 4 bytes.
1869
1870 format("struct Impl_ {\n");
1871 format.Indent();
1872
1873 // Members assumed to align to 8 bytes:
1874
1875 if (descriptor_->extension_range_count() > 0) {
1876 format(
1877 "::$proto_ns$::internal::ExtensionSet _extensions_;\n"
1878 "\n");
1879 }
1880
1881 if (HasTracker(desc: descriptor_, options: options_)) {
1882 format("static ::$proto_ns$::AccessListener<$1$> _tracker_;\n",
1883 ClassName(descriptor: descriptor_));
1884 }
1885
1886 // Generate _inlined_string_donated_ for inlined string type.
1887 // TODO(congliu): To avoid affecting the locality of `_has_bits_`, should this
1888 // be below or above `_has_bits_`?
1889 if (!inlined_string_indices_.empty()) {
1890 format("::$proto_ns$::internal::HasBits<$1$> _inlined_string_donated_;\n",
1891 InlinedStringDonatedSize());
1892 }
1893
1894 if (!has_bit_indices_.empty()) {
1895 // _has_bits_ is frequently accessed, so to reduce code size and improve
1896 // speed, it should be close to the start of the object. Placing
1897 // _cached_size_ together with _has_bits_ improves cache locality despite
1898 // potential alignment padding.
1899 format(has_bits_decl.c_str());
1900 if (need_to_emit_cached_size) {
1901 format(cached_size_decl.c_str());
1902 need_to_emit_cached_size = false;
1903 }
1904 }
1905
1906 // Field members:
1907
1908 // Emit some private and static members
1909 for (auto field : optimized_order_) {
1910 const FieldGenerator& generator = field_generators_.get(field);
1911 generator.GenerateStaticMembers(printer);
1912 if (!ShouldSplit(field, options: options_)) {
1913 generator.GeneratePrivateMembers(printer);
1914 }
1915 }
1916 if (ShouldSplit(desc: descriptor_, options: options_)) {
1917 format("struct Split {\n");
1918 format.Indent();
1919 for (auto field : optimized_order_) {
1920 if (!ShouldSplit(field, options: options_)) continue;
1921 const FieldGenerator& generator = field_generators_.get(field);
1922 generator.GeneratePrivateMembers(printer);
1923 }
1924 format.Outdent();
1925 format(
1926 " typedef void InternalArenaConstructable_;\n"
1927 " typedef void DestructorSkippable_;\n"
1928 "};\n"
1929 "Split* _split_;\n");
1930 }
1931
1932 // For each oneof generate a union
1933 for (auto oneof : OneOfRange(desc: descriptor_)) {
1934 std::string camel_oneof_name = UnderscoresToCamelCase(input: oneof->name(), cap_next_letter: true);
1935 format("union $1$Union {\n", camel_oneof_name);
1936 format.Indent();
1937 format(
1938 // explicit empty constructor is needed when union contains
1939 // ArenaStringPtr members for string fields.
1940 "constexpr $1$Union() : _constinit_{} {}\n"
1941 " ::$proto_ns$::internal::ConstantInitialized _constinit_;\n",
1942 camel_oneof_name);
1943 for (auto field : FieldRange(desc: oneof)) {
1944 if (!IsFieldStripped(field, options_)) {
1945 field_generators_.get(field).GeneratePrivateMembers(printer);
1946 }
1947 }
1948 format.Outdent();
1949 format("} $1$_;\n", oneof->name());
1950 for (auto field : FieldRange(desc: oneof)) {
1951 if (!IsFieldStripped(field, options_)) {
1952 field_generators_.get(field).GenerateStaticMembers(printer);
1953 }
1954 }
1955 }
1956
1957 // Members assumed to align to 4 bytes:
1958
1959 if (need_to_emit_cached_size) {
1960 format(cached_size_decl.c_str());
1961 need_to_emit_cached_size = false;
1962 }
1963
1964 // Generate _oneof_case_.
1965 if (descriptor_->real_oneof_decl_count() > 0) {
1966 format(
1967 "$uint32$ _oneof_case_[$1$];\n"
1968 "\n",
1969 descriptor_->real_oneof_decl_count());
1970 }
1971
1972 if (num_weak_fields_) {
1973 format("::$proto_ns$::internal::WeakFieldMap _weak_field_map_;\n");
1974 }
1975 // Generate _any_metadata_ for the Any type.
1976 if (IsAnyMessage(descriptor: descriptor_, options: options_)) {
1977 format("::$proto_ns$::internal::AnyMetadata _any_metadata_;\n");
1978 }
1979
1980 format.Outdent();
1981 format("};\n");
1982
1983 // Only create the _impl_ field if it contains data.
1984 if (HasImplData(desc: descriptor_, options: options_)) {
1985 format("union { Impl_ _impl_; };\n");
1986 }
1987
1988 if (ShouldSplit(desc: descriptor_, options: options_)) {
1989 format(
1990 "static Impl_::Split* CreateSplitMessage("
1991 "::$proto_ns$::Arena* arena);\n");
1992 format("friend struct $1$;\n",
1993 DefaultInstanceType(descriptor: descriptor_, options: options_, /*split=*/true));
1994 }
1995
1996 // The TableStruct struct needs access to the private parts, in order to
1997 // construct the offsets of all members.
1998 format("friend struct ::$tablename$;\n");
1999
2000 format.Outdent();
2001 format("};");
2002 GOOGLE_DCHECK(!need_to_emit_cached_size);
2003} // NOLINT(readability/fn_size)
2004
2005void MessageGenerator::GenerateInlineMethods(io::Printer* printer) {
2006 if (IsMapEntryMessage(descriptor: descriptor_)) return;
2007 GenerateFieldAccessorDefinitions(printer);
2008
2009 // Generate oneof_case() functions.
2010 for (auto oneof : OneOfRange(desc: descriptor_)) {
2011 Formatter format(printer, variables_);
2012 format.Set(key: "camel_oneof_name", value: UnderscoresToCamelCase(input: oneof->name(), cap_next_letter: true));
2013 format.Set(key: "oneof_name", value: oneof->name());
2014 format.Set(key: "oneof_index", value: oneof->index());
2015 format(
2016 "inline $classname$::$camel_oneof_name$Case $classname$::"
2017 "${1$$oneof_name$_case$}$() const {\n"
2018 " return $classname$::$camel_oneof_name$Case("
2019 "$oneof_case$[$oneof_index$]);\n"
2020 "}\n",
2021 oneof);
2022 }
2023}
2024
2025void MessageGenerator::GenerateSchema(io::Printer* printer, int offset,
2026 int has_offset) {
2027 Formatter format(printer, variables_);
2028 has_offset = !has_bit_indices_.empty() || IsMapEntryMessage(descriptor: descriptor_)
2029 ? offset + has_offset
2030 : -1;
2031 int inlined_string_indices_offset;
2032 if (inlined_string_indices_.empty()) {
2033 inlined_string_indices_offset = -1;
2034 } else {
2035 GOOGLE_DCHECK_NE(has_offset, -1);
2036 GOOGLE_DCHECK(!IsMapEntryMessage(descriptor_));
2037 inlined_string_indices_offset = has_offset + has_bit_indices_.size();
2038 }
2039
2040 format("{ $1$, $2$, $3$, sizeof($classtype$)},\n", offset, has_offset,
2041 inlined_string_indices_offset);
2042}
2043
2044void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
2045 Formatter format(printer, variables_);
2046 if (IsMapEntryMessage(descriptor: descriptor_)) {
2047 format(
2048 "$classname$::$classname$() {}\n"
2049 "$classname$::$classname$(::$proto_ns$::Arena* arena)\n"
2050 " : SuperType(arena) {}\n"
2051 "void $classname$::MergeFrom(const $classname$& other) {\n"
2052 " MergeFromInternal(other);\n"
2053 "}\n");
2054 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
2055 if (!descriptor_->options().map_entry()) {
2056 format(
2057 "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
2058 "$annotate_reflection$"
2059 " return ::_pbi::AssignDescriptors(\n"
2060 " &$desc_table$_getter, &$desc_table$_once,\n"
2061 " $file_level_metadata$[$1$]);\n"
2062 "}\n",
2063 index_in_file_messages_);
2064 } else {
2065 format(
2066 "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
2067 " return ::_pbi::AssignDescriptors(\n"
2068 " &$desc_table$_getter, &$desc_table$_once,\n"
2069 " $file_level_metadata$[$1$]);\n"
2070 "}\n",
2071 index_in_file_messages_);
2072 }
2073 }
2074 return;
2075 }
2076
2077 if (IsAnyMessage(descriptor: descriptor_, options: options_)) {
2078 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
2079 format(
2080 "bool $classname$::GetAnyFieldDescriptors(\n"
2081 " const ::$proto_ns$::Message& message,\n"
2082 " const ::$proto_ns$::FieldDescriptor** type_url_field,\n"
2083 " const ::$proto_ns$::FieldDescriptor** value_field) {\n"
2084 " return ::_pbi::GetAnyFieldDescriptors(\n"
2085 " message, type_url_field, value_field);\n"
2086 "}\n");
2087 }
2088 format(
2089 "bool $classname$::ParseAnyTypeUrl(\n"
2090 " ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,\n"
2091 " std::string* full_type_name) {\n"
2092 " return ::_pbi::ParseAnyTypeUrl(type_url, full_type_name);\n"
2093 "}\n"
2094 "\n");
2095 }
2096
2097 format(
2098 "class $classname$::_Internal {\n"
2099 " public:\n");
2100 format.Indent();
2101 if (!has_bit_indices_.empty()) {
2102 format(
2103 "using HasBits = "
2104 "decltype(std::declval<$classname$>().$has_bits$);\n");
2105 }
2106 for (auto field : FieldRange(desc: descriptor_)) {
2107 field_generators_.get(field).GenerateInternalAccessorDeclarations(printer);
2108 if (IsFieldStripped(field, options_)) {
2109 continue;
2110 }
2111 if (HasHasbit(field)) {
2112 int has_bit_index = HasBitIndex(field);
2113 GOOGLE_CHECK_NE(has_bit_index, kNoHasbit) << field->full_name();
2114 format(
2115 "static void set_has_$1$(HasBits* has_bits) {\n"
2116 " (*has_bits)[$2$] |= $3$u;\n"
2117 "}\n",
2118 FieldName(field), has_bit_index / 32, (1u << (has_bit_index % 32)));
2119 }
2120 }
2121 if (num_required_fields_ > 0) {
2122 const std::vector<uint32_t> masks_for_has_bits = RequiredFieldsBitMask();
2123 format(
2124 "static bool MissingRequiredFields(const HasBits& has_bits) "
2125 "{\n"
2126 " return $1$;\n"
2127 "}\n",
2128 ConditionalToCheckBitmasks(masks: masks_for_has_bits, return_success: false, has_bits_var: "has_bits"));
2129 }
2130
2131 format.Outdent();
2132 format("};\n\n");
2133 for (auto field : FieldRange(desc: descriptor_)) {
2134 if (!IsFieldStripped(field, options_)) {
2135 field_generators_.get(field).GenerateInternalAccessorDefinitions(
2136 printer);
2137 }
2138 }
2139
2140 // Generate non-inline field definitions.
2141 for (auto field : FieldRange(desc: descriptor_)) {
2142 if (IsFieldStripped(field, options_)) {
2143 continue;
2144 }
2145 field_generators_.get(field).GenerateNonInlineAccessorDefinitions(printer);
2146 if (IsCrossFileMaybeMap(field)) {
2147 Formatter::SaveState saver(&format);
2148 std::map<std::string, std::string> vars;
2149 SetCommonFieldVariables(descriptor: field, variables: &vars, options: options_);
2150 if (field->real_containing_oneof()) {
2151 SetCommonOneofFieldVariables(descriptor: field, variables: &vars);
2152 }
2153 format.AddMap(vars);
2154 GenerateFieldClear(field, is_inline: false, format);
2155 }
2156 }
2157
2158 GenerateStructors(printer);
2159 format("\n");
2160
2161 if (descriptor_->real_oneof_decl_count() > 0) {
2162 GenerateOneofClear(printer);
2163 format("\n");
2164 }
2165
2166 if (HasGeneratedMethods(file: descriptor_->file(), options: options_)) {
2167 GenerateClear(printer);
2168 format("\n");
2169
2170 if (!HasSimpleBaseClass(desc: descriptor_, options: options_)) {
2171 parse_function_generator_->GenerateMethodImpls(printer);
2172 format("\n");
2173
2174 parse_function_generator_->GenerateDataDefinitions(printer);
2175 }
2176
2177 GenerateSerializeWithCachedSizesToArray(printer);
2178 format("\n");
2179
2180 GenerateByteSize(printer);
2181 format("\n");
2182
2183 GenerateMergeFrom(printer);
2184 format("\n");
2185
2186 GenerateClassSpecificMergeImpl(printer);
2187 format("\n");
2188
2189 GenerateCopyFrom(printer);
2190 format("\n");
2191
2192 GenerateIsInitialized(printer);
2193 format("\n");
2194 }
2195
2196 if (ShouldSplit(desc: descriptor_, options: options_)) {
2197 format(
2198 "void $classname$::PrepareSplitMessageForWrite() {\n"
2199 " if (IsSplitMessageDefault()) {\n"
2200 " $split$ = CreateSplitMessage(GetArenaForAllocation());\n"
2201 " }\n"
2202 "}\n");
2203 }
2204
2205 GenerateVerify(printer);
2206
2207 GenerateSwap(printer);
2208 format("\n");
2209
2210 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
2211 if (!descriptor_->options().map_entry()) {
2212 format(
2213 "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
2214 "$annotate_reflection$"
2215 " return ::_pbi::AssignDescriptors(\n"
2216 " &$desc_table$_getter, &$desc_table$_once,\n"
2217 " $file_level_metadata$[$1$]);\n"
2218 "}\n",
2219 index_in_file_messages_);
2220 } else {
2221 format(
2222 "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
2223 " return ::_pbi::AssignDescriptors(\n"
2224 " &$desc_table$_getter, &$desc_table$_once,\n"
2225 " $file_level_metadata$[$1$]);\n"
2226 "}\n",
2227 index_in_file_messages_);
2228 }
2229 } else {
2230 format(
2231 "std::string $classname$::GetTypeName() const {\n"
2232 " return \"$full_name$\";\n"
2233 "}\n"
2234 "\n");
2235 }
2236
2237 if (HasTracker(desc: descriptor_, options: options_)) {
2238 format(
2239 "::$proto_ns$::AccessListener<$classtype$> "
2240 "$1$::$tracker$(&FullMessageName);\n",
2241 ClassName(descriptor: descriptor_));
2242 }
2243}
2244
2245std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
2246 io::Printer* printer) {
2247 Formatter format(printer, variables_);
2248
2249 if (!has_bit_indices_.empty() || IsMapEntryMessage(descriptor: descriptor_)) {
2250 format("PROTOBUF_FIELD_OFFSET($classtype$, $has_bits$),\n");
2251 } else {
2252 format("~0u, // no _has_bits_\n");
2253 }
2254 format("PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_),\n");
2255 if (descriptor_->extension_range_count() > 0) {
2256 format("PROTOBUF_FIELD_OFFSET($classtype$, $extensions$),\n");
2257 } else {
2258 format("~0u, // no _extensions_\n");
2259 }
2260 if (descriptor_->real_oneof_decl_count() > 0) {
2261 format("PROTOBUF_FIELD_OFFSET($classtype$, $oneof_case$[0]),\n");
2262 } else {
2263 format("~0u, // no _oneof_case_\n");
2264 }
2265 if (num_weak_fields_ > 0) {
2266 format("PROTOBUF_FIELD_OFFSET($classtype$, $weak_field_map$),\n");
2267 } else {
2268 format("~0u, // no _weak_field_map_\n");
2269 }
2270 if (!inlined_string_indices_.empty()) {
2271 format(
2272 "PROTOBUF_FIELD_OFFSET($classtype$, "
2273 "$inlined_string_donated_array$),\n");
2274 } else {
2275 format("~0u, // no _inlined_string_donated_\n");
2276 }
2277 const int kNumGenericOffsets = 6; // the number of fixed offsets above
2278 const size_t offsets = kNumGenericOffsets + descriptor_->field_count() +
2279 descriptor_->real_oneof_decl_count();
2280 size_t entries = offsets;
2281 for (auto field : FieldRange(desc: descriptor_)) {
2282 if (IsFieldStripped(field, options_)) {
2283 format("~0u, // stripped\n");
2284 continue;
2285 }
2286 // TODO(sbenza): We should not have an entry in the offset table for fields
2287 // that do not use them.
2288 if (field->options().weak() || field->real_containing_oneof()) {
2289 // Mark the field to prevent unintentional access through reflection.
2290 // Don't use the top bit because that is for unused fields.
2291 format("::_pbi::kInvalidFieldOffsetTag");
2292 } else {
2293 format("PROTOBUF_FIELD_OFFSET($classtype$$1$, $2$)",
2294 ShouldSplit(field, options: options_) ? "::Impl_::Split" : "",
2295 ShouldSplit(field, options: options_)
2296 ? FieldName(field) + "_"
2297 : FieldMemberName(field, /*cold=*/split: false));
2298 }
2299
2300 // Some information about a field is in the pdproto profile. The profile is
2301 // only available at compile time. So we embed such information in the
2302 // offset of the field, so that the information is available when
2303 // reflectively accessing the field at run time.
2304 //
2305 // Embed whether the field is eagerly verified lazy or inlined string to the
2306 // LSB of the offset.
2307 if (IsEagerlyVerifiedLazy(field, options: options_, scc_analyzer: scc_analyzer_)) {
2308 format(" | 0x1u // eagerly verified lazy\n");
2309 } else if (IsStringInlined(descriptor: field, options: options_)) {
2310 format(" | 0x1u // inlined\n");
2311 }
2312 format(",\n");
2313 }
2314
2315 int count = 0;
2316 for (auto oneof : OneOfRange(desc: descriptor_)) {
2317 format("PROTOBUF_FIELD_OFFSET($classtype$, _impl_.$1$_),\n", oneof->name());
2318 count++;
2319 }
2320 GOOGLE_CHECK_EQ(count, descriptor_->real_oneof_decl_count());
2321
2322 if (IsMapEntryMessage(descriptor: descriptor_)) {
2323 entries += 2;
2324 format(
2325 "0,\n"
2326 "1,\n");
2327 } else if (!has_bit_indices_.empty()) {
2328 entries += has_bit_indices_.size();
2329 for (int i = 0; i < has_bit_indices_.size(); i++) {
2330 const std::string index =
2331 has_bit_indices_[i] >= 0 ? StrCat(a: has_bit_indices_[i]) : "~0u";
2332 format("$1$,\n", index);
2333 }
2334 }
2335 if (!inlined_string_indices_.empty()) {
2336 entries += inlined_string_indices_.size();
2337 for (int inlined_string_index : inlined_string_indices_) {
2338 const std::string index =
2339 inlined_string_index >= 0
2340 ? StrCat(a: inlined_string_index, b: ", // inlined_string_index")
2341 : "~0u,";
2342 format("$1$\n", index);
2343 }
2344 }
2345
2346 return std::make_pair(x&: entries, y: offsets);
2347}
2348
2349void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) {
2350 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return;
2351 Formatter format(printer, variables_);
2352
2353 format(
2354 "inline void $classname$::SharedCtor(\n"
2355 " ::_pb::Arena* arena, bool is_message_owned) {\n"
2356 " (void)arena;\n"
2357 " (void)is_message_owned;\n");
2358
2359 format.Indent();
2360 // Impl_ _impl_.
2361 format("new (&_impl_) Impl_{");
2362 format.Indent();
2363 const char* field_sep = " ";
2364 const auto put_sep = [&] {
2365 format("\n$1$ ", field_sep);
2366 field_sep = ",";
2367 };
2368
2369 // Note: any fields without move/copy constructors can't be explicitly
2370 // aggregate initialized pre-C++17.
2371 if (descriptor_->extension_range_count() > 0) {
2372 put_sep();
2373 format("/*decltype($extensions$)*/{::_pbi::ArenaInitialized(), arena}");
2374 }
2375 if (!inlined_string_indices_.empty()) {
2376 put_sep();
2377 format("decltype($inlined_string_donated_array$){}");
2378 }
2379 bool need_to_emit_cached_size = !HasSimpleBaseClass(desc: descriptor_, options: options_);
2380 if (!has_bit_indices_.empty()) {
2381 put_sep();
2382 format("decltype($has_bits$){}");
2383 if (need_to_emit_cached_size) {
2384 put_sep();
2385 format("/*decltype($cached_size$)*/{}");
2386 need_to_emit_cached_size = false;
2387 }
2388 }
2389
2390 // Initialize member variables with arena constructor.
2391 for (auto field : optimized_order_) {
2392 GOOGLE_DCHECK(!IsFieldStripped(field, options_));
2393 if (ShouldSplit(field, options: options_)) {
2394 continue;
2395 }
2396 put_sep();
2397 field_generators_.get(field).GenerateAggregateInitializer(printer);
2398 }
2399 if (ShouldSplit(desc: descriptor_, options: options_)) {
2400 put_sep();
2401 format("decltype($split$){reinterpret_cast<Impl_::Split*>(&$1$)}",
2402 DefaultInstanceName(descriptor: descriptor_, options: options_, /*split=*/true));
2403 }
2404 for (auto oneof : OneOfRange(desc: descriptor_)) {
2405 put_sep();
2406 format("decltype(_impl_.$1$_){}", oneof->name());
2407 }
2408
2409 if (need_to_emit_cached_size) {
2410 put_sep();
2411 format("/*decltype($cached_size$)*/{}");
2412 }
2413
2414 if (descriptor_->real_oneof_decl_count() != 0) {
2415 put_sep();
2416 format("/*decltype($oneof_case$)*/{}");
2417 }
2418 if (num_weak_fields_ > 0) {
2419 put_sep();
2420 format("decltype($weak_field_map$){arena}");
2421 }
2422 if (IsAnyMessage(descriptor: descriptor_, options: options_)) {
2423 put_sep();
2424 // AnyMetadata has no move constructor.
2425 format("/*decltype($any_metadata$)*/{&_impl_.type_url_, &_impl_.value_}");
2426 }
2427
2428 format.Outdent();
2429 format("\n};\n");
2430
2431 if (!inlined_string_indices_.empty()) {
2432 // Donate inline string fields.
2433 format.Indent();
2434 // The last bit is the tracking bit for registering ArenaDtor. The bit is 1
2435 // means ArenaDtor is not registered on construction, and on demand register
2436 // is needed.
2437 format("if (arena != nullptr) {\n");
2438 if (NeedsArenaDestructor() == ArenaDtorNeeds::kOnDemand) {
2439 format(
2440 " if (!is_message_owned) {\n"
2441 " $inlined_string_donated_array$[0] = ~0u;\n"
2442 " } else {\n"
2443 // We should not register ArenaDtor for MOA.
2444 " $inlined_string_donated_array$[0] = 0xFFFFFFFEu;\n"
2445 " }\n");
2446 } else {
2447 format(" $inlined_string_donated_array$[0] = 0xFFFFFFFEu;\n");
2448 }
2449 for (size_t i = 1; i < InlinedStringDonatedSize(); ++i) {
2450 format(" $inlined_string_donated_array$[$1$] = ~0u;\n", i);
2451 }
2452 format("}\n");
2453 format.Outdent();
2454 }
2455
2456 for (const FieldDescriptor* field : optimized_order_) {
2457 if (ShouldSplit(field, options: options_)) {
2458 continue;
2459 }
2460 field_generators_.get(field).GenerateConstructorCode(printer);
2461 }
2462
2463 for (auto oneof : OneOfRange(desc: descriptor_)) {
2464 format("clear_has_$1$();\n", oneof->name());
2465 }
2466
2467 format.Outdent();
2468 format("}\n\n");
2469}
2470
2471void MessageGenerator::GenerateCreateSplitMessage(io::Printer* printer) {
2472 Formatter format(printer, variables_);
2473 format(
2474 "$classname$::Impl_::Split* "
2475 "$classname$::CreateSplitMessage(::$proto_ns$::Arena* arena) {\n");
2476 format.Indent();
2477 const char* field_sep = " ";
2478 const auto put_sep = [&] {
2479 format("\n$1$ ", field_sep);
2480 field_sep = ",";
2481 };
2482 format(
2483 "const size_t size = sizeof(Impl_::Split);\n"
2484 "void* chunk = (arena == nullptr) ?\n"
2485 " ::operator new(size) :\n"
2486 " arena->AllocateAligned(size, alignof(Impl_::Split));\n"
2487 "Impl_::Split* ptr = reinterpret_cast<Impl_::Split*>(chunk);\n"
2488 "new (ptr) Impl_::Split{");
2489 format.Indent();
2490 for (const FieldDescriptor* field : optimized_order_) {
2491 GOOGLE_DCHECK(!IsFieldStripped(field, options_));
2492 if (ShouldSplit(field, options: options_)) {
2493 put_sep();
2494 field_generators_.get(field).GenerateAggregateInitializer(printer);
2495 }
2496 }
2497 format.Outdent();
2498 format("};\n");
2499 for (const FieldDescriptor* field : optimized_order_) {
2500 GOOGLE_DCHECK(!IsFieldStripped(field, options_));
2501 if (ShouldSplit(field, options: options_)) {
2502 field_generators_.get(field).GenerateCreateSplitMessageCode(printer);
2503 }
2504 }
2505 format("return ptr;\n");
2506 format.Outdent();
2507 format("}\n");
2508}
2509
2510void MessageGenerator::GenerateInitDefaultSplitInstance(io::Printer* printer) {
2511 if (!ShouldSplit(desc: descriptor_, options: options_)) return;
2512
2513 Formatter format(printer, variables_);
2514 const char* field_sep = " ";
2515 const auto put_sep = [&] {
2516 format("\n$1$ ", field_sep);
2517 field_sep = ",";
2518 };
2519 for (const auto* field : optimized_order_) {
2520 if (ShouldSplit(field, options: options_)) {
2521 put_sep();
2522 field_generators_.get(field).GenerateConstexprAggregateInitializer(
2523 printer);
2524 }
2525 }
2526}
2527
2528void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) {
2529 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return;
2530 Formatter format(printer, variables_);
2531
2532 format("inline void $classname$::SharedDtor() {\n");
2533 format.Indent();
2534 format("$DCHK$(GetArenaForAllocation() == nullptr);\n");
2535
2536 if (descriptor_->extension_range_count() > 0) {
2537 format("$extensions$.~ExtensionSet();\n");
2538 }
2539
2540 // Write the destructors for each field except oneof members.
2541 // optimized_order_ does not contain oneof fields.
2542 for (auto field : optimized_order_) {
2543 if (ShouldSplit(field, options: options_)) {
2544 continue;
2545 }
2546 field_generators_.get(field).GenerateDestructorCode(printer);
2547 }
2548 if (ShouldSplit(desc: descriptor_, options: options_)) {
2549 format("if (!IsSplitMessageDefault()) {\n");
2550 format.Indent();
2551 format("auto* $cached_split_ptr$ = $split$;\n");
2552 for (auto field : optimized_order_) {
2553 if (ShouldSplit(field, options: options_)) {
2554 field_generators_.get(field).GenerateDestructorCode(printer);
2555 }
2556 }
2557 format("delete $cached_split_ptr$;\n");
2558 format.Outdent();
2559 format("}\n");
2560 }
2561
2562 // Generate code to destruct oneofs. Clearing should do the work.
2563 for (auto oneof : OneOfRange(desc: descriptor_)) {
2564 format(
2565 "if (has_$1$()) {\n"
2566 " clear_$1$();\n"
2567 "}\n",
2568 oneof->name());
2569 }
2570
2571 if (num_weak_fields_) {
2572 format("$weak_field_map$.ClearAll();\n");
2573 }
2574
2575 if (IsAnyMessage(descriptor: descriptor_, options: options_)) {
2576 format("$any_metadata$.~AnyMetadata();\n");
2577 }
2578
2579 format.Outdent();
2580 format(
2581 "}\n"
2582 "\n");
2583}
2584
2585ArenaDtorNeeds MessageGenerator::NeedsArenaDestructor() const {
2586 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return ArenaDtorNeeds::kNone;
2587 ArenaDtorNeeds needs = ArenaDtorNeeds::kNone;
2588 for (const auto* field : FieldRange(desc: descriptor_)) {
2589 if (IsFieldStripped(field, options_)) continue;
2590 needs =
2591 std::max(needs, field_generators_.get(field).NeedsArenaDestructor());
2592 }
2593 return needs;
2594}
2595
2596void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) {
2597 GOOGLE_CHECK(NeedsArenaDestructor() > ArenaDtorNeeds::kNone);
2598
2599 Formatter format(printer, variables_);
2600
2601 // Generate the ArenaDtor() method. Track whether any fields actually produced
2602 // code that needs to be called.
2603 format("void $classname$::ArenaDtor(void* object) {\n");
2604 format.Indent();
2605
2606 // This code is placed inside a static method, rather than an ordinary one,
2607 // since that simplifies Arena's destructor list (ordinary function pointers
2608 // rather than member function pointers). _this is the object being
2609 // destructed.
2610 format("$classname$* _this = reinterpret_cast< $classname$* >(object);\n");
2611
2612 // Process non-oneof fields first.
2613 for (auto field : optimized_order_) {
2614 if (IsFieldStripped(field, options_) || ShouldSplit(field, options: options_))
2615 continue;
2616 const FieldGenerator& fg = field_generators_.get(field);
2617 fg.GenerateArenaDestructorCode(printer);
2618 }
2619 if (ShouldSplit(desc: descriptor_, options: options_)) {
2620 format("if (!_this->IsSplitMessageDefault()) {\n");
2621 format.Indent();
2622 for (auto field : optimized_order_) {
2623 if (IsFieldStripped(field, options_) || !ShouldSplit(field, options: options_))
2624 continue;
2625 const FieldGenerator& fg = field_generators_.get(field);
2626 fg.GenerateArenaDestructorCode(printer);
2627 }
2628 format.Outdent();
2629 format("}\n");
2630 }
2631
2632 // Process oneof fields.
2633 for (auto oneof : OneOfRange(desc: descriptor_)) {
2634 for (auto field : FieldRange(desc: oneof)) {
2635 if (IsFieldStripped(field, options_)) continue;
2636 field_generators_.get(field).GenerateArenaDestructorCode(printer);
2637 }
2638 }
2639
2640 format.Outdent();
2641 format("}\n");
2642}
2643
2644void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) {
2645 Formatter format(printer, variables_);
2646
2647 if (IsMapEntryMessage(descriptor: descriptor_) || !HasImplData(desc: descriptor_, options: options_)) {
2648 format(
2649 "PROTOBUF_CONSTEXPR $classname$::$classname$(\n"
2650 " ::_pbi::ConstantInitialized) {}\n");
2651 return;
2652 }
2653
2654 format(
2655 "PROTOBUF_CONSTEXPR $classname$::$classname$(\n"
2656 " ::_pbi::ConstantInitialized)");
2657
2658 bool need_to_emit_cached_size = !HasSimpleBaseClass(desc: descriptor_, options: options_);
2659 format(": _impl_{");
2660 format.Indent();
2661 const char* field_sep = " ";
2662 const auto put_sep = [&] {
2663 format("\n$1$ ", field_sep);
2664 field_sep = ",";
2665 };
2666 if (descriptor_->extension_range_count() > 0) {
2667 put_sep();
2668 format("/*decltype($extensions$)*/{}");
2669 }
2670 if (!inlined_string_indices_.empty()) {
2671 put_sep();
2672 format("/*decltype($inlined_string_donated_array$)*/{}");
2673 }
2674 if (!has_bit_indices_.empty()) {
2675 put_sep();
2676 format("/*decltype($has_bits$)*/{}");
2677 if (need_to_emit_cached_size) {
2678 put_sep();
2679 format("/*decltype($cached_size$)*/{}");
2680 need_to_emit_cached_size = false;
2681 }
2682 }
2683 for (auto field : optimized_order_) {
2684 if (ShouldSplit(field, options: options_)) {
2685 continue;
2686 }
2687 put_sep();
2688 field_generators_.get(field).GenerateConstexprAggregateInitializer(
2689 printer);
2690 }
2691 if (ShouldSplit(desc: descriptor_, options: options_)) {
2692 put_sep();
2693 format("/*decltype($split$)*/&$1$._instance",
2694 DefaultInstanceName(descriptor: descriptor_, options: options_, /*split=*/true));
2695 }
2696
2697 for (auto oneof : OneOfRange(desc: descriptor_)) {
2698 put_sep();
2699 format("/*decltype(_impl_.$1$_)*/{}", oneof->name());
2700 }
2701
2702 if (need_to_emit_cached_size) {
2703 put_sep();
2704 format("/*decltype($cached_size$)*/{}");
2705 }
2706
2707 if (descriptor_->real_oneof_decl_count() != 0) {
2708 put_sep();
2709 format("/*decltype($oneof_case$)*/{}");
2710 }
2711
2712 if (num_weak_fields_) {
2713 put_sep();
2714 format("/*decltype($weak_field_map$)*/{}");
2715 }
2716
2717 if (IsAnyMessage(descriptor: descriptor_, options: options_)) {
2718 put_sep();
2719 format(
2720 "/*decltype($any_metadata$)*/{&_impl_.type_url_, "
2721 "&_impl_.value_}");
2722 }
2723
2724 format.Outdent();
2725 format("} {}\n");
2726}
2727
2728void MessageGenerator::GenerateCopyConstructorBody(io::Printer* printer) const {
2729 Formatter format(printer, variables_);
2730
2731 const RunMap runs =
2732 FindRuns(fields: optimized_order_, predicate: [this](const FieldDescriptor* field) {
2733 return IsPOD(field) && !ShouldSplit(field, options: options_);
2734 });
2735
2736 std::string pod_template =
2737 "::memcpy(&$first$, &from.$first$,\n"
2738 " static_cast<size_t>(reinterpret_cast<char*>(&$last$) -\n"
2739 " reinterpret_cast<char*>(&$first$)) + sizeof($last$));\n";
2740
2741 if (ShouldSplit(desc: descriptor_, options: options_)) {
2742 format("if (!from.IsSplitMessageDefault()) {\n");
2743 format.Indent();
2744 format("_this->PrepareSplitMessageForWrite();\n");
2745 for (auto field : optimized_order_) {
2746 if (ShouldSplit(field, options: options_)) {
2747 field_generators_.get(field).GenerateCopyConstructorCode(printer);
2748 }
2749 }
2750 format.Outdent();
2751 format("}\n");
2752 }
2753
2754 for (size_t i = 0; i < optimized_order_.size(); ++i) {
2755 const FieldDescriptor* field = optimized_order_[i];
2756 if (ShouldSplit(field, options: options_)) {
2757 continue;
2758 }
2759 const auto it = runs.find(x: field);
2760
2761 // We only apply the memset technique to runs of more than one field, as
2762 // assignment is better than memset for generated code clarity.
2763 if (it != runs.end() && it->second > 1) {
2764 // Use a memset, then skip run_length fields.
2765 const size_t run_length = it->second;
2766 const std::string first_field_name =
2767 FieldMemberName(field, /*cold=*/split: false);
2768 const std::string last_field_name =
2769 FieldMemberName(field: optimized_order_[i + run_length - 1], /*cold=*/split: false);
2770
2771 format.Set(key: "first", value: first_field_name);
2772 format.Set(key: "last", value: last_field_name);
2773
2774 format(pod_template.c_str());
2775
2776 i += run_length - 1;
2777 // ++i at the top of the loop.
2778 } else {
2779 field_generators_.get(field).GenerateCopyConstructorCode(printer);
2780 }
2781 }
2782}
2783
2784void MessageGenerator::GenerateStructors(io::Printer* printer) {
2785 Formatter format(printer, variables_);
2786
2787 format(
2788 "$classname$::$classname$(::$proto_ns$::Arena* arena,\n"
2789 " bool is_message_owned)\n"
2790 " : $1$(arena, is_message_owned) {\n",
2791 SuperClassName(descriptor: descriptor_, options: options_));
2792
2793 if (!HasSimpleBaseClass(desc: descriptor_, options: options_)) {
2794 format(" SharedCtor(arena, is_message_owned);\n");
2795 if (NeedsArenaDestructor() == ArenaDtorNeeds::kRequired) {
2796 format(
2797 " if (arena != nullptr && !is_message_owned) {\n"
2798 " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n"
2799 " }\n");
2800 }
2801 }
2802 format(
2803 " // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
2804 "}\n");
2805
2806 std::map<std::string, std::string> vars;
2807 SetUnknownFieldsVariable(descriptor: descriptor_, options: options_, variables: &vars);
2808 format.AddMap(vars);
2809
2810 // Generate the copy constructor.
2811 if (UsingImplicitWeakFields(file: descriptor_->file(), options: options_)) {
2812 // If we are in lite mode and using implicit weak fields, we generate a
2813 // one-liner copy constructor that delegates to MergeFrom. This saves some
2814 // code size and also cuts down on the complexity of implicit weak fields.
2815 // We might eventually want to do this for all lite protos.
2816 format(
2817 "$classname$::$classname$(const $classname$& from)\n"
2818 " : $classname$() {\n"
2819 " MergeFrom(from);\n"
2820 "}\n");
2821 } else {
2822 format(
2823 "$classname$::$classname$(const $classname$& from)\n"
2824 " : $superclass$() {\n");
2825 format.Indent();
2826 format("$classname$* const _this = this; (void)_this;\n");
2827
2828 if (HasImplData(desc: descriptor_, options: options_)) {
2829 const char* field_sep = " ";
2830 const auto put_sep = [&] {
2831 format("\n$1$ ", field_sep);
2832 field_sep = ",";
2833 };
2834
2835 format("new (&_impl_) Impl_{");
2836 format.Indent();
2837
2838 if (descriptor_->extension_range_count() > 0) {
2839 put_sep();
2840 format("/*decltype($extensions$)*/{}");
2841 }
2842 if (!inlined_string_indices_.empty()) {
2843 // Do not copy inlined_string_donated_, because this is not an arena
2844 // constructor.
2845 put_sep();
2846 format("decltype($inlined_string_donated_array$){}");
2847 }
2848 bool need_to_emit_cached_size =
2849 !HasSimpleBaseClass(desc: descriptor_, options: options_);
2850 if (!has_bit_indices_.empty()) {
2851 put_sep();
2852 format("decltype($has_bits$){from.$has_bits$}");
2853 if (need_to_emit_cached_size) {
2854 put_sep();
2855 format("/*decltype($cached_size$)*/{}");
2856 need_to_emit_cached_size = false;
2857 }
2858 }
2859
2860 // Initialize member variables with arena constructor.
2861 for (auto field : optimized_order_) {
2862 if (ShouldSplit(field, options: options_)) {
2863 continue;
2864 }
2865 put_sep();
2866 field_generators_.get(field).GenerateCopyAggregateInitializer(printer);
2867 }
2868 if (ShouldSplit(desc: descriptor_, options: options_)) {
2869 put_sep();
2870 format("decltype($split$){reinterpret_cast<Impl_::Split*>(&$1$)}",
2871 DefaultInstanceName(descriptor: descriptor_, options: options_, /*split=*/true));
2872 }
2873 for (auto oneof : OneOfRange(desc: descriptor_)) {
2874 put_sep();
2875 format("decltype(_impl_.$1$_){}", oneof->name());
2876 }
2877
2878 if (need_to_emit_cached_size) {
2879 put_sep();
2880 format("/*decltype($cached_size$)*/{}");
2881 }
2882
2883 if (descriptor_->real_oneof_decl_count() != 0) {
2884 put_sep();
2885 format("/*decltype($oneof_case$)*/{}");
2886 }
2887 if (num_weak_fields_ > 0) {
2888 put_sep();
2889 format("decltype($weak_field_map$){from.$weak_field_map$}");
2890 }
2891 if (IsAnyMessage(descriptor: descriptor_, options: options_)) {
2892 put_sep();
2893 format(
2894 "/*decltype($any_metadata$)*/{&_impl_.type_url_, &_impl_.value_}");
2895 }
2896 format.Outdent();
2897 format("};\n\n");
2898 }
2899
2900 format(
2901 "_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_"
2902 "metadata_);\n");
2903
2904 if (descriptor_->extension_range_count() > 0) {
2905 format(
2906 "$extensions$.MergeFrom(internal_default_instance(), "
2907 "from.$extensions$);\n");
2908 }
2909
2910 GenerateCopyConstructorBody(printer);
2911
2912 // Copy oneof fields. Oneof field requires oneof case check.
2913 for (auto oneof : OneOfRange(desc: descriptor_)) {
2914 format(
2915 "clear_has_$1$();\n"
2916 "switch (from.$1$_case()) {\n",
2917 oneof->name());
2918 format.Indent();
2919 for (auto field : FieldRange(desc: oneof)) {
2920 format("case k$1$: {\n", UnderscoresToCamelCase(input: field->name(), cap_next_letter: true));
2921 format.Indent();
2922 if (!IsFieldStripped(field, options_)) {
2923 field_generators_.get(field).GenerateMergingCode(printer);
2924 }
2925 format("break;\n");
2926 format.Outdent();
2927 format("}\n");
2928 }
2929 format(
2930 "case $1$_NOT_SET: {\n"
2931 " break;\n"
2932 "}\n",
2933 ToUpper(s: oneof->name()));
2934 format.Outdent();
2935 format("}\n");
2936 }
2937
2938 format.Outdent();
2939 format(
2940 " // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
2941 "}\n"
2942 "\n");
2943 }
2944
2945 // Generate the shared constructor code.
2946 GenerateSharedConstructorCode(printer);
2947
2948 if (ShouldSplit(desc: descriptor_, options: options_)) {
2949 GenerateCreateSplitMessage(printer);
2950 }
2951
2952 // Generate the destructor.
2953 if (!HasSimpleBaseClass(desc: descriptor_, options: options_)) {
2954 format(
2955 "$classname$::~$classname$() {\n"
2956 " // @@protoc_insertion_point(destructor:$full_name$)\n");
2957 format(
2958 " if (auto *arena = "
2959 "_internal_metadata_.DeleteReturnArena<$unknown_fields_type$>()) {\n"
2960 " (void)arena;\n");
2961 if (NeedsArenaDestructor() > ArenaDtorNeeds::kNone) {
2962 format(" ArenaDtor(this);\n");
2963 }
2964 format(
2965 " return;\n"
2966 " }\n");
2967 format(
2968 " SharedDtor();\n"
2969 "}\n"
2970 "\n");
2971 } else {
2972 // For messages using simple base classes, having no destructor
2973 // allows our vtable to share the same destructor as every other
2974 // message with a simple base class. This works only as long as
2975 // we have no fields needing destruction, of course. (No strings
2976 // or extensions)
2977 }
2978
2979 // Generate the shared destructor code.
2980 GenerateSharedDestructorCode(printer);
2981
2982 // Generate the arena-specific destructor code.
2983 if (NeedsArenaDestructor() > ArenaDtorNeeds::kNone) {
2984 GenerateArenaDestructorCode(printer);
2985 }
2986
2987 if (!HasSimpleBaseClass(desc: descriptor_, options: options_)) {
2988 // Generate SetCachedSize.
2989 format(
2990 "void $classname$::SetCachedSize(int size) const {\n"
2991 " $cached_size$.Set(size);\n"
2992 "}\n");
2993 }
2994}
2995
2996void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) {
2997 Formatter format(printer, variables_);
2998 format(
2999 "template<> "
3000 "PROTOBUF_NOINLINE $classtype$*\n"
3001 "Arena::CreateMaybeMessage< $classtype$ >(Arena* arena) {\n"
3002 " return Arena::CreateMessageInternal< $classtype$ >(arena);\n"
3003 "}\n");
3004}
3005
3006void MessageGenerator::GenerateClear(io::Printer* printer) {
3007 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return;
3008 Formatter format(printer, variables_);
3009
3010 // The maximum number of bytes we will memset to zero without checking their
3011 // hasbit to see if a zero-init is necessary.
3012 const int kMaxUnconditionalPrimitiveBytesClear = 4;
3013
3014 format(
3015 "void $classname$::Clear() {\n"
3016 "// @@protoc_insertion_point(message_clear_start:$full_name$)\n");
3017 format.Indent();
3018
3019 format(
3020 // TODO(jwb): It would be better to avoid emitting this if it is not used,
3021 // rather than emitting a workaround for the resulting warning.
3022 "$uint32$ cached_has_bits = 0;\n"
3023 "// Prevent compiler warnings about cached_has_bits being unused\n"
3024 "(void) cached_has_bits;\n\n");
3025
3026 if (descriptor_->extension_range_count() > 0) {
3027 format("$extensions$.Clear();\n");
3028 }
3029
3030 // Collect fields into chunks. Each chunk may have an if() condition that
3031 // checks all hasbits in the chunk and skips it if none are set.
3032 int zero_init_bytes = 0;
3033 for (const auto& field : optimized_order_) {
3034 if (CanInitializeByZeroing(field)) {
3035 zero_init_bytes += EstimateAlignmentSize(field);
3036 }
3037 }
3038 bool merge_zero_init = zero_init_bytes > kMaxUnconditionalPrimitiveBytesClear;
3039 int chunk_count = 0;
3040
3041 std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
3042 fields: optimized_order_,
3043 equivalent: [&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool {
3044 chunk_count++;
3045 // This predicate guarantees that there is only a single zero-init
3046 // (memset) per chunk, and if present it will be at the beginning.
3047 bool same = HasByteIndex(field: a) == HasByteIndex(field: b) &&
3048 a->is_repeated() == b->is_repeated() &&
3049 ShouldSplit(field: a, options: options_) == ShouldSplit(field: b, options: options_) &&
3050 (CanInitializeByZeroing(field: a) == CanInitializeByZeroing(field: b) ||
3051 (CanInitializeByZeroing(field: a) &&
3052 (chunk_count == 1 || merge_zero_init)));
3053 if (!same) chunk_count = 0;
3054 return same;
3055 });
3056
3057 ColdChunkSkipper cold_skipper(descriptor_, options_, chunks, has_bit_indices_,
3058 kColdRatio);
3059 int cached_has_word_index = -1;
3060
3061 for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
3062 std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
3063 cold_skipper.OnStartChunk(chunk: chunk_index, cached_has_word_index, from: "", printer);
3064
3065 const FieldDescriptor* memset_start = nullptr;
3066 const FieldDescriptor* memset_end = nullptr;
3067 bool saw_non_zero_init = false;
3068 bool chunk_is_cold = !chunk.empty() && ShouldSplit(field: chunk.front(), options: options_);
3069 for (const auto& field : chunk) {
3070 if (CanInitializeByZeroing(field)) {
3071 GOOGLE_CHECK(!saw_non_zero_init);
3072 if (!memset_start) memset_start = field;
3073 memset_end = field;
3074 } else {
3075 saw_non_zero_init = true;
3076 }
3077 }
3078
3079 // Whether we wrap this chunk in:
3080 // if (cached_has_bits & <chunk hasbits) { /* chunk. */ }
3081 // We can omit the if() for chunk size 1, or if our fields do not have
3082 // hasbits. I don't understand the rationale for the last part of the
3083 // condition, but it matches the old logic.
3084 const bool have_outer_if = HasBitIndex(field: chunk.front()) != kNoHasbit &&
3085 chunk.size() > 1 &&
3086 (memset_end != chunk.back() || merge_zero_init);
3087
3088 if (have_outer_if) {
3089 // Emit an if() that will let us skip the whole chunk if none are set.
3090 uint32_t chunk_mask = GenChunkMask(fields: chunk, has_bit_indices: has_bit_indices_);
3091 std::string chunk_mask_str =
3092 StrCat(a: strings::Hex(chunk_mask, strings::ZERO_PAD_8));
3093
3094 // Check (up to) 8 has_bits at a time if we have more than one field in
3095 // this chunk. Due to field layout ordering, we may check
3096 // _has_bits_[last_chunk * 8 / 32] multiple times.
3097 GOOGLE_DCHECK_LE(2, popcnt(chunk_mask));
3098 GOOGLE_DCHECK_GE(8, popcnt(chunk_mask));
3099
3100 if (cached_has_word_index != HasWordIndex(field: chunk.front())) {
3101 cached_has_word_index = HasWordIndex(field: chunk.front());
3102 format("cached_has_bits = $has_bits$[$1$];\n", cached_has_word_index);
3103 }
3104 format("if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str);
3105 format.Indent();
3106 }
3107
3108 if (chunk_is_cold) {
3109 format("if (!IsSplitMessageDefault()) {\n");
3110 format.Indent();
3111 }
3112
3113 if (memset_start) {
3114 if (memset_start == memset_end) {
3115 // For clarity, do not memset a single field.
3116 field_generators_.get(field: memset_start)
3117 .GenerateMessageClearingCode(printer);
3118 } else {
3119 GOOGLE_CHECK_EQ(chunk_is_cold, ShouldSplit(memset_start, options_));
3120 GOOGLE_CHECK_EQ(chunk_is_cold, ShouldSplit(memset_end, options_));
3121 format(
3122 "::memset(&$1$, 0, static_cast<size_t>(\n"
3123 " reinterpret_cast<char*>(&$2$) -\n"
3124 " reinterpret_cast<char*>(&$1$)) + sizeof($2$));\n",
3125 FieldMemberName(field: memset_start, split: chunk_is_cold),
3126 FieldMemberName(field: memset_end, split: chunk_is_cold));
3127 }
3128 }
3129
3130 // Clear all non-zero-initializable fields in the chunk.
3131 for (const auto& field : chunk) {
3132 if (CanInitializeByZeroing(field)) continue;
3133 // It's faster to just overwrite primitive types, but we should only
3134 // clear strings and messages if they were set.
3135 //
3136 // TODO(kenton): Let the CppFieldGenerator decide this somehow.
3137 bool have_enclosing_if =
3138 HasBitIndex(field) != kNoHasbit &&
3139 (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
3140 field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
3141
3142 if (have_enclosing_if) {
3143 PrintPresenceCheck(format, field, has_bit_indices: has_bit_indices_, printer,
3144 cached_has_word_index: &cached_has_word_index);
3145 }
3146
3147 field_generators_.get(field).GenerateMessageClearingCode(printer);
3148
3149 if (have_enclosing_if) {
3150 format.Outdent();
3151 format("}\n");
3152 }
3153 }
3154
3155 if (chunk_is_cold) {
3156 format.Outdent();
3157 format("}\n");
3158 }
3159
3160 if (have_outer_if) {
3161 format.Outdent();
3162 format("}\n");
3163 }
3164
3165 if (cold_skipper.OnEndChunk(chunk: chunk_index, printer)) {
3166 // Reset here as it may have been updated in just closed if statement.
3167 cached_has_word_index = -1;
3168 }
3169 }
3170
3171 // Step 4: Unions.
3172 for (auto oneof : OneOfRange(desc: descriptor_)) {
3173 format("clear_$1$();\n", oneof->name());
3174 }
3175
3176 if (num_weak_fields_) {
3177 format("$weak_field_map$.ClearAll();\n");
3178 }
3179
3180 // We don't clear donated status.
3181
3182 if (!has_bit_indices_.empty()) {
3183 // Step 5: Everything else.
3184 format("$has_bits$.Clear();\n");
3185 }
3186
3187 std::map<std::string, std::string> vars;
3188 SetUnknownFieldsVariable(descriptor: descriptor_, options: options_, variables: &vars);
3189 format.AddMap(vars);
3190 format("_internal_metadata_.Clear<$unknown_fields_type$>();\n");
3191
3192 format.Outdent();
3193 format("}\n");
3194}
3195
3196void MessageGenerator::GenerateOneofClear(io::Printer* printer) {
3197 // Generated function clears the active field and union case (e.g. foo_case_).
3198 int i = 0;
3199 for (auto oneof : OneOfRange(desc: descriptor_)) {
3200 Formatter format(printer, variables_);
3201 format.Set(key: "oneofname", value: oneof->name());
3202
3203 format(
3204 "void $classname$::clear_$oneofname$() {\n"
3205 "// @@protoc_insertion_point(one_of_clear_start:$full_name$)\n");
3206 format.Indent();
3207 format("switch ($oneofname$_case()) {\n");
3208 format.Indent();
3209 for (auto field : FieldRange(desc: oneof)) {
3210 format("case k$1$: {\n", UnderscoresToCamelCase(input: field->name(), cap_next_letter: true));
3211 format.Indent();
3212 // We clear only allocated objects in oneofs
3213 if (!IsStringOrMessage(field) || IsFieldStripped(field, options_)) {
3214 format("// No need to clear\n");
3215 } else {
3216 field_generators_.get(field).GenerateClearingCode(printer);
3217 }
3218 format("break;\n");
3219 format.Outdent();
3220 format("}\n");
3221 }
3222 format(
3223 "case $1$_NOT_SET: {\n"
3224 " break;\n"
3225 "}\n",
3226 ToUpper(s: oneof->name()));
3227 format.Outdent();
3228 format(
3229 "}\n"
3230 "$oneof_case$[$1$] = $2$_NOT_SET;\n",
3231 i, ToUpper(s: oneof->name()));
3232 format.Outdent();
3233 format(
3234 "}\n"
3235 "\n");
3236 i++;
3237 }
3238}
3239
3240void MessageGenerator::GenerateSwap(io::Printer* printer) {
3241 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return;
3242 Formatter format(printer, variables_);
3243
3244 format("void $classname$::InternalSwap($classname$* other) {\n");
3245 format.Indent();
3246 format("using std::swap;\n");
3247
3248 if (HasGeneratedMethods(file: descriptor_->file(), options: options_)) {
3249 if (descriptor_->extension_range_count() > 0) {
3250 format(
3251 "$extensions$.InternalSwap(&other->$extensions$);"
3252 "\n");
3253 }
3254
3255 std::map<std::string, std::string> vars;
3256 SetUnknownFieldsVariable(descriptor: descriptor_, options: options_, variables: &vars);
3257 format.AddMap(vars);
3258 if (HasNonSplitOptionalString(desc: descriptor_, options: options_)) {
3259 format(
3260 "auto* lhs_arena = GetArenaForAllocation();\n"
3261 "auto* rhs_arena = other->GetArenaForAllocation();\n");
3262 }
3263 format("_internal_metadata_.InternalSwap(&other->_internal_metadata_);\n");
3264
3265 if (!has_bit_indices_.empty()) {
3266 for (int i = 0; i < HasBitsSize(); ++i) {
3267 format("swap($has_bits$[$1$], other->$has_bits$[$1$]);\n", i);
3268 }
3269 }
3270
3271 // If possible, we swap several fields at once, including padding.
3272 const RunMap runs =
3273 FindRuns(fields: optimized_order_, predicate: [this](const FieldDescriptor* field) {
3274 return !ShouldSplit(field, options: options_) &&
3275 CanBeManipulatedAsRawBytes(field, options: options_, scc_analyzer: scc_analyzer_);
3276 });
3277
3278 for (size_t i = 0; i < optimized_order_.size(); ++i) {
3279 const FieldDescriptor* field = optimized_order_[i];
3280 if (ShouldSplit(field, options: options_)) {
3281 continue;
3282 }
3283 const auto it = runs.find(x: field);
3284
3285 // We only apply the memswap technique to runs of more than one field, as
3286 // `swap(field_, other.field_)` is better than
3287 // `memswap<...>(&field_, &other.field_)` for generated code readability.
3288 if (it != runs.end() && it->second > 1) {
3289 // Use a memswap, then skip run_length fields.
3290 const size_t run_length = it->second;
3291 const std::string first_field_name =
3292 FieldMemberName(field, /*cold=*/split: false);
3293 const std::string last_field_name = FieldMemberName(
3294 field: optimized_order_[i + run_length - 1], /*cold=*/split: false);
3295
3296 format.Set(key: "first", value: first_field_name);
3297 format.Set(key: "last", value: last_field_name);
3298
3299 format(
3300 "::PROTOBUF_NAMESPACE_ID::internal::memswap<\n"
3301 " PROTOBUF_FIELD_OFFSET($classname$, $last$)\n"
3302 " + sizeof($classname$::$last$)\n"
3303 " - PROTOBUF_FIELD_OFFSET($classname$, $first$)>(\n"
3304 " reinterpret_cast<char*>(&$first$),\n"
3305 " reinterpret_cast<char*>(&other->$first$));\n");
3306
3307 i += run_length - 1;
3308 // ++i at the top of the loop.
3309 } else {
3310 field_generators_.get(field).GenerateSwappingCode(printer);
3311 }
3312 }
3313 if (ShouldSplit(desc: descriptor_, options: options_)) {
3314 format("swap($split$, other->$split$);\n");
3315 }
3316
3317 for (auto oneof : OneOfRange(desc: descriptor_)) {
3318 format("swap(_impl_.$1$_, other->_impl_.$1$_);\n", oneof->name());
3319 }
3320
3321 for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
3322 format("swap($oneof_case$[$1$], other->$oneof_case$[$1$]);\n", i);
3323 }
3324
3325 if (num_weak_fields_) {
3326 format(
3327 "$weak_field_map$.UnsafeArenaSwap(&other->$weak_field_map$)"
3328 ";\n");
3329 }
3330
3331 if (!inlined_string_indices_.empty()) {
3332 for (size_t i = 0; i < InlinedStringDonatedSize(); ++i) {
3333 format(
3334 "swap($inlined_string_donated_array$[$1$], "
3335 "other->$inlined_string_donated_array$[$1$]);\n",
3336 i);
3337 }
3338 }
3339 } else {
3340 format("GetReflection()->Swap(this, other);");
3341 }
3342
3343 format.Outdent();
3344 format("}\n");
3345}
3346
3347void MessageGenerator::GenerateMergeFrom(io::Printer* printer) {
3348 Formatter format(printer, variables_);
3349 if (!HasSimpleBaseClass(desc: descriptor_, options: options_)) {
3350 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
3351 // We don't override the generalized MergeFrom (aka that which
3352 // takes in the Message base class as a parameter); instead we just
3353 // let the base Message::MergeFrom take care of it. The base MergeFrom
3354 // knows how to quickly confirm the types exactly match, and if so, will
3355 // use GetClassData() to retrieve the address of MergeImpl, which calls
3356 // the fast MergeFrom overload. Most callers avoid all this by passing
3357 // a "from" message that is the same type as the message being merged
3358 // into, rather than a generic Message.
3359
3360 format(
3361 "const ::$proto_ns$::Message::ClassData "
3362 "$classname$::_class_data_ = {\n"
3363 " ::$proto_ns$::Message::CopyWithSourceCheck,\n"
3364 " $classname$::MergeImpl\n"
3365 "};\n"
3366 "const ::$proto_ns$::Message::ClassData*"
3367 "$classname$::GetClassData() const { return &_class_data_; }\n"
3368 "\n");
3369 } else {
3370 // Generate CheckTypeAndMergeFrom().
3371 format(
3372 "void $classname$::CheckTypeAndMergeFrom(\n"
3373 " const ::$proto_ns$::MessageLite& from) {\n"
3374 " MergeFrom(*::_pbi::DownCast<const $classname$*>(\n"
3375 " &from));\n"
3376 "}\n");
3377 }
3378 } else {
3379 // In the simple case, we just define ClassData that vectors back to the
3380 // simple implementation of Copy and Merge.
3381 format(
3382 "const ::$proto_ns$::Message::ClassData "
3383 "$classname$::_class_data_ = {\n"
3384 " $superclass$::CopyImpl,\n"
3385 " $superclass$::MergeImpl,\n"
3386 "};\n"
3387 "const ::$proto_ns$::Message::ClassData*"
3388 "$classname$::GetClassData() const { return &_class_data_; }\n"
3389 "\n"
3390 "\n");
3391 }
3392}
3393
3394void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) {
3395 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return;
3396 // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
3397 Formatter format(printer, variables_);
3398 if (!HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
3399 // For messages that don't inherit from Message, just implement MergeFrom
3400 // directly.
3401 format(
3402 "void $classname$::MergeFrom(const $classname$& from) {\n"
3403 " $classname$* const _this = this;\n");
3404 } else {
3405 format(
3406 "void $classname$::MergeImpl(::$proto_ns$::Message& to_msg, const "
3407 "::$proto_ns$::Message& from_msg) {\n"
3408 " auto* const _this = static_cast<$classname$*>(&to_msg);\n"
3409 " auto& from = static_cast<const $classname$&>(from_msg);\n");
3410 }
3411 format.Indent();
3412 format(
3413 "$annotate_mergefrom$"
3414 "// @@protoc_insertion_point(class_specific_merge_from_start:"
3415 "$full_name$)\n");
3416 format("$DCHK$_NE(&from, _this);\n");
3417
3418 format(
3419 "$uint32$ cached_has_bits = 0;\n"
3420 "(void) cached_has_bits;\n\n");
3421
3422 if (ShouldSplit(desc: descriptor_, options: options_)) {
3423 format(
3424 "if (!from.IsSplitMessageDefault()) {\n"
3425 " _this->PrepareSplitMessageForWrite();\n"
3426 "}\n");
3427 }
3428
3429 std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
3430 fields: optimized_order_,
3431 equivalent: [&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool {
3432 return HasByteIndex(field: a) == HasByteIndex(field: b) &&
3433 ShouldSplit(field: a, options: options_) == ShouldSplit(field: b, options: options_);
3434 });
3435
3436 ColdChunkSkipper cold_skipper(descriptor_, options_, chunks, has_bit_indices_,
3437 kColdRatio);
3438
3439 // cached_has_word_index maintains that:
3440 // cached_has_bits = from._has_bits_[cached_has_word_index]
3441 // for cached_has_word_index >= 0
3442 int cached_has_word_index = -1;
3443
3444 for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
3445 const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
3446 bool have_outer_if =
3447 chunk.size() > 1 && HasByteIndex(field: chunk.front()) != kNoHasbit;
3448 cold_skipper.OnStartChunk(chunk: chunk_index, cached_has_word_index, from: "from.",
3449 printer);
3450
3451 if (have_outer_if) {
3452 // Emit an if() that will let us skip the whole chunk if none are set.
3453 uint32_t chunk_mask = GenChunkMask(fields: chunk, has_bit_indices: has_bit_indices_);
3454 std::string chunk_mask_str =
3455 StrCat(a: strings::Hex(chunk_mask, strings::ZERO_PAD_8));
3456
3457 // Check (up to) 8 has_bits at a time if we have more than one field in
3458 // this chunk. Due to field layout ordering, we may check
3459 // _has_bits_[last_chunk * 8 / 32] multiple times.
3460 GOOGLE_DCHECK_LE(2, popcnt(chunk_mask));
3461 GOOGLE_DCHECK_GE(8, popcnt(chunk_mask));
3462
3463 if (cached_has_word_index != HasWordIndex(field: chunk.front())) {
3464 cached_has_word_index = HasWordIndex(field: chunk.front());
3465 format("cached_has_bits = from.$has_bits$[$1$];\n",
3466 cached_has_word_index);
3467 }
3468
3469 format("if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str);
3470 format.Indent();
3471 }
3472
3473 // Go back and emit merging code for each of the fields we processed.
3474 bool deferred_has_bit_changes = false;
3475 for (const auto field : chunk) {
3476 const FieldGenerator& generator = field_generators_.get(field);
3477
3478 if (field->is_repeated()) {
3479 generator.GenerateMergingCode(printer);
3480 } else if (field->is_optional() && !HasHasbit(field)) {
3481 // Merge semantics without true field presence: primitive fields are
3482 // merged only if non-zero (numeric) or non-empty (string).
3483 bool have_enclosing_if =
3484 EmitFieldNonDefaultCondition(printer, prefix: "from.", field);
3485 generator.GenerateMergingCode(printer);
3486 if (have_enclosing_if) {
3487 format.Outdent();
3488 format("}\n");
3489 }
3490 } else if (field->options().weak() ||
3491 cached_has_word_index != HasWordIndex(field)) {
3492 // Check hasbit, not using cached bits.
3493 GOOGLE_CHECK(HasHasbit(field));
3494 format("if (from._internal_has_$1$()) {\n", FieldName(field));
3495 format.Indent();
3496 generator.GenerateMergingCode(printer);
3497 format.Outdent();
3498 format("}\n");
3499 } else {
3500 // Check hasbit, using cached bits.
3501 GOOGLE_CHECK(HasHasbit(field));
3502 int has_bit_index = has_bit_indices_[field->index()];
3503 const std::string mask = StrCat(
3504 a: strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
3505 format("if (cached_has_bits & 0x$1$u) {\n", mask);
3506 format.Indent();
3507
3508 if (have_outer_if && IsPOD(field)) {
3509 // Defer hasbit modification until the end of chunk.
3510 // This can reduce the number of loads/stores by up to 7 per 8 fields.
3511 deferred_has_bit_changes = true;
3512 generator.GenerateCopyConstructorCode(printer);
3513 } else {
3514 generator.GenerateMergingCode(printer);
3515 }
3516
3517 format.Outdent();
3518 format("}\n");
3519 }
3520 }
3521
3522 if (have_outer_if) {
3523 if (deferred_has_bit_changes) {
3524 // Flush the has bits for the primitives we deferred.
3525 GOOGLE_CHECK_LE(0, cached_has_word_index);
3526 format("_this->$has_bits$[$1$] |= cached_has_bits;\n",
3527 cached_has_word_index);
3528 }
3529
3530 format.Outdent();
3531 format("}\n");
3532 }
3533
3534 if (cold_skipper.OnEndChunk(chunk: chunk_index, printer)) {
3535 // Reset here as it may have been updated in just closed if statement.
3536 cached_has_word_index = -1;
3537 }
3538 }
3539
3540 // Merge oneof fields. Oneof field requires oneof case check.
3541 for (auto oneof : OneOfRange(desc: descriptor_)) {
3542 format("switch (from.$1$_case()) {\n", oneof->name());
3543 format.Indent();
3544 for (auto field : FieldRange(desc: oneof)) {
3545 format("case k$1$: {\n", UnderscoresToCamelCase(input: field->name(), cap_next_letter: true));
3546 format.Indent();
3547 if (!IsFieldStripped(field, options_)) {
3548 field_generators_.get(field).GenerateMergingCode(printer);
3549 }
3550 format("break;\n");
3551 format.Outdent();
3552 format("}\n");
3553 }
3554 format(
3555 "case $1$_NOT_SET: {\n"
3556 " break;\n"
3557 "}\n",
3558 ToUpper(s: oneof->name()));
3559 format.Outdent();
3560 format("}\n");
3561 }
3562 if (num_weak_fields_) {
3563 format(
3564 "_this->$weak_field_map$.MergeFrom(from.$weak_field_map$);"
3565 "\n");
3566 }
3567
3568 // Merging of extensions and unknown fields is done last, to maximize
3569 // the opportunity for tail calls.
3570 if (descriptor_->extension_range_count() > 0) {
3571 format(
3572 "_this->$extensions$.MergeFrom(internal_default_instance(), "
3573 "from.$extensions$);\n");
3574 }
3575
3576 format(
3577 "_this->_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._"
3578 "internal_"
3579 "metadata_);\n");
3580
3581 format.Outdent();
3582 format("}\n");
3583}
3584
3585void MessageGenerator::GenerateCopyFrom(io::Printer* printer) {
3586 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return;
3587 Formatter format(printer, variables_);
3588 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
3589 // We don't override the generalized CopyFrom (aka that which
3590 // takes in the Message base class as a parameter); instead we just
3591 // let the base Message::CopyFrom take care of it. The base MergeFrom
3592 // knows how to quickly confirm the types exactly match, and if so, will
3593 // use GetClassData() to get the address of Message::CopyWithSourceCheck,
3594 // which calls Clear() and then MergeFrom(), as well as making sure that
3595 // clearing the destination message doesn't alter the source, when in debug
3596 // builds. Most callers avoid this by passing a "from" message that is the
3597 // same type as the message being merged into, rather than a generic
3598 // Message.
3599 }
3600
3601 // Generate the class-specific CopyFrom.
3602 format(
3603 "void $classname$::CopyFrom(const $classname$& from) {\n"
3604 "// @@protoc_insertion_point(class_specific_copy_from_start:"
3605 "$full_name$)\n");
3606 format.Indent();
3607
3608 format("if (&from == this) return;\n");
3609
3610 if (!options_.opensource_runtime && HasMessageFieldOrExtension(desc: descriptor_)) {
3611 // This check is disabled in the opensource release because we're
3612 // concerned that many users do not define NDEBUG in their release builds.
3613 // It is also disabled if a message has neither message fields nor
3614 // extensions, as it's impossible to copy from its descendant.
3615 //
3616 // Note that FailIfCopyFromDescendant is implemented by reflection and not
3617 // available for lite runtime. In that case, check if the size of the source
3618 // has changed after Clear.
3619 format("#ifndef NDEBUG\n");
3620 if (HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
3621 format("FailIfCopyFromDescendant(*this, from);\n");
3622 } else {
3623 format("size_t from_size = from.ByteSizeLong();\n");
3624 }
3625 format(
3626 "#endif\n"
3627 "Clear();\n");
3628 if (!HasDescriptorMethods(file: descriptor_->file(), options: options_)) {
3629 format(
3630 "#ifndef NDEBUG\n"
3631 "$CHK$_EQ(from_size, from.ByteSizeLong())\n"
3632 " << \"Source of CopyFrom changed when clearing target. Either \"\n"
3633 " \"source is a nested message in target (not allowed), or \"\n"
3634 " \"another thread is modifying the source.\";\n"
3635 "#endif\n");
3636 }
3637 } else {
3638 format("Clear();\n");
3639 }
3640 format("MergeFrom(from);\n");
3641
3642 format.Outdent();
3643 format("}\n");
3644}
3645
3646void MessageGenerator::GenerateVerify(io::Printer* printer) {
3647}
3648
3649void MessageGenerator::GenerateSerializeOneofFields(
3650 io::Printer* printer, const std::vector<const FieldDescriptor*>& fields) {
3651 Formatter format(printer, variables_);
3652 GOOGLE_CHECK(!fields.empty());
3653 if (fields.size() == 1) {
3654 GenerateSerializeOneField(printer, field: fields[0], cached_has_bits_index: -1);
3655 return;
3656 }
3657 // We have multiple mutually exclusive choices. Emit a switch statement.
3658 const OneofDescriptor* oneof = fields[0]->containing_oneof();
3659 format("switch ($1$_case()) {\n", oneof->name());
3660 format.Indent();
3661 for (auto field : fields) {
3662 format("case k$1$: {\n", UnderscoresToCamelCase(input: field->name(), cap_next_letter: true));
3663 format.Indent();
3664 field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
3665 printer);
3666 format("break;\n");
3667 format.Outdent();
3668 format("}\n");
3669 }
3670 format.Outdent();
3671 // Doing nothing is an option.
3672 format(
3673 " default: ;\n"
3674 "}\n");
3675}
3676
3677void MessageGenerator::GenerateSerializeOneField(io::Printer* printer,
3678 const FieldDescriptor* field,
3679 int cached_has_bits_index) {
3680 Formatter format(printer, variables_);
3681 if (!field->options().weak()) {
3682 // For weakfields, PrintFieldComment is called during iteration.
3683 PrintFieldComment(format, field);
3684 }
3685
3686 bool have_enclosing_if = false;
3687 if (field->options().weak()) {
3688 } else if (HasHasbit(field)) {
3689 // Attempt to use the state of cached_has_bits, if possible.
3690 int has_bit_index = HasBitIndex(field);
3691 if (cached_has_bits_index == has_bit_index / 32) {
3692 const std::string mask =
3693 StrCat(a: strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
3694
3695 format("if (cached_has_bits & 0x$1$u) {\n", mask);
3696 } else {
3697 format("if (_internal_has_$1$()) {\n", FieldName(field));
3698 }
3699
3700 format.Indent();
3701 have_enclosing_if = true;
3702 } else if (field->is_optional() && !HasHasbit(field)) {
3703 have_enclosing_if = EmitFieldNonDefaultCondition(printer, prefix: "this->", field);
3704 }
3705
3706 field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(printer);
3707
3708 if (have_enclosing_if) {
3709 format.Outdent();
3710 format("}\n");
3711 }
3712 format("\n");
3713}
3714
3715void MessageGenerator::GenerateSerializeOneExtensionRange(
3716 io::Printer* printer, const Descriptor::ExtensionRange* range) {
3717 std::map<std::string, std::string> vars = variables_;
3718 vars["start"] = StrCat(a: range->start);
3719 vars["end"] = StrCat(a: range->end);
3720 Formatter format(printer, vars);
3721 format("// Extension range [$start$, $end$)\n");
3722 format(
3723 "target = $extensions$._InternalSerialize(\n"
3724 "internal_default_instance(), $start$, $end$, target, stream);\n\n");
3725}
3726
3727void MessageGenerator::GenerateSerializeWithCachedSizesToArray(
3728 io::Printer* printer) {
3729 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return;
3730 Formatter format(printer, variables_);
3731 if (descriptor_->options().message_set_wire_format()) {
3732 // Special-case MessageSet.
3733 format(
3734 "$uint8$* $classname$::_InternalSerialize(\n"
3735 " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
3736 "const {\n"
3737 "$annotate_serialize$"
3738 " target = $extensions$."
3739 "InternalSerializeMessageSetWithCachedSizesToArray(\n" //
3740 "internal_default_instance(), target, stream);\n");
3741 std::map<std::string, std::string> vars;
3742 SetUnknownFieldsVariable(descriptor: descriptor_, options: options_, variables: &vars);
3743 format.AddMap(vars);
3744 format(
3745 " target = ::_pbi::"
3746 "InternalSerializeUnknownMessageSetItemsToArray(\n"
3747 " $unknown_fields$, target, stream);\n");
3748 format(
3749 " return target;\n"
3750 "}\n");
3751 return;
3752 }
3753
3754 format(
3755 "$uint8$* $classname$::_InternalSerialize(\n"
3756 " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
3757 "const {\n"
3758 "$annotate_serialize$");
3759 format.Indent();
3760
3761 format("// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n");
3762
3763 if (!ShouldSerializeInOrder(descriptor: descriptor_, options: options_)) {
3764 format.Outdent();
3765 format("#ifdef NDEBUG\n");
3766 format.Indent();
3767 }
3768
3769 GenerateSerializeWithCachedSizesBody(printer);
3770
3771 if (!ShouldSerializeInOrder(descriptor: descriptor_, options: options_)) {
3772 format.Outdent();
3773 format("#else // NDEBUG\n");
3774 format.Indent();
3775
3776 GenerateSerializeWithCachedSizesBodyShuffled(printer);
3777
3778 format.Outdent();
3779 format("#endif // !NDEBUG\n");
3780 format.Indent();
3781 }
3782
3783 format("// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n");
3784
3785 format.Outdent();
3786 format(
3787 " return target;\n"
3788 "}\n");
3789}
3790
3791void MessageGenerator::GenerateSerializeWithCachedSizesBody(
3792 io::Printer* printer) {
3793 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return;
3794 Formatter format(printer, variables_);
3795 // If there are multiple fields in a row from the same oneof then we
3796 // coalesce them and emit a switch statement. This is more efficient
3797 // because it lets the C++ compiler know this is a "at most one can happen"
3798 // situation. If we emitted "if (has_x()) ...; if (has_y()) ..." the C++
3799 // compiler's emitted code might check has_y() even when has_x() is true.
3800 class LazySerializerEmitter {
3801 public:
3802 LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer)
3803 : mg_(mg),
3804 format_(printer),
3805 eager_(IsProto3(file: mg->descriptor_->file())),
3806 cached_has_bit_index_(kNoHasbit) {}
3807
3808 ~LazySerializerEmitter() { Flush(); }
3809
3810 // If conditions allow, try to accumulate a run of fields from the same
3811 // oneof, and handle them at the next Flush().
3812 void Emit(const FieldDescriptor* field) {
3813 if (eager_ || MustFlush(field)) {
3814 Flush();
3815 }
3816 if (!field->real_containing_oneof()) {
3817 // TODO(ckennelly): Defer non-oneof fields similarly to oneof fields.
3818
3819 if (!field->options().weak() && !field->is_repeated() && !eager_) {
3820 // We speculatively load the entire _has_bits_[index] contents, even
3821 // if it is for only one field. Deferring non-oneof emitting would
3822 // allow us to determine whether this is going to be useful.
3823 int has_bit_index = mg_->has_bit_indices_[field->index()];
3824 if (cached_has_bit_index_ != has_bit_index / 32) {
3825 // Reload.
3826 int new_index = has_bit_index / 32;
3827
3828 format_("cached_has_bits = _impl_._has_bits_[$1$];\n", new_index);
3829
3830 cached_has_bit_index_ = new_index;
3831 }
3832 }
3833
3834 mg_->GenerateSerializeOneField(printer: format_.printer(), field,
3835 cached_has_bits_index: cached_has_bit_index_);
3836 } else {
3837 v_.push_back(x: field);
3838 }
3839 }
3840
3841 void EmitIfNotNull(const FieldDescriptor* field) {
3842 if (field != nullptr) {
3843 Emit(field);
3844 }
3845 }
3846
3847 void Flush() {
3848 if (!v_.empty()) {
3849 mg_->GenerateSerializeOneofFields(printer: format_.printer(), fields: v_);
3850 v_.clear();
3851 }
3852 }
3853
3854 private:
3855 // If we have multiple fields in v_ then they all must be from the same
3856 // oneof. Would adding field to v_ break that invariant?
3857 bool MustFlush(const FieldDescriptor* field) {
3858 return !v_.empty() &&
3859 v_[0]->containing_oneof() != field->containing_oneof();
3860 }
3861
3862 MessageGenerator* mg_;
3863 Formatter format_;
3864 const bool eager_;
3865 std::vector<const FieldDescriptor*> v_;
3866
3867 // cached_has_bit_index_ maintains that:
3868 // cached_has_bits = from._has_bits_[cached_has_bit_index_]
3869 // for cached_has_bit_index_ >= 0
3870 int cached_has_bit_index_;
3871 };
3872
3873 class LazyExtensionRangeEmitter {
3874 public:
3875 LazyExtensionRangeEmitter(MessageGenerator* mg, io::Printer* printer)
3876 : mg_(mg), format_(printer) {}
3877
3878 void AddToRange(const Descriptor::ExtensionRange* range) {
3879 if (!has_current_range_) {
3880 current_combined_range_ = *range;
3881 has_current_range_ = true;
3882 } else {
3883 current_combined_range_.start =
3884 std::min(current_combined_range_.start, range->start);
3885 current_combined_range_.end =
3886 std::max(current_combined_range_.end, range->end);
3887 }
3888 }
3889
3890 void Flush() {
3891 if (has_current_range_) {
3892 mg_->GenerateSerializeOneExtensionRange(printer: format_.printer(),
3893 range: &current_combined_range_);
3894 }
3895 has_current_range_ = false;
3896 }
3897
3898 private:
3899 MessageGenerator* mg_;
3900 Formatter format_;
3901 bool has_current_range_ = false;
3902 Descriptor::ExtensionRange current_combined_range_;
3903 };
3904
3905 // We need to track the largest weak field, because weak fields are serialized
3906 // differently than normal fields. The WeakFieldMap::FieldWriter will
3907 // serialize all weak fields that are ordinally between the last serialized
3908 // weak field and the current field. In order to guarantee that all weak
3909 // fields are serialized, we need to make sure to emit the code to serialize
3910 // the largest weak field present at some point.
3911 class LargestWeakFieldHolder {
3912 public:
3913 const FieldDescriptor* Release() {
3914 const FieldDescriptor* result = field_;
3915 field_ = nullptr;
3916 return result;
3917 }
3918 void ReplaceIfLarger(const FieldDescriptor* field) {
3919 if (field_ == nullptr || field_->number() < field->number()) {
3920 field_ = field;
3921 }
3922 }
3923
3924 private:
3925 const FieldDescriptor* field_ = nullptr;
3926 };
3927
3928 std::vector<const FieldDescriptor*> ordered_fields =
3929 SortFieldsByNumber(descriptor: descriptor_);
3930
3931 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
3932 sorted_extensions.reserve(n: descriptor_->extension_range_count());
3933 for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
3934 sorted_extensions.push_back(x: descriptor_->extension_range(index: i));
3935 }
3936 std::sort(first: sorted_extensions.begin(), last: sorted_extensions.end(),
3937 comp: ExtensionRangeSorter());
3938 if (num_weak_fields_) {
3939 format(
3940 "::_pbi::WeakFieldMap::FieldWriter field_writer("
3941 "$weak_field_map$);\n");
3942 }
3943
3944 format(
3945 "$uint32$ cached_has_bits = 0;\n"
3946 "(void) cached_has_bits;\n\n");
3947
3948 // Merge the fields and the extension ranges, both sorted by field number.
3949 {
3950 LazySerializerEmitter e(this, printer);
3951 LazyExtensionRangeEmitter re(this, printer);
3952 LargestWeakFieldHolder largest_weak_field;
3953 int i, j;
3954 for (i = 0, j = 0;
3955 i < ordered_fields.size() || j < sorted_extensions.size();) {
3956 if ((j == sorted_extensions.size()) ||
3957 (i < descriptor_->field_count() &&
3958 ordered_fields[i]->number() < sorted_extensions[j]->start)) {
3959 const FieldDescriptor* field = ordered_fields[i++];
3960 if (IsFieldStripped(field, options_)) {
3961 continue;
3962 }
3963 re.Flush();
3964 if (field->options().weak()) {
3965 largest_weak_field.ReplaceIfLarger(field);
3966 PrintFieldComment(format, field);
3967 } else {
3968 e.EmitIfNotNull(field: largest_weak_field.Release());
3969 e.Emit(field);
3970 }
3971 } else {
3972 e.EmitIfNotNull(field: largest_weak_field.Release());
3973 e.Flush();
3974 re.AddToRange(range: sorted_extensions[j++]);
3975 }
3976 }
3977 re.Flush();
3978 e.EmitIfNotNull(field: largest_weak_field.Release());
3979 }
3980
3981 std::map<std::string, std::string> vars;
3982 SetUnknownFieldsVariable(descriptor: descriptor_, options: options_, variables: &vars);
3983 format.AddMap(vars);
3984 format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
3985 format.Indent();
3986 if (UseUnknownFieldSet(file: descriptor_->file(), options: options_)) {
3987 format(
3988 "target = "
3989 "::_pbi::WireFormat::"
3990 "InternalSerializeUnknownFieldsToArray(\n"
3991 " $unknown_fields$, target, stream);\n");
3992 } else {
3993 format(
3994 "target = stream->WriteRaw($unknown_fields$.data(),\n"
3995 " static_cast<int>($unknown_fields$.size()), target);\n");
3996 }
3997 format.Outdent();
3998 format("}\n");
3999}
4000
4001void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled(
4002 io::Printer* printer) {
4003 Formatter format(printer, variables_);
4004
4005 std::vector<const FieldDescriptor*> ordered_fields =
4006 SortFieldsByNumber(descriptor: descriptor_);
4007 ordered_fields.erase(
4008 first: std::remove_if(first: ordered_fields.begin(), last: ordered_fields.end(),
4009 pred: [this](const FieldDescriptor* f) {
4010 return !IsFieldUsed(f, options_);
4011 }),
4012 last: ordered_fields.end());
4013
4014 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
4015 sorted_extensions.reserve(n: descriptor_->extension_range_count());
4016 for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
4017 sorted_extensions.push_back(x: descriptor_->extension_range(index: i));
4018 }
4019 std::sort(first: sorted_extensions.begin(), last: sorted_extensions.end(),
4020 comp: ExtensionRangeSorter());
4021
4022 int num_fields = ordered_fields.size() + sorted_extensions.size();
4023 constexpr int kLargePrime = 1000003;
4024 GOOGLE_CHECK_LT(num_fields, kLargePrime)
4025 << "Prime offset must be greater than the number of fields to ensure "
4026 "those are coprime.";
4027
4028 if (num_weak_fields_) {
4029 format(
4030 "::_pbi::WeakFieldMap::FieldWriter field_writer("
4031 "$weak_field_map$);\n");
4032 }
4033
4034 format("for (int i = $1$; i >= 0; i-- ) {\n", num_fields - 1);
4035
4036 format.Indent();
4037 format("switch(i) {\n");
4038 format.Indent();
4039
4040 int index = 0;
4041 for (const auto* f : ordered_fields) {
4042 format("case $1$: {\n", index++);
4043 format.Indent();
4044
4045 GenerateSerializeOneField(printer, field: f, cached_has_bits_index: -1);
4046
4047 format("break;\n");
4048 format.Outdent();
4049 format("}\n");
4050 }
4051
4052 for (const auto* r : sorted_extensions) {
4053 format("case $1$: {\n", index++);
4054 format.Indent();
4055
4056 GenerateSerializeOneExtensionRange(printer, range: r);
4057
4058 format("break;\n");
4059 format.Outdent();
4060 format("}\n");
4061 }
4062
4063 format(
4064 "default: {\n"
4065 " $DCHK$(false) << \"Unexpected index: \" << i;\n"
4066 "}\n");
4067 format.Outdent();
4068 format("}\n");
4069
4070 format.Outdent();
4071 format("}\n");
4072
4073 std::map<std::string, std::string> vars;
4074 SetUnknownFieldsVariable(descriptor: descriptor_, options: options_, variables: &vars);
4075 format.AddMap(vars);
4076 format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
4077 format.Indent();
4078 if (UseUnknownFieldSet(file: descriptor_->file(), options: options_)) {
4079 format(
4080 "target = "
4081 "::_pbi::WireFormat::"
4082 "InternalSerializeUnknownFieldsToArray(\n"
4083 " $unknown_fields$, target, stream);\n");
4084 } else {
4085 format(
4086 "target = stream->WriteRaw($unknown_fields$.data(),\n"
4087 " static_cast<int>($unknown_fields$.size()), target);\n");
4088 }
4089 format.Outdent();
4090 format("}\n");
4091}
4092
4093std::vector<uint32_t> MessageGenerator::RequiredFieldsBitMask() const {
4094 const int array_size = HasBitsSize();
4095 std::vector<uint32_t> masks(array_size, 0);
4096
4097 for (auto field : FieldRange(desc: descriptor_)) {
4098 if (!field->is_required()) {
4099 continue;
4100 }
4101
4102 const int has_bit_index = has_bit_indices_[field->index()];
4103 masks[has_bit_index / 32] |= static_cast<uint32_t>(1)
4104 << (has_bit_index % 32);
4105 }
4106 return masks;
4107}
4108
4109void MessageGenerator::GenerateByteSize(io::Printer* printer) {
4110 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return;
4111 Formatter format(printer, variables_);
4112
4113 if (descriptor_->options().message_set_wire_format()) {
4114 // Special-case MessageSet.
4115 std::map<std::string, std::string> vars;
4116 SetUnknownFieldsVariable(descriptor: descriptor_, options: options_, variables: &vars);
4117 format.AddMap(vars);
4118 format(
4119 "size_t $classname$::ByteSizeLong() const {\n"
4120 "$annotate_bytesize$"
4121 "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n"
4122 " size_t total_size = $extensions$.MessageSetByteSize();\n"
4123 " if ($have_unknown_fields$) {\n"
4124 " total_size += ::_pbi::\n"
4125 " ComputeUnknownMessageSetItemsSize($unknown_fields$);\n"
4126 " }\n"
4127 " int cached_size = "
4128 "::_pbi::ToCachedSize(total_size);\n"
4129 " SetCachedSize(cached_size);\n"
4130 " return total_size;\n"
4131 "}\n");
4132 return;
4133 }
4134
4135 if (num_required_fields_ > 1) {
4136 // Emit a function (rarely used, we hope) that handles the required fields
4137 // by checking for each one individually.
4138 format(
4139 "size_t $classname$::RequiredFieldsByteSizeFallback() const {\n"
4140 "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:"
4141 "$full_name$)\n");
4142 format.Indent();
4143 format("size_t total_size = 0;\n");
4144 for (auto field : optimized_order_) {
4145 if (field->is_required()) {
4146 format(
4147 "\n"
4148 "if (_internal_has_$1$()) {\n",
4149 FieldName(field));
4150 format.Indent();
4151 PrintFieldComment(format, field);
4152 field_generators_.get(field).GenerateByteSize(printer);
4153 format.Outdent();
4154 format("}\n");
4155 }
4156 }
4157 format(
4158 "\n"
4159 "return total_size;\n");
4160 format.Outdent();
4161 format("}\n");
4162 }
4163
4164 format(
4165 "size_t $classname$::ByteSizeLong() const {\n"
4166 "$annotate_bytesize$"
4167 "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n");
4168 format.Indent();
4169 format(
4170 "size_t total_size = 0;\n"
4171 "\n");
4172
4173 if (descriptor_->extension_range_count() > 0) {
4174 format(
4175 "total_size += $extensions$.ByteSize();\n"
4176 "\n");
4177 }
4178
4179 std::map<std::string, std::string> vars;
4180 SetUnknownFieldsVariable(descriptor: descriptor_, options: options_, variables: &vars);
4181 format.AddMap(vars);
4182
4183 // Handle required fields (if any). We expect all of them to be
4184 // present, so emit one conditional that checks for that. If they are all
4185 // present then the fast path executes; otherwise the slow path executes.
4186 if (num_required_fields_ > 1) {
4187 // The fast path works if all required fields are present.
4188 const std::vector<uint32_t> masks_for_has_bits = RequiredFieldsBitMask();
4189 format("if ($1$) { // All required fields are present.\n",
4190 ConditionalToCheckBitmasks(masks: masks_for_has_bits));
4191 format.Indent();
4192 // Oneof fields cannot be required, so optimized_order_ contains all of the
4193 // fields that we need to potentially emit.
4194 for (auto field : optimized_order_) {
4195 if (!field->is_required()) continue;
4196 PrintFieldComment(format, field);
4197 field_generators_.get(field).GenerateByteSize(printer);
4198 format("\n");
4199 }
4200 format.Outdent();
4201 format(
4202 "} else {\n" // the slow path
4203 " total_size += RequiredFieldsByteSizeFallback();\n"
4204 "}\n");
4205 } else {
4206 // num_required_fields_ <= 1: no need to be tricky
4207 for (auto field : optimized_order_) {
4208 if (!field->is_required()) continue;
4209 PrintFieldComment(format, field);
4210 format("if (_internal_has_$1$()) {\n", FieldName(field));
4211 format.Indent();
4212 field_generators_.get(field).GenerateByteSize(printer);
4213 format.Outdent();
4214 format("}\n");
4215 }
4216 }
4217
4218 std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
4219 fields: optimized_order_,
4220 equivalent: [&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool {
4221 return a->label() == b->label() && HasByteIndex(field: a) == HasByteIndex(field: b) &&
4222 ShouldSplit(field: a, options: options_) == ShouldSplit(field: b, options: options_);
4223 });
4224
4225 // Remove chunks with required fields.
4226 chunks.erase(first: std::remove_if(first: chunks.begin(), last: chunks.end(), pred: IsRequired),
4227 last: chunks.end());
4228
4229 ColdChunkSkipper cold_skipper(descriptor_, options_, chunks, has_bit_indices_,
4230 kColdRatio);
4231 int cached_has_word_index = -1;
4232
4233 format(
4234 "$uint32$ cached_has_bits = 0;\n"
4235 "// Prevent compiler warnings about cached_has_bits being unused\n"
4236 "(void) cached_has_bits;\n\n");
4237
4238 for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
4239 const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
4240 const bool have_outer_if =
4241 chunk.size() > 1 && HasWordIndex(field: chunk[0]) != kNoHasbit;
4242 cold_skipper.OnStartChunk(chunk: chunk_index, cached_has_word_index, from: "", printer);
4243
4244 if (have_outer_if) {
4245 // Emit an if() that will let us skip the whole chunk if none are set.
4246 uint32_t chunk_mask = GenChunkMask(fields: chunk, has_bit_indices: has_bit_indices_);
4247 std::string chunk_mask_str =
4248 StrCat(a: strings::Hex(chunk_mask, strings::ZERO_PAD_8));
4249
4250 // Check (up to) 8 has_bits at a time if we have more than one field in
4251 // this chunk. Due to field layout ordering, we may check
4252 // _has_bits_[last_chunk * 8 / 32] multiple times.
4253 GOOGLE_DCHECK_LE(2, popcnt(chunk_mask));
4254 GOOGLE_DCHECK_GE(8, popcnt(chunk_mask));
4255
4256 if (cached_has_word_index != HasWordIndex(field: chunk.front())) {
4257 cached_has_word_index = HasWordIndex(field: chunk.front());
4258 format("cached_has_bits = $has_bits$[$1$];\n", cached_has_word_index);
4259 }
4260 format("if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str);
4261 format.Indent();
4262 }
4263
4264 // Go back and emit checks for each of the fields we processed.
4265 for (int j = 0; j < chunk.size(); j++) {
4266 const FieldDescriptor* field = chunk[j];
4267 const FieldGenerator& generator = field_generators_.get(field);
4268 bool have_enclosing_if = false;
4269 bool need_extra_newline = false;
4270
4271 PrintFieldComment(format, field);
4272
4273 if (field->is_repeated()) {
4274 // No presence check is required.
4275 need_extra_newline = true;
4276 } else if (HasHasbit(field)) {
4277 PrintPresenceCheck(format, field, has_bit_indices: has_bit_indices_, printer,
4278 cached_has_word_index: &cached_has_word_index);
4279 have_enclosing_if = true;
4280 } else {
4281 // Without field presence: field is serialized only if it has a
4282 // non-default value.
4283 have_enclosing_if =
4284 EmitFieldNonDefaultCondition(printer, prefix: "this->", field);
4285 }
4286
4287 generator.GenerateByteSize(printer);
4288
4289 if (have_enclosing_if) {
4290 format.Outdent();
4291 format(
4292 "}\n"
4293 "\n");
4294 }
4295 if (need_extra_newline) {
4296 format("\n");
4297 }
4298 }
4299
4300 if (have_outer_if) {
4301 format.Outdent();
4302 format("}\n");
4303 }
4304
4305 if (cold_skipper.OnEndChunk(chunk: chunk_index, printer)) {
4306 // Reset here as it may have been updated in just closed if statement.
4307 cached_has_word_index = -1;
4308 }
4309 }
4310
4311 // Fields inside a oneof don't use _has_bits_ so we count them in a separate
4312 // pass.
4313 for (auto oneof : OneOfRange(desc: descriptor_)) {
4314 format("switch ($1$_case()) {\n", oneof->name());
4315 format.Indent();
4316 for (auto field : FieldRange(desc: oneof)) {
4317 PrintFieldComment(format, field);
4318 format("case k$1$: {\n", UnderscoresToCamelCase(input: field->name(), cap_next_letter: true));
4319 format.Indent();
4320 if (!IsFieldStripped(field, options_)) {
4321 field_generators_.get(field).GenerateByteSize(printer);
4322 }
4323 format("break;\n");
4324 format.Outdent();
4325 format("}\n");
4326 }
4327 format(
4328 "case $1$_NOT_SET: {\n"
4329 " break;\n"
4330 "}\n",
4331 ToUpper(s: oneof->name()));
4332 format.Outdent();
4333 format("}\n");
4334 }
4335
4336 if (num_weak_fields_) {
4337 // TagSize + MessageSize
4338 format("total_size += $weak_field_map$.ByteSizeLong();\n");
4339 }
4340
4341 if (UseUnknownFieldSet(file: descriptor_->file(), options: options_)) {
4342 // We go out of our way to put the computation of the uncommon path of
4343 // unknown fields in tail position. This allows for better code generation
4344 // of this function for simple protos.
4345 format(
4346 "return MaybeComputeUnknownFieldsSize(total_size, &$cached_size$);\n");
4347 } else {
4348 format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
4349 format(" total_size += $unknown_fields$.size();\n");
4350 format("}\n");
4351
4352 // We update _cached_size_ even though this is a const method. Because
4353 // const methods might be called concurrently this needs to be atomic
4354 // operations or the program is undefined. In practice, since any
4355 // concurrent writes will be writing the exact same value, normal writes
4356 // will work on all common processors. We use a dedicated wrapper class to
4357 // abstract away the underlying atomic. This makes it easier on platforms
4358 // where even relaxed memory order might have perf impact to replace it with
4359 // ordinary loads and stores.
4360 format(
4361 "int cached_size = ::_pbi::ToCachedSize(total_size);\n"
4362 "SetCachedSize(cached_size);\n"
4363 "return total_size;\n");
4364 }
4365
4366 format.Outdent();
4367 format("}\n");
4368}
4369
4370void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
4371 if (HasSimpleBaseClass(desc: descriptor_, options: options_)) return;
4372 Formatter format(printer, variables_);
4373 format("bool $classname$::IsInitialized() const {\n");
4374 format.Indent();
4375
4376 if (descriptor_->extension_range_count() > 0) {
4377 format(
4378 "if (!$extensions$.IsInitialized()) {\n"
4379 " return false;\n"
4380 "}\n\n");
4381 }
4382
4383 if (num_required_fields_ > 0) {
4384 format(
4385 "if (_Internal::MissingRequiredFields($has_bits$))"
4386 " return false;\n");
4387 }
4388
4389 // Now check that all non-oneof embedded messages are initialized.
4390 for (auto field : optimized_order_) {
4391 field_generators_.get(field).GenerateIsInitialized(printer);
4392 }
4393 if (num_weak_fields_) {
4394 // For Weak fields.
4395 format("if (!$weak_field_map$.IsInitialized()) return false;\n");
4396 }
4397 // Go through the oneof fields, emitting a switch if any might have required
4398 // fields.
4399 for (auto oneof : OneOfRange(desc: descriptor_)) {
4400 bool has_required_fields = false;
4401 for (auto field : FieldRange(desc: oneof)) {
4402 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
4403 !ShouldIgnoreRequiredFieldCheck(field, options: options_) &&
4404 scc_analyzer_->HasRequiredFields(descriptor: field->message_type())) {
4405 has_required_fields = true;
4406 break;
4407 }
4408 }
4409
4410 if (!has_required_fields) {
4411 continue;
4412 }
4413
4414 format("switch ($1$_case()) {\n", oneof->name());
4415 format.Indent();
4416 for (auto field : FieldRange(desc: oneof)) {
4417 format("case k$1$: {\n", UnderscoresToCamelCase(input: field->name(), cap_next_letter: true));
4418 format.Indent();
4419 if (!IsFieldStripped(field, options_)) {
4420 field_generators_.get(field).GenerateIsInitialized(printer);
4421 }
4422 format("break;\n");
4423 format.Outdent();
4424 format("}\n");
4425 }
4426 format(
4427 "case $1$_NOT_SET: {\n"
4428 " break;\n"
4429 "}\n",
4430 ToUpper(s: oneof->name()));
4431 format.Outdent();
4432 format("}\n");
4433 }
4434
4435 format.Outdent();
4436 format(
4437 " return true;\n"
4438 "}\n");
4439}
4440
4441} // namespace cpp
4442} // namespace compiler
4443} // namespace protobuf
4444} // namespace google
4445
4446#include <google/protobuf/port_undef.inc>
4447