Rollback the behavior of using `constexpr` on `_table_` instances for all types except for the types in descriptor.proto

DLLs get in the way of making these tables constexpr in the general case because cross-DLL references are not constant.
However, we need descriptor.proto tables to be constexpr so we keep constexpr there were we know it works. They do not reference other DLLs.

PiperOrigin-RevId: 531256398
pull/12458/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent a46bc0d7d7
commit 903968a548
  1. 17
      src/google/protobuf/compiler/cpp/file.cc
  2. 2
      src/google/protobuf/compiler/cpp/file.h
  3. 11
      src/google/protobuf/compiler/cpp/helpers.cc
  4. 5
      src/google/protobuf/compiler/cpp/helpers.h
  5. 9
      src/google/protobuf/compiler/cpp/parse_function_generator.cc

@ -529,17 +529,6 @@ void FileGenerator::GenerateSourcePrelude(io::Printer* p) {
}
}
bool FileGenerator::IsFileDescriptorProto() const {
if (Namespace(file_, options_) !=
absl::StrCat("::", ProtobufNamespace(options_))) {
return false;
}
for (int i = 0; i < file_->message_type_count(); ++i) {
if (file_->message_type(i)->name() == "FileDescriptorProto") return true;
}
return false;
}
void FileGenerator::GenerateSourceDefaultInstance(int idx, io::Printer* p) {
MessageGenerator* generator = message_generators_[idx].get();
@ -580,7 +569,7 @@ void FileGenerator::GenerateSourceDefaultInstance(int idx, io::Printer* p) {
generator->GenerateConstexprConstructor(p);
if (IsFileDescriptorProto()) {
if (IsFileDescriptorProto(file_, options_)) {
p->Emit(
{
{"type", DefaultInstanceType(generator->descriptor(), options_)},
@ -1158,7 +1147,7 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* p) {
// However, we must provide a way to force initialize the default instances
// of FileDescriptorProto which will be used during registration of other
// files.
if (IsFileDescriptorProto()) {
if (IsFileDescriptorProto(file_, options_)) {
NamespaceOpener ns(p);
ns.ChangeTo(absl::StrCat(ProtobufNamespace(options_), "::internal"));
p->Emit(
@ -1306,7 +1295,7 @@ void FileGenerator::GenerateForwardDeclarations(io::Printer* p) {
decl.second.PrintTopLevelDecl(p, options_);
}
if (IsFileDescriptorProto()) {
if (IsFileDescriptorProto(file_, options_)) {
ns.ChangeTo(absl::StrCat(ProtobufNamespace(options_), "::internal"));
p->Emit(R"cc(
//~ Emit wants an indented line, so give it a comment to strip.

@ -168,8 +168,6 @@ class FileGenerator {
void GenerateProto2NamespaceEnumSpecializations(io::Printer* p);
bool IsFileDescriptorProto() const;
// Sometimes the names we use in a .proto file happen to be defined as
// macros on some platforms (e.g., macro/minor used in plugin.proto are
// defined as macros in sys/types.h on FreeBSD and a few other platforms).

@ -1648,6 +1648,17 @@ std::vector<io::Printer::Sub> AnnotatedAccessors(
return vars;
}
bool IsFileDescriptorProto(const FileDescriptor* file, const Options& options) {
if (Namespace(file, options) !=
absl::StrCat("::", ProtobufNamespace(options))) {
return false;
}
for (int i = 0; i < file->message_type_count(); ++i) {
if (file->message_type(i)->name() == "FileDescriptorProto") return true;
}
return false;
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf

@ -1049,6 +1049,11 @@ std::vector<io::Printer::Sub> AnnotatedAccessors(
absl::optional<google::protobuf::io::AnnotationCollector::Semantic> semantic =
absl::nullopt);
// Check whether `file` represents the .proto file FileDescriptorProto and
// friends. This file needs special handling because it must be usable during
// dynamic initialization.
bool IsFileDescriptorProto(const FileDescriptor* file, const Options& options);
} // namespace cpp
} // namespace compiler
} // namespace protobuf

@ -406,9 +406,16 @@ void ParseFunctionGenerator::GenerateTailCallTable(Formatter& format) {
// unknown fields and potentially an extension range.
auto field_num_to_entry_table = MakeNumToEntryTable(ordered_fields_);
format(
"constexpr ::_pbi::TcParseTable<$1$, $2$, $3$, $4$, $5$> "
"$1$ ::_pbi::TcParseTable<$2$, $3$, $4$, $5$, $6$> "
"$classname$::_table_ = "
"{\n",
// FileDescriptorProto's table must be constant initialized. For MSVC this
// means using `constexpr`. However, we can't use `constexpr` for all
// tables because it breaks when crossing DLL boundaries.
// FileDescriptorProto is safe from this.
IsFileDescriptorProto(descriptor_->file(), options_)
? "constexpr"
: "PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1\nconst",
tc_table_info_->table_size_log2, ordered_fields_.size(),
tc_table_info_->aux_entries.size(),
FieldNameDataSize(tc_table_info_->field_name_data),

Loading…
Cancel
Save