Coverage Report

Created: 2023-11-27 06:16

/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/strings/ascii.h"
61
#include "absl/strings/escaping.h"
62
#include "absl/strings/match.h"
63
#include "absl/strings/str_cat.h"
64
#include "absl/strings/str_format.h"
65
#include "absl/strings/str_join.h"
66
#include "absl/strings/str_split.h"
67
#include "absl/strings/string_view.h"
68
#include "absl/strings/strip.h"
69
#include "absl/strings/substitute.h"
70
#include "absl/synchronization/mutex.h"
71
#include "absl/types/optional.h"
72
#include "google/protobuf/any.h"
73
#include "google/protobuf/descriptor.pb.h"
74
#include "google/protobuf/descriptor_database.h"
75
#include "google/protobuf/descriptor_legacy.h"
76
#include "google/protobuf/dynamic_message.h"
77
#include "google/protobuf/generated_message_util.h"
78
#include "google/protobuf/io/strtod.h"
79
#include "google/protobuf/io/tokenizer.h"
80
#include "google/protobuf/port.h"
81
#include "google/protobuf/repeated_ptr_field.h"
82
#include "google/protobuf/text_format.h"
83
#include "google/protobuf/unknown_field_set.h"
84
85
86
// Must be included last.
87
#include "google/protobuf/port_def.inc"
88
89
namespace google {
90
namespace protobuf {
91
namespace {
92
using ::google::protobuf::internal::DownCast;
93
94
const int kPackageLimit = 100;
95
96
97
0
std::string ToCamelCase(const std::string& input, bool lower_first) {
98
0
  bool capitalize_next = !lower_first;
99
0
  std::string result;
100
0
  result.reserve(input.size());
101
102
0
  for (char character : input) {
103
0
    if (character == '_') {
104
0
      capitalize_next = true;
105
0
    } else if (capitalize_next) {
106
0
      result.push_back(absl::ascii_toupper(character));
107
0
      capitalize_next = false;
108
0
    } else {
109
0
      result.push_back(character);
110
0
    }
111
0
  }
112
113
  // Lower-case the first letter.
114
0
  if (lower_first && !result.empty()) {
115
0
    result[0] = absl::ascii_tolower(result[0]);
116
0
  }
117
118
0
  return result;
119
0
}
120
121
0
std::string ToJsonName(const std::string& input) {
122
0
  bool capitalize_next = false;
123
0
  std::string result;
124
0
  result.reserve(input.size());
125
126
0
  for (char character : input) {
127
0
    if (character == '_') {
128
0
      capitalize_next = true;
129
0
    } else if (capitalize_next) {
130
0
      result.push_back(absl::ascii_toupper(character));
131
0
      capitalize_next = false;
132
0
    } else {
133
0
      result.push_back(character);
134
0
    }
135
0
  }
136
137
0
  return result;
138
0
}
139
140
template <typename OptionsT>
141
0
bool IsLegacyJsonFieldConflictEnabled(const OptionsT& options) {
142
0
#ifdef __GNUC__
143
0
#pragma GCC diagnostic push
144
0
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
145
0
#endif
146
0
  return options.deprecated_legacy_json_field_conflicts();
147
0
#ifdef __GNUC__
148
0
#pragma GCC diagnostic pop
149
0
#endif
150
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&)
151
152
// Backport of fold expressions for the comma operator to C++11.
153
// Usage:  Fold({expr...});
154
// Guaranteed to evaluate left-to-right
155
struct ExpressionEater {
156
  template <typename T>
157
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*&)
158
};
159
0
void Fold(std::initializer_list<ExpressionEater>) {}
160
161
template <int R>
162
0
constexpr size_t RoundUpTo(size_t n) {
163
0
  static_assert((R & (R - 1)) == 0, "Must be power of two");
164
0
  return (n + (R - 1)) & ~(R - 1);
165
0
}
166
167
0
constexpr size_t Max(size_t a, size_t b) { return a > b ? a : b; }
168
template <typename T, typename... Ts>
169
0
constexpr size_t Max(T a, Ts... b) {
170
0
  return Max(a, Max(b...));
171
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)
172
173
template <typename T>
174
0
constexpr size_t EffectiveAlignof() {
175
0
  // `char` is special in that it gets aligned to 8. It is where we drop the
176
0
  // trivial structs.
177
0
  return std::is_same<T, char>::value ? 8 : alignof(T);
178
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>()
179
180
template <int align, typename U, typename... T>
181
using AppendIfAlign =
182
    typename std::conditional<EffectiveAlignof<U>() == align, void (*)(T..., U),
183
                              void (*)(T...)>::type;
184
185
// Metafunction to sort types in descending order of alignment.
186
// Useful for the flat allocator to ensure proper alignment of all elements
187
// without having to add padding.
188
// Instead of implementing a proper sort metafunction we just do a
189
// filter+merge, which is much simpler to write as a metafunction.
190
// We have a fixed set of alignments we can filter on.
191
// For simplicity we use a function pointer as a type list.
192
template <typename In, typename T16, typename T8, typename T4, typename T2,
193
          typename T1>
194
struct TypeListSortImpl;
195
196
template <typename... T16, typename... T8, typename... T4, typename... T2,
197
          typename... T1>
198
struct TypeListSortImpl<void (*)(), void (*)(T16...), void (*)(T8...),
199
                        void (*)(T4...), void (*)(T2...), void (*)(T1...)> {
200
  using type = void (*)(T16..., T8..., T4..., T2..., T1...);
201
};
202
203
template <typename First, typename... Rest, typename... T16, typename... T8,
204
          typename... T4, typename... T2, typename... T1>
205
struct TypeListSortImpl<void (*)(First, Rest...), void (*)(T16...),
206
                        void (*)(T8...), void (*)(T4...), void (*)(T2...),
207
                        void (*)(T1...)> {
208
  using type = typename TypeListSortImpl<
209
      void (*)(Rest...), AppendIfAlign<16, First, T16...>,
210
      AppendIfAlign<8, First, T8...>, AppendIfAlign<4, First, T4...>,
211
      AppendIfAlign<2, First, T2...>, AppendIfAlign<1, First, T1...>>::type;
212
};
213
214
template <typename... T>
215
using SortByAlignment =
216
    typename TypeListSortImpl<void (*)(T...), void (*)(), void (*)(),
217
                              void (*)(), void (*)(), void (*)()>::type;
218
219
template <template <typename...> class C, typename... T>
220
auto ApplyTypeList(void (*)(T...)) -> C<T...>;
221
222
template <typename T>
223
0
constexpr int FindTypeIndex() {
224
0
  return -1;
225
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>()
226
227
template <typename T, typename T1, typename... Ts>
228
0
constexpr int FindTypeIndex() {
229
0
  return std::is_same<T, T1>::value ? 0 : FindTypeIndex<T, Ts...>() + 1;
230
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>()
231
232
// A type to value map, where the possible keys as specified in `Keys...`.
233
// The values for key `K` is `ValueT<K>`
234
template <template <typename> class ValueT, typename... Keys>
235
class TypeMap {
236
 public:
237
  template <typename K>
238
0
  ValueT<K>& Get() {
239
0
    return static_cast<Base<K>&>(payload_).value;
240
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>()
241
242
  template <typename K>
243
0
  const ValueT<K>& Get() const {
244
0
    return static_cast<const Base<K>&>(payload_).value;
245
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
246
247
 private:
248
  template <typename K>
249
  struct Base {
250
    ValueT<K> value{};
251
  };
252
  struct Payload : Base<Keys>... {};
253
  Payload payload_;
254
};
255
256
template <typename T>
257
using IntT = int;
258
template <typename T>
259
using PointerT = T*;
260
261
// Manages an allocation of sequential arrays of type `T...`.
262
// It is more space efficient than storing N (ptr, size) pairs, by storing only
263
// the pointer to the head and the boundaries between the arrays.
264
template <typename... T>
265
class FlatAllocation {
266
 public:
267
  static constexpr size_t kMaxAlign = Max(alignof(T)...);
268
269
0
  FlatAllocation(const TypeMap<IntT, T...>& ends) : ends_(ends) {
270
    // The arrays start just after FlatAllocation, so adjust the ends.
271
0
    Fold({(ends_.template Get<T>() +=
272
0
           RoundUpTo<kMaxAlign>(sizeof(FlatAllocation)))...});
273
0
    Fold({Init<T>()...});
274
0
  }
275
276
0
  void Destroy() {
277
0
    Fold({Destroy<T>()...});
278
0
    internal::SizedDelete(this, total_bytes());
279
0
  }
280
281
  template <int I>
282
  using type = typename std::tuple_element<I, std::tuple<T...>>::type;
283
284
  // Gets a tuple of the head pointers for the arrays
285
0
  TypeMap<PointerT, T...> Pointers() const {
286
0
    TypeMap<PointerT, T...> out;
287
0
    Fold({(out.template Get<T>() = Begin<T>())...});
288
0
    return out;
289
0
  }
290
291
292
 private:
293
  // Total number of bytes used by all arrays.
294
0
  int total_bytes() const {
295
    // Get the last end.
296
0
    return ends_.template Get<typename std::tuple_element<
297
0
        sizeof...(T) - 1, std::tuple<T...>>::type>();
298
0
  }
299
300
301
  template <typename U>
302
0
  int BeginOffset() const {
303
0
    constexpr int type_index = FindTypeIndex<U, T...>();
304
    // Avoid a negative value here to keep it compiling when type_index == 0
305
0
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
306
0
    using PrevType =
307
0
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
308
    // Ensure the types are properly aligned.
309
0
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
310
0
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
311
0
                           : ends_.template Get<PrevType>();
312
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
313
314
  template <typename U>
315
0
  int EndOffset() const {
316
0
    return ends_.template Get<U>();
317
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
318
319
  // Avoid the reinterpret_cast if the array is empty.
320
  // Clang's Control Flow Integrity does not like the cast pointing to memory
321
  // that is not yet initialized to be of that type.
322
  // (from -fsanitize=cfi-unrelated-cast)
323
  template <typename U>
324
0
  U* Begin() const {
325
0
    int begin = BeginOffset<U>(), end = EndOffset<U>();
326
0
    if (begin == end) return nullptr;
327
0
    return reinterpret_cast<U*>(data() + begin);
328
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
329
330
  template <typename U>
331
0
  U* End() const {
332
0
    int begin = BeginOffset<U>(), end = EndOffset<U>();
333
0
    if (begin == end) return nullptr;
334
0
    return reinterpret_cast<U*>(data() + end);
335
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
336
337
  template <typename U>
338
0
  bool Init() {
339
    // Skip for the `char` block. No need to zero initialize it.
340
0
    if (std::is_same<U, char>::value) return true;
341
0
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
342
0
         p != end; p += sizeof(U)) {
343
0
      ::new (p) U{};
344
0
    }
345
0
    return true;
346
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>()
347
348
  template <typename U>
349
0
  bool Destroy() {
350
0
    if (std::is_trivially_destructible<U>::value) return true;
351
0
    for (U* it = Begin<U>(), *end = End<U>(); it != end; ++it) {
352
0
      it->~U();
353
0
    }
354
0
    return true;
355
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>()
356
357
0
  char* data() const {
358
0
    return const_cast<char*>(reinterpret_cast<const char*>(this));
359
0
  }
360
361
  TypeMap<IntT, T...> ends_;
362
};
363
364
template <typename... T>
365
0
TypeMap<IntT, T...> CalculateEnds(const TypeMap<IntT, T...>& sizes) {
366
0
  int total = 0;
367
0
  TypeMap<IntT, T...> out;
368
0
  Fold({(out.template Get<T>() = total +=
369
0
         sizeof(T) * sizes.template Get<T>())...});
370
0
  return out;
371
0
}
372
373
// The implementation for FlatAllocator below.
374
// This separate class template makes it easier to have methods that fold on
375
// `T...`.
376
template <typename... T>
377
class FlatAllocatorImpl {
378
 public:
379
  using Allocation = FlatAllocation<T...>;
380
381
  template <typename U>
382
0
  void PlanArray(int array_size) {
383
    // We can't call PlanArray after FinalizePlanning has been called.
384
0
    ABSL_CHECK(!has_allocated());
385
0
    if (std::is_trivially_destructible<U>::value) {
386
      // Trivial types are aligned to 8 bytes.
387
0
      static_assert(alignof(U) <= 8, "");
388
0
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
389
0
    } else {
390
      // Since we can't use `if constexpr`, just make the expression compile
391
      // when this path is not taken.
392
0
      using TypeToUse =
393
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
394
0
                                    char, U>::type;
395
0
      total_.template Get<TypeToUse>() += array_size;
396
0
    }
397
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)
398
399
  template <typename U>
400
0
  U* AllocateArray(int array_size) {
401
0
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
402
0
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
403
404
    // We can only allocate after FinalizePlanning has been called.
405
0
    ABSL_CHECK(has_allocated());
406
407
0
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
408
0
    int& used = used_.template Get<TypeToUse>();
409
0
    U* res = reinterpret_cast<U*>(data + used);
410
0
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
411
0
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
412
0
    return res;
413
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)
414
415
  template <typename... In>
416
0
  const std::string* AllocateStrings(In&&... in) {
417
0
    std::string* strings = AllocateArray<std::string>(sizeof...(in));
418
0
    std::string* res = strings;
419
0
    Fold({(*strings++ = std::string(std::forward<In>(in)))...});
420
0
    return res;
421
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<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_string_view<char, std::__1::char_traits<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<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<std::__1::basic_string_view<char, std::__1::char_traits<char> >&, std::__1::basic_string_view<char, std::__1::char_traits<char> >&>(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, std::__1::basic_string_view<char, std::__1::char_traits<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<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<std::__1::basic_string_view<char, std::__1::char_traits<char> >&>(std::__1::basic_string_view<char, std::__1::char_traits<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> > 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> >&)
422
423
  // Allocate all 5 names of the field:
424
  // name, full name, lowercase, camelcase and json.
425
  // It will dedup the strings when possible.
426
  // The resulting array contains `name` at index 0, `full_name` at index 1
427
  // and the other 3 indices are specified in the result.
428
  void PlanFieldNames(const std::string& name,
429
0
                      const std::string* opt_json_name) {
430
0
    ABSL_CHECK(!has_allocated());
431
432
    // Fast path for snake_case names, which follow the style guide.
433
0
    if (opt_json_name == nullptr) {
434
0
      switch (GetFieldNameCase(name)) {
435
0
        case FieldNameCase::kAllLower:
436
          // Case 1: they are all the same.
437
0
          return PlanArray<std::string>(2);
438
0
        case FieldNameCase::kSnakeCase:
439
          // Case 2: name==lower, camel==json
440
0
          return PlanArray<std::string>(3);
441
0
        default:
442
0
          break;
443
0
      }
444
0
    }
445
446
0
    std::string lowercase_name = name;
447
0
    absl::AsciiStrToLower(&lowercase_name);
448
449
0
    std::string camelcase_name = ToCamelCase(name, /* lower_first = */ true);
450
0
    std::string json_name =
451
0
        opt_json_name != nullptr ? *opt_json_name : ToJsonName(name);
452
453
0
    absl::string_view all_names[] = {name, lowercase_name, camelcase_name,
454
0
                                     json_name};
455
0
    std::sort(all_names, all_names + 4);
456
0
    int unique =
457
0
        static_cast<int>(std::unique(all_names, all_names + 4) - all_names);
458
459
0
    PlanArray<std::string>(unique + 1);
460
0
  }
461
462
  struct FieldNamesResult {
463
    const std::string* array;
464
    int lowercase_index;
465
    int camelcase_index;
466
    int json_index;
467
  };
468
  FieldNamesResult AllocateFieldNames(const std::string& name,
469
                                      const std::string& scope,
470
0
                                      const std::string* opt_json_name) {
471
0
    ABSL_CHECK(has_allocated());
472
473
0
    std::string full_name =
474
0
        scope.empty() ? name : absl::StrCat(scope, ".", name);
475
476
    // Fast path for snake_case names, which follow the style guide.
477
0
    if (opt_json_name == nullptr) {
478
0
      switch (GetFieldNameCase(name)) {
479
0
        case FieldNameCase::kAllLower:
480
          // Case 1: they are all the same.
481
0
          return {AllocateStrings(name, std::move(full_name)), 0, 0, 0};
482
0
        case FieldNameCase::kSnakeCase:
483
          // Case 2: name==lower, camel==json
484
0
          return {AllocateStrings(name, std::move(full_name),
485
0
                                  ToCamelCase(name, /* lower_first = */ true)),
486
0
                  0, 2, 2};
487
0
        default:
488
0
          break;
489
0
      }
490
0
    }
491
492
0
    std::vector<std::string> names;
493
0
    names.push_back(name);
494
0
    names.push_back(std::move(full_name));
495
496
0
    const auto push_name = [&](std::string new_name) {
497
0
      for (size_t i = 0; i < names.size(); ++i) {
498
        // Do not compare the full_name. It is unlikely to match, except in
499
        // custom json_name. We are not taking this into account in
500
        // PlanFieldNames so better to not try it.
501
0
        if (i == 1) continue;
502
0
        if (names[i] == new_name) return i;
503
0
      }
504
0
      names.push_back(std::move(new_name));
505
0
      return names.size() - 1;
506
0
    };
507
508
0
    FieldNamesResult result{nullptr, 0, 0, 0};
509
510
0
    std::string lowercase_name = name;
511
0
    absl::AsciiStrToLower(&lowercase_name);
512
0
    result.lowercase_index = push_name(std::move(lowercase_name));
513
0
    result.camelcase_index =
514
0
        push_name(ToCamelCase(name, /* lower_first = */ true));
515
0
    result.json_index =
516
0
        push_name(opt_json_name != nullptr ? *opt_json_name : ToJsonName(name));
517
518
0
    std::string* all_names = AllocateArray<std::string>(names.size());
519
0
    result.array = all_names;
520
0
    std::move(names.begin(), names.end(), all_names);
521
522
0
    return result;
523
0
  }
524
525
  template <typename Alloc>
526
0
  void FinalizePlanning(Alloc& alloc) {
527
0
    ABSL_CHECK(!has_allocated());
528
529
0
    pointers_ = alloc->CreateFlatAlloc(total_)->Pointers();
530
531
0
    ABSL_CHECK(has_allocated());
532
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&)
533
534
0
  void ExpectConsumed() const {
535
    // We verify that we consumed all the memory requested if there was no
536
    // error in processing.
537
0
    Fold({ExpectConsumed<T>()...});
538
0
  }
539
540
 private:
541
0
  bool has_allocated() const {
542
0
    return pointers_.template Get<char>() != nullptr;
543
0
  }
544
545
0
  static bool IsLower(char c) { return 'a' <= c && c <= 'z'; }
546
0
  static bool IsDigit(char c) { return '0' <= c && c <= '9'; }
547
0
  static bool IsLowerOrDigit(char c) { return IsLower(c) || IsDigit(c); }
548
549
  enum class FieldNameCase { kAllLower, kSnakeCase, kOther };
550
0
  FieldNameCase GetFieldNameCase(const std::string& name) {
551
0
    if (!IsLower(name[0])) return FieldNameCase::kOther;
552
0
    FieldNameCase best = FieldNameCase::kAllLower;
553
0
    for (char c : name) {
554
0
      if (IsLowerOrDigit(c)) {
555
        // nothing to do
556
0
      } else if (c == '_') {
557
0
        best = FieldNameCase::kSnakeCase;
558
0
      } else {
559
0
        return FieldNameCase::kOther;
560
0
      }
561
0
    }
562
0
    return best;
563
0
  }
564
565
  template <typename U>
566
0
  bool ExpectConsumed() const {
567
0
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
568
0
    return true;
569
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
570
571
  TypeMap<PointerT, T...> pointers_;
572
  TypeMap<IntT, T...> total_;
573
  TypeMap<IntT, T...> used_;
574
};
575
576
}  // namespace
577
578
class Symbol {
579
 public:
580
  enum Type {
581
    NULL_SYMBOL,
582
    MESSAGE,
583
    FIELD,
584
    ONEOF,
585
    ENUM,
586
    ENUM_VALUE,
587
    ENUM_VALUE_OTHER_PARENT,
588
    SERVICE,
589
    METHOD,
590
    FULL_PACKAGE,
591
    SUB_PACKAGE,
592
  };
593
594
0
  Symbol() {
595
0
    static constexpr internal::SymbolBase null_symbol{};
596
0
    static_assert(null_symbol.symbol_type_ == NULL_SYMBOL, "");
597
    // Initialize with a sentinel to make sure `ptr_` is never null.
598
0
    ptr_ = &null_symbol;
599
0
  }
600
601
  // Every object we store derives from internal::SymbolBase, where we store the
602
  // symbol type enum.
603
  // Storing in the object can be done without using more space in most cases,
604
  // while storing it in the Symbol type would require 8 bytes.
605
#define DEFINE_MEMBERS(TYPE, TYPE_CONSTANT, FIELD)                             \
606
0
  explicit Symbol(TYPE* value) : ptr_(value) {                                 \
607
0
    value->symbol_type_ = TYPE_CONSTANT;                                       \
608
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*)
609
0
  const TYPE* FIELD() const {                                                  \
610
0
    return type() == TYPE_CONSTANT ? static_cast<const TYPE*>(ptr_) : nullptr; \
611
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
612
613
  DEFINE_MEMBERS(Descriptor, MESSAGE, descriptor)
614
  DEFINE_MEMBERS(FieldDescriptor, FIELD, field_descriptor)
615
  DEFINE_MEMBERS(OneofDescriptor, ONEOF, oneof_descriptor)
616
  DEFINE_MEMBERS(EnumDescriptor, ENUM, enum_descriptor)
617
  DEFINE_MEMBERS(ServiceDescriptor, SERVICE, service_descriptor)
618
  DEFINE_MEMBERS(MethodDescriptor, METHOD, method_descriptor)
619
  DEFINE_MEMBERS(FileDescriptor, FULL_PACKAGE, file_descriptor)
620
621
  // We use a special node for subpackage FileDescriptor.
622
  // It is potentially added to the table with multiple different names, so we
623
  // need a separate place to put the name.
624
  struct Subpackage : internal::SymbolBase {
625
    int name_size;
626
    const FileDescriptor* file;
627
  };
628
  DEFINE_MEMBERS(Subpackage, SUB_PACKAGE, sub_package_file_descriptor)
629
630
  // Enum values have two different parents.
631
  // We use two different identitied for the same object to determine the two
632
  // different insertions in the map.
633
0
  static Symbol EnumValue(EnumValueDescriptor* value, int n) {
634
0
    Symbol s;
635
0
    internal::SymbolBase* ptr;
636
0
    if (n == 0) {
637
0
      ptr = static_cast<internal::SymbolBaseN<0>*>(value);
638
0
      ptr->symbol_type_ = ENUM_VALUE;
639
0
    } else {
640
0
      ptr = static_cast<internal::SymbolBaseN<1>*>(value);
641
0
      ptr->symbol_type_ = ENUM_VALUE_OTHER_PARENT;
642
0
    }
643
0
    s.ptr_ = ptr;
644
0
    return s;
645
0
  }
646
647
0
  const EnumValueDescriptor* enum_value_descriptor() const {
648
0
    return type() == ENUM_VALUE
649
0
               ? static_cast<const EnumValueDescriptor*>(
650
0
                     static_cast<const internal::SymbolBaseN<0>*>(ptr_))
651
0
           : type() == ENUM_VALUE_OTHER_PARENT
652
0
               ? static_cast<const EnumValueDescriptor*>(
653
0
                     static_cast<const internal::SymbolBaseN<1>*>(ptr_))
654
0
               : nullptr;
655
0
  }
656
657
#undef DEFINE_MEMBERS
658
659
0
  Type type() const { return static_cast<Type>(ptr_->symbol_type_); }
660
0
  bool IsNull() const { return type() == NULL_SYMBOL; }
661
0
  bool IsType() const { return type() == MESSAGE || type() == ENUM; }
662
0
  bool IsAggregate() const {
663
0
    return IsType() || IsPackage() || type() == SERVICE;
664
0
  }
665
0
  bool IsPackage() const {
666
0
    return type() == FULL_PACKAGE || type() == SUB_PACKAGE;
667
0
  }
668
669
0
  const FileDescriptor* GetFile() const {
670
0
    switch (type()) {
671
0
      case MESSAGE:
672
0
        return descriptor()->file();
673
0
      case FIELD:
674
0
        return field_descriptor()->file();
675
0
      case ONEOF:
676
0
        return oneof_descriptor()->containing_type()->file();
677
0
      case ENUM:
678
0
        return enum_descriptor()->file();
679
0
      case ENUM_VALUE:
680
0
        return enum_value_descriptor()->type()->file();
681
0
      case SERVICE:
682
0
        return service_descriptor()->file();
683
0
      case METHOD:
684
0
        return method_descriptor()->service()->file();
685
0
      case FULL_PACKAGE:
686
0
        return file_descriptor();
687
0
      case SUB_PACKAGE:
688
0
        return sub_package_file_descriptor()->file;
689
0
      default:
690
0
        return nullptr;
691
0
    }
692
0
  }
693
694
0
  absl::string_view full_name() const {
695
0
    switch (type()) {
696
0
      case MESSAGE:
697
0
        return descriptor()->full_name();
698
0
      case FIELD:
699
0
        return field_descriptor()->full_name();
700
0
      case ONEOF:
701
0
        return oneof_descriptor()->full_name();
702
0
      case ENUM:
703
0
        return enum_descriptor()->full_name();
704
0
      case ENUM_VALUE:
705
0
        return enum_value_descriptor()->full_name();
706
0
      case SERVICE:
707
0
        return service_descriptor()->full_name();
708
0
      case METHOD:
709
0
        return method_descriptor()->full_name();
710
0
      case FULL_PACKAGE:
711
0
        return file_descriptor()->package();
712
0
      case SUB_PACKAGE:
713
0
        return absl::string_view(sub_package_file_descriptor()->file->package())
714
0
            .substr(0, sub_package_file_descriptor()->name_size);
715
0
      default:
716
0
        ABSL_CHECK(false);
717
0
    }
718
0
    return "";
719
0
  }
720
721
0
  std::pair<const void*, absl::string_view> parent_name_key() const {
722
0
    const auto or_file = [&](const void* p) { return p ? p : GetFile(); };
723
0
    switch (type()) {
724
0
      case MESSAGE:
725
0
        return {or_file(descriptor()->containing_type()), descriptor()->name()};
726
0
      case FIELD: {
727
0
        auto* field = field_descriptor();
728
0
        return {or_file(field->is_extension() ? field->extension_scope()
729
0
                                              : field->containing_type()),
730
0
                field->name()};
731
0
      }
732
0
      case ONEOF:
733
0
        return {oneof_descriptor()->containing_type(),
734
0
                oneof_descriptor()->name()};
735
0
      case ENUM:
736
0
        return {or_file(enum_descriptor()->containing_type()),
737
0
                enum_descriptor()->name()};
738
0
      case ENUM_VALUE:
739
0
        return {or_file(enum_value_descriptor()->type()->containing_type()),
740
0
                enum_value_descriptor()->name()};
741
0
      case ENUM_VALUE_OTHER_PARENT:
742
0
        return {enum_value_descriptor()->type(),
743
0
                enum_value_descriptor()->name()};
744
0
      case SERVICE:
745
0
        return {GetFile(), service_descriptor()->name()};
746
0
      case METHOD:
747
0
        return {method_descriptor()->service(), method_descriptor()->name()};
748
0
      default:
749
0
        ABSL_CHECK(false);
750
0
    }
751
0
    return {};
752
0
  }
753
754
 private:
755
  const internal::SymbolBase* ptr_;
756
};
757
758
const FieldDescriptor::CppType
759
    FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = {
760
        static_cast<CppType>(0),  // 0 is reserved for errors
761
762
        CPPTYPE_DOUBLE,   // TYPE_DOUBLE
763
        CPPTYPE_FLOAT,    // TYPE_FLOAT
764
        CPPTYPE_INT64,    // TYPE_INT64
765
        CPPTYPE_UINT64,   // TYPE_UINT64
766
        CPPTYPE_INT32,    // TYPE_INT32
767
        CPPTYPE_UINT64,   // TYPE_FIXED64
768
        CPPTYPE_UINT32,   // TYPE_FIXED32
769
        CPPTYPE_BOOL,     // TYPE_BOOL
770
        CPPTYPE_STRING,   // TYPE_STRING
771
        CPPTYPE_MESSAGE,  // TYPE_GROUP
772
        CPPTYPE_MESSAGE,  // TYPE_MESSAGE
773
        CPPTYPE_STRING,   // TYPE_BYTES
774
        CPPTYPE_UINT32,   // TYPE_UINT32
775
        CPPTYPE_ENUM,     // TYPE_ENUM
776
        CPPTYPE_INT32,    // TYPE_SFIXED32
777
        CPPTYPE_INT64,    // TYPE_SFIXED64
778
        CPPTYPE_INT32,    // TYPE_SINT32
779
        CPPTYPE_INT64,    // TYPE_SINT64
780
};
781
782
const char* const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = {
783
    "ERROR",  // 0 is reserved for errors
784
785
    "double",    // TYPE_DOUBLE
786
    "float",     // TYPE_FLOAT
787
    "int64",     // TYPE_INT64
788
    "uint64",    // TYPE_UINT64
789
    "int32",     // TYPE_INT32
790
    "fixed64",   // TYPE_FIXED64
791
    "fixed32",   // TYPE_FIXED32
792
    "bool",      // TYPE_BOOL
793
    "string",    // TYPE_STRING
794
    "group",     // TYPE_GROUP
795
    "message",   // TYPE_MESSAGE
796
    "bytes",     // TYPE_BYTES
797
    "uint32",    // TYPE_UINT32
798
    "enum",      // TYPE_ENUM
799
    "sfixed32",  // TYPE_SFIXED32
800
    "sfixed64",  // TYPE_SFIXED64
801
    "sint32",    // TYPE_SINT32
802
    "sint64",    // TYPE_SINT64
803
};
804
805
const char* const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
806
    "ERROR",  // 0 is reserved for errors
807
808
    "int32",    // CPPTYPE_INT32
809
    "int64",    // CPPTYPE_INT64
810
    "uint32",   // CPPTYPE_UINT32
811
    "uint64",   // CPPTYPE_UINT64
812
    "double",   // CPPTYPE_DOUBLE
813
    "float",    // CPPTYPE_FLOAT
814
    "bool",     // CPPTYPE_BOOL
815
    "enum",     // CPPTYPE_ENUM
816
    "string",   // CPPTYPE_STRING
817
    "message",  // CPPTYPE_MESSAGE
818
};
819
820
const char* const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
821
    "ERROR",  // 0 is reserved for errors
822
823
    "optional",  // LABEL_OPTIONAL
824
    "required",  // LABEL_REQUIRED
825
    "repeated",  // LABEL_REPEATED
826
};
827
828
PROTOBUF_IGNORE_DEPRECATION_START
829
0
const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) {
830
0
  switch (syntax) {
831
0
    case SYNTAX_PROTO2:
832
0
      return "proto2";
833
0
    case SYNTAX_PROTO3:
834
0
      return "proto3";
835
0
    case SYNTAX_UNKNOWN:
836
0
      return "unknown";
837
0
  }
838
0
  ABSL_LOG(FATAL) << "can't reach here.";
839
0
  return nullptr;
840
0
}
841
PROTOBUF_IGNORE_DEPRECATION_STOP
842
843
static const char* const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty";
844
845
#if !defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)
846
const int FieldDescriptor::kMaxNumber;
847
const int FieldDescriptor::kFirstReservedNumber;
848
const int FieldDescriptor::kLastReservedNumber;
849
#endif
850
851
namespace {
852
853
0
std::string EnumValueToPascalCase(const std::string& input) {
854
0
  bool next_upper = true;
855
0
  std::string result;
856
0
  result.reserve(input.size());
857
858
0
  for (char character : input) {
859
0
    if (character == '_') {
860
0
      next_upper = true;
861
0
    } else {
862
0
      if (next_upper) {
863
0
        result.push_back(absl::ascii_toupper(character));
864
0
      } else {
865
0
        result.push_back(absl::ascii_tolower(character));
866
0
      }
867
0
      next_upper = false;
868
0
    }
869
0
  }
870
871
0
  return result;
872
0
}
873
874
// Class to remove an enum prefix from enum values.
875
class PrefixRemover {
876
 public:
877
0
  PrefixRemover(absl::string_view prefix) {
878
    // Strip underscores and lower-case the prefix.
879
0
    for (char character : prefix) {
880
0
      if (character != '_') {
881
0
        prefix_ += absl::ascii_tolower(character);
882
0
      }
883
0
    }
884
0
  }
885
886
  // Tries to remove the enum prefix from this enum value.
887
  // If this is not possible, returns the input verbatim.
888
0
  std::string MaybeRemove(absl::string_view str) {
889
    // We can't just lowercase and strip str and look for a prefix.
890
    // We need to properly recognize the difference between:
891
    //
892
    //   enum Foo {
893
    //     FOO_BAR_BAZ = 0;
894
    //     FOO_BARBAZ = 1;
895
    //   }
896
    //
897
    // This is acceptable (though perhaps not advisable) because even when
898
    // we PascalCase, these two will still be distinct (BarBaz vs. Barbaz).
899
0
    size_t i, j;
900
901
    // Skip past prefix_ in str if we can.
902
0
    for (i = 0, j = 0; i < str.size() && j < prefix_.size(); i++) {
903
0
      if (str[i] == '_') {
904
0
        continue;
905
0
      }
906
907
0
      if (absl::ascii_tolower(str[i]) != prefix_[j++]) {
908
0
        return std::string(str);
909
0
      }
910
0
    }
911
912
    // If we didn't make it through the prefix, we've failed to strip the
913
    // prefix.
914
0
    if (j < prefix_.size()) {
915
0
      return std::string(str);
916
0
    }
917
918
    // Skip underscores between prefix and further characters.
919
0
    while (i < str.size() && str[i] == '_') {
920
0
      i++;
921
0
    }
922
923
    // Enum label can't be the empty string.
924
0
    if (i == str.size()) {
925
0
      return std::string(str);
926
0
    }
927
928
    // We successfully stripped the prefix.
929
0
    str.remove_prefix(i);
930
0
    return std::string(str);
931
0
  }
932
933
 private:
934
  std::string prefix_;
935
};
936
937
// A DescriptorPool contains a bunch of hash-maps to implement the
938
// various Find*By*() methods.  Since hashtable lookups are O(1), it's
939
// most efficient to construct a fixed set of large hash-maps used by
940
// all objects in the pool rather than construct one or more small
941
// hash-maps for each object.
942
//
943
// The keys to these hash-maps are (parent, name) or (parent, number) pairs.
944
struct FullNameQuery {
945
  absl::string_view query;
946
0
  absl::string_view full_name() const { return query; }
947
};
948
struct SymbolByFullNameHash {
949
  using is_transparent = void;
950
951
  template <typename T>
952
0
  size_t operator()(const T& s) const {
953
0
    return absl::HashOf(s.full_name());
954
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
955
};
956
struct SymbolByFullNameEq {
957
  using is_transparent = void;
958
959
  template <typename T, typename U>
960
0
  bool operator()(const T& a, const U& b) const {
961
0
    return a.full_name() == b.full_name();
962
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
963
};
964
using SymbolsByNameSet =
965
    absl::flat_hash_set<Symbol, SymbolByFullNameHash, SymbolByFullNameEq>;
966
967
struct ParentNameQuery {
968
  std::pair<const void*, absl::string_view> query;
969
0
  std::pair<const void*, absl::string_view> parent_name_key() const {
970
0
    return query;
971
0
  }
972
};
973
struct SymbolByParentHash {
974
  using is_transparent = void;
975
976
  template <typename T>
977
0
  size_t operator()(const T& s) const {
978
0
    return absl::HashOf(s.parent_name_key());
979
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
980
};
981
struct SymbolByParentEq {
982
  using is_transparent = void;
983
984
  template <typename T, typename U>
985
0
  bool operator()(const T& a, const U& b) const {
986
0
    return a.parent_name_key() == b.parent_name_key();
987
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
988
};
989
using SymbolsByParentSet =
990
    absl::flat_hash_set<Symbol, SymbolByParentHash, SymbolByParentEq>;
991
992
template <typename DescriptorT>
993
struct DescriptorsByNameHash {
994
  using is_transparent = void;
995
996
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()(std::__1::basic_string_view<char, std::__1::char_traits<char> >) const
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameHash<google::protobuf::Descriptor>::operator()(std::__1::basic_string_view<char, std::__1::char_traits<char> >) const
997
998
0
  size_t operator()(const DescriptorT* file) const {
999
0
    return absl::HashOf(file->name());
1000
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
1001
};
1002
1003
template <typename DescriptorT>
1004
struct DescriptorsByNameEq {
1005
  using is_transparent = void;
1006
1007
  bool operator()(absl::string_view lhs, absl::string_view rhs) const {
1008
    return lhs == rhs;
1009
  }
1010
  bool operator()(absl::string_view lhs, const DescriptorT* rhs) const {
1011
    return lhs == rhs->name();
1012
  }
1013
0
  bool operator()(const DescriptorT* lhs, absl::string_view rhs) const {
1014
0
    return lhs->name() == rhs;
1015
0
  }
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameEq<google::protobuf::FileDescriptor>::operator()(google::protobuf::FileDescriptor const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >) const
Unexecuted instantiation: descriptor.cc:google::protobuf::(anonymous namespace)::DescriptorsByNameEq<google::protobuf::Descriptor>::operator()(google::protobuf::Descriptor const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >) const
1016
0
  bool operator()(const DescriptorT* lhs, const DescriptorT* rhs) const {
1017
0
    return lhs == rhs || lhs->name() == rhs->name();
1018
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
1019
};
1020
1021
template <typename DescriptorT>
1022
using DescriptorsByNameSet =
1023
    absl::flat_hash_set<const DescriptorT*, DescriptorsByNameHash<DescriptorT>,
1024
                        DescriptorsByNameEq<DescriptorT>>;
1025
1026
using FieldsByNameMap =
1027
    absl::flat_hash_map<std::pair<const void*, absl::string_view>,
1028
                        const FieldDescriptor*>;
1029
1030
struct ParentNumberQuery {
1031
  std::pair<const void*, int> query;
1032
};
1033
0
std::pair<const void*, int> ObjectToParentNumber(const FieldDescriptor* field) {
1034
0
  return {field->containing_type(), field->number()};
1035
0
}
1036
std::pair<const void*, int> ObjectToParentNumber(
1037
0
    const EnumValueDescriptor* enum_value) {
1038
0
  return {enum_value->type(), enum_value->number()};
1039
0
}
1040
0
std::pair<const void*, int> ObjectToParentNumber(ParentNumberQuery query) {
1041
0
  return query.query;
1042
0
}
1043
struct ParentNumberHash {
1044
  using is_transparent = void;
1045
1046
  template <typename T>
1047
0
  size_t operator()(const T& t) const {
1048
0
    return absl::HashOf(ObjectToParentNumber(t));
1049
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
1050
};
1051
struct ParentNumberEq {
1052
  using is_transparent = void;
1053
1054
  template <typename T, typename U>
1055
0
  bool operator()(const T& a, const U& b) const {
1056
0
    return ObjectToParentNumber(a) == ObjectToParentNumber(b);
1057
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
1058
};
1059
using FieldsByNumberSet = absl::flat_hash_set<const FieldDescriptor*,
1060
                                              ParentNumberHash, ParentNumberEq>;
1061
using EnumValuesByNumberSet =
1062
    absl::flat_hash_set<const EnumValueDescriptor*, ParentNumberHash,
1063
                        ParentNumberEq>;
1064
1065
// This is a map rather than a hash-map, since we use it to iterate
1066
// through all the extensions that extend a given Descriptor, and an
1067
// ordered data structure that implements lower_bound is convenient
1068
// for that.
1069
using ExtensionsGroupedByDescriptorMap =
1070
    absl::btree_map<std::pair<const Descriptor*, int>, const FieldDescriptor*>;
1071
using LocationsByPathMap =
1072
    absl::flat_hash_map<std::string, const SourceCodeInfo_Location*>;
1073
1074
0
absl::flat_hash_set<std::string>* NewAllowedProto3Extendee() {
1075
0
  const char* kOptionNames[] = {
1076
0
      "FileOptions",   "MessageOptions",   "FieldOptions",
1077
0
      "EnumOptions",   "EnumValueOptions", "ServiceOptions",
1078
0
      "MethodOptions", "OneofOptions",     "ExtensionRangeOptions"};
1079
0
  auto allowed_proto3_extendees = new absl::flat_hash_set<std::string>();
1080
0
  allowed_proto3_extendees->reserve(sizeof(kOptionNames) /
1081
0
                                    sizeof(kOptionNames[0]));
1082
1083
0
  for (const char* option_name : kOptionNames) {
1084
    // descriptor.proto has a different package name in opensource. We allow
1085
    // both so the opensource protocol compiler can also compile internal
1086
    // proto3 files with custom options. See: b/27567912
1087
0
    allowed_proto3_extendees->insert(std::string("google.protobuf.") +
1088
0
                                     option_name);
1089
    // Split the word to trick the opensource processing scripts so they
1090
    // will keep the original package name.
1091
0
    allowed_proto3_extendees->insert(std::string("proto2.") + option_name);
1092
0
  }
1093
0
  return allowed_proto3_extendees;
1094
0
}
1095
1096
// Checks whether the extendee type is allowed in proto3.
1097
// Only extensions to descriptor options are allowed. We use name comparison
1098
// instead of comparing the descriptor directly because the extensions may be
1099
// defined in a different pool.
1100
0
bool AllowedExtendeeInProto3(const std::string& name) {
1101
0
  static auto allowed_proto3_extendees =
1102
0
      internal::OnShutdownDelete(NewAllowedProto3Extendee());
1103
0
  return allowed_proto3_extendees->find(name) !=
1104
0
         allowed_proto3_extendees->end();
1105
0
}
1106
}  // anonymous namespace
1107
1108
// Contains tables specific to a particular file.  These tables are not
1109
// modified once the file has been constructed, so they need not be
1110
// protected by a mutex.  This makes operations that depend only on the
1111
// contents of a single file -- e.g. Descriptor::FindFieldByName() --
1112
// lock-free.
1113
//
1114
// For historical reasons, the definitions of the methods of
1115
// FileDescriptorTables and DescriptorPool::Tables are interleaved below.
1116
// These used to be a single class.
1117
class FileDescriptorTables {
1118
 public:
1119
  FileDescriptorTables();
1120
  ~FileDescriptorTables();
1121
1122
  // Empty table, used with placeholder files.
1123
  inline static const FileDescriptorTables& GetEmptyInstance();
1124
1125
  // -----------------------------------------------------------------
1126
  // Finding items.
1127
1128
  // Returns a null Symbol (symbol.IsNull() is true) if not found.
1129
  // TODO(sbenza): All callers to this function know the type they are looking
1130
  // for. If we propagate that information statically we can make the query
1131
  // faster.
1132
  inline Symbol FindNestedSymbol(const void* parent,
1133
                                 absl::string_view name) const;
1134
1135
  // These return nullptr if not found.
1136
  inline const FieldDescriptor* FindFieldByNumber(const Descriptor* parent,
1137
                                                  int number) const;
1138
  inline const FieldDescriptor* FindFieldByLowercaseName(
1139
      const void* parent, absl::string_view lowercase_name) const;
1140
  inline const FieldDescriptor* FindFieldByCamelcaseName(
1141
      const void* parent, absl::string_view camelcase_name) const;
1142
  inline const EnumValueDescriptor* FindEnumValueByNumber(
1143
      const EnumDescriptor* parent, int number) const;
1144
  // This creates a new EnumValueDescriptor if not found, in a thread-safe way.
1145
  inline const EnumValueDescriptor* FindEnumValueByNumberCreatingIfUnknown(
1146
      const EnumDescriptor* parent, int number) const;
1147
1148
  // -----------------------------------------------------------------
1149
  // Adding items.
1150
1151
  // These add items to the corresponding tables.  They return false if
1152
  // the key already exists in the table.
1153
  bool AddAliasUnderParent(const void* parent, absl::string_view name,
1154
                           Symbol symbol);
1155
  bool AddFieldByNumber(FieldDescriptor* field);
1156
  bool AddEnumValueByNumber(EnumValueDescriptor* value);
1157
1158
  // Populates p->first->locations_by_path_ from p->second.
1159
  // Unusual signature dictated by absl::call_once.
1160
  static void BuildLocationsByPath(
1161
      std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p);
1162
1163
  // Returns the location denoted by the specified path through info,
1164
  // or nullptr if not found.
1165
  // The value of info must be that of the corresponding FileDescriptor.
1166
  // (Conceptually a pure function, but stateful as an optimisation.)
1167
  const SourceCodeInfo_Location* GetSourceLocation(
1168
      const std::vector<int>& path, const SourceCodeInfo* info) const;
1169
1170
  // Must be called after BuildFileImpl(), even if the build failed and
1171
  // we are going to roll back to the last checkpoint.
1172
  void FinalizeTables();
1173
1174
 private:
1175
  const void* FindParentForFieldsByMap(const FieldDescriptor* field) const;
1176
  static void FieldsByLowercaseNamesLazyInitStatic(
1177
      const FileDescriptorTables* tables);
1178
  void FieldsByLowercaseNamesLazyInitInternal() const;
1179
  static void FieldsByCamelcaseNamesLazyInitStatic(
1180
      const FileDescriptorTables* tables);
1181
  void FieldsByCamelcaseNamesLazyInitInternal() const;
1182
1183
  SymbolsByParentSet symbols_by_parent_;
1184
  mutable absl::once_flag fields_by_lowercase_name_once_;
1185
  mutable absl::once_flag fields_by_camelcase_name_once_;
1186
  // Make these fields atomic to avoid race conditions with
1187
  // GetEstimatedOwnedMemoryBytesSize. Once the pointer is set the map won't
1188
  // change anymore.
1189
  mutable std::atomic<const FieldsByNameMap*> fields_by_lowercase_name_{};
1190
  mutable std::atomic<const FieldsByNameMap*> fields_by_camelcase_name_{};
1191
  FieldsByNumberSet fields_by_number_;  // Not including extensions.
1192
  EnumValuesByNumberSet enum_values_by_number_;
1193
  mutable EnumValuesByNumberSet unknown_enum_values_by_number_
1194
      PROTOBUF_GUARDED_BY(unknown_enum_values_mu_);
1195
1196
  // Populated on first request to save space, hence constness games.
1197
  mutable absl::once_flag locations_by_path_once_;
1198
  mutable LocationsByPathMap locations_by_path_;
1199
1200
  // Mutex to protect the unknown-enum-value map due to dynamic
1201
  // EnumValueDescriptor creation on unknown values.
1202
  mutable absl::Mutex unknown_enum_values_mu_;
1203
};
1204
1205
namespace internal {
1206
1207
// Small sequential allocator to be used within a single file.
1208
// Most of the memory for a single FileDescriptor and everything under it is
1209
// allocated in a single block of memory, with the FlatAllocator giving it out
1210
// in parts later.
1211
// The code first plans the total number of bytes needed by calling PlanArray
1212
// with all the allocations that will happen afterwards, then calls
1213
// FinalizePlanning passing the underlying allocator (the DescriptorPool::Tables
1214
// instance), and then proceeds to get the memory via
1215
// `AllocateArray`/`AllocateString` calls. The calls to PlanArray and
1216
// The calls have to match between planning and allocating, though not
1217
// necessarily in the same order.
1218
class FlatAllocator
1219
    : public decltype(ApplyTypeList<FlatAllocatorImpl>(
1220
          SortByAlignment<char, std::string, SourceCodeInfo,
1221
                          FileDescriptorTables,
1222
                          // Option types
1223
                          MessageOptions, FieldOptions, EnumOptions,
1224
                          EnumValueOptions, ExtensionRangeOptions, OneofOptions,
1225
                          ServiceOptions, MethodOptions, FileOptions>())) {};
1226
1227
}  // namespace internal
1228
1229
// ===================================================================
1230
// DescriptorPool::Tables
1231
1232
class DescriptorPool::Tables {
1233
 public:
1234
  Tables();
1235
  ~Tables();
1236
1237
  // Record the current state of the tables to the stack of checkpoints.
1238
  // Each call to AddCheckpoint() must be paired with exactly one call to either
1239
  // ClearLastCheckpoint() or RollbackToLastCheckpoint().
1240
  //
1241
  // This is used when building files, since some kinds of validation errors
1242
  // cannot be detected until the file's descriptors have already been added to
1243
  // the tables.
1244
  //
1245
  // This supports recursive checkpoints, since building a file may trigger
1246
  // recursive building of other files. Note that recursive checkpoints are not
1247
  // normally necessary; explicit dependencies are built prior to checkpointing.
1248
  // So although we recursively build transitive imports, there is at most one
1249
  // checkpoint in the stack during dependency building.
1250
  //
1251
  // Recursive checkpoints only arise during cross-linking of the descriptors.
1252
  // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and
1253
  // friends. If the pending file references an unknown symbol
1254
  // (e.g., it is not defined in the pending file's explicit dependencies), and
1255
  // the pool is using a fallback database, and that database contains a file
1256
  // defining that symbol, and that file has not yet been built by the pool,
1257
  // the pool builds the file during cross-linking, leading to another
1258
  // checkpoint.
1259
  void AddCheckpoint();
1260
1261
  // Mark the last checkpoint as having cleared successfully, removing it from
1262
  // the stack. If the stack is empty, all pending symbols will be committed.
1263
  //
1264
  // Note that this does not guarantee that the symbols added since the last
1265
  // checkpoint won't be rolled back: if a checkpoint gets rolled back,
1266
  // everything past that point gets rolled back, including symbols added after
1267
  // checkpoints that were pushed onto the stack after it and marked as cleared.
1268
  void ClearLastCheckpoint();
1269
1270
  // Roll back the Tables to the state of the checkpoint at the top of the
1271
  // stack, removing everything that was added after that point.
1272
  void RollbackToLastCheckpoint();
1273
1274
  // The stack of files which are currently being built.  Used to detect
1275
  // cyclic dependencies when loading files from a DescriptorDatabase.  Not
1276
  // used when fallback_database_ == nullptr.
1277
  std::vector<std::string> pending_files_;
1278
1279
  // A set of files which we have tried to load from the fallback database
1280
  // and encountered errors.  We will not attempt to load them again during
1281
  // execution of the current public API call, but for compatibility with
1282
  // legacy clients, this is cleared at the beginning of each public API call.
1283
  // Not used when fallback_database_ == nullptr.
1284
  absl::flat_hash_set<std::string> known_bad_files_;
1285
1286
  // A set of symbols which we have tried to load from the fallback database
1287
  // and encountered errors. We will not attempt to load them again during
1288
  // execution of the current public API call, but for compatibility with
1289
  // legacy clients, this is cleared at the beginning of each public API call.
1290
  absl::flat_hash_set<std::string> known_bad_symbols_;
1291
1292
  // The set of descriptors for which we've already loaded the full
1293
  // set of extensions numbers from fallback_database_.
1294
  absl::flat_hash_set<const Descriptor*> extensions_loaded_from_db_;
1295
1296
  // Maps type name to Descriptor::WellKnownType.  This is logically global
1297
  // and const, but we make it a member here to simplify its construction and
1298
  // destruction.  This only has 20-ish entries and is one per DescriptorPool,
1299
  // so the overhead is small.
1300
  absl::flat_hash_map<std::string, Descriptor::WellKnownType> well_known_types_;
1301
1302
  // -----------------------------------------------------------------
1303
  // Finding items.
1304
1305
  // Find symbols.  This returns a null Symbol (symbol.IsNull() is true)
1306
  // if not found.
1307
  inline Symbol FindSymbol(absl::string_view key) const;
1308
1309
  // This implements the body of DescriptorPool::Find*ByName().  It should
1310
  // really be a private method of DescriptorPool, but that would require
1311
  // declaring Symbol in descriptor.h, which would drag all kinds of other
1312
  // stuff into the header.  Yay C++.
1313
  Symbol FindByNameHelper(const DescriptorPool* pool, absl::string_view name);
1314
1315
  // These return nullptr if not found.
1316
  inline const FileDescriptor* FindFile(absl::string_view key) const;
1317
  inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
1318
                                              int number) const;
1319
  inline void FindAllExtensions(const Descriptor* extendee,
1320
                                std::vector<const FieldDescriptor*>* out) const;
1321
1322
  // -----------------------------------------------------------------
1323
  // Adding items.
1324
1325
  // These add items to the corresponding tables.  They return false if
1326
  // the key already exists in the table.  For AddSymbol(), the string passed
1327
  // in must be one that was constructed using AllocateString(), as it will
1328
  // be used as a key in the symbols_by_name_ map without copying.
1329
  bool AddSymbol(absl::string_view full_name, Symbol symbol);
1330
  bool AddFile(const FileDescriptor* file);
1331
  bool AddExtension(const FieldDescriptor* field);
1332
1333
  // -----------------------------------------------------------------
1334
  // Allocating memory.
1335
1336
  // Allocate an object which will be reclaimed when the pool is
1337
  // destroyed.  Note that the object's destructor will never be called,
1338
  // so its fields must be plain old data (primitive data types and
1339
  // pointers).  All of the descriptor types are such objects.
1340
  template <typename Type>
1341
  Type* Allocate();
1342
1343
  // Allocate some bytes which will be reclaimed when the pool is
1344
  // destroyed. Memory is aligned to 8 bytes.
1345
  void* AllocateBytes(int size);
1346
1347
  // Create a FlatAllocation for the corresponding sizes.
1348
  // All objects within it will be default constructed.
1349
  // The whole allocation, including the non-trivial objects within, will be
1350
  // destroyed with the pool.
1351
  template <typename... T>
1352
  internal::FlatAllocator::Allocation* CreateFlatAlloc(
1353
      const TypeMap<IntT, T...>& sizes);
1354
1355
1356
 private:
1357
  // All memory allocated in the pool.  Must be first as other objects can
1358
  // point into these.
1359
  struct MiscDeleter {
1360
0
    void operator()(int* p) const { internal::SizedDelete(p, *p + 8); }
1361
  };
1362
  // Miscellaneous allocations are length prefixed. The paylaod is 8 bytes after
1363
  // the `int` that contains the size. This keeps the payload aligned.
1364
  std::vector<std::unique_ptr<int, MiscDeleter>> misc_allocs_;
1365
  struct FlatAllocDeleter {
1366
0
    void operator()(internal::FlatAllocator::Allocation* p) const {
1367
0
      p->Destroy();
1368
0
    }
1369
  };
1370
  std::vector<
1371
      std::unique_ptr<internal::FlatAllocator::Allocation, FlatAllocDeleter>>
1372
      flat_allocs_;
1373
1374
  SymbolsByNameSet symbols_by_name_;
1375
  DescriptorsByNameSet<FileDescriptor> files_by_name_;
1376
  ExtensionsGroupedByDescriptorMap extensions_;
1377
1378
  struct CheckPoint {
1379
    explicit CheckPoint(const Tables* tables)
1380
        : flat_allocations_before_checkpoint(
1381
              static_cast<int>(tables->flat_allocs_.size())),
1382
          misc_allocations_before_checkpoint(
1383
              static_cast<int>(tables->misc_allocs_.size())),
1384
          pending_symbols_before_checkpoint(
1385
              tables->symbols_after_checkpoint_.size()),
1386
          pending_files_before_checkpoint(
1387
              tables->files_after_checkpoint_.size()),
1388
          pending_extensions_before_checkpoint(
1389
0
              tables->extensions_after_checkpoint_.size()) {}
1390
    int flat_allocations_before_checkpoint;
1391
    int misc_allocations_before_checkpoint;
1392
    int pending_symbols_before_checkpoint;
1393
    int pending_files_before_checkpoint;
1394
    int pending_extensions_before_checkpoint;
1395
  };
1396
  std::vector<CheckPoint> checkpoints_;
1397
  std::vector<Symbol> symbols_after_checkpoint_;
1398
  std::vector<const FileDescriptor*> files_after_checkpoint_;
1399
  std::vector<std::pair<const Descriptor*, int>> extensions_after_checkpoint_;
1400
};
1401
1402
0
DescriptorPool::Tables::Tables() {
1403
0
  well_known_types_.insert({
1404
0
      {"google.protobuf.DoubleValue", Descriptor::WELLKNOWNTYPE_DOUBLEVALUE},
1405
0
      {"google.protobuf.FloatValue", Descriptor::WELLKNOWNTYPE_FLOATVALUE},
1406
0
      {"google.protobuf.Int64Value", Descriptor::WELLKNOWNTYPE_INT64VALUE},
1407
0
      {"google.protobuf.UInt64Value", Descriptor::WELLKNOWNTYPE_UINT64VALUE},
1408
0
      {"google.protobuf.Int32Value", Descriptor::WELLKNOWNTYPE_INT32VALUE},
1409
0
      {"google.protobuf.UInt32Value", Descriptor::WELLKNOWNTYPE_UINT32VALUE},
1410
0
      {"google.protobuf.StringValue", Descriptor::WELLKNOWNTYPE_STRINGVALUE},
1411
0
      {"google.protobuf.BytesValue", Descriptor::WELLKNOWNTYPE_BYTESVALUE},
1412
0
      {"google.protobuf.BoolValue", Descriptor::WELLKNOWNTYPE_BOOLVALUE},
1413
0
      {"google.protobuf.Any", Descriptor::WELLKNOWNTYPE_ANY},
1414
0
      {"google.protobuf.FieldMask", Descriptor::WELLKNOWNTYPE_FIELDMASK},
1415
0
      {"google.protobuf.Duration", Descriptor::WELLKNOWNTYPE_DURATION},
1416
0
      {"google.protobuf.Timestamp", Descriptor::WELLKNOWNTYPE_TIMESTAMP},
1417
0
      {"google.protobuf.Value", Descriptor::WELLKNOWNTYPE_VALUE},
1418
0
      {"google.protobuf.ListValue", Descriptor::WELLKNOWNTYPE_LISTVALUE},
1419
0
      {"google.protobuf.Struct", Descriptor::WELLKNOWNTYPE_STRUCT},
1420
0
  });
1421
0
}
1422
1423
0
DescriptorPool::Tables::~Tables() { ABSL_DCHECK(checkpoints_.empty()); }
1424
1425
0
FileDescriptorTables::FileDescriptorTables() {}
1426
1427
0
FileDescriptorTables::~FileDescriptorTables() {
1428
0
  delete fields_by_lowercase_name_.load(std::memory_order_acquire);
1429
0
  delete fields_by_camelcase_name_.load(std::memory_order_acquire);
1430
0
}
1431
1432
0
inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() {
1433
0
  static auto file_descriptor_tables =
1434
0
      internal::OnShutdownDelete(new FileDescriptorTables());
1435
0
  return *file_descriptor_tables;
1436
0
}
1437
1438
0
void DescriptorPool::Tables::AddCheckpoint() {
1439
0
  checkpoints_.emplace_back(this);
1440
0
}
1441
1442
0
void DescriptorPool::Tables::ClearLastCheckpoint() {
1443
0
  ABSL_DCHECK(!checkpoints_.empty());
1444
0
  checkpoints_.pop_back();
1445
0
  if (checkpoints_.empty()) {
1446
    // All checkpoints have been cleared: we can now commit all of the pending
1447
    // data.
1448
0
    symbols_after_checkpoint_.clear();
1449
0
    files_after_checkpoint_.clear();
1450
0
    extensions_after_checkpoint_.clear();
1451
0
  }
1452
0
}
1453
1454
0
void DescriptorPool::Tables::RollbackToLastCheckpoint() {
1455
0
  ABSL_DCHECK(!checkpoints_.empty());
1456
0
  const CheckPoint& checkpoint = checkpoints_.back();
1457
1458
0
  for (size_t i = checkpoint.pending_symbols_before_checkpoint;
1459
0
       i < symbols_after_checkpoint_.size(); i++) {
1460
0
    symbols_by_name_.erase(symbols_after_checkpoint_[i]);
1461
0
  }
1462
0
  for (size_t i = checkpoint.pending_files_before_checkpoint;
1463
0
       i < files_after_checkpoint_.size(); i++) {
1464
0
    files_by_name_.erase(files_after_checkpoint_[i]);
1465
0
  }
1466
0
  for (size_t i = checkpoint.pending_extensions_before_checkpoint;
1467
0
       i < extensions_after_checkpoint_.size(); i++) {
1468
0
    extensions_.erase(extensions_after_checkpoint_[i]);
1469
0
  }
1470
1471
0
  symbols_after_checkpoint_.resize(
1472
0
      checkpoint.pending_symbols_before_checkpoint);
1473
0
  files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint);
1474
0
  extensions_after_checkpoint_.resize(
1475
0
      checkpoint.pending_extensions_before_checkpoint);
1476
1477
0
  flat_allocs_.resize(checkpoint.flat_allocations_before_checkpoint);
1478
0
  misc_allocs_.resize(checkpoint.misc_allocations_before_checkpoint);
1479
0
  checkpoints_.pop_back();
1480
0
}
1481
1482
// -------------------------------------------------------------------
1483
1484
0
inline Symbol DescriptorPool::Tables::FindSymbol(absl::string_view key) const {
1485
0
  auto it = symbols_by_name_.find(FullNameQuery{key});
1486
0
  return it == symbols_by_name_.end() ? Symbol() : *it;
1487
0
}
1488
1489
inline Symbol FileDescriptorTables::FindNestedSymbol(
1490
0
    const void* parent, absl::string_view name) const {
1491
0
  auto it = symbols_by_parent_.find(ParentNameQuery{{parent, name}});
1492
0
  return it == symbols_by_parent_.end() ? Symbol() : *it;
1493
0
}
1494
1495
Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool,
1496
0
                                                absl::string_view name) {
1497
0
  if (pool->mutex_ != nullptr) {
1498
    // Fast path: the Symbol is already cached.  This is just a hash lookup.
1499
0
    absl::ReaderMutexLock lock(pool->mutex_);
1500
0
    if (known_bad_symbols_.empty() && known_bad_files_.empty()) {
1501
0
      Symbol result = FindSymbol(name);
1502
0
      if (!result.IsNull()) return result;
1503
0
    }
1504
0
  }
1505
0
  absl::MutexLockMaybe lock(pool->mutex_);
1506
0
  if (pool->fallback_database_ != nullptr) {
1507
0
    known_bad_symbols_.clear();
1508
0
    known_bad_files_.clear();
1509
0
  }
1510
0
  Symbol result = FindSymbol(name);
1511
1512
0
  if (result.IsNull() && pool->underlay_ != nullptr) {
1513
    // Symbol not found; check the underlay.
1514
0
    result = pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name);
1515
0
  }
1516
1517
0
  if (result.IsNull()) {
1518
    // Symbol still not found, so check fallback database.
1519
0
    if (pool->TryFindSymbolInFallbackDatabase(name)) {
1520
0
      result = FindSymbol(name);
1521
0
    }
1522
0
  }
1523
1524
0
  return result;
1525
0
}
1526
1527
inline const FileDescriptor* DescriptorPool::Tables::FindFile(
1528
0
    absl::string_view key) const {
1529
0
  auto it = files_by_name_.find(key);
1530
0
  if (it == files_by_name_.end()) return nullptr;
1531
0
  return *it;
1532
0
}
1533
1534
inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
1535
0
    const Descriptor* parent, int number) const {
1536
  // If `number` is within the sequential range, just index into the parent
1537
  // without doing a table lookup.
1538
0
  if (parent != nullptr &&  //
1539
0
      1 <= number && number <= parent->sequential_field_limit_) {
1540
0
    return parent->field(number - 1);
1541
0
  }
1542
1543
0
  auto it = fields_by_number_.find(ParentNumberQuery{{parent, number}});
1544
0
  return it == fields_by_number_.end() ? nullptr : *it;
1545
0
}
1546
1547
const void* FileDescriptorTables::FindParentForFieldsByMap(
1548
0
    const FieldDescriptor* field) const {
1549
0
  if (field->is_extension()) {
1550
0
    if (field->extension_scope() == nullptr) {
1551
0
      return field->file();
1552
0
    } else {
1553
0
      return field->extension_scope();
1554
0
    }
1555
0
  } else {
1556
0
    return field->containing_type();
1557
0
  }
1558
0
}
1559
1560
void FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic(
1561
0
    const FileDescriptorTables* tables) {
1562
0
  tables->FieldsByLowercaseNamesLazyInitInternal();
1563
0
}
1564
1565
0
void FileDescriptorTables::FieldsByLowercaseNamesLazyInitInternal() const {
1566
0
  auto* map = new FieldsByNameMap;
1567
0
  for (Symbol symbol : symbols_by_parent_) {
1568
0
    const FieldDescriptor* field = symbol.field_descriptor();
1569
0
    if (!field) continue;
1570
0
    (*map)[{FindParentForFieldsByMap(field), field->lowercase_name().c_str()}] =
1571
0
        field;
1572
0
  }
1573
0
  fields_by_lowercase_name_.store(map, std::memory_order_release);
1574
0
}
1575
1576
inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
1577
0
    const void* parent, absl::string_view lowercase_name) const {
1578
0
  absl::call_once(fields_by_lowercase_name_once_,
1579
0
                  &FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic,
1580
0
                  this);
1581
0
  const auto* fields =
1582
0
      fields_by_lowercase_name_.load(std::memory_order_acquire);
1583
0
  auto it = fields->find({parent, lowercase_name});
1584
0
  if (it == fields->end()) return nullptr;
1585
0
  return it->second;
1586
0
}
1587
1588
void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic(
1589
0
    const FileDescriptorTables* tables) {
1590
0
  tables->FieldsByCamelcaseNamesLazyInitInternal();
1591
0
}
1592
1593
0
void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitInternal() const {
1594
0
  auto* map = new FieldsByNameMap;
1595
0
  for (Symbol symbol : symbols_by_parent_) {
1596
0
    const FieldDescriptor* field = symbol.field_descriptor();
1597
0
    if (!field) continue;
1598
0
    (*map)[{FindParentForFieldsByMap(field), field->camelcase_name().c_str()}] =
1599
0
        field;
1600
0
  }
1601
0
  fields_by_camelcase_name_.store(map, std::memory_order_release);
1602
0
}
1603
1604
inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
1605
0
    const void* parent, absl::string_view camelcase_name) const {
1606
0
  absl::call_once(fields_by_camelcase_name_once_,
1607
0
                  FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic,
1608
0
                  this);
1609
0
  auto* fields = fields_by_camelcase_name_.load(std::memory_order_acquire);
1610
0
  auto it = fields->find({parent, camelcase_name});
1611
0
  if (it == fields->end()) return nullptr;
1612
0
  return it->second;
1613
0
}
1614
1615
inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
1616
0
    const EnumDescriptor* parent, int number) const {
1617
  // If `number` is within the sequential range, just index into the parent
1618
  // without doing a table lookup.
1619
0
  const int base = parent->value(0)->number();
1620
0
  if (base <= number &&
1621
0
      number <= static_cast<int64_t>(base) + parent->sequential_value_limit_) {
1622
0
    return parent->value(number - base);
1623
0
  }
1624
1625
0
  auto it = enum_values_by_number_.find(ParentNumberQuery{{parent, number}});
1626
0
  return it == enum_values_by_number_.end() ? nullptr : *it;
1627
0
}
1628
1629
inline const EnumValueDescriptor*
1630
FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
1631
0
    const EnumDescriptor* parent, int number) const {
1632
  // First try, with map of compiled-in values.
1633
0
  {
1634
0
    const auto* value = FindEnumValueByNumber(parent, number);
1635
0
    if (value != nullptr) {
1636
0
      return value;
1637
0
    }
1638
0
  }
1639
1640
0
  const ParentNumberQuery query{{parent, number}};
1641
1642
  // Second try, with reader lock held on unknown enum values: common case.
1643
0
  {
1644
0
    absl::ReaderMutexLock l(&unknown_enum_values_mu_);
1645
0
    auto it = unknown_enum_values_by_number_.find(query);
1646
0
    if (it != unknown_enum_values_by_number_.end()) {
1647
0
      return *it;
1648
0
    }
1649
0
  }
1650
  // If not found, try again with writer lock held, and create new descriptor if
1651
  // necessary.
1652
0
  {
1653
0
    absl::WriterMutexLock l(&unknown_enum_values_mu_);
1654
0
    auto it = unknown_enum_values_by_number_.find(query);
1655
0
    if (it != unknown_enum_values_by_number_.end()) {
1656
0
      return *it;
1657
0
    }
1658
1659
    // Create an EnumValueDescriptor dynamically. We don't insert it into the
1660
    // EnumDescriptor (it's not a part of the enum as originally defined), but
1661
    // we do insert it into the table so that we can return the same pointer
1662
    // later.
1663
0
    std::string enum_value_name = absl::StrFormat(
1664
0
        "UNKNOWN_ENUM_VALUE_%s_%d", parent->name().c_str(), number);
1665
0
    auto* pool = DescriptorPool::generated_pool();
1666
0
    auto* tables = const_cast<DescriptorPool::Tables*>(pool->tables_.get());
1667
0
    internal::FlatAllocator alloc;
1668
0
    alloc.PlanArray<EnumValueDescriptor>(1);
1669
0
    alloc.PlanArray<std::string>(2);
1670
1671
0
    {
1672
      // Must lock the pool because we will do allocations in the shared arena.
1673
0
      absl::MutexLockMaybe l2(pool->mutex_);
1674
0
      alloc.FinalizePlanning(tables);
1675
0
    }
1676
0
    EnumValueDescriptor* result = alloc.AllocateArray<EnumValueDescriptor>(1);
1677
0
    result->all_names_ = alloc.AllocateStrings(
1678
0
        enum_value_name,
1679
0
        absl::StrCat(parent->full_name(), ".", enum_value_name));
1680
0
    result->number_ = number;
1681
0
    result->type_ = parent;
1682
0
    result->options_ = &EnumValueOptions::default_instance();
1683
0
    unknown_enum_values_by_number_.insert(result);
1684
0
    return result;
1685
0
  }
1686
0
}
1687
1688
inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
1689
0
    const Descriptor* extendee, int number) const {
1690
0
  auto it = extensions_.find({extendee, number});
1691
0
  if (it == extensions_.end()) return nullptr;
1692
0
  return it->second;
1693
0
}
1694
1695
inline void DescriptorPool::Tables::FindAllExtensions(
1696
    const Descriptor* extendee,
1697
0
    std::vector<const FieldDescriptor*>* out) const {
1698
0
  ExtensionsGroupedByDescriptorMap::const_iterator it =
1699
0
      extensions_.lower_bound(std::make_pair(extendee, 0));
1700
0
  for (; it != extensions_.end() && it->first.first == extendee; ++it) {
1701
0
    out->push_back(it->second);
1702
0
  }
1703
0
}
1704
1705
// -------------------------------------------------------------------
1706
1707
bool DescriptorPool::Tables::AddSymbol(absl::string_view full_name,
1708
0
                                       Symbol symbol) {
1709
0
  ABSL_DCHECK_EQ(full_name, symbol.full_name());
1710
0
  if (symbols_by_name_.insert(symbol).second) {
1711
0
    symbols_after_checkpoint_.push_back(symbol);
1712
0
    return true;
1713
0
  } else {
1714
0
    return false;
1715
0
  }
1716
0
}
1717
1718
bool FileDescriptorTables::AddAliasUnderParent(const void* parent,
1719
                                               absl::string_view name,
1720
0
                                               Symbol symbol) {
1721
0
  ABSL_DCHECK_EQ(name, symbol.parent_name_key().second);
1722
0
  ABSL_DCHECK_EQ(parent, symbol.parent_name_key().first);
1723
0
  return symbols_by_parent_.insert(symbol).second;
1724
0
}
1725
1726
0
bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
1727
0
  if (files_by_name_.insert(file).second) {
1728
0
    files_after_checkpoint_.push_back(file);
1729
0
    return true;
1730
0
  } else {
1731
0
    return false;
1732
0
  }
1733
0
}
1734
1735
0
void FileDescriptorTables::FinalizeTables() {}
1736
1737
0
bool FileDescriptorTables::AddFieldByNumber(FieldDescriptor* field) {
1738
  // Skip fields that are at the start of the sequence.
1739
0
  if (field->containing_type() != nullptr && field->number() >= 1 &&
1740
0
      field->number() <= field->containing_type()->sequential_field_limit_) {
1741
0
    if (field->is_extension()) {
1742
      // Conflicts with the field that already exists in the sequential range.
1743
0
      return false;
1744
0
    }
1745
    // Only return true if the field at that index matches. Otherwise it
1746
    // conflicts with the existing field in the sequential range.
1747
0
    return field->containing_type()->field(field->number() - 1) == field;
1748
0
  }
1749
1750
0
  return fields_by_number_.insert(field).second;
1751
0
}
1752
1753
0
bool FileDescriptorTables::AddEnumValueByNumber(EnumValueDescriptor* value) {
1754
  // Skip values that are at the start of the sequence.
1755
0
  const int base = value->type()->value(0)->number();
1756
0
  if (base <= value->number() &&
1757
0
      value->number() <=
1758
0
          static_cast<int64_t>(base) + value->type()->sequential_value_limit_)
1759
0
    return true;
1760
0
  return enum_values_by_number_.insert(value).second;
1761
0
}
1762
1763
0
bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
1764
0
  auto it_inserted =
1765
0
      extensions_.insert({{field->containing_type(), field->number()}, field});
1766
0
  if (it_inserted.second) {
1767
0
    extensions_after_checkpoint_.push_back(it_inserted.first->first);
1768
0
    return true;
1769
0
  } else {
1770
0
    return false;
1771
0
  }
1772
0
}
1773
1774
// -------------------------------------------------------------------
1775
1776
template <typename Type>
1777
0
Type* DescriptorPool::Tables::Allocate() {
1778
0
  static_assert(std::is_trivially_destructible<Type>::value, "");
1779
0
  static_assert(alignof(Type) <= 8, "");
1780
0
  return ::new (AllocateBytes(sizeof(Type))) Type{};
1781
0
}
1782
1783
0
void* DescriptorPool::Tables::AllocateBytes(int size) {
1784
0
  if (size == 0) return nullptr;
1785
0
  void* p = ::operator new(size + RoundUpTo<8>(sizeof(int)));
1786
0
  int* sizep = static_cast<int*>(p);
1787
0
  misc_allocs_.emplace_back(sizep);
1788
0
  *sizep = size;
1789
0
  return static_cast<char*>(p) + RoundUpTo<8>(sizeof(int));
1790
0
}
1791
1792
template <typename... T>
1793
internal::FlatAllocator::Allocation* DescriptorPool::Tables::CreateFlatAlloc(
1794
0
    const TypeMap<IntT, T...>& sizes) {
1795
0
  auto ends = CalculateEnds(sizes);
1796
0
  using FlatAlloc = internal::FlatAllocator::Allocation;
1797
1798
0
  int last_end = ends.template Get<
1799
0
      typename std::tuple_element<sizeof...(T) - 1, std::tuple<T...>>::type>();
1800
0
  size_t total_size =
1801
0
      last_end + RoundUpTo<FlatAlloc::kMaxAlign>(sizeof(FlatAlloc));
1802
0
  char* data = static_cast<char*>(::operator new(total_size));
1803
0
  auto* res = ::new (data) FlatAlloc(ends);
1804
0
  flat_allocs_.emplace_back(res);
1805
1806
0
  return res;
1807
0
}
1808
1809
void FileDescriptorTables::BuildLocationsByPath(
1810
0
    std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p) {
1811
0
  for (int i = 0, len = p->second->location_size(); i < len; ++i) {
1812
0
    const SourceCodeInfo_Location* loc = &p->second->location().Get(i);
1813
0
    p->first->locations_by_path_[absl::StrJoin(loc->path(), ",")] = loc;
1814
0
  }
1815
0
}
1816
1817
const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
1818
0
    const std::vector<int>& path, const SourceCodeInfo* info) const {
1819
0
  std::pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
1820
0
      std::make_pair(this, info));
1821
0
  absl::call_once(locations_by_path_once_,
1822
0
                  FileDescriptorTables::BuildLocationsByPath, &p);
1823
0
  auto it = locations_by_path_.find(absl::StrJoin(path, ","));
1824
0
  if (it == locations_by_path_.end()) return nullptr;
1825
0
  return it->second;
1826
0
}
1827
1828
// ===================================================================
1829
// DescriptorPool
1830
1831
1832
0
DescriptorPool::ErrorCollector::~ErrorCollector() {}
1833
1834
absl::string_view DescriptorPool::ErrorCollector::ErrorLocationName(
1835
0
    ErrorLocation location) {
1836
0
  switch (location) {
1837
0
    case NAME:
1838
0
      return "NAME";
1839
0
    case NUMBER:
1840
0
      return "NUMBER";
1841
0
    case TYPE:
1842
0
      return "TYPE";
1843
0
    case EXTENDEE:
1844
0
      return "EXTENDEE";
1845
0
    case DEFAULT_VALUE:
1846
0
      return "DEFAULT_VALUE";
1847
0
    case OPTION_NAME:
1848
0
      return "OPTION_NAME";
1849
0
    case OPTION_VALUE:
1850
0
      return "OPTION_VALUE";
1851
0
    case INPUT_TYPE:
1852
0
      return "INPUT_TYPE";
1853
0
    case OUTPUT_TYPE:
1854
0
      return "OUTPUT_TYPE";
1855
0
    case IMPORT:
1856
0
      return "IMPORT";
1857
0
    case OTHER:
1858
0
      return "OTHER";
1859
0
  }
1860
0
  return "UNKNOWN";
1861
0
}
1862
1863
DescriptorPool::DescriptorPool()
1864
    : mutex_(nullptr),
1865
      fallback_database_(nullptr),
1866
      default_error_collector_(nullptr),
1867
      underlay_(nullptr),
1868
      tables_(new Tables),
1869
      enforce_dependencies_(true),
1870
      lazily_build_dependencies_(false),
1871
      allow_unknown_(false),
1872
      enforce_weak_(false),
1873
      enforce_special_extension_ranges_(false),
1874
      disallow_enforce_utf8_(false),
1875
0
      deprecated_legacy_json_field_conflicts_(false) {}
1876
1877
DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
1878
                               ErrorCollector* error_collector)
1879
    : mutex_(new absl::Mutex),
1880
      fallback_database_(fallback_database),
1881
      default_error_collector_(error_collector),
1882
      underlay_(nullptr),
1883
      tables_(new Tables),
1884
      enforce_dependencies_(true),
1885
      lazily_build_dependencies_(false),
1886
      allow_unknown_(false),
1887
      enforce_weak_(false),
1888
      enforce_special_extension_ranges_(false),
1889
      disallow_enforce_utf8_(false),
1890
0
      deprecated_legacy_json_field_conflicts_(false) {}
1891
1892
DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
1893
    : mutex_(nullptr),
1894
      fallback_database_(nullptr),
1895
      default_error_collector_(nullptr),
1896
      underlay_(underlay),
1897
      tables_(new Tables),
1898
      enforce_dependencies_(true),
1899
      lazily_build_dependencies_(false),
1900
      allow_unknown_(false),
1901
      enforce_weak_(false),
1902
      enforce_special_extension_ranges_(false),
1903
      disallow_enforce_utf8_(false),
1904
0
      deprecated_legacy_json_field_conflicts_(false) {}
1905
1906
0
DescriptorPool::~DescriptorPool() {
1907
0
  if (mutex_ != nullptr) delete mutex_;
1908
0
}
1909
1910
// DescriptorPool::BuildFile() defined later.
1911
// DescriptorPool::BuildFileCollectingErrors() defined later.
1912
1913
0
void DescriptorPool::InternalDontEnforceDependencies() {
1914
0
  enforce_dependencies_ = false;
1915
0
}
1916
1917
void DescriptorPool::AddUnusedImportTrackFile(absl::string_view file_name,
1918
0
                                              bool is_error) {
1919
0
  unused_import_track_files_[file_name] = is_error;
1920
0
}
1921
1922
1923
0
void DescriptorPool::ClearUnusedImportTrackFiles() {
1924
0
  unused_import_track_files_.clear();
1925
0
}
1926
1927
0
bool DescriptorPool::InternalIsFileLoaded(absl::string_view filename) const {
1928
0
  absl::MutexLockMaybe lock(mutex_);
1929
0
  return tables_->FindFile(filename) != nullptr;
1930
0
}
1931
1932
// generated_pool ====================================================
1933
1934
namespace {
1935
1936
1937
10
EncodedDescriptorDatabase* GeneratedDatabase() {
1938
10
  static auto generated_database =
1939
10
      internal::OnShutdownDelete(new EncodedDescriptorDatabase());
1940
10
  return generated_database;
1941
10
}
1942
1943
0
DescriptorPool* NewGeneratedPool() {
1944
0
  auto generated_pool = new DescriptorPool(GeneratedDatabase());
1945
0
  generated_pool->InternalSetLazilyBuildDependencies();
1946
0
  return generated_pool;
1947
0
}
1948
1949
}  // anonymous namespace
1950
1951
0
DescriptorDatabase* DescriptorPool::internal_generated_database() {
1952
0
  return GeneratedDatabase();
1953
0
}
1954
1955
0
DescriptorPool* DescriptorPool::internal_generated_pool() {
1956
0
  static DescriptorPool* generated_pool =
1957
0
      internal::OnShutdownDelete(NewGeneratedPool());
1958
0
  return generated_pool;
1959
0
}
1960
1961
0
const DescriptorPool* DescriptorPool::generated_pool() {
1962
0
  const DescriptorPool* pool = internal_generated_pool();
1963
  // Ensure that descriptor.proto gets registered in the generated pool. It is a
1964
  // special case because it is included in the full runtime. We have to avoid
1965
  // registering it pre-main, because we need to ensure that the linker
1966
  // --gc-sections step can strip out the full runtime if it is unused.
1967
0
  DescriptorProto::descriptor();
1968
0
  return pool;
1969
0
}
1970
1971
1972
void DescriptorPool::InternalAddGeneratedFile(
1973
10
    const void* encoded_file_descriptor, int size) {
1974
  // So, this function is called in the process of initializing the
1975
  // descriptors for generated proto classes.  Each generated .pb.cc file
1976
  // has an internal procedure called AddDescriptors() which is called at
1977
  // process startup, and that function calls this one in order to register
1978
  // the raw bytes of the FileDescriptorProto representing the file.
1979
  //
1980
  // We do not actually construct the descriptor objects right away.  We just
1981
  // hang on to the bytes until they are actually needed.  We actually construct
1982
  // the descriptor the first time one of the following things happens:
1983
  // * Someone calls a method like descriptor(), GetDescriptor(), or
1984
  //   GetReflection() on the generated types, which requires returning the
1985
  //   descriptor or an object based on it.
1986
  // * Someone looks up the descriptor in DescriptorPool::generated_pool().
1987
  //
1988
  // Once one of these happens, the DescriptorPool actually parses the
1989
  // FileDescriptorProto and generates a FileDescriptor (and all its children)
1990
  // based on it.
1991
  //
1992
  // Note that FileDescriptorProto is itself a generated protocol message.
1993
  // Therefore, when we parse one, we have to be very careful to avoid using
1994
  // any descriptor-based operations, since this might cause infinite recursion
1995
  // or deadlock.
1996
10
  ABSL_CHECK(GeneratedDatabase()->Add(encoded_file_descriptor, size));
1997
10
}
1998
1999
2000
// Find*By* methods ==================================================
2001
2002
// TODO(kenton):  There's a lot of repeated code here, but I'm not sure if
2003
//   there's any good way to factor it out.  Think about this some time when
2004
//   there's nothing more important to do (read: never).
2005
2006
const FileDescriptor* DescriptorPool::FindFileByName(
2007
0
    absl::string_view name) const {
2008
0
  absl::MutexLockMaybe lock(mutex_);
2009
0
  if (fallback_database_ != nullptr) {
2010
0
    tables_->known_bad_symbols_.clear();
2011
0
    tables_->known_bad_files_.clear();
2012
0
  }
2013
0
  const FileDescriptor* result = tables_->FindFile(name);
2014
0
  if (result != nullptr) return result;
2015
0
  if (underlay_ != nullptr) {
2016
0
    result = underlay_->FindFileByName(name);
2017
0
    if (result != nullptr) return result;
2018
0
  }
2019
0
  if (TryFindFileInFallbackDatabase(name)) {
2020
0
    result = tables_->FindFile(name);
2021
0
    if (result != nullptr) return result;
2022
0
  }
2023
0
  return nullptr;
2024
0
}
2025
2026
const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
2027
0
    absl::string_view symbol_name) const {
2028
0
  absl::MutexLockMaybe lock(mutex_);
2029
0
  if (fallback_database_ != nullptr) {
2030
0
    tables_->known_bad_symbols_.clear();
2031
0
    tables_->known_bad_files_.clear();
2032
0
  }
2033
0
  Symbol result = tables_->FindSymbol(symbol_name);
2034
0
  if (!result.IsNull()) return result.GetFile();
2035
0
  if (underlay_ != nullptr) {
2036
0
    const FileDescriptor* file_result =
2037
0
        underlay_->FindFileContainingSymbol(symbol_name);
2038
0
    if (file_result != nullptr) return file_result;
2039
0
  }
2040
0
  if (TryFindSymbolInFallbackDatabase(symbol_name)) {
2041
0
    result = tables_->FindSymbol(symbol_name);
2042
0
    if (!result.IsNull()) return result.GetFile();
2043
0
  }
2044
0
  return nullptr;
2045
0
}
2046
2047
const Descriptor* DescriptorPool::FindMessageTypeByName(
2048
0
    absl::string_view name) const {
2049
0
  return tables_->FindByNameHelper(this, name).descriptor();
2050
0
}
2051
2052
const FieldDescriptor* DescriptorPool::FindFieldByName(
2053
0
    absl::string_view name) const {
2054
0
  if (const FieldDescriptor* field =
2055
0
          tables_->FindByNameHelper(this, name).field_descriptor()) {
2056
0
    if (!field->is_extension()) {
2057
0
      return field;
2058
0
    }
2059
0
  }
2060
0
  return nullptr;
2061
0
}
2062
2063
const FieldDescriptor* DescriptorPool::FindExtensionByName(
2064
0
    absl::string_view name) const {
2065
0
  if (const FieldDescriptor* field =
2066
0
          tables_->FindByNameHelper(this, name).field_descriptor()) {
2067
0
    if (field->is_extension()) {
2068
0
      return field;
2069
0
    }
2070
0
  }
2071
0
  return nullptr;
2072
0
}
2073
2074
const OneofDescriptor* DescriptorPool::FindOneofByName(
2075
0
    absl::string_view name) const {
2076
0
  return tables_->FindByNameHelper(this, name).oneof_descriptor();
2077
0
}
2078
2079
const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
2080
0
    absl::string_view name) const {
2081
0
  return tables_->FindByNameHelper(this, name).enum_descriptor();
2082
0
}
2083
2084
const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
2085
0
    absl::string_view name) const {
2086
0
  return tables_->FindByNameHelper(this, name).enum_value_descriptor();
2087
0
}
2088
2089
const ServiceDescriptor* DescriptorPool::FindServiceByName(
2090
0
    absl::string_view name) const {
2091
0
  return tables_->FindByNameHelper(this, name).service_descriptor();
2092
0
}
2093
2094
const MethodDescriptor* DescriptorPool::FindMethodByName(
2095
0
    absl::string_view name) const {
2096
0
  return tables_->FindByNameHelper(this, name).method_descriptor();
2097
0
}
2098
2099
const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
2100
0
    const Descriptor* extendee, int number) const {
2101
0
  if (extendee->extension_range_count() == 0) return nullptr;
2102
  // A faster path to reduce lock contention in finding extensions, assuming
2103
  // most extensions will be cache hit.
2104
0
  if (mutex_ != nullptr) {
2105
0
    absl::ReaderMutexLock lock(mutex_);
2106
0
    const FieldDescriptor* result = tables_->FindExtension(extendee, number);
2107
0
    if (result != nullptr) {
2108
0
      return result;
2109
0
    }
2110
0
  }
2111
0
  absl::MutexLockMaybe lock(mutex_);
2112
0
  if (fallback_database_ != nullptr) {
2113
0
    tables_->known_bad_symbols_.clear();
2114
0
    tables_->known_bad_files_.clear();
2115
0
  }
2116
0
  const FieldDescriptor* result = tables_->FindExtension(extendee, number);
2117
0
  if (result != nullptr) {
2118
0
    return result;
2119
0
  }
2120
0
  if (underlay_ != nullptr) {
2121
0
    result = underlay_->FindExtensionByNumber(extendee, number);
2122
0
    if (result != nullptr) return result;
2123
0
  }
2124
0
  if (TryFindExtensionInFallbackDatabase(extendee, number)) {
2125
0
    result = tables_->FindExtension(extendee, number);
2126
0
    if (result != nullptr) {
2127
0
      return result;
2128
0
    }
2129
0
  }
2130
0
  return nullptr;
2131
0
}
2132
2133
const FieldDescriptor* DescriptorPool::InternalFindExtensionByNumberNoLock(
2134
0
    const Descriptor* extendee, int number) const {
2135
0
  if (extendee->extension_range_count() == 0) return nullptr;
2136
2137
0
  const FieldDescriptor* result = tables_->FindExtension(extendee, number);
2138
0
  if (result != nullptr) {
2139
0
    return result;
2140
0
  }
2141
2142
0
  if (underlay_ != nullptr) {
2143
0
    result = underlay_->InternalFindExtensionByNumberNoLock(extendee, number);
2144
0
    if (result != nullptr) return result;
2145
0
  }
2146
2147
0
  return nullptr;
2148
0
}
2149
2150
const FieldDescriptor* DescriptorPool::FindExtensionByPrintableName(
2151
0
    const Descriptor* extendee, absl::string_view printable_name) const {
2152
0
  if (extendee->extension_range_count() == 0) return nullptr;
2153
0
  const FieldDescriptor* result = FindExtensionByName(printable_name);
2154
0
  if (result != nullptr && result->containing_type() == extendee) {
2155
0
    return result;
2156
0
  }
2157
0
  if (extendee->options().message_set_wire_format()) {
2158
    // MessageSet extensions may be identified by type name.
2159
0
    const Descriptor* type = FindMessageTypeByName(printable_name);
2160
0
    if (type != nullptr) {
2161
      // Look for a matching extension in the foreign type's scope.
2162
0
      const int type_extension_count = type->extension_count();
2163
0
      for (int i = 0; i < type_extension_count; i++) {
2164
0
        const FieldDescriptor* extension = type->extension(i);
2165
0
        if (extension->containing_type() == extendee &&
2166
0
            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
2167
0
            extension->is_optional() && extension->message_type() == type) {
2168
          // Found it.
2169
0
          return extension;
2170
0
        }
2171
0
      }
2172
0
    }
2173
0
  }
2174
0
  return nullptr;
2175
0
}
2176
2177
void DescriptorPool::FindAllExtensions(
2178
    const Descriptor* extendee,
2179
0
    std::vector<const FieldDescriptor*>* out) const {
2180
0
  absl::MutexLockMaybe lock(mutex_);
2181
0
  if (fallback_database_ != nullptr) {
2182
0
    tables_->known_bad_symbols_.clear();
2183
0
    tables_->known_bad_files_.clear();
2184
0
  }
2185
2186
  // Initialize tables_->extensions_ from the fallback database first
2187
  // (but do this only once per descriptor).
2188
0
  if (fallback_database_ != nullptr &&
2189
0
      tables_->extensions_loaded_from_db_.count(extendee) == 0) {
2190
0
    std::vector<int> numbers;
2191
0
    if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
2192
0
                                                    &numbers)) {
2193
0
      for (int number : numbers) {
2194
0
        if (tables_->FindExtension(extendee, number) == nullptr) {
2195
0
          TryFindExtensionInFallbackDatabase(extendee, number);
2196
0
        }
2197
0
      }
2198
0
      tables_->extensions_loaded_from_db_.insert(extendee);
2199
0
    }
2200
0
  }
2201
2202
0
  tables_->FindAllExtensions(extendee, out);
2203
0
  if (underlay_ != nullptr) {
2204
0
    underlay_->FindAllExtensions(extendee, out);
2205
0
  }
2206
0
}
2207
2208
2209
// -------------------------------------------------------------------
2210
2211
0
const FieldDescriptor* Descriptor::FindFieldByNumber(int key) const {
2212
0
  const FieldDescriptor* result = file()->tables_->FindFieldByNumber(this, key);
2213
0
  if (result == nullptr || result->is_extension()) {
2214
0
    return nullptr;
2215
0
  } else {
2216
0
    return result;
2217
0
  }
2218
0
}
2219
2220
const FieldDescriptor* Descriptor::FindFieldByLowercaseName(
2221
0
    absl::string_view key) const {
2222
0
  const FieldDescriptor* result =
2223
0
      file()->tables_->FindFieldByLowercaseName(this, key);
2224
0
  if (result == nullptr || result->is_extension()) {
2225
0
    return nullptr;
2226
0
  } else {
2227
0
    return result;
2228
0
  }
2229
0
}
2230
2231
const FieldDescriptor* Descriptor::FindFieldByCamelcaseName(
2232
0
    absl::string_view key) const {
2233
0
  const FieldDescriptor* result =
2234
0
      file()->tables_->FindFieldByCamelcaseName(this, key);
2235
0
  if (result == nullptr || result->is_extension()) {
2236
0
    return nullptr;
2237
0
  } else {
2238
0
    return result;
2239
0
  }
2240
0
}
2241
2242
const FieldDescriptor* Descriptor::FindFieldByName(
2243
0
    absl::string_view key) const {
2244
0
  const FieldDescriptor* field =
2245
0
      file()->tables_->FindNestedSymbol(this, key).field_descriptor();
2246
0
  return field != nullptr && !field->is_extension() ? field : nullptr;
2247
0
}
2248
2249
const OneofDescriptor* Descriptor::FindOneofByName(
2250
0
    absl::string_view key) const {
2251
0
  return file()->tables_->FindNestedSymbol(this, key).oneof_descriptor();
2252
0
}
2253
2254
const FieldDescriptor* Descriptor::FindExtensionByName(
2255
0
    absl::string_view key) const {
2256
0
  const FieldDescriptor* field =
2257
0
      file()->tables_->FindNestedSymbol(this, key).field_descriptor();
2258
0
  return field != nullptr && field->is_extension() ? field : nullptr;
2259
0
}
2260
2261
const FieldDescriptor* Descriptor::FindExtensionByLowercaseName(
2262
0
    absl::string_view key) const {
2263
0
  const FieldDescriptor* result =
2264
0
      file()->tables_->FindFieldByLowercaseName(this, key);
2265
0
  if (result == nullptr || !result->is_extension()) {
2266
0
    return nullptr;
2267
0
  } else {
2268
0
    return result;
2269
0
  }
2270
0
}
2271
2272
const FieldDescriptor* Descriptor::FindExtensionByCamelcaseName(
2273
0
    absl::string_view key) const {
2274
0
  const FieldDescriptor* result =
2275
0
      file()->tables_->FindFieldByCamelcaseName(this, key);
2276
0
  if (result == nullptr || !result->is_extension()) {
2277
0
    return nullptr;
2278
0
  } else {
2279
0
    return result;
2280
0
  }
2281
0
}
2282
2283
const Descriptor* Descriptor::FindNestedTypeByName(
2284
0
    absl::string_view key) const {
2285
0
  return file()->tables_->FindNestedSymbol(this, key).descriptor();
2286
0
}
2287
2288
const EnumDescriptor* Descriptor::FindEnumTypeByName(
2289
0
    absl::string_view key) const {
2290
0
  return file()->tables_->FindNestedSymbol(this, key).enum_descriptor();
2291
0
}
2292
2293
const EnumValueDescriptor* Descriptor::FindEnumValueByName(
2294
0
    absl::string_view key) const {
2295
0
  return file()->tables_->FindNestedSymbol(this, key).enum_value_descriptor();
2296
0
}
2297
2298
0
const FieldDescriptor* Descriptor::map_key() const {
2299
0
  if (!options().map_entry()) return nullptr;
2300
0
  ABSL_DCHECK_EQ(field_count(), 2);
2301
0
  return field(0);
2302
0
}
2303
2304
0
const FieldDescriptor* Descriptor::map_value() const {
2305
0
  if (!options().map_entry()) return nullptr;
2306
0
  ABSL_DCHECK_EQ(field_count(), 2);
2307
0
  return field(1);
2308
0
}
2309
2310
const EnumValueDescriptor* EnumDescriptor::FindValueByName(
2311
0
    absl::string_view key) const {
2312
0
  return file()->tables_->FindNestedSymbol(this, key).enum_value_descriptor();
2313
0
}
2314
2315
0
const EnumValueDescriptor* EnumDescriptor::FindValueByNumber(int key) const {
2316
0
  return file()->tables_->FindEnumValueByNumber(this, key);
2317
0
}
2318
2319
const EnumValueDescriptor* EnumDescriptor::FindValueByNumberCreatingIfUnknown(
2320
0
    int key) const {
2321
0
  return file()->tables_->FindEnumValueByNumberCreatingIfUnknown(this, key);
2322
0
}
2323
2324
const MethodDescriptor* ServiceDescriptor::FindMethodByName(
2325
0
    absl::string_view key) const {
2326
0
  return file()->tables_->FindNestedSymbol(this, key).method_descriptor();
2327
0
}
2328
2329
const Descriptor* FileDescriptor::FindMessageTypeByName(
2330
0
    absl::string_view key) const {
2331
0
  return tables_->FindNestedSymbol(this, key).descriptor();
2332
0
}
2333
2334
const EnumDescriptor* FileDescriptor::FindEnumTypeByName(
2335
0
    absl::string_view key) const {
2336
0
  return tables_->FindNestedSymbol(this, key).enum_descriptor();
2337
0
}
2338
2339
const EnumValueDescriptor* FileDescriptor::FindEnumValueByName(
2340
0
    absl::string_view key) const {
2341
0
  return tables_->FindNestedSymbol(this, key).enum_value_descriptor();
2342
0
}
2343
2344
const ServiceDescriptor* FileDescriptor::FindServiceByName(
2345
0
    absl::string_view key) const {
2346
0
  return tables_->FindNestedSymbol(this, key).service_descriptor();
2347
0
}
2348
2349
const FieldDescriptor* FileDescriptor::FindExtensionByName(
2350
0
    absl::string_view key) const {
2351
0
  const FieldDescriptor* field =
2352
0
      tables_->FindNestedSymbol(this, key).field_descriptor();
2353
0
  return field != nullptr && field->is_extension() ? field : nullptr;
2354
0
}
2355
2356
const FieldDescriptor* FileDescriptor::FindExtensionByLowercaseName(
2357
0
    absl::string_view key) const {
2358
0
  const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
2359
0
  if (result == nullptr || !result->is_extension()) {
2360
0
    return nullptr;
2361
0
  } else {
2362
0
    return result;
2363
0
  }
2364
0
}
2365
2366
const FieldDescriptor* FileDescriptor::FindExtensionByCamelcaseName(
2367
0
    absl::string_view key) const {
2368
0
  const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
2369
0
  if (result == nullptr || !result->is_extension()) {
2370
0
    return nullptr;
2371
0
  } else {
2372
0
    return result;
2373
0
  }
2374
0
}
2375
2376
void Descriptor::ExtensionRange::CopyTo(
2377
0
    DescriptorProto_ExtensionRange* proto) const {
2378
0
  proto->set_start(this->start);
2379
0
  proto->set_end(this->end);
2380
0
  if (options_ != &ExtensionRangeOptions::default_instance()) {
2381
0
    *proto->mutable_options() = *options_;
2382
0
  }
2383
0
}
2384
2385
const Descriptor::ExtensionRange*
2386
0
Descriptor::FindExtensionRangeContainingNumber(int number) const {
2387
  // Linear search should be fine because we don't expect a message to have
2388
  // more than a couple extension ranges.
2389
0
  for (int i = 0; i < extension_range_count(); i++) {
2390
0
    if (number >= extension_range(i)->start &&
2391
0
        number < extension_range(i)->end) {
2392
0
      return extension_range(i);
2393
0
    }
2394
0
  }
2395
0
  return nullptr;
2396
0
}
2397
2398
const Descriptor::ReservedRange* Descriptor::FindReservedRangeContainingNumber(
2399
0
    int number) const {
2400
  // TODO(chrisn): Consider a non-linear search.
2401
0
  for (int i = 0; i < reserved_range_count(); i++) {
2402
0
    if (number >= reserved_range(i)->start && number < reserved_range(i)->end) {
2403
0
      return reserved_range(i);
2404
0
    }
2405
0
  }
2406
0
  return nullptr;
2407
0
}
2408
2409
const EnumDescriptor::ReservedRange*
2410
0
EnumDescriptor::FindReservedRangeContainingNumber(int number) const {
2411
  // TODO(chrisn): Consider a non-linear search.
2412
0
  for (int i = 0; i < reserved_range_count(); i++) {
2413
0
    if (number >= reserved_range(i)->start &&
2414
0
        number <= reserved_range(i)->end) {
2415
0
      return reserved_range(i);
2416
0
    }
2417
0
  }
2418
0
  return nullptr;
2419
0
}
2420
2421
// -------------------------------------------------------------------
2422
2423
bool DescriptorPool::TryFindFileInFallbackDatabase(
2424
0
    absl::string_view name) const {
2425
0
  if (fallback_database_ == nullptr) return false;
2426
2427
0
  if (tables_->known_bad_files_.contains(name)) return false;
2428
2429
  // NOINLINE to reduce the stack cost of the operation in the caller.
2430
0
  const auto find_file = [](DescriptorDatabase& database,
2431
0
                            absl::string_view filename,
2432
0
                            FileDescriptorProto& output) PROTOBUF_NOINLINE {
2433
0
    return database.FindFileByName(std::string(filename), &output);
2434
0
  };
2435
2436
0
  auto file_proto = absl::make_unique<FileDescriptorProto>();
2437
0
  if (!find_file(*fallback_database_, name, *file_proto) ||
2438
0
      BuildFileFromDatabase(*file_proto) == nullptr) {
2439
0
    tables_->known_bad_files_.emplace(name);
2440
0
    return false;
2441
0
  }
2442
0
  return true;
2443
0
}
2444
2445
0
bool DescriptorPool::IsSubSymbolOfBuiltType(absl::string_view name) const {
2446
0
  auto prefix = std::string(name);
2447
0
  for (;;) {
2448
0
    std::string::size_type dot_pos = prefix.find_last_of('.');
2449
0
    if (dot_pos == std::string::npos) {
2450
0
      break;
2451
0
    }
2452
0
    prefix = prefix.substr(0, dot_pos);
2453
0
    Symbol symbol = tables_->FindSymbol(prefix);
2454
    // If the symbol type is anything other than PACKAGE, then its complete
2455
    // definition is already known.
2456
0
    if (!symbol.IsNull() && !symbol.IsPackage()) {
2457
0
      return true;
2458
0
    }
2459
0
  }
2460
0
  if (underlay_ != nullptr) {
2461
    // Check to see if any prefix of this symbol exists in the underlay.
2462
0
    return underlay_->IsSubSymbolOfBuiltType(name);
2463
0
  }
2464
0
  return false;
2465
0
}
2466
2467
bool DescriptorPool::TryFindSymbolInFallbackDatabase(
2468
0
    absl::string_view name) const {
2469
0
  if (fallback_database_ == nullptr) return false;
2470
2471
0
  if (tables_->known_bad_symbols_.contains(name)) return false;
2472
2473
0
  std::string name_string(name);
2474
0
  auto file_proto = absl::make_unique<FileDescriptorProto>();
2475
0
  if (  // We skip looking in the fallback database if the name is a sub-symbol
2476
        // of any descriptor that already exists in the descriptor pool (except
2477
        // for package descriptors).  This is valid because all symbols except
2478
        // for packages are defined in a single file, so if the symbol exists
2479
        // then we should already have its definition.
2480
        //
2481
        // The other reason to do this is to support "overriding" type
2482
        // definitions by merging two databases that define the same type. (Yes,
2483
        // people do this.)  The main difficulty with making this work is that
2484
        // FindFileContainingSymbol() is allowed to return both false positives
2485
        // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and
2486
        // false negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase).
2487
        // When two such databases are merged, looking up a non-existent
2488
        // sub-symbol of a type that already exists in the descriptor pool can
2489
        // result in an attempt to load multiple definitions of the same type.
2490
        // The check below avoids this.
2491
0
      IsSubSymbolOfBuiltType(name)
2492
2493
      // Look up file containing this symbol in fallback database.
2494
0
      || !fallback_database_->FindFileContainingSymbol(name_string,
2495
0
                                                       file_proto.get())
2496
2497
      // Check if we've already built this file. If so, it apparently doesn't
2498
      // contain the symbol we're looking for.  Some DescriptorDatabases
2499
      // return false positives.
2500
0
      || tables_->FindFile(file_proto->name()) != nullptr
2501
2502
      // Build the file.
2503
0
      || BuildFileFromDatabase(*file_proto) == nullptr) {
2504
0
    tables_->known_bad_symbols_.insert(std::move(name_string));
2505
0
    return false;
2506
0
  }
2507
2508
0
  return true;
2509
0
}
2510
2511
bool DescriptorPool::TryFindExtensionInFallbackDatabase(
2512
0
    const Descriptor* containing_type, int field_number) const {
2513
0
  if (fallback_database_ == nullptr) return false;
2514
2515
0
  auto file_proto = absl::make_unique<FileDescriptorProto>();
2516
0
  if (!fallback_database_->FindFileContainingExtension(
2517
0
          containing_type->full_name(), field_number, file_proto.get())) {
2518
0
    return false;
2519
0
  }
2520
2521
0
  if (tables_->FindFile(file_proto->name()) != nullptr) {
2522
    // We've already loaded this file, and it apparently doesn't contain the
2523
    // extension we're looking for.  Some DescriptorDatabases return false
2524
    // positives.
2525
0
    return false;
2526
0
  }
2527
2528
0
  if (BuildFileFromDatabase(*file_proto) == nullptr) {
2529
0
    return false;
2530
0
  }
2531
2532
0
  return true;
2533
0
}
2534
2535
// ===================================================================
2536
2537
0
bool FieldDescriptor::is_map_message_type() const {
2538
0
  return type_descriptor_.message_type->options().map_entry();
2539
0
}
2540
2541
std::string FieldDescriptor::DefaultValueAsString(
2542
0
    bool quote_string_type) const {
2543
0
  ABSL_CHECK(has_default_value()) << "No default value";
2544
0
  switch (cpp_type()) {
2545
0
    case CPPTYPE_INT32:
2546
0
      return absl::StrCat(default_value_int32_t());
2547
0
    case CPPTYPE_INT64:
2548
0
      return absl::StrCat(default_value_int64_t());
2549
0
    case CPPTYPE_UINT32:
2550
0
      return absl::StrCat(default_value_uint32_t());
2551
0
    case CPPTYPE_UINT64:
2552
0
      return absl::StrCat(default_value_uint64_t());
2553
0
    case CPPTYPE_FLOAT:
2554
0
      return io::SimpleFtoa(default_value_float());
2555
0
    case CPPTYPE_DOUBLE:
2556
0
      return io::SimpleDtoa(default_value_double());
2557
0
    case CPPTYPE_BOOL:
2558
0
      return default_value_bool() ? "true" : "false";
2559
0
    case CPPTYPE_STRING:
2560
0
      if (quote_string_type) {
2561
0
        return absl::StrCat("\"", absl::CEscape(default_value_string()), "\"");
2562
0
      } else {
2563
0
        if (type() == TYPE_BYTES) {
2564
0
          return absl::CEscape(default_value_string());
2565
0
        } else {
2566
0
          return default_value_string();
2567
0
        }
2568
0
      }
2569
0
    case CPPTYPE_ENUM:
2570
0
      return default_value_enum()->name();
2571
0
    case CPPTYPE_MESSAGE:
2572
0
      ABSL_DLOG(FATAL) << "Messages can't have default values!";
2573
0
      break;
2574
0
  }
2575
0
  ABSL_LOG(FATAL) << "Can't get here: failed to get default value as string";
2576
0
  return "";
2577
0
}
2578
2579
// CopyTo methods ====================================================
2580
2581
0
void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
2582
0
  CopyHeadingTo(proto);
2583
2584
0
  for (int i = 0; i < dependency_count(); i++) {
2585
0
    proto->add_dependency(dependency(i)->name());
2586
0
  }
2587
2588
0
  for (int i = 0; i < public_dependency_count(); i++) {
2589
0
    proto->add_public_dependency(public_dependencies_[i]);
2590
0
  }
2591
2592
0
  for (int i = 0; i < weak_dependency_count(); i++) {
2593
0
    proto->add_weak_dependency(weak_dependencies_[i]);
2594
0
  }
2595
2596
0
  for (int i = 0; i < message_type_count(); i++) {
2597
0
    message_type(i)->CopyTo(proto->add_message_type());
2598
0
  }
2599
0
  for (int i = 0; i < enum_type_count(); i++) {
2600
0
    enum_type(i)->CopyTo(proto->add_enum_type());
2601
0
  }
2602
0
  for (int i = 0; i < service_count(); i++) {
2603
0
    service(i)->CopyTo(proto->add_service());
2604
0
  }
2605
0
  for (int i = 0; i < extension_count(); i++) {
2606
0
    extension(i)->CopyTo(proto->add_extension());
2607
0
  }
2608
0
}
2609
2610
0
void FileDescriptor::CopyHeadingTo(FileDescriptorProto* proto) const {
2611
0
  proto->set_name(name());
2612
0
  if (!package().empty()) {
2613
0
    proto->set_package(package());
2614
0
  }
2615
2616
  // TODO(liujisi): Also populate when syntax="proto2".
2617
0
  FileDescriptorLegacy::Syntax syntax = FileDescriptorLegacy(this).syntax();
2618
0
  if (syntax == FileDescriptorLegacy::Syntax::SYNTAX_PROTO3
2619
0
  ) {
2620
0
    proto->set_syntax(FileDescriptorLegacy::SyntaxName(syntax));
2621
0
  }
2622
2623
0
  if (&options() != &FileOptions::default_instance()) {
2624
0
    *proto->mutable_options() = options();
2625
0
  }
2626
0
}
2627
2628
0
void FileDescriptor::CopyJsonNameTo(FileDescriptorProto* proto) const {
2629
0
  if (message_type_count() != proto->message_type_size() ||
2630
0
      extension_count() != proto->extension_size()) {
2631
0
    ABSL_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
2632
0
    return;
2633
0
  }
2634
0
  for (int i = 0; i < message_type_count(); i++) {
2635
0
    message_type(i)->CopyJsonNameTo(proto->mutable_message_type(i));
2636
0
  }
2637
0
  for (int i = 0; i < extension_count(); i++) {
2638
0
    extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
2639
0
  }
2640
0
}
2641
2642
0
void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
2643
0
  if (source_code_info_ &&
2644
0
      source_code_info_ != &SourceCodeInfo::default_instance()) {
2645
0
    proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
2646
0
  }
2647
0
}
2648
2649
0
void Descriptor::CopyTo(DescriptorProto* proto) const {
2650
0
  proto->set_name(name());
2651
2652
0
  for (int i = 0; i < field_count(); i++) {
2653
0
    field(i)->CopyTo(proto->add_field());
2654
0
  }
2655
0
  for (int i = 0; i < oneof_decl_count(); i++) {
2656
0
    oneof_decl(i)->CopyTo(proto->add_oneof_decl());
2657
0
  }
2658
0
  for (int i = 0; i < nested_type_count(); i++) {
2659
0
    nested_type(i)->CopyTo(proto->add_nested_type());
2660
0
  }
2661
0
  for (int i = 0; i < enum_type_count(); i++) {
2662
0
    enum_type(i)->CopyTo(proto->add_enum_type());
2663
0
  }
2664
0
  for (int i = 0; i < extension_range_count(); i++) {
2665
0
    extension_range(i)->CopyTo(proto->add_extension_range());
2666
0
  }
2667
0
  for (int i = 0; i < extension_count(); i++) {
2668
0
    extension(i)->CopyTo(proto->add_extension());
2669
0
  }
2670
0
  for (int i = 0; i < reserved_range_count(); i++) {
2671
0
    DescriptorProto::ReservedRange* range = proto->add_reserved_range();
2672
0
    range->set_start(reserved_range(i)->start);
2673
0
    range->set_end(reserved_range(i)->end);
2674
0
  }
2675
0
  for (int i = 0; i < reserved_name_count(); i++) {
2676
0
    proto->add_reserved_name(reserved_name(i));
2677
0
  }
2678
2679
0
  if (&options() != &MessageOptions::default_instance()) {
2680
0
    proto->mutable_options()->CopyFrom(options());
2681
0
  }
2682
0
}
2683
2684
0
void Descriptor::CopyJsonNameTo(DescriptorProto* proto) const {
2685
0
  if (field_count() != proto->field_size() ||
2686
0
      nested_type_count() != proto->nested_type_size() ||
2687
0
      extension_count() != proto->extension_size()) {
2688
0
    ABSL_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
2689
0
    return;
2690
0
  }
2691
0
  for (int i = 0; i < field_count(); i++) {
2692
0
    field(i)->CopyJsonNameTo(proto->mutable_field(i));
2693
0
  }
2694
0
  for (int i = 0; i < nested_type_count(); i++) {
2695
0
    nested_type(i)->CopyJsonNameTo(proto->mutable_nested_type(i));
2696
0
  }
2697
0
  for (int i = 0; i < extension_count(); i++) {
2698
0
    extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
2699
0
  }
2700
0
}
2701
2702
0
void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
2703
0
  proto->set_name(name());
2704
0
  proto->set_number(number());
2705
0
  if (has_json_name_) {
2706
0
    proto->set_json_name(json_name());
2707
0
  }
2708
0
  if (proto3_optional_) {
2709
0
    proto->set_proto3_optional(true);
2710
0
  }
2711
  // Some compilers do not allow static_cast directly between two enum types,
2712
  // so we must cast to int first.
2713
0
  proto->set_label(static_cast<FieldDescriptorProto::Label>(
2714
0
      absl::implicit_cast<int>(label())));
2715
0
  proto->set_type(static_cast<FieldDescriptorProto::Type>(
2716
0
      absl::implicit_cast<int>(type())));
2717
2718
0
  if (is_extension()) {
2719
0
    if (!containing_type()->is_unqualified_placeholder_) {
2720
0
      proto->set_extendee(".");
2721
0
    }
2722
0
    proto->mutable_extendee()->append(containing_type()->full_name());
2723
0
  }
2724
2725
0
  if (cpp_type() == CPPTYPE_MESSAGE) {
2726
0
    if (message_type()->is_placeholder_) {
2727
      // We don't actually know if the type is a message type.  It could be
2728
      // an enum.
2729
0
      proto->clear_type();
2730
0
    }
2731
2732
0
    if (!message_type()->is_unqualified_placeholder_) {
2733
0
      proto->set_type_name(".");
2734
0
    }
2735
0
    proto->mutable_type_name()->append(message_type()->full_name());
2736
0
  } else if (cpp_type() == CPPTYPE_ENUM) {
2737
0
    if (!enum_type()->is_unqualified_placeholder_) {
2738
0
      proto->set_type_name(".");
2739
0
    }
2740
0
    proto->mutable_type_name()->append(enum_type()->full_name());
2741
0
  }
2742
2743
0
  if (has_default_value()) {
2744
0
    proto->set_default_value(DefaultValueAsString(false));
2745
0
  }
2746
2747
0
  if (containing_oneof() != nullptr && !is_extension()) {
2748
0
    proto->set_oneof_index(containing_oneof()->index());
2749
0
  }
2750
2751
0
  if (&options() != &FieldOptions::default_instance()) {
2752
0
    proto->mutable_options()->CopyFrom(options());
2753
0
  }
2754
0
}
2755
2756
0
void FieldDescriptor::CopyJsonNameTo(FieldDescriptorProto* proto) const {
2757
0
  proto->set_json_name(json_name());
2758
0
}
2759
2760
0
void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const {
2761
0
  proto->set_name(name());
2762
0
  if (&options() != &OneofOptions::default_instance()) {
2763
0
    proto->mutable_options()->CopyFrom(options());
2764
0
  }
2765
0
}
2766
2767
0
void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const {
2768
0
  proto->set_name(name());
2769
2770
0
  for (int i = 0; i < value_count(); i++) {
2771
0
    value(i)->CopyTo(proto->add_value());
2772
0
  }
2773
0
  for (int i = 0; i < reserved_range_count(); i++) {
2774
0
    EnumDescriptorProto::EnumReservedRange* range = proto->add_reserved_range();
2775
0
    range->set_start(reserved_range(i)->start);
2776
0
    range->set_end(reserved_range(i)->end);
2777
0
  }
2778
0
  for (int i = 0; i < reserved_name_count(); i++) {
2779
0
    proto->add_reserved_name(reserved_name(i));
2780
0
  }
2781
2782
0
  if (&options() != &EnumOptions::default_instance()) {
2783
0
    proto->mutable_options()->CopyFrom(options());
2784
0
  }
2785
0
}
2786
2787
0
void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const {
2788
0
  proto->set_name(name());
2789
0
  proto->set_number(number());
2790
2791
0
  if (&options() != &EnumValueOptions::default_instance()) {
2792
0
    proto->mutable_options()->CopyFrom(options());
2793
0
  }
2794
0
}
2795
2796
0
void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const {
2797
0
  proto->set_name(name());
2798
2799
0
  for (int i = 0; i < method_count(); i++) {
2800
0
    method(i)->CopyTo(proto->add_method());
2801
0
  }
2802
2803
0
  if (&options() != &ServiceOptions::default_instance()) {
2804
0
    proto->mutable_options()->CopyFrom(options());
2805
0
  }
2806
0
}
2807
2808
0
void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const {
2809
0
  proto->set_name(name());
2810
2811
0
  if (!input_type()->is_unqualified_placeholder_) {
2812
0
    proto->set_input_type(".");
2813
0
  }
2814
0
  proto->mutable_input_type()->append(input_type()->full_name());
2815
2816
0
  if (!output_type()->is_unqualified_placeholder_) {
2817
0
    proto->set_output_type(".");
2818
0
  }
2819
0
  proto->mutable_output_type()->append(output_type()->full_name());
2820
2821
0
  if (&options() != &MethodOptions::default_instance()) {
2822
0
    proto->mutable_options()->CopyFrom(options());
2823
0
  }
2824
2825
0
  if (client_streaming_) {
2826
0
    proto->set_client_streaming(true);
2827
0
  }
2828
0
  if (server_streaming_) {
2829
0
    proto->set_server_streaming(true);
2830
0
  }
2831
0
}
2832
2833
// DebugString methods ===============================================
2834
2835
namespace {
2836
2837
bool RetrieveOptionsAssumingRightPool(
2838
    int depth, const Message& options,
2839
0
    std::vector<std::string>* option_entries) {
2840
0
  option_entries->clear();
2841
0
  const Reflection* reflection = options.GetReflection();
2842
0
  std::vector<const FieldDescriptor*> fields;
2843
0
  reflection->ListFields(options, &fields);
2844
0
  for (const FieldDescriptor* field : fields) {
2845
0
    int count = 1;
2846
0
    bool repeated = false;
2847
0
    if (field->is_repeated()) {
2848
0
      count = reflection->FieldSize(options, field);
2849
0
      repeated = true;
2850
0
    }
2851
0
    for (int j = 0; j < count; j++) {
2852
0
      std::string fieldval;
2853
0
      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2854
0
        std::string tmp;
2855
0
        TextFormat::Printer printer;
2856
0
        printer.SetExpandAny(true);
2857
0
        printer.SetInitialIndentLevel(depth + 1);
2858
0
        printer.PrintFieldValueToString(options, field, repeated ? j : -1,
2859
0
                                        &tmp);
2860
0
        fieldval.append("{\n");
2861
0
        fieldval.append(tmp);
2862
0
        fieldval.append(depth * 2, ' ');
2863
0
        fieldval.append("}");
2864
0
      } else {
2865
0
        TextFormat::PrintFieldValueToString(options, field, repeated ? j : -1,
2866
0
                                            &fieldval);
2867
0
      }
2868
0
      std::string name;
2869
0
      if (field->is_extension()) {
2870
0
        name = absl::StrCat("(.", field->full_name(), ")");
2871
0
      } else {
2872
0
        name = field->name();
2873
0
      }
2874
0
      option_entries->push_back(absl::StrCat(name, " = ", fieldval));
2875
0
    }
2876
0
  }
2877
0
  return !option_entries->empty();
2878
0
}
2879
2880
// Used by each of the option formatters.
2881
bool RetrieveOptions(int depth, const Message& options,
2882
                     const DescriptorPool* pool,
2883
0
                     std::vector<std::string>* option_entries) {
2884
  // When printing custom options for a descriptor, we must use an options
2885
  // message built on top of the same DescriptorPool where the descriptor
2886
  // is coming from. This is to ensure we are interpreting custom options
2887
  // against the right pool.
2888
0
  if (options.GetDescriptor()->file()->pool() == pool) {
2889
0
    return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2890
0
  } else {
2891
0
    const Descriptor* option_descriptor =
2892
0
        pool->FindMessageTypeByName(options.GetDescriptor()->full_name());
2893
0
    if (option_descriptor == nullptr) {
2894
      // descriptor.proto is not in the pool. This means no custom options are
2895
      // used so we are safe to proceed with the compiled options message type.
2896
0
      return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2897
0
    }
2898
0
    DynamicMessageFactory factory;
2899
0
    std::unique_ptr<Message> dynamic_options(
2900
0
        factory.GetPrototype(option_descriptor)->New());
2901
0
    std::string serialized = options.SerializeAsString();
2902
0
    io::CodedInputStream input(
2903
0
        reinterpret_cast<const uint8_t*>(serialized.c_str()),
2904
0
        serialized.size());
2905
0
    input.SetExtensionRegistry(pool, &factory);
2906
0
    if (dynamic_options->ParseFromCodedStream(&input)) {
2907
0
      return RetrieveOptionsAssumingRightPool(depth, *dynamic_options,
2908
0
                                              option_entries);
2909
0
    } else {
2910
0
      ABSL_LOG(ERROR) << "Found invalid proto option data for: "
2911
0
                      << options.GetDescriptor()->full_name();
2912
0
      return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2913
0
    }
2914
0
  }
2915
0
}
2916
2917
// Formats options that all appear together in brackets. Does not include
2918
// brackets.
2919
bool FormatBracketedOptions(int depth, const Message& options,
2920
0
                            const DescriptorPool* pool, std::string* output) {
2921
0
  std::vector<std::string> all_options;
2922
0
  if (RetrieveOptions(depth, options, pool, &all_options)) {
2923
0
    output->append(absl::StrJoin(all_options, ", "));
2924
0
  }
2925
0
  return !all_options.empty();
2926
0
}
2927
2928
// Formats options one per line
2929
bool FormatLineOptions(int depth, const Message& options,
2930
0
                       const DescriptorPool* pool, std::string* output) {
2931
0
  std::string prefix(depth * 2, ' ');
2932
0
  std::vector<std::string> all_options;
2933
0
  if (RetrieveOptions(depth, options, pool, &all_options)) {
2934
0
    for (const std::string& option : all_options) {
2935
0
      absl::SubstituteAndAppend(output, "$0option $1;\n", prefix, option);
2936
0
    }
2937
0
  }
2938
0
  return !all_options.empty();
2939
0
}
2940
2941
class SourceLocationCommentPrinter {
2942
 public:
2943
  template <typename DescType>
2944
  SourceLocationCommentPrinter(const DescType* desc, const std::string& prefix,
2945
                               const DebugStringOptions& options)
2946
0
      : options_(options), prefix_(prefix) {
2947
    // Perform the SourceLocation lookup only if we're including user comments,
2948
    // because the lookup is fairly expensive.
2949
0
    have_source_loc_ =
2950
0
        options.include_comments && desc->GetSourceLocation(&source_loc_);
2951
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&)
2952
  SourceLocationCommentPrinter(const FileDescriptor* file,
2953
                               const std::vector<int>& path,
2954
                               const std::string& prefix,
2955
                               const DebugStringOptions& options)
2956
0
      : options_(options), prefix_(prefix) {
2957
    // Perform the SourceLocation lookup only if we're including user comments,
2958
    // because the lookup is fairly expensive.
2959
0
    have_source_loc_ =
2960
0
        options.include_comments && file->GetSourceLocation(path, &source_loc_);
2961
0
  }
2962
0
  void AddPreComment(std::string* output) {
2963
0
    if (have_source_loc_) {
2964
      // Detached leading comments.
2965
0
      for (const std::string& leading_detached_comment :
2966
0
           source_loc_.leading_detached_comments) {
2967
0
        absl::StrAppend(output, FormatComment(leading_detached_comment), "\n");
2968
0
      }
2969
      // Attached leading comments.
2970
0
      if (!source_loc_.leading_comments.empty()) {
2971
0
        absl::StrAppend(output, FormatComment(source_loc_.leading_comments));
2972
0
      }
2973
0
    }
2974
0
  }
2975
0
  void AddPostComment(std::string* output) {
2976
0
    if (have_source_loc_ && source_loc_.trailing_comments.size() > 0) {
2977
0
      absl::StrAppend(output, FormatComment(source_loc_.trailing_comments));
2978
0
    }
2979
0
  }
2980
2981
  // Format comment such that each line becomes a full-line C++-style comment in
2982
  // the DebugString() output.
2983
0
  std::string FormatComment(const std::string& comment_text) {
2984
0
    std::string stripped_comment = comment_text;
2985
0
    absl::StripAsciiWhitespace(&stripped_comment);
2986
0
    std::string output;
2987
0
    for (absl::string_view line : absl::StrSplit(stripped_comment, '\n')) {
2988
0
      absl::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
2989
0
    }
2990
0
    return output;
2991
0
  }
2992
2993
 private:
2994
2995
  bool have_source_loc_;
2996
  SourceLocation source_loc_;
2997
  DebugStringOptions options_;
2998
  std::string prefix_;
2999
};
3000
3001
}  // anonymous namespace
3002
3003
0
std::string FileDescriptor::DebugString() const {
3004
0
  DebugStringOptions options;  // default options
3005
0
  return DebugStringWithOptions(options);
3006
0
}
3007
3008
std::string FileDescriptor::DebugStringWithOptions(
3009
0
    const DebugStringOptions& debug_string_options) const {
3010
0
  std::string contents;
3011
0
  {
3012
0
    std::vector<int> path;
3013
0
    path.push_back(FileDescriptorProto::kSyntaxFieldNumber);
3014
0
    SourceLocationCommentPrinter syntax_comment(this, path, "",
3015
0
                                                debug_string_options);
3016
0
    syntax_comment.AddPreComment(&contents);
3017
0
    absl::SubstituteAndAppend(
3018
0
        &contents, "syntax = \"$0\";\n\n",
3019
0
        FileDescriptorLegacy::SyntaxName(FileDescriptorLegacy(this).syntax()));
3020
0
    syntax_comment.AddPostComment(&contents);
3021
0
  }
3022
3023
0
  SourceLocationCommentPrinter comment_printer(this, "", debug_string_options);
3024
0
  comment_printer.AddPreComment(&contents);
3025
3026
0
  absl::flat_hash_set<int> public_dependencies(
3027
0
      public_dependencies_, public_dependencies_ + public_dependency_count_);
3028
0
  absl::flat_hash_set<int> weak_dependencies(
3029
0
      weak_dependencies_, weak_dependencies_ + weak_dependency_count_);
3030
3031
0
  for (int i = 0; i < dependency_count(); i++) {
3032
0
    if (public_dependencies.contains(i)) {
3033
0
      absl::SubstituteAndAppend(&contents, "import public \"$0\";\n",
3034
0
                                dependency(i)->name());
3035
0
    } else if (weak_dependencies.contains(i)) {
3036
0
      absl::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
3037
0
                                dependency(i)->name());
3038
0
    } else {
3039
0
      absl::SubstituteAndAppend(&contents, "import \"$0\";\n",
3040
0
                                dependency(i)->name());
3041
0
    }
3042
0
  }
3043
3044
0
  if (!package().empty()) {
3045
0
    std::vector<int> path;
3046
0
    path.push_back(FileDescriptorProto::kPackageFieldNumber);
3047
0
    SourceLocationCommentPrinter package_comment(this, path, "",
3048
0
                                                 debug_string_options);
3049
0
    package_comment.AddPreComment(&contents);
3050
0
    absl::SubstituteAndAppend(&contents, "package $0;\n\n", package());
3051
0
    package_comment.AddPostComment(&contents);
3052
0
  }
3053
3054
0
  if (FormatLineOptions(0, options(), pool(), &contents)) {
3055
0
    contents.append("\n");  // add some space if we had options
3056
0
  }
3057
3058
0
  for (int i = 0; i < enum_type_count(); i++) {
3059
0
    enum_type(i)->DebugString(0, &contents, debug_string_options);
3060
0
    contents.append("\n");
3061
0
  }
3062
3063
  // Find all the 'group' type extensions; we will not output their nested
3064
  // definitions (those will be done with their group field descriptor).
3065
0
  absl::flat_hash_set<const Descriptor*> groups;
3066
0
  for (int i = 0; i < extension_count(); i++) {
3067
0
    if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
3068
0
      groups.insert(extension(i)->message_type());
3069
0
    }
3070
0
  }
3071
3072
0
  for (int i = 0; i < message_type_count(); i++) {
3073
0
    if (!groups.contains(message_type(i))) {
3074
0
      message_type(i)->DebugString(0, &contents, debug_string_options,
3075
0
                                   /* include_opening_clause */ true);
3076
0
      contents.append("\n");
3077
0
    }
3078
0
  }
3079
3080
0
  for (int i = 0; i < service_count(); i++) {
3081
0
    service(i)->DebugString(&contents, debug_string_options);
3082
0
    contents.append("\n");
3083
0
  }
3084
3085
0
  const Descriptor* containing_type = nullptr;
3086
0
  for (int i = 0; i < extension_count(); i++) {
3087
0
    if (extension(i)->containing_type() != containing_type) {
3088
0
      if (i > 0) contents.append("}\n\n");
3089
0
      containing_type = extension(i)->containing_type();
3090
0
      absl::SubstituteAndAppend(&contents, "extend .$0 {\n",
3091
0
                                containing_type->full_name());
3092
0
    }
3093
0
    extension(i)->DebugString(1, &contents, debug_string_options);
3094
0
  }
3095
0
  if (extension_count() > 0) contents.append("}\n\n");
3096
3097
0
  comment_printer.AddPostComment(&contents);
3098
3099
0
  return contents;
3100
0
}
3101
3102
0
std::string Descriptor::DebugString() const {
3103
0
  DebugStringOptions options;  // default options
3104
0
  return DebugStringWithOptions(options);
3105
0
}
3106
3107
std::string Descriptor::DebugStringWithOptions(
3108
0
    const DebugStringOptions& options) const {
3109
0
  std::string contents;
3110
0
  DebugString(0, &contents, options, /* include_opening_clause */ true);
3111
0
  return contents;
3112
0
}
3113
3114
void Descriptor::DebugString(int depth, std::string* contents,
3115
                             const DebugStringOptions& debug_string_options,
3116
0
                             bool include_opening_clause) const {
3117
0
  if (options().map_entry()) {
3118
    // Do not generate debug string for auto-generated map-entry type.
3119
0
    return;
3120
0
  }
3121
0
  std::string prefix(depth * 2, ' ');
3122
0
  ++depth;
3123
3124
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3125
0
                                               debug_string_options);
3126
0
  comment_printer.AddPreComment(contents);
3127
3128
0
  if (include_opening_clause) {
3129
0
    absl::SubstituteAndAppend(contents, "$0message $1", prefix, name());
3130
0
  }
3131
0
  contents->append(" {\n");
3132
3133
0
  FormatLineOptions(depth, options(), file()->pool(), contents);
3134
3135
  // Find all the 'group' types for fields and extensions; we will not output
3136
  // their nested definitions (those will be done with their group field
3137
  // descriptor).
3138
0
  absl::flat_hash_set<const Descriptor*> groups;
3139
0
  for (int i = 0; i < field_count(); i++) {
3140
0
    if (field(i)->type() == FieldDescriptor::TYPE_GROUP) {
3141
0
      groups.insert(field(i)->message_type());
3142
0
    }
3143
0
  }
3144
0
  for (int i = 0; i < extension_count(); i++) {
3145
0
    if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
3146
0
      groups.insert(extension(i)->message_type());
3147
0
    }
3148
0
  }
3149
3150
0
  for (int i = 0; i < nested_type_count(); i++) {
3151
0
    if (!groups.contains(nested_type(i))) {
3152
0
      nested_type(i)->DebugString(depth, contents, debug_string_options,
3153
0
                                  /* include_opening_clause */ true);
3154
0
    }
3155
0
  }
3156
0
  for (int i = 0; i < enum_type_count(); i++) {
3157
0
    enum_type(i)->DebugString(depth, contents, debug_string_options);
3158
0
  }
3159
0
  for (int i = 0; i < field_count(); i++) {
3160
0
    if (field(i)->real_containing_oneof() == nullptr) {
3161
0
      field(i)->DebugString(depth, contents, debug_string_options);
3162
0
    } else if (field(i)->containing_oneof()->field(0) == field(i)) {
3163
      // This is the first field in this oneof, so print the whole oneof.
3164
0
      field(i)->containing_oneof()->DebugString(depth, contents,
3165
0
                                                debug_string_options);
3166
0
    }
3167
0
  }
3168
3169
0
  for (int i = 0; i < extension_range_count(); i++) {
3170
0
    absl::SubstituteAndAppend(contents, "$0  extensions $1", prefix,
3171
0
                              extension_range(i)->start);
3172
0
    if (extension_range(i)->end > extension_range(i)->start + 1) {
3173
0
      absl::SubstituteAndAppend(contents, " to $0",
3174
0
                                extension_range(i)->end - 1);
3175
0
    }
3176
0
    if (extension_range(i)->options_ != nullptr) {
3177
0
      if (extension_range(i)->options_->declaration_size() > 0) {
3178
0
        absl::StrAppend(contents, " [");
3179
0
        for (int j = 0; j < extension_range(i)->options_->declaration_size();
3180
0
             ++j) {
3181
0
          if (j > 0) {
3182
0
            absl::StrAppend(contents, ",");
3183
0
          }
3184
0
          absl::SubstituteAndAppend(
3185
0
              contents, " declaration = { $0 }",
3186
0
              extension_range(i)->options_->declaration(j).ShortDebugString());
3187
0
        }
3188
0
        absl::StrAppend(contents, " ] ");
3189
0
      }
3190
0
    }
3191
0
    absl::StrAppend(contents, ";\n");
3192
0
  }
3193
3194
  // Group extensions by what they extend, so they can be printed out together.
3195
0
  const Descriptor* containing_type = nullptr;
3196
0
  for (int i = 0; i < extension_count(); i++) {
3197
0
    if (extension(i)->containing_type() != containing_type) {
3198
0
      if (i > 0) absl::SubstituteAndAppend(contents, "$0  }\n", prefix);
3199
0
      containing_type = extension(i)->containing_type();
3200
0
      absl::SubstituteAndAppend(contents, "$0  extend .$1 {\n", prefix,
3201
0
                                containing_type->full_name());
3202
0
    }
3203
0
    extension(i)->DebugString(depth + 1, contents, debug_string_options);
3204
0
  }
3205
0
  if (extension_count() > 0)
3206
0
    absl::SubstituteAndAppend(contents, "$0  }\n", prefix);
3207
3208
0
  if (reserved_range_count() > 0) {
3209
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3210
0
    for (int i = 0; i < reserved_range_count(); i++) {
3211
0
      const Descriptor::ReservedRange* range = reserved_range(i);
3212
0
      if (range->end == range->start + 1) {
3213
0
        absl::SubstituteAndAppend(contents, "$0, ", range->start);
3214
0
      } else if (range->end > FieldDescriptor::kMaxNumber) {
3215
0
        absl::SubstituteAndAppend(contents, "$0 to max, ", range->start);
3216
0
      } else {
3217
0
        absl::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
3218
0
                                  range->end - 1);
3219
0
      }
3220
0
    }
3221
0
    contents->replace(contents->size() - 2, 2, ";\n");
3222
0
  }
3223
3224
0
  if (reserved_name_count() > 0) {
3225
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3226
0
    for (int i = 0; i < reserved_name_count(); i++) {
3227
0
      absl::SubstituteAndAppend(contents, "\"$0\", ",
3228
0
                                absl::CEscape(reserved_name(i)));
3229
0
    }
3230
0
    contents->replace(contents->size() - 2, 2, ";\n");
3231
0
  }
3232
3233
0
  absl::SubstituteAndAppend(contents, "$0}\n", prefix);
3234
0
  comment_printer.AddPostComment(contents);
3235
0
}
3236
3237
0
std::string FieldDescriptor::DebugString() const {
3238
0
  DebugStringOptions options;  // default options
3239
0
  return DebugStringWithOptions(options);
3240
0
}
3241
3242
std::string FieldDescriptor::DebugStringWithOptions(
3243
0
    const DebugStringOptions& debug_string_options) const {
3244
0
  std::string contents;
3245
0
  int depth = 0;
3246
0
  if (is_extension()) {
3247
0
    absl::SubstituteAndAppend(&contents, "extend .$0 {\n",
3248
0
                              containing_type()->full_name());
3249
0
    depth = 1;
3250
0
  }
3251
0
  DebugString(depth, &contents, debug_string_options);
3252
0
  if (is_extension()) {
3253
0
    contents.append("}\n");
3254
0
  }
3255
0
  return contents;
3256
0
}
3257
3258
// The field type string used in FieldDescriptor::DebugString()
3259
0
std::string FieldDescriptor::FieldTypeNameDebugString() const {
3260
0
  switch (type()) {
3261
0
    case TYPE_MESSAGE:
3262
0
      return absl::StrCat(".", message_type()->full_name());
3263
0
    case TYPE_ENUM:
3264
0
      return absl::StrCat(".", enum_type()->full_name());
3265
0
    default:
3266
0
      return kTypeToName[type()];
3267
0
  }
3268
0
}
3269
3270
void FieldDescriptor::DebugString(
3271
    int depth, std::string* contents,
3272
0
    const DebugStringOptions& debug_string_options) const {
3273
0
  std::string prefix(depth * 2, ' ');
3274
0
  std::string field_type;
3275
3276
  // Special case map fields.
3277
0
  if (is_map()) {
3278
0
    absl::SubstituteAndAppend(
3279
0
        &field_type, "map<$0, $1>",
3280
0
        message_type()->field(0)->FieldTypeNameDebugString(),
3281
0
        message_type()->field(1)->FieldTypeNameDebugString());
3282
0
  } else {
3283
0
    field_type = FieldTypeNameDebugString();
3284
0
  }
3285
3286
0
  std::string label = absl::StrCat(kLabelToName[this->label()], " ");
3287
3288
  // Label is omitted for maps, oneof, and plain proto3 fields.
3289
0
  if (is_map() || real_containing_oneof() ||
3290
0
      (is_optional() && !FieldDescriptorLegacy(this).has_optional_keyword())) {
3291
0
    label.clear();
3292
0
  }
3293
3294
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3295
0
                                               debug_string_options);
3296
0
  comment_printer.AddPreComment(contents);
3297
3298
0
  absl::SubstituteAndAppend(
3299
0
      contents, "$0$1$2 $3 = $4", prefix, label, field_type,
3300
0
      type() == TYPE_GROUP ? message_type()->name() : name(), number());
3301
3302
0
  bool bracketed = false;
3303
0
  if (has_default_value()) {
3304
0
    bracketed = true;
3305
0
    absl::SubstituteAndAppend(contents, " [default = $0",
3306
0
                              DefaultValueAsString(true));
3307
0
  }
3308
0
  if (has_json_name_) {
3309
0
    if (!bracketed) {
3310
0
      bracketed = true;
3311
0
      contents->append(" [");
3312
0
    } else {
3313
0
      contents->append(", ");
3314
0
    }
3315
0
    contents->append("json_name = \"");
3316
0
    contents->append(absl::CEscape(json_name()));
3317
0
    contents->append("\"");
3318
0
  }
3319
3320
0
  std::string formatted_options;
3321
0
  if (FormatBracketedOptions(depth, options(), file()->pool(),
3322
0
                             &formatted_options)) {
3323
0
    contents->append(bracketed ? ", " : " [");
3324
0
    bracketed = true;
3325
0
    contents->append(formatted_options);
3326
0
  }
3327
3328
0
  if (bracketed) {
3329
0
    contents->append("]");
3330
0
  }
3331
3332
0
  if (type() == TYPE_GROUP) {
3333
0
    if (debug_string_options.elide_group_body) {
3334
0
      contents->append(" { ... };\n");
3335
0
    } else {
3336
0
      message_type()->DebugString(depth, contents, debug_string_options,
3337
0
                                  /* include_opening_clause */ false);
3338
0
    }
3339
0
  } else {
3340
0
    contents->append(";\n");
3341
0
  }
3342
3343
0
  comment_printer.AddPostComment(contents);
3344
0
}
3345
3346
0
std::string OneofDescriptor::DebugString() const {
3347
0
  DebugStringOptions options;  // default values
3348
0
  return DebugStringWithOptions(options);
3349
0
}
3350
3351
std::string OneofDescriptor::DebugStringWithOptions(
3352
0
    const DebugStringOptions& options) const {
3353
0
  std::string contents;
3354
0
  DebugString(0, &contents, options);
3355
0
  return contents;
3356
0
}
3357
3358
void OneofDescriptor::DebugString(
3359
    int depth, std::string* contents,
3360
0
    const DebugStringOptions& debug_string_options) const {
3361
0
  std::string prefix(depth * 2, ' ');
3362
0
  ++depth;
3363
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3364
0
                                               debug_string_options);
3365
0
  comment_printer.AddPreComment(contents);
3366
0
  absl::SubstituteAndAppend(contents, "$0oneof $1 {", prefix, name());
3367
3368
0
  FormatLineOptions(depth, options(), containing_type()->file()->pool(),
3369
0
                    contents);
3370
3371
0
  if (debug_string_options.elide_oneof_body) {
3372
0
    contents->append(" ... }\n");
3373
0
  } else {
3374
0
    contents->append("\n");
3375
0
    for (int i = 0; i < field_count(); i++) {
3376
0
      field(i)->DebugString(depth, contents, debug_string_options);
3377
0
    }
3378
0
    absl::SubstituteAndAppend(contents, "$0}\n", prefix);
3379
0
  }
3380
0
  comment_printer.AddPostComment(contents);
3381
0
}
3382
3383
0
std::string EnumDescriptor::DebugString() const {
3384
0
  DebugStringOptions options;  // default values
3385
0
  return DebugStringWithOptions(options);
3386
0
}
3387
3388
std::string EnumDescriptor::DebugStringWithOptions(
3389
0
    const DebugStringOptions& options) const {
3390
0
  std::string contents;
3391
0
  DebugString(0, &contents, options);
3392
0
  return contents;
3393
0
}
3394
3395
void EnumDescriptor::DebugString(
3396
    int depth, std::string* contents,
3397
0
    const DebugStringOptions& debug_string_options) const {
3398
0
  std::string prefix(depth * 2, ' ');
3399
0
  ++depth;
3400
3401
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3402
0
                                               debug_string_options);
3403
0
  comment_printer.AddPreComment(contents);
3404
3405
0
  absl::SubstituteAndAppend(contents, "$0enum $1 {\n", prefix, name());
3406
3407
0
  FormatLineOptions(depth, options(), file()->pool(), contents);
3408
3409
0
  for (int i = 0; i < value_count(); i++) {
3410
0
    value(i)->DebugString(depth, contents, debug_string_options);
3411
0
  }
3412
3413
0
  if (reserved_range_count() > 0) {
3414
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3415
0
    for (int i = 0; i < reserved_range_count(); i++) {
3416
0
      const EnumDescriptor::ReservedRange* range = reserved_range(i);
3417
0
      if (range->end == range->start) {
3418
0
        absl::SubstituteAndAppend(contents, "$0, ", range->start);
3419
0
      } else if (range->end == INT_MAX) {
3420
0
        absl::SubstituteAndAppend(contents, "$0 to max, ", range->start);
3421
0
      } else {
3422
0
        absl::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
3423
0
                                  range->end);
3424
0
      }
3425
0
    }
3426
0
    contents->replace(contents->size() - 2, 2, ";\n");
3427
0
  }
3428
3429
0
  if (reserved_name_count() > 0) {
3430
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3431
0
    for (int i = 0; i < reserved_name_count(); i++) {
3432
0
      absl::SubstituteAndAppend(contents, "\"$0\", ",
3433
0
                                absl::CEscape(reserved_name(i)));
3434
0
    }
3435
0
    contents->replace(contents->size() - 2, 2, ";\n");
3436
0
  }
3437
3438
0
  absl::SubstituteAndAppend(contents, "$0}\n", prefix);
3439
3440
0
  comment_printer.AddPostComment(contents);
3441
0
}
3442
3443
0
std::string EnumValueDescriptor::DebugString() const {
3444
0
  DebugStringOptions options;  // default values
3445
0
  return DebugStringWithOptions(options);
3446
0
}
3447
3448
std::string EnumValueDescriptor::DebugStringWithOptions(
3449
0
    const DebugStringOptions& options) const {
3450
0
  std::string contents;
3451
0
  DebugString(0, &contents, options);
3452
0
  return contents;
3453
0
}
3454
3455
void EnumValueDescriptor::DebugString(
3456
    int depth, std::string* contents,
3457
0
    const DebugStringOptions& debug_string_options) const {
3458
0
  std::string prefix(depth * 2, ' ');
3459
3460
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3461
0
                                               debug_string_options);
3462
0
  comment_printer.AddPreComment(contents);
3463
3464
0
  absl::SubstituteAndAppend(contents, "$0$1 = $2", prefix, name(), number());
3465
3466
0
  std::string formatted_options;
3467
0
  if (FormatBracketedOptions(depth, options(), type()->file()->pool(),
3468
0
                             &formatted_options)) {
3469
0
    absl::SubstituteAndAppend(contents, " [$0]", formatted_options);
3470
0
  }
3471
0
  contents->append(";\n");
3472
3473
0
  comment_printer.AddPostComment(contents);
3474
0
}
3475
3476
0
std::string ServiceDescriptor::DebugString() const {
3477
0
  DebugStringOptions options;  // default values
3478
0
  return DebugStringWithOptions(options);
3479
0
}
3480
3481
std::string ServiceDescriptor::DebugStringWithOptions(
3482
0
    const DebugStringOptions& options) const {
3483
0
  std::string contents;
3484
0
  DebugString(&contents, options);
3485
0
  return contents;
3486
0
}
3487
3488
void ServiceDescriptor::DebugString(
3489
    std::string* contents,
3490
0
    const DebugStringOptions& debug_string_options) const {
3491
0
  SourceLocationCommentPrinter comment_printer(this, /* prefix */ "",
3492
0
                                               debug_string_options);
3493
0
  comment_printer.AddPreComment(contents);
3494
3495
0
  absl::SubstituteAndAppend(contents, "service $0 {\n", name());
3496
3497
0
  FormatLineOptions(1, options(), file()->pool(), contents);
3498
3499
0
  for (int i = 0; i < method_count(); i++) {
3500
0
    method(i)->DebugString(1, contents, debug_string_options);
3501
0
  }
3502
3503
0
  contents->append("}\n");
3504
3505
0
  comment_printer.AddPostComment(contents);
3506
0
}
3507
3508
0
std::string MethodDescriptor::DebugString() const {
3509
0
  DebugStringOptions options;  // default values
3510
0
  return DebugStringWithOptions(options);
3511
0
}
3512
3513
std::string MethodDescriptor::DebugStringWithOptions(
3514
0
    const DebugStringOptions& options) const {
3515
0
  std::string contents;
3516
0
  DebugString(0, &contents, options);
3517
0
  return contents;
3518
0
}
3519
3520
void MethodDescriptor::DebugString(
3521
    int depth, std::string* contents,
3522
0
    const DebugStringOptions& debug_string_options) const {
3523
0
  std::string prefix(depth * 2, ' ');
3524
0
  ++depth;
3525
3526
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3527
0
                                               debug_string_options);
3528
0
  comment_printer.AddPreComment(contents);
3529
3530
0
  absl::SubstituteAndAppend(
3531
0
      contents, "$0rpc $1($4.$2) returns ($5.$3)", prefix, name(),
3532
0
      input_type()->full_name(), output_type()->full_name(),
3533
0
      client_streaming() ? "stream " : "", server_streaming() ? "stream " : "");
3534
3535
0
  std::string formatted_options;
3536
0
  if (FormatLineOptions(depth, options(), service()->file()->pool(),
3537
0
                        &formatted_options)) {
3538
0
    absl::SubstituteAndAppend(contents, " {\n$0$1}\n", formatted_options,
3539
0
                              prefix);
3540
0
  } else {
3541
0
    contents->append(";\n");
3542
0
  }
3543
3544
0
  comment_printer.AddPostComment(contents);
3545
0
}
3546
3547
// Location methods ===============================================
3548
3549
bool FileDescriptor::GetSourceLocation(const std::vector<int>& path,
3550
0
                                       SourceLocation* out_location) const {
3551
0
  ABSL_CHECK(out_location != nullptr);
3552
0
  if (source_code_info_) {
3553
0
    if (const SourceCodeInfo_Location* loc =
3554
0
            tables_->GetSourceLocation(path, source_code_info_)) {
3555
0
      const RepeatedField<int32_t>& span = loc->span();
3556
0
      if (span.size() == 3 || span.size() == 4) {
3557
0
        out_location->start_line = span.Get(0);
3558
0
        out_location->start_column = span.Get(1);
3559
0
        out_location->end_line = span.Get(span.size() == 3 ? 0 : 2);
3560
0
        out_location->end_column = span.Get(span.size() - 1);
3561
3562
0
        out_location->leading_comments = loc->leading_comments();
3563
0
        out_location->trailing_comments = loc->trailing_comments();
3564
0
        out_location->leading_detached_comments.assign(
3565
0
            loc->leading_detached_comments().begin(),
3566
0
            loc->leading_detached_comments().end());
3567
0
        return true;
3568
0
      }
3569
0
    }
3570
0
  }
3571
0
  return false;
3572
0
}
3573
3574
0
bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3575
0
  std::vector<int> path;  // empty path for root FileDescriptor
3576
0
  return GetSourceLocation(path, out_location);
3577
0
}
3578
3579
0
bool FieldDescriptor::is_packed() const {
3580
0
  if (!is_packable()) return false;
3581
0
  if (FileDescriptorLegacy(file_).syntax() ==
3582
0
      FileDescriptorLegacy::Syntax::SYNTAX_PROTO2) {
3583
0
    return (options_ != nullptr) && options_->packed();
3584
0
  } else {
3585
0
    return options_ == nullptr || !options_->has_packed() || options_->packed();
3586
0
  }
3587
0
}
3588
3589
0
bool FieldDescriptor::requires_utf8_validation() const {
3590
0
  return type() == TYPE_STRING &&
3591
0
         FileDescriptorLegacy(file_).syntax() ==
3592
0
             FileDescriptorLegacy::Syntax::SYNTAX_PROTO3;
3593
0
}
3594
3595
0
bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
3596
0
  std::vector<int> path;
3597
0
  GetLocationPath(&path);
3598
0
  return file()->GetSourceLocation(path, out_location);
3599
0
}
3600
3601
0
bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3602
0
  std::vector<int> path;
3603
0
  GetLocationPath(&path);
3604
0
  return file()->GetSourceLocation(path, out_location);
3605
0
}
3606
3607
0
bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3608
0
  std::vector<int> path;
3609
0
  GetLocationPath(&path);
3610
0
  return containing_type()->file()->GetSourceLocation(path, out_location);
3611
0
}
3612
3613
0
bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3614
0
  std::vector<int> path;
3615
0
  GetLocationPath(&path);
3616
0
  return file()->GetSourceLocation(path, out_location);
3617
0
}
3618
3619
0
bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3620
0
  std::vector<int> path;
3621
0
  GetLocationPath(&path);
3622
0
  return service()->file()->GetSourceLocation(path, out_location);
3623
0
}
3624
3625
0
bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3626
0
  std::vector<int> path;
3627
0
  GetLocationPath(&path);
3628
0
  return file()->GetSourceLocation(path, out_location);
3629
0
}
3630
3631
bool EnumValueDescriptor::GetSourceLocation(
3632
0
    SourceLocation* out_location) const {
3633
0
  std::vector<int> path;
3634
0
  GetLocationPath(&path);
3635
0
  return type()->file()->GetSourceLocation(path, out_location);
3636
0
}
3637
3638
0
void Descriptor::GetLocationPath(std::vector<int>* output) const {
3639
0
  if (containing_type()) {
3640
0
    containing_type()->GetLocationPath(output);
3641
0
    output->push_back(DescriptorProto::kNestedTypeFieldNumber);
3642
0
    output->push_back(index());
3643
0
  } else {
3644
0
    output->push_back(FileDescriptorProto::kMessageTypeFieldNumber);
3645
0
    output->push_back(index());
3646
0
  }
3647
0
}
3648
3649
0
void FieldDescriptor::GetLocationPath(std::vector<int>* output) const {
3650
0
  if (is_extension()) {
3651
0
    if (extension_scope() == nullptr) {
3652
0
      output->push_back(FileDescriptorProto::kExtensionFieldNumber);
3653
0
      output->push_back(index());
3654
0
    } else {
3655
0
      extension_scope()->GetLocationPath(output);
3656
0
      output->push_back(DescriptorProto::kExtensionFieldNumber);
3657
0
      output->push_back(index());
3658
0
    }
3659
0
  } else {
3660
0
    containing_type()->GetLocationPath(output);
3661
0
    output->push_back(DescriptorProto::kFieldFieldNumber);
3662
0
    output->push_back(index());
3663
0
  }
3664
0
}
3665
3666
0
void OneofDescriptor::GetLocationPath(std::vector<int>* output) const {
3667
0
  containing_type()->GetLocationPath(output);
3668
0
  output->push_back(DescriptorProto::kOneofDeclFieldNumber);
3669
0
  output->push_back(index());
3670
0
}
3671
3672
0
void EnumDescriptor::GetLocationPath(std::vector<int>* output) const {
3673
0
  if (containing_type()) {
3674
0
    containing_type()->GetLocationPath(output);
3675
0
    output->push_back(DescriptorProto::kEnumTypeFieldNumber);
3676
0
    output->push_back(index());
3677
0
  } else {
3678
0
    output->push_back(FileDescriptorProto::kEnumTypeFieldNumber);
3679
0
    output->push_back(index());
3680
0
  }
3681
0
}
3682
3683
0
void EnumValueDescriptor::GetLocationPath(std::vector<int>* output) const {
3684
0
  type()->GetLocationPath(output);
3685
0
  output->push_back(EnumDescriptorProto::kValueFieldNumber);
3686
0
  output->push_back(index());
3687
0
}
3688
3689
0
void ServiceDescriptor::GetLocationPath(std::vector<int>* output) const {
3690
0
  output->push_back(FileDescriptorProto::kServiceFieldNumber);
3691
0
  output->push_back(index());
3692
0
}
3693
3694
0
void MethodDescriptor::GetLocationPath(std::vector<int>* output) const {
3695
0
  service()->GetLocationPath(output);
3696
0
  output->push_back(ServiceDescriptorProto::kMethodFieldNumber);
3697
0
  output->push_back(index());
3698
0
}
3699
3700
// ===================================================================
3701
3702
namespace {
3703
3704
// Represents an options message to interpret. Extension names in the option
3705
// name are resolved relative to name_scope. element_name and orig_opt are
3706
// used only for error reporting (since the parser records locations against
3707
// pointers in the original options, not the mutable copy). The Message must be
3708
// one of the Options messages in descriptor.proto.
3709
struct OptionsToInterpret {
3710
  OptionsToInterpret(absl::string_view ns, absl::string_view el,
3711
                     const std::vector<int>& path, const Message* orig_opt,
3712
                     Message* opt)
3713
      : name_scope(ns),
3714
        element_name(el),
3715
        element_path(path),
3716
        original_options(orig_opt),
3717
0
        options(opt) {}
3718
  std::string name_scope;
3719
  std::string element_name;
3720
  std::vector<int> element_path;
3721
  const Message* original_options;
3722
  Message* options;
3723
};
3724
3725
}  // namespace
3726
3727
class DescriptorBuilder {
3728
 public:
3729
  static std::unique_ptr<DescriptorBuilder> New(
3730
      const DescriptorPool* pool, DescriptorPool::Tables* tables,
3731
0
      DescriptorPool::ErrorCollector* error_collector) {
3732
0
    return std::unique_ptr<DescriptorBuilder>(
3733
0
        new DescriptorBuilder(pool, tables, error_collector));
3734
0
  }
3735
3736
  ~DescriptorBuilder();
3737
3738
  const FileDescriptor* BuildFile(const FileDescriptorProto& proto);
3739
3740
 private:
3741
  DescriptorBuilder(const DescriptorPool* pool, DescriptorPool::Tables* tables,
3742
                    DescriptorPool::ErrorCollector* error_collector);
3743
3744
  friend class OptionInterpreter;
3745
3746
  // Non-recursive part of BuildFile functionality.
3747
  FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto,
3748
                                internal::FlatAllocator& alloc);
3749
3750
  const DescriptorPool* pool_;
3751
  DescriptorPool::Tables* tables_;  // for convenience
3752
  DescriptorPool::ErrorCollector* error_collector_;
3753
3754
  // As we build descriptors we store copies of the options messages in
3755
  // them. We put pointers to those copies in this vector, as we build, so we
3756
  // can later (after cross-linking) interpret those options.
3757
  std::vector<OptionsToInterpret> options_to_interpret_;
3758
3759
  bool had_errors_;
3760
  std::string filename_;
3761
  FileDescriptor* file_;
3762
  FileDescriptorTables* file_tables_;
3763
  absl::flat_hash_set<const FileDescriptor*> dependencies_;
3764
3765
  struct MessageHints {
3766
    int fields_to_suggest = 0;
3767
    const Message* first_reason = nullptr;
3768
    DescriptorPool::ErrorCollector::ErrorLocation first_reason_location =
3769
        DescriptorPool::ErrorCollector::ErrorLocation::OTHER;
3770
3771
    void RequestHintOnFieldNumbers(
3772
        const Message& reason,
3773
        DescriptorPool::ErrorCollector::ErrorLocation reason_location,
3774
0
        int range_start = 0, int range_end = 1) {
3775
0
      auto fit = [](int value) {
3776
0
        return std::min(std::max(value, 0), FieldDescriptor::kMaxNumber);
3777
0
      };
3778
0
      fields_to_suggest =
3779
0
          fit(fields_to_suggest + fit(fit(range_end) - fit(range_start)));
3780
0
      if (first_reason) return;
3781
0
      first_reason = &reason;
3782
0
      first_reason_location = reason_location;
3783
0
    }
3784
  };
3785
3786
  absl::flat_hash_map<const Descriptor*, MessageHints> message_hints_;
3787
3788
  // unused_dependency_ is used to record the unused imported files.
3789
  // Note: public import is not considered.
3790
  absl::flat_hash_set<const FileDescriptor*> unused_dependency_;
3791
3792
  // If LookupSymbol() finds a symbol that is in a file which is not a declared
3793
  // dependency of this file, it will fail, but will set
3794
  // possible_undeclared_dependency_ to point at that file.  This is only used
3795
  // by AddNotDefinedError() to report a more useful error message.
3796
  // possible_undeclared_dependency_name_ is the name of the symbol that was
3797
  // actually found in possible_undeclared_dependency_, which may be a parent
3798
  // of the symbol actually looked for.
3799
  const FileDescriptor* possible_undeclared_dependency_;
3800
  std::string possible_undeclared_dependency_name_;
3801
3802
  // If LookupSymbol() could resolve a symbol which is not defined,
3803
  // record the resolved name.  This is only used by AddNotDefinedError()
3804
  // to report a more useful error message.
3805
  std::string undefine_resolved_name_;
3806
3807
  // Tracker for current recursion depth to implement recursion protection.
3808
  //
3809
  // Counts down to 0 when there is no depth remaining.
3810
  //
3811
  // Maximum recursion depth corresponds to 32 nested message declarations.
3812
  int recursion_depth_ = 32;
3813
3814
  // Note: Both AddError and AddWarning functions are extremely sensitive to
3815
  // the *caller* stack space used. We call these functions many times in
3816
  // complex code paths that are hot and likely to be inlined heavily. However,
3817
  // these calls themselves are cold error paths. But stack space used by the
3818
  // code that sets up the call in many cases is paid for even when the call
3819
  // isn't reached. To optimize this, we use `const std::string &` to reuse
3820
  // string objects where possible for the inputs and for the error message
3821
  // itself we use a closure to build the error message inside these routines.
3822
  // The routines themselves are marked to prevent inlining and this lets us
3823
  // move the large code sometimes required to produce a useful error message
3824
  // entirely into a helper closure rather than the immediate caller.
3825
  //
3826
  // The `const char*` overload should only be used for string literal messages
3827
  // where this is a frustrating amount of overhead and there is no harm in
3828
  // directly using the literal.
3829
  void AddError(const std::string& element_name, const Message& descriptor,
3830
                DescriptorPool::ErrorCollector::ErrorLocation location,
3831
                absl::FunctionRef<std::string()> make_error);
3832
  void AddError(const std::string& element_name, const Message& descriptor,
3833
                DescriptorPool::ErrorCollector::ErrorLocation location,
3834
                const char* error);
3835
  void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here);
3836
  void AddTwiceListedError(const FileDescriptorProto& proto, int index);
3837
  void AddImportError(const FileDescriptorProto& proto, int index);
3838
3839
  // Adds an error indicating that undefined_symbol was not defined.  Must
3840
  // only be called after LookupSymbol() fails.
3841
  void AddNotDefinedError(
3842
      const std::string& element_name, const Message& descriptor,
3843
      DescriptorPool::ErrorCollector::ErrorLocation location,
3844
      const std::string& undefined_symbol);
3845
3846
  void AddWarning(const std::string& element_name, const Message& descriptor,
3847
                  DescriptorPool::ErrorCollector::ErrorLocation location,
3848
                  absl::FunctionRef<std::string()> make_error);
3849
  void AddWarning(const std::string& element_name, const Message& descriptor,
3850
                  DescriptorPool::ErrorCollector::ErrorLocation location,
3851
                  const char* error);
3852
3853
  // Silly helper which determines if the given file is in the given package.
3854
  // I.e., either file->package() == package_name or file->package() is a
3855
  // nested package within package_name.
3856
  bool IsInPackage(const FileDescriptor* file, absl::string_view package_name);
3857
3858
  // Helper function which finds all public dependencies of the given file, and
3859
  // stores the them in the dependencies_ set in the builder.
3860
  void RecordPublicDependencies(const FileDescriptor* file);
3861
3862
  // Like tables_->FindSymbol(), but additionally:
3863
  // - Search the pool's underlay if not found in tables_.
3864
  // - Insure that the resulting Symbol is from one of the file's declared
3865
  //   dependencies.
3866
  Symbol FindSymbol(const std::string& name, bool build_it = true);
3867
3868
  // Like FindSymbol() but does not require that the symbol is in one of the
3869
  // file's declared dependencies.
3870
  Symbol FindSymbolNotEnforcingDeps(const std::string& name,
3871
                                    bool build_it = true);
3872
3873
  // This implements the body of FindSymbolNotEnforcingDeps().
3874
  Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool,
3875
                                          const std::string& name,
3876
                                          bool build_it = true);
3877
3878
  // Like FindSymbol(), but looks up the name relative to some other symbol
3879
  // name.  This first searches siblings of relative_to, then siblings of its
3880
  // parents, etc.  For example, LookupSymbol("foo.bar", "baz.moo.corge") makes
3881
  // the following calls, returning the first non-null result:
3882
  // FindSymbol("baz.moo.foo.bar"), FindSymbol("baz.foo.bar"),
3883
  // FindSymbol("foo.bar").  If AllowUnknownDependencies() has been called
3884
  // on the DescriptorPool, this will generate a placeholder type if
3885
  // the name is not found (unless the name itself is malformed).  The
3886
  // placeholder_type parameter indicates what kind of placeholder should be
3887
  // constructed in this case.  The resolve_mode parameter determines whether
3888
  // any symbol is returned, or only symbols that are types.  Note, however,
3889
  // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode,
3890
  // if it believes that's all it could refer to.  The caller should always
3891
  // check that it receives the type of symbol it was expecting.
3892
  enum ResolveMode { LOOKUP_ALL, LOOKUP_TYPES };
3893
  Symbol LookupSymbol(const std::string& name, const std::string& relative_to,
3894
                      DescriptorPool::PlaceholderType placeholder_type =
3895
                          DescriptorPool::PLACEHOLDER_MESSAGE,
3896
                      ResolveMode resolve_mode = LOOKUP_ALL,
3897
                      bool build_it = true);
3898
3899
  // Like LookupSymbol() but will not return a placeholder even if
3900
  // AllowUnknownDependencies() has been used.
3901
  Symbol LookupSymbolNoPlaceholder(const std::string& name,
3902
                                   const std::string& relative_to,
3903
                                   ResolveMode resolve_mode = LOOKUP_ALL,
3904
                                   bool build_it = true);
3905
3906
  // Calls tables_->AddSymbol() and records an error if it fails.  Returns
3907
  // true if successful or false if failed, though most callers can ignore
3908
  // the return value since an error has already been recorded.
3909
  bool AddSymbol(const std::string& full_name, const void* parent,
3910
                 const std::string& name, const Message& proto, Symbol symbol);
3911
3912
  // Like AddSymbol(), but succeeds if the symbol is already defined as long
3913
  // as the existing definition is also a package (because it's OK to define
3914
  // the same package in two different files).  Also adds all parents of the
3915
  // package to the symbol table (e.g. AddPackage("foo.bar", ...) will add
3916
  // "foo.bar" and "foo" to the table).
3917
  void AddPackage(const std::string& name, const Message& proto,
3918
                  FileDescriptor* file);
3919
3920
  // Checks that the symbol name contains only alphanumeric characters and
3921
  // underscores.  Records an error otherwise.
3922
  void ValidateSymbolName(const std::string& name, const std::string& full_name,
3923
                          const Message& proto);
3924
3925
  // Allocates a copy of orig_options in tables_ and stores it in the
3926
  // descriptor. Remembers its uninterpreted options, to be interpreted
3927
  // later. DescriptorT must be one of the Descriptor messages from
3928
  // descriptor.proto.
3929
  template <class DescriptorT>
3930
  void AllocateOptions(const typename DescriptorT::OptionsType& orig_options,
3931
                       DescriptorT* descriptor, int options_field_tag,
3932
                       absl::string_view option_name,
3933
                       internal::FlatAllocator& alloc);
3934
  // Specialization for FileOptions.
3935
  void AllocateOptions(const FileOptions& orig_options,
3936
                       FileDescriptor* descriptor,
3937
                       internal::FlatAllocator& alloc);
3938
3939
  // Implementation for AllocateOptions(). Don't call this directly.
3940
  template <class DescriptorT>
3941
  void AllocateOptionsImpl(
3942
      absl::string_view name_scope, absl::string_view element_name,
3943
      const typename DescriptorT::OptionsType& orig_options,
3944
      DescriptorT* descriptor, const std::vector<int>& options_path,
3945
      absl::string_view option_name, internal::FlatAllocator& alloc);
3946
3947
  // Allocates an array of two strings, the first one is a copy of `proto_name`,
3948
  // and the second one is the full name.
3949
  // Full proto name is "scope.proto_name" if scope is non-empty and
3950
  // "proto_name" otherwise.
3951
  const std::string* AllocateNameStrings(const std::string& scope,
3952
                                         const std::string& proto_name,
3953
                                         internal::FlatAllocator& alloc);
3954
3955
  // These methods all have the same signature for the sake of the BUILD_ARRAY
3956
  // macro, below.
3957
  void BuildMessage(const DescriptorProto& proto, const Descriptor* parent,
3958
                    Descriptor* result, internal::FlatAllocator& alloc);
3959
  void BuildFieldOrExtension(const FieldDescriptorProto& proto,
3960
                             Descriptor* parent, FieldDescriptor* result,
3961
                             bool is_extension, internal::FlatAllocator& alloc);
3962
  void BuildField(const FieldDescriptorProto& proto, Descriptor* parent,
3963
0
                  FieldDescriptor* result, internal::FlatAllocator& alloc) {
3964
0
    BuildFieldOrExtension(proto, parent, result, false, alloc);
3965
0
  }
3966
  void BuildExtension(const FieldDescriptorProto& proto, Descriptor* parent,
3967
0
                      FieldDescriptor* result, internal::FlatAllocator& alloc) {
3968
0
    BuildFieldOrExtension(proto, parent, result, true, alloc);
3969
0
  }
3970
  void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
3971
                           const Descriptor* parent,
3972
                           Descriptor::ExtensionRange* result,
3973
                           internal::FlatAllocator& alloc);
3974
  void BuildReservedRange(const DescriptorProto::ReservedRange& proto,
3975
                          const Descriptor* parent,
3976
                          Descriptor::ReservedRange* result,
3977
                          internal::FlatAllocator& alloc);
3978
  void BuildReservedRange(const EnumDescriptorProto::EnumReservedRange& proto,
3979
                          const EnumDescriptor* parent,
3980
                          EnumDescriptor::ReservedRange* result,
3981
                          internal::FlatAllocator& alloc);
3982
  void BuildOneof(const OneofDescriptorProto& proto, Descriptor* parent,
3983
                  OneofDescriptor* result, internal::FlatAllocator& alloc);
3984
  void BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent,
3985
                 EnumDescriptor* result, internal::FlatAllocator& alloc);
3986
  void BuildEnumValue(const EnumValueDescriptorProto& proto,
3987
                      const EnumDescriptor* parent, EnumValueDescriptor* result,
3988
                      internal::FlatAllocator& alloc);
3989
  void BuildService(const ServiceDescriptorProto& proto, const void* dummy,
3990
                    ServiceDescriptor* result, internal::FlatAllocator& alloc);
3991
  void BuildMethod(const MethodDescriptorProto& proto,
3992
                   const ServiceDescriptor* parent, MethodDescriptor* result,
3993
                   internal::FlatAllocator& alloc);
3994
3995
  void CheckFieldJsonNameUniqueness(const DescriptorProto& proto,
3996
                                    const Descriptor* result);
3997
  void CheckFieldJsonNameUniqueness(const std::string& message_name,
3998
                                    const DescriptorProto& message,
3999
                                    FileDescriptorLegacy::Syntax syntax,
4000
                                    bool use_custom_names);
4001
  void CheckEnumValueUniqueness(const EnumDescriptorProto& proto,
4002
                                const EnumDescriptor* result);
4003
4004
  void LogUnusedDependency(const FileDescriptorProto& proto,
4005
                           const FileDescriptor* result);
4006
4007
  // Must be run only after building.
4008
  //
4009
  // NOTE: Options will not be available during cross-linking, as they
4010
  // have not yet been interpreted. Defer any handling of options to the
4011
  // Validate*Options methods.
4012
  void CrossLinkFile(FileDescriptor* file, const FileDescriptorProto& proto);
4013
  void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto);
4014
  void CrossLinkField(FieldDescriptor* field,
4015
                      const FieldDescriptorProto& proto);
4016
  void CrossLinkExtensionRange(Descriptor::ExtensionRange* range,
4017
                               const DescriptorProto::ExtensionRange& proto);
4018
  void CrossLinkEnum(EnumDescriptor* enum_type,
4019
                     const EnumDescriptorProto& proto);
4020
  void CrossLinkEnumValue(EnumValueDescriptor* enum_value,
4021
                          const EnumValueDescriptorProto& proto);
4022
  void CrossLinkService(ServiceDescriptor* service,
4023
                        const ServiceDescriptorProto& proto);
4024
  void CrossLinkMethod(MethodDescriptor* method,
4025
                       const MethodDescriptorProto& proto);
4026
  void SuggestFieldNumbers(FileDescriptor* file,
4027
                           const FileDescriptorProto& proto);
4028
4029
  // Checks that the extension field matches what is declared.
4030
  void CheckExtensionDeclaration(const FieldDescriptor& field,
4031
                                 const FieldDescriptorProto& proto,
4032
                                 absl::string_view declared_full_name,
4033
                                 absl::string_view declared_type_name,
4034
                                 bool is_repeated);
4035
4036
  // Must be run only after cross-linking.
4037
  void InterpretOptions();
4038
4039
  // A helper class for interpreting options.
4040
  class OptionInterpreter {
4041
   public:
4042
    // Creates an interpreter that operates in the context of the pool of the
4043
    // specified builder, which must not be nullptr. We don't take ownership of
4044
    // the builder.
4045
    explicit OptionInterpreter(DescriptorBuilder* builder);
4046
    OptionInterpreter(const OptionInterpreter&) = delete;
4047
    OptionInterpreter& operator=(const OptionInterpreter&) = delete;
4048
4049
    ~OptionInterpreter();
4050
4051
    // Interprets the uninterpreted options in the specified Options message.
4052
    // On error, calls AddError() on the underlying builder and returns false.
4053
    // Otherwise returns true.
4054
    bool InterpretOptions(OptionsToInterpret* options_to_interpret);
4055
4056
    // Updates the given source code info by re-writing uninterpreted option
4057
    // locations to refer to the corresponding interpreted option.
4058
    void UpdateSourceCodeInfo(SourceCodeInfo* info);
4059
4060
    class AggregateOptionFinder;
4061
4062
   private:
4063
    // Interprets uninterpreted_option_ on the specified message, which
4064
    // must be the mutable copy of the original options message to which
4065
    // uninterpreted_option_ belongs. The given src_path is the source
4066
    // location path to the uninterpreted option, and options_path is the
4067
    // source location path to the options message. The location paths are
4068
    // recorded and then used in UpdateSourceCodeInfo.
4069
    bool InterpretSingleOption(Message* options,
4070
                               const std::vector<int>& src_path,
4071
                               const std::vector<int>& options_path);
4072
4073
    // Adds the uninterpreted_option to the given options message verbatim.
4074
    // Used when AllowUnknownDependencies() is in effect and we can't find
4075
    // the option's definition.
4076
    void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option,
4077
                                Message* options);
4078
4079
    // A recursive helper function that drills into the intermediate fields
4080
    // in unknown_fields to check if field innermost_field is set on the
4081
    // innermost message. Returns false and sets an error if so.
4082
    bool ExamineIfOptionIsSet(
4083
        std::vector<const FieldDescriptor*>::const_iterator
4084
            intermediate_fields_iter,
4085
        std::vector<const FieldDescriptor*>::const_iterator
4086
            intermediate_fields_end,
4087
        const FieldDescriptor* innermost_field,
4088
        const std::string& debug_msg_name,
4089
        const UnknownFieldSet& unknown_fields);
4090
4091
    // Validates the value for the option field of the currently interpreted
4092
    // option and then sets it on the unknown_field.
4093
    bool SetOptionValue(const FieldDescriptor* option_field,
4094
                        UnknownFieldSet* unknown_fields);
4095
4096
    // Parses an aggregate value for a CPPTYPE_MESSAGE option and
4097
    // saves it into *unknown_fields.
4098
    bool SetAggregateOption(const FieldDescriptor* option_field,
4099
                            UnknownFieldSet* unknown_fields);
4100
4101
    // Convenience functions to set an int field the right way, depending on
4102
    // its wire type (a single int CppType can represent multiple wire types).
4103
    void SetInt32(int number, int32_t value, FieldDescriptor::Type type,
4104
                  UnknownFieldSet* unknown_fields);
4105
    void SetInt64(int number, int64_t value, FieldDescriptor::Type type,
4106
                  UnknownFieldSet* unknown_fields);
4107
    void SetUInt32(int number, uint32_t value, FieldDescriptor::Type type,
4108
                   UnknownFieldSet* unknown_fields);
4109
    void SetUInt64(int number, uint64_t value, FieldDescriptor::Type type,
4110
                   UnknownFieldSet* unknown_fields);
4111
4112
    // A helper function that adds an error at the specified location of the
4113
    // option we're currently interpreting, and returns false.
4114
    bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,
4115
0
                        absl::FunctionRef<std::string()> make_error) {
4116
0
      builder_->AddError(options_to_interpret_->element_name,
4117
0
                         *uninterpreted_option_, location, make_error);
4118
0
      return false;
4119
0
    }
4120
4121
    // A helper function that adds an error at the location of the option name
4122
    // and returns false.
4123
0
    bool AddNameError(absl::FunctionRef<std::string()> make_error) {
4124
#ifdef PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_
4125
      return true;
4126
#else   // PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_
4127
0
      return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME,
4128
0
                            make_error);
4129
0
#endif  // PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_
4130
0
    }
4131
4132
    // A helper function that adds an error at the location of the option name
4133
    // and returns false.
4134
0
    bool AddValueError(absl::FunctionRef<std::string()> make_error) {
4135
0
      return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE,
4136
0
                            make_error);
4137
0
    }
4138
4139
    // We interpret against this builder's pool. Is never nullptr. We don't own
4140
    // this pointer.
4141
    DescriptorBuilder* builder_;
4142
4143
    // The options we're currently interpreting, or nullptr if we're not in a
4144
    // call to InterpretOptions.
4145
    const OptionsToInterpret* options_to_interpret_;
4146
4147
    // The option we're currently interpreting within options_to_interpret_, or
4148
    // nullptr if we're not in a call to InterpretOptions(). This points to a
4149
    // submessage of the original option, not the mutable copy. Therefore we
4150
    // can use it to find locations recorded by the parser.
4151
    const UninterpretedOption* uninterpreted_option_;
4152
4153
    // This maps the element path of uninterpreted options to the element path
4154
    // of the resulting interpreted option. This is used to modify a file's
4155
    // source code info to account for option interpretation.
4156
    absl::flat_hash_map<std::vector<int>, std::vector<int>> interpreted_paths_;
4157
4158
    // This maps the path to a repeated option field to the known number of
4159
    // elements the field contains. This is used to track the compute the
4160
    // index portion of the element path when interpreting a single option.
4161
    absl::flat_hash_map<std::vector<int>, int> repeated_option_counts_;
4162
4163
    // Factory used to create the dynamic messages we need to parse
4164
    // any aggregate option values we encounter.
4165
    DynamicMessageFactory dynamic_factory_;
4166
  };
4167
4168
  // Work-around for broken compilers:  According to the C++ standard,
4169
  // OptionInterpreter should have access to the private members of any class
4170
  // which has declared DescriptorBuilder as a friend.  Unfortunately some old
4171
  // versions of GCC and other compilers do not implement this correctly.  So,
4172
  // we have to have these intermediate methods to provide access.  We also
4173
  // redundantly declare OptionInterpreter a friend just to make things extra
4174
  // clear for these bad compilers.
4175
  friend class OptionInterpreter;
4176
  friend class OptionInterpreter::AggregateOptionFinder;
4177
4178
0
  static inline bool get_allow_unknown(const DescriptorPool* pool) {
4179
0
    return pool->allow_unknown_;
4180
0
  }
4181
0
  static inline bool get_enforce_weak(const DescriptorPool* pool) {
4182
0
    return pool->enforce_weak_;
4183
0
  }
4184
0
  static inline bool get_is_placeholder(const Descriptor* descriptor) {
4185
0
    return descriptor != nullptr && descriptor->is_placeholder_;
4186
0
  }
4187
0
  static inline void assert_mutex_held(const DescriptorPool* pool) {
4188
0
    if (pool->mutex_ != nullptr) {
4189
0
      pool->mutex_->AssertHeld();
4190
0
    }
4191
0
  }
4192
4193
  // Must be run only after options have been interpreted.
4194
  //
4195
  // NOTE: Validation code must only reference the options in the mutable
4196
  // descriptors, which are the ones that have been interpreted. The const
4197
  // proto references are passed in only so they can be provided to calls to
4198
  // AddError(). Do not look at their options, which have not been interpreted.
4199
  void ValidateFileOptions(FileDescriptor* file,
4200
                           const FileDescriptorProto& proto);
4201
  void ValidateMessageOptions(Descriptor* message,
4202
                              const DescriptorProto& proto);
4203
  void ValidateFieldOptions(FieldDescriptor* field,
4204
                            const FieldDescriptorProto& proto);
4205
  void ValidateEnumOptions(EnumDescriptor* enm,
4206
                           const EnumDescriptorProto& proto);
4207
  void ValidateEnumValueOptions(EnumValueDescriptor* enum_value,
4208
                                const EnumValueDescriptorProto& proto);
4209
  void ValidateExtensionRangeOptions(const DescriptorProto& proto,
4210
                                     const Descriptor& message);
4211
  void ValidateExtensionDeclaration(
4212
      const std::string& full_name,
4213
      const RepeatedPtrField<ExtensionRangeOptions_Declaration>& declarations,
4214
      const DescriptorProto_ExtensionRange& proto,
4215
      absl::flat_hash_set<absl::string_view>& full_name_set);
4216
  void ValidateServiceOptions(ServiceDescriptor* service,
4217
                              const ServiceDescriptorProto& proto);
4218
  void ValidateMethodOptions(MethodDescriptor* method,
4219
                             const MethodDescriptorProto& proto);
4220
  void ValidateProto3(FileDescriptor* file, const FileDescriptorProto& proto);
4221
  void ValidateProto3Message(Descriptor* message, const DescriptorProto& proto);
4222
  void ValidateProto3Field(FieldDescriptor* field,
4223
                           const FieldDescriptorProto& proto);
4224
  void ValidateProto3Enum(EnumDescriptor* enm,
4225
                          const EnumDescriptorProto& proto);
4226
4227
  // Returns true if the map entry message is compatible with the
4228
  // auto-generated entry message from map fields syntax.
4229
  bool ValidateMapEntry(FieldDescriptor* field,
4230
                        const FieldDescriptorProto& proto);
4231
4232
  // Recursively detects naming conflicts with map entry types for a
4233
  // better error message.
4234
  void DetectMapConflicts(const Descriptor* message,
4235
                          const DescriptorProto& proto);
4236
4237
  void ValidateJSType(FieldDescriptor* field,
4238
                      const FieldDescriptorProto& proto);
4239
};
4240
4241
const FileDescriptor* DescriptorPool::BuildFile(
4242
0
    const FileDescriptorProto& proto) {
4243
0
  ABSL_CHECK(fallback_database_ == nullptr)
4244
0
      << "Cannot call BuildFile on a DescriptorPool that uses a "
4245
0
         "DescriptorDatabase.  You must instead find a way to get your file "
4246
0
         "into the underlying database.";
4247
0
  ABSL_CHECK(mutex_ == nullptr);  // Implied by the above ABSL_CHECK.
4248
0
  tables_->known_bad_symbols_.clear();
4249
0
  tables_->known_bad_files_.clear();
4250
0
  return DescriptorBuilder::New(this, tables_.get(), nullptr)->BuildFile(proto);
4251
0
}
4252
4253
const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
4254
0
    const FileDescriptorProto& proto, ErrorCollector* error_collector) {
4255
0
  ABSL_CHECK(fallback_database_ == nullptr)
4256
0
      << "Cannot call BuildFile on a DescriptorPool that uses a "
4257
0
         "DescriptorDatabase.  You must instead find a way to get your file "
4258
0
         "into the underlying database.";
4259
0
  ABSL_CHECK(mutex_ == nullptr);  // Implied by the above ABSL_CHECK.
4260
0
  tables_->known_bad_symbols_.clear();
4261
0
  tables_->known_bad_files_.clear();
4262
0
  return DescriptorBuilder::New(this, tables_.get(), error_collector)
4263
0
      ->BuildFile(proto);
4264
0
}
4265
4266
const FileDescriptor* DescriptorPool::BuildFileFromDatabase(
4267
0
    const FileDescriptorProto& proto) const {
4268
0
  mutex_->AssertHeld();
4269
0
  if (tables_->known_bad_files_.contains(proto.name())) {
4270
0
    return nullptr;
4271
0
  }
4272
0
  const FileDescriptor* result =
4273
0
      DescriptorBuilder::New(this, tables_.get(), default_error_collector_)
4274
0
          ->BuildFile(proto);
4275
0
  if (result == nullptr) {
4276
0
    tables_->known_bad_files_.insert(proto.name());
4277
0
  }
4278
0
  return result;
4279
0
}
4280
4281
DescriptorBuilder::DescriptorBuilder(
4282
    const DescriptorPool* pool, DescriptorPool::Tables* tables,
4283
    DescriptorPool::ErrorCollector* error_collector)
4284
    : pool_(pool),
4285
      tables_(tables),
4286
      error_collector_(error_collector),
4287
      had_errors_(false),
4288
      possible_undeclared_dependency_(nullptr),
4289
0
      undefine_resolved_name_("") {}
4290
4291
0
DescriptorBuilder::~DescriptorBuilder() {}
4292
4293
PROTOBUF_NOINLINE void DescriptorBuilder::AddError(
4294
    const std::string& element_name, const Message& descriptor,
4295
    DescriptorPool::ErrorCollector::ErrorLocation location,
4296
0
    absl::FunctionRef<std::string()> make_error) {
4297
0
  std::string error = make_error();
4298
0
  if (error_collector_ == nullptr) {
4299
0
    if (!had_errors_) {
4300
0
      ABSL_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_
4301
0
                      << "\":";
4302
0
    }
4303
0
    ABSL_LOG(ERROR) << "  " << element_name << ": " << error;
4304
0
  } else {
4305
0
    error_collector_->RecordError(filename_, element_name, &descriptor,
4306
0
                                  location, error);
4307
0
  }
4308
0
  had_errors_ = true;
4309
0
}
4310
4311
PROTOBUF_NOINLINE void DescriptorBuilder::AddError(
4312
    const std::string& element_name, const Message& descriptor,
4313
0
    DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) {
4314
0
  AddError(element_name, descriptor, location, [error] { return error; });
4315
0
}
4316
4317
PROTOBUF_NOINLINE void DescriptorBuilder::AddNotDefinedError(
4318
    const std::string& element_name, const Message& descriptor,
4319
    DescriptorPool::ErrorCollector::ErrorLocation location,
4320
0
    const std::string& undefined_symbol) {
4321
0
  if (possible_undeclared_dependency_ == nullptr &&
4322
0
      undefine_resolved_name_.empty()) {
4323
0
    AddError(element_name, descriptor, location, [&] {
4324
0
      return absl::StrCat("\"", undefined_symbol, "\" is not defined.");
4325
0
    });
4326
0
  } else {
4327
0
    if (possible_undeclared_dependency_ != nullptr) {
4328
0
      AddError(element_name, descriptor, location, [&] {
4329
0
        return absl::StrCat("\"", possible_undeclared_dependency_name_,
4330
0
                            "\" seems to be defined in \"",
4331
0
                            possible_undeclared_dependency_->name(),
4332
0
                            "\", which is not "
4333
0
                            "imported by \"",
4334
0
                            filename_,
4335
0
                            "\".  To use it here, please "
4336
0
                            "add the necessary import.");
4337
0
      });
4338
0
    }
4339
0
    if (!undefine_resolved_name_.empty()) {
4340
0
      AddError(element_name, descriptor, location, [&] {
4341
0
        return absl::StrCat(
4342
0
            "\"", undefined_symbol, "\" is resolved to \"",
4343
0
            undefine_resolved_name_,
4344
0
            "\", which is not defined. "
4345
0
            "The innermost scope is searched first in name resolution. "
4346
0
            "Consider using a leading '.'(i.e., \".",
4347
0
            undefined_symbol, "\") to start from the outermost scope.");
4348
0
      });
4349
0
    }
4350
0
  }
4351
0
}
4352
4353
PROTOBUF_NOINLINE void DescriptorBuilder::AddWarning(
4354
    const std::string& element_name, const Message& descriptor,
4355
    DescriptorPool::ErrorCollector::ErrorLocation location,
4356
0
    absl::FunctionRef<std::string()> make_error) {
4357
0
  std::string error = make_error();
4358
0
  if (error_collector_ == nullptr) {
4359
0
    ABSL_LOG(WARNING) << filename_ << " " << element_name << ": " << error;
4360
0
  } else {
4361
0
    error_collector_->RecordWarning(filename_, element_name, &descriptor,
4362
0
                                    location, error);
4363
0
  }
4364
0
}
4365
4366
PROTOBUF_NOINLINE void DescriptorBuilder::AddWarning(
4367
    const std::string& element_name, const Message& descriptor,
4368
0
    DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) {
4369
0
  AddWarning(element_name, descriptor, location,
4370
0
             [error]() -> std::string { return error; });
4371
0
}
4372
4373
bool DescriptorBuilder::IsInPackage(const FileDescriptor* file,
4374
0
                                    absl::string_view package_name) {
4375
0
  return absl::StartsWith(file->package(), package_name) &&
4376
0
         (file->package().size() == package_name.size() ||
4377
0
          file->package()[package_name.size()] == '.');
4378
0
}
4379
4380
0
void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
4381
0
  if (file == nullptr || !dependencies_.insert(file).second) return;
4382
0
  for (int i = 0; file != nullptr && i < file->public_dependency_count(); i++) {
4383
0
    RecordPublicDependencies(file->public_dependency(i));
4384
0
  }
4385
0
}
4386
4387
Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
4388
0
    const DescriptorPool* pool, const std::string& name, bool build_it) {
4389
  // If we are looking at an underlay, we must lock its mutex_, since we are
4390
  // accessing the underlay's tables_ directly.
4391
0
  absl::MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_);
4392
4393
0
  Symbol result = pool->tables_->FindSymbol(name);
4394
0
  if (result.IsNull() && pool->underlay_ != nullptr) {
4395
    // Symbol not found; check the underlay.
4396
0
    result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
4397
0
  }
4398
4399
0
  if (result.IsNull()) {
4400
    // With lazily_build_dependencies_, a symbol lookup at cross link time is
4401
    // not guaranteed to be successful. In most cases, build_it will be false,
4402
    // which intentionally prevents us from building an import until it's
4403
    // actually needed. In some cases, like registering an extension, we want
4404
    // to build the file containing the symbol, and build_it will be set.
4405
    // Also, build_it will be true when !lazily_build_dependencies_, to provide
4406
    // better error reporting of missing dependencies.
4407
0
    if (build_it && pool->TryFindSymbolInFallbackDatabase(name)) {
4408
0
      result = pool->tables_->FindSymbol(name);
4409
0
    }
4410
0
  }
4411
4412
0
  return result;
4413
0
}
4414
4415
Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const std::string& name,
4416
0
                                                     bool build_it) {
4417
0
  Symbol result = FindSymbolNotEnforcingDepsHelper(pool_, name, build_it);
4418
  // Only find symbols which were defined in this file or one of its
4419
  // dependencies.
4420
0
  const FileDescriptor* file = result.GetFile();
4421
0
  if (file == file_ || dependencies_.contains(file)) {
4422
0
    unused_dependency_.erase(file);
4423
0
  }
4424
0
  return result;
4425
0
}
4426
4427
0
Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) {
4428
0
  Symbol result = FindSymbolNotEnforcingDeps(name, build_it);
4429
4430
0
  if (result.IsNull()) return result;
4431
4432
0
  if (!pool_->enforce_dependencies_) {
4433
    // Hack for CompilerUpgrader, and also used for lazily_build_dependencies_
4434
0
    return result;
4435
0
  }
4436
4437
  // Only find symbols which were defined in this file or one of its
4438
  // dependencies.
4439
0
  const FileDescriptor* file = result.GetFile();
4440
0
  if (file == file_ || dependencies_.contains(file)) {
4441
0
    return result;
4442
0
  }
4443
4444
0
  if (result.IsPackage()) {
4445
    // Arg, this is overcomplicated.  The symbol is a package name.  It could
4446
    // be that the package was defined in multiple files.  result.GetFile()
4447
    // returns the first file we saw that used this package.  We've determined
4448
    // that that file is not a direct dependency of the file we are currently
4449
    // building, but it could be that some other file which *is* a direct
4450
    // dependency also defines the same package.  We can't really rule out this
4451
    // symbol unless none of the dependencies define it.
4452
0
    if (IsInPackage(file_, name)) return result;
4453
0
    for (const auto* dep : dependencies_) {
4454
      // Note:  A dependency may be nullptr if it was not found or had errors.
4455
0
      if (dep != nullptr && IsInPackage(dep, name)) return result;
4456
0
    }
4457
0
  }
4458
4459
0
  possible_undeclared_dependency_ = file;
4460
0
  possible_undeclared_dependency_name_ = name;
4461
0
  return Symbol();
4462
0
}
4463
4464
Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(
4465
    const std::string& name, const std::string& relative_to,
4466
0
    ResolveMode resolve_mode, bool build_it) {
4467
0
  possible_undeclared_dependency_ = nullptr;
4468
0
  undefine_resolved_name_.clear();
4469
4470
0
  if (!name.empty() && name[0] == '.') {
4471
    // Fully-qualified name.
4472
0
    return FindSymbol(name.substr(1), build_it);
4473
0
  }
4474
4475
  // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
4476
  // defined in multiple parent scopes, we only want to find "Bar.baz" in the
4477
  // innermost one.  E.g., the following should produce an error:
4478
  //   message Bar { message Baz {} }
4479
  //   message Foo {
4480
  //     message Bar {
4481
  //     }
4482
  //     optional Bar.Baz baz = 1;
4483
  //   }
4484
  // So, we look for just "Foo" first, then look for "Bar.baz" within it if
4485
  // found.
4486
0
  std::string::size_type name_dot_pos = name.find_first_of('.');
4487
0
  std::string first_part_of_name;
4488
0
  if (name_dot_pos == std::string::npos) {
4489
0
    first_part_of_name = name;
4490
0
  } else {
4491
0
    first_part_of_name = name.substr(0, name_dot_pos);
4492
0
  }
4493
4494
0
  std::string scope_to_try(relative_to);
4495
4496
0
  while (true) {
4497
    // Chop off the last component of the scope.
4498
0
    std::string::size_type dot_pos = scope_to_try.find_last_of('.');
4499
0
    if (dot_pos == std::string::npos) {
4500
0
      return FindSymbol(name, build_it);
4501
0
    } else {
4502
0
      scope_to_try.erase(dot_pos);
4503
0
    }
4504
4505
    // Append ".first_part_of_name" and try to find.
4506
0
    std::string::size_type old_size = scope_to_try.size();
4507
0
    scope_to_try.append(1, '.');
4508
0
    scope_to_try.append(first_part_of_name);
4509
0
    Symbol result = FindSymbol(scope_to_try, build_it);
4510
0
    if (!result.IsNull()) {
4511
0
      if (first_part_of_name.size() < name.size()) {
4512
        // name is a compound symbol, of which we only found the first part.
4513
        // Now try to look up the rest of it.
4514
0
        if (result.IsAggregate()) {
4515
0
          scope_to_try.append(name, first_part_of_name.size(),
4516
0
                              name.size() - first_part_of_name.size());
4517
0
          result = FindSymbol(scope_to_try, build_it);
4518
0
          if (result.IsNull()) {
4519
0
            undefine_resolved_name_ = scope_to_try;
4520
0
          }
4521
0
          return result;
4522
0
        } else {
4523
          // We found a symbol but it's not an aggregate.  Continue the loop.
4524
0
        }
4525
0
      } else {
4526
0
        if (resolve_mode == LOOKUP_TYPES && !result.IsType()) {
4527
          // We found a symbol but it's not a type.  Continue the loop.
4528
0
        } else {
4529
0
          return result;
4530
0
        }
4531
0
      }
4532
0
    }
4533
4534
    // Not found.  Remove the name so we can try again.
4535
0
    scope_to_try.erase(old_size);
4536
0
  }
4537
0
}
4538
4539
Symbol DescriptorBuilder::LookupSymbol(
4540
    const std::string& name, const std::string& relative_to,
4541
    DescriptorPool::PlaceholderType placeholder_type, ResolveMode resolve_mode,
4542
0
    bool build_it) {
4543
0
  Symbol result =
4544
0
      LookupSymbolNoPlaceholder(name, relative_to, resolve_mode, build_it);
4545
0
  if (result.IsNull() && pool_->allow_unknown_) {
4546
    // Not found, but AllowUnknownDependencies() is enabled.  Return a
4547
    // placeholder instead.
4548
0
    result = pool_->NewPlaceholderWithMutexHeld(name, placeholder_type);
4549
0
  }
4550
0
  return result;
4551
0
}
4552
4553
0
static bool ValidateQualifiedName(absl::string_view name) {
4554
0
  bool last_was_period = false;
4555
4556
0
  for (char character : name) {
4557
    // I don't trust isalnum() due to locales.  :(
4558
0
    if (('a' <= character && character <= 'z') ||
4559
0
        ('A' <= character && character <= 'Z') ||
4560
0
        ('0' <= character && character <= '9') || (character == '_')) {
4561
0
      last_was_period = false;
4562
0
    } else if (character == '.') {
4563
0
      if (last_was_period) return false;
4564
0
      last_was_period = true;
4565
0
    } else {
4566
0
      return false;
4567
0
    }
4568
0
  }
4569
4570
0
  return !name.empty() && !last_was_period;
4571
0
}
4572
4573
Symbol DescriptorPool::NewPlaceholder(absl::string_view name,
4574
0
                                      PlaceholderType placeholder_type) const {
4575
0
  absl::MutexLockMaybe lock(mutex_);
4576
0
  return NewPlaceholderWithMutexHeld(name, placeholder_type);
4577
0
}
4578
4579
Symbol DescriptorPool::NewPlaceholderWithMutexHeld(
4580
0
    absl::string_view name, PlaceholderType placeholder_type) const {
4581
0
  if (mutex_) {
4582
0
    mutex_->AssertHeld();
4583
0
  }
4584
  // Compute names.
4585
0
  absl::string_view placeholder_full_name;
4586
0
  absl::string_view placeholder_name;
4587
0
  const std::string* placeholder_package;
4588
4589
0
  if (!ValidateQualifiedName(name)) return Symbol();
4590
0
  if (name[0] == '.') {
4591
    // Fully-qualified.
4592
0
    placeholder_full_name = name.substr(1);
4593
0
  } else {
4594
0
    placeholder_full_name = name;
4595
0
  }
4596
4597
  // Create the placeholders.
4598
0
  internal::FlatAllocator alloc;
4599
0
  alloc.PlanArray<FileDescriptor>(1);
4600
0
  alloc.PlanArray<std::string>(2);
4601
0
  if (placeholder_type == PLACEHOLDER_ENUM) {
4602
0
    alloc.PlanArray<EnumDescriptor>(1);
4603
0
    alloc.PlanArray<EnumValueDescriptor>(1);
4604
0
    alloc.PlanArray<std::string>(2);  // names for the descriptor.
4605
0
    alloc.PlanArray<std::string>(2);  // names for the value.
4606
0
  } else {
4607
0
    alloc.PlanArray<Descriptor>(1);
4608
0
    alloc.PlanArray<std::string>(2);  // names for the descriptor.
4609
0
    if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
4610
0
      alloc.PlanArray<Descriptor::ExtensionRange>(1);
4611
0
    }
4612
0
  }
4613
0
  alloc.FinalizePlanning(tables_);
4614
4615
0
  const std::string::size_type dotpos = placeholder_full_name.find_last_of('.');
4616
0
  if (dotpos != std::string::npos) {
4617
0
    placeholder_package =
4618
0
        alloc.AllocateStrings(placeholder_full_name.substr(0, dotpos));
4619
0
    placeholder_name = placeholder_full_name.substr(dotpos + 1);
4620
0
  } else {
4621
0
    placeholder_package = alloc.AllocateStrings("");
4622
0
    placeholder_name = placeholder_full_name;
4623
0
  }
4624
4625
0
  FileDescriptor* placeholder_file = NewPlaceholderFileWithMutexHeld(
4626
0
      absl::StrCat(placeholder_full_name, ".placeholder.proto"), alloc);
4627
0
  placeholder_file->package_ = placeholder_package;
4628
4629
0
  if (placeholder_type == PLACEHOLDER_ENUM) {
4630
0
    placeholder_file->enum_type_count_ = 1;
4631
0
    placeholder_file->enum_types_ = alloc.AllocateArray<EnumDescriptor>(1);
4632
4633
0
    EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0];
4634
0
    memset(static_cast<void*>(placeholder_enum), 0, sizeof(*placeholder_enum));
4635
4636
0
    placeholder_enum->all_names_ =
4637
0
        alloc.AllocateStrings(placeholder_name, placeholder_full_name);
4638
0
    placeholder_enum->file_ = placeholder_file;
4639
0
    placeholder_enum->options_ = &EnumOptions::default_instance();
4640
0
    placeholder_enum->is_placeholder_ = true;
4641
0
    placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.');
4642
4643
    // Enums must have at least one value.
4644
0
    placeholder_enum->value_count_ = 1;
4645
0
    placeholder_enum->values_ = alloc.AllocateArray<EnumValueDescriptor>(1);
4646
    // Disable fast-path lookup for this enum.
4647
0
    placeholder_enum->sequential_value_limit_ = -1;
4648
4649
0
    EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0];
4650
0
    memset(static_cast<void*>(placeholder_value), 0,
4651
0
           sizeof(*placeholder_value));
4652
4653
    // Note that enum value names are siblings of their type, not children.
4654
0
    placeholder_value->all_names_ = alloc.AllocateStrings(
4655
0
        "PLACEHOLDER_VALUE",
4656
0
        placeholder_package->empty()
4657
0
            ? "PLACEHOLDER_VALUE"
4658
0
            : absl::StrCat(*placeholder_package, ".PLACEHOLDER_VALUE"));
4659
4660
0
    placeholder_value->number_ = 0;
4661
0
    placeholder_value->type_ = placeholder_enum;
4662
0
    placeholder_value->options_ = &EnumValueOptions::default_instance();
4663
4664
0
    return Symbol(placeholder_enum);
4665
0
  } else {
4666
0
    placeholder_file->message_type_count_ = 1;
4667
0
    placeholder_file->message_types_ = alloc.AllocateArray<Descriptor>(1);
4668
4669
0
    Descriptor* placeholder_message = &placeholder_file->message_types_[0];
4670
0
    memset(static_cast<void*>(placeholder_message), 0,
4671
0
           sizeof(*placeholder_message));
4672
4673
0
    placeholder_message->all_names_ =
4674
0
        alloc.AllocateStrings(placeholder_name, placeholder_full_name);
4675
0
    placeholder_message->file_ = placeholder_file;
4676
0
    placeholder_message->options_ = &MessageOptions::default_instance();
4677
0
    placeholder_message->is_placeholder_ = true;
4678
0
    placeholder_message->is_unqualified_placeholder_ = (name[0] != '.');
4679
4680
0
    if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
4681
0
      placeholder_message->extension_range_count_ = 1;
4682
0
      placeholder_message->extension_ranges_ =
4683
0
          alloc.AllocateArray<Descriptor::ExtensionRange>(1);
4684
0
      placeholder_message->extension_ranges_[0].start = 1;
4685
      // kMaxNumber + 1 because ExtensionRange::end is exclusive.
4686
0
      placeholder_message->extension_ranges_[0].end =
4687
0
          FieldDescriptor::kMaxNumber + 1;
4688
0
      placeholder_message->extension_ranges_[0].options_ = nullptr;
4689
0
    }
4690
4691
0
    return Symbol(placeholder_message);
4692
0
  }
4693
0
}
4694
4695
FileDescriptor* DescriptorPool::NewPlaceholderFile(
4696
0
    absl::string_view name) const {
4697
0
  absl::MutexLockMaybe lock(mutex_);
4698
0
  internal::FlatAllocator alloc;
4699
0
  alloc.PlanArray<FileDescriptor>(1);
4700
0
  alloc.PlanArray<std::string>(1);
4701
0
  alloc.FinalizePlanning(tables_);
4702
4703
0
  return NewPlaceholderFileWithMutexHeld(name, alloc);
4704
0
}
4705
4706
FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld(
4707
0
    absl::string_view name, internal::FlatAllocator& alloc) const {
4708
0
  if (mutex_) {
4709
0
    mutex_->AssertHeld();
4710
0
  }
4711
0
  FileDescriptor* placeholder = alloc.AllocateArray<FileDescriptor>(1);
4712
0
  memset(static_cast<void*>(placeholder), 0, sizeof(*placeholder));
4713
4714
0
  placeholder->name_ = alloc.AllocateStrings(name);
4715
0
  placeholder->package_ = &internal::GetEmptyString();
4716
0
  placeholder->pool_ = this;
4717
0
  placeholder->options_ = &FileOptions::default_instance();
4718
0
  placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance();
4719
0
  placeholder->source_code_info_ = &SourceCodeInfo::default_instance();
4720
0
  placeholder->is_placeholder_ = true;
4721
0
  placeholder->syntax_ = FileDescriptorLegacy::SYNTAX_UNKNOWN;
4722
0
  placeholder->finished_building_ = true;
4723
  // All other fields are zero or nullptr.
4724
4725
0
  return placeholder;
4726
0
}
4727
4728
bool DescriptorBuilder::AddSymbol(const std::string& full_name,
4729
                                  const void* parent, const std::string& name,
4730
0
                                  const Message& proto, Symbol symbol) {
4731
  // If the caller passed nullptr for the parent, the symbol is at file scope.
4732
  // Use its file as the parent instead.
4733
0
  if (parent == nullptr) parent = file_;
4734
4735
0
  if (absl::StrContains(full_name, '\0')) {
4736
0
    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4737
0
      return absl::StrCat("\"", full_name, "\" contains null character.");
4738
0
    });
4739
0
    return false;
4740
0
  }
4741
0
  if (tables_->AddSymbol(full_name, symbol)) {
4742
0
    if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
4743
      // This is only possible if there was already an error adding something of
4744
      // the same name.
4745
0
      if (!had_errors_) {
4746
0
        ABSL_DLOG(FATAL) << "\"" << full_name
4747
0
                         << "\" not previously defined in "
4748
0
                            "symbols_by_name_, but was defined in "
4749
0
                            "symbols_by_parent_; this shouldn't be possible.";
4750
0
      }
4751
0
      return false;
4752
0
    }
4753
0
    return true;
4754
0
  } else {
4755
0
    const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile();
4756
0
    if (other_file == file_) {
4757
0
      std::string::size_type dot_pos = full_name.find_last_of('.');
4758
0
      if (dot_pos == std::string::npos) {
4759
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4760
0
          return absl::StrCat("\"", full_name, "\" is already defined.");
4761
0
        });
4762
0
      } else {
4763
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4764
0
          return absl::StrCat("\"", full_name.substr(dot_pos + 1),
4765
0
                              "\" is already defined in \"",
4766
0
                              full_name.substr(0, dot_pos), "\".");
4767
0
        });
4768
0
      }
4769
0
    } else {
4770
      // Symbol seems to have been defined in a different file.
4771
0
      AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4772
0
        return absl::StrCat(
4773
0
            "\"", full_name, "\" is already defined in file \"",
4774
0
            (other_file == nullptr ? "null" : other_file->name()), "\".");
4775
0
      });
4776
0
    }
4777
0
    return false;
4778
0
  }
4779
0
}
4780
4781
void DescriptorBuilder::AddPackage(const std::string& name,
4782
0
                                   const Message& proto, FileDescriptor* file) {
4783
0
  if (name.find('\0') != std::string::npos) {
4784
0
    AddError(name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4785
0
      return absl::StrCat("\"", name, "\" contains null character.");
4786
0
    });
4787
0
    return;
4788
0
  }
4789
4790
0
  Symbol existing_symbol = tables_->FindSymbol(name);
4791
  // It's OK to redefine a package.
4792
0
  if (existing_symbol.IsNull()) {
4793
0
    if (name.data() == file->package().data()) {
4794
      // It is the toplevel package name, so insert the descriptor directly.
4795
0
      tables_->AddSymbol(file->package(), Symbol(file));
4796
0
    } else {
4797
0
      auto* package = tables_->Allocate<Symbol::Subpackage>();
4798
      // If the name is the package name, then it is already in the arena.
4799
      // If not, copy it there. It came from the call to AddPackage below.
4800
0
      package->name_size = static_cast<int>(name.size());
4801
0
      package->file = file;
4802
0
      tables_->AddSymbol(name, Symbol(package));
4803
0
    }
4804
    // Also add parent package, if any.
4805
0
    std::string::size_type dot_pos = name.find_last_of('.');
4806
0
    if (dot_pos == std::string::npos) {
4807
      // No parents.
4808
0
      ValidateSymbolName(name, name, proto);
4809
0
    } else {
4810
      // Has parent.
4811
0
      AddPackage(name.substr(0, dot_pos), proto, file);
4812
0
      ValidateSymbolName(name.substr(dot_pos + 1), name, proto);
4813
0
    }
4814
0
  } else if (!existing_symbol.IsPackage()) {
4815
    // Symbol seems to have been defined in a different file.
4816
0
    const FileDescriptor* other_file = existing_symbol.GetFile();
4817
0
    AddError(name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4818
0
      return absl::StrCat("\"", name,
4819
0
                          "\" is already defined (as something other than "
4820
0
                          "a package) in file \"",
4821
0
                          (other_file == nullptr ? "null" : other_file->name()),
4822
0
                          "\".");
4823
0
    });
4824
0
  }
4825
0
}
4826
4827
void DescriptorBuilder::ValidateSymbolName(const std::string& name,
4828
                                           const std::string& full_name,
4829
0
                                           const Message& proto) {
4830
0
  if (name.empty()) {
4831
0
    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4832
0
             "Missing name.");
4833
0
  } else {
4834
0
    for (char character : name) {
4835
      // I don't trust isalnum() due to locales.  :(
4836
0
      if ((character < 'a' || 'z' < character) &&
4837
0
          (character < 'A' || 'Z' < character) &&
4838
0
          (character < '0' || '9' < character) && (character != '_')) {
4839
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
4840
0
          return absl::StrCat("\"", name, "\" is not a valid identifier.");
4841
0
        });
4842
0
        return;
4843
0
      }
4844
0
    }
4845
0
  }
4846
0
}
4847
4848
// -------------------------------------------------------------------
4849
4850
// This generic implementation is good for all descriptors except
4851
// FileDescriptor.
4852
template <class DescriptorT>
4853
void DescriptorBuilder::AllocateOptions(
4854
    const typename DescriptorT::OptionsType& orig_options,
4855
    DescriptorT* descriptor, int options_field_tag,
4856
0
    absl::string_view option_name, internal::FlatAllocator& alloc) {
4857
0
  std::vector<int> options_path;
4858
0
  descriptor->GetLocationPath(&options_path);
4859
0
  options_path.push_back(options_field_tag);
4860
0
  AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(),
4861
0
                      orig_options, descriptor, options_path, option_name,
4862
0
                      alloc);
4863
0
}
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::Descriptor>(google::protobuf::Descriptor::OptionsType const&, google::protobuf::Descriptor*, int, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::FieldDescriptor>(google::protobuf::FieldDescriptor::OptionsType const&, google::protobuf::FieldDescriptor*, int, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::OneofDescriptor>(google::protobuf::OneofDescriptor::OptionsType const&, google::protobuf::OneofDescriptor*, int, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::EnumDescriptor>(google::protobuf::EnumDescriptor::OptionsType const&, google::protobuf::EnumDescriptor*, int, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::EnumValueDescriptor>(google::protobuf::EnumValueDescriptor::OptionsType const&, google::protobuf::EnumValueDescriptor*, int, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::ServiceDescriptor>(google::protobuf::ServiceDescriptor::OptionsType const&, google::protobuf::ServiceDescriptor*, int, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::MethodDescriptor>(google::protobuf::MethodDescriptor::OptionsType const&, google::protobuf::MethodDescriptor*, int, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
4864
4865
// We specialize for FileDescriptor.
4866
void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options,
4867
                                        FileDescriptor* descriptor,
4868
0
                                        internal::FlatAllocator& alloc) {
4869
0
  std::vector<int> options_path;
4870
0
  options_path.push_back(FileDescriptorProto::kOptionsFieldNumber);
4871
  // We add the dummy token so that LookupSymbol does the right thing.
4872
0
  AllocateOptionsImpl(absl::StrCat(descriptor->package(), ".dummy"),
4873
0
                      descriptor->name(), orig_options, descriptor,
4874
0
                      options_path, "google.protobuf.FileOptions", alloc);
4875
0
}
4876
4877
template <class DescriptorT>
4878
void DescriptorBuilder::AllocateOptionsImpl(
4879
    absl::string_view name_scope, absl::string_view element_name,
4880
    const typename DescriptorT::OptionsType& orig_options,
4881
    DescriptorT* descriptor, const std::vector<int>& options_path,
4882
0
    absl::string_view option_name, internal::FlatAllocator& alloc) {
4883
0
  auto* options = alloc.AllocateArray<typename DescriptorT::OptionsType>(1);
4884
4885
0
  if (!orig_options.IsInitialized()) {
4886
0
    AddError(absl::StrCat(name_scope, ".", element_name), orig_options,
4887
0
             DescriptorPool::ErrorCollector::OPTION_NAME,
4888
0
             "Uninterpreted option is missing name or value.");
4889
0
    return;
4890
0
  }
4891
4892
  // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti
4893
  // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the
4894
  // reflection based method, which requires the Descriptor. However, we are in
4895
  // the middle of building the descriptors, thus the deadlock.
4896
0
  options->ParseFromString(orig_options.SerializeAsString());
4897
0
  descriptor->options_ = options;
4898
4899
  // Don't add to options_to_interpret_ unless there were uninterpreted
4900
  // options.  This not only avoids unnecessary work, but prevents a
4901
  // bootstrapping problem when building descriptors for descriptor.proto.
4902
  // descriptor.proto does not contain any uninterpreted options, but
4903
  // attempting to interpret options anyway will cause
4904
  // OptionsType::GetDescriptor() to be called which may then deadlock since
4905
  // we're still trying to build it.
4906
0
  if (options->uninterpreted_option_size() > 0) {
4907
0
    options_to_interpret_.push_back(OptionsToInterpret(
4908
0
        name_scope, element_name, options_path, &orig_options, options));
4909
0
  }
4910
4911
  // If the custom option is in unknown fields, no need to interpret it.
4912
  // Remove the dependency file from unused_dependency.
4913
0
  const UnknownFieldSet& unknown_fields = orig_options.unknown_fields();
4914
0
  if (!unknown_fields.empty()) {
4915
    // Can not use options->GetDescriptor() which may case deadlock.
4916
0
    Symbol msg_symbol = tables_->FindSymbol(option_name);
4917
0
    if (msg_symbol.type() == Symbol::MESSAGE) {
4918
0
      for (int i = 0; i < unknown_fields.field_count(); ++i) {
4919
0
        assert_mutex_held(pool_);
4920
0
        const FieldDescriptor* field =
4921
0
            pool_->InternalFindExtensionByNumberNoLock(
4922
0
                msg_symbol.descriptor(), unknown_fields.field(i).number());
4923
0
        if (field) {
4924
0
          unused_dependency_.erase(field->file());
4925
0
        }
4926
0
      }
4927
0
    }
4928
0
  }
4929
0
}
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::FileDescriptor>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::FileDescriptor::OptionsType const&, google::protobuf::FileDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::Descriptor>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::Descriptor::OptionsType const&, google::protobuf::Descriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::FieldDescriptor>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::FieldDescriptor::OptionsType const&, google::protobuf::FieldDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::Descriptor::ExtensionRange>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::Descriptor::ExtensionRange::OptionsType const&, google::protobuf::Descriptor::ExtensionRange*, std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::OneofDescriptor>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::OneofDescriptor::OptionsType const&, google::protobuf::OneofDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::EnumDescriptor>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::EnumDescriptor::OptionsType const&, google::protobuf::EnumDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::EnumValueDescriptor>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::EnumValueDescriptor::OptionsType const&, google::protobuf::EnumValueDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::ServiceDescriptor>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::ServiceDescriptor::OptionsType const&, google::protobuf::ServiceDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::MethodDescriptor>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::MethodDescriptor::OptionsType const&, google::protobuf::MethodDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, google::protobuf::internal::FlatAllocator&)
4930
4931
// A common pattern:  We want to convert a repeated field in the descriptor
4932
// to an array of values, calling some method to build each value.
4933
#define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT)               \
4934
0
  OUTPUT->NAME##_count_ = INPUT.NAME##_size();                         \
4935
0
  OUTPUT->NAME##s_ = alloc.AllocateArray<                              \
4936
0
      typename std::remove_pointer<decltype(OUTPUT->NAME##s_)>::type>( \
4937
0
      INPUT.NAME##_size());                                            \
4938
0
  for (int i = 0; i < INPUT.NAME##_size(); i++) {                      \
4939
0
    METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i, alloc);        \
4940
0
  }
4941
4942
PROTOBUF_NOINLINE void DescriptorBuilder::AddRecursiveImportError(
4943
0
    const FileDescriptorProto& proto, int from_here) {
4944
0
  auto make_error = [&] {
4945
0
    std::string error_message("File recursively imports itself: ");
4946
0
    for (size_t i = from_here; i < tables_->pending_files_.size(); i++) {
4947
0
      error_message.append(tables_->pending_files_[i]);
4948
0
      error_message.append(" -> ");
4949
0
    }
4950
0
    error_message.append(proto.name());
4951
0
    return error_message;
4952
0
  };
4953
4954
0
  if (static_cast<size_t>(from_here) < tables_->pending_files_.size() - 1) {
4955
0
    AddError(tables_->pending_files_[from_here + 1], proto,
4956
0
             DescriptorPool::ErrorCollector::IMPORT, make_error);
4957
0
  } else {
4958
0
    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::IMPORT,
4959
0
             make_error);
4960
0
  }
4961
0
}
4962
4963
void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto,
4964
0
                                            int index) {
4965
0
  AddError(proto.dependency(index), proto,
4966
0
           DescriptorPool::ErrorCollector::IMPORT, [&] {
4967
0
             return absl::StrCat("Import \"", proto.dependency(index),
4968
0
                                 "\" was listed twice.");
4969
0
           });
4970
0
}
4971
4972
void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto,
4973
0
                                       int index) {
4974
0
  auto make_error = [&] {
4975
0
    if (pool_->fallback_database_ == nullptr) {
4976
0
      return absl::StrCat("Import \"", proto.dependency(index),
4977
0
                          "\" has not been loaded.");
4978
0
    }
4979
0
    return absl::StrCat("Import \"", proto.dependency(index),
4980
0
                        "\" was not found or had errors.");
4981
0
  };
4982
0
  AddError(proto.dependency(index), proto,
4983
0
           DescriptorPool::ErrorCollector::IMPORT, make_error);
4984
0
}
4985
4986
PROTOBUF_NOINLINE static bool ExistingFileMatchesProto(
4987
0
    const FileDescriptor* existing_file, const FileDescriptorProto& proto) {
4988
0
  FileDescriptorProto existing_proto;
4989
0
  existing_file->CopyTo(&existing_proto);
4990
  // TODO(liujisi): Remove it when CopyTo supports copying syntax params when
4991
  // syntax="proto2".
4992
0
  if (FileDescriptorLegacy(existing_file).syntax() ==
4993
0
          FileDescriptorLegacy::Syntax::SYNTAX_PROTO2 &&
4994
0
      proto.has_syntax()) {
4995
0
    existing_proto.set_syntax(FileDescriptorLegacy::SyntaxName(
4996
0
        FileDescriptorLegacy(existing_file).syntax()));
4997
0
  }
4998
4999
0
  return existing_proto.SerializeAsString() == proto.SerializeAsString();
5000
0
}
5001
5002
// These PlanAllocationSize functions will gather into the FlatAllocator all the
5003
// necessary memory allocations that BuildXXX functions below will do on the
5004
// Tables object.
5005
// They *must* be kept in sync. If we miss some PlanArray call we won't have
5006
// enough memory and will ABSL_CHECK-fail.
5007
static void PlanAllocationSize(
5008
    const RepeatedPtrField<EnumValueDescriptorProto>& values,
5009
0
    internal::FlatAllocator& alloc) {
5010
0
  alloc.PlanArray<EnumValueDescriptor>(values.size());
5011
0
  alloc.PlanArray<std::string>(2 * values.size());  // name + full_name
5012
0
  for (const auto& v : values) {
5013
0
    if (v.has_options()) alloc.PlanArray<EnumValueOptions>(1);
5014
0
  }
5015
0
}
5016
5017
static void PlanAllocationSize(
5018
    const RepeatedPtrField<EnumDescriptorProto>& enums,
5019
0
    internal::FlatAllocator& alloc) {
5020
0
  alloc.PlanArray<EnumDescriptor>(enums.size());
5021
0
  alloc.PlanArray<std::string>(2 * enums.size());  // name + full_name
5022
0
  for (const auto& e : enums) {
5023
0
    if (e.has_options()) alloc.PlanArray<EnumOptions>(1);
5024
0
    PlanAllocationSize(e.value(), alloc);
5025
0
    alloc.PlanArray<EnumDescriptor::ReservedRange>(e.reserved_range_size());
5026
0
    alloc.PlanArray<const std::string*>(e.reserved_name_size());
5027
0
    alloc.PlanArray<std::string>(e.reserved_name_size());
5028
0
  }
5029
0
}
5030
5031
static void PlanAllocationSize(
5032
    const RepeatedPtrField<OneofDescriptorProto>& oneofs,
5033
0
    internal::FlatAllocator& alloc) {
5034
0
  alloc.PlanArray<OneofDescriptor>(oneofs.size());
5035
0
  alloc.PlanArray<std::string>(2 * oneofs.size());  // name + full_name
5036
0
  for (const auto& oneof : oneofs) {
5037
0
    if (oneof.has_options()) alloc.PlanArray<OneofOptions>(1);
5038
0
  }
5039
0
}
5040
5041
static void PlanAllocationSize(
5042
    const RepeatedPtrField<FieldDescriptorProto>& fields,
5043
0
    internal::FlatAllocator& alloc) {
5044
0
  alloc.PlanArray<FieldDescriptor>(fields.size());
5045
0
  for (const auto& field : fields) {
5046
0
    if (field.has_options()) alloc.PlanArray<FieldOptions>(1);
5047
0
    alloc.PlanFieldNames(field.name(),
5048
0
                         field.has_json_name() ? &field.json_name() : nullptr);
5049
0
    if (field.has_default_value() && field.has_type() &&
5050
0
        (field.type() == FieldDescriptorProto::TYPE_STRING ||
5051
0
         field.type() == FieldDescriptorProto::TYPE_BYTES)) {
5052
      // For the default string value.
5053
0
      alloc.PlanArray<std::string>(1);
5054
0
    }
5055
0
  }
5056
0
}
5057
5058
static void PlanAllocationSize(
5059
    const RepeatedPtrField<DescriptorProto::ExtensionRange>& ranges,
5060
0
    internal::FlatAllocator& alloc) {
5061
0
  alloc.PlanArray<Descriptor::ExtensionRange>(ranges.size());
5062
0
  for (const auto& r : ranges) {
5063
0
    if (r.has_options()) alloc.PlanArray<ExtensionRangeOptions>(1);
5064
0
  }
5065
0
}
5066
5067
static void PlanAllocationSize(
5068
    const RepeatedPtrField<DescriptorProto>& messages,
5069
0
    internal::FlatAllocator& alloc) {
5070
0
  alloc.PlanArray<Descriptor>(messages.size());
5071
0
  alloc.PlanArray<std::string>(2 * messages.size());  // name + full_name
5072
5073
0
  for (const auto& message : messages) {
5074
0
    if (message.has_options()) alloc.PlanArray<MessageOptions>(1);
5075
0
    PlanAllocationSize(message.nested_type(), alloc);
5076
0
    PlanAllocationSize(message.field(), alloc);
5077
0
    PlanAllocationSize(message.extension(), alloc);
5078
0
    PlanAllocationSize(message.extension_range(), alloc);
5079
0
    alloc.PlanArray<Descriptor::ReservedRange>(message.reserved_range_size());
5080
0
    alloc.PlanArray<const std::string*>(message.reserved_name_size());
5081
0
    alloc.PlanArray<std::string>(message.reserved_name_size());
5082
0
    PlanAllocationSize(message.enum_type(), alloc);
5083
0
    PlanAllocationSize(message.oneof_decl(), alloc);
5084
0
  }
5085
0
}
5086
5087
static void PlanAllocationSize(
5088
    const RepeatedPtrField<MethodDescriptorProto>& methods,
5089
0
    internal::FlatAllocator& alloc) {
5090
0
  alloc.PlanArray<MethodDescriptor>(methods.size());
5091
0
  alloc.PlanArray<std::string>(2 * methods.size());  // name + full_name
5092
0
  for (const auto& m : methods) {
5093
0
    if (m.has_options()) alloc.PlanArray<MethodOptions>(1);
5094
0
  }
5095
0
}
5096
5097
static void PlanAllocationSize(
5098
    const RepeatedPtrField<ServiceDescriptorProto>& services,
5099
0
    internal::FlatAllocator& alloc) {
5100
0
  alloc.PlanArray<ServiceDescriptor>(services.size());
5101
0
  alloc.PlanArray<std::string>(2 * services.size());  // name + full_name
5102
0
  for (const auto& service : services) {
5103
0
    if (service.has_options()) alloc.PlanArray<ServiceOptions>(1);
5104
0
    PlanAllocationSize(service.method(), alloc);
5105
0
  }
5106
0
}
5107
5108
static void PlanAllocationSize(const FileDescriptorProto& proto,
5109
0
                               internal::FlatAllocator& alloc) {
5110
0
  alloc.PlanArray<FileDescriptor>(1);
5111
0
  alloc.PlanArray<FileDescriptorTables>(1);
5112
0
  alloc.PlanArray<std::string>(2
5113
0
  );    // name + package
5114
0
  if (proto.has_options()) alloc.PlanArray<FileOptions>(1);
5115
0
  if (proto.has_source_code_info()) alloc.PlanArray<SourceCodeInfo>(1);
5116
5117
0
  PlanAllocationSize(proto.service(), alloc);
5118
0
  PlanAllocationSize(proto.message_type(), alloc);
5119
0
  PlanAllocationSize(proto.enum_type(), alloc);
5120
0
  PlanAllocationSize(proto.extension(), alloc);
5121
5122
0
  alloc.PlanArray<int>(proto.weak_dependency_size());
5123
0
  alloc.PlanArray<int>(proto.public_dependency_size());
5124
0
  alloc.PlanArray<const FileDescriptor*>(proto.dependency_size());
5125
0
}
5126
5127
const FileDescriptor* DescriptorBuilder::BuildFile(
5128
0
    const FileDescriptorProto& proto) {
5129
0
  filename_ = proto.name();
5130
5131
  // Check if the file already exists and is identical to the one being built.
5132
  // Note:  This only works if the input is canonical -- that is, it
5133
  //   fully-qualifies all type names, has no UninterpretedOptions, etc.
5134
  //   This is fine, because this idempotency "feature" really only exists to
5135
  //   accommodate one hack in the proto1->proto2 migration layer.
5136
0
  const FileDescriptor* existing_file = tables_->FindFile(filename_);
5137
0
  if (existing_file != nullptr) {
5138
    // File already in pool.  Compare the existing one to the input.
5139
0
    if (ExistingFileMatchesProto(existing_file, proto)) {
5140
      // They're identical.  Return the existing descriptor.
5141
0
      return existing_file;
5142
0
    }
5143
5144
    // Not a match.  The error will be detected and handled later.
5145
0
  }
5146
5147
  // Check to see if this file is already on the pending files list.
5148
  // TODO(kenton):  Allow recursive imports?  It may not work with some
5149
  //   (most?) programming languages.  E.g., in C++, a forward declaration
5150
  //   of a type is not sufficient to allow it to be used even in a
5151
  //   generated header file due to inlining.  This could perhaps be
5152
  //   worked around using tricks involving inserting #include statements
5153
  //   mid-file, but that's pretty ugly, and I'm pretty sure there are
5154
  //   some languages out there that do not allow recursive dependencies
5155
  //   at all.
5156
0
  for (size_t i = 0; i < tables_->pending_files_.size(); i++) {
5157
0
    if (tables_->pending_files_[i] == proto.name()) {
5158
0
      AddRecursiveImportError(proto, i);
5159
0
      return nullptr;
5160
0
    }
5161
0
  }
5162
5163
0
  static const int kMaximumPackageLength = 511;
5164
0
  if (proto.package().size() > kMaximumPackageLength) {
5165
0
    AddError(proto.package(), proto, DescriptorPool::ErrorCollector::NAME,
5166
0
             "Package name is too long");
5167
0
    return nullptr;
5168
0
  }
5169
5170
  // If we have a fallback_database_, and we aren't doing lazy import building,
5171
  // attempt to load all dependencies now, before checkpointing tables_.  This
5172
  // avoids confusion with recursive checkpoints.
5173
0
  if (!pool_->lazily_build_dependencies_) {
5174
0
    if (pool_->fallback_database_ != nullptr) {
5175
0
      tables_->pending_files_.push_back(proto.name());
5176
0
      for (int i = 0; i < proto.dependency_size(); i++) {
5177
0
        if (tables_->FindFile(proto.dependency(i)) == nullptr &&
5178
0
            (pool_->underlay_ == nullptr ||
5179
0
             pool_->underlay_->FindFileByName(proto.dependency(i)) ==
5180
0
                 nullptr)) {
5181
          // We don't care what this returns since we'll find out below anyway.
5182
0
          pool_->TryFindFileInFallbackDatabase(proto.dependency(i));
5183
0
        }
5184
0
      }
5185
0
      tables_->pending_files_.pop_back();
5186
0
    }
5187
0
  }
5188
5189
  // Checkpoint the tables so that we can roll back if something goes wrong.
5190
0
  tables_->AddCheckpoint();
5191
5192
0
  auto alloc = absl::make_unique<internal::FlatAllocator>();
5193
0
  PlanAllocationSize(proto, *alloc);
5194
0
  alloc->FinalizePlanning(tables_);
5195
0
  FileDescriptor* result = BuildFileImpl(proto, *alloc);
5196
5197
0
  file_tables_->FinalizeTables();
5198
0
  if (result) {
5199
0
    tables_->ClearLastCheckpoint();
5200
0
    result->finished_building_ = true;
5201
0
    alloc->ExpectConsumed();
5202
0
  } else {
5203
0
    tables_->RollbackToLastCheckpoint();
5204
0
  }
5205
5206
0
  return result;
5207
0
}
5208
5209
FileDescriptor* DescriptorBuilder::BuildFileImpl(
5210
0
    const FileDescriptorProto& proto, internal::FlatAllocator& alloc) {
5211
0
  FileDescriptor* result = alloc.AllocateArray<FileDescriptor>(1);
5212
0
  file_ = result;
5213
5214
0
  result->is_placeholder_ = false;
5215
0
  result->finished_building_ = false;
5216
0
  SourceCodeInfo* info = nullptr;
5217
0
  if (proto.has_source_code_info()) {
5218
0
    info = alloc.AllocateArray<SourceCodeInfo>(1);
5219
0
    info->CopyFrom(proto.source_code_info());
5220
0
    result->source_code_info_ = info;
5221
0
  } else {
5222
0
    result->source_code_info_ = &SourceCodeInfo::default_instance();
5223
0
  }
5224
5225
0
  file_tables_ = alloc.AllocateArray<FileDescriptorTables>(1);
5226
0
  file_->tables_ = file_tables_;
5227
5228
0
  if (!proto.has_name()) {
5229
0
    AddError("", proto, DescriptorPool::ErrorCollector::OTHER,
5230
0
             "Missing field: FileDescriptorProto.name.");
5231
0
  }
5232
5233
  // TODO(liujisi): Report error when the syntax is empty after all the protos
5234
  // have added the syntax statement.
5235
0
  if (proto.syntax().empty() || proto.syntax() == "proto2") {
5236
0
    file_->syntax_ = FileDescriptorLegacy::SYNTAX_PROTO2;
5237
0
  } else if (proto.syntax() == "proto3") {
5238
0
    file_->syntax_ = FileDescriptorLegacy::SYNTAX_PROTO3;
5239
0
  } else {
5240
0
    file_->syntax_ = FileDescriptorLegacy::SYNTAX_UNKNOWN;
5241
0
    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, [&] {
5242
0
      return absl::StrCat("Unrecognized syntax: ", proto.syntax());
5243
0
    });
5244
0
  }
5245
5246
0
  result->name_ = alloc.AllocateStrings(proto.name());
5247
0
  if (proto.has_package()) {
5248
0
    result->package_ = alloc.AllocateStrings(proto.package());
5249
0
  } else {
5250
    // We cannot rely on proto.package() returning a valid string if
5251
    // proto.has_package() is false, because we might be running at static
5252
    // initialization time, in which case default values have not yet been
5253
    // initialized.
5254
0
    result->package_ = alloc.AllocateStrings("");
5255
0
  }
5256
0
  result->pool_ = pool_;
5257
5258
0
  if (result->name().find('\0') != std::string::npos) {
5259
0
    AddError(result->name(), proto, DescriptorPool::ErrorCollector::NAME, [&] {
5260
0
      return absl::StrCat("\"", result->name(), "\" contains null character.");
5261
0
    });
5262
0
    return nullptr;
5263
0
  }
5264
5265
  // Add to tables.
5266
0
  if (!tables_->AddFile(result)) {
5267
0
    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
5268
0
             "A file with this name is already in the pool.");
5269
    // Bail out early so that if this is actually the exact same file, we
5270
    // don't end up reporting that every single symbol is already defined.
5271
0
    return nullptr;
5272
0
  }
5273
0
  if (!result->package().empty()) {
5274
0
    if (std::count(result->package().begin(), result->package().end(), '.') >
5275
0
        kPackageLimit) {
5276
0
      AddError(result->package(), proto, DescriptorPool::ErrorCollector::NAME,
5277
0
               "Exceeds Maximum Package Depth");
5278
0
      return nullptr;
5279
0
    }
5280
0
    AddPackage(result->package(), proto, result);
5281
0
  }
5282
5283
  // Make sure all dependencies are loaded.
5284
0
  absl::flat_hash_set<absl::string_view> seen_dependencies;
5285
0
  result->dependency_count_ = proto.dependency_size();
5286
0
  result->dependencies_ =
5287
0
      alloc.AllocateArray<const FileDescriptor*>(proto.dependency_size());
5288
0
  result->dependencies_once_ = nullptr;
5289
0
  unused_dependency_.clear();
5290
0
  absl::flat_hash_set<int> weak_deps;
5291
0
  for (int i = 0; i < proto.weak_dependency_size(); ++i) {
5292
0
    weak_deps.insert(proto.weak_dependency(i));
5293
0
  }
5294
5295
0
  bool need_lazy_deps = false;
5296
0
  for (int i = 0; i < proto.dependency_size(); i++) {
5297
0
    if (!seen_dependencies.insert(proto.dependency(i)).second) {
5298
0
      AddTwiceListedError(proto, i);
5299
0
    }
5300
5301
0
    const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
5302
0
    if (dependency == nullptr && pool_->underlay_ != nullptr) {
5303
0
      dependency = pool_->underlay_->FindFileByName(proto.dependency(i));
5304
0
    }
5305
5306
0
    if (dependency == result) {
5307
      // Recursive import.  dependency/result is not fully initialized, and it's
5308
      // dangerous to try to do anything with it.  The recursive import error
5309
      // will be detected and reported in DescriptorBuilder::BuildFile().
5310
0
      return nullptr;
5311
0
    }
5312
5313
0
    if (dependency == nullptr) {
5314
0
      if (!pool_->lazily_build_dependencies_) {
5315
0
        if (pool_->allow_unknown_ ||
5316
0
            (!pool_->enforce_weak_ && weak_deps.contains(i))) {
5317
0
          internal::FlatAllocator lazy_dep_alloc;
5318
0
          lazy_dep_alloc.PlanArray<FileDescriptor>(1);
5319
0
          lazy_dep_alloc.PlanArray<std::string>(1);
5320
0
          lazy_dep_alloc.FinalizePlanning(tables_);
5321
0
          dependency = pool_->NewPlaceholderFileWithMutexHeld(
5322
0
              proto.dependency(i), lazy_dep_alloc);
5323
0
        } else {
5324
0
          AddImportError(proto, i);
5325
0
        }
5326
0
      }
5327
0
    } else {
5328
      // Add to unused_dependency_ to track unused imported files.
5329
      // Note: do not track unused imported files for public import.
5330
0
      if (pool_->enforce_dependencies_ &&
5331
0
          (pool_->unused_import_track_files_.find(proto.name()) !=
5332
0
           pool_->unused_import_track_files_.end()) &&
5333
0
          (dependency->public_dependency_count() == 0)) {
5334
0
        unused_dependency_.insert(dependency);
5335
0
      }
5336
0
    }
5337
5338
0
    result->dependencies_[i] = dependency;
5339
0
    if (pool_->lazily_build_dependencies_ && !dependency) {
5340
0
      need_lazy_deps = true;
5341
0
    }
5342
0
  }
5343
0
  if (need_lazy_deps) {
5344
0
    int total_char_size = 0;
5345
0
    for (int i = 0; i < proto.dependency_size(); i++) {
5346
0
      if (result->dependencies_[i] == nullptr) {
5347
0
        total_char_size += static_cast<int>(proto.dependency(i).size());
5348
0
      }
5349
0
      ++total_char_size;  // For NUL char
5350
0
    }
5351
5352
0
    void* data = tables_->AllocateBytes(
5353
0
        static_cast<int>(sizeof(absl::once_flag)) + total_char_size);
5354
0
    result->dependencies_once_ = ::new (data) absl::once_flag{};
5355
0
    char* name_data = reinterpret_cast<char*>(result->dependencies_once_ + 1);
5356
5357
0
    for (int i = 0; i < proto.dependency_size(); i++) {
5358
0
      if (result->dependencies_[i] == nullptr) {
5359
0
        memcpy(name_data, proto.dependency(i).c_str(),
5360
0
               proto.dependency(i).size());
5361
0
        name_data += proto.dependency(i).size();
5362
0
      }
5363
0
      *name_data++ = '\0';
5364
0
    }
5365
0
  }
5366
5367
  // Check public dependencies.
5368
0
  int public_dependency_count = 0;
5369
0
  result->public_dependencies_ =
5370
0
      alloc.AllocateArray<int>(proto.public_dependency_size());
5371
0
  for (int i = 0; i < proto.public_dependency_size(); i++) {
5372
    // Only put valid public dependency indexes.
5373
0
    int index = proto.public_dependency(i);
5374
0
    if (index >= 0 && index < proto.dependency_size()) {
5375
0
      result->public_dependencies_[public_dependency_count++] = index;
5376
      // Do not track unused imported files for public import.
5377
      // Calling dependency(i) builds that file when doing lazy imports,
5378
      // need to avoid doing this. Unused dependency detection isn't done
5379
      // when building lazily, anyways.
5380
0
      if (!pool_->lazily_build_dependencies_) {
5381
0
        unused_dependency_.erase(result->dependency(index));
5382
0
      }
5383
0
    } else {
5384
0
      AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
5385
0
               "Invalid public dependency index.");
5386
0
    }
5387
0
  }
5388
0
  result->public_dependency_count_ = public_dependency_count;
5389
5390
  // Build dependency set
5391
0
  dependencies_.clear();
5392
  // We don't/can't do proper dependency error checking when
5393
  // lazily_build_dependencies_, and calling dependency(i) will force
5394
  // a dependency to be built, which we don't want.
5395
0
  if (!pool_->lazily_build_dependencies_) {
5396
0
    for (int i = 0; i < result->dependency_count(); i++) {
5397
0
      RecordPublicDependencies(result->dependency(i));
5398
0
    }
5399
0
  }
5400
5401
  // Check weak dependencies.
5402
0
  int weak_dependency_count = 0;
5403
0
  result->weak_dependencies_ =
5404
0
      alloc.AllocateArray<int>(proto.weak_dependency_size());
5405
0
  for (int i = 0; i < proto.weak_dependency_size(); i++) {
5406
0
    int index = proto.weak_dependency(i);
5407
0
    if (index >= 0 && index < proto.dependency_size()) {
5408
0
      result->weak_dependencies_[weak_dependency_count++] = index;
5409
0
    } else {
5410
0
      AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
5411
0
               "Invalid weak dependency index.");
5412
0
    }
5413
0
  }
5414
0
  result->weak_dependency_count_ = weak_dependency_count;
5415
5416
  // Convert children.
5417
0
  BUILD_ARRAY(proto, result, message_type, BuildMessage, nullptr);
5418
0
  BUILD_ARRAY(proto, result, enum_type, BuildEnum, nullptr);
5419
0
  BUILD_ARRAY(proto, result, service, BuildService, nullptr);
5420
0
  BUILD_ARRAY(proto, result, extension, BuildExtension, nullptr);
5421
5422
  // Copy options.
5423
0
  result->options_ = nullptr;  // Set to default_instance later if necessary.
5424
0
  if (proto.has_options()) {
5425
0
    AllocateOptions(proto.options(), result, alloc);
5426
0
  }
5427
5428
  // Note that the following steps must occur in exactly the specified order.
5429
5430
  // Cross-link.
5431
0
  CrossLinkFile(result, proto);
5432
5433
0
  if (!message_hints_.empty()) {
5434
0
    SuggestFieldNumbers(result, proto);
5435
0
  }
5436
5437
  // Interpret any remaining uninterpreted options gathered into
5438
  // options_to_interpret_ during descriptor building.  Cross-linking has made
5439
  // extension options known, so all interpretations should now succeed.
5440
0
  if (!had_errors_) {
5441
0
    OptionInterpreter option_interpreter(this);
5442
0
    for (std::vector<OptionsToInterpret>::iterator iter =
5443
0
             options_to_interpret_.begin();
5444
0
         iter != options_to_interpret_.end(); ++iter) {
5445
0
      option_interpreter.InterpretOptions(&(*iter));
5446
0
    }
5447
0
    options_to_interpret_.clear();
5448
0
    if (info != nullptr) {
5449
0
      option_interpreter.UpdateSourceCodeInfo(info);
5450
0
    }
5451
0
  }
5452
5453
  // Validate options. See comments at InternalSetLazilyBuildDependencies about
5454
  // error checking and lazy import building.
5455
0
  if (!had_errors_ && !pool_->lazily_build_dependencies_) {
5456
0
    ValidateFileOptions(result, proto);
5457
0
  }
5458
5459
  // Additional naming conflict check for map entry types. Only need to check
5460
  // this if there are already errors.
5461
0
  if (had_errors_) {
5462
0
    for (int i = 0; i < proto.message_type_size(); ++i) {
5463
0
      DetectMapConflicts(result->message_type(i), proto.message_type(i));
5464
0
    }
5465
0
  }
5466
5467
5468
  // Again, see comments at InternalSetLazilyBuildDependencies about error
5469
  // checking. Also, don't log unused dependencies if there were previous
5470
  // errors, since the results might be inaccurate.
5471
0
  if (!had_errors_ && !unused_dependency_.empty() &&
5472
0
      !pool_->lazily_build_dependencies_) {
5473
0
    LogUnusedDependency(proto, result);
5474
0
  }
5475
5476
0
  if (had_errors_) {
5477
0
    return nullptr;
5478
0
  } else {
5479
0
    return result;
5480
0
  }
5481
0
}
5482
5483
5484
const std::string* DescriptorBuilder::AllocateNameStrings(
5485
    const std::string& scope, const std::string& proto_name,
5486
0
    internal::FlatAllocator& alloc) {
5487
0
  if (scope.empty()) {
5488
0
    return alloc.AllocateStrings(proto_name, proto_name);
5489
0
  } else {
5490
0
    return alloc.AllocateStrings(proto_name,
5491
0
                                 absl::StrCat(scope, ".", proto_name));
5492
0
  }
5493
0
}
5494
5495
namespace {
5496
5497
// Helper for BuildMessage below.
5498
struct IncrementWhenDestroyed {
5499
0
  ~IncrementWhenDestroyed() { ++to_increment; }
5500
  int& to_increment;
5501
};
5502
5503
}  // namespace
5504
5505
namespace {
5506
0
bool IsNonMessageType(absl::string_view type) {
5507
0
  static const auto* non_message_types =
5508
0
      new absl::flat_hash_set<absl::string_view>(
5509
0
          {"double", "float", "int64", "uint64", "int32", "fixed32", "fixed64",
5510
0
           "bool", "string", "bytes", "uint32", "enum", "sfixed32", "sfixed64",
5511
0
           "sint32", "sint64"});
5512
0
  return non_message_types->contains(type);
5513
0
}
5514
}  // namespace
5515
5516
5517
void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
5518
                                     const Descriptor* parent,
5519
                                     Descriptor* result,
5520
0
                                     internal::FlatAllocator& alloc) {
5521
0
  const std::string& scope =
5522
0
      (parent == nullptr) ? file_->package() : parent->full_name();
5523
0
  result->all_names_ = AllocateNameStrings(scope, proto.name(), alloc);
5524
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
5525
5526
0
  result->file_ = file_;
5527
0
  result->containing_type_ = parent;
5528
0
  result->is_placeholder_ = false;
5529
0
  result->is_unqualified_placeholder_ = false;
5530
0
  result->well_known_type_ = Descriptor::WELLKNOWNTYPE_UNSPECIFIED;
5531
0
  result->options_ = nullptr;  // Set to default_instance later if necessary.
5532
5533
0
  auto it = pool_->tables_->well_known_types_.find(result->full_name());
5534
0
  if (it != pool_->tables_->well_known_types_.end()) {
5535
0
    result->well_known_type_ = it->second;
5536
0
  }
5537
5538
  // Calculate the continuous sequence of fields.
5539
  // These can be fast-path'd during lookup and don't need to be added to the
5540
  // tables.
5541
  // We use uint16_t to save space for sequential_field_limit_, so stop before
5542
  // overflowing it. Worst case, we are not taking full advantage on huge
5543
  // messages, but it is unlikely.
5544
0
  result->sequential_field_limit_ = 0;
5545
0
  for (int i = 0; i < std::numeric_limits<uint16_t>::max() &&
5546
0
                  i < proto.field_size() && proto.field(i).number() == i + 1;
5547
0
       ++i) {
5548
0
    result->sequential_field_limit_ = i + 1;
5549
0
  }
5550
5551
  // Build oneofs first so that fields and extension ranges can refer to them.
5552
0
  BUILD_ARRAY(proto, result, oneof_decl, BuildOneof, result);
5553
0
  BUILD_ARRAY(proto, result, field, BuildField, result);
5554
0
  BUILD_ARRAY(proto, result, enum_type, BuildEnum, result);
5555
0
  BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result);
5556
0
  BUILD_ARRAY(proto, result, extension, BuildExtension, result);
5557
0
  BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);
5558
5559
  // Before building submessages, check recursion limit.
5560
0
  --recursion_depth_;
5561
0
  IncrementWhenDestroyed revert{recursion_depth_};
5562
0
  if (recursion_depth_ <= 0) {
5563
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::OTHER,
5564
0
             "Reached maximum recursion limit for nested messages.");
5565
0
    result->nested_types_ = nullptr;
5566
0
    result->nested_type_count_ = 0;
5567
0
    return;
5568
0
  }
5569
0
  BUILD_ARRAY(proto, result, nested_type, BuildMessage, result);
5570
5571
  // Copy reserved names.
5572
0
  int reserved_name_count = proto.reserved_name_size();
5573
0
  result->reserved_name_count_ = reserved_name_count;
5574
0
  result->reserved_names_ =
5575
0
      alloc.AllocateArray<const std::string*>(reserved_name_count);
5576
0
  for (int i = 0; i < reserved_name_count; ++i) {
5577
0
    result->reserved_names_[i] =
5578
0
        alloc.AllocateStrings(proto.reserved_name(i));
5579
0
  }
5580
5581
  // Copy options.
5582
0
  if (proto.has_options()) {
5583
0
    AllocateOptions(proto.options(), result,
5584
0
                    DescriptorProto::kOptionsFieldNumber,
5585
0
                    "google.protobuf.MessageOptions", alloc);
5586
0
  }
5587
5588
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5589
5590
0
  for (int i = 0; i < proto.reserved_range_size(); i++) {
5591
0
    const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i);
5592
0
    for (int j = i + 1; j < proto.reserved_range_size(); j++) {
5593
0
      const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j);
5594
0
      if (range1.end() > range2.start() && range2.end() > range1.start()) {
5595
0
        AddError(result->full_name(), proto.reserved_range(i),
5596
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
5597
0
                   return absl::Substitute(
5598
0
                       "Reserved range $0 to $1 overlaps with "
5599
0
                       "already-defined range $2 to $3.",
5600
0
                       range2.start(), range2.end() - 1, range1.start(),
5601
0
                       range1.end() - 1);
5602
0
                 });
5603
0
      }
5604
0
    }
5605
0
  }
5606
5607
0
  absl::flat_hash_set<absl::string_view> reserved_name_set;
5608
0
  for (const std::string& name : proto.reserved_name()) {
5609
0
    if (!reserved_name_set.insert(name).second) {
5610
0
      AddError(name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
5611
0
        return absl::Substitute("Field name \"$0\" is reserved multiple times.",
5612
0
                                name);
5613
0
      });
5614
0
    }
5615
0
  }
5616
  // Check that fields aren't using reserved names or numbers and that they
5617
  // aren't using extension numbers.
5618
0
  for (int i = 0; i < result->field_count(); i++) {
5619
0
    const FieldDescriptor* field = result->field(i);
5620
0
    for (int j = 0; j < result->extension_range_count(); j++) {
5621
0
      const Descriptor::ExtensionRange* range = result->extension_range(j);
5622
0
      if (range->start <= field->number() && field->number() < range->end) {
5623
0
        message_hints_[result].RequestHintOnFieldNumbers(
5624
0
            proto.extension_range(j), DescriptorPool::ErrorCollector::NUMBER);
5625
0
        AddError(field->full_name(), proto.extension_range(j),
5626
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
5627
0
                   return absl::Substitute(
5628
0
                       "Extension range $0 to $1 includes field \"$2\" ($3).",
5629
0
                       range->start, range->end - 1, field->name(),
5630
0
                       field->number());
5631
0
                 });
5632
0
      }
5633
0
    }
5634
0
    for (int j = 0; j < result->reserved_range_count(); j++) {
5635
0
      const Descriptor::ReservedRange* range = result->reserved_range(j);
5636
0
      if (range->start <= field->number() && field->number() < range->end) {
5637
0
        message_hints_[result].RequestHintOnFieldNumbers(
5638
0
            proto.reserved_range(j), DescriptorPool::ErrorCollector::NUMBER);
5639
0
        AddError(field->full_name(), proto.reserved_range(j),
5640
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
5641
0
                   return absl::Substitute(
5642
0
                       "Field \"$0\" uses reserved number $1.", field->name(),
5643
0
                       field->number());
5644
0
                 });
5645
0
      }
5646
0
    }
5647
0
    if (reserved_name_set.contains(field->name())) {
5648
0
      AddError(field->full_name(), proto.field(i),
5649
0
               DescriptorPool::ErrorCollector::NAME, [&] {
5650
0
                 return absl::Substitute("Field name \"$0\" is reserved.",
5651
0
                                         field->name());
5652
0
               });
5653
0
    }
5654
0
  }
5655
5656
  // Check that extension ranges don't overlap and don't include
5657
  // reserved field numbers or names.
5658
0
  for (int i = 0; i < result->extension_range_count(); i++) {
5659
0
    const Descriptor::ExtensionRange* range1 = result->extension_range(i);
5660
0
    for (int j = 0; j < result->reserved_range_count(); j++) {
5661
0
      const Descriptor::ReservedRange* range2 = result->reserved_range(j);
5662
0
      if (range1->end > range2->start && range2->end > range1->start) {
5663
0
        AddError(result->full_name(), proto.extension_range(i),
5664
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
5665
0
                   return absl::Substitute(
5666
0
                       "Extension range $0 to $1 overlaps with "
5667
0
                       "reserved range $2 to $3.",
5668
0
                       range1->start, range1->end - 1, range2->start,
5669
0
                       range2->end - 1);
5670
0
                 });
5671
0
      }
5672
0
    }
5673
0
    for (int j = i + 1; j < result->extension_range_count(); j++) {
5674
0
      const Descriptor::ExtensionRange* range2 = result->extension_range(j);
5675
0
      if (range1->end > range2->start && range2->end > range1->start) {
5676
0
        AddError(result->full_name(), proto.extension_range(i),
5677
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
5678
0
                   return absl::Substitute(
5679
0
                       "Extension range $0 to $1 overlaps with "
5680
0
                       "already-defined range $2 to $3.",
5681
0
                       range2->start, range2->end - 1, range1->start,
5682
0
                       range1->end - 1);
5683
0
                 });
5684
0
      }
5685
0
    }
5686
0
  }
5687
0
}
5688
5689
void DescriptorBuilder::CheckFieldJsonNameUniqueness(
5690
0
    const DescriptorProto& proto, const Descriptor* result) {
5691
0
  FileDescriptorLegacy::Syntax syntax =
5692
0
      FileDescriptorLegacy(result->file()).syntax();
5693
0
  std::string message_name = result->full_name();
5694
0
  if (pool_->deprecated_legacy_json_field_conflicts_ ||
5695
0
      IsLegacyJsonFieldConflictEnabled(result->options())) {
5696
0
    if (syntax == FileDescriptorLegacy::Syntax::SYNTAX_PROTO3) {
5697
      // Only check default JSON names for conflicts in proto3.  This is legacy
5698
      // behavior that will be removed in a later version.
5699
0
      CheckFieldJsonNameUniqueness(message_name, proto, syntax, false);
5700
0
    }
5701
0
  } else {
5702
    // Check both with and without taking json_name into consideration.  This is
5703
    // needed for field masks, which don't use json_name.
5704
0
    CheckFieldJsonNameUniqueness(message_name, proto, syntax, false);
5705
0
    CheckFieldJsonNameUniqueness(message_name, proto, syntax, true);
5706
0
  }
5707
0
}
5708
5709
namespace {
5710
// Helpers for function below
5711
5712
struct JsonNameDetails {
5713
  const FieldDescriptorProto* field;
5714
  std::string orig_name;
5715
  bool is_custom;
5716
};
5717
5718
JsonNameDetails GetJsonNameDetails(const FieldDescriptorProto* field,
5719
0
                                   bool use_custom) {
5720
0
  std::string default_json_name = ToJsonName(field->name());
5721
0
  if (use_custom && field->has_json_name() &&
5722
0
      field->json_name() != default_json_name) {
5723
0
    return {field, field->json_name(), true};
5724
0
  }
5725
0
  return {field, default_json_name, false};
5726
0
}
5727
5728
0
bool JsonNameLooksLikeExtension(std::string name) {
5729
0
  return !name.empty() && name.front() == '[' && name.back() == ']';
5730
0
}
5731
5732
}  // namespace
5733
5734
void DescriptorBuilder::CheckFieldJsonNameUniqueness(
5735
    const std::string& message_name, const DescriptorProto& message,
5736
0
    FileDescriptorLegacy::Syntax syntax, bool use_custom_names) {
5737
0
  absl::flat_hash_map<std::string, JsonNameDetails> name_to_field;
5738
0
  for (const FieldDescriptorProto& field : message.field()) {
5739
0
    JsonNameDetails details = GetJsonNameDetails(&field, use_custom_names);
5740
0
    if (details.is_custom && JsonNameLooksLikeExtension(details.orig_name)) {
5741
0
      auto make_error = [&] {
5742
0
        return absl::StrFormat(
5743
0
            "The custom JSON name of field \"%s\" (\"%s\") is invalid: "
5744
0
            "JSON names may not start with '[' and end with ']'.",
5745
0
            field.name(), details.orig_name);
5746
0
      };
5747
0
      AddError(message_name, field, DescriptorPool::ErrorCollector::NAME,
5748
0
               make_error);
5749
0
      continue;
5750
0
    }
5751
0
    auto it_inserted = name_to_field.try_emplace(details.orig_name, details);
5752
0
    if (it_inserted.second) {
5753
0
      continue;
5754
0
    }
5755
0
    JsonNameDetails& match = it_inserted.first->second;
5756
0
    if (use_custom_names && !details.is_custom && !match.is_custom) {
5757
      // if this pass is considering custom JSON names, but neither of the
5758
      // names involved in the conflict are custom, don't bother with a
5759
      // message. That will have been reported from other pass (non-custom
5760
      // JSON names).
5761
0
      continue;
5762
0
    }
5763
0
    auto make_error = [&] {
5764
0
      absl::string_view this_type = details.is_custom ? "custom" : "default";
5765
0
      absl::string_view existing_type = match.is_custom ? "custom" : "default";
5766
      // If the matched name differs (which it can only differ in case), include
5767
      // it in the error message, for maximum clarity to user.
5768
0
      std::string name_suffix = "";
5769
0
      if (details.orig_name != match.orig_name) {
5770
0
        name_suffix = absl::StrCat(" (\"", match.orig_name, "\")");
5771
0
      }
5772
0
      return absl::StrFormat(
5773
0
          "The %s JSON name of field \"%s\" (\"%s\") conflicts "
5774
0
          "with the %s JSON name of field \"%s\"%s.",
5775
0
          this_type, field.name(), details.orig_name, existing_type,
5776
0
          match.field->name(), name_suffix);
5777
0
    };
5778
5779
0
    bool involves_default = !details.is_custom || !match.is_custom;
5780
0
    if (syntax == FileDescriptorLegacy::SYNTAX_PROTO2 && involves_default) {
5781
      // TODO(b/261750676) Upgrade this to an error once downstream protos have
5782
      // been fixed.
5783
0
      AddWarning(message_name, field, DescriptorPool::ErrorCollector::NAME,
5784
0
                 make_error);
5785
0
    } else {
5786
0
      AddError(message_name, field, DescriptorPool::ErrorCollector::NAME,
5787
0
               make_error);
5788
0
    }
5789
0
  }
5790
0
}
5791
5792
void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
5793
                                              Descriptor* parent,
5794
                                              FieldDescriptor* result,
5795
                                              bool is_extension,
5796
0
                                              internal::FlatAllocator& alloc) {
5797
0
  const std::string& scope =
5798
0
      (parent == nullptr) ? file_->package() : parent->full_name();
5799
5800
  // We allocate all names in a single array, and dedup them.
5801
  // We remember the indices for the potentially deduped values.
5802
0
  auto all_names = alloc.AllocateFieldNames(
5803
0
      proto.name(), scope,
5804
0
      proto.has_json_name() ? &proto.json_name() : nullptr);
5805
0
  result->all_names_ = all_names.array;
5806
0
  result->lowercase_name_index_ = all_names.lowercase_index;
5807
0
  result->camelcase_name_index_ = all_names.camelcase_index;
5808
0
  result->json_name_index_ = all_names.json_index;
5809
5810
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
5811
5812
0
  result->file_ = file_;
5813
0
  result->number_ = proto.number();
5814
0
  result->is_extension_ = is_extension;
5815
0
  result->is_oneof_ = false;
5816
0
  result->proto3_optional_ = proto.proto3_optional();
5817
5818
0
  if (proto.proto3_optional() &&
5819
0
      FileDescriptorLegacy(file_).syntax() !=
5820
0
          FileDescriptorLegacy::Syntax::SYNTAX_PROTO3) {
5821
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5822
0
             [&] {
5823
0
               return absl::StrCat(
5824
0
                   "The [proto3_optional=true] option may only be set on proto3"
5825
0
                   "fields, not ",
5826
0
                   result->full_name());
5827
0
             });
5828
0
  }
5829
5830
0
  result->has_json_name_ = proto.has_json_name();
5831
5832
  // Some compilers do not allow static_cast directly between two enum types,
5833
  // so we must cast to int first.
5834
0
  result->type_ = static_cast<FieldDescriptor::Type>(
5835
0
      absl::implicit_cast<int>(proto.type()));
5836
0
  result->label_ = static_cast<FieldDescriptor::Label>(
5837
0
      absl::implicit_cast<int>(proto.label()));
5838
5839
0
  if (result->label_ == FieldDescriptor::LABEL_REQUIRED) {
5840
    // An extension cannot have a required field (b/13365836).
5841
0
    if (result->is_extension_) {
5842
0
      AddError(result->full_name(), proto,
5843
               // Error location `TYPE`: we would really like to indicate
5844
               // `LABEL`, but the `ErrorLocation` enum has no entry for this,
5845
               // and we don't necessarily know about all implementations of the
5846
               // `ErrorCollector` interface to extend them to handle the new
5847
               // error location type properly.
5848
0
               DescriptorPool::ErrorCollector::TYPE, [&] {
5849
0
                 return absl::StrCat("The extension ", result->full_name(),
5850
0
                                     " cannot be required.");
5851
0
               });
5852
0
    }
5853
0
  }
5854
5855
  // Some of these may be filled in when cross-linking.
5856
0
  result->containing_type_ = nullptr;
5857
0
  result->type_once_ = nullptr;
5858
0
  result->default_value_enum_ = nullptr;
5859
5860
0
  result->has_default_value_ = proto.has_default_value();
5861
0
  if (proto.has_default_value() && result->is_repeated()) {
5862
0
    AddError(result->full_name(), proto,
5863
0
             DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5864
0
             "Repeated fields can't have default values.");
5865
0
  }
5866
5867
0
  if (proto.has_type()) {
5868
0
    if (proto.has_default_value()) {
5869
0
      char* end_pos = nullptr;
5870
0
      switch (result->cpp_type()) {
5871
0
        case FieldDescriptor::CPPTYPE_INT32:
5872
0
          result->default_value_int32_t_ =
5873
0
              std::strtol(proto.default_value().c_str(), &end_pos, 0);
5874
0
          break;
5875
0
        case FieldDescriptor::CPPTYPE_INT64:
5876
0
          static_assert(sizeof(int64_t) == sizeof(long long),
5877
0
                        "sizeof int64_t is not sizeof long long");
5878
0
          result->default_value_int64_t_ =
5879
0
              std::strtoll(proto.default_value().c_str(), &end_pos, 0);
5880
0
          break;
5881
0
        case FieldDescriptor::CPPTYPE_UINT32:
5882
0
          result->default_value_uint32_t_ =
5883
0
              std::strtoul(proto.default_value().c_str(), &end_pos, 0);
5884
0
          break;
5885
0
        case FieldDescriptor::CPPTYPE_UINT64:
5886
0
          static_assert(sizeof(uint64_t) == sizeof(unsigned long long),
5887
0
                        "sizeof uint64_t is not sizeof unsigned long long");
5888
0
          result->default_value_uint64_t_ =
5889
0
              std::strtoull(proto.default_value().c_str(), &end_pos, 0);
5890
0
          break;
5891
0
        case FieldDescriptor::CPPTYPE_FLOAT:
5892
0
          if (proto.default_value() == "inf") {
5893
0
            result->default_value_float_ =
5894
0
                std::numeric_limits<float>::infinity();
5895
0
          } else if (proto.default_value() == "-inf") {
5896
0
            result->default_value_float_ =
5897
0
                -std::numeric_limits<float>::infinity();
5898
0
          } else if (proto.default_value() == "nan") {
5899
0
            result->default_value_float_ =
5900
0
                std::numeric_limits<float>::quiet_NaN();
5901
0
          } else {
5902
0
            result->default_value_float_ = io::SafeDoubleToFloat(
5903
0
                io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos));
5904
0
          }
5905
0
          break;
5906
0
        case FieldDescriptor::CPPTYPE_DOUBLE:
5907
0
          if (proto.default_value() == "inf") {
5908
0
            result->default_value_double_ =
5909
0
                std::numeric_limits<double>::infinity();
5910
0
          } else if (proto.default_value() == "-inf") {
5911
0
            result->default_value_double_ =
5912
0
                -std::numeric_limits<double>::infinity();
5913
0
          } else if (proto.default_value() == "nan") {
5914
0
            result->default_value_double_ =
5915
0
                std::numeric_limits<double>::quiet_NaN();
5916
0
          } else {
5917
0
            result->default_value_double_ =
5918
0
                io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
5919
0
          }
5920
0
          break;
5921
0
        case FieldDescriptor::CPPTYPE_BOOL:
5922
0
          if (proto.default_value() == "true") {
5923
0
            result->default_value_bool_ = true;
5924
0
          } else if (proto.default_value() == "false") {
5925
0
            result->default_value_bool_ = false;
5926
0
          } else {
5927
0
            AddError(result->full_name(), proto,
5928
0
                     DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5929
0
                     "Boolean default must be true or false.");
5930
0
          }
5931
0
          break;
5932
0
        case FieldDescriptor::CPPTYPE_ENUM:
5933
          // This will be filled in when cross-linking.
5934
0
          result->default_value_enum_ = nullptr;
5935
0
          break;
5936
0
        case FieldDescriptor::CPPTYPE_STRING:
5937
0
          if (result->type() == FieldDescriptor::TYPE_BYTES) {
5938
0
            std::string value;
5939
0
            if (absl::CUnescape(proto.default_value(), &value)) {
5940
0
              result->default_value_string_ = alloc.AllocateStrings(value);
5941
0
            } else {
5942
0
              AddError(result->full_name(), proto,
5943
0
                       DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5944
0
                       "Invalid escaping in default value.");
5945
0
            }
5946
0
          } else {
5947
0
            result->default_value_string_ =
5948
0
                alloc.AllocateStrings(proto.default_value());
5949
0
          }
5950
0
          break;
5951
0
        case FieldDescriptor::CPPTYPE_MESSAGE:
5952
0
          AddError(result->full_name(), proto,
5953
0
                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5954
0
                   "Messages can't have default values.");
5955
0
          result->has_default_value_ = false;
5956
0
          result->default_generated_instance_ = nullptr;
5957
0
          break;
5958
0
      }
5959
5960
0
      if (end_pos != nullptr) {
5961
        // end_pos is only set non-null by the parsers for numeric types,
5962
        // above. This checks that the default was non-empty and had no extra
5963
        // junk after the end of the number.
5964
0
        if (proto.default_value().empty() || *end_pos != '\0') {
5965
0
          AddError(result->full_name(), proto,
5966
0
                   DescriptorPool::ErrorCollector::DEFAULT_VALUE, [&] {
5967
0
                     return absl::StrCat("Couldn't parse default value \"",
5968
0
                                         proto.default_value(), "\".");
5969
0
                   });
5970
0
        }
5971
0
      }
5972
0
    } else {
5973
      // No explicit default value
5974
0
      switch (result->cpp_type()) {
5975
0
        case FieldDescriptor::CPPTYPE_INT32:
5976
0
          result->default_value_int32_t_ = 0;
5977
0
          break;
5978
0
        case FieldDescriptor::CPPTYPE_INT64:
5979
0
          result->default_value_int64_t_ = 0;
5980
0
          break;
5981
0
        case FieldDescriptor::CPPTYPE_UINT32:
5982
0
          result->default_value_uint32_t_ = 0;
5983
0
          break;
5984
0
        case FieldDescriptor::CPPTYPE_UINT64:
5985
0
          result->default_value_uint64_t_ = 0;
5986
0
          break;
5987
0
        case FieldDescriptor::CPPTYPE_FLOAT:
5988
0
          result->default_value_float_ = 0.0f;
5989
0
          break;
5990
0
        case FieldDescriptor::CPPTYPE_DOUBLE:
5991
0
          result->default_value_double_ = 0.0;
5992
0
          break;
5993
0
        case FieldDescriptor::CPPTYPE_BOOL:
5994
0
          result->default_value_bool_ = false;
5995
0
          break;
5996
0
        case FieldDescriptor::CPPTYPE_ENUM:
5997
          // This will be filled in when cross-linking.
5998
0
          result->default_value_enum_ = nullptr;
5999
0
          break;
6000
0
        case FieldDescriptor::CPPTYPE_STRING:
6001
0
          result->default_value_string_ = &internal::GetEmptyString();
6002
0
          break;
6003
0
        case FieldDescriptor::CPPTYPE_MESSAGE:
6004
0
          result->default_generated_instance_ = nullptr;
6005
0
          break;
6006
0
      }
6007
0
    }
6008
0
  }
6009
6010
0
  if (result->number() <= 0) {
6011
0
    message_hints_[parent].RequestHintOnFieldNumbers(
6012
0
        proto, DescriptorPool::ErrorCollector::NUMBER);
6013
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6014
0
             "Field numbers must be positive integers.");
6015
0
  } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) {
6016
    // Only validate that the number is within the valid field range if it is
6017
    // not an extension. Since extension numbers are validated with the
6018
    // extendee's valid set of extension numbers, and those are in turn
6019
    // validated against the max allowed number, the check is unnecessary for
6020
    // extension fields.
6021
    // This avoids cross-linking issues that arise when attempting to check if
6022
    // the extendee is a message_set_wire_format message, which has a higher max
6023
    // on extension numbers.
6024
0
    message_hints_[parent].RequestHintOnFieldNumbers(
6025
0
        proto, DescriptorPool::ErrorCollector::NUMBER);
6026
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6027
0
             [&] {
6028
0
               return absl::Substitute(
6029
0
                   "Field numbers cannot be greater than $0.",
6030
0
                   FieldDescriptor::kMaxNumber);
6031
0
             });
6032
0
  }
6033
6034
0
  if (is_extension) {
6035
0
    if (!proto.has_extendee()) {
6036
0
      AddError(result->full_name(), proto,
6037
0
               DescriptorPool::ErrorCollector::EXTENDEE,
6038
0
               "FieldDescriptorProto.extendee not set for extension field.");
6039
0
    }
6040
6041
0
    result->scope_.extension_scope = parent;
6042
6043
0
    if (proto.has_oneof_index()) {
6044
0
      AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6045
0
               "FieldDescriptorProto.oneof_index should not be set for "
6046
0
               "extensions.");
6047
0
    }
6048
0
  } else {
6049
0
    if (proto.has_extendee()) {
6050
0
      AddError(result->full_name(), proto,
6051
0
               DescriptorPool::ErrorCollector::EXTENDEE,
6052
0
               "FieldDescriptorProto.extendee set for non-extension field.");
6053
0
    }
6054
6055
0
    result->containing_type_ = parent;
6056
6057
0
    if (proto.has_oneof_index()) {
6058
0
      if (proto.oneof_index() < 0 ||
6059
0
          proto.oneof_index() >= parent->oneof_decl_count()) {
6060
0
        AddError(result->full_name(), proto,
6061
0
                 DescriptorPool::ErrorCollector::TYPE, [&] {
6062
0
                   return absl::Substitute(
6063
0
                       "FieldDescriptorProto.oneof_index $0 is "
6064
0
                       "out of range for type \"$1\".",
6065
0
                       proto.oneof_index(), parent->name());
6066
0
                 });
6067
0
      } else {
6068
0
        result->is_oneof_ = true;
6069
0
        result->scope_.containing_oneof =
6070
0
            parent->oneof_decl(proto.oneof_index());
6071
0
      }
6072
0
    }
6073
0
  }
6074
6075
  // Copy options.
6076
0
  result->options_ = nullptr;  // Set to default_instance later if necessary.
6077
0
  if (proto.has_options()) {
6078
0
    AllocateOptions(proto.options(), result,
6079
0
                    FieldDescriptorProto::kOptionsFieldNumber,
6080
0
                    "google.protobuf.FieldOptions", alloc);
6081
0
  }
6082
6083
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6084
0
}
6085
6086
void DescriptorBuilder::BuildExtensionRange(
6087
    const DescriptorProto::ExtensionRange& proto, const Descriptor* parent,
6088
0
    Descriptor::ExtensionRange* result, internal::FlatAllocator& alloc) {
6089
0
  result->start = proto.start();
6090
0
  result->end = proto.end();
6091
0
  if (result->start <= 0) {
6092
0
    message_hints_[parent].RequestHintOnFieldNumbers(
6093
0
        proto, DescriptorPool::ErrorCollector::NUMBER, result->start,
6094
0
        result->end);
6095
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6096
0
             "Extension numbers must be positive integers.");
6097
0
  }
6098
6099
  // Checking of the upper bound of the extension range is deferred until after
6100
  // options interpreting. This allows messages with message_set_wire_format to
6101
  // have extensions beyond FieldDescriptor::kMaxNumber, since the extension
6102
  // numbers are actually used as int32s in the message_set_wire_format.
6103
6104
0
  if (result->start >= result->end) {
6105
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6106
0
             "Extension range end number must be greater than start number.");
6107
0
  }
6108
6109
0
  result->options_ = nullptr;  // Set to default_instance later if necessary.
6110
0
  if (proto.has_options()) {
6111
0
    std::vector<int> options_path;
6112
0
    parent->GetLocationPath(&options_path);
6113
0
    options_path.push_back(DescriptorProto::kExtensionRangeFieldNumber);
6114
    // find index of this extension range in order to compute path
6115
0
    int index;
6116
0
    for (index = 0; parent->extension_ranges_ + index != result; index++) {
6117
0
    }
6118
0
    options_path.push_back(index);
6119
0
    options_path.push_back(DescriptorProto_ExtensionRange::kOptionsFieldNumber);
6120
0
    AllocateOptionsImpl(parent->full_name(), parent->full_name(),
6121
0
                        proto.options(), result, options_path,
6122
0
                        "google.protobuf.ExtensionRangeOptions", alloc);
6123
0
  }
6124
0
}
6125
6126
void DescriptorBuilder::BuildReservedRange(
6127
    const DescriptorProto::ReservedRange& proto, const Descriptor* parent,
6128
0
    Descriptor::ReservedRange* result, internal::FlatAllocator&) {
6129
0
  result->start = proto.start();
6130
0
  result->end = proto.end();
6131
0
  if (result->start <= 0) {
6132
0
    message_hints_[parent].RequestHintOnFieldNumbers(
6133
0
        proto, DescriptorPool::ErrorCollector::NUMBER, result->start,
6134
0
        result->end);
6135
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6136
0
             "Reserved numbers must be positive integers.");
6137
0
  }
6138
0
}
6139
6140
void DescriptorBuilder::BuildReservedRange(
6141
    const EnumDescriptorProto::EnumReservedRange& proto,
6142
    const EnumDescriptor* parent, EnumDescriptor::ReservedRange* result,
6143
0
    internal::FlatAllocator&) {
6144
0
  result->start = proto.start();
6145
0
  result->end = proto.end();
6146
6147
0
  if (result->start > result->end) {
6148
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
6149
0
             "Reserved range end number must be greater than start number.");
6150
0
  }
6151
0
}
6152
6153
void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
6154
                                   Descriptor* parent, OneofDescriptor* result,
6155
0
                                   internal::FlatAllocator& alloc) {
6156
0
  result->all_names_ =
6157
0
      AllocateNameStrings(parent->full_name(), proto.name(), alloc);
6158
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6159
6160
0
  result->containing_type_ = parent;
6161
6162
  // We need to fill these in later.
6163
0
  result->field_count_ = 0;
6164
0
  result->fields_ = nullptr;
6165
0
  result->options_ = nullptr;
6166
6167
  // Copy options.
6168
0
  if (proto.has_options()) {
6169
0
    AllocateOptions(proto.options(), result,
6170
0
                    OneofDescriptorProto::kOptionsFieldNumber,
6171
0
                    "google.protobuf.OneofOptions", alloc);
6172
0
  }
6173
6174
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6175
0
}
6176
6177
void DescriptorBuilder::CheckEnumValueUniqueness(
6178
0
    const EnumDescriptorProto& proto, const EnumDescriptor* result) {
6179
6180
  // Check that enum labels are still unique when we remove the enum prefix from
6181
  // values that have it.
6182
  //
6183
  // This will fail for something like:
6184
  //
6185
  //   enum MyEnum {
6186
  //     MY_ENUM_FOO = 0;
6187
  //     FOO = 1;
6188
  //   }
6189
  //
6190
  // By enforcing this reasonable constraint, we allow code generators to strip
6191
  // the prefix and/or PascalCase it without creating conflicts.  This can lead
6192
  // to much nicer language-specific enums like:
6193
  //
6194
  //   enum NameType {
6195
  //     FirstName = 1,
6196
  //     LastName = 2,
6197
  //   }
6198
  //
6199
  // Instead of:
6200
  //
6201
  //   enum NameType {
6202
  //     NAME_TYPE_FIRST_NAME = 1,
6203
  //     NAME_TYPE_LAST_NAME = 2,
6204
  //   }
6205
0
  PrefixRemover remover(result->name());
6206
0
  absl::flat_hash_map<std::string, const EnumValueDescriptor*> values;
6207
0
  for (int i = 0; i < result->value_count(); i++) {
6208
0
    const EnumValueDescriptor* value = result->value(i);
6209
0
    std::string stripped =
6210
0
        EnumValueToPascalCase(remover.MaybeRemove(value->name()));
6211
0
    auto insert_result = values.try_emplace(stripped, value);
6212
0
    bool inserted = insert_result.second;
6213
6214
    // We don't throw the error if the two conflicting symbols are identical, or
6215
    // if they map to the same number.  In the former case, the normal symbol
6216
    // duplication error will fire so we don't need to (and its error message
6217
    // will make more sense). We allow the latter case so users can create
6218
    // aliases which add or remove the prefix (code generators that do prefix
6219
    // stripping should de-dup the labels in this case).
6220
0
    if (!inserted && insert_result.first->second->name() != value->name() &&
6221
0
        insert_result.first->second->number() != value->number()) {
6222
0
      auto make_error = [&] {
6223
0
        return absl::StrFormat(
6224
0
            "Enum name %s has the same name as %s if you ignore case and strip "
6225
0
            "out the enum name prefix (if any). (If you are using allow_alias, "
6226
0
            "please assign the same numeric value to both enums.)",
6227
0
            value->name(), insert_result.first->second->name());
6228
0
      };
6229
      // There are proto2 enums out there with conflicting names, so to preserve
6230
      // compatibility we issue only a warning for proto2.
6231
0
      if ((pool_->deprecated_legacy_json_field_conflicts_ ||
6232
0
           IsLegacyJsonFieldConflictEnabled(result->options())) &&
6233
0
          FileDescriptorLegacy(result->file()).syntax() ==
6234
0
              FileDescriptorLegacy::Syntax::SYNTAX_PROTO2) {
6235
0
        AddWarning(value->full_name(), proto.value(i),
6236
0
                   DescriptorPool::ErrorCollector::NAME, make_error);
6237
0
        continue;
6238
0
      }
6239
0
      AddError(value->full_name(), proto.value(i),
6240
0
               DescriptorPool::ErrorCollector::NAME, make_error);
6241
0
    }
6242
0
  }
6243
0
}
6244
6245
void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
6246
                                  const Descriptor* parent,
6247
                                  EnumDescriptor* result,
6248
0
                                  internal::FlatAllocator& alloc) {
6249
0
  const std::string& scope =
6250
0
      (parent == nullptr) ? file_->package() : parent->full_name();
6251
6252
0
  result->all_names_ = AllocateNameStrings(scope, proto.name(), alloc);
6253
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6254
0
  result->file_ = file_;
6255
0
  result->containing_type_ = parent;
6256
0
  result->is_placeholder_ = false;
6257
0
  result->is_unqualified_placeholder_ = false;
6258
6259
0
  if (proto.value_size() == 0) {
6260
    // We cannot allow enums with no values because this would mean there
6261
    // would be no valid default value for fields of this type.
6262
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6263
0
             "Enums must contain at least one value.");
6264
0
  }
6265
6266
  // Calculate the continuous sequence of the labels.
6267
  // These can be fast-path'd during lookup and don't need to be added to the
6268
  // tables.
6269
  // We use uint16_t to save space for sequential_value_limit_, so stop before
6270
  // overflowing it. Worst case, we are not taking full advantage on huge
6271
  // enums, but it is unlikely.
6272
0
  for (int i = 0;
6273
0
       i < std::numeric_limits<uint16_t>::max() && i < proto.value_size() &&
6274
       // We do the math in int64_t to avoid overflows.
6275
0
       proto.value(i).number() ==
6276
0
           static_cast<int64_t>(i) + proto.value(0).number();
6277
0
       ++i) {
6278
0
    result->sequential_value_limit_ = i;
6279
0
  }
6280
6281
0
  BUILD_ARRAY(proto, result, value, BuildEnumValue, result);
6282
0
  BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);
6283
6284
  // Copy reserved names.
6285
0
  int reserved_name_count = proto.reserved_name_size();
6286
0
  result->reserved_name_count_ = reserved_name_count;
6287
0
  result->reserved_names_ =
6288
0
      alloc.AllocateArray<const std::string*>(reserved_name_count);
6289
0
  for (int i = 0; i < reserved_name_count; ++i) {
6290
0
    result->reserved_names_[i] =
6291
0
        alloc.AllocateStrings(proto.reserved_name(i));
6292
0
  }
6293
6294
  // Copy options.
6295
0
  result->options_ = nullptr;  // Set to default_instance later if necessary.
6296
0
  if (proto.has_options()) {
6297
0
    AllocateOptions(proto.options(), result,
6298
0
                    EnumDescriptorProto::kOptionsFieldNumber,
6299
0
                    "google.protobuf.EnumOptions", alloc);
6300
0
  }
6301
6302
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6303
6304
0
  for (int i = 0; i < proto.reserved_range_size(); i++) {
6305
0
    const EnumDescriptorProto_EnumReservedRange& range1 =
6306
0
        proto.reserved_range(i);
6307
0
    for (int j = i + 1; j < proto.reserved_range_size(); j++) {
6308
0
      const EnumDescriptorProto_EnumReservedRange& range2 =
6309
0
          proto.reserved_range(j);
6310
0
      if (range1.end() >= range2.start() && range2.end() >= range1.start()) {
6311
0
        AddError(result->full_name(), proto.reserved_range(i),
6312
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
6313
0
                   return absl::Substitute(
6314
0
                       "Reserved range $0 to $1 overlaps with "
6315
0
                       "already-defined range $2 to $3.",
6316
0
                       range2.start(), range2.end(), range1.start(),
6317
0
                       range1.end());
6318
0
                 });
6319
0
      }
6320
0
    }
6321
0
  }
6322
6323
0
  absl::flat_hash_set<absl::string_view> reserved_name_set;
6324
0
  for (const std::string& name : proto.reserved_name()) {
6325
0
    if (!reserved_name_set.insert(name).second) {
6326
0
      AddError(name, proto, DescriptorPool::ErrorCollector::NAME, [&] {
6327
0
        return absl::Substitute("Enum value \"$0\" is reserved multiple times.",
6328
0
                                name);
6329
0
      });
6330
0
    }
6331
0
  }
6332
6333
0
  for (int i = 0; i < result->value_count(); i++) {
6334
0
    const EnumValueDescriptor* value = result->value(i);
6335
0
    for (int j = 0; j < result->reserved_range_count(); j++) {
6336
0
      const EnumDescriptor::ReservedRange* range = result->reserved_range(j);
6337
0
      if (range->start <= value->number() && value->number() <= range->end) {
6338
0
        AddError(value->full_name(), proto.reserved_range(j),
6339
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
6340
0
                   return absl::Substitute(
6341
0
                       "Enum value \"$0\" uses reserved number $1.",
6342
0
                       value->name(), value->number());
6343
0
                 });
6344
0
      }
6345
0
    }
6346
0
    if (reserved_name_set.contains(value->name())) {
6347
0
      AddError(value->full_name(), proto.value(i),
6348
0
               DescriptorPool::ErrorCollector::NAME, [&] {
6349
0
                 return absl::Substitute("Enum value \"$0\" is reserved.",
6350
0
                                         value->name());
6351
0
               });
6352
0
    }
6353
0
  }
6354
0
}
6355
6356
void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto,
6357
                                       const EnumDescriptor* parent,
6358
                                       EnumValueDescriptor* result,
6359
0
                                       internal::FlatAllocator& alloc) {
6360
  // Note:  full_name for enum values is a sibling to the parent's name, not a
6361
  //   child of it.
6362
0
  std::string full_name;
6363
0
  size_t scope_len = parent->full_name().size() - parent->name().size();
6364
0
  full_name.reserve(scope_len + proto.name().size());
6365
0
  full_name.append(parent->full_name().data(), scope_len);
6366
0
  full_name.append(proto.name());
6367
6368
0
  result->all_names_ =
6369
0
      alloc.AllocateStrings(proto.name(), std::move(full_name));
6370
0
  result->number_ = proto.number();
6371
0
  result->type_ = parent;
6372
6373
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6374
6375
  // Copy options.
6376
0
  result->options_ = nullptr;  // Set to default_instance later if necessary.
6377
0
  if (proto.has_options()) {
6378
0
    AllocateOptions(proto.options(), result,
6379
0
                    EnumValueDescriptorProto::kOptionsFieldNumber,
6380
0
                    "google.protobuf.EnumValueOptions", alloc);
6381
0
  }
6382
6383
  // Again, enum values are weird because we makes them appear as siblings
6384
  // of the enum type instead of children of it.  So, we use
6385
  // parent->containing_type() as the value's parent.
6386
0
  bool added_to_outer_scope =
6387
0
      AddSymbol(result->full_name(), parent->containing_type(), result->name(),
6388
0
                proto, Symbol::EnumValue(result, 0));
6389
6390
  // However, we also want to be able to search for values within a single
6391
  // enum type, so we add it as a child of the enum type itself, too.
6392
  // Note:  This could fail, but if it does, the error has already been
6393
  //   reported by the above AddSymbol() call, so we ignore the return code.
6394
0
  bool added_to_inner_scope = file_tables_->AddAliasUnderParent(
6395
0
      parent, result->name(), Symbol::EnumValue(result, 1));
6396
6397
0
  if (added_to_inner_scope && !added_to_outer_scope) {
6398
    // This value did not conflict with any values defined in the same enum,
6399
    // but it did conflict with some other symbol defined in the enum type's
6400
    // scope.  Let's print an additional error to explain this.
6401
0
    std::string outer_scope;
6402
0
    if (parent->containing_type() == nullptr) {
6403
0
      outer_scope = file_->package();
6404
0
    } else {
6405
0
      outer_scope = parent->containing_type()->full_name();
6406
0
    }
6407
6408
0
    if (outer_scope.empty()) {
6409
0
      outer_scope = "the global scope";
6410
0
    } else {
6411
0
      outer_scope = absl::StrCat("\"", outer_scope, "\"");
6412
0
    }
6413
6414
0
    AddError(
6415
0
        result->full_name(), proto, DescriptorPool::ErrorCollector::NAME, [&] {
6416
0
          return absl::StrCat(
6417
0
              "Note that enum values use C++ scoping rules, meaning that "
6418
0
              "enum values are siblings of their type, not children of it.  "
6419
0
              "Therefore, \"",
6420
0
              result->name(), "\" must be unique within ", outer_scope,
6421
0
              ", not just within \"", parent->name(), "\".");
6422
0
        });
6423
0
  }
6424
6425
  // An enum is allowed to define two numbers that refer to the same value.
6426
  // FindValueByNumber() should return the first such value, so we simply
6427
  // ignore AddEnumValueByNumber()'s return code.
6428
0
  file_tables_->AddEnumValueByNumber(result);
6429
0
}
6430
6431
void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
6432
                                     const void* /* dummy */,
6433
                                     ServiceDescriptor* result,
6434
0
                                     internal::FlatAllocator& alloc) {
6435
0
  result->all_names_ =
6436
0
      AllocateNameStrings(file_->package(), proto.name(), alloc);
6437
0
  result->file_ = file_;
6438
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6439
6440
0
  BUILD_ARRAY(proto, result, method, BuildMethod, result);
6441
6442
  // Copy options.
6443
0
  result->options_ = nullptr;  // Set to default_instance later if necessary.
6444
0
  if (proto.has_options()) {
6445
0
    AllocateOptions(proto.options(), result,
6446
0
                    ServiceDescriptorProto::kOptionsFieldNumber,
6447
0
                    "google.protobuf.ServiceOptions", alloc);
6448
0
  }
6449
6450
0
  AddSymbol(result->full_name(), nullptr, result->name(), proto,
6451
0
            Symbol(result));
6452
0
}
6453
6454
void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto,
6455
                                    const ServiceDescriptor* parent,
6456
                                    MethodDescriptor* result,
6457
0
                                    internal::FlatAllocator& alloc) {
6458
0
  result->service_ = parent;
6459
0
  result->all_names_ =
6460
0
      AllocateNameStrings(parent->full_name(), proto.name(), alloc);
6461
6462
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6463
6464
  // These will be filled in when cross-linking.
6465
0
  result->input_type_.Init();
6466
0
  result->output_type_.Init();
6467
6468
  // Copy options.
6469
0
  result->options_ = nullptr;  // Set to default_instance later if necessary.
6470
0
  if (proto.has_options()) {
6471
0
    AllocateOptions(proto.options(), result,
6472
0
                    MethodDescriptorProto::kOptionsFieldNumber,
6473
0
                    "google.protobuf.MethodOptions", alloc);
6474
0
  }
6475
6476
0
  result->client_streaming_ = proto.client_streaming();
6477
0
  result->server_streaming_ = proto.server_streaming();
6478
6479
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6480
0
}
6481
6482
#undef BUILD_ARRAY
6483
6484
// -------------------------------------------------------------------
6485
6486
void DescriptorBuilder::CrossLinkFile(FileDescriptor* file,
6487
0
                                      const FileDescriptorProto& proto) {
6488
0
  if (file->options_ == nullptr) {
6489
0
    file->options_ = &FileOptions::default_instance();
6490
0
  }
6491
6492
0
  for (int i = 0; i < file->message_type_count(); i++) {
6493
0
    CrossLinkMessage(&file->message_types_[i], proto.message_type(i));
6494
0
  }
6495
6496
0
  for (int i = 0; i < file->extension_count(); i++) {
6497
0
    CrossLinkField(&file->extensions_[i], proto.extension(i));
6498
0
  }
6499
6500
0
  for (int i = 0; i < file->enum_type_count(); i++) {
6501
0
    CrossLinkEnum(&file->enum_types_[i], proto.enum_type(i));
6502
0
  }
6503
6504
0
  for (int i = 0; i < file->service_count(); i++) {
6505
0
    CrossLinkService(&file->services_[i], proto.service(i));
6506
0
  }
6507
0
}
6508
6509
void DescriptorBuilder::CrossLinkMessage(Descriptor* message,
6510
0
                                         const DescriptorProto& proto) {
6511
0
  if (message->options_ == nullptr) {
6512
0
    message->options_ = &MessageOptions::default_instance();
6513
0
  }
6514
6515
0
  for (int i = 0; i < message->nested_type_count(); i++) {
6516
0
    CrossLinkMessage(&message->nested_types_[i], proto.nested_type(i));
6517
0
  }
6518
6519
0
  for (int i = 0; i < message->enum_type_count(); i++) {
6520
0
    CrossLinkEnum(&message->enum_types_[i], proto.enum_type(i));
6521
0
  }
6522
6523
0
  for (int i = 0; i < message->field_count(); i++) {
6524
0
    CrossLinkField(&message->fields_[i], proto.field(i));
6525
0
  }
6526
6527
0
  for (int i = 0; i < message->extension_count(); i++) {
6528
0
    CrossLinkField(&message->extensions_[i], proto.extension(i));
6529
0
  }
6530
6531
0
  for (int i = 0; i < message->extension_range_count(); i++) {
6532
0
    CrossLinkExtensionRange(&message->extension_ranges_[i],
6533
0
                            proto.extension_range(i));
6534
0
  }
6535
6536
  // Set up field array for each oneof.
6537
6538
  // First count the number of fields per oneof.
6539
0
  for (int i = 0; i < message->field_count(); i++) {
6540
0
    const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
6541
0
    if (oneof_decl != nullptr) {
6542
      // Make sure fields belonging to the same oneof are defined consecutively.
6543
      // This enables optimizations in codegens and reflection libraries to
6544
      // skip fields in the oneof group, as only one of the field can be set.
6545
      // Note that field_count() returns how many fields in this oneof we have
6546
      // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is
6547
      // safe.
6548
0
      if (oneof_decl->field_count() > 0 &&
6549
0
          message->field(i - 1)->containing_oneof() != oneof_decl) {
6550
0
        AddError(
6551
0
            absl::StrCat(message->full_name(), ".",
6552
0
                         message->field(i - 1)->name()),
6553
0
            proto.field(i - 1), DescriptorPool::ErrorCollector::TYPE, [&] {
6554
0
              return absl::Substitute(
6555
0
                  "Fields in the same oneof must be defined consecutively. "
6556
0
                  "\"$0\" cannot be defined before the completion of the "
6557
0
                  "\"$1\" oneof definition.",
6558
0
                  message->field(i - 1)->name(), oneof_decl->name());
6559
0
            });
6560
0
      }
6561
      // Must go through oneof_decls_ array to get a non-const version of the
6562
      // OneofDescriptor.
6563
0
      auto& out_oneof_decl = message->oneof_decls_[oneof_decl->index()];
6564
0
      if (out_oneof_decl.field_count_ == 0) {
6565
0
        out_oneof_decl.fields_ = message->field(i);
6566
0
      }
6567
6568
0
      if (!had_errors_) {
6569
        // Verify that they are contiguous.
6570
        // This is assumed by OneofDescriptor::field(i).
6571
        // But only if there are no errors.
6572
0
        ABSL_CHECK_EQ(out_oneof_decl.fields_ + out_oneof_decl.field_count_,
6573
0
                      message->field(i));
6574
0
      }
6575
0
      ++out_oneof_decl.field_count_;
6576
0
    }
6577
0
  }
6578
6579
  // Then verify the sizes.
6580
0
  for (int i = 0; i < message->oneof_decl_count(); i++) {
6581
0
    OneofDescriptor* oneof_decl = &message->oneof_decls_[i];
6582
6583
0
    if (oneof_decl->field_count() == 0) {
6584
0
      AddError(absl::StrCat(message->full_name(), ".", oneof_decl->name()),
6585
0
               proto.oneof_decl(i), DescriptorPool::ErrorCollector::NAME,
6586
0
               "Oneof must have at least one field.");
6587
0
    }
6588
6589
0
    if (oneof_decl->options_ == nullptr) {
6590
0
      oneof_decl->options_ = &OneofOptions::default_instance();
6591
0
    }
6592
0
  }
6593
6594
0
  for (int i = 0; i < message->field_count(); i++) {
6595
0
    const FieldDescriptor* field = message->field(i);
6596
0
    if (field->proto3_optional_) {
6597
0
      if (!field->containing_oneof() ||
6598
0
          !OneofDescriptorLegacy(field->containing_oneof()).is_synthetic()) {
6599
0
        AddError(message->full_name(), proto.field(i),
6600
0
                 DescriptorPool::ErrorCollector::OTHER,
6601
0
                 "Fields with proto3_optional set must be "
6602
0
                 "a member of a one-field oneof");
6603
0
      }
6604
0
    }
6605
0
  }
6606
6607
  // Synthetic oneofs must be last.
6608
0
  int first_synthetic = -1;
6609
0
  for (int i = 0; i < message->oneof_decl_count(); i++) {
6610
0
    const OneofDescriptor* oneof = message->oneof_decl(i);
6611
0
    if (OneofDescriptorLegacy(oneof).is_synthetic()) {
6612
0
      if (first_synthetic == -1) {
6613
0
        first_synthetic = i;
6614
0
      }
6615
0
    } else {
6616
0
      if (first_synthetic != -1) {
6617
0
        AddError(message->full_name(), proto.oneof_decl(i),
6618
0
                 DescriptorPool::ErrorCollector::OTHER,
6619
0
                 "Synthetic oneofs must be after all other oneofs");
6620
0
      }
6621
0
    }
6622
0
  }
6623
6624
0
  if (first_synthetic == -1) {
6625
0
    message->real_oneof_decl_count_ = message->oneof_decl_count_;
6626
0
  } else {
6627
0
    message->real_oneof_decl_count_ = first_synthetic;
6628
0
  }
6629
0
}
6630
6631
void DescriptorBuilder::CrossLinkExtensionRange(
6632
    Descriptor::ExtensionRange* range,
6633
0
    const DescriptorProto::ExtensionRange& /*proto*/) {
6634
0
  if (range->options_ == nullptr) {
6635
0
    range->options_ = &ExtensionRangeOptions::default_instance();
6636
0
  }
6637
0
}
6638
6639
6640
void DescriptorBuilder::CheckExtensionDeclaration(
6641
    const FieldDescriptor& field, const FieldDescriptorProto& proto,
6642
    absl::string_view declared_full_name, absl::string_view declared_type_name,
6643
0
    bool is_repeated) {
6644
6645
0
  if (!declared_full_name.empty()) {
6646
0
    std::string actual_full_name = absl::StrCat(".", field.full_name());
6647
0
    if (declared_full_name != actual_full_name) {
6648
0
      AddError(field.full_name(), proto,
6649
0
               DescriptorPool::ErrorCollector::EXTENDEE, [&] {
6650
0
                 return absl::Substitute(
6651
0
                     "\"$0\" extension field $1 is expected to have field name "
6652
0
                     "\"$2\", not \"$3\".",
6653
0
                     field.containing_type()->full_name(), field.number(),
6654
0
                     declared_full_name, actual_full_name);
6655
0
               });
6656
0
    }
6657
0
  }
6658
6659
0
  if (is_repeated != field.is_repeated()) {
6660
0
    AddError(field.full_name(), proto, DescriptorPool::ErrorCollector::EXTENDEE,
6661
0
             [&] {
6662
0
               return absl::Substitute(
6663
0
                   "\"$0\" extension field $1 is expected to be $2.",
6664
0
                   field.containing_type()->full_name(), field.number(),
6665
0
                   is_repeated ? "repeated" : "optional");
6666
0
             });
6667
0
  }
6668
0
}
6669
6670
void DescriptorBuilder::CrossLinkField(FieldDescriptor* field,
6671
0
                                       const FieldDescriptorProto& proto) {
6672
0
  if (field->options_ == nullptr) {
6673
0
    field->options_ = &FieldOptions::default_instance();
6674
0
  }
6675
6676
0
  if (proto.has_extendee()) {
6677
0
    Symbol extendee =
6678
0
        LookupSymbol(proto.extendee(), field->full_name(),
6679
0
                     DescriptorPool::PLACEHOLDER_EXTENDABLE_MESSAGE);
6680
0
    if (extendee.IsNull()) {
6681
0
      AddNotDefinedError(field->full_name(), proto,
6682
0
                         DescriptorPool::ErrorCollector::EXTENDEE,
6683
0
                         proto.extendee());
6684
0
      return;
6685
0
    } else if (extendee.type() != Symbol::MESSAGE) {
6686
0
      AddError(field->full_name(), proto,
6687
0
               DescriptorPool::ErrorCollector::EXTENDEE, [&] {
6688
0
                 return absl::StrCat("\"", proto.extendee(),
6689
0
                                     "\" is not a message type.");
6690
0
               });
6691
0
      return;
6692
0
    }
6693
0
    field->containing_type_ = extendee.descriptor();
6694
6695
0
    const Descriptor::ExtensionRange* extension_range =
6696
0
        field->containing_type()->FindExtensionRangeContainingNumber(
6697
0
            field->number());
6698
6699
0
    if (extension_range == nullptr) {
6700
      // Set of valid extension numbers for MessageSet is different (< 2^32)
6701
      // from other extendees (< 2^29). If unknown deps are allowed, we may not
6702
      // have that information, and wrongly deem the extension as invalid.
6703
0
      auto skip_check = get_allow_unknown(pool_) &&
6704
0
                        proto.extendee() == "google.protobuf.bridge.MessageSet";
6705
0
      if (!skip_check) {
6706
0
        AddError(field->full_name(), proto,
6707
0
                 DescriptorPool::ErrorCollector::NUMBER, [&] {
6708
0
                   return absl::Substitute(
6709
0
                       "\"$0\" does not declare $1 as an "
6710
0
                       "extension number.",
6711
0
                       field->containing_type()->full_name(), field->number());
6712
0
                 });
6713
0
      }
6714
0
    }
6715
0
  }
6716
6717
0
  if (field->containing_oneof() != nullptr) {
6718
0
    if (field->label() != FieldDescriptor::LABEL_OPTIONAL) {
6719
      // Note that this error will never happen when parsing .proto files.
6720
      // It can only happen if you manually construct a FileDescriptorProto
6721
      // that is incorrect.
6722
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6723
0
               "Fields of oneofs must themselves have label LABEL_OPTIONAL.");
6724
0
    }
6725
0
  }
6726
6727
0
  if (proto.has_type_name()) {
6728
    // Assume we are expecting a message type unless the proto contains some
6729
    // evidence that it expects an enum type.  This only makes a difference if
6730
    // we end up creating a placeholder.
6731
0
    bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) ||
6732
0
                          proto.has_default_value();
6733
6734
    // In case of weak fields we force building the dependency. We need to know
6735
    // if the type exist or not. If it doesn't exist we substitute Empty which
6736
    // should only be done if the type can't be found in the generated pool.
6737
    // TODO(gerbens) Ideally we should query the database directly to check
6738
    // if weak fields exist or not so that we don't need to force building
6739
    // weak dependencies. However the name lookup rules for symbols are
6740
    // somewhat complicated, so I defer it too another CL.
6741
0
    bool is_weak = !pool_->enforce_weak_ && proto.options().weak();
6742
0
    bool is_lazy = pool_->lazily_build_dependencies_ && !is_weak;
6743
6744
0
    Symbol type =
6745
0
        LookupSymbol(proto.type_name(), field->full_name(),
6746
0
                     expecting_enum ? DescriptorPool::PLACEHOLDER_ENUM
6747
0
                                    : DescriptorPool::PLACEHOLDER_MESSAGE,
6748
0
                     LOOKUP_TYPES, !is_lazy);
6749
6750
0
    if (type.IsNull()) {
6751
0
      if (is_lazy) {
6752
        // Save the symbol names for later for lookup, and allocate the once
6753
        // object needed for the accessors.
6754
0
        const std::string& name = proto.type_name();
6755
6756
0
        int name_sizes = static_cast<int>(name.size() + 1 +
6757
0
                                          proto.default_value().size() + 1);
6758
6759
0
        field->type_once_ = ::new (tables_->AllocateBytes(
6760
0
            static_cast<int>(sizeof(absl::once_flag)) + name_sizes))
6761
0
            absl::once_flag{};
6762
0
        char* names = reinterpret_cast<char*>(field->type_once_ + 1);
6763
6764
0
        memcpy(names, name.c_str(), name.size() + 1);
6765
0
        memcpy(names + name.size() + 1, proto.default_value().c_str(),
6766
0
               proto.default_value().size() + 1);
6767
6768
        // AddFieldByNumber and AddExtension are done later in this function,
6769
        // and can/must be done if the field type was not found. The related
6770
        // error checking is not necessary when in lazily_build_dependencies_
6771
        // mode, and can't be done without building the type's descriptor,
6772
        // which we don't want to do.
6773
0
        file_tables_->AddFieldByNumber(field);
6774
0
        if (field->is_extension()) {
6775
0
          tables_->AddExtension(field);
6776
0
        }
6777
0
        return;
6778
0
      } else {
6779
        // If the type is a weak type, we change the type to a google.protobuf.Empty
6780
        // field.
6781
0
        if (is_weak) {
6782
0
          type = FindSymbol(kNonLinkedWeakMessageReplacementName);
6783
0
        }
6784
0
        if (type.IsNull()) {
6785
0
          AddNotDefinedError(field->full_name(), proto,
6786
0
                             DescriptorPool::ErrorCollector::TYPE,
6787
0
                             proto.type_name());
6788
0
          return;
6789
0
        }
6790
0
      }
6791
0
    }
6792
6793
0
    if (!proto.has_type()) {
6794
      // Choose field type based on symbol.
6795
0
      if (type.type() == Symbol::MESSAGE) {
6796
0
        field->type_ = FieldDescriptor::TYPE_MESSAGE;
6797
0
      } else if (type.type() == Symbol::ENUM) {
6798
0
        field->type_ = FieldDescriptor::TYPE_ENUM;
6799
0
      } else {
6800
0
        AddError(field->full_name(), proto,
6801
0
                 DescriptorPool::ErrorCollector::TYPE, [&] {
6802
0
                   return absl::StrCat("\"", proto.type_name(),
6803
0
                                       "\" is not a type.");
6804
0
                 });
6805
0
        return;
6806
0
      }
6807
0
    }
6808
6809
0
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
6810
0
      field->type_descriptor_.message_type = type.descriptor();
6811
0
      if (field->type_descriptor_.message_type == nullptr) {
6812
0
        AddError(field->full_name(), proto,
6813
0
                 DescriptorPool::ErrorCollector::TYPE, [&] {
6814
0
                   return absl::StrCat("\"", proto.type_name(),
6815
0
                                       "\" is not a message type.");
6816
0
                 });
6817
0
        return;
6818
0
      }
6819
6820
0
      if (field->has_default_value()) {
6821
0
        AddError(field->full_name(), proto,
6822
0
                 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
6823
0
                 "Messages can't have default values.");
6824
0
      }
6825
0
    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
6826
0
      field->type_descriptor_.enum_type = type.enum_descriptor();
6827
0
      if (field->type_descriptor_.enum_type == nullptr) {
6828
0
        AddError(field->full_name(), proto,
6829
0
                 DescriptorPool::ErrorCollector::TYPE, [&] {
6830
0
                   return absl::StrCat("\"", proto.type_name(),
6831
0
                                       "\" is not an enum type.");
6832
0
                 });
6833
0
        return;
6834
0
      }
6835
6836
0
      if (field->enum_type()->is_placeholder_) {
6837
        // We can't look up default values for placeholder types.  We'll have
6838
        // to just drop them.
6839
0
        field->has_default_value_ = false;
6840
0
      }
6841
6842
0
      if (field->has_default_value()) {
6843
        // Ensure that the default value is an identifier. Parser cannot always
6844
        // verify this because it does not have complete type information.
6845
        // N.B. that this check yields better error messages but is not
6846
        // necessary for correctness (an enum symbol must be a valid identifier
6847
        // anyway), only for better errors.
6848
0
        if (!io::Tokenizer::IsIdentifier(proto.default_value())) {
6849
0
          AddError(field->full_name(), proto,
6850
0
                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
6851
0
                   "Default value for an enum field must be an identifier.");
6852
0
        } else {
6853
          // We can't just use field->enum_type()->FindValueByName() here
6854
          // because that locks the pool's mutex, which we have already locked
6855
          // at this point.
6856
0
          const EnumValueDescriptor* default_value =
6857
0
              LookupSymbolNoPlaceholder(proto.default_value(),
6858
0
                                        field->enum_type()->full_name())
6859
0
                  .enum_value_descriptor();
6860
6861
0
          if (default_value != nullptr &&
6862
0
              default_value->type() == field->enum_type()) {
6863
0
            field->default_value_enum_ = default_value;
6864
0
          } else {
6865
0
            AddError(field->full_name(), proto,
6866
0
                     DescriptorPool::ErrorCollector::DEFAULT_VALUE, [&] {
6867
0
                       return absl::StrCat("Enum type \"",
6868
0
                                           field->enum_type()->full_name(),
6869
0
                                           "\" has no value named \"",
6870
0
                                           proto.default_value(), "\".");
6871
0
                     });
6872
0
          }
6873
0
        }
6874
0
      } else if (field->enum_type()->value_count() > 0) {
6875
        // All enums must have at least one value, or we would have reported
6876
        // an error elsewhere.  We use the first defined value as the default
6877
        // if a default is not explicitly defined.
6878
0
        field->default_value_enum_ = field->enum_type()->value(0);
6879
0
      }
6880
0
    } else {
6881
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6882
0
               "Field with primitive type has type_name.");
6883
0
    }
6884
0
  } else {
6885
0
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
6886
0
        field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
6887
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6888
0
               "Field with message or enum type missing type_name.");
6889
0
    }
6890
0
  }
6891
6892
  // Add the field to the fields-by-number table.
6893
  // Note:  We have to do this *after* cross-linking because extensions do not
6894
  // know their containing type until now. If we're in
6895
  // lazily_build_dependencies_ mode, we're guaranteed there's no errors, so no
6896
  // risk to calling containing_type() or other accessors that will build
6897
  // dependencies.
6898
0
  if (!file_tables_->AddFieldByNumber(field)) {
6899
0
    const FieldDescriptor* conflicting_field = file_tables_->FindFieldByNumber(
6900
0
        field->containing_type(), field->number());
6901
0
    std::string containing_type_name =
6902
0
        field->containing_type() == nullptr
6903
0
            ? "unknown"
6904
0
            : field->containing_type()->full_name();
6905
0
    if (field->is_extension()) {
6906
0
      AddError(field->full_name(), proto,
6907
0
               DescriptorPool::ErrorCollector::NUMBER, [&] {
6908
0
                 return absl::Substitute(
6909
0
                     "Extension number $0 has already been used "
6910
0
                     "in \"$1\" by extension \"$2\".",
6911
0
                     field->number(), containing_type_name,
6912
0
                     conflicting_field->full_name());
6913
0
               });
6914
0
    } else {
6915
0
      AddError(field->full_name(), proto,
6916
0
               DescriptorPool::ErrorCollector::NUMBER, [&] {
6917
0
                 return absl::Substitute(
6918
0
                     "Field number $0 has already been used in "
6919
0
                     "\"$1\" by field \"$2\".",
6920
0
                     field->number(), containing_type_name,
6921
0
                     conflicting_field->name());
6922
0
               });
6923
0
    }
6924
0
  } else {
6925
0
    if (field->is_extension()) {
6926
0
      if (!tables_->AddExtension(field)) {
6927
0
        auto make_error = [&] {
6928
0
          const FieldDescriptor* conflicting_field =
6929
0
              tables_->FindExtension(field->containing_type(), field->number());
6930
0
          std::string containing_type_name =
6931
0
              field->containing_type() == nullptr
6932
0
                  ? "unknown"
6933
0
                  : field->containing_type()->full_name();
6934
0
          return absl::Substitute(
6935
0
              "Extension number $0 has already been used in \"$1\" by "
6936
0
              "extension "
6937
0
              "\"$2\" defined in $3.",
6938
0
              field->number(), containing_type_name,
6939
0
              conflicting_field->full_name(),
6940
0
              conflicting_field->file()->name());
6941
0
        };
6942
        // Conflicting extension numbers should be an error. However, before
6943
        // turning this into an error we need to fix all existing broken
6944
        // protos first.
6945
        // TODO(xiaofeng): Change this to an error.
6946
0
        AddWarning(field->full_name(), proto,
6947
0
                   DescriptorPool::ErrorCollector::NUMBER, make_error);
6948
0
      }
6949
0
    }
6950
0
  }
6951
0
}
6952
6953
void DescriptorBuilder::CrossLinkEnum(EnumDescriptor* enum_type,
6954
0
                                      const EnumDescriptorProto& proto) {
6955
0
  if (enum_type->options_ == nullptr) {
6956
0
    enum_type->options_ = &EnumOptions::default_instance();
6957
0
  }
6958
6959
0
  for (int i = 0; i < enum_type->value_count(); i++) {
6960
0
    CrossLinkEnumValue(&enum_type->values_[i], proto.value(i));
6961
0
  }
6962
0
}
6963
6964
void DescriptorBuilder::CrossLinkEnumValue(
6965
    EnumValueDescriptor* enum_value,
6966
0
    const EnumValueDescriptorProto& /* proto */) {
6967
0
  if (enum_value->options_ == nullptr) {
6968
0
    enum_value->options_ = &EnumValueOptions::default_instance();
6969
0
  }
6970
0
}
6971
6972
void DescriptorBuilder::CrossLinkService(ServiceDescriptor* service,
6973
0
                                         const ServiceDescriptorProto& proto) {
6974
0
  if (service->options_ == nullptr) {
6975
0
    service->options_ = &ServiceOptions::default_instance();
6976
0
  }
6977
6978
0
  for (int i = 0; i < service->method_count(); i++) {
6979
0
    CrossLinkMethod(&service->methods_[i], proto.method(i));
6980
0
  }
6981
0
}
6982
6983
void DescriptorBuilder::CrossLinkMethod(MethodDescriptor* method,
6984
0
                                        const MethodDescriptorProto& proto) {
6985
0
  if (method->options_ == nullptr) {
6986
0
    method->options_ = &MethodOptions::default_instance();
6987
0
  }
6988
6989
0
  Symbol input_type =
6990
0
      LookupSymbol(proto.input_type(), method->full_name(),
6991
0
                   DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
6992
0
                   !pool_->lazily_build_dependencies_);
6993
0
  if (input_type.IsNull()) {
6994
0
    if (!pool_->lazily_build_dependencies_) {
6995
0
      AddNotDefinedError(method->full_name(), proto,
6996
0
                         DescriptorPool::ErrorCollector::INPUT_TYPE,
6997
0
                         proto.input_type());
6998
0
    } else {
6999
0
      method->input_type_.SetLazy(proto.input_type(), file_);
7000
0
    }
7001
0
  } else if (input_type.type() != Symbol::MESSAGE) {
7002
0
    AddError(method->full_name(), proto,
7003
0
             DescriptorPool::ErrorCollector::INPUT_TYPE, [&] {
7004
0
               return absl::StrCat("\"", proto.input_type(),
7005
0
                                   "\" is not a message type.");
7006
0
             });
7007
0
  } else {
7008
0
    method->input_type_.Set(input_type.descriptor());
7009
0
  }
7010
7011
0
  Symbol output_type =
7012
0
      LookupSymbol(proto.output_type(), method->full_name(),
7013
0
                   DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
7014
0
                   !pool_->lazily_build_dependencies_);
7015
0
  if (output_type.IsNull()) {
7016
0
    if (!pool_->lazily_build_dependencies_) {
7017
0
      AddNotDefinedError(method->full_name(), proto,
7018
0
                         DescriptorPool::ErrorCollector::OUTPUT_TYPE,
7019
0
                         proto.output_type());
7020
0
    } else {
7021
0
      method->output_type_.SetLazy(proto.output_type(), file_);
7022
0
    }
7023
0
  } else if (output_type.type() != Symbol::MESSAGE) {
7024
0
    AddError(method->full_name(), proto,
7025
0
             DescriptorPool::ErrorCollector::OUTPUT_TYPE, [&] {
7026
0
               return absl::StrCat("\"", proto.output_type(),
7027
0
                                   "\" is not a message type.");
7028
0
             });
7029
0
  } else {
7030
0
    method->output_type_.Set(output_type.descriptor());
7031
0
  }
7032
0
}
7033
7034
void DescriptorBuilder::SuggestFieldNumbers(FileDescriptor* file,
7035
0
                                            const FileDescriptorProto& proto) {
7036
0
  for (int message_index = 0; message_index < file->message_type_count();
7037
0
       message_index++) {
7038
0
    const Descriptor* message = &file->message_types_[message_index];
7039
0
    auto hints_it = message_hints_.find(message);
7040
0
    if (hints_it == message_hints_.end()) continue;
7041
0
    auto* hints = &hints_it->second;
7042
0
    constexpr int kMaxSuggestions = 3;
7043
0
    int fields_to_suggest = std::min(kMaxSuggestions, hints->fields_to_suggest);
7044
0
    if (fields_to_suggest <= 0) continue;
7045
0
    struct Range {
7046
0
      int from;
7047
0
      int to;
7048
0
    };
7049
0
    std::vector<Range> used_ordinals;
7050
0
    auto add_ordinal = [&](int ordinal) {
7051
0
      if (ordinal <= 0 || ordinal > FieldDescriptor::kMaxNumber) return;
7052
0
      if (!used_ordinals.empty() &&
7053
0
          ordinal == used_ordinals.back().to) {
7054
0
        used_ordinals.back().to = ordinal + 1;
7055
0
      } else {
7056
0
        used_ordinals.push_back({ordinal, ordinal + 1});
7057
0
      }
7058
0
    };
7059
0
    auto add_range = [&](int from, int to) {
7060
0
      from = std::max(0, std::min(FieldDescriptor::kMaxNumber + 1, from));
7061
0
      to = std::max(0, std::min(FieldDescriptor::kMaxNumber + 1, to));
7062
0
      if (from >= to) return;
7063
0
      used_ordinals.push_back({from, to});
7064
0
    };
7065
0
    for (int i = 0; i < message->field_count(); i++) {
7066
0
      add_ordinal(message->field(i)->number());
7067
0
    }
7068
0
    for (int i = 0; i < message->extension_count(); i++) {
7069
0
      add_ordinal(message->extension(i)->number());
7070
0
    }
7071
0
    for (int i = 0; i < message->reserved_range_count(); i++) {
7072
0
      auto range = message->reserved_range(i);
7073
0
      add_range(range->start, range->end);
7074
0
    }
7075
0
    for (int i = 0; i < message->extension_range_count(); i++) {
7076
0
      auto range = message->extension_range(i);
7077
0
      add_range(range->start, range->end);
7078
0
    }
7079
0
    used_ordinals.push_back(
7080
0
        {FieldDescriptor::kMaxNumber, FieldDescriptor::kMaxNumber + 1});
7081
0
    used_ordinals.push_back({FieldDescriptor::kFirstReservedNumber,
7082
0
                             FieldDescriptor::kLastReservedNumber});
7083
0
    std::sort(used_ordinals.begin(), used_ordinals.end(),
7084
0
              [](Range lhs, Range rhs) {
7085
0
                return std::tie(lhs.from, lhs.to) < std::tie(rhs.from, rhs.to);
7086
0
              });
7087
0
    int current_ordinal = 1;
7088
0
    if (hints->first_reason) {
7089
0
      auto make_error = [&] {
7090
0
        std::stringstream id_list;
7091
0
        id_list << "Suggested field numbers for " << message->full_name()
7092
0
                << ": ";
7093
0
        const char* separator = "";
7094
0
        for (auto& current_range : used_ordinals) {
7095
0
          while (current_ordinal < current_range.from &&
7096
0
                 fields_to_suggest > 0) {
7097
0
            id_list << separator << current_ordinal++;
7098
0
            separator = ", ";
7099
0
            fields_to_suggest--;
7100
0
          }
7101
0
          if (fields_to_suggest == 0) break;
7102
0
          current_ordinal = std::max(current_ordinal, current_range.to);
7103
0
        }
7104
0
        return id_list.str();
7105
0
      };
7106
0
      AddError(message->full_name(), *hints->first_reason,
7107
0
               hints->first_reason_location, make_error);
7108
0
    }
7109
0
  }
7110
0
}
7111
7112
// -------------------------------------------------------------------
7113
7114
#define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type) \
7115
0
  for (int i = 0; i < descriptor->array_name##_count(); ++i) {    \
7116
0
    Validate##type##Options(descriptor->array_name##s_ + i,       \
7117
0
                            proto.array_name(i));                 \
7118
0
  }
7119
7120
// Determine if the file uses optimize_for = LITE_RUNTIME, being careful to
7121
// avoid problems that exist at init time.
7122
0
static bool IsLite(const FileDescriptor* file) {
7123
  // TODO(kenton):  I don't even remember how many of these conditions are
7124
  //   actually possible.  I'm just being super-safe.
7125
0
  return file != nullptr &&
7126
0
         &file->options() != &FileOptions::default_instance() &&
7127
0
         file->options().optimize_for() == FileOptions::LITE_RUNTIME;
7128
0
}
7129
7130
void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
7131
0
                                            const FileDescriptorProto& proto) {
7132
0
  VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
7133
0
  VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
7134
0
  VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
7135
0
  VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field);
7136
7137
  // Lite files can only be imported by other Lite files.
7138
0
  if (!IsLite(file)) {
7139
0
    for (int i = 0; i < file->dependency_count(); i++) {
7140
0
      if (IsLite(file->dependency(i))) {
7141
0
        AddError(file->dependency(i)->name(), proto,
7142
0
                 DescriptorPool::ErrorCollector::IMPORT, [&] {
7143
0
                   return absl::StrCat(
7144
0
                       "Files that do not use optimize_for = LITE_RUNTIME "
7145
0
                       "cannot import files which do use this option.  This "
7146
0
                       "file is not lite, but it imports \"",
7147
0
                       file->dependency(i)->name(), "\" which is.");
7148
0
                 });
7149
0
        break;
7150
0
      }
7151
0
    }
7152
0
  }
7153
0
  if (FileDescriptorLegacy(file).syntax() ==
7154
0
      FileDescriptorLegacy::Syntax::SYNTAX_PROTO3) {
7155
0
    ValidateProto3(file, proto);
7156
0
  }
7157
0
}
7158
7159
void DescriptorBuilder::ValidateProto3(FileDescriptor* file,
7160
0
                                       const FileDescriptorProto& proto) {
7161
0
  for (int i = 0; i < file->extension_count(); ++i) {
7162
0
    ValidateProto3Field(file->extensions_ + i, proto.extension(i));
7163
0
  }
7164
0
  for (int i = 0; i < file->message_type_count(); ++i) {
7165
0
    ValidateProto3Message(file->message_types_ + i, proto.message_type(i));
7166
0
  }
7167
0
  for (int i = 0; i < file->enum_type_count(); ++i) {
7168
0
    ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i));
7169
0
  }
7170
0
}
7171
7172
void DescriptorBuilder::ValidateProto3Message(Descriptor* message,
7173
0
                                              const DescriptorProto& proto) {
7174
0
  for (int i = 0; i < message->nested_type_count(); ++i) {
7175
0
    ValidateProto3Message(message->nested_types_ + i, proto.nested_type(i));
7176
0
  }
7177
0
  for (int i = 0; i < message->enum_type_count(); ++i) {
7178
0
    ValidateProto3Enum(message->enum_types_ + i, proto.enum_type(i));
7179
0
  }
7180
0
  for (int i = 0; i < message->field_count(); ++i) {
7181
0
    ValidateProto3Field(message->fields_ + i, proto.field(i));
7182
0
  }
7183
0
  for (int i = 0; i < message->extension_count(); ++i) {
7184
0
    ValidateProto3Field(message->extensions_ + i, proto.extension(i));
7185
0
  }
7186
0
  if (message->extension_range_count() > 0) {
7187
0
    AddError(message->full_name(), proto.extension_range(0),
7188
0
             DescriptorPool::ErrorCollector::NUMBER,
7189
0
             "Extension ranges are not allowed in proto3.");
7190
0
  }
7191
0
  if (message->options().message_set_wire_format()) {
7192
    // Using MessageSet doesn't make sense since we disallow extensions.
7193
0
    AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
7194
0
             "MessageSet is not supported in proto3.");
7195
0
  }
7196
0
}
7197
7198
void DescriptorBuilder::ValidateProto3Field(FieldDescriptor* field,
7199
0
                                            const FieldDescriptorProto& proto) {
7200
0
  if (field->is_extension() &&
7201
0
      !AllowedExtendeeInProto3(field->containing_type()->full_name())) {
7202
0
    AddError(field->full_name(), proto,
7203
0
             DescriptorPool::ErrorCollector::EXTENDEE,
7204
0
             "Extensions in proto3 are only allowed for defining options.");
7205
0
  }
7206
0
  if (field->is_required()) {
7207
0
    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7208
0
             "Required fields are not allowed in proto3.");
7209
0
  }
7210
0
  if (field->has_default_value()) {
7211
0
    AddError(field->full_name(), proto,
7212
0
             DescriptorPool::ErrorCollector::DEFAULT_VALUE,
7213
0
             "Explicit default values are not allowed in proto3.");
7214
0
  }
7215
0
  if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
7216
0
      field->enum_type() &&
7217
0
      FileDescriptorLegacy(field->enum_type()->file()).syntax() !=
7218
0
          FileDescriptorLegacy::Syntax::SYNTAX_PROTO3 &&
7219
0
      FileDescriptorLegacy(field->enum_type()->file()).syntax() !=
7220
0
          FileDescriptorLegacy::Syntax::SYNTAX_UNKNOWN) {
7221
    // Proto3 messages can only use Proto3 enum types; otherwise we can't
7222
    // guarantee that the default value is zero.
7223
0
    AddError(
7224
0
        field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, [&] {
7225
0
          return absl::StrCat("Enum type \"", field->enum_type()->full_name(),
7226
0
                              "\" is not a proto3 enum, but is used in \"",
7227
0
                              field->containing_type()->full_name(),
7228
0
                              "\" which is a proto3 message type.");
7229
0
        });
7230
0
  }
7231
0
  if (field->type() == FieldDescriptor::TYPE_GROUP) {
7232
0
    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7233
0
             "Groups are not supported in proto3 syntax.");
7234
0
  }
7235
0
}
7236
7237
void DescriptorBuilder::ValidateProto3Enum(EnumDescriptor* enm,
7238
0
                                           const EnumDescriptorProto& proto) {
7239
0
  if (enm->value_count() > 0 && enm->value(0)->number() != 0) {
7240
0
    AddError(enm->full_name(), proto.value(0),
7241
0
             DescriptorPool::ErrorCollector::NUMBER,
7242
0
             "The first enum value must be zero in proto3.");
7243
0
  }
7244
0
}
7245
7246
void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
7247
0
                                               const DescriptorProto& proto) {
7248
0
  VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field);
7249
0
  VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message);
7250
0
  VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum);
7251
0
  VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field);
7252
7253
0
  CheckFieldJsonNameUniqueness(proto, message);
7254
0
  ValidateExtensionRangeOptions(proto, *message);
7255
0
}
7256
7257
7258
void DescriptorBuilder::ValidateFieldOptions(
7259
0
    FieldDescriptor* field, const FieldDescriptorProto& proto) {
7260
0
  if (pool_->lazily_build_dependencies_ && (!field || !field->message_type())) {
7261
0
    return;
7262
0
  }
7263
  // Only message type fields may be lazy.
7264
0
  if (field->options().lazy() || field->options().unverified_lazy()) {
7265
0
    if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
7266
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7267
0
               "[lazy = true] can only be specified for submessage fields.");
7268
0
    }
7269
0
  }
7270
7271
  // Only repeated primitive fields may be packed.
7272
0
  if (field->options().packed() && !field->is_packable()) {
7273
0
    AddError(
7274
0
        field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7275
0
        "[packed = true] can only be specified for repeated primitive fields.");
7276
0
  }
7277
7278
  // Note:  Default instance may not yet be initialized here, so we have to
7279
  //   avoid reading from it.
7280
0
  if (field->containing_type_ != nullptr &&
7281
0
      &field->containing_type()->options() !=
7282
0
          &MessageOptions::default_instance() &&
7283
0
      field->containing_type()->options().message_set_wire_format()) {
7284
0
    if (field->is_extension()) {
7285
0
      if (!field->is_optional() ||
7286
0
          field->type() != FieldDescriptor::TYPE_MESSAGE) {
7287
0
        AddError(field->full_name(), proto,
7288
0
                 DescriptorPool::ErrorCollector::TYPE,
7289
0
                 "Extensions of MessageSets must be optional messages.");
7290
0
      }
7291
0
    } else {
7292
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
7293
0
               "MessageSets cannot have fields, only extensions.");
7294
0
    }
7295
0
  }
7296
7297
  // Lite extensions can only be of Lite types.
7298
0
  if (IsLite(field->file()) && field->containing_type_ != nullptr &&
7299
0
      !IsLite(field->containing_type()->file())) {
7300
0
    AddError(field->full_name(), proto,
7301
0
             DescriptorPool::ErrorCollector::EXTENDEE,
7302
0
             "Extensions to non-lite types can only be declared in non-lite "
7303
0
             "files.  Note that you cannot extend a non-lite type to contain "
7304
0
             "a lite type, but the reverse is allowed.");
7305
0
  }
7306
7307
  // Validate map types.
7308
0
  if (field->is_map()) {
7309
0
    if (!ValidateMapEntry(field, proto)) {
7310
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7311
0
               "map_entry should not be set explicitly. Use map<KeyType, "
7312
0
               "ValueType> instead.");
7313
0
    }
7314
0
  }
7315
7316
0
  ValidateJSType(field, proto);
7317
7318
  // json_name option is not allowed on extension fields. Note that the
7319
  // json_name field in FieldDescriptorProto is always populated by protoc
7320
  // when it sends descriptor data to plugins (calculated from field name if
7321
  // the option is not explicitly set) so we can't rely on its presence to
7322
  // determine whether the json_name option is set on the field. Here we
7323
  // compare it against the default calculated json_name value and consider
7324
  // the option set if they are different. This won't catch the case when
7325
  // a user explicitly sets json_name to the default value, but should be
7326
  // good enough to catch common misuses.
7327
0
  if (field->is_extension() &&
7328
0
      (field->has_json_name() &&
7329
0
       field->json_name() != ToJsonName(field->name()))) {
7330
0
    AddError(field->full_name(), proto,
7331
0
             DescriptorPool::ErrorCollector::OPTION_NAME,
7332
0
             "option json_name is not allowed on extension fields.");
7333
0
  }
7334
7335
0
}
7336
7337
void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
7338
0
                                            const EnumDescriptorProto& proto) {
7339
0
  VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue);
7340
7341
0
  CheckEnumValueUniqueness(proto, enm);
7342
7343
0
  if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) {
7344
0
    absl::flat_hash_map<int, std::string> used_values;
7345
0
    for (int i = 0; i < enm->value_count(); ++i) {
7346
0
      const EnumValueDescriptor* enum_value = enm->value(i);
7347
0
      auto insert_result =
7348
0
          used_values.emplace(enum_value->number(), enum_value->full_name());
7349
0
      bool inserted = insert_result.second;
7350
0
      if (!inserted) {
7351
0
        if (!enm->options().allow_alias()) {
7352
          // Generate error if duplicated enum values are explicitly disallowed.
7353
0
          auto make_error = [&] {
7354
            // Find the next free number.
7355
0
            absl::flat_hash_set<int64_t> used;
7356
0
            for (int j = 0; j < enm->value_count(); ++j) {
7357
0
              used.insert(enm->value(j)->number());
7358
0
            }
7359
0
            int64_t next_value = static_cast<int64_t>(enum_value->number()) + 1;
7360
0
            while (used.contains(next_value)) ++next_value;
7361
7362
0
            std::string error = absl::StrCat(
7363
0
                "\"", enum_value->full_name(),
7364
0
                "\" uses the same enum value as \"",
7365
0
                insert_result.first->second,
7366
0
                "\". If this is intended, set "
7367
0
                "'option allow_alias = true;' to the enum definition.");
7368
0
            if (next_value < std::numeric_limits<int32_t>::max()) {
7369
0
              absl::StrAppend(&error, " The next available enum value is ",
7370
0
                              next_value, ".");
7371
0
            }
7372
0
            return error;
7373
0
          };
7374
0
          AddError(enm->full_name(), proto.value(i),
7375
0
                   DescriptorPool::ErrorCollector::NUMBER, make_error);
7376
0
        }
7377
0
      }
7378
0
    }
7379
0
  }
7380
0
}
7381
7382
void DescriptorBuilder::ValidateEnumValueOptions(
7383
    EnumValueDescriptor* /* enum_value */,
7384
0
    const EnumValueDescriptorProto& /* proto */) {
7385
  // Nothing to do so far.
7386
0
}
7387
7388
namespace {
7389
// Validates that a fully-qualified symbol for extension declaration must
7390
// have a leading dot and valid identifiers.
7391
absl::optional<std::string> ValidateSymbolForDeclaration(
7392
0
    absl::string_view symbol) {
7393
0
  if (!absl::StartsWith(symbol, ".")) {
7394
0
    return absl::StrCat("\"", symbol,
7395
0
                        "\" must have a leading dot to indicate the "
7396
0
                        "fully-qualified scope.");
7397
0
  }
7398
0
  if (!ValidateQualifiedName(symbol)) {
7399
0
    return absl::StrCat("\"", symbol, "\" contains invalid identifiers.");
7400
0
  }
7401
0
  return absl::nullopt;
7402
0
}
7403
}  // namespace
7404
7405
7406
void DescriptorBuilder::ValidateExtensionDeclaration(
7407
    const std::string& full_name,
7408
    const RepeatedPtrField<ExtensionRangeOptions_Declaration>& declarations,
7409
    const DescriptorProto_ExtensionRange& proto,
7410
0
    absl::flat_hash_set<absl::string_view>& full_name_set) {
7411
0
  absl::flat_hash_set<int> extension_number_set;
7412
0
  for (const auto& declaration : declarations) {
7413
0
    if (declaration.number() < proto.start() ||
7414
0
        declaration.number() >= proto.end()) {
7415
0
      AddError(full_name, proto, DescriptorPool::ErrorCollector::NUMBER, [&] {
7416
0
        return absl::Substitute(
7417
0
            "Extension declaration number $0 is not in the "
7418
0
            "extension range.",
7419
0
            declaration.number());
7420
0
      });
7421
0
    }
7422
7423
0
    if (!extension_number_set.insert(declaration.number()).second) {
7424
0
      AddError(full_name, proto, DescriptorPool::ErrorCollector::NUMBER, [&] {
7425
0
        return absl::Substitute(
7426
0
            "Extension declaration number $0 is declared multiple times.",
7427
0
            declaration.number());
7428
0
      });
7429
0
    }
7430
7431
    // Both full_name and type should be present. If none of them is set,
7432
    // add an error unless reserved is set to true. If only one of them is set,
7433
    // add an error whether or not reserved is set to true.
7434
0
    if (!declaration.has_full_name() || !declaration.has_type()) {
7435
0
      if (declaration.has_full_name() != declaration.has_type() ||
7436
0
          !declaration.reserved()) {
7437
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::EXTENDEE,
7438
0
                 [&] {
7439
0
                   return absl::StrCat(
7440
0
                       "Extension declaration #", declaration.number(),
7441
0
                       " should have both \"full_name\" and \"type\" set.");
7442
0
                 });
7443
0
      }
7444
0
    } else {
7445
0
      if (!full_name_set.insert(declaration.full_name()).second) {
7446
0
        AddError(
7447
0
            declaration.full_name(), proto,
7448
0
            DescriptorPool::ErrorCollector::NAME, [&] {
7449
0
              return absl::Substitute(
7450
0
                  "Extension field name \"$0\" is declared multiple times.",
7451
0
                  declaration.full_name());
7452
0
            });
7453
0
        return;
7454
0
      }
7455
0
      absl::optional<std::string> err =
7456
0
          ValidateSymbolForDeclaration(declaration.full_name());
7457
0
      if (err.has_value()) {
7458
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
7459
0
                 [err] { return *err; });
7460
0
      }
7461
0
      if (!IsNonMessageType(declaration.type())) {
7462
0
        err = ValidateSymbolForDeclaration(declaration.type());
7463
0
        if (err.has_value()) {
7464
0
          AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
7465
0
                   [err] { return *err; });
7466
0
        }
7467
0
      }
7468
0
    }
7469
0
  }
7470
0
}
7471
7472
void DescriptorBuilder::ValidateExtensionRangeOptions(
7473
0
    const DescriptorProto& proto, const Descriptor& message) {
7474
0
  const int64_t max_extension_range =
7475
0
      static_cast<int64_t>(message.options().message_set_wire_format()
7476
0
                               ? std::numeric_limits<int32_t>::max()
7477
0
                               : FieldDescriptor::kMaxNumber);
7478
7479
0
  size_t num_declarations = 0;
7480
0
  for (int i = 0; i < message.extension_range_count(); i++) {
7481
0
    if (message.extension_range(i)->options_ == nullptr) continue;
7482
0
    num_declarations +=
7483
0
        message.extension_range(i)->options_->declaration_size();
7484
0
  }
7485
7486
  // Contains the full names from both "declaration" and "metadata".
7487
0
  absl::flat_hash_set<absl::string_view> declaration_full_name_set;
7488
0
  declaration_full_name_set.reserve(num_declarations);
7489
7490
0
  for (int i = 0; i < message.extension_range_count(); i++) {
7491
0
    const auto& range = *message.extension_range(i);
7492
0
    if (range.end > max_extension_range + 1) {
7493
0
      AddError(message.full_name(), proto,
7494
0
               DescriptorPool::ErrorCollector::NUMBER, [&] {
7495
0
                 return absl::Substitute(
7496
0
                     "Extension numbers cannot be greater than $0.",
7497
0
                     max_extension_range);
7498
0
               });
7499
0
    }
7500
0
    const auto& range_options = *range.options_;
7501
7502
7503
0
    if (!range_options.declaration().empty()) {
7504
      // TODO(b/278783756): remove the "has_verification" check once the default
7505
      // is flipped to DECLARATION.
7506
0
      if (range_options.has_verification() &&
7507
0
          range_options.verification() == ExtensionRangeOptions::UNVERIFIED) {
7508
0
        AddError(message.full_name(), proto.extension_range(i),
7509
0
                 DescriptorPool::ErrorCollector::EXTENDEE, [&] {
7510
0
                   return absl::Substitute(
7511
0
                       "Cannot mark the extension range as UNVERIFIED when it "
7512
0
                       "has extension(s) declared.");
7513
0
                 });
7514
0
        return;
7515
0
      }
7516
0
      ValidateExtensionDeclaration(
7517
0
          message.full_name(), range_options.declaration(),
7518
0
          proto.extension_range(i), declaration_full_name_set);
7519
0
    }
7520
0
  }
7521
0
}
7522
7523
void DescriptorBuilder::ValidateServiceOptions(
7524
0
    ServiceDescriptor* service, const ServiceDescriptorProto& proto) {
7525
0
  if (IsLite(service->file()) &&
7526
0
      (service->file()->options().cc_generic_services() ||
7527
0
       service->file()->options().java_generic_services())) {
7528
0
    AddError(service->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
7529
0
             "Files with optimize_for = LITE_RUNTIME cannot define services "
7530
0
             "unless you set both options cc_generic_services and "
7531
0
             "java_generic_services to false.");
7532
0
  }
7533
7534
0
  VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
7535
0
}
7536
7537
void DescriptorBuilder::ValidateMethodOptions(
7538
0
    MethodDescriptor* /* method */, const MethodDescriptorProto& /* proto */) {
7539
  // Nothing to do so far.
7540
0
}
7541
7542
bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
7543
0
                                         const FieldDescriptorProto& proto) {
7544
0
  const Descriptor* message = field->message_type();
7545
0
  if (  // Must not contain extensions, extension range or nested message or
7546
        // enums
7547
0
      message->extension_count() != 0 ||
7548
0
      field->label() != FieldDescriptor::LABEL_REPEATED ||
7549
0
      message->extension_range_count() != 0 ||
7550
0
      message->nested_type_count() != 0 || message->enum_type_count() != 0 ||
7551
      // Must contain exactly two fields
7552
0
      message->field_count() != 2 ||
7553
      // Field name and message name must match
7554
0
      message->name() !=
7555
0
          absl::StrCat(ToCamelCase(field->name(), false), "Entry") ||
7556
      // Entry message must be in the same containing type of the field.
7557
0
      field->containing_type() != message->containing_type()) {
7558
0
    return false;
7559
0
  }
7560
7561
0
  const FieldDescriptor* key = message->map_key();
7562
0
  const FieldDescriptor* value = message->map_value();
7563
0
  if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 ||
7564
0
      key->name() != "key") {
7565
0
    return false;
7566
0
  }
7567
0
  if (value->label() != FieldDescriptor::LABEL_OPTIONAL ||
7568
0
      value->number() != 2 || value->name() != "value") {
7569
0
    return false;
7570
0
  }
7571
7572
  // Check key types are legal.
7573
0
  switch (key->type()) {
7574
0
    case FieldDescriptor::TYPE_ENUM:
7575
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7576
0
               "Key in map fields cannot be enum types.");
7577
0
      break;
7578
0
    case FieldDescriptor::TYPE_FLOAT:
7579
0
    case FieldDescriptor::TYPE_DOUBLE:
7580
0
    case FieldDescriptor::TYPE_MESSAGE:
7581
0
    case FieldDescriptor::TYPE_GROUP:
7582
0
    case FieldDescriptor::TYPE_BYTES:
7583
0
      AddError(
7584
0
          field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7585
0
          "Key in map fields cannot be float/double, bytes or message types.");
7586
0
      break;
7587
0
    case FieldDescriptor::TYPE_BOOL:
7588
0
    case FieldDescriptor::TYPE_INT32:
7589
0
    case FieldDescriptor::TYPE_INT64:
7590
0
    case FieldDescriptor::TYPE_SINT32:
7591
0
    case FieldDescriptor::TYPE_SINT64:
7592
0
    case FieldDescriptor::TYPE_STRING:
7593
0
    case FieldDescriptor::TYPE_UINT32:
7594
0
    case FieldDescriptor::TYPE_UINT64:
7595
0
    case FieldDescriptor::TYPE_FIXED32:
7596
0
    case FieldDescriptor::TYPE_FIXED64:
7597
0
    case FieldDescriptor::TYPE_SFIXED32:
7598
0
    case FieldDescriptor::TYPE_SFIXED64:
7599
      // Legal cases
7600
0
      break;
7601
      // Do not add a default, so that the compiler will complain when new types
7602
      // are added.
7603
0
  }
7604
7605
0
  if (value->type() == FieldDescriptor::TYPE_ENUM) {
7606
0
    if (value->enum_type()->value(0)->number() != 0) {
7607
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7608
0
               "Enum value in map must define 0 as the first value.");
7609
0
    }
7610
0
  }
7611
7612
0
  return true;
7613
0
}
7614
7615
void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
7616
0
                                           const DescriptorProto& proto) {
7617
0
  DescriptorsByNameSet<Descriptor> seen_types;
7618
0
  for (int i = 0; i < message->nested_type_count(); ++i) {
7619
0
    const Descriptor* nested = message->nested_type(i);
7620
0
    auto insert_result = seen_types.insert(nested);
7621
0
    bool inserted = insert_result.second;
7622
0
    if (!inserted) {
7623
0
      if ((*insert_result.first)->options().map_entry() ||
7624
0
          nested->options().map_entry()) {
7625
0
        AddError(message->full_name(), proto,
7626
0
                 DescriptorPool::ErrorCollector::NAME, [&] {
7627
0
                   return absl::StrCat(
7628
0
                       "Expanded map entry type ", nested->name(),
7629
0
                       " conflicts with an existing nested message type.");
7630
0
                 });
7631
0
        break;
7632
0
      }
7633
0
    }
7634
    // Recursively test on the nested types.
7635
0
    DetectMapConflicts(message->nested_type(i), proto.nested_type(i));
7636
0
  }
7637
  // Check for conflicted field names.
7638
0
  for (int i = 0; i < message->field_count(); ++i) {
7639
0
    const FieldDescriptor* field = message->field(i);
7640
0
    auto iter = seen_types.find(field->name());
7641
0
    if (iter != seen_types.end() && (*iter)->options().map_entry()) {
7642
0
      AddError(message->full_name(), proto,
7643
0
               DescriptorPool::ErrorCollector::NAME, [&] {
7644
0
                 return absl::StrCat("Expanded map entry type ",
7645
0
                                     (*iter)->name(),
7646
0
                                     " conflicts with an existing field.");
7647
0
               });
7648
0
    }
7649
0
  }
7650
  // Check for conflicted enum names.
7651
0
  for (int i = 0; i < message->enum_type_count(); ++i) {
7652
0
    const EnumDescriptor* enum_desc = message->enum_type(i);
7653
0
    auto iter = seen_types.find(enum_desc->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 enum type.");
7660
0
               });
7661
0
    }
7662
0
  }
7663
  // Check for conflicted oneof names.
7664
0
  for (int i = 0; i < message->oneof_decl_count(); ++i) {
7665
0
    const OneofDescriptor* oneof_desc = message->oneof_decl(i);
7666
0
    auto iter = seen_types.find(oneof_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 oneof type.");
7673
0
               });
7674
0
    }
7675
0
  }
7676
0
}
7677
7678
void DescriptorBuilder::ValidateJSType(FieldDescriptor* field,
7679
0
                                       const FieldDescriptorProto& proto) {
7680
0
  FieldOptions::JSType jstype = field->options().jstype();
7681
  // The default is always acceptable.
7682
0
  if (jstype == FieldOptions::JS_NORMAL) {
7683
0
    return;
7684
0
  }
7685
7686
0
  switch (field->type()) {
7687
    // Integral 64-bit types may be represented as JavaScript numbers or
7688
    // strings.
7689
0
    case FieldDescriptor::TYPE_UINT64:
7690
0
    case FieldDescriptor::TYPE_INT64:
7691
0
    case FieldDescriptor::TYPE_SINT64:
7692
0
    case FieldDescriptor::TYPE_FIXED64:
7693
0
    case FieldDescriptor::TYPE_SFIXED64:
7694
0
      if (jstype == FieldOptions::JS_STRING ||
7695
0
          jstype == FieldOptions::JS_NUMBER) {
7696
0
        return;
7697
0
      }
7698
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7699
0
               [&] {
7700
0
                 return absl::StrCat(
7701
0
                     "Illegal jstype for int64, uint64, sint64, fixed64 "
7702
0
                     "or sfixed64 field: ",
7703
0
                     FieldOptions_JSType_descriptor()->value(jstype)->name());
7704
0
               });
7705
0
      break;
7706
7707
    // No other types permit a jstype option.
7708
0
    default:
7709
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7710
0
               "jstype is only allowed on int64, uint64, sint64, fixed64 "
7711
0
               "or sfixed64 fields.");
7712
0
      break;
7713
0
  }
7714
0
}
7715
7716
#undef VALIDATE_OPTIONS_FROM_ARRAY
7717
7718
// -------------------------------------------------------------------
7719
7720
DescriptorBuilder::OptionInterpreter::OptionInterpreter(
7721
    DescriptorBuilder* builder)
7722
0
    : builder_(builder) {
7723
0
  ABSL_CHECK(builder_);
7724
0
}
7725
7726
0
DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {}
7727
7728
bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
7729
0
    OptionsToInterpret* options_to_interpret) {
7730
  // Note that these may be in different pools, so we can't use the same
7731
  // descriptor and reflection objects on both.
7732
0
  Message* options = options_to_interpret->options;
7733
0
  const Message* original_options = options_to_interpret->original_options;
7734
7735
0
  bool failed = false;
7736
0
  options_to_interpret_ = options_to_interpret;
7737
7738
  // Find the uninterpreted_option field in the mutable copy of the options
7739
  // and clear them, since we're about to interpret them.
7740
0
  const FieldDescriptor* uninterpreted_options_field =
7741
0
      options->GetDescriptor()->FindFieldByName("uninterpreted_option");
7742
0
  ABSL_CHECK(uninterpreted_options_field != nullptr)
7743
0
      << "No field named \"uninterpreted_option\" in the Options proto.";
7744
0
  options->GetReflection()->ClearField(options, uninterpreted_options_field);
7745
7746
0
  std::vector<int> src_path = options_to_interpret->element_path;
7747
0
  src_path.push_back(uninterpreted_options_field->number());
7748
7749
  // Find the uninterpreted_option field in the original options.
7750
0
  const FieldDescriptor* original_uninterpreted_options_field =
7751
0
      original_options->GetDescriptor()->FindFieldByName(
7752
0
          "uninterpreted_option");
7753
0
  ABSL_CHECK(original_uninterpreted_options_field != nullptr)
7754
0
      << "No field named \"uninterpreted_option\" in the Options proto.";
7755
7756
0
  const int num_uninterpreted_options =
7757
0
      original_options->GetReflection()->FieldSize(
7758
0
          *original_options, original_uninterpreted_options_field);
7759
0
  for (int i = 0; i < num_uninterpreted_options; ++i) {
7760
0
    src_path.push_back(i);
7761
0
    uninterpreted_option_ = DownCast<const UninterpretedOption*>(
7762
0
        &original_options->GetReflection()->GetRepeatedMessage(
7763
0
            *original_options, original_uninterpreted_options_field, i));
7764
0
    if (!InterpretSingleOption(options, src_path,
7765
0
                               options_to_interpret->element_path)) {
7766
      // Error already added by InterpretSingleOption().
7767
0
      failed = true;
7768
0
      break;
7769
0
    }
7770
0
    src_path.pop_back();
7771
0
  }
7772
  // Reset these, so we don't have any dangling pointers.
7773
0
  uninterpreted_option_ = nullptr;
7774
0
  options_to_interpret_ = nullptr;
7775
7776
0
  if (!failed) {
7777
    // InterpretSingleOption() added the interpreted options in the
7778
    // UnknownFieldSet, in case the option isn't yet known to us.  Now we
7779
    // serialize the options message and deserialize it back.  That way, any
7780
    // option fields that we do happen to know about will get moved from the
7781
    // UnknownFieldSet into the real fields, and thus be available right away.
7782
    // If they are not known, that's OK too. They will get reparsed into the
7783
    // UnknownFieldSet and wait there until the message is parsed by something
7784
    // that does know about the options.
7785
7786
    // Keep the unparsed options around in case the reparsing fails.
7787
0
    std::unique_ptr<Message> unparsed_options(options->New());
7788
0
    options->GetReflection()->Swap(unparsed_options.get(), options);
7789
7790
0
    std::string buf;
7791
0
    if (!unparsed_options->AppendToString(&buf) ||
7792
0
        !options->ParseFromString(buf)) {
7793
0
      builder_->AddError(
7794
0
          options_to_interpret->element_name, *original_options,
7795
0
          DescriptorPool::ErrorCollector::OTHER, [&] {
7796
0
            return absl::StrCat(
7797
0
                "Some options could not be correctly parsed using the proto "
7798
0
                "descriptors compiled into this binary.\n"
7799
0
                "Unparsed options: ",
7800
0
                unparsed_options->ShortDebugString(),
7801
0
                "\n"
7802
0
                "Parsing attempt:  ",
7803
0
                options->ShortDebugString());
7804
0
          });
7805
      // Restore the unparsed options.
7806
0
      options->GetReflection()->Swap(unparsed_options.get(), options);
7807
0
    }
7808
0
  }
7809
7810
0
  return !failed;
7811
0
}
7812
7813
bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
7814
    Message* options, const std::vector<int>& src_path,
7815
0
    const std::vector<int>& options_path) {
7816
  // First do some basic validation.
7817
0
  if (uninterpreted_option_->name_size() == 0) {
7818
    // This should never happen unless the parser has gone seriously awry or
7819
    // someone has manually created the uninterpreted option badly.
7820
0
    return AddNameError(
7821
0
        []() -> std::string { return "Option must have a name."; });
7822
0
  }
7823
0
  if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") {
7824
0
    return AddNameError([]() -> std::string {
7825
0
      return "Option must not use reserved name \"uninterpreted_option\".";
7826
0
    });
7827
0
  }
7828
7829
0
  const Descriptor* options_descriptor = nullptr;
7830
  // Get the options message's descriptor from the builder's pool, so that we
7831
  // get the version that knows about any extension options declared in the file
7832
  // we're currently building. The descriptor should be there as long as the
7833
  // file we're building imported descriptor.proto.
7834
7835
  // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
7836
  // DescriptorPool::FindMessageTypeByName() because we're already holding the
7837
  // pool's mutex, and the latter method locks it again.  We don't use
7838
  // FindSymbol() because files that use custom options only need to depend on
7839
  // the file that defines the option, not descriptor.proto itself.
7840
0
  Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
7841
0
      options->GetDescriptor()->full_name());
7842
0
  options_descriptor = symbol.descriptor();
7843
0
  if (options_descriptor == nullptr) {
7844
    // The options message's descriptor was not in the builder's pool, so use
7845
    // the standard version from the generated pool. We're not holding the
7846
    // generated pool's mutex, so we can search it the straightforward way.
7847
0
    options_descriptor = options->GetDescriptor();
7848
0
  }
7849
0
  ABSL_CHECK(options_descriptor);
7850
7851
  // We iterate over the name parts to drill into the submessages until we find
7852
  // the leaf field for the option. As we drill down we remember the current
7853
  // submessage's descriptor in |descriptor| and the next field in that
7854
  // submessage in |field|. We also track the fields we're drilling down
7855
  // through in |intermediate_fields|. As we go, we reconstruct the full option
7856
  // name in |debug_msg_name|, for use in error messages.
7857
0
  const Descriptor* descriptor = options_descriptor;
7858
0
  const FieldDescriptor* field = nullptr;
7859
0
  std::vector<const FieldDescriptor*> intermediate_fields;
7860
0
  std::string debug_msg_name = "";
7861
7862
0
  std::vector<int> dest_path = options_path;
7863
7864
0
  for (int i = 0; i < uninterpreted_option_->name_size(); ++i) {
7865
0
    builder_->undefine_resolved_name_.clear();
7866
0
    const std::string& name_part = uninterpreted_option_->name(i).name_part();
7867
0
    if (!debug_msg_name.empty()) {
7868
0
      absl::StrAppend(&debug_msg_name, ".");
7869
0
    }
7870
0
    if (uninterpreted_option_->name(i).is_extension()) {
7871
0
      absl::StrAppend(&debug_msg_name, "(", name_part, ")");
7872
      // Search for the extension's descriptor as an extension in the builder's
7873
      // pool. Note that we use DescriptorBuilder::LookupSymbol(), not
7874
      // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows
7875
      // relative lookups, and 2) because we're already holding the pool's
7876
      // mutex, and the latter method locks it again.
7877
0
      symbol =
7878
0
          builder_->LookupSymbol(name_part, options_to_interpret_->name_scope);
7879
0
      field = symbol.field_descriptor();
7880
      // If we don't find the field then the field's descriptor was not in the
7881
      // builder's pool, but there's no point in looking in the generated
7882
      // pool. We require that you import the file that defines any extensions
7883
      // you use, so they must be present in the builder's pool.
7884
0
    } else {
7885
0
      absl::StrAppend(&debug_msg_name, name_part);
7886
      // Search for the field's descriptor as a regular field.
7887
0
      field = descriptor->FindFieldByName(name_part);
7888
0
    }
7889
7890
0
    if (field == nullptr) {
7891
0
      if (get_allow_unknown(builder_->pool_)) {
7892
        // We can't find the option, but AllowUnknownDependencies() is enabled,
7893
        // so we will just leave it as uninterpreted.
7894
0
        AddWithoutInterpreting(*uninterpreted_option_, options);
7895
0
        return true;
7896
0
      } else if (!(builder_->undefine_resolved_name_).empty()) {
7897
        // Option is resolved to a name which is not defined.
7898
0
        return AddNameError([&] {
7899
0
          return absl::StrCat(
7900
0
              "Option \"", debug_msg_name, "\" is resolved to \"(",
7901
0
              builder_->undefine_resolved_name_,
7902
0
              ")\", which is not defined. The innermost scope is searched "
7903
0
              "first "
7904
0
              "in name resolution. Consider using a leading '.'(i.e., \"(.",
7905
0
              debug_msg_name.substr(1),
7906
0
              "\") to start from the outermost scope.");
7907
0
        });
7908
0
      } else {
7909
0
        return AddNameError([&] {
7910
0
          return absl::StrCat(
7911
0
              "Option \"", debug_msg_name, "\" unknown. Ensure that your proto",
7912
0
              " definition file imports the proto which defines the option.");
7913
0
        });
7914
0
      }
7915
0
    } else if (field->containing_type() != descriptor) {
7916
0
      if (get_is_placeholder(field->containing_type())) {
7917
        // The field is an extension of a placeholder type, so we can't
7918
        // reliably verify whether it is a valid extension to use here (e.g.
7919
        // we don't know if it is an extension of the correct *Options message,
7920
        // or if it has a valid field number, etc.).  Just leave it as
7921
        // uninterpreted instead.
7922
0
        AddWithoutInterpreting(*uninterpreted_option_, options);
7923
0
        return true;
7924
0
      } else {
7925
        // This can only happen if, due to some insane misconfiguration of the
7926
        // pools, we find the options message in one pool but the field in
7927
        // another. This would probably imply a hefty bug somewhere.
7928
0
        return AddNameError([&] {
7929
0
          return absl::StrCat("Option field \"", debug_msg_name,
7930
0
                              "\" is not a field or extension of message \"",
7931
0
                              descriptor->name(), "\".");
7932
0
        });
7933
0
      }
7934
0
    } else {
7935
      // accumulate field numbers to form path to interpreted option
7936
0
      dest_path.push_back(field->number());
7937
7938
0
      if (i < uninterpreted_option_->name_size() - 1) {
7939
0
        if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
7940
0
          return AddNameError([&] {
7941
0
            return absl::StrCat("Option \"", debug_msg_name,
7942
0
                                "\" is an atomic type, not a message.");
7943
0
          });
7944
0
        } else if (field->is_repeated()) {
7945
0
          return AddNameError([&] {
7946
0
            return absl::StrCat("Option field \"", debug_msg_name,
7947
0
                                "\" is a repeated message. Repeated message "
7948
0
                                "options must be initialized using an "
7949
0
                                "aggregate value.");
7950
0
          });
7951
0
        } else {
7952
          // Drill down into the submessage.
7953
0
          intermediate_fields.push_back(field);
7954
0
          descriptor = field->message_type();
7955
0
        }
7956
0
      }
7957
0
    }
7958
0
  }
7959
7960
  // We've found the leaf field. Now we use UnknownFieldSets to set its value
7961
  // on the options message. We do so because the message may not yet know
7962
  // about its extension fields, so we may not be able to set the fields
7963
  // directly. But the UnknownFieldSets will serialize to the same wire-format
7964
  // message, so reading that message back in once the extension fields are
7965
  // known will populate them correctly.
7966
7967
  // First see if the option is already set.
7968
0
  if (!field->is_repeated() &&
7969
0
      !ExamineIfOptionIsSet(
7970
0
          intermediate_fields.begin(), intermediate_fields.end(), field,
7971
0
          debug_msg_name,
7972
0
          options->GetReflection()->GetUnknownFields(*options))) {
7973
0
    return false;  // ExamineIfOptionIsSet() already added the error.
7974
0
  }
7975
7976
  // First set the value on the UnknownFieldSet corresponding to the
7977
  // innermost message.
7978
0
  std::unique_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
7979
0
  if (!SetOptionValue(field, unknown_fields.get())) {
7980
0
    return false;  // SetOptionValue() already added the error.
7981
0
  }
7982
7983
  // Now wrap the UnknownFieldSet with UnknownFieldSets corresponding to all
7984
  // the intermediate messages.
7985
0
  for (std::vector<const FieldDescriptor*>::reverse_iterator iter =
7986
0
           intermediate_fields.rbegin();
7987
0
       iter != intermediate_fields.rend(); ++iter) {
7988
0
    std::unique_ptr<UnknownFieldSet> parent_unknown_fields(
7989
0
        new UnknownFieldSet());
7990
0
    switch ((*iter)->type()) {
7991
0
      case FieldDescriptor::TYPE_MESSAGE: {
7992
0
        std::string* outstr =
7993
0
            parent_unknown_fields->AddLengthDelimited((*iter)->number());
7994
0
        ABSL_CHECK(unknown_fields->SerializeToString(outstr))
7995
0
            << "Unexpected failure while serializing option submessage "
7996
0
            << debug_msg_name << "\".";
7997
0
        break;
7998
0
      }
7999
8000
0
      case FieldDescriptor::TYPE_GROUP: {
8001
0
        parent_unknown_fields->AddGroup((*iter)->number())
8002
0
            ->MergeFrom(*unknown_fields);
8003
0
        break;
8004
0
      }
8005
8006
0
      default:
8007
0
        ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: "
8008
0
                        << (*iter)->type();
8009
0
        return false;
8010
0
    }
8011
0
    unknown_fields.reset(parent_unknown_fields.release());
8012
0
  }
8013
8014
  // Now merge the UnknownFieldSet corresponding to the top-level message into
8015
  // the options message.
8016
0
  options->GetReflection()->MutableUnknownFields(options)->MergeFrom(
8017
0
      *unknown_fields);
8018
8019
  // record the element path of the interpreted option
8020
0
  if (field->is_repeated()) {
8021
0
    int index = repeated_option_counts_[dest_path]++;
8022
0
    dest_path.push_back(index);
8023
0
  }
8024
0
  interpreted_paths_[src_path] = dest_path;
8025
8026
0
  return true;
8027
0
}
8028
8029
void DescriptorBuilder::OptionInterpreter::UpdateSourceCodeInfo(
8030
0
    SourceCodeInfo* info) {
8031
0
  if (interpreted_paths_.empty()) {
8032
    // nothing to do!
8033
0
    return;
8034
0
  }
8035
8036
  // We find locations that match keys in interpreted_paths_ and
8037
  // 1) replace the path with the corresponding value in interpreted_paths_
8038
  // 2) remove any subsequent sub-locations (sub-location is one whose path
8039
  //    has the parent path as a prefix)
8040
  //
8041
  // To avoid quadratic behavior of removing interior rows as we go,
8042
  // we keep a copy. But we don't actually copy anything until we've
8043
  // found the first match (so if the source code info has no locations
8044
  // that need to be changed, there is zero copy overhead).
8045
8046
0
  RepeatedPtrField<SourceCodeInfo_Location>* locs = info->mutable_location();
8047
0
  RepeatedPtrField<SourceCodeInfo_Location> new_locs;
8048
0
  bool copying = false;
8049
8050
0
  std::vector<int> pathv;
8051
0
  bool matched = false;
8052
8053
0
  for (RepeatedPtrField<SourceCodeInfo_Location>::iterator loc = locs->begin();
8054
0
       loc != locs->end(); loc++) {
8055
0
    if (matched) {
8056
      // see if this location is in the range to remove
8057
0
      bool loc_matches = true;
8058
0
      if (loc->path_size() < static_cast<int64_t>(pathv.size())) {
8059
0
        loc_matches = false;
8060
0
      } else {
8061
0
        for (size_t j = 0; j < pathv.size(); j++) {
8062
0
          if (loc->path(j) != pathv[j]) {
8063
0
            loc_matches = false;
8064
0
            break;
8065
0
          }
8066
0
        }
8067
0
      }
8068
8069
0
      if (loc_matches) {
8070
        // don't copy this row since it is a sub-location that we're removing
8071
0
        continue;
8072
0
      }
8073
8074
0
      matched = false;
8075
0
    }
8076
8077
0
    pathv.clear();
8078
0
    for (int j = 0; j < loc->path_size(); j++) {
8079
0
      pathv.push_back(loc->path(j));
8080
0
    }
8081
8082
0
    auto entry = interpreted_paths_.find(pathv);
8083
8084
0
    if (entry == interpreted_paths_.end()) {
8085
      // not a match
8086
0
      if (copying) {
8087
0
        *new_locs.Add() = *loc;
8088
0
      }
8089
0
      continue;
8090
0
    }
8091
8092
0
    matched = true;
8093
8094
0
    if (!copying) {
8095
      // initialize the copy we are building
8096
0
      copying = true;
8097
0
      new_locs.Reserve(locs->size());
8098
0
      for (RepeatedPtrField<SourceCodeInfo_Location>::iterator it =
8099
0
               locs->begin();
8100
0
           it != loc; it++) {
8101
0
        *new_locs.Add() = *it;
8102
0
      }
8103
0
    }
8104
8105
    // add replacement and update its path
8106
0
    SourceCodeInfo_Location* replacement = new_locs.Add();
8107
0
    *replacement = *loc;
8108
0
    replacement->clear_path();
8109
0
    for (std::vector<int>::iterator rit = entry->second.begin();
8110
0
         rit != entry->second.end(); rit++) {
8111
0
      replacement->add_path(*rit);
8112
0
    }
8113
0
  }
8114
8115
  // if we made a changed copy, put it in place
8116
0
  if (copying) {
8117
0
    *locs = new_locs;
8118
0
  }
8119
0
}
8120
8121
void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting(
8122
0
    const UninterpretedOption& uninterpreted_option, Message* options) {
8123
0
  const FieldDescriptor* field =
8124
0
      options->GetDescriptor()->FindFieldByName("uninterpreted_option");
8125
0
  ABSL_CHECK(field != nullptr);
8126
8127
0
  options->GetReflection()
8128
0
      ->AddMessage(options, field)
8129
0
      ->CopyFrom(uninterpreted_option);
8130
0
}
8131
8132
bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
8133
    std::vector<const FieldDescriptor*>::const_iterator
8134
        intermediate_fields_iter,
8135
    std::vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
8136
    const FieldDescriptor* innermost_field, const std::string& debug_msg_name,
8137
0
    const UnknownFieldSet& unknown_fields) {
8138
  // We do linear searches of the UnknownFieldSet and its sub-groups.  This
8139
  // should be fine since it's unlikely that any one options structure will
8140
  // contain more than a handful of options.
8141
8142
0
  if (intermediate_fields_iter == intermediate_fields_end) {
8143
    // We're at the innermost submessage.
8144
0
    for (int i = 0; i < unknown_fields.field_count(); i++) {
8145
0
      if (unknown_fields.field(i).number() == innermost_field->number()) {
8146
0
        return AddNameError([&] {
8147
0
          return absl::StrCat("Option \"", debug_msg_name,
8148
0
                              "\" was already set.");
8149
0
        });
8150
0
      }
8151
0
    }
8152
0
    return true;
8153
0
  }
8154
8155
0
  for (int i = 0; i < unknown_fields.field_count(); i++) {
8156
0
    if (unknown_fields.field(i).number() ==
8157
0
        (*intermediate_fields_iter)->number()) {
8158
0
      const UnknownField* unknown_field = &unknown_fields.field(i);
8159
0
      FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
8160
      // Recurse into the next submessage.
8161
0
      switch (type) {
8162
0
        case FieldDescriptor::TYPE_MESSAGE:
8163
0
          if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
8164
0
            UnknownFieldSet intermediate_unknown_fields;
8165
0
            if (intermediate_unknown_fields.ParseFromString(
8166
0
                    unknown_field->length_delimited()) &&
8167
0
                !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
8168
0
                                      intermediate_fields_end, innermost_field,
8169
0
                                      debug_msg_name,
8170
0
                                      intermediate_unknown_fields)) {
8171
0
              return false;  // Error already added.
8172
0
            }
8173
0
          }
8174
0
          break;
8175
8176
0
        case FieldDescriptor::TYPE_GROUP:
8177
0
          if (unknown_field->type() == UnknownField::TYPE_GROUP) {
8178
0
            if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
8179
0
                                      intermediate_fields_end, innermost_field,
8180
0
                                      debug_msg_name, unknown_field->group())) {
8181
0
              return false;  // Error already added.
8182
0
            }
8183
0
          }
8184
0
          break;
8185
8186
0
        default:
8187
0
          ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type;
8188
0
          return false;
8189
0
      }
8190
0
    }
8191
0
  }
8192
0
  return true;
8193
0
}
8194
8195
namespace {
8196
// Helpers for method below
8197
8198
template <typename T> std::string ValueOutOfRange(
8199
0
    absl::string_view type_name, absl::string_view option_name) {
8200
0
  return absl::StrFormat(
8201
0
    "Value out of range, %d to %d, for %s option \"%s\".", \
8202
0
    std::numeric_limits<T>::min(), std::numeric_limits<T>::max(),
8203
0
    type_name, option_name);
8204
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>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueOutOfRange<long>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
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>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
8205
8206
template <typename T> std::string ValueMustBeInt(
8207
0
    absl::string_view type_name, absl::string_view option_name) {
8208
0
  return absl::StrFormat(
8209
0
    "Value must be integer, from %d to %d, for %s option \"%s\".", \
8210
0
    std::numeric_limits<T>::min(), std::numeric_limits<T>::max(),
8211
0
    type_name, option_name);
8212
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>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueMustBeInt<long>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
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>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
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>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
8213
8214
} // namespace
8215
8216
bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
8217
0
    const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
8218
  // We switch on the CppType to validate.
8219
0
  switch (option_field->cpp_type()) {
8220
0
    case FieldDescriptor::CPPTYPE_INT32:
8221
0
      if (uninterpreted_option_->has_positive_int_value()) {
8222
0
        if (uninterpreted_option_->positive_int_value() >
8223
0
            static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
8224
0
          return AddValueError([&] {
8225
0
            return ValueOutOfRange<int32_t>("int32", option_field->full_name());
8226
0
          });
8227
0
        } else {
8228
0
          SetInt32(option_field->number(),
8229
0
                   uninterpreted_option_->positive_int_value(),
8230
0
                   option_field->type(), unknown_fields);
8231
0
        }
8232
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
8233
0
        if (uninterpreted_option_->negative_int_value() <
8234
0
            static_cast<int64_t>(std::numeric_limits<int32_t>::min())) {
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_->negative_int_value(),
8241
0
                   option_field->type(), unknown_fields);
8242
0
        }
8243
0
      } else {
8244
0
        return AddValueError([&] {
8245
0
          return ValueMustBeInt<int32_t>("int32", option_field->full_name());
8246
0
        });
8247
0
      }
8248
0
      break;
8249
8250
0
    case FieldDescriptor::CPPTYPE_INT64:
8251
0
      if (uninterpreted_option_->has_positive_int_value()) {
8252
0
        if (uninterpreted_option_->positive_int_value() >
8253
0
            static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
8254
0
          return AddValueError([&] {
8255
0
            return ValueOutOfRange<int64_t>("int64", option_field->full_name());
8256
0
          });
8257
0
        } else {
8258
0
          SetInt64(option_field->number(),
8259
0
                   uninterpreted_option_->positive_int_value(),
8260
0
                   option_field->type(), unknown_fields);
8261
0
        }
8262
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
8263
0
        SetInt64(option_field->number(),
8264
0
                 uninterpreted_option_->negative_int_value(),
8265
0
                 option_field->type(), unknown_fields);
8266
0
      } else {
8267
0
        return AddValueError([&] {
8268
0
          return ValueMustBeInt<int64_t>("int64", option_field->full_name());
8269
0
        });
8270
0
      }
8271
0
      break;
8272
8273
0
    case FieldDescriptor::CPPTYPE_UINT32:
8274
0
      if (uninterpreted_option_->has_positive_int_value()) {
8275
0
        if (uninterpreted_option_->positive_int_value() >
8276
0
            std::numeric_limits<uint32_t>::max()) {
8277
0
          return AddValueError([&] {
8278
0
            return ValueOutOfRange<uint32_t>("uint32",
8279
0
                                             option_field->full_name());
8280
0
          });
8281
0
        } else {
8282
0
          SetUInt32(option_field->number(),
8283
0
                    uninterpreted_option_->positive_int_value(),
8284
0
                    option_field->type(), unknown_fields);
8285
0
        }
8286
0
      } else {
8287
0
        return AddValueError([&] {
8288
0
          return ValueMustBeInt<uint32_t>("uint32", option_field->full_name());
8289
0
        });
8290
0
      }
8291
0
      break;
8292
8293
0
    case FieldDescriptor::CPPTYPE_UINT64:
8294
0
      if (uninterpreted_option_->has_positive_int_value()) {
8295
0
        SetUInt64(option_field->number(),
8296
0
                  uninterpreted_option_->positive_int_value(),
8297
0
                  option_field->type(), unknown_fields);
8298
0
      } else {
8299
0
        return AddValueError([&] {
8300
0
          return ValueMustBeInt<uint64_t>("uint64", option_field->full_name());
8301
0
        });
8302
0
      }
8303
0
      break;
8304
8305
0
    case FieldDescriptor::CPPTYPE_FLOAT: {
8306
0
      float value;
8307
0
      if (uninterpreted_option_->has_double_value()) {
8308
0
        value = uninterpreted_option_->double_value();
8309
0
      } else if (uninterpreted_option_->has_positive_int_value()) {
8310
0
        value = uninterpreted_option_->positive_int_value();
8311
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
8312
0
        value = uninterpreted_option_->negative_int_value();
8313
0
      } else {
8314
0
        return AddValueError([&] {
8315
0
          return absl::StrCat("Value must be number for float option \"",
8316
0
                              option_field->full_name(), "\".");
8317
0
        });
8318
0
      }
8319
0
      unknown_fields->AddFixed32(option_field->number(),
8320
0
                                 internal::WireFormatLite::EncodeFloat(value));
8321
0
      break;
8322
0
    }
8323
8324
0
    case FieldDescriptor::CPPTYPE_DOUBLE: {
8325
0
      double value;
8326
0
      if (uninterpreted_option_->has_double_value()) {
8327
0
        value = uninterpreted_option_->double_value();
8328
0
      } else if (uninterpreted_option_->has_positive_int_value()) {
8329
0
        value = uninterpreted_option_->positive_int_value();
8330
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
8331
0
        value = uninterpreted_option_->negative_int_value();
8332
0
      } else {
8333
0
        return AddValueError([&] {
8334
0
          return absl::StrCat("Value must be number for double option \"",
8335
0
                              option_field->full_name(), "\".");
8336
0
        });
8337
0
      }
8338
0
      unknown_fields->AddFixed64(option_field->number(),
8339
0
                                 internal::WireFormatLite::EncodeDouble(value));
8340
0
      break;
8341
0
    }
8342
8343
0
    case FieldDescriptor::CPPTYPE_BOOL:
8344
0
      uint64_t value;
8345
0
      if (!uninterpreted_option_->has_identifier_value()) {
8346
0
        return AddValueError([&] {
8347
0
          return absl::StrCat("Value must be identifier for boolean option \"",
8348
0
                              option_field->full_name(), "\".");
8349
0
        });
8350
0
      }
8351
0
      if (uninterpreted_option_->identifier_value() == "true") {
8352
0
        value = 1;
8353
0
      } else if (uninterpreted_option_->identifier_value() == "false") {
8354
0
        value = 0;
8355
0
      } else {
8356
0
        return AddValueError([&] {
8357
0
          return absl::StrCat(
8358
0
              "Value must be \"true\" or \"false\" for boolean option \"",
8359
0
              option_field->full_name(), "\".");
8360
0
        });
8361
0
      }
8362
0
      unknown_fields->AddVarint(option_field->number(), value);
8363
0
      break;
8364
8365
0
    case FieldDescriptor::CPPTYPE_ENUM: {
8366
0
      if (!uninterpreted_option_->has_identifier_value()) {
8367
0
        return AddValueError([&] {
8368
0
          return absl::StrCat(
8369
0
              "Value must be identifier for enum-valued option \"",
8370
0
              option_field->full_name(), "\".");
8371
0
        });
8372
0
      }
8373
0
      const EnumDescriptor* enum_type = option_field->enum_type();
8374
0
      const std::string& value_name = uninterpreted_option_->identifier_value();
8375
0
      const EnumValueDescriptor* enum_value = nullptr;
8376
8377
0
      if (enum_type->file()->pool() != DescriptorPool::generated_pool()) {
8378
        // Note that the enum value's fully-qualified name is a sibling of the
8379
        // enum's name, not a child of it.
8380
0
        std::string fully_qualified_name = enum_type->full_name();
8381
0
        fully_qualified_name.resize(fully_qualified_name.size() -
8382
0
                                    enum_type->name().size());
8383
0
        fully_qualified_name += value_name;
8384
8385
        // Search for the enum value's descriptor in the builder's pool. Note
8386
        // that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
8387
        // DescriptorPool::FindEnumValueByName() because we're already holding
8388
        // the pool's mutex, and the latter method locks it again.
8389
0
        Symbol symbol =
8390
0
            builder_->FindSymbolNotEnforcingDeps(fully_qualified_name);
8391
0
        if (auto* candicate_descriptor = symbol.enum_value_descriptor()) {
8392
0
          if (candicate_descriptor->type() != enum_type) {
8393
0
            return AddValueError([&] {
8394
0
              return absl::StrCat(
8395
0
                  "Enum type \"", enum_type->full_name(),
8396
0
                  "\" has no value named \"", value_name, "\" for option \"",
8397
0
                  option_field->full_name(),
8398
0
                  "\". This appears to be a value from a sibling type.");
8399
0
            });
8400
0
          } else {
8401
0
            enum_value = candicate_descriptor;
8402
0
          }
8403
0
        }
8404
0
      } else {
8405
        // The enum type is in the generated pool, so we can search for the
8406
        // value there.
8407
0
        enum_value = enum_type->FindValueByName(value_name);
8408
0
      }
8409
8410
0
      if (enum_value == nullptr) {
8411
0
        return AddValueError([&] {
8412
0
          return absl::StrCat(
8413
0
              "Enum type \"", option_field->enum_type()->full_name(),
8414
0
              "\" has no value named \"", value_name, "\" for option \"",
8415
0
              option_field->full_name(), "\".");
8416
0
        });
8417
0
      } else {
8418
        // Sign-extension is not a problem, since we cast directly from int32_t
8419
        // to uint64_t, without first going through uint32_t.
8420
0
        unknown_fields->AddVarint(
8421
0
            option_field->number(),
8422
0
            static_cast<uint64_t>(static_cast<int64_t>(enum_value->number())));
8423
0
      }
8424
0
      break;
8425
0
    }
8426
8427
0
    case FieldDescriptor::CPPTYPE_STRING:
8428
0
      if (!uninterpreted_option_->has_string_value()) {
8429
0
        return AddValueError([&] {
8430
0
          return absl::StrCat(
8431
0
              "Value must be quoted string for string option \"",
8432
0
              option_field->full_name(), "\".");
8433
0
        });
8434
0
      }
8435
      // The string has already been unquoted and unescaped by the parser.
8436
0
      unknown_fields->AddLengthDelimited(option_field->number(),
8437
0
                                         uninterpreted_option_->string_value());
8438
0
      break;
8439
8440
0
    case FieldDescriptor::CPPTYPE_MESSAGE:
8441
0
      if (!SetAggregateOption(option_field, unknown_fields)) {
8442
0
        return false;
8443
0
      }
8444
0
      break;
8445
0
  }
8446
8447
0
  return true;
8448
0
}
8449
8450
class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
8451
    : public TextFormat::Finder {
8452
 public:
8453
  DescriptorBuilder* builder_;
8454
8455
  const Descriptor* FindAnyType(const Message& /*message*/,
8456
                                const std::string& prefix,
8457
0
                                const std::string& name) const override {
8458
0
    if (prefix != internal::kTypeGoogleApisComPrefix &&
8459
0
        prefix != internal::kTypeGoogleProdComPrefix) {
8460
0
      return nullptr;
8461
0
    }
8462
0
    assert_mutex_held(builder_->pool_);
8463
0
    return builder_->FindSymbol(name).descriptor();
8464
0
  }
8465
8466
  const FieldDescriptor* FindExtension(Message* message,
8467
0
                                       const std::string& name) const override {
8468
0
    assert_mutex_held(builder_->pool_);
8469
0
    const Descriptor* descriptor = message->GetDescriptor();
8470
0
    Symbol result =
8471
0
        builder_->LookupSymbolNoPlaceholder(name, descriptor->full_name());
8472
0
    if (auto* field = result.field_descriptor()) {
8473
0
      return field;
8474
0
    } else if (result.type() == Symbol::MESSAGE &&
8475
0
               descriptor->options().message_set_wire_format()) {
8476
0
      const Descriptor* foreign_type = result.descriptor();
8477
      // The text format allows MessageSet items to be specified using
8478
      // the type name, rather than the extension identifier. If the symbol
8479
      // lookup returned a Message, and the enclosing Message has
8480
      // message_set_wire_format = true, then return the message set
8481
      // extension, if one exists.
8482
0
      for (int i = 0; i < foreign_type->extension_count(); i++) {
8483
0
        const FieldDescriptor* extension = foreign_type->extension(i);
8484
0
        if (extension->containing_type() == descriptor &&
8485
0
            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
8486
0
            extension->is_optional() &&
8487
0
            extension->message_type() == foreign_type) {
8488
          // Found it.
8489
0
          return extension;
8490
0
        }
8491
0
      }
8492
0
    }
8493
0
    return nullptr;
8494
0
  }
8495
};
8496
8497
// A custom error collector to record any text-format parsing errors
8498
namespace {
8499
class AggregateErrorCollector : public io::ErrorCollector {
8500
 public:
8501
  std::string error_;
8502
8503
  void RecordError(int /* line */, int /* column */,
8504
0
                   const absl::string_view message) override {
8505
0
    if (!error_.empty()) {
8506
0
      absl::StrAppend(&error_, "; ");
8507
0
    }
8508
0
    absl::StrAppend(&error_, message);
8509
0
  }
8510
8511
  void RecordWarning(int /* line */, int /* column */,
8512
0
                     const absl::string_view /* message */) override {
8513
    // Ignore warnings
8514
0
  }
8515
};
8516
}  // namespace
8517
8518
// We construct a dynamic message of the type corresponding to
8519
// option_field, parse the supplied text-format string into this
8520
// message, and serialize the resulting message to produce the value.
8521
bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
8522
0
    const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
8523
0
  if (!uninterpreted_option_->has_aggregate_value()) {
8524
0
    return AddValueError([&] {
8525
0
      return absl::StrCat("Option \"", option_field->full_name(),
8526
0
                          "\" is a message. "
8527
0
                          "To set the entire message, use syntax like \"",
8528
0
                          option_field->name(),
8529
0
                          " = { <proto text format> }\". "
8530
0
                          "To set fields within it, use syntax like \"",
8531
0
                          option_field->name(), ".foo = value\".");
8532
0
    });
8533
0
  }
8534
8535
0
  const Descriptor* type = option_field->message_type();
8536
0
  std::unique_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
8537
0
  ABSL_CHECK(dynamic.get() != nullptr)
8538
0
      << "Could not create an instance of " << option_field->DebugString();
8539
8540
0
  AggregateErrorCollector collector;
8541
0
  AggregateOptionFinder finder;
8542
0
  finder.builder_ = builder_;
8543
0
  TextFormat::Parser parser;
8544
0
  parser.RecordErrorsTo(&collector);
8545
0
  parser.SetFinder(&finder);
8546
0
  if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
8547
0
                              dynamic.get())) {
8548
0
    AddValueError([&] {
8549
0
      return absl::StrCat("Error while parsing option value for \"",
8550
0
                          option_field->name(), "\": ", collector.error_);
8551
0
    });
8552
0
    return false;
8553
0
  } else {
8554
0
    std::string serial;
8555
0
    dynamic->SerializeToString(&serial);  // Never fails
8556
0
    if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) {
8557
0
      unknown_fields->AddLengthDelimited(option_field->number(), serial);
8558
0
    } else {
8559
0
      ABSL_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP);
8560
0
      UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number());
8561
0
      group->ParseFromString(serial);
8562
0
    }
8563
0
    return true;
8564
0
  }
8565
0
}
8566
8567
void DescriptorBuilder::OptionInterpreter::SetInt32(
8568
    int number, int32_t value, FieldDescriptor::Type type,
8569
0
    UnknownFieldSet* unknown_fields) {
8570
0
  switch (type) {
8571
0
    case FieldDescriptor::TYPE_INT32:
8572
0
      unknown_fields->AddVarint(
8573
0
          number, static_cast<uint64_t>(static_cast<int64_t>(value)));
8574
0
      break;
8575
8576
0
    case FieldDescriptor::TYPE_SFIXED32:
8577
0
      unknown_fields->AddFixed32(number, static_cast<uint32_t>(value));
8578
0
      break;
8579
8580
0
    case FieldDescriptor::TYPE_SINT32:
8581
0
      unknown_fields->AddVarint(
8582
0
          number, internal::WireFormatLite::ZigZagEncode32(value));
8583
0
      break;
8584
8585
0
    default:
8586
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT32: " << type;
8587
0
      break;
8588
0
  }
8589
0
}
8590
8591
void DescriptorBuilder::OptionInterpreter::SetInt64(
8592
    int number, int64_t value, FieldDescriptor::Type type,
8593
0
    UnknownFieldSet* unknown_fields) {
8594
0
  switch (type) {
8595
0
    case FieldDescriptor::TYPE_INT64:
8596
0
      unknown_fields->AddVarint(number, static_cast<uint64_t>(value));
8597
0
      break;
8598
8599
0
    case FieldDescriptor::TYPE_SFIXED64:
8600
0
      unknown_fields->AddFixed64(number, static_cast<uint64_t>(value));
8601
0
      break;
8602
8603
0
    case FieldDescriptor::TYPE_SINT64:
8604
0
      unknown_fields->AddVarint(
8605
0
          number, internal::WireFormatLite::ZigZagEncode64(value));
8606
0
      break;
8607
8608
0
    default:
8609
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT64: " << type;
8610
0
      break;
8611
0
  }
8612
0
}
8613
8614
void DescriptorBuilder::OptionInterpreter::SetUInt32(
8615
    int number, uint32_t value, FieldDescriptor::Type type,
8616
0
    UnknownFieldSet* unknown_fields) {
8617
0
  switch (type) {
8618
0
    case FieldDescriptor::TYPE_UINT32:
8619
0
      unknown_fields->AddVarint(number, static_cast<uint64_t>(value));
8620
0
      break;
8621
8622
0
    case FieldDescriptor::TYPE_FIXED32:
8623
0
      unknown_fields->AddFixed32(number, static_cast<uint32_t>(value));
8624
0
      break;
8625
8626
0
    default:
8627
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT32: " << type;
8628
0
      break;
8629
0
  }
8630
0
}
8631
8632
void DescriptorBuilder::OptionInterpreter::SetUInt64(
8633
    int number, uint64_t value, FieldDescriptor::Type type,
8634
0
    UnknownFieldSet* unknown_fields) {
8635
0
  switch (type) {
8636
0
    case FieldDescriptor::TYPE_UINT64:
8637
0
      unknown_fields->AddVarint(number, value);
8638
0
      break;
8639
8640
0
    case FieldDescriptor::TYPE_FIXED64:
8641
0
      unknown_fields->AddFixed64(number, value);
8642
0
      break;
8643
8644
0
    default:
8645
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT64: " << type;
8646
0
      break;
8647
0
  }
8648
0
}
8649
8650
void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto,
8651
0
                                            const FileDescriptor* result) {
8652
0
  (void)result;  // Parameter is used by Google-internal code.
8653
8654
0
  if (!unused_dependency_.empty()) {
8655
0
    auto itr = pool_->unused_import_track_files_.find(proto.name());
8656
0
    bool is_error =
8657
0
        itr != pool_->unused_import_track_files_.end() && itr->second;
8658
0
    for (const auto* unused : unused_dependency_) {
8659
0
      auto make_error = [&] {
8660
0
        return absl::StrCat("Import ", unused->name(), " is unused.");
8661
0
      };
8662
0
      if (is_error) {
8663
0
        AddError(unused->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
8664
0
                 make_error);
8665
0
      } else {
8666
0
        AddWarning(unused->name(), proto,
8667
0
                   DescriptorPool::ErrorCollector::IMPORT, make_error);
8668
0
      }
8669
0
    }
8670
0
  }
8671
0
}
8672
8673
Symbol DescriptorPool::CrossLinkOnDemandHelper(absl::string_view name,
8674
0
                                               bool expecting_enum) const {
8675
0
  (void)expecting_enum;  // Parameter is used by Google-internal code.
8676
0
  auto lookup_name = std::string(name);
8677
0
  if (!lookup_name.empty() && lookup_name[0] == '.') {
8678
0
    lookup_name = lookup_name.substr(1);
8679
0
  }
8680
0
  Symbol result = tables_->FindByNameHelper(this, lookup_name);
8681
0
  return result;
8682
0
}
8683
8684
// Handle the lazy import building for a message field whose type wasn't built
8685
// at cross link time. If that was the case, we saved the name of the type to
8686
// be looked up when the accessor for the type was called. Set type_,
8687
// enum_type_, message_type_, and default_value_enum_ appropriately.
8688
0
void FieldDescriptor::InternalTypeOnceInit() const {
8689
0
  ABSL_CHECK(file()->finished_building_ == true);
8690
0
  const EnumDescriptor* enum_type = nullptr;
8691
0
  const char* lazy_type_name = reinterpret_cast<const char*>(type_once_ + 1);
8692
0
  const char* lazy_default_value_enum_name =
8693
0
      lazy_type_name + strlen(lazy_type_name) + 1;
8694
0
  Symbol result = file()->pool()->CrossLinkOnDemandHelper(
8695
0
      lazy_type_name, type_ == FieldDescriptor::TYPE_ENUM);
8696
0
  if (result.type() == Symbol::MESSAGE) {
8697
0
    type_ = FieldDescriptor::TYPE_MESSAGE;
8698
0
    type_descriptor_.message_type = result.descriptor();
8699
0
  } else if (result.type() == Symbol::ENUM) {
8700
0
    type_ = FieldDescriptor::TYPE_ENUM;
8701
0
    enum_type = type_descriptor_.enum_type = result.enum_descriptor();
8702
0
  }
8703
8704
0
  if (enum_type) {
8705
0
    if (lazy_default_value_enum_name[0] != '\0') {
8706
      // Have to build the full name now instead of at CrossLink time,
8707
      // because enum_type may not be known at the time.
8708
0
      std::string name = enum_type->full_name();
8709
      // Enum values reside in the same scope as the enum type.
8710
0
      std::string::size_type last_dot = name.find_last_of('.');
8711
0
      if (last_dot != std::string::npos) {
8712
0
        name = absl::StrCat(name.substr(0, last_dot), ".",
8713
0
                            lazy_default_value_enum_name);
8714
0
      } else {
8715
0
        name = lazy_default_value_enum_name;
8716
0
      }
8717
0
      Symbol result = file()->pool()->CrossLinkOnDemandHelper(name, true);
8718
0
      default_value_enum_ = result.enum_value_descriptor();
8719
0
    } else {
8720
0
      default_value_enum_ = nullptr;
8721
0
    }
8722
0
    if (!default_value_enum_) {
8723
      // We use the first defined value as the default
8724
      // if a default is not explicitly defined.
8725
0
      ABSL_CHECK(enum_type->value_count());
8726
0
      default_value_enum_ = enum_type->value(0);
8727
0
    }
8728
0
  }
8729
0
}
8730
8731
0
void FieldDescriptor::TypeOnceInit(const FieldDescriptor* to_init) {
8732
0
  to_init->InternalTypeOnceInit();
8733
0
}
8734
8735
// message_type(), enum_type(), default_value_enum(), and type()
8736
// all share the same absl::call_once init path to do lazy
8737
// import building and cross linking of a field of a message.
8738
0
const Descriptor* FieldDescriptor::message_type() const {
8739
0
  if (type_once_) {
8740
0
    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
8741
0
  }
8742
0
  return type_ == TYPE_MESSAGE || type_ == TYPE_GROUP
8743
0
             ? type_descriptor_.message_type
8744
0
             : nullptr;
8745
0
}
8746
8747
0
const EnumDescriptor* FieldDescriptor::enum_type() const {
8748
0
  if (type_once_) {
8749
0
    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
8750
0
  }
8751
0
  return type_ == TYPE_ENUM ? type_descriptor_.enum_type : nullptr;
8752
0
}
8753
8754
0
const EnumValueDescriptor* FieldDescriptor::default_value_enum() const {
8755
0
  if (type_once_) {
8756
0
    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
8757
0
  }
8758
0
  return default_value_enum_;
8759
0
}
8760
8761
0
const std::string& FieldDescriptor::PrintableNameForExtension() const {
8762
0
  const bool is_message_set_extension =
8763
0
      is_extension() &&
8764
0
      containing_type()->options().message_set_wire_format() &&
8765
0
      type() == FieldDescriptor::TYPE_MESSAGE && is_optional() &&
8766
0
      extension_scope() == message_type();
8767
0
  return is_message_set_extension ? message_type()->full_name() : full_name();
8768
0
}
8769
8770
0
void FileDescriptor::InternalDependenciesOnceInit() const {
8771
0
  ABSL_CHECK(finished_building_ == true);
8772
0
  const char* names_ptr = reinterpret_cast<const char*>(dependencies_once_ + 1);
8773
0
  for (int i = 0; i < dependency_count(); i++) {
8774
0
    const char* name = names_ptr;
8775
0
    names_ptr += strlen(name) + 1;
8776
0
    if (name[0] != '\0') {
8777
0
      dependencies_[i] = pool_->FindFileByName(name);
8778
0
    }
8779
0
  }
8780
0
}
8781
8782
0
void FileDescriptor::DependenciesOnceInit(const FileDescriptor* to_init) {
8783
0
  to_init->InternalDependenciesOnceInit();
8784
0
}
8785
8786
0
const FileDescriptor* FileDescriptor::dependency(int index) const {
8787
0
  if (dependencies_once_) {
8788
    // Do once init for all indices, as it's unlikely only a single index would
8789
    // be called, and saves on absl::call_once allocations.
8790
0
    absl::call_once(*dependencies_once_, FileDescriptor::DependenciesOnceInit,
8791
0
                    this);
8792
0
  }
8793
0
  return dependencies_[index];
8794
0
}
8795
8796
0
const Descriptor* MethodDescriptor::input_type() const {
8797
0
  return input_type_.Get(service());
8798
0
}
8799
8800
0
const Descriptor* MethodDescriptor::output_type() const {
8801
0
  return output_type_.Get(service());
8802
0
}
8803
8804
namespace internal {
8805
0
void LazyDescriptor::Set(const Descriptor* descriptor) {
8806
0
  ABSL_CHECK(!once_);
8807
0
  descriptor_ = descriptor;
8808
0
}
8809
8810
void LazyDescriptor::SetLazy(absl::string_view name,
8811
0
                             const FileDescriptor* file) {
8812
  // verify Init() has been called and Set hasn't been called yet.
8813
0
  ABSL_CHECK(!descriptor_);
8814
0
  ABSL_CHECK(!once_);
8815
0
  ABSL_CHECK(file && file->pool_);
8816
0
  ABSL_CHECK(file->pool_->lazily_build_dependencies_);
8817
0
  ABSL_CHECK(!file->finished_building_);
8818
0
  once_ = ::new (file->pool_->tables_->AllocateBytes(static_cast<int>(
8819
0
      sizeof(absl::once_flag) + name.size() + 1))) absl::once_flag{};
8820
0
  char* lazy_name = reinterpret_cast<char*>(once_ + 1);
8821
0
  memcpy(lazy_name, name.data(), name.size());
8822
0
  lazy_name[name.size()] = 0;
8823
0
}
8824
8825
0
void LazyDescriptor::Once(const ServiceDescriptor* service) {
8826
0
  if (once_) {
8827
0
    absl::call_once(*once_, [&] {
8828
0
      auto* file = service->file();
8829
0
      ABSL_CHECK(file->finished_building_);
8830
0
      const char* lazy_name = reinterpret_cast<const char*>(once_ + 1);
8831
0
      descriptor_ =
8832
0
          file->pool_->CrossLinkOnDemandHelper(lazy_name, false).descriptor();
8833
0
    });
8834
0
  }
8835
0
}
8836
8837
namespace cpp {
8838
0
bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) {
8839
0
  return !field->legacy_enum_field_treated_as_closed();
8840
0
}
8841
8842
0
bool HasHasbit(const FieldDescriptor* field) {
8843
0
  return field->has_presence() && !field->real_containing_oneof() &&
8844
0
         !field->options().weak();
8845
0
}
8846
8847
0
static bool FieldEnforceUtf8(const FieldDescriptor* field) {
8848
0
  return true;
8849
0
}
8850
8851
0
static bool FileUtf8Verification(const FileDescriptor* file) {
8852
0
  return true;
8853
0
}
8854
8855
// Which level of UTF-8 enforcemant is placed on this file.
8856
0
Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, bool is_lite) {
8857
0
  if (FileDescriptorLegacy(field->file()).syntax() ==
8858
0
          FileDescriptorLegacy::Syntax::SYNTAX_PROTO3 &&
8859
0
      FieldEnforceUtf8(field)) {
8860
0
    return Utf8CheckMode::kStrict;
8861
0
  } else if (!is_lite && FileUtf8Verification(field->file())) {
8862
0
    return Utf8CheckMode::kVerify;
8863
0
  } else {
8864
0
    return Utf8CheckMode::kNone;
8865
0
  }
8866
0
}
8867
8868
}  // namespace cpp
8869
}  // namespace internal
8870
8871
}  // namespace protobuf
8872
}  // namespace google
8873
8874
#include "google/protobuf/port_undef.inc"