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