Coverage Report

Created: 2023-11-19 07:03

/proc/self/cwd/external/com_google_protobuf/src/google/protobuf/descriptor.cc
Line
Count
Source (jump to first uncovered line)
1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2008 Google Inc.  All rights reserved.
3
// https://developers.google.com/protocol-buffers/
4
//
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
7
// met:
8
//
9
//     * Redistributions of source code must retain the above copyright
10
// notice, this list of conditions and the following disclaimer.
11
//     * Redistributions in binary form must reproduce the above
12
// copyright notice, this list of conditions and the following disclaimer
13
// in the documentation and/or other materials provided with the
14
// distribution.
15
//     * Neither the name of Google Inc. nor the names of its
16
// contributors may be used to endorse or promote products derived from
17
// this software without specific prior written permission.
18
//
19
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31
// Author: kenton@google.com (Kenton Varda)
32
//  Based on original Protocol Buffers design by
33
//  Sanjay Ghemawat, Jeff Dean, and others.
34
35
#include "google/protobuf/descriptor.h"
36
37
#include <algorithm>
38
#include <array>
39
#include <cstdlib>
40
#include <functional>
41
#include <iterator>
42
#include <limits>
43
#include <memory>
44
#include <sstream>
45
#include <string>
46
#include <type_traits>
47
#include <vector>
48
49
#include "google/protobuf/stubs/common.h"
50
#include "absl/base/call_once.h"
51
#include "absl/base/casts.h"
52
#include "absl/base/dynamic_annotations.h"
53
#include "absl/container/btree_map.h"
54
#include "absl/container/flat_hash_map.h"
55
#include "absl/container/flat_hash_set.h"
56
#include "absl/functional/function_ref.h"
57
#include "absl/hash/hash.h"
58
#include "absl/log/absl_check.h"
59
#include "absl/log/absl_log.h"
60
#include "absl/status/statusor.h"
61
#include "absl/strings/ascii.h"
62
#include "absl/strings/escaping.h"
63
#include "absl/strings/match.h"
64
#include "absl/strings/str_cat.h"
65
#include "absl/strings/str_format.h"
66
#include "absl/strings/str_join.h"
67
#include "absl/strings/str_split.h"
68
#include "absl/strings/string_view.h"
69
#include "absl/strings/strip.h"
70
#include "absl/strings/substitute.h"
71
#include "absl/synchronization/mutex.h"
72
#include "absl/types/optional.h"
73
#include "google/protobuf/any.h"
74
#include "google/protobuf/descriptor.pb.h"
75
#include "google/protobuf/descriptor_database.h"
76
#include "google/protobuf/descriptor_legacy.h"
77
#include "google/protobuf/descriptor_visitor.h"
78
#include "google/protobuf/dynamic_message.h"
79
#include "google/protobuf/generated_message_util.h"
80
#include "google/protobuf/io/strtod.h"
81
#include "google/protobuf/io/tokenizer.h"
82
#include "google/protobuf/port.h"
83
#include "google/protobuf/repeated_ptr_field.h"
84
#include "google/protobuf/text_format.h"
85
#include "google/protobuf/unknown_field_set.h"
86
87
88
// Must be included last.
89
#include "google/protobuf/port_def.inc"
90
91
namespace google {
92
namespace protobuf {
93
namespace {
94
using ::google::protobuf::internal::DownCast;
95
96
const int kPackageLimit = 100;
97
98
99
0
std::string ToCamelCase(const std::string& input, bool lower_first) {
100
0
  bool capitalize_next = !lower_first;
101
0
  std::string result;
102
0
  result.reserve(input.size());
103
104
0
  for (char character : input) {
105
0
    if (character == '_') {
106
0
      capitalize_next = true;
107
0
    } else if (capitalize_next) {
108
0
      result.push_back(absl::ascii_toupper(character));
109
0
      capitalize_next = false;
110
0
    } else {
111
0
      result.push_back(character);
112
0
    }
113
0
  }
114
115
  // Lower-case the first letter.
116
0
  if (lower_first && !result.empty()) {
117
0
    result[0] = absl::ascii_tolower(result[0]);
118
0
  }
119
120
0
  return result;
121
0
}
122
123
0
std::string ToJsonName(const std::string& input) {
124
0
  bool capitalize_next = false;
125
0
  std::string result;
126
0
  result.reserve(input.size());
127
128
0
  for (char character : input) {
129
0
    if (character == '_') {
130
0
      capitalize_next = true;
131
0
    } else if (capitalize_next) {
132
0
      result.push_back(absl::ascii_toupper(character));
133
0
      capitalize_next = false;
134
0
    } else {
135
0
      result.push_back(character);
136
0
    }
137
0
  }
138
139
0
  return result;
140
0
}
141
142
template <typename OptionsT>
143
0
bool IsLegacyJsonFieldConflictEnabled(const OptionsT& options) {
144
0
#ifdef __GNUC__
145
0
#pragma GCC diagnostic push
146
0
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
147
0
#endif
148
0
  return options.deprecated_legacy_json_field_conflicts();
149
0
#ifdef __GNUC__
150
0
#pragma GCC diagnostic pop
151
0
#endif
152
0
}
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::IsLegacyJsonFieldConflictEnabled<google::protobuf::MessageOptions>(google::protobuf::MessageOptions const&)
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::IsLegacyJsonFieldConflictEnabled<google::protobuf::EnumOptions>(google::protobuf::EnumOptions const&)
153
154
// Backport of fold expressions for the comma operator to C++11.
155
// Usage:  Fold({expr...});
156
// Guaranteed to evaluate left-to-right
157
struct ExpressionEater {
158
  template <typename T>
159
0
  ExpressionEater(T&&) {}  // NOLINT
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<bool>(bool&&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<int&>(int&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<char*&>(char*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::SourceCodeInfo*&>(google::protobuf::SourceCodeInfo*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::FileDescriptorTables*&>(google::protobuf::FileDescriptorTables*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::MessageOptions*&>(google::protobuf::MessageOptions*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::FieldOptions*&>(google::protobuf::FieldOptions*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::EnumOptions*&>(google::protobuf::EnumOptions*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::EnumValueOptions*&>(google::protobuf::EnumValueOptions*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::ExtensionRangeOptions*&>(google::protobuf::ExtensionRangeOptions*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::OneofOptions*&>(google::protobuf::OneofOptions*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::ServiceOptions*&>(google::protobuf::ServiceOptions*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::MethodOptions*&>(google::protobuf::MethodOptions*&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::FileOptions*&>(google::protobuf::FileOptions*&)
160
};
161
0
void Fold(std::initializer_list<ExpressionEater>) {}
162
163
template <int R>
164
0
constexpr size_t RoundUpTo(size_t n) {
165
0
  static_assert((R & (R - 1)) == 0, "Must be power of two");
166
0
  return (n + (R - 1)) & ~(R - 1);
167
0
}
168
169
0
constexpr size_t Max(size_t a, size_t b) { return a > b ? a : b; }
170
template <typename T, typename... Ts>
171
0
constexpr size_t Max(T a, Ts... b) {
172
0
  return Max(a, Max(b...));
173
0
}
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::Max<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long>(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
174
175
template <typename T>
176
0
constexpr size_t EffectiveAlignof() {
177
0
  // `char` is special in that it gets aligned to 8. It is where we drop the
178
0
  // trivial structs.
179
0
  return std::is_same<T, char>::value ? 8 : alignof(T);
180
0
}
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<char>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::SourceCodeInfo>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::FileDescriptorTables>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::MessageOptions>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::FieldOptions>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::EnumOptions>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::EnumValueOptions>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::ExtensionRangeOptions>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::OneofOptions>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::ServiceOptions>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::MethodOptions>()
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::EffectiveAlignof<google::protobuf::FileOptions>()
181
182
template <int align, typename U, typename... T>
183
using AppendIfAlign =
184
    typename std::conditional<EffectiveAlignof<U>() == align, void (*)(T..., U),
185
                              void (*)(T...)>::type;
186
187
// Metafunction to sort types in descending order of alignment.
188
// Useful for the flat allocator to ensure proper alignment of all elements
189
// without having to add padding.
190
// Instead of implementing a proper sort metafunction we just do a
191
// filter+merge, which is much simpler to write as a metafunction.
192
// We have a fixed set of alignments we can filter on.
193
// For simplicity we use a function pointer as a type list.
194
template <typename In, typename T16, typename T8, typename T4, typename T2,
195
          typename T1>
196
struct TypeListSortImpl;
197
198
template <typename... T16, typename... T8, typename... T4, typename... T2,
199
          typename... T1>
200
struct TypeListSortImpl<void (*)(), void (*)(T16...), void (*)(T8...),
201
                        void (*)(T4...), void (*)(T2...), void (*)(T1...)> {
202
  using type = void (*)(T16..., T8..., T4..., T2..., T1...);
203
};
204
205
template <typename First, typename... Rest, typename... T16, typename... T8,
206
          typename... T4, typename... T2, typename... T1>
207
struct TypeListSortImpl<void (*)(First, Rest...), void (*)(T16...),
208
                        void (*)(T8...), void (*)(T4...), void (*)(T2...),
209
                        void (*)(T1...)> {
210
  using type = typename TypeListSortImpl<
211
      void (*)(Rest...), AppendIfAlign<16, First, T16...>,
212
      AppendIfAlign<8, First, T8...>, AppendIfAlign<4, First, T4...>,
213
      AppendIfAlign<2, First, T2...>, AppendIfAlign<1, First, T1...>>::type;
214
};
215
216
template <typename... T>
217
using SortByAlignment =
218
    typename TypeListSortImpl<void (*)(T...), void (*)(), void (*)(),
219
                              void (*)(), void (*)(), void (*)()>::type;
220
221
template <template <typename...> class C, typename... T>
222
auto ApplyTypeList(void (*)(T...)) -> C<T...>;
223
224
template <typename T>
225
0
constexpr int FindTypeIndex() {
226
0
  return -1;
227
0
}
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions>()
228
229
template <typename T, typename T1, typename... Ts>
230
0
constexpr int FindTypeIndex() {
231
0
  return std::is_same<T, T1>::value ? 0 : FindTypeIndex<T, Ts...>() + 1;
232
0
}
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<char, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::SourceCodeInfo, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileDescriptorTables, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MessageOptions, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FieldOptions, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumOptions, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::EnumValueOptions, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ExtensionRangeOptions, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::OneofOptions, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::ServiceOptions, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::MethodOptions, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FindTypeIndex<google::protobuf::FileOptions, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>()
233
234
// A type to value map, where the possible keys as specified in `Keys...`.
235
// The values for key `K` is `ValueT<K>`
236
template <template <typename> class ValueT, typename... Keys>
237
class TypeMap {
238
 public:
239
  template <typename K>
240
0
  ValueT<K>& Get() {
241
0
    return static_cast<Base<K>&>(payload_).value;
242
0
  }
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::FileDescriptorTables>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::FileOptions>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::SourceCodeInfo>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<char>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::ServiceOptions>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::MethodOptions>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::MessageOptions>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::ExtensionRangeOptions>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::OneofOptions>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::EnumOptions>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::EnumValueOptions>()
Unexecuted instantiation: descriptor.cc:int& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::FieldOptions>()
Unexecuted instantiation: descriptor.cc:char*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<char>()
Unexecuted instantiation: descriptor.cc:google::protobuf::SourceCodeInfo*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::SourceCodeInfo>()
Unexecuted instantiation: descriptor.cc:google::protobuf::FileDescriptorTables*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::FileDescriptorTables>()
Unexecuted instantiation: descriptor.cc:google::protobuf::MessageOptions*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::MessageOptions>()
Unexecuted instantiation: descriptor.cc:google::protobuf::FieldOptions*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::FieldOptions>()
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumOptions*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::EnumOptions>()
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumValueOptions*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::EnumValueOptions>()
Unexecuted instantiation: descriptor.cc:google::protobuf::ExtensionRangeOptions*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::ExtensionRangeOptions>()
Unexecuted instantiation: descriptor.cc:google::protobuf::OneofOptions*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::OneofOptions>()
Unexecuted instantiation: descriptor.cc:google::protobuf::ServiceOptions*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::ServiceOptions>()
Unexecuted instantiation: descriptor.cc:google::protobuf::MethodOptions*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::MethodOptions>()
Unexecuted instantiation: descriptor.cc:google::protobuf::FileOptions*& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::FileOptions>()
243
244
  template <typename K>
245
0
  const ValueT<K>& Get() const {
246
0
    return static_cast<const Base<K>&>(payload_).value;
247
0
  }
Unexecuted instantiation: descriptor.cc:char* const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::PointerT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<char>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<char>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::SourceCodeInfo>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::FileDescriptorTables>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::MessageOptions>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::FieldOptions>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::EnumOptions>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::EnumValueOptions>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::ExtensionRangeOptions>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::OneofOptions>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::ServiceOptions>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::MethodOptions>() const
Unexecuted instantiation: descriptor.cc:int const& google::protobuf::(anonymous namespace)::TypeMap<google::protobuf::(anonymous namespace)::IntT, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Get<google::protobuf::FileOptions>() const
248
249
 private:
250
  template <typename K>
251
  struct Base {
252
    ValueT<K> value{};
253
  };
254
  struct Payload : Base<Keys>... {};
255
  Payload payload_;
256
};
257
258
template <typename T>
259
using IntT = int;
260
template <typename T>
261
using PointerT = T*;
262
263
// Manages an allocation of sequential arrays of type `T...`.
264
// It is more space efficient than storing N (ptr, size) pairs, by storing only
265
// the pointer to the head and the boundaries between the arrays.
266
template <typename... T>
267
class FlatAllocation {
268
 public:
269
  static constexpr size_t kMaxAlign = Max(alignof(T)...);
270
271
0
  FlatAllocation(const TypeMap<IntT, T...>& ends) : ends_(ends) {
272
    // The arrays start just after FlatAllocation, so adjust the ends.
273
0
    Fold({(ends_.template Get<T>() +=
274
0
           RoundUpTo<kMaxAlign>(sizeof(FlatAllocation)))...});
275
0
    Fold({Init<T>()...});
276
0
  }
277
278
0
  void Destroy() {
279
0
    Fold({Destroy<T>()...});
280
0
    internal::SizedDelete(this, total_bytes());
281
0
  }
282
283
  template <int I>
284
  using type = typename std::tuple_element<I, std::tuple<T...>>::type;
285
286
  // Gets a tuple of the head pointers for the arrays
287
0
  TypeMap<PointerT, T...> Pointers() const {
288
0
    TypeMap<PointerT, T...> out;
289
0
    Fold({(out.template Get<T>() = Begin<T>())...});
290
0
    return out;
291
0
  }
292
293
294
 private:
295
  // Total number of bytes used by all arrays.
296
0
  int total_bytes() const {
297
    // Get the last end.
298
0
    return ends_.template Get<typename std::tuple_element<
299
0
        sizeof...(T) - 1, std::tuple<T...>>::type>();
300
0
  }
301
302
303
  template <typename U>
304
0
  int BeginOffset() const {
305
0
    constexpr int type_index = FindTypeIndex<U, T...>();
306
    // Avoid a negative value here to keep it compiling when type_index == 0
307
0
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
308
0
    using PrevType =
309
0
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
310
    // Ensure the types are properly aligned.
311
0
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
312
0
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
313
0
                           : ends_.template Get<PrevType>();
314
0
  }
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::SourceCodeInfo>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::FileDescriptorTables>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::MessageOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::FieldOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::EnumOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::EnumValueOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::ExtensionRangeOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::OneofOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::ServiceOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::MethodOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<google::protobuf::FileOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::BeginOffset<char>() const
315
316
  template <typename U>
317
0
  int EndOffset() const {
318
0
    return ends_.template Get<U>();
319
0
  }
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::SourceCodeInfo>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::FileDescriptorTables>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::MessageOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::FieldOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::EnumOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::EnumValueOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::ExtensionRangeOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::OneofOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::ServiceOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::MethodOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<google::protobuf::FileOptions>() const
Unexecuted instantiation: descriptor.cc:int google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::EndOffset<char>() const
320
321
  // Avoid the reinterpret_cast if the array is empty.
322
  // Clang's Control Flow Integrity does not like the cast pointing to memory
323
  // that is not yet initialized to be of that type.
324
  // (from -fsanitize=cfi-unrelated-cast)
325
  template <typename U>
326
0
  U* Begin() const {
327
0
    int begin = BeginOffset<U>(), end = EndOffset<U>();
328
0
    if (begin == end) return nullptr;
329
0
    return reinterpret_cast<U*>(data() + begin);
330
0
  }
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >() const
Unexecuted instantiation: descriptor.cc:google::protobuf::SourceCodeInfo* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::SourceCodeInfo>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::FileDescriptorTables* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::FileDescriptorTables>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::MessageOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::MessageOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::FieldOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::FieldOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::EnumOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumValueOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::EnumValueOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::ExtensionRangeOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::ExtensionRangeOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::OneofOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::OneofOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::ServiceOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::ServiceOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::MethodOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::MethodOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::FileOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<google::protobuf::FileOptions>() const
Unexecuted instantiation: descriptor.cc:char* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Begin<char>() const
331
332
  template <typename U>
333
0
  U* End() const {
334
0
    int begin = BeginOffset<U>(), end = EndOffset<U>();
335
0
    if (begin == end) return nullptr;
336
0
    return reinterpret_cast<U*>(data() + end);
337
0
  }
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >() const
Unexecuted instantiation: descriptor.cc:google::protobuf::SourceCodeInfo* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::SourceCodeInfo>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::FileDescriptorTables* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::FileDescriptorTables>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::MessageOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::MessageOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::FieldOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::FieldOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::EnumOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumValueOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::EnumValueOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::ExtensionRangeOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::ExtensionRangeOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::OneofOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::OneofOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::ServiceOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::ServiceOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::MethodOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::MethodOptions>() const
Unexecuted instantiation: descriptor.cc:google::protobuf::FileOptions* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<google::protobuf::FileOptions>() const
Unexecuted instantiation: descriptor.cc:char* google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::End<char>() const
338
339
  template <typename U>
340
0
  bool Init() {
341
    // Skip for the `char` block. No need to zero initialize it.
342
0
    if (std::is_same<U, char>::value) return true;
343
0
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
344
0
         p != end; p += sizeof(U)) {
345
0
      ::new (p) U{};
346
0
    }
347
0
    return true;
348
0
  }
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<char>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::SourceCodeInfo>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::FileDescriptorTables>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::MessageOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::FieldOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::EnumOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::EnumValueOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::ExtensionRangeOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::OneofOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::ServiceOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::MethodOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Init<google::protobuf::FileOptions>()
349
350
  template <typename U>
351
0
  bool Destroy() {
352
0
    if (std::is_trivially_destructible<U>::value) return true;
353
0
    for (U* it = Begin<U>(), *end = End<U>(); it != end; ++it) {
354
0
      it->~U();
355
0
    }
356
0
    return true;
357
0
  }
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<char>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::SourceCodeInfo>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::FileDescriptorTables>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::MessageOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::FieldOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::EnumOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::EnumValueOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::ExtensionRangeOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::OneofOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::ServiceOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::MethodOptions>()
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocation<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::Destroy<google::protobuf::FileOptions>()
358
359
0
  char* data() const {
360
0
    return const_cast<char*>(reinterpret_cast<const char*>(this));
361
0
  }
362
363
  TypeMap<IntT, T...> ends_;
364
};
365
366
template <typename... T>
367
0
TypeMap<IntT, T...> CalculateEnds(const TypeMap<IntT, T...>& sizes) {
368
0
  int total = 0;
369
0
  TypeMap<IntT, T...> out;
370
0
  Fold({(out.template Get<T>() = total +=
371
0
         sizeof(T) * sizes.template Get<T>())...});
372
0
  return out;
373
0
}
374
375
// The implementation for FlatAllocator below.
376
// This separate class template makes it easier to have methods that fold on
377
// `T...`.
378
template <typename... T>
379
class FlatAllocatorImpl {
380
 public:
381
  using Allocation = FlatAllocation<T...>;
382
383
  template <typename U>
384
0
  void PlanArray(int array_size) {
385
    // We can't call PlanArray after FinalizePlanning has been called.
386
0
    ABSL_CHECK(!has_allocated());
387
0
    if (std::is_trivially_destructible<U>::value) {
388
      // Trivial types are aligned to 8 bytes.
389
0
      static_assert(alignof(U) <= 8, "");
390
0
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
391
0
    } else {
392
      // Since we can't use `if constexpr`, just make the expression compile
393
      // when this path is not taken.
394
0
      using TypeToUse =
395
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
396
0
                                    char, U>::type;
397
0
      total_.template Get<TypeToUse>() += array_size;
398
0
    }
399
0
  }
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::FileDescriptorTables>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::FileOptions>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::SourceCodeInfo>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::ServiceDescriptor>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::ServiceOptions>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::MethodDescriptor>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::MethodOptions>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::MessageOptions>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::ExtensionRangeOptions>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::Descriptor::ReservedRange>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::OneofDescriptor>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::OneofOptions>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::EnumOptions>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::EnumValueOptions>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::EnumDescriptor::ReservedRange>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::FieldDescriptor>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::FieldOptions>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<int>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::FileDescriptor const*>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::EnumValueDescriptor>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::FileDescriptor>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::EnumDescriptor>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::Descriptor>(int)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::PlanArray<google::protobuf::Descriptor::ExtensionRange>(int)
400
401
  template <typename U>
402
0
  U* AllocateArray(int array_size) {
403
0
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
404
0
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
405
406
    // We can only allocate after FinalizePlanning has been called.
407
0
    ABSL_CHECK(has_allocated());
408
409
0
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
410
0
    int& used = used_.template Get<TypeToUse>();
411
0
    U* res = reinterpret_cast<U*>(data + used);
412
0
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
413
0
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
414
0
    return res;
415
0
  }
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumValueDescriptor* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::EnumValueDescriptor>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumDescriptor* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::EnumDescriptor>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::Descriptor* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::Descriptor>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::Descriptor::ExtensionRange* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::Descriptor::ExtensionRange>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::FileDescriptor* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::FileDescriptor>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::FileOptions* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::FileOptions>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::SourceCodeInfo* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::SourceCodeInfo>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::FileDescriptorTables* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::FileDescriptorTables>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::FileDescriptor const** google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::FileDescriptor const*>(int)
Unexecuted instantiation: descriptor.cc:int* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<int>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::ServiceDescriptor* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::ServiceDescriptor>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::FieldDescriptor* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::FieldDescriptor>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::OneofDescriptor* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::OneofDescriptor>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::Descriptor::ReservedRange* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::Descriptor::ReservedRange>(int)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const** google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::MessageOptions* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::MessageOptions>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::FieldOptions* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::FieldOptions>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::ExtensionRangeOptions* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::ExtensionRangeOptions>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::OneofOptions* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::OneofOptions>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumDescriptor::ReservedRange* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::EnumDescriptor::ReservedRange>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumOptions* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::EnumOptions>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::EnumValueOptions* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::EnumValueOptions>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::MethodDescriptor* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::MethodDescriptor>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::ServiceOptions* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::ServiceOptions>(int)
Unexecuted instantiation: descriptor.cc:google::protobuf::MethodOptions* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateArray<google::protobuf::MethodOptions>(int)
416
417
  template <typename... In>
418
0
  const std::string* AllocateStrings(In&&... in) {
419
0
    std::string* strings = AllocateArray<std::string>(sizeof...(in));
420
0
    std::string* res = strings;
421
0
    Fold({(*strings++ = std::string(std::forward<In>(in)))...});
422
0
    return res;
423
0
  }
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<absl::lts_20230125::string_view>(absl::lts_20230125::string_view&&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<char const (&) [1]>(char const (&) [1])
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<absl::lts_20230125::string_view&, absl::lts_20230125::string_view&>(absl::lts_20230125::string_view&, absl::lts_20230125::string_view&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<char const (&) [18], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(char const (&) [18], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<absl::lts_20230125::string_view&>(absl::lts_20230125::string_view&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
424
425
  // Allocate all 5 names of the field:
426
  // name, full name, lowercase, camelcase and json.
427
  // It will dedup the strings when possible.
428
  // The resulting array contains `name` at index 0, `full_name` at index 1
429
  // and the other 3 indices are specified in the result.
430
  void PlanFieldNames(const std::string& name,
431
0
                      const std::string* opt_json_name) {
432
0
    ABSL_CHECK(!has_allocated());
433
434
    // Fast path for snake_case names, which follow the style guide.
435
0
    if (opt_json_name == nullptr) {
436
0
      switch (GetFieldNameCase(name)) {
437
0
        case FieldNameCase::kAllLower:
438
          // Case 1: they are all the same.
439
0
          return PlanArray<std::string>(2);
440
0
        case FieldNameCase::kSnakeCase:
441
          // Case 2: name==lower, camel==json
442
0
          return PlanArray<std::string>(3);
443
0
        default:
444
0
          break;
445
0
      }
446
0
    }
447
448
0
    std::string lowercase_name = name;
449
0
    absl::AsciiStrToLower(&lowercase_name);
450
451
0
    std::string camelcase_name = ToCamelCase(name, /* lower_first = */ true);
452
0
    std::string json_name =
453
0
        opt_json_name != nullptr ? *opt_json_name : ToJsonName(name);
454
455
0
    absl::string_view all_names[] = {name, lowercase_name, camelcase_name,
456
0
                                     json_name};
457
0
    std::sort(all_names, all_names + 4);
458
0
    int unique =
459
0
        static_cast<int>(std::unique(all_names, all_names + 4) - all_names);
460
461
0
    PlanArray<std::string>(unique + 1);
462
0
  }
463
464
  struct FieldNamesResult {
465
    const std::string* array;
466
    int lowercase_index;
467
    int camelcase_index;
468
    int json_index;
469
  };
470
  FieldNamesResult AllocateFieldNames(const std::string& name,
471
                                      const std::string& scope,
472
0
                                      const std::string* opt_json_name) {
473
0
    ABSL_CHECK(has_allocated());
474
475
0
    std::string full_name =
476
0
        scope.empty() ? name : absl::StrCat(scope, ".", name);
477
478
    // Fast path for snake_case names, which follow the style guide.
479
0
    if (opt_json_name == nullptr) {
480
0
      switch (GetFieldNameCase(name)) {
481
0
        case FieldNameCase::kAllLower:
482
          // Case 1: they are all the same.
483
0
          return {AllocateStrings(name, std::move(full_name)), 0, 0, 0};
484
0
        case FieldNameCase::kSnakeCase:
485
          // Case 2: name==lower, camel==json
486
0
          return {AllocateStrings(name, std::move(full_name),
487
0
                                  ToCamelCase(name, /* lower_first = */ true)),
488
0
                  0, 2, 2};
489
0
        default:
490
0
          break;
491
0
      }
492
0
    }
493
494
0
    std::vector<std::string> names;
495
0
    names.push_back(name);
496
0
    names.push_back(std::move(full_name));
497
498
0
    const auto push_name = [&](std::string new_name) {
499
0
      for (size_t i = 0; i < names.size(); ++i) {
500
        // Do not compare the full_name. It is unlikely to match, except in
501
        // custom json_name. We are not taking this into account in
502
        // PlanFieldNames so better to not try it.
503
0
        if (i == 1) continue;
504
0
        if (names[i] == new_name) return i;
505
0
      }
506
0
      names.push_back(std::move(new_name));
507
0
      return names.size() - 1;
508
0
    };
509
510
0
    FieldNamesResult result{nullptr, 0, 0, 0};
511
512
0
    std::string lowercase_name = name;
513
0
    absl::AsciiStrToLower(&lowercase_name);
514
0
    result.lowercase_index = push_name(std::move(lowercase_name));
515
0
    result.camelcase_index =
516
0
        push_name(ToCamelCase(name, /* lower_first = */ true));
517
0
    result.json_index =
518
0
        push_name(opt_json_name != nullptr ? *opt_json_name : ToJsonName(name));
519
520
0
    std::string* all_names = AllocateArray<std::string>(names.size());
521
0
    result.array = all_names;
522
0
    std::move(names.begin(), names.end(), all_names);
523
524
0
    return result;
525
0
  }
526
527
  template <typename Alloc>
528
0
  void FinalizePlanning(Alloc& alloc) {
529
0
    ABSL_CHECK(!has_allocated());
530
531
0
    pointers_ = alloc->CreateFlatAlloc(total_)->Pointers();
532
533
0
    ABSL_CHECK(has_allocated());
534
0
  }
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::FinalizePlanning<google::protobuf::DescriptorPool::Tables*>(google::protobuf::DescriptorPool::Tables*&)
Unexecuted instantiation: descriptor.cc:void google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::FinalizePlanning<std::__1::unique_ptr<google::protobuf::DescriptorPool::Tables, std::__1::default_delete<google::protobuf::DescriptorPool::Tables> > const>(std::__1::unique_ptr<google::protobuf::DescriptorPool::Tables, std::__1::default_delete<google::protobuf::DescriptorPool::Tables> > const&)
535
536
0
  void ExpectConsumed() const {
537
    // We verify that we consumed all the memory requested if there was no
538
    // error in processing.
539
0
    Fold({ExpectConsumed<T>()...});
540
0
  }
541
542
 private:
543
0
  bool has_allocated() const {
544
0
    return pointers_.template Get<char>() != nullptr;
545
0
  }
546
547
0
  static bool IsLower(char c) { return 'a' <= c && c <= 'z'; }
548
0
  static bool IsDigit(char c) { return '0' <= c && c <= '9'; }
549
0
  static bool IsLowerOrDigit(char c) { return IsLower(c) || IsDigit(c); }
550
551
  enum class FieldNameCase { kAllLower, kSnakeCase, kOther };
552
0
  FieldNameCase GetFieldNameCase(const std::string& name) {
553
0
    if (!IsLower(name[0])) return FieldNameCase::kOther;
554
0
    FieldNameCase best = FieldNameCase::kAllLower;
555
0
    for (char c : name) {
556
0
      if (IsLowerOrDigit(c)) {
557
        // nothing to do
558
0
      } else if (c == '_') {
559
0
        best = FieldNameCase::kSnakeCase;
560
0
      } else {
561
0
        return FieldNameCase::kOther;
562
0
      }
563
0
    }
564
0
    return best;
565
0
  }
566
567
  template <typename U>
568
0
  bool ExpectConsumed() const {
569
0
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
570
0
    return true;
571
0
  }
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<char>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::SourceCodeInfo>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::FileDescriptorTables>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::MessageOptions>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::FieldOptions>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::EnumOptions>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::EnumValueOptions>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::ExtensionRangeOptions>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::OneofOptions>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::ServiceOptions>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::MethodOptions>() const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::ExpectConsumed<google::protobuf::FileOptions>() const
572
573
  TypeMap<PointerT, T...> pointers_;
574
  TypeMap<IntT, T...> total_;
575
  TypeMap<IntT, T...> used_;
576
};
577
578
}  // namespace
579
580
class Symbol {
581
 public:
582
  enum Type {
583
    NULL_SYMBOL,
584
    MESSAGE,
585
    FIELD,
586
    ONEOF,
587
    ENUM,
588
    ENUM_VALUE,
589
    ENUM_VALUE_OTHER_PARENT,
590
    SERVICE,
591
    METHOD,
592
    FULL_PACKAGE,
593
    SUB_PACKAGE,
594
  };
595
596
0
  Symbol() {
597
0
    static constexpr internal::SymbolBase null_symbol{};
598
0
    static_assert(null_symbol.symbol_type_ == NULL_SYMBOL, "");
599
    // Initialize with a sentinel to make sure `ptr_` is never null.
600
0
    ptr_ = &null_symbol;
601
0
  }
602
603
  // Every object we store derives from internal::SymbolBase, where we store the
604
  // symbol type enum.
605
  // Storing in the object can be done without using more space in most cases,
606
  // while storing it in the Symbol type would require 8 bytes.
607
#define DEFINE_MEMBERS(TYPE, TYPE_CONSTANT, FIELD)                             \
608
0
  explicit Symbol(TYPE* value) : ptr_(value) {                                 \
609
0
    value->symbol_type_ = TYPE_CONSTANT;                                       \
610
0
  }                                                                            \
Unexecuted instantiation: google::protobuf::Symbol::Symbol(google::protobuf::EnumDescriptor*)
Unexecuted instantiation: google::protobuf::Symbol::Symbol(google::protobuf::Descriptor*)
Unexecuted instantiation: google::protobuf::Symbol::Symbol(google::protobuf::FileDescriptor*)
Unexecuted instantiation: google::protobuf::Symbol::Symbol(google::protobuf::Symbol::Subpackage*)
Unexecuted instantiation: google::protobuf::Symbol::Symbol(google::protobuf::FieldDescriptor*)
Unexecuted instantiation: google::protobuf::Symbol::Symbol(google::protobuf::OneofDescriptor*)
Unexecuted instantiation: google::protobuf::Symbol::Symbol(google::protobuf::ServiceDescriptor*)
Unexecuted instantiation: google::protobuf::Symbol::Symbol(google::protobuf::MethodDescriptor*)
611
0
  const TYPE* FIELD() const {                                                  \
612
0
    return type() == TYPE_CONSTANT ? static_cast<const TYPE*>(ptr_) : nullptr; \
613
0
  }
Unexecuted instantiation: google::protobuf::Symbol::file_descriptor() const
Unexecuted instantiation: google::protobuf::Symbol::sub_package_file_descriptor() const
Unexecuted instantiation: google::protobuf::Symbol::field_descriptor() const
Unexecuted instantiation: google::protobuf::Symbol::descriptor() const
Unexecuted instantiation: google::protobuf::Symbol::oneof_descriptor() const
Unexecuted instantiation: google::protobuf::Symbol::enum_descriptor() const
Unexecuted instantiation: google::protobuf::Symbol::service_descriptor() const
Unexecuted instantiation: google::protobuf::Symbol::method_descriptor() const
614
615
  DEFINE_MEMBERS(Descriptor, MESSAGE, descriptor)
616
  DEFINE_MEMBERS(FieldDescriptor, FIELD, field_descriptor)
617
  DEFINE_MEMBERS(OneofDescriptor, ONEOF, oneof_descriptor)
618
  DEFINE_MEMBERS(EnumDescriptor, ENUM, enum_descriptor)
619
  DEFINE_MEMBERS(ServiceDescriptor, SERVICE, service_descriptor)
620
  DEFINE_MEMBERS(MethodDescriptor, METHOD, method_descriptor)
621
  DEFINE_MEMBERS(FileDescriptor, FULL_PACKAGE, file_descriptor)
622
623
  // We use a special node for subpackage FileDescriptor.
624
  // It is potentially added to the table with multiple different names, so we
625
  // need a separate place to put the name.
626
  struct Subpackage : internal::SymbolBase {
627
    int name_size;
628
    const FileDescriptor* file;
629
  };
630
  DEFINE_MEMBERS(Subpackage, SUB_PACKAGE, sub_package_file_descriptor)
631
632
  // Enum values have two different parents.
633
  // We use two different identitied for the same object to determine the two
634
  // different insertions in the map.
635
0
  static Symbol EnumValue(EnumValueDescriptor* value, int n) {
636
0
    Symbol s;
637
0
    internal::SymbolBase* ptr;
638
0
    if (n == 0) {
639
0
      ptr = static_cast<internal::SymbolBaseN<0>*>(value);
640
0
      ptr->symbol_type_ = ENUM_VALUE;
641
0
    } else {
642
0
      ptr = static_cast<internal::SymbolBaseN<1>*>(value);
643
0
      ptr->symbol_type_ = ENUM_VALUE_OTHER_PARENT;
644
0
    }
645
0
    s.ptr_ = ptr;
646
0
    return s;
647
0
  }
648
649
0
  const EnumValueDescriptor* enum_value_descriptor() const {
650
0
    return type() == ENUM_VALUE
651
0
               ? static_cast<const EnumValueDescriptor*>(
652
0
                     static_cast<const internal::SymbolBaseN<0>*>(ptr_))
653
0
           : type() == ENUM_VALUE_OTHER_PARENT
654
0
               ? static_cast<const EnumValueDescriptor*>(
655
0
                     static_cast<const internal::SymbolBaseN<1>*>(ptr_))
656
0
               : nullptr;
657
0
  }
658
659
#undef DEFINE_MEMBERS
660
661
0
  Type type() const { return static_cast<Type>(ptr_->symbol_type_); }
662
0
  bool IsNull() const { return type() == NULL_SYMBOL; }
663
0
  bool IsType() const { return type() == MESSAGE || type() == ENUM; }
664
0
  bool IsAggregate() const {
665
0
    return IsType() || IsPackage() || type() == SERVICE;
666
0
  }
667
0
  bool IsPackage() const {
668
0
    return type() == FULL_PACKAGE || type() == SUB_PACKAGE;
669
0
  }
670
671
0
  const FileDescriptor* GetFile() const {
672
0
    switch (type()) {
673
0
      case MESSAGE:
674
0
        return descriptor()->file();
675
0
      case FIELD:
676
0
        return field_descriptor()->file();
677
0
      case ONEOF:
678
0
        return oneof_descriptor()->containing_type()->file();
679
0
      case ENUM:
680
0
        return enum_descriptor()->file();
681
0
      case ENUM_VALUE:
682
0
        return enum_value_descriptor()->type()->file();
683
0
      case SERVICE:
684
0
        return service_descriptor()->file();
685
0
      case METHOD:
686
0
        return method_descriptor()->service()->file();
687
0
      case FULL_PACKAGE:
688
0
        return file_descriptor();
689
0
      case SUB_PACKAGE:
690
0
        return sub_package_file_descriptor()->file;
691
0
      default:
692
0
        return nullptr;
693
0
    }
694
0
  }
695
696
0
  absl::string_view full_name() const {
697
0
    switch (type()) {
698
0
      case MESSAGE:
699
0
        return descriptor()->full_name();
700
0
      case FIELD:
701
0
        return field_descriptor()->full_name();
702
0
      case ONEOF:
703
0
        return oneof_descriptor()->full_name();
704
0
      case ENUM:
705
0
        return enum_descriptor()->full_name();
706
0
      case ENUM_VALUE:
707
0
        return enum_value_descriptor()->full_name();
708
0
      case SERVICE:
709
0
        return service_descriptor()->full_name();
710
0
      case METHOD:
711
0
        return method_descriptor()->full_name();
712
0
      case FULL_PACKAGE:
713
0
        return file_descriptor()->package();
714
0
      case SUB_PACKAGE:
715
0
        return absl::string_view(sub_package_file_descriptor()->file->package())
716
0
            .substr(0, sub_package_file_descriptor()->name_size);
717
0
      default:
718
0
        ABSL_CHECK(false);
719
0
    }
720
0
    return "";
721
0
  }
722
723
0
  std::pair<const void*, absl::string_view> parent_name_key() const {
724
0
    const auto or_file = [&](const void* p) { return p ? p : GetFile(); };
725
0
    switch (type()) {
726
0
      case MESSAGE:
727
0
        return {or_file(descriptor()->containing_type()), descriptor()->name()};
728
0
      case FIELD: {
729
0
        auto* field = field_descriptor();
730
0
        return {or_file(field->is_extension() ? field->extension_scope()
731
0
                                              : field->containing_type()),
732
0
                field->name()};
733
0
      }
734
0
      case ONEOF:
735
0
        return {oneof_descriptor()->containing_type(),
736
0
                oneof_descriptor()->name()};
737
0
      case ENUM:
738
0
        return {or_file(enum_descriptor()->containing_type()),
739
0
                enum_descriptor()->name()};
740
0
      case ENUM_VALUE:
741
0
        return {or_file(enum_value_descriptor()->type()->containing_type()),
742
0
                enum_value_descriptor()->name()};
743
0
      case ENUM_VALUE_OTHER_PARENT:
744
0
        return {enum_value_descriptor()->type(),
745
0
                enum_value_descriptor()->name()};
746
0
      case SERVICE:
747
0
        return {GetFile(), service_descriptor()->name()};
748
0
      case METHOD:
749
0
        return {method_descriptor()->service(), method_descriptor()->name()};
750
0
      default:
751
0
        ABSL_CHECK(false);
752
0
    }
753
0
    return {};
754
0
  }
755
756
 private:
757
  const internal::SymbolBase* ptr_;
758
};
759
760
const FieldDescriptor::CppType
761
    FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = {
762
        static_cast<CppType>(0),  // 0 is reserved for errors
763
764
        CPPTYPE_DOUBLE,   // TYPE_DOUBLE
765
        CPPTYPE_FLOAT,    // TYPE_FLOAT
766
        CPPTYPE_INT64,    // TYPE_INT64
767
        CPPTYPE_UINT64,   // TYPE_UINT64
768
        CPPTYPE_INT32,    // TYPE_INT32
769
        CPPTYPE_UINT64,   // TYPE_FIXED64
770
        CPPTYPE_UINT32,   // TYPE_FIXED32
771
        CPPTYPE_BOOL,     // TYPE_BOOL
772
        CPPTYPE_STRING,   // TYPE_STRING
773
        CPPTYPE_MESSAGE,  // TYPE_GROUP
774
        CPPTYPE_MESSAGE,  // TYPE_MESSAGE
775
        CPPTYPE_STRING,   // TYPE_BYTES
776
        CPPTYPE_UINT32,   // TYPE_UINT32
777
        CPPTYPE_ENUM,     // TYPE_ENUM
778
        CPPTYPE_INT32,    // TYPE_SFIXED32
779
        CPPTYPE_INT64,    // TYPE_SFIXED64
780
        CPPTYPE_INT32,    // TYPE_SINT32
781
        CPPTYPE_INT64,    // TYPE_SINT64
782
};
783
784
const char* const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = {
785
    "ERROR",  // 0 is reserved for errors
786
787
    "double",    // TYPE_DOUBLE
788
    "float",     // TYPE_FLOAT
789
    "int64",     // TYPE_INT64
790
    "uint64",    // TYPE_UINT64
791
    "int32",     // TYPE_INT32
792
    "fixed64",   // TYPE_FIXED64
793
    "fixed32",   // TYPE_FIXED32
794
    "bool",      // TYPE_BOOL
795
    "string",    // TYPE_STRING
796
    "group",     // TYPE_GROUP
797
    "message",   // TYPE_MESSAGE
798
    "bytes",     // TYPE_BYTES
799
    "uint32",    // TYPE_UINT32
800
    "enum",      // TYPE_ENUM
801
    "sfixed32",  // TYPE_SFIXED32
802
    "sfixed64",  // TYPE_SFIXED64
803
    "sint32",    // TYPE_SINT32
804
    "sint64",    // TYPE_SINT64
805
};
806
807
const char* const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
808
    "ERROR",  // 0 is reserved for errors
809
810
    "int32",    // CPPTYPE_INT32
811
    "int64",    // CPPTYPE_INT64
812
    "uint32",   // CPPTYPE_UINT32
813
    "uint64",   // CPPTYPE_UINT64
814
    "double",   // CPPTYPE_DOUBLE
815
    "float",    // CPPTYPE_FLOAT
816
    "bool",     // CPPTYPE_BOOL
817
    "enum",     // CPPTYPE_ENUM
818
    "string",   // CPPTYPE_STRING
819
    "message",  // CPPTYPE_MESSAGE
820
};
821
822
const char* const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
823
    "ERROR",  // 0 is reserved for errors
824
825
    "optional",  // LABEL_OPTIONAL
826
    "required",  // LABEL_REQUIRED
827
    "repeated",  // LABEL_REPEATED
828
};
829
830
PROTOBUF_IGNORE_DEPRECATION_START
831
0
const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) {
832
0
  switch (syntax) {
833
0
    case SYNTAX_PROTO2:
834
0
      return "proto2";
835
0
    case SYNTAX_PROTO3:
836
0
      return "proto3";
837
0
    case SYNTAX_UNKNOWN:
838
0
      return "unknown";
839
0
  }
840
0
  ABSL_LOG(FATAL) << "can't reach here.";
841
0
  return nullptr;
842
0
}
843
PROTOBUF_IGNORE_DEPRECATION_STOP
844
845
static const char* const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty";
846
847
#if !defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)
848
const int FieldDescriptor::kMaxNumber;
849
const int FieldDescriptor::kFirstReservedNumber;
850
const int FieldDescriptor::kLastReservedNumber;
851
#endif
852
853
namespace {
854
855
0
std::string EnumValueToPascalCase(const std::string& input) {
856
0
  bool next_upper = true;
857
0
  std::string result;
858
0
  result.reserve(input.size());
859
860
0
  for (char character : input) {
861
0
    if (character == '_') {
862
0
      next_upper = true;
863
0
    } else {
864
0
      if (next_upper) {
865
0
        result.push_back(absl::ascii_toupper(character));
866
0
      } else {
867
0
        result.push_back(absl::ascii_tolower(character));
868
0
      }
869
0
      next_upper = false;
870
0
    }
871
0
  }
872
873
0
  return result;
874
0
}
875
876
// Class to remove an enum prefix from enum values.
877
class PrefixRemover {
878
 public:
879
0
  PrefixRemover(absl::string_view prefix) {
880
    // Strip underscores and lower-case the prefix.
881
0
    for (char character : prefix) {
882
0
      if (character != '_') {
883
0
        prefix_ += absl::ascii_tolower(character);
884
0
      }
885
0
    }
886
0
  }
887
888
  // Tries to remove the enum prefix from this enum value.
889
  // If this is not possible, returns the input verbatim.
890
0
  std::string MaybeRemove(absl::string_view str) {
891
    // We can't just lowercase and strip str and look for a prefix.
892
    // We need to properly recognize the difference between:
893
    //
894
    //   enum Foo {
895
    //     FOO_BAR_BAZ = 0;
896
    //     FOO_BARBAZ = 1;
897
    //   }
898
    //
899
    // This is acceptable (though perhaps not advisable) because even when
900
    // we PascalCase, these two will still be distinct (BarBaz vs. Barbaz).
901
0
    size_t i, j;
902
903
    // Skip past prefix_ in str if we can.
904
0
    for (i = 0, j = 0; i < str.size() && j < prefix_.size(); i++) {
905
0
      if (str[i] == '_') {
906
0
        continue;
907
0
      }
908
909
0
      if (absl::ascii_tolower(str[i]) != prefix_[j++]) {
910
0
        return std::string(str);
911
0
      }
912
0
    }
913
914
    // If we didn't make it through the prefix, we've failed to strip the
915
    // prefix.
916
0
    if (j < prefix_.size()) {
917
0
      return std::string(str);
918
0
    }
919
920
    // Skip underscores between prefix and further characters.
921
0
    while (i < str.size() && str[i] == '_') {
922
0
      i++;
923
0
    }
924
925
    // Enum label can't be the empty string.
926
0
    if (i == str.size()) {
927
0
      return std::string(str);
928
0
    }
929
930
    // We successfully stripped the prefix.
931
0
    str.remove_prefix(i);
932
0
    return std::string(str);
933
0
  }
934
935
 private:
936
  std::string prefix_;
937
};
938
939
// A DescriptorPool contains a bunch of hash-maps to implement the
940
// various Find*By*() methods.  Since hashtable lookups are O(1), it's
941
// most efficient to construct a fixed set of large hash-maps used by
942
// all objects in the pool rather than construct one or more small
943
// hash-maps for each object.
944
//
945
// The keys to these hash-maps are (parent, name) or (parent, number) pairs.
946
struct FullNameQuery {
947
  absl::string_view query;
948
0
  absl::string_view full_name() const { return query; }
949
};
950
struct SymbolByFullNameHash {
951
  using is_transparent = void;
952
953
  template <typename T>
954
0
  size_t operator()(const T& s) const {
955
0
    return absl::HashOf(s.full_name());
956
0
  }
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::SymbolByFullNameHash::operator()<google::protobuf::(anonymous namespace)::FullNameQuery>(google::protobuf::(anonymous namespace)::FullNameQuery const&) const
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::SymbolByFullNameHash::operator()<google::protobuf::Symbol>(google::protobuf::Symbol const&) const
957
};
958
struct SymbolByFullNameEq {
959
  using is_transparent = void;
960
961
  template <typename T, typename U>
962
0
  bool operator()(const T& a, const U& b) const {
963
0
    return a.full_name() == b.full_name();
964
0
  }
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::SymbolByFullNameEq::operator()<google::protobuf::Symbol, google::protobuf::(anonymous namespace)::FullNameQuery>(google::protobuf::Symbol const&, google::protobuf::(anonymous namespace)::FullNameQuery const&) const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::SymbolByFullNameEq::operator()<google::protobuf::Symbol, google::protobuf::Symbol>(google::protobuf::Symbol const&, google::protobuf::Symbol const&) const
965
};
966
using SymbolsByNameSet =
967
    absl::flat_hash_set<Symbol, SymbolByFullNameHash, SymbolByFullNameEq>;
968
969
struct ParentNameQuery {
970
  std::pair<const void*, absl::string_view> query;
971
0
  std::pair<const void*, absl::string_view> parent_name_key() const {
972
0
    return query;
973
0
  }
974
};
975
struct SymbolByParentHash {
976
  using is_transparent = void;
977
978
  template <typename T>
979
0
  size_t operator()(const T& s) const {
980
0
    return absl::HashOf(s.parent_name_key());
981
0
  }
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::SymbolByParentHash::operator()<google::protobuf::(anonymous namespace)::ParentNameQuery>(google::protobuf::(anonymous namespace)::ParentNameQuery const&) const
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::SymbolByParentHash::operator()<google::protobuf::Symbol>(google::protobuf::Symbol const&) const
982
};
983
struct SymbolByParentEq {
984
  using is_transparent = void;
985
986
  template <typename T, typename U>
987
0
  bool operator()(const T& a, const U& b) const {
988
0
    return a.parent_name_key() == b.parent_name_key();
989
0
  }
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::SymbolByParentEq::operator()<google::protobuf::Symbol, google::protobuf::(anonymous namespace)::ParentNameQuery>(google::protobuf::Symbol const&, google::protobuf::(anonymous namespace)::ParentNameQuery const&) const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::SymbolByParentEq::operator()<google::protobuf::Symbol, google::protobuf::Symbol>(google::protobuf::Symbol const&, google::protobuf::Symbol const&) const
990
};
991
using SymbolsByParentSet =
992
    absl::flat_hash_set<Symbol, SymbolByParentHash, SymbolByParentEq>;
993
994
template <typename DescriptorT>
995
struct DescriptorsByNameHash {
996
  using is_transparent = void;
997
998
0
  size_t operator()(absl::string_view name) const { return absl::HashOf(name); }
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameHash<google::protobuf::FileDescriptor>::operator()(absl::lts_20230125::string_view) const
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameHash<google::protobuf::Descriptor>::operator()(absl::lts_20230125::string_view) const
999
1000
0
  size_t operator()(const DescriptorT* file) const {
1001
0
    return absl::HashOf(file->name());
1002
0
  }
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameHash<google::protobuf::FileDescriptor>::operator()(google::protobuf::FileDescriptor const*) const
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameHash<google::protobuf::Descriptor>::operator()(google::protobuf::Descriptor const*) const
1003
};
1004
1005
template <typename DescriptorT>
1006
struct DescriptorsByNameEq {
1007
  using is_transparent = void;
1008
1009
  bool operator()(absl::string_view lhs, absl::string_view rhs) const {
1010
    return lhs == rhs;
1011
  }
1012
  bool operator()(absl::string_view lhs, const DescriptorT* rhs) const {
1013
    return lhs == rhs->name();
1014
  }
1015
0
  bool operator()(const DescriptorT* lhs, absl::string_view rhs) const {
1016
0
    return lhs->name() == rhs;
1017
0
  }
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameEq<google::protobuf::FileDescriptor>::operator()(google::protobuf::FileDescriptor const*, absl::lts_20230125::string_view) const
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameEq<google::protobuf::Descriptor>::operator()(google::protobuf::Descriptor const*, absl::lts_20230125::string_view) const
1018
0
  bool operator()(const DescriptorT* lhs, const DescriptorT* rhs) const {
1019
0
    return lhs == rhs || lhs->name() == rhs->name();
1020
0
  }
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameEq<google::protobuf::FileDescriptor>::operator()(google::protobuf::FileDescriptor const*, google::protobuf::FileDescriptor const*) const
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameEq<google::protobuf::Descriptor>::operator()(google::protobuf::Descriptor const*, google::protobuf::Descriptor const*) const
1021
};
1022
1023
template <typename DescriptorT>
1024
using DescriptorsByNameSet =
1025
    absl::flat_hash_set<const DescriptorT*, DescriptorsByNameHash<DescriptorT>,
1026
                        DescriptorsByNameEq<DescriptorT>>;
1027
1028
using FieldsByNameMap =
1029
    absl::flat_hash_map<std::pair<const void*, absl::string_view>,
1030
                        const FieldDescriptor*>;
1031
1032
struct ParentNumberQuery {
1033
  std::pair<const void*, int> query;
1034
};
1035
0
std::pair<const void*, int> ObjectToParentNumber(const FieldDescriptor* field) {
1036
0
  return {field->containing_type(), field->number()};
1037
0
}
1038
std::pair<const void*, int> ObjectToParentNumber(
1039
0
    const EnumValueDescriptor* enum_value) {
1040
0
  return {enum_value->type(), enum_value->number()};
1041
0
}
1042
0
std::pair<const void*, int> ObjectToParentNumber(ParentNumberQuery query) {
1043
0
  return query.query;
1044
0
}
1045
struct ParentNumberHash {
1046
  using is_transparent = void;
1047
1048
  template <typename T>
1049
0
  size_t operator()(const T& t) const {
1050
0
    return absl::HashOf(ObjectToParentNumber(t));
1051
0
  }
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::ParentNumberHash::operator()<google::protobuf::(anonymous namespace)::ParentNumberQuery>(google::protobuf::(anonymous namespace)::ParentNumberQuery const&) const
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::ParentNumberHash::operator()<google::protobuf::EnumValueDescriptor*>(google::protobuf::EnumValueDescriptor* const&) const
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::ParentNumberHash::operator()<google::protobuf::EnumValueDescriptor const*>(google::protobuf::EnumValueDescriptor const* const&) const
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::ParentNumberHash::operator()<google::protobuf::FieldDescriptor*>(google::protobuf::FieldDescriptor* const&) const
Unexecuted instantiation: descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::ParentNumberHash::operator()<google::protobuf::FieldDescriptor const*>(google::protobuf::FieldDescriptor const* const&) const
1052
};
1053
struct ParentNumberEq {
1054
  using is_transparent = void;
1055
1056
  template <typename T, typename U>
1057
0
  bool operator()(const T& a, const U& b) const {
1058
0
    return ObjectToParentNumber(a) == ObjectToParentNumber(b);
1059
0
  }
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::ParentNumberEq::operator()<google::protobuf::FieldDescriptor const*, google::protobuf::(anonymous namespace)::ParentNumberQuery>(google::protobuf::FieldDescriptor const* const&, google::protobuf::(anonymous namespace)::ParentNumberQuery const&) const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::ParentNumberEq::operator()<google::protobuf::EnumValueDescriptor const*, google::protobuf::(anonymous namespace)::ParentNumberQuery>(google::protobuf::EnumValueDescriptor const* const&, google::protobuf::(anonymous namespace)::ParentNumberQuery const&) const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::ParentNumberEq::operator()<google::protobuf::EnumValueDescriptor const*, google::protobuf::EnumValueDescriptor*>(google::protobuf::EnumValueDescriptor const* const&, google::protobuf::EnumValueDescriptor* const&) const
Unexecuted instantiation: descriptor.cc:bool google::protobuf::(anonymous namespace)::ParentNumberEq::operator()<google::protobuf::FieldDescriptor const*, google::protobuf::FieldDescriptor*>(google::protobuf::FieldDescriptor const* const&, google::protobuf::FieldDescriptor* const&) const
1060
};
1061
using FieldsByNumberSet = absl::flat_hash_set<const FieldDescriptor*,
1062
                                              ParentNumberHash, ParentNumberEq>;
1063
using EnumValuesByNumberSet =
1064
    absl::flat_hash_set<const EnumValueDescriptor*, ParentNumberHash,
1065
                        ParentNumberEq>;
1066
1067
// This is a map rather than a hash-map, since we use it to iterate
1068
// through all the extensions that extend a given Descriptor, and an
1069
// ordered data structure that implements lower_bound is convenient
1070
// for that.
1071
using ExtensionsGroupedByDescriptorMap =
1072
    absl::btree_map<std::pair<const Descriptor*, int>, const FieldDescriptor*>;
1073
using LocationsByPathMap =
1074
    absl::flat_hash_map<std::string, const SourceCodeInfo_Location*>;
1075
1076
0
absl::flat_hash_set<std::string>* NewAllowedProto3Extendee() {
1077
0
  const char* kOptionNames[] = {
1078
0
      "FileOptions",   "MessageOptions",   "FieldOptions",
1079
0
      "EnumOptions",   "EnumValueOptions", "ServiceOptions",
1080
0
      "MethodOptions", "OneofOptions",     "ExtensionRangeOptions"};
1081
0
  auto allowed_proto3_extendees = new absl::flat_hash_set<std::string>();
1082
0
  allowed_proto3_extendees->reserve(sizeof(kOptionNames) /
1083
0
                                    sizeof(kOptionNames[0]));
1084
1085
0
  for (const char* option_name : kOptionNames) {
1086
    // descriptor.proto has a different package name in opensource. We allow
1087
    // both so the opensource protocol compiler can also compile internal
1088
    // proto3 files with custom options. See: b/27567912
1089
0
    allowed_proto3_extendees->insert(std::string("google.protobuf.") +
1090
0
                                     option_name);
1091
    // Split the word to trick the opensource processing scripts so they
1092
    // will keep the original package name.
1093
0
    allowed_proto3_extendees->insert(std::string("proto2.") + option_name);
1094
0
  }
1095
0
  return allowed_proto3_extendees;
1096
0
}
1097
1098
// Checks whether the extendee type is allowed in proto3.
1099
// Only extensions to descriptor options are allowed. We use name comparison
1100
// instead of comparing the descriptor directly because the extensions may be
1101
// defined in a different pool.
1102
0
bool AllowedExtendeeInProto3(const std::string& name) {
1103
0
  static auto allowed_proto3_extendees =
1104
0
      internal::OnShutdownDelete(NewAllowedProto3Extendee());
1105
0
  return allowed_proto3_extendees->find(name) !=
1106
0
         allowed_proto3_extendees->end();
1107
0
}
1108
1109
}  // anonymous namespace
1110
1111
// Contains tables specific to a particular file.  These tables are not
1112
// modified once the file has been constructed, so they need not be
1113
// protected by a mutex.  This makes operations that depend only on the
1114
// contents of a single file -- e.g. Descriptor::FindFieldByName() --
1115
// lock-free.
1116
//
1117
// For historical reasons, the definitions of the methods of
1118
// FileDescriptorTables and DescriptorPool::Tables are interleaved below.
1119
// These used to be a single class.
1120
class FileDescriptorTables {
1121
 public:
1122
  FileDescriptorTables();
1123
  ~FileDescriptorTables();
1124
1125
  // Empty table, used with placeholder files.
1126
  inline static const FileDescriptorTables& GetEmptyInstance();
1127
1128
  // -----------------------------------------------------------------
1129
  // Finding items.
1130
1131
  // Returns a null Symbol (symbol.IsNull() is true) if not found.
1132
  // TODO(sbenza): All callers to this function know the type they are looking
1133
  // for. If we propagate that information statically we can make the query
1134
  // faster.
1135
  inline Symbol FindNestedSymbol(const void* parent,
1136
                                 absl::string_view name) const;
1137
1138
  // These return nullptr if not found.
1139
  inline const FieldDescriptor* FindFieldByNumber(const Descriptor* parent,
1140
                                                  int number) const;
1141
  inline const FieldDescriptor* FindFieldByLowercaseName(
1142
      const void* parent, absl::string_view lowercase_name) const;
1143
  inline const FieldDescriptor* FindFieldByCamelcaseName(
1144
      const void* parent, absl::string_view camelcase_name) const;
1145
  inline const EnumValueDescriptor* FindEnumValueByNumber(
1146
      const EnumDescriptor* parent, int number) const;
1147
  // This creates a new EnumValueDescriptor if not found, in a thread-safe way.
1148
  inline const EnumValueDescriptor* FindEnumValueByNumberCreatingIfUnknown(
1149
      const EnumDescriptor* parent, int number) const;
1150
1151
  // -----------------------------------------------------------------
1152
  // Adding items.
1153
1154
  // These add items to the corresponding tables.  They return false if
1155
  // the key already exists in the table.
1156
  bool AddAliasUnderParent(const void* parent, absl::string_view name,
1157
                           Symbol symbol);
1158
  bool AddFieldByNumber(FieldDescriptor* field);
1159
  bool AddEnumValueByNumber(EnumValueDescriptor* value);
1160
1161
  // Populates p->first->locations_by_path_ from p->second.
1162
  // Unusual signature dictated by absl::call_once.
1163
  static void BuildLocationsByPath(
1164
      std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p);
1165
1166
  // Returns the location denoted by the specified path through info,
1167
  // or nullptr if not found.
1168
  // The value of info must be that of the corresponding FileDescriptor.
1169
  // (Conceptually a pure function, but stateful as an optimisation.)
1170
  const SourceCodeInfo_Location* GetSourceLocation(
1171
      const std::vector<int>& path, const SourceCodeInfo* info) const;
1172
1173
  // Must be called after BuildFileImpl(), even if the build failed and
1174
  // we are going to roll back to the last checkpoint.
1175
  void FinalizeTables();
1176
1177
 private:
1178
  const void* FindParentForFieldsByMap(const FieldDescriptor* field) const;
1179
  static void FieldsByLowercaseNamesLazyInitStatic(
1180
      const FileDescriptorTables* tables);
1181
  void FieldsByLowercaseNamesLazyInitInternal() const;
1182
  static void FieldsByCamelcaseNamesLazyInitStatic(
1183
      const FileDescriptorTables* tables);
1184
  void FieldsByCamelcaseNamesLazyInitInternal() const;
1185
1186
  SymbolsByParentSet symbols_by_parent_;
1187
  mutable absl::once_flag fields_by_lowercase_name_once_;
1188
  mutable absl::once_flag fields_by_camelcase_name_once_;
1189
  // Make these fields atomic to avoid race conditions with
1190
  // GetEstimatedOwnedMemoryBytesSize. Once the pointer is set the map won't
1191
  // change anymore.
1192
  mutable std::atomic<const FieldsByNameMap*> fields_by_lowercase_name_{};
1193
  mutable std::atomic<const FieldsByNameMap*> fields_by_camelcase_name_{};
1194
  FieldsByNumberSet fields_by_number_;  // Not including extensions.
1195
  EnumValuesByNumberSet enum_values_by_number_;
1196
  mutable EnumValuesByNumberSet unknown_enum_values_by_number_
1197
      PROTOBUF_GUARDED_BY(unknown_enum_values_mu_);
1198
1199
  // Populated on first request to save space, hence constness games.
1200
  mutable absl::once_flag locations_by_path_once_;
1201
  mutable LocationsByPathMap locations_by_path_;
1202
1203
  // Mutex to protect the unknown-enum-value map due to dynamic
1204
  // EnumValueDescriptor creation on unknown values.
1205
  mutable absl::Mutex unknown_enum_values_mu_;
1206
};
1207
1208
namespace internal {
1209
1210
// Small sequential allocator to be used within a single file.
1211
// Most of the memory for a single FileDescriptor and everything under it is
1212
// allocated in a single block of memory, with the FlatAllocator giving it out
1213
// in parts later.
1214
// The code first plans the total number of bytes needed by calling PlanArray
1215
// with all the allocations that will happen afterwards, then calls
1216
// FinalizePlanning passing the underlying allocator (the DescriptorPool::Tables
1217
// instance), and then proceeds to get the memory via
1218
// `AllocateArray`/`AllocateString` calls. The calls to PlanArray and
1219
// The calls have to match between planning and allocating, though not
1220
// necessarily in the same order.
1221
class FlatAllocator
1222
    : public decltype(ApplyTypeList<FlatAllocatorImpl>(
1223
          SortByAlignment<char, std::string, SourceCodeInfo,
1224
                          FileDescriptorTables,
1225
        // Option types
1226
                          MessageOptions, FieldOptions, EnumOptions,
1227
                          EnumValueOptions, ExtensionRangeOptions, OneofOptions,
1228
                          ServiceOptions, MethodOptions, FileOptions>())) {
1229
};
1230
1231
}  // namespace internal
1232
1233
// ===================================================================
1234
// DescriptorPool::Tables
1235
1236
class DescriptorPool::Tables {
1237
 public:
1238
  Tables();
1239
  ~Tables();
1240
1241
  // Record the current state of the tables to the stack of checkpoints.
1242
  // Each call to AddCheckpoint() must be paired with exactly one call to either
1243
  // ClearLastCheckpoint() or RollbackToLastCheckpoint().
1244
  //
1245
  // This is used when building files, since some kinds of validation errors
1246
  // cannot be detected until the file's descriptors have already been added to
1247
  // the tables.
1248
  //
1249
  // This supports recursive checkpoints, since building a file may trigger
1250
  // recursive building of other files. Note that recursive checkpoints are not
1251
  // normally necessary; explicit dependencies are built prior to checkpointing.
1252
  // So although we recursively build transitive imports, there is at most one
1253
  // checkpoint in the stack during dependency building.
1254
  //
1255
  // Recursive checkpoints only arise during cross-linking of the descriptors.
1256
  // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and
1257
  // friends. If the pending file references an unknown symbol
1258
  // (e.g., it is not defined in the pending file's explicit dependencies), and
1259
  // the pool is using a fallback database, and that database contains a file
1260
  // defining that symbol, and that file has not yet been built by the pool,
1261
  // the pool builds the file during cross-linking, leading to another
1262
  // checkpoint.
1263
  void AddCheckpoint();
1264
1265
  // Mark the last checkpoint as having cleared successfully, removing it from
1266
  // the stack. If the stack is empty, all pending symbols will be committed.
1267
  //
1268
  // Note that this does not guarantee that the symbols added since the last
1269
  // checkpoint won't be rolled back: if a checkpoint gets rolled back,
1270
  // everything past that point gets rolled back, including symbols added after
1271
  // checkpoints that were pushed onto the stack after it and marked as cleared.
1272
  void ClearLastCheckpoint();
1273
1274
  // Roll back the Tables to the state of the checkpoint at the top of the
1275
  // stack, removing everything that was added after that point.
1276
  void RollbackToLastCheckpoint();
1277
1278
  // The stack of files which are currently being built.  Used to detect
1279
  // cyclic dependencies when loading files from a DescriptorDatabase.  Not
1280
  // used when fallback_database_ == nullptr.
1281
  std::vector<std::string> pending_files_;
1282
1283
  // A set of files which we have tried to load from the fallback database
1284
  // and encountered errors.  We will not attempt to load them again during
1285
  // execution of the current public API call, but for compatibility with
1286
  // legacy clients, this is cleared at the beginning of each public API call.
1287
  // Not used when fallback_database_ == nullptr.
1288
  absl::flat_hash_set<std::string> known_bad_files_;
1289
1290
  // A set of symbols which we have tried to load from the fallback database
1291
  // and encountered errors. We will not attempt to load them again during
1292
  // execution of the current public API call, but for compatibility with
1293
  // legacy clients, this is cleared at the beginning of each public API call.
1294
  absl::flat_hash_set<std::string> known_bad_symbols_;
1295
1296
  // The set of descriptors for which we've already loaded the full
1297
  // set of extensions numbers from fallback_database_.
1298
  absl::flat_hash_set<const Descriptor*> extensions_loaded_from_db_;
1299
1300
  // Maps type name to Descriptor::WellKnownType.  This is logically global
1301
  // and const, but we make it a member here to simplify its construction and
1302
  // destruction.  This only has 20-ish entries and is one per DescriptorPool,
1303
  // so the overhead is small.
1304
  absl::flat_hash_map<std::string, Descriptor::WellKnownType> well_known_types_;
1305
1306
  // -----------------------------------------------------------------
1307
  // Finding items.
1308
1309
  // Find symbols.  This returns a null Symbol (symbol.IsNull() is true)
1310
  // if not found.
1311
  inline Symbol FindSymbol(absl::string_view key) const;
1312
1313
  // This implements the body of DescriptorPool::Find*ByName().  It should
1314
  // really be a private method of DescriptorPool, but that would require
1315
  // declaring Symbol in descriptor.h, which would drag all kinds of other
1316
  // stuff into the header.  Yay C++.
1317
  Symbol FindByNameHelper(const DescriptorPool* pool, absl::string_view name);
1318
1319
  // These return nullptr if not found.
1320
  inline const FileDescriptor* FindFile(absl::string_view key) const;
1321
  inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
1322
                                              int number) const;
1323
  inline void FindAllExtensions(const Descriptor* extendee,
1324
                                std::vector<const FieldDescriptor*>* out) const;
1325
1326
  // -----------------------------------------------------------------
1327
  // Adding items.
1328
1329
  // These add items to the corresponding tables.  They return false if
1330
  // the key already exists in the table.  For AddSymbol(), the string passed
1331
  // in must be one that was constructed using AllocateString(), as it will
1332
  // be used as a key in the symbols_by_name_ map without copying.
1333
  bool AddSymbol(absl::string_view full_name, Symbol symbol);
1334
  bool AddFile(const FileDescriptor* file);
1335
  bool AddExtension(const FieldDescriptor* field);
1336
1337
  // -----------------------------------------------------------------
1338
  // Allocating memory.
1339
1340
  // Allocate an object which will be reclaimed when the pool is
1341
  // destroyed.  Note that the object's destructor will never be called,
1342
  // so its fields must be plain old data (primitive data types and
1343
  // pointers).  All of the descriptor types are such objects.
1344
  template <typename Type>
1345
  Type* Allocate();
1346
1347
  // Allocate some bytes which will be reclaimed when the pool is
1348
  // destroyed. Memory is aligned to 8 bytes.
1349
  void* AllocateBytes(int size);
1350
1351
  // Create a FlatAllocation for the corresponding sizes.
1352
  // All objects within it will be default constructed.
1353
  // The whole allocation, including the non-trivial objects within, will be
1354
  // destroyed with the pool.
1355
  template <typename... T>
1356
  internal::FlatAllocator::Allocation* CreateFlatAlloc(
1357
      const TypeMap<IntT, T...>& sizes);
1358
1359
1360
 private:
1361
  // All memory allocated in the pool.  Must be first as other objects can
1362
  // point into these.
1363
  struct MiscDeleter {
1364
0
    void operator()(int* p) const { internal::SizedDelete(p, *p + 8); }
1365
  };
1366
  // Miscellaneous allocations are length prefixed. The paylaod is 8 bytes after
1367
  // the `int` that contains the size. This keeps the payload aligned.
1368
  std::vector<std::unique_ptr<int, MiscDeleter>> misc_allocs_;
1369
  struct FlatAllocDeleter {
1370
0
    void operator()(internal::FlatAllocator::Allocation* p) const {
1371
0
      p->Destroy();
1372
0
    }
1373
  };
1374
  std::vector<
1375
      std::unique_ptr<internal::FlatAllocator::Allocation, FlatAllocDeleter>>
1376
      flat_allocs_;
1377
1378
  SymbolsByNameSet symbols_by_name_;
1379
  DescriptorsByNameSet<FileDescriptor> files_by_name_;
1380
  ExtensionsGroupedByDescriptorMap extensions_;
1381
1382
  struct CheckPoint {
1383
    explicit CheckPoint(const Tables* tables)
1384
        : flat_allocations_before_checkpoint(
1385
              static_cast<int>(tables->flat_allocs_.size())),
1386
          misc_allocations_before_checkpoint(
1387
              static_cast<int>(tables->misc_allocs_.size())),
1388
          pending_symbols_before_checkpoint(
1389
              tables->symbols_after_checkpoint_.size()),
1390
          pending_files_before_checkpoint(
1391
              tables->files_after_checkpoint_.size()),
1392
          pending_extensions_before_checkpoint(
1393
0
              tables->extensions_after_checkpoint_.size()) {}
1394
    int flat_allocations_before_checkpoint;
1395
    int misc_allocations_before_checkpoint;
1396
    int pending_symbols_before_checkpoint;
1397
    int pending_files_before_checkpoint;
1398
    int pending_extensions_before_checkpoint;
1399
  };
1400
  std::vector<CheckPoint> checkpoints_;
1401
  std::vector<Symbol> symbols_after_checkpoint_;
1402
  std::vector<const FileDescriptor*> files_after_checkpoint_;
1403
  std::vector<std::pair<const Descriptor*, int>> extensions_after_checkpoint_;
1404
};
1405
1406
0
DescriptorPool::Tables::Tables() {
1407
0
  well_known_types_.insert({
1408
0
      {"google.protobuf.DoubleValue", Descriptor::WELLKNOWNTYPE_DOUBLEVALUE},
1409
0
      {"google.protobuf.FloatValue", Descriptor::WELLKNOWNTYPE_FLOATVALUE},
1410
0
      {"google.protobuf.Int64Value", Descriptor::WELLKNOWNTYPE_INT64VALUE},
1411
0
      {"google.protobuf.UInt64Value", Descriptor::WELLKNOWNTYPE_UINT64VALUE},
1412
0
      {"google.protobuf.Int32Value", Descriptor::WELLKNOWNTYPE_INT32VALUE},
1413
0
      {"google.protobuf.UInt32Value", Descriptor::WELLKNOWNTYPE_UINT32VALUE},
1414
0
      {"google.protobuf.StringValue", Descriptor::WELLKNOWNTYPE_STRINGVALUE},
1415
0
      {"google.protobuf.BytesValue", Descriptor::WELLKNOWNTYPE_BYTESVALUE},
1416
0
      {"google.protobuf.BoolValue", Descriptor::WELLKNOWNTYPE_BOOLVALUE},
1417
0
      {"google.protobuf.Any", Descriptor::WELLKNOWNTYPE_ANY},
1418
0
      {"google.protobuf.FieldMask", Descriptor::WELLKNOWNTYPE_FIELDMASK},
1419
0
      {"google.protobuf.Duration", Descriptor::WELLKNOWNTYPE_DURATION},
1420
0
      {"google.protobuf.Timestamp", Descriptor::WELLKNOWNTYPE_TIMESTAMP},
1421
0
      {"google.protobuf.Value", Descriptor::WELLKNOWNTYPE_VALUE},
1422
0
      {"google.protobuf.ListValue", Descriptor::WELLKNOWNTYPE_LISTVALUE},
1423
0
      {"google.protobuf.Struct", Descriptor::WELLKNOWNTYPE_STRUCT},
1424
0
  });
1425
0
}
1426
1427
0
DescriptorPool::Tables::~Tables() { ABSL_DCHECK(checkpoints_.empty()); }
1428
1429
0
FileDescriptorTables::FileDescriptorTables() {}
1430
1431
0
FileDescriptorTables::~FileDescriptorTables() {
1432
0
  delete fields_by_lowercase_name_.load(std::memory_order_acquire);
1433
0
  delete fields_by_camelcase_name_.load(std::memory_order_acquire);
1434
0
}
1435
1436
0
inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() {
1437
0
  static auto file_descriptor_tables =
1438
0
      internal::OnShutdownDelete(new FileDescriptorTables());
1439
0
  return *file_descriptor_tables;
1440
0
}
1441
1442
0
void DescriptorPool::Tables::AddCheckpoint() {
1443
0
  checkpoints_.emplace_back(this);
1444
0
}
1445
1446
0
void DescriptorPool::Tables::ClearLastCheckpoint() {
1447
0
  ABSL_DCHECK(!checkpoints_.empty());
1448
0
  checkpoints_.pop_back();
1449
0
  if (checkpoints_.empty()) {
1450
    // All checkpoints have been cleared: we can now commit all of the pending
1451
    // data.
1452
0
    symbols_after_checkpoint_.clear();
1453
0
    files_after_checkpoint_.clear();
1454
0
    extensions_after_checkpoint_.clear();
1455
0
  }
1456
0
}
1457
1458
0
void DescriptorPool::Tables::RollbackToLastCheckpoint() {
1459
0
  ABSL_DCHECK(!checkpoints_.empty());
1460
0
  const CheckPoint& checkpoint = checkpoints_.back();
1461
1462
0
  for (size_t i = checkpoint.pending_symbols_before_checkpoint;
1463
0
       i < symbols_after_checkpoint_.size(); i++) {
1464
0
    symbols_by_name_.erase(symbols_after_checkpoint_[i]);
1465
0
  }
1466
0
  for (size_t i = checkpoint.pending_files_before_checkpoint;
1467
0
       i < files_after_checkpoint_.size(); i++) {
1468
0
    files_by_name_.erase(files_after_checkpoint_[i]);
1469
0
  }
1470
0
  for (size_t i = checkpoint.pending_extensions_before_checkpoint;
1471
0
       i < extensions_after_checkpoint_.size(); i++) {
1472
0
    extensions_.erase(extensions_after_checkpoint_[i]);
1473
0
  }
1474
1475
0
  symbols_after_checkpoint_.resize(
1476
0
      checkpoint.pending_symbols_before_checkpoint);
1477
0
  files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint);
1478
0
  extensions_after_checkpoint_.resize(
1479
0
      checkpoint.pending_extensions_before_checkpoint);
1480
1481
0
  flat_allocs_.resize(checkpoint.flat_allocations_before_checkpoint);
1482
0
  misc_allocs_.resize(checkpoint.misc_allocations_before_checkpoint);
1483
0
  checkpoints_.pop_back();
1484
0
}
1485
1486
// -------------------------------------------------------------------
1487
1488
0
inline Symbol DescriptorPool::Tables::FindSymbol(absl::string_view key) const {
1489
0
  auto it = symbols_by_name_.find(FullNameQuery{key});
1490
0
  return it == symbols_by_name_.end() ? Symbol() : *it;
1491
0
}
1492
1493
inline Symbol FileDescriptorTables::FindNestedSymbol(
1494
0
    const void* parent, absl::string_view name) const {
1495
0
  auto it = symbols_by_parent_.find(ParentNameQuery{{parent, name}});
1496
0
  return it == symbols_by_parent_.end() ? Symbol() : *it;
1497
0
}
1498
1499
Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool,
1500
0
                                                absl::string_view name) {
1501
0
  if (pool->mutex_ != nullptr) {
1502
    // Fast path: the Symbol is already cached.  This is just a hash lookup.
1503
0
    absl::ReaderMutexLock lock(pool->mutex_);
1504
0
    if (known_bad_symbols_.empty() && known_bad_files_.empty()) {
1505
0
      Symbol result = FindSymbol(name);
1506
0
      if (!result.IsNull()) return result;
1507
0
    }
1508
0
  }
1509
0
  absl::MutexLockMaybe lock(pool->mutex_);
1510
0
  if (pool->fallback_database_ != nullptr) {
1511
0
    known_bad_symbols_.clear();
1512
0
    known_bad_files_.clear();
1513
0
  }
1514
0
  Symbol result = FindSymbol(name);
1515
1516
0
  if (result.IsNull() && pool->underlay_ != nullptr) {
1517
    // Symbol not found; check the underlay.
1518
0
    result = pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name);
1519
0
  }
1520
1521
0
  if (result.IsNull()) {
1522
    // Symbol still not found, so check fallback database.
1523
0
    if (pool->TryFindSymbolInFallbackDatabase(name)) {
1524
0
      result = FindSymbol(name);
1525
0
    }
1526
0
  }
1527
1528
0
  return result;
1529
0
}
1530
1531
inline const FileDescriptor* DescriptorPool::Tables::FindFile(
1532
0
    absl::string_view key) const {
1533
0
  auto it = files_by_name_.find(key);
1534
0
  if (it == files_by_name_.end()) return nullptr;
1535
0
  return *it;
1536
0
}
1537
1538
inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
1539
0
    const Descriptor* parent, int number) const {
1540
  // If `number` is within the sequential range, just index into the parent
1541
  // without doing a table lookup.
1542
0
  if (parent != nullptr &&  //
1543
0
      1 <= number && number <= parent->sequential_field_limit_) {
1544
0
    return parent->field(number - 1);
1545
0
  }
1546
1547
0
  auto it = fields_by_number_.find(ParentNumberQuery{{parent, number}});
1548
0
  return it == fields_by_number_.end() ? nullptr : *it;
1549
0
}
1550
1551
const void* FileDescriptorTables::FindParentForFieldsByMap(
1552
0
    const FieldDescriptor* field) const {
1553
0
  if (field->is_extension()) {
1554
0
    if (field->extension_scope() == nullptr) {
1555
0
      return field->file();
1556
0
    } else {
1557
0
      return field->extension_scope();
1558
0
    }
1559
0
  } else {
1560
0
    return field->containing_type();
1561
0
  }
1562
0
}
1563
1564
void FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic(
1565
0
    const FileDescriptorTables* tables) {
1566
0
  tables->FieldsByLowercaseNamesLazyInitInternal();
1567
0
}
1568
1569
0
void FileDescriptorTables::FieldsByLowercaseNamesLazyInitInternal() const {
1570
0
  auto* map = new FieldsByNameMap;
1571
0
  for (Symbol symbol : symbols_by_parent_) {
1572
0
    const FieldDescriptor* field = symbol.field_descriptor();
1573
0
    if (!field) continue;
1574
0
    (*map)[{FindParentForFieldsByMap(field), field->lowercase_name().c_str()}] =
1575
0
        field;
1576
0
  }
1577
0
  fields_by_lowercase_name_.store(map, std::memory_order_release);
1578
0
}
1579
1580
inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
1581
0
    const void* parent, absl::string_view lowercase_name) const {
1582
0
  absl::call_once(fields_by_lowercase_name_once_,
1583
0
                  &FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic,
1584
0
                  this);
1585
0
  const auto* fields =
1586
0
      fields_by_lowercase_name_.load(std::memory_order_acquire);
1587
0
  auto it = fields->find({parent, lowercase_name});
1588
0
  if (it == fields->end()) return nullptr;
1589
0
  return it->second;
1590
0
}
1591
1592
void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic(
1593
0
    const FileDescriptorTables* tables) {
1594
0
  tables->FieldsByCamelcaseNamesLazyInitInternal();
1595
0
}
1596
1597
0
void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitInternal() const {
1598
0
  auto* map = new FieldsByNameMap;
1599
0
  for (Symbol symbol : symbols_by_parent_) {
1600
0
    const FieldDescriptor* field = symbol.field_descriptor();
1601
0
    if (!field) continue;
1602
0
    (*map)[{FindParentForFieldsByMap(field), field->camelcase_name().c_str()}] =
1603
0
        field;
1604
0
  }
1605
0
  fields_by_camelcase_name_.store(map, std::memory_order_release);
1606
0
}
1607
1608
inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
1609
0
    const void* parent, absl::string_view camelcase_name) const {
1610
0
  absl::call_once(fields_by_camelcase_name_once_,
1611
0
                  FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic,
1612
0
                  this);
1613
0
  auto* fields = fields_by_camelcase_name_.load(std::memory_order_acquire);
1614
0
  auto it = fields->find({parent, camelcase_name});
1615
0
  if (it == fields->end()) return nullptr;
1616
0
  return it->second;
1617
0
}
1618
1619
inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
1620
0
    const EnumDescriptor* parent, int number) const {
1621
  // If `number` is within the sequential range, just index into the parent
1622
  // without doing a table lookup.
1623
0
  const int base = parent->value(0)->number();
1624
0
  if (base <= number &&
1625
0
      number <= static_cast<int64_t>(base) + parent->sequential_value_limit_) {
1626
0
    return parent->value(number - base);
1627
0
  }
1628
1629
0
  auto it = enum_values_by_number_.find(ParentNumberQuery{{parent, number}});
1630
0
  return it == enum_values_by_number_.end() ? nullptr : *it;
1631
0
}
1632
1633
inline const EnumValueDescriptor*
1634
FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
1635
0
    const EnumDescriptor* parent, int number) const {
1636
  // First try, with map of compiled-in values.
1637
0
  {
1638
0
    const auto* value = FindEnumValueByNumber(parent, number);
1639
0
    if (value != nullptr) {
1640
0
      return value;
1641
0
    }
1642
0
  }
1643
1644
0
  const ParentNumberQuery query{{parent, number}};
1645
1646
  // Second try, with reader lock held on unknown enum values: common case.
1647
0
  {
1648
0
    absl::ReaderMutexLock l(&unknown_enum_values_mu_);
1649
0
    auto it = unknown_enum_values_by_number_.find(query);
1650
0
    if (it != unknown_enum_values_by_number_.end()) {
1651
0
      return *it;
1652
0
    }
1653
0
  }
1654
  // If not found, try again with writer lock held, and create new descriptor if
1655
  // necessary.
1656
0
  {
1657
0
    absl::WriterMutexLock l(&unknown_enum_values_mu_);
1658
0
    auto it = unknown_enum_values_by_number_.find(query);
1659
0
    if (it != unknown_enum_values_by_number_.end()) {
1660
0
      return *it;
1661
0
    }
1662
1663
    // Create an EnumValueDescriptor dynamically. We don't insert it into the
1664
    // EnumDescriptor (it's not a part of the enum as originally defined), but
1665
    // we do insert it into the table so that we can return the same pointer
1666
    // later.
1667
0
    std::string enum_value_name = absl::StrFormat(
1668
0
        "UNKNOWN_ENUM_VALUE_%s_%d", parent->name().c_str(), number);
1669
0
    auto* pool = DescriptorPool::generated_pool();
1670
0
    auto* tables = const_cast<DescriptorPool::Tables*>(pool->tables_.get());
1671
0
    internal::FlatAllocator alloc;
1672
0
    alloc.PlanArray<EnumValueDescriptor>(1);
1673
0
    alloc.PlanArray<std::string>(2);
1674
1675
0
    {
1676
      // Must lock the pool because we will do allocations in the shared arena.
1677
0
      absl::MutexLockMaybe l2(pool->mutex_);
1678
0
      alloc.FinalizePlanning(tables);
1679
0
    }
1680
0
    EnumValueDescriptor* result = alloc.AllocateArray<EnumValueDescriptor>(1);
1681
0
    result->all_names_ = alloc.AllocateStrings(
1682
0
        enum_value_name,
1683
0
        absl::StrCat(parent->full_name(), ".", enum_value_name));
1684
0
    result->number_ = number;
1685
0
    result->type_ = parent;
1686
0
    result->options_ = &EnumValueOptions::default_instance();
1687
0
    unknown_enum_values_by_number_.insert(result);
1688
0
    return result;
1689
0
  }
1690
0
}
1691
1692
inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
1693
0
    const Descriptor* extendee, int number) const {
1694
0
  auto it = extensions_.find({extendee, number});
1695
0
  if (it == extensions_.end()) return nullptr;
1696
0
  return it->second;
1697
0
}
1698
1699
inline void DescriptorPool::Tables::FindAllExtensions(
1700
    const Descriptor* extendee,
1701
0
    std::vector<const FieldDescriptor*>* out) const {
1702
0
  ExtensionsGroupedByDescriptorMap::const_iterator it =
1703
0
      extensions_.lower_bound(std::make_pair(extendee, 0));
1704
0
  for (; it != extensions_.end() && it->first.first == extendee; ++it) {
1705
0
    out->push_back(it->second);
1706
0
  }
1707
0
}
1708
1709
// -------------------------------------------------------------------
1710
1711
bool DescriptorPool::Tables::AddSymbol(absl::string_view full_name,
1712
0
                                       Symbol symbol) {
1713
0
  ABSL_DCHECK_EQ(full_name, symbol.full_name());
1714
0
  if (symbols_by_name_.insert(symbol).second) {
1715
0
    symbols_after_checkpoint_.push_back(symbol);
1716
0
    return true;
1717
0
  } else {
1718
0
    return false;
1719
0
  }
1720
0
}
1721
1722
bool FileDescriptorTables::AddAliasUnderParent(const void* parent,
1723
                                               absl::string_view name,
1724
0
                                               Symbol symbol) {
1725
0
  ABSL_DCHECK_EQ(name, symbol.parent_name_key().second);
1726
0
  ABSL_DCHECK_EQ(parent, symbol.parent_name_key().first);
1727
0
  return symbols_by_parent_.insert(symbol).second;
1728
0
}
1729
1730
0
bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
1731
0
  if (files_by_name_.insert(file).second) {
1732
0
    files_after_checkpoint_.push_back(file);
1733
0
    return true;
1734
0
  } else {
1735
0
    return false;
1736
0
  }
1737
0
}
1738
1739
0
void FileDescriptorTables::FinalizeTables() {}
1740
1741
0
bool FileDescriptorTables::AddFieldByNumber(FieldDescriptor* field) {
1742
  // Skip fields that are at the start of the sequence.
1743
0
  if (field->containing_type() != nullptr && field->number() >= 1 &&
1744
0
      field->number() <= field->containing_type()->sequential_field_limit_) {
1745
0
    if (field->is_extension()) {
1746
      // Conflicts with the field that already exists in the sequential range.
1747
0
      return false;
1748
0
    }
1749
    // Only return true if the field at that index matches. Otherwise it
1750
    // conflicts with the existing field in the sequential range.
1751
0
    return field->containing_type()->field(field->number() - 1) == field;
1752
0
  }
1753
1754
0
  return fields_by_number_.insert(field).second;
1755
0
}
1756
1757
0
bool FileDescriptorTables::AddEnumValueByNumber(EnumValueDescriptor* value) {
1758
  // Skip values that are at the start of the sequence.
1759
0
  const int base = value->type()->value(0)->number();
1760
0
  if (base <= value->number() &&
1761
0
      value->number() <=
1762
0
          static_cast<int64_t>(base) + value->type()->sequential_value_limit_)
1763
0
    return true;
1764
0
  return enum_values_by_number_.insert(value).second;
1765
0
}
1766
1767
0
bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
1768
0
  auto it_inserted =
1769
0
      extensions_.insert({{field->containing_type(), field->number()}, field});
1770
0
  if (it_inserted.second) {
1771
0
    extensions_after_checkpoint_.push_back(it_inserted.first->first);
1772
0
    return true;
1773
0
  } else {
1774
0
    return false;
1775
0
  }
1776
0
}
1777
1778
// -------------------------------------------------------------------
1779
1780
template <typename Type>
1781
0
Type* DescriptorPool::Tables::Allocate() {
1782
0
  static_assert(std::is_trivially_destructible<Type>::value, "");
1783
0
  static_assert(alignof(Type) <= 8, "");
1784
0
  return ::new (AllocateBytes(sizeof(Type))) Type{};
1785
0
}
1786
1787
0
void* DescriptorPool::Tables::AllocateBytes(int size) {
1788
0
  if (size == 0) return nullptr;
1789
0
  void* p = ::operator new(size + RoundUpTo<8>(sizeof(int)));
1790
0
  int* sizep = static_cast<int*>(p);
1791
0
  misc_allocs_.emplace_back(sizep);
1792
0
  *sizep = size;
1793
0
  return static_cast<char*>(p) + RoundUpTo<8>(sizeof(int));
1794
0
}
1795
1796
template <typename... T>
1797
internal::FlatAllocator::Allocation* DescriptorPool::Tables::CreateFlatAlloc(
1798
0
    const TypeMap<IntT, T...>& sizes) {
1799
0
  auto ends = CalculateEnds(sizes);
1800
0
  using FlatAlloc = internal::FlatAllocator::Allocation;
1801
1802
0
  int last_end = ends.template Get<
1803
0
      typename std::tuple_element<sizeof...(T) - 1, std::tuple<T...>>::type>();
1804
0
  size_t total_size =
1805
0
      last_end + RoundUpTo<FlatAlloc::kMaxAlign>(sizeof(FlatAlloc));
1806
0
  char* data = static_cast<char*>(::operator new(total_size));
1807
0
  auto* res = ::new (data) FlatAlloc(ends);
1808
0
  flat_allocs_.emplace_back(res);
1809
1810
0
  return res;
1811
0
}
1812
1813
void FileDescriptorTables::BuildLocationsByPath(
1814
0
    std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p) {
1815
0
  for (int i = 0, len = p->second->location_size(); i < len; ++i) {
1816
0
    const SourceCodeInfo_Location* loc = &p->second->location().Get(i);
1817
0
    p->first->locations_by_path_[absl::StrJoin(loc->path(), ",")] = loc;
1818
0
  }
1819
0
}
1820
1821
const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
1822
0
    const std::vector<int>& path, const SourceCodeInfo* info) const {
1823
0
  std::pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
1824
0
      std::make_pair(this, info));
1825
0
  absl::call_once(locations_by_path_once_,
1826
0
                  FileDescriptorTables::BuildLocationsByPath, &p);
1827
0
  auto it = locations_by_path_.find(absl::StrJoin(path, ","));
1828
0
  if (it == locations_by_path_.end()) return nullptr;
1829
0
  return it->second;
1830
0
}
1831
1832
// ===================================================================
1833
// DescriptorPool
1834
1835
1836
0
DescriptorPool::ErrorCollector::~ErrorCollector() {}
1837
1838
absl::string_view DescriptorPool::ErrorCollector::ErrorLocationName(
1839
0
    ErrorLocation location) {
1840
0
  switch (location) {
1841
0
    case NAME:
1842
0
      return "NAME";
1843
0
    case NUMBER:
1844
0
      return "NUMBER";
1845
0
    case TYPE:
1846
0
      return "TYPE";
1847
0
    case EXTENDEE:
1848
0
      return "EXTENDEE";
1849
0
    case DEFAULT_VALUE:
1850
0
      return "DEFAULT_VALUE";
1851
0
    case OPTION_NAME:
1852
0
      return "OPTION_NAME";
1853
0
    case OPTION_VALUE:
1854
0
      return "OPTION_VALUE";
1855
0
    case INPUT_TYPE:
1856
0
      return "INPUT_TYPE";
1857
0
    case OUTPUT_TYPE:
1858
0
      return "OUTPUT_TYPE";
1859
0
    case IMPORT:
1860
0
      return "IMPORT";
1861
0
    case OTHER:
1862
0
      return "OTHER";
1863
0
  }
1864
0
  return "UNKNOWN";
1865
0
}
1866
1867
DescriptorPool::DescriptorPool()
1868
    : mutex_(nullptr),
1869
      fallback_database_(nullptr),
1870
      default_error_collector_(nullptr),
1871
      underlay_(nullptr),
1872
      tables_(new Tables),
1873
      enforce_dependencies_(true),
1874
      lazily_build_dependencies_(false),
1875
      allow_unknown_(false),
1876
      enforce_weak_(false),
1877
      enforce_extension_declarations_(false),
1878
      disallow_enforce_utf8_(false),
1879
0
      deprecated_legacy_json_field_conflicts_(false) {}
1880
1881
DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
1882
                               ErrorCollector* error_collector)
1883
    : mutex_(new absl::Mutex),
1884
      fallback_database_(fallback_database),
1885
      default_error_collector_(error_collector),
1886
      underlay_(nullptr),
1887
      tables_(new Tables),
1888
      enforce_dependencies_(true),
1889
      lazily_build_dependencies_(false),
1890
      allow_unknown_(false),
1891
      enforce_weak_(false),
1892
      enforce_extension_declarations_(false),
1893
      disallow_enforce_utf8_(false),
1894
0
      deprecated_legacy_json_field_conflicts_(false) {}
1895
1896
DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
1897
    : mutex_(nullptr),
1898
      fallback_database_(nullptr),
1899
      default_error_collector_(nullptr),
1900
      underlay_(underlay),
1901
      tables_(new Tables),
1902
      enforce_dependencies_(true),
1903
      lazily_build_dependencies_(false),
1904
      allow_unknown_(false),
1905
      enforce_weak_(false),
1906
      enforce_extension_declarations_(false),
1907
      disallow_enforce_utf8_(false),
1908
0
      deprecated_legacy_json_field_conflicts_(false) {}
1909
1910
0
DescriptorPool::~DescriptorPool() {
1911
0
  if (mutex_ != nullptr) delete mutex_;
1912
0
}
1913
1914
// DescriptorPool::BuildFile() defined later.
1915
// DescriptorPool::BuildFileCollectingErrors() defined later.
1916
1917
0
void DescriptorPool::InternalDontEnforceDependencies() {
1918
0
  enforce_dependencies_ = false;
1919
0
}
1920
1921
void DescriptorPool::AddUnusedImportTrackFile(absl::string_view file_name,
1922
0
                                              bool is_error) {
1923
0
  unused_import_track_files_[file_name] = is_error;
1924
0
}
1925
1926
1927
0
void DescriptorPool::ClearUnusedImportTrackFiles() {
1928
0
  unused_import_track_files_.clear();
1929
0
}
1930
1931
0
bool DescriptorPool::InternalIsFileLoaded(absl::string_view filename) const {
1932
0
  absl::MutexLockMaybe lock(mutex_);
1933
0
  return tables_->FindFile(filename) != nullptr;
1934
0
}
1935
1936
// generated_pool ====================================================
1937
1938
namespace {
1939
1940
1941
12
EncodedDescriptorDatabase* GeneratedDatabase() {
1942
12
  static auto generated_database =
1943
12
      internal::OnShutdownDelete(new EncodedDescriptorDatabase());
1944
12
  return generated_database;
1945
12
}
1946
1947
0
DescriptorPool* NewGeneratedPool() {
1948
0
  auto generated_pool = new DescriptorPool(GeneratedDatabase());
1949
0
  generated_pool->InternalSetLazilyBuildDependencies();
1950
0
  return generated_pool;
1951
0
}
1952
1953
}  // anonymous namespace
1954
1955
0
DescriptorDatabase* DescriptorPool::internal_generated_database() {
1956
0
  return GeneratedDatabase();
1957
0
}
1958
1959
0
DescriptorPool* DescriptorPool::internal_generated_pool() {
1960
0
  static DescriptorPool* generated_pool =
1961
0
      internal::OnShutdownDelete(NewGeneratedPool());
1962
0
  return generated_pool;
1963
0
}
1964
1965
0
const DescriptorPool* DescriptorPool::generated_pool() {
1966
0
  const DescriptorPool* pool = internal_generated_pool();
1967
  // Ensure that descriptor.proto gets registered in the generated pool. It is a
1968
  // special case because it is included in the full runtime. We have to avoid
1969
  // registering it pre-main, because we need to ensure that the linker
1970
  // --gc-sections step can strip out the full runtime if it is unused.
1971
0
  DescriptorProto::descriptor();
1972
0
  return pool;
1973
0
}
1974
1975
1976
void DescriptorPool::InternalAddGeneratedFile(
1977
12
    const void* encoded_file_descriptor, int size) {
1978
  // So, this function is called in the process of initializing the
1979
  // descriptors for generated proto classes.  Each generated .pb.cc file
1980
  // has an internal procedure called AddDescriptors() which is called at
1981
  // process startup, and that function calls this one in order to register
1982
  // the raw bytes of the FileDescriptorProto representing the file.
1983
  //
1984
  // We do not actually construct the descriptor objects right away.  We just
1985
  // hang on to the bytes until they are actually needed.  We actually construct
1986
  // the descriptor the first time one of the following things happens:
1987
  // * Someone calls a method like descriptor(), GetDescriptor(), or
1988
  //   GetReflection() on the generated types, which requires returning the
1989
  //   descriptor or an object based on it.
1990
  // * Someone looks up the descriptor in DescriptorPool::generated_pool().
1991
  //
1992
  // Once one of these happens, the DescriptorPool actually parses the
1993
  // FileDescriptorProto and generates a FileDescriptor (and all its children)
1994
  // based on it.
1995
  //
1996
  // Note that FileDescriptorProto is itself a generated protocol message.
1997
  // Therefore, when we parse one, we have to be very careful to avoid using
1998
  // any descriptor-based operations, since this might cause infinite recursion
1999
  // or deadlock.
2000
12
  ABSL_CHECK(GeneratedDatabase()->Add(encoded_file_descriptor, size));
2001
12
}
2002
2003
2004
// Find*By* methods ==================================================
2005
2006
// TODO(kenton):  There's a lot of repeated code here, but I'm not sure if
2007
//   there's any good way to factor it out.  Think about this some time when
2008
//   there's nothing more important to do (read: never).
2009
2010
const FileDescriptor* DescriptorPool::FindFileByName(
2011
0
    absl::string_view name) const {
2012
0
  absl::MutexLockMaybe lock(mutex_);
2013
0
  if (fallback_database_ != nullptr) {
2014
0
    tables_->known_bad_symbols_.clear();
2015
0
    tables_->known_bad_files_.clear();
2016
0
  }
2017
0
  const FileDescriptor* result = tables_->FindFile(name);
2018
0
  if (result != nullptr) return result;
2019
0
  if (underlay_ != nullptr) {
2020
0
    result = underlay_->FindFileByName(name);
2021
0
    if (result != nullptr) return result;
2022
0
  }
2023
0
  if (TryFindFileInFallbackDatabase(name)) {
2024
0
    result = tables_->FindFile(name);
2025
0
    if (result != nullptr) return result;
2026
0
  }
2027
0
  return nullptr;
2028
0
}
2029
2030
const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
2031
0
    absl::string_view symbol_name) const {
2032
0
  absl::MutexLockMaybe lock(mutex_);
2033
0
  if (fallback_database_ != nullptr) {
2034
0
    tables_->known_bad_symbols_.clear();
2035
0
    tables_->known_bad_files_.clear();
2036
0
  }
2037
0
  Symbol result = tables_->FindSymbol(symbol_name);
2038
0
  if (!result.IsNull()) return result.GetFile();
2039
0
  if (underlay_ != nullptr) {
2040
0
    const FileDescriptor* file_result =
2041
0
        underlay_->FindFileContainingSymbol(symbol_name);
2042
0
    if (file_result != nullptr) return file_result;
2043
0
  }
2044
0
  if (TryFindSymbolInFallbackDatabase(symbol_name)) {
2045
0
    result = tables_->FindSymbol(symbol_name);
2046
0
    if (!result.IsNull()) return result.GetFile();
2047
0
  }
2048
0
  return nullptr;
2049
0
}
2050
2051
const Descriptor* DescriptorPool::FindMessageTypeByName(
2052
0
    absl::string_view name) const {
2053
0
  return tables_->FindByNameHelper(this, name).descriptor();
2054
0
}
2055
2056
const FieldDescriptor* DescriptorPool::FindFieldByName(
2057
0
    absl::string_view name) const {
2058
0
  if (const FieldDescriptor* field =
2059
0
          tables_->FindByNameHelper(this, name).field_descriptor()) {
2060
0
    if (!field->is_extension()) {
2061
0
      return field;
2062
0
    }
2063
0
  }
2064
0
  return nullptr;
2065
0
}
2066
2067
const FieldDescriptor* DescriptorPool::FindExtensionByName(
2068
0
    absl::string_view name) const {
2069
0
  if (const FieldDescriptor* field =
2070
0
          tables_->FindByNameHelper(this, name).field_descriptor()) {
2071
0
    if (field->is_extension()) {
2072
0
      return field;
2073
0
    }
2074
0
  }
2075
0
  return nullptr;
2076
0
}
2077
2078
const OneofDescriptor* DescriptorPool::FindOneofByName(
2079
0
    absl::string_view name) const {
2080
0
  return tables_->FindByNameHelper(this, name).oneof_descriptor();
2081
0
}
2082
2083
const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
2084
0
    absl::string_view name) const {
2085
0
  return tables_->FindByNameHelper(this, name).enum_descriptor();
2086
0
}
2087
2088
const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
2089
0
    absl::string_view name) const {
2090
0
  return tables_->FindByNameHelper(this, name).enum_value_descriptor();
2091
0
}
2092
2093
const ServiceDescriptor* DescriptorPool::FindServiceByName(
2094
0
    absl::string_view name) const {
2095
0
  return tables_->FindByNameHelper(this, name).service_descriptor();
2096
0
}
2097
2098
const MethodDescriptor* DescriptorPool::FindMethodByName(
2099
0
    absl::string_view name) const {
2100
0
  return tables_->FindByNameHelper(this, name).method_descriptor();
2101
0
}
2102
2103
const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
2104
0
    const Descriptor* extendee, int number) const {
2105
0
  if (extendee->extension_range_count() == 0) return nullptr;
2106
  // A faster path to reduce lock contention in finding extensions, assuming
2107
  // most extensions will be cache hit.
2108
0
  if (mutex_ != nullptr) {
2109
0
    absl::ReaderMutexLock lock(mutex_);
2110
0
    const FieldDescriptor* result = tables_->FindExtension(extendee, number);
2111
0
    if (result != nullptr) {
2112
0
      return result;
2113
0
    }
2114
0
  }
2115
0
  absl::MutexLockMaybe lock(mutex_);
2116
0
  if (fallback_database_ != nullptr) {
2117
0
    tables_->known_bad_symbols_.clear();
2118
0
    tables_->known_bad_files_.clear();
2119
0
  }
2120
0
  const FieldDescriptor* result = tables_->FindExtension(extendee, number);
2121
0
  if (result != nullptr) {
2122
0
    return result;
2123
0
  }
2124
0
  if (underlay_ != nullptr) {
2125
0
    result = underlay_->FindExtensionByNumber(extendee, number);
2126
0
    if (result != nullptr) return result;
2127
0
  }
2128
0
  if (TryFindExtensionInFallbackDatabase(extendee, number)) {
2129
0
    result = tables_->FindExtension(extendee, number);
2130
0
    if (result != nullptr) {
2131
0
      return result;
2132
0
    }
2133
0
  }
2134
0
  return nullptr;
2135
0
}
2136
2137
const FieldDescriptor* DescriptorPool::InternalFindExtensionByNumberNoLock(
2138
0
    const Descriptor* extendee, int number) const {
2139
0
  if (extendee->extension_range_count() == 0) return nullptr;
2140
2141
0
  const FieldDescriptor* result = tables_->FindExtension(extendee, number);
2142
0
  if (result != nullptr) {
2143
0
    return result;
2144
0
  }
2145
2146
0
  if (underlay_ != nullptr) {
2147
0
    result = underlay_->InternalFindExtensionByNumberNoLock(extendee, number);
2148
0
    if (result != nullptr) return result;
2149
0
  }
2150
2151
0
  return nullptr;
2152
0
}
2153
2154
const FieldDescriptor* DescriptorPool::FindExtensionByPrintableName(
2155
0
    const Descriptor* extendee, absl::string_view printable_name) const {
2156
0
  if (extendee->extension_range_count() == 0) return nullptr;
2157
0
  const FieldDescriptor* result = FindExtensionByName(printable_name);
2158
0
  if (result != nullptr && result->containing_type() == extendee) {
2159
0
    return result;
2160
0
  }
2161
0
  if (extendee->options().message_set_wire_format()) {
2162
    // MessageSet extensions may be identified by type name.
2163
0
    const Descriptor* type = FindMessageTypeByName(printable_name);
2164
0
    if (type != nullptr) {
2165
      // Look for a matching extension in the foreign type's scope.
2166
0
      const int type_extension_count = type->extension_count();
2167
0
      for (int i = 0; i < type_extension_count; i++) {
2168
0
        const FieldDescriptor* extension = type->extension(i);
2169
0
        if (extension->containing_type() == extendee &&
2170
0
            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
2171
0
            extension->is_optional() && extension->message_type() == type) {
2172
          // Found it.
2173
0
          return extension;
2174
0
        }
2175
0
      }
2176
0
    }
2177
0
  }
2178
0
  return nullptr;
2179
0
}
2180
2181
void DescriptorPool::FindAllExtensions(
2182
    const Descriptor* extendee,
2183
0
    std::vector<const FieldDescriptor*>* out) const {
2184
0
  absl::MutexLockMaybe lock(mutex_);
2185
0
  if (fallback_database_ != nullptr) {
2186
0
    tables_->known_bad_symbols_.clear();
2187
0
    tables_->known_bad_files_.clear();
2188
0
  }
2189
2190
  // Initialize tables_->extensions_ from the fallback database first
2191
  // (but do this only once per descriptor).
2192
0
  if (fallback_database_ != nullptr &&
2193
0
      tables_->extensions_loaded_from_db_.count(extendee) == 0) {
2194
0
    std::vector<int> numbers;
2195
0
    if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
2196
0
                                                    &numbers)) {
2197
0
      for (int number : numbers) {
2198
0
        if (tables_->FindExtension(extendee, number) == nullptr) {
2199
0
          TryFindExtensionInFallbackDatabase(extendee, number);
2200
0
        }
2201
0
      }
2202
0
      tables_->extensions_loaded_from_db_.insert(extendee);
2203
0
    }
2204
0
  }
2205
2206
0
  tables_->FindAllExtensions(extendee, out);
2207
0
  if (underlay_ != nullptr) {
2208
0
    underlay_->FindAllExtensions(extendee, out);
2209
0
  }
2210
0
}
2211
2212
2213
// -------------------------------------------------------------------
2214
2215
0
const FieldDescriptor* Descriptor::FindFieldByNumber(int key) const {
2216
0
  const FieldDescriptor* result = file()->tables_->FindFieldByNumber(this, key);
2217
0
  if (result == nullptr || result->is_extension()) {
2218
0
    return nullptr;
2219
0
  } else {
2220
0
    return result;
2221
0
  }
2222
0
}
2223
2224
const FieldDescriptor* Descriptor::FindFieldByLowercaseName(
2225
0
    absl::string_view key) const {
2226
0
  const FieldDescriptor* result =
2227
0
      file()->tables_->FindFieldByLowercaseName(this, key);
2228
0
  if (result == nullptr || result->is_extension()) {
2229
0
    return nullptr;
2230
0
  } else {
2231
0
    return result;
2232
0
  }
2233
0
}
2234
2235
const FieldDescriptor* Descriptor::FindFieldByCamelcaseName(
2236
0
    absl::string_view key) const {
2237
0
  const FieldDescriptor* result =
2238
0
      file()->tables_->FindFieldByCamelcaseName(this, key);
2239
0
  if (result == nullptr || result->is_extension()) {
2240
0
    return nullptr;
2241
0
  } else {
2242
0
    return result;
2243
0
  }
2244
0
}
2245
2246
const FieldDescriptor* Descriptor::FindFieldByName(
2247
0
    absl::string_view key) const {
2248
0
  const FieldDescriptor* field =
2249
0
      file()->tables_->FindNestedSymbol(this, key).field_descriptor();
2250
0
  return field != nullptr && !field->is_extension() ? field : nullptr;
2251
0
}
2252
2253
const OneofDescriptor* Descriptor::FindOneofByName(
2254
0
    absl::string_view key) const {
2255
0
  return file()->tables_->FindNestedSymbol(this, key).oneof_descriptor();
2256
0
}
2257
2258
const FieldDescriptor* Descriptor::FindExtensionByName(
2259
0
    absl::string_view key) const {
2260
0
  const FieldDescriptor* field =
2261
0
      file()->tables_->FindNestedSymbol(this, key).field_descriptor();
2262
0
  return field != nullptr && field->is_extension() ? field : nullptr;
2263
0
}
2264
2265
const FieldDescriptor* Descriptor::FindExtensionByLowercaseName(
2266
0
    absl::string_view key) const {
2267
0
  const FieldDescriptor* result =
2268
0
      file()->tables_->FindFieldByLowercaseName(this, key);
2269
0
  if (result == nullptr || !result->is_extension()) {
2270
0
    return nullptr;
2271
0
  } else {
2272
0
    return result;
2273
0
  }
2274
0
}
2275
2276
const FieldDescriptor* Descriptor::FindExtensionByCamelcaseName(
2277
0
    absl::string_view key) const {
2278
0
  const FieldDescriptor* result =
2279
0
      file()->tables_->FindFieldByCamelcaseName(this, key);
2280
0
  if (result == nullptr || !result->is_extension()) {
2281
0
    return nullptr;
2282
0
  } else {
2283
0
    return result;
2284
0
  }
2285
0
}
2286
2287
const Descriptor* Descriptor::FindNestedTypeByName(
2288
0
    absl::string_view key) const {
2289
0
  return file()->tables_->FindNestedSymbol(this, key).descriptor();
2290
0
}
2291
2292
const EnumDescriptor* Descriptor::FindEnumTypeByName(
2293
0
    absl::string_view key) const {
2294
0
  return file()->tables_->FindNestedSymbol(this, key).enum_descriptor();
2295
0
}
2296
2297
const EnumValueDescriptor* Descriptor::FindEnumValueByName(
2298
0
    absl::string_view key) const {
2299
0
  return file()->tables_->FindNestedSymbol(this, key).enum_value_descriptor();
2300
0
}
2301
2302
0
const FieldDescriptor* Descriptor::map_key() const {
2303
0
  if (!options().map_entry()) return nullptr;
2304
0
  ABSL_DCHECK_EQ(field_count(), 2);
2305
0
  return field(0);
2306
0
}
2307
2308
0
const FieldDescriptor* Descriptor::map_value() const {
2309
0
  if (!options().map_entry()) return nullptr;
2310
0
  ABSL_DCHECK_EQ(field_count(), 2);
2311
0
  return field(1);
2312
0
}
2313
2314
const EnumValueDescriptor* EnumDescriptor::FindValueByName(
2315
0
    absl::string_view key) const {
2316
0
  return file()->tables_->FindNestedSymbol(this, key).enum_value_descriptor();
2317
0
}
2318
2319
0
const EnumValueDescriptor* EnumDescriptor::FindValueByNumber(int key) const {
2320
0
  return file()->tables_->FindEnumValueByNumber(this, key);
2321
0
}
2322
2323
const EnumValueDescriptor* EnumDescriptor::FindValueByNumberCreatingIfUnknown(
2324
0
    int key) const {
2325
0
  return file()->tables_->FindEnumValueByNumberCreatingIfUnknown(this, key);
2326
0
}
2327
2328
const MethodDescriptor* ServiceDescriptor::FindMethodByName(
2329
0
    absl::string_view key) const {
2330
0
  return file()->tables_->FindNestedSymbol(this, key).method_descriptor();
2331
0
}
2332
2333
const Descriptor* FileDescriptor::FindMessageTypeByName(
2334
0
    absl::string_view key) const {
2335
0
  return tables_->FindNestedSymbol(this, key).descriptor();
2336
0
}
2337
2338
const EnumDescriptor* FileDescriptor::FindEnumTypeByName(
2339
0
    absl::string_view key) const {
2340
0
  return tables_->FindNestedSymbol(this, key).enum_descriptor();
2341
0
}
2342
2343
const EnumValueDescriptor* FileDescriptor::FindEnumValueByName(
2344
0
    absl::string_view key) const {
2345
0
  return tables_->FindNestedSymbol(this, key).enum_value_descriptor();
2346
0
}
2347
2348
const ServiceDescriptor* FileDescriptor::FindServiceByName(
2349
0
    absl::string_view key) const {
2350
0
  return tables_->FindNestedSymbol(this, key).service_descriptor();
2351
0
}
2352
2353
const FieldDescriptor* FileDescriptor::FindExtensionByName(
2354
0
    absl::string_view key) const {
2355
0
  const FieldDescriptor* field =
2356
0
      tables_->FindNestedSymbol(this, key).field_descriptor();
2357
0
  return field != nullptr && field->is_extension() ? field : nullptr;
2358
0
}
2359
2360
const FieldDescriptor* FileDescriptor::FindExtensionByLowercaseName(
2361
0
    absl::string_view key) const {
2362
0
  const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
2363
0
  if (result == nullptr || !result->is_extension()) {
2364
0
    return nullptr;
2365
0
  } else {
2366
0
    return result;
2367
0
  }
2368
0
}
2369
2370
const FieldDescriptor* FileDescriptor::FindExtensionByCamelcaseName(
2371
0
    absl::string_view key) const {
2372
0
  const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
2373
0
  if (result == nullptr || !result->is_extension()) {
2374
0
    return nullptr;
2375
0
  } else {
2376
0
    return result;
2377
0
  }
2378
0
}
2379
2380
void Descriptor::ExtensionRange::CopyTo(
2381
0
    DescriptorProto_ExtensionRange* proto) const {
2382
0
  proto->set_start(start_);
2383
0
  proto->set_end(end_);
2384
0
  if (options_ != &ExtensionRangeOptions::default_instance()) {
2385
0
    *proto->mutable_options() = *options_;
2386
0
  }
2387
0
}
2388
2389
const Descriptor::ExtensionRange*
2390
0
Descriptor::FindExtensionRangeContainingNumber(int number) const {
2391
  // Linear search should be fine because we don't expect a message to have
2392
  // more than a couple extension ranges.
2393
0
  for (int i = 0; i < extension_range_count(); i++) {
2394
0
    if (number >= extension_range(i)->start_number() &&
2395
0
        number < extension_range(i)->end_number()) {
2396
0
      return extension_range(i);
2397
0
    }
2398
0
  }
2399
0
  return nullptr;
2400
0
}
2401
2402
const Descriptor::ReservedRange* Descriptor::FindReservedRangeContainingNumber(
2403
0
    int number) const {
2404
  // TODO(chrisn): Consider a non-linear search.
2405
0
  for (int i = 0; i < reserved_range_count(); i++) {
2406
0
    if (number >= reserved_range(i)->start && number < reserved_range(i)->end) {
2407
0
      return reserved_range(i);
2408
0
    }
2409
0
  }
2410
0
  return nullptr;
2411
0
}
2412
2413
const EnumDescriptor::ReservedRange*
2414
0
EnumDescriptor::FindReservedRangeContainingNumber(int number) const {
2415
  // TODO(chrisn): Consider a non-linear search.
2416
0
  for (int i = 0; i < reserved_range_count(); i++) {
2417
0
    if (number >= reserved_range(i)->start &&
2418
0
        number <= reserved_range(i)->end) {
2419
0
      return reserved_range(i);
2420
0
    }
2421
0
  }
2422
0
  return nullptr;
2423
0
}
2424
2425
// -------------------------------------------------------------------
2426
2427
bool DescriptorPool::TryFindFileInFallbackDatabase(
2428
0
    absl::string_view name) const {
2429
0
  if (fallback_database_ == nullptr) return false;
2430
2431
0
  if (tables_->known_bad_files_.contains(name)) return false;
2432
2433
  // NOINLINE to reduce the stack cost of the operation in the caller.
2434
0
  const auto find_file = [](DescriptorDatabase& database,
2435
0
                            absl::string_view filename,
2436
0
                            FileDescriptorProto& output) PROTOBUF_NOINLINE {
2437
0
    return database.FindFileByName(std::string(filename), &output);
2438
0
  };
2439
2440
0
  auto file_proto = absl::make_unique<FileDescriptorProto>();
2441
0
  if (!find_file(*fallback_database_, name, *file_proto) ||
2442
0
      BuildFileFromDatabase(*file_proto) == nullptr) {
2443
0
    tables_->known_bad_files_.emplace(name);
2444
0
    return false;
2445
0
  }
2446
0
  return true;
2447
0
}
2448
2449
0
bool DescriptorPool::IsSubSymbolOfBuiltType(absl::string_view name) const {
2450
0
  for (size_t pos = name.find('.'); pos != name.npos;
2451
0
       pos = name.find('.', pos + 1)) {
2452
0
    auto prefix = name.substr(0, pos);
2453
0
    Symbol symbol = tables_->FindSymbol(prefix);
2454
0
    if (symbol.IsNull()) {
2455
0
      break;
2456
0
    }
2457
0
    if (!symbol.IsPackage()) {
2458
      // If the symbol type is anything other than PACKAGE, then its complete
2459
      // definition is already known.
2460
0
      return true;
2461
0
    }
2462
0
  }
2463
0
  if (underlay_ != nullptr) {
2464
    // Check to see if any prefix of this symbol exists in the underlay.
2465
0
    return underlay_->IsSubSymbolOfBuiltType(name);
2466
0
  }
2467
0
  return false;
2468
0
}
2469
2470
bool DescriptorPool::TryFindSymbolInFallbackDatabase(
2471
0
    absl::string_view name) const {
2472
0
  if (fallback_database_ == nullptr) return false;
2473
2474
0
  if (tables_->known_bad_symbols_.contains(name)) return false;
2475
2476
0
  std::string name_string(name);
2477
0
  auto file_proto = absl::make_unique<FileDescriptorProto>();
2478
0
  if (  // We skip looking in the fallback database if the name is a sub-symbol
2479
        // of any descriptor that already exists in the descriptor pool (except
2480
        // for package descriptors).  This is valid because all symbols except
2481
        // for packages are defined in a single file, so if the symbol exists
2482
        // then we should already have its definition.
2483
        //
2484
        // The other reason to do this is to support "overriding" type
2485
        // definitions by merging two databases that define the same type. (Yes,
2486
        // people do this.)  The main difficulty with making this work is that
2487
        // FindFileContainingSymbol() is allowed to return both false positives
2488
        // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and
2489
        // false negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase).
2490
        // When two such databases are merged, looking up a non-existent
2491
        // sub-symbol of a type that already exists in the descriptor pool can
2492
        // result in an attempt to load multiple definitions of the same type.
2493
        // The check below avoids this.
2494
0
      IsSubSymbolOfBuiltType(name)
2495
2496
      // Look up file containing this symbol in fallback database.
2497
0
      || !fallback_database_->FindFileContainingSymbol(name_string,
2498
0
                                                       file_proto.get())
2499
2500
      // Check if we've already built this file. If so, it apparently doesn't
2501
      // contain the symbol we're looking for.  Some DescriptorDatabases
2502
      // return false positives.
2503
0
      || tables_->FindFile(file_proto->name()) != nullptr
2504
2505
      // Build the file.
2506
0
      || BuildFileFromDatabase(*file_proto) == nullptr) {
2507
0
    tables_->known_bad_symbols_.insert(std::move(name_string));
2508
0
    return false;
2509
0
  }
2510
2511
0
  return true;
2512
0
}
2513
2514
bool DescriptorPool::TryFindExtensionInFallbackDatabase(
2515
0
    const Descriptor* containing_type, int field_number) const {
2516
0
  if (fallback_database_ == nullptr) return false;
2517
2518
0
  auto file_proto = absl::make_unique<FileDescriptorProto>();
2519
0
  if (!fallback_database_->FindFileContainingExtension(
2520
0
          containing_type->full_name(), field_number, file_proto.get())) {
2521
0
    return false;
2522
0
  }
2523
2524
0
  if (tables_->FindFile(file_proto->name()) != nullptr) {
2525
    // We've already loaded this file, and it apparently doesn't contain the
2526
    // extension we're looking for.  Some DescriptorDatabases return false
2527
    // positives.
2528
0
    return false;
2529
0
  }
2530
2531
0
  if (BuildFileFromDatabase(*file_proto) == nullptr) {
2532
0
    return false;
2533
0
  }
2534
2535
0
  return true;
2536
0
}
2537
2538
// ===================================================================
2539
2540
0
bool FieldDescriptor::is_map_message_type() const {
2541
0
  return type_descriptor_.message_type->options().map_entry();
2542
0
}
2543
2544
std::string FieldDescriptor::DefaultValueAsString(
2545
0
    bool quote_string_type) const {
2546
0
  ABSL_CHECK(has_default_value()) << "No default value";
2547
0
  switch (cpp_type()) {
2548
0
    case CPPTYPE_INT32:
2549
0
      return absl::StrCat(default_value_int32_t());
2550
0
    case CPPTYPE_INT64:
2551
0
      return absl::StrCat(default_value_int64_t());
2552
0
    case CPPTYPE_UINT32:
2553
0
      return absl::StrCat(default_value_uint32_t());
2554
0
    case CPPTYPE_UINT64:
2555
0
      return absl::StrCat(default_value_uint64_t());
2556
0
    case CPPTYPE_FLOAT:
2557
0
      return io::SimpleFtoa(default_value_float());
2558
0
    case CPPTYPE_DOUBLE:
2559
0
      return io::SimpleDtoa(default_value_double());
2560
0
    case CPPTYPE_BOOL:
2561
0
      return default_value_bool() ? "true" : "false";
2562
0
    case CPPTYPE_STRING:
2563
0
      if (quote_string_type) {
2564
0
        return absl::StrCat("\"", absl::CEscape(default_value_string()), "\"");
2565
0
      } else {
2566
0
        if (type() == TYPE_BYTES) {
2567
0
          return absl::CEscape(default_value_string());
2568
0
        } else {
2569
0
          return default_value_string();
2570
0
        }
2571
0
      }
2572
0
    case CPPTYPE_ENUM:
2573
0
      return default_value_enum()->name();
2574
0
    case CPPTYPE_MESSAGE:
2575
0
      ABSL_DLOG(FATAL) << "Messages can't have default values!";
2576
0
      break;
2577
0
  }
2578
0
  ABSL_LOG(FATAL) << "Can't get here: failed to get default value as string";
2579
0
  return "";
2580
0
}
2581
2582
// Out-of-line constructor definitions ==============================
2583
// When using constructor type homing in Clang, debug info for a type
2584
// is only emitted when a constructor definition is emitted, as an
2585
// optimization. These constructors are never called, so we define them
2586
// out of line to make sure the debug info is emitted somewhere.
2587
2588
0
Descriptor::Descriptor() {}
2589
0
FieldDescriptor::FieldDescriptor() {}
2590
0
OneofDescriptor::OneofDescriptor() {}
2591
0
EnumDescriptor::EnumDescriptor() {}
2592
0
EnumValueDescriptor::EnumValueDescriptor() {}
2593
0
ServiceDescriptor::ServiceDescriptor() {}
2594
0
MethodDescriptor::MethodDescriptor() {}
2595
0
FileDescriptor::FileDescriptor() {}
2596
2597
// CopyTo methods ====================================================
2598
2599
0
void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
2600
0
  CopyHeadingTo(proto);
2601
2602
0
  for (int i = 0; i < dependency_count(); i++) {
2603
0
    proto->add_dependency(dependency(i)->name());
2604
0
  }
2605
2606
0
  for (int i = 0; i < public_dependency_count(); i++) {
2607
0
    proto->add_public_dependency(public_dependencies_[i]);
2608
0
  }
2609
2610
0
  for (int i = 0; i < weak_dependency_count(); i++) {
2611
0
    proto->add_weak_dependency(weak_dependencies_[i]);
2612
0
  }
2613
2614
0
  for (int i = 0; i < message_type_count(); i++) {
2615
0
    message_type(i)->CopyTo(proto->add_message_type());
2616
0
  }
2617
0
  for (int i = 0; i < enum_type_count(); i++) {
2618
0
    enum_type(i)->CopyTo(proto->add_enum_type());
2619
0
  }
2620
0
  for (int i = 0; i < service_count(); i++) {
2621
0
    service(i)->CopyTo(proto->add_service());
2622
0
  }
2623
0
  for (int i = 0; i < extension_count(); i++) {
2624
0
    extension(i)->CopyTo(proto->add_extension());
2625
0
  }
2626
0
}
2627
2628
0
void FileDescriptor::CopyHeadingTo(FileDescriptorProto* proto) const {
2629
0
  proto->set_name(name());
2630
0
  if (!package().empty()) {
2631
0
    proto->set_package(package());
2632
0
  }
2633
2634
  // TODO(liujisi): Also populate when syntax="proto2".
2635
0
  FileDescriptorLegacy::Syntax syntax = FileDescriptorLegacy(this).syntax();
2636
0
  if (syntax == FileDescriptorLegacy::Syntax::SYNTAX_PROTO3
2637
0
  ) {
2638
0
    proto->set_syntax(FileDescriptorLegacy::SyntaxName(syntax));
2639
0
  }
2640
2641
0
  if (&options() != &FileOptions::default_instance()) {
2642
0
    *proto->mutable_options() = options();
2643
0
  }
2644
0
}
2645
2646
0
void FileDescriptor::CopyJsonNameTo(FileDescriptorProto* proto) const {
2647
0
  if (message_type_count() != proto->message_type_size() ||
2648
0
      extension_count() != proto->extension_size()) {
2649
0
    ABSL_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
2650
0
    return;
2651
0
  }
2652
0
  for (int i = 0; i < message_type_count(); i++) {
2653
0
    message_type(i)->CopyJsonNameTo(proto->mutable_message_type(i));
2654
0
  }
2655
0
  for (int i = 0; i < extension_count(); i++) {
2656
0
    extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
2657
0
  }
2658
0
}
2659
2660
0
void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
2661
0
  if (source_code_info_ &&
2662
0
      source_code_info_ != &SourceCodeInfo::default_instance()) {
2663
0
    proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
2664
0
  }
2665
0
}
2666
2667
0
void Descriptor::CopyTo(DescriptorProto* proto) const {
2668
0
  proto->set_name(name());
2669
2670
0
  for (int i = 0; i < field_count(); i++) {
2671
0
    field(i)->CopyTo(proto->add_field());
2672
0
  }
2673
0
  for (int i = 0; i < oneof_decl_count(); i++) {
2674
0
    oneof_decl(i)->CopyTo(proto->add_oneof_decl());
2675
0
  }
2676
0
  for (int i = 0; i < nested_type_count(); i++) {
2677
0
    nested_type(i)->CopyTo(proto->add_nested_type());
2678
0
  }
2679
0
  for (int i = 0; i < enum_type_count(); i++) {
2680
0
    enum_type(i)->CopyTo(proto->add_enum_type());
2681
0
  }
2682
0
  for (int i = 0; i < extension_range_count(); i++) {
2683
0
    extension_range(i)->CopyTo(proto->add_extension_range());
2684
0
  }
2685
0
  for (int i = 0; i < extension_count(); i++) {
2686
0
    extension(i)->CopyTo(proto->add_extension());
2687
0
  }
2688
0
  for (int i = 0; i < reserved_range_count(); i++) {
2689
0
    DescriptorProto::ReservedRange* range = proto->add_reserved_range();
2690
0
    range->set_start(reserved_range(i)->start);
2691
0
    range->set_end(reserved_range(i)->end);
2692
0
  }
2693
0
  for (int i = 0; i < reserved_name_count(); i++) {
2694
0
    proto->add_reserved_name(reserved_name(i));
2695
0
  }
2696
2697
0
  if (&options() != &MessageOptions::default_instance()) {
2698
0
    proto->mutable_options()->CopyFrom(options());
2699
0
  }
2700
2701
0
}
2702
2703
0
void Descriptor::CopyJsonNameTo(DescriptorProto* proto) const {
2704
0
  if (field_count() != proto->field_size() ||
2705
0
      nested_type_count() != proto->nested_type_size() ||
2706
0
      extension_count() != proto->extension_size()) {
2707
0
    ABSL_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
2708
0
    return;
2709
0
  }
2710
0
  for (int i = 0; i < field_count(); i++) {
2711
0
    field(i)->CopyJsonNameTo(proto->mutable_field(i));
2712
0
  }
2713
0
  for (int i = 0; i < nested_type_count(); i++) {
2714
0
    nested_type(i)->CopyJsonNameTo(proto->mutable_nested_type(i));
2715
0
  }
2716
0
  for (int i = 0; i < extension_count(); i++) {
2717
0
    extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
2718
0
  }
2719
0
}
2720
2721
0
void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
2722
0
  proto->set_name(name());
2723
0
  proto->set_number(number());
2724
0
  if (has_json_name_) {
2725
0
    proto->set_json_name(json_name());
2726
0
  }
2727
0
  if (proto3_optional_) {
2728
0
    proto->set_proto3_optional(true);
2729
0
  }
2730
  // Some compilers do not allow static_cast directly between two enum types,
2731
  // so we must cast to int first.
2732
0
  proto->set_label(static_cast<FieldDescriptorProto::Label>(
2733
0
      absl::implicit_cast<int>(label())));
2734
0
  proto->set_type(static_cast<FieldDescriptorProto::Type>(
2735
0
      absl::implicit_cast<int>(type())));
2736
2737
0
  if (is_extension()) {
2738
0
    if (!containing_type()->is_unqualified_placeholder_) {
2739
0
      proto->set_extendee(".");
2740
0
    }
2741
0
    proto->mutable_extendee()->append(containing_type()->full_name());
2742
0
  }
2743
2744
0
  if (cpp_type() == CPPTYPE_MESSAGE) {
2745
0
    if (message_type()->is_placeholder_) {
2746
      // We don't actually know if the type is a message type.  It could be
2747
      // an enum.
2748
0
      proto->clear_type();
2749
0
    }
2750
2751
0
    if (!message_type()->is_unqualified_placeholder_) {
2752
0
      proto->set_type_name(".");
2753
0
    }
2754
0
    proto->mutable_type_name()->append(message_type()->full_name());
2755
0
  } else if (cpp_type() == CPPTYPE_ENUM) {
2756
0
    if (!enum_type()->is_unqualified_placeholder_) {
2757
0
      proto->set_type_name(".");
2758
0
    }
2759
0
    proto->mutable_type_name()->append(enum_type()->full_name());
2760
0
  }
2761
2762
0
  if (has_default_value()) {
2763
0
    proto->set_default_value(DefaultValueAsString(false));
2764
0
  }
2765
2766
0
  if (containing_oneof() != nullptr && !is_extension()) {
2767
0
    proto->set_oneof_index(containing_oneof()->index());
2768
0
  }
2769
2770
0
  if (&options() != &FieldOptions::default_instance()) {
2771
0
    proto->mutable_options()->CopyFrom(options());
2772
0
  }
2773
2774
0
}
2775
2776
0
void FieldDescriptor::CopyJsonNameTo(FieldDescriptorProto* proto) const {
2777
0
  proto->set_json_name(json_name());
2778
0
}
2779
2780
0
void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const {
2781
0
  proto->set_name(name());
2782
0
  if (&options() != &OneofOptions::default_instance()) {
2783
0
    proto->mutable_options()->CopyFrom(options());
2784
0
  }
2785
0
}
2786
2787
0
void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const {
2788
0
  proto->set_name(name());
2789
2790
0
  for (int i = 0; i < value_count(); i++) {
2791
0
    value(i)->CopyTo(proto->add_value());
2792
0
  }
2793
0
  for (int i = 0; i < reserved_range_count(); i++) {
2794
0
    EnumDescriptorProto::EnumReservedRange* range = proto->add_reserved_range();
2795
0
    range->set_start(reserved_range(i)->start);
2796
0
    range->set_end(reserved_range(i)->end);
2797
0
  }
2798
0
  for (int i = 0; i < reserved_name_count(); i++) {
2799
0
    proto->add_reserved_name(reserved_name(i));
2800
0
  }
2801
2802
0
  if (&options() != &EnumOptions::default_instance()) {
2803
0
    proto->mutable_options()->CopyFrom(options());
2804
0
  }
2805
0
}
2806
2807
0
void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const {
2808
0
  proto->set_name(name());
2809
0
  proto->set_number(number());
2810
2811
0
  if (&options() != &EnumValueOptions::default_instance()) {
2812
0
    proto->mutable_options()->CopyFrom(options());
2813
0
  }
2814
0
}
2815
2816
0
void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const {
2817
0
  proto->set_name(name());
2818
2819
0
  for (int i = 0; i < method_count(); i++) {
2820
0
    method(i)->CopyTo(proto->add_method());
2821
0
  }
2822
2823
0
  if (&options() != &ServiceOptions::default_instance()) {
2824
0
    proto->mutable_options()->CopyFrom(options());
2825
0
  }
2826
0
}
2827
2828
0
void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const {
2829
0
  proto->set_name(name());
2830
2831
0
  if (!input_type()->is_unqualified_placeholder_) {
2832
0
    proto->set_input_type(".");
2833
0
  }
2834
0
  proto->mutable_input_type()->append(input_type()->full_name());
2835
2836
0
  if (!output_type()->is_unqualified_placeholder_) {
2837
0
    proto->set_output_type(".");
2838
0
  }
2839
0
  proto->mutable_output_type()->append(output_type()->full_name());
2840
2841
0
  if (&options() != &MethodOptions::default_instance()) {
2842
0
    proto->mutable_options()->CopyFrom(options());
2843
0
  }
2844
2845
0
  if (client_streaming_) {
2846
0
    proto->set_client_streaming(true);
2847
0
  }
2848
0
  if (server_streaming_) {
2849
0
    proto->set_server_streaming(true);
2850
0
  }
2851
0
}
2852
2853
// DebugString methods ===============================================
2854
2855
namespace {
2856
2857
bool RetrieveOptionsAssumingRightPool(
2858
    int depth, const Message& options,
2859
0
    std::vector<std::string>* option_entries) {
2860
0
  option_entries->clear();
2861
0
  const Reflection* reflection = options.GetReflection();
2862
0
  std::vector<const FieldDescriptor*> fields;
2863
0
  reflection->ListFields(options, &fields);
2864
0
  for (const FieldDescriptor* field : fields) {
2865
0
    int count = 1;
2866
0
    bool repeated = false;
2867
0
    if (field->is_repeated()) {
2868
0
      count = reflection->FieldSize(options, field);
2869
0
      repeated = true;
2870
0
    }
2871
0
    for (int j = 0; j < count; j++) {
2872
0
      std::string fieldval;
2873
0
      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2874
0
        std::string tmp;
2875
0
        TextFormat::Printer printer;
2876
0
        printer.SetExpandAny(true);
2877
0
        printer.SetInitialIndentLevel(depth + 1);
2878
0
        printer.PrintFieldValueToString(options, field, repeated ? j : -1,
2879
0
                                        &tmp);
2880
0
        fieldval.append("{\n");
2881
0
        fieldval.append(tmp);
2882
0
        fieldval.append(depth * 2, ' ');
2883
0
        fieldval.append("}");
2884
0
      } else {
2885
0
        TextFormat::PrintFieldValueToString(options, field, repeated ? j : -1,
2886
0
                                            &fieldval);
2887
0
      }
2888
0
      std::string name;
2889
0
      if (field->is_extension()) {
2890
0
        name = absl::StrCat("(.", field->full_name(), ")");
2891
0
      } else {
2892
0
        name = field->name();
2893
0
      }
2894
0
      option_entries->push_back(absl::StrCat(name, " = ", fieldval));
2895
0
    }
2896
0
  }
2897
0
  return !option_entries->empty();
2898
0
}
2899
2900
// Used by each of the option formatters.
2901
bool RetrieveOptions(int depth, const Message& options,
2902
                     const DescriptorPool* pool,
2903
0
                     std::vector<std::string>* option_entries) {
2904
  // When printing custom options for a descriptor, we must use an options
2905
  // message built on top of the same DescriptorPool where the descriptor
2906
  // is coming from. This is to ensure we are interpreting custom options
2907
  // against the right pool.
2908
0
  if (options.GetDescriptor()->file()->pool() == pool) {
2909
0
    return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2910
0
  } else {
2911
0
    const Descriptor* option_descriptor =
2912
0
        pool->FindMessageTypeByName(options.GetDescriptor()->full_name());
2913
0
    if (option_descriptor == nullptr) {
2914
      // descriptor.proto is not in the pool. This means no custom options are
2915
      // used so we are safe to proceed with the compiled options message type.
2916
0
      return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2917
0
    }
2918
0
    DynamicMessageFactory factory;
2919
0
    std::unique_ptr<Message> dynamic_options(
2920
0
        factory.GetPrototype(option_descriptor)->New());
2921
0
    std::string serialized = options.SerializeAsString();
2922
0
    io::CodedInputStream input(
2923
0
        reinterpret_cast<const uint8_t*>(serialized.c_str()),
2924
0
        serialized.size());
2925
0
    input.SetExtensionRegistry(pool, &factory);
2926
0
    if (dynamic_options->ParseFromCodedStream(&input)) {
2927
0
      return RetrieveOptionsAssumingRightPool(depth, *dynamic_options,
2928
0
                                              option_entries);
2929
0
    } else {
2930
0
      ABSL_LOG(ERROR) << "Found invalid proto option data for: "
2931
0
                      << options.GetDescriptor()->full_name();
2932
0
      return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2933
0
    }
2934
0
  }
2935
0
}
2936
2937
// Formats options that all appear together in brackets. Does not include
2938
// brackets.
2939
bool FormatBracketedOptions(int depth, const Message& options,
2940
0
                            const DescriptorPool* pool, std::string* output) {
2941
0
  std::vector<std::string> all_options;
2942
0
  if (RetrieveOptions(depth, options, pool, &all_options)) {
2943
0
    output->append(absl::StrJoin(all_options, ", "));
2944
0
  }
2945
0
  return !all_options.empty();
2946
0
}
2947
2948
// Formats options one per line
2949
bool FormatLineOptions(int depth, const Message& options,
2950
0
                       const DescriptorPool* pool, std::string* output) {
2951
0
  std::string prefix(depth * 2, ' ');
2952
0
  std::vector<std::string> all_options;
2953
0
  if (RetrieveOptions(depth, options, pool, &all_options)) {
2954
0
    for (const std::string& option : all_options) {
2955
0
      absl::SubstituteAndAppend(output, "$0option $1;\n", prefix, option);
2956
0
    }
2957
0
  }
2958
0
  return !all_options.empty();
2959
0
}
2960
2961
class SourceLocationCommentPrinter {
2962
 public:
2963
  template <typename DescType>
2964
  SourceLocationCommentPrinter(const DescType* desc, const std::string& prefix,
2965
                               const DebugStringOptions& options)
2966
0
      : options_(options), prefix_(prefix) {
2967
    // Perform the SourceLocation lookup only if we're including user comments,
2968
    // because the lookup is fairly expensive.
2969
0
    have_source_loc_ =
2970
0
        options.include_comments && desc->GetSourceLocation(&source_loc_);
2971
0
  }
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::SourceLocationCommentPrinter::SourceLocationCommentPrinter<google::protobuf::FileDescriptor>(google::protobuf::FileDescriptor const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::DebugStringOptions const&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::SourceLocationCommentPrinter::SourceLocationCommentPrinter<google::protobuf::Descriptor>(google::protobuf::Descriptor const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::DebugStringOptions const&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::SourceLocationCommentPrinter::SourceLocationCommentPrinter<google::protobuf::FieldDescriptor>(google::protobuf::FieldDescriptor const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::DebugStringOptions const&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::SourceLocationCommentPrinter::SourceLocationCommentPrinter<google::protobuf::OneofDescriptor>(google::protobuf::OneofDescriptor const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::DebugStringOptions const&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::SourceLocationCommentPrinter::SourceLocationCommentPrinter<google::protobuf::EnumDescriptor>(google::protobuf::EnumDescriptor const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::DebugStringOptions const&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::SourceLocationCommentPrinter::SourceLocationCommentPrinter<google::protobuf::EnumValueDescriptor>(google::protobuf::EnumValueDescriptor const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::DebugStringOptions const&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::SourceLocationCommentPrinter::SourceLocationCommentPrinter<google::protobuf::ServiceDescriptor>(google::protobuf::ServiceDescriptor const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::DebugStringOptions const&)
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::SourceLocationCommentPrinter::SourceLocationCommentPrinter<google::protobuf::MethodDescriptor>(google::protobuf::MethodDescriptor const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::DebugStringOptions const&)
2972
  SourceLocationCommentPrinter(const FileDescriptor* file,
2973
                               const std::vector<int>& path,
2974
                               const std::string& prefix,
2975
                               const DebugStringOptions& options)
2976
0
      : options_(options), prefix_(prefix) {
2977
    // Perform the SourceLocation lookup only if we're including user comments,
2978
    // because the lookup is fairly expensive.
2979
0
    have_source_loc_ =
2980
0
        options.include_comments && file->GetSourceLocation(path, &source_loc_);
2981
0
  }
2982
0
  void AddPreComment(std::string* output) {
2983
0
    if (have_source_loc_) {
2984
      // Detached leading comments.
2985
0
      for (const std::string& leading_detached_comment :
2986
0
           source_loc_.leading_detached_comments) {
2987
0
        absl::StrAppend(output, FormatComment(leading_detached_comment), "\n");
2988
0
      }
2989
      // Attached leading comments.
2990
0
      if (!source_loc_.leading_comments.empty()) {
2991
0
        absl::StrAppend(output, FormatComment(source_loc_.leading_comments));
2992
0
      }
2993
0
    }
2994
0
  }
2995
0
  void AddPostComment(std::string* output) {
2996
0
    if (have_source_loc_ && source_loc_.trailing_comments.size() > 0) {
2997
0
      absl::StrAppend(output, FormatComment(source_loc_.trailing_comments));
2998
0
    }
2999
0
  }
3000
3001
  // Format comment such that each line becomes a full-line C++-style comment in
3002
  // the DebugString() output.
3003
0
  std::string FormatComment(const std::string& comment_text) {
3004
0
    std::string stripped_comment = comment_text;
3005
0
    absl::StripAsciiWhitespace(&stripped_comment);
3006
0
    std::string output;
3007
0
    for (absl::string_view line : absl::StrSplit(stripped_comment, '\n')) {
3008
0
      absl::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
3009
0
    }
3010
0
    return output;
3011
0
  }
3012
3013
 private:
3014
3015
  bool have_source_loc_;
3016
  SourceLocation source_loc_;
3017
  DebugStringOptions options_;
3018
  std::string prefix_;
3019
};
3020
3021
}  // anonymous namespace
3022
3023
0
std::string FileDescriptor::DebugString() const {
3024
0
  DebugStringOptions options;  // default options
3025
0
  return DebugStringWithOptions(options);
3026
0
}
3027
3028
std::string FileDescriptor::DebugStringWithOptions(
3029
0
    const DebugStringOptions& debug_string_options) const {
3030
0
  std::string contents;
3031
0
  {
3032
0
    std::vector<int> path;
3033
0
    path.push_back(FileDescriptorProto::kSyntaxFieldNumber);
3034
0
    SourceLocationCommentPrinter syntax_comment(this, path, "",
3035
0
                                                debug_string_options);
3036
0
    syntax_comment.AddPreComment(&contents);
3037
0
    absl::SubstituteAndAppend(
3038
0
        &contents, "syntax = \"$0\";\n\n",
3039
0
        FileDescriptorLegacy::SyntaxName(FileDescriptorLegacy(this).syntax()));
3040
0
    syntax_comment.AddPostComment(&contents);
3041
0
  }
3042
3043
0
  SourceLocationCommentPrinter comment_printer(this, "", debug_string_options);
3044
0
  comment_printer.AddPreComment(&contents);
3045
3046
0
  absl::flat_hash_set<int> public_dependencies(
3047
0
      public_dependencies_, public_dependencies_ + public_dependency_count_);
3048
0
  absl::flat_hash_set<int> weak_dependencies(
3049
0
      weak_dependencies_, weak_dependencies_ + weak_dependency_count_);
3050
3051
0
  for (int i = 0; i < dependency_count(); i++) {
3052
0
    if (public_dependencies.contains(i)) {
3053
0
      absl::SubstituteAndAppend(&contents, "import public \"$0\";\n",
3054
0
                                dependency(i)->name());
3055
0
    } else if (weak_dependencies.contains(i)) {
3056
0
      absl::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
3057
0
                                dependency(i)->name());
3058
0
    } else {
3059
0
      absl::SubstituteAndAppend(&contents, "import \"$0\";\n",
3060
0
                                dependency(i)->name());
3061
0
    }
3062
0
  }
3063
3064
0
  if (!package().empty()) {
3065
0
    std::vector<int> path;
3066
0
    path.push_back(FileDescriptorProto::kPackageFieldNumber);
3067
0
    SourceLocationCommentPrinter package_comment(this, path, "",
3068
0
                                                 debug_string_options);
3069
0
    package_comment.AddPreComment(&contents);
3070
0
    absl::SubstituteAndAppend(&contents, "package $0;\n\n", package());
3071
0
    package_comment.AddPostComment(&contents);
3072
0
  }
3073
3074
0
  if (FormatLineOptions(0, options(), pool(), &contents)) {
3075
0
    contents.append("\n");  // add some space if we had options
3076
0
  }
3077
3078
0
  for (int i = 0; i < enum_type_count(); i++) {
3079
0
    enum_type(i)->DebugString(0, &contents, debug_string_options);
3080
0
    contents.append("\n");
3081
0
  }
3082
3083
  // Find all the 'group' type extensions; we will not output their nested
3084
  // definitions (those will be done with their group field descriptor).
3085
0
  absl::flat_hash_set<const Descriptor*> groups;
3086
0
  for (int i = 0; i < extension_count(); i++) {
3087
0
    if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
3088
0
      groups.insert(extension(i)->message_type());
3089
0
    }
3090
0
  }
3091
3092
0
  for (int i = 0; i < message_type_count(); i++) {
3093
0
    if (!groups.contains(message_type(i))) {
3094
0
      message_type(i)->DebugString(0, &contents, debug_string_options,
3095
0
                                   /* include_opening_clause */ true);
3096
0
      contents.append("\n");
3097
0
    }
3098
0
  }
3099
3100
0
  for (int i = 0; i < service_count(); i++) {
3101
0
    service(i)->DebugString(&contents, debug_string_options);
3102
0
    contents.append("\n");
3103
0
  }
3104
3105
0
  const Descriptor* containing_type = nullptr;
3106
0
  for (int i = 0; i < extension_count(); i++) {
3107
0
    if (extension(i)->containing_type() != containing_type) {
3108
0
      if (i > 0) contents.append("}\n\n");
3109
0
      containing_type = extension(i)->containing_type();
3110
0
      absl::SubstituteAndAppend(&contents, "extend .$0 {\n",
3111
0
                                containing_type->full_name());
3112
0
    }
3113
0
    extension(i)->DebugString(1, &contents, debug_string_options);
3114
0
  }
3115
0
  if (extension_count() > 0) contents.append("}\n\n");
3116
3117
0
  comment_printer.AddPostComment(&contents);
3118
3119
0
  return contents;
3120
0
}
3121
3122
0
std::string Descriptor::DebugString() const {
3123
0
  DebugStringOptions options;  // default options
3124
0
  return DebugStringWithOptions(options);
3125
0
}
3126
3127
std::string Descriptor::DebugStringWithOptions(
3128
0
    const DebugStringOptions& options) const {
3129
0
  std::string contents;
3130
0
  DebugString(0, &contents, options, /* include_opening_clause */ true);
3131
0
  return contents;
3132
0
}
3133
3134
void Descriptor::DebugString(int depth, std::string* contents,
3135
                             const DebugStringOptions& debug_string_options,
3136
0
                             bool include_opening_clause) const {
3137
0
  if (options().map_entry()) {
3138
    // Do not generate debug string for auto-generated map-entry type.
3139
0
    return;
3140
0
  }
3141
0
  std::string prefix(depth * 2, ' ');
3142
0
  ++depth;
3143
3144
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3145
0
                                               debug_string_options);
3146
0
  comment_printer.AddPreComment(contents);
3147
3148
0
  if (include_opening_clause) {
3149
0
    absl::SubstituteAndAppend(contents, "$0message $1", prefix, name());
3150
0
  }
3151
0
  contents->append(" {\n");
3152
3153
0
  FormatLineOptions(depth, options(), file()->pool(), contents);
3154
3155
  // Find all the 'group' types for fields and extensions; we will not output
3156
  // their nested definitions (those will be done with their group field
3157
  // descriptor).
3158
0
  absl::flat_hash_set<const Descriptor*> groups;
3159
0
  for (int i = 0; i < field_count(); i++) {
3160
0
    if (field(i)->type() == FieldDescriptor::TYPE_GROUP) {
3161
0
      groups.insert(field(i)->message_type());
3162
0
    }
3163
0
  }
3164
0
  for (int i = 0; i < extension_count(); i++) {
3165
0
    if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
3166
0
      groups.insert(extension(i)->message_type());
3167
0
    }
3168
0
  }
3169
3170
0
  for (int i = 0; i < nested_type_count(); i++) {
3171
0
    if (!groups.contains(nested_type(i))) {
3172
0
      nested_type(i)->DebugString(depth, contents, debug_string_options,
3173
0
                                  /* include_opening_clause */ true);
3174
0
    }
3175
0
  }
3176
0
  for (int i = 0; i < enum_type_count(); i++) {
3177
0
    enum_type(i)->DebugString(depth, contents, debug_string_options);
3178
0
  }
3179
0
  for (int i = 0; i < field_count(); i++) {
3180
0
    if (field(i)->real_containing_oneof() == nullptr) {
3181
0
      field(i)->DebugString(depth, contents, debug_string_options);
3182
0
    } else if (field(i)->containing_oneof()->field(0) == field(i)) {
3183
      // This is the first field in this oneof, so print the whole oneof.
3184
0
      field(i)->containing_oneof()->DebugString(depth, contents,
3185
0
                                                debug_string_options);
3186
0
    }
3187
0
  }
3188
3189
0
  for (int i = 0; i < extension_range_count(); i++) {
3190
0
    absl::SubstituteAndAppend(contents, "$0  extensions $1", prefix,
3191
0
                              extension_range(i)->start_number());
3192
0
    if (extension_range(i)->end_number() >
3193
0
        extension_range(i)->start_number() + 1) {
3194
0
      absl::SubstituteAndAppend(contents, " to $0",
3195
0
                                extension_range(i)->end_number() - 1);
3196
0
    }
3197
0
    if (extension_range(i)->options().declaration_size() > 0) {
3198
0
      absl::StrAppend(contents, " [");
3199
0
      for (int j = 0; j < extension_range(i)->options().declaration_size();
3200
0
           ++j) {
3201
0
        if (j > 0) {
3202
0
          absl::StrAppend(contents, ",");
3203
0
        }
3204
0
        absl::SubstituteAndAppend(
3205
0
            contents, " declaration = { $0 }",
3206
0
            extension_range(i)->options().declaration(j).ShortDebugString());
3207
0
      }
3208
0
      absl::StrAppend(contents, " ] ");
3209
0
    }
3210
0
    absl::StrAppend(contents, ";\n");
3211
0
  }
3212
3213
  // Group extensions by what they extend, so they can be printed out together.
3214
0
  const Descriptor* containing_type = nullptr;
3215
0
  for (int i = 0; i < extension_count(); i++) {
3216
0
    if (extension(i)->containing_type() != containing_type) {
3217
0
      if (i > 0) absl::SubstituteAndAppend(contents, "$0  }\n", prefix);
3218
0
      containing_type = extension(i)->containing_type();
3219
0
      absl::SubstituteAndAppend(contents, "$0  extend .$1 {\n", prefix,
3220
0
                                containing_type->full_name());
3221
0
    }
3222
0
    extension(i)->DebugString(depth + 1, contents, debug_string_options);
3223
0
  }
3224
0
  if (extension_count() > 0)
3225
0
    absl::SubstituteAndAppend(contents, "$0  }\n", prefix);
3226
3227
0
  if (reserved_range_count() > 0) {
3228
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3229
0
    for (int i = 0; i < reserved_range_count(); i++) {
3230
0
      const Descriptor::ReservedRange* range = reserved_range(i);
3231
0
      if (range->end == range->start + 1) {
3232
0
        absl::SubstituteAndAppend(contents, "$0, ", range->start);
3233
0
      } else if (range->end > FieldDescriptor::kMaxNumber) {
3234
0
        absl::SubstituteAndAppend(contents, "$0 to max, ", range->start);
3235
0
      } else {
3236
0
        absl::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
3237
0
                                  range->end - 1);
3238
0
      }
3239
0
    }
3240
0
    contents->replace(contents->size() - 2, 2, ";\n");
3241
0
  }
3242
3243
0
  if (reserved_name_count() > 0) {
3244
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3245
0
    for (int i = 0; i < reserved_name_count(); i++) {
3246
0
      absl::SubstituteAndAppend(contents, "\"$0\", ",
3247
0
                                absl::CEscape(reserved_name(i)));
3248
0
    }
3249
0
    contents->replace(contents->size() - 2, 2, ";\n");
3250
0
  }
3251
3252
0
  absl::SubstituteAndAppend(contents, "$0}\n", prefix);
3253
0
  comment_printer.AddPostComment(contents);
3254
0
}
3255
3256
0
std::string FieldDescriptor::DebugString() const {
3257
0
  DebugStringOptions options;  // default options
3258
0
  return DebugStringWithOptions(options);
3259
0
}
3260
3261
std::string FieldDescriptor::DebugStringWithOptions(
3262
0
    const DebugStringOptions& debug_string_options) const {
3263
0
  std::string contents;
3264
0
  int depth = 0;
3265
0
  if (is_extension()) {
3266
0
    absl::SubstituteAndAppend(&contents, "extend .$0 {\n",
3267
0
                              containing_type()->full_name());
3268
0
    depth = 1;
3269
0
  }
3270
0
  DebugString(depth, &contents, debug_string_options);
3271
0
  if (is_extension()) {
3272
0
    contents.append("}\n");
3273
0
  }
3274
0
  return contents;
3275
0
}
3276
3277
// The field type string used in FieldDescriptor::DebugString()
3278
0
std::string FieldDescriptor::FieldTypeNameDebugString() const {
3279
0
  switch (type()) {
3280
0
    case TYPE_MESSAGE:
3281
0
      return absl::StrCat(".", message_type()->full_name());
3282
0
    case TYPE_ENUM:
3283
0
      return absl::StrCat(".", enum_type()->full_name());
3284
0
    default:
3285
0
      return kTypeToName[type()];
3286
0
  }
3287
0
}
3288
3289
void FieldDescriptor::DebugString(
3290
    int depth, std::string* contents,
3291
0
    const DebugStringOptions& debug_string_options) const {
3292
0
  std::string prefix(depth * 2, ' ');
3293
0
  std::string field_type;
3294
3295
  // Special case map fields.
3296
0
  if (is_map()) {
3297
0
    absl::SubstituteAndAppend(
3298
0
        &field_type, "map<$0, $1>",
3299
0
        message_type()->field(0)->FieldTypeNameDebugString(),
3300
0
        message_type()->field(1)->FieldTypeNameDebugString());
3301
0
  } else {
3302
0
    field_type = FieldTypeNameDebugString();
3303
0
  }
3304
3305
0
  std::string label = absl::StrCat(kLabelToName[this->label()], " ");
3306
3307
  // Label is omitted for maps, oneof, and plain proto3 fields.
3308
0
  if (is_map() || real_containing_oneof() ||
3309
0
      (is_optional() && !FieldDescriptorLegacy(this).has_optional_keyword())) {
3310
0
    label.clear();
3311
0
  }
3312
3313
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3314
0
                                               debug_string_options);
3315
0
  comment_printer.AddPreComment(contents);
3316
3317
0
  absl::SubstituteAndAppend(
3318
0
      contents, "$0$1$2 $3 = $4", prefix, label, field_type,
3319
0
      type() == TYPE_GROUP ? message_type()->name() : name(), number());
3320
3321
0
  bool bracketed = false;
3322
0
  if (has_default_value()) {
3323
0
    bracketed = true;
3324
0
    absl::SubstituteAndAppend(contents, " [default = $0",
3325
0
                              DefaultValueAsString(true));
3326
0
  }
3327
0
  if (has_json_name_) {
3328
0
    if (!bracketed) {
3329
0
      bracketed = true;
3330
0
      contents->append(" [");
3331
0
    } else {
3332
0
      contents->append(", ");
3333
0
    }
3334
0
    contents->append("json_name = \"");
3335
0
    contents->append(absl::CEscape(json_name()));
3336
0
    contents->append("\"");
3337
0
  }
3338
3339
0
  std::string formatted_options;
3340
0
  if (FormatBracketedOptions(depth, options(), file()->pool(),
3341
0
                             &formatted_options)) {
3342
0
    contents->append(bracketed ? ", " : " [");
3343
0
    bracketed = true;
3344
0
    contents->append(formatted_options);
3345
0
  }
3346
3347
0
  if (bracketed) {
3348
0
    contents->append("]");
3349
0
  }
3350
3351
0
  if (type() == TYPE_GROUP) {
3352
0
    if (debug_string_options.elide_group_body) {
3353
0
      contents->append(" { ... };\n");
3354
0
    } else {
3355
0
      message_type()->DebugString(depth, contents, debug_string_options,
3356
0
                                  /* include_opening_clause */ false);
3357
0
    }
3358
0
  } else {
3359
0
    contents->append(";\n");
3360
0
  }
3361
3362
0
  comment_printer.AddPostComment(contents);
3363
0
}
3364
3365
0
std::string OneofDescriptor::DebugString() const {
3366
0
  DebugStringOptions options;  // default values
3367
0
  return DebugStringWithOptions(options);
3368
0
}
3369
3370
std::string OneofDescriptor::DebugStringWithOptions(
3371
0
    const DebugStringOptions& options) const {
3372
0
  std::string contents;
3373
0
  DebugString(0, &contents, options);
3374
0
  return contents;
3375
0
}
3376
3377
void OneofDescriptor::DebugString(
3378
    int depth, std::string* contents,
3379
0
    const DebugStringOptions& debug_string_options) const {
3380
0
  std::string prefix(depth * 2, ' ');
3381
0
  ++depth;
3382
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3383
0
                                               debug_string_options);
3384
0
  comment_printer.AddPreComment(contents);
3385
0
  absl::SubstituteAndAppend(contents, "$0oneof $1 {", prefix, name());
3386
3387
0
  FormatLineOptions(depth, options(), containing_type()->file()->pool(),
3388
0
                    contents);
3389
3390
0
  if (debug_string_options.elide_oneof_body) {
3391
0
    contents->append(" ... }\n");
3392
0
  } else {
3393
0
    contents->append("\n");
3394
0
    for (int i = 0; i < field_count(); i++) {
3395
0
      field(i)->DebugString(depth, contents, debug_string_options);
3396
0
    }
3397
0
    absl::SubstituteAndAppend(contents, "$0}\n", prefix);
3398
0
  }
3399
0
  comment_printer.AddPostComment(contents);
3400
0
}
3401
3402
0
std::string EnumDescriptor::DebugString() const {
3403
0
  DebugStringOptions options;  // default values
3404
0
  return DebugStringWithOptions(options);
3405
0
}
3406
3407
std::string EnumDescriptor::DebugStringWithOptions(
3408
0
    const DebugStringOptions& options) const {
3409
0
  std::string contents;
3410
0
  DebugString(0, &contents, options);
3411
0
  return contents;
3412
0
}
3413
3414
void EnumDescriptor::DebugString(
3415
    int depth, std::string* contents,
3416
0
    const DebugStringOptions& debug_string_options) const {
3417
0
  std::string prefix(depth * 2, ' ');
3418
0
  ++depth;
3419
3420
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3421
0
                                               debug_string_options);
3422
0
  comment_printer.AddPreComment(contents);
3423
3424
0
  absl::SubstituteAndAppend(contents, "$0enum $1 {\n", prefix, name());
3425
3426
0
  FormatLineOptions(depth, options(), file()->pool(), contents);
3427
3428
0
  for (int i = 0; i < value_count(); i++) {
3429
0
    value(i)->DebugString(depth, contents, debug_string_options);
3430
0
  }
3431
3432
0
  if (reserved_range_count() > 0) {
3433
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3434
0
    for (int i = 0; i < reserved_range_count(); i++) {
3435
0
      const EnumDescriptor::ReservedRange* range = reserved_range(i);
3436
0
      if (range->end == range->start) {
3437
0
        absl::SubstituteAndAppend(contents, "$0, ", range->start);
3438
0
      } else if (range->end == INT_MAX) {
3439
0
        absl::SubstituteAndAppend(contents, "$0 to max, ", range->start);
3440
0
      } else {
3441
0
        absl::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
3442
0
                                  range->end);
3443
0
      }
3444
0
    }
3445
0
    contents->replace(contents->size() - 2, 2, ";\n");
3446
0
  }
3447
3448
0
  if (reserved_name_count() > 0) {
3449
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3450
0
    for (int i = 0; i < reserved_name_count(); i++) {
3451
0
      absl::SubstituteAndAppend(contents, "\"$0\", ",
3452
0
                                absl::CEscape(reserved_name(i)));
3453
0
    }
3454
0
    contents->replace(contents->size() - 2, 2, ";\n");
3455
0
  }
3456
3457
0
  absl::SubstituteAndAppend(contents, "$0}\n", prefix);
3458
3459
0
  comment_printer.AddPostComment(contents);
3460
0
}
3461
3462
0
std::string EnumValueDescriptor::DebugString() const {
3463
0
  DebugStringOptions options;  // default values
3464
0
  return DebugStringWithOptions(options);
3465
0
}
3466
3467
std::string EnumValueDescriptor::DebugStringWithOptions(
3468
0
    const DebugStringOptions& options) const {
3469
0
  std::string contents;
3470
0
  DebugString(0, &contents, options);
3471
0
  return contents;
3472
0
}
3473
3474
void EnumValueDescriptor::DebugString(
3475
    int depth, std::string* contents,
3476
0
    const DebugStringOptions& debug_string_options) const {
3477
0
  std::string prefix(depth * 2, ' ');
3478
3479
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3480
0
                                               debug_string_options);
3481
0
  comment_printer.AddPreComment(contents);
3482
3483
0
  absl::SubstituteAndAppend(contents, "$0$1 = $2", prefix, name(), number());
3484
3485
0
  std::string formatted_options;
3486
0
  if (FormatBracketedOptions(depth, options(), type()->file()->pool(),
3487
0
                             &formatted_options)) {
3488
0
    absl::SubstituteAndAppend(contents, " [$0]", formatted_options);
3489
0
  }
3490
0
  contents->append(";\n");
3491
3492
0
  comment_printer.AddPostComment(contents);
3493
0
}
3494
3495
0
std::string ServiceDescriptor::DebugString() const {
3496
0
  DebugStringOptions options;  // default values
3497
0
  return DebugStringWithOptions(options);
3498
0
}
3499
3500
std::string ServiceDescriptor::DebugStringWithOptions(
3501
0
    const DebugStringOptions& options) const {
3502
0
  std::string contents;
3503
0
  DebugString(&contents, options);
3504
0
  return contents;
3505
0
}
3506
3507
void ServiceDescriptor::DebugString(
3508
    std::string* contents,
3509
0
    const DebugStringOptions& debug_string_options) const {
3510
0
  SourceLocationCommentPrinter comment_printer(this, /* prefix */ "",
3511
0
                                               debug_string_options);
3512
0
  comment_printer.AddPreComment(contents);
3513
3514
0
  absl::SubstituteAndAppend(contents, "service $0 {\n", name());
3515
3516
0
  FormatLineOptions(1, options(), file()->pool(), contents);
3517
3518
0
  for (int i = 0; i < method_count(); i++) {
3519
0
    method(i)->DebugString(1, contents, debug_string_options);
3520
0
  }
3521
3522
0
  contents->append("}\n");
3523
3524
0
  comment_printer.AddPostComment(contents);
3525
0
}
3526
3527
0
std::string MethodDescriptor::DebugString() const {
3528
0
  DebugStringOptions options;  // default values
3529
0
  return DebugStringWithOptions(options);
3530
0
}
3531
3532
std::string MethodDescriptor::DebugStringWithOptions(
3533
0
    const DebugStringOptions& options) const {
3534
0
  std::string contents;
3535
0
  DebugString(0, &contents, options);
3536
0
  return contents;
3537
0
}
3538
3539
void MethodDescriptor::DebugString(
3540
    int depth, std::string* contents,
3541
0
    const DebugStringOptions& debug_string_options) const {
3542
0
  std::string prefix(depth * 2, ' ');
3543
0
  ++depth;
3544
3545
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3546
0
                                               debug_string_options);
3547
0
  comment_printer.AddPreComment(contents);
3548
3549
0
  absl::SubstituteAndAppend(
3550
0
      contents, "$0rpc $1($4.$2) returns ($5.$3)", prefix, name(),
3551
0
      input_type()->full_name(), output_type()->full_name(),
3552
0
      client_streaming() ? "stream " : "", server_streaming() ? "stream " : "");
3553
3554
0
  std::string formatted_options;
3555
0
  if (FormatLineOptions(depth, options(), service()->file()->pool(),
3556
0
                        &formatted_options)) {
3557
0
    absl::SubstituteAndAppend(contents, " {\n$0$1}\n", formatted_options,
3558
0
                              prefix);
3559
0
  } else {
3560
0
    contents->append(";\n");
3561
0
  }
3562
3563
0
  comment_printer.AddPostComment(contents);
3564
0
}
3565
3566
// Location methods ===============================================
3567
3568
bool FileDescriptor::GetSourceLocation(const std::vector<int>& path,
3569
0
                                       SourceLocation* out_location) const {
3570
0
  ABSL_CHECK(out_location != nullptr);
3571
0
  if (source_code_info_) {
3572
0
    if (const SourceCodeInfo_Location* loc =
3573
0
            tables_->GetSourceLocation(path, source_code_info_)) {
3574
0
      const RepeatedField<int32_t>& span = loc->span();
3575
0
      if (span.size() == 3 || span.size() == 4) {
3576
0
        out_location->start_line = span.Get(0);
3577
0
        out_location->start_column = span.Get(1);
3578
0
        out_location->end_line = span.Get(span.size() == 3 ? 0 : 2);
3579
0
        out_location->end_column = span.Get(span.size() - 1);
3580
3581
0
        out_location->leading_comments = loc->leading_comments();
3582
0
        out_location->trailing_comments = loc->trailing_comments();
3583
0
        out_location->leading_detached_comments.assign(
3584
0
            loc->leading_detached_comments().begin(),
3585
0
            loc->leading_detached_comments().end());
3586
0
        return true;
3587
0
      }
3588
0
    }
3589
0
  }
3590
0
  return false;
3591
0
}
3592
3593
0
bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3594
0
  std::vector<int> path;  // empty path for root FileDescriptor
3595
0
  return GetSourceLocation(path, out_location);
3596
0
}
3597
3598
0
bool FieldDescriptor::is_packed() const {
3599
0
  if (!is_packable()) return false;
3600
0
  if (FileDescriptorLegacy(file_).syntax() ==
3601
0
      FileDescriptorLegacy::Syntax::SYNTAX_PROTO2) {
3602
0
    return (options_ != nullptr) && options_->packed();
3603
0
  } else {
3604
0
    return options_ == nullptr || !options_->has_packed() || options_->packed();
3605
0
  }
3606
0
}
3607
3608
0
bool FieldDescriptor::requires_utf8_validation() const {
3609
0
  return type() == TYPE_STRING &&
3610
0
         FileDescriptorLegacy(file_).syntax() ==
3611
0
             FileDescriptorLegacy::Syntax::SYNTAX_PROTO3;
3612
0
}
3613
3614
0
bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
3615
0
  std::vector<int> path;
3616
0
  GetLocationPath(&path);
3617
0
  return file()->GetSourceLocation(path, out_location);
3618
0
}
3619
3620
0
bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3621
0
  std::vector<int> path;
3622
0
  GetLocationPath(&path);
3623
0
  return file()->GetSourceLocation(path, out_location);
3624
0
}
3625
3626
0
bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3627
0
  std::vector<int> path;
3628
0
  GetLocationPath(&path);
3629
0
  return containing_type()->file()->GetSourceLocation(path, out_location);
3630
0
}
3631
3632
0
bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3633
0
  std::vector<int> path;
3634
0
  GetLocationPath(&path);
3635
0
  return file()->GetSourceLocation(path, out_location);
3636
0
}
3637
3638
0
bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3639
0
  std::vector<int> path;
3640
0
  GetLocationPath(&path);
3641
0
  return service()->file()->GetSourceLocation(path, out_location);
3642
0
}
3643
3644
0
bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3645
0
  std::vector<int> path;
3646
0
  GetLocationPath(&path);
3647
0
  return file()->GetSourceLocation(path, out_location);
3648
0
}
3649
3650
bool EnumValueDescriptor::GetSourceLocation(
3651
0
    SourceLocation* out_location) const {
3652
0
  std::vector<int> path;
3653
0
  GetLocationPath(&path);
3654
0
  return type()->file()->GetSourceLocation(path, out_location);
3655
0
}
3656
3657
0
void Descriptor::GetLocationPath(std::vector<int>* output) const {
3658
0
  if (containing_type()) {
3659
0
    containing_type()->GetLocationPath(output);
3660
0
    output->push_back(DescriptorProto::kNestedTypeFieldNumber);
3661
0
    output->push_back(index());
3662
0
  } else {
3663
0
    output->push_back(FileDescriptorProto::kMessageTypeFieldNumber);
3664
0
    output->push_back(index());
3665
0
  }
3666
0
}
3667
3668
0
void FieldDescriptor::GetLocationPath(std::vector<int>* output) const {
3669
0
  if (is_extension()) {
3670
0
    if (extension_scope() == nullptr) {
3671
0
      output->push_back(FileDescriptorProto::kExtensionFieldNumber);
3672
0
      output->push_back(index());
3673
0
    } else {
3674
0
      extension_scope()->GetLocationPath(output);
3675
0
      output->push_back(DescriptorProto::kExtensionFieldNumber);
3676
0
      output->push_back(index());
3677
0
    }
3678
0
  } else {
3679
0
    containing_type()->GetLocationPath(output);
3680
0
    output->push_back(DescriptorProto::kFieldFieldNumber);
3681
0
    output->push_back(index());
3682
0
  }
3683
0
}
3684
3685
0
void OneofDescriptor::GetLocationPath(std::vector<int>* output) const {
3686
0
  containing_type()->GetLocationPath(output);
3687
0
  output->push_back(DescriptorProto::kOneofDeclFieldNumber);
3688
0
  output->push_back(index());
3689
0
}
3690
3691
void Descriptor::ExtensionRange::GetLocationPath(
3692
0
    std::vector<int>* output) const {
3693
0
  containing_type()->GetLocationPath(output);
3694
0
  output->push_back(DescriptorProto::kExtensionRangeFieldNumber);
3695
0
  output->push_back(index());
3696
0
}
3697
3698
0
void EnumDescriptor::GetLocationPath(std::vector<int>* output) const {
3699
0
  if (containing_type()) {
3700
0
    containing_type()->GetLocationPath(output);
3701
0
    output->push_back(DescriptorProto::kEnumTypeFieldNumber);
3702
0
    output->push_back(index());
3703
0
  } else {
3704
0
    output->push_back(FileDescriptorProto::kEnumTypeFieldNumber);
3705
0
    output->push_back(index());
3706
0
  }
3707
0
}
3708
3709
0
void EnumValueDescriptor::GetLocationPath(std::vector<int>* output) const {
3710
0
  type()->GetLocationPath(output);
3711
0
  output->push_back(EnumDescriptorProto::kValueFieldNumber);
3712
0
  output->push_back(index());
3713
0
}
3714
3715
0
void ServiceDescriptor::GetLocationPath(std::vector<int>* output) const {
3716
0
  output->push_back(FileDescriptorProto::kServiceFieldNumber);
3717
0
  output->push_back(index());
3718
0
}
3719
3720
0
void MethodDescriptor::GetLocationPath(std::vector<int>* output) const {
3721
0
  service()->GetLocationPath(output);
3722
0
  output->push_back(ServiceDescriptorProto::kMethodFieldNumber);
3723
0
  output->push_back(index());
3724
0
}
3725
3726
// ===================================================================
3727
3728
namespace {
3729
3730
// Represents an options message to interpret. Extension names in the option
3731
// name are resolved relative to name_scope. element_name and orig_opt are
3732
// used only for error reporting (since the parser records locations against
3733
// pointers in the original options, not the mutable copy). The Message must be
3734
// one of the Options messages in descriptor.proto.
3735
struct OptionsToInterpret {
3736
  OptionsToInterpret(absl::string_view ns, absl::string_view el,
3737
                     absl::Span<const int> path, const Message* orig_opt,
3738
                     Message* opt)
3739
      : name_scope(ns),
3740
        element_name(el),
3741
        element_path(path.begin(), path.end()),
3742
        original_options(orig_opt),
3743
0
        options(opt) {}
3744
  std::string name_scope;
3745
  std::string element_name;
3746
  std::vector<int> element_path;
3747
  const Message* original_options;
3748
  Message* options;
3749
};
3750
3751
}  // namespace
3752
3753
class DescriptorBuilder {
3754
 public:
3755
  static std::unique_ptr<DescriptorBuilder> New(
3756
      const DescriptorPool* pool, DescriptorPool::Tables* tables,
3757
0
      DescriptorPool::ErrorCollector* error_collector) {
3758
0
    return std::unique_ptr<DescriptorBuilder>(
3759
0
        new DescriptorBuilder(pool, tables, error_collector));
3760
0
  }
3761
3762
  ~DescriptorBuilder();
3763
3764
  const FileDescriptor* BuildFile(const FileDescriptorProto& original_proto);
3765
3766
 private:
3767
  DescriptorBuilder(const DescriptorPool* pool, DescriptorPool::Tables* tables,
3768
                    DescriptorPool::ErrorCollector* error_collector);
3769
3770
  friend class OptionInterpreter;
3771
3772
  // Non-recursive part of BuildFile functionality.
3773
  FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto,
3774
                                internal::FlatAllocator& alloc);
3775
3776
  const DescriptorPool* pool_;
3777
  DescriptorPool::Tables* tables_;  // for convenience
3778
  DescriptorPool::ErrorCollector* error_collector_;
3779
3780
3781
  // As we build descriptors we store copies of the options messages in
3782
  // them. We put pointers to those copies in this vector, as we build, so we
3783
  // can later (after cross-linking) interpret those options.
3784
  std::vector<OptionsToInterpret> options_to_interpret_;
3785
3786
  bool had_errors_;
3787
  std::string filename_;
3788
  FileDescriptor* file_;
3789
  FileDescriptorTables* file_tables_;
3790
  absl::flat_hash_set<const FileDescriptor*> dependencies_;
3791
3792
  struct MessageHints {
3793
    int fields_to_suggest = 0;
3794
    const Message* first_reason = nullptr;
3795
    DescriptorPool::ErrorCollector::ErrorLocation first_reason_location =
3796
        DescriptorPool::ErrorCollector::ErrorLocation::OTHER;
3797
3798
    void RequestHintOnFieldNumbers(
3799
        const Message& reason,
3800
        DescriptorPool::ErrorCollector::ErrorLocation reason_location,
3801
0
        int range_start = 0, int range_end = 1) {
3802
0
      auto fit = [](int value) {
3803
0
        return std::min(std::max(value, 0), FieldDescriptor::kMaxNumber);
3804
0
      };
3805
0
      fields_to_suggest =
3806
0
          fit(fields_to_suggest + fit(fit(range_end) - fit(range_start)));
3807
0
      if (first_reason) return;
3808
0
      first_reason = &reason;
3809
0
      first_reason_location = reason_location;
3810
0
    }
3811
  };
3812
3813
  absl::flat_hash_map<const Descriptor*, MessageHints> message_hints_;
3814
3815
  // unused_dependency_ is used to record the unused imported files.
3816
  // Note: public import is not considered.
3817
  absl::flat_hash_set<const FileDescriptor*> unused_dependency_;
3818
3819
  // If LookupSymbol() finds a symbol that is in a file which is not a declared
3820
  // dependency of this file, it will fail, but will set
3821
  // possible_undeclared_dependency_ to point at that file.  This is only used
3822
  // by AddNotDefinedError() to report a more useful error message.
3823
  // possible_undeclared_dependency_name_ is the name of the symbol that was
3824
  // actually found in possible_undeclared_dependency_, which may be a parent
3825
  // of the symbol actually looked for.
3826
  const FileDescriptor* possible_undeclared_dependency_;
3827
  std::string possible_undeclared_dependency_name_;
3828
3829
  // If LookupSymbol() could resolve a symbol which is not defined,
3830
  // record the resolved name.  This is only used by AddNotDefinedError()
3831
  // to report a more useful error message.
3832
  std::string undefine_resolved_name_;
3833
3834
  // Tracker for current recursion depth to implement recursion protection.
3835
  //
3836
  // Counts down to 0 when there is no depth remaining.
3837
  //
3838
  // Maximum recursion depth corresponds to 32 nested message declarations.
3839
  int recursion_depth_ = 32;
3840
3841
  // Note: Both AddError and AddWarning functions are extremely sensitive to
3842
  // the *caller* stack space used. We call these functions many times in
3843
  // complex code paths that are hot and likely to be inlined heavily. However,
3844
  // these calls themselves are cold error paths. But stack space used by the
3845
  // code that sets up the call in many cases is paid for even when the call
3846
  // isn't reached. To optimize this, we use `const std::string &` to reuse
3847
  // string objects where possible for the inputs and for the error message
3848
  // itself we use a closure to build the error message inside these routines.
3849
  // The routines themselves are marked to prevent inlining and this lets us
3850
  // move the large code sometimes required to produce a useful error message
3851
  // entirely into a helper closure rather than the immediate caller.
3852
  //
3853
  // The `const char*` overload should only be used for string literal messages
3854
  // where this is a frustrating amount of overhead and there is no harm in
3855
  // directly using the literal.
3856
  void AddError(const std::string& element_name, const Message& descriptor,
3857
                DescriptorPool::ErrorCollector::ErrorLocation location,
3858
                absl::FunctionRef<std::string()> make_error);
3859
  void AddError(const std::string& element_name, const Message& descriptor,
3860
                DescriptorPool::ErrorCollector::ErrorLocation location,
3861
                const char* error);
3862
  void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here);
3863
  void AddTwiceListedError(const FileDescriptorProto& proto, int index);
3864
  void AddImportError(const FileDescriptorProto& proto, int index);
3865
3866
  // Adds an error indicating that undefined_symbol was not defined.  Must
3867
  // only be called after LookupSymbol() fails.
3868
  void AddNotDefinedError(
3869
      const std::string& element_name, const Message& descriptor,
3870
      DescriptorPool::ErrorCollector::ErrorLocation location,
3871
      const std::string& undefined_symbol);
3872
3873
  void AddWarning(const std::string& element_name, const Message& descriptor,
3874
                  DescriptorPool::ErrorCollector::ErrorLocation location,
3875
                  absl::FunctionRef<std::string()> make_error);
3876
  void AddWarning(const std::string& element_name, const Message& descriptor,
3877
                  DescriptorPool::ErrorCollector::ErrorLocation location,
3878
                  const char* error);
3879
3880
  // Silly helper which determines if the given file is in the given package.
3881
  // I.e., either file->package() == package_name or file->package() is a
3882
  // nested package within package_name.
3883
  bool IsInPackage(const FileDescriptor* file, absl::string_view package_name);
3884
3885
  // Helper function which finds all public dependencies of the given file, and
3886
  // stores the them in the dependencies_ set in the builder.
3887
  void RecordPublicDependencies(const FileDescriptor* file);
3888
3889
  // Like tables_->FindSymbol(), but additionally:
3890
  // - Search the pool's underlay if not found in tables_.
3891
  // - Insure that the resulting Symbol is from one of the file's declared
3892
  //   dependencies.
3893
  Symbol FindSymbol(const std::string& name, bool build_it = true);
3894
3895
  // Like FindSymbol() but does not require that the symbol is in one of the
3896
  // file's declared dependencies.
3897
  Symbol FindSymbolNotEnforcingDeps(const std::string& name,
3898
                                    bool build_it = true);
3899
3900
  // This implements the body of FindSymbolNotEnforcingDeps().
3901
  Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool,
3902
                                          const std::string& name,
3903
                                          bool build_it = true);
3904
3905
  // Like FindSymbol(), but looks up the name relative to some other symbol
3906
  // name.  This first searches siblings of relative_to, then siblings of its
3907
  // parents, etc.  For example, LookupSymbol("foo.bar", "baz.moo.corge") makes
3908
  // the following calls, returning the first non-null result:
3909
  // FindSymbol("baz.moo.foo.bar"), FindSymbol("baz.foo.bar"),
3910
  // FindSymbol("foo.bar").  If AllowUnknownDependencies() has been called
3911
  // on the DescriptorPool, this will generate a placeholder type if
3912
  // the name is not found (unless the name itself is malformed).  The
3913
  // placeholder_type parameter indicates what kind of placeholder should be
3914
  // constructed in this case.  The resolve_mode parameter determines whether
3915
  // any symbol is returned, or only symbols that are types.  Note, however,
3916
  // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode,
3917
  // if it believes that's all it could refer to.  The caller should always
3918
  // check that it receives the type of symbol it was expecting.
3919
  enum ResolveMode { LOOKUP_ALL, LOOKUP_TYPES };
3920
  Symbol LookupSymbol(const std::string& name, const std::string& relative_to,
3921
                      DescriptorPool::PlaceholderType placeholder_type =
3922
                          DescriptorPool::PLACEHOLDER_MESSAGE,
3923
                      ResolveMode resolve_mode = LOOKUP_ALL,
3924
                      bool build_it = true);
3925
3926
  // Like LookupSymbol() but will not return a placeholder even if
3927
  // AllowUnknownDependencies() has been used.
3928
  Symbol LookupSymbolNoPlaceholder(const std::string& name,
3929
                                   const std::string& relative_to,
3930
                                   ResolveMode resolve_mode = LOOKUP_ALL,
3931
                                   bool build_it = true);
3932
3933
  // Calls tables_->AddSymbol() and records an error if it fails.  Returns
3934
  // true if successful or false if failed, though most callers can ignore
3935
  // the return value since an error has already been recorded.
3936
  bool AddSymbol(const std::string& full_name, const void* parent,
3937
                 const std::string& name, const Message& proto, Symbol symbol);
3938
3939
  // Like AddSymbol(), but succeeds if the symbol is already defined as long
3940
  // as the existing definition is also a package (because it's OK to define
3941
  // the same package in two different files).  Also adds all parents of the
3942
  // package to the symbol table (e.g. AddPackage("foo.bar", ...) will add
3943
  // "foo.bar" and "foo" to the table).
3944
  void AddPackage(const std::string& name, const Message& proto,
3945
                  FileDescriptor* file);
3946
3947
  // Checks that the symbol name contains only alphanumeric characters and
3948
  // underscores.  Records an error otherwise.
3949
  void ValidateSymbolName(const std::string& name, const std::string& full_name,
3950
                          const Message& proto);
3951
3952
  // Allocates a copy of orig_options in tables_ and stores it in the
3953
  // descriptor. Remembers its uninterpreted options, to be interpreted
3954
  // later. DescriptorT must be one of the Descriptor messages from
3955
  // descriptor.proto.
3956
  template <class DescriptorT>
3957
  void AllocateOptions(const typename DescriptorT::Proto& proto,
3958
                       DescriptorT* descriptor, int options_field_tag,
3959
                       absl::string_view option_name,
3960
                       internal::FlatAllocator& alloc);
3961
  // Specialization for FileOptions.
3962
  void AllocateOptions(const FileDescriptorProto& proto,
3963
                       FileDescriptor* descriptor,
3964
                       internal::FlatAllocator& alloc);
3965
3966
  // Implementation for AllocateOptions(). Don't call this directly.
3967
  template <class DescriptorT>
3968
  typename DescriptorT::OptionsType* AllocateOptionsImpl(
3969
      absl::string_view name_scope, absl::string_view element_name,
3970
      const typename DescriptorT::Proto& proto,
3971
      absl::Span<const int> options_path, absl::string_view option_name,
3972
      internal::FlatAllocator& alloc);
3973
3974
3975
  // Allocates an array of two strings, the first one is a copy of
3976
  // `proto_name`, and the second one is the full name. Full proto name is
3977
  // "scope.proto_name" if scope is non-empty and "proto_name" otherwise.
3978
  const std::string* AllocateNameStrings(const std::string& scope,
3979
                                         const std::string& proto_name,
3980
                                         internal::FlatAllocator& alloc);
3981
3982
  // These methods all have the same signature for the sake of the BUILD_ARRAY
3983
  // macro, below.
3984
  void BuildMessage(const DescriptorProto& proto, const Descriptor* parent,
3985
                    Descriptor* result, internal::FlatAllocator& alloc);
3986
  void BuildFieldOrExtension(const FieldDescriptorProto& proto,
3987
                             Descriptor* parent, FieldDescriptor* result,
3988
                             bool is_extension, internal::FlatAllocator& alloc);
3989
  void BuildField(const FieldDescriptorProto& proto, Descriptor* parent,
3990
0
                  FieldDescriptor* result, internal::FlatAllocator& alloc) {
3991
0
    BuildFieldOrExtension(proto, parent, result, false, alloc);
3992
0
  }
3993
  void BuildExtension(const FieldDescriptorProto& proto, Descriptor* parent,
3994
0
                      FieldDescriptor* result, internal::FlatAllocator& alloc) {
3995
0
    BuildFieldOrExtension(proto, parent, result, true, alloc);
3996
0
  }
3997
  void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
3998
                           const Descriptor* parent,
3999
                           Descriptor::ExtensionRange* result,
4000
                           internal::FlatAllocator& alloc);
4001
  void BuildReservedRange(const DescriptorProto::ReservedRange& proto,
4002
                          const Descriptor* parent,
4003
                          Descriptor::ReservedRange* result,
4004
                          internal::FlatAllocator& alloc);
4005
  void BuildReservedRange(const EnumDescriptorProto::EnumReservedRange& proto,
4006
                          const EnumDescriptor* parent,
4007
                          EnumDescriptor::ReservedRange* result,
4008
                          internal::FlatAllocator& alloc);
4009
  void BuildOneof(const OneofDescriptorProto& proto, Descriptor* parent,
4010
                  OneofDescriptor* result, internal::FlatAllocator& alloc);
4011
  void BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent,
4012
                 EnumDescriptor* result, internal::FlatAllocator& alloc);
4013
  void BuildEnumValue(const EnumValueDescriptorProto& proto,
4014
                      const EnumDescriptor* parent, EnumValueDescriptor* result,
4015
                      internal::FlatAllocator& alloc);
4016
  void BuildService(const ServiceDescriptorProto& proto, const void* dummy,
4017
                    ServiceDescriptor* result, internal::FlatAllocator& alloc);
4018
  void BuildMethod(const MethodDescriptorProto& proto,
4019
                   const ServiceDescriptor* parent, MethodDescriptor* result,
4020
                   internal::FlatAllocator& alloc);
4021
4022
  void CheckFieldJsonNameUniqueness(const DescriptorProto& proto,
4023
                                    const Descriptor* result);
4024
  void CheckFieldJsonNameUniqueness(const std::string& message_name,
4025
                                    const DescriptorProto& message,
4026
                                    FileDescriptorLegacy::Syntax syntax,
4027
                                    bool use_custom_names);
4028
  void CheckEnumValueUniqueness(const EnumDescriptorProto& proto,
4029
                                const EnumDescriptor* result);
4030
4031
  void LogUnusedDependency(const FileDescriptorProto& proto,
4032
                           const FileDescriptor* result);
4033
4034
  // Must be run only after building.
4035
  //
4036
  // NOTE: Options will not be available during cross-linking, as they
4037
  // have not yet been interpreted. Defer any handling of options to the
4038
  // Validate*Options methods.
4039
  void CrossLinkFile(FileDescriptor* file, const FileDescriptorProto& proto);
4040
  void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto);
4041
  void CrossLinkField(FieldDescriptor* field,
4042
                      const FieldDescriptorProto& proto);
4043
  void CrossLinkExtensionRange(Descriptor::ExtensionRange* range,
4044
                               const DescriptorProto::ExtensionRange& proto);
4045
  void CrossLinkEnum(EnumDescriptor* enum_type,
4046
                     const EnumDescriptorProto& proto);
4047
  void CrossLinkEnumValue(EnumValueDescriptor* enum_value,
4048
                          const EnumValueDescriptorProto& proto);
4049
  void CrossLinkService(ServiceDescriptor* service,
4050
                        const ServiceDescriptorProto& proto);
4051
  void CrossLinkMethod(MethodDescriptor* method,
4052
                       const MethodDescriptorProto& proto);
4053
  void SuggestFieldNumbers(FileDescriptor* file,
4054
                           const FileDescriptorProto& proto);
4055
4056
  // Checks that the extension field matches what is declared.
4057
  void CheckExtensionDeclaration(const FieldDescriptor& field,
4058
                                 const FieldDescriptorProto& proto,
4059
                                 absl::string_view declared_full_name,
4060
                                 absl::string_view declared_type_name,
4061
                                 bool is_repeated);
4062
4063
  // Must be run only after cross-linking.
4064
  void InterpretOptions();
4065
4066
  // A helper class for interpreting options.
4067
  class OptionInterpreter {
4068
   public:
4069
    // Creates an interpreter that operates in the context of the pool of the
4070
    // specified builder, which must not be nullptr. We don't take ownership of
4071
    // the builder.
4072
    explicit OptionInterpreter(DescriptorBuilder* builder);
4073
    OptionInterpreter(const OptionInterpreter&) = delete;
4074
    OptionInterpreter& operator=(const OptionInterpreter&) = delete;
4075
4076
    ~OptionInterpreter();
4077
4078
    // Interprets the uninterpreted options in the specified Options message.
4079
    // On error, calls AddError() on the underlying builder and returns false.
4080
    // Otherwise returns true.
4081
    bool InterpretOptions(OptionsToInterpret* options_to_interpret);
4082
4083
    // Updates the given source code info by re-writing uninterpreted option
4084
    // locations to refer to the corresponding interpreted option.
4085
    void UpdateSourceCodeInfo(SourceCodeInfo* info);
4086
4087
    class AggregateOptionFinder;
4088
4089
   private:
4090
    // Interprets uninterpreted_option_ on the specified message, which
4091
    // must be the mutable copy of the original options message to which
4092
    // uninterpreted_option_ belongs. The given src_path is the source
4093
    // location path to the uninterpreted option, and options_path is the
4094
    // source location path to the options message. The location paths are
4095
    // recorded and then used in UpdateSourceCodeInfo.
4096
    bool InterpretSingleOption(Message* options,
4097
                               const std::vector<int>& src_path,
4098
                               const std::vector<int>& options_path);
4099
4100
    // Adds the uninterpreted_option to the given options message verbatim.
4101
    // Used when AllowUnknownDependencies() is in effect and we can't find
4102
    // the option's definition.
4103
    void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option,
4104
                                Message* options);
4105
4106
    // A recursive helper function that drills into the intermediate fields
4107
    // in unknown_fields to check if field innermost_field is set on the
4108
    // innermost message. Returns false and sets an error if so.
4109
    bool ExamineIfOptionIsSet(
4110
        std::vector<const FieldDescriptor*>::const_iterator
4111
            intermediate_fields_iter,
4112
        std::vector<const FieldDescriptor*>::const_iterator
4113
            intermediate_fields_end,
4114
        const FieldDescriptor* innermost_field,
4115
        const std::string& debug_msg_name,
4116
        const UnknownFieldSet& unknown_fields);
4117
4118
    // Validates the value for the option field of the currently interpreted
4119
    // option and then sets it on the unknown_field.
4120
    bool SetOptionValue(const FieldDescriptor* option_field,
4121
                        UnknownFieldSet* unknown_fields);
4122
4123
    // Parses an aggregate value for a CPPTYPE_MESSAGE option and
4124
    // saves it into *unknown_fields.
4125
    bool SetAggregateOption(const FieldDescriptor* option_field,
4126
                            UnknownFieldSet* unknown_fields);
4127
4128
    // Convenience functions to set an int field the right way, depending on
4129
    // its wire type (a single int CppType can represent multiple wire types).
4130
    void SetInt32(int number, int32_t value, FieldDescriptor::Type type,
4131
                  UnknownFieldSet* unknown_fields);
4132
    void SetInt64(int number, int64_t value, FieldDescriptor::Type type,
4133
                  UnknownFieldSet* unknown_fields);
4134
    void SetUInt32(int number, uint32_t value, FieldDescriptor::Type type,
4135
                   UnknownFieldSet* unknown_fields);
4136
    void SetUInt64(int number, uint64_t value, FieldDescriptor::Type type,
4137
                   UnknownFieldSet* unknown_fields);
4138
4139
    // A helper function that adds an error at the specified location of the
4140
    // option we're currently interpreting, and returns false.
4141
    bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,
4142
0
                        absl::FunctionRef<std::string()> make_error) {
4143
0
      builder_->AddError(options_to_interpret_->element_name,
4144
0
                         *uninterpreted_option_, location, make_error);
4145
0
      return false;
4146
0
    }
4147
4148
    // A helper function that adds an error at the location of the option name
4149
    // and returns false.
4150
0
    bool AddNameError(absl::FunctionRef<std::string()> make_error) {
4151
#ifdef PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_
4152
      return true;
4153
#else   // PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_
4154
0
      return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME,
4155
0
                            make_error);
4156
0
#endif  // PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_
4157
0
    }
4158
4159
    // A helper function that adds an error at the location of the option name
4160
    // and returns false.
4161
0
    bool AddValueError(absl::FunctionRef<std::string()> make_error) {
4162
0
      return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE,
4163
0
                            make_error);
4164
0
    }
4165
4166
    // We interpret against this builder's pool. Is never nullptr. We don't own
4167
    // this pointer.
4168
    DescriptorBuilder* builder_;
4169
4170
    // The options we're currently interpreting, or nullptr if we're not in a
4171
    // call to InterpretOptions.
4172
    const OptionsToInterpret* options_to_interpret_;
4173
4174
    // The option we're currently interpreting within options_to_interpret_, or
4175
    // nullptr if we're not in a call to InterpretOptions(). This points to a
4176
    // submessage of the original option, not the mutable copy. Therefore we
4177
    // can use it to find locations recorded by the parser.
4178
    const UninterpretedOption* uninterpreted_option_;
4179
4180
    // This maps the element path of uninterpreted options to the element path
4181
    // of the resulting interpreted option. This is used to modify a file's
4182
    // source code info to account for option interpretation.
4183
    absl::flat_hash_map<std::vector<int>, std::vector<int>> interpreted_paths_;
4184
4185
    // This maps the path to a repeated option field to the known number of
4186
    // elements the field contains. This is used to track the compute the
4187
    // index portion of the element path when interpreting a single option.
4188
    absl::flat_hash_map<std::vector<int>, int> repeated_option_counts_;
4189
4190
    // Factory used to create the dynamic messages we need to parse
4191
    // any aggregate option values we encounter.
4192
    DynamicMessageFactory dynamic_factory_;
4193
  };
4194
4195
  // Work-around for broken compilers:  According to the C++ standard,
4196
  // OptionInterpreter should have access to the private members of any class
4197
  // which has declared DescriptorBuilder as a friend.  Unfortunately some old
4198
  // versions of GCC and other compilers do not implement this correctly.  So,
4199
  // we have to have these intermediate methods to provide access.  We also
4200
  // redundantly declare OptionInterpreter a friend just to make things extra
4201
  // clear for these bad compilers.
4202
  friend class OptionInterpreter;
4203
  friend class OptionInterpreter::AggregateOptionFinder;
4204
4205
0
  static inline bool get_allow_unknown(const DescriptorPool* pool) {
4206
0
    return pool->allow_unknown_;
4207
0
  }
4208
0
  static inline bool get_enforce_weak(const DescriptorPool* pool) {
4209
0
    return pool->enforce_weak_;
4210
0
  }
4211
0
  static inline bool get_is_placeholder(const Descriptor* descriptor) {
4212
0
    return descriptor != nullptr && descriptor->is_placeholder_;
4213
0
  }
4214
0
  static inline void assert_mutex_held(const DescriptorPool* pool) {
4215
0
    if (pool->mutex_ != nullptr) {
4216
0
      pool->mutex_->AssertHeld();
4217
0
    }
4218
0
  }
4219
4220
  // Must be run only after options have been interpreted.
4221
  //
4222
  // NOTE: Validation code must only reference the options in the mutable
4223
  // descriptors, which are the ones that have been interpreted. The const
4224
  // proto references are passed in only so they can be provided to calls to
4225
  // AddError(). Do not look at their options, which have not been interpreted.
4226
  void ValidateOptions(const FileDescriptor* file,
4227
                       const FileDescriptorProto& proto);
4228
  void ValidateOptions(const Descriptor* message, const DescriptorProto& proto);
4229
  void ValidateOptions(const OneofDescriptor* oneof,
4230
                       const OneofDescriptorProto& proto);
4231
  void ValidateOptions(const FieldDescriptor* field,
4232
                       const FieldDescriptorProto& proto);
4233
  void ValidateFieldFeatures(const FieldDescriptor* field,
4234
                             const FieldDescriptorProto& proto);
4235
  void ValidateOptions(const EnumDescriptor* enm,
4236
                       const EnumDescriptorProto& proto);
4237
  void ValidateOptions(const EnumValueDescriptor* enum_value,
4238
                       const EnumValueDescriptorProto& proto);
4239
  void ValidateOptions(const Descriptor::ExtensionRange* range,
4240
0
                       const DescriptorProto::ExtensionRange& proto) {}
4241
  void ValidateExtensionRangeOptions(const DescriptorProto& proto,
4242
                                     const Descriptor& message);
4243
  void ValidateExtensionDeclaration(
4244
      const std::string& full_name,
4245
      const RepeatedPtrField<ExtensionRangeOptions_Declaration>& declarations,
4246
      const DescriptorProto_ExtensionRange& proto,
4247
      absl::flat_hash_set<absl::string_view>& full_name_set);
4248
  void ValidateOptions(const ServiceDescriptor* service,
4249
                       const ServiceDescriptorProto& proto);
4250
  void ValidateOptions(const MethodDescriptor* method,
4251
                       const MethodDescriptorProto& proto);
4252
  void ValidateProto3(const FileDescriptor* file,
4253
                      const FileDescriptorProto& proto);
4254
  void ValidateProto3Message(const Descriptor* message,
4255
                             const DescriptorProto& proto);
4256
  void ValidateProto3Field(const FieldDescriptor* field,
4257
                           const FieldDescriptorProto& proto);
4258
  void ValidateProto3Enum(const EnumDescriptor* enm,
4259
                          const EnumDescriptorProto& proto);
4260
4261
  // Returns true if the map entry message is compatible with the
4262
  // auto-generated entry message from map fields syntax.
4263
  bool ValidateMapEntry(const FieldDescriptor* field,
4264
                        const FieldDescriptorProto& proto);
4265
4266
  // Recursively detects naming conflicts with map entry types for a
4267
  // better error message.
4268
  void DetectMapConflicts(const Descriptor* message,
4269
                          const DescriptorProto& proto);
4270
4271
  void ValidateJSType(const FieldDescriptor* field,
4272
                      const FieldDescriptorProto& proto);
4273
};
4274
4275
const FileDescriptor* DescriptorPool::BuildFile(
4276
0
    const FileDescriptorProto& proto) {
4277
0
  ABSL_CHECK(fallback_database_ == nullptr)
4278
0
      << "Cannot call BuildFile on a DescriptorPool that uses a "
4279
0
         "DescriptorDatabase.  You must instead find a way to get your file "
4280
0
         "into the underlying database.";
4281
0
  ABSL_CHECK(mutex_ == nullptr);  // Implied by the above ABSL_CHECK.
4282
0
  tables_->known_bad_symbols_.clear();
4283
0
  tables_->known_bad_files_.clear();
4284
0
  return DescriptorBuilder::New(this, tables_.get(), nullptr)->BuildFile(proto);
4285
0
}
4286
4287
const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
4288
0
    const FileDescriptorProto& proto, ErrorCollector* error_collector) {
4289
0
  ABSL_CHECK(fallback_database_ == nullptr)
4290
0
      << "Cannot call BuildFile on a DescriptorPool that uses a "
4291
0
         "DescriptorDatabase.  You must instead find a way to get your file "
4292
0
         "into the underlying database.";
4293
0
  ABSL_CHECK(mutex_ == nullptr);  // Implied by the above ABSL_CHECK.
4294
0
  tables_->known_bad_symbols_.clear();
4295
0
  tables_->known_bad_files_.clear();
4296
0
  return DescriptorBuilder::New(this, tables_.get(), error_collector)
4297
0
      ->BuildFile(proto);
4298
0
}
4299
4300
const FileDescriptor* DescriptorPool::BuildFileFromDatabase(
4301
0
    const FileDescriptorProto& proto) const {
4302
0
  mutex_->AssertHeld();
4303
0
  if (tables_->known_bad_files_.contains(proto.name())) {
4304
0
    return nullptr;
4305
0
  }
4306
0
  const FileDescriptor* result =
4307
0
      DescriptorBuilder::New(this, tables_.get(), default_error_collector_)
4308
0
          ->BuildFile(proto);
4309
0
  if (result == nullptr) {
4310
0
    tables_->known_bad_files_.insert(proto.name());
4311
0
  }
4312
0
  return result;
4313
0
}
4314
4315
DescriptorBuilder::DescriptorBuilder(
4316
    const DescriptorPool* pool, DescriptorPool::Tables* tables,
4317
    DescriptorPool::ErrorCollector* error_collector)
4318
    : pool_(pool),
4319
      tables_(tables),
4320
      error_collector_(error_collector),
4321
      had_errors_(false),
4322
      possible_undeclared_dependency_(nullptr),
4323
0
      undefine_resolved_name_("") {}
4324
4325
0
DescriptorBuilder::~DescriptorBuilder() {}
4326
4327
PROTOBUF_NOINLINE void DescriptorBuilder::AddError(
4328
    const std::string& element_name, const Message& descriptor,
4329
    DescriptorPool::ErrorCollector::ErrorLocation location,
4330
0
    absl::FunctionRef<std::string()> make_error) {
4331
0
  std::string error = make_error();
4332
0
  if (error_collector_ == nullptr) {
4333
0
    if (!had_errors_) {
4334
0
      ABSL_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_
4335
0
                      << "\":";
4336
0
    }
4337
0
    ABSL_LOG(ERROR) << "  " << element_name << ": " << error;
4338
0
  } else {
4339
0
    error_collector_->RecordError(filename_, element_name, &descriptor,
4340
0
                                  location, error);
4341
0
  }
4342
0
  had_errors_ = true;
4343
0
}
4344
4345
PROTOBUF_NOINLINE void DescriptorBuilder::AddError(
4346
    const std::string& element_name, const Message& descriptor,
4347
0
    DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) {
4348
0
  AddError(element_name, descriptor, location, [error] { return error; });
4349
0
}
4350
4351
PROTOBUF_NOINLINE void DescriptorBuilder::AddNotDefinedError(
4352
    const std::string& element_name, const Message& descriptor,
4353
    DescriptorPool::ErrorCollector::ErrorLocation location,
4354
0
    const std::string& undefined_symbol) {
4355
0
  if (possible_undeclared_dependency_ == nullptr &&
4356
0
      undefine_resolved_name_.empty()) {
4357
0
    AddError(element_name, descriptor, location, [&] {
4358
0
      return absl::StrCat("\"", undefined_symbol, "\" is not defined.");
4359
0
    });
4360
0
  } else {
4361
0
    if (possible_undeclared_dependency_ != nullptr) {
4362
0
      AddError(element_name, descriptor, location, [&] {
4363
0
        return absl::StrCat("\"", possible_undeclared_dependency_name_,
4364
0
                            "\" seems to be defined in \"",
4365
0
                            possible_undeclared_dependency_->name(),
4366
0
                            "\", which is not "
4367
0
                            "imported by \"",
4368
0
                            filename_,
4369
0
                            "\".  To use it here, please "
4370
0
                            "add the necessary import.");
4371
0
      });
4372
0
    }
4373
0
    if (!undefine_resolved_name_.empty()) {
4374
0
      AddError(element_name, descriptor, location, [&] {
4375
0
        return absl::StrCat(
4376
0
            "\"", undefined_symbol, "\" is resolved to \"",
4377
0
            undefine_resolved_name_,
4378
0
            "\", which is not defined. "
4379
0
            "The innermost scope is searched first in name resolution. "
4380
0
            "Consider using a leading '.'(i.e., \".",
4381
0
            undefined_symbol, "\") to start from the outermost scope.");
4382
0
      });
4383
0
    }
4384
0
  }
4385
0
}
4386
4387
PROTOBUF_NOINLINE void DescriptorBuilder::AddWarning(
4388
    const std::string& element_name, const Message& descriptor,
4389
    DescriptorPool::ErrorCollector::ErrorLocation location,
4390
0
    absl::FunctionRef<std::string()> make_error) {
4391
0
  std::string error = make_error();
4392
0
  if (error_collector_ == nullptr) {
4393
0
    ABSL_LOG(WARNING) << filename_ << " " << element_name << ": " << error;
4394
0
  } else {
4395
0
    error_collector_->RecordWarning(filename_, element_name, &descriptor,
4396
0
                                    location, error);
4397
0
  }
4398
0
}
4399
4400
PROTOBUF_NOINLINE void DescriptorBuilder::AddWarning(
4401
    const std::string& element_name, const Message& descriptor,
4402
0
    DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) {
4403
0
  AddWarning(element_name, descriptor, location,
4404
0
             [error]() -> std::string { return error; });
4405
0
}
4406
4407
bool DescriptorBuilder::IsInPackage(const FileDescriptor* file,
4408
0
                                    absl::string_view package_name) {
4409
0
  return absl::StartsWith(file->package(), package_name) &&
4410
0
         (file->package().size() == package_name.size() ||
4411
0
          file->package()[package_name.size()] == '.');
4412
0
}
4413
4414
0
void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
4415
0
  if (file == nullptr || !dependencies_.insert(file).second) return;
4416
0
  for (int i = 0; file != nullptr && i < file->public_dependency_count(); i++) {
4417
0
    RecordPublicDependencies(file->public_dependency(i));
4418
0
  }
4419
0
}
4420
4421
Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
4422
0
    const DescriptorPool* pool, const std::string& name, bool build_it) {
4423
  // If we are looking at an underlay, we must lock its mutex_, since we are
4424
  // accessing the underlay's tables_ directly.
4425
0
  absl::MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_);
4426
4427
0
  Symbol result = pool->tables_->FindSymbol(name);
4428
0
  if (result.IsNull() && pool->underlay_ != nullptr) {
4429
    // Symbol not found; check the underlay.
4430
0
    result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
4431
0
  }
4432
4433
0
  if (result.IsNull()) {
4434
    // With lazily_build_dependencies_, a symbol lookup at cross link time is
4435
    // not guaranteed to be successful. In most cases, build_it will be false,
4436
    // which intentionally prevents us from building an import until it's
4437
    // actually needed. In some cases, like registering an extension, we want
4438
    // to build the file containing the symbol, and build_it will be set.
4439
    // Also, build_it will be true when !lazily_build_dependencies_, to provide
4440
    // better error reporting of missing dependencies.
4441
0
    if (build_it && pool->TryFindSymbolInFallbackDatabase(name)) {
4442
0
      result = pool->tables_->FindSymbol(name);
4443
0
    }
4444
0
  }
4445
4446
0
  return result;
4447
0
}
4448
4449
Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const std::string& name,
4450
0
                                                     bool build_it) {
4451
0
  Symbol result = FindSymbolNotEnforcingDepsHelper(pool_, name, build_it);
4452
  // Only find symbols which were defined in this file or one of its
4453
  // dependencies.
4454
0
  const FileDescriptor* file = result.GetFile();
4455
0
  if ((file == file_ || dependencies_.contains(file)) && !result.IsPackage()) {
4456
0
    unused_dependency_.erase(file);
4457
0
  }
4458
0
  return result;
4459
0
}
4460
4461
0
Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) {
4462
0
  Symbol result = FindSymbolNotEnforcingDeps(name, build_it);
4463
4464
0
  if (result.IsNull()) return result;
4465
4466
0
  if (!pool_->enforce_dependencies_) {
4467
    // Hack for CompilerUpgrader, and also used for lazily_build_dependencies_
4468
0
    return result;
4469
0
  }
4470
4471
  // Only find symbols which were defined in this file or one of its
4472
  // dependencies.
4473
0
  const FileDescriptor* file = result.GetFile();
4474
0
  if (file == file_ || dependencies_.contains(file)) {
4475
0
    return result;
4476
0
  }
4477
4478
0
  if (result.IsPackage()) {
4479
    // Arg, this is overcomplicated.  The symbol is a package name.  It could
4480
    // be that the package was defined in multiple files.  result.GetFile()
4481
    // returns the first file we saw that used this package.  We've determined
4482
    // that that file is not a direct dependency of the file we are currently
4483
    // building, but it could be that some other file which *is* a direct
4484
    // dependency also defines the same package.  We can't really rule out this
4485
    // symbol unless none of the dependencies define it.
4486
0
    if (IsInPackage(file_, name)) return result;
4487
0
    for (const auto* dep : dependencies_) {
4488
      // Note:  A dependency may be nullptr if it was not found or had errors.
4489
0
      if (dep != nullptr && IsInPackage(dep, name)) return result;
4490
0
    }
4491
0
  }
4492
4493
0
  possible_undeclared_dependency_ = file;
4494
0
  possible_undeclared_dependency_name_ = name;
4495
0
  return Symbol();
4496
0
}
4497
4498
Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(
4499
    const std::string& name, const std::string& relative_to,
4500
0
    ResolveMode resolve_mode, bool build_it) {
4501
0
  possible_undeclared_dependency_ = nullptr;
4502
0
  undefine_resolved_name_.clear();
4503
4504
0
  if (!name.empty() && name[0] == '.') {
4505
    // Fully-qualified name.
4506
0
    return FindSymbol(name.substr(1), build_it);
4507
0
  }
4508
4509
  // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
4510
  // defined in multiple parent scopes, we only want to find "Bar.baz" in the
4511
  // innermost one.  E.g., the following should produce an error:
4512
  //   message Bar { message Baz {} }
4513
  //   message Foo {
4514
  //     message Bar {
4515
  //     }
4516
  //     optional Bar.Baz baz = 1;
4517
  //   }
4518
  // So, we look for just "Foo" first, then look for "Bar.baz" within it if
4519
  // found.
4520
0
  std::string::size_type name_dot_pos = name.find_first_of('.');
4521
0
  std::string first_part_of_name;
4522
0
  if (name_dot_pos == std::string::npos) {
4523
0
    first_part_of_name = name;
4524
0
  } else {
4525
0
    first_part_of_name = name.substr(0, name_dot_pos);
4526
0
  }
4527
4528
0
  std::string scope_to_try(relative_to);
4529
4530
0
  while (true) {
4531
    // Chop off the last component of the scope.
4532
0
    std::string::size_type dot_pos = scope_to_try.find_last_of('.');
4533
0
    if (dot_pos == std::string::npos) {
4534
0
      return FindSymbol(name, build_it);
4535
0
    } else {
4536
0
      scope_to_try.erase(dot_pos);
4537
0
    }
4538
4539
    // Append ".first_part_of_name" and try to find.
4540
0
    std::string::size_type old_size = scope_to_try.size();
4541
0
    scope_to_try.append(1, '.');
4542
0
    scope_to_try.append(first_part_of_name);
4543
0
    Symbol result = FindSymbol(scope_to_try, build_it);
4544
0
    if (!result.IsNull()) {
4545
0
      if (first_part_of_name.size() < name.size()) {
4546
        // name is a compound symbol, of which we only found the first part.
4547
        // Now try to look up the rest of it.
4548
0
        if (result.IsAggregate()) {
4549
0
          scope_to_try.append(name, first_part_of_name.size(),
4550
0
                              name.size() - first_part_of_name.size());
4551
0
          result = FindSymbol(scope_to_try, build_it);
4552
0
          if (result.IsNull()) {
4553
0
            undefine_resolved_name_ = scope_to_try;
4554
0
          }
4555
0
          return result;
4556
0
        } else {
4557
          // We found a symbol but it's not an aggregate.  Continue the loop.
4558
0
        }
4559
0
      } else {
4560
0
        if (resolve_mode == LOOKUP_TYPES && !result.IsType()) {
4561
          // We found a symbol but it's not a type.  Continue the loop.
4562
0
        } else {
4563
0
          return result;
4564
0
        }
4565
0
      }
4566
0
    }
4567
4568
    // Not found.  Remove the name so we can try again.
4569
0
    scope_to_try.erase(old_size);
4570
0
  }
4571
0
}
4572
4573
Symbol DescriptorBuilder::LookupSymbol(
4574
    const std::string& name, const std::string& relative_to,
4575
    DescriptorPool::PlaceholderType placeholder_type, ResolveMode resolve_mode,
4576
0
    bool build_it) {
4577
0
  Symbol result =
4578
0
      LookupSymbolNoPlaceholder(name, relative_to, resolve_mode, build_it);
4579
0
  if (result.IsNull() && pool_->allow_unknown_) {
4580
    // Not found, but AllowUnknownDependencies() is enabled.  Return a
4581
    // placeholder instead.
4582
0
    result = pool_->NewPlaceholderWithMutexHeld(name, placeholder_type);
4583
0
  }
4584
0
  return result;
4585
0
}
4586
4587
0
static bool ValidateQualifiedName(absl::string_view name) {
4588
0
  bool last_was_period = false;
4589
4590
0
  for (char character : name) {
4591
    // I don't trust isalnum() due to locales.  :(
4592
0
    if (('a' <= character && character <= 'z') ||
4593
0
        ('A' <= character && character <= 'Z') ||
4594
0
        ('0' <= character && character <= '9') || (character == '_')) {
4595
0
      last_was_period = false;
4596
0
    } else if (character == '.') {
4597
0
      if (last_was_period) return false;
4598
0
      last_was_period = true;
4599
0
    } else {
4600
0
      return false;
4601
0
    }
4602
0
  }
4603
4604
0
  return !name.empty() && !last_was_period;
4605
0
}
4606
4607
Symbol DescriptorPool::NewPlaceholder(absl::string_view name,
4608
0
                                      PlaceholderType placeholder_type) const {
4609
0
  absl::MutexLockMaybe lock(mutex_);
4610
0
  return NewPlaceholderWithMutexHeld(name, placeholder_type);
4611
0
}
4612
4613
Symbol DescriptorPool::NewPlaceholderWithMutexHeld(
4614
0
    absl::string_view name, PlaceholderType placeholder_type) const {
4615
0
  if (mutex_) {
4616
0
    mutex_->AssertHeld();
4617
0
  }
4618
  // Compute names.
4619
0
  absl::string_view placeholder_full_name;
4620
0
  absl::string_view placeholder_name;
4621
0
  const std::string* placeholder_package;
4622
4623
0
  if (!ValidateQualifiedName(name)) return Symbol();
4624
0
  if (name[0] == '.') {
4625
    // Fully-qualified.
4626
0
    placeholder_full_name = name.substr(1);
4627
0
  } else {
4628
0
    placeholder_full_name = name;
4629
0
  }
4630
4631
  // Create the placeholders.
4632
0
  internal::FlatAllocator alloc;
4633
0
  alloc.PlanArray<FileDescriptor>(1);
4634
0
  alloc.PlanArray<std::string>(2);
4635
0
  if (placeholder_type == PLACEHOLDER_ENUM) {
4636
0
    alloc.PlanArray<EnumDescriptor>(1);
4637
0
    alloc.PlanArray<EnumValueDescriptor>(1);
4638
0
    alloc.PlanArray<std::string>(2);  // names for the descriptor.
4639
0
    alloc.PlanArray<std::string>(2);  // names for the value.
4640
0
  } else {
4641
0
    alloc.PlanArray<Descriptor>(1);
4642
0
    alloc.PlanArray<std::string>(2);  // names for the descriptor.
4643
0
    if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
4644
0
      alloc.PlanArray<Descriptor::ExtensionRange>(1);
4645
0
    }
4646
0
  }
4647
0
  alloc.FinalizePlanning(tables_);
4648
4649
0
  const std::string::size_type dotpos = placeholder_full_name.find_last_of('.');
4650
0
  if (dotpos != std::string::npos) {
4651
0
    placeholder_package =
4652
0
        alloc.AllocateStrings(placeholder_full_name.substr(0, dotpos));
4653
0
    placeholder_name = placeholder_full_name.substr(dotpos + 1);
4654
0
  } else {
4655
0
    placeholder_package = alloc.AllocateStrings("");
4656
0
    placeholder_name = placeholder_full_name;
4657
0
  }
4658
4659
0
  FileDescriptor* placeholder_file = NewPlaceholderFileWithMutexHeld(
4660
0
      absl::StrCat(placeholder_full_name, ".placeholder.proto"), alloc);
4661
0
  placeholder_file->package_ = placeholder_package;
4662
4663
0
  if (placeholder_type == PLACEHOLDER_ENUM) {
4664
0
    placeholder_file->enum_type_count_ = 1;
4665
0
    placeholder_file->enum_types_ = alloc.AllocateArray<EnumDescriptor>(1);
4666
4667
0
    EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0];
4668
0
    memset(static_cast<void*>(placeholder_enum), 0, sizeof(*placeholder_enum));
4669
4670
0
    placeholder_enum->all_names_ =
4671
0
        alloc.AllocateStrings(placeholder_name, placeholder_full_name);
4672
0
    placeholder_enum->file_ = placeholder_file;
4673
0
    placeholder_enum->options_ = &EnumOptions::default_instance();
4674
0
    placeholder_enum->is_placeholder_ = true;
4675
0
    placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.');
4676
4677
    // Enums must have at least one value.
4678
0
    placeholder_enum->value_count_ = 1;
4679
0
    placeholder_enum->values_ = alloc.AllocateArray<EnumValueDescriptor>(1);
4680
    // Disable fast-path lookup for this enum.
4681
0
    placeholder_enum->sequential_value_limit_ = -1;
4682
4683
0
    EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0];
4684
0
    memset(static_cast<void*>(placeholder_value), 0,
4685
0
           sizeof(*placeholder_value));
4686
4687
    // Note that enum value names are siblings of their type, not children.
4688
0
    placeholder_value->all_names_ = alloc.AllocateStrings(
4689
0
        "PLACEHOLDER_VALUE",
4690
0
        placeholder_package->empty()
4691
0
            ? "PLACEHOLDER_VALUE"
4692
0
            : absl::StrCat(*placeholder_package, ".PLACEHOLDER_VALUE"));
4693
4694
0
    placeholder_value->number_ = 0;
4695
0
    placeholder_value->type_ = placeholder_enum;
4696
0
    placeholder_value->options_ = &EnumValueOptions::default_instance();
4697
4698
0
    return Symbol(placeholder_enum);
4699
0
  } else {
4700
0
    placeholder_file->message_type_count_ = 1;
4701
0
    placeholder_file->message_types_ = alloc.AllocateArray<Descriptor>(1);
4702
4703
0
    Descriptor* placeholder_message = &placeholder_file->message_types_[0];
4704
0
    memset(static_cast<void*>(placeholder_message), 0,
4705
0
           sizeof(*placeholder_message));
4706
4707
0
    placeholder_message->all_names_ =
4708
0
        alloc.AllocateStrings(placeholder_name, placeholder_full_name);
4709
0
    placeholder_message->file_ = placeholder_file;
4710
0
    placeholder_message->options_ = &MessageOptions::default_instance();
4711
0
    placeholder_message->is_placeholder_ = true;
4712
0
    placeholder_message->is_unqualified_placeholder_ = (name[0] != '.');
4713
4714
0
    if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
4715
0
      placeholder_message->extension_range_count_ = 1;
4716
0
      placeholder_message->extension_ranges_ =
4717
0
          alloc.AllocateArray<Descriptor::ExtensionRange>(1);
4718
0
      placeholder_message->extension_ranges_[0].start_ = 1;
4719
      // kMaxNumber + 1 because ExtensionRange::end is exclusive.
4720
0
      placeholder_message->extension_ranges_[0].end_ =
4721
0
          FieldDescriptor::kMaxNumber + 1;
4722
0
      placeholder_message->extension_ranges_[0].options_ = nullptr;
4723
0
    }
4724
4725
0
    return Symbol(placeholder_message);
4726
0
  }
4727
0
}
4728
4729
FileDescriptor* DescriptorPool::NewPlaceholderFile(
4730
0
    absl::string_view name) const {
4731
0
  absl::MutexLockMaybe lock(mutex_);
4732
0
  internal::FlatAllocator alloc;
4733
0
  alloc.PlanArray<FileDescriptor>(1);
4734
0
  alloc.PlanArray<std::string>(1);
4735
0
  alloc.FinalizePlanning(tables_);
4736
4737
0
  return NewPlaceholderFileWithMutexHeld(name, alloc);
4738
0
}
4739
4740
FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld(
4741
0
    absl::string_view name, internal::FlatAllocator& alloc) const {
4742
0
  if (mutex_) {
4743
0
    mutex_->AssertHeld();
4744
0
  }
4745
0
  FileDescriptor* placeholder = alloc.AllocateArray<FileDescriptor>(1);
4746
0
  memset(static_cast<void*>(placeholder), 0, sizeof(*placeholder));
4747
4748
0
  placeholder->name_ = alloc.AllocateStrings(name);
4749
0
  placeholder->package_ = &internal::GetEmptyString();
4750
0
  placeholder->pool_ = this;
4751
0
  placeholder->options_ = &FileOptions::default_instance();
4752
0
  placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance();
4753
0
  placeholder->source_code_info_ = &SourceCodeInfo::default_instance();
4754
0
  placeholder->is_placeholder_ = true;
4755
0
  placeholder->syntax_ = FileDescriptorLegacy::SYNTAX_UNKNOWN;
4756
0
  placeholder->finished_building_ = true;
4757
  // All other fields are zero or nullptr.
4758
4759
0
  return placeholder;
4760
0
}
4761
4762
bool DescriptorBuilder::AddSymbol(const std::string& full_name,
4763
                                  const void* parent, const std::string& name,
4764
0
                                  const Message& proto, Symbol symbol) {
4765
  // If the caller passed nullptr for the parent, the symbol is at file scope.
4766
  // Use its file as the parent instead.
4767
0
  if (parent == nullptr) parent = file_;
4768
4769
0
  if (absl::StrContains(full_name, '\0')) {
4770
0
    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4771
0
      return absl::StrCat("\"", full_name, "\" contains null character.");
4772
0
    });
4773
0
    return false;
4774
0
  }
4775
0
  if (tables_->AddSymbol(full_name, symbol)) {
4776
0
    if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
4777
      // This is only possible if there was already an error adding something of
4778
      // the same name.
4779
0
      if (!had_errors_) {
4780
0
        ABSL_DLOG(FATAL) << "\"" << full_name
4781
0
                         << "\" not previously defined in "
4782
0
                            "symbols_by_name_, but was defined in "
4783
0
                            "symbols_by_parent_; this shouldn't be possible.";
4784
0
      }
4785
0
      return false;
4786
0
    }
4787
0
    return true;
4788
0
  } else {
4789
0
    const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile();
4790
0
    if (other_file == file_) {
4791
0
      std::string::size_type dot_pos = full_name.find_last_of('.');
4792
0
      if (dot_pos == std::string::npos) {
4793
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4794
0
          return absl::StrCat("\"", full_name, "\" is already defined.");
4795
0
        });
4796
0
      } else {
4797
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4798
0
          return absl::StrCat("\"", full_name.substr(dot_pos + 1),
4799
0
                              "\" is already defined in \"",
4800
0
                              full_name.substr(0, dot_pos), "\".");
4801
0
        });
4802
0
      }
4803
0
    } else {
4804
      // Symbol seems to have been defined in a different file.
4805
0
      AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4806
0
        return absl::StrCat(
4807
0
            "\"", full_name, "\" is already defined in file \"",
4808
0
            (other_file == nullptr ? "null" : other_file->name()), "\".");
4809
0
      });
4810
0
    }
4811
0
    return false;
4812
0
  }
4813
0
}
4814
4815
void DescriptorBuilder::AddPackage(const std::string& name,
4816
0
                                   const Message& proto, FileDescriptor* file) {
4817
0
  if (name.find('\0') != std::string::npos) {
4818
0
    AddError(name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4819
0
      return absl::StrCat("\"", name, "\" contains null character.");
4820
0
    });
4821
0
    return;
4822
0
  }
4823
4824
0
  Symbol existing_symbol = tables_->FindSymbol(name);
4825
  // It's OK to redefine a package.
4826
0
  if (existing_symbol.IsNull()) {
4827
0
    if (name.data() == file->package().data()) {
4828
      // It is the toplevel package name, so insert the descriptor directly.
4829
0
      tables_->AddSymbol(file->package(), Symbol(file));
4830
0
    } else {
4831
0
      auto* package = tables_->Allocate<Symbol::Subpackage>();
4832
      // If the name is the package name, then it is already in the arena.
4833
      // If not, copy it there. It came from the call to AddPackage below.
4834
0
      package->name_size = static_cast<int>(name.size());
4835
0
      package->file = file;
4836
0
      tables_->AddSymbol(name, Symbol(package));
4837
0
    }
4838
    // Also add parent package, if any.
4839
0
    std::string::size_type dot_pos = name.find_last_of('.');
4840
0
    if (dot_pos == std::string::npos) {
4841
      // No parents.
4842
0
      ValidateSymbolName(name, name, proto);
4843
0
    } else {
4844
      // Has parent.
4845
0
      AddPackage(name.substr(0, dot_pos), proto, file);
4846
0
      ValidateSymbolName(name.substr(dot_pos + 1), name, proto);
4847
0
    }
4848
0
  } else if (!existing_symbol.IsPackage()) {
4849
    // Symbol seems to have been defined in a different file.
4850
0
    const FileDescriptor* other_file = existing_symbol.GetFile();
4851
0
    AddError(name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4852
0
      return absl::StrCat("\"", name,
4853
0
                          "\" is already defined (as something other than "
4854
0
                          "a package) in file \"",
4855
0
                          (other_file == nullptr ? "null" : other_file->name()),
4856
0
                          "\".");
4857
0
    });
4858
0
  }
4859
0
}
4860
4861
void DescriptorBuilder::ValidateSymbolName(const std::string& name,
4862
                                           const std::string& full_name,
4863
0
                                           const Message& proto) {
4864
0
  if (name.empty()) {
4865
0
    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4866
0
             "Missing name.");
4867
0
  } else {
4868
0
    for (char character : name) {
4869
      // I don't trust isalnum() due to locales.  :(
4870
0
      if ((character < 'a' || 'z' < character) &&
4871
0
          (character < 'A' || 'Z' < character) &&
4872
0
          (character < '0' || '9' < character) && (character != '_')) {
4873
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4874
0
          return absl::StrCat("\"", name, "\" is not a valid identifier.");
4875
0
        });
4876
0
        return;
4877
0
      }
4878
0
    }
4879
0
  }
4880
0
}
4881
4882
// -------------------------------------------------------------------
4883
4884
// This generic implementation is good for all descriptors except
4885
// FileDescriptor.
4886
template <class DescriptorT>
4887
void DescriptorBuilder::AllocateOptions(
4888
    const typename DescriptorT::Proto& proto, DescriptorT* descriptor,
4889
    int options_field_tag, absl::string_view option_name,
4890
0
    internal::FlatAllocator& alloc) {
4891
0
  std::vector<int> options_path;
4892
0
  descriptor->GetLocationPath(&options_path);
4893
0
  options_path.push_back(options_field_tag);
4894
0
  auto options = AllocateOptionsImpl<DescriptorT>(
4895
0
      descriptor->full_name(), descriptor->full_name(), proto, options_path,
4896
0
      option_name, alloc);
4897
0
  descriptor->options_ = options;
4898
0
}
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::Descriptor>(google::protobuf::Descriptor::Proto const&, google::protobuf::Descriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::FieldDescriptor>(google::protobuf::FieldDescriptor::Proto const&, google::protobuf::FieldDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::Descriptor::ExtensionRange>(google::protobuf::Descriptor::ExtensionRange::Proto const&, google::protobuf::Descriptor::ExtensionRange*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::OneofDescriptor>(google::protobuf::OneofDescriptor::Proto const&, google::protobuf::OneofDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::EnumDescriptor>(google::protobuf::EnumDescriptor::Proto const&, google::protobuf::EnumDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::EnumValueDescriptor>(google::protobuf::EnumValueDescriptor::Proto const&, google::protobuf::EnumValueDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::ServiceDescriptor>(google::protobuf::ServiceDescriptor::Proto const&, google::protobuf::ServiceDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::MethodDescriptor>(google::protobuf::MethodDescriptor::Proto const&, google::protobuf::MethodDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
4899
4900
// We specialize for FileDescriptor.
4901
void DescriptorBuilder::AllocateOptions(const FileDescriptorProto& proto,
4902
                                        FileDescriptor* descriptor,
4903
0
                                        internal::FlatAllocator& alloc) {
4904
0
  std::vector<int> options_path;
4905
0
  options_path.push_back(FileDescriptorProto::kOptionsFieldNumber);
4906
  // We add the dummy token so that LookupSymbol does the right thing.
4907
0
  auto options = AllocateOptionsImpl<FileDescriptor>(
4908
0
      absl::StrCat(descriptor->package(), ".dummy"), descriptor->name(), proto,
4909
0
      options_path, "google.protobuf.FileOptions", alloc);
4910
0
  descriptor->options_ = options;
4911
0
}
4912
4913
template <class DescriptorT>
4914
typename DescriptorT::OptionsType* DescriptorBuilder::AllocateOptionsImpl(
4915
    absl::string_view name_scope, absl::string_view element_name,
4916
    const typename DescriptorT::Proto& proto,
4917
    absl::Span<const int> options_path, absl::string_view option_name,
4918
0
    internal::FlatAllocator& alloc) {
4919
0
  if (!proto.has_options()) {
4920
    // Set to default_instance later if necessary.
4921
0
    return nullptr;
4922
0
  }
4923
0
  const typename DescriptorT::OptionsType& orig_options = proto.options();
4924
4925
0
  auto* options = alloc.AllocateArray<typename DescriptorT::OptionsType>(1);
4926
4927
0
  if (!orig_options.IsInitialized()) {
4928
0
    AddError(absl::StrCat(name_scope, ".", element_name), orig_options,
4929
0
             DescriptorPool::ErrorCollector::OPTION_NAME,
4930
0
             "Uninterpreted option is missing name or value.");
4931
0
    return nullptr;
4932
0
  }
4933
4934
  // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti
4935
  // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the
4936
  // reflection based method, which requires the Descriptor. However, we are in
4937
  // the middle of building the descriptors, thus the deadlock.
4938
0
  options->ParseFromString(orig_options.SerializeAsString());
4939
4940
  // Don't add to options_to_interpret_ unless there were uninterpreted
4941
  // options.  This not only avoids unnecessary work, but prevents a
4942
  // bootstrapping problem when building descriptors for descriptor.proto.
4943
  // descriptor.proto does not contain any uninterpreted options, but
4944
  // attempting to interpret options anyway will cause
4945
  // OptionsType::GetDescriptor() to be called which may then deadlock since
4946
  // we're still trying to build it.
4947
0
  if (options->uninterpreted_option_size() > 0) {
4948
0
    options_to_interpret_.push_back(OptionsToInterpret(
4949
0
        name_scope, element_name, options_path, &orig_options, options));
4950
0
  }
4951
4952
  // If the custom option is in unknown fields, no need to interpret it.
4953
  // Remove the dependency file from unused_dependency.
4954
0
  const UnknownFieldSet& unknown_fields = orig_options.unknown_fields();
4955
0
  if (!unknown_fields.empty()) {
4956
    // Can not use options->GetDescriptor() which may case deadlock.
4957
0
    Symbol msg_symbol = tables_->FindSymbol(option_name);
4958
0
    if (msg_symbol.type() == Symbol::MESSAGE) {
4959
0
      for (int i = 0; i < unknown_fields.field_count(); ++i) {
4960
0
        assert_mutex_held(pool_);
4961
0
        const FieldDescriptor* field =
4962
0
            pool_->InternalFindExtensionByNumberNoLock(
4963
0
                msg_symbol.descriptor(), unknown_fields.field(i).number());
4964
0
        if (field) {
4965
0
          unused_dependency_.erase(field->file());
4966
0
        }
4967
0
      }
4968
0
    }
4969
0
  }
4970
0
  return options;
4971
0
}
Unexecuted instantiation: google::protobuf::FileDescriptor::OptionsType* google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::FileDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::FileDescriptor::Proto const&, absl::lts_20230125::Span<int const>, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: google::protobuf::Descriptor::OptionsType* google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::Descriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::Descriptor::Proto const&, absl::lts_20230125::Span<int const>, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: google::protobuf::FieldDescriptor::OptionsType* google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::FieldDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::FieldDescriptor::Proto const&, absl::lts_20230125::Span<int const>, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: google::protobuf::Descriptor::ExtensionRange::OptionsType* google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::Descriptor::ExtensionRange>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::Descriptor::ExtensionRange::Proto const&, absl::lts_20230125::Span<int const>, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: google::protobuf::OneofDescriptor::OptionsType* google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::OneofDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::OneofDescriptor::Proto const&, absl::lts_20230125::Span<int const>, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: google::protobuf::EnumDescriptor::OptionsType* google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::EnumDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::EnumDescriptor::Proto const&, absl::lts_20230125::Span<int const>, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: google::protobuf::EnumValueDescriptor::OptionsType* google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::EnumValueDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::EnumValueDescriptor::Proto const&, absl::lts_20230125::Span<int const>, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: google::protobuf::ServiceDescriptor::OptionsType* google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::ServiceDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::ServiceDescriptor::Proto const&, absl::lts_20230125::Span<int const>, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: google::protobuf::MethodDescriptor::OptionsType* google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::MethodDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::MethodDescriptor::Proto const&, absl::lts_20230125::Span<int const>, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
4972
4973
4974
// A common pattern:  We want to convert a repeated field in the descriptor
4975
// to an array of values, calling some method to build each value.
4976
#define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT)               \
4977
0
  OUTPUT->NAME##_count_ = INPUT.NAME##_size();                         \
4978
0
  OUTPUT->NAME##s_ = alloc.AllocateArray<                              \
4979
0
      typename std::remove_pointer<decltype(OUTPUT->NAME##s_)>::type>( \
4980
0
      INPUT.NAME##_size());                                            \
4981
0
  for (int i = 0; i < INPUT.NAME##_size(); i++) {                      \
4982
0
    METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i, alloc);        \
4983
0
  }
4984
4985
PROTOBUF_NOINLINE void DescriptorBuilder::AddRecursiveImportError(
4986
0
    const FileDescriptorProto& proto, int from_here) {
4987
0
  auto make_error = [&] {
4988
0
    std::string error_message("File recursively imports itself: ");
4989
0
    for (size_t i = from_here; i < tables_->pending_files_.size(); i++) {
4990
0
      error_message.append(tables_->pending_files_[i]);
4991
0
      error_message.append(" -> ");
4992
0
    }
4993
0
    error_message.append(proto.name());
4994
0
    return error_message;
4995
0
  };
4996
4997
0
  if (static_cast<size_t>(from_here) < tables_->pending_files_.size() - 1) {
4998
0
    AddError(tables_->pending_files_[from_here + 1], proto,
4999
0
             DescriptorPool::ErrorCollector::IMPORT, make_error);
5000
0
  } else {
5001
0
    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::IMPORT,
5002
0
             make_error);
5003
0
  }
5004
0
}
5005
5006
void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto,
5007
0
                                            int index) {
5008
0
  AddError(proto.dependency(index), proto,
5009
0
           DescriptorPool::ErrorCollector::IMPORT, [&] {
5010
0
             return absl::StrCat("Import \"", proto.dependency(index),
5011
0
                                 "\" was listed twice.");
5012
0
           });
5013
0
}
5014
5015
void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto,
5016
0
                                       int index) {
5017
0
  auto make_error = [&] {
5018
0
    if (pool_->fallback_database_ == nullptr) {
5019
0
      return absl::StrCat("Import \"", proto.dependency(index),
5020
0
                          "\" has not been loaded.");
5021
0
    }
5022
0
    return absl::StrCat("Import \"", proto.dependency(index),
5023
0
                        "\" was not found or had errors.");
5024
0
  };
5025
0
  AddError(proto.dependency(index), proto,
5026
0
           DescriptorPool::ErrorCollector::IMPORT, make_error);
5027
0
}
5028
5029
PROTOBUF_NOINLINE static bool ExistingFileMatchesProto(
5030
0
    const FileDescriptor* existing_file, const FileDescriptorProto& proto) {
5031
0
  FileDescriptorProto existing_proto;
5032
0
  existing_file->CopyTo(&existing_proto);
5033
  // TODO(liujisi): Remove it when CopyTo supports copying syntax params when
5034
  // syntax="proto2".
5035
0
  if (FileDescriptorLegacy(existing_file).syntax() ==
5036
0
          FileDescriptorLegacy::Syntax::SYNTAX_PROTO2 &&
5037
0
      proto.has_syntax()) {
5038
0
    existing_proto.set_syntax(FileDescriptorLegacy::SyntaxName(
5039
0
        FileDescriptorLegacy(existing_file).syntax()));
5040
0
  }
5041
5042
0
  return existing_proto.SerializeAsString() == proto.SerializeAsString();
5043
0
}
5044
5045
// These PlanAllocationSize functions will gather into the FlatAllocator all the
5046
// necessary memory allocations that BuildXXX functions below will do on the
5047
// Tables object.
5048
// They *must* be kept in sync. If we miss some PlanArray call we won't have
5049
// enough memory and will ABSL_CHECK-fail.
5050
static void PlanAllocationSize(
5051
    const RepeatedPtrField<EnumValueDescriptorProto>& values,
5052
0
    internal::FlatAllocator& alloc) {
5053
0
  alloc.PlanArray<EnumValueDescriptor>(values.size());
5054
0
  alloc.PlanArray<std::string>(2 * values.size());  // name + full_name
5055
0
  for (const auto& v : values) {
5056
0
    if (v.has_options()) alloc.PlanArray<EnumValueOptions>(1);
5057
0
  }
5058
0
}
5059
5060
static void PlanAllocationSize(
5061
    const RepeatedPtrField<EnumDescriptorProto>& enums,
5062
0
    internal::FlatAllocator& alloc) {
5063
0
  alloc.PlanArray<EnumDescriptor>(enums.size());
5064
0
  alloc.PlanArray<std::string>(2 * enums.size());  // name + full_name
5065
0
  for (const auto& e : enums) {
5066
0
    if (e.has_options()) alloc.PlanArray<EnumOptions>(1);
5067
0
    PlanAllocationSize(e.value(), alloc);
5068
0
    alloc.PlanArray<EnumDescriptor::ReservedRange>(e.reserved_range_size());
5069
0
    alloc.PlanArray<const std::string*>(e.reserved_name_size());
5070
0
    alloc.PlanArray<std::string>(e.reserved_name_size());
5071
0
  }
5072
0
}
5073
5074
static void PlanAllocationSize(
5075
    const RepeatedPtrField<OneofDescriptorProto>& oneofs,
5076
0
    internal::FlatAllocator& alloc) {
5077
0
  alloc.PlanArray<OneofDescriptor>(oneofs.size());
5078
0
  alloc.PlanArray<std::string>(2 * oneofs.size());  // name + full_name
5079
0
  for (const auto& oneof : oneofs) {
5080
0
    if (oneof.has_options()) alloc.PlanArray<OneofOptions>(1);
5081
0
  }
5082
0
}
5083
5084
static void PlanAllocationSize(
5085
    const RepeatedPtrField<FieldDescriptorProto>& fields,
5086
0
    internal::FlatAllocator& alloc) {
5087
0
  alloc.PlanArray<FieldDescriptor>(fields.size());
5088
0
  for (const auto& field : fields) {
5089
0
    if (field.has_options()) alloc.PlanArray<FieldOptions>(1);
5090
0
    alloc.PlanFieldNames(field.name(),
5091
0
                         field.has_json_name() ? &field.json_name() : nullptr);
5092
0
    if (field.has_default_value() && field.has_type() &&
5093
0
        (field.type() == FieldDescriptorProto::TYPE_STRING ||
5094
0
         field.type() == FieldDescriptorProto::TYPE_BYTES)) {
5095
      // For the default string value.
5096
0
      alloc.PlanArray<std::string>(1);
5097
0
    }
5098
0
  }
5099
0
}
5100
5101
static void PlanAllocationSize(
5102
    const RepeatedPtrField<DescriptorProto::ExtensionRange>& ranges,
5103
0
    internal::FlatAllocator& alloc) {
5104
0
  alloc.PlanArray<Descriptor::ExtensionRange>(ranges.size());
5105
0
  for (const auto& r : ranges) {
5106
0
    if (r.has_options()) alloc.PlanArray<ExtensionRangeOptions>(1);
5107
0
  }
5108
0
}
5109
5110
static void PlanAllocationSize(
5111
    const RepeatedPtrField<DescriptorProto>& messages,
5112
0
    internal::FlatAllocator& alloc) {
5113
0
  alloc.PlanArray<Descriptor>(messages.size());
5114
0
  alloc.PlanArray<std::string>(2 * messages.size());  // name + full_name
5115
5116
0
  for (const auto& message : messages) {
5117
0
    if (message.has_options()) alloc.PlanArray<MessageOptions>(1);
5118
0
    PlanAllocationSize(message.nested_type(), alloc);
5119
0
    PlanAllocationSize(message.field(), alloc);
5120
0
    PlanAllocationSize(message.extension(), alloc);
5121
0
    PlanAllocationSize(message.extension_range(), alloc);
5122
0
    alloc.PlanArray<Descriptor::ReservedRange>(message.reserved_range_size());
5123
0
    alloc.PlanArray<const std::string*>(message.reserved_name_size());
5124
0
    alloc.PlanArray<std::string>(message.reserved_name_size());
5125
0
    PlanAllocationSize(message.enum_type(), alloc);
5126
0
    PlanAllocationSize(message.oneof_decl(), alloc);
5127
0
  }
5128
0
}
5129
5130
static void PlanAllocationSize(
5131
    const RepeatedPtrField<MethodDescriptorProto>& methods,
5132
0
    internal::FlatAllocator& alloc) {
5133
0
  alloc.PlanArray<MethodDescriptor>(methods.size());
5134
0
  alloc.PlanArray<std::string>(2 * methods.size());  // name + full_name
5135
0
  for (const auto& m : methods) {
5136
0
    if (m.has_options()) alloc.PlanArray<MethodOptions>(1);
5137
0
  }
5138
0
}
5139
5140
static void PlanAllocationSize(
5141
    const RepeatedPtrField<ServiceDescriptorProto>& services,
5142
0
    internal::FlatAllocator& alloc) {
5143
0
  alloc.PlanArray<ServiceDescriptor>(services.size());
5144
0
  alloc.PlanArray<std::string>(2 * services.size());  // name + full_name
5145
0
  for (const auto& service : services) {
5146
0
    if (service.has_options()) alloc.PlanArray<ServiceOptions>(1);
5147
0
    PlanAllocationSize(service.method(), alloc);
5148
0
  }
5149
0
}
5150
5151
static void PlanAllocationSize(const FileDescriptorProto& proto,
5152
0
                               internal::FlatAllocator& alloc) {
5153
0
  alloc.PlanArray<FileDescriptor>(1);
5154
0
  alloc.PlanArray<FileDescriptorTables>(1);
5155
0
  alloc.PlanArray<std::string>(2
5156
0
  );    // name + package
5157
0
  if (proto.has_options()) alloc.PlanArray<FileOptions>(1);
5158
0
  if (proto.has_source_code_info()) alloc.PlanArray<SourceCodeInfo>(1);
5159
5160
0
  PlanAllocationSize(proto.service(), alloc);
5161
0
  PlanAllocationSize(proto.message_type(), alloc);
5162
0
  PlanAllocationSize(proto.enum_type(), alloc);
5163
0
  PlanAllocationSize(proto.extension(), alloc);
5164
5165
0
  alloc.PlanArray<int>(proto.weak_dependency_size());
5166
0
  alloc.PlanArray<int>(proto.public_dependency_size());
5167
0
  alloc.PlanArray<const FileDescriptor*>(proto.dependency_size());
5168
0
}
5169
5170
const FileDescriptor* DescriptorBuilder::BuildFile(
5171
0
    const FileDescriptorProto& original_proto) {
5172
0
  filename_ = original_proto.name();
5173
5174
0
  const FileDescriptorProto& proto = original_proto;
5175
5176
  // Check if the file already exists and is identical to the one being built.
5177
  // Note:  This only works if the input is canonical -- that is, it
5178
  //   fully-qualifies all type names, has no UninterpretedOptions, etc.
5179
  //   This is fine, because this idempotency "feature" really only exists to
5180
  //   accommodate one hack in the proto1->proto2 migration layer.
5181
0
  const FileDescriptor* existing_file = tables_->FindFile(filename_);
5182
0
  if (existing_file != nullptr) {
5183
    // File already in pool.  Compare the existing one to the input.
5184
0
    if (ExistingFileMatchesProto(existing_file, proto)) {
5185
      // They're identical.  Return the existing descriptor.
5186
0
      return existing_file;
5187
0
    }
5188
5189
    // Not a match.  The error will be detected and handled later.
5190
0
  }
5191
5192
  // Check to see if this file is already on the pending files list.
5193
  // TODO(kenton):  Allow recursive imports?  It may not work with some
5194
  //   (most?) programming languages.  E.g., in C++, a forward declaration
5195
  //   of a type is not sufficient to allow it to be used even in a
5196
  //   generated header file due to inlining.  This could perhaps be
5197
  //   worked around using tricks involving inserting #include statements
5198
  //   mid-file, but that's pretty ugly, and I'm pretty sure there are
5199
  //   some languages out there that do not allow recursive dependencies
5200
  //   at all.
5201
0
  for (size_t i = 0; i < tables_->pending_files_.size(); i++) {
5202
0
    if (tables_->pending_files_[i] == proto.name()) {
5203
0
      AddRecursiveImportError(proto, i);
5204
0
      return nullptr;
5205
0
    }
5206
0
  }
5207
5208
0
  static const int kMaximumPackageLength = 511;
5209
0
  if (proto.package().size() > kMaximumPackageLength) {
5210
0
    AddError(proto.package(), proto, DescriptorPool::ErrorCollector::NAME,
5211
0
             "Package name is too long");
5212
0
    return nullptr;
5213
0
  }
5214
5215
  // If we have a fallback_database_, and we aren't doing lazy import building,
5216
  // attempt to load all dependencies now, before checkpointing tables_.  This
5217
  // avoids confusion with recursive checkpoints.
5218
0
  if (!pool_->lazily_build_dependencies_) {
5219
0
    if (pool_->fallback_database_ != nullptr) {
5220
0
      tables_->pending_files_.push_back(proto.name());
5221
0
      for (int i = 0; i < proto.dependency_size(); i++) {
5222
0
        if (tables_->FindFile(proto.dependency(i)) == nullptr &&
5223
0
            (pool_->underlay_ == nullptr ||
5224
0
             pool_->underlay_->FindFileByName(proto.dependency(i)) ==
5225
0
                 nullptr)) {
5226
          // We don't care what this returns since we'll find out below anyway.
5227
0
          pool_->TryFindFileInFallbackDatabase(proto.dependency(i));
5228
0
        }
5229
0
      }
5230
0
      tables_->pending_files_.pop_back();
5231
0
    }
5232
0
  }
5233
5234
  // Checkpoint the tables so that we can roll back if something goes wrong.
5235
0
  tables_->AddCheckpoint();
5236
5237
0
  auto alloc = absl::make_unique<internal::FlatAllocator>();
5238
0
  PlanAllocationSize(proto, *alloc);
5239
0
  alloc->FinalizePlanning(tables_);
5240
0
  FileDescriptor* result = BuildFileImpl(proto, *alloc);
5241
5242
0
  file_tables_->FinalizeTables();
5243
0
  if (result) {
5244
0
    tables_->ClearLastCheckpoint();
5245
0
    result->finished_building_ = true;
5246
0
    alloc->ExpectConsumed();
5247
0
  } else {
5248
0
    tables_->RollbackToLastCheckpoint();
5249
0
  }
5250
5251
0
  return result;
5252
0
}
5253
5254
FileDescriptor* DescriptorBuilder::BuildFileImpl(
5255
0
    const FileDescriptorProto& proto, internal::FlatAllocator& alloc) {
5256
0
  FileDescriptor* result = alloc.AllocateArray<FileDescriptor>(1);
5257
0
  file_ = result;
5258
5259
5260
0
  result->is_placeholder_ = false;
5261
0
  result->finished_building_ = false;
5262
0
  SourceCodeInfo* info = nullptr;
5263
0
  if (proto.has_source_code_info()) {
5264
0
    info = alloc.AllocateArray<SourceCodeInfo>(1);
5265
0
    info->CopyFrom(proto.source_code_info());
5266
0
    result->source_code_info_ = info;
5267
0
  } else {
5268
0
    result->source_code_info_ = &SourceCodeInfo::default_instance();
5269
0
  }
5270
5271
0
  file_tables_ = alloc.AllocateArray<FileDescriptorTables>(1);
5272
0
  file_->tables_ = file_tables_;
5273
5274
0
  if (!proto.has_name()) {
5275
0
    AddError("", proto, DescriptorPool::ErrorCollector::OTHER,
5276
0
             "Missing field: FileDescriptorProto.name.");
5277
0
  }
5278
5279
  // TODO(liujisi): Report error when the syntax is empty after all the protos
5280
  // have added the syntax statement.
5281
0
  if (proto.syntax().empty() || proto.syntax() == "proto2") {
5282
0
    file_->syntax_ = FileDescriptorLegacy::SYNTAX_PROTO2;
5283
0
  } else if (proto.syntax() == "proto3") {
5284
0
    file_->syntax_ = FileDescriptorLegacy::SYNTAX_PROTO3;
5285
0
  } else {
5286
0
    file_->syntax_ = FileDescriptorLegacy::SYNTAX_UNKNOWN;
5287
0
    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, [&] {
5288
0
      return absl::StrCat("Unrecognized syntax: ", proto.syntax());
5289
0
    });
5290
0
  }
5291
5292
0
  result->name_ = alloc.AllocateStrings(proto.name());
5293
0
  if (proto.has_package()) {
5294
0
    result->package_ = alloc.AllocateStrings(proto.package());
5295
0
  } else {
5296
    // We cannot rely on proto.package() returning a valid string if
5297
    // proto.has_package() is false, because we might be running at static
5298
    // initialization time, in which case default values have not yet been
5299
    // initialized.
5300
0
    result->package_ = alloc.AllocateStrings("");
5301
0
  }
5302
0
  result->pool_ = pool_;
5303
5304
0
  if (result->name().find('\0') != std::string::npos) {
5305
0
    AddError(result->name(), proto, DescriptorPool::ErrorCollector::NAME, [&] {
5306
0
      return absl::StrCat("\"", result->name(), "\" contains null character.");
5307
0
    });
5308
0
    return nullptr;
5309
0
  }
5310
5311
  // Add to tables.
5312
0
  if (!tables_->AddFile(result)) {
5313
0
    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
5314
0
             "A file with this name is already in the pool.");
5315
    // Bail out early so that if this is actually the exact same file, we
5316
    // don't end up reporting that every single symbol is already defined.
5317
0
    return nullptr;
5318
0
  }
5319
0
  if (!result->package().empty()) {
5320
0
    if (std::count(result->package().begin(), result->package().end(), '.') >
5321
0
        kPackageLimit) {
5322
0
      AddError(result->package(), proto, DescriptorPool::ErrorCollector::NAME,
5323
0
               "Exceeds Maximum Package Depth");
5324
0
      return nullptr;
5325
0
    }
5326
0
    AddPackage(result->package(), proto, result);
5327
0
  }
5328
5329
  // Make sure all dependencies are loaded.
5330
0
  absl::flat_hash_set<absl::string_view> seen_dependencies;
5331
0
  result->dependency_count_ = proto.dependency_size();
5332
0
  result->dependencies_ =
5333
0
      alloc.AllocateArray<const FileDescriptor*>(proto.dependency_size());
5334
0
  result->dependencies_once_ = nullptr;
5335
0
  unused_dependency_.clear();
5336
0
  absl::flat_hash_set<int> weak_deps;
5337
0
  for (int i = 0; i < proto.weak_dependency_size(); ++i) {
5338
0
    weak_deps.insert(proto.weak_dependency(i));
5339
0
  }
5340
5341
0
  bool need_lazy_deps = false;
5342
0
  for (int i = 0; i < proto.dependency_size(); i++) {
5343
0
    if (!seen_dependencies.insert(proto.dependency(i)).second) {
5344
0
      AddTwiceListedError(proto, i);
5345
0
    }
5346
5347
0
    const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
5348
0
    if (dependency == nullptr && pool_->underlay_ != nullptr) {
5349
0
      dependency = pool_->underlay_->FindFileByName(proto.dependency(i));
5350
0
    }
5351
5352
0
    if (dependency == result) {
5353
      // Recursive import.  dependency/result is not fully initialized, and it's
5354
      // dangerous to try to do anything with it.  The recursive import error
5355
      // will be detected and reported in DescriptorBuilder::BuildFile().
5356
0
      return nullptr;
5357
0
    }
5358
5359
5360
0
    if (dependency == nullptr) {
5361
0
      if (!pool_->lazily_build_dependencies_) {
5362
0
        if (pool_->allow_unknown_ ||
5363
0
            (!pool_->enforce_weak_ && weak_deps.contains(i))) {
5364
0
          internal::FlatAllocator lazy_dep_alloc;
5365
0
          lazy_dep_alloc.PlanArray<FileDescriptor>(1);
5366
0
          lazy_dep_alloc.PlanArray<std::string>(1);
5367
0
          lazy_dep_alloc.FinalizePlanning(tables_);
5368
0
          dependency = pool_->NewPlaceholderFileWithMutexHeld(
5369
0
              proto.dependency(i), lazy_dep_alloc);
5370
0
        } else {
5371
0
          AddImportError(proto, i);
5372
0
        }
5373
0
      }
5374
0
    } else {
5375
      // Add to unused_dependency_ to track unused imported files.
5376
      // Note: do not track unused imported files for public import.
5377
0
      if (pool_->enforce_dependencies_ &&
5378
0
          (pool_->unused_import_track_files_.find(proto.name()) !=
5379
0
           pool_->unused_import_track_files_.end()) &&
5380
0
          (dependency->public_dependency_count() == 0)) {
5381
0
        unused_dependency_.insert(dependency);
5382
0
      }
5383
0
    }
5384
5385
0
    result->dependencies_[i] = dependency;
5386
0
    if (pool_->lazily_build_dependencies_ && !dependency) {
5387
0
      need_lazy_deps = true;
5388
0
    }
5389
0
  }
5390
0
  if (need_lazy_deps) {
5391
0
    int total_char_size = 0;
5392
0
    for (int i = 0; i < proto.dependency_size(); i++) {
5393
0
      if (result->dependencies_[i] == nullptr) {
5394
0
        total_char_size += static_cast<int>(proto.dependency(i).size());
5395
0
      }
5396
0
      ++total_char_size;  // For NUL char
5397
0
    }
5398
5399
0
    void* data = tables_->AllocateBytes(
5400
0
        static_cast<int>(sizeof(absl::once_flag)) + total_char_size);
5401
0
    result->dependencies_once_ = ::new (data) absl::once_flag{};
5402
0
    char* name_data = reinterpret_cast<char*>(result->dependencies_once_ + 1);
5403
5404
0
    for (int i = 0; i < proto.dependency_size(); i++) {
5405
0
      if (result->dependencies_[i] == nullptr) {
5406
0
        memcpy(name_data, proto.dependency(i).c_str(),
5407
0
               proto.dependency(i).size());
5408
0
        name_data += proto.dependency(i).size();
5409
0
      }
5410
0
      *name_data++ = '\0';
5411
0
    }
5412
0
  }
5413
5414
  // Check public dependencies.
5415
0
  int public_dependency_count = 0;
5416
0
  result->public_dependencies_ =
5417
0
      alloc.AllocateArray<int>(proto.public_dependency_size());
5418
0
  for (int i = 0; i < proto.public_dependency_size(); i++) {
5419
    // Only put valid public dependency indexes.
5420
0
    int index = proto.public_dependency(i);
5421
0
    if (index >= 0 && index < proto.dependency_size()) {
5422
0
      result->public_dependencies_[public_dependency_count++] = index;
5423
      // Do not track unused imported files for public import.
5424
      // Calling dependency(i) builds that file when doing lazy imports,
5425
      // need to avoid doing this. Unused dependency detection isn't done
5426
      // when building lazily, anyways.
5427
0
      if (!pool_->lazily_build_dependencies_) {
5428
0
        unused_dependency_.erase(result->dependency(index));
5429
0
      }
5430
0
    } else {
5431
0
      AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
5432
0
               "Invalid public dependency index.");
5433
0
    }
5434
0
  }
5435
0
  result->public_dependency_count_ = public_dependency_count;
5436
5437
  // Build dependency set
5438
0
  dependencies_.clear();
5439
  // We don't/can't do proper dependency error checking when
5440
  // lazily_build_dependencies_, and calling dependency(i) will force
5441
  // a dependency to be built, which we don't want.
5442
0
  if (!pool_->lazily_build_dependencies_) {
5443
0
    for (int i = 0; i < result->dependency_count(); i++) {
5444
0
      RecordPublicDependencies(result->dependency(i));
5445
0
    }
5446
0
  }
5447
5448
  // Check weak dependencies.
5449
0
  int weak_dependency_count = 0;
5450
0
  result->weak_dependencies_ =
5451
0
      alloc.AllocateArray<int>(proto.weak_dependency_size());
5452
0
  for (int i = 0; i < proto.weak_dependency_size(); i++) {
5453
0
    int index = proto.weak_dependency(i);
5454
0
    if (index >= 0 && index < proto.dependency_size()) {
5455
0
      result->weak_dependencies_[weak_dependency_count++] = index;
5456
0
    } else {
5457
0
      AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
5458
0
               "Invalid weak dependency index.");
5459
0
    }
5460
0
  }
5461
0
  result->weak_dependency_count_ = weak_dependency_count;
5462
5463
  // Convert children.
5464
0
  BUILD_ARRAY(proto, result, message_type, BuildMessage, nullptr);
5465
0
  BUILD_ARRAY(proto, result, enum_type, BuildEnum, nullptr);
5466
0
  BUILD_ARRAY(proto, result, service, BuildService, nullptr);
5467
0
  BUILD_ARRAY(proto, result, extension, BuildExtension, nullptr);
5468
5469
  // Copy options.
5470
0
  AllocateOptions(proto, result, alloc);
5471
5472
  // Note that the following steps must occur in exactly the specified order.
5473
5474
  // Cross-link.
5475
0
  CrossLinkFile(result, proto);
5476
5477
0
  if (!message_hints_.empty()) {
5478
0
    SuggestFieldNumbers(result, proto);
5479
0
  }
5480
5481
  // Interpret any remaining uninterpreted options gathered into
5482
  // options_to_interpret_ during descriptor building.  Cross-linking has made
5483
  // extension options known, so all interpretations should now succeed.
5484
0
  if (!had_errors_) {
5485
0
    OptionInterpreter option_interpreter(this);
5486
0
    for (std::vector<OptionsToInterpret>::iterator iter =
5487
0
             options_to_interpret_.begin();
5488
0
         iter != options_to_interpret_.end(); ++iter) {
5489
0
      option_interpreter.InterpretOptions(&(*iter));
5490
0
    }
5491
0
    options_to_interpret_.clear();
5492
0
    if (info != nullptr) {
5493
0
      option_interpreter.UpdateSourceCodeInfo(info);
5494
0
    }
5495
0
  }
5496
5497
5498
  // Validate options. See comments at InternalSetLazilyBuildDependencies about
5499
  // error checking and lazy import building.
5500
0
  if (!had_errors_ && !pool_->lazily_build_dependencies_) {
5501
0
    internal::VisitDescriptors(*result, proto,
5502
0
                               [&](const auto& descriptor, const auto& proto) {
5503
0
                                 ValidateOptions(&descriptor, proto);
5504
0
                               });
Unexecuted instantiation: descriptor.cc:auto google::protobuf::DescriptorBuilder::BuildFileImpl(google::protobuf::FileDescriptorProto const&, google::protobuf::internal::FlatAllocator&)::$_18::operator()<google::protobuf::FileDescriptor, google::protobuf::FileDescriptorProto>(google::protobuf::FileDescriptor const&, google::protobuf::FileDescriptorProto const&) const
Unexecuted instantiation: descriptor.cc:auto google::protobuf::DescriptorBuilder::BuildFileImpl(google::protobuf::FileDescriptorProto const&, google::protobuf::internal::FlatAllocator&)::$_18::operator()<google::protobuf::Descriptor, google::protobuf::DescriptorProto>(google::protobuf::Descriptor const&, google::protobuf::DescriptorProto const&) const
Unexecuted instantiation: descriptor.cc:auto google::protobuf::DescriptorBuilder::BuildFileImpl(google::protobuf::FileDescriptorProto const&, google::protobuf::internal::FlatAllocator&)::$_18::operator()<google::protobuf::OneofDescriptor, google::protobuf::OneofDescriptorProto>(google::protobuf::OneofDescriptor const&, google::protobuf::OneofDescriptorProto const&) const
Unexecuted instantiation: descriptor.cc:auto google::protobuf::DescriptorBuilder::BuildFileImpl(google::protobuf::FileDescriptorProto const&, google::protobuf::internal::FlatAllocator&)::$_18::operator()<google::protobuf::Descriptor::ExtensionRange, google::protobuf::DescriptorProto_ExtensionRange>(google::protobuf::Descriptor::ExtensionRange const&, google::protobuf::DescriptorProto_ExtensionRange const&) const
Unexecuted instantiation: descriptor.cc:auto google::protobuf::DescriptorBuilder::BuildFileImpl(google::protobuf::FileDescriptorProto const&, google::protobuf::internal::FlatAllocator&)::$_18::operator()<google::protobuf::EnumDescriptor, google::protobuf::EnumDescriptorProto>(google::protobuf::EnumDescriptor const&, google::protobuf::EnumDescriptorProto const&) const
Unexecuted instantiation: descriptor.cc:auto google::protobuf::DescriptorBuilder::BuildFileImpl(google::protobuf::FileDescriptorProto const&, google::protobuf::internal::FlatAllocator&)::$_18::operator()<google::protobuf::EnumValueDescriptor, google::protobuf::EnumValueDescriptorProto>(google::protobuf::EnumValueDescriptor const&, google::protobuf::EnumValueDescriptorProto const&) const
Unexecuted instantiation: descriptor.cc:auto google::protobuf::DescriptorBuilder::BuildFileImpl(google::protobuf::FileDescriptorProto const&, google::protobuf::internal::FlatAllocator&)::$_18::operator()<google::protobuf::FieldDescriptor, google::protobuf::FieldDescriptorProto>(google::protobuf::FieldDescriptor const&, google::protobuf::FieldDescriptorProto const&) const
Unexecuted instantiation: descriptor.cc:auto google::protobuf::DescriptorBuilder::BuildFileImpl(google::protobuf::FileDescriptorProto const&, google::protobuf::internal::FlatAllocator&)::$_18::operator()<google::protobuf::ServiceDescriptor, google::protobuf::ServiceDescriptorProto>(google::protobuf::ServiceDescriptor const&, google::protobuf::ServiceDescriptorProto const&) const
Unexecuted instantiation: descriptor.cc:auto google::protobuf::DescriptorBuilder::BuildFileImpl(google::protobuf::FileDescriptorProto const&, google::protobuf::internal::FlatAllocator&)::$_18::operator()<google::protobuf::MethodDescriptor, google::protobuf::MethodDescriptorProto>(google::protobuf::MethodDescriptor const&, google::protobuf::MethodDescriptorProto const&) const
5505
0
  }
5506
5507
  // Additional naming conflict check for map entry types. Only need to check
5508
  // this if there are already errors.
5509
0
  if (had_errors_) {
5510
0
    for (int i = 0; i < proto.message_type_size(); ++i) {
5511
0
      DetectMapConflicts(result->message_type(i), proto.message_type(i));
5512
0
    }
5513
0
  }
5514
5515
5516
  // Again, see comments at InternalSetLazilyBuildDependencies about error
5517
  // checking. Also, don't log unused dependencies if there were previous
5518
  // errors, since the results might be inaccurate.
5519
0
  if (!had_errors_ && !unused_dependency_.empty() &&
5520
0
      !pool_->lazily_build_dependencies_) {
5521
0
    LogUnusedDependency(proto, result);
5522
0
  }
5523
5524
0
  if (had_errors_) {
5525
0
    return nullptr;
5526
0
  } else {
5527
0
    return result;
5528
0
  }
5529
0
}
5530
5531
5532
const std::string* DescriptorBuilder::AllocateNameStrings(
5533
    const std::string& scope, const std::string& proto_name,
5534
0
    internal::FlatAllocator& alloc) {
5535
0
  if (scope.empty()) {
5536
0
    return alloc.AllocateStrings(proto_name, proto_name);
5537
0
  } else {
5538
0
    return alloc.AllocateStrings(proto_name,
5539
0
                                 absl::StrCat(scope, ".", proto_name));
5540
0
  }
5541
0
}
5542
5543
namespace {
5544
5545
// Helper for BuildMessage below.
5546
struct IncrementWhenDestroyed {
5547
0
  ~IncrementWhenDestroyed() { ++to_increment; }
5548
  int& to_increment;
5549
};
5550
5551
}  // namespace
5552
5553
namespace {
5554
0
bool IsNonMessageType(absl::string_view type) {
5555
0
  static const auto* non_message_types =
5556
0
      new absl::flat_hash_set<absl::string_view>(
5557
0
          {"double", "float", "int64", "uint64", "int32", "fixed32", "fixed64",
5558
0
           "bool", "string", "bytes", "uint32", "enum", "sfixed32", "sfixed64",
5559
0
           "sint32", "sint64"});
5560
0
  return non_message_types->contains(type);
5561
0
}
5562
}  // namespace
5563
5564
5565
void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
5566
                                     const Descriptor* parent,
5567
                                     Descriptor* result,
5568
0
                                     internal::FlatAllocator& alloc) {
5569
0
  const std::string& scope =
5570
0
      (parent == nullptr) ? file_->package() : parent->full_name();
5571
0
  result->all_names_ = AllocateNameStrings(scope, proto.name(), alloc);
5572
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
5573
5574
0
  result->file_ = file_;
5575
0
  result->containing_type_ = parent;
5576
0
  result->is_placeholder_ = false;
5577
0
  result->is_unqualified_placeholder_ = false;
5578
0
  result->well_known_type_ = Descriptor::WELLKNOWNTYPE_UNSPECIFIED;
5579
0
  result->options_ = nullptr;  // Set to default_instance later if necessary.
5580
5581
0
  auto it = pool_->tables_->well_known_types_.find(result->full_name());
5582
0
  if (it != pool_->tables_->well_known_types_.end()) {
5583
0
    result->well_known_type_ = it->second;
5584
0
  }
5585
5586
  // Calculate the continuous sequence of fields.
5587
  // These can be fast-path'd during lookup and don't need to be added to the
5588
  // tables.
5589
  // We use uint16_t to save space for sequential_field_limit_, so stop before
5590
  // overflowing it. Worst case, we are not taking full advantage on huge
5591
  // messages, but it is unlikely.
5592
0
  result->sequential_field_limit_ = 0;
5593
0
  for (int i = 0; i < std::numeric_limits<uint16_t>::max() &&
5594
0
                  i < proto.field_size() && proto.field(i).number() == i + 1;
5595
0
       ++i) {
5596
0
    result->sequential_field_limit_ = i + 1;
5597
0
  }
5598
5599
  // Build oneofs first so that fields and extension ranges can refer to them.
5600
0
  BUILD_ARRAY(proto, result, oneof_decl, BuildOneof, result);
5601
0
  BUILD_ARRAY(proto, result, field, BuildField, result);
5602
0
  BUILD_ARRAY(proto, result, enum_type, BuildEnum, result);
5603
0
  BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result);
5604
0
  BUILD_ARRAY(proto, result, extension, BuildExtension, result);
5605
0
  BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);
5606
5607
  // Before building submessages, check recursion limit.
5608
0
  --recursion_depth_;
5609
0
  IncrementWhenDestroyed revert{recursion_depth_};
5610
0
  if (recursion_depth_ <= 0) {
5611
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::OTHER,
5612
0
             "Reached maximum recursion limit for nested messages.");
5613
0
    result->nested_types_ = nullptr;
5614
0
    result->nested_type_count_ = 0;
5615
0
    return;
5616
0
  }
5617
0
  BUILD_ARRAY(proto, result, nested_type, BuildMessage, result);
5618
5619
  // Copy reserved names.
5620
0
  int reserved_name_count = proto.reserved_name_size();
5621
0
  result->reserved_name_count_ = reserved_name_count;
5622
0
  result->reserved_names_ =
5623
0
      alloc.AllocateArray<const std::string*>(reserved_name_count);
5624
0
  for (int i = 0; i < reserved_name_count; ++i) {
5625
0
    result->reserved_names_[i] =
5626
0
        alloc.AllocateStrings(proto.reserved_name(i));
5627
0
  }
5628
5629
  // Copy options.
5630
0
  AllocateOptions(proto, result, DescriptorProto::kOptionsFieldNumber,
5631
0
                  "google.protobuf.MessageOptions", alloc);
5632
5633
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5634
5635
0
  for (int i = 0; i < proto.reserved_range_size(); i++) {
5636
0
    const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i);
5637
0
    for (int j = i + 1; j < proto.reserved_range_size(); j++) {
5638
0
      const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j);
5639
0
      if (range1.end() > range2.start() && range2.end() > range1.start()) {
5640
0
        AddError(result->full_name(), proto.reserved_range(i),
5641
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
5642
0
                   return absl::Substitute(
5643
0
                       "Reserved range $0 to $1 overlaps with "
5644
0
                       "already-defined range $2 to $3.",
5645
0
                       range2.start(), range2.end() - 1, range1.start(),
5646
0
                       range1.end() - 1);
5647
0
                 });
5648
0
      }
5649
0
    }
5650
0
  }
5651
5652
0
  absl::flat_hash_set<absl::string_view> reserved_name_set;
5653
0
  for (const std::string& name : proto.reserved_name()) {
5654
0
    if (!reserved_name_set.insert(name).second) {
5655
0
      AddError(name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
5656
0
        return absl::Substitute("Field name \"$0\" is reserved multiple times.",
5657
0
                                name);
5658
0
      });
5659
0
    }
5660
0
  }
5661
  // Check that fields aren't using reserved names or numbers and that they
5662
  // aren't using extension numbers.
5663
0
  for (int i = 0; i < result->field_count(); i++) {
5664
0
    const FieldDescriptor* field = result->field(i);
5665
0
    for (int j = 0; j < result->extension_range_count(); j++) {
5666
0
      const Descriptor::ExtensionRange* range = result->extension_range(j);
5667
0
      if (range->start_number() <= field->number() &&
5668
0
          field->number() < range->end_number()) {
5669
0
        message_hints_[result].RequestHintOnFieldNumbers(
5670
0
            proto.extension_range(j), DescriptorPool::ErrorCollector::NUMBER);
5671
0
        AddError(field->full_name(), proto.extension_range(j),
5672
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
5673
0
                   return absl::Substitute(
5674
0
                       "Extension range $0 to $1 includes field \"$2\" ($3).",
5675
0
                       range->start_number(), range->end_number() - 1,
5676
0
                       field->name(), field->number());
5677
0
                 });
5678
0
      }
5679
0
    }
5680
0
    for (int j = 0; j < result->reserved_range_count(); j++) {
5681
0
      const Descriptor::ReservedRange* range = result->reserved_range(j);
5682
0
      if (range->start <= field->number() && field->number() < range->end) {
5683
0
        message_hints_[result].RequestHintOnFieldNumbers(
5684
0
            proto.reserved_range(j), DescriptorPool::ErrorCollector::NUMBER);
5685
0
        AddError(field->full_name(), proto.reserved_range(j),
5686
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
5687
0
                   return absl::Substitute(
5688
0
                       "Field \"$0\" uses reserved number $1.", field->name(),
5689
0
                       field->number());
5690
0
                 });
5691
0
      }
5692
0
    }
5693
0
    if (reserved_name_set.contains(field->name())) {
5694
0
      AddError(field->full_name(), proto.field(i),
5695
0
               DescriptorPool::ErrorCollector::NAME, [&] {
5696
0
                 return absl::Substitute("Field name \"$0\" is reserved.",
5697
0
                                         field->name());
5698
0
               });
5699
0
    }
5700
0
  }
5701
5702
  // Check that extension ranges don't overlap and don't include
5703
  // reserved field numbers or names.
5704
0
  for (int i = 0; i < result->extension_range_count(); i++) {
5705
0
    const Descriptor::ExtensionRange* range1 = result->extension_range(i);
5706
0
    for (int j = 0; j < result->reserved_range_count(); j++) {
5707
0
      const Descriptor::ReservedRange* range2 = result->reserved_range(j);
5708
0
      if (range1->end_number() > range2->start &&
5709
0
          range2->end > range1->start_number()) {
5710
0
        AddError(result->full_name(), proto.extension_range(i),
5711
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
5712
0
                   return absl::Substitute(
5713
0
                       "Extension range $0 to $1 overlaps with "
5714
0
                       "reserved range $2 to $3.",
5715
0
                       range1->start_number(), range1->end_number() - 1,
5716
0
                       range2->start, range2->end - 1);
5717
0
                 });
5718
0
      }
5719
0
    }
5720
0
    for (int j = i + 1; j < result->extension_range_count(); j++) {
5721
0
      const Descriptor::ExtensionRange* range2 = result->extension_range(j);
5722
0
      if (range1->end_number() > range2->start_number() &&
5723
0
          range2->end_number() > range1->start_number()) {
5724
0
        AddError(result->full_name(), proto.extension_range(i),
5725
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
5726
0
                   return absl::Substitute(
5727
0
                       "Extension range $0 to $1 overlaps with "
5728
0
                       "already-defined range $2 to $3.",
5729
0
                       range2->start_number(), range2->end_number() - 1,
5730
0
                       range1->start_number(), range1->end_number() - 1);
5731
0
                 });
5732
0
      }
5733
0
    }
5734
0
  }
5735
0
}
5736
5737
void DescriptorBuilder::CheckFieldJsonNameUniqueness(
5738
0
    const DescriptorProto& proto, const Descriptor* result) {
5739
0
  FileDescriptorLegacy::Syntax syntax =
5740
0
      FileDescriptorLegacy(result->file()).syntax();
5741
0
  std::string message_name = result->full_name();
5742
0
  if (pool_->deprecated_legacy_json_field_conflicts_ ||
5743
0
      IsLegacyJsonFieldConflictEnabled(result->options())) {
5744
0
    if (syntax == FileDescriptorLegacy::Syntax::SYNTAX_PROTO3) {
5745
      // Only check default JSON names for conflicts in proto3.  This is legacy
5746
      // behavior that will be removed in a later version.
5747
0
      CheckFieldJsonNameUniqueness(message_name, proto, syntax, false);
5748
0
    }
5749
0
  } else {
5750
    // Check both with and without taking json_name into consideration.  This is
5751
    // needed for field masks, which don't use json_name.
5752
0
    CheckFieldJsonNameUniqueness(message_name, proto, syntax, false);
5753
0
    CheckFieldJsonNameUniqueness(message_name, proto, syntax, true);
5754
0
  }
5755
0
}
5756
5757
namespace {
5758
// Helpers for function below
5759
5760
struct JsonNameDetails {
5761
  const FieldDescriptorProto* field;
5762
  std::string orig_name;
5763
  bool is_custom;
5764
};
5765
5766
JsonNameDetails GetJsonNameDetails(const FieldDescriptorProto* field,
5767
0
                                   bool use_custom) {
5768
0
  std::string default_json_name = ToJsonName(field->name());
5769
0
  if (use_custom && field->has_json_name() &&
5770
0
      field->json_name() != default_json_name) {
5771
0
    return {field, field->json_name(), true};
5772
0
  }
5773
0
  return {field, default_json_name, false};
5774
0
}
5775
5776
0
bool JsonNameLooksLikeExtension(std::string name) {
5777
0
  return !name.empty() && name.front() == '[' && name.back() == ']';
5778
0
}
5779
5780
}  // namespace
5781
5782
void DescriptorBuilder::CheckFieldJsonNameUniqueness(
5783
    const std::string& message_name, const DescriptorProto& message,
5784
0
    FileDescriptorLegacy::Syntax syntax, bool use_custom_names) {
5785
0
  absl::flat_hash_map<std::string, JsonNameDetails> name_to_field;
5786
0
  for (const FieldDescriptorProto& field : message.field()) {
5787
0
    JsonNameDetails details = GetJsonNameDetails(&field, use_custom_names);
5788
0
    if (details.is_custom && JsonNameLooksLikeExtension(details.orig_name)) {
5789
0
      auto make_error = [&] {
5790
0
        return absl::StrFormat(
5791
0
            "The custom JSON name of field \"%s\" (\"%s\") is invalid: "
5792
0
            "JSON names may not start with '[' and end with ']'.",
5793
0
            field.name(), details.orig_name);
5794
0
      };
5795
0
      AddError(message_name, field, DescriptorPool::ErrorCollector::NAME,
5796
0
               make_error);
5797
0
      continue;
5798
0
    }
5799
0
    auto it_inserted = name_to_field.try_emplace(details.orig_name, details);
5800
0
    if (it_inserted.second) {
5801
0
      continue;
5802
0
    }
5803
0
    JsonNameDetails& match = it_inserted.first->second;
5804
0
    if (use_custom_names && !details.is_custom && !match.is_custom) {
5805
      // if this pass is considering custom JSON names, but neither of the
5806
      // names involved in the conflict are custom, don't bother with a
5807
      // message. That will have been reported from other pass (non-custom
5808
      // JSON names).
5809
0
      continue;
5810
0
    }
5811
0
    auto make_error = [&] {
5812
0
      absl::string_view this_type = details.is_custom ? "custom" : "default";
5813
0
      absl::string_view existing_type = match.is_custom ? "custom" : "default";
5814
      // If the matched name differs (which it can only differ in case), include
5815
      // it in the error message, for maximum clarity to user.
5816
0
      std::string name_suffix = "";
5817
0
      if (details.orig_name != match.orig_name) {
5818
0
        name_suffix = absl::StrCat(" (\"", match.orig_name, "\")");
5819
0
      }
5820
0
      return absl::StrFormat(
5821
0
          "The %s JSON name of field \"%s\" (\"%s\") conflicts "
5822
0
          "with the %s JSON name of field \"%s\"%s.",
5823
0
          this_type, field.name(), details.orig_name, existing_type,
5824
0
          match.field->name(), name_suffix);
5825
0
    };
5826
5827
0
    bool involves_default = !details.is_custom || !match.is_custom;
5828
0
    if (syntax == FileDescriptorLegacy::SYNTAX_PROTO2 && involves_default) {
5829
      // TODO(b/261750676) Upgrade this to an error once downstream protos have
5830
      // been fixed.
5831
0
      AddWarning(message_name, field, DescriptorPool::ErrorCollector::NAME,
5832
0
                 make_error);
5833
0
    } else {
5834
0
      AddError(message_name, field, DescriptorPool::ErrorCollector::NAME,
5835
0
               make_error);
5836
0
    }
5837
0
  }
5838
0
}
5839
5840
void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
5841
                                              Descriptor* parent,
5842
                                              FieldDescriptor* result,
5843
                                              bool is_extension,
5844
0
                                              internal::FlatAllocator& alloc) {
5845
0
  const std::string& scope =
5846
0
      (parent == nullptr) ? file_->package() : parent->full_name();
5847
5848
  // We allocate all names in a single array, and dedup them.
5849
  // We remember the indices for the potentially deduped values.
5850
0
  auto all_names = alloc.AllocateFieldNames(
5851
0
      proto.name(), scope,
5852
0
      proto.has_json_name() ? &proto.json_name() : nullptr);
5853
0
  result->all_names_ = all_names.array;
5854
0
  result->lowercase_name_index_ = all_names.lowercase_index;
5855
0
  result->camelcase_name_index_ = all_names.camelcase_index;
5856
0
  result->json_name_index_ = all_names.json_index;
5857
5858
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
5859
5860
0
  result->file_ = file_;
5861
0
  result->number_ = proto.number();
5862
0
  result->is_extension_ = is_extension;
5863
0
  result->is_oneof_ = false;
5864
0
  result->proto3_optional_ = proto.proto3_optional();
5865
5866
0
  if (proto.proto3_optional() &&
5867
0
      FileDescriptorLegacy(file_).syntax() !=
5868
0
          FileDescriptorLegacy::Syntax::SYNTAX_PROTO3) {
5869
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5870
0
             [&] {
5871
0
               return absl::StrCat(
5872
0
                   "The [proto3_optional=true] option may only be set on proto3"
5873
0
                   "fields, not ",
5874
0
                   result->full_name());
5875
0
             });
5876
0
  }
5877
5878
0
  result->has_json_name_ = proto.has_json_name();
5879
5880
  // Some compilers do not allow static_cast directly between two enum types,
5881
  // so we must cast to int first.
5882
0
  result->type_ = static_cast<FieldDescriptor::Type>(
5883
0
      absl::implicit_cast<int>(proto.type()));
5884
0
  result->label_ = static_cast<FieldDescriptor::Label>(
5885
0
      absl::implicit_cast<int>(proto.label()));
5886
5887
0
  if (result->label_ == FieldDescriptor::LABEL_REQUIRED) {
5888
    // An extension cannot have a required field (b/13365836).
5889
0
    if (result->is_extension_) {
5890
0
      AddError(result->full_name(), proto,
5891
               // Error location `TYPE`: we would really like to indicate
5892
               // `LABEL`, but the `ErrorLocation` enum has no entry for this,
5893
               // and we don't necessarily know about all implementations of the
5894
               // `ErrorCollector` interface to extend them to handle the new
5895
               // error location type properly.
5896
0
               DescriptorPool::ErrorCollector::TYPE, [&] {
5897
0
                 return absl::StrCat("The extension ", result->full_name(),
5898
0
                                     " cannot be required.");
5899
0
               });
5900
0
    }
5901
0
  }
5902
5903
  // Some of these may be filled in when cross-linking.
5904
0
  result->containing_type_ = nullptr;
5905
0
  result->type_once_ = nullptr;
5906
0
  result->default_value_enum_ = nullptr;
5907
5908
0
  result->has_default_value_ = proto.has_default_value();
5909
0
  if (proto.has_default_value() && result->is_repeated()) {
5910
0
    AddError(result->full_name(), proto,
5911
0
             DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5912
0
             "Repeated fields can't have default values.");
5913
0
  }
5914
5915
0
  if (proto.has_type()) {
5916
0
    if (proto.has_default_value()) {
5917
0
      char* end_pos = nullptr;
5918
0
      switch (result->cpp_type()) {
5919
0
        case FieldDescriptor::CPPTYPE_INT32:
5920
0
          result->default_value_int32_t_ =
5921
0
              std::strtol(proto.default_value().c_str(), &end_pos, 0);
5922
0
          break;
5923
0
        case FieldDescriptor::CPPTYPE_INT64:
5924
0
          static_assert(sizeof(int64_t) == sizeof(long long),
5925
0
                        "sizeof int64_t is not sizeof long long");
5926
0
          result->default_value_int64_t_ =
5927
0
              std::strtoll(proto.default_value().c_str(), &end_pos, 0);
5928
0
          break;
5929
0
        case FieldDescriptor::CPPTYPE_UINT32:
5930
0
          result->default_value_uint32_t_ =
5931
0
              std::strtoul(proto.default_value().c_str(), &end_pos, 0);
5932
0
          break;
5933
0
        case FieldDescriptor::CPPTYPE_UINT64:
5934
0
          static_assert(sizeof(uint64_t) == sizeof(unsigned long long),
5935
0
                        "sizeof uint64_t is not sizeof unsigned long long");
5936
0
          result->default_value_uint64_t_ =
5937
0
              std::strtoull(proto.default_value().c_str(), &end_pos, 0);
5938
0
          break;
5939
0
        case FieldDescriptor::CPPTYPE_FLOAT:
5940
0
          if (proto.default_value() == "inf") {
5941
0
            result->default_value_float_ =
5942
0
                std::numeric_limits<float>::infinity();
5943
0
          } else if (proto.default_value() == "-inf") {
5944
0
            result->default_value_float_ =
5945
0
                -std::numeric_limits<float>::infinity();
5946
0
          } else if (proto.default_value() == "nan") {
5947
0
            result->default_value_float_ =
5948
0
                std::numeric_limits<float>::quiet_NaN();
5949
0
          } else {
5950
0
            result->default_value_float_ = io::SafeDoubleToFloat(
5951
0
                io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos));
5952
0
          }
5953
0
          break;
5954
0
        case FieldDescriptor::CPPTYPE_DOUBLE:
5955
0
          if (proto.default_value() == "inf") {
5956
0
            result->default_value_double_ =
5957
0
                std::numeric_limits<double>::infinity();
5958
0
          } else if (proto.default_value() == "-inf") {
5959
0
            result->default_value_double_ =
5960
0
                -std::numeric_limits<double>::infinity();
5961
0
          } else if (proto.default_value() == "nan") {
5962
0
            result->default_value_double_ =
5963
0
                std::numeric_limits<double>::quiet_NaN();
5964
0
          } else {
5965
0
            result->default_value_double_ =
5966
0
                io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
5967
0
          }
5968
0
          break;
5969
0
        case FieldDescriptor::CPPTYPE_BOOL:
5970
0
          if (proto.default_value() == "true") {
5971
0
            result->default_value_bool_ = true;
5972
0
          } else if (proto.default_value() == "false") {
5973
0
            result->default_value_bool_ = false;
5974
0
          } else {
5975
0
            AddError(result->full_name(), proto,
5976
0
                     DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5977
0
                     "Boolean default must be true or false.");
5978
0
          }
5979
0
          break;
5980
0
        case FieldDescriptor::CPPTYPE_ENUM:
5981
          // This will be filled in when cross-linking.
5982
0
          result->default_value_enum_ = nullptr;
5983
0
          break;
5984
0
        case FieldDescriptor::CPPTYPE_STRING:
5985
0
          if (result->type() == FieldDescriptor::TYPE_BYTES) {
5986
0
            std::string value;
5987
0
            if (absl::CUnescape(proto.default_value(), &value)) {
5988
0
              result->default_value_string_ = alloc.AllocateStrings(value);
5989
0
            } else {
5990
0
              AddError(result->full_name(), proto,
5991
0
                       DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5992
0
                       "Invalid escaping in default value.");
5993
0
            }
5994
0
          } else {
5995
0
            result->default_value_string_ =
5996
0
                alloc.AllocateStrings(proto.default_value());
5997
0
          }
5998
0
          break;
5999
0
        case FieldDescriptor::CPPTYPE_MESSAGE:
6000
0
          AddError(result->full_name(), proto,
6001
0
                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
6002
0
                   "Messages can't have default values.");
6003
0
          result->has_default_value_ = false;
6004
0
          result->default_generated_instance_ = nullptr;
6005
0
          break;
6006
0
      }
6007
6008
0
      if (end_pos != nullptr) {
6009
        // end_pos is only set non-null by the parsers for numeric types,
6010
        // above. This checks that the default was non-empty and had no extra
6011
        // junk after the end of the number.
6012
0
        if (proto.default_value().empty() || *end_pos != '\0') {
6013
0
          AddError(result->full_name(), proto,
6014
0
                   DescriptorPool::ErrorCollector::DEFAULT_VALUE, [&] {
6015
0
                     return absl::StrCat("Couldn't parse default value \"",
6016
0
                                         proto.default_value(), "\".");
6017
0
                   });
6018
0
        }
6019
0
      }
6020
0
    } else {
6021
      // No explicit default value
6022
0
      switch (result->cpp_type()) {
6023
0
        case FieldDescriptor::CPPTYPE_INT32:
6024
0
          result->default_value_int32_t_ = 0;
6025
0
          break;
6026
0
        case FieldDescriptor::CPPTYPE_INT64:
6027
0
          result->default_value_int64_t_ = 0;
6028
0
          break;
6029
0
        case FieldDescriptor::CPPTYPE_UINT32:
6030
0
          result->default_value_uint32_t_ = 0;
6031
0
          break;
6032
0
        case FieldDescriptor::CPPTYPE_UINT64:
6033
0
          result->default_value_uint64_t_ = 0;
6034
0
          break;
6035
0
        case FieldDescriptor::CPPTYPE_FLOAT:
6036
0
          result->default_value_float_ = 0.0f;
6037
0
          break;
6038
0
        case FieldDescriptor::CPPTYPE_DOUBLE:
6039
0
          result->default_value_double_ = 0.0;
6040
0
          break;
6041
0
        case FieldDescriptor::CPPTYPE_BOOL:
6042
0
          result->default_value_bool_ = false;
6043
0
          break;
6044
0
        case FieldDescriptor::CPPTYPE_ENUM:
6045
          // This will be filled in when cross-linking.
6046
0
          result->default_value_enum_ = nullptr;
6047
0
          break;
6048
0
        case FieldDescriptor::CPPTYPE_STRING:
6049
0
          result->default_value_string_ = &internal::GetEmptyString();
6050
0
          break;
6051
0
        case FieldDescriptor::CPPTYPE_MESSAGE:
6052
0
          result->default_generated_instance_ = nullptr;
6053
0
          break;
6054
0
      }
6055
0
    }
6056
0
  }
6057
6058
0
  if (result->number() <= 0) {
6059
0
    message_hints_[parent].RequestHintOnFieldNumbers(
6060
0
        proto, DescriptorPool::ErrorCollector::NUMBER);
6061
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6062
0
             "Field numbers must be positive integers.");
6063
0
  } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) {
6064
    // Only validate that the number is within the valid field range if it is
6065
    // not an extension. Since extension numbers are validated with the
6066
    // extendee's valid set of extension numbers, and those are in turn
6067
    // validated against the max allowed number, the check is unnecessary for
6068
    // extension fields.
6069
    // This avoids cross-linking issues that arise when attempting to check if
6070
    // the extendee is a message_set_wire_format message, which has a higher max
6071
    // on extension numbers.
6072
0
    message_hints_[parent].RequestHintOnFieldNumbers(
6073
0
        proto, DescriptorPool::ErrorCollector::NUMBER);
6074
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6075
0
             [&] {
6076
0
               return absl::Substitute(
6077
0
                   "Field numbers cannot be greater than $0.",
6078
0
                   FieldDescriptor::kMaxNumber);
6079
0
             });
6080
0
  }
6081
6082
0
  if (is_extension) {
6083
0
    if (!proto.has_extendee()) {
6084
0
      AddError(result->full_name(), proto,
6085
0
               DescriptorPool::ErrorCollector::EXTENDEE,
6086
0
               "FieldDescriptorProto.extendee not set for extension field.");
6087
0
    }
6088
6089
0
    result->scope_.extension_scope = parent;
6090
6091
0
    if (proto.has_oneof_index()) {
6092
0
      AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6093
0
               "FieldDescriptorProto.oneof_index should not be set for "
6094
0
               "extensions.");
6095
0
    }
6096
0
  } else {
6097
0
    if (proto.has_extendee()) {
6098
0
      AddError(result->full_name(), proto,
6099
0
               DescriptorPool::ErrorCollector::EXTENDEE,
6100
0
               "FieldDescriptorProto.extendee set for non-extension field.");
6101
0
    }
6102
6103
0
    result->containing_type_ = parent;
6104
6105
0
    if (proto.has_oneof_index()) {
6106
0
      if (proto.oneof_index() < 0 ||
6107
0
          proto.oneof_index() >= parent->oneof_decl_count()) {
6108
0
        AddError(result->full_name(), proto,
6109
0
                 DescriptorPool::ErrorCollector::TYPE, [&] {
6110
0
                   return absl::Substitute(
6111
0
                       "FieldDescriptorProto.oneof_index $0 is "
6112
0
                       "out of range for type \"$1\".",
6113
0
                       proto.oneof_index(), parent->name());
6114
0
                 });
6115
0
      } else {
6116
0
        result->is_oneof_ = true;
6117
0
        result->scope_.containing_oneof =
6118
0
            parent->oneof_decl(proto.oneof_index());
6119
0
      }
6120
0
    }
6121
0
  }
6122
6123
  // Copy options.
6124
0
  AllocateOptions(proto, result, FieldDescriptorProto::kOptionsFieldNumber,
6125
0
                  "google.protobuf.FieldOptions", alloc);
6126
6127
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6128
0
}
6129
6130
void DescriptorBuilder::BuildExtensionRange(
6131
    const DescriptorProto::ExtensionRange& proto, const Descriptor* parent,
6132
0
    Descriptor::ExtensionRange* result, internal::FlatAllocator& alloc) {
6133
0
  result->start_ = proto.start();
6134
0
  result->end_ = proto.end();
6135
0
  result->containing_type_ = parent;
6136
6137
0
  if (result->start_number() <= 0) {
6138
0
    message_hints_[parent].RequestHintOnFieldNumbers(
6139
0
        proto, DescriptorPool::ErrorCollector::NUMBER, result->start_number(),
6140
0
        result->end_number());
6141
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6142
0
             "Extension numbers must be positive integers.");
6143
0
  }
6144
6145
  // Checking of the upper bound of the extension range is deferred until after
6146
  // options interpreting. This allows messages with message_set_wire_format to
6147
  // have extensions beyond FieldDescriptor::kMaxNumber, since the extension
6148
  // numbers are actually used as int32s in the message_set_wire_format.
6149
6150
0
  if (result->start_number() >= result->end_number()) {
6151
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6152
0
             "Extension range end number must be greater than start number.");
6153
0
  }
6154
6155
  // Copy options
6156
0
  AllocateOptions(proto, result,
6157
0
                  DescriptorProto_ExtensionRange::kOptionsFieldNumber,
6158
0
                  "google.protobuf.ExtensionRangeOptions", alloc);
6159
0
}
6160
6161
void DescriptorBuilder::BuildReservedRange(
6162
    const DescriptorProto::ReservedRange& proto, const Descriptor* parent,
6163
0
    Descriptor::ReservedRange* result, internal::FlatAllocator&) {
6164
0
  result->start = proto.start();
6165
0
  result->end = proto.end();
6166
0
  if (result->start <= 0) {
6167
0
    message_hints_[parent].RequestHintOnFieldNumbers(
6168
0
        proto, DescriptorPool::ErrorCollector::NUMBER, result->start,
6169
0
        result->end);
6170
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6171
0
             "Reserved numbers must be positive integers.");
6172
0
  }
6173
0
}
6174
6175
void DescriptorBuilder::BuildReservedRange(
6176
    const EnumDescriptorProto::EnumReservedRange& proto,
6177
    const EnumDescriptor* parent, EnumDescriptor::ReservedRange* result,
6178
0
    internal::FlatAllocator&) {
6179
0
  result->start = proto.start();
6180
0
  result->end = proto.end();
6181
6182
0
  if (result->start > result->end) {
6183
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6184
0
             "Reserved range end number must be greater than start number.");
6185
0
  }
6186
0
}
6187
6188
void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
6189
                                   Descriptor* parent, OneofDescriptor* result,
6190
0
                                   internal::FlatAllocator& alloc) {
6191
0
  result->all_names_ =
6192
0
      AllocateNameStrings(parent->full_name(), proto.name(), alloc);
6193
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6194
6195
0
  result->containing_type_ = parent;
6196
6197
  // We need to fill these in later.
6198
0
  result->field_count_ = 0;
6199
0
  result->fields_ = nullptr;
6200
6201
  // Copy options.
6202
0
  AllocateOptions(proto, result, OneofDescriptorProto::kOptionsFieldNumber,
6203
0
                  "google.protobuf.OneofOptions", alloc);
6204
6205
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6206
0
}
6207
6208
void DescriptorBuilder::CheckEnumValueUniqueness(
6209
0
    const EnumDescriptorProto& proto, const EnumDescriptor* result) {
6210
6211
  // Check that enum labels are still unique when we remove the enum prefix from
6212
  // values that have it.
6213
  //
6214
  // This will fail for something like:
6215
  //
6216
  //   enum MyEnum {
6217
  //     MY_ENUM_FOO = 0;
6218
  //     FOO = 1;
6219
  //   }
6220
  //
6221
  // By enforcing this reasonable constraint, we allow code generators to strip
6222
  // the prefix and/or PascalCase it without creating conflicts.  This can lead
6223
  // to much nicer language-specific enums like:
6224
  //
6225
  //   enum NameType {
6226
  //     FirstName = 1,
6227
  //     LastName = 2,
6228
  //   }
6229
  //
6230
  // Instead of:
6231
  //
6232
  //   enum NameType {
6233
  //     NAME_TYPE_FIRST_NAME = 1,
6234
  //     NAME_TYPE_LAST_NAME = 2,
6235
  //   }
6236
0
  PrefixRemover remover(result->name());
6237
0
  absl::flat_hash_map<std::string, const EnumValueDescriptor*> values;
6238
0
  for (int i = 0; i < result->value_count(); i++) {
6239
0
    const EnumValueDescriptor* value = result->value(i);
6240
0
    std::string stripped =
6241
0
        EnumValueToPascalCase(remover.MaybeRemove(value->name()));
6242
0
    auto insert_result = values.try_emplace(stripped, value);
6243
0
    bool inserted = insert_result.second;
6244
6245
    // We don't throw the error if the two conflicting symbols are identical, or
6246
    // if they map to the same number.  In the former case, the normal symbol
6247
    // duplication error will fire so we don't need to (and its error message
6248
    // will make more sense). We allow the latter case so users can create
6249
    // aliases which add or remove the prefix (code generators that do prefix
6250
    // stripping should de-dup the labels in this case).
6251
0
    if (!inserted && insert_result.first->second->name() != value->name() &&
6252
0
        insert_result.first->second->number() != value->number()) {
6253
0
      auto make_error = [&] {
6254
0
        return absl::StrFormat(
6255
0
            "Enum name %s has the same name as %s if you ignore case and strip "
6256
0
            "out the enum name prefix (if any). (If you are using allow_alias, "
6257
0
            "please assign the same numeric value to both enums.)",
6258
0
            value->name(), insert_result.first->second->name());
6259
0
      };
6260
      // There are proto2 enums out there with conflicting names, so to preserve
6261
      // compatibility we issue only a warning for proto2.
6262
0
      if ((pool_->deprecated_legacy_json_field_conflicts_ ||
6263
0
           IsLegacyJsonFieldConflictEnabled(result->options())) &&
6264
0
          FileDescriptorLegacy(result->file()).syntax() ==
6265
0
              FileDescriptorLegacy::Syntax::SYNTAX_PROTO2) {
6266
0
        AddWarning(value->full_name(), proto.value(i),
6267
0
                   DescriptorPool::ErrorCollector::NAME, make_error);
6268
0
        continue;
6269
0
      }
6270
0
      AddError(value->full_name(), proto.value(i),
6271
0
               DescriptorPool::ErrorCollector::NAME, make_error);
6272
0
    }
6273
0
  }
6274
0
}
6275
6276
void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
6277
                                  const Descriptor* parent,
6278
                                  EnumDescriptor* result,
6279
0
                                  internal::FlatAllocator& alloc) {
6280
0
  const std::string& scope =
6281
0
      (parent == nullptr) ? file_->package() : parent->full_name();
6282
6283
0
  result->all_names_ = AllocateNameStrings(scope, proto.name(), alloc);
6284
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6285
0
  result->file_ = file_;
6286
0
  result->containing_type_ = parent;
6287
0
  result->is_placeholder_ = false;
6288
0
  result->is_unqualified_placeholder_ = false;
6289
6290
0
  if (proto.value_size() == 0) {
6291
    // We cannot allow enums with no values because this would mean there
6292
    // would be no valid default value for fields of this type.
6293
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6294
0
             "Enums must contain at least one value.");
6295
0
  }
6296
6297
  // Calculate the continuous sequence of the labels.
6298
  // These can be fast-path'd during lookup and don't need to be added to the
6299
  // tables.
6300
  // We use uint16_t to save space for sequential_value_limit_, so stop before
6301
  // overflowing it. Worst case, we are not taking full advantage on huge
6302
  // enums, but it is unlikely.
6303
0
  for (int i = 0;
6304
0
       i < std::numeric_limits<uint16_t>::max() && i < proto.value_size() &&
6305
       // We do the math in int64_t to avoid overflows.
6306
0
       proto.value(i).number() ==
6307
0
           static_cast<int64_t>(i) + proto.value(0).number();
6308
0
       ++i) {
6309
0
    result->sequential_value_limit_ = i;
6310
0
  }
6311
6312
0
  BUILD_ARRAY(proto, result, value, BuildEnumValue, result);
6313
0
  BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);
6314
6315
  // Copy reserved names.
6316
0
  int reserved_name_count = proto.reserved_name_size();
6317
0
  result->reserved_name_count_ = reserved_name_count;
6318
0
  result->reserved_names_ =
6319
0
      alloc.AllocateArray<const std::string*>(reserved_name_count);
6320
0
  for (int i = 0; i < reserved_name_count; ++i) {
6321
0
    result->reserved_names_[i] =
6322
0
        alloc.AllocateStrings(proto.reserved_name(i));
6323
0
  }
6324
6325
  // Copy options.
6326
0
  AllocateOptions(proto, result, EnumDescriptorProto::kOptionsFieldNumber,
6327
0
                  "google.protobuf.EnumOptions", alloc);
6328
6329
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6330
6331
0
  for (int i = 0; i < proto.reserved_range_size(); i++) {
6332
0
    const EnumDescriptorProto_EnumReservedRange& range1 =
6333
0
        proto.reserved_range(i);
6334
0
    for (int j = i + 1; j < proto.reserved_range_size(); j++) {
6335
0
      const EnumDescriptorProto_EnumReservedRange& range2 =
6336
0
          proto.reserved_range(j);
6337
0
      if (range1.end() >= range2.start() && range2.end() >= range1.start()) {
6338
0
        AddError(result->full_name(), proto.reserved_range(i),
6339
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
6340
0
                   return absl::Substitute(
6341
0
                       "Reserved range $0 to $1 overlaps with "
6342
0
                       "already-defined range $2 to $3.",
6343
0
                       range2.start(), range2.end(), range1.start(),
6344
0
                       range1.end());
6345
0
                 });
6346
0
      }
6347
0
    }
6348
0
  }
6349
6350
0
  absl::flat_hash_set<absl::string_view> reserved_name_set;
6351
0
  for (const std::string& name : proto.reserved_name()) {
6352
0
    if (!reserved_name_set.insert(name).second) {
6353
0
      AddError(name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
6354
0
        return absl::Substitute("Enum value \"$0\" is reserved multiple times.",
6355
0
                                name);
6356
0
      });
6357
0
    }
6358
0
  }
6359
6360
0
  for (int i = 0; i < result->value_count(); i++) {
6361
0
    const EnumValueDescriptor* value = result->value(i);
6362
0
    for (int j = 0; j < result->reserved_range_count(); j++) {
6363
0
      const EnumDescriptor::ReservedRange* range = result->reserved_range(j);
6364
0
      if (range->start <= value->number() && value->number() <= range->end) {
6365
0
        AddError(value->full_name(), proto.reserved_range(j),
6366
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
6367
0
                   return absl::Substitute(
6368
0
                       "Enum value \"$0\" uses reserved number $1.",
6369
0
                       value->name(), value->number());
6370
0
                 });
6371
0
      }
6372
0
    }
6373
0
    if (reserved_name_set.contains(value->name())) {
6374
0
      AddError(value->full_name(), proto.value(i),
6375
0
               DescriptorPool::ErrorCollector::NAME, [&] {
6376
0
                 return absl::Substitute("Enum value \"$0\" is reserved.",
6377
0
                                         value->name());
6378
0
               });
6379
0
    }
6380
0
  }
6381
0
}
6382
6383
void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto,
6384
                                       const EnumDescriptor* parent,
6385
                                       EnumValueDescriptor* result,
6386
0
                                       internal::FlatAllocator& alloc) {
6387
  // Note:  full_name for enum values is a sibling to the parent's name, not a
6388
  //   child of it.
6389
0
  std::string full_name;
6390
0
  size_t scope_len = parent->full_name().size() - parent->name().size();
6391
0
  full_name.reserve(scope_len + proto.name().size());
6392
0
  full_name.append(parent->full_name().data(), scope_len);
6393
0
  full_name.append(proto.name());
6394
6395
0
  result->all_names_ =
6396
0
      alloc.AllocateStrings(proto.name(), std::move(full_name));
6397
0
  result->number_ = proto.number();
6398
0
  result->type_ = parent;
6399
6400
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6401
6402
  // Copy options.
6403
0
  AllocateOptions(proto, result, EnumValueDescriptorProto::kOptionsFieldNumber,
6404
0
                  "google.protobuf.EnumValueOptions", alloc);
6405
6406
  // Again, enum values are weird because we makes them appear as siblings
6407
  // of the enum type instead of children of it.  So, we use
6408
  // parent->containing_type() as the value's parent.
6409
0
  bool added_to_outer_scope =
6410
0
      AddSymbol(result->full_name(), parent->containing_type(), result->name(),
6411
0
                proto, Symbol::EnumValue(result, 0));
6412
6413
  // However, we also want to be able to search for values within a single
6414
  // enum type, so we add it as a child of the enum type itself, too.
6415
  // Note:  This could fail, but if it does, the error has already been
6416
  //   reported by the above AddSymbol() call, so we ignore the return code.
6417
0
  bool added_to_inner_scope = file_tables_->AddAliasUnderParent(
6418
0
      parent, result->name(), Symbol::EnumValue(result, 1));
6419
6420
0
  if (added_to_inner_scope && !added_to_outer_scope) {
6421
    // This value did not conflict with any values defined in the same enum,
6422
    // but it did conflict with some other symbol defined in the enum type's
6423
    // scope.  Let's print an additional error to explain this.
6424
0
    std::string outer_scope;
6425
0
    if (parent->containing_type() == nullptr) {
6426
0
      outer_scope = file_->package();
6427
0
    } else {
6428
0
      outer_scope = parent->containing_type()->full_name();
6429
0
    }
6430
6431
0
    if (outer_scope.empty()) {
6432
0
      outer_scope = "the global scope";
6433
0
    } else {
6434
0
      outer_scope = absl::StrCat("\"", outer_scope, "\"");
6435
0
    }
6436
6437
0
    AddError(
6438
0
        result->full_name(), proto, DescriptorPool::ErrorCollector::NAME, [&] {
6439
0
          return absl::StrCat(
6440
0
              "Note that enum values use C++ scoping rules, meaning that "
6441
0
              "enum values are siblings of their type, not children of it.  "
6442
0
              "Therefore, \"",
6443
0
              result->name(), "\" must be unique within ", outer_scope,
6444
0
              ", not just within \"", parent->name(), "\".");
6445
0
        });
6446
0
  }
6447
6448
  // An enum is allowed to define two numbers that refer to the same value.
6449
  // FindValueByNumber() should return the first such value, so we simply
6450
  // ignore AddEnumValueByNumber()'s return code.
6451
0
  file_tables_->AddEnumValueByNumber(result);
6452
0
}
6453
6454
void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
6455
                                     const void* /* dummy */,
6456
                                     ServiceDescriptor* result,
6457
0
                                     internal::FlatAllocator& alloc) {
6458
0
  result->all_names_ =
6459
0
      AllocateNameStrings(file_->package(), proto.name(), alloc);
6460
0
  result->file_ = file_;
6461
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6462
6463
0
  BUILD_ARRAY(proto, result, method, BuildMethod, result);
6464
6465
  // Copy options.
6466
0
  AllocateOptions(proto, result, ServiceDescriptorProto::kOptionsFieldNumber,
6467
0
                  "google.protobuf.ServiceOptions", alloc);
6468
6469
0
  AddSymbol(result->full_name(), nullptr, result->name(), proto,
6470
0
            Symbol(result));
6471
0
}
6472
6473
void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto,
6474
                                    const ServiceDescriptor* parent,
6475
                                    MethodDescriptor* result,
6476
0
                                    internal::FlatAllocator& alloc) {
6477
0
  result->service_ = parent;
6478
0
  result->all_names_ =
6479
0
      AllocateNameStrings(parent->full_name(), proto.name(), alloc);
6480
6481
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6482
6483
  // These will be filled in when cross-linking.
6484
0
  result->input_type_.Init();
6485
0
  result->output_type_.Init();
6486
6487
  // Copy options.
6488
0
  AllocateOptions(proto, result, MethodDescriptorProto::kOptionsFieldNumber,
6489
0
                  "google.protobuf.MethodOptions", alloc);
6490
6491
0
  result->client_streaming_ = proto.client_streaming();
6492
0
  result->server_streaming_ = proto.server_streaming();
6493
6494
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6495
0
}
6496
6497
#undef BUILD_ARRAY
6498
6499
// -------------------------------------------------------------------
6500
6501
void DescriptorBuilder::CrossLinkFile(FileDescriptor* file,
6502
0
                                      const FileDescriptorProto& proto) {
6503
0
  if (file->options_ == nullptr) {
6504
0
    file->options_ = &FileOptions::default_instance();
6505
0
  }
6506
6507
0
  for (int i = 0; i < file->message_type_count(); i++) {
6508
0
    CrossLinkMessage(&file->message_types_[i], proto.message_type(i));
6509
0
  }
6510
6511
0
  for (int i = 0; i < file->extension_count(); i++) {
6512
0
    CrossLinkField(&file->extensions_[i], proto.extension(i));
6513
0
  }
6514
6515
0
  for (int i = 0; i < file->enum_type_count(); i++) {
6516
0
    CrossLinkEnum(&file->enum_types_[i], proto.enum_type(i));
6517
0
  }
6518
6519
0
  for (int i = 0; i < file->service_count(); i++) {
6520
0
    CrossLinkService(&file->services_[i], proto.service(i));
6521
0
  }
6522
0
}
6523
6524
void DescriptorBuilder::CrossLinkMessage(Descriptor* message,
6525
0
                                         const DescriptorProto& proto) {
6526
0
  if (message->options_ == nullptr) {
6527
0
    message->options_ = &MessageOptions::default_instance();
6528
0
  }
6529
6530
0
  for (int i = 0; i < message->nested_type_count(); i++) {
6531
0
    CrossLinkMessage(&message->nested_types_[i], proto.nested_type(i));
6532
0
  }
6533
6534
0
  for (int i = 0; i < message->enum_type_count(); i++) {
6535
0
    CrossLinkEnum(&message->enum_types_[i], proto.enum_type(i));
6536
0
  }
6537
6538
0
  for (int i = 0; i < message->field_count(); i++) {
6539
0
    CrossLinkField(&message->fields_[i], proto.field(i));
6540
0
  }
6541
6542
0
  for (int i = 0; i < message->extension_count(); i++) {
6543
0
    CrossLinkField(&message->extensions_[i], proto.extension(i));
6544
0
  }
6545
6546
0
  for (int i = 0; i < message->extension_range_count(); i++) {
6547
0
    CrossLinkExtensionRange(&message->extension_ranges_[i],
6548
0
                            proto.extension_range(i));
6549
0
  }
6550
6551
  // Set up field array for each oneof.
6552
6553
  // First count the number of fields per oneof.
6554
0
  for (int i = 0; i < message->field_count(); i++) {
6555
0
    const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
6556
0
    if (oneof_decl != nullptr) {
6557
      // Make sure fields belonging to the same oneof are defined consecutively.
6558
      // This enables optimizations in codegens and reflection libraries to
6559
      // skip fields in the oneof group, as only one of the field can be set.
6560
      // Note that field_count() returns how many fields in this oneof we have
6561
      // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is
6562
      // safe.
6563
0
      if (oneof_decl->field_count() > 0 &&
6564
0
          message->field(i - 1)->containing_oneof() != oneof_decl) {
6565
0
        AddError(
6566
0
            absl::StrCat(message->full_name(), ".",
6567
0
                         message->field(i - 1)->name()),
6568
0
            proto.field(i - 1), DescriptorPool::ErrorCollector::TYPE, [&] {
6569
0
              return absl::Substitute(
6570
0
                  "Fields in the same oneof must be defined consecutively. "
6571
0
                  "\"$0\" cannot be defined before the completion of the "
6572
0
                  "\"$1\" oneof definition.",
6573
0
                  message->field(i - 1)->name(), oneof_decl->name());
6574
0
            });
6575
0
      }
6576
      // Must go through oneof_decls_ array to get a non-const version of the
6577
      // OneofDescriptor.
6578
0
      auto& out_oneof_decl = message->oneof_decls_[oneof_decl->index()];
6579
0
      if (out_oneof_decl.field_count_ == 0) {
6580
0
        out_oneof_decl.fields_ = message->field(i);
6581
0
      }
6582
6583
0
      if (!had_errors_) {
6584
        // Verify that they are contiguous.
6585
        // This is assumed by OneofDescriptor::field(i).
6586
        // But only if there are no errors.
6587
0
        ABSL_CHECK_EQ(out_oneof_decl.fields_ + out_oneof_decl.field_count_,
6588
0
                      message->field(i));
6589
0
      }
6590
0
      ++out_oneof_decl.field_count_;
6591
0
    }
6592
0
  }
6593
6594
  // Then verify the sizes.
6595
0
  for (int i = 0; i < message->oneof_decl_count(); i++) {
6596
0
    OneofDescriptor* oneof_decl = &message->oneof_decls_[i];
6597
6598
0
    if (oneof_decl->field_count() == 0) {
6599
0
      AddError(absl::StrCat(message->full_name(), ".", oneof_decl->name()),
6600
0
               proto.oneof_decl(i), DescriptorPool::ErrorCollector::NAME,
6601
0
               "Oneof must have at least one field.");
6602
0
    }
6603
6604
0
    if (oneof_decl->options_ == nullptr) {
6605
0
      oneof_decl->options_ = &OneofOptions::default_instance();
6606
0
    }
6607
0
  }
6608
6609
0
  for (int i = 0; i < message->field_count(); i++) {
6610
0
    const FieldDescriptor* field = message->field(i);
6611
0
    if (field->proto3_optional_) {
6612
0
      if (!field->containing_oneof() ||
6613
0
          !OneofDescriptorLegacy(field->containing_oneof()).is_synthetic()) {
6614
0
        AddError(message->full_name(), proto.field(i),
6615
0
                 DescriptorPool::ErrorCollector::OTHER,
6616
0
                 "Fields with proto3_optional set must be "
6617
0
                 "a member of a one-field oneof");
6618
0
      }
6619
0
    }
6620
0
  }
6621
6622
  // Synthetic oneofs must be last.
6623
0
  int first_synthetic = -1;
6624
0
  for (int i = 0; i < message->oneof_decl_count(); i++) {
6625
0
    const OneofDescriptor* oneof = message->oneof_decl(i);
6626
0
    if (OneofDescriptorLegacy(oneof).is_synthetic()) {
6627
0
      if (first_synthetic == -1) {
6628
0
        first_synthetic = i;
6629
0
      }
6630
0
    } else {
6631
0
      if (first_synthetic != -1) {
6632
0
        AddError(message->full_name(), proto.oneof_decl(i),
6633
0
                 DescriptorPool::ErrorCollector::OTHER,
6634
0
                 "Synthetic oneofs must be after all other oneofs");
6635
0
      }
6636
0
    }
6637
0
  }
6638
6639
0
  if (first_synthetic == -1) {
6640
0
    message->real_oneof_decl_count_ = message->oneof_decl_count_;
6641
0
  } else {
6642
0
    message->real_oneof_decl_count_ = first_synthetic;
6643
0
  }
6644
0
}
6645
6646
void DescriptorBuilder::CrossLinkExtensionRange(
6647
    Descriptor::ExtensionRange* range,
6648
0
    const DescriptorProto::ExtensionRange& /*proto*/) {
6649
0
  if (range->options_ == nullptr) {
6650
0
    range->options_ = &ExtensionRangeOptions::default_instance();
6651
0
  }
6652
0
}
6653
6654
6655
void DescriptorBuilder::CheckExtensionDeclaration(
6656
    const FieldDescriptor& field, const FieldDescriptorProto& proto,
6657
    absl::string_view declared_full_name, absl::string_view declared_type_name,
6658
0
    bool is_repeated) {
6659
6660
0
  if (!declared_full_name.empty()) {
6661
0
    std::string actual_full_name = absl::StrCat(".", field.full_name());
6662
0
    if (declared_full_name != actual_full_name) {
6663
0
      AddError(field.full_name(), proto,
6664
0
               DescriptorPool::ErrorCollector::EXTENDEE, [&] {
6665
0
                 return absl::Substitute(
6666
0
                     "\"$0\" extension field $1 is expected to have field name "
6667
0
                     "\"$2\", not \"$3\".",
6668
0
                     field.containing_type()->full_name(), field.number(),
6669
0
                     declared_full_name, actual_full_name);
6670
0
               });
6671
0
    }
6672
0
  }
6673
6674
0
  if (is_repeated != field.is_repeated()) {
6675
0
    AddError(field.full_name(), proto, DescriptorPool::ErrorCollector::EXTENDEE,
6676
0
             [&] {
6677
0
               return absl::Substitute(
6678
0
                   "\"$0\" extension field $1 is expected to be $2.",
6679
0
                   field.containing_type()->full_name(), field.number(),
6680
0
                   is_repeated ? "repeated" : "optional");
6681
0
             });
6682
0
  }
6683
0
}
6684
6685
void DescriptorBuilder::CrossLinkField(FieldDescriptor* field,
6686
0
                                       const FieldDescriptorProto& proto) {
6687
0
  if (field->options_ == nullptr) {
6688
0
    field->options_ = &FieldOptions::default_instance();
6689
0
  }
6690
6691
0
  if (proto.has_extendee()) {
6692
0
    Symbol extendee =
6693
0
        LookupSymbol(proto.extendee(), field->full_name(),
6694
0
                     DescriptorPool::PLACEHOLDER_EXTENDABLE_MESSAGE);
6695
0
    if (extendee.IsNull()) {
6696
0
      AddNotDefinedError(field->full_name(), proto,
6697
0
                         DescriptorPool::ErrorCollector::EXTENDEE,
6698
0
                         proto.extendee());
6699
0
      return;
6700
0
    } else if (extendee.type() != Symbol::MESSAGE) {
6701
0
      AddError(field->full_name(), proto,
6702
0
               DescriptorPool::ErrorCollector::EXTENDEE, [&] {
6703
0
                 return absl::StrCat("\"", proto.extendee(),
6704
0
                                     "\" is not a message type.");
6705
0
               });
6706
0
      return;
6707
0
    }
6708
0
    field->containing_type_ = extendee.descriptor();
6709
6710
0
    const Descriptor::ExtensionRange* extension_range =
6711
0
        field->containing_type()->FindExtensionRangeContainingNumber(
6712
0
            field->number());
6713
6714
0
    if (extension_range == nullptr) {
6715
      // Set of valid extension numbers for MessageSet is different (< 2^32)
6716
      // from other extendees (< 2^29). If unknown deps are allowed, we may not
6717
      // have that information, and wrongly deem the extension as invalid.
6718
0
      auto skip_check = get_allow_unknown(pool_) &&
6719
0
                        proto.extendee() == "google.protobuf.bridge.MessageSet";
6720
0
      if (!skip_check) {
6721
0
        AddError(field->full_name(), proto,
6722
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
6723
0
                   return absl::Substitute(
6724
0
                       "\"$0\" does not declare $1 as an "
6725
0
                       "extension number.",
6726
0
                       field->containing_type()->full_name(), field->number());
6727
0
                 });
6728
0
      }
6729
0
    }
6730
0
  }
6731
6732
0
  if (field->containing_oneof() != nullptr) {
6733
0
    if (field->label() != FieldDescriptor::LABEL_OPTIONAL) {
6734
      // Note that this error will never happen when parsing .proto files.
6735
      // It can only happen if you manually construct a FileDescriptorProto
6736
      // that is incorrect.
6737
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6738
0
               "Fields of oneofs must themselves have label LABEL_OPTIONAL.");
6739
0
    }
6740
0
  }
6741
6742
0
  if (proto.has_type_name()) {
6743
    // Assume we are expecting a message type unless the proto contains some
6744
    // evidence that it expects an enum type.  This only makes a difference if
6745
    // we end up creating a placeholder.
6746
0
    bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) ||
6747
0
                          proto.has_default_value();
6748
6749
    // In case of weak fields we force building the dependency. We need to know
6750
    // if the type exist or not. If it doesn't exist we substitute Empty which
6751
    // should only be done if the type can't be found in the generated pool.
6752
    // TODO(gerbens) Ideally we should query the database directly to check
6753
    // if weak fields exist or not so that we don't need to force building
6754
    // weak dependencies. However the name lookup rules for symbols are
6755
    // somewhat complicated, so I defer it too another CL.
6756
0
    bool is_weak = !pool_->enforce_weak_ && proto.options().weak();
6757
0
    bool is_lazy = pool_->lazily_build_dependencies_ && !is_weak;
6758
6759
0
    Symbol type =
6760
0
        LookupSymbol(proto.type_name(), field->full_name(),
6761
0
                     expecting_enum ? DescriptorPool::PLACEHOLDER_ENUM
6762
0
                                    : DescriptorPool::PLACEHOLDER_MESSAGE,
6763
0
                     LOOKUP_TYPES, !is_lazy);
6764
6765
0
    if (type.IsNull()) {
6766
0
      if (is_lazy) {
6767
        // Save the symbol names for later for lookup, and allocate the once
6768
        // object needed for the accessors.
6769
0
        const std::string& name = proto.type_name();
6770
6771
0
        int name_sizes = static_cast<int>(name.size() + 1 +
6772
0
                                          proto.default_value().size() + 1);
6773
6774
0
        field->type_once_ = ::new (tables_->AllocateBytes(
6775
0
            static_cast<int>(sizeof(absl::once_flag)) + name_sizes))
6776
0
            absl::once_flag{};
6777
0
        char* names = reinterpret_cast<char*>(field->type_once_ + 1);
6778
6779
0
        memcpy(names, name.c_str(), name.size() + 1);
6780
0
        memcpy(names + name.size() + 1, proto.default_value().c_str(),
6781
0
               proto.default_value().size() + 1);
6782
6783
        // AddFieldByNumber and AddExtension are done later in this function,
6784
        // and can/must be done if the field type was not found. The related
6785
        // error checking is not necessary when in lazily_build_dependencies_
6786
        // mode, and can't be done without building the type's descriptor,
6787
        // which we don't want to do.
6788
0
        file_tables_->AddFieldByNumber(field);
6789
0
        if (field->is_extension()) {
6790
0
          tables_->AddExtension(field);
6791
0
        }
6792
0
        return;
6793
0
      } else {
6794
        // If the type is a weak type, we change the type to a google.protobuf.Empty
6795
        // field.
6796
0
        if (is_weak) {
6797
0
          type = FindSymbol(kNonLinkedWeakMessageReplacementName);
6798
0
        }
6799
0
        if (type.IsNull()) {
6800
0
          AddNotDefinedError(field->full_name(), proto,
6801
0
                             DescriptorPool::ErrorCollector::TYPE,
6802
0
                             proto.type_name());
6803
0
          return;
6804
0
        }
6805
0
      }
6806
0
    }
6807
6808
0
    if (!proto.has_type()) {
6809
      // Choose field type based on symbol.
6810
0
      if (type.type() == Symbol::MESSAGE) {
6811
0
        field->type_ = FieldDescriptor::TYPE_MESSAGE;
6812
0
      } else if (type.type() == Symbol::ENUM) {
6813
0
        field->type_ = FieldDescriptor::TYPE_ENUM;
6814
0
      } else {
6815
0
        AddError(field->full_name(), proto,
6816
0
                 DescriptorPool::ErrorCollector::TYPE, [&] {
6817
0
                   return absl::StrCat("\"", proto.type_name(),
6818
0
                                       "\" is not a type.");
6819
0
                 });
6820
0
        return;
6821
0
      }
6822
0
    }
6823
6824
0
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
6825
0
      field->type_descriptor_.message_type = type.descriptor();
6826
0
      if (field->type_descriptor_.message_type == nullptr) {
6827
0
        AddError(field->full_name(), proto,
6828
0
                 DescriptorPool::ErrorCollector::TYPE, [&] {
6829
0
                   return absl::StrCat("\"", proto.type_name(),
6830
0
                                       "\" is not a message type.");
6831
0
                 });
6832
0
        return;
6833
0
      }
6834
6835
0
      if (field->has_default_value()) {
6836
0
        AddError(field->full_name(), proto,
6837
0
                 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
6838
0
                 "Messages can't have default values.");
6839
0
      }
6840
0
    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
6841
0
      field->type_descriptor_.enum_type = type.enum_descriptor();
6842
0
      if (field->type_descriptor_.enum_type == nullptr) {
6843
0
        AddError(field->full_name(), proto,
6844
0
                 DescriptorPool::ErrorCollector::TYPE, [&] {
6845
0
                   return absl::StrCat("\"", proto.type_name(),
6846
0
                                       "\" is not an enum type.");
6847
0
                 });
6848
0
        return;
6849
0
      }
6850
6851
0
      if (field->enum_type()->is_placeholder_) {
6852
        // We can't look up default values for placeholder types.  We'll have
6853
        // to just drop them.
6854
0
        field->has_default_value_ = false;
6855
0
      }
6856
6857
0
      if (field->has_default_value()) {
6858
        // Ensure that the default value is an identifier. Parser cannot always
6859
        // verify this because it does not have complete type information.
6860
        // N.B. that this check yields better error messages but is not
6861
        // necessary for correctness (an enum symbol must be a valid identifier
6862
        // anyway), only for better errors.
6863
0
        if (!io::Tokenizer::IsIdentifier(proto.default_value())) {
6864
0
          AddError(field->full_name(), proto,
6865
0
                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
6866
0
                   "Default value for an enum field must be an identifier.");
6867
0
        } else {
6868
          // We can't just use field->enum_type()->FindValueByName() here
6869
          // because that locks the pool's mutex, which we have already locked
6870
          // at this point.
6871
0
          const EnumValueDescriptor* default_value =
6872
0
              LookupSymbolNoPlaceholder(proto.default_value(),
6873
0
                                        field->enum_type()->full_name())
6874
0
                  .enum_value_descriptor();
6875
6876
0
          if (default_value != nullptr &&
6877
0
              default_value->type() == field->enum_type()) {
6878
0
            field->default_value_enum_ = default_value;
6879
0
          } else {
6880
0
            AddError(field->full_name(), proto,
6881
0
                     DescriptorPool::ErrorCollector::DEFAULT_VALUE, [&] {
6882
0
                       return absl::StrCat("Enum type \"",
6883
0
                                           field->enum_type()->full_name(),
6884
0
                                           "\" has no value named \"",
6885
0
                                           proto.default_value(), "\".");
6886
0
                     });
6887
0
          }
6888
0
        }
6889
0
      } else if (field->enum_type()->value_count() > 0) {
6890
        // All enums must have at least one value, or we would have reported
6891
        // an error elsewhere.  We use the first defined value as the default
6892
        // if a default is not explicitly defined.
6893
0
        field->default_value_enum_ = field->enum_type()->value(0);
6894
0
      }
6895
0
    } else {
6896
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6897
0
               "Field with primitive type has type_name.");
6898
0
    }
6899
0
  } else {
6900
0
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
6901
0
        field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
6902
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6903
0
               "Field with message or enum type missing type_name.");
6904
0
    }
6905
0
  }
6906
6907
  // Add the field to the fields-by-number table.
6908
  // Note:  We have to do this *after* cross-linking because extensions do not
6909
  // know their containing type until now. If we're in
6910
  // lazily_build_dependencies_ mode, we're guaranteed there's no errors, so no
6911
  // risk to calling containing_type() or other accessors that will build
6912
  // dependencies.
6913
0
  if (!file_tables_->AddFieldByNumber(field)) {
6914
0
    const FieldDescriptor* conflicting_field = file_tables_->FindFieldByNumber(
6915
0
        field->containing_type(), field->number());
6916
0
    std::string containing_type_name =
6917
0
        field->containing_type() == nullptr
6918
0
            ? "unknown"
6919
0
            : field->containing_type()->full_name();
6920
0
    if (field->is_extension()) {
6921
0
      AddError(field->full_name(), proto,
6922
0
               DescriptorPool::ErrorCollector::NUMBER, [&] {
6923
0
                 return absl::Substitute(
6924
0
                     "Extension number $0 has already been used "
6925
0
                     "in \"$1\" by extension \"$2\".",
6926
0
                     field->number(), containing_type_name,
6927
0
                     conflicting_field->full_name());
6928
0
               });
6929
0
    } else {
6930
0
      AddError(field->full_name(), proto,
6931
0
               DescriptorPool::ErrorCollector::NUMBER, [&] {
6932
0
                 return absl::Substitute(
6933
0
                     "Field number $0 has already been used in "
6934
0
                     "\"$1\" by field \"$2\".",
6935
0
                     field->number(), containing_type_name,
6936
0
                     conflicting_field->name());
6937
0
               });
6938
0
    }
6939
0
  } else {
6940
0
    if (field->is_extension()) {
6941
0
      if (!tables_->AddExtension(field)) {
6942
0
        auto make_error = [&] {
6943
0
          const FieldDescriptor* conflicting_field =
6944
0
              tables_->FindExtension(field->containing_type(), field->number());
6945
0
          std::string containing_type_name =
6946
0
              field->containing_type() == nullptr
6947
0
                  ? "unknown"
6948
0
                  : field->containing_type()->full_name();
6949
0
          return absl::Substitute(
6950
0
              "Extension number $0 has already been used in \"$1\" by "
6951
0
              "extension "
6952
0
              "\"$2\" defined in $3.",
6953
0
              field->number(), containing_type_name,
6954
0
              conflicting_field->full_name(),
6955
0
              conflicting_field->file()->name());
6956
0
        };
6957
        // Conflicting extension numbers should be an error. However, before
6958
        // turning this into an error we need to fix all existing broken
6959
        // protos first.
6960
        // TODO(xiaofeng): Change this to an error.
6961
0
        AddWarning(field->full_name(), proto,
6962
0
                   DescriptorPool::ErrorCollector::NUMBER, make_error);
6963
0
      }
6964
0
    }
6965
0
  }
6966
0
}
6967
6968
void DescriptorBuilder::CrossLinkEnum(EnumDescriptor* enum_type,
6969
0
                                      const EnumDescriptorProto& proto) {
6970
0
  if (enum_type->options_ == nullptr) {
6971
0
    enum_type->options_ = &EnumOptions::default_instance();
6972
0
  }
6973
6974
0
  for (int i = 0; i < enum_type->value_count(); i++) {
6975
0
    CrossLinkEnumValue(&enum_type->values_[i], proto.value(i));
6976
0
  }
6977
0
}
6978
6979
void DescriptorBuilder::CrossLinkEnumValue(
6980
    EnumValueDescriptor* enum_value,
6981
0
    const EnumValueDescriptorProto& /* proto */) {
6982
0
  if (enum_value->options_ == nullptr) {
6983
0
    enum_value->options_ = &EnumValueOptions::default_instance();
6984
0
  }
6985
0
}
6986
6987
void DescriptorBuilder::CrossLinkService(ServiceDescriptor* service,
6988
0
                                         const ServiceDescriptorProto& proto) {
6989
0
  if (service->options_ == nullptr) {
6990
0
    service->options_ = &ServiceOptions::default_instance();
6991
0
  }
6992
6993
0
  for (int i = 0; i < service->method_count(); i++) {
6994
0
    CrossLinkMethod(&service->methods_[i], proto.method(i));
6995
0
  }
6996
0
}
6997
6998
void DescriptorBuilder::CrossLinkMethod(MethodDescriptor* method,
6999
0
                                        const MethodDescriptorProto& proto) {
7000
0
  if (method->options_ == nullptr) {
7001
0
    method->options_ = &MethodOptions::default_instance();
7002
0
  }
7003
7004
0
  Symbol input_type =
7005
0
      LookupSymbol(proto.input_type(), method->full_name(),
7006
0
                   DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
7007
0
                   !pool_->lazily_build_dependencies_);
7008
0
  if (input_type.IsNull()) {
7009
0
    if (!pool_->lazily_build_dependencies_) {
7010
0
      AddNotDefinedError(method->full_name(), proto,
7011
0
                         DescriptorPool::ErrorCollector::INPUT_TYPE,
7012
0
                         proto.input_type());
7013
0
    } else {
7014
0
      method->input_type_.SetLazy(proto.input_type(), file_);
7015
0
    }
7016
0
  } else if (input_type.type() != Symbol::MESSAGE) {
7017
0
    AddError(method->full_name(), proto,
7018
0
             DescriptorPool::ErrorCollector::INPUT_TYPE, [&] {
7019
0
               return absl::StrCat("\"", proto.input_type(),
7020
0
                                   "\" is not a message type.");
7021
0
             });
7022
0
  } else {
7023
0
    method->input_type_.Set(input_type.descriptor());
7024
0
  }
7025
7026
0
  Symbol output_type =
7027
0
      LookupSymbol(proto.output_type(), method->full_name(),
7028
0
                   DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
7029
0
                   !pool_->lazily_build_dependencies_);
7030
0
  if (output_type.IsNull()) {
7031
0
    if (!pool_->lazily_build_dependencies_) {
7032
0
      AddNotDefinedError(method->full_name(), proto,
7033
0
                         DescriptorPool::ErrorCollector::OUTPUT_TYPE,
7034
0
                         proto.output_type());
7035
0
    } else {
7036
0
      method->output_type_.SetLazy(proto.output_type(), file_);
7037
0
    }
7038
0
  } else if (output_type.type() != Symbol::MESSAGE) {
7039
0
    AddError(method->full_name(), proto,
7040
0
             DescriptorPool::ErrorCollector::OUTPUT_TYPE, [&] {
7041
0
               return absl::StrCat("\"", proto.output_type(),
7042
0
                                   "\" is not a message type.");
7043
0
             });
7044
0
  } else {
7045
0
    method->output_type_.Set(output_type.descriptor());
7046
0
  }
7047
0
}
7048
7049
void DescriptorBuilder::SuggestFieldNumbers(FileDescriptor* file,
7050
0
                                            const FileDescriptorProto& proto) {
7051
0
  for (int message_index = 0; message_index < file->message_type_count();
7052
0
       message_index++) {
7053
0
    const Descriptor* message = &file->message_types_[message_index];
7054
0
    auto hints_it = message_hints_.find(message);
7055
0
    if (hints_it == message_hints_.end()) continue;
7056
0
    auto* hints = &hints_it->second;
7057
0
    constexpr int kMaxSuggestions = 3;
7058
0
    int fields_to_suggest = std::min(kMaxSuggestions, hints->fields_to_suggest);
7059
0
    if (fields_to_suggest <= 0) continue;
7060
0
    struct Range {
7061
0
      int from;
7062
0
      int to;
7063
0
    };
7064
0
    std::vector<Range> used_ordinals;
7065
0
    auto add_ordinal = [&](int ordinal) {
7066
0
      if (ordinal <= 0 || ordinal > FieldDescriptor::kMaxNumber) return;
7067
0
      if (!used_ordinals.empty() &&
7068
0
          ordinal == used_ordinals.back().to) {
7069
0
        used_ordinals.back().to = ordinal + 1;
7070
0
      } else {
7071
0
        used_ordinals.push_back({ordinal, ordinal + 1});
7072
0
      }
7073
0
    };
7074
0
    auto add_range = [&](int from, int to) {
7075
0
      from = std::max(0, std::min(FieldDescriptor::kMaxNumber + 1, from));
7076
0
      to = std::max(0, std::min(FieldDescriptor::kMaxNumber + 1, to));
7077
0
      if (from >= to) return;
7078
0
      used_ordinals.push_back({from, to});
7079
0
    };
7080
0
    for (int i = 0; i < message->field_count(); i++) {
7081
0
      add_ordinal(message->field(i)->number());
7082
0
    }
7083
0
    for (int i = 0; i < message->extension_count(); i++) {
7084
0
      add_ordinal(message->extension(i)->number());
7085
0
    }
7086
0
    for (int i = 0; i < message->reserved_range_count(); i++) {
7087
0
      auto range = message->reserved_range(i);
7088
0
      add_range(range->start, range->end);
7089
0
    }
7090
0
    for (int i = 0; i < message->extension_range_count(); i++) {
7091
0
      auto range = message->extension_range(i);
7092
0
      add_range(range->start_number(), range->end_number());
7093
0
    }
7094
0
    used_ordinals.push_back(
7095
0
        {FieldDescriptor::kMaxNumber, FieldDescriptor::kMaxNumber + 1});
7096
0
    used_ordinals.push_back({FieldDescriptor::kFirstReservedNumber,
7097
0
                             FieldDescriptor::kLastReservedNumber});
7098
0
    std::sort(used_ordinals.begin(), used_ordinals.end(),
7099
0
              [](Range lhs, Range rhs) {
7100
0
                return std::tie(lhs.from, lhs.to) < std::tie(rhs.from, rhs.to);
7101
0
              });
7102
0
    int current_ordinal = 1;
7103
0
    if (hints->first_reason) {
7104
0
      auto make_error = [&] {
7105
0
        std::stringstream id_list;
7106
0
        id_list << "Suggested field numbers for " << message->full_name()
7107
0
                << ": ";
7108
0
        const char* separator = "";
7109
0
        for (auto& current_range : used_ordinals) {
7110
0
          while (current_ordinal < current_range.from &&
7111
0
                 fields_to_suggest > 0) {
7112
0
            id_list << separator << current_ordinal++;
7113
0
            separator = ", ";
7114
0
            fields_to_suggest--;
7115
0
          }
7116
0
          if (fields_to_suggest == 0) break;
7117
0
          current_ordinal = std::max(current_ordinal, current_range.to);
7118
0
        }
7119
0
        return id_list.str();
7120
0
      };
7121
0
      AddError(message->full_name(), *hints->first_reason,
7122
0
               hints->first_reason_location, make_error);
7123
0
    }
7124
0
  }
7125
0
}
7126
7127
// -------------------------------------------------------------------
7128
7129
// Determine if the file uses optimize_for = LITE_RUNTIME, being careful to
7130
// avoid problems that exist at init time.
7131
0
static bool IsLite(const FileDescriptor* file) {
7132
  // TODO(kenton):  I don't even remember how many of these conditions are
7133
  //   actually possible.  I'm just being super-safe.
7134
0
  return file != nullptr &&
7135
0
         &file->options() != &FileOptions::default_instance() &&
7136
0
         file->options().optimize_for() == FileOptions::LITE_RUNTIME;
7137
0
}
7138
7139
void DescriptorBuilder::ValidateOptions(const FileDescriptor* file,
7140
0
                                        const FileDescriptorProto& proto) {
7141
  // Lite files can only be imported by other Lite files.
7142
0
  if (!IsLite(file)) {
7143
0
    for (int i = 0; i < file->dependency_count(); i++) {
7144
0
      if (IsLite(file->dependency(i))) {
7145
0
        AddError(file->dependency(i)->name(), proto,
7146
0
                 DescriptorPool::ErrorCollector::IMPORT, [&] {
7147
0
                   return absl::StrCat(
7148
0
                       "Files that do not use optimize_for = LITE_RUNTIME "
7149
0
                       "cannot import files which do use this option.  This "
7150
0
                       "file is not lite, but it imports \"",
7151
0
                       file->dependency(i)->name(), "\" which is.");
7152
0
                 });
7153
0
        break;
7154
0
      }
7155
0
    }
7156
0
  }
7157
0
  if (FileDescriptorLegacy(file).syntax() ==
7158
0
      FileDescriptorLegacy::Syntax::SYNTAX_PROTO3) {
7159
0
    ValidateProto3(file, proto);
7160
0
  }
7161
0
}
7162
7163
void DescriptorBuilder::ValidateProto3(const FileDescriptor* file,
7164
0
                                       const FileDescriptorProto& proto) {
7165
0
  for (int i = 0; i < file->extension_count(); ++i) {
7166
0
    ValidateProto3Field(file->extensions_ + i, proto.extension(i));
7167
0
  }
7168
0
  for (int i = 0; i < file->message_type_count(); ++i) {
7169
0
    ValidateProto3Message(file->message_types_ + i, proto.message_type(i));
7170
0
  }
7171
0
  for (int i = 0; i < file->enum_type_count(); ++i) {
7172
0
    ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i));
7173
0
  }
7174
0
}
7175
7176
void DescriptorBuilder::ValidateProto3Message(const Descriptor* message,
7177
0
                                              const DescriptorProto& proto) {
7178
0
  for (int i = 0; i < message->nested_type_count(); ++i) {
7179
0
    ValidateProto3Message(message->nested_types_ + i, proto.nested_type(i));
7180
0
  }
7181
0
  for (int i = 0; i < message->enum_type_count(); ++i) {
7182
0
    ValidateProto3Enum(message->enum_types_ + i, proto.enum_type(i));
7183
0
  }
7184
0
  for (int i = 0; i < message->field_count(); ++i) {
7185
0
    ValidateProto3Field(message->fields_ + i, proto.field(i));
7186
0
  }
7187
0
  for (int i = 0; i < message->extension_count(); ++i) {
7188
0
    ValidateProto3Field(message->extensions_ + i, proto.extension(i));
7189
0
  }
7190
0
  if (message->extension_range_count() > 0) {
7191
0
    AddError(message->full_name(), proto.extension_range(0),
7192
0
             DescriptorPool::ErrorCollector::NUMBER,
7193
0
             "Extension ranges are not allowed in proto3.");
7194
0
  }
7195
0
  if (message->options().message_set_wire_format()) {
7196
    // Using MessageSet doesn't make sense since we disallow extensions.
7197
0
    AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
7198
0
             "MessageSet is not supported in proto3.");
7199
0
  }
7200
0
}
7201
7202
void DescriptorBuilder::ValidateProto3Field(const FieldDescriptor* field,
7203
0
                                            const FieldDescriptorProto& proto) {
7204
0
  if (field->is_extension() &&
7205
0
      !AllowedExtendeeInProto3(field->containing_type()->full_name())) {
7206
0
    AddError(field->full_name(), proto,
7207
0
             DescriptorPool::ErrorCollector::EXTENDEE,
7208
0
             "Extensions in proto3 are only allowed for defining options.");
7209
0
  }
7210
0
  if (field->is_required()) {
7211
0
    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7212
0
             "Required fields are not allowed in proto3.");
7213
0
  }
7214
0
  if (field->has_default_value()) {
7215
0
    AddError(field->full_name(), proto,
7216
0
             DescriptorPool::ErrorCollector::DEFAULT_VALUE,
7217
0
             "Explicit default values are not allowed in proto3.");
7218
0
  }
7219
0
  if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
7220
0
      field->enum_type() &&
7221
0
      FileDescriptorLegacy(field->enum_type()->file()).syntax() !=
7222
0
          FileDescriptorLegacy::Syntax::SYNTAX_PROTO3 &&
7223
0
      FileDescriptorLegacy(field->enum_type()->file()).syntax() !=
7224
0
          FileDescriptorLegacy::Syntax::SYNTAX_UNKNOWN) {
7225
    // Proto3 messages can only use Proto3 enum types; otherwise we can't
7226
    // guarantee that the default value is zero.
7227
0
    AddError(
7228
0
        field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, [&] {
7229
0
          return absl::StrCat("Enum type \"", field->enum_type()->full_name(),
7230
0
                              "\" is not a proto3 enum, but is used in \"",
7231
0
                              field->containing_type()->full_name(),
7232
0
                              "\" which is a proto3 message type.");
7233
0
        });
7234
0
  }
7235
0
  if (field->type() == FieldDescriptor::TYPE_GROUP) {
7236
0
    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7237
0
             "Groups are not supported in proto3 syntax.");
7238
0
  }
7239
0
}
7240
7241
void DescriptorBuilder::ValidateProto3Enum(const EnumDescriptor* enm,
7242
0
                                           const EnumDescriptorProto& proto) {
7243
0
  if (enm->value_count() > 0 && enm->value(0)->number() != 0) {
7244
0
    AddError(enm->full_name(), proto.value(0),
7245
0
             DescriptorPool::ErrorCollector::NUMBER,
7246
0
             "The first enum value must be zero in proto3.");
7247
0
  }
7248
0
}
7249
7250
void DescriptorBuilder::ValidateOptions(const Descriptor* message,
7251
0
                                        const DescriptorProto& proto) {
7252
0
  CheckFieldJsonNameUniqueness(proto, message);
7253
0
  ValidateExtensionRangeOptions(proto, *message);
7254
0
}
7255
7256
void DescriptorBuilder::ValidateOptions(const OneofDescriptor* /*oneof*/,
7257
0
                                        const OneofDescriptorProto& /*proto*/) {
7258
0
}
7259
7260
7261
void DescriptorBuilder::ValidateOptions(const FieldDescriptor* field,
7262
0
                                        const FieldDescriptorProto& proto) {
7263
0
  if (pool_->lazily_build_dependencies_ && (!field || !field->message_type())) {
7264
0
    return;
7265
0
  }
7266
7267
0
  ValidateFieldFeatures(field, proto);
7268
7269
  // Only message type fields may be lazy.
7270
0
  if (field->options().lazy() || field->options().unverified_lazy()) {
7271
0
    if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
7272
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7273
0
               "[lazy = true] can only be specified for submessage fields.");
7274
0
    }
7275
0
  }
7276
7277
  // Only repeated primitive fields may be packed.
7278
0
  if (field->options().packed() && !field->is_packable()) {
7279
0
    AddError(
7280
0
        field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7281
0
        "[packed = true] can only be specified for repeated primitive fields.");
7282
0
  }
7283
7284
  // Note:  Default instance may not yet be initialized here, so we have to
7285
  //   avoid reading from it.
7286
0
  if (field->containing_type_ != nullptr &&
7287
0
      &field->containing_type()->options() !=
7288
0
          &MessageOptions::default_instance() &&
7289
0
      field->containing_type()->options().message_set_wire_format()) {
7290
0
    if (field->is_extension()) {
7291
0
      if (!field->is_optional() ||
7292
0
          field->type() != FieldDescriptor::TYPE_MESSAGE) {
7293
0
        AddError(field->full_name(), proto,
7294
0
                 DescriptorPool::ErrorCollector::TYPE,
7295
0
                 "Extensions of MessageSets must be optional messages.");
7296
0
      }
7297
0
    } else {
7298
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
7299
0
               "MessageSets cannot have fields, only extensions.");
7300
0
    }
7301
0
  }
7302
7303
  // Lite extensions can only be of Lite types.
7304
0
  if (IsLite(field->file()) && field->containing_type_ != nullptr &&
7305
0
      !IsLite(field->containing_type()->file())) {
7306
0
    AddError(field->full_name(), proto,
7307
0
             DescriptorPool::ErrorCollector::EXTENDEE,
7308
0
             "Extensions to non-lite types can only be declared in non-lite "
7309
0
             "files.  Note that you cannot extend a non-lite type to contain "
7310
0
             "a lite type, but the reverse is allowed.");
7311
0
  }
7312
7313
  // Validate map types.
7314
0
  if (field->is_map()) {
7315
0
    if (!ValidateMapEntry(field, proto)) {
7316
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7317
0
               "map_entry should not be set explicitly. Use map<KeyType, "
7318
0
               "ValueType> instead.");
7319
0
    }
7320
0
  }
7321
7322
0
  ValidateJSType(field, proto);
7323
7324
  // json_name option is not allowed on extension fields. Note that the
7325
  // json_name field in FieldDescriptorProto is always populated by protoc
7326
  // when it sends descriptor data to plugins (calculated from field name if
7327
  // the option is not explicitly set) so we can't rely on its presence to
7328
  // determine whether the json_name option is set on the field. Here we
7329
  // compare it against the default calculated json_name value and consider
7330
  // the option set if they are different. This won't catch the case when
7331
  // a user explicitly sets json_name to the default value, but should be
7332
  // good enough to catch common misuses.
7333
0
  if (field->is_extension() &&
7334
0
      (field->has_json_name() &&
7335
0
       field->json_name() != ToJsonName(field->name()))) {
7336
0
    AddError(field->full_name(), proto,
7337
0
             DescriptorPool::ErrorCollector::OPTION_NAME,
7338
0
             "option json_name is not allowed on extension fields.");
7339
0
  }
7340
7341
0
  if (absl::StrContains(field->json_name(), '\0')) {
7342
0
    AddError(field->full_name(), proto,
7343
0
             DescriptorPool::ErrorCollector::OPTION_NAME,
7344
0
             "json_name cannot have embedded null characters.");
7345
0
  }
7346
7347
0
}
7348
7349
void DescriptorBuilder::ValidateFieldFeatures(
7350
0
    const FieldDescriptor* field, const FieldDescriptorProto& proto) {
7351
0
}
7352
7353
void DescriptorBuilder::ValidateOptions(const EnumDescriptor* enm,
7354
0
                                        const EnumDescriptorProto& proto) {
7355
0
  CheckEnumValueUniqueness(proto, enm);
7356
7357
0
  if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) {
7358
0
    absl::flat_hash_map<int, std::string> used_values;
7359
0
    for (int i = 0; i < enm->value_count(); ++i) {
7360
0
      const EnumValueDescriptor* enum_value = enm->value(i);
7361
0
      auto insert_result =
7362
0
          used_values.emplace(enum_value->number(), enum_value->full_name());
7363
0
      bool inserted = insert_result.second;
7364
0
      if (!inserted) {
7365
0
        if (!enm->options().allow_alias()) {
7366
          // Generate error if duplicated enum values are explicitly disallowed.
7367
0
          auto make_error = [&] {
7368
            // Find the next free number.
7369
0
            absl::flat_hash_set<int64_t> used;
7370
0
            for (int j = 0; j < enm->value_count(); ++j) {
7371
0
              used.insert(enm->value(j)->number());
7372
0
            }
7373
0
            int64_t next_value = static_cast<int64_t>(enum_value->number()) + 1;
7374
0
            while (used.contains(next_value)) ++next_value;
7375
7376
0
            std::string error = absl::StrCat(
7377
0
                "\"", enum_value->full_name(),
7378
0
                "\" uses the same enum value as \"",
7379
0
                insert_result.first->second,
7380
0
                "\". If this is intended, set "
7381
0
                "'option allow_alias = true;' to the enum definition.");
7382
0
            if (next_value < std::numeric_limits<int32_t>::max()) {
7383
0
              absl::StrAppend(&error, " The next available enum value is ",
7384
0
                              next_value, ".");
7385
0
            }
7386
0
            return error;
7387
0
          };
7388
0
          AddError(enm->full_name(), proto.value(i),
7389
0
                   DescriptorPool::ErrorCollector::NUMBER, make_error);
7390
0
        }
7391
0
      }
7392
0
    }
7393
0
  }
7394
0
}
7395
7396
void DescriptorBuilder::ValidateOptions(
7397
    const EnumValueDescriptor* /* enum_value */,
7398
0
    const EnumValueDescriptorProto& /* proto */) {
7399
  // Nothing to do so far.
7400
0
}
7401
7402
namespace {
7403
// Validates that a fully-qualified symbol for extension declaration must
7404
// have a leading dot and valid identifiers.
7405
absl::optional<std::string> ValidateSymbolForDeclaration(
7406
0
    absl::string_view symbol) {
7407
0
  if (!absl::StartsWith(symbol, ".")) {
7408
0
    return absl::StrCat("\"", symbol,
7409
0
                        "\" must have a leading dot to indicate the "
7410
0
                        "fully-qualified scope.");
7411
0
  }
7412
0
  if (!ValidateQualifiedName(symbol)) {
7413
0
    return absl::StrCat("\"", symbol, "\" contains invalid identifiers.");
7414
0
  }
7415
0
  return absl::nullopt;
7416
0
}
7417
}  // namespace
7418
7419
7420
void DescriptorBuilder::ValidateExtensionDeclaration(
7421
    const std::string& full_name,
7422
    const RepeatedPtrField<ExtensionRangeOptions_Declaration>& declarations,
7423
    const DescriptorProto_ExtensionRange& proto,
7424
0
    absl::flat_hash_set<absl::string_view>& full_name_set) {
7425
0
  absl::flat_hash_set<int> extension_number_set;
7426
0
  for (const auto& declaration : declarations) {
7427
0
    if (declaration.number() < proto.start() ||
7428
0
        declaration.number() >= proto.end()) {
7429
0
      AddError(full_name, proto, DescriptorPool::ErrorCollector::NUMBER, [&] {
7430
0
        return absl::Substitute(
7431
0
            "Extension declaration number $0 is not in the "
7432
0
            "extension range.",
7433
0
            declaration.number());
7434
0
      });
7435
0
    }
7436
7437
0
    if (!extension_number_set.insert(declaration.number()).second) {
7438
0
      AddError(full_name, proto, DescriptorPool::ErrorCollector::NUMBER, [&] {
7439
0
        return absl::Substitute(
7440
0
            "Extension declaration number $0 is declared multiple times.",
7441
0
            declaration.number());
7442
0
      });
7443
0
    }
7444
7445
    // Both full_name and type should be present. If none of them is set,
7446
    // add an error unless reserved is set to true. If only one of them is set,
7447
    // add an error whether or not reserved is set to true.
7448
0
    if (!declaration.has_full_name() || !declaration.has_type()) {
7449
0
      if (declaration.has_full_name() != declaration.has_type() ||
7450
0
          !declaration.reserved()) {
7451
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::EXTENDEE,
7452
0
                 [&] {
7453
0
                   return absl::StrCat(
7454
0
                       "Extension declaration #", declaration.number(),
7455
0
                       " should have both \"full_name\" and \"type\" set.");
7456
0
                 });
7457
0
      }
7458
0
    } else {
7459
0
      if (!full_name_set.insert(declaration.full_name()).second) {
7460
0
        AddError(
7461
0
            declaration.full_name(), proto,
7462
0
            DescriptorPool::ErrorCollector::NAME, [&] {
7463
0
              return absl::Substitute(
7464
0
                  "Extension field name \"$0\" is declared multiple times.",
7465
0
                  declaration.full_name());
7466
0
            });
7467
0
        return;
7468
0
      }
7469
0
      absl::optional<std::string> err =
7470
0
          ValidateSymbolForDeclaration(declaration.full_name());
7471
0
      if (err.has_value()) {
7472
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
7473
0
                 [err] { return *err; });
7474
0
      }
7475
0
      if (!IsNonMessageType(declaration.type())) {
7476
0
        err = ValidateSymbolForDeclaration(declaration.type());
7477
0
        if (err.has_value()) {
7478
0
          AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
7479
0
                   [err] { return *err; });
7480
0
        }
7481
0
      }
7482
0
    }
7483
0
  }
7484
0
}
7485
7486
void DescriptorBuilder::ValidateExtensionRangeOptions(
7487
0
    const DescriptorProto& proto, const Descriptor& message) {
7488
0
  const int64_t max_extension_range =
7489
0
      static_cast<int64_t>(message.options().message_set_wire_format()
7490
0
                               ? std::numeric_limits<int32_t>::max()
7491
0
                               : FieldDescriptor::kMaxNumber);
7492
7493
0
  size_t num_declarations = 0;
7494
0
  for (int i = 0; i < message.extension_range_count(); i++) {
7495
0
    if (message.extension_range(i)->options_ == nullptr) continue;
7496
0
    num_declarations +=
7497
0
        message.extension_range(i)->options_->declaration_size();
7498
0
  }
7499
7500
  // Contains the full names from both "declaration" and "metadata".
7501
0
  absl::flat_hash_set<absl::string_view> declaration_full_name_set;
7502
0
  declaration_full_name_set.reserve(num_declarations);
7503
7504
0
  for (int i = 0; i < message.extension_range_count(); i++) {
7505
0
    const auto& range = *message.extension_range(i);
7506
0
    if (range.end_number() > max_extension_range + 1) {
7507
0
      AddError(message.full_name(), proto,
7508
0
               DescriptorPool::ErrorCollector::NUMBER, [&] {
7509
0
                 return absl::Substitute(
7510
0
                     "Extension numbers cannot be greater than $0.",
7511
0
                     max_extension_range);
7512
0
               });
7513
0
    }
7514
0
    const auto& range_options = *range.options_;
7515
7516
7517
0
    if (!range_options.declaration().empty()) {
7518
      // TODO(b/278783756): remove the "has_verification" check once the default
7519
      // is flipped to DECLARATION.
7520
0
      if (range_options.has_verification() &&
7521
0
          range_options.verification() == ExtensionRangeOptions::UNVERIFIED) {
7522
0
        AddError(message.full_name(), proto.extension_range(i),
7523
0
                 DescriptorPool::ErrorCollector::EXTENDEE, [&] {
7524
0
                   return absl::Substitute(
7525
0
                       "Cannot mark the extension range as UNVERIFIED when it "
7526
0
                       "has extension(s) declared.");
7527
0
                 });
7528
0
        return;
7529
0
      }
7530
0
      ValidateExtensionDeclaration(
7531
0
          message.full_name(), range_options.declaration(),
7532
0
          proto.extension_range(i), declaration_full_name_set);
7533
0
    }
7534
0
  }
7535
0
}
7536
7537
void DescriptorBuilder::ValidateOptions(const ServiceDescriptor* service,
7538
0
                                        const ServiceDescriptorProto& proto) {
7539
0
  if (IsLite(service->file()) &&
7540
0
      (service->file()->options().cc_generic_services() ||
7541
0
       service->file()->options().java_generic_services())) {
7542
0
    AddError(service->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
7543
0
             "Files with optimize_for = LITE_RUNTIME cannot define services "
7544
0
             "unless you set both options cc_generic_services and "
7545
0
             "java_generic_services to false.");
7546
0
  }
7547
0
}
7548
7549
void DescriptorBuilder::ValidateOptions(
7550
    const MethodDescriptor* /* method */,
7551
0
    const MethodDescriptorProto& /* proto */) {
7552
  // Nothing to do so far.
7553
0
}
7554
7555
bool DescriptorBuilder::ValidateMapEntry(const FieldDescriptor* field,
7556
0
                                         const FieldDescriptorProto& proto) {
7557
0
  const Descriptor* message = field->message_type();
7558
0
  if (  // Must not contain extensions, extension range or nested message or
7559
        // enums
7560
0
      message->extension_count() != 0 ||
7561
0
      field->label() != FieldDescriptor::LABEL_REPEATED ||
7562
0
      message->extension_range_count() != 0 ||
7563
0
      message->nested_type_count() != 0 || message->enum_type_count() != 0 ||
7564
      // Must contain exactly two fields
7565
0
      message->field_count() != 2 ||
7566
      // Field name and message name must match
7567
0
      message->name() !=
7568
0
          absl::StrCat(ToCamelCase(field->name(), false), "Entry") ||
7569
      // Entry message must be in the same containing type of the field.
7570
0
      field->containing_type() != message->containing_type()) {
7571
0
    return false;
7572
0
  }
7573
7574
0
  const FieldDescriptor* key = message->map_key();
7575
0
  const FieldDescriptor* value = message->map_value();
7576
0
  if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 ||
7577
0
      key->name() != "key") {
7578
0
    return false;
7579
0
  }
7580
0
  if (value->label() != FieldDescriptor::LABEL_OPTIONAL ||
7581
0
      value->number() != 2 || value->name() != "value") {
7582
0
    return false;
7583
0
  }
7584
7585
  // Check key types are legal.
7586
0
  switch (key->type()) {
7587
0
    case FieldDescriptor::TYPE_ENUM:
7588
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7589
0
               "Key in map fields cannot be enum types.");
7590
0
      break;
7591
0
    case FieldDescriptor::TYPE_FLOAT:
7592
0
    case FieldDescriptor::TYPE_DOUBLE:
7593
0
    case FieldDescriptor::TYPE_MESSAGE:
7594
0
    case FieldDescriptor::TYPE_GROUP:
7595
0
    case FieldDescriptor::TYPE_BYTES:
7596
0
      AddError(
7597
0
          field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7598
0
          "Key in map fields cannot be float/double, bytes or message types.");
7599
0
      break;
7600
0
    case FieldDescriptor::TYPE_BOOL:
7601
0
    case FieldDescriptor::TYPE_INT32:
7602
0
    case FieldDescriptor::TYPE_INT64:
7603
0
    case FieldDescriptor::TYPE_SINT32:
7604
0
    case FieldDescriptor::TYPE_SINT64:
7605
0
    case FieldDescriptor::TYPE_STRING:
7606
0
    case FieldDescriptor::TYPE_UINT32:
7607
0
    case FieldDescriptor::TYPE_UINT64:
7608
0
    case FieldDescriptor::TYPE_FIXED32:
7609
0
    case FieldDescriptor::TYPE_FIXED64:
7610
0
    case FieldDescriptor::TYPE_SFIXED32:
7611
0
    case FieldDescriptor::TYPE_SFIXED64:
7612
      // Legal cases
7613
0
      break;
7614
      // Do not add a default, so that the compiler will complain when new types
7615
      // are added.
7616
0
  }
7617
7618
0
  if (value->type() == FieldDescriptor::TYPE_ENUM) {
7619
0
    if (value->enum_type()->value(0)->number() != 0) {
7620
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7621
0
               "Enum value in map must define 0 as the first value.");
7622
0
    }
7623
0
  }
7624
7625
0
  return true;
7626
0
}
7627
7628
void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
7629
0
                                           const DescriptorProto& proto) {
7630
0
  DescriptorsByNameSet<Descriptor> seen_types;
7631
0
  for (int i = 0; i < message->nested_type_count(); ++i) {
7632
0
    const Descriptor* nested = message->nested_type(i);
7633
0
    auto insert_result = seen_types.insert(nested);
7634
0
    bool inserted = insert_result.second;
7635
0
    if (!inserted) {
7636
0
      if ((*insert_result.first)->options().map_entry() ||
7637
0
          nested->options().map_entry()) {
7638
0
        AddError(message->full_name(), proto,
7639
0
                 DescriptorPool::ErrorCollector::NAME, [&] {
7640
0
                   return absl::StrCat(
7641
0
                       "Expanded map entry type ", nested->name(),
7642
0
                       " conflicts with an existing nested message type.");
7643
0
                 });
7644
0
        break;
7645
0
      }
7646
0
    }
7647
    // Recursively test on the nested types.
7648
0
    DetectMapConflicts(message->nested_type(i), proto.nested_type(i));
7649
0
  }
7650
  // Check for conflicted field names.
7651
0
  for (int i = 0; i < message->field_count(); ++i) {
7652
0
    const FieldDescriptor* field = message->field(i);
7653
0
    auto iter = seen_types.find(field->name());
7654
0
    if (iter != seen_types.end() && (*iter)->options().map_entry()) {
7655
0
      AddError(message->full_name(), proto,
7656
0
               DescriptorPool::ErrorCollector::NAME, [&] {
7657
0
                 return absl::StrCat("Expanded map entry type ",
7658
0
                                     (*iter)->name(),
7659
0
                                     " conflicts with an existing field.");
7660
0
               });
7661
0
    }
7662
0
  }
7663
  // Check for conflicted enum names.
7664
0
  for (int i = 0; i < message->enum_type_count(); ++i) {
7665
0
    const EnumDescriptor* enum_desc = message->enum_type(i);
7666
0
    auto iter = seen_types.find(enum_desc->name());
7667
0
    if (iter != seen_types.end() && (*iter)->options().map_entry()) {
7668
0
      AddError(message->full_name(), proto,
7669
0
               DescriptorPool::ErrorCollector::NAME, [&] {
7670
0
                 return absl::StrCat("Expanded map entry type ",
7671
0
                                     (*iter)->name(),
7672
0
                                     " conflicts with an existing enum type.");
7673
0
               });
7674
0
    }
7675
0
  }
7676
  // Check for conflicted oneof names.
7677
0
  for (int i = 0; i < message->oneof_decl_count(); ++i) {
7678
0
    const OneofDescriptor* oneof_desc = message->oneof_decl(i);
7679
0
    auto iter = seen_types.find(oneof_desc->name());
7680
0
    if (iter != seen_types.end() && (*iter)->options().map_entry()) {
7681
0
      AddError(message->full_name(), proto,
7682
0
               DescriptorPool::ErrorCollector::NAME, [&] {
7683
0
                 return absl::StrCat("Expanded map entry type ",
7684
0
                                     (*iter)->name(),
7685
0
                                     " conflicts with an existing oneof type.");
7686
0
               });
7687
0
    }
7688
0
  }
7689
0
}
7690
7691
void DescriptorBuilder::ValidateJSType(const FieldDescriptor* field,
7692
0
                                       const FieldDescriptorProto& proto) {
7693
0
  FieldOptions::JSType jstype = field->options().jstype();
7694
  // The default is always acceptable.
7695
0
  if (jstype == FieldOptions::JS_NORMAL) {
7696
0
    return;
7697
0
  }
7698
7699
0
  switch (field->type()) {
7700
    // Integral 64-bit types may be represented as JavaScript numbers or
7701
    // strings.
7702
0
    case FieldDescriptor::TYPE_UINT64:
7703
0
    case FieldDescriptor::TYPE_INT64:
7704
0
    case FieldDescriptor::TYPE_SINT64:
7705
0
    case FieldDescriptor::TYPE_FIXED64:
7706
0
    case FieldDescriptor::TYPE_SFIXED64:
7707
0
      if (jstype == FieldOptions::JS_STRING ||
7708
0
          jstype == FieldOptions::JS_NUMBER) {
7709
0
        return;
7710
0
      }
7711
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7712
0
               [&] {
7713
0
                 return absl::StrCat(
7714
0
                     "Illegal jstype for int64, uint64, sint64, fixed64 "
7715
0
                     "or sfixed64 field: ",
7716
0
                     FieldOptions_JSType_descriptor()->value(jstype)->name());
7717
0
               });
7718
0
      break;
7719
7720
    // No other types permit a jstype option.
7721
0
    default:
7722
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7723
0
               "jstype is only allowed on int64, uint64, sint64, fixed64 "
7724
0
               "or sfixed64 fields.");
7725
0
      break;
7726
0
  }
7727
0
}
7728
7729
// -------------------------------------------------------------------
7730
7731
DescriptorBuilder::OptionInterpreter::OptionInterpreter(
7732
    DescriptorBuilder* builder)
7733
0
    : builder_(builder) {
7734
0
  ABSL_CHECK(builder_);
7735
0
}
7736
7737
0
DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {}
7738
7739
bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
7740
0
    OptionsToInterpret* options_to_interpret) {
7741
  // Note that these may be in different pools, so we can't use the same
7742
  // descriptor and reflection objects on both.
7743
0
  Message* options = options_to_interpret->options;
7744
0
  const Message* original_options = options_to_interpret->original_options;
7745
7746
0
  bool failed = false;
7747
0
  options_to_interpret_ = options_to_interpret;
7748
7749
  // Find the uninterpreted_option field in the mutable copy of the options
7750
  // and clear them, since we're about to interpret them.
7751
0
  const FieldDescriptor* uninterpreted_options_field =
7752
0
      options->GetDescriptor()->FindFieldByName("uninterpreted_option");
7753
0
  ABSL_CHECK(uninterpreted_options_field != nullptr)
7754
0
      << "No field named \"uninterpreted_option\" in the Options proto.";
7755
0
  options->GetReflection()->ClearField(options, uninterpreted_options_field);
7756
7757
0
  std::vector<int> src_path = options_to_interpret->element_path;
7758
0
  src_path.push_back(uninterpreted_options_field->number());
7759
7760
  // Find the uninterpreted_option field in the original options.
7761
0
  const FieldDescriptor* original_uninterpreted_options_field =
7762
0
      original_options->GetDescriptor()->FindFieldByName(
7763
0
          "uninterpreted_option");
7764
0
  ABSL_CHECK(original_uninterpreted_options_field != nullptr)
7765
0
      << "No field named \"uninterpreted_option\" in the Options proto.";
7766
7767
0
  const int num_uninterpreted_options =
7768
0
      original_options->GetReflection()->FieldSize(
7769
0
          *original_options, original_uninterpreted_options_field);
7770
0
  for (int i = 0; i < num_uninterpreted_options; ++i) {
7771
0
    src_path.push_back(i);
7772
0
    uninterpreted_option_ = DownCast<const UninterpretedOption*>(
7773
0
        &original_options->GetReflection()->GetRepeatedMessage(
7774
0
            *original_options, original_uninterpreted_options_field, i));
7775
0
    if (!InterpretSingleOption(options, src_path,
7776
0
                               options_to_interpret->element_path)) {
7777
      // Error already added by InterpretSingleOption().
7778
0
      failed = true;
7779
0
      break;
7780
0
    }
7781
0
    src_path.pop_back();
7782
0
  }
7783
  // Reset these, so we don't have any dangling pointers.
7784
0
  uninterpreted_option_ = nullptr;
7785
0
  options_to_interpret_ = nullptr;
7786
7787
0
  if (!failed) {
7788
    // InterpretSingleOption() added the interpreted options in the
7789
    // UnknownFieldSet, in case the option isn't yet known to us.  Now we
7790
    // serialize the options message and deserialize it back.  That way, any
7791
    // option fields that we do happen to know about will get moved from the
7792
    // UnknownFieldSet into the real fields, and thus be available right away.
7793
    // If they are not known, that's OK too. They will get reparsed into the
7794
    // UnknownFieldSet and wait there until the message is parsed by something
7795
    // that does know about the options.
7796
7797
    // Keep the unparsed options around in case the reparsing fails.
7798
0
    std::unique_ptr<Message> unparsed_options(options->New());
7799
0
    options->GetReflection()->Swap(unparsed_options.get(), options);
7800
7801
0
    std::string buf;
7802
0
    if (!unparsed_options->AppendToString(&buf) ||
7803
0
        !options->ParseFromString(buf)) {
7804
0
      builder_->AddError(
7805
0
          options_to_interpret->element_name, *original_options,
7806
0
          DescriptorPool::ErrorCollector::OTHER, [&] {
7807
0
            return absl::StrCat(
7808
0
                "Some options could not be correctly parsed using the proto "
7809
0
                "descriptors compiled into this binary.\n"
7810
0
                "Unparsed options: ",
7811
0
                unparsed_options->ShortDebugString(),
7812
0
                "\n"
7813
0
                "Parsing attempt:  ",
7814
0
                options->ShortDebugString());
7815
0
          });
7816
      // Restore the unparsed options.
7817
0
      options->GetReflection()->Swap(unparsed_options.get(), options);
7818
0
    }
7819
0
  }
7820
7821
0
  return !failed;
7822
0
}
7823
7824
bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
7825
    Message* options, const std::vector<int>& src_path,
7826
0
    const std::vector<int>& options_path) {
7827
  // First do some basic validation.
7828
0
  if (uninterpreted_option_->name_size() == 0) {
7829
    // This should never happen unless the parser has gone seriously awry or
7830
    // someone has manually created the uninterpreted option badly.
7831
0
    return AddNameError(
7832
0
        []() -> std::string { return "Option must have a name."; });
7833
0
  }
7834
0
  if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") {
7835
0
    return AddNameError([]() -> std::string {
7836
0
      return "Option must not use reserved name \"uninterpreted_option\".";
7837
0
    });
7838
0
  }
7839
7840
0
  const Descriptor* options_descriptor = nullptr;
7841
  // Get the options message's descriptor from the builder's pool, so that we
7842
  // get the version that knows about any extension options declared in the file
7843
  // we're currently building. The descriptor should be there as long as the
7844
  // file we're building imported descriptor.proto.
7845
7846
  // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
7847
  // DescriptorPool::FindMessageTypeByName() because we're already holding the
7848
  // pool's mutex, and the latter method locks it again.  We don't use
7849
  // FindSymbol() because files that use custom options only need to depend on
7850
  // the file that defines the option, not descriptor.proto itself.
7851
0
  Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
7852
0
      options->GetDescriptor()->full_name());
7853
0
  options_descriptor = symbol.descriptor();
7854
0
  if (options_descriptor == nullptr) {
7855
    // The options message's descriptor was not in the builder's pool, so use
7856
    // the standard version from the generated pool. We're not holding the
7857
    // generated pool's mutex, so we can search it the straightforward way.
7858
0
    options_descriptor = options->GetDescriptor();
7859
0
  }
7860
0
  ABSL_CHECK(options_descriptor);
7861
7862
  // We iterate over the name parts to drill into the submessages until we find
7863
  // the leaf field for the option. As we drill down we remember the current
7864
  // submessage's descriptor in |descriptor| and the next field in that
7865
  // submessage in |field|. We also track the fields we're drilling down
7866
  // through in |intermediate_fields|. As we go, we reconstruct the full option
7867
  // name in |debug_msg_name|, for use in error messages.
7868
0
  const Descriptor* descriptor = options_descriptor;
7869
0
  const FieldDescriptor* field = nullptr;
7870
0
  std::vector<const FieldDescriptor*> intermediate_fields;
7871
0
  std::string debug_msg_name = "";
7872
7873
0
  std::vector<int> dest_path = options_path;
7874
7875
0
  for (int i = 0; i < uninterpreted_option_->name_size(); ++i) {
7876
0
    builder_->undefine_resolved_name_.clear();
7877
0
    const std::string& name_part = uninterpreted_option_->name(i).name_part();
7878
0
    if (!debug_msg_name.empty()) {
7879
0
      absl::StrAppend(&debug_msg_name, ".");
7880
0
    }
7881
0
    if (uninterpreted_option_->name(i).is_extension()) {
7882
0
      absl::StrAppend(&debug_msg_name, "(", name_part, ")");
7883
      // Search for the extension's descriptor as an extension in the builder's
7884
      // pool. Note that we use DescriptorBuilder::LookupSymbol(), not
7885
      // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows
7886
      // relative lookups, and 2) because we're already holding the pool's
7887
      // mutex, and the latter method locks it again.
7888
0
      symbol =
7889
0
          builder_->LookupSymbol(name_part, options_to_interpret_->name_scope);
7890
0
      field = symbol.field_descriptor();
7891
      // If we don't find the field then the field's descriptor was not in the
7892
      // builder's pool, but there's no point in looking in the generated
7893
      // pool. We require that you import the file that defines any extensions
7894
      // you use, so they must be present in the builder's pool.
7895
0
    } else {
7896
0
      absl::StrAppend(&debug_msg_name, name_part);
7897
      // Search for the field's descriptor as a regular field.
7898
0
      field = descriptor->FindFieldByName(name_part);
7899
0
    }
7900
7901
0
    if (field == nullptr) {
7902
0
      if (get_allow_unknown(builder_->pool_)) {
7903
        // We can't find the option, but AllowUnknownDependencies() is enabled,
7904
        // so we will just leave it as uninterpreted.
7905
0
        AddWithoutInterpreting(*uninterpreted_option_, options);
7906
0
        return true;
7907
0
      } else if (!(builder_->undefine_resolved_name_).empty()) {
7908
        // Option is resolved to a name which is not defined.
7909
0
        return AddNameError([&] {
7910
0
          return absl::StrCat(
7911
0
              "Option \"", debug_msg_name, "\" is resolved to \"(",
7912
0
              builder_->undefine_resolved_name_,
7913
0
              ")\", which is not defined. The innermost scope is searched "
7914
0
              "first "
7915
0
              "in name resolution. Consider using a leading '.'(i.e., \"(.",
7916
0
              debug_msg_name.substr(1),
7917
0
              "\") to start from the outermost scope.");
7918
0
        });
7919
0
      } else {
7920
0
        return AddNameError([&] {
7921
0
          return absl::StrCat(
7922
0
              "Option \"", debug_msg_name, "\" unknown. Ensure that your proto",
7923
0
              " definition file imports the proto which defines the option.");
7924
0
        });
7925
0
      }
7926
0
    } else if (field->containing_type() != descriptor) {
7927
0
      if (get_is_placeholder(field->containing_type())) {
7928
        // The field is an extension of a placeholder type, so we can't
7929
        // reliably verify whether it is a valid extension to use here (e.g.
7930
        // we don't know if it is an extension of the correct *Options message,
7931
        // or if it has a valid field number, etc.).  Just leave it as
7932
        // uninterpreted instead.
7933
0
        AddWithoutInterpreting(*uninterpreted_option_, options);
7934
0
        return true;
7935
0
      } else {
7936
        // This can only happen if, due to some insane misconfiguration of the
7937
        // pools, we find the options message in one pool but the field in
7938
        // another. This would probably imply a hefty bug somewhere.
7939
0
        return AddNameError([&] {
7940
0
          return absl::StrCat("Option field \"", debug_msg_name,
7941
0
                              "\" is not a field or extension of message \"",
7942
0
                              descriptor->name(), "\".");
7943
0
        });
7944
0
      }
7945
0
    } else {
7946
      // accumulate field numbers to form path to interpreted option
7947
0
      dest_path.push_back(field->number());
7948
7949
0
      if (i < uninterpreted_option_->name_size() - 1) {
7950
0
        if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
7951
0
          return AddNameError([&] {
7952
0
            return absl::StrCat("Option \"", debug_msg_name,
7953
0
                                "\" is an atomic type, not a message.");
7954
0
          });
7955
0
        } else if (field->is_repeated()) {
7956
0
          return AddNameError([&] {
7957
0
            return absl::StrCat("Option field \"", debug_msg_name,
7958
0
                                "\" is a repeated message. Repeated message "
7959
0
                                "options must be initialized using an "
7960
0
                                "aggregate value.");
7961
0
          });
7962
0
        } else {
7963
          // Drill down into the submessage.
7964
0
          intermediate_fields.push_back(field);
7965
0
          descriptor = field->message_type();
7966
0
        }
7967
0
      }
7968
0
    }
7969
0
  }
7970
7971
  // We've found the leaf field. Now we use UnknownFieldSets to set its value
7972
  // on the options message. We do so because the message may not yet know
7973
  // about its extension fields, so we may not be able to set the fields
7974
  // directly. But the UnknownFieldSets will serialize to the same wire-format
7975
  // message, so reading that message back in once the extension fields are
7976
  // known will populate them correctly.
7977
7978
  // First see if the option is already set.
7979
0
  if (!field->is_repeated() &&
7980
0
      !ExamineIfOptionIsSet(
7981
0
          intermediate_fields.begin(), intermediate_fields.end(), field,
7982
0
          debug_msg_name,
7983
0
          options->GetReflection()->GetUnknownFields(*options))) {
7984
0
    return false;  // ExamineIfOptionIsSet() already added the error.
7985
0
  }
7986
7987
  // First set the value on the UnknownFieldSet corresponding to the
7988
  // innermost message.
7989
0
  std::unique_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
7990
0
  if (!SetOptionValue(field, unknown_fields.get())) {
7991
0
    return false;  // SetOptionValue() already added the error.
7992
0
  }
7993
7994
  // Now wrap the UnknownFieldSet with UnknownFieldSets corresponding to all
7995
  // the intermediate messages.
7996
0
  for (std::vector<const FieldDescriptor*>::reverse_iterator iter =
7997
0
           intermediate_fields.rbegin();
7998
0
       iter != intermediate_fields.rend(); ++iter) {
7999
0
    std::unique_ptr<UnknownFieldSet> parent_unknown_fields(
8000
0
        new UnknownFieldSet());
8001
0
    switch ((*iter)->type()) {
8002
0
      case FieldDescriptor::TYPE_MESSAGE: {
8003
0
        std::string* outstr =
8004
0
            parent_unknown_fields->AddLengthDelimited((*iter)->number());
8005
0
        ABSL_CHECK(unknown_fields->SerializeToString(outstr))
8006
0
            << "Unexpected failure while serializing option submessage "
8007
0
            << debug_msg_name << "\".";
8008
0
        break;
8009
0
      }
8010
8011
0
      case FieldDescriptor::TYPE_GROUP: {
8012
0
        parent_unknown_fields->AddGroup((*iter)->number())
8013
0
            ->MergeFrom(*unknown_fields);
8014
0
        break;
8015
0
      }
8016
8017
0
      default:
8018
0
        ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: "
8019
0
                        << (*iter)->type();
8020
0
        return false;
8021
0
    }
8022
0
    unknown_fields.reset(parent_unknown_fields.release());
8023
0
  }
8024
8025
  // Now merge the UnknownFieldSet corresponding to the top-level message into
8026
  // the options message.
8027
0
  options->GetReflection()->MutableUnknownFields(options)->MergeFrom(
8028
0
      *unknown_fields);
8029
8030
  // record the element path of the interpreted option
8031
0
  if (field->is_repeated()) {
8032
0
    int index = repeated_option_counts_[dest_path]++;
8033
0
    dest_path.push_back(index);
8034
0
  }
8035
0
  interpreted_paths_[src_path] = dest_path;
8036
8037
0
  return true;
8038
0
}
8039
8040
void DescriptorBuilder::OptionInterpreter::UpdateSourceCodeInfo(
8041
0
    SourceCodeInfo* info) {
8042
0
  if (interpreted_paths_.empty()) {
8043
    // nothing to do!
8044
0
    return;
8045
0
  }
8046
8047
  // We find locations that match keys in interpreted_paths_ and
8048
  // 1) replace the path with the corresponding value in interpreted_paths_
8049
  // 2) remove any subsequent sub-locations (sub-location is one whose path
8050
  //    has the parent path as a prefix)
8051
  //
8052
  // To avoid quadratic behavior of removing interior rows as we go,
8053
  // we keep a copy. But we don't actually copy anything until we've
8054
  // found the first match (so if the source code info has no locations
8055
  // that need to be changed, there is zero copy overhead).
8056
8057
0
  RepeatedPtrField<SourceCodeInfo_Location>* locs = info->mutable_location();
8058
0
  RepeatedPtrField<SourceCodeInfo_Location> new_locs;
8059
0
  bool copying = false;
8060
8061
0
  std::vector<int> pathv;
8062
0
  bool matched = false;
8063
8064
0
  for (RepeatedPtrField<SourceCodeInfo_Location>::iterator loc = locs->begin();
8065
0
       loc != locs->end(); loc++) {
8066
0
    if (matched) {
8067
      // see if this location is in the range to remove
8068
0
      bool loc_matches = true;
8069
0
      if (loc->path_size() < static_cast<int64_t>(pathv.size())) {
8070
0
        loc_matches = false;
8071
0
      } else {
8072
0
        for (size_t j = 0; j < pathv.size(); j++) {
8073
0
          if (loc->path(j) != pathv[j]) {
8074
0
            loc_matches = false;
8075
0
            break;
8076
0
          }
8077
0
        }
8078
0
      }
8079
8080
0
      if (loc_matches) {
8081
        // don't copy this row since it is a sub-location that we're removing
8082
0
        continue;
8083
0
      }
8084
8085
0
      matched = false;
8086
0
    }
8087
8088
0
    pathv.clear();
8089
0
    for (int j = 0; j < loc->path_size(); j++) {
8090
0
      pathv.push_back(loc->path(j));
8091
0
    }
8092
8093
0
    auto entry = interpreted_paths_.find(pathv);
8094
8095
0
    if (entry == interpreted_paths_.end()) {
8096
      // not a match
8097
0
      if (copying) {
8098
0
        *new_locs.Add() = *loc;
8099
0
      }
8100
0
      continue;
8101
0
    }
8102
8103
0
    matched = true;
8104
8105
0
    if (!copying) {
8106
      // initialize the copy we are building
8107
0
      copying = true;
8108
0
      new_locs.Reserve(locs->size());
8109
0
      for (RepeatedPtrField<SourceCodeInfo_Location>::iterator it =
8110
0
               locs->begin();
8111
0
           it != loc; it++) {
8112
0
        *new_locs.Add() = *it;
8113
0
      }
8114
0
    }
8115
8116
    // add replacement and update its path
8117
0
    SourceCodeInfo_Location* replacement = new_locs.Add();
8118
0
    *replacement = *loc;
8119
0
    replacement->clear_path();
8120
0
    for (std::vector<int>::iterator rit = entry->second.begin();
8121
0
         rit != entry->second.end(); rit++) {
8122
0
      replacement->add_path(*rit);
8123
0
    }
8124
0
  }
8125
8126
  // if we made a changed copy, put it in place
8127
0
  if (copying) {
8128
0
    *locs = new_locs;
8129
0
  }
8130
0
}
8131
8132
void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting(
8133
0
    const UninterpretedOption& uninterpreted_option, Message* options) {
8134
0
  const FieldDescriptor* field =
8135
0
      options->GetDescriptor()->FindFieldByName("uninterpreted_option");
8136
0
  ABSL_CHECK(field != nullptr);
8137
8138
0
  options->GetReflection()
8139
0
      ->AddMessage(options, field)
8140
0
      ->CopyFrom(uninterpreted_option);
8141
0
}
8142
8143
bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
8144
    std::vector<const FieldDescriptor*>::const_iterator
8145
        intermediate_fields_iter,
8146
    std::vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
8147
    const FieldDescriptor* innermost_field, const std::string& debug_msg_name,
8148
0
    const UnknownFieldSet& unknown_fields) {
8149
  // We do linear searches of the UnknownFieldSet and its sub-groups.  This
8150
  // should be fine since it's unlikely that any one options structure will
8151
  // contain more than a handful of options.
8152
8153
0
  if (intermediate_fields_iter == intermediate_fields_end) {
8154
    // We're at the innermost submessage.
8155
0
    for (int i = 0; i < unknown_fields.field_count(); i++) {
8156
0
      if (unknown_fields.field(i).number() == innermost_field->number()) {
8157
0
        return AddNameError([&] {
8158
0
          return absl::StrCat("Option \"", debug_msg_name,
8159
0
                              "\" was already set.");
8160
0
        });
8161
0
      }
8162
0
    }
8163
0
    return true;
8164
0
  }
8165
8166
0
  for (int i = 0; i < unknown_fields.field_count(); i++) {
8167
0
    if (unknown_fields.field(i).number() ==
8168
0
        (*intermediate_fields_iter)->number()) {
8169
0
      const UnknownField* unknown_field = &unknown_fields.field(i);
8170
0
      FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
8171
      // Recurse into the next submessage.
8172
0
      switch (type) {
8173
0
        case FieldDescriptor::TYPE_MESSAGE:
8174
0
          if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
8175
0
            UnknownFieldSet intermediate_unknown_fields;
8176
0
            if (intermediate_unknown_fields.ParseFromString(
8177
0
                    unknown_field->length_delimited()) &&
8178
0
                !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
8179
0
                                      intermediate_fields_end, innermost_field,
8180
0
                                      debug_msg_name,
8181
0
                                      intermediate_unknown_fields)) {
8182
0
              return false;  // Error already added.
8183
0
            }
8184
0
          }
8185
0
          break;
8186
8187
0
        case FieldDescriptor::TYPE_GROUP:
8188
0
          if (unknown_field->type() == UnknownField::TYPE_GROUP) {
8189
0
            if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
8190
0
                                      intermediate_fields_end, innermost_field,
8191
0
                                      debug_msg_name, unknown_field->group())) {
8192
0
              return false;  // Error already added.
8193
0
            }
8194
0
          }
8195
0
          break;
8196
8197
0
        default:
8198
0
          ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type;
8199
0
          return false;
8200
0
      }
8201
0
    }
8202
0
  }
8203
0
  return true;
8204
0
}
8205
8206
namespace {
8207
// Helpers for method below
8208
8209
template <typename T> std::string ValueOutOfRange(
8210
0
    absl::string_view type_name, absl::string_view option_name) {
8211
0
  return absl::StrFormat(
8212
0
    "Value out of range, %d to %d, for %s option \"%s\".", \
8213
0
    std::numeric_limits<T>::min(), std::numeric_limits<T>::max(),
8214
0
    type_name, option_name);
8215
0
}
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueOutOfRange<int>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueOutOfRange<long>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueOutOfRange<unsigned int>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
8216
8217
template <typename T> std::string ValueMustBeInt(
8218
0
    absl::string_view type_name, absl::string_view option_name) {
8219
0
  return absl::StrFormat(
8220
0
    "Value must be integer, from %d to %d, for %s option \"%s\".", \
8221
0
    std::numeric_limits<T>::min(), std::numeric_limits<T>::max(),
8222
0
    type_name, option_name);
8223
0
}
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueMustBeInt<int>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueMustBeInt<long>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueMustBeInt<unsigned int>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueMustBeInt<unsigned long>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
8224
8225
} // namespace
8226
8227
bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
8228
0
    const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
8229
  // We switch on the CppType to validate.
8230
0
  switch (option_field->cpp_type()) {
8231
0
    case FieldDescriptor::CPPTYPE_INT32:
8232
0
      if (uninterpreted_option_->has_positive_int_value()) {
8233
0
        if (uninterpreted_option_->positive_int_value() >
8234
0
            static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
8235
0
          return AddValueError([&] {
8236
0
            return ValueOutOfRange<int32_t>("int32", option_field->full_name());
8237
0
          });
8238
0
        } else {
8239
0
          SetInt32(option_field->number(),
8240
0
                   uninterpreted_option_->positive_int_value(),
8241
0
                   option_field->type(), unknown_fields);
8242
0
        }
8243
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
8244
0
        if (uninterpreted_option_->negative_int_value() <
8245
0
            static_cast<int64_t>(std::numeric_limits<int32_t>::min())) {
8246
0
          return AddValueError([&] {
8247
0
            return ValueOutOfRange<int32_t>("int32", option_field->full_name());
8248
0
          });
8249
0
        } else {
8250
0
          SetInt32(option_field->number(),
8251
0
                   uninterpreted_option_->negative_int_value(),
8252
0
                   option_field->type(), unknown_fields);
8253
0
        }
8254
0
      } else {
8255
0
        return AddValueError([&] {
8256
0
          return ValueMustBeInt<int32_t>("int32", option_field->full_name());
8257
0
        });
8258
0
      }
8259
0
      break;
8260
8261
0
    case FieldDescriptor::CPPTYPE_INT64:
8262
0
      if (uninterpreted_option_->has_positive_int_value()) {
8263
0
        if (uninterpreted_option_->positive_int_value() >
8264
0
            static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
8265
0
          return AddValueError([&] {
8266
0
            return ValueOutOfRange<int64_t>("int64", option_field->full_name());
8267
0
          });
8268
0
        } else {
8269
0
          SetInt64(option_field->number(),
8270
0
                   uninterpreted_option_->positive_int_value(),
8271
0
                   option_field->type(), unknown_fields);
8272
0
        }
8273
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
8274
0
        SetInt64(option_field->number(),
8275
0
                 uninterpreted_option_->negative_int_value(),
8276
0
                 option_field->type(), unknown_fields);
8277
0
      } else {
8278
0
        return AddValueError([&] {
8279
0
          return ValueMustBeInt<int64_t>("int64", option_field->full_name());
8280
0
        });
8281
0
      }
8282
0
      break;
8283
8284
0
    case FieldDescriptor::CPPTYPE_UINT32:
8285
0
      if (uninterpreted_option_->has_positive_int_value()) {
8286
0
        if (uninterpreted_option_->positive_int_value() >
8287
0
            std::numeric_limits<uint32_t>::max()) {
8288
0
          return AddValueError([&] {
8289
0
            return ValueOutOfRange<uint32_t>("uint32",
8290
0
                                             option_field->full_name());
8291
0
          });
8292
0
        } else {
8293
0
          SetUInt32(option_field->number(),
8294
0
                    uninterpreted_option_->positive_int_value(),
8295
0
                    option_field->type(), unknown_fields);
8296
0
        }
8297
0
      } else {
8298
0
        return AddValueError([&] {
8299
0
          return ValueMustBeInt<uint32_t>("uint32", option_field->full_name());
8300
0
        });
8301
0
      }
8302
0
      break;
8303
8304
0
    case FieldDescriptor::CPPTYPE_UINT64:
8305
0
      if (uninterpreted_option_->has_positive_int_value()) {
8306
0
        SetUInt64(option_field->number(),
8307
0
                  uninterpreted_option_->positive_int_value(),
8308
0
                  option_field->type(), unknown_fields);
8309
0
      } else {
8310
0
        return AddValueError([&] {
8311
0
          return ValueMustBeInt<uint64_t>("uint64", option_field->full_name());
8312
0
        });
8313
0
      }
8314
0
      break;
8315
8316
0
    case FieldDescriptor::CPPTYPE_FLOAT: {
8317
0
      float value;
8318
0
      if (uninterpreted_option_->has_double_value()) {
8319
0
        value = uninterpreted_option_->double_value();
8320
0
      } else if (uninterpreted_option_->has_positive_int_value()) {
8321
0
        value = uninterpreted_option_->positive_int_value();
8322
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
8323
0
        value = uninterpreted_option_->negative_int_value();
8324
0
      } else {
8325
0
        return AddValueError([&] {
8326
0
          return absl::StrCat("Value must be number for float option \"",
8327
0
                              option_field->full_name(), "\".");
8328
0
        });
8329
0
      }
8330
0
      unknown_fields->AddFixed32(option_field->number(),
8331
0
                                 internal::WireFormatLite::EncodeFloat(value));
8332
0
      break;
8333
0
    }
8334
8335
0
    case FieldDescriptor::CPPTYPE_DOUBLE: {
8336
0
      double value;
8337
0
      if (uninterpreted_option_->has_double_value()) {
8338
0
        value = uninterpreted_option_->double_value();
8339
0
      } else if (uninterpreted_option_->has_positive_int_value()) {
8340
0
        value = uninterpreted_option_->positive_int_value();
8341
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
8342
0
        value = uninterpreted_option_->negative_int_value();
8343
0
      } else {
8344
0
        return AddValueError([&] {
8345
0
          return absl::StrCat("Value must be number for double option \"",
8346
0
                              option_field->full_name(), "\".");
8347
0
        });
8348
0
      }
8349
0
      unknown_fields->AddFixed64(option_field->number(),
8350
0
                                 internal::WireFormatLite::EncodeDouble(value));
8351
0
      break;
8352
0
    }
8353
8354
0
    case FieldDescriptor::CPPTYPE_BOOL:
8355
0
      uint64_t value;
8356
0
      if (!uninterpreted_option_->has_identifier_value()) {
8357
0
        return AddValueError([&] {
8358
0
          return absl::StrCat("Value must be identifier for boolean option \"",
8359
0
                              option_field->full_name(), "\".");
8360
0
        });
8361
0
      }
8362
0
      if (uninterpreted_option_->identifier_value() == "true") {
8363
0
        value = 1;
8364
0
      } else if (uninterpreted_option_->identifier_value() == "false") {
8365
0
        value = 0;
8366
0
      } else {
8367
0
        return AddValueError([&] {
8368
0
          return absl::StrCat(
8369
0
              "Value must be \"true\" or \"false\" for boolean option \"",
8370
0
              option_field->full_name(), "\".");
8371
0
        });
8372
0
      }
8373
0
      unknown_fields->AddVarint(option_field->number(), value);
8374
0
      break;
8375
8376
0
    case FieldDescriptor::CPPTYPE_ENUM: {
8377
0
      if (!uninterpreted_option_->has_identifier_value()) {
8378
0
        return AddValueError([&] {
8379
0
          return absl::StrCat(
8380
0
              "Value must be identifier for enum-valued option \"",
8381
0
              option_field->full_name(), "\".");
8382
0
        });
8383
0
      }
8384
0
      const EnumDescriptor* enum_type = option_field->enum_type();
8385
0
      const std::string& value_name = uninterpreted_option_->identifier_value();
8386
0
      const EnumValueDescriptor* enum_value = nullptr;
8387
8388
0
      if (enum_type->file()->pool() != DescriptorPool::generated_pool()) {
8389
        // Note that the enum value's fully-qualified name is a sibling of the
8390
        // enum's name, not a child of it.
8391
0
        std::string fully_qualified_name = enum_type->full_name();
8392
0
        fully_qualified_name.resize(fully_qualified_name.size() -
8393
0
                                    enum_type->name().size());
8394
0
        fully_qualified_name += value_name;
8395
8396
        // Search for the enum value's descriptor in the builder's pool. Note
8397
        // that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
8398
        // DescriptorPool::FindEnumValueByName() because we're already holding
8399
        // the pool's mutex, and the latter method locks it again.
8400
0
        Symbol symbol =
8401
0
            builder_->FindSymbolNotEnforcingDeps(fully_qualified_name);
8402
0
        if (auto* candicate_descriptor = symbol.enum_value_descriptor()) {
8403
0
          if (candicate_descriptor->type() != enum_type) {
8404
0
            return AddValueError([&] {
8405
0
              return absl::StrCat(
8406
0
                  "Enum type \"", enum_type->full_name(),
8407
0
                  "\" has no value named \"", value_name, "\" for option \"",
8408
0
                  option_field->full_name(),
8409
0
                  "\". This appears to be a value from a sibling type.");
8410
0
            });
8411
0
          } else {
8412
0
            enum_value = candicate_descriptor;
8413
0
          }
8414
0
        }
8415
0
      } else {
8416
        // The enum type is in the generated pool, so we can search for the
8417
        // value there.
8418
0
        enum_value = enum_type->FindValueByName(value_name);
8419
0
      }
8420
8421
0
      if (enum_value == nullptr) {
8422
0
        return AddValueError([&] {
8423
0
          return absl::StrCat(
8424
0
              "Enum type \"", option_field->enum_type()->full_name(),
8425
0
              "\" has no value named \"", value_name, "\" for option \"",
8426
0
              option_field->full_name(), "\".");
8427
0
        });
8428
0
      } else {
8429
        // Sign-extension is not a problem, since we cast directly from int32_t
8430
        // to uint64_t, without first going through uint32_t.
8431
0
        unknown_fields->AddVarint(
8432
0
            option_field->number(),
8433
0
            static_cast<uint64_t>(static_cast<int64_t>(enum_value->number())));
8434
0
      }
8435
0
      break;
8436
0
    }
8437
8438
0
    case FieldDescriptor::CPPTYPE_STRING:
8439
0
      if (!uninterpreted_option_->has_string_value()) {
8440
0
        return AddValueError([&] {
8441
0
          return absl::StrCat(
8442
0
              "Value must be quoted string for string option \"",
8443
0
              option_field->full_name(), "\".");
8444
0
        });
8445
0
      }
8446
      // The string has already been unquoted and unescaped by the parser.
8447
0
      unknown_fields->AddLengthDelimited(option_field->number(),
8448
0
                                         uninterpreted_option_->string_value());
8449
0
      break;
8450
8451
0
    case FieldDescriptor::CPPTYPE_MESSAGE:
8452
0
      if (!SetAggregateOption(option_field, unknown_fields)) {
8453
0
        return false;
8454
0
      }
8455
0
      break;
8456
0
  }
8457
8458
0
  return true;
8459
0
}
8460
8461
class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
8462
    : public TextFormat::Finder {
8463
 public:
8464
  DescriptorBuilder* builder_;
8465
8466
  const Descriptor* FindAnyType(const Message& /*message*/,
8467
                                const std::string& prefix,
8468
0
                                const std::string& name) const override {
8469
0
    if (prefix != internal::kTypeGoogleApisComPrefix &&
8470
0
        prefix != internal::kTypeGoogleProdComPrefix) {
8471
0
      return nullptr;
8472
0
    }
8473
0
    assert_mutex_held(builder_->pool_);
8474
0
    return builder_->FindSymbol(name).descriptor();
8475
0
  }
8476
8477
  const FieldDescriptor* FindExtension(Message* message,
8478
0
                                       const std::string& name) const override {
8479
0
    assert_mutex_held(builder_->pool_);
8480
0
    const Descriptor* descriptor = message->GetDescriptor();
8481
0
    Symbol result =
8482
0
        builder_->LookupSymbolNoPlaceholder(name, descriptor->full_name());
8483
0
    if (auto* field = result.field_descriptor()) {
8484
0
      return field;
8485
0
    } else if (result.type() == Symbol::MESSAGE &&
8486
0
               descriptor->options().message_set_wire_format()) {
8487
0
      const Descriptor* foreign_type = result.descriptor();
8488
      // The text format allows MessageSet items to be specified using
8489
      // the type name, rather than the extension identifier. If the symbol
8490
      // lookup returned a Message, and the enclosing Message has
8491
      // message_set_wire_format = true, then return the message set
8492
      // extension, if one exists.
8493
0
      for (int i = 0; i < foreign_type->extension_count(); i++) {
8494
0
        const FieldDescriptor* extension = foreign_type->extension(i);
8495
0
        if (extension->containing_type() == descriptor &&
8496
0
            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
8497
0
            extension->is_optional() &&
8498
0
            extension->message_type() == foreign_type) {
8499
          // Found it.
8500
0
          return extension;
8501
0
        }
8502
0
      }
8503
0
    }
8504
0
    return nullptr;
8505
0
  }
8506
};
8507
8508
// A custom error collector to record any text-format parsing errors
8509
namespace {
8510
class AggregateErrorCollector : public io::ErrorCollector {
8511
 public:
8512
  std::string error_;
8513
8514
  void RecordError(int /* line */, int /* column */,
8515
0
                   const absl::string_view message) override {
8516
0
    if (!error_.empty()) {
8517
0
      absl::StrAppend(&error_, "; ");
8518
0
    }
8519
0
    absl::StrAppend(&error_, message);
8520
0
  }
8521
8522
  void RecordWarning(int /* line */, int /* column */,
8523
0
                     const absl::string_view /* message */) override {
8524
    // Ignore warnings
8525
0
  }
8526
};
8527
}  // namespace
8528
8529
// We construct a dynamic message of the type corresponding to
8530
// option_field, parse the supplied text-format string into this
8531
// message, and serialize the resulting message to produce the value.
8532
bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
8533
0
    const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
8534
0
  if (!uninterpreted_option_->has_aggregate_value()) {
8535
0
    return AddValueError([&] {
8536
0
      return absl::StrCat("Option \"", option_field->full_name(),
8537
0
                          "\" is a message. "
8538
0
                          "To set the entire message, use syntax like \"",
8539
0
                          option_field->name(),
8540
0
                          " = { <proto text format> }\". "
8541
0
                          "To set fields within it, use syntax like \"",
8542
0
                          option_field->name(), ".foo = value\".");
8543
0
    });
8544
0
  }
8545
8546
0
  const Descriptor* type = option_field->message_type();
8547
0
  std::unique_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
8548
0
  ABSL_CHECK(dynamic.get() != nullptr)
8549
0
      << "Could not create an instance of " << option_field->DebugString();
8550
8551
0
  AggregateErrorCollector collector;
8552
0
  AggregateOptionFinder finder;
8553
0
  finder.builder_ = builder_;
8554
0
  TextFormat::Parser parser;
8555
0
  parser.RecordErrorsTo(&collector);
8556
0
  parser.SetFinder(&finder);
8557
0
  if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
8558
0
                              dynamic.get())) {
8559
0
    AddValueError([&] {
8560
0
      return absl::StrCat("Error while parsing option value for \"",
8561
0
                          option_field->name(), "\": ", collector.error_);
8562
0
    });
8563
0
    return false;
8564
0
  } else {
8565
0
    std::string serial;
8566
0
    dynamic->SerializeToString(&serial);  // Never fails
8567
0
    if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) {
8568
0
      unknown_fields->AddLengthDelimited(option_field->number(), serial);
8569
0
    } else {
8570
0
      ABSL_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP);
8571
0
      UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number());
8572
0
      group->ParseFromString(serial);
8573
0
    }
8574
0
    return true;
8575
0
  }
8576
0
}
8577
8578
void DescriptorBuilder::OptionInterpreter::SetInt32(
8579
    int number, int32_t value, FieldDescriptor::Type type,
8580
0
    UnknownFieldSet* unknown_fields) {
8581
0
  switch (type) {
8582
0
    case FieldDescriptor::TYPE_INT32:
8583
0
      unknown_fields->AddVarint(
8584
0
          number, static_cast<uint64_t>(static_cast<int64_t>(value)));
8585
0
      break;
8586
8587
0
    case FieldDescriptor::TYPE_SFIXED32:
8588
0
      unknown_fields->AddFixed32(number, static_cast<uint32_t>(value));
8589
0
      break;
8590
8591
0
    case FieldDescriptor::TYPE_SINT32:
8592
0
      unknown_fields->AddVarint(
8593
0
          number, internal::WireFormatLite::ZigZagEncode32(value));
8594
0
      break;
8595
8596
0
    default:
8597
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT32: " << type;
8598
0
      break;
8599
0
  }
8600
0
}
8601
8602
void DescriptorBuilder::OptionInterpreter::SetInt64(
8603
    int number, int64_t value, FieldDescriptor::Type type,
8604
0
    UnknownFieldSet* unknown_fields) {
8605
0
  switch (type) {
8606
0
    case FieldDescriptor::TYPE_INT64:
8607
0
      unknown_fields->AddVarint(number, static_cast<uint64_t>(value));
8608
0
      break;
8609
8610
0
    case FieldDescriptor::TYPE_SFIXED64:
8611
0
      unknown_fields->AddFixed64(number, static_cast<uint64_t>(value));
8612
0
      break;
8613
8614
0
    case FieldDescriptor::TYPE_SINT64:
8615
0
      unknown_fields->AddVarint(
8616
0
          number, internal::WireFormatLite::ZigZagEncode64(value));
8617
0
      break;
8618
8619
0
    default:
8620
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT64: " << type;
8621
0
      break;
8622
0
  }
8623
0
}
8624
8625
void DescriptorBuilder::OptionInterpreter::SetUInt32(
8626
    int number, uint32_t value, FieldDescriptor::Type type,
8627
0
    UnknownFieldSet* unknown_fields) {
8628
0
  switch (type) {
8629
0
    case FieldDescriptor::TYPE_UINT32:
8630
0
      unknown_fields->AddVarint(number, static_cast<uint64_t>(value));
8631
0
      break;
8632
8633
0
    case FieldDescriptor::TYPE_FIXED32:
8634
0
      unknown_fields->AddFixed32(number, static_cast<uint32_t>(value));
8635
0
      break;
8636
8637
0
    default:
8638
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT32: " << type;
8639
0
      break;
8640
0
  }
8641
0
}
8642
8643
void DescriptorBuilder::OptionInterpreter::SetUInt64(
8644
    int number, uint64_t value, FieldDescriptor::Type type,
8645
0
    UnknownFieldSet* unknown_fields) {
8646
0
  switch (type) {
8647
0
    case FieldDescriptor::TYPE_UINT64:
8648
0
      unknown_fields->AddVarint(number, value);
8649
0
      break;
8650
8651
0
    case FieldDescriptor::TYPE_FIXED64:
8652
0
      unknown_fields->AddFixed64(number, value);
8653
0
      break;
8654
8655
0
    default:
8656
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT64: " << type;
8657
0
      break;
8658
0
  }
8659
0
}
8660
8661
void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto,
8662
0
                                            const FileDescriptor* result) {
8663
0
  (void)result;  // Parameter is used by Google-internal code.
8664
8665
0
  if (!unused_dependency_.empty()) {
8666
0
    auto itr = pool_->unused_import_track_files_.find(proto.name());
8667
0
    bool is_error =
8668
0
        itr != pool_->unused_import_track_files_.end() && itr->second;
8669
0
    for (const auto* unused : unused_dependency_) {
8670
0
      auto make_error = [&] {
8671
0
        return absl::StrCat("Import ", unused->name(), " is unused.");
8672
0
      };
8673
0
      if (is_error) {
8674
0
        AddError(unused->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
8675
0
                 make_error);
8676
0
      } else {
8677
0
        AddWarning(unused->name(), proto,
8678
0
                   DescriptorPool::ErrorCollector::IMPORT, make_error);
8679
0
      }
8680
0
    }
8681
0
  }
8682
0
}
8683
8684
Symbol DescriptorPool::CrossLinkOnDemandHelper(absl::string_view name,
8685
0
                                               bool expecting_enum) const {
8686
0
  (void)expecting_enum;  // Parameter is used by Google-internal code.
8687
0
  auto lookup_name = std::string(name);
8688
0
  if (!lookup_name.empty() && lookup_name[0] == '.') {
8689
0
    lookup_name = lookup_name.substr(1);
8690
0
  }
8691
0
  Symbol result = tables_->FindByNameHelper(this, lookup_name);
8692
0
  return result;
8693
0
}
8694
8695
// Handle the lazy import building for a message field whose type wasn't built
8696
// at cross link time. If that was the case, we saved the name of the type to
8697
// be looked up when the accessor for the type was called. Set type_,
8698
// enum_type_, message_type_, and default_value_enum_ appropriately.
8699
0
void FieldDescriptor::InternalTypeOnceInit() const {
8700
0
  ABSL_CHECK(file()->finished_building_ == true);
8701
0
  const EnumDescriptor* enum_type = nullptr;
8702
0
  const char* lazy_type_name = reinterpret_cast<const char*>(type_once_ + 1);
8703
0
  const char* lazy_default_value_enum_name =
8704
0
      lazy_type_name + strlen(lazy_type_name) + 1;
8705
0
  Symbol result = file()->pool()->CrossLinkOnDemandHelper(
8706
0
      lazy_type_name, type_ == FieldDescriptor::TYPE_ENUM);
8707
0
  if (result.type() == Symbol::MESSAGE) {
8708
0
    type_ = FieldDescriptor::TYPE_MESSAGE;
8709
0
    type_descriptor_.message_type = result.descriptor();
8710
0
  } else if (result.type() == Symbol::ENUM) {
8711
0
    type_ = FieldDescriptor::TYPE_ENUM;
8712
0
    enum_type = type_descriptor_.enum_type = result.enum_descriptor();
8713
0
  }
8714
8715
0
  if (enum_type) {
8716
0
    if (lazy_default_value_enum_name[0] != '\0') {
8717
      // Have to build the full name now instead of at CrossLink time,
8718
      // because enum_type may not be known at the time.
8719
0
      std::string name = enum_type->full_name();
8720
      // Enum values reside in the same scope as the enum type.
8721
0
      std::string::size_type last_dot = name.find_last_of('.');
8722
0
      if (last_dot != std::string::npos) {
8723
0
        name = absl::StrCat(name.substr(0, last_dot), ".",
8724
0
                            lazy_default_value_enum_name);
8725
0
      } else {
8726
0
        name = lazy_default_value_enum_name;
8727
0
      }
8728
0
      Symbol result = file()->pool()->CrossLinkOnDemandHelper(name, true);
8729
0
      default_value_enum_ = result.enum_value_descriptor();
8730
0
    } else {
8731
0
      default_value_enum_ = nullptr;
8732
0
    }
8733
0
    if (!default_value_enum_) {
8734
      // We use the first defined value as the default
8735
      // if a default is not explicitly defined.
8736
0
      ABSL_CHECK(enum_type->value_count());
8737
0
      default_value_enum_ = enum_type->value(0);
8738
0
    }
8739
0
  }
8740
0
}
8741
8742
0
void FieldDescriptor::TypeOnceInit(const FieldDescriptor* to_init) {
8743
0
  to_init->InternalTypeOnceInit();
8744
0
}
8745
8746
// message_type(), enum_type(), default_value_enum(), and type()
8747
// all share the same absl::call_once init path to do lazy
8748
// import building and cross linking of a field of a message.
8749
0
const Descriptor* FieldDescriptor::message_type() const {
8750
0
  if (type_once_) {
8751
0
    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
8752
0
  }
8753
0
  return type_ == TYPE_MESSAGE || type_ == TYPE_GROUP
8754
0
             ? type_descriptor_.message_type
8755
0
             : nullptr;
8756
0
}
8757
8758
0
const EnumDescriptor* FieldDescriptor::enum_type() const {
8759
0
  if (type_once_) {
8760
0
    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
8761
0
  }
8762
0
  return type_ == TYPE_ENUM ? type_descriptor_.enum_type : nullptr;
8763
0
}
8764
8765
0
const EnumValueDescriptor* FieldDescriptor::default_value_enum() const {
8766
0
  if (type_once_) {
8767
0
    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
8768
0
  }
8769
0
  return default_value_enum_;
8770
0
}
8771
8772
0
const std::string& FieldDescriptor::PrintableNameForExtension() const {
8773
0
  const bool is_message_set_extension =
8774
0
      is_extension() &&
8775
0
      containing_type()->options().message_set_wire_format() &&
8776
0
      type() == FieldDescriptor::TYPE_MESSAGE && is_optional() &&
8777
0
      extension_scope() == message_type();
8778
0
  return is_message_set_extension ? message_type()->full_name() : full_name();
8779
0
}
8780
8781
0
void FileDescriptor::InternalDependenciesOnceInit() const {
8782
0
  ABSL_CHECK(finished_building_ == true);
8783
0
  const char* names_ptr = reinterpret_cast<const char*>(dependencies_once_ + 1);
8784
0
  for (int i = 0; i < dependency_count(); i++) {
8785
0
    const char* name = names_ptr;
8786
0
    names_ptr += strlen(name) + 1;
8787
0
    if (name[0] != '\0') {
8788
0
      dependencies_[i] = pool_->FindFileByName(name);
8789
0
    }
8790
0
  }
8791
0
}
8792
8793
0
void FileDescriptor::DependenciesOnceInit(const FileDescriptor* to_init) {
8794
0
  to_init->InternalDependenciesOnceInit();
8795
0
}
8796
8797
0
const FileDescriptor* FileDescriptor::dependency(int index) const {
8798
0
  if (dependencies_once_) {
8799
    // Do once init for all indices, as it's unlikely only a single index would
8800
    // be called, and saves on absl::call_once allocations.
8801
0
    absl::call_once(*dependencies_once_, FileDescriptor::DependenciesOnceInit,
8802
0
                    this);
8803
0
  }
8804
0
  return dependencies_[index];
8805
0
}
8806
8807
0
const Descriptor* MethodDescriptor::input_type() const {
8808
0
  return input_type_.Get(service());
8809
0
}
8810
8811
0
const Descriptor* MethodDescriptor::output_type() const {
8812
0
  return output_type_.Get(service());
8813
0
}
8814
8815
namespace internal {
8816
0
void LazyDescriptor::Set(const Descriptor* descriptor) {
8817
0
  ABSL_CHECK(!once_);
8818
0
  descriptor_ = descriptor;
8819
0
}
8820
8821
void LazyDescriptor::SetLazy(absl::string_view name,
8822
0
                             const FileDescriptor* file) {
8823
  // verify Init() has been called and Set hasn't been called yet.
8824
0
  ABSL_CHECK(!descriptor_);
8825
0
  ABSL_CHECK(!once_);
8826
0
  ABSL_CHECK(file && file->pool_);
8827
0
  ABSL_CHECK(file->pool_->lazily_build_dependencies_);
8828
0
  ABSL_CHECK(!file->finished_building_);
8829
0
  once_ = ::new (file->pool_->tables_->AllocateBytes(static_cast<int>(
8830
0
      sizeof(absl::once_flag) + name.size() + 1))) absl::once_flag{};
8831
0
  char* lazy_name = reinterpret_cast<char*>(once_ + 1);
8832
0
  memcpy(lazy_name, name.data(), name.size());
8833
0
  lazy_name[name.size()] = 0;
8834
0
}
8835
8836
0
void LazyDescriptor::Once(const ServiceDescriptor* service) {
8837
0
  if (once_) {
8838
0
    absl::call_once(*once_, [&] {
8839
0
      auto* file = service->file();
8840
0
      ABSL_CHECK(file->finished_building_);
8841
0
      const char* lazy_name = reinterpret_cast<const char*>(once_ + 1);
8842
0
      descriptor_ =
8843
0
          file->pool_->CrossLinkOnDemandHelper(lazy_name, false).descriptor();
8844
0
    });
8845
0
  }
8846
0
}
8847
8848
namespace cpp {
8849
0
bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) {
8850
0
  return !field->legacy_enum_field_treated_as_closed();
8851
0
}
8852
8853
0
bool HasHasbit(const FieldDescriptor* field) {
8854
0
  return field->has_presence() && !field->real_containing_oneof() &&
8855
0
         !field->options().weak();
8856
0
}
8857
8858
0
static bool FieldEnforceUtf8(const FieldDescriptor* field) {
8859
0
  return true;
8860
0
}
8861
8862
0
static bool FileUtf8Verification(const FileDescriptor* file) {
8863
0
  return true;
8864
0
}
8865
8866
// Which level of UTF-8 enforcemant is placed on this file.
8867
0
Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, bool is_lite) {
8868
0
  if (FileDescriptorLegacy(field->file()).syntax() ==
8869
0
          FileDescriptorLegacy::Syntax::SYNTAX_PROTO3 &&
8870
0
      FieldEnforceUtf8(field)) {
8871
0
    return Utf8CheckMode::kStrict;
8872
0
  } else if (!is_lite && FileUtf8Verification(field->file())) {
8873
0
    return Utf8CheckMode::kVerify;
8874
0
  } else {
8875
0
    return Utf8CheckMode::kNone;
8876
0
  }
8877
0
}
8878
8879
}  // namespace cpp
8880
}  // namespace internal
8881
8882
}  // namespace protobuf
8883
}  // namespace google
8884
8885
#include "google/protobuf/port_undef.inc"