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