• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: kenton@google.com (Kenton Varda)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 
12 #include <memory>
13 #include <string>
14 #include <vector>
15 
16 #include "absl/log/absl_check.h"
17 #include "absl/memory/memory.h"
18 #include "absl/strings/str_cat.h"
19 #include "google/protobuf/compiler/cpp/field.h"
20 #include "google/protobuf/compiler/cpp/field_generators/generators.h"
21 #include "google/protobuf/compiler/cpp/helpers.h"
22 #include "google/protobuf/compiler/cpp/options.h"
23 #include "google/protobuf/descriptor.h"
24 #include "google/protobuf/descriptor.pb.h"
25 #include "google/protobuf/io/printer.h"
26 
27 namespace google {
28 namespace protobuf {
29 namespace compiler {
30 namespace cpp {
31 namespace {
32 using ::google::protobuf::internal::cpp::HasHasbit;
33 using ::google::protobuf::io::AnnotationCollector;
34 using Sub = ::google::protobuf::io::Printer::Sub;
35 
Vars(const FieldDescriptor * field,const Options & opts)36 std::vector<Sub> Vars(const FieldDescriptor* field, const Options& opts) {
37   auto trivial_default =
38       absl::StrCat("::", ProtobufNamespace(opts),
39                    "::internal::GetEmptyStringAlreadyInited()");
40   auto lazy_var =
41       absl::StrCat(QualifiedClassName(field->containing_type(), opts),
42                    "::", MakeDefaultFieldName(field));
43 
44   bool empty_default = field->default_value_string().empty();
45   bool bytes = field->type() == FieldDescriptor::TYPE_BYTES;
46 
47   return {
48       {"kDefault", DefaultValue(opts, field)},
49       {"kDefaultLen", field->default_value_string().size()},
50       {"default_variable_name", MakeDefaultName(field)},
51       {"default_variable_field", MakeDefaultFieldName(field)},
52 
53       {"kDefaultStr",
54        !empty_default ? absl::StrCat(lazy_var, ".get()") : trivial_default},
55       {"kDefaultValue",
56        !empty_default ? "nullptr" : absl::StrCat("&", trivial_default)},
57 
58       {"lazy_var", lazy_var},
59       Sub{"lazy_args", !empty_default ? absl::StrCat(lazy_var, ",") : ""}
60           .WithSuffix(","),
61 
62       {"Set", bytes ? "SetBytes" : "Set"},
63   };
64 }
65 
66 class SingularString : public FieldGeneratorBase {
67  public:
SingularString(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)68   SingularString(const FieldDescriptor* field, const Options& opts,
69                  MessageSCCAnalyzer* scc)
70       : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
71   ~SingularString() override = default;
72 
MakeVars() const73   std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
74 
IsInlined() const75   bool IsInlined() const override { return is_inlined(); }
76 
NeedsArenaDestructor() const77   ArenaDtorNeeds NeedsArenaDestructor() const override {
78     return is_inlined() ? ArenaDtorNeeds::kOnDemand : ArenaDtorNeeds::kNone;
79   }
80 
GeneratePrivateMembers(io::Printer * p) const81   void GeneratePrivateMembers(io::Printer* p) const override {
82     // Skips the automatic destruction if inlined; rather calls it explicitly if
83     // allocating arena is null.
84     p->Emit({{"Str", is_inlined() ? "InlinedStringField" : "ArenaStringPtr"}},
85             R"cc(
86               $pbi$::$Str$ $name$_;
87             )cc");
88   }
89 
RequiresArena(GeneratorFunction function) const90   bool RequiresArena(GeneratorFunction function) const override {
91     switch (function) {
92       case GeneratorFunction::kMergeFrom:
93         return is_oneof();
94     }
95     return false;
96   }
97 
GenerateMergingCode(io::Printer * p) const98   void GenerateMergingCode(io::Printer* p) const override {
99     if (is_oneof()) {
100       p->Emit(R"cc(
101         if (oneof_needs_init) {
102           _this->$field_$.InitDefault();
103         }
104         _this->$field_$.Set(from._internal_$name$(), arena);
105       )cc");
106     } else {
107       p->Emit(R"cc(
108         _this->_internal_set_$name$(from._internal_$name$());
109       )cc");
110     }
111   }
112 
GenerateArenaDestructorCode(io::Printer * p) const113   void GenerateArenaDestructorCode(io::Printer* p) const override {
114     if (!is_inlined()) return;
115 
116     p->Emit(R"cc(
117       if (!_this->_internal_$name$_donated()) {
118         _this->$field_$.~InlinedStringField();
119       }
120     )cc");
121   }
122 
GenerateNonInlineAccessorDefinitions(io::Printer * p) const123   void GenerateNonInlineAccessorDefinitions(io::Printer* p) const override {
124     if (EmptyDefault()) return;
125     p->Emit(R"cc(
126       /*static*/ const ::_pbi::LazyString $Msg$::$default_variable_field${
127           {{$kDefault$, $kDefaultLen$}},
128           {nullptr},
129       };
130     )cc");
131   }
132 
GenerateByteSize(io::Printer * p) const133   void GenerateByteSize(io::Printer* p) const override {
134     p->Emit(R"cc(
135       total_size += $kTagBytes$ + $pbi$::WireFormatLite::$DeclaredType$Size(
136                                       this_._internal_$name$());
137     )cc");
138   }
139 
GenerateCopyAggregateInitializer(io::Printer * p) const140   void GenerateCopyAggregateInitializer(io::Printer* p) const override {
141     p->Emit(R"cc(
142       decltype($field_$){},
143     )cc");
144   }
145 
GenerateMemberConstexprConstructor(io::Printer * p) const146   void GenerateMemberConstexprConstructor(io::Printer* p) const override {
147     if (is_inlined()) {
148       p->Emit("$name$_(nullptr, false)");
149     } else {
150       p->Emit(
151           "$name$_(\n"
152           "    &$pbi$::fixed_address_empty_string,\n"
153           "    ::_pbi::ConstantInitialized())");
154     }
155   }
156 
GenerateMemberConstructor(io::Printer * p) const157   void GenerateMemberConstructor(io::Printer* p) const override {
158     if (is_inlined()) {
159       p->Emit("$name$_{}");
160     } else if (EmptyDefault()) {
161       p->Emit("$name$_(arena)");
162     } else {
163       p->Emit("$name$_(arena, $default_variable_field$)");
164     }
165   }
166 
GenerateMemberCopyConstructor(io::Printer * p) const167   void GenerateMemberCopyConstructor(io::Printer* p) const override {
168     if (is_inlined() || EmptyDefault()) {
169       p->Emit("$name$_(arena, from.$name$_)");
170     } else {
171       p->Emit("$name$_(arena, from.$name$_, $default_variable_name$)");
172     }
173   }
174 
GenerateOneofCopyConstruct(io::Printer * p) const175   void GenerateOneofCopyConstruct(io::Printer* p) const override {
176     if (is_inlined() || EmptyDefault()) {
177       p->Emit("new (&$field$) decltype($field$){arena, from.$field$};\n");
178     } else {
179       p->Emit(
180           "new (&$field$) decltype($field$){arena, from.$field$,"
181           " $default_variable_field$};\n");
182     }
183   }
184 
185   void GenerateStaticMembers(io::Printer* p) const override;
186   void GenerateAccessorDeclarations(io::Printer* p) const override;
187   void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
188   void GenerateClearingCode(io::Printer* p) const override;
189   void GenerateMessageClearingCode(io::Printer* p) const override;
190   void GenerateSwappingCode(io::Printer* p) const override;
191   void GenerateConstructorCode(io::Printer* p) const override;
192   void GenerateCopyConstructorCode(io::Printer* p) const override;
193   void GenerateDestructorCode(io::Printer* p) const override;
194   void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override;
195   void GenerateConstexprAggregateInitializer(io::Printer* p) const override;
196   void GenerateAggregateInitializer(io::Printer* p) const override;
197 
198  private:
EmptyDefault() const199   bool EmptyDefault() const { return field_->default_value_string().empty(); }
200   void ReleaseImpl(io::Printer* p) const;
201   void SetAllocatedImpl(io::Printer* p) const;
202 
203   const Options* opts_;
204 };
205 
GenerateStaticMembers(io::Printer * p) const206 void SingularString::GenerateStaticMembers(io::Printer* p) const {
207   if (!EmptyDefault()) {
208     p->Emit(R"cc(
209       static const $pbi$::LazyString $default_variable_name$;
210     )cc");
211   }
212   if (is_inlined()) {
213     // `_init_inline_xxx` is used for initializing default instances.
214     p->Emit(R"cc(
215       static std::true_type _init_inline_$name$_;
216     )cc");
217   }
218 }
219 
GenerateAccessorDeclarations(io::Printer * p) const220 void SingularString::GenerateAccessorDeclarations(io::Printer* p) const {
221   // If we're using SingularString for a field with a ctype, it's
222   // because that ctype isn't actually implemented.  In particular, this is
223   // true of ctype=CORD and ctype=STRING_PIECE in the open source release.
224   // We aren't releasing Cord because it has too many Google-specific
225   // dependencies and we aren't releasing StringPiece because it's hardly
226   // useful outside of Google and because it would get confusing to have
227   // multiple instances of the StringPiece class in different libraries (PCRE
228   // already includes it for their C++ bindings, which came from Google).
229   //
230   // In any case, we make all the accessors private while still actually
231   // using a string to represent the field internally.  This way, we can
232   // guarantee that if we do ever implement the ctype, it won't break any
233   // existing users who might be -- for whatever reason -- already using .proto
234   // files that applied the ctype.  The field can still be accessed via the
235   // reflection interface since the reflection interface is independent of
236   // the string's underlying representation.
237   bool unknown_ctype =
238       field_->options().ctype() != internal::cpp::EffectiveStringCType(field_);
239 
240   if (unknown_ctype) {
241     p->Emit(R"cc(
242       private:  // Hidden due to unknown ctype option.
243     )cc");
244   }
245 
246   auto vars = AnnotatedAccessors(field_, {"", "set_allocated_"});
247   vars.push_back(Sub{
248       "release_name",
249       SafeFunctionName(field_->containing_type(), field_, "release_"),
250   }
251                      .AnnotatedAs(field_));
252   auto v1 = p->WithVars(vars);
253   auto v2 = p->WithVars(
254       AnnotatedAccessors(field_, {"set_"}, AnnotationCollector::kSet));
255   auto v3 = p->WithVars(
256       AnnotatedAccessors(field_, {"mutable_"}, AnnotationCollector::kAlias));
257 
258   p->Emit(
259       {{"donated",
260         [&] {
261           if (!is_inlined()) return;
262           p->Emit(R"cc(
263             inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() const;
264           )cc");
265         }}},
266       R"cc(
267         $DEPRECATED$ const std::string& $name$() const;
268         //~ Using `Arg_ = const std::string&` will make the type of `arg`
269         //~ default to `const std::string&`, due to reference collapse. This is
270         //~ necessary because there are a handful of users that rely on this
271         //~ default.
272         template <typename Arg_ = const std::string&, typename... Args_>
273         $DEPRECATED$ void $set_name$(Arg_&& arg, Args_... args);
274         $DEPRECATED$ std::string* $mutable_name$();
275         $DEPRECATED$ PROTOBUF_NODISCARD std::string* $release_name$();
276         $DEPRECATED$ void $set_allocated_name$(std::string* value);
277 
278         private:
279         const std::string& _internal_$name$() const;
280         inline PROTOBUF_ALWAYS_INLINE void _internal_set_$name$(
281             const std::string& value);
282         std::string* _internal_mutable_$name$();
283         $donated$;
284 
285         public:
286       )cc");
287 }
288 
UpdateHasbitSet(io::Printer * p,bool is_oneof)289 void UpdateHasbitSet(io::Printer* p, bool is_oneof) {
290   if (!is_oneof) {
291     p->Emit(R"cc(
292       $set_hasbit$;
293     )cc");
294     return;
295   }
296 
297   p->Emit(R"cc(
298     if ($not_has_field$) {
299       clear_$oneof_name$();
300 
301       set_has_$name_internal$();
302       $field_$.InitDefault();
303     }
304   )cc");
305 }
306 
ArgsForSetter(io::Printer * p,bool inlined)307 void ArgsForSetter(io::Printer* p, bool inlined) {
308   if (!inlined) {
309     p->Emit("GetArena()");
310     return;
311   }
312   p->Emit(
313       "GetArena(), _internal_$name_internal$_donated(), "
314       "&$donating_states_word$, $mask_for_undonate$, this");
315 }
316 
ReleaseImpl(io::Printer * p) const317 void SingularString::ReleaseImpl(io::Printer* p) const {
318   if (is_oneof()) {
319     p->Emit(R"cc(
320       if ($not_has_field$) {
321         return nullptr;
322       }
323       clear_has_$oneof_name$();
324       return $field_$.Release();
325     )cc");
326     return;
327   }
328 
329   if (!HasHasbit(field_)) {
330     p->Emit(R"cc(
331       return $field_$.Release();
332     )cc");
333     return;
334   }
335 
336   if (is_inlined()) {
337     p->Emit(R"cc(
338       if (($has_hasbit$) == 0) {
339         return nullptr;
340       }
341       $clear_hasbit$;
342 
343       return $field_$.Release(GetArena(), _internal_$name_internal$_donated());
344     )cc");
345     return;
346   }
347 
348   p->Emit(R"cc(
349     if (($has_hasbit$) == 0) {
350       return nullptr;
351     }
352     $clear_hasbit$;
353   )cc");
354 
355   if (!EmptyDefault()) {
356     p->Emit(R"cc(
357       return $field_$.Release();
358     )cc");
359     return;
360   }
361 
362   p->Emit(R"cc(
363     auto* released = $field_$.Release();
364     if ($pbi$::DebugHardenForceCopyDefaultString()) {
365       $field_$.Set("", $set_args$);
366     }
367     return released;
368   )cc");
369 }
370 
SetAllocatedImpl(io::Printer * p) const371 void SingularString::SetAllocatedImpl(io::Printer* p) const {
372   if (is_oneof()) {
373     p->Emit(R"cc(
374       if (has_$oneof_name$()) {
375         clear_$oneof_name$();
376       }
377       if (value != nullptr) {
378         set_has_$name_internal$();
379         $field_$.InitAllocated(value, GetArena());
380       }
381     )cc");
382     return;
383   }
384 
385   if (HasHasbit(field_)) {
386     p->Emit(R"cc(
387       if (value != nullptr) {
388         $set_hasbit$
389       } else {
390         $clear_hasbit$
391       }
392     )cc");
393   }
394 
395   if (is_inlined()) {
396     // Currently, string fields with default value can't be inlined.
397     p->Emit(R"cc(
398       $field_$.SetAllocated(nullptr, value, $set_args$);
399     )cc");
400     return;
401   }
402 
403   p->Emit(R"cc(
404     $field_$.SetAllocated(value, $set_args$);
405   )cc");
406 
407   if (EmptyDefault()) {
408     p->Emit(R"cc(
409       if ($pbi$::DebugHardenForceCopyDefaultString() && $field_$.IsDefault()) {
410         $field_$.Set("", $set_args$);
411       }
412     )cc");
413   }
414 }
415 
GenerateInlineAccessorDefinitions(io::Printer * p) const416 void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const {
417   p->Emit(
418       {
419           {"if_IsDefault",
420            [&] {
421              if (EmptyDefault() || is_oneof()) return;
422              p->Emit(R"cc(
423                if ($field_$.IsDefault()) {
424                  return $default_variable_field$.get();
425                }
426              )cc");
427            }},
428           {"update_hasbit", [&] { UpdateHasbitSet(p, is_oneof()); }},
429           {"set_args", [&] { ArgsForSetter(p, is_inlined()); }},
430           {"check_hasbit",
431            [&] {
432              if (!is_oneof()) return;
433              p->Emit(R"cc(
434                if ($not_has_field$) {
435                  return $kDefaultStr$;
436                }
437              )cc");
438            }},
439           {"release_name",
440            SafeFunctionName(field_->containing_type(), field_, "release_")},
441           {"release_impl", [&] { ReleaseImpl(p); }},
442           {"set_allocated_impl", [&] { SetAllocatedImpl(p); }},
443       },
444       R"cc(
445         inline const std::string& $Msg$::$name$() const
446             ABSL_ATTRIBUTE_LIFETIME_BOUND {
447           $WeakDescriptorSelfPin$;
448           $annotate_get$;
449           // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
450           $if_IsDefault$;
451           return _internal_$name_internal$();
452         }
453         template <typename Arg_, typename... Args_>
454         inline PROTOBUF_ALWAYS_INLINE void $Msg$::set_$name$(Arg_&& arg,
455                                                              Args_... args) {
456           $WeakDescriptorSelfPin$;
457           $TsanDetectConcurrentMutation$;
458           $PrepareSplitMessageForWrite$;
459           $update_hasbit$;
460           $field_$.$Set$(static_cast<Arg_&&>(arg), args..., $set_args$);
461           $annotate_set$;
462           // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
463         }
464         inline std::string* $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
465           $WeakDescriptorSelfPin$;
466           $PrepareSplitMessageForWrite$;
467           std::string* _s = _internal_mutable_$name_internal$();
468           $annotate_mutable$;
469           // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$)
470           return _s;
471         }
472         inline const std::string& $Msg$::_internal_$name_internal$() const {
473           $TsanDetectConcurrentRead$;
474           $check_hasbit$;
475           return $field_$.Get();
476         }
477         inline void $Msg$::_internal_set_$name_internal$(const std::string& value) {
478           $TsanDetectConcurrentMutation$;
479           $update_hasbit$;
480           //~ Don't use $Set$ here; we always want the std::string variant
481           //~ regardless of whether this is a `bytes` field.
482           $field_$.Set(value, $set_args$);
483         }
484         inline std::string* $Msg$::_internal_mutable_$name_internal$() {
485           $TsanDetectConcurrentMutation$;
486           $update_hasbit$;
487           return $field_$.Mutable($lazy_args$, $set_args$);
488         }
489         inline std::string* $Msg$::$release_name$() {
490           $WeakDescriptorSelfPin$;
491           $TsanDetectConcurrentMutation$;
492           $annotate_release$;
493           $PrepareSplitMessageForWrite$;
494           // @@protoc_insertion_point(field_release:$pkg.Msg.field$)
495           $release_impl$;
496         }
497         inline void $Msg$::set_allocated_$name$(std::string* value) {
498           $WeakDescriptorSelfPin$;
499           $TsanDetectConcurrentMutation$;
500           $PrepareSplitMessageForWrite$;
501           $set_allocated_impl$;
502           $annotate_set$;
503           // @@protoc_insertion_point(field_set_allocated:$pkg.Msg.field$)
504         }
505       )cc");
506 
507   if (is_inlined()) {
508     p->Emit(R"cc(
509       inline bool $Msg$::_internal_$name_internal$_donated() const {
510         return $inlined_string_donated$;
511       }
512     )cc");
513   }
514 }
515 
GenerateClearingCode(io::Printer * p) const516 void SingularString::GenerateClearingCode(io::Printer* p) const {
517   if (is_oneof()) {
518     p->Emit(R"cc(
519       $field_$.Destroy();
520     )cc");
521     return;
522   }
523 
524   if (EmptyDefault()) {
525     p->Emit(R"cc(
526       $field_$.ClearToEmpty();
527     )cc");
528     return;
529   }
530 
531   ABSL_DCHECK(!is_inlined());
532   p->Emit(R"cc(
533     $field_$.ClearToDefault($lazy_var$, GetArena());
534   )cc");
535 }
536 
GenerateMessageClearingCode(io::Printer * p) const537 void SingularString::GenerateMessageClearingCode(io::Printer* p) const {
538   if (is_oneof()) {
539     p->Emit(R"cc(
540       $field_$.Destroy();
541     )cc");
542     return;
543   }
544 
545   // Two-dimension specialization here: supporting arenas, field presence, or
546   // not, and default value is the empty string or not. Complexity here ensures
547   // the minimal number of branches / amount of extraneous code at runtime
548   // (given that the below methods are inlined one-liners)!
549 
550   // If we have a hasbit, then the Clear() method of the protocol buffer
551   // will have checked that this field is set.  If so, we can avoid redundant
552   // checks against the default variable.
553 
554   if (is_inlined() && HasHasbit(field_)) {
555     // Calling mutable_$name$() gives us a string reference and sets the has bit
556     // for $name$ (in proto2).  We may get here when the string field is inlined
557     // but the string's contents have not been changed by the user, so we cannot
558     // make an assertion about the contents of the string and could never make
559     // an assertion about the string instance.
560     //
561     // For non-inlined strings, we distinguish from non-default by comparing
562     // instances, rather than contents.
563     p->Emit(R"cc(
564       $DCHK$(!$field_$.IsDefault());
565     )cc");
566   }
567 
568   if (!EmptyDefault()) {
569     // Clear to a non-empty default is more involved, as we try to use the
570     // Arena if one is present and may need to reallocate the string.
571     p->Emit(R"cc(
572       $field_$.ClearToDefault($lazy_var$, GetArena());
573     )cc");
574     return;
575   }
576 
577   p->Emit({{"Clear",
578             HasHasbit(field_) ? "ClearNonDefaultToEmpty" : "ClearToEmpty"}},
579           R"cc(
580             $field_$.$Clear$();
581           )cc");
582 }
583 
GenerateSwappingCode(io::Printer * p) const584 void SingularString::GenerateSwappingCode(io::Printer* p) const {
585   if (is_oneof()) {
586     // Don't print any swapping code. Swapping the union will swap this field.
587     return;
588   }
589 
590   if (!is_inlined()) {
591     p->Emit(R"cc(
592       ::_pbi::ArenaStringPtr::InternalSwap(&$field_$, &other->$field_$, arena);
593     )cc");
594     return;
595   }
596 
597   p->Emit(R"cc(
598     {
599       bool lhs_dtor_registered = ($inlined_string_donated_array$[0] & 1) == 0;
600       bool rhs_dtor_registered =
601           (other->$inlined_string_donated_array$[0] & 1) == 0;
602       ::_pbi::InlinedStringField::InternalSwap(
603           &$field_$, lhs_dtor_registered, this, &other->$field_$,
604           rhs_dtor_registered, other, arena);
605     }
606   )cc");
607 }
608 
GenerateConstructorCode(io::Printer * p) const609 void SingularString::GenerateConstructorCode(io::Printer* p) const {
610   if ((is_inlined() && EmptyDefault()) || is_oneof()) return;
611   ABSL_DCHECK(!is_inlined());
612 
613   p->Emit(R"cc(
614     $field_$.InitDefault();
615   )cc");
616 
617   if (IsString(field_) && EmptyDefault()) {
618     p->Emit(R"cc(
619       if ($pbi$::DebugHardenForceCopyDefaultString()) {
620         $field_$.Set("", GetArena());
621       }
622     )cc");
623   }
624 }
625 
GenerateCopyConstructorCode(io::Printer * p) const626 void SingularString::GenerateCopyConstructorCode(io::Printer* p) const {
627   GenerateConstructorCode(p);
628 
629   if (is_inlined()) {
630     p->Emit(R"cc(
631       new (&_this->$field_$)::_pbi::InlinedStringField;
632     )cc");
633   }
634 
635   p->Emit(
636       {{"hazzer",
637         [&] {
638           if (HasHasbit(field_)) {
639             p->Emit(R"cc((from.$has_hasbit$) != 0)cc");
640           } else {
641             p->Emit(R"cc(!from._internal_$name$().empty())cc");
642           }
643         }},
644        {"set_args",
645         [&] {
646           if (!is_inlined()) {
647             p->Emit("_this->GetArena()");
648           } else {
649             p->Emit(
650                 "_this->GetArena(), "
651                 "_this->_internal_$name$_donated(), "
652                 "&_this->$donating_states_word$, $mask_for_undonate$, _this");
653           }
654         }}},
655       R"cc(
656         if ($hazzer$) {
657           _this->$field_$.Set(from._internal_$name$(), $set_args$);
658         }
659       )cc");
660 }
661 
GenerateDestructorCode(io::Printer * p) const662 void SingularString::GenerateDestructorCode(io::Printer* p) const {
663   if (is_inlined()) {
664     ABSL_DCHECK(!should_split());
665     return;
666   }
667 
668   if (should_split()) {
669     p->Emit(R"cc(
670       $cached_split_ptr$->$name$_.Destroy();
671     )cc");
672     return;
673   }
674 
675   p->Emit(R"cc(
676     this_.$field_$.Destroy();
677   )cc");
678 }
679 
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const680 void SingularString::GenerateSerializeWithCachedSizesToArray(
681     io::Printer* p) const {
682   p->Emit({{"utf8_check",
683             [&] {
684               GenerateUtf8CheckCodeForString(p, field_, options_, false,
685                                              "_s.data(), "
686                                              "static_cast<int>(_s.length()),");
687             }}},
688           R"cc(
689             const std::string& _s = this_._internal_$name$();
690             $utf8_check$;
691             target = stream->Write$DeclaredType$MaybeAliased($number$, _s, target);
692           )cc");
693 }
694 
GenerateConstexprAggregateInitializer(io::Printer * p) const695 void SingularString::GenerateConstexprAggregateInitializer(
696     io::Printer* p) const {
697   if (is_inlined()) {
698     p->Emit(R"cc(
699       /*decltype($field_$)*/ {nullptr, false},
700     )cc");
701   } else {
702     p->Emit(R"cc(
703       /*decltype($field_$)*/ {
704           &::_pbi::fixed_address_empty_string,
705           ::_pbi::ConstantInitialized{},
706       },
707     )cc");
708   }
709 }
710 
GenerateAggregateInitializer(io::Printer * p) const711 void SingularString::GenerateAggregateInitializer(io::Printer* p) const {
712   if (should_split()) {
713     ABSL_CHECK(!is_inlined());
714     p->Emit(R"cc(
715       decltype(Impl_::Split::$name$_){},
716     )cc");
717   } else if (!is_inlined()) {
718     p->Emit(R"cc(
719       decltype($field_$){},
720     )cc");
721   } else {
722     p->Emit(R"cc(
723       decltype($field_$){arena},
724     )cc");
725   }
726 }
727 
728 class RepeatedString : public FieldGeneratorBase {
729  public:
RepeatedString(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)730   RepeatedString(const FieldDescriptor* field, const Options& opts,
731                  MessageSCCAnalyzer* scc)
732       : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
733   ~RepeatedString() override = default;
734 
MakeVars() const735   std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
736 
GeneratePrivateMembers(io::Printer * p) const737   void GeneratePrivateMembers(io::Printer* p) const override {
738     if (should_split()) {
739       p->Emit(R"cc(
740         $pbi$::RawPtr<$pb$::RepeatedPtrField<std::string>> $name$_;
741       )cc");
742     } else {
743       p->Emit(R"cc(
744         $pb$::RepeatedPtrField<std::string> $name$_;
745       )cc");
746     }
747   }
748 
GenerateClearingCode(io::Printer * p) const749   void GenerateClearingCode(io::Printer* p) const override {
750     if (should_split()) {
751       p->Emit("$field_$.ClearIfNotDefault();\n");
752     } else {
753       p->Emit("$field_$.Clear();\n");
754     }
755   }
756 
GenerateMergingCode(io::Printer * p) const757   void GenerateMergingCode(io::Printer* p) const override {
758     // TODO: experiment with simplifying this to be
759     // `if (!from.empty()) { body(); }` for both split and non-split cases.
760     auto body = [&] {
761       p->Emit(R"cc(
762         _this->_internal_mutable_$name$()->MergeFrom(from._internal_$name$());
763       )cc");
764     };
765     if (!should_split()) {
766       body();
767     } else {
768       p->Emit({{"body", body}}, R"cc(
769         if (!from.$field_$.IsDefault()) {
770           $body$;
771         }
772       )cc");
773     }
774   }
775 
GenerateSwappingCode(io::Printer * p) const776   void GenerateSwappingCode(io::Printer* p) const override {
777     ABSL_CHECK(!should_split());
778     p->Emit(R"cc(
779       $field_$.InternalSwap(&other->$field_$);
780     )cc");
781   }
782 
GenerateDestructorCode(io::Printer * p) const783   void GenerateDestructorCode(io::Printer* p) const override {
784     if (should_split()) {
785       p->Emit(R"cc(
786         this_.$field_$.DeleteIfNotDefault();
787       )cc");
788     }
789   }
790 
GenerateConstructorCode(io::Printer * p) const791   void GenerateConstructorCode(io::Printer* p) const override {}
792 
GenerateCopyConstructorCode(io::Printer * p) const793   void GenerateCopyConstructorCode(io::Printer* p) const override {
794     if (should_split()) {
795       p->Emit(R"cc(
796         if (!from._internal_$name$().empty()) {
797           _internal_mutable_$name$()->MergeFrom(from._internal_$name$());
798         }
799       )cc");
800     }
801   }
802 
GenerateByteSize(io::Printer * p) const803   void GenerateByteSize(io::Printer* p) const override {
804     p->Emit(R"cc(
805       total_size +=
806           $kTagBytes$ * $pbi$::FromIntSize(this_._internal_$name$().size());
807       for (int i = 0, n = this_._internal_$name$().size(); i < n; ++i) {
808         total_size += $pbi$::WireFormatLite::$DeclaredType$Size(
809             this_._internal_$name$().Get(i));
810       }
811     )cc");
812   }
813 
814   void GenerateAccessorDeclarations(io::Printer* p) const override;
815   void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
816   void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override;
817 
818  private:
819   const Options* opts_;
820 };
821 
GenerateAccessorDeclarations(io::Printer * p) const822 void RepeatedString::GenerateAccessorDeclarations(io::Printer* p) const {
823   bool unknown_ctype =
824       field_->options().ctype() != internal::cpp::EffectiveStringCType(field_);
825 
826   if (unknown_ctype) {
827     p->Emit(R"cc(
828       private:  // Hidden due to unknown ctype option.
829     )cc");
830   }
831 
832   auto v1 = p->WithVars(AnnotatedAccessors(field_, {"", "_internal_"}));
833   auto v2 = p->WithVars(
834       AnnotatedAccessors(field_, {"set_", "add_"}, AnnotationCollector::kSet));
835   auto v3 = p->WithVars(
836       AnnotatedAccessors(field_, {"mutable_"}, AnnotationCollector::kAlias));
837 
838   p->Emit(R"cc(
839     $DEPRECATED$ const std::string& $name$(int index) const;
840     $DEPRECATED$ std::string* $mutable_name$(int index);
841     template <typename Arg_ = const std::string&, typename... Args_>
842     $DEPRECATED$ void set_$name$(int index, Arg_&& value, Args_... args);
843     $DEPRECATED$ std::string* $add_name$();
844     template <typename Arg_ = const std::string&, typename... Args_>
845     $DEPRECATED$ void $add_name$(Arg_&& value, Args_... args);
846     $DEPRECATED$ const $pb$::RepeatedPtrField<std::string>& $name$() const;
847     $DEPRECATED$ $pb$::RepeatedPtrField<std::string>* $mutable_name$();
848 
849     private:
850     const $pb$::RepeatedPtrField<std::string>& _internal_$name$() const;
851     $pb$::RepeatedPtrField<std::string>* _internal_mutable_$name$();
852 
853     public:
854   )cc");
855 }
856 
GenerateInlineAccessorDefinitions(io::Printer * p) const857 void RepeatedString::GenerateInlineAccessorDefinitions(io::Printer* p) const {
858   bool bytes = field_->type() == FieldDescriptor::TYPE_BYTES;
859   p->Emit(
860       {
861           {"Get", opts_->safe_boundary_check ? "InternalCheckedGet" : "Get"},
862           {"GetExtraArg",
863            [&] {
864              p->Emit(opts_->safe_boundary_check
865                          ? ", $pbi$::GetEmptyStringAlreadyInited()"
866                          : "");
867            }},
868           {"bytes_tag",
869            [&] {
870              if (bytes) {
871                p->Emit(", $pbi$::BytesTag{}");
872              }
873            }},
874       },
875       R"cc(
876         inline std::string* $Msg$::add_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
877           $WeakDescriptorSelfPin$;
878           $TsanDetectConcurrentMutation$;
879           std::string* _s = _internal_mutable_$name_internal$()->Add();
880           $annotate_add_mutable$;
881           // @@protoc_insertion_point(field_add_mutable:$pkg.Msg.field$)
882           return _s;
883         }
884         inline const std::string& $Msg$::$name$(int index) const
885             ABSL_ATTRIBUTE_LIFETIME_BOUND {
886           $WeakDescriptorSelfPin$;
887           $annotate_get$;
888           // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
889           return _internal_$name_internal$().$Get$(index$GetExtraArg$);
890         }
891         inline std::string* $Msg$::mutable_$name$(int index)
892             ABSL_ATTRIBUTE_LIFETIME_BOUND {
893           $WeakDescriptorSelfPin$;
894           $annotate_mutable$;
895           // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$)
896           return _internal_mutable_$name_internal$()->Mutable(index);
897         }
898         template <typename Arg_, typename... Args_>
899         inline void $Msg$::set_$name$(int index, Arg_&& value, Args_... args) {
900           $WeakDescriptorSelfPin$;
901           $pbi$::AssignToString(
902               *_internal_mutable_$name_internal$()->Mutable(index),
903               std::forward<Arg_>(value), args... $bytes_tag$);
904           $annotate_set$;
905           // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
906         }
907         template <typename Arg_, typename... Args_>
908         inline void $Msg$::add_$name$(Arg_&& value, Args_... args) {
909           $WeakDescriptorSelfPin$;
910           $TsanDetectConcurrentMutation$;
911           $pbi$::AddToRepeatedPtrField(*_internal_mutable_$name_internal$(),
912                                        std::forward<Arg_>(value),
913                                        args... $bytes_tag$);
914           $annotate_add$;
915           // @@protoc_insertion_point(field_add:$pkg.Msg.field$)
916         }
917         inline const ::$proto_ns$::RepeatedPtrField<std::string>&
918         $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
919           $WeakDescriptorSelfPin$;
920           $annotate_list$;
921           // @@protoc_insertion_point(field_list:$pkg.Msg.field$)
922           return _internal_$name_internal$();
923         }
924         inline ::$proto_ns$::RepeatedPtrField<std::string>*
925         $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
926           $WeakDescriptorSelfPin$;
927           $annotate_mutable_list$;
928           // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$)
929           $TsanDetectConcurrentMutation$;
930           return _internal_mutable_$name_internal$();
931         }
932       )cc");
933   if (should_split()) {
934     p->Emit(R"cc(
935       inline const $pb$::RepeatedPtrField<std::string>&
936       $Msg$::_internal_$name_internal$() const {
937         $TsanDetectConcurrentRead$;
938         return *$field_$;
939       }
940       inline $pb$::RepeatedPtrField<std::string>*
941       $Msg$::_internal_mutable_$name_internal$() {
942         $TsanDetectConcurrentRead$;
943         $PrepareSplitMessageForWrite$;
944         if ($field_$.IsDefault()) {
945           $field_$.Set($pb$::Arena::Create<$pb$::RepeatedPtrField<std::string>>(
946               GetArena()));
947         }
948         return $field_$.Get();
949       }
950     )cc");
951   } else {
952     p->Emit(R"cc(
953       inline const ::$proto_ns$::RepeatedPtrField<std::string>&
954       $Msg$::_internal_$name_internal$() const {
955         $TsanDetectConcurrentRead$;
956         return $field_$;
957       }
958       inline ::$proto_ns$::RepeatedPtrField<std::string>*
959       $Msg$::_internal_mutable_$name_internal$() {
960         $TsanDetectConcurrentRead$;
961         return &$field_$;
962       }
963     )cc");
964   }
965 }
966 
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const967 void RepeatedString::GenerateSerializeWithCachedSizesToArray(
968     io::Printer* p) const {
969   p->Emit({{"utf8_check",
970             [&] {
971               GenerateUtf8CheckCodeForString(
972                   p, field_, options_, false,
973                   "s.data(), static_cast<int>(s.length()),");
974             }}},
975           R"cc(
976             for (int i = 0, n = this_._internal_$name$_size(); i < n; ++i) {
977               const auto& s = this_._internal_$name$().Get(i);
978               $utf8_check$;
979               target = stream->Write$DeclaredType$($number$, s, target);
980             }
981           )cc");
982 }
983 }  // namespace
984 
MakeSinguarStringGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)985 std::unique_ptr<FieldGeneratorBase> MakeSinguarStringGenerator(
986     const FieldDescriptor* desc, const Options& options,
987     MessageSCCAnalyzer* scc) {
988   return absl::make_unique<SingularString>(desc, options, scc);
989 }
990 
MakeRepeatedStringGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)991 std::unique_ptr<FieldGeneratorBase> MakeRepeatedStringGenerator(
992     const FieldDescriptor* desc, const Options& options,
993     MessageSCCAnalyzer* scc) {
994   return absl::make_unique<RepeatedString>(desc, options, scc);
995 }
996 
997 }  // namespace cpp
998 }  // namespace compiler
999 }  // namespace protobuf
1000 }  // namespace google
1001