• 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/log/absl_log.h"
18 #include "absl/memory/memory.h"
19 #include "absl/strings/substitute.h"
20 #include "google/protobuf/compiler/cpp/field.h"
21 #include "google/protobuf/compiler/cpp/field_generators/generators.h"
22 #include "google/protobuf/compiler/cpp/helpers.h"
23 #include "google/protobuf/compiler/cpp/options.h"
24 #include "google/protobuf/descriptor.h"
25 #include "google/protobuf/descriptor.pb.h"
26 #include "google/protobuf/io/printer.h"
27 
28 namespace google {
29 namespace protobuf {
30 namespace compiler {
31 namespace cpp {
32 namespace {
33 using Semantic = ::google::protobuf::io::AnnotationCollector::Semantic;
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   const EnumValueDescriptor* default_value = field->default_value_enum();
38   bool split = ShouldSplit(field, opts);
39   bool is_open = internal::cpp::HasPreservingUnknownEnumSemantics(field);
40   auto enum_name = QualifiedClassName(field->enum_type(), opts);
41   return {
42       {"Enum", enum_name},
43       {"kDefault", Int32ToString(default_value->number())},
44       Sub("assert_valid",
45           is_open ? ""
46                   : absl::Substitute("assert($0_IsValid(value));", enum_name))
47           .WithSuffix(";"),
48 
49       {"cached_size_name", MakeVarintCachedSizeName(field)},
50       {"cached_size_", MakeVarintCachedSizeFieldName(field, split)},
51   };
52 }
53 
54 class SingularEnum : public FieldGeneratorBase {
55  public:
SingularEnum(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)56   SingularEnum(const FieldDescriptor* field, const Options& opts,
57                MessageSCCAnalyzer* scc)
58       : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
59   ~SingularEnum() override = default;
60 
MakeVars() const61   std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
62 
GeneratePrivateMembers(io::Printer * p) const63   void GeneratePrivateMembers(io::Printer* p) const override {
64     p->Emit(R"cc(
65       int $name$_;
66     )cc");
67   }
68 
GenerateClearingCode(io::Printer * p) const69   void GenerateClearingCode(io::Printer* p) const override {
70     p->Emit(R"cc(
71       $field_$ = $kDefault$;
72     )cc");
73   }
74 
GenerateMergingCode(io::Printer * p) const75   void GenerateMergingCode(io::Printer* p) const override {
76     p->Emit(R"cc(
77       _this->$field_$ = from.$field_$;
78     )cc");
79   }
80 
GenerateSwappingCode(io::Printer * p) const81   void GenerateSwappingCode(io::Printer* p) const override {
82     if (is_oneof()) return;
83 
84     p->Emit(R"cc(
85       swap($field_$, other->$field_$);
86     )cc");
87   }
88 
GenerateConstructorCode(io::Printer * p) const89   void GenerateConstructorCode(io::Printer* p) const override {
90     if (!is_oneof()) return;
91     p->Emit(R"cc(
92       $ns$::_$Msg$_default_instance_.$field_$ = $kDefault$;
93     )cc");
94   }
95 
GenerateCopyConstructorCode(io::Printer * p) const96   void GenerateCopyConstructorCode(io::Printer* p) const override {
97     p->Emit(R"cc(
98       _this->$field_$ = from.$field_$;
99     )cc");
100   }
101 
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const102   void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override {
103     p->Emit(R"cc(
104       target = stream->EnsureSpace(target);
105       target = ::_pbi::WireFormatLite::WriteEnumToArray(
106           $number$, this_._internal_$name$(), target);
107     )cc");
108   }
109 
GenerateByteSize(io::Printer * p) const110   void GenerateByteSize(io::Printer* p) const override {
111     p->Emit(R"cc(
112       total_size += $kTagBytes$ +
113                     ::_pbi::WireFormatLite::EnumSize(this_._internal_$name$());
114     )cc");
115   }
116 
GenerateConstexprAggregateInitializer(io::Printer * p) const117   void GenerateConstexprAggregateInitializer(io::Printer* p) const override {
118     p->Emit(R"cc(
119       /*decltype($field_$)*/ $kDefault$,
120     )cc");
121   }
122 
GenerateAggregateInitializer(io::Printer * p) const123   void GenerateAggregateInitializer(io::Printer* p) const override {
124     if (should_split()) {
125       p->Emit(R"cc(
126         decltype(Impl_::Split::$name$_){$kDefault$},
127       )cc");
128     } else {
129       p->Emit(R"cc(
130         decltype($field_$){$kDefault$},
131       )cc");
132     }
133   }
134 
GenerateCopyAggregateInitializer(io::Printer * p) const135   void GenerateCopyAggregateInitializer(io::Printer* p) const override {
136     p->Emit(R"cc(
137       decltype($field_$){},
138     )cc");
139   }
140 
141   void GenerateAccessorDeclarations(io::Printer* p) const override;
142   void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
143 
144  private:
145   const Options* opts_;
146 };
147 
GenerateAccessorDeclarations(io::Printer * p) const148 void SingularEnum::GenerateAccessorDeclarations(io::Printer* p) const {
149   auto v = p->WithVars(
150       AnnotatedAccessors(field_, {"", "_internal_", "_internal_set_"}));
151   auto vs = p->WithVars(AnnotatedAccessors(field_, {"set_"}, Semantic::kSet));
152   p->Emit(R"cc(
153     $DEPRECATED$ $Enum$ $name$() const;
154     $DEPRECATED$ void $set_name$($Enum$ value);
155 
156     private:
157     $Enum$ $_internal_name$() const;
158     void $_internal_set_name$($Enum$ value);
159 
160     public:
161   )cc");
162 }
163 
GenerateInlineAccessorDefinitions(io::Printer * p) const164 void SingularEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const {
165   p->Emit(R"cc(
166     inline $Enum$ $Msg$::$name$() const {
167       $WeakDescriptorSelfPin$;
168       $annotate_get$;
169       // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
170       return _internal_$name_internal$();
171     }
172   )cc");
173 
174   if (is_oneof()) {
175     p->Emit(R"cc(
176       inline void $Msg$::set_$name$($Enum$ value) {
177         $WeakDescriptorSelfPin$;
178         $PrepareSplitMessageForWrite$;
179         $assert_valid$;
180         if ($not_has_field$) {
181           clear_$oneof_name$();
182           set_has_$name_internal$();
183         }
184         $field_$ = value;
185         $annotate_set$;
186         // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
187       }
188       inline $Enum$ $Msg$::_internal_$name_internal$() const {
189         if ($has_field$) {
190           return static_cast<$Enum$>($field_$);
191         }
192         return static_cast<$Enum$>($kDefault$);
193       }
194     )cc");
195   } else {
196     p->Emit(R"cc(
197       inline void $Msg$::set_$name$($Enum$ value) {
198         $WeakDescriptorSelfPin$;
199         $PrepareSplitMessageForWrite$;
200         _internal_set_$name_internal$(value);
201         $set_hasbit$;
202         $annotate_set$;
203         // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
204       }
205       inline $Enum$ $Msg$::_internal_$name_internal$() const {
206         $TsanDetectConcurrentRead$;
207         return static_cast<$Enum$>($field_$);
208       }
209       inline void $Msg$::_internal_set_$name_internal$($Enum$ value) {
210         $TsanDetectConcurrentMutation$;
211         $assert_valid$;
212         $field_$ = value;
213       }
214     )cc");
215   }
216 }
217 
218 class RepeatedEnum : public FieldGeneratorBase {
219  public:
RepeatedEnum(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)220   RepeatedEnum(const FieldDescriptor* field, const Options& opts,
221                MessageSCCAnalyzer* scc)
222       : FieldGeneratorBase(field, opts, scc),
223         opts_(&opts),
224         has_cached_size_(field_->is_packed() &&
225                          HasGeneratedMethods(field_->file(), opts) &&
226                          !should_split()) {}
227   ~RepeatedEnum() override = default;
228 
MakeVars() const229   std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
230 
GeneratePrivateMembers(io::Printer * p) const231   void GeneratePrivateMembers(io::Printer* p) const override {
232     if (should_split()) {
233       p->Emit(R"cc(
234         $pbi$::RawPtr<$pb$::RepeatedField<int>> $name$_;
235       )cc");
236     } else {
237       p->Emit(R"cc(
238         $pb$::RepeatedField<int> $name$_;
239       )cc");
240     }
241 
242     if (has_cached_size_) {
243       p->Emit(R"cc(
244         $pbi$::CachedSize $cached_size_name$;
245       )cc");
246     }
247   }
248 
GenerateClearingCode(io::Printer * p) const249   void GenerateClearingCode(io::Printer* p) const override {
250     if (should_split()) {
251       p->Emit("$field_$.ClearIfNotDefault();\n");
252     } else {
253       p->Emit("$field_$.Clear();\n");
254     }
255   }
256 
GenerateMergingCode(io::Printer * p) const257   void GenerateMergingCode(io::Printer* p) const override {
258     // TODO: experiment with simplifying this to be
259     // `if (!from.empty()) { body(); }` for both split and non-split cases.
260     auto body = [&] {
261       p->Emit(R"cc(
262         _this->_internal_mutable_$name$()->MergeFrom(from._internal_$name$());
263       )cc");
264     };
265     if (!should_split()) {
266       body();
267     } else {
268       p->Emit({{"body", body}}, R"cc(
269         if (!from.$field_$.IsDefault()) {
270           $body$;
271         }
272       )cc");
273     }
274   }
275 
GenerateSwappingCode(io::Printer * p) const276   void GenerateSwappingCode(io::Printer* p) const override {
277     ABSL_CHECK(!should_split());
278     p->Emit(R"cc(
279       $field_$.InternalSwap(&other->$field_$);
280     )cc");
281   }
282 
GenerateDestructorCode(io::Printer * p) const283   void GenerateDestructorCode(io::Printer* p) const override {
284     if (should_split()) {
285       p->Emit(R"cc(
286         this_.$field_$.DeleteIfNotDefault();
287       )cc");
288     }
289   }
290 
GenerateConstexprAggregateInitializer(io::Printer * p) const291   void GenerateConstexprAggregateInitializer(io::Printer* p) const override {
292     p->Emit(R"cc(
293       /*decltype($field_$)*/ {},
294     )cc");
295     if (has_cached_size_) {
296       p->Emit(R"cc(
297         /*decltype($cached_size_$)*/ {0},
298       )cc");
299     }
300   }
301 
GenerateAggregateInitializer(io::Printer * p) const302   void GenerateAggregateInitializer(io::Printer* p) const override {
303     p->Emit(R"cc(
304       decltype($field_$){arena},
305     )cc");
306     if (has_cached_size_) {
307       // std::atomic has no copy constructor, which prevents explicit aggregate
308       // initialization pre-C++17.
309       p->Emit(R"cc(
310         /*decltype($cached_size_$)*/ {0},
311       )cc");
312     }
313   }
314 
GenerateCopyAggregateInitializer(io::Printer * p) const315   void GenerateCopyAggregateInitializer(io::Printer* p) const override {
316     p->Emit(R"cc(
317       decltype($field_$){from._internal_$name$()},
318     )cc");
319     if (has_cached_size_) {
320       // std::atomic has no copy constructor.
321       p->Emit(R"cc(
322         /*decltype($cached_size_$)*/ {0},
323       )cc");
324     }
325   }
326 
GenerateMemberConstexprConstructor(io::Printer * p) const327   void GenerateMemberConstexprConstructor(io::Printer* p) const override {
328     p->Emit("$name$_{}");
329     if (has_cached_size_) {
330       p->Emit(",\n_$name$_cached_byte_size_{0}");
331     }
332   }
333 
GenerateMemberConstructor(io::Printer * p) const334   void GenerateMemberConstructor(io::Printer* p) const override {
335     p->Emit("$name$_{visibility, arena}");
336     if (has_cached_size_) {
337       p->Emit(",\n_$name$_cached_byte_size_{0}");
338     }
339   }
340 
GenerateMemberCopyConstructor(io::Printer * p) const341   void GenerateMemberCopyConstructor(io::Printer* p) const override {
342     p->Emit("$name$_{visibility, arena, from.$name$_}");
343     if (has_cached_size_) {
344       p->Emit(",\n_$name$_cached_byte_size_{0}");
345     }
346   }
347 
GenerateOneofCopyConstruct(io::Printer * p) const348   void GenerateOneofCopyConstruct(io::Printer* p) const override {
349     ABSL_LOG(FATAL) << "Not supported";
350   }
351 
GenerateCopyConstructorCode(io::Printer * p) const352   void GenerateCopyConstructorCode(io::Printer* p) const override {
353     if (should_split()) {
354       p->Emit(R"cc(
355         if (!from._internal_$name$().empty()) {
356           _internal_mutable_$name$()->MergeFrom(from._internal_$name$());
357         }
358       )cc");
359     }
360   }
361 
GenerateConstructorCode(io::Printer * p) const362   void GenerateConstructorCode(io::Printer* p) const override {}
363 
364   void GenerateAccessorDeclarations(io::Printer* p) const override;
365   void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
366   void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override;
367   void GenerateByteSize(io::Printer* p) const override;
368 
369  private:
370   const Options* opts_;
371   bool has_cached_size_;
372 };
373 
GenerateAccessorDeclarations(io::Printer * p) const374 void RepeatedEnum::GenerateAccessorDeclarations(io::Printer* p) const {
375   auto v = p->WithVars(
376       AnnotatedAccessors(field_, {"", "_internal_", "_internal_mutable_"}));
377   auto vs =
378       p->WithVars(AnnotatedAccessors(field_, {"set_", "add_"}, Semantic::kSet));
379   auto vm =
380       p->WithVars(AnnotatedAccessors(field_, {"mutable_"}, Semantic::kAlias));
381 
382   p->Emit(R"cc(
383     public:
384     $DEPRECATED$ $Enum$ $name$(int index) const;
385     $DEPRECATED$ void $set_name$(int index, $Enum$ value);
386     $DEPRECATED$ void $add_name$($Enum$ value);
387     $DEPRECATED$ const $pb$::RepeatedField<int>& $name$() const;
388     $DEPRECATED$ $pb$::RepeatedField<int>* $mutable_name$();
389 
390     private:
391     const $pb$::RepeatedField<int>& $_internal_name$() const;
392     $pb$::RepeatedField<int>* $_internal_mutable_name$();
393 
394     public:
395   )cc");
396 }
397 
GenerateInlineAccessorDefinitions(io::Printer * p) const398 void RepeatedEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const {
399   p->Emit(R"cc(
400     inline $Enum$ $Msg$::$name$(int index) const {
401       $WeakDescriptorSelfPin$;
402       $annotate_get$;
403       // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
404       return static_cast<$Enum$>(_internal_$name_internal$().Get(index));
405     }
406   )cc");
407   p->Emit(R"cc(
408     inline void $Msg$::set_$name$(int index, $Enum$ value) {
409       $WeakDescriptorSelfPin$;
410       $assert_valid$;
411       _internal_mutable_$name_internal$()->Set(index, value);
412       $annotate_set$
413       // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
414     }
415   )cc");
416   p->Emit(R"cc(
417     inline void $Msg$::add_$name$($Enum$ value) {
418       $WeakDescriptorSelfPin$;
419       $assert_valid$;
420       $TsanDetectConcurrentMutation$;
421       _internal_mutable_$name_internal$()->Add(value);
422       $annotate_add$
423       // @@protoc_insertion_point(field_add:$pkg.Msg.field$)
424     }
425   )cc");
426   p->Emit(R"cc(
427     inline const $pb$::RepeatedField<int>& $Msg$::$name$() const
428         ABSL_ATTRIBUTE_LIFETIME_BOUND {
429       $WeakDescriptorSelfPin$;
430       $annotate_list$;
431       // @@protoc_insertion_point(field_list:$pkg.Msg.field$)
432       return _internal_$name_internal$();
433     }
434   )cc");
435   p->Emit(R"cc(
436     inline $pb$::RepeatedField<int>* $Msg$::mutable_$name$()
437         ABSL_ATTRIBUTE_LIFETIME_BOUND {
438       $WeakDescriptorSelfPin$;
439       $annotate_mutable_list$;
440       // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$)
441       $TsanDetectConcurrentMutation$;
442       return _internal_mutable_$name_internal$();
443     }
444   )cc");
445   if (should_split()) {
446     p->Emit(R"cc(
447       inline const $pb$::RepeatedField<int>& $Msg$::_internal_$name_internal$()
448           const {
449         $TsanDetectConcurrentRead$;
450         return *$field_$;
451       }
452       inline $pb$::RepeatedField<int>* $Msg$::_internal_mutable_$name_internal$() {
453         $TsanDetectConcurrentRead$;
454         $PrepareSplitMessageForWrite$;
455         if ($field_$.IsDefault()) {
456           $field_$.Set($pb$::Arena::Create<$pb$::RepeatedField<int>>(GetArena()));
457         }
458         return $field_$.Get();
459       }
460     )cc");
461   } else {
462     p->Emit(R"cc(
463       inline const $pb$::RepeatedField<int>& $Msg$::_internal_$name_internal$()
464           const {
465         $TsanDetectConcurrentRead$;
466         return $field_$;
467       }
468       inline $pb$::RepeatedField<int>* $Msg$::_internal_mutable_$name_internal$() {
469         $TsanDetectConcurrentRead$;
470         return &$field_$;
471       }
472     )cc");
473   }
474 }
475 
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const476 void RepeatedEnum::GenerateSerializeWithCachedSizesToArray(
477     io::Printer* p) const {
478   if (field_->is_packed()) {
479     p->Emit(
480         {
481             {"byte_size",
482              [&] {
483                if (has_cached_size_) {
484                  p->Emit(R"cc(std::size_t byte_size =
485                                   this_.$cached_size_$.Get();)cc");
486                } else {
487                  p->Emit(R"cc(
488                    std::size_t byte_size = 0;
489                    auto count = static_cast<std::size_t>(this_._internal_$name$_size());
490 
491                    for (std::size_t i = 0; i < count; ++i) {
492                      byte_size += ::_pbi::WireFormatLite::EnumSize(
493                          this_._internal_$name$().Get(static_cast<int>(i)));
494                    }
495                  )cc");
496                }
497              }},
498         },
499         R"cc(
500           {
501             $byte_size$;
502             if (byte_size > 0) {
503               target = stream->WriteEnumPacked(
504                   $number$, this_._internal_$name$(), byte_size, target);
505             }
506           }
507         )cc");
508     return;
509   }
510   p->Emit(R"cc(
511     for (int i = 0, n = this_._internal_$name$_size(); i < n; ++i) {
512       target = stream->EnsureSpace(target);
513       target = ::_pbi::WireFormatLite::WriteEnumToArray(
514           $number$, static_cast<$Enum$>(this_._internal_$name$().Get(i)),
515           target);
516     }
517   )cc");
518 }
519 
GenerateByteSize(io::Printer * p) const520 void RepeatedEnum::GenerateByteSize(io::Printer* p) const {
521   if (has_cached_size_) {
522     ABSL_CHECK(field_->is_packed());
523     p->Emit(R"cc(
524       total_size += ::_pbi::WireFormatLite::EnumSizeWithPackedTagSize(
525           this_._internal_$name$(), $kTagBytes$, this_.$cached_size_$);
526     )cc");
527     return;
528   }
529   p->Emit(
530       {
531           {"tag_size",
532            [&] {
533              if (field_->is_packed()) {
534                p->Emit(R"cc(
535                  data_size == 0
536                      ? 0
537                      : $kTagBytes$ + ::_pbi::WireFormatLite::Int32Size(
538                                          static_cast<int32_t>(data_size));
539                )cc");
540              } else {
541                p->Emit(R"cc(
542                  std::size_t{$kTagBytes$} *
543                      ::_pbi::FromIntSize(this_._internal_$name$_size());
544                )cc");
545              }
546            }},
547       },
548       R"cc(
549         std::size_t data_size =
550             ::_pbi::WireFormatLite::EnumSize(this_._internal_$name$());
551         std::size_t tag_size = $tag_size$;
552         total_size += data_size + tag_size;
553       )cc");
554 }
555 }  // namespace
556 
MakeSinguarEnumGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)557 std::unique_ptr<FieldGeneratorBase> MakeSinguarEnumGenerator(
558     const FieldDescriptor* desc, const Options& options,
559     MessageSCCAnalyzer* scc) {
560   return absl::make_unique<SingularEnum>(desc, options, scc);
561 }
562 
MakeRepeatedEnumGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)563 std::unique_ptr<FieldGeneratorBase> MakeRepeatedEnumGenerator(
564     const FieldDescriptor* desc, const Options& options,
565     MessageSCCAnalyzer* scc) {
566   return absl::make_unique<RepeatedEnum>(desc, options, scc);
567 }
568 
569 }  // namespace cpp
570 }  // namespace compiler
571 }  // namespace protobuf
572 }  // namespace google
573