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 "google/protobuf/compiler/cpp/field.h"
13
14 #include <cstddef>
15 #include <cstdint>
16 #include <memory>
17 #include <string>
18 #include <vector>
19
20 #include "absl/base/attributes.h"
21 #include "absl/log/absl_check.h"
22 #include "absl/strings/str_cat.h"
23 #include "absl/strings/str_format.h"
24 #include "absl/strings/string_view.h"
25 #include "absl/types/optional.h"
26 #include "absl/types/span.h"
27 #include "google/protobuf/compiler/cpp/field_generators/generators.h"
28 #include "google/protobuf/compiler/cpp/generator.h"
29 #include "google/protobuf/compiler/cpp/helpers.h"
30 #include "google/protobuf/compiler/cpp/options.h"
31 #include "google/protobuf/compiler/cpp/tracker.h"
32 #include "google/protobuf/cpp_features.pb.h"
33 #include "google/protobuf/descriptor.h"
34 #include "google/protobuf/descriptor.pb.h"
35 #include "google/protobuf/io/printer.h"
36 #include "google/protobuf/wire_format.h"
37
38 namespace google {
39 namespace protobuf {
40 namespace compiler {
41 namespace cpp {
42 using ::google::protobuf::internal::WireFormat;
43 using Sub = ::google::protobuf::io::Printer::Sub;
44
FieldVars(const FieldDescriptor * field,const Options & opts)45 std::vector<Sub> FieldVars(const FieldDescriptor* field, const Options& opts) {
46 bool split = ShouldSplit(field, opts);
47 std::vector<Sub> vars = {
48 // This will eventually be renamed to "field", once the existing "field"
49 // variable is replaced with "field_" everywhere.
50 {"name", FieldName(field)},
51 // Same as above, but represents internal use.
52 {"name_internal", FieldName(field)},
53
54 {"index", field->index()},
55 {"number", field->number()},
56 {"pkg.Msg.field", field->full_name()},
57
58 {"field_", FieldMemberName(field, split)},
59 {"DeclaredType", DeclaredTypeMethodName(field->type())},
60 {"kTagBytes", WireFormat::TagSize(field->number(), field->type())},
61 Sub("PrepareSplitMessageForWrite",
62 split ? "PrepareSplitMessageForWrite();" : "")
63 .WithSuffix(";"),
64 Sub("DEPRECATED", DeprecatedAttribute(opts, field)).WithSuffix(" "),
65
66 // These variables are placeholders to pick out the beginning and ends of
67 // identifiers for annotations (when doing so with existing variables
68 // would be ambiguous or impossible). They should never be set to anything
69 // but the empty string.
70 {"{", ""},
71 {"}", ""},
72
73 // For TSan validation.
74 {"TsanDetectConcurrentMutation",
75 absl::StrCat("::", ProtobufNamespace(opts),
76 "::internal::TSanWrite(&_impl_)")},
77 {"TsanDetectConcurrentRead",
78 absl::StrCat("::", ProtobufNamespace(opts),
79 "::internal::TSanRead(&_impl_)")},
80
81 // Old-style names.
82 {"field", FieldMemberName(field, split)},
83 {"declared_type", DeclaredTypeMethodName(field->type())},
84 {"classname", ClassName(FieldScope(field), false)},
85 {"ns", Namespace(field, opts)},
86 {"tag_size", WireFormat::TagSize(field->number(), field->type())},
87 {"deprecated_attr", DeprecatedAttribute(opts, field)},
88 Sub("WeakDescriptorSelfPin",
89 UsingImplicitWeakDescriptor(field->file(), opts)
90 ? absl::StrCat(
91 StrongReferenceToType(field->containing_type(), opts), ";")
92 : "")
93 .WithSuffix(";"),
94 };
95
96 if (const auto* oneof = field->containing_oneof()) {
97 auto field_name = UnderscoresToCamelCase(field->name(), true);
98
99 vars.push_back({"oneof_name", oneof->name()});
100 vars.push_back({"field_name", field_name});
101 vars.push_back({"oneof_index", oneof->index()});
102 vars.push_back({"has_field", absl::StrFormat("%s_case() == k%s",
103 oneof->name(), field_name)});
104 vars.push_back(
105 {"not_has_field",
106 absl::StrFormat("%s_case() != k%s", oneof->name(), field_name)});
107 }
108
109 return vars;
110 }
111
FieldGeneratorBase(const FieldDescriptor * field,const Options & options,MessageSCCAnalyzer * scc)112 FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* field,
113 const Options& options,
114 MessageSCCAnalyzer* scc)
115 : field_(field), options_(options) {
116 bool is_repeated_or_map = field->is_repeated();
117 should_split_ = ShouldSplit(field, options);
118 is_oneof_ = field->real_containing_oneof() != nullptr;
119 switch (field->cpp_type()) {
120 case FieldDescriptor::CPPTYPE_ENUM:
121 case FieldDescriptor::CPPTYPE_INT32:
122 case FieldDescriptor::CPPTYPE_INT64:
123 case FieldDescriptor::CPPTYPE_UINT32:
124 case FieldDescriptor::CPPTYPE_UINT64:
125 case FieldDescriptor::CPPTYPE_FLOAT:
126 case FieldDescriptor::CPPTYPE_DOUBLE:
127 case FieldDescriptor::CPPTYPE_BOOL:
128 is_trivial_ = has_trivial_value_ = !is_repeated_or_map;
129 has_default_constexpr_constructor_ = is_repeated_or_map;
130 break;
131 case FieldDescriptor::CPPTYPE_STRING:
132 is_string_ = true;
133 is_inlined_ = IsStringInlined(field, options);
134 is_bytes_ = field->type() == FieldDescriptor::TYPE_BYTES;
135 has_default_constexpr_constructor_ = is_repeated_or_map;
136 break;
137 case FieldDescriptor::CPPTYPE_MESSAGE:
138 is_message_ = true;
139 is_group_ = field->type() == FieldDescriptor::TYPE_GROUP;
140 is_foreign_ = IsCrossFileMessage(field);
141 is_weak_ = IsImplicitWeakField(field, options, scc);
142 is_lazy_ = IsLazy(field, options, scc);
143 has_trivial_value_ = !(is_repeated_or_map || is_lazy_);
144 has_default_constexpr_constructor_ = is_repeated_or_map || is_lazy_;
145 break;
146 }
147
148 has_trivial_zero_default_ = CanInitializeByZeroing(field, options, scc);
149 has_brace_default_assign_ = has_trivial_zero_default_ && !is_lazy_;
150 }
151
GenerateMemberConstexprConstructor(io::Printer * p) const152 void FieldGeneratorBase::GenerateMemberConstexprConstructor(
153 io::Printer* p) const {
154 ABSL_CHECK(!field_->is_extension());
155 if (field_->is_repeated()) {
156 p->Emit("$name$_{}");
157 } else {
158 p->Emit({{"default", DefaultValue(options_, field_)}},
159 "$name$_{$default$}");
160 }
161 }
162
GenerateMemberConstructor(io::Printer * p) const163 void FieldGeneratorBase::GenerateMemberConstructor(io::Printer* p) const {
164 ABSL_CHECK(!field_->is_extension());
165 if (field_->is_map()) {
166 p->Emit("$name$_{visibility, arena}");
167 } else if (field_->is_repeated()) {
168 if (ShouldSplit(field_, options_)) {
169 p->Emit("$name$_{}"); // RawPtr<Repeated>
170 } else {
171 p->Emit("$name$_{visibility, arena}");
172 }
173 } else {
174 p->Emit({{"default", DefaultValue(options_, field_)}},
175 "$name$_{$default$}");
176 }
177 }
178
GenerateMemberCopyConstructor(io::Printer * p) const179 void FieldGeneratorBase::GenerateMemberCopyConstructor(io::Printer* p) const {
180 ABSL_CHECK(!field_->is_extension());
181 if (field_->is_repeated()) {
182 p->Emit("$name$_{visibility, arena, from.$name$_}");
183 } else {
184 p->Emit("$name$_{from.$name$_}");
185 }
186 }
187
GenerateOneofCopyConstruct(io::Printer * p) const188 void FieldGeneratorBase::GenerateOneofCopyConstruct(io::Printer* p) const {
189 ABSL_CHECK(!field_->is_extension()) << "Not supported";
190 ABSL_CHECK(!field_->is_repeated()) << "Not supported";
191 ABSL_CHECK(!field_->is_map()) << "Not supported";
192 p->Emit("$field$ = from.$field$;\n");
193 }
194
GenerateAggregateInitializer(io::Printer * p) const195 void FieldGeneratorBase::GenerateAggregateInitializer(io::Printer* p) const {
196 if (ShouldSplit(field_, options_)) {
197 p->Emit(R"cc(
198 decltype(Impl_::Split::$name$_){arena},
199 )cc");
200 } else {
201 p->Emit(R"cc(
202 decltype($field$){arena},
203 )cc");
204 }
205 }
206
GenerateConstexprAggregateInitializer(io::Printer * p) const207 void FieldGeneratorBase::GenerateConstexprAggregateInitializer(
208 io::Printer* p) const {
209 p->Emit(R"cc(
210 /*decltype($field$)*/ {},
211 )cc");
212 }
213
GenerateCopyAggregateInitializer(io::Printer * p) const214 void FieldGeneratorBase::GenerateCopyAggregateInitializer(
215 io::Printer* p) const {
216 p->Emit(R"cc(
217 decltype($field$){from.$field$},
218 )cc");
219 }
220
GenerateCopyConstructorCode(io::Printer * p) const221 void FieldGeneratorBase::GenerateCopyConstructorCode(io::Printer* p) const {
222 if (should_split()) {
223 // There is no copy constructor for the `Split` struct, so we need to copy
224 // the value here.
225 Formatter format(p, variables_);
226 format("$field$ = from.$field$;\n");
227 }
228 }
229
230 namespace {
MakeGenerator(const FieldDescriptor * field,const Options & options,MessageSCCAnalyzer * scc)231 std::unique_ptr<FieldGeneratorBase> MakeGenerator(const FieldDescriptor* field,
232 const Options& options,
233 MessageSCCAnalyzer* scc) {
234
235 if (field->is_map()) {
236 ABSL_CHECK(
237 !(field->options().lazy() || field->options().unverified_lazy()));
238 return MakeMapGenerator(field, options, scc);
239 }
240 if (field->is_repeated()) {
241 ABSL_CHECK(!field->options().unverified_lazy());
242
243 switch (field->cpp_type()) {
244 case FieldDescriptor::CPPTYPE_MESSAGE:
245 return MakeRepeatedMessageGenerator(field, options, scc);
246 case FieldDescriptor::CPPTYPE_STRING: {
247 if (field->cpp_string_type() == FieldDescriptor::CppStringType::kView) {
248 return MakeRepeatedStringViewGenerator(field, options, scc);
249 } else {
250 return MakeRepeatedStringGenerator(field, options, scc);
251 }
252 }
253 case FieldDescriptor::CPPTYPE_ENUM:
254 return MakeRepeatedEnumGenerator(field, options, scc);
255 default:
256 return MakeRepeatedPrimitiveGenerator(field, options, scc);
257 }
258 }
259
260 if (field->real_containing_oneof() &&
261 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
262 return MakeOneofMessageGenerator(field, options, scc);
263 }
264
265 switch (field->cpp_type()) {
266 case FieldDescriptor::CPPTYPE_MESSAGE:
267 return MakeSinguarMessageGenerator(field, options, scc);
268 case FieldDescriptor::CPPTYPE_ENUM:
269 return MakeSinguarEnumGenerator(field, options, scc);
270 case FieldDescriptor::CPPTYPE_STRING: {
271 switch (field->cpp_string_type()) {
272 case FieldDescriptor::CppStringType::kView:
273 return MakeSingularStringViewGenerator(field, options, scc);
274 case FieldDescriptor::CppStringType::kCord:
275 if (field->type() == FieldDescriptor::TYPE_BYTES) {
276 if (field->real_containing_oneof()) {
277 return MakeOneofCordGenerator(field, options, scc);
278 } else {
279 return MakeSingularCordGenerator(field, options, scc);
280 }
281 }
282 ABSL_FALLTHROUGH_INTENDED;
283 default:
284 return MakeSinguarStringGenerator(field, options, scc);
285 }
286 }
287 default:
288 return MakeSinguarPrimitiveGenerator(field, options, scc);
289 }
290 }
291
HasBitVars(const FieldDescriptor * field,const Options & opts,absl::optional<uint32_t> idx,std::vector<Sub> & vars)292 void HasBitVars(const FieldDescriptor* field, const Options& opts,
293 absl::optional<uint32_t> idx, std::vector<Sub>& vars) {
294 if (!idx.has_value()) {
295 vars.emplace_back(Sub("set_hasbit", "").WithSuffix(";"));
296 vars.emplace_back(Sub("clear_hasbit", "").WithSuffix(";"));
297 return;
298 }
299
300 ABSL_CHECK(internal::cpp::HasHasbit(field));
301
302 int32_t index = *idx / 32;
303 std::string mask = absl::StrFormat("0x%08xu", 1u << (*idx % 32));
304
305 absl::string_view has_bits = IsMapEntryMessage(field->containing_type())
306 ? "_has_bits_"
307 : "_impl_._has_bits_";
308
309 auto has = absl::StrFormat("%s[%d] & %s", has_bits, index, mask);
310 auto set = absl::StrFormat("%s[%d] |= %s;", has_bits, index, mask);
311 auto clr = absl::StrFormat("%s[%d] &= ~%s;", has_bits, index, mask);
312
313 vars.emplace_back("has_hasbit", has);
314 vars.emplace_back(Sub("set_hasbit", set).WithSuffix(";"));
315 vars.emplace_back(Sub("clear_hasbit", clr).WithSuffix(";"));
316 }
317
InlinedStringVars(const FieldDescriptor * field,const Options & opts,absl::optional<uint32_t> idx,std::vector<Sub> & vars)318 void InlinedStringVars(const FieldDescriptor* field, const Options& opts,
319 absl::optional<uint32_t> idx, std::vector<Sub>& vars) {
320 if (!IsStringInlined(field, opts)) {
321 ABSL_CHECK(!idx.has_value());
322 return;
323 }
324
325 // The first bit is the tracking bit for on demand registering ArenaDtor.
326 ABSL_CHECK_GT(*idx, 0u)
327 << "_inlined_string_donated_'s bit 0 is reserved for arena dtor tracking";
328
329 int32_t index = *idx / 32;
330 std::string mask = absl::StrFormat("0x%08xu", 1u << (*idx % 32));
331 vars.emplace_back("inlined_string_index", index);
332 vars.emplace_back("inlined_string_mask", mask);
333
334 absl::string_view array = IsMapEntryMessage(field->containing_type())
335 ? "_inlined_string_donated_"
336 : "_impl_._inlined_string_donated_";
337
338 vars.emplace_back("inlined_string_donated",
339 absl::StrFormat("(%s[%d] & %s) != 0;", array, index, mask));
340 vars.emplace_back("donating_states_word",
341 absl::StrFormat("%s[%d]", array, index));
342 vars.emplace_back("mask_for_undonate", absl::StrFormat("~%s", mask));
343 }
344 } // namespace
345
FieldGenerator(const FieldDescriptor * field,const Options & options,MessageSCCAnalyzer * scc_analyzer,absl::optional<uint32_t> hasbit_index,absl::optional<uint32_t> inlined_string_index)346 FieldGenerator::FieldGenerator(const FieldDescriptor* field,
347 const Options& options,
348 MessageSCCAnalyzer* scc_analyzer,
349 absl::optional<uint32_t> hasbit_index,
350 absl::optional<uint32_t> inlined_string_index)
351 : impl_(MakeGenerator(field, options, scc_analyzer)),
352 field_vars_(FieldVars(field, options)),
353 tracker_vars_(MakeTrackerCalls(field, options)),
354 per_generator_vars_(impl_->MakeVars()) {
355 HasBitVars(field, options, hasbit_index, field_vars_);
356 InlinedStringVars(field, options, inlined_string_index, field_vars_);
357 }
358
Build(const Options & options,MessageSCCAnalyzer * scc,absl::Span<const int32_t> has_bit_indices,absl::Span<const int32_t> inlined_string_indices)359 void FieldGeneratorTable::Build(
360 const Options& options, MessageSCCAnalyzer* scc,
361 absl::Span<const int32_t> has_bit_indices,
362 absl::Span<const int32_t> inlined_string_indices) {
363 // Construct all the FieldGenerators.
364 fields_.reserve(static_cast<size_t>(descriptor_->field_count()));
365 for (const auto* field : internal::FieldRange(descriptor_)) {
366 size_t index = static_cast<size_t>(field->index());
367 absl::optional<uint32_t> has_bit_index;
368 if (!has_bit_indices.empty() && has_bit_indices[index] >= 0) {
369 has_bit_index = static_cast<uint32_t>(has_bit_indices[index]);
370 }
371
372 absl::optional<uint32_t> inlined_string_index;
373 if (!inlined_string_indices.empty() && inlined_string_indices[index] >= 0) {
374 inlined_string_index =
375 static_cast<uint32_t>(inlined_string_indices[index]);
376 }
377
378 fields_.push_back(FieldGenerator(field, options, scc, has_bit_index,
379 inlined_string_index));
380 }
381 }
382
383 } // namespace cpp
384 } // namespace compiler
385 } // namespace protobuf
386 } // namespace google
387