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 ¤t_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