Move definitions for empty private constructors out of line.

When building in debug mode, clang uses constructor type homing as an
optimization for debug info size. This means the debug info for types is
emitted at the same time as the constructor definition.

Some `*Descriptor` types in this file only have an inline constructor which is
never called (by design). Instead of properly constructing these objects, it
looks like memory is allocated elsewhere and then cast to the needed type. This
causes the compiler to never emit neither the inline constructor definition nor
the debug info for these types, which harms the debugger experience (it is also
technically undefined behavior).

This change moves their definitions out of line to the .cc file. This doesn't
solve the UB but it makes the compiler emit the definitions for the
constructors somewhere, and thus the debug info too.

PiperOrigin-RevId: 533579527
pull/12863/head
Jorge Gorbe Moya 2 years ago committed by Copybara-Service
parent 1147bb6284
commit af23ec69a8
  1. 15
      src/google/protobuf/descriptor.cc
  2. 16
      src/google/protobuf/descriptor.h

@ -2579,6 +2579,21 @@ std::string FieldDescriptor::DefaultValueAsString(
return "";
}
// Out-of-line constructor definitions ==============================
// When using constructor type homing in Clang, debug info for a type
// is only emitted when a constructor definition is emitted, as an
// optimization. These constructors are never called, so we define them
// out of line to make sure the debug info is emitted somewhere.
Descriptor::Descriptor() {}
FieldDescriptor::FieldDescriptor() {}
OneofDescriptor::OneofDescriptor() {}
EnumDescriptor::EnumDescriptor() {}
EnumValueDescriptor::EnumValueDescriptor() {}
ServiceDescriptor::ServiceDescriptor() {}
MethodDescriptor::MethodDescriptor() {}
FileDescriptor::FileDescriptor() {}
// CopyTo methods ====================================================
void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {

@ -660,7 +660,7 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase {
// and update them to initialize the field.
// Must be constructed using DescriptorPool.
Descriptor() {}
Descriptor();
friend class DescriptorBuilder;
friend class DescriptorPool;
friend class EnumDescriptor;
@ -1077,7 +1077,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase {
static const char* const kLabelToName[MAX_LABEL + 1];
// Must be constructed using DescriptorPool.
FieldDescriptor() {}
FieldDescriptor();
friend class DescriptorBuilder;
friend class FileDescriptor;
friend class Descriptor;
@ -1173,7 +1173,7 @@ class PROTOBUF_EXPORT OneofDescriptor : private internal::SymbolBase {
// in descriptor.cc and update them to initialize the field.
// Must be constructed using DescriptorPool.
OneofDescriptor() {}
OneofDescriptor();
friend class DescriptorBuilder;
friend class Descriptor;
friend class FieldDescriptor;
@ -1363,7 +1363,7 @@ class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase {
// descriptor.cc and update them to initialize the field.
// Must be constructed using DescriptorPool.
EnumDescriptor() {}
EnumDescriptor();
friend class DescriptorBuilder;
friend class Descriptor;
friend class FieldDescriptor;
@ -1456,7 +1456,7 @@ class PROTOBUF_EXPORT EnumValueDescriptor : private internal::SymbolBaseN<0>,
// in descriptor.cc and update them to initialize the field.
// Must be constructed using DescriptorPool.
EnumValueDescriptor() {}
EnumValueDescriptor();
friend class DescriptorBuilder;
friend class EnumDescriptor;
friend class DescriptorPool;
@ -1546,7 +1546,7 @@ class PROTOBUF_EXPORT ServiceDescriptor : private internal::SymbolBase {
// descriptor.cc and update them to initialize the field.
// Must be constructed using DescriptorPool.
ServiceDescriptor() {}
ServiceDescriptor();
friend class DescriptorBuilder;
friend class FileDescriptor;
friend class MethodDescriptor;
@ -1641,7 +1641,7 @@ class PROTOBUF_EXPORT MethodDescriptor : private internal::SymbolBase {
// descriptor.cc and update them to initialize the field.
// Must be constructed using DescriptorPool.
MethodDescriptor() {}
MethodDescriptor();
friend class DescriptorBuilder;
friend class ServiceDescriptor;
};
@ -1875,7 +1875,7 @@ class PROTOBUF_EXPORT FileDescriptor : private internal::SymbolBase {
// of Allocate<FileDescriptor>() and AllocateArray<FileDescriptor>() in
// descriptor.cc and update them to initialize the field.
FileDescriptor() {}
FileDescriptor();
friend class DescriptorBuilder;
friend class DescriptorPool;
friend class Descriptor;

Loading…
Cancel
Save