File indexing completed on 2026-09-11 09:13:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
0013 #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
0014
0015 #include <cstdint>
0016 #include <iterator>
0017 #include <optional>
0018 #include <string>
0019 #include <tuple>
0020 #include <type_traits>
0021 #include <vector>
0022
0023 #include "absl/container/flat_hash_map.h"
0024 #include "absl/log/absl_check.h"
0025 #include "absl/strings/str_cat.h"
0026 #include "absl/strings/str_split.h"
0027 #include "absl/strings/string_view.h"
0028 #include "absl/types/span.h"
0029 #include "google/protobuf/compiler/code_generator.h"
0030 #include "google/protobuf/compiler/cpp/names.h"
0031 #include "google/protobuf/compiler/cpp/options.h"
0032 #include "google/protobuf/compiler/scc.h"
0033 #include "google/protobuf/descriptor.h"
0034 #include "google/protobuf/descriptor.pb.h"
0035 #include "google/protobuf/generated_message_tctable_impl.h"
0036 #include "google/protobuf/io/printer.h"
0037
0038
0039
0040 #include "google/protobuf/port_def.inc"
0041
0042 namespace google {
0043 namespace protobuf {
0044 namespace compiler {
0045 namespace cpp {
0046 enum class ArenaDtorNeeds { kNone = 0, kOnDemand = 1, kRequired = 2 };
0047
0048 inline absl::string_view ProtobufNamespace(const Options& opts) {
0049
0050 constexpr absl::string_view kGoogle3Ns = "proto2";
0051 constexpr absl::string_view kOssNs = "google::protobuf";
0052
0053 return opts.opensource_runtime ? kOssNs : kGoogle3Ns;
0054 }
0055
0056 inline std::string DeprecatedAttribute(const Options&,
0057 const FieldDescriptor* d) {
0058 return d->options().deprecated() ? "[[deprecated]] " : "";
0059 }
0060
0061 inline std::string DeprecatedAttribute(const Options&,
0062 const EnumValueDescriptor* d) {
0063 return d->options().deprecated() ? "[[deprecated]] " : "";
0064 }
0065
0066
0067
0068 extern const char kThickSeparator[];
0069 extern const char kThinSeparator[];
0070
0071 absl::flat_hash_map<absl::string_view, std::string> MessageVars(
0072 const Descriptor* desc);
0073
0074
0075 void SetCommonMessageDataVariables(
0076 const Descriptor* descriptor,
0077 absl::flat_hash_map<absl::string_view, std::string>* variables);
0078
0079 absl::flat_hash_map<absl::string_view, std::string> UnknownFieldsVars(
0080 const Descriptor* desc, const Options& opts);
0081
0082 void SetUnknownFieldsVariable(
0083 const Descriptor* descriptor, const Options& options,
0084 absl::flat_hash_map<absl::string_view, std::string>* variables);
0085
0086 bool GetBootstrapBasename(const Options& options, absl::string_view basename,
0087 std::string* bootstrap_basename);
0088 bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context,
0089 bool bootstrap_flag, std::string* basename);
0090 bool IsBootstrapProto(const Options& options, const FileDescriptor* file);
0091
0092
0093
0094
0095
0096 std::string Namespace(const FileDescriptor* d, const Options& options);
0097 std::string Namespace(const Descriptor* d, const Options& options);
0098 std::string Namespace(const FieldDescriptor* d, const Options& options);
0099 std::string Namespace(const EnumDescriptor* d, const Options& options);
0100 PROTOC_EXPORT std::string Namespace(const FileDescriptor* d);
0101 PROTOC_EXPORT std::string Namespace(const Descriptor* d);
0102 PROTOC_EXPORT std::string Namespace(const FieldDescriptor* d);
0103 PROTOC_EXPORT std::string Namespace(const EnumDescriptor* d);
0104
0105 class MessageSCCAnalyzer;
0106
0107
0108 bool CanInitializeByZeroing(const FieldDescriptor* field,
0109 const Options& options,
0110 MessageSCCAnalyzer* scc_analyzer);
0111
0112 bool CanClearByZeroing(const FieldDescriptor* field);
0113
0114 bool HasTrivialSwap(const FieldDescriptor* field, const Options& options,
0115 MessageSCCAnalyzer* scc_analyzer);
0116
0117 PROTOC_EXPORT std::string ClassName(const Descriptor* descriptor);
0118 PROTOC_EXPORT std::string ClassName(const EnumDescriptor* enum_descriptor);
0119
0120 std::string QualifiedClassName(const Descriptor* d, const Options& options);
0121 std::string QualifiedClassName(const EnumDescriptor* d, const Options& options);
0122
0123 PROTOC_EXPORT std::string QualifiedClassName(const Descriptor* d);
0124 PROTOC_EXPORT std::string QualifiedClassName(const EnumDescriptor* d);
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 inline std::string ClassName(const Descriptor* descriptor, bool qualified) {
0137 return qualified ? QualifiedClassName(descriptor, Options())
0138 : ClassName(descriptor);
0139 }
0140
0141 inline std::string ClassName(const EnumDescriptor* descriptor, bool qualified) {
0142 return qualified ? QualifiedClassName(descriptor, Options())
0143 : ClassName(descriptor);
0144 }
0145
0146
0147
0148 std::string ExtensionName(const FieldDescriptor* d);
0149
0150 std::string QualifiedExtensionName(const FieldDescriptor* d,
0151 const Options& options);
0152 std::string QualifiedExtensionName(const FieldDescriptor* d);
0153
0154
0155 std::string DefaultInstanceType(const Descriptor* descriptor,
0156 const Options& options, bool split = false);
0157
0158
0159 std::string DefaultInstanceName(const Descriptor* descriptor,
0160 const Options& options, bool split = false);
0161
0162
0163
0164 std::string DefaultInstancePtr(const Descriptor* descriptor,
0165 const Options& options, bool split = false);
0166
0167
0168 std::string QualifiedDefaultInstanceName(const Descriptor* descriptor,
0169 const Options& options,
0170 bool split = false);
0171
0172
0173 std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor,
0174 const Options& options,
0175 bool split = false);
0176
0177
0178 std::string ClassDataType(const Descriptor* descriptor, const Options& options);
0179
0180
0181 std::string DescriptorTableName(const FileDescriptor* file,
0182 const Options& options);
0183
0184
0185
0186 std::string FileDllExport(const FileDescriptor* file, const Options& options);
0187
0188
0189 std::string SuperClassName(const Descriptor* descriptor,
0190 const Options& options);
0191
0192
0193
0194
0195
0196
0197
0198 enum class NameContext {
0199 kFile,
0200 kMessage,
0201 };
0202 enum class NameKind {
0203 kType,
0204 kFunction,
0205 kValue,
0206 };
0207 std::string ResolveKnownNameCollisions(absl::string_view name,
0208 NameContext name_context,
0209 NameKind name_kind);
0210
0211 std::string ResolveKeyword(absl::string_view name);
0212
0213
0214
0215
0216
0217 PROTOC_EXPORT std::string FieldName(const FieldDescriptor* field);
0218
0219
0220 std::string FieldMemberName(const FieldDescriptor* field, bool split);
0221
0222
0223
0224
0225
0226 int EstimateAlignmentSize(const FieldDescriptor* field);
0227
0228
0229
0230
0231
0232 int EstimateSize(const FieldDescriptor* field);
0233
0234
0235
0236 std::string FieldConstantName(const FieldDescriptor* field);
0237
0238
0239
0240 inline const Descriptor* FieldScope(const FieldDescriptor* field) {
0241 return field->is_extension() ? field->extension_scope()
0242 : field->containing_type();
0243 }
0244
0245
0246
0247 std::string FieldMessageTypeName(const FieldDescriptor* field,
0248 const Options& options);
0249
0250
0251 const char* PrimitiveTypeName(FieldDescriptor::CppType type);
0252 std::string PrimitiveTypeName(const Options& options,
0253 FieldDescriptor::CppType type);
0254
0255
0256
0257 const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
0258
0259
0260
0261 absl::string_view DeclaredCppTypeMethodName(FieldDescriptor::CppType type);
0262
0263
0264 std::string Int32ToString(int number);
0265
0266
0267 std::string DefaultValue(const Options& options, const FieldDescriptor* field);
0268
0269
0270 std::string DefaultValue(const FieldDescriptor* field);
0271
0272
0273 std::string FilenameIdentifier(absl::string_view filename);
0274
0275
0276
0277 std::string UniqueName(absl::string_view name, absl::string_view filename,
0278 const Options& options);
0279 inline std::string UniqueName(absl::string_view name, const FileDescriptor* d,
0280 const Options& options) {
0281 return UniqueName(name, d->name(), options);
0282 }
0283 inline std::string UniqueName(absl::string_view name, const Descriptor* d,
0284 const Options& options) {
0285 return UniqueName(name, d->file(), options);
0286 }
0287 inline std::string UniqueName(absl::string_view name, const EnumDescriptor* d,
0288 const Options& options) {
0289 return UniqueName(name, d->file(), options);
0290 }
0291 inline std::string UniqueName(absl::string_view name,
0292 const ServiceDescriptor* d,
0293 const Options& options) {
0294 return UniqueName(name, d->file(), options);
0295 }
0296
0297
0298
0299 inline Options InternalRuntimeOptions() {
0300 Options options;
0301 options.opensource_runtime = false;
0302 return options;
0303 }
0304 inline std::string UniqueName(absl::string_view name,
0305 absl::string_view filename) {
0306 return UniqueName(name, filename, InternalRuntimeOptions());
0307 }
0308 inline std::string UniqueName(absl::string_view name, const FileDescriptor* d) {
0309 return UniqueName(name, d->name(), InternalRuntimeOptions());
0310 }
0311 inline std::string UniqueName(absl::string_view name, const Descriptor* d) {
0312 return UniqueName(name, d->file(), InternalRuntimeOptions());
0313 }
0314 inline std::string UniqueName(absl::string_view name, const EnumDescriptor* d) {
0315 return UniqueName(name, d->file(), InternalRuntimeOptions());
0316 }
0317 inline std::string UniqueName(absl::string_view name,
0318 const ServiceDescriptor* d) {
0319 return UniqueName(name, d->file(), InternalRuntimeOptions());
0320 }
0321
0322
0323 std::string QualifiedFileLevelSymbol(const FileDescriptor* file,
0324 absl::string_view name,
0325 const Options& options);
0326
0327
0328 std::string EscapeTrigraphs(absl::string_view to_escape);
0329
0330
0331 std::string SafeFunctionName(const Descriptor* descriptor,
0332 const FieldDescriptor* field,
0333 absl::string_view prefix);
0334
0335
0336 FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
0337 const Options& options);
0338
0339
0340
0341 inline bool UseUnknownFieldSet(const FileDescriptor* file,
0342 const Options& options) {
0343 return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
0344 }
0345
0346 inline bool IsWeak(const FieldDescriptor* field, const Options& options) {
0347 if (field->options().weak()) {
0348 ABSL_CHECK(!options.opensource_runtime);
0349 return true;
0350 }
0351 return false;
0352 }
0353
0354 inline bool IsCord(const FieldDescriptor* field) {
0355 return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
0356 field->cpp_string_type() == FieldDescriptor::CppStringType::kCord;
0357 }
0358
0359 inline bool IsString(const FieldDescriptor* field) {
0360 return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
0361 (field->cpp_string_type() == FieldDescriptor::CppStringType::kString ||
0362 field->cpp_string_type() == FieldDescriptor::CppStringType::kView);
0363 }
0364
0365
0366 bool IsArenaStringPtr(const FieldDescriptor* field, const Options& opts);
0367 bool IsMicroString(const FieldDescriptor* field, const Options& opts);
0368
0369 bool IsProfileDriven(const Options& options);
0370
0371
0372 PROTOC_EXPORT bool IsRarelyPresent(const FieldDescriptor* field,
0373 const Options& options);
0374
0375
0376 bool IsLikelyPresent(const FieldDescriptor* field, const Options& options);
0377
0378 std::optional<float> GetPresenceProbability(const FieldDescriptor* field,
0379 const Options& options);
0380
0381
0382
0383
0384
0385 std::optional<float> GetFieldGroupPresenceProbability(
0386 const std::vector<const FieldDescriptor*>& fields, const Options& options);
0387
0388
0389 internal::cpp::HasbitMode GetFieldHasbitMode(const FieldDescriptor* field,
0390 const Options& options);
0391
0392
0393
0394 PROTOC_EXPORT bool HasHasbit(const FieldDescriptor* field,
0395 const Options& options);
0396
0397 bool IsStringInliningEnabled(const Options& options);
0398
0399
0400 bool CanStringBeInlined(const FieldDescriptor* field, const Options& options);
0401
0402
0403
0404 bool IsStringInlined(const FieldDescriptor* field, const Options& options);
0405
0406
0407
0408
0409 inline bool IsFieldInlined(const FieldDescriptor* field,
0410 const Options& options) {
0411 return IsStringInlined(field, options);
0412 }
0413
0414
0415 bool HasLazyFields(const FileDescriptor* file, const Options& options,
0416 MessageSCCAnalyzer* scc_analyzer);
0417
0418
0419 bool IsLazy(const FieldDescriptor* field, const Options& options,
0420 MessageSCCAnalyzer* scc_analyzer);
0421
0422
0423
0424 inline bool IsExplicitLazy(const FieldDescriptor* field) {
0425 if (field->is_map() || field->is_repeated()) {
0426 return false;
0427 }
0428
0429 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
0430 return false;
0431 }
0432
0433 return field->options().lazy() || field->options().unverified_lazy();
0434 }
0435
0436 internal::field_layout::TransformValidation GetLazyStyle(
0437 const FieldDescriptor* field, const Options& options,
0438 MessageSCCAnalyzer* scc_analyzer);
0439
0440 bool IsEagerlyVerifiedLazy(const FieldDescriptor* field, const Options& options,
0441 MessageSCCAnalyzer* scc_analyzer);
0442
0443 bool IsLazilyVerifiedLazy(const FieldDescriptor* field, const Options& options);
0444
0445 bool ShouldVerify(const Descriptor* descriptor, const Options& options,
0446 MessageSCCAnalyzer* scc_analyzer);
0447 bool ShouldVerify(const FileDescriptor* file, const Options& options,
0448 MessageSCCAnalyzer* scc_analyzer);
0449 bool ShouldVerifyRecursively(const FieldDescriptor* field);
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459 enum class VerifySimpleType {
0460 kSimpleInt32Never,
0461 kSimpleInt32Always,
0462 kCustom,
0463 kCustomInt32Never,
0464 kCustomInt32Always,
0465 };
0466
0467
0468 VerifySimpleType ShouldVerifySimple(const Descriptor* descriptor);
0469
0470
0471
0472 PROTOC_EXPORT bool ShouldSplit(const Descriptor* desc, const Options& options);
0473
0474
0475 PROTOC_EXPORT bool ShouldSplit(const FieldDescriptor* field,
0476 const Options& options);
0477
0478
0479
0480 bool ShouldForceAllocationOnConstruction(const Descriptor* desc,
0481 const Options& options);
0482
0483
0484 bool IsPresentMessage(const Descriptor* descriptor, const Options& options);
0485
0486
0487 const FieldDescriptor* FindHottestField(
0488 const std::vector<const FieldDescriptor*>& fields, const Options& options);
0489
0490
0491 bool HasExtensionsOrExtendableMessage(const FileDescriptor* file);
0492
0493
0494
0495
0496 bool HasRepeatedFields(const FileDescriptor* file);
0497
0498
0499
0500 bool HasStringPieceFields(const FileDescriptor* file, const Options& options);
0501
0502
0503
0504 bool HasRegularStringFields(const FileDescriptor* file, const Options& options);
0505
0506
0507
0508 bool HasCordFields(const FileDescriptor* file, const Options& options);
0509
0510
0511
0512 bool HasMapFields(const FileDescriptor* file);
0513
0514
0515 bool HasEnumDefinitions(const FileDescriptor* file);
0516
0517
0518 bool HasV2MessageTable(const FileDescriptor* file, const Options& options);
0519 bool HasV2ParseTable(const FileDescriptor* file, const Options& options);
0520
0521 bool IsV2ParseEnabledForMessage(const Descriptor* descriptor,
0522 const Options& options);
0523
0524
0525 bool IsV2EnabledForMessage(const Descriptor* descriptor,
0526 const Options& options);
0527
0528 #ifdef PROTOBUF_INTERNAL_V2_EXPERIMENT
0529 bool IsV2CodegenEnabled(const Options& options);
0530 bool ShouldGenerateV2Code(const Descriptor* descriptor, const Options& options);
0531
0532
0533 bool IsEligibleForV2Batching(const FieldDescriptor* field);
0534 bool HasFieldEligibleForV2Batching(const Descriptor* descriptor);
0535 #endif
0536
0537
0538
0539 inline bool HasGeneratedMethods(const FileDescriptor* file,
0540 const Options& options) {
0541 return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
0542 }
0543
0544
0545 inline bool HasDescriptorMethods(const FileDescriptor* file,
0546 const Options& options) {
0547 return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
0548 }
0549
0550
0551 inline bool HasGenericServices(const FileDescriptor* file,
0552 const Options& options) {
0553 return file->service_count() > 0 &&
0554 GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
0555 file->options().cc_generic_services();
0556 }
0557
0558 inline bool IsProto2MessageSet(const Descriptor* descriptor,
0559 const Options& options) {
0560 return !options.opensource_runtime &&
0561 options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
0562 !options.lite_implicit_weak_fields &&
0563 descriptor->options().message_set_wire_format() &&
0564 descriptor->full_name() == "google.protobuf.bridge.MessageSet";
0565 }
0566
0567 inline bool IsMapEntryMessage(const Descriptor* descriptor) {
0568 return descriptor->options().map_entry();
0569 }
0570
0571
0572 bool IsStringOrMessage(const FieldDescriptor* field);
0573
0574 std::string UnderscoresToCamelCase(absl::string_view input,
0575 bool cap_next_letter);
0576
0577 inline bool IsCrossFileMessage(const FieldDescriptor* field) {
0578 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
0579 field->message_type()->file() != field->file();
0580 }
0581
0582 inline std::string MakeDefaultName(const FieldDescriptor* field) {
0583 return absl::StrCat("_i_give_permission_to_break_this_code_default_",
0584 FieldName(field), "_");
0585 }
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597 inline std::string MakeDefaultFieldName(const FieldDescriptor* field) {
0598 return absl::StrCat("Impl_::", MakeDefaultName(field));
0599 }
0600
0601 inline std::string MakeVarintCachedSizeName(const FieldDescriptor* field) {
0602 return absl::StrCat("_", FieldName(field), "_cached_byte_size_");
0603 }
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616 inline std::string MakeVarintCachedSizeFieldName(const FieldDescriptor* field,
0617 bool split) {
0618 return absl::StrCat("_impl_.", split ? "_split_->" : "", "_",
0619 FieldName(field), "_cached_byte_size_");
0620 }
0621
0622
0623
0624
0625
0626 bool IsAnyMessage(const FileDescriptor* descriptor);
0627 bool IsAnyMessage(const Descriptor* descriptor);
0628
0629 bool IsWellKnownMessage(const FileDescriptor* file);
0630
0631 enum class GeneratedFileType : int { kPbH, kProtoH, kProtoStaticReflectionH };
0632
0633 inline std::string IncludeGuard(const FileDescriptor* file,
0634 GeneratedFileType file_type,
0635 const Options& options) {
0636
0637
0638 std::string extension;
0639 switch (file_type) {
0640 case GeneratedFileType::kPbH:
0641 extension = ".pb.h";
0642 break;
0643 case GeneratedFileType::kProtoH:
0644 extension = ".proto.h";
0645 break;
0646 case GeneratedFileType::kProtoStaticReflectionH:
0647 extension = ".proto.static_reflection.h";
0648 }
0649 return FilenameIdentifier(absl::StrCat(file->name(), extension));
0650 }
0651
0652
0653
0654
0655
0656 FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
0657 const Options& options,
0658 bool* has_opt_codesize_extension);
0659 inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
0660 const Options& options) {
0661 return GetOptimizeFor(file, options, nullptr);
0662 }
0663 inline bool NeedsEagerDescriptorAssignment(const FileDescriptor* file,
0664 const Options& options) {
0665 bool has_opt_codesize_extension;
0666 if (GetOptimizeFor(file, options, &has_opt_codesize_extension) ==
0667 FileOptions::CODE_SIZE &&
0668 has_opt_codesize_extension) {
0669
0670
0671
0672
0673 return true;
0674 } else {
0675
0676
0677 return false;
0678 }
0679 }
0680
0681
0682 void FlattenMessagesInFile(const FileDescriptor* file,
0683 std::vector<const Descriptor*>* result);
0684 inline std::vector<const Descriptor*> FlattenMessagesInFile(
0685 const FileDescriptor* file) {
0686 std::vector<const Descriptor*> result;
0687 FlattenMessagesInFile(file, &result);
0688 return result;
0689 }
0690
0691 std::vector<const Descriptor*> TopologicalSortMessagesInFile(
0692 const FileDescriptor* file, MessageSCCAnalyzer& scc_analyzer);
0693
0694 bool HasWeakFields(const Descriptor* desc, const Options& options);
0695 bool HasWeakFields(const FileDescriptor* file, const Options& options);
0696
0697
0698
0699 inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
0700 const Options& options) {
0701
0702 return IsLazilyVerifiedLazy(field, options);
0703 }
0704
0705 struct MessageAnalysis {
0706 bool is_recursive = false;
0707 bool contains_cord = false;
0708 bool contains_extension = false;
0709 bool contains_required = false;
0710 bool contains_weak = false;
0711 };
0712
0713
0714
0715
0716
0717 class PROTOC_EXPORT MessageSCCAnalyzer {
0718 public:
0719 explicit MessageSCCAnalyzer(const Options& options) : options_(options) {}
0720
0721 MessageAnalysis GetSCCAnalysis(const SCC* scc);
0722
0723 bool HasRequiredFields(const Descriptor* descriptor) {
0724 MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
0725 return result.contains_required || result.contains_extension;
0726 }
0727 bool HasWeakField(const Descriptor* descriptor) {
0728 MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
0729 return result.contains_weak;
0730 }
0731 const SCC* GetSCC(const Descriptor* descriptor) {
0732 return analyzer_.GetSCC(descriptor);
0733 }
0734
0735 private:
0736 struct DepsGenerator {
0737 std::vector<const Descriptor*> operator()(const Descriptor* desc) const {
0738 std::vector<const Descriptor*> deps;
0739 for (int i = 0; i < desc->field_count(); i++) {
0740 if (desc->field(i)->message_type()) {
0741 deps.push_back(desc->field(i)->message_type());
0742 }
0743 }
0744 return deps;
0745 }
0746 };
0747 SCCAnalyzer<DepsGenerator> analyzer_;
0748 Options options_;
0749 absl::flat_hash_map<const SCC*, MessageAnalysis> analysis_cache_;
0750 };
0751
0752 void ListAllFields(const Descriptor* d,
0753 std::vector<const FieldDescriptor*>* fields);
0754 void ListAllFields(const FileDescriptor* d,
0755 std::vector<const FieldDescriptor*>* fields);
0756
0757
0758
0759 bool IsLayoutOptimized(const FieldDescriptor* field, const Options& options);
0760
0761
0762
0763
0764
0765 int CollectFieldsExcludingWeakAndOneof(
0766 const Descriptor* d, const Options& options,
0767 std::vector<const FieldDescriptor*>& fields);
0768
0769 template <bool do_nested_types, class T>
0770 void ForEachField(const Descriptor* d, T&& func) {
0771 if (do_nested_types) {
0772 for (int i = 0; i < d->nested_type_count(); i++) {
0773 ForEachField<true>(d->nested_type(i), std::forward<T&&>(func));
0774 }
0775 }
0776 for (int i = 0; i < d->extension_count(); i++) {
0777 func(d->extension(i));
0778 }
0779 for (int i = 0; i < d->field_count(); i++) {
0780 func(d->field(i));
0781 }
0782 }
0783
0784 template <class T>
0785 void ForEachField(const FileDescriptor* d, T&& func) {
0786 for (int i = 0; i < d->message_type_count(); i++) {
0787 ForEachField<true>(d->message_type(i), std::forward<T&&>(func));
0788 }
0789 for (int i = 0; i < d->extension_count(); i++) {
0790 func(d->extension(i));
0791 }
0792 }
0793
0794 void ListAllTypesForServices(const FileDescriptor* fd,
0795 std::vector<const Descriptor*>* types);
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806
0807
0808
0809
0810
0811
0812
0813
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850 bool UsingImplicitWeakDescriptor(const FileDescriptor* file,
0851 const Options& options);
0852
0853
0854 std::string StrongReferenceToType(const Descriptor* desc,
0855 const Options& options);
0856
0857
0858
0859
0860
0861 std::string WeakDescriptorDataSection(absl::string_view prefix,
0862 const Descriptor* descriptor,
0863 int index_in_file_messages,
0864 const Options& options);
0865
0866
0867
0868 inline std::string WeakDefaultInstanceSection(const Descriptor* descriptor,
0869 int index_in_file_messages,
0870 const Options& options) {
0871 return WeakDescriptorDataSection("def", descriptor, index_in_file_messages,
0872 options);
0873 }
0874
0875
0876 bool UsingImplicitWeakFields(const FileDescriptor* file,
0877 const Options& options);
0878
0879
0880 bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
0881 MessageSCCAnalyzer* scc_analyzer);
0882
0883 inline std::string SimpleBaseClass(const Descriptor* desc,
0884 const Options& options) {
0885
0886 if (!HasDescriptorMethods(desc->file(), options)) return "";
0887
0888 if (UsingImplicitWeakDescriptor(desc->file(), options)) return "";
0889 if (desc->extension_range_count() != 0) return "";
0890
0891
0892 if (options.field_listener_options.inject_field_listener_events) return "";
0893 if (desc->field_count() == 0) {
0894 return "ZeroFieldsBase";
0895 }
0896
0897
0898 return "";
0899 }
0900
0901 inline bool HasSimpleBaseClass(const Descriptor* desc, const Options& options) {
0902 return !SimpleBaseClass(desc, options).empty();
0903 }
0904
0905 inline bool HasSimpleBaseClasses(const FileDescriptor* file,
0906 const Options& options) {
0907 return internal::cpp::VisitDescriptorsInFileOrder(
0908 file, [&](const Descriptor* desc) {
0909 return HasSimpleBaseClass(desc, options);
0910 });
0911 }
0912
0913
0914 inline bool HasTracker(const Descriptor* desc, const Options& options) {
0915 return options.field_listener_options.inject_field_listener_events &&
0916 desc->file()->options().optimize_for() !=
0917 google::protobuf::FileOptions::LITE_RUNTIME &&
0918 !IsMapEntryMessage(desc);
0919 }
0920
0921
0922 inline bool HasImplData(const Descriptor* desc, const Options& options) {
0923 return !HasSimpleBaseClass(desc, options);
0924 }
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966 class PROTOC_EXPORT Formatter {
0967 public:
0968 explicit Formatter(io::Printer* printer) : printer_(printer) {}
0969 Formatter(io::Printer* printer,
0970 const absl::flat_hash_map<absl::string_view, std::string>& vars)
0971 : printer_(printer), vars_(vars) {}
0972
0973 template <typename T>
0974 void Set(absl::string_view key, const T& value) {
0975 vars_[key] = ToString(value);
0976 }
0977
0978 template <typename... Args>
0979 void operator()(const char* format, const Args&... args) const {
0980 printer_->FormatInternal({ToString(args)...}, vars_, format);
0981 }
0982
0983 void Indent() const { printer_->Indent(); }
0984 void Outdent() const { printer_->Outdent(); }
0985 io::Printer* printer() const { return printer_; }
0986
0987 class PROTOC_EXPORT ScopedIndenter {
0988 public:
0989 explicit ScopedIndenter(Formatter* format) : format_(format) {
0990 format_->Indent();
0991 }
0992 ~ScopedIndenter() { format_->Outdent(); }
0993
0994 private:
0995 Formatter* format_;
0996 };
0997
0998 [[nodiscard]] ScopedIndenter ScopedIndent() { return ScopedIndenter(this); }
0999 template <typename... Args>
1000 [[nodiscard]] ScopedIndenter ScopedIndent(const char* format,
1001 const Args&&... args) {
1002 (*this)(format, static_cast<Args&&>(args)...);
1003 return ScopedIndenter(this);
1004 }
1005
1006 private:
1007 io::Printer* printer_;
1008 absl::flat_hash_map<absl::string_view, std::string> vars_;
1009
1010
1011 static std::string ToString(absl::string_view s) { return std::string(s); }
1012 template <typename I, typename = typename std::enable_if<
1013 std::is_integral<I>::value>::type>
1014 static std::string ToString(I x) {
1015 return absl::StrCat(x);
1016 }
1017 static std::string ToString(absl::Hex x) { return absl::StrCat(x); }
1018 static std::string ToString(const FieldDescriptor* d) {
1019 return Payload(d, GeneratedCodeInfo::Annotation::NONE);
1020 }
1021 static std::string ToString(const Descriptor* d) {
1022 return Payload(d, GeneratedCodeInfo::Annotation::NONE);
1023 }
1024 static std::string ToString(const EnumDescriptor* d) {
1025 return Payload(d, GeneratedCodeInfo::Annotation::NONE);
1026 }
1027 static std::string ToString(const EnumValueDescriptor* d) {
1028 return Payload(d, GeneratedCodeInfo::Annotation::NONE);
1029 }
1030 static std::string ToString(const OneofDescriptor* d) {
1031 return Payload(d, GeneratedCodeInfo::Annotation::NONE);
1032 }
1033
1034 static std::string ToString(
1035 std::tuple<const FieldDescriptor*,
1036 GeneratedCodeInfo::Annotation::Semantic>
1037 p) {
1038 return Payload(std::get<0>(p), std::get<1>(p));
1039 }
1040 static std::string ToString(
1041 std::tuple<const Descriptor*, GeneratedCodeInfo::Annotation::Semantic>
1042 p) {
1043 return Payload(std::get<0>(p), std::get<1>(p));
1044 }
1045 static std::string ToString(
1046 std::tuple<const EnumDescriptor*, GeneratedCodeInfo::Annotation::Semantic>
1047 p) {
1048 return Payload(std::get<0>(p), std::get<1>(p));
1049 }
1050 static std::string ToString(
1051 std::tuple<const EnumValueDescriptor*,
1052 GeneratedCodeInfo::Annotation::Semantic>
1053 p) {
1054 return Payload(std::get<0>(p), std::get<1>(p));
1055 }
1056 static std::string ToString(
1057 std::tuple<const OneofDescriptor*,
1058 GeneratedCodeInfo::Annotation::Semantic>
1059 p) {
1060 return Payload(std::get<0>(p), std::get<1>(p));
1061 }
1062
1063 template <typename Descriptor>
1064 static std::string Payload(const Descriptor* descriptor,
1065 GeneratedCodeInfo::Annotation::Semantic semantic) {
1066 std::vector<int> path;
1067 descriptor->GetLocationPath(&path);
1068 GeneratedCodeInfo::Annotation annotation;
1069 for (int index : path) {
1070 annotation.add_path(index);
1071 }
1072 annotation.set_source_file(descriptor->file()->name());
1073 annotation.set_semantic(semantic);
1074 return annotation.SerializeAsString();
1075 }
1076 };
1077
1078 template <typename T>
1079 std::string FieldComment(const T* field, const Options& options) {
1080 if (options.strip_nonfunctional_codegen) {
1081 return std::string(field->name());
1082 }
1083
1084
1085
1086 DebugStringOptions debug_options;
1087 debug_options.elide_group_body = true;
1088 debug_options.elide_oneof_body = true;
1089
1090 for (absl::string_view chunk :
1091 absl::StrSplit(field->DebugStringWithOptions(debug_options), '\n')) {
1092 return std::string(chunk);
1093 }
1094
1095 return "<unknown>";
1096 }
1097
1098 template <class T>
1099 void PrintFieldComment(const Formatter& format, const T* field,
1100 const Options& options) {
1101 format("// $1$\n", FieldComment(field, options));
1102 }
1103
1104 class PROTOC_EXPORT NamespaceOpener {
1105 public:
1106 explicit NamespaceOpener(
1107 io::Printer* p,
1108 io::Printer::SourceLocation loc = io::Printer::SourceLocation::current())
1109 : p_(p), loc_(loc) {}
1110
1111 explicit NamespaceOpener(
1112 const Formatter& format,
1113 io::Printer::SourceLocation loc = io::Printer::SourceLocation::current())
1114 : NamespaceOpener(format.printer(), loc) {}
1115
1116 NamespaceOpener(
1117 absl::string_view name, const Formatter& format,
1118 io::Printer::SourceLocation loc = io::Printer::SourceLocation::current())
1119 : NamespaceOpener(name, format.printer(), loc) {}
1120
1121 NamespaceOpener(
1122 absl::string_view name, io::Printer* p,
1123 io::Printer::SourceLocation loc = io::Printer::SourceLocation::current())
1124 : NamespaceOpener(p, loc) {
1125 ChangeTo(name, loc);
1126 }
1127
1128 ~NamespaceOpener() { ChangeTo("", loc_); }
1129
1130 void ChangeTo(
1131 absl::string_view name,
1132 io::Printer::SourceLocation loc = io::Printer::SourceLocation::current());
1133
1134 private:
1135 io::Printer* p_;
1136 io::Printer::SourceLocation loc_;
1137 std::vector<std::string> name_stack_;
1138 };
1139
1140 void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
1141 const Options& options, bool for_parse,
1142 absl::string_view parameters,
1143 const Formatter& format);
1144
1145 void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
1146 const Options& options, bool for_parse,
1147 absl::string_view parameters,
1148 const Formatter& format);
1149
1150 void GenerateUtf8CheckCodeForString(io::Printer* p,
1151 const FieldDescriptor* field,
1152 const Options& options, bool for_parse,
1153 absl::string_view parameters);
1154
1155 void GenerateUtf8CheckCodeForCord(io::Printer* p, const FieldDescriptor* field,
1156 const Options& options, bool for_parse,
1157 absl::string_view parameters);
1158
1159 bool IsStrictUtf8String(const FieldDescriptor* field, const Options& options);
1160
1161 inline bool ShouldGenerateExternSpecializations(const Options& options) {
1162
1163
1164
1165
1166 return !options.opensource_runtime;
1167 }
1168
1169 struct OneOfRangeImpl {
1170 struct Iterator {
1171 using iterator_category = std::forward_iterator_tag;
1172 using value_type = const OneofDescriptor*;
1173 using difference_type = int;
1174
1175 value_type operator*() { return descriptor->oneof_decl(idx); }
1176
1177 friend bool operator==(const Iterator& a, const Iterator& b) {
1178 ABSL_DCHECK(a.descriptor == b.descriptor);
1179 return a.idx == b.idx;
1180 }
1181 friend bool operator!=(const Iterator& a, const Iterator& b) {
1182 return !(a == b);
1183 }
1184
1185 Iterator& operator++() {
1186 idx++;
1187 return *this;
1188 }
1189
1190 int idx;
1191 const Descriptor* descriptor;
1192 };
1193
1194 Iterator begin() const { return {0, descriptor}; }
1195 Iterator end() const {
1196 return {descriptor->real_oneof_decl_count(), descriptor};
1197 }
1198
1199 const Descriptor* descriptor;
1200 };
1201
1202 inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; }
1203
1204
1205 PROTOC_EXPORT std::string StripProto(absl::string_view filename);
1206
1207 bool HasMessageFieldOrExtension(const Descriptor* desc);
1208
1209
1210
1211
1212
1213
1214 std::vector<io::Printer::Sub> AnnotatedAccessors(
1215 const FieldDescriptor* field, absl::Span<const absl::string_view> prefixes,
1216 std::optional<google::protobuf::io::AnnotationCollector::Semantic> semantic =
1217 std::nullopt);
1218
1219
1220
1221
1222 bool IsFileDescriptorProto(const FileDescriptor* file, const Options& options);
1223
1224
1225
1226
1227 bool ShouldGenerateClass(const Descriptor* descriptor, const Options& options);
1228
1229
1230
1231
1232
1233 bool HasOnDeserializeTracker(const Descriptor* descriptor,
1234 const Options& options);
1235
1236
1237
1238
1239
1240
1241 bool NeedsPostLoopHandler(const Descriptor* descriptor, const Options& options);
1242
1243
1244
1245
1246 inline auto GetEmitRepeatedFieldGetterSub(const Options& options,
1247 io::Printer* p) {
1248 return io::Printer::Sub{
1249 "getter",
1250 [&options, p] {
1251 switch (options.bounds_check_mode) {
1252 case BoundsCheckMode::kNoEnforcement:
1253 p->Emit(R"cc(_internal_$name_internal$().Get(index))cc");
1254 break;
1255 case BoundsCheckMode::kReturnDefaultValue:
1256 p->Emit(R"cc(
1257 $pbi$::CheckedGetOrDefault(_internal_$name_internal$(), index)
1258 )cc");
1259 break;
1260 case BoundsCheckMode::kAbort:
1261 p->Emit(R"cc(
1262 $pbi$::CheckedGetOrAbort(_internal_$name_internal$(), index)
1263 )cc");
1264 break;
1265 }
1266 }}
1267 .WithSuffix("");
1268 }
1269
1270
1271
1272
1273
1274
1275 inline auto GetEmitRepeatedFieldMutableSub(const Options& options,
1276 io::Printer* p,
1277 bool use_stringpiecefield = false) {
1278 return io::Printer::Sub{
1279 "mutable",
1280 [&options, p, use_stringpiecefield] {
1281 switch (options.bounds_check_mode) {
1282 case BoundsCheckMode::kNoEnforcement:
1283 case BoundsCheckMode::kReturnDefaultValue:
1284 if (use_stringpiecefield) {
1285 p->Emit("$field$.Mutable(index)");
1286 } else {
1287 p->Emit(
1288 R"cc(_internal_mutable_$name_internal$()->Mutable(index))cc");
1289 }
1290 break;
1291 case BoundsCheckMode::kAbort:
1292 if (use_stringpiecefield) {
1293 p->Emit("$pbi$::CheckedMutableOrAbort(&$field$, index)");
1294 } else {
1295 p->Emit(R"cc(
1296 $pbi$::CheckedMutableOrAbort(
1297 _internal_mutable_$name_internal$(), index)
1298 )cc");
1299 }
1300 break;
1301 }
1302 }}
1303 .WithSuffix("");
1304 }
1305
1306
1307 enum InitPriority {
1308 kInitPriority101,
1309 kInitPriority102,
1310 };
1311
1312 }
1313 }
1314 }
1315 }
1316
1317 #include "google/protobuf/port_undef.inc"
1318
1319 #endif