• 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/helpers.h"
21 #include "google/protobuf/compiler/cpp/options.h"
22 #include "google/protobuf/descriptor.h"
23 #include "google/protobuf/descriptor.pb.h"
24 #include "google/protobuf/io/printer.h"
25 
26 namespace google {
27 namespace protobuf {
28 namespace compiler {
29 namespace cpp {
30 namespace {
31 using ::google::protobuf::internal::cpp::HasHasbit;
32 using ::google::protobuf::io::AnnotationCollector;
33 using Sub = ::google::protobuf::io::Printer::Sub;
34 
Vars(const FieldDescriptor * field,const Options & opts)35 std::vector<Sub> Vars(const FieldDescriptor* field, const Options& opts) {
36   auto trivial_default =
37       absl::StrCat("::", ProtobufNamespace(opts),
38                    "::internal::GetEmptyStringAlreadyInited()");
39   auto lazy_var =
40       absl::StrCat(QualifiedClassName(field->containing_type(), opts),
41                    "::", MakeDefaultFieldName(field));
42 
43   bool empty_default = field->default_value_string().empty();
44   bool bytes = field->type() == FieldDescriptor::TYPE_BYTES;
45 
46   return {
47       {"kDefault", DefaultValue(opts, field)},
48       {"kDefaultLen", field->default_value_string().size()},
49       {"default_variable_name", MakeDefaultName(field)},
50       {"default_variable_field", MakeDefaultFieldName(field)},
51 
52       {"kDefaultStr",
53        !empty_default ? absl::StrCat(lazy_var, ".get()") : trivial_default},
54       {"kDefaultValue",
55        !empty_default ? "nullptr" : absl::StrCat("&", trivial_default)},
56 
57       {"lazy_var", lazy_var},
58       Sub{"lazy_args", !empty_default ? absl::StrCat(lazy_var, ",") : ""}
59           .WithSuffix(","),
60 
61       {"byte", bytes ? "void" : "char"},
62       {"Set", bytes ? "SetBytes" : "Set"},
63   };
64 }
65 
66 class SingularStringView : public FieldGeneratorBase {
67  public:
SingularStringView(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)68   SingularStringView(const FieldDescriptor* field, const Options& opts,
69                      MessageSCCAnalyzer* scc)
70       : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
71   ~SingularStringView() 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 
201   const Options* opts_;
202 };
203 
GenerateStaticMembers(io::Printer * p) const204 void SingularStringView::GenerateStaticMembers(io::Printer* p) const {
205   if (!EmptyDefault()) {
206     p->Emit(R"cc(
207       static const $pbi$::LazyString $default_variable_name$;
208     )cc");
209   }
210   if (is_inlined()) {
211     // `_init_inline_xxx` is used for initializing default instances.
212     p->Emit(R"cc(
213       static std::true_type _init_inline_$name$_;
214     )cc");
215   }
216 }
217 
GenerateAccessorDeclarations(io::Printer * p) const218 void SingularStringView::GenerateAccessorDeclarations(io::Printer* p) const {
219   auto v1 = p->WithVars(AnnotatedAccessors(field_, {""}));
220   auto v2 = p->WithVars(
221       AnnotatedAccessors(field_, {"set_"}, AnnotationCollector::kSet));
222 
223   p->Emit(
224       {{"donated",
225         [&] {
226           if (!is_inlined()) return;
227           p->Emit(R"cc(
228             inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() const;
229           )cc");
230         }}},
231       R"cc(
232         $DEPRECATED$ absl::string_view $name$() const;
233         template <typename Arg_ = std::string&&>
234         $DEPRECATED$ void $set_name$(Arg_&& arg);
235 
236         private:
237         const std::string& _internal_$name$() const;
238         inline PROTOBUF_ALWAYS_INLINE void _internal_set_$name$(
239             absl::string_view value);
240         $donated$;
241 
242         public:
243       )cc");
244 }
245 
UpdateHasbitSet(io::Printer * p,bool is_oneof)246 void UpdateHasbitSet(io::Printer* p, bool is_oneof) {
247   if (!is_oneof) {
248     p->Emit(R"cc(
249       $set_hasbit$;
250     )cc");
251     return;
252   }
253 
254   p->Emit(R"cc(
255     if ($not_has_field$) {
256       clear_$oneof_name$();
257 
258       set_has_$name_internal$();
259       $field_$.InitDefault();
260     }
261   )cc");
262 }
263 
ArgsForSetter(io::Printer * p,bool inlined)264 void ArgsForSetter(io::Printer* p, bool inlined) {
265   if (!inlined) {
266     p->Emit("GetArena()");
267     return;
268   }
269   p->Emit(
270       "GetArena(), _internal_$name_internal$_donated(), "
271       "&$donating_states_word$, $mask_for_undonate$, this");
272 }
273 
GenerateInlineAccessorDefinitions(io::Printer * p) const274 void SingularStringView::GenerateInlineAccessorDefinitions(
275     io::Printer* p) const {
276   p->Emit(
277       {
278           {"if_IsDefault",
279            [&] {
280              if (EmptyDefault() || is_oneof()) return;
281              p->Emit(R"cc(
282                if ($field_$.IsDefault()) {
283                  return $default_variable_field$.get();
284                }
285              )cc");
286            }},
287           {"update_hasbit", [&] { UpdateHasbitSet(p, is_oneof()); }},
288           {"set_args", [&] { ArgsForSetter(p, is_inlined()); }},
289           {"check_hasbit",
290            [&] {
291              if (!is_oneof()) return;
292              p->Emit(R"cc(
293                if ($not_has_field$) {
294                  return $kDefaultStr$;
295                }
296              )cc");
297            }},
298       },
299       R"cc(
300         inline absl::string_view $Msg$::$name$() const
301             ABSL_ATTRIBUTE_LIFETIME_BOUND {
302           $WeakDescriptorSelfPin$;
303           $annotate_get$;
304           // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
305           $if_IsDefault$;
306           return _internal_$name_internal$();
307         }
308         template <typename Arg_>
309         inline PROTOBUF_ALWAYS_INLINE void $Msg$::set_$name$(Arg_&& arg) {
310           $WeakDescriptorSelfPin$;
311           $TsanDetectConcurrentMutation$;
312           $PrepareSplitMessageForWrite$;
313           $update_hasbit$;
314           $field_$.$Set$(static_cast<Arg_&&>(arg), $set_args$);
315           $annotate_set$;
316           // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
317         }
318         inline const std::string& $Msg$::_internal_$name_internal$() const {
319           $TsanDetectConcurrentRead$;
320           $check_hasbit$;
321           return $field_$.Get();
322         }
323         inline void $Msg$::_internal_set_$name_internal$(absl::string_view value) {
324           $TsanDetectConcurrentMutation$;
325           $update_hasbit$;
326           //~ Don't use $Set$ here; we always want the std::string variant
327           //~ regardless of whether this is a `bytes` field.
328           $field_$.Set(value, $set_args$);
329         }
330       )cc");
331 
332   if (is_inlined()) {
333     p->Emit(R"cc(
334       inline bool $Msg$::_internal_$name_internal$_donated() const {
335         return $inlined_string_donated$;
336       }
337     )cc");
338   }
339 }
340 
GenerateClearingCode(io::Printer * p) const341 void SingularStringView::GenerateClearingCode(io::Printer* p) const {
342   if (is_oneof()) {
343     p->Emit(R"cc(
344       $field_$.Destroy();
345     )cc");
346     return;
347   }
348 
349   if (EmptyDefault()) {
350     p->Emit(R"cc(
351       $field_$.ClearToEmpty();
352     )cc");
353     return;
354   }
355 
356   ABSL_DCHECK(!is_inlined());
357   p->Emit(R"cc(
358     $field_$.ClearToDefault($lazy_var$, GetArena());
359   )cc");
360 }
361 
GenerateMessageClearingCode(io::Printer * p) const362 void SingularStringView::GenerateMessageClearingCode(io::Printer* p) const {
363   if (is_oneof()) {
364     p->Emit(R"cc(
365       $field_$.Destroy();
366     )cc");
367     return;
368   }
369 
370   // Two-dimension specialization here: supporting arenas, field presence, or
371   // not, and default value is the empty string or not. Complexity here ensures
372   // the minimal number of branches / amount of extraneous code at runtime
373   // (given that the below methods are inlined one-liners)!
374 
375   // If we have a hasbit, then the Clear() method of the protocol buffer
376   // will have checked that this field is set.  If so, we can avoid redundant
377   // checks against the default variable.
378 
379   if (is_inlined() && HasHasbit(field_)) {
380     p->Emit(R"cc(
381       $DCHK$(!$field_$.IsDefault());
382     )cc");
383   }
384 
385   if (!EmptyDefault()) {
386     // Clear to a non-empty default is more involved, as we try to use the
387     // Arena if one is present and may need to reallocate the string.
388     p->Emit(R"cc(
389       $field_$.ClearToDefault($lazy_var$, GetArena());
390     )cc");
391     return;
392   }
393 
394   p->Emit({{"Clear",
395             HasHasbit(field_) ? "ClearNonDefaultToEmpty" : "ClearToEmpty"}},
396           R"cc(
397             $field_$.$Clear$();
398           )cc");
399 }
400 
GenerateSwappingCode(io::Printer * p) const401 void SingularStringView::GenerateSwappingCode(io::Printer* p) const {
402   if (is_oneof()) {
403     // Don't print any swapping code. Swapping the union will swap this field.
404     return;
405   }
406 
407   if (!is_inlined()) {
408     p->Emit(R"cc(
409       ::_pbi::ArenaStringPtr::InternalSwap(&$field_$, &other->$field_$, arena);
410     )cc");
411     return;
412   }
413 
414   p->Emit(R"cc(
415     {
416       bool lhs_dtor_registered = ($inlined_string_donated_array$[0] & 1) == 0;
417       bool rhs_dtor_registered =
418           (other->$inlined_string_donated_array$[0] & 1) == 0;
419       ::_pbi::InlinedStringField::InternalSwap(
420           &$field_$, lhs_dtor_registered, this, &other->$field_$,
421           rhs_dtor_registered, other, arena);
422     }
423   )cc");
424 }
425 
GenerateConstructorCode(io::Printer * p) const426 void SingularStringView::GenerateConstructorCode(io::Printer* p) const {
427   if ((is_inlined() && EmptyDefault()) || is_oneof()) return;
428   ABSL_DCHECK(!is_inlined());
429 
430   p->Emit(R"cc(
431     $field_$.InitDefault();
432   )cc");
433 
434   if (EmptyDefault()) {
435     p->Emit(R"cc(
436       if ($pbi$::DebugHardenForceCopyDefaultString()) {
437         $field_$.Set("", GetArena());
438       }
439     )cc");
440   }
441 }
442 
GenerateCopyConstructorCode(io::Printer * p) const443 void SingularStringView::GenerateCopyConstructorCode(io::Printer* p) const {
444   GenerateConstructorCode(p);
445 
446   if (is_inlined()) {
447     p->Emit(R"cc(
448       new (&_this->$field_$)::_pbi::InlinedStringField;
449     )cc");
450   }
451 
452   p->Emit(
453       {{"hazzer",
454         [&] {
455           if (HasHasbit(field_)) {
456             p->Emit(R"cc((from.$has_hasbit$) != 0)cc");
457           } else {
458             p->Emit(R"cc(!from._internal_$name$().empty())cc");
459           }
460         }},
461        {"set_args",
462         [&] {
463           if (!is_inlined()) {
464             p->Emit("_this->GetArena()");
465           } else {
466             p->Emit(
467                 "_this->GetArena(), "
468                 "_this->_internal_$name$_donated(), "
469                 "&_this->$donating_states_word$, $mask_for_undonate$, _this");
470           }
471         }}},
472       R"cc(
473         if ($hazzer$) {
474           _this->$field_$.Set(from._internal_$name$(), $set_args$);
475         }
476       )cc");
477 }
478 
GenerateDestructorCode(io::Printer * p) const479 void SingularStringView::GenerateDestructorCode(io::Printer* p) const {
480   if (is_inlined()) {
481     ABSL_DCHECK(!should_split());
482     return;
483   }
484 
485   if (should_split()) {
486     p->Emit(R"cc(
487       $cached_split_ptr$->$name$_.Destroy();
488     )cc");
489     return;
490   }
491 
492   p->Emit(R"cc(
493     this_.$field_$.Destroy();
494   )cc");
495 }
496 
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const497 void SingularStringView::GenerateSerializeWithCachedSizesToArray(
498     io::Printer* p) const {
499   p->Emit({{"utf8_check",
500             [&] {
501               GenerateUtf8CheckCodeForString(p, field_, options_, false,
502                                              "_s.data(), "
503                                              "static_cast<int>(_s.length()),");
504             }}},
505           R"cc(
506             const std::string& _s = this_._internal_$name$();
507             $utf8_check$;
508             target = stream->Write$DeclaredType$MaybeAliased($number$, _s, target);
509           )cc");
510 }
511 
GenerateConstexprAggregateInitializer(io::Printer * p) const512 void SingularStringView::GenerateConstexprAggregateInitializer(
513     io::Printer* p) const {
514   if (is_inlined()) {
515     p->Emit(R"cc(
516       /*decltype($field_$)*/ {nullptr, false},
517     )cc");
518   } else {
519     p->Emit(R"cc(
520       /*decltype($field_$)*/ {
521           &::_pbi::fixed_address_empty_string,
522           ::_pbi::ConstantInitialized{},
523       },
524     )cc");
525   }
526 }
527 
GenerateAggregateInitializer(io::Printer * p) const528 void SingularStringView::GenerateAggregateInitializer(io::Printer* p) const {
529   if (should_split()) {
530     ABSL_CHECK(!is_inlined());
531     p->Emit(R"cc(
532       decltype(Impl_::Split::$name$_){},
533     )cc");
534   } else if (!is_inlined()) {
535     p->Emit(R"cc(
536       decltype($field_$){},
537     )cc");
538   } else {
539     p->Emit(R"cc(
540       decltype($field_$){arena},
541     )cc");
542   }
543 }
544 
545 class RepeatedStringView : public FieldGeneratorBase {
546  public:
RepeatedStringView(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)547   RepeatedStringView(const FieldDescriptor* field, const Options& opts,
548                      MessageSCCAnalyzer* scc)
549       : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
550   ~RepeatedStringView() override = default;
551 
MakeVars() const552   std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
553 
GeneratePrivateMembers(io::Printer * p) const554   void GeneratePrivateMembers(io::Printer* p) const override {
555     if (should_split()) {
556       p->Emit(R"cc(
557         $pbi$::RawPtr<$pb$::RepeatedPtrField<std::string>> $name$_;
558       )cc");
559     } else {
560       p->Emit(R"cc(
561         $pb$::RepeatedPtrField<std::string> $name$_;
562       )cc");
563     }
564   }
565 
GenerateClearingCode(io::Printer * p) const566   void GenerateClearingCode(io::Printer* p) const override {
567     if (should_split()) {
568       p->Emit("$field_$.ClearIfNotDefault();\n");
569     } else {
570       p->Emit("$field_$.Clear();\n");
571     }
572   }
573 
GenerateMergingCode(io::Printer * p) const574   void GenerateMergingCode(io::Printer* p) const override {
575     // TODO: experiment with simplifying this to be
576     // `if (!from.empty()) { body(); }` for both split and non-split cases.
577     auto body = [&] {
578       p->Emit(R"cc(
579         _this->_internal_mutable_$name$()->MergeFrom(from._internal_$name$());
580       )cc");
581     };
582     if (!should_split()) {
583       body();
584     } else {
585       p->Emit({{"body", body}}, R"cc(
586         if (!from.$field_$.IsDefault()) {
587           $body$;
588         }
589       )cc");
590     }
591   }
592 
GenerateSwappingCode(io::Printer * p) const593   void GenerateSwappingCode(io::Printer* p) const override {
594     ABSL_CHECK(!should_split());
595     p->Emit(R"cc(
596       $field_$.InternalSwap(&other->$field_$);
597     )cc");
598   }
599 
GenerateDestructorCode(io::Printer * p) const600   void GenerateDestructorCode(io::Printer* p) const override {
601     if (should_split()) {
602       p->Emit(R"cc(
603         this_.$field_$.DeleteIfNotDefault();
604       )cc");
605     }
606   }
607 
GenerateConstructorCode(io::Printer * p) const608   void GenerateConstructorCode(io::Printer* p) const override {}
609 
GenerateCopyConstructorCode(io::Printer * p) const610   void GenerateCopyConstructorCode(io::Printer* p) const override {
611     if (should_split()) {
612       p->Emit(R"cc(
613         if (!from._internal_$name$().empty()) {
614           _internal_mutable_$name$()->MergeFrom(from._internal_$name$());
615         }
616       )cc");
617     }
618   }
619 
GenerateByteSize(io::Printer * p) const620   void GenerateByteSize(io::Printer* p) const override {
621     p->Emit(R"cc(
622       total_size +=
623           $kTagBytes$ * $pbi$::FromIntSize(this_._internal_$name$().size());
624       for (int i = 0, n = this_._internal_$name$().size(); i < n; ++i) {
625         total_size += $pbi$::WireFormatLite::$DeclaredType$Size(
626             this_._internal_$name$().Get(i));
627       }
628     )cc");
629   }
630 
631   void GenerateAccessorDeclarations(io::Printer* p) const override;
632   void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
633   void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override;
634 
635  private:
636   const Options* opts_;
637 };
638 
GenerateAccessorDeclarations(io::Printer * p) const639 void RepeatedStringView::GenerateAccessorDeclarations(io::Printer* p) const {
640   bool unknown_ctype =
641       field_->options().ctype() != internal::cpp::EffectiveStringCType(field_);
642 
643   if (unknown_ctype) {
644     p->Emit(R"cc(
645       private:  // Hidden due to unknown ctype option.
646     )cc");
647   }
648 
649   auto v1 = p->WithVars(AnnotatedAccessors(field_, {"", "_internal_"}));
650   auto v2 = p->WithVars(
651       AnnotatedAccessors(field_, {"set_", "add_"}, AnnotationCollector::kSet));
652   auto v3 = p->WithVars(
653       AnnotatedAccessors(field_, {"mutable_"}, AnnotationCollector::kAlias));
654 
655   p->Emit(R"cc(
656     $DEPRECATED$ absl::string_view $name$(int index) const;
657     $DEPRECATED$ void $set_name$(int index, const std::string& value);
658     $DEPRECATED$ void $set_name$(int index, std::string&& value);
659     $DEPRECATED$ void $set_name$(int index, const char* value);
660     $DEPRECATED$ void $set_name$(int index, absl::string_view value);
661     $DEPRECATED$ void $add_name$(const std::string& value);
662     $DEPRECATED$ void $add_name$(std::string&& value);
663     $DEPRECATED$ void $add_name$(const char* value);
664     $DEPRECATED$ void $add_name$(absl::string_view value);
665     $DEPRECATED$ const $pb$::RepeatedPtrField<std::string>& $name$() const;
666     $DEPRECATED$ $pb$::RepeatedPtrField<std::string>* $mutable_name$();
667 
668     private:
669     const $pb$::RepeatedPtrField<std::string>& _internal_$name$() const;
670     $pb$::RepeatedPtrField<std::string>* _internal_mutable_$name$();
671 
672     public:
673   )cc");
674 }
675 
GenerateInlineAccessorDefinitions(io::Printer * p) const676 void RepeatedStringView::GenerateInlineAccessorDefinitions(
677     io::Printer* p) const {
678   p->Emit({{"Get", opts_->safe_boundary_check ? "InternalCheckedGet" : "Get"},
679            {"GetExtraArg",
680             [&] {
681               p->Emit(opts_->safe_boundary_check
682                           ? ", $pbi$::GetEmptyStringAlreadyInited()"
683                           : "");
684             }}},
685           R"cc(
686             inline absl::string_view $Msg$::$name$(int index) const
687                 ABSL_ATTRIBUTE_LIFETIME_BOUND {
688               $WeakDescriptorSelfPin$;
689               $annotate_get$;
690               // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
691               return _internal_$name_internal$().$Get$(index$GetExtraArg$);
692             }
693             inline void $Msg$::set_$name$(int index, const std::string& value) {
694               $WeakDescriptorSelfPin$;
695               _internal_mutable_$name_internal$()->Mutable(index)->assign(value);
696               $annotate_set$;
697               // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
698             }
699             inline void $Msg$::set_$name$(int index, std::string&& value) {
700               $WeakDescriptorSelfPin$;
701               _internal_mutable_$name_internal$()->Mutable(index)->assign(std::move(value));
702               $annotate_set$;
703               // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
704             }
705             inline void $Msg$::set_$name$(int index, const char* value) {
706               $WeakDescriptorSelfPin$;
707               $DCHK$(value != nullptr);
708               _internal_mutable_$name_internal$()->Mutable(index)->assign(value);
709               $annotate_set$;
710               // @@protoc_insertion_point(field_set_char:$pkg.Msg.field$)
711             }
712             inline void $Msg$::set_$name$(int index, absl::string_view value) {
713               $WeakDescriptorSelfPin$;
714               _internal_mutable_$name_internal$()->Mutable(index)->assign(
715                   value.data(), value.size());
716               $annotate_set$;
717               // @@protoc_insertion_point(field_set_string_piece:$pkg.Msg.field$)
718             }
719             inline void $Msg$::add_$name$(const std::string& value) {
720               $WeakDescriptorSelfPin$;
721               $TsanDetectConcurrentMutation$;
722               _internal_mutable_$name_internal$()->Add()->assign(value);
723               $annotate_add$;
724               // @@protoc_insertion_point(field_add:$pkg.Msg.field$)
725             }
726             inline void $Msg$::add_$name$(std::string&& value) {
727               $WeakDescriptorSelfPin$;
728               $TsanDetectConcurrentMutation$;
729               _internal_mutable_$name_internal$()->Add(std::move(value));
730               $annotate_add$;
731               // @@protoc_insertion_point(field_add:$pkg.Msg.field$)
732             }
733             inline void $Msg$::add_$name$(const char* value) {
734               $WeakDescriptorSelfPin$;
735               $DCHK$(value != nullptr);
736               $TsanDetectConcurrentMutation$;
737               _internal_mutable_$name_internal$()->Add()->assign(value);
738               $annotate_add$;
739               // @@protoc_insertion_point(field_add_char:$pkg.Msg.field$)
740             }
741             inline void $Msg$::add_$name$(absl::string_view value) {
742               $WeakDescriptorSelfPin$;
743               $TsanDetectConcurrentMutation$;
744               _internal_mutable_$name_internal$()->Add()->assign(value.data(),
745                                                                  value.size());
746               $annotate_add$;
747               // @@protoc_insertion_point(field_add_string_piece:$pkg.Msg.field$)
748             }
749             inline const ::$proto_ns$::RepeatedPtrField<std::string>&
750             $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
751               $WeakDescriptorSelfPin$;
752               $annotate_list$;
753               // @@protoc_insertion_point(field_list:$pkg.Msg.field$)
754               return _internal_$name_internal$();
755             }
756             inline ::$proto_ns$::RepeatedPtrField<std::string>*
757             $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
758               $WeakDescriptorSelfPin$;
759               $annotate_mutable_list$;
760               // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$)
761               $TsanDetectConcurrentMutation$;
762               return _internal_mutable_$name_internal$();
763             }
764           )cc");
765   if (should_split()) {
766     p->Emit(R"cc(
767       inline const $pb$::RepeatedPtrField<std::string>&
768       $Msg$::_internal_$name_internal$() const {
769         $TsanDetectConcurrentRead$;
770         return *$field_$;
771       }
772       inline $pb$::RepeatedPtrField<std::string>*
773       $Msg$::_internal_mutable_$name_internal$() {
774         $TsanDetectConcurrentRead$;
775         $PrepareSplitMessageForWrite$;
776         if ($field_$.IsDefault()) {
777           $field_$.Set($pb$::Arena::Create<$pb$::RepeatedPtrField<std::string>>(
778               GetArena()));
779         }
780         return $field_$.Get();
781       }
782     )cc");
783   } else {
784     p->Emit(R"cc(
785       inline const ::$proto_ns$::RepeatedPtrField<std::string>&
786       $Msg$::_internal_$name_internal$() const {
787         $TsanDetectConcurrentRead$;
788         return $field_$;
789       }
790       inline ::$proto_ns$::RepeatedPtrField<std::string>*
791       $Msg$::_internal_mutable_$name_internal$() {
792         $TsanDetectConcurrentRead$;
793         return &$field_$;
794       }
795     )cc");
796   }
797 }
798 
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const799 void RepeatedStringView::GenerateSerializeWithCachedSizesToArray(
800     io::Printer* p) const {
801   p->Emit({{"utf8_check",
802             [&] {
803               GenerateUtf8CheckCodeForString(
804                   p, field_, options_, false,
805                   "s.data(), static_cast<int>(s.length()),");
806             }}},
807           R"cc(
808             for (int i = 0, n = this_._internal_$name$_size(); i < n; ++i) {
809               const auto& s = this_._internal_$name$().Get(i);
810               $utf8_check$;
811               target = stream->Write$DeclaredType$($number$, s, target);
812             }
813           )cc");
814 }
815 }  // namespace
816 
MakeSingularStringViewGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)817 std::unique_ptr<FieldGeneratorBase> MakeSingularStringViewGenerator(
818     const FieldDescriptor* desc, const Options& options,
819     MessageSCCAnalyzer* scc) {
820   return absl::make_unique<SingularStringView>(desc, options, scc);
821 }
822 
MakeRepeatedStringViewGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)823 std::unique_ptr<FieldGeneratorBase> MakeRepeatedStringViewGenerator(
824     const FieldDescriptor* desc, const Options& options,
825     MessageSCCAnalyzer* scc) {
826   return absl::make_unique<RepeatedStringView>(desc, options, scc);
827 }
828 
829 }  // namespace cpp
830 }  // namespace compiler
831 }  // namespace protobuf
832 }  // namespace google
833