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


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:05