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