Coverage Report

Created: 2023-11-19 07:09

/src/libprotobuf-mutator/build/external.protobuf/src/external.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/hash/hash.h"
57
#include "absl/log/absl_check.h"
58
#include "absl/log/absl_log.h"
59
#include "absl/strings/ascii.h"
60
#include "absl/strings/escaping.h"
61
#include "absl/strings/match.h"
62
#include "absl/strings/str_cat.h"
63
#include "absl/strings/str_format.h"
64
#include "absl/strings/str_join.h"
65
#include "absl/strings/str_split.h"
66
#include "absl/strings/string_view.h"
67
#include "absl/strings/strip.h"
68
#include "absl/strings/substitute.h"
69
#include "absl/synchronization/mutex.h"
70
#include "absl/types/optional.h"
71
#include "google/protobuf/any.h"
72
#include "google/protobuf/descriptor.pb.h"
73
#include "google/protobuf/descriptor_database.h"
74
#include "google/protobuf/dynamic_message.h"
75
#include "google/protobuf/generated_message_util.h"
76
#include "google/protobuf/io/strtod.h"
77
#include "google/protobuf/io/tokenizer.h"
78
#include "google/protobuf/port.h"
79
#include "google/protobuf/text_format.h"
80
#include "google/protobuf/unknown_field_set.h"
81
82
83
// Must be included last.
84
#include "google/protobuf/port_def.inc"
85
86
namespace google {
87
namespace protobuf {
88
namespace {
89
using ::google::protobuf::internal::DownCast;
90
91
const int kPackageLimit = 100;
92
93
94
150
std::string ToCamelCase(const std::string& input, bool lower_first) {
95
150
  bool capitalize_next = !lower_first;
96
150
  std::string result;
97
150
  result.reserve(input.size());
98
99
2.39k
  for (char character : input) {
100
2.39k
    if (character == '_') {
101
208
      capitalize_next = true;
102
2.18k
    } else if (capitalize_next) {
103
208
      result.push_back(absl::ascii_toupper(character));
104
208
      capitalize_next = false;
105
1.98k
    } else {
106
1.98k
      result.push_back(character);
107
1.98k
    }
108
2.39k
  }
109
110
  // Lower-case the first letter.
111
150
  if (lower_first && !result.empty()) {
112
150
    result[0] = absl::ascii_tolower(result[0]);
113
150
  }
114
115
150
  return result;
116
150
}
117
118
0
std::string ToJsonName(const std::string& input) {
119
0
  bool capitalize_next = false;
120
0
  std::string result;
121
0
  result.reserve(input.size());
122
123
0
  for (char character : input) {
124
0
    if (character == '_') {
125
0
      capitalize_next = true;
126
0
    } else if (capitalize_next) {
127
0
      result.push_back(absl::ascii_toupper(character));
128
0
      capitalize_next = false;
129
0
    } else {
130
0
      result.push_back(character);
131
0
    }
132
0
  }
133
134
0
  return result;
135
0
}
136
137
template <typename OptionsT>
138
0
bool IsLegacyJsonFieldConflictEnabled(const OptionsT& options) {
139
0
#ifdef __GNUC__
140
0
#pragma GCC diagnostic push
141
0
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
142
0
#endif
143
0
  return options.deprecated_legacy_json_field_conflicts();
144
0
#ifdef __GNUC__
145
0
#pragma GCC diagnostic pop
146
0
#endif
147
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&)
148
149
// Backport of fold expressions for the comma operator to C++11.
150
// Usage:  Fold({expr...});
151
// Guaranteed to evaluate left-to-right
152
struct ExpressionEater {
153
  template <typename T>
154
1.60k
  ExpressionEater(T&&) {}  // NOLINT
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> >&)
Line
Count
Source
154
1.21k
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<bool>(bool&&)
Line
Count
Source
154
156
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<int&>(int&)
Line
Count
Source
154
156
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<char*&>(char*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
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> >*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::SourceCodeInfo*&>(google::protobuf::SourceCodeInfo*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::FileDescriptorTables*&>(google::protobuf::FileDescriptorTables*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::MessageOptions*&>(google::protobuf::MessageOptions*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::FieldOptions*&>(google::protobuf::FieldOptions*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::EnumOptions*&>(google::protobuf::EnumOptions*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::EnumValueOptions*&>(google::protobuf::EnumValueOptions*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::ExtensionRangeOptions*&>(google::protobuf::ExtensionRangeOptions*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::OneofOptions*&>(google::protobuf::OneofOptions*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::ServiceOptions*&>(google::protobuf::ServiceOptions*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::MethodOptions*&>(google::protobuf::MethodOptions*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
descriptor.cc:google::protobuf::(anonymous namespace)::ExpressionEater::ExpressionEater<google::protobuf::FileOptions*&>(google::protobuf::FileOptions*&)
Line
Count
Source
154
6
  ExpressionEater(T&&) {}  // NOLINT
155
};
156
568
void Fold(std::initializer_list<ExpressionEater>) {}
157
158
template <int R>
159
1.51k
constexpr size_t RoundUpTo(size_t n) {
160
1.51k
  static_assert((R & (R - 1)) == 0, "Must be power of two");
161
1.51k
  return (n + (R - 1)) & ~(R - 1);
162
1.51k
}
163
164
0
constexpr size_t Max(size_t a, size_t b) { return a > b ? a : b; }
165
template <typename T, typename... Ts>
166
0
constexpr size_t Max(T a, Ts... b) {
167
0
  return Max(a, Max(b...));
168
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)
169
170
template <typename T>
171
0
constexpr size_t EffectiveAlignof() {
172
0
  // `char` is special in that it gets aligned to 8. It is where we drop the
173
0
  // trivial structs.
174
0
  return std::is_same<T, char>::value ? 8 : alignof(T);
175
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>()
176
177
template <int align, typename U, typename... T>
178
using AppendIfAlign =
179
    typename std::conditional<EffectiveAlignof<U>() == align, void (*)(T..., U),
180
                              void (*)(T...)>::type;
181
182
// Metafunction to sort types in descending order of alignment.
183
// Useful for the flat allocator to ensure proper alignment of all elements
184
// without having to add padding.
185
// Instead of implementing a proper sort metafunction we just do a
186
// filter+merge, which is much simpler to write as a metafunction.
187
// We have a fixed set of alignments we can filter on.
188
// For simplicity we use a function pointer as a type list.
189
template <typename In, typename T16, typename T8, typename T4, typename T2,
190
          typename T1>
191
struct TypeListSortImpl;
192
193
template <typename... T16, typename... T8, typename... T4, typename... T2,
194
          typename... T1>
195
struct TypeListSortImpl<void (*)(), void (*)(T16...), void (*)(T8...),
196
                        void (*)(T4...), void (*)(T2...), void (*)(T1...)> {
197
  using type = void (*)(T16..., T8..., T4..., T2..., T1...);
198
};
199
200
template <typename First, typename... Rest, typename... T16, typename... T8,
201
          typename... T4, typename... T2, typename... T1>
202
struct TypeListSortImpl<void (*)(First, Rest...), void (*)(T16...),
203
                        void (*)(T8...), void (*)(T4...), void (*)(T2...),
204
                        void (*)(T1...)> {
205
  using type = typename TypeListSortImpl<
206
      void (*)(Rest...), AppendIfAlign<16, First, T16...>,
207
      AppendIfAlign<8, First, T8...>, AppendIfAlign<4, First, T4...>,
208
      AppendIfAlign<2, First, T2...>, AppendIfAlign<1, First, T1...>>::type;
209
};
210
211
template <typename... T>
212
using SortByAlignment =
213
    typename TypeListSortImpl<void (*)(T...), void (*)(), void (*)(),
214
                              void (*)(), void (*)(), void (*)()>::type;
215
216
template <template <typename...> class C, typename... T>
217
auto ApplyTypeList(void (*)(T...)) -> C<T...>;
218
219
template <typename T>
220
0
constexpr int FindTypeIndex() {
221
0
  return -1;
222
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>()
223
224
template <typename T, typename T1, typename... Ts>
225
0
constexpr int FindTypeIndex() {
226
0
  return std::is_same<T, T1>::value ? 0 : FindTypeIndex<T, Ts...>() + 1;
227
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>()
228
229
// A type to value map, where the possible keys as specified in `Keys...`.
230
// The values for key `K` is `ValueT<K>`
231
template <template <typename> class ValueT, typename... Keys>
232
class TypeMap {
233
 public:
234
  template <typename K>
235
5.47k
  ValueT<K>& Get() {
236
5.47k
    return static_cast<Base<K>&>(payload_).value;
237
5.47k
  }
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> > >()
Line
Count
Source
235
544
  ValueT<K>& Get() {
236
544
    return static_cast<Base<K>&>(payload_).value;
237
544
  }
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> > >()
Line
Count
Source
235
1.78k
  ValueT<K>& Get() {
236
1.78k
    return static_cast<Base<K>&>(payload_).value;
237
1.78k
  }
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>()
Line
Count
Source
235
30
  ValueT<K>& Get() {
236
30
    return static_cast<Base<K>&>(payload_).value;
237
30
  }
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>()
Line
Count
Source
235
30
  ValueT<K>& Get() {
236
30
    return static_cast<Base<K>&>(payload_).value;
237
30
  }
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>()
Line
Count
Source
235
12
  ValueT<K>& Get() {
236
12
    return static_cast<Base<K>&>(payload_).value;
237
12
  }
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>()
Line
Count
Source
235
2.14k
  ValueT<K>& Get() {
236
2.14k
    return static_cast<Base<K>&>(payload_).value;
237
2.14k
  }
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>()
Line
Count
Source
235
12
  ValueT<K>& Get() {
236
12
    return static_cast<Base<K>&>(payload_).value;
237
12
  }
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>()
Line
Count
Source
235
12
  ValueT<K>& Get() {
236
12
    return static_cast<Base<K>&>(payload_).value;
237
12
  }
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>()
Line
Count
Source
235
12
  ValueT<K>& Get() {
236
12
    return static_cast<Base<K>&>(payload_).value;
237
12
  }
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>()
Line
Count
Source
235
12
  ValueT<K>& Get() {
236
12
    return static_cast<Base<K>&>(payload_).value;
237
12
  }
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>()
Line
Count
Source
235
12
  ValueT<K>& Get() {
236
12
    return static_cast<Base<K>&>(payload_).value;
237
12
  }
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>()
Line
Count
Source
235
12
  ValueT<K>& Get() {
236
12
    return static_cast<Base<K>&>(payload_).value;
237
12
  }
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>()
Line
Count
Source
235
12
  ValueT<K>& Get() {
236
12
    return static_cast<Base<K>&>(payload_).value;
237
12
  }
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>()
Line
Count
Source
235
48
  ValueT<K>& Get() {
236
48
    return static_cast<Base<K>&>(payload_).value;
237
48
  }
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>()
Line
Count
Source
235
716
  ValueT<K>& Get() {
236
716
    return static_cast<Base<K>&>(payload_).value;
237
716
  }
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>()
Line
Count
Source
235
6
  ValueT<K>& Get() {
236
6
    return static_cast<Base<K>&>(payload_).value;
237
6
  }
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>()
Line
Count
Source
235
12
  ValueT<K>& Get() {
236
12
    return static_cast<Base<K>&>(payload_).value;
237
12
  }
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>()
Line
Count
Source
235
6
  ValueT<K>& Get() {
236
6
    return static_cast<Base<K>&>(payload_).value;
237
6
  }
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>()
Line
Count
Source
235
18
  ValueT<K>& Get() {
236
18
    return static_cast<Base<K>&>(payload_).value;
237
18
  }
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>()
Line
Count
Source
235
6
  ValueT<K>& Get() {
236
6
    return static_cast<Base<K>&>(payload_).value;
237
6
  }
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>()
Line
Count
Source
235
6
  ValueT<K>& Get() {
236
6
    return static_cast<Base<K>&>(payload_).value;
237
6
  }
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>()
Line
Count
Source
235
6
  ValueT<K>& Get() {
236
6
    return static_cast<Base<K>&>(payload_).value;
237
6
  }
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>()
Line
Count
Source
235
6
  ValueT<K>& Get() {
236
6
    return static_cast<Base<K>&>(payload_).value;
237
6
  }
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>()
Line
Count
Source
235
6
  ValueT<K>& Get() {
236
6
    return static_cast<Base<K>&>(payload_).value;
237
6
  }
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>()
Line
Count
Source
235
6
  ValueT<K>& Get() {
236
6
    return static_cast<Base<K>&>(payload_).value;
237
6
  }
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>()
Line
Count
Source
235
10
  ValueT<K>& Get() {
236
10
    return static_cast<Base<K>&>(payload_).value;
237
10
  }
238
239
  template <typename K>
240
3.89k
  const ValueT<K>& Get() const {
241
3.89k
    return static_cast<const Base<K>&>(payload_).value;
242
3.89k
  }
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
Line
Count
Source
240
3.36k
  const ValueT<K>& Get() const {
241
3.36k
    return static_cast<const Base<K>&>(payload_).value;
242
3.36k
  }
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
Line
Count
Source
240
36
  const ValueT<K>& Get() const {
241
36
    return static_cast<const Base<K>&>(payload_).value;
242
36
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
42
  const ValueT<K>& Get() const {
241
42
    return static_cast<const Base<K>&>(payload_).value;
242
42
  }
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
Line
Count
Source
240
30
  const ValueT<K>& Get() const {
241
30
    return static_cast<const Base<K>&>(payload_).value;
242
30
  }
243
244
 private:
245
  template <typename K>
246
  struct Base {
247
    ValueT<K> value{};
248
  };
249
  struct Payload : Base<Keys>... {};
250
  Payload payload_;
251
};
252
253
template <typename T>
254
using IntT = int;
255
template <typename T>
256
using PointerT = T*;
257
258
// Manages an allocation of sequential arrays of type `T...`.
259
// It is more space efficient than storing N (ptr, size) pairs, by storing only
260
// the pointer to the head and the boundaries between the arrays.
261
template <typename... T>
262
class FlatAllocation {
263
 public:
264
  static constexpr size_t kMaxAlign = Max(alignof(T)...);
265
266
6
  FlatAllocation(const TypeMap<IntT, T...>& ends) : ends_(ends) {
267
    // The arrays start just after FlatAllocation, so adjust the ends.
268
6
    Fold({(ends_.template Get<T>() +=
269
6
           RoundUpTo<kMaxAlign>(sizeof(FlatAllocation)))...});
270
6
    Fold({Init<T>()...});
271
6
  }
272
273
0
  void Destroy() {
274
0
    Fold({Destroy<T>()...});
275
0
    internal::SizedDelete(this, total_bytes());
276
0
  }
277
278
  template <int I>
279
  using type = typename std::tuple_element<I, std::tuple<T...>>::type;
280
281
  // Gets a tuple of the head pointers for the arrays
282
6
  TypeMap<PointerT, T...> Pointers() const {
283
6
    TypeMap<PointerT, T...> out;
284
6
    Fold({(out.template Get<T>() = Begin<T>())...});
285
6
    return out;
286
6
  }
287
288
289
 private:
290
  // Total number of bytes used by all arrays.
291
0
  int total_bytes() const {
292
    // Get the last end.
293
0
    return ends_.template Get<typename std::tuple_element<
294
0
        sizeof...(T) - 1, std::tuple<T...>>::type>();
295
0
  }
296
297
298
  template <typename U>
299
150
  int BeginOffset() const {
300
150
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
150
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
150
    using PrevType =
304
150
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
150
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
150
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
150
                           : ends_.template Get<PrevType>();
309
150
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
12
  int BeginOffset() const {
300
12
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
12
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
12
    using PrevType =
304
12
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
12
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
12
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
12
                           : ends_.template Get<PrevType>();
309
12
  }
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
Line
Count
Source
299
6
  int BeginOffset() const {
300
6
    constexpr int type_index = FindTypeIndex<U, T...>();
301
    // Avoid a negative value here to keep it compiling when type_index == 0
302
6
    constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1;
303
6
    using PrevType =
304
6
        typename std::tuple_element<prev_type_index, std::tuple<T...>>::type;
305
    // Ensure the types are properly aligned.
306
6
    static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), "");
307
6
    return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation))
308
6
                           : ends_.template Get<PrevType>();
309
6
  }
310
311
  template <typename U>
312
150
  int EndOffset() const {
313
150
    return ends_.template Get<U>();
314
150
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
12
  int EndOffset() const {
313
12
    return ends_.template Get<U>();
314
12
  }
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
Line
Count
Source
312
6
  int EndOffset() const {
313
6
    return ends_.template Get<U>();
314
6
  }
315
316
  // Avoid the reinterpret_cast if the array is empty.
317
  // Clang's Control Flow Integrity does not like the cast pointing to memory
318
  // that is not yet initialized to be of that type.
319
  // (from -fsanitize=cfi-unrelated-cast)
320
  template <typename U>
321
78
  U* Begin() const {
322
78
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
78
    if (begin == end) return nullptr;
324
24
    return reinterpret_cast<U*>(data() + begin);
325
78
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
6
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
0
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
6
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
0
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
2
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
0
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
0
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
0
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
0
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
0
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
0
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
4
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
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
Line
Count
Source
321
6
  U* Begin() const {
322
6
    int begin = BeginOffset<U>(), end = EndOffset<U>();
323
6
    if (begin == end) return nullptr;
324
6
    return reinterpret_cast<U*>(data() + begin);
325
6
  }
326
327
  template <typename U>
328
0
  U* End() const {
329
0
    int begin = BeginOffset<U>(), end = EndOffset<U>();
330
0
    if (begin == end) return nullptr;
331
0
    return reinterpret_cast<U*>(data() + end);
332
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
333
334
  template <typename U>
335
78
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
78
    if (std::is_same<U, char>::value) return true;
338
72
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
1.30k
         p != end; p += sizeof(U)) {
340
1.23k
      ::new (p) U{};
341
1.23k
    }
342
72
    return true;
343
78
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
0
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
0
         p != end; p += sizeof(U)) {
340
0
      ::new (p) U{};
341
0
    }
342
0
    return true;
343
6
  }
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> > >()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
1.22k
         p != end; p += sizeof(U)) {
340
1.21k
      ::new (p) U{};
341
1.21k
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
6
         p != end; p += sizeof(U)) {
340
0
      ::new (p) U{};
341
0
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
12
         p != end; p += sizeof(U)) {
340
6
      ::new (p) U{};
341
6
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
6
         p != end; p += sizeof(U)) {
340
0
      ::new (p) U{};
341
0
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
18
         p != end; p += sizeof(U)) {
340
12
      ::new (p) U{};
341
12
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
6
         p != end; p += sizeof(U)) {
340
0
      ::new (p) U{};
341
0
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
6
         p != end; p += sizeof(U)) {
340
0
      ::new (p) U{};
341
0
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
6
         p != end; p += sizeof(U)) {
340
0
      ::new (p) U{};
341
0
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
6
         p != end; p += sizeof(U)) {
340
0
      ::new (p) U{};
341
0
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
6
         p != end; p += sizeof(U)) {
340
0
      ::new (p) U{};
341
0
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
6
         p != end; p += sizeof(U)) {
340
0
      ::new (p) U{};
341
0
    }
342
6
    return true;
343
6
  }
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>()
Line
Count
Source
335
6
  bool Init() {
336
    // Skip for the `char` block. No need to zero initialize it.
337
6
    if (std::is_same<U, char>::value) return true;
338
6
    for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>();
339
10
         p != end; p += sizeof(U)) {
340
4
      ::new (p) U{};
341
4
    }
342
6
    return true;
343
6
  }
344
345
  template <typename U>
346
0
  bool Destroy() {
347
0
    if (std::is_trivially_destructible<U>::value) return true;
348
0
    for (U* it = Begin<U>(), *end = End<U>(); it != end; ++it) {
349
0
      it->~U();
350
0
    }
351
0
    return true;
352
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>()
353
354
168
  char* data() const {
355
168
    return const_cast<char*>(reinterpret_cast<const char*>(this));
356
168
  }
357
358
  TypeMap<IntT, T...> ends_;
359
};
360
361
template <typename... T>
362
6
TypeMap<IntT, T...> CalculateEnds(const TypeMap<IntT, T...>& sizes) {
363
6
  int total = 0;
364
6
  TypeMap<IntT, T...> out;
365
6
  Fold({(out.template Get<T>() = total +=
366
6
         sizeof(T) * sizes.template Get<T>())...});
367
6
  return out;
368
6
}
369
370
// The implementation for FlatAllocator below.
371
// This separate class template makes it easier to have methods that fold on
372
// `T...`.
373
template <typename... T>
374
class FlatAllocatorImpl {
375
 public:
376
  using Allocation = FlatAllocation<T...>;
377
378
  template <typename U>
379
1.42k
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
1.42k
    ABSL_CHECK(!has_allocated());
382
1.42k
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
710
      static_assert(alignof(U) <= 8, "");
385
710
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
716
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
716
      using TypeToUse =
390
716
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
716
                                    char, U>::type;
392
716
      total_.template Get<TypeToUse>() += array_size;
393
716
    }
394
1.42k
  }
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)
Line
Count
Source
379
6
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
6
    ABSL_CHECK(!has_allocated());
382
6
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
0
      static_assert(alignof(U) <= 8, "");
385
0
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
6
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
6
      using TypeToUse =
390
6
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
6
                                    char, U>::type;
392
6
      total_.template Get<TypeToUse>() += array_size;
393
6
    }
394
6
  }
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)
Line
Count
Source
379
4
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
4
    ABSL_CHECK(!has_allocated());
382
4
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
0
      static_assert(alignof(U) <= 8, "");
385
0
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
4
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
4
      using TypeToUse =
390
4
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
4
                                    char, U>::type;
392
4
      total_.template Get<TypeToUse>() += array_size;
393
4
    }
394
4
  }
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)
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)
Line
Count
Source
379
6
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
6
    ABSL_CHECK(!has_allocated());
382
6
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
6
      static_assert(alignof(U) <= 8, "");
385
6
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
6
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
6
  }
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)
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)
Line
Count
Source
379
76
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
76
    ABSL_CHECK(!has_allocated());
382
76
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
76
      static_assert(alignof(U) <= 8, "");
385
76
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
76
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
76
  }
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)
Line
Count
Source
379
94
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
94
    ABSL_CHECK(!has_allocated());
382
94
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
94
      static_assert(alignof(U) <= 8, "");
385
94
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
94
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
94
  }
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)
Line
Count
Source
379
76
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
76
    ABSL_CHECK(!has_allocated());
382
76
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
76
      static_assert(alignof(U) <= 8, "");
385
76
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
76
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
76
  }
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)
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)
Line
Count
Source
379
18
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
18
    ABSL_CHECK(!has_allocated());
382
18
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
18
      static_assert(alignof(U) <= 8, "");
385
18
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
18
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
18
  }
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)
Line
Count
Source
379
158
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
158
    ABSL_CHECK(!has_allocated());
382
158
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
158
      static_assert(alignof(U) <= 8, "");
385
158
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
158
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
158
  }
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)
Line
Count
Source
379
12
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
12
    ABSL_CHECK(!has_allocated());
382
12
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
0
      static_assert(alignof(U) <= 8, "");
385
0
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
12
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
12
      using TypeToUse =
390
12
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
12
                                    char, U>::type;
392
12
      total_.template Get<TypeToUse>() += array_size;
393
12
    }
394
12
  }
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)
Line
Count
Source
379
12
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
12
    ABSL_CHECK(!has_allocated());
382
12
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
12
      static_assert(alignof(U) <= 8, "");
385
12
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
12
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
12
  }
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)
Line
Count
Source
379
6
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
6
    ABSL_CHECK(!has_allocated());
382
6
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
6
      static_assert(alignof(U) <= 8, "");
385
6
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
6
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
6
  }
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)
Line
Count
Source
379
18
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
18
    ABSL_CHECK(!has_allocated());
382
18
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
18
      static_assert(alignof(U) <= 8, "");
385
18
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
18
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
18
  }
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)
Line
Count
Source
379
694
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
694
    ABSL_CHECK(!has_allocated());
382
694
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
0
      static_assert(alignof(U) <= 8, "");
385
0
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
694
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
694
      using TypeToUse =
390
694
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
694
                                    char, U>::type;
392
694
      total_.template Get<TypeToUse>() += array_size;
393
694
    }
394
694
  }
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)
Line
Count
Source
379
6
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
6
    ABSL_CHECK(!has_allocated());
382
6
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
6
      static_assert(alignof(U) <= 8, "");
385
6
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
6
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
6
  }
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)
Line
Count
Source
379
82
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
82
    ABSL_CHECK(!has_allocated());
382
82
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
82
      static_assert(alignof(U) <= 8, "");
385
82
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
82
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
82
  }
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)
Line
Count
Source
379
82
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
82
    ABSL_CHECK(!has_allocated());
382
82
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
82
      static_assert(alignof(U) <= 8, "");
385
82
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
82
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
82
  }
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)
Line
Count
Source
379
76
  void PlanArray(int array_size) {
380
    // We can't call PlanArray after FinalizePlanning has been called.
381
76
    ABSL_CHECK(!has_allocated());
382
76
    if (std::is_trivially_destructible<U>::value) {
383
      // Trivial types are aligned to 8 bytes.
384
76
      static_assert(alignof(U) <= 8, "");
385
76
      total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U));
386
76
    } else {
387
      // Since we can't use `if constexpr`, just make the expression compile
388
      // when this path is not taken.
389
0
      using TypeToUse =
390
0
          typename std::conditional<std::is_trivially_destructible<U>::value,
391
0
                                    char, U>::type;
392
0
      total_.template Get<TypeToUse>() += array_size;
393
0
    }
394
76
  }
395
396
  template <typename U>
397
1.27k
  U* AllocateArray(int array_size) {
398
1.27k
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
1.27k
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
1.27k
    ABSL_CHECK(has_allocated());
403
404
1.27k
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
1.27k
    int& used = used_.template Get<TypeToUse>();
406
1.27k
    U* res = reinterpret_cast<U*>(data + used);
407
1.27k
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
1.27k
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
1.27k
    return res;
410
1.27k
  }
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)
Line
Count
Source
397
538
  U* AllocateArray(int array_size) {
398
538
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
538
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
538
    ABSL_CHECK(has_allocated());
403
404
538
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
538
    int& used = used_.template Get<TypeToUse>();
406
538
    U* res = reinterpret_cast<U*>(data + used);
407
538
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
538
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
538
    return res;
410
538
  }
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)
Line
Count
Source
397
18
  U* AllocateArray(int array_size) {
398
18
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
18
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
18
    ABSL_CHECK(has_allocated());
403
404
18
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
18
    int& used = used_.template Get<TypeToUse>();
406
18
    U* res = reinterpret_cast<U*>(data + used);
407
18
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
18
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
18
    return res;
410
18
  }
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)
Line
Count
Source
397
82
  U* AllocateArray(int array_size) {
398
82
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
82
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
82
    ABSL_CHECK(has_allocated());
403
404
82
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
82
    int& used = used_.template Get<TypeToUse>();
406
82
    U* res = reinterpret_cast<U*>(data + used);
407
82
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
82
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
82
    return res;
410
82
  }
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)
Line
Count
Source
397
82
  U* AllocateArray(int array_size) {
398
82
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
82
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
82
    ABSL_CHECK(has_allocated());
403
404
82
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
82
    int& used = used_.template Get<TypeToUse>();
406
82
    U* res = reinterpret_cast<U*>(data + used);
407
82
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
82
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
82
    return res;
410
82
  }
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)
Line
Count
Source
397
76
  U* AllocateArray(int array_size) {
398
76
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
76
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
76
    ABSL_CHECK(has_allocated());
403
404
76
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
76
    int& used = used_.template Get<TypeToUse>();
406
76
    U* res = reinterpret_cast<U*>(data + used);
407
76
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
76
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
76
    return res;
410
76
  }
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)
Line
Count
Source
397
6
  U* AllocateArray(int array_size) {
398
6
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
6
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
6
    ABSL_CHECK(has_allocated());
403
404
6
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
6
    int& used = used_.template Get<TypeToUse>();
406
6
    U* res = reinterpret_cast<U*>(data + used);
407
6
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
6
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
6
    return res;
410
6
  }
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)
Line
Count
Source
397
4
  U* AllocateArray(int array_size) {
398
4
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
4
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
4
    ABSL_CHECK(has_allocated());
403
404
4
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
4
    int& used = used_.template Get<TypeToUse>();
406
4
    U* res = reinterpret_cast<U*>(data + used);
407
4
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
4
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
4
    return res;
410
4
  }
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)
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)
Line
Count
Source
397
6
  U* AllocateArray(int array_size) {
398
6
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
6
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
6
    ABSL_CHECK(has_allocated());
403
404
6
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
6
    int& used = used_.template Get<TypeToUse>();
406
6
    U* res = reinterpret_cast<U*>(data + used);
407
6
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
6
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
6
    return res;
410
6
  }
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)
Line
Count
Source
397
6
  U* AllocateArray(int array_size) {
398
6
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
6
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
6
    ABSL_CHECK(has_allocated());
403
404
6
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
6
    int& used = used_.template Get<TypeToUse>();
406
6
    U* res = reinterpret_cast<U*>(data + used);
407
6
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
6
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
6
    return res;
410
6
  }
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)
Line
Count
Source
397
12
  U* AllocateArray(int array_size) {
398
12
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
12
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
12
    ABSL_CHECK(has_allocated());
403
404
12
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
12
    int& used = used_.template Get<TypeToUse>();
406
12
    U* res = reinterpret_cast<U*>(data + used);
407
12
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
12
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
12
    return res;
410
12
  }
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)
Line
Count
Source
397
6
  U* AllocateArray(int array_size) {
398
6
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
6
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
6
    ABSL_CHECK(has_allocated());
403
404
6
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
6
    int& used = used_.template Get<TypeToUse>();
406
6
    U* res = reinterpret_cast<U*>(data + used);
407
6
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
6
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
6
    return res;
410
6
  }
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)
Line
Count
Source
397
158
  U* AllocateArray(int array_size) {
398
158
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
158
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
158
    ABSL_CHECK(has_allocated());
403
404
158
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
158
    int& used = used_.template Get<TypeToUse>();
406
158
    U* res = reinterpret_cast<U*>(data + used);
407
158
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
158
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
158
    return res;
410
158
  }
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)
Line
Count
Source
397
76
  U* AllocateArray(int array_size) {
398
76
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
76
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
76
    ABSL_CHECK(has_allocated());
403
404
76
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
76
    int& used = used_.template Get<TypeToUse>();
406
76
    U* res = reinterpret_cast<U*>(data + used);
407
76
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
76
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
76
    return res;
410
76
  }
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)
Line
Count
Source
397
76
  U* AllocateArray(int array_size) {
398
76
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
76
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
76
    ABSL_CHECK(has_allocated());
403
404
76
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
76
    int& used = used_.template Get<TypeToUse>();
406
76
    U* res = reinterpret_cast<U*>(data + used);
407
76
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
76
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
76
    return res;
410
76
  }
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)
Line
Count
Source
397
94
  U* AllocateArray(int array_size) {
398
94
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
94
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
94
    ABSL_CHECK(has_allocated());
403
404
94
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
94
    int& used = used_.template Get<TypeToUse>();
406
94
    U* res = reinterpret_cast<U*>(data + used);
407
94
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
94
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
94
    return res;
410
94
  }
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)
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)
Line
Count
Source
397
12
  U* AllocateArray(int array_size) {
398
12
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
12
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
12
    ABSL_CHECK(has_allocated());
403
404
12
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
12
    int& used = used_.template Get<TypeToUse>();
406
12
    U* res = reinterpret_cast<U*>(data + used);
407
12
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
12
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
12
    return res;
410
12
  }
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)
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)
Line
Count
Source
397
18
  U* AllocateArray(int array_size) {
398
18
    constexpr bool trivial = std::is_trivially_destructible<U>::value;
399
18
    using TypeToUse = typename std::conditional<trivial, char, U>::type;
400
401
    // We can only allocate after FinalizePlanning has been called.
402
18
    ABSL_CHECK(has_allocated());
403
404
18
    TypeToUse*& data = pointers_.template Get<TypeToUse>();
405
18
    int& used = used_.template Get<TypeToUse>();
406
18
    U* res = reinterpret_cast<U*>(data + used);
407
18
    used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size;
408
18
    ABSL_CHECK_LE(used, total_.template Get<TypeToUse>());
409
18
    return res;
410
18
  }
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)
411
412
  template <typename... In>
413
538
  const std::string* AllocateStrings(In&&... in) {
414
538
    std::string* strings = AllocateArray<std::string>(sizeof...(in));
415
538
    std::string* res = strings;
416
538
    Fold({(*strings++ = std::string(std::forward<In>(in)))...});
417
538
    return res;
418
538
  }
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<absl::lts_20230125::string_view>(absl::lts_20230125::string_view&&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<char const (&) [1]>(char const (&) [1])
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<absl::lts_20230125::string_view&, absl::lts_20230125::string_view&>(absl::lts_20230125::string_view&, absl::lts_20230125::string_view&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<char const (&) [18], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(char const (&) [18], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const* google::protobuf::(anonymous namespace)::FlatAllocatorImpl<char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, google::protobuf::SourceCodeInfo, google::protobuf::FileDescriptorTables, google::protobuf::MessageOptions, google::protobuf::FieldOptions, google::protobuf::EnumOptions, google::protobuf::EnumValueOptions, google::protobuf::ExtensionRangeOptions, google::protobuf::OneofOptions, google::protobuf::ServiceOptions, google::protobuf::MethodOptions, google::protobuf::FileOptions>::AllocateStrings<absl::lts_20230125::string_view&>(absl::lts_20230125::string_view&)
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&)
Line
Count
Source
413
12
  const std::string* AllocateStrings(In&&... in) {
414
12
    std::string* strings = AllocateArray<std::string>(sizeof...(in));
415
12
    std::string* res = strings;
416
12
    Fold({(*strings++ = std::string(std::forward<In>(in)))...});
417
12
    return res;
418
12
  }
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&)
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> >&&)
Line
Count
Source
413
376
  const std::string* AllocateStrings(In&&... in) {
414
376
    std::string* strings = AllocateArray<std::string>(sizeof...(in));
415
376
    std::string* res = strings;
416
376
    Fold({(*strings++ = std::string(std::forward<In>(in)))...});
417
376
    return res;
418
376
  }
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> >&&)
Line
Count
Source
413
150
  const std::string* AllocateStrings(In&&... in) {
414
150
    std::string* strings = AllocateArray<std::string>(sizeof...(in));
415
150
    std::string* res = strings;
416
150
    Fold({(*strings++ = std::string(std::forward<In>(in)))...});
417
150
    return res;
418
150
  }
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> >&)
419
420
  // Allocate all 5 names of the field:
421
  // name, full name, lowercase, camelcase and json.
422
  // It will dedup the strings when possible.
423
  // The resulting array contains `name` at index 0, `full_name` at index 1
424
  // and the other 3 indices are specified in the result.
425
  void PlanFieldNames(const std::string& name,
426
330
                      const std::string* opt_json_name) {
427
330
    ABSL_CHECK(!has_allocated());
428
429
    // Fast path for snake_case names, which follow the style guide.
430
330
    if (opt_json_name == nullptr) {
431
330
      switch (GetFieldNameCase(name)) {
432
180
        case FieldNameCase::kAllLower:
433
          // Case 1: they are all the same.
434
180
          return PlanArray<std::string>(2);
435
150
        case FieldNameCase::kSnakeCase:
436
          // Case 2: name==lower, camel==json
437
150
          return PlanArray<std::string>(3);
438
0
        default:
439
0
          break;
440
330
      }
441
330
    }
442
443
0
    std::string lowercase_name = name;
444
0
    absl::AsciiStrToLower(&lowercase_name);
445
446
0
    std::string camelcase_name = ToCamelCase(name, /* lower_first = */ true);
447
0
    std::string json_name =
448
0
        opt_json_name != nullptr ? *opt_json_name : ToJsonName(name);
449
450
0
    absl::string_view all_names[] = {name, lowercase_name, camelcase_name,
451
0
                                     json_name};
452
0
    std::sort(all_names, all_names + 4);
453
0
    int unique =
454
0
        static_cast<int>(std::unique(all_names, all_names + 4) - all_names);
455
456
0
    PlanArray<std::string>(unique + 1);
457
0
  }
458
459
  struct FieldNamesResult {
460
    const std::string* array;
461
    int lowercase_index;
462
    int camelcase_index;
463
    int json_index;
464
  };
465
  FieldNamesResult AllocateFieldNames(const std::string& name,
466
                                      const std::string& scope,
467
330
                                      const std::string* opt_json_name) {
468
330
    ABSL_CHECK(has_allocated());
469
470
330
    std::string full_name =
471
330
        scope.empty() ? name : absl::StrCat(scope, ".", name);
472
473
    // Fast path for snake_case names, which follow the style guide.
474
330
    if (opt_json_name == nullptr) {
475
330
      switch (GetFieldNameCase(name)) {
476
180
        case FieldNameCase::kAllLower:
477
          // Case 1: they are all the same.
478
180
          return {AllocateStrings(name, std::move(full_name)), 0, 0, 0};
479
150
        case FieldNameCase::kSnakeCase:
480
          // Case 2: name==lower, camel==json
481
150
          return {AllocateStrings(name, std::move(full_name),
482
150
                                  ToCamelCase(name, /* lower_first = */ true)),
483
150
                  0, 2, 2};
484
0
        default:
485
0
          break;
486
330
      }
487
330
    }
488
489
0
    std::vector<std::string> names;
490
0
    names.push_back(name);
491
0
    names.push_back(std::move(full_name));
492
493
0
    const auto push_name = [&](std::string new_name) {
494
0
      for (size_t i = 0; i < names.size(); ++i) {
495
        // Do not compare the full_name. It is unlikely to match, except in
496
        // custom json_name. We are not taking this into account in
497
        // PlanFieldNames so better to not try it.
498
0
        if (i == 1) continue;
499
0
        if (names[i] == new_name) return i;
500
0
      }
501
0
      names.push_back(std::move(new_name));
502
0
      return names.size() - 1;
503
0
    };
504
505
0
    FieldNamesResult result{nullptr, 0, 0, 0};
506
507
0
    std::string lowercase_name = name;
508
0
    absl::AsciiStrToLower(&lowercase_name);
509
0
    result.lowercase_index = push_name(std::move(lowercase_name));
510
0
    result.camelcase_index =
511
0
        push_name(ToCamelCase(name, /* lower_first = */ true));
512
0
    result.json_index =
513
0
        push_name(opt_json_name != nullptr ? *opt_json_name : ToJsonName(name));
514
515
0
    std::string* all_names = AllocateArray<std::string>(names.size());
516
0
    result.array = all_names;
517
0
    std::move(names.begin(), names.end(), all_names);
518
519
0
    return result;
520
330
  }
521
522
  template <typename Alloc>
523
6
  void FinalizePlanning(Alloc& alloc) {
524
6
    ABSL_CHECK(!has_allocated());
525
526
6
    pointers_ = alloc->CreateFlatAlloc(total_)->Pointers();
527
528
6
    ABSL_CHECK(has_allocated());
529
6
  }
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*&)
Line
Count
Source
523
6
  void FinalizePlanning(Alloc& alloc) {
524
6
    ABSL_CHECK(!has_allocated());
525
526
6
    pointers_ = alloc->CreateFlatAlloc(total_)->Pointers();
527
528
6
    ABSL_CHECK(has_allocated());
529
6
  }
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&)
530
531
6
  void ExpectConsumed() const {
532
    // We verify that we consumed all the memory requested if there was no
533
    // error in processing.
534
6
    Fold({ExpectConsumed<T>()...});
535
6
  }
536
537
 private:
538
3.36k
  bool has_allocated() const {
539
3.36k
    return pointers_.template Get<char>() != nullptr;
540
3.36k
  }
541
542
7.63k
  static bool IsLower(char c) { return 'a' <= c && c <= 'z'; }
543
432
  static bool IsDigit(char c) { return '0' <= c && c <= '9'; }
544
6.97k
  static bool IsLowerOrDigit(char c) { return IsLower(c) || IsDigit(c); }
545
546
  enum class FieldNameCase { kAllLower, kSnakeCase, kOther };
547
660
  FieldNameCase GetFieldNameCase(const std::string& name) {
548
660
    if (!IsLower(name[0])) return FieldNameCase::kOther;
549
660
    FieldNameCase best = FieldNameCase::kAllLower;
550
6.97k
    for (char c : name) {
551
6.97k
      if (IsLowerOrDigit(c)) {
552
        // nothing to do
553
6.56k
      } else if (c == '_') {
554
416
        best = FieldNameCase::kSnakeCase;
555
416
      } else {
556
0
        return FieldNameCase::kOther;
557
0
      }
558
6.97k
    }
559
660
    return best;
560
660
  }
561
562
  template <typename U>
563
78
  bool ExpectConsumed() const {
564
78
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
78
    return true;
566
78
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
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
Line
Count
Source
563
6
  bool ExpectConsumed() const {
564
6
    ABSL_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>());
565
6
    return true;
566
6
  }
567
568
  TypeMap<PointerT, T...> pointers_;
569
  TypeMap<IntT, T...> total_;
570
  TypeMap<IntT, T...> used_;
571
};
572
573
}  // namespace
574
575
class Symbol {
576
 public:
577
  enum Type {
578
    NULL_SYMBOL,
579
    MESSAGE,
580
    FIELD,
581
    ONEOF,
582
    ENUM,
583
    ENUM_VALUE,
584
    ENUM_VALUE_OTHER_PARENT,
585
    SERVICE,
586
    METHOD,
587
    FULL_PACKAGE,
588
    SUB_PACKAGE,
589
  };
590
591
372
  Symbol() {
592
372
    static constexpr internal::SymbolBase null_symbol{};
593
372
    static_assert(null_symbol.symbol_type_ == NULL_SYMBOL, "");
594
    // Initialize with a sentinel to make sure `ptr_` is never null.
595
372
    ptr_ = &null_symbol;
596
372
  }
597
598
  // Every object we store derives from internal::SymbolBase, where we store the
599
  // symbol type enum.
600
  // Storing in the object can be done without using more space in most cases,
601
  // while storing it in the Symbol type would require 8 bytes.
602
#define DEFINE_MEMBERS(TYPE, TYPE_CONSTANT, FIELD)                             \
603
436
  explicit Symbol(TYPE* value) : ptr_(value) {                                 \
604
436
    value->symbol_type_ = TYPE_CONSTANT;                                       \
605
436
  }                                                                            \
google::protobuf::Symbol::Symbol(google::protobuf::EnumDescriptor*)
Line
Count
Source
603
18
  explicit Symbol(TYPE* value) : ptr_(value) {                                 \
604
18
    value->symbol_type_ = TYPE_CONSTANT;                                       \
605
18
  }                                                                            \
google::protobuf::Symbol::Symbol(google::protobuf::Descriptor*)
Line
Count
Source
603
76
  explicit Symbol(TYPE* value) : ptr_(value) {                                 \
604
76
    value->symbol_type_ = TYPE_CONSTANT;                                       \
605
76
  }                                                                            \
google::protobuf::Symbol::Symbol(google::protobuf::FileDescriptor*)
Line
Count
Source
603
4
  explicit Symbol(TYPE* value) : ptr_(value) {                                 \
604
4
    value->symbol_type_ = TYPE_CONSTANT;                                       \
605
4
  }                                                                            \
google::protobuf::Symbol::Symbol(google::protobuf::Symbol::Subpackage*)
Line
Count
Source
603
4
  explicit Symbol(TYPE* value) : ptr_(value) {                                 \
604
4
    value->symbol_type_ = TYPE_CONSTANT;                                       \
605
4
  }                                                                            \
google::protobuf::Symbol::Symbol(google::protobuf::FieldDescriptor*)
Line
Count
Source
603
330
  explicit Symbol(TYPE* value) : ptr_(value) {                                 \
604
330
    value->symbol_type_ = TYPE_CONSTANT;                                       \
605
330
  }                                                                            \
google::protobuf::Symbol::Symbol(google::protobuf::OneofDescriptor*)
Line
Count
Source
603
4
  explicit Symbol(TYPE* value) : ptr_(value) {                                 \
604
4
    value->symbol_type_ = TYPE_CONSTANT;                                       \
605
4
  }                                                                            \
Unexecuted instantiation: google::protobuf::Symbol::Symbol(google::protobuf::ServiceDescriptor*)
Unexecuted instantiation: google::protobuf::Symbol::Symbol(google::protobuf::MethodDescriptor*)
606
309k
  const TYPE* FIELD() const {                                                  \
607
309k
    return type() == TYPE_CONSTANT ? static_cast<const TYPE*>(ptr_) : nullptr; \
608
309k
  }
google::protobuf::Symbol::file_descriptor() const
Line
Count
Source
606
30
  const TYPE* FIELD() const {                                                  \
607
30
    return type() == TYPE_CONSTANT ? static_cast<const TYPE*>(ptr_) : nullptr; \
608
30
  }
google::protobuf::Symbol::sub_package_file_descriptor() const
Line
Count
Source
606
52
  const TYPE* FIELD() const {                                                  \
607
52
    return type() == TYPE_CONSTANT ? static_cast<const TYPE*>(ptr_) : nullptr; \
608
52
  }
google::protobuf::Symbol::field_descriptor() const
Line
Count
Source
606
307k
  const TYPE* FIELD() const {                                                  \
607
307k
    return type() == TYPE_CONSTANT ? static_cast<const TYPE*>(ptr_) : nullptr; \
608
307k
  }
google::protobuf::Symbol::descriptor() const
Line
Count
Source
606
1.05k
  const TYPE* FIELD() const {                                                  \
607
1.05k
    return type() == TYPE_CONSTANT ? static_cast<const TYPE*>(ptr_) : nullptr; \
608
1.05k
  }
google::protobuf::Symbol::oneof_descriptor() const
Line
Count
Source
606
36
  const TYPE* FIELD() const {                                                  \
607
36
    return type() == TYPE_CONSTANT ? static_cast<const TYPE*>(ptr_) : nullptr; \
608
36
  }
google::protobuf::Symbol::enum_descriptor() const
Line
Count
Source
606
172
  const TYPE* FIELD() const {                                                  \
607
172
    return type() == TYPE_CONSTANT ? static_cast<const TYPE*>(ptr_) : nullptr; \
608
172
  }
Unexecuted instantiation: google::protobuf::Symbol::service_descriptor() const
Unexecuted instantiation: google::protobuf::Symbol::method_descriptor() const
609
610
  DEFINE_MEMBERS(Descriptor, MESSAGE, descriptor)
611
  DEFINE_MEMBERS(FieldDescriptor, FIELD, field_descriptor)
612
  DEFINE_MEMBERS(OneofDescriptor, ONEOF, oneof_descriptor)
613
  DEFINE_MEMBERS(EnumDescriptor, ENUM, enum_descriptor)
614
  DEFINE_MEMBERS(ServiceDescriptor, SERVICE, service_descriptor)
615
  DEFINE_MEMBERS(MethodDescriptor, METHOD, method_descriptor)
616
  DEFINE_MEMBERS(FileDescriptor, FULL_PACKAGE, file_descriptor)
617
618
  // We use a special node for subpackage FileDescriptor.
619
  // It is potentially added to the table with multiple different names, so we
620
  // need a separate place to put the name.
621
  struct Subpackage : internal::SymbolBase {
622
    int name_size;
623
    const FileDescriptor* file;
624
  };
625
  DEFINE_MEMBERS(Subpackage, SUB_PACKAGE, sub_package_file_descriptor)
626
627
  // Enum values have two different parents.
628
  // We use two different identitied for the same object to determine the two
629
  // different insertions in the map.
630
196
  static Symbol EnumValue(EnumValueDescriptor* value, int n) {
631
196
    Symbol s;
632
196
    internal::SymbolBase* ptr;
633
196
    if (n == 0) {
634
98
      ptr = static_cast<internal::SymbolBaseN<0>*>(value);
635
98
      ptr->symbol_type_ = ENUM_VALUE;
636
98
    } else {
637
98
      ptr = static_cast<internal::SymbolBaseN<1>*>(value);
638
98
      ptr->symbol_type_ = ENUM_VALUE_OTHER_PARENT;
639
98
    }
640
196
    s.ptr_ = ptr;
641
196
    return s;
642
196
  }
643
644
1.26k
  const EnumValueDescriptor* enum_value_descriptor() const {
645
1.26k
    return type() == ENUM_VALUE
646
1.26k
               ? static_cast<const EnumValueDescriptor*>(
647
780
                     static_cast<const internal::SymbolBaseN<0>*>(ptr_))
648
1.26k
           : type() == ENUM_VALUE_OTHER_PARENT
649
488
               ? static_cast<const EnumValueDescriptor*>(
650
488
                     static_cast<const internal::SymbolBaseN<1>*>(ptr_))
651
488
               : nullptr;
652
1.26k
  }
653
654
#undef DEFINE_MEMBERS
655
656
468k
  Type type() const { return static_cast<Type>(ptr_->symbol_type_); }
657
632
  bool IsNull() const { return type() == NULL_SYMBOL; }
658
0
  bool IsType() const { return type() == MESSAGE || type() == ENUM; }
659
0
  bool IsAggregate() const {
660
0
    return IsType() || IsPackage() || type() == SERVICE;
661
0
  }
662
2
  bool IsPackage() const {
663
2
    return type() == FULL_PACKAGE || type() == SUB_PACKAGE;
664
2
  }
665
666
286
  const FileDescriptor* GetFile() const {
667
286
    switch (type()) {
668
260
      case MESSAGE:
669
260
        return descriptor()->file();
670
0
      case FIELD:
671
0
        return field_descriptor()->file();
672
0
      case ONEOF:
673
0
        return oneof_descriptor()->containing_type()->file();
674
18
      case ENUM:
675
18
        return enum_descriptor()->file();
676
8
      case ENUM_VALUE:
677
8
        return enum_value_descriptor()->type()->file();
678
0
      case SERVICE:
679
0
        return service_descriptor()->file();
680
0
      case METHOD:
681
0
        return method_descriptor()->service()->file();
682
0
      case FULL_PACKAGE:
683
0
        return file_descriptor();
684
0
      case SUB_PACKAGE:
685
0
        return sub_package_file_descriptor()->file;
686
0
      default:
687
0
        return nullptr;
688
286
    }
689
286
  }
690
691
1.64k
  absl::string_view full_name() const {
692
1.64k
    switch (type()) {
693
316
      case MESSAGE:
694
316
        return descriptor()->full_name();
695
954
      case FIELD:
696
954
        return field_descriptor()->full_name();
697
20
      case ONEOF:
698
20
        return oneof_descriptor()->full_name();
699
52
      case ENUM:
700
52
        return enum_descriptor()->full_name();
701
244
      case ENUM_VALUE:
702
244
        return enum_value_descriptor()->full_name();
703
0
      case SERVICE:
704
0
        return service_descriptor()->full_name();
705
0
      case METHOD:
706
0
        return method_descriptor()->full_name();
707
30
      case FULL_PACKAGE:
708
30
        return file_descriptor()->package();
709
26
      case SUB_PACKAGE:
710
26
        return absl::string_view(sub_package_file_descriptor()->file->package())
711
26
            .substr(0, sub_package_file_descriptor()->name_size);
712
0
      default:
713
0
        ABSL_CHECK(false);
714
1.64k
    }
715
0
    return "";
716
1.64k
  }
717
718
154k
  std::pair<const void*, absl::string_view> parent_name_key() const {
719
154k
    const auto or_file = [&](const void* p) { return p ? p : GetFile(); };
720
154k
    switch (type()) {
721
189
      case MESSAGE:
722
189
        return {or_file(descriptor()->containing_type()), descriptor()->name()};
723
153k
      case FIELD: {
724
153k
        auto* field = field_descriptor();
725
153k
        return {or_file(field->is_extension() ? field->extension_scope()
726
153k
                                              : field->containing_type()),
727
153k
                field->name()};
728
0
      }
729
8
      case ONEOF:
730
8
        return {oneof_descriptor()->containing_type(),
731
8
                oneof_descriptor()->name()};
732
42
      case ENUM:
733
42
        return {or_file(enum_descriptor()->containing_type()),
734
42
                enum_descriptor()->name()};
735
260
      case ENUM_VALUE:
736
260
        return {or_file(enum_value_descriptor()->type()->containing_type()),
737
260
                enum_value_descriptor()->name()};
738
244
      case ENUM_VALUE_OTHER_PARENT:
739
244
        return {enum_value_descriptor()->type(),
740
244
                enum_value_descriptor()->name()};
741
0
      case SERVICE:
742
0
        return {GetFile(), service_descriptor()->name()};
743
0
      case METHOD:
744
0
        return {method_descriptor()->service(), method_descriptor()->name()};
745
0
      default:
746
0
        ABSL_CHECK(false);
747
154k
    }
748
0
    return {};
749
154k
  }
750
751
 private:
752
  const internal::SymbolBase* ptr_;
753
};
754
755
const FieldDescriptor::CppType
756
    FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = {
757
        static_cast<CppType>(0),  // 0 is reserved for errors
758
759
        CPPTYPE_DOUBLE,   // TYPE_DOUBLE
760
        CPPTYPE_FLOAT,    // TYPE_FLOAT
761
        CPPTYPE_INT64,    // TYPE_INT64
762
        CPPTYPE_UINT64,   // TYPE_UINT64
763
        CPPTYPE_INT32,    // TYPE_INT32
764
        CPPTYPE_UINT64,   // TYPE_FIXED64
765
        CPPTYPE_UINT32,   // TYPE_FIXED32
766
        CPPTYPE_BOOL,     // TYPE_BOOL
767
        CPPTYPE_STRING,   // TYPE_STRING
768
        CPPTYPE_MESSAGE,  // TYPE_GROUP
769
        CPPTYPE_MESSAGE,  // TYPE_MESSAGE
770
        CPPTYPE_STRING,   // TYPE_BYTES
771
        CPPTYPE_UINT32,   // TYPE_UINT32
772
        CPPTYPE_ENUM,     // TYPE_ENUM
773
        CPPTYPE_INT32,    // TYPE_SFIXED32
774
        CPPTYPE_INT64,    // TYPE_SFIXED64
775
        CPPTYPE_INT32,    // TYPE_SINT32
776
        CPPTYPE_INT64,    // TYPE_SINT64
777
};
778
779
const char* const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = {
780
    "ERROR",  // 0 is reserved for errors
781
782
    "double",    // TYPE_DOUBLE
783
    "float",     // TYPE_FLOAT
784
    "int64",     // TYPE_INT64
785
    "uint64",    // TYPE_UINT64
786
    "int32",     // TYPE_INT32
787
    "fixed64",   // TYPE_FIXED64
788
    "fixed32",   // TYPE_FIXED32
789
    "bool",      // TYPE_BOOL
790
    "string",    // TYPE_STRING
791
    "group",     // TYPE_GROUP
792
    "message",   // TYPE_MESSAGE
793
    "bytes",     // TYPE_BYTES
794
    "uint32",    // TYPE_UINT32
795
    "enum",      // TYPE_ENUM
796
    "sfixed32",  // TYPE_SFIXED32
797
    "sfixed64",  // TYPE_SFIXED64
798
    "sint32",    // TYPE_SINT32
799
    "sint64",    // TYPE_SINT64
800
};
801
802
const char* const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
803
    "ERROR",  // 0 is reserved for errors
804
805
    "int32",    // CPPTYPE_INT32
806
    "int64",    // CPPTYPE_INT64
807
    "uint32",   // CPPTYPE_UINT32
808
    "uint64",   // CPPTYPE_UINT64
809
    "double",   // CPPTYPE_DOUBLE
810
    "float",    // CPPTYPE_FLOAT
811
    "bool",     // CPPTYPE_BOOL
812
    "enum",     // CPPTYPE_ENUM
813
    "string",   // CPPTYPE_STRING
814
    "message",  // CPPTYPE_MESSAGE
815
};
816
817
const char* const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
818
    "ERROR",  // 0 is reserved for errors
819
820
    "optional",  // LABEL_OPTIONAL
821
    "required",  // LABEL_REQUIRED
822
    "repeated",  // LABEL_REPEATED
823
};
824
825
0
const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) {
826
0
  switch (syntax) {
827
0
    case SYNTAX_PROTO2:
828
0
      return "proto2";
829
0
    case SYNTAX_PROTO3:
830
0
      return "proto3";
831
0
    case SYNTAX_UNKNOWN:
832
0
      return "unknown";
833
0
  }
834
0
  ABSL_LOG(FATAL) << "can't reach here.";
835
0
  return nullptr;
836
0
}
837
838
static const char* const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty";
839
840
#if !defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)
841
const int FieldDescriptor::kMaxNumber;
842
const int FieldDescriptor::kFirstReservedNumber;
843
const int FieldDescriptor::kLastReservedNumber;
844
#endif
845
846
namespace {
847
848
0
std::string EnumValueToPascalCase(const std::string& input) {
849
0
  bool next_upper = true;
850
0
  std::string result;
851
0
  result.reserve(input.size());
852
853
0
  for (char character : input) {
854
0
    if (character == '_') {
855
0
      next_upper = true;
856
0
    } else {
857
0
      if (next_upper) {
858
0
        result.push_back(absl::ascii_toupper(character));
859
0
      } else {
860
0
        result.push_back(absl::ascii_tolower(character));
861
0
      }
862
0
      next_upper = false;
863
0
    }
864
0
  }
865
866
0
  return result;
867
0
}
868
869
// Class to remove an enum prefix from enum values.
870
class PrefixRemover {
871
 public:
872
0
  PrefixRemover(absl::string_view prefix) {
873
    // Strip underscores and lower-case the prefix.
874
0
    for (char character : prefix) {
875
0
      if (character != '_') {
876
0
        prefix_ += absl::ascii_tolower(character);
877
0
      }
878
0
    }
879
0
  }
880
881
  // Tries to remove the enum prefix from this enum value.
882
  // If this is not possible, returns the input verbatim.
883
0
  std::string MaybeRemove(absl::string_view str) {
884
    // We can't just lowercase and strip str and look for a prefix.
885
    // We need to properly recognize the difference between:
886
    //
887
    //   enum Foo {
888
    //     FOO_BAR_BAZ = 0;
889
    //     FOO_BARBAZ = 1;
890
    //   }
891
    //
892
    // This is acceptable (though perhaps not advisable) because even when
893
    // we PascalCase, these two will still be distinct (BarBaz vs. Barbaz).
894
0
    size_t i, j;
895
896
    // Skip past prefix_ in str if we can.
897
0
    for (i = 0, j = 0; i < str.size() && j < prefix_.size(); i++) {
898
0
      if (str[i] == '_') {
899
0
        continue;
900
0
      }
901
902
0
      if (absl::ascii_tolower(str[i]) != prefix_[j++]) {
903
0
        return std::string(str);
904
0
      }
905
0
    }
906
907
    // If we didn't make it through the prefix, we've failed to strip the
908
    // prefix.
909
0
    if (j < prefix_.size()) {
910
0
      return std::string(str);
911
0
    }
912
913
    // Skip underscores between prefix and further characters.
914
0
    while (i < str.size() && str[i] == '_') {
915
0
      i++;
916
0
    }
917
918
    // Enum label can't be the empty string.
919
0
    if (i == str.size()) {
920
0
      return std::string(str);
921
0
    }
922
923
    // We successfully stripped the prefix.
924
0
    str.remove_prefix(i);
925
0
    return std::string(str);
926
0
  }
927
928
 private:
929
  std::string prefix_;
930
};
931
932
// A DescriptorPool contains a bunch of hash-maps to implement the
933
// various Find*By*() methods.  Since hashtable lookups are O(1), it's
934
// most efficient to construct a fixed set of large hash-maps used by
935
// all objects in the pool rather than construct one or more small
936
// hash-maps for each object.
937
//
938
// The keys to these hash-maps are (parent, name) or (parent, number) pairs.
939
struct FullNameQuery {
940
  absl::string_view query;
941
264
  absl::string_view full_name() const { return query; }
942
};
943
struct SymbolByFullNameHash {
944
  using is_transparent = void;
945
946
  template <typename T>
947
1.56k
  size_t operator()(const T& s) const {
948
1.56k
    return absl::HashOf(s.full_name());
949
1.56k
  }
descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::SymbolByFullNameHash::operator()<google::protobuf::(anonymous namespace)::FullNameQuery>(google::protobuf::(anonymous namespace)::FullNameQuery const&) const
Line
Count
Source
947
136
  size_t operator()(const T& s) const {
948
136
    return absl::HashOf(s.full_name());
949
136
  }
descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::SymbolByFullNameHash::operator()<google::protobuf::Symbol>(google::protobuf::Symbol const&) const
Line
Count
Source
947
1.42k
  size_t operator()(const T& s) const {
948
1.42k
    return absl::HashOf(s.full_name());
949
1.42k
  }
950
};
951
struct SymbolByFullNameEq {
952
  using is_transparent = void;
953
954
  template <typename T, typename U>
955
173
  bool operator()(const T& a, const U& b) const {
956
173
    return a.full_name() == b.full_name();
957
173
  }
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
Line
Count
Source
955
128
  bool operator()(const T& a, const U& b) const {
956
128
    return a.full_name() == b.full_name();
957
128
  }
descriptor.cc:bool google::protobuf::(anonymous namespace)::SymbolByFullNameEq::operator()<google::protobuf::Symbol, google::protobuf::Symbol>(google::protobuf::Symbol const&, google::protobuf::Symbol const&) const
Line
Count
Source
955
45
  bool operator()(const T& a, const U& b) const {
956
45
    return a.full_name() == b.full_name();
957
45
  }
958
};
959
using SymbolsByNameSet =
960
    absl::flat_hash_set<Symbol, SymbolByFullNameHash, SymbolByFullNameEq>;
961
962
struct ParentNameQuery {
963
  std::pair<const void*, absl::string_view> query;
964
305k
  std::pair<const void*, absl::string_view> parent_name_key() const {
965
305k
    return query;
966
305k
  }
967
};
968
struct SymbolByParentHash {
969
  using is_transparent = void;
970
971
  template <typename T>
972
154k
  size_t operator()(const T& s) const {
973
154k
    return absl::HashOf(s.parent_name_key());
974
154k
  }
descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::SymbolByParentHash::operator()<google::protobuf::(anonymous namespace)::ParentNameQuery>(google::protobuf::(anonymous namespace)::ParentNameQuery const&) const
Line
Count
Source
972
152k
  size_t operator()(const T& s) const {
973
152k
    return absl::HashOf(s.parent_name_key());
974
152k
  }
descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::SymbolByParentHash::operator()<google::protobuf::Symbol>(google::protobuf::Symbol const&) const
Line
Count
Source
972
1.62k
  size_t operator()(const T& s) const {
973
1.62k
    return absl::HashOf(s.parent_name_key());
974
1.62k
  }
975
};
976
struct SymbolByParentEq {
977
  using is_transparent = void;
978
979
  template <typename T, typename U>
980
153k
  bool operator()(const T& a, const U& b) const {
981
153k
    return a.parent_name_key() == b.parent_name_key();
982
153k
  }
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
Line
Count
Source
980
152k
  bool operator()(const T& a, const U& b) const {
981
152k
    return a.parent_name_key() == b.parent_name_key();
982
152k
  }
descriptor.cc:bool google::protobuf::(anonymous namespace)::SymbolByParentEq::operator()<google::protobuf::Symbol, google::protobuf::Symbol>(google::protobuf::Symbol const&, google::protobuf::Symbol const&) const
Line
Count
Source
980
55
  bool operator()(const T& a, const U& b) const {
981
55
    return a.parent_name_key() == b.parent_name_key();
982
55
  }
983
};
984
using SymbolsByParentSet =
985
    absl::flat_hash_set<Symbol, SymbolByParentHash, SymbolByParentEq>;
986
987
struct FilesByNameHash {
988
  using is_transparent = void;
989
990
18
  size_t operator()(absl::string_view name) const { return absl::HashOf(name); }
991
992
8
  size_t operator()(const FileDescriptor* file) const {
993
8
    return absl::HashOf(file->name());
994
8
  }
995
};
996
997
struct FilesByNameEq {
998
  using is_transparent = void;
999
1000
0
  bool operator()(absl::string_view lhs, absl::string_view rhs) const {
1001
0
    return lhs == rhs;
1002
0
  }
1003
0
  bool operator()(absl::string_view lhs, const FileDescriptor* rhs) const {
1004
0
    return lhs == rhs->name();
1005
0
  }
1006
6
  bool operator()(const FileDescriptor* lhs, absl::string_view rhs) const {
1007
6
    return lhs->name() == rhs;
1008
6
  }
1009
0
  bool operator()(const FileDescriptor* lhs, const FileDescriptor* rhs) const {
1010
0
    return lhs == rhs || lhs->name() == rhs->name();
1011
0
  }
1012
};
1013
using FilesByNameSet =
1014
    absl::flat_hash_set<const FileDescriptor*, FilesByNameHash, FilesByNameEq>;
1015
1016
using FieldsByNameMap =
1017
    absl::flat_hash_map<std::pair<const void*, absl::string_view>,
1018
                        const FieldDescriptor*>;
1019
1020
struct ParentNumberQuery {
1021
  std::pair<const void*, int> query;
1022
};
1023
400
std::pair<const void*, int> ObjectToParentNumber(const FieldDescriptor* field) {
1024
400
  return {field->containing_type(), field->number()};
1025
400
}
1026
std::pair<const void*, int> ObjectToParentNumber(
1027
0
    const EnumValueDescriptor* enum_value) {
1028
0
  return {enum_value->type(), enum_value->number()};
1029
0
}
1030
0
std::pair<const void*, int> ObjectToParentNumber(ParentNumberQuery query) {
1031
0
  return query.query;
1032
0
}
1033
struct ParentNumberHash {
1034
  using is_transparent = void;
1035
1036
  template <typename T>
1037
378
  size_t operator()(const T& t) const {
1038
378
    return absl::HashOf(ObjectToParentNumber(t));
1039
378
  }
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
descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::ParentNumberHash::operator()<google::protobuf::FieldDescriptor*>(google::protobuf::FieldDescriptor* const&) const
Line
Count
Source
1037
160
  size_t operator()(const T& t) const {
1038
160
    return absl::HashOf(ObjectToParentNumber(t));
1039
160
  }
descriptor.cc:unsigned long google::protobuf::(anonymous namespace)::ParentNumberHash::operator()<google::protobuf::FieldDescriptor const*>(google::protobuf::FieldDescriptor const* const&) const
Line
Count
Source
1037
218
  size_t operator()(const T& t) const {
1038
218
    return absl::HashOf(ObjectToParentNumber(t));
1039
218
  }
1040
};
1041
struct ParentNumberEq {
1042
  using is_transparent = void;
1043
1044
  template <typename T, typename U>
1045
11
  bool operator()(const T& a, const U& b) const {
1046
11
    return ObjectToParentNumber(a) == ObjectToParentNumber(b);
1047
11
  }
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
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
Line
Count
Source
1045
11
  bool operator()(const T& a, const U& b) const {
1046
11
    return ObjectToParentNumber(a) == ObjectToParentNumber(b);
1047
11
  }
1048
};
1049
using FieldsByNumberSet = absl::flat_hash_set<const FieldDescriptor*,
1050
                                              ParentNumberHash, ParentNumberEq>;
1051
using EnumValuesByNumberSet =
1052
    absl::flat_hash_set<const EnumValueDescriptor*, ParentNumberHash,
1053
                        ParentNumberEq>;
1054
1055
// This is a map rather than a hash-map, since we use it to iterate
1056
// through all the extensions that extend a given Descriptor, and an
1057
// ordered data structure that implements lower_bound is convenient
1058
// for that.
1059
using ExtensionsGroupedByDescriptorMap =
1060
    absl::btree_map<std::pair<const Descriptor*, int>, const FieldDescriptor*>;
1061
using LocationsByPathMap =
1062
    absl::flat_hash_map<std::string, const SourceCodeInfo_Location*>;
1063
1064
0
absl::flat_hash_set<std::string>* NewAllowedProto3Extendee() {
1065
0
  const char* kOptionNames[] = {
1066
0
      "FileOptions",   "MessageOptions",   "FieldOptions",
1067
0
      "EnumOptions",   "EnumValueOptions", "ServiceOptions",
1068
0
      "MethodOptions", "OneofOptions",     "ExtensionRangeOptions"};
1069
0
  auto allowed_proto3_extendees = new absl::flat_hash_set<std::string>();
1070
0
  allowed_proto3_extendees->reserve(sizeof(kOptionNames) /
1071
0
                                    sizeof(kOptionNames[0]));
1072
1073
0
  for (const char* option_name : kOptionNames) {
1074
    // descriptor.proto has a different package name in opensource. We allow
1075
    // both so the opensource protocol compiler can also compile internal
1076
    // proto3 files with custom options. See: b/27567912
1077
0
    allowed_proto3_extendees->insert(std::string("google.protobuf.") +
1078
0
                                     option_name);
1079
    // Split the word to trick the opensource processing scripts so they
1080
    // will keep the original package name.
1081
0
    allowed_proto3_extendees->insert(std::string("proto2.") + option_name);
1082
0
  }
1083
0
  return allowed_proto3_extendees;
1084
0
}
1085
1086
// Checks whether the extendee type is allowed in proto3.
1087
// Only extensions to descriptor options are allowed. We use name comparison
1088
// instead of comparing the descriptor directly because the extensions may be
1089
// defined in a different pool.
1090
0
bool AllowedExtendeeInProto3(const std::string& name) {
1091
0
  static auto allowed_proto3_extendees =
1092
0
      internal::OnShutdownDelete(NewAllowedProto3Extendee());
1093
0
  return allowed_proto3_extendees->find(name) !=
1094
0
         allowed_proto3_extendees->end();
1095
0
}
1096
}  // anonymous namespace
1097
1098
// Contains tables specific to a particular file.  These tables are not
1099
// modified once the file has been constructed, so they need not be
1100
// protected by a mutex.  This makes operations that depend only on the
1101
// contents of a single file -- e.g. Descriptor::FindFieldByName() --
1102
// lock-free.
1103
//
1104
// For historical reasons, the definitions of the methods of
1105
// FileDescriptorTables and DescriptorPool::Tables are interleaved below.
1106
// These used to be a single class.
1107
class FileDescriptorTables {
1108
 public:
1109
  FileDescriptorTables();
1110
  ~FileDescriptorTables();
1111
1112
  // Empty table, used with placeholder files.
1113
  inline static const FileDescriptorTables& GetEmptyInstance();
1114
1115
  // -----------------------------------------------------------------
1116
  // Finding items.
1117
1118
  // Returns a null Symbol (symbol.IsNull() is true) if not found.
1119
  // TODO(sbenza): All callers to this function know the type they are looking
1120
  // for. If we propagate that information statically we can make the query
1121
  // faster.
1122
  inline Symbol FindNestedSymbol(const void* parent,
1123
                                 absl::string_view name) const;
1124
1125
  // These return nullptr if not found.
1126
  inline const FieldDescriptor* FindFieldByNumber(const Descriptor* parent,
1127
                                                  int number) const;
1128
  inline const FieldDescriptor* FindFieldByLowercaseName(
1129
      const void* parent, absl::string_view lowercase_name) const;
1130
  inline const FieldDescriptor* FindFieldByCamelcaseName(
1131
      const void* parent, absl::string_view camelcase_name) const;
1132
  inline const EnumValueDescriptor* FindEnumValueByNumber(
1133
      const EnumDescriptor* parent, int number) const;
1134
  // This creates a new EnumValueDescriptor if not found, in a thread-safe way.
1135
  inline const EnumValueDescriptor* FindEnumValueByNumberCreatingIfUnknown(
1136
      const EnumDescriptor* parent, int number) const;
1137
1138
  // -----------------------------------------------------------------
1139
  // Adding items.
1140
1141
  // These add items to the corresponding tables.  They return false if
1142
  // the key already exists in the table.
1143
  bool AddAliasUnderParent(const void* parent, absl::string_view name,
1144
                           Symbol symbol);
1145
  bool AddFieldByNumber(FieldDescriptor* field);
1146
  bool AddEnumValueByNumber(EnumValueDescriptor* value);
1147
1148
  // Populates p->first->locations_by_path_ from p->second.
1149
  // Unusual signature dictated by absl::call_once.
1150
  static void BuildLocationsByPath(
1151
      std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p);
1152
1153
  // Returns the location denoted by the specified path through info,
1154
  // or nullptr if not found.
1155
  // The value of info must be that of the corresponding FileDescriptor.
1156
  // (Conceptually a pure function, but stateful as an optimisation.)
1157
  const SourceCodeInfo_Location* GetSourceLocation(
1158
      const std::vector<int>& path, const SourceCodeInfo* info) const;
1159
1160
  // Must be called after BuildFileImpl(), even if the build failed and
1161
  // we are going to roll back to the last checkpoint.
1162
  void FinalizeTables();
1163
1164
 private:
1165
  const void* FindParentForFieldsByMap(const FieldDescriptor* field) const;
1166
  static void FieldsByLowercaseNamesLazyInitStatic(
1167
      const FileDescriptorTables* tables);
1168
  void FieldsByLowercaseNamesLazyInitInternal() const;
1169
  static void FieldsByCamelcaseNamesLazyInitStatic(
1170
      const FileDescriptorTables* tables);
1171
  void FieldsByCamelcaseNamesLazyInitInternal() const;
1172
1173
  SymbolsByParentSet symbols_by_parent_;
1174
  mutable absl::once_flag fields_by_lowercase_name_once_;
1175
  mutable absl::once_flag fields_by_camelcase_name_once_;
1176
  // Make these fields atomic to avoid race conditions with
1177
  // GetEstimatedOwnedMemoryBytesSize. Once the pointer is set the map won't
1178
  // change anymore.
1179
  mutable std::atomic<const FieldsByNameMap*> fields_by_lowercase_name_{};
1180
  mutable std::atomic<const FieldsByNameMap*> fields_by_camelcase_name_{};
1181
  FieldsByNumberSet fields_by_number_;  // Not including extensions.
1182
  EnumValuesByNumberSet enum_values_by_number_;
1183
  mutable EnumValuesByNumberSet unknown_enum_values_by_number_
1184
      PROTOBUF_GUARDED_BY(unknown_enum_values_mu_);
1185
1186
  // Populated on first request to save space, hence constness games.
1187
  mutable absl::once_flag locations_by_path_once_;
1188
  mutable LocationsByPathMap locations_by_path_;
1189
1190
  // Mutex to protect the unknown-enum-value map due to dynamic
1191
  // EnumValueDescriptor creation on unknown values.
1192
  mutable absl::Mutex unknown_enum_values_mu_;
1193
};
1194
1195
namespace internal {
1196
1197
// Small sequential allocator to be used within a single file.
1198
// Most of the memory for a single FileDescriptor and everything under it is
1199
// allocated in a single block of memory, with the FlatAllocator giving it out
1200
// in parts later.
1201
// The code first plans the total number of bytes needed by calling PlanArray
1202
// with all the allocations that will happen afterwards, then calls
1203
// FinalizePlanning passing the underlying allocator (the DescriptorPool::Tables
1204
// instance), and then proceeds to get the memory via
1205
// `AllocateArray`/`AllocateString` calls. The calls to PlanArray and
1206
// The calls have to match between planning and allocating, though not
1207
// necessarily in the same order.
1208
class FlatAllocator
1209
    : public decltype(ApplyTypeList<FlatAllocatorImpl>(
1210
          SortByAlignment<char, std::string, SourceCodeInfo,
1211
                          FileDescriptorTables,
1212
                          // Option types
1213
                          MessageOptions, FieldOptions, EnumOptions,
1214
                          EnumValueOptions, ExtensionRangeOptions, OneofOptions,
1215
                          ServiceOptions, MethodOptions, FileOptions>())) {};
1216
1217
}  // namespace internal
1218
1219
// ===================================================================
1220
// DescriptorPool::Tables
1221
1222
class DescriptorPool::Tables {
1223
 public:
1224
  Tables();
1225
  ~Tables();
1226
1227
  // Record the current state of the tables to the stack of checkpoints.
1228
  // Each call to AddCheckpoint() must be paired with exactly one call to either
1229
  // ClearLastCheckpoint() or RollbackToLastCheckpoint().
1230
  //
1231
  // This is used when building files, since some kinds of validation errors
1232
  // cannot be detected until the file's descriptors have already been added to
1233
  // the tables.
1234
  //
1235
  // This supports recursive checkpoints, since building a file may trigger
1236
  // recursive building of other files. Note that recursive checkpoints are not
1237
  // normally necessary; explicit dependencies are built prior to checkpointing.
1238
  // So although we recursively build transitive imports, there is at most one
1239
  // checkpoint in the stack during dependency building.
1240
  //
1241
  // Recursive checkpoints only arise during cross-linking of the descriptors.
1242
  // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and
1243
  // friends. If the pending file references an unknown symbol
1244
  // (e.g., it is not defined in the pending file's explicit dependencies), and
1245
  // the pool is using a fallback database, and that database contains a file
1246
  // defining that symbol, and that file has not yet been built by the pool,
1247
  // the pool builds the file during cross-linking, leading to another
1248
  // checkpoint.
1249
  void AddCheckpoint();
1250
1251
  // Mark the last checkpoint as having cleared successfully, removing it from
1252
  // the stack. If the stack is empty, all pending symbols will be committed.
1253
  //
1254
  // Note that this does not guarantee that the symbols added since the last
1255
  // checkpoint won't be rolled back: if a checkpoint gets rolled back,
1256
  // everything past that point gets rolled back, including symbols added after
1257
  // checkpoints that were pushed onto the stack after it and marked as cleared.
1258
  void ClearLastCheckpoint();
1259
1260
  // Roll back the Tables to the state of the checkpoint at the top of the
1261
  // stack, removing everything that was added after that point.
1262
  void RollbackToLastCheckpoint();
1263
1264
  // The stack of files which are currently being built.  Used to detect
1265
  // cyclic dependencies when loading files from a DescriptorDatabase.  Not
1266
  // used when fallback_database_ == nullptr.
1267
  std::vector<std::string> pending_files_;
1268
1269
  // A set of files which we have tried to load from the fallback database
1270
  // and encountered errors.  We will not attempt to load them again during
1271
  // execution of the current public API call, but for compatibility with
1272
  // legacy clients, this is cleared at the beginning of each public API call.
1273
  // Not used when fallback_database_ == nullptr.
1274
  absl::flat_hash_set<std::string> known_bad_files_;
1275
1276
  // A set of symbols which we have tried to load from the fallback database
1277
  // and encountered errors. We will not attempt to load them again during
1278
  // execution of the current public API call, but for compatibility with
1279
  // legacy clients, this is cleared at the beginning of each public API call.
1280
  absl::flat_hash_set<std::string> known_bad_symbols_;
1281
1282
  // The set of descriptors for which we've already loaded the full
1283
  // set of extensions numbers from fallback_database_.
1284
  absl::flat_hash_set<const Descriptor*> extensions_loaded_from_db_;
1285
1286
  // Maps type name to Descriptor::WellKnownType.  This is logically global
1287
  // and const, but we make it a member here to simplify its construction and
1288
  // destruction.  This only has 20-ish entries and is one per DescriptorPool,
1289
  // so the overhead is small.
1290
  absl::flat_hash_map<std::string, Descriptor::WellKnownType> well_known_types_;
1291
1292
  // -----------------------------------------------------------------
1293
  // Finding items.
1294
1295
  // Find symbols.  This returns a null Symbol (symbol.IsNull() is true)
1296
  // if not found.
1297
  inline Symbol FindSymbol(absl::string_view key) const;
1298
1299
  // This implements the body of DescriptorPool::Find*ByName().  It should
1300
  // really be a private method of DescriptorPool, but that would require
1301
  // declaring Symbol in descriptor.h, which would drag all kinds of other
1302
  // stuff into the header.  Yay C++.
1303
  Symbol FindByNameHelper(const DescriptorPool* pool, absl::string_view name);
1304
1305
  // These return nullptr if not found.
1306
  inline const FileDescriptor* FindFile(absl::string_view key) const;
1307
  inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
1308
                                              int number) const;
1309
  inline void FindAllExtensions(const Descriptor* extendee,
1310
                                std::vector<const FieldDescriptor*>* out) const;
1311
1312
  // -----------------------------------------------------------------
1313
  // Adding items.
1314
1315
  // These add items to the corresponding tables.  They return false if
1316
  // the key already exists in the table.  For AddSymbol(), the string passed
1317
  // in must be one that was constructed using AllocateString(), as it will
1318
  // be used as a key in the symbols_by_name_ map without copying.
1319
  bool AddSymbol(absl::string_view full_name, Symbol symbol);
1320
  bool AddFile(const FileDescriptor* file);
1321
  bool AddExtension(const FieldDescriptor* field);
1322
1323
  // -----------------------------------------------------------------
1324
  // Allocating memory.
1325
1326
  // Allocate an object which will be reclaimed when the pool is
1327
  // destroyed.  Note that the object's destructor will never be called,
1328
  // so its fields must be plain old data (primitive data types and
1329
  // pointers).  All of the descriptor types are such objects.
1330
  template <typename Type>
1331
  Type* Allocate();
1332
1333
  // Allocate some bytes which will be reclaimed when the pool is
1334
  // destroyed. Memory is aligned to 8 bytes.
1335
  void* AllocateBytes(int size);
1336
1337
  // Create a FlatAllocation for the corresponding sizes.
1338
  // All objects within it will be default constructed.
1339
  // The whole allocation, including the non-trivial objects within, will be
1340
  // destroyed with the pool.
1341
  template <typename... T>
1342
  internal::FlatAllocator::Allocation* CreateFlatAlloc(
1343
      const TypeMap<IntT, T...>& sizes);
1344
1345
1346
 private:
1347
  // All memory allocated in the pool.  Must be first as other objects can
1348
  // point into these.
1349
  struct MiscDeleter {
1350
0
    void operator()(int* p) const { internal::SizedDelete(p, *p + 8); }
1351
  };
1352
  // Miscellaneous allocations are length prefixed. The paylaod is 8 bytes after
1353
  // the `int` that contains the size. This keeps the payload aligned.
1354
  std::vector<std::unique_ptr<int, MiscDeleter>> misc_allocs_;
1355
  struct FlatAllocDeleter {
1356
0
    void operator()(internal::FlatAllocator::Allocation* p) const {
1357
0
      p->Destroy();
1358
0
    }
1359
  };
1360
  std::vector<
1361
      std::unique_ptr<internal::FlatAllocator::Allocation, FlatAllocDeleter>>
1362
      flat_allocs_;
1363
1364
  SymbolsByNameSet symbols_by_name_;
1365
  FilesByNameSet files_by_name_;
1366
  ExtensionsGroupedByDescriptorMap extensions_;
1367
1368
  struct CheckPoint {
1369
    explicit CheckPoint(const Tables* tables)
1370
        : flat_allocations_before_checkpoint(
1371
              static_cast<int>(tables->flat_allocs_.size())),
1372
          misc_allocations_before_checkpoint(
1373
              static_cast<int>(tables->misc_allocs_.size())),
1374
          pending_symbols_before_checkpoint(
1375
              tables->symbols_after_checkpoint_.size()),
1376
          pending_files_before_checkpoint(
1377
              tables->files_after_checkpoint_.size()),
1378
          pending_extensions_before_checkpoint(
1379
6
              tables->extensions_after_checkpoint_.size()) {}
1380
    int flat_allocations_before_checkpoint;
1381
    int misc_allocations_before_checkpoint;
1382
    int pending_symbols_before_checkpoint;
1383
    int pending_files_before_checkpoint;
1384
    int pending_extensions_before_checkpoint;
1385
  };
1386
  std::vector<CheckPoint> checkpoints_;
1387
  std::vector<Symbol> symbols_after_checkpoint_;
1388
  std::vector<const FileDescriptor*> files_after_checkpoint_;
1389
  std::vector<std::pair<const Descriptor*, int>> extensions_after_checkpoint_;
1390
};
1391
1392
2
DescriptorPool::Tables::Tables() {
1393
2
  well_known_types_.insert({
1394
2
      {"google.protobuf.DoubleValue", Descriptor::WELLKNOWNTYPE_DOUBLEVALUE},
1395
2
      {"google.protobuf.FloatValue", Descriptor::WELLKNOWNTYPE_FLOATVALUE},
1396
2
      {"google.protobuf.Int64Value", Descriptor::WELLKNOWNTYPE_INT64VALUE},
1397
2
      {"google.protobuf.UInt64Value", Descriptor::WELLKNOWNTYPE_UINT64VALUE},
1398
2
      {"google.protobuf.Int32Value", Descriptor::WELLKNOWNTYPE_INT32VALUE},
1399
2
      {"google.protobuf.UInt32Value", Descriptor::WELLKNOWNTYPE_UINT32VALUE},
1400
2
      {"google.protobuf.StringValue", Descriptor::WELLKNOWNTYPE_STRINGVALUE},
1401
2
      {"google.protobuf.BytesValue", Descriptor::WELLKNOWNTYPE_BYTESVALUE},
1402
2
      {"google.protobuf.BoolValue", Descriptor::WELLKNOWNTYPE_BOOLVALUE},
1403
2
      {"google.protobuf.Any", Descriptor::WELLKNOWNTYPE_ANY},
1404
2
      {"google.protobuf.FieldMask", Descriptor::WELLKNOWNTYPE_FIELDMASK},
1405
2
      {"google.protobuf.Duration", Descriptor::WELLKNOWNTYPE_DURATION},
1406
2
      {"google.protobuf.Timestamp", Descriptor::WELLKNOWNTYPE_TIMESTAMP},
1407
2
      {"google.protobuf.Value", Descriptor::WELLKNOWNTYPE_VALUE},
1408
2
      {"google.protobuf.ListValue", Descriptor::WELLKNOWNTYPE_LISTVALUE},
1409
2
      {"google.protobuf.Struct", Descriptor::WELLKNOWNTYPE_STRUCT},
1410
2
  });
1411
2
}
1412
1413
0
DescriptorPool::Tables::~Tables() { ABSL_DCHECK(checkpoints_.empty()); }
1414
1415
6
FileDescriptorTables::FileDescriptorTables() {}
1416
1417
0
FileDescriptorTables::~FileDescriptorTables() {
1418
0
  delete fields_by_lowercase_name_.load(std::memory_order_acquire);
1419
0
  delete fields_by_camelcase_name_.load(std::memory_order_acquire);
1420
0
}
1421
1422
0
inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() {
1423
0
  static auto file_descriptor_tables =
1424
0
      internal::OnShutdownDelete(new FileDescriptorTables());
1425
0
  return *file_descriptor_tables;
1426
0
}
1427
1428
6
void DescriptorPool::Tables::AddCheckpoint() {
1429
6
  checkpoints_.emplace_back(this);
1430
6
}
1431
1432
6
void DescriptorPool::Tables::ClearLastCheckpoint() {
1433
6
  ABSL_DCHECK(!checkpoints_.empty());
1434
6
  checkpoints_.pop_back();
1435
6
  if (checkpoints_.empty()) {
1436
    // All checkpoints have been cleared: we can now commit all of the pending
1437
    // data.
1438
6
    symbols_after_checkpoint_.clear();
1439
6
    files_after_checkpoint_.clear();
1440
6
    extensions_after_checkpoint_.clear();
1441
6
  }
1442
6
}
1443
1444
0
void DescriptorPool::Tables::RollbackToLastCheckpoint() {
1445
0
  ABSL_DCHECK(!checkpoints_.empty());
1446
0
  const CheckPoint& checkpoint = checkpoints_.back();
1447
1448
0
  for (size_t i = checkpoint.pending_symbols_before_checkpoint;
1449
0
       i < symbols_after_checkpoint_.size(); i++) {
1450
0
    symbols_by_name_.erase(symbols_after_checkpoint_[i]);
1451
0
  }
1452
0
  for (size_t i = checkpoint.pending_files_before_checkpoint;
1453
0
       i < files_after_checkpoint_.size(); i++) {
1454
0
    files_by_name_.erase(files_after_checkpoint_[i]);
1455
0
  }
1456
0
  for (size_t i = checkpoint.pending_extensions_before_checkpoint;
1457
0
       i < extensions_after_checkpoint_.size(); i++) {
1458
0
    extensions_.erase(extensions_after_checkpoint_[i]);
1459
0
  }
1460
1461
0
  symbols_after_checkpoint_.resize(
1462
0
      checkpoint.pending_symbols_before_checkpoint);
1463
0
  files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint);
1464
0
  extensions_after_checkpoint_.resize(
1465
0
      checkpoint.pending_extensions_before_checkpoint);
1466
1467
0
  flat_allocs_.resize(checkpoint.flat_allocations_before_checkpoint);
1468
0
  misc_allocs_.resize(checkpoint.misc_allocations_before_checkpoint);
1469
0
  checkpoints_.pop_back();
1470
0
}
1471
1472
// -------------------------------------------------------------------
1473
1474
136
inline Symbol DescriptorPool::Tables::FindSymbol(absl::string_view key) const {
1475
136
  auto it = symbols_by_name_.find(FullNameQuery{key});
1476
136
  return it == symbols_by_name_.end() ? Symbol() : *it;
1477
136
}
1478
1479
inline Symbol FileDescriptorTables::FindNestedSymbol(
1480
152k
    const void* parent, absl::string_view name) const {
1481
152k
  auto it = symbols_by_parent_.find(ParentNameQuery{{parent, name}});
1482
152k
  return it == symbols_by_parent_.end() ? Symbol() : *it;
1483
152k
}
1484
1485
Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool,
1486
0
                                                absl::string_view name) {
1487
0
  if (pool->mutex_ != nullptr) {
1488
    // Fast path: the Symbol is already cached.  This is just a hash lookup.
1489
0
    absl::ReaderMutexLock lock(pool->mutex_);
1490
0
    if (known_bad_symbols_.empty() && known_bad_files_.empty()) {
1491
0
      Symbol result = FindSymbol(name);
1492
0
      if (!result.IsNull()) return result;
1493
0
    }
1494
0
  }
1495
0
  absl::MutexLockMaybe lock(pool->mutex_);
1496
0
  if (pool->fallback_database_ != nullptr) {
1497
0
    known_bad_symbols_.clear();
1498
0
    known_bad_files_.clear();
1499
0
  }
1500
0
  Symbol result = FindSymbol(name);
1501
1502
0
  if (result.IsNull() && pool->underlay_ != nullptr) {
1503
    // Symbol not found; check the underlay.
1504
0
    result = pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name);
1505
0
  }
1506
1507
0
  if (result.IsNull()) {
1508
    // Symbol still not found, so check fallback database.
1509
0
    if (pool->TryFindSymbolInFallbackDatabase(name)) {
1510
0
      result = FindSymbol(name);
1511
0
    }
1512
0
  }
1513
1514
0
  return result;
1515
0
}
1516
1517
inline const FileDescriptor* DescriptorPool::Tables::FindFile(
1518
18
    absl::string_view key) const {
1519
18
  auto it = files_by_name_.find(key);
1520
18
  if (it == files_by_name_.end()) return nullptr;
1521
6
  return *it;
1522
18
}
1523
1524
inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
1525
0
    const Descriptor* parent, int number) const {
1526
  // If `number` is within the sequential range, just index into the parent
1527
  // without doing a table lookup.
1528
0
  if (parent != nullptr &&  //
1529
0
      1 <= number && number <= parent->sequential_field_limit_) {
1530
0
    return parent->field(number - 1);
1531
0
  }
1532
1533
0
  auto it = fields_by_number_.find(ParentNumberQuery{{parent, number}});
1534
0
  return it == fields_by_number_.end() ? nullptr : *it;
1535
0
}
1536
1537
const void* FileDescriptorTables::FindParentForFieldsByMap(
1538
0
    const FieldDescriptor* field) const {
1539
0
  if (field->is_extension()) {
1540
0
    if (field->extension_scope() == nullptr) {
1541
0
      return field->file();
1542
0
    } else {
1543
0
      return field->extension_scope();
1544
0
    }
1545
0
  } else {
1546
0
    return field->containing_type();
1547
0
  }
1548
0
}
1549
1550
void FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic(
1551
0
    const FileDescriptorTables* tables) {
1552
0
  tables->FieldsByLowercaseNamesLazyInitInternal();
1553
0
}
1554
1555
0
void FileDescriptorTables::FieldsByLowercaseNamesLazyInitInternal() const {
1556
0
  auto* map = new FieldsByNameMap;
1557
0
  for (Symbol symbol : symbols_by_parent_) {
1558
0
    const FieldDescriptor* field = symbol.field_descriptor();
1559
0
    if (!field) continue;
1560
0
    (*map)[{FindParentForFieldsByMap(field), field->lowercase_name().c_str()}] =
1561
0
        field;
1562
0
  }
1563
0
  fields_by_lowercase_name_.store(map, std::memory_order_release);
1564
0
}
1565
1566
inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
1567
0
    const void* parent, absl::string_view lowercase_name) const {
1568
0
  absl::call_once(fields_by_lowercase_name_once_,
1569
0
                  &FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic,
1570
0
                  this);
1571
0
  const auto* fields =
1572
0
      fields_by_lowercase_name_.load(std::memory_order_acquire);
1573
0
  auto it = fields->find({parent, lowercase_name});
1574
0
  if (it == fields->end()) return nullptr;
1575
0
  return it->second;
1576
0
}
1577
1578
void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic(
1579
0
    const FileDescriptorTables* tables) {
1580
0
  tables->FieldsByCamelcaseNamesLazyInitInternal();
1581
0
}
1582
1583
0
void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitInternal() const {
1584
0
  auto* map = new FieldsByNameMap;
1585
0
  for (Symbol symbol : symbols_by_parent_) {
1586
0
    const FieldDescriptor* field = symbol.field_descriptor();
1587
0
    if (!field) continue;
1588
0
    (*map)[{FindParentForFieldsByMap(field), field->camelcase_name().c_str()}] =
1589
0
        field;
1590
0
  }
1591
0
  fields_by_camelcase_name_.store(map, std::memory_order_release);
1592
0
}
1593
1594
inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
1595
0
    const void* parent, absl::string_view camelcase_name) const {
1596
0
  absl::call_once(fields_by_camelcase_name_once_,
1597
0
                  FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic,
1598
0
                  this);
1599
0
  auto* fields = fields_by_camelcase_name_.load(std::memory_order_acquire);
1600
0
  auto it = fields->find({parent, camelcase_name});
1601
0
  if (it == fields->end()) return nullptr;
1602
0
  return it->second;
1603
0
}
1604
1605
inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
1606
0
    const EnumDescriptor* parent, int number) const {
1607
  // If `number` is within the sequential range, just index into the parent
1608
  // without doing a table lookup.
1609
0
  const int base = parent->value(0)->number();
1610
0
  if (base <= number &&
1611
0
      number <= static_cast<int64_t>(base) + parent->sequential_value_limit_) {
1612
0
    return parent->value(number - base);
1613
0
  }
1614
1615
0
  auto it = enum_values_by_number_.find(ParentNumberQuery{{parent, number}});
1616
0
  return it == enum_values_by_number_.end() ? nullptr : *it;
1617
0
}
1618
1619
inline const EnumValueDescriptor*
1620
FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
1621
0
    const EnumDescriptor* parent, int number) const {
1622
  // First try, with map of compiled-in values.
1623
0
  {
1624
0
    const auto* value = FindEnumValueByNumber(parent, number);
1625
0
    if (value != nullptr) {
1626
0
      return value;
1627
0
    }
1628
0
  }
1629
1630
0
  const ParentNumberQuery query{{parent, number}};
1631
1632
  // Second try, with reader lock held on unknown enum values: common case.
1633
0
  {
1634
0
    absl::ReaderMutexLock l(&unknown_enum_values_mu_);
1635
0
    auto it = unknown_enum_values_by_number_.find(query);
1636
0
    if (it != unknown_enum_values_by_number_.end()) {
1637
0
      return *it;
1638
0
    }
1639
0
  }
1640
  // If not found, try again with writer lock held, and create new descriptor if
1641
  // necessary.
1642
0
  {
1643
0
    absl::WriterMutexLock l(&unknown_enum_values_mu_);
1644
0
    auto it = unknown_enum_values_by_number_.find(query);
1645
0
    if (it != unknown_enum_values_by_number_.end()) {
1646
0
      return *it;
1647
0
    }
1648
1649
    // Create an EnumValueDescriptor dynamically. We don't insert it into the
1650
    // EnumDescriptor (it's not a part of the enum as originally defined), but
1651
    // we do insert it into the table so that we can return the same pointer
1652
    // later.
1653
0
    std::string enum_value_name = absl::StrFormat(
1654
0
        "UNKNOWN_ENUM_VALUE_%s_%d", parent->name().c_str(), number);
1655
0
    auto* pool = DescriptorPool::generated_pool();
1656
0
    auto* tables = const_cast<DescriptorPool::Tables*>(pool->tables_.get());
1657
0
    internal::FlatAllocator alloc;
1658
0
    alloc.PlanArray<EnumValueDescriptor>(1);
1659
0
    alloc.PlanArray<std::string>(2);
1660
1661
0
    {
1662
      // Must lock the pool because we will do allocations in the shared arena.
1663
0
      absl::MutexLockMaybe l2(pool->mutex_);
1664
0
      alloc.FinalizePlanning(tables);
1665
0
    }
1666
0
    EnumValueDescriptor* result = alloc.AllocateArray<EnumValueDescriptor>(1);
1667
0
    result->all_names_ = alloc.AllocateStrings(
1668
0
        enum_value_name,
1669
0
        absl::StrCat(parent->full_name(), ".", enum_value_name));
1670
0
    result->number_ = number;
1671
0
    result->type_ = parent;
1672
0
    result->options_ = &EnumValueOptions::default_instance();
1673
0
    unknown_enum_values_by_number_.insert(result);
1674
0
    return result;
1675
0
  }
1676
0
}
1677
1678
inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
1679
0
    const Descriptor* extendee, int number) const {
1680
0
  auto it = extensions_.find({extendee, number});
1681
0
  if (it == extensions_.end()) return nullptr;
1682
0
  return it->second;
1683
0
}
1684
1685
inline void DescriptorPool::Tables::FindAllExtensions(
1686
    const Descriptor* extendee,
1687
0
    std::vector<const FieldDescriptor*>* out) const {
1688
0
  ExtensionsGroupedByDescriptorMap::const_iterator it =
1689
0
      extensions_.lower_bound(std::make_pair(extendee, 0));
1690
0
  for (; it != extensions_.end() && it->first.first == extendee; ++it) {
1691
0
    out->push_back(it->second);
1692
0
  }
1693
0
}
1694
1695
// -------------------------------------------------------------------
1696
1697
bool DescriptorPool::Tables::AddSymbol(absl::string_view full_name,
1698
534
                                       Symbol symbol) {
1699
534
  ABSL_DCHECK_EQ(full_name, symbol.full_name());
1700
534
  if (symbols_by_name_.insert(symbol).second) {
1701
534
    symbols_after_checkpoint_.push_back(symbol);
1702
534
    return true;
1703
534
  } else {
1704
0
    return false;
1705
0
  }
1706
534
}
1707
1708
bool FileDescriptorTables::AddAliasUnderParent(const void* parent,
1709
                                               absl::string_view name,
1710
624
                                               Symbol symbol) {
1711
624
  ABSL_DCHECK_EQ(name, symbol.parent_name_key().second);
1712
624
  ABSL_DCHECK_EQ(parent, symbol.parent_name_key().first);
1713
624
  return symbols_by_parent_.insert(symbol).second;
1714
624
}
1715
1716
6
bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
1717
6
  if (files_by_name_.insert(file).second) {
1718
6
    files_after_checkpoint_.push_back(file);
1719
6
    return true;
1720
6
  } else {
1721
0
    return false;
1722
0
  }
1723
6
}
1724
1725
6
void FileDescriptorTables::FinalizeTables() {}
1726
1727
330
bool FileDescriptorTables::AddFieldByNumber(FieldDescriptor* field) {
1728
  // Skip fields that are at the start of the sequence.
1729
330
  if (field->containing_type() != nullptr && field->number() >= 1 &&
1730
330
      field->number() <= field->containing_type()->sequential_field_limit_) {
1731
170
    if (field->is_extension()) {
1732
      // Conflicts with the field that already exists in the sequential range.
1733
0
      return false;
1734
0
    }
1735
    // Only return true if the field at that index matches. Otherwise it
1736
    // conflicts with the existing field in the sequential range.
1737
170
    return field->containing_type()->field(field->number() - 1) == field;
1738
170
  }
1739
1740
160
  return fields_by_number_.insert(field).second;
1741
330
}
1742
1743
98
bool FileDescriptorTables::AddEnumValueByNumber(EnumValueDescriptor* value) {
1744
  // Skip values that are at the start of the sequence.
1745
98
  const int base = value->type()->value(0)->number();
1746
98
  if (base <= value->number() &&
1747
98
      value->number() <=
1748
98
          static_cast<int64_t>(base) + value->type()->sequential_value_limit_)
1749
98
    return true;
1750
0
  return enum_values_by_number_.insert(value).second;
1751
98
}
1752
1753
0
bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
1754
0
  auto it_inserted =
1755
0
      extensions_.insert({{field->containing_type(), field->number()}, field});
1756
0
  if (it_inserted.second) {
1757
0
    extensions_after_checkpoint_.push_back(it_inserted.first->first);
1758
0
    return true;
1759
0
  } else {
1760
0
    return false;
1761
0
  }
1762
0
}
1763
1764
// -------------------------------------------------------------------
1765
1766
template <typename Type>
1767
4
Type* DescriptorPool::Tables::Allocate() {
1768
4
  static_assert(std::is_trivially_destructible<Type>::value, "");
1769
4
  static_assert(alignof(Type) <= 8, "");
1770
4
  return ::new (AllocateBytes(sizeof(Type))) Type{};
1771
4
}
1772
1773
4
void* DescriptorPool::Tables::AllocateBytes(int size) {
1774
4
  if (size == 0) return nullptr;
1775
4
  void* p = ::operator new(size + RoundUpTo<8>(sizeof(int)));
1776
4
  int* sizep = static_cast<int*>(p);
1777
4
  misc_allocs_.emplace_back(sizep);
1778
4
  *sizep = size;
1779
4
  return static_cast<char*>(p) + RoundUpTo<8>(sizeof(int));
1780
4
}
1781
1782
template <typename... T>
1783
internal::FlatAllocator::Allocation* DescriptorPool::Tables::CreateFlatAlloc(
1784
6
    const TypeMap<IntT, T...>& sizes) {
1785
6
  auto ends = CalculateEnds(sizes);
1786
6
  using FlatAlloc = internal::FlatAllocator::Allocation;
1787
1788
6
  int last_end = ends.template Get<
1789
6
      typename std::tuple_element<sizeof...(T) - 1, std::tuple<T...>>::type>();
1790
6
  size_t total_size =
1791
6
      last_end + RoundUpTo<FlatAlloc::kMaxAlign>(sizeof(FlatAlloc));
1792
6
  char* data = static_cast<char*>(::operator new(total_size));
1793
6
  auto* res = ::new (data) FlatAlloc(ends);
1794
6
  flat_allocs_.emplace_back(res);
1795
1796
6
  return res;
1797
6
}
1798
1799
void FileDescriptorTables::BuildLocationsByPath(
1800
0
    std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p) {
1801
0
  for (int i = 0, len = p->second->location_size(); i < len; ++i) {
1802
0
    const SourceCodeInfo_Location* loc = &p->second->location().Get(i);
1803
0
    p->first->locations_by_path_[absl::StrJoin(loc->path(), ",")] = loc;
1804
0
  }
1805
0
}
1806
1807
const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
1808
0
    const std::vector<int>& path, const SourceCodeInfo* info) const {
1809
0
  std::pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
1810
0
      std::make_pair(this, info));
1811
0
  absl::call_once(locations_by_path_once_,
1812
0
                  FileDescriptorTables::BuildLocationsByPath, &p);
1813
0
  auto it = locations_by_path_.find(absl::StrJoin(path, ","));
1814
0
  if (it == locations_by_path_.end()) return nullptr;
1815
0
  return it->second;
1816
0
}
1817
1818
// ===================================================================
1819
// DescriptorPool
1820
1821
0
DescriptorPool::ErrorCollector::~ErrorCollector() {}
1822
1823
DescriptorPool::DescriptorPool()
1824
    : mutex_(nullptr),
1825
      fallback_database_(nullptr),
1826
      default_error_collector_(nullptr),
1827
      underlay_(nullptr),
1828
      tables_(new Tables),
1829
      enforce_dependencies_(true),
1830
      lazily_build_dependencies_(false),
1831
      allow_unknown_(false),
1832
      enforce_weak_(false),
1833
      disallow_enforce_utf8_(false),
1834
0
      deprecated_legacy_json_field_conflicts_(false) {}
1835
1836
DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
1837
                               ErrorCollector* error_collector)
1838
    : mutex_(new absl::Mutex),
1839
      fallback_database_(fallback_database),
1840
      default_error_collector_(error_collector),
1841
      underlay_(nullptr),
1842
      tables_(new Tables),
1843
      enforce_dependencies_(true),
1844
      lazily_build_dependencies_(false),
1845
      allow_unknown_(false),
1846
      enforce_weak_(false),
1847
      disallow_enforce_utf8_(false),
1848
2
      deprecated_legacy_json_field_conflicts_(false) {}
1849
1850
DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
1851
    : mutex_(nullptr),
1852
      fallback_database_(nullptr),
1853
      default_error_collector_(nullptr),
1854
      underlay_(underlay),
1855
      tables_(new Tables),
1856
      enforce_dependencies_(true),
1857
      lazily_build_dependencies_(false),
1858
      allow_unknown_(false),
1859
      enforce_weak_(false),
1860
      disallow_enforce_utf8_(false),
1861
0
      deprecated_legacy_json_field_conflicts_(false) {}
1862
1863
0
DescriptorPool::~DescriptorPool() {
1864
0
  if (mutex_ != nullptr) delete mutex_;
1865
0
}
1866
1867
// DescriptorPool::BuildFile() defined later.
1868
// DescriptorPool::BuildFileCollectingErrors() defined later.
1869
1870
2
void DescriptorPool::InternalDontEnforceDependencies() {
1871
2
  enforce_dependencies_ = false;
1872
2
}
1873
1874
void DescriptorPool::AddUnusedImportTrackFile(absl::string_view file_name,
1875
0
                                              bool is_error) {
1876
0
  unused_import_track_files_[file_name] = is_error;
1877
0
}
1878
1879
1880
0
void DescriptorPool::ClearUnusedImportTrackFiles() {
1881
0
  unused_import_track_files_.clear();
1882
0
}
1883
1884
0
bool DescriptorPool::InternalIsFileLoaded(absl::string_view filename) const {
1885
0
  absl::MutexLockMaybe lock(mutex_);
1886
0
  return tables_->FindFile(filename) != nullptr;
1887
0
}
1888
1889
// generated_pool ====================================================
1890
1891
namespace {
1892
1893
1894
14
EncodedDescriptorDatabase* GeneratedDatabase() {
1895
14
  static auto generated_database =
1896
14
      internal::OnShutdownDelete(new EncodedDescriptorDatabase());
1897
14
  return generated_database;
1898
14
}
1899
1900
2
DescriptorPool* NewGeneratedPool() {
1901
2
  auto generated_pool = new DescriptorPool(GeneratedDatabase());
1902
2
  generated_pool->InternalSetLazilyBuildDependencies();
1903
2
  return generated_pool;
1904
2
}
1905
1906
}  // anonymous namespace
1907
1908
0
DescriptorDatabase* DescriptorPool::internal_generated_database() {
1909
0
  return GeneratedDatabase();
1910
0
}
1911
1912
84
DescriptorPool* DescriptorPool::internal_generated_pool() {
1913
84
  static DescriptorPool* generated_pool =
1914
84
      internal::OnShutdownDelete(NewGeneratedPool());
1915
84
  return generated_pool;
1916
84
}
1917
1918
2
const DescriptorPool* DescriptorPool::generated_pool() {
1919
2
  const DescriptorPool* pool = internal_generated_pool();
1920
  // Ensure that descriptor.proto gets registered in the generated pool. It is a
1921
  // special case because it is included in the full runtime. We have to avoid
1922
  // registering it pre-main, because we need to ensure that the linker
1923
  // --gc-sections step can strip out the full runtime if it is unused.
1924
2
  DescriptorProto::descriptor();
1925
2
  return pool;
1926
2
}
1927
1928
1929
void DescriptorPool::InternalAddGeneratedFile(
1930
12
    const void* encoded_file_descriptor, int size) {
1931
  // So, this function is called in the process of initializing the
1932
  // descriptors for generated proto classes.  Each generated .pb.cc file
1933
  // has an internal procedure called AddDescriptors() which is called at
1934
  // process startup, and that function calls this one in order to register
1935
  // the raw bytes of the FileDescriptorProto representing the file.
1936
  //
1937
  // We do not actually construct the descriptor objects right away.  We just
1938
  // hang on to the bytes until they are actually needed.  We actually construct
1939
  // the descriptor the first time one of the following things happens:
1940
  // * Someone calls a method like descriptor(), GetDescriptor(), or
1941
  //   GetReflection() on the generated types, which requires returning the
1942
  //   descriptor or an object based on it.
1943
  // * Someone looks up the descriptor in DescriptorPool::generated_pool().
1944
  //
1945
  // Once one of these happens, the DescriptorPool actually parses the
1946
  // FileDescriptorProto and generates a FileDescriptor (and all its children)
1947
  // based on it.
1948
  //
1949
  // Note that FileDescriptorProto is itself a generated protocol message.
1950
  // Therefore, when we parse one, we have to be very careful to avoid using
1951
  // any descriptor-based operations, since this might cause infinite recursion
1952
  // or deadlock.
1953
12
  ABSL_CHECK(GeneratedDatabase()->Add(encoded_file_descriptor, size));
1954
12
}
1955
1956
1957
// Find*By* methods ==================================================
1958
1959
// TODO(kenton):  There's a lot of repeated code here, but I'm not sure if
1960
//   there's any good way to factor it out.  Think about this some time when
1961
//   there's nothing more important to do (read: never).
1962
1963
const FileDescriptor* DescriptorPool::FindFileByName(
1964
6
    absl::string_view name) const {
1965
6
  absl::MutexLockMaybe lock(mutex_);
1966
6
  if (fallback_database_ != nullptr) {
1967
6
    tables_->known_bad_symbols_.clear();
1968
6
    tables_->known_bad_files_.clear();
1969
6
  }
1970
6
  const FileDescriptor* result = tables_->FindFile(name);
1971
6
  if (result != nullptr) return result;
1972
6
  if (underlay_ != nullptr) {
1973
0
    result = underlay_->FindFileByName(name);
1974
0
    if (result != nullptr) return result;
1975
0
  }
1976
6
  if (TryFindFileInFallbackDatabase(name)) {
1977
6
    result = tables_->FindFile(name);
1978
6
    if (result != nullptr) return result;
1979
6
  }
1980
0
  return nullptr;
1981
6
}
1982
1983
const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
1984
0
    absl::string_view symbol_name) const {
1985
0
  absl::MutexLockMaybe lock(mutex_);
1986
0
  if (fallback_database_ != nullptr) {
1987
0
    tables_->known_bad_symbols_.clear();
1988
0
    tables_->known_bad_files_.clear();
1989
0
  }
1990
0
  Symbol result = tables_->FindSymbol(symbol_name);
1991
0
  if (!result.IsNull()) return result.GetFile();
1992
0
  if (underlay_ != nullptr) {
1993
0
    const FileDescriptor* file_result =
1994
0
        underlay_->FindFileContainingSymbol(symbol_name);
1995
0
    if (file_result != nullptr) return file_result;
1996
0
  }
1997
0
  if (TryFindSymbolInFallbackDatabase(symbol_name)) {
1998
0
    result = tables_->FindSymbol(symbol_name);
1999
0
    if (!result.IsNull()) return result.GetFile();
2000
0
  }
2001
0
  return nullptr;
2002
0
}
2003
2004
const Descriptor* DescriptorPool::FindMessageTypeByName(
2005
0
    absl::string_view name) const {
2006
0
  return tables_->FindByNameHelper(this, name).descriptor();
2007
0
}
2008
2009
const FieldDescriptor* DescriptorPool::FindFieldByName(
2010
0
    absl::string_view name) const {
2011
0
  if (const FieldDescriptor* field =
2012
0
          tables_->FindByNameHelper(this, name).field_descriptor()) {
2013
0
    if (!field->is_extension()) {
2014
0
      return field;
2015
0
    }
2016
0
  }
2017
0
  return nullptr;
2018
0
}
2019
2020
const FieldDescriptor* DescriptorPool::FindExtensionByName(
2021
0
    absl::string_view name) const {
2022
0
  if (const FieldDescriptor* field =
2023
0
          tables_->FindByNameHelper(this, name).field_descriptor()) {
2024
0
    if (field->is_extension()) {
2025
0
      return field;
2026
0
    }
2027
0
  }
2028
0
  return nullptr;
2029
0
}
2030
2031
const OneofDescriptor* DescriptorPool::FindOneofByName(
2032
0
    absl::string_view name) const {
2033
0
  return tables_->FindByNameHelper(this, name).oneof_descriptor();
2034
0
}
2035
2036
const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
2037
0
    absl::string_view name) const {
2038
0
  return tables_->FindByNameHelper(this, name).enum_descriptor();
2039
0
}
2040
2041
const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
2042
0
    absl::string_view name) const {
2043
0
  return tables_->FindByNameHelper(this, name).enum_value_descriptor();
2044
0
}
2045
2046
const ServiceDescriptor* DescriptorPool::FindServiceByName(
2047
0
    absl::string_view name) const {
2048
0
  return tables_->FindByNameHelper(this, name).service_descriptor();
2049
0
}
2050
2051
const MethodDescriptor* DescriptorPool::FindMethodByName(
2052
0
    absl::string_view name) const {
2053
0
  return tables_->FindByNameHelper(this, name).method_descriptor();
2054
0
}
2055
2056
const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
2057
0
    const Descriptor* extendee, int number) const {
2058
0
  if (extendee->extension_range_count() == 0) return nullptr;
2059
  // A faster path to reduce lock contention in finding extensions, assuming
2060
  // most extensions will be cache hit.
2061
0
  if (mutex_ != nullptr) {
2062
0
    absl::ReaderMutexLock lock(mutex_);
2063
0
    const FieldDescriptor* result = tables_->FindExtension(extendee, number);
2064
0
    if (result != nullptr) {
2065
0
      return result;
2066
0
    }
2067
0
  }
2068
0
  absl::MutexLockMaybe lock(mutex_);
2069
0
  if (fallback_database_ != nullptr) {
2070
0
    tables_->known_bad_symbols_.clear();
2071
0
    tables_->known_bad_files_.clear();
2072
0
  }
2073
0
  const FieldDescriptor* result = tables_->FindExtension(extendee, number);
2074
0
  if (result != nullptr) {
2075
0
    return result;
2076
0
  }
2077
0
  if (underlay_ != nullptr) {
2078
0
    result = underlay_->FindExtensionByNumber(extendee, number);
2079
0
    if (result != nullptr) return result;
2080
0
  }
2081
0
  if (TryFindExtensionInFallbackDatabase(extendee, number)) {
2082
0
    result = tables_->FindExtension(extendee, number);
2083
0
    if (result != nullptr) {
2084
0
      return result;
2085
0
    }
2086
0
  }
2087
0
  return nullptr;
2088
0
}
2089
2090
const FieldDescriptor* DescriptorPool::InternalFindExtensionByNumberNoLock(
2091
0
    const Descriptor* extendee, int number) const {
2092
0
  if (extendee->extension_range_count() == 0) return nullptr;
2093
2094
0
  const FieldDescriptor* result = tables_->FindExtension(extendee, number);
2095
0
  if (result != nullptr) {
2096
0
    return result;
2097
0
  }
2098
2099
0
  if (underlay_ != nullptr) {
2100
0
    result = underlay_->InternalFindExtensionByNumberNoLock(extendee, number);
2101
0
    if (result != nullptr) return result;
2102
0
  }
2103
2104
0
  return nullptr;
2105
0
}
2106
2107
const FieldDescriptor* DescriptorPool::FindExtensionByPrintableName(
2108
0
    const Descriptor* extendee, absl::string_view printable_name) const {
2109
0
  if (extendee->extension_range_count() == 0) return nullptr;
2110
0
  const FieldDescriptor* result = FindExtensionByName(printable_name);
2111
0
  if (result != nullptr && result->containing_type() == extendee) {
2112
0
    return result;
2113
0
  }
2114
0
  if (extendee->options().message_set_wire_format()) {
2115
    // MessageSet extensions may be identified by type name.
2116
0
    const Descriptor* type = FindMessageTypeByName(printable_name);
2117
0
    if (type != nullptr) {
2118
      // Look for a matching extension in the foreign type's scope.
2119
0
      const int type_extension_count = type->extension_count();
2120
0
      for (int i = 0; i < type_extension_count; i++) {
2121
0
        const FieldDescriptor* extension = type->extension(i);
2122
0
        if (extension->containing_type() == extendee &&
2123
0
            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
2124
0
            extension->is_optional() && extension->message_type() == type) {
2125
          // Found it.
2126
0
          return extension;
2127
0
        }
2128
0
      }
2129
0
    }
2130
0
  }
2131
0
  return nullptr;
2132
0
}
2133
2134
void DescriptorPool::FindAllExtensions(
2135
    const Descriptor* extendee,
2136
0
    std::vector<const FieldDescriptor*>* out) const {
2137
0
  absl::MutexLockMaybe lock(mutex_);
2138
0
  if (fallback_database_ != nullptr) {
2139
0
    tables_->known_bad_symbols_.clear();
2140
0
    tables_->known_bad_files_.clear();
2141
0
  }
2142
2143
  // Initialize tables_->extensions_ from the fallback database first
2144
  // (but do this only once per descriptor).
2145
0
  if (fallback_database_ != nullptr &&
2146
0
      tables_->extensions_loaded_from_db_.count(extendee) == 0) {
2147
0
    std::vector<int> numbers;
2148
0
    if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
2149
0
                                                    &numbers)) {
2150
0
      for (int number : numbers) {
2151
0
        if (tables_->FindExtension(extendee, number) == nullptr) {
2152
0
          TryFindExtensionInFallbackDatabase(extendee, number);
2153
0
        }
2154
0
      }
2155
0
      tables_->extensions_loaded_from_db_.insert(extendee);
2156
0
    }
2157
0
  }
2158
2159
0
  tables_->FindAllExtensions(extendee, out);
2160
0
  if (underlay_ != nullptr) {
2161
0
    underlay_->FindAllExtensions(extendee, out);
2162
0
  }
2163
0
}
2164
2165
2166
// -------------------------------------------------------------------
2167
2168
0
const FieldDescriptor* Descriptor::FindFieldByNumber(int key) const {
2169
0
  const FieldDescriptor* result = file()->tables_->FindFieldByNumber(this, key);
2170
0
  if (result == nullptr || result->is_extension()) {
2171
0
    return nullptr;
2172
0
  } else {
2173
0
    return result;
2174
0
  }
2175
0
}
2176
2177
const FieldDescriptor* Descriptor::FindFieldByLowercaseName(
2178
0
    absl::string_view key) const {
2179
0
  const FieldDescriptor* result =
2180
0
      file()->tables_->FindFieldByLowercaseName(this, key);
2181
0
  if (result == nullptr || result->is_extension()) {
2182
0
    return nullptr;
2183
0
  } else {
2184
0
    return result;
2185
0
  }
2186
0
}
2187
2188
const FieldDescriptor* Descriptor::FindFieldByCamelcaseName(
2189
0
    absl::string_view key) const {
2190
0
  const FieldDescriptor* result =
2191
0
      file()->tables_->FindFieldByCamelcaseName(this, key);
2192
0
  if (result == nullptr || result->is_extension()) {
2193
0
    return nullptr;
2194
0
  } else {
2195
0
    return result;
2196
0
  }
2197
0
}
2198
2199
const FieldDescriptor* Descriptor::FindFieldByName(
2200
152k
    absl::string_view key) const {
2201
152k
  const FieldDescriptor* field =
2202
152k
      file()->tables_->FindNestedSymbol(this, key).field_descriptor();
2203
152k
  return field != nullptr && !field->is_extension() ? field : nullptr;
2204
152k
}
2205
2206
const OneofDescriptor* Descriptor::FindOneofByName(
2207
0
    absl::string_view key) const {
2208
0
  return file()->tables_->FindNestedSymbol(this, key).oneof_descriptor();
2209
0
}
2210
2211
const FieldDescriptor* Descriptor::FindExtensionByName(
2212
0
    absl::string_view key) const {
2213
0
  const FieldDescriptor* field =
2214
0
      file()->tables_->FindNestedSymbol(this, key).field_descriptor();
2215
0
  return field != nullptr && field->is_extension() ? field : nullptr;
2216
0
}
2217
2218
const FieldDescriptor* Descriptor::FindExtensionByLowercaseName(
2219
0
    absl::string_view key) const {
2220
0
  const FieldDescriptor* result =
2221
0
      file()->tables_->FindFieldByLowercaseName(this, key);
2222
0
  if (result == nullptr || !result->is_extension()) {
2223
0
    return nullptr;
2224
0
  } else {
2225
0
    return result;
2226
0
  }
2227
0
}
2228
2229
const FieldDescriptor* Descriptor::FindExtensionByCamelcaseName(
2230
0
    absl::string_view key) const {
2231
0
  const FieldDescriptor* result =
2232
0
      file()->tables_->FindFieldByCamelcaseName(this, key);
2233
0
  if (result == nullptr || !result->is_extension()) {
2234
0
    return nullptr;
2235
0
  } else {
2236
0
    return result;
2237
0
  }
2238
0
}
2239
2240
const Descriptor* Descriptor::FindNestedTypeByName(
2241
0
    absl::string_view key) const {
2242
0
  return file()->tables_->FindNestedSymbol(this, key).descriptor();
2243
0
}
2244
2245
const EnumDescriptor* Descriptor::FindEnumTypeByName(
2246
0
    absl::string_view key) const {
2247
0
  return file()->tables_->FindNestedSymbol(this, key).enum_descriptor();
2248
0
}
2249
2250
const EnumValueDescriptor* Descriptor::FindEnumValueByName(
2251
0
    absl::string_view key) const {
2252
0
  return file()->tables_->FindNestedSymbol(this, key).enum_value_descriptor();
2253
0
}
2254
2255
0
const FieldDescriptor* Descriptor::map_key() const {
2256
0
  if (!options().map_entry()) return nullptr;
2257
0
  ABSL_DCHECK_EQ(field_count(), 2);
2258
0
  return field(0);
2259
0
}
2260
2261
0
const FieldDescriptor* Descriptor::map_value() const {
2262
0
  if (!options().map_entry()) return nullptr;
2263
0
  ABSL_DCHECK_EQ(field_count(), 2);
2264
0
  return field(1);
2265
0
}
2266
2267
const EnumValueDescriptor* EnumDescriptor::FindValueByName(
2268
0
    absl::string_view key) const {
2269
0
  return file()->tables_->FindNestedSymbol(this, key).enum_value_descriptor();
2270
0
}
2271
2272
0
const EnumValueDescriptor* EnumDescriptor::FindValueByNumber(int key) const {
2273
0
  return file()->tables_->FindEnumValueByNumber(this, key);
2274
0
}
2275
2276
const EnumValueDescriptor* EnumDescriptor::FindValueByNumberCreatingIfUnknown(
2277
0
    int key) const {
2278
0
  return file()->tables_->FindEnumValueByNumberCreatingIfUnknown(this, key);
2279
0
}
2280
2281
const MethodDescriptor* ServiceDescriptor::FindMethodByName(
2282
0
    absl::string_view key) const {
2283
0
  return file()->tables_->FindNestedSymbol(this, key).method_descriptor();
2284
0
}
2285
2286
const Descriptor* FileDescriptor::FindMessageTypeByName(
2287
0
    absl::string_view key) const {
2288
0
  return tables_->FindNestedSymbol(this, key).descriptor();
2289
0
}
2290
2291
const EnumDescriptor* FileDescriptor::FindEnumTypeByName(
2292
0
    absl::string_view key) const {
2293
0
  return tables_->FindNestedSymbol(this, key).enum_descriptor();
2294
0
}
2295
2296
const EnumValueDescriptor* FileDescriptor::FindEnumValueByName(
2297
0
    absl::string_view key) const {
2298
0
  return tables_->FindNestedSymbol(this, key).enum_value_descriptor();
2299
0
}
2300
2301
const ServiceDescriptor* FileDescriptor::FindServiceByName(
2302
0
    absl::string_view key) const {
2303
0
  return tables_->FindNestedSymbol(this, key).service_descriptor();
2304
0
}
2305
2306
const FieldDescriptor* FileDescriptor::FindExtensionByName(
2307
0
    absl::string_view key) const {
2308
0
  const FieldDescriptor* field =
2309
0
      tables_->FindNestedSymbol(this, key).field_descriptor();
2310
0
  return field != nullptr && field->is_extension() ? field : nullptr;
2311
0
}
2312
2313
const FieldDescriptor* FileDescriptor::FindExtensionByLowercaseName(
2314
0
    absl::string_view key) const {
2315
0
  const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
2316
0
  if (result == nullptr || !result->is_extension()) {
2317
0
    return nullptr;
2318
0
  } else {
2319
0
    return result;
2320
0
  }
2321
0
}
2322
2323
const FieldDescriptor* FileDescriptor::FindExtensionByCamelcaseName(
2324
0
    absl::string_view key) const {
2325
0
  const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
2326
0
  if (result == nullptr || !result->is_extension()) {
2327
0
    return nullptr;
2328
0
  } else {
2329
0
    return result;
2330
0
  }
2331
0
}
2332
2333
void Descriptor::ExtensionRange::CopyTo(
2334
0
    DescriptorProto_ExtensionRange* proto) const {
2335
0
  proto->set_start(this->start);
2336
0
  proto->set_end(this->end);
2337
0
  if (options_ != &ExtensionRangeOptions::default_instance()) {
2338
0
    *proto->mutable_options() = *options_;
2339
0
  }
2340
0
}
2341
2342
const Descriptor::ExtensionRange*
2343
0
Descriptor::FindExtensionRangeContainingNumber(int number) const {
2344
  // Linear search should be fine because we don't expect a message to have
2345
  // more than a couple extension ranges.
2346
0
  for (int i = 0; i < extension_range_count(); i++) {
2347
0
    if (number >= extension_range(i)->start &&
2348
0
        number < extension_range(i)->end) {
2349
0
      return extension_range(i);
2350
0
    }
2351
0
  }
2352
0
  return nullptr;
2353
0
}
2354
2355
const Descriptor::ReservedRange* Descriptor::FindReservedRangeContainingNumber(
2356
0
    int number) const {
2357
  // TODO(chrisn): Consider a non-linear search.
2358
0
  for (int i = 0; i < reserved_range_count(); i++) {
2359
0
    if (number >= reserved_range(i)->start && number < reserved_range(i)->end) {
2360
0
      return reserved_range(i);
2361
0
    }
2362
0
  }
2363
0
  return nullptr;
2364
0
}
2365
2366
const EnumDescriptor::ReservedRange*
2367
0
EnumDescriptor::FindReservedRangeContainingNumber(int number) const {
2368
  // TODO(chrisn): Consider a non-linear search.
2369
0
  for (int i = 0; i < reserved_range_count(); i++) {
2370
0
    if (number >= reserved_range(i)->start &&
2371
0
        number <= reserved_range(i)->end) {
2372
0
      return reserved_range(i);
2373
0
    }
2374
0
  }
2375
0
  return nullptr;
2376
0
}
2377
2378
// -------------------------------------------------------------------
2379
2380
bool DescriptorPool::TryFindFileInFallbackDatabase(
2381
6
    absl::string_view name) const {
2382
6
  if (fallback_database_ == nullptr) return false;
2383
2384
6
  if (tables_->known_bad_files_.contains(name)) return false;
2385
2386
  // NOINLINE to reduce the stack cost of the operation in the caller.
2387
6
  const auto find_file = [](DescriptorDatabase& database,
2388
6
                            absl::string_view filename,
2389
6
                            FileDescriptorProto& output) PROTOBUF_NOINLINE {
2390
6
    return database.FindFileByName(std::string(filename), &output);
2391
6
  };
2392
2393
6
  auto file_proto = absl::make_unique<FileDescriptorProto>();
2394
6
  if (!find_file(*fallback_database_, name, *file_proto) ||
2395
6
      BuildFileFromDatabase(*file_proto) == nullptr) {
2396
0
    tables_->known_bad_files_.emplace(name);
2397
0
    return false;
2398
0
  }
2399
6
  return true;
2400
6
}
2401
2402
0
bool DescriptorPool::IsSubSymbolOfBuiltType(absl::string_view name) const {
2403
0
  auto prefix = std::string(name);
2404
0
  for (;;) {
2405
0
    std::string::size_type dot_pos = prefix.find_last_of('.');
2406
0
    if (dot_pos == std::string::npos) {
2407
0
      break;
2408
0
    }
2409
0
    prefix = prefix.substr(0, dot_pos);
2410
0
    Symbol symbol = tables_->FindSymbol(prefix);
2411
    // If the symbol type is anything other than PACKAGE, then its complete
2412
    // definition is already known.
2413
0
    if (!symbol.IsNull() && !symbol.IsPackage()) {
2414
0
      return true;
2415
0
    }
2416
0
  }
2417
0
  if (underlay_ != nullptr) {
2418
    // Check to see if any prefix of this symbol exists in the underlay.
2419
0
    return underlay_->IsSubSymbolOfBuiltType(name);
2420
0
  }
2421
0
  return false;
2422
0
}
2423
2424
bool DescriptorPool::TryFindSymbolInFallbackDatabase(
2425
0
    absl::string_view name) const {
2426
0
  if (fallback_database_ == nullptr) return false;
2427
2428
0
  if (tables_->known_bad_symbols_.contains(name)) return false;
2429
2430
0
  std::string name_string(name);
2431
0
  auto file_proto = absl::make_unique<FileDescriptorProto>();
2432
0
  if (  // We skip looking in the fallback database if the name is a sub-symbol
2433
        // of any descriptor that already exists in the descriptor pool (except
2434
        // for package descriptors).  This is valid because all symbols except
2435
        // for packages are defined in a single file, so if the symbol exists
2436
        // then we should already have its definition.
2437
        //
2438
        // The other reason to do this is to support "overriding" type
2439
        // definitions by merging two databases that define the same type. (Yes,
2440
        // people do this.)  The main difficulty with making this work is that
2441
        // FindFileContainingSymbol() is allowed to return both false positives
2442
        // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and
2443
        // false negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase).
2444
        // When two such databases are merged, looking up a non-existent
2445
        // sub-symbol of a type that already exists in the descriptor pool can
2446
        // result in an attempt to load multiple definitions of the same type.
2447
        // The check below avoids this.
2448
0
      IsSubSymbolOfBuiltType(name)
2449
2450
      // Look up file containing this symbol in fallback database.
2451
0
      || !fallback_database_->FindFileContainingSymbol(name_string,
2452
0
                                                       file_proto.get())
2453
2454
      // Check if we've already built this file. If so, it apparently doesn't
2455
      // contain the symbol we're looking for.  Some DescriptorDatabases
2456
      // return false positives.
2457
0
      || tables_->FindFile(file_proto->name()) != nullptr
2458
2459
      // Build the file.
2460
0
      || BuildFileFromDatabase(*file_proto) == nullptr) {
2461
0
    tables_->known_bad_symbols_.insert(std::move(name_string));
2462
0
    return false;
2463
0
  }
2464
2465
0
  return true;
2466
0
}
2467
2468
bool DescriptorPool::TryFindExtensionInFallbackDatabase(
2469
0
    const Descriptor* containing_type, int field_number) const {
2470
0
  if (fallback_database_ == nullptr) return false;
2471
2472
0
  auto file_proto = absl::make_unique<FileDescriptorProto>();
2473
0
  if (!fallback_database_->FindFileContainingExtension(
2474
0
          containing_type->full_name(), field_number, file_proto.get())) {
2475
0
    return false;
2476
0
  }
2477
2478
0
  if (tables_->FindFile(file_proto->name()) != nullptr) {
2479
    // We've already loaded this file, and it apparently doesn't contain the
2480
    // extension we're looking for.  Some DescriptorDatabases return false
2481
    // positives.
2482
0
    return false;
2483
0
  }
2484
2485
0
  if (BuildFileFromDatabase(*file_proto) == nullptr) {
2486
0
    return false;
2487
0
  }
2488
2489
0
  return true;
2490
0
}
2491
2492
// ===================================================================
2493
2494
237k
bool FieldDescriptor::is_map_message_type() const {
2495
237k
  return type_descriptor_.message_type->options().map_entry();
2496
237k
}
2497
2498
std::string FieldDescriptor::DefaultValueAsString(
2499
0
    bool quote_string_type) const {
2500
0
  ABSL_CHECK(has_default_value()) << "No default value";
2501
0
  switch (cpp_type()) {
2502
0
    case CPPTYPE_INT32:
2503
0
      return absl::StrCat(default_value_int32_t());
2504
0
    case CPPTYPE_INT64:
2505
0
      return absl::StrCat(default_value_int64_t());
2506
0
    case CPPTYPE_UINT32:
2507
0
      return absl::StrCat(default_value_uint32_t());
2508
0
    case CPPTYPE_UINT64:
2509
0
      return absl::StrCat(default_value_uint64_t());
2510
0
    case CPPTYPE_FLOAT:
2511
0
      return io::SimpleFtoa(default_value_float());
2512
0
    case CPPTYPE_DOUBLE:
2513
0
      return io::SimpleDtoa(default_value_double());
2514
0
    case CPPTYPE_BOOL:
2515
0
      return default_value_bool() ? "true" : "false";
2516
0
    case CPPTYPE_STRING:
2517
0
      if (quote_string_type) {
2518
0
        return absl::StrCat("\"", absl::CEscape(default_value_string()), "\"");
2519
0
      } else {
2520
0
        if (type() == TYPE_BYTES) {
2521
0
          return absl::CEscape(default_value_string());
2522
0
        } else {
2523
0
          return default_value_string();
2524
0
        }
2525
0
      }
2526
0
    case CPPTYPE_ENUM:
2527
0
      return default_value_enum()->name();
2528
0
    case CPPTYPE_MESSAGE:
2529
0
      ABSL_DLOG(FATAL) << "Messages can't have default values!";
2530
0
      break;
2531
0
  }
2532
0
  ABSL_LOG(FATAL) << "Can't get here: failed to get default value as string";
2533
0
  return "";
2534
0
}
2535
2536
// CopyTo methods ====================================================
2537
2538
0
void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
2539
0
  CopyHeadingTo(proto);
2540
2541
0
  for (int i = 0; i < dependency_count(); i++) {
2542
0
    proto->add_dependency(dependency(i)->name());
2543
0
  }
2544
2545
0
  for (int i = 0; i < public_dependency_count(); i++) {
2546
0
    proto->add_public_dependency(public_dependencies_[i]);
2547
0
  }
2548
2549
0
  for (int i = 0; i < weak_dependency_count(); i++) {
2550
0
    proto->add_weak_dependency(weak_dependencies_[i]);
2551
0
  }
2552
2553
0
  for (int i = 0; i < message_type_count(); i++) {
2554
0
    message_type(i)->CopyTo(proto->add_message_type());
2555
0
  }
2556
0
  for (int i = 0; i < enum_type_count(); i++) {
2557
0
    enum_type(i)->CopyTo(proto->add_enum_type());
2558
0
  }
2559
0
  for (int i = 0; i < service_count(); i++) {
2560
0
    service(i)->CopyTo(proto->add_service());
2561
0
  }
2562
0
  for (int i = 0; i < extension_count(); i++) {
2563
0
    extension(i)->CopyTo(proto->add_extension());
2564
0
  }
2565
0
}
2566
2567
0
void FileDescriptor::CopyHeadingTo(FileDescriptorProto* proto) const {
2568
0
  proto->set_name(name());
2569
0
  if (!package().empty()) {
2570
0
    proto->set_package(package());
2571
0
  }
2572
2573
  // TODO(liujisi): Also populate when syntax="proto2".
2574
0
  if (syntax() == SYNTAX_PROTO3
2575
0
  ) {
2576
0
    proto->set_syntax(SyntaxName(syntax()));
2577
0
  }
2578
0
  if (&options() != &FileOptions::default_instance()) {
2579
0
    *proto->mutable_options() = options();
2580
0
  }
2581
0
}
2582
2583
0
void FileDescriptor::CopyJsonNameTo(FileDescriptorProto* proto) const {
2584
0
  if (message_type_count() != proto->message_type_size() ||
2585
0
      extension_count() != proto->extension_size()) {
2586
0
    ABSL_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
2587
0
    return;
2588
0
  }
2589
0
  for (int i = 0; i < message_type_count(); i++) {
2590
0
    message_type(i)->CopyJsonNameTo(proto->mutable_message_type(i));
2591
0
  }
2592
0
  for (int i = 0; i < extension_count(); i++) {
2593
0
    extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
2594
0
  }
2595
0
}
2596
2597
0
void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
2598
0
  if (source_code_info_ &&
2599
0
      source_code_info_ != &SourceCodeInfo::default_instance()) {
2600
0
    proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
2601
0
  }
2602
0
}
2603
2604
0
void Descriptor::CopyTo(DescriptorProto* proto) const {
2605
0
  proto->set_name(name());
2606
2607
0
  for (int i = 0; i < field_count(); i++) {
2608
0
    field(i)->CopyTo(proto->add_field());
2609
0
  }
2610
0
  for (int i = 0; i < oneof_decl_count(); i++) {
2611
0
    oneof_decl(i)->CopyTo(proto->add_oneof_decl());
2612
0
  }
2613
0
  for (int i = 0; i < nested_type_count(); i++) {
2614
0
    nested_type(i)->CopyTo(proto->add_nested_type());
2615
0
  }
2616
0
  for (int i = 0; i < enum_type_count(); i++) {
2617
0
    enum_type(i)->CopyTo(proto->add_enum_type());
2618
0
  }
2619
0
  for (int i = 0; i < extension_range_count(); i++) {
2620
0
    extension_range(i)->CopyTo(proto->add_extension_range());
2621
0
  }
2622
0
  for (int i = 0; i < extension_count(); i++) {
2623
0
    extension(i)->CopyTo(proto->add_extension());
2624
0
  }
2625
0
  for (int i = 0; i < reserved_range_count(); i++) {
2626
0
    DescriptorProto::ReservedRange* range = proto->add_reserved_range();
2627
0
    range->set_start(reserved_range(i)->start);
2628
0
    range->set_end(reserved_range(i)->end);
2629
0
  }
2630
0
  for (int i = 0; i < reserved_name_count(); i++) {
2631
0
    proto->add_reserved_name(reserved_name(i));
2632
0
  }
2633
2634
0
  if (&options() != &MessageOptions::default_instance()) {
2635
0
    proto->mutable_options()->CopyFrom(options());
2636
0
  }
2637
0
}
2638
2639
0
void Descriptor::CopyJsonNameTo(DescriptorProto* proto) const {
2640
0
  if (field_count() != proto->field_size() ||
2641
0
      nested_type_count() != proto->nested_type_size() ||
2642
0
      extension_count() != proto->extension_size()) {
2643
0
    ABSL_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
2644
0
    return;
2645
0
  }
2646
0
  for (int i = 0; i < field_count(); i++) {
2647
0
    field(i)->CopyJsonNameTo(proto->mutable_field(i));
2648
0
  }
2649
0
  for (int i = 0; i < nested_type_count(); i++) {
2650
0
    nested_type(i)->CopyJsonNameTo(proto->mutable_nested_type(i));
2651
0
  }
2652
0
  for (int i = 0; i < extension_count(); i++) {
2653
0
    extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
2654
0
  }
2655
0
}
2656
2657
0
void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
2658
0
  proto->set_name(name());
2659
0
  proto->set_number(number());
2660
0
  if (has_json_name_) {
2661
0
    proto->set_json_name(json_name());
2662
0
  }
2663
0
  if (proto3_optional_) {
2664
0
    proto->set_proto3_optional(true);
2665
0
  }
2666
  // Some compilers do not allow static_cast directly between two enum types,
2667
  // so we must cast to int first.
2668
0
  proto->set_label(static_cast<FieldDescriptorProto::Label>(
2669
0
      absl::implicit_cast<int>(label())));
2670
0
  proto->set_type(static_cast<FieldDescriptorProto::Type>(
2671
0
      absl::implicit_cast<int>(type())));
2672
2673
0
  if (is_extension()) {
2674
0
    if (!containing_type()->is_unqualified_placeholder_) {
2675
0
      proto->set_extendee(".");
2676
0
    }
2677
0
    proto->mutable_extendee()->append(containing_type()->full_name());
2678
0
  }
2679
2680
0
  if (cpp_type() == CPPTYPE_MESSAGE) {
2681
0
    if (message_type()->is_placeholder_) {
2682
      // We don't actually know if the type is a message type.  It could be
2683
      // an enum.
2684
0
      proto->clear_type();
2685
0
    }
2686
2687
0
    if (!message_type()->is_unqualified_placeholder_) {
2688
0
      proto->set_type_name(".");
2689
0
    }
2690
0
    proto->mutable_type_name()->append(message_type()->full_name());
2691
0
  } else if (cpp_type() == CPPTYPE_ENUM) {
2692
0
    if (!enum_type()->is_unqualified_placeholder_) {
2693
0
      proto->set_type_name(".");
2694
0
    }
2695
0
    proto->mutable_type_name()->append(enum_type()->full_name());
2696
0
  }
2697
2698
0
  if (has_default_value()) {
2699
0
    proto->set_default_value(DefaultValueAsString(false));
2700
0
  }
2701
2702
0
  if (containing_oneof() != nullptr && !is_extension()) {
2703
0
    proto->set_oneof_index(containing_oneof()->index());
2704
0
  }
2705
2706
0
  if (&options() != &FieldOptions::default_instance()) {
2707
0
    proto->mutable_options()->CopyFrom(options());
2708
0
  }
2709
0
}
2710
2711
0
void FieldDescriptor::CopyJsonNameTo(FieldDescriptorProto* proto) const {
2712
0
  proto->set_json_name(json_name());
2713
0
}
2714
2715
0
void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const {
2716
0
  proto->set_name(name());
2717
0
  if (&options() != &OneofOptions::default_instance()) {
2718
0
    proto->mutable_options()->CopyFrom(options());
2719
0
  }
2720
0
}
2721
2722
0
void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const {
2723
0
  proto->set_name(name());
2724
2725
0
  for (int i = 0; i < value_count(); i++) {
2726
0
    value(i)->CopyTo(proto->add_value());
2727
0
  }
2728
0
  for (int i = 0; i < reserved_range_count(); i++) {
2729
0
    EnumDescriptorProto::EnumReservedRange* range = proto->add_reserved_range();
2730
0
    range->set_start(reserved_range(i)->start);
2731
0
    range->set_end(reserved_range(i)->end);
2732
0
  }
2733
0
  for (int i = 0; i < reserved_name_count(); i++) {
2734
0
    proto->add_reserved_name(reserved_name(i));
2735
0
  }
2736
2737
0
  if (&options() != &EnumOptions::default_instance()) {
2738
0
    proto->mutable_options()->CopyFrom(options());
2739
0
  }
2740
0
}
2741
2742
0
void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const {
2743
0
  proto->set_name(name());
2744
0
  proto->set_number(number());
2745
2746
0
  if (&options() != &EnumValueOptions::default_instance()) {
2747
0
    proto->mutable_options()->CopyFrom(options());
2748
0
  }
2749
0
}
2750
2751
0
void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const {
2752
0
  proto->set_name(name());
2753
2754
0
  for (int i = 0; i < method_count(); i++) {
2755
0
    method(i)->CopyTo(proto->add_method());
2756
0
  }
2757
2758
0
  if (&options() != &ServiceOptions::default_instance()) {
2759
0
    proto->mutable_options()->CopyFrom(options());
2760
0
  }
2761
0
}
2762
2763
0
void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const {
2764
0
  proto->set_name(name());
2765
2766
0
  if (!input_type()->is_unqualified_placeholder_) {
2767
0
    proto->set_input_type(".");
2768
0
  }
2769
0
  proto->mutable_input_type()->append(input_type()->full_name());
2770
2771
0
  if (!output_type()->is_unqualified_placeholder_) {
2772
0
    proto->set_output_type(".");
2773
0
  }
2774
0
  proto->mutable_output_type()->append(output_type()->full_name());
2775
2776
0
  if (&options() != &MethodOptions::default_instance()) {
2777
0
    proto->mutable_options()->CopyFrom(options());
2778
0
  }
2779
2780
0
  if (client_streaming_) {
2781
0
    proto->set_client_streaming(true);
2782
0
  }
2783
0
  if (server_streaming_) {
2784
0
    proto->set_server_streaming(true);
2785
0
  }
2786
0
}
2787
2788
// DebugString methods ===============================================
2789
2790
namespace {
2791
2792
bool RetrieveOptionsAssumingRightPool(
2793
    int depth, const Message& options,
2794
0
    std::vector<std::string>* option_entries) {
2795
0
  option_entries->clear();
2796
0
  const Reflection* reflection = options.GetReflection();
2797
0
  std::vector<const FieldDescriptor*> fields;
2798
0
  reflection->ListFields(options, &fields);
2799
0
  for (const FieldDescriptor* field : fields) {
2800
0
    int count = 1;
2801
0
    bool repeated = false;
2802
0
    if (field->is_repeated()) {
2803
0
      count = reflection->FieldSize(options, field);
2804
0
      repeated = true;
2805
0
    }
2806
0
    for (int j = 0; j < count; j++) {
2807
0
      std::string fieldval;
2808
0
      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2809
0
        std::string tmp;
2810
0
        TextFormat::Printer printer;
2811
0
        printer.SetExpandAny(true);
2812
0
        printer.SetInitialIndentLevel(depth + 1);
2813
0
        printer.PrintFieldValueToString(options, field, repeated ? j : -1,
2814
0
                                        &tmp);
2815
0
        fieldval.append("{\n");
2816
0
        fieldval.append(tmp);
2817
0
        fieldval.append(depth * 2, ' ');
2818
0
        fieldval.append("}");
2819
0
      } else {
2820
0
        TextFormat::PrintFieldValueToString(options, field, repeated ? j : -1,
2821
0
                                            &fieldval);
2822
0
      }
2823
0
      std::string name;
2824
0
      if (field->is_extension()) {
2825
0
        name = absl::StrCat("(.", field->full_name(), ")");
2826
0
      } else {
2827
0
        name = field->name();
2828
0
      }
2829
0
      option_entries->push_back(absl::StrCat(name, " = ", fieldval));
2830
0
    }
2831
0
  }
2832
0
  return !option_entries->empty();
2833
0
}
2834
2835
// Used by each of the option formatters.
2836
bool RetrieveOptions(int depth, const Message& options,
2837
                     const DescriptorPool* pool,
2838
0
                     std::vector<std::string>* option_entries) {
2839
  // When printing custom options for a descriptor, we must use an options
2840
  // message built on top of the same DescriptorPool where the descriptor
2841
  // is coming from. This is to ensure we are interpreting custom options
2842
  // against the right pool.
2843
0
  if (options.GetDescriptor()->file()->pool() == pool) {
2844
0
    return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2845
0
  } else {
2846
0
    const Descriptor* option_descriptor =
2847
0
        pool->FindMessageTypeByName(options.GetDescriptor()->full_name());
2848
0
    if (option_descriptor == nullptr) {
2849
      // descriptor.proto is not in the pool. This means no custom options are
2850
      // used so we are safe to proceed with the compiled options message type.
2851
0
      return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2852
0
    }
2853
0
    DynamicMessageFactory factory;
2854
0
    std::unique_ptr<Message> dynamic_options(
2855
0
        factory.GetPrototype(option_descriptor)->New());
2856
0
    std::string serialized = options.SerializeAsString();
2857
0
    io::CodedInputStream input(
2858
0
        reinterpret_cast<const uint8_t*>(serialized.c_str()),
2859
0
        serialized.size());
2860
0
    input.SetExtensionRegistry(pool, &factory);
2861
0
    if (dynamic_options->ParseFromCodedStream(&input)) {
2862
0
      return RetrieveOptionsAssumingRightPool(depth, *dynamic_options,
2863
0
                                              option_entries);
2864
0
    } else {
2865
0
      ABSL_LOG(ERROR) << "Found invalid proto option data for: "
2866
0
                      << options.GetDescriptor()->full_name();
2867
0
      return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2868
0
    }
2869
0
  }
2870
0
}
2871
2872
// Formats options that all appear together in brackets. Does not include
2873
// brackets.
2874
bool FormatBracketedOptions(int depth, const Message& options,
2875
0
                            const DescriptorPool* pool, std::string* output) {
2876
0
  std::vector<std::string> all_options;
2877
0
  if (RetrieveOptions(depth, options, pool, &all_options)) {
2878
0
    output->append(absl::StrJoin(all_options, ", "));
2879
0
  }
2880
0
  return !all_options.empty();
2881
0
}
2882
2883
// Formats options one per line
2884
bool FormatLineOptions(int depth, const Message& options,
2885
0
                       const DescriptorPool* pool, std::string* output) {
2886
0
  std::string prefix(depth * 2, ' ');
2887
0
  std::vector<std::string> all_options;
2888
0
  if (RetrieveOptions(depth, options, pool, &all_options)) {
2889
0
    for (const std::string& option : all_options) {
2890
0
      absl::SubstituteAndAppend(output, "$0option $1;\n", prefix, option);
2891
0
    }
2892
0
  }
2893
0
  return !all_options.empty();
2894
0
}
2895
2896
class SourceLocationCommentPrinter {
2897
 public:
2898
  template <typename DescType>
2899
  SourceLocationCommentPrinter(const DescType* desc, const std::string& prefix,
2900
                               const DebugStringOptions& options)
2901
0
      : options_(options), prefix_(prefix) {
2902
    // Perform the SourceLocation lookup only if we're including user comments,
2903
    // because the lookup is fairly expensive.
2904
0
    have_source_loc_ =
2905
0
        options.include_comments && desc->GetSourceLocation(&source_loc_);
2906
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&)
2907
  SourceLocationCommentPrinter(const FileDescriptor* file,
2908
                               const std::vector<int>& path,
2909
                               const std::string& prefix,
2910
                               const DebugStringOptions& options)
2911
0
      : options_(options), prefix_(prefix) {
2912
    // Perform the SourceLocation lookup only if we're including user comments,
2913
    // because the lookup is fairly expensive.
2914
0
    have_source_loc_ =
2915
0
        options.include_comments && file->GetSourceLocation(path, &source_loc_);
2916
0
  }
2917
0
  void AddPreComment(std::string* output) {
2918
0
    if (have_source_loc_) {
2919
      // Detached leading comments.
2920
0
      for (const std::string& leading_detached_comment :
2921
0
           source_loc_.leading_detached_comments) {
2922
0
        absl::StrAppend(output, FormatComment(leading_detached_comment), "\n");
2923
0
      }
2924
      // Attached leading comments.
2925
0
      if (!source_loc_.leading_comments.empty()) {
2926
0
        absl::StrAppend(output, FormatComment(source_loc_.leading_comments));
2927
0
      }
2928
0
    }
2929
0
  }
2930
0
  void AddPostComment(std::string* output) {
2931
0
    if (have_source_loc_ && source_loc_.trailing_comments.size() > 0) {
2932
0
      absl::StrAppend(output, FormatComment(source_loc_.trailing_comments));
2933
0
    }
2934
0
  }
2935
2936
  // Format comment such that each line becomes a full-line C++-style comment in
2937
  // the DebugString() output.
2938
0
  std::string FormatComment(const std::string& comment_text) {
2939
0
    std::string stripped_comment = comment_text;
2940
0
    absl::StripAsciiWhitespace(&stripped_comment);
2941
0
    std::vector<std::string> lines = absl::StrSplit(stripped_comment, "\n");
2942
0
    std::string output;
2943
0
    for (const std::string& line : lines) {
2944
0
      absl::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
2945
0
    }
2946
0
    return output;
2947
0
  }
2948
2949
 private:
2950
2951
  bool have_source_loc_;
2952
  SourceLocation source_loc_;
2953
  DebugStringOptions options_;
2954
  std::string prefix_;
2955
};
2956
2957
}  // anonymous namespace
2958
2959
0
std::string FileDescriptor::DebugString() const {
2960
0
  DebugStringOptions options;  // default options
2961
0
  return DebugStringWithOptions(options);
2962
0
}
2963
2964
std::string FileDescriptor::DebugStringWithOptions(
2965
0
    const DebugStringOptions& debug_string_options) const {
2966
0
  std::string contents;
2967
0
  {
2968
0
    std::vector<int> path;
2969
0
    path.push_back(FileDescriptorProto::kSyntaxFieldNumber);
2970
0
    SourceLocationCommentPrinter syntax_comment(this, path, "",
2971
0
                                                debug_string_options);
2972
0
    syntax_comment.AddPreComment(&contents);
2973
0
    absl::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
2974
0
                              SyntaxName(syntax()));
2975
0
    syntax_comment.AddPostComment(&contents);
2976
0
  }
2977
2978
0
  SourceLocationCommentPrinter comment_printer(this, "", debug_string_options);
2979
0
  comment_printer.AddPreComment(&contents);
2980
2981
0
  absl::flat_hash_set<int> public_dependencies(
2982
0
      public_dependencies_, public_dependencies_ + public_dependency_count_);
2983
0
  absl::flat_hash_set<int> weak_dependencies(
2984
0
      weak_dependencies_, weak_dependencies_ + weak_dependency_count_);
2985
2986
0
  for (int i = 0; i < dependency_count(); i++) {
2987
0
    if (public_dependencies.contains(i)) {
2988
0
      absl::SubstituteAndAppend(&contents, "import public \"$0\";\n",
2989
0
                                dependency(i)->name());
2990
0
    } else if (weak_dependencies.contains(i)) {
2991
0
      absl::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
2992
0
                                dependency(i)->name());
2993
0
    } else {
2994
0
      absl::SubstituteAndAppend(&contents, "import \"$0\";\n",
2995
0
                                dependency(i)->name());
2996
0
    }
2997
0
  }
2998
2999
0
  if (!package().empty()) {
3000
0
    std::vector<int> path;
3001
0
    path.push_back(FileDescriptorProto::kPackageFieldNumber);
3002
0
    SourceLocationCommentPrinter package_comment(this, path, "",
3003
0
                                                 debug_string_options);
3004
0
    package_comment.AddPreComment(&contents);
3005
0
    absl::SubstituteAndAppend(&contents, "package $0;\n\n", package());
3006
0
    package_comment.AddPostComment(&contents);
3007
0
  }
3008
3009
0
  if (FormatLineOptions(0, options(), pool(), &contents)) {
3010
0
    contents.append("\n");  // add some space if we had options
3011
0
  }
3012
3013
0
  for (int i = 0; i < enum_type_count(); i++) {
3014
0
    enum_type(i)->DebugString(0, &contents, debug_string_options);
3015
0
    contents.append("\n");
3016
0
  }
3017
3018
  // Find all the 'group' type extensions; we will not output their nested
3019
  // definitions (those will be done with their group field descriptor).
3020
0
  absl::flat_hash_set<const Descriptor*> groups;
3021
0
  for (int i = 0; i < extension_count(); i++) {
3022
0
    if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
3023
0
      groups.insert(extension(i)->message_type());
3024
0
    }
3025
0
  }
3026
3027
0
  for (int i = 0; i < message_type_count(); i++) {
3028
0
    if (!groups.contains(message_type(i))) {
3029
0
      message_type(i)->DebugString(0, &contents, debug_string_options,
3030
0
                                   /* include_opening_clause */ true);
3031
0
      contents.append("\n");
3032
0
    }
3033
0
  }
3034
3035
0
  for (int i = 0; i < service_count(); i++) {
3036
0
    service(i)->DebugString(&contents, debug_string_options);
3037
0
    contents.append("\n");
3038
0
  }
3039
3040
0
  const Descriptor* containing_type = nullptr;
3041
0
  for (int i = 0; i < extension_count(); i++) {
3042
0
    if (extension(i)->containing_type() != containing_type) {
3043
0
      if (i > 0) contents.append("}\n\n");
3044
0
      containing_type = extension(i)->containing_type();
3045
0
      absl::SubstituteAndAppend(&contents, "extend .$0 {\n",
3046
0
                                containing_type->full_name());
3047
0
    }
3048
0
    extension(i)->DebugString(1, &contents, debug_string_options);
3049
0
  }
3050
0
  if (extension_count() > 0) contents.append("}\n\n");
3051
3052
0
  comment_printer.AddPostComment(&contents);
3053
3054
0
  return contents;
3055
0
}
3056
3057
0
std::string Descriptor::DebugString() const {
3058
0
  DebugStringOptions options;  // default options
3059
0
  return DebugStringWithOptions(options);
3060
0
}
3061
3062
std::string Descriptor::DebugStringWithOptions(
3063
0
    const DebugStringOptions& options) const {
3064
0
  std::string contents;
3065
0
  DebugString(0, &contents, options, /* include_opening_clause */ true);
3066
0
  return contents;
3067
0
}
3068
3069
void Descriptor::DebugString(int depth, std::string* contents,
3070
                             const DebugStringOptions& debug_string_options,
3071
0
                             bool include_opening_clause) const {
3072
0
  if (options().map_entry()) {
3073
    // Do not generate debug string for auto-generated map-entry type.
3074
0
    return;
3075
0
  }
3076
0
  std::string prefix(depth * 2, ' ');
3077
0
  ++depth;
3078
3079
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3080
0
                                               debug_string_options);
3081
0
  comment_printer.AddPreComment(contents);
3082
3083
0
  if (include_opening_clause) {
3084
0
    absl::SubstituteAndAppend(contents, "$0message $1", prefix, name());
3085
0
  }
3086
0
  contents->append(" {\n");
3087
3088
0
  FormatLineOptions(depth, options(), file()->pool(), contents);
3089
3090
  // Find all the 'group' types for fields and extensions; we will not output
3091
  // their nested definitions (those will be done with their group field
3092
  // descriptor).
3093
0
  absl::flat_hash_set<const Descriptor*> groups;
3094
0
  for (int i = 0; i < field_count(); i++) {
3095
0
    if (field(i)->type() == FieldDescriptor::TYPE_GROUP) {
3096
0
      groups.insert(field(i)->message_type());
3097
0
    }
3098
0
  }
3099
0
  for (int i = 0; i < extension_count(); i++) {
3100
0
    if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
3101
0
      groups.insert(extension(i)->message_type());
3102
0
    }
3103
0
  }
3104
3105
0
  for (int i = 0; i < nested_type_count(); i++) {
3106
0
    if (!groups.contains(nested_type(i))) {
3107
0
      nested_type(i)->DebugString(depth, contents, debug_string_options,
3108
0
                                  /* include_opening_clause */ true);
3109
0
    }
3110
0
  }
3111
0
  for (int i = 0; i < enum_type_count(); i++) {
3112
0
    enum_type(i)->DebugString(depth, contents, debug_string_options);
3113
0
  }
3114
0
  for (int i = 0; i < field_count(); i++) {
3115
0
    if (field(i)->real_containing_oneof() == nullptr) {
3116
0
      field(i)->DebugString(depth, contents, debug_string_options);
3117
0
    } else if (field(i)->containing_oneof()->field(0) == field(i)) {
3118
      // This is the first field in this oneof, so print the whole oneof.
3119
0
      field(i)->containing_oneof()->DebugString(depth, contents,
3120
0
                                                debug_string_options);
3121
0
    }
3122
0
  }
3123
3124
0
  for (int i = 0; i < extension_range_count(); i++) {
3125
0
    absl::SubstituteAndAppend(contents, "$0  extensions $1 to $2;\n", prefix,
3126
0
                              extension_range(i)->start,
3127
0
                              extension_range(i)->end - 1);
3128
0
  }
3129
3130
  // Group extensions by what they extend, so they can be printed out together.
3131
0
  const Descriptor* containing_type = nullptr;
3132
0
  for (int i = 0; i < extension_count(); i++) {
3133
0
    if (extension(i)->containing_type() != containing_type) {
3134
0
      if (i > 0) absl::SubstituteAndAppend(contents, "$0  }\n", prefix);
3135
0
      containing_type = extension(i)->containing_type();
3136
0
      absl::SubstituteAndAppend(contents, "$0  extend .$1 {\n", prefix,
3137
0
                                containing_type->full_name());
3138
0
    }
3139
0
    extension(i)->DebugString(depth + 1, contents, debug_string_options);
3140
0
  }
3141
0
  if (extension_count() > 0)
3142
0
    absl::SubstituteAndAppend(contents, "$0  }\n", prefix);
3143
3144
0
  if (reserved_range_count() > 0) {
3145
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3146
0
    for (int i = 0; i < reserved_range_count(); i++) {
3147
0
      const Descriptor::ReservedRange* range = reserved_range(i);
3148
0
      if (range->end == range->start + 1) {
3149
0
        absl::SubstituteAndAppend(contents, "$0, ", range->start);
3150
0
      } else if (range->end > FieldDescriptor::kMaxNumber) {
3151
0
        absl::SubstituteAndAppend(contents, "$0 to max, ", range->start);
3152
0
      } else {
3153
0
        absl::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
3154
0
                                  range->end - 1);
3155
0
      }
3156
0
    }
3157
0
    contents->replace(contents->size() - 2, 2, ";\n");
3158
0
  }
3159
3160
0
  if (reserved_name_count() > 0) {
3161
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3162
0
    for (int i = 0; i < reserved_name_count(); i++) {
3163
0
      absl::SubstituteAndAppend(contents, "\"$0\", ",
3164
0
                                absl::CEscape(reserved_name(i)));
3165
0
    }
3166
0
    contents->replace(contents->size() - 2, 2, ";\n");
3167
0
  }
3168
3169
0
  absl::SubstituteAndAppend(contents, "$0}\n", prefix);
3170
0
  comment_printer.AddPostComment(contents);
3171
0
}
3172
3173
0
std::string FieldDescriptor::DebugString() const {
3174
0
  DebugStringOptions options;  // default options
3175
0
  return DebugStringWithOptions(options);
3176
0
}
3177
3178
std::string FieldDescriptor::DebugStringWithOptions(
3179
0
    const DebugStringOptions& debug_string_options) const {
3180
0
  std::string contents;
3181
0
  int depth = 0;
3182
0
  if (is_extension()) {
3183
0
    absl::SubstituteAndAppend(&contents, "extend .$0 {\n",
3184
0
                              containing_type()->full_name());
3185
0
    depth = 1;
3186
0
  }
3187
0
  DebugString(depth, &contents, debug_string_options);
3188
0
  if (is_extension()) {
3189
0
    contents.append("}\n");
3190
0
  }
3191
0
  return contents;
3192
0
}
3193
3194
// The field type string used in FieldDescriptor::DebugString()
3195
0
std::string FieldDescriptor::FieldTypeNameDebugString() const {
3196
0
  switch (type()) {
3197
0
    case TYPE_MESSAGE:
3198
0
      return absl::StrCat(".", message_type()->full_name());
3199
0
    case TYPE_ENUM:
3200
0
      return absl::StrCat(".", enum_type()->full_name());
3201
0
    default:
3202
0
      return kTypeToName[type()];
3203
0
  }
3204
0
}
3205
3206
void FieldDescriptor::DebugString(
3207
    int depth, std::string* contents,
3208
0
    const DebugStringOptions& debug_string_options) const {
3209
0
  std::string prefix(depth * 2, ' ');
3210
0
  std::string field_type;
3211
3212
  // Special case map fields.
3213
0
  if (is_map()) {
3214
0
    absl::SubstituteAndAppend(
3215
0
        &field_type, "map<$0, $1>",
3216
0
        message_type()->field(0)->FieldTypeNameDebugString(),
3217
0
        message_type()->field(1)->FieldTypeNameDebugString());
3218
0
  } else {
3219
0
    field_type = FieldTypeNameDebugString();
3220
0
  }
3221
3222
0
  std::string label = absl::StrCat(kLabelToName[this->label()], " ");
3223
3224
  // Label is omitted for maps, oneof, and plain proto3 fields.
3225
0
  if (is_map() || real_containing_oneof() ||
3226
0
      (is_optional() && !has_optional_keyword())) {
3227
0
    label.clear();
3228
0
  }
3229
3230
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3231
0
                                               debug_string_options);
3232
0
  comment_printer.AddPreComment(contents);
3233
3234
0
  absl::SubstituteAndAppend(
3235
0
      contents, "$0$1$2 $3 = $4", prefix, label, field_type,
3236
0
      type() == TYPE_GROUP ? message_type()->name() : name(), number());
3237
3238
0
  bool bracketed = false;
3239
0
  if (has_default_value()) {
3240
0
    bracketed = true;
3241
0
    absl::SubstituteAndAppend(contents, " [default = $0",
3242
0
                              DefaultValueAsString(true));
3243
0
  }
3244
0
  if (has_json_name_) {
3245
0
    if (!bracketed) {
3246
0
      bracketed = true;
3247
0
      contents->append(" [");
3248
0
    } else {
3249
0
      contents->append(", ");
3250
0
    }
3251
0
    contents->append("json_name = \"");
3252
0
    contents->append(absl::CEscape(json_name()));
3253
0
    contents->append("\"");
3254
0
  }
3255
3256
0
  std::string formatted_options;
3257
0
  if (FormatBracketedOptions(depth, options(), file()->pool(),
3258
0
                             &formatted_options)) {
3259
0
    contents->append(bracketed ? ", " : " [");
3260
0
    bracketed = true;
3261
0
    contents->append(formatted_options);
3262
0
  }
3263
3264
0
  if (bracketed) {
3265
0
    contents->append("]");
3266
0
  }
3267
3268
0
  if (type() == TYPE_GROUP) {
3269
0
    if (debug_string_options.elide_group_body) {
3270
0
      contents->append(" { ... };\n");
3271
0
    } else {
3272
0
      message_type()->DebugString(depth, contents, debug_string_options,
3273
0
                                  /* include_opening_clause */ false);
3274
0
    }
3275
0
  } else {
3276
0
    contents->append(";\n");
3277
0
  }
3278
3279
0
  comment_printer.AddPostComment(contents);
3280
0
}
3281
3282
0
std::string OneofDescriptor::DebugString() const {
3283
0
  DebugStringOptions options;  // default values
3284
0
  return DebugStringWithOptions(options);
3285
0
}
3286
3287
std::string OneofDescriptor::DebugStringWithOptions(
3288
0
    const DebugStringOptions& options) const {
3289
0
  std::string contents;
3290
0
  DebugString(0, &contents, options);
3291
0
  return contents;
3292
0
}
3293
3294
void OneofDescriptor::DebugString(
3295
    int depth, std::string* contents,
3296
0
    const DebugStringOptions& debug_string_options) const {
3297
0
  std::string prefix(depth * 2, ' ');
3298
0
  ++depth;
3299
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3300
0
                                               debug_string_options);
3301
0
  comment_printer.AddPreComment(contents);
3302
0
  absl::SubstituteAndAppend(contents, "$0oneof $1 {", prefix, name());
3303
3304
0
  FormatLineOptions(depth, options(), containing_type()->file()->pool(),
3305
0
                    contents);
3306
3307
0
  if (debug_string_options.elide_oneof_body) {
3308
0
    contents->append(" ... }\n");
3309
0
  } else {
3310
0
    contents->append("\n");
3311
0
    for (int i = 0; i < field_count(); i++) {
3312
0
      field(i)->DebugString(depth, contents, debug_string_options);
3313
0
    }
3314
0
    absl::SubstituteAndAppend(contents, "$0}\n", prefix);
3315
0
  }
3316
0
  comment_printer.AddPostComment(contents);
3317
0
}
3318
3319
0
std::string EnumDescriptor::DebugString() const {
3320
0
  DebugStringOptions options;  // default values
3321
0
  return DebugStringWithOptions(options);
3322
0
}
3323
3324
std::string EnumDescriptor::DebugStringWithOptions(
3325
0
    const DebugStringOptions& options) const {
3326
0
  std::string contents;
3327
0
  DebugString(0, &contents, options);
3328
0
  return contents;
3329
0
}
3330
3331
void EnumDescriptor::DebugString(
3332
    int depth, std::string* contents,
3333
0
    const DebugStringOptions& debug_string_options) const {
3334
0
  std::string prefix(depth * 2, ' ');
3335
0
  ++depth;
3336
3337
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3338
0
                                               debug_string_options);
3339
0
  comment_printer.AddPreComment(contents);
3340
3341
0
  absl::SubstituteAndAppend(contents, "$0enum $1 {\n", prefix, name());
3342
3343
0
  FormatLineOptions(depth, options(), file()->pool(), contents);
3344
3345
0
  for (int i = 0; i < value_count(); i++) {
3346
0
    value(i)->DebugString(depth, contents, debug_string_options);
3347
0
  }
3348
3349
0
  if (reserved_range_count() > 0) {
3350
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3351
0
    for (int i = 0; i < reserved_range_count(); i++) {
3352
0
      const EnumDescriptor::ReservedRange* range = reserved_range(i);
3353
0
      if (range->end == range->start) {
3354
0
        absl::SubstituteAndAppend(contents, "$0, ", range->start);
3355
0
      } else if (range->end == INT_MAX) {
3356
0
        absl::SubstituteAndAppend(contents, "$0 to max, ", range->start);
3357
0
      } else {
3358
0
        absl::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
3359
0
                                  range->end);
3360
0
      }
3361
0
    }
3362
0
    contents->replace(contents->size() - 2, 2, ";\n");
3363
0
  }
3364
3365
0
  if (reserved_name_count() > 0) {
3366
0
    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
3367
0
    for (int i = 0; i < reserved_name_count(); i++) {
3368
0
      absl::SubstituteAndAppend(contents, "\"$0\", ",
3369
0
                                absl::CEscape(reserved_name(i)));
3370
0
    }
3371
0
    contents->replace(contents->size() - 2, 2, ";\n");
3372
0
  }
3373
3374
0
  absl::SubstituteAndAppend(contents, "$0}\n", prefix);
3375
3376
0
  comment_printer.AddPostComment(contents);
3377
0
}
3378
3379
0
std::string EnumValueDescriptor::DebugString() const {
3380
0
  DebugStringOptions options;  // default values
3381
0
  return DebugStringWithOptions(options);
3382
0
}
3383
3384
std::string EnumValueDescriptor::DebugStringWithOptions(
3385
0
    const DebugStringOptions& options) const {
3386
0
  std::string contents;
3387
0
  DebugString(0, &contents, options);
3388
0
  return contents;
3389
0
}
3390
3391
void EnumValueDescriptor::DebugString(
3392
    int depth, std::string* contents,
3393
0
    const DebugStringOptions& debug_string_options) const {
3394
0
  std::string prefix(depth * 2, ' ');
3395
3396
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3397
0
                                               debug_string_options);
3398
0
  comment_printer.AddPreComment(contents);
3399
3400
0
  absl::SubstituteAndAppend(contents, "$0$1 = $2", prefix, name(), number());
3401
3402
0
  std::string formatted_options;
3403
0
  if (FormatBracketedOptions(depth, options(), type()->file()->pool(),
3404
0
                             &formatted_options)) {
3405
0
    absl::SubstituteAndAppend(contents, " [$0]", formatted_options);
3406
0
  }
3407
0
  contents->append(";\n");
3408
3409
0
  comment_printer.AddPostComment(contents);
3410
0
}
3411
3412
0
std::string ServiceDescriptor::DebugString() const {
3413
0
  DebugStringOptions options;  // default values
3414
0
  return DebugStringWithOptions(options);
3415
0
}
3416
3417
std::string ServiceDescriptor::DebugStringWithOptions(
3418
0
    const DebugStringOptions& options) const {
3419
0
  std::string contents;
3420
0
  DebugString(&contents, options);
3421
0
  return contents;
3422
0
}
3423
3424
void ServiceDescriptor::DebugString(
3425
    std::string* contents,
3426
0
    const DebugStringOptions& debug_string_options) const {
3427
0
  SourceLocationCommentPrinter comment_printer(this, /* prefix */ "",
3428
0
                                               debug_string_options);
3429
0
  comment_printer.AddPreComment(contents);
3430
3431
0
  absl::SubstituteAndAppend(contents, "service $0 {\n", name());
3432
3433
0
  FormatLineOptions(1, options(), file()->pool(), contents);
3434
3435
0
  for (int i = 0; i < method_count(); i++) {
3436
0
    method(i)->DebugString(1, contents, debug_string_options);
3437
0
  }
3438
3439
0
  contents->append("}\n");
3440
3441
0
  comment_printer.AddPostComment(contents);
3442
0
}
3443
3444
0
std::string MethodDescriptor::DebugString() const {
3445
0
  DebugStringOptions options;  // default values
3446
0
  return DebugStringWithOptions(options);
3447
0
}
3448
3449
std::string MethodDescriptor::DebugStringWithOptions(
3450
0
    const DebugStringOptions& options) const {
3451
0
  std::string contents;
3452
0
  DebugString(0, &contents, options);
3453
0
  return contents;
3454
0
}
3455
3456
void MethodDescriptor::DebugString(
3457
    int depth, std::string* contents,
3458
0
    const DebugStringOptions& debug_string_options) const {
3459
0
  std::string prefix(depth * 2, ' ');
3460
0
  ++depth;
3461
3462
0
  SourceLocationCommentPrinter comment_printer(this, prefix,
3463
0
                                               debug_string_options);
3464
0
  comment_printer.AddPreComment(contents);
3465
3466
0
  absl::SubstituteAndAppend(
3467
0
      contents, "$0rpc $1($4.$2) returns ($5.$3)", prefix, name(),
3468
0
      input_type()->full_name(), output_type()->full_name(),
3469
0
      client_streaming() ? "stream " : "", server_streaming() ? "stream " : "");
3470
3471
0
  std::string formatted_options;
3472
0
  if (FormatLineOptions(depth, options(), service()->file()->pool(),
3473
0
                        &formatted_options)) {
3474
0
    absl::SubstituteAndAppend(contents, " {\n$0$1}\n", formatted_options,
3475
0
                              prefix);
3476
0
  } else {
3477
0
    contents->append(";\n");
3478
0
  }
3479
3480
0
  comment_printer.AddPostComment(contents);
3481
0
}
3482
3483
// Location methods ===============================================
3484
3485
bool FileDescriptor::GetSourceLocation(const std::vector<int>& path,
3486
0
                                       SourceLocation* out_location) const {
3487
0
  ABSL_CHECK(out_location != nullptr);
3488
0
  if (source_code_info_) {
3489
0
    if (const SourceCodeInfo_Location* loc =
3490
0
            tables_->GetSourceLocation(path, source_code_info_)) {
3491
0
      const RepeatedField<int32_t>& span = loc->span();
3492
0
      if (span.size() == 3 || span.size() == 4) {
3493
0
        out_location->start_line = span.Get(0);
3494
0
        out_location->start_column = span.Get(1);
3495
0
        out_location->end_line = span.Get(span.size() == 3 ? 0 : 2);
3496
0
        out_location->end_column = span.Get(span.size() - 1);
3497
3498
0
        out_location->leading_comments = loc->leading_comments();
3499
0
        out_location->trailing_comments = loc->trailing_comments();
3500
0
        out_location->leading_detached_comments.assign(
3501
0
            loc->leading_detached_comments().begin(),
3502
0
            loc->leading_detached_comments().end());
3503
0
        return true;
3504
0
      }
3505
0
    }
3506
0
  }
3507
0
  return false;
3508
0
}
3509
3510
0
bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3511
0
  std::vector<int> path;  // empty path for root FileDescriptor
3512
0
  return GetSourceLocation(path, out_location);
3513
0
}
3514
3515
0
bool FieldDescriptor::is_packed() const {
3516
0
  if (!is_packable()) return false;
3517
0
  if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) {
3518
0
    return (options_ != nullptr) && options_->packed();
3519
0
  } else {
3520
0
    return options_ == nullptr || !options_->has_packed() || options_->packed();
3521
0
  }
3522
0
}
3523
3524
0
bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
3525
0
  std::vector<int> path;
3526
0
  GetLocationPath(&path);
3527
0
  return file()->GetSourceLocation(path, out_location);
3528
0
}
3529
3530
0
bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3531
0
  std::vector<int> path;
3532
0
  GetLocationPath(&path);
3533
0
  return file()->GetSourceLocation(path, out_location);
3534
0
}
3535
3536
0
bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3537
0
  std::vector<int> path;
3538
0
  GetLocationPath(&path);
3539
0
  return containing_type()->file()->GetSourceLocation(path, out_location);
3540
0
}
3541
3542
0
bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3543
0
  std::vector<int> path;
3544
0
  GetLocationPath(&path);
3545
0
  return file()->GetSourceLocation(path, out_location);
3546
0
}
3547
3548
0
bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3549
0
  std::vector<int> path;
3550
0
  GetLocationPath(&path);
3551
0
  return service()->file()->GetSourceLocation(path, out_location);
3552
0
}
3553
3554
0
bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3555
0
  std::vector<int> path;
3556
0
  GetLocationPath(&path);
3557
0
  return file()->GetSourceLocation(path, out_location);
3558
0
}
3559
3560
bool EnumValueDescriptor::GetSourceLocation(
3561
0
    SourceLocation* out_location) const {
3562
0
  std::vector<int> path;
3563
0
  GetLocationPath(&path);
3564
0
  return type()->file()->GetSourceLocation(path, out_location);
3565
0
}
3566
3567
18
void Descriptor::GetLocationPath(std::vector<int>* output) const {
3568
18
  if (containing_type()) {
3569
6
    containing_type()->GetLocationPath(output);
3570
6
    output->push_back(DescriptorProto::kNestedTypeFieldNumber);
3571
6
    output->push_back(index());
3572
12
  } else {
3573
12
    output->push_back(FileDescriptorProto::kMessageTypeFieldNumber);
3574
12
    output->push_back(index());
3575
12
  }
3576
18
}
3577
3578
12
void FieldDescriptor::GetLocationPath(std::vector<int>* output) const {
3579
12
  if (is_extension()) {
3580
0
    if (extension_scope() == nullptr) {
3581
0
      output->push_back(FileDescriptorProto::kExtensionFieldNumber);
3582
0
      output->push_back(index());
3583
0
    } else {
3584
0
      extension_scope()->GetLocationPath(output);
3585
0
      output->push_back(DescriptorProto::kExtensionFieldNumber);
3586
0
      output->push_back(index());
3587
0
    }
3588
12
  } else {
3589
12
    containing_type()->GetLocationPath(output);
3590
12
    output->push_back(DescriptorProto::kFieldFieldNumber);
3591
12
    output->push_back(index());
3592
12
  }
3593
12
}
3594
3595
0
void OneofDescriptor::GetLocationPath(std::vector<int>* output) const {
3596
0
  containing_type()->GetLocationPath(output);
3597
0
  output->push_back(DescriptorProto::kOneofDeclFieldNumber);
3598
0
  output->push_back(index());
3599
0
}
3600
3601
0
void EnumDescriptor::GetLocationPath(std::vector<int>* output) const {
3602
0
  if (containing_type()) {
3603
0
    containing_type()->GetLocationPath(output);
3604
0
    output->push_back(DescriptorProto::kEnumTypeFieldNumber);
3605
0
    output->push_back(index());
3606
0
  } else {
3607
0
    output->push_back(FileDescriptorProto::kEnumTypeFieldNumber);
3608
0
    output->push_back(index());
3609
0
  }
3610
0
}
3611
3612
0
void EnumValueDescriptor::GetLocationPath(std::vector<int>* output) const {
3613
0
  type()->GetLocationPath(output);
3614
0
  output->push_back(EnumDescriptorProto::kValueFieldNumber);
3615
0
  output->push_back(index());
3616
0
}
3617
3618
0
void ServiceDescriptor::GetLocationPath(std::vector<int>* output) const {
3619
0
  output->push_back(FileDescriptorProto::kServiceFieldNumber);
3620
0
  output->push_back(index());
3621
0
}
3622
3623
0
void MethodDescriptor::GetLocationPath(std::vector<int>* output) const {
3624
0
  service()->GetLocationPath(output);
3625
0
  output->push_back(ServiceDescriptorProto::kMethodFieldNumber);
3626
0
  output->push_back(index());
3627
0
}
3628
3629
// ===================================================================
3630
3631
namespace {
3632
3633
// Represents an options message to interpret. Extension names in the option
3634
// name are resolved relative to name_scope. element_name and orig_opt are
3635
// used only for error reporting (since the parser records locations against
3636
// pointers in the original options, not the mutable copy). The Message must be
3637
// one of the Options messages in descriptor.proto.
3638
struct OptionsToInterpret {
3639
  OptionsToInterpret(absl::string_view ns, absl::string_view el,
3640
                     const std::vector<int>& path, const Message* orig_opt,
3641
                     Message* opt)
3642
      : name_scope(ns),
3643
        element_name(el),
3644
        element_path(path),
3645
        original_options(orig_opt),
3646
0
        options(opt) {}
3647
  std::string name_scope;
3648
  std::string element_name;
3649
  std::vector<int> element_path;
3650
  const Message* original_options;
3651
  Message* options;
3652
};
3653
3654
}  // namespace
3655
3656
class DescriptorBuilder {
3657
 public:
3658
  static std::unique_ptr<DescriptorBuilder> New(
3659
      const DescriptorPool* pool, DescriptorPool::Tables* tables,
3660
6
      DescriptorPool::ErrorCollector* error_collector) {
3661
6
    return std::unique_ptr<DescriptorBuilder>(
3662
6
        new DescriptorBuilder(pool, tables, error_collector));
3663
6
  }
3664
3665
  ~DescriptorBuilder();
3666
3667
  const FileDescriptor* BuildFile(const FileDescriptorProto& proto);
3668
3669
 private:
3670
  DescriptorBuilder(const DescriptorPool* pool, DescriptorPool::Tables* tables,
3671
                    DescriptorPool::ErrorCollector* error_collector);
3672
3673
  friend class OptionInterpreter;
3674
3675
  // Non-recursive part of BuildFile functionality.
3676
  FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto,
3677
                                internal::FlatAllocator& alloc);
3678
3679
  const DescriptorPool* pool_;
3680
  DescriptorPool::Tables* tables_;  // for convenience
3681
  DescriptorPool::ErrorCollector* error_collector_;
3682
3683
  // As we build descriptors we store copies of the options messages in
3684
  // them. We put pointers to those copies in this vector, as we build, so we
3685
  // can later (after cross-linking) interpret those options.
3686
  std::vector<OptionsToInterpret> options_to_interpret_;
3687
3688
  bool had_errors_;
3689
  std::string filename_;
3690
  FileDescriptor* file_;
3691
  FileDescriptorTables* file_tables_;
3692
  absl::flat_hash_set<const FileDescriptor*> dependencies_;
3693
3694
  struct MessageHints {
3695
    int fields_to_suggest = 0;
3696
    const Message* first_reason = nullptr;
3697
    DescriptorPool::ErrorCollector::ErrorLocation first_reason_location =
3698
        DescriptorPool::ErrorCollector::ErrorLocation::OTHER;
3699
3700
    void RequestHintOnFieldNumbers(
3701
        const Message& reason,
3702
        DescriptorPool::ErrorCollector::ErrorLocation reason_location,
3703
0
        int range_start = 0, int range_end = 1) {
3704
0
      auto fit = [](int value) {
3705
0
        return std::min(std::max(value, 0), FieldDescriptor::kMaxNumber);
3706
0
      };
3707
0
      fields_to_suggest =
3708
0
          fit(fields_to_suggest + fit(fit(range_end) - fit(range_start)));
3709
0
      if (first_reason) return;
3710
0
      first_reason = &reason;
3711
0
      first_reason_location = reason_location;
3712
0
    }
3713
  };
3714
3715
  absl::flat_hash_map<const Descriptor*, MessageHints> message_hints_;
3716
3717
  // unused_dependency_ is used to record the unused imported files.
3718
  // Note: public import is not considered.
3719
  absl::flat_hash_set<const FileDescriptor*> unused_dependency_;
3720
3721
  // If LookupSymbol() finds a symbol that is in a file which is not a declared
3722
  // dependency of this file, it will fail, but will set
3723
  // possible_undeclared_dependency_ to point at that file.  This is only used
3724
  // by AddNotDefinedError() to report a more useful error message.
3725
  // possible_undeclared_dependency_name_ is the name of the symbol that was
3726
  // actually found in possible_undeclared_dependency_, which may be a parent
3727
  // of the symbol actually looked for.
3728
  const FileDescriptor* possible_undeclared_dependency_;
3729
  std::string possible_undeclared_dependency_name_;
3730
3731
  // If LookupSymbol() could resolve a symbol which is not defined,
3732
  // record the resolved name.  This is only used by AddNotDefinedError()
3733
  // to report a more useful error message.
3734
  std::string undefine_resolved_name_;
3735
3736
  // Tracker for current recursion depth to implement recursion protection.
3737
  //
3738
  // Counts down to 0 when there is no depth remaining.
3739
  //
3740
  // Maximum recursion depth corresponds to 32 nested message declarations.
3741
  int recursion_depth_ = 32;
3742
3743
  void AddError(const std::string& element_name, const Message& descriptor,
3744
                DescriptorPool::ErrorCollector::ErrorLocation location,
3745
                const std::string& error);
3746
  void AddError(const std::string& element_name, const Message& descriptor,
3747
                DescriptorPool::ErrorCollector::ErrorLocation location,
3748
                const char* error);
3749
  void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here);
3750
  void AddTwiceListedError(const FileDescriptorProto& proto, int index);
3751
  void AddImportError(const FileDescriptorProto& proto, int index);
3752
3753
  // Adds an error indicating that undefined_symbol was not defined.  Must
3754
  // only be called after LookupSymbol() fails.
3755
  void AddNotDefinedError(
3756
      const std::string& element_name, const Message& descriptor,
3757
      DescriptorPool::ErrorCollector::ErrorLocation location,
3758
      const std::string& undefined_symbol);
3759
3760
  void AddWarning(const std::string& element_name, const Message& descriptor,
3761
                  DescriptorPool::ErrorCollector::ErrorLocation location,
3762
                  const std::string& error);
3763
3764
  // Silly helper which determines if the given file is in the given package.
3765
  // I.e., either file->package() == package_name or file->package() is a
3766
  // nested package within package_name.
3767
  bool IsInPackage(const FileDescriptor* file, absl::string_view package_name);
3768
3769
  // Helper function which finds all public dependencies of the given file, and
3770
  // stores the them in the dependencies_ set in the builder.
3771
  void RecordPublicDependencies(const FileDescriptor* file);
3772
3773
  // Like tables_->FindSymbol(), but additionally:
3774
  // - Search the pool's underlay if not found in tables_.
3775
  // - Insure that the resulting Symbol is from one of the file's declared
3776
  //   dependencies.
3777
  Symbol FindSymbol(const std::string& name, bool build_it = true);
3778
3779
  // Like FindSymbol() but does not require that the symbol is in one of the
3780
  // file's declared dependencies.
3781
  Symbol FindSymbolNotEnforcingDeps(const std::string& name,
3782
                                    bool build_it = true);
3783
3784
  // This implements the body of FindSymbolNotEnforcingDeps().
3785
  Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool,
3786
                                          const std::string& name,
3787
                                          bool build_it = true);
3788
3789
  // Like FindSymbol(), but looks up the name relative to some other symbol
3790
  // name.  This first searches siblings of relative_to, then siblings of its
3791
  // parents, etc.  For example, LookupSymbol("foo.bar", "baz.moo.corge") makes
3792
  // the following calls, returning the first non-null result:
3793
  // FindSymbol("baz.moo.foo.bar"), FindSymbol("baz.foo.bar"),
3794
  // FindSymbol("foo.bar").  If AllowUnknownDependencies() has been called
3795
  // on the DescriptorPool, this will generate a placeholder type if
3796
  // the name is not found (unless the name itself is malformed).  The
3797
  // placeholder_type parameter indicates what kind of placeholder should be
3798
  // constructed in this case.  The resolve_mode parameter determines whether
3799
  // any symbol is returned, or only symbols that are types.  Note, however,
3800
  // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode,
3801
  // if it believes that's all it could refer to.  The caller should always
3802
  // check that it receives the type of symbol it was expecting.
3803
  enum ResolveMode { LOOKUP_ALL, LOOKUP_TYPES };
3804
  Symbol LookupSymbol(const std::string& name, const std::string& relative_to,
3805
                      DescriptorPool::PlaceholderType placeholder_type =
3806
                          DescriptorPool::PLACEHOLDER_MESSAGE,
3807
                      ResolveMode resolve_mode = LOOKUP_ALL,
3808
                      bool build_it = true);
3809
3810
  // Like LookupSymbol() but will not return a placeholder even if
3811
  // AllowUnknownDependencies() has been used.
3812
  Symbol LookupSymbolNoPlaceholder(const std::string& name,
3813
                                   const std::string& relative_to,
3814
                                   ResolveMode resolve_mode = LOOKUP_ALL,
3815
                                   bool build_it = true);
3816
3817
  // Calls tables_->AddSymbol() and records an error if it fails.  Returns
3818
  // true if successful or false if failed, though most callers can ignore
3819
  // the return value since an error has already been recorded.
3820
  bool AddSymbol(const std::string& full_name, const void* parent,
3821
                 const std::string& name, const Message& proto, Symbol symbol);
3822
3823
  // Like AddSymbol(), but succeeds if the symbol is already defined as long
3824
  // as the existing definition is also a package (because it's OK to define
3825
  // the same package in two different files).  Also adds all parents of the
3826
  // package to the symbol table (e.g. AddPackage("foo.bar", ...) will add
3827
  // "foo.bar" and "foo" to the table).
3828
  void AddPackage(const std::string& name, const Message& proto,
3829
                  FileDescriptor* file);
3830
3831
  // Checks that the symbol name contains only alphanumeric characters and
3832
  // underscores.  Records an error otherwise.
3833
  void ValidateSymbolName(const std::string& name, const std::string& full_name,
3834
                          const Message& proto);
3835
3836
  // Allocates a copy of orig_options in tables_ and stores it in the
3837
  // descriptor. Remembers its uninterpreted options, to be interpreted
3838
  // later. DescriptorT must be one of the Descriptor messages from
3839
  // descriptor.proto.
3840
  template <class DescriptorT>
3841
  void AllocateOptions(const typename DescriptorT::OptionsType& orig_options,
3842
                       DescriptorT* descriptor, int options_field_tag,
3843
                       absl::string_view option_name,
3844
                       internal::FlatAllocator& alloc);
3845
  // Specialization for FileOptions.
3846
  void AllocateOptions(const FileOptions& orig_options,
3847
                       FileDescriptor* descriptor,
3848
                       internal::FlatAllocator& alloc);
3849
3850
  // Implementation for AllocateOptions(). Don't call this directly.
3851
  template <class DescriptorT>
3852
  void AllocateOptionsImpl(
3853
      absl::string_view name_scope, absl::string_view element_name,
3854
      const typename DescriptorT::OptionsType& orig_options,
3855
      DescriptorT* descriptor, const std::vector<int>& options_path,
3856
      absl::string_view option_name, internal::FlatAllocator& alloc);
3857
3858
  // Allocates an array of two strings, the first one is a copy of `proto_name`,
3859
  // and the second one is the full name.
3860
  // Full proto name is "scope.proto_name" if scope is non-empty and
3861
  // "proto_name" otherwise.
3862
  const std::string* AllocateNameStrings(const std::string& scope,
3863
                                         const std::string& proto_name,
3864
                                         internal::FlatAllocator& alloc);
3865
3866
  // These methods all have the same signature for the sake of the BUILD_ARRAY
3867
  // macro, below.
3868
  void BuildMessage(const DescriptorProto& proto, const Descriptor* parent,
3869
                    Descriptor* result, internal::FlatAllocator& alloc);
3870
  void BuildFieldOrExtension(const FieldDescriptorProto& proto,
3871
                             Descriptor* parent, FieldDescriptor* result,
3872
                             bool is_extension, internal::FlatAllocator& alloc);
3873
  void BuildField(const FieldDescriptorProto& proto, Descriptor* parent,
3874
330
                  FieldDescriptor* result, internal::FlatAllocator& alloc) {
3875
330
    BuildFieldOrExtension(proto, parent, result, false, alloc);
3876
330
  }
3877
  void BuildExtension(const FieldDescriptorProto& proto, Descriptor* parent,
3878
0
                      FieldDescriptor* result, internal::FlatAllocator& alloc) {
3879
0
    BuildFieldOrExtension(proto, parent, result, true, alloc);
3880
0
  }
3881
  void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
3882
                           const Descriptor* parent,
3883
                           Descriptor::ExtensionRange* result,
3884
                           internal::FlatAllocator& alloc);
3885
  void BuildReservedRange(const DescriptorProto::ReservedRange& proto,
3886
                          const Descriptor* parent,
3887
                          Descriptor::ReservedRange* result,
3888
                          internal::FlatAllocator& alloc);
3889
  void BuildReservedRange(const EnumDescriptorProto::EnumReservedRange& proto,
3890
                          const EnumDescriptor* parent,
3891
                          EnumDescriptor::ReservedRange* result,
3892
                          internal::FlatAllocator& alloc);
3893
  void BuildOneof(const OneofDescriptorProto& proto, Descriptor* parent,
3894
                  OneofDescriptor* result, internal::FlatAllocator& alloc);
3895
  void BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent,
3896
                 EnumDescriptor* result, internal::FlatAllocator& alloc);
3897
  void BuildEnumValue(const EnumValueDescriptorProto& proto,
3898
                      const EnumDescriptor* parent, EnumValueDescriptor* result,
3899
                      internal::FlatAllocator& alloc);
3900
  void BuildService(const ServiceDescriptorProto& proto, const void* dummy,
3901
                    ServiceDescriptor* result, internal::FlatAllocator& alloc);
3902
  void BuildMethod(const MethodDescriptorProto& proto,
3903
                   const ServiceDescriptor* parent, MethodDescriptor* result,
3904
                   internal::FlatAllocator& alloc);
3905
3906
  void CheckFieldJsonNameUniqueness(const DescriptorProto& proto,
3907
                                    const Descriptor* result);
3908
  void CheckFieldJsonNameUniqueness(const std::string& message_name,
3909
                                    const DescriptorProto& message,
3910
                                    FileDescriptor::Syntax syntax,
3911
                                    bool use_custom_names);
3912
  void CheckEnumValueUniqueness(const EnumDescriptorProto& proto,
3913
                                const EnumDescriptor* result);
3914
3915
  void LogUnusedDependency(const FileDescriptorProto& proto,
3916
                           const FileDescriptor* result);
3917
3918
  // Must be run only after building.
3919
  //
3920
  // NOTE: Options will not be available during cross-linking, as they
3921
  // have not yet been interpreted. Defer any handling of options to the
3922
  // Validate*Options methods.
3923
  void CrossLinkFile(FileDescriptor* file, const FileDescriptorProto& proto);
3924
  void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto);
3925
  void CrossLinkField(FieldDescriptor* field,
3926
                      const FieldDescriptorProto& proto);
3927
  void CrossLinkExtensionRange(Descriptor::ExtensionRange* range,
3928
                               const DescriptorProto::ExtensionRange& proto);
3929
  void CrossLinkEnum(EnumDescriptor* enum_type,
3930
                     const EnumDescriptorProto& proto);
3931
  void CrossLinkEnumValue(EnumValueDescriptor* enum_value,
3932
                          const EnumValueDescriptorProto& proto);
3933
  void CrossLinkService(ServiceDescriptor* service,
3934
                        const ServiceDescriptorProto& proto);
3935
  void CrossLinkMethod(MethodDescriptor* method,
3936
                       const MethodDescriptorProto& proto);
3937
  void SuggestFieldNumbers(FileDescriptor* file,
3938
                           const FileDescriptorProto& proto);
3939
3940
  // Must be run only after cross-linking.
3941
  void InterpretOptions();
3942
3943
  // A helper class for interpreting options.
3944
  class OptionInterpreter {
3945
   public:
3946
    // Creates an interpreter that operates in the context of the pool of the
3947
    // specified builder, which must not be nullptr. We don't take ownership of
3948
    // the builder.
3949
    explicit OptionInterpreter(DescriptorBuilder* builder);
3950
    OptionInterpreter(const OptionInterpreter&) = delete;
3951
    OptionInterpreter& operator=(const OptionInterpreter&) = delete;
3952
3953
    ~OptionInterpreter();
3954
3955
    // Interprets the uninterpreted options in the specified Options message.
3956
    // On error, calls AddError() on the underlying builder and returns false.
3957
    // Otherwise returns true.
3958
    bool InterpretOptions(OptionsToInterpret* options_to_interpret);
3959
3960
    // Updates the given source code info by re-writing uninterpreted option
3961
    // locations to refer to the corresponding interpreted option.
3962
    void UpdateSourceCodeInfo(SourceCodeInfo* info);
3963
3964
    class AggregateOptionFinder;
3965
3966
   private:
3967
    // Interprets uninterpreted_option_ on the specified message, which
3968
    // must be the mutable copy of the original options message to which
3969
    // uninterpreted_option_ belongs. The given src_path is the source
3970
    // location path to the uninterpreted option, and options_path is the
3971
    // source location path to the options message. The location paths are
3972
    // recorded and then used in UpdateSourceCodeInfo.
3973
    bool InterpretSingleOption(Message* options,
3974
                               const std::vector<int>& src_path,
3975
                               const std::vector<int>& options_path);
3976
3977
    // Adds the uninterpreted_option to the given options message verbatim.
3978
    // Used when AllowUnknownDependencies() is in effect and we can't find
3979
    // the option's definition.
3980
    void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option,
3981
                                Message* options);
3982
3983
    // A recursive helper function that drills into the intermediate fields
3984
    // in unknown_fields to check if field innermost_field is set on the
3985
    // innermost message. Returns false and sets an error if so.
3986
    bool ExamineIfOptionIsSet(
3987
        std::vector<const FieldDescriptor*>::const_iterator
3988
            intermediate_fields_iter,
3989
        std::vector<const FieldDescriptor*>::const_iterator
3990
            intermediate_fields_end,
3991
        const FieldDescriptor* innermost_field,
3992
        const std::string& debug_msg_name,
3993
        const UnknownFieldSet& unknown_fields);
3994
3995
    // Validates the value for the option field of the currently interpreted
3996
    // option and then sets it on the unknown_field.
3997
    bool SetOptionValue(const FieldDescriptor* option_field,
3998
                        UnknownFieldSet* unknown_fields);
3999
4000
    // Parses an aggregate value for a CPPTYPE_MESSAGE option and
4001
    // saves it into *unknown_fields.
4002
    bool SetAggregateOption(const FieldDescriptor* option_field,
4003
                            UnknownFieldSet* unknown_fields);
4004
4005
    // Convenience functions to set an int field the right way, depending on
4006
    // its wire type (a single int CppType can represent multiple wire types).
4007
    void SetInt32(int number, int32_t value, FieldDescriptor::Type type,
4008
                  UnknownFieldSet* unknown_fields);
4009
    void SetInt64(int number, int64_t value, FieldDescriptor::Type type,
4010
                  UnknownFieldSet* unknown_fields);
4011
    void SetUInt32(int number, uint32_t value, FieldDescriptor::Type type,
4012
                   UnknownFieldSet* unknown_fields);
4013
    void SetUInt64(int number, uint64_t value, FieldDescriptor::Type type,
4014
                   UnknownFieldSet* unknown_fields);
4015
4016
    // A helper function that adds an error at the specified location of the
4017
    // option we're currently interpreting, and returns false.
4018
    bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,
4019
0
                        const std::string& msg) {
4020
0
      builder_->AddError(options_to_interpret_->element_name,
4021
0
                         *uninterpreted_option_, location, msg);
4022
0
      return false;
4023
0
    }
4024
4025
    // A helper function that adds an error at the location of the option name
4026
    // and returns false.
4027
0
    bool AddNameError(const std::string& msg) {
4028
#ifdef PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_
4029
      return true;
4030
#else   // PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_
4031
0
      return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME, msg);
4032
0
#endif  // PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_
4033
0
    }
4034
4035
    // A helper function that adds an error at the location of the option name
4036
    // and returns false.
4037
0
    bool AddValueError(const std::string& msg) {
4038
0
      return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE, msg);
4039
0
    }
4040
4041
    // We interpret against this builder's pool. Is never nullptr. We don't own
4042
    // this pointer.
4043
    DescriptorBuilder* builder_;
4044
4045
    // The options we're currently interpreting, or nullptr if we're not in a
4046
    // call to InterpretOptions.
4047
    const OptionsToInterpret* options_to_interpret_;
4048
4049
    // The option we're currently interpreting within options_to_interpret_, or
4050
    // nullptr if we're not in a call to InterpretOptions(). This points to a
4051
    // submessage of the original option, not the mutable copy. Therefore we
4052
    // can use it to find locations recorded by the parser.
4053
    const UninterpretedOption* uninterpreted_option_;
4054
4055
    // This maps the element path of uninterpreted options to the element path
4056
    // of the resulting interpreted option. This is used to modify a file's
4057
    // source code info to account for option interpretation.
4058
    absl::flat_hash_map<std::vector<int>, std::vector<int>> interpreted_paths_;
4059
4060
    // This maps the path to a repeated option field to the known number of
4061
    // elements the field contains. This is used to track the compute the
4062
    // index portion of the element path when interpreting a single option.
4063
    absl::flat_hash_map<std::vector<int>, int> repeated_option_counts_;
4064
4065
    // Factory used to create the dynamic messages we need to parse
4066
    // any aggregate option values we encounter.
4067
    DynamicMessageFactory dynamic_factory_;
4068
  };
4069
4070
  // Work-around for broken compilers:  According to the C++ standard,
4071
  // OptionInterpreter should have access to the private members of any class
4072
  // which has declared DescriptorBuilder as a friend.  Unfortunately some old
4073
  // versions of GCC and other compilers do not implement this correctly.  So,
4074
  // we have to have these intermediate methods to provide access.  We also
4075
  // redundantly declare OptionInterpreter a friend just to make things extra
4076
  // clear for these bad compilers.
4077
  friend class OptionInterpreter;
4078
  friend class OptionInterpreter::AggregateOptionFinder;
4079
4080
0
  static inline bool get_allow_unknown(const DescriptorPool* pool) {
4081
0
    return pool->allow_unknown_;
4082
0
  }
4083
0
  static inline bool get_enforce_weak(const DescriptorPool* pool) {
4084
0
    return pool->enforce_weak_;
4085
0
  }
4086
0
  static inline bool get_is_placeholder(const Descriptor* descriptor) {
4087
0
    return descriptor != nullptr && descriptor->is_placeholder_;
4088
0
  }
4089
0
  static inline void assert_mutex_held(const DescriptorPool* pool) {
4090
0
    if (pool->mutex_ != nullptr) {
4091
0
      pool->mutex_->AssertHeld();
4092
0
    }
4093
0
  }
4094
4095
  // Must be run only after options have been interpreted.
4096
  //
4097
  // NOTE: Validation code must only reference the options in the mutable
4098
  // descriptors, which are the ones that have been interpreted. The const
4099
  // proto references are passed in only so they can be provided to calls to
4100
  // AddError(). Do not look at their options, which have not been interpreted.
4101
  void ValidateFileOptions(FileDescriptor* file,
4102
                           const FileDescriptorProto& proto);
4103
  void ValidateMessageOptions(Descriptor* message,
4104
                              const DescriptorProto& proto);
4105
  void ValidateFieldOptions(FieldDescriptor* field,
4106
                            const FieldDescriptorProto& proto);
4107
  void ValidateEnumOptions(EnumDescriptor* enm,
4108
                           const EnumDescriptorProto& proto);
4109
  void ValidateEnumValueOptions(EnumValueDescriptor* enum_value,
4110
                                const EnumValueDescriptorProto& proto);
4111
  void ValidateExtensionRangeOptions(
4112
      const std::string& full_name, Descriptor::ExtensionRange* extension_range,
4113
      const DescriptorProto_ExtensionRange& proto);
4114
  void ValidateServiceOptions(ServiceDescriptor* service,
4115
                              const ServiceDescriptorProto& proto);
4116
  void ValidateMethodOptions(MethodDescriptor* method,
4117
                             const MethodDescriptorProto& proto);
4118
  void ValidateProto3(FileDescriptor* file, const FileDescriptorProto& proto);
4119
  void ValidateProto3Message(Descriptor* message, const DescriptorProto& proto);
4120
  void ValidateProto3Field(FieldDescriptor* field,
4121
                           const FieldDescriptorProto& proto);
4122
  void ValidateProto3Enum(EnumDescriptor* enm,
4123
                          const EnumDescriptorProto& proto);
4124
4125
  // Returns true if the map entry message is compatible with the
4126
  // auto-generated entry message from map fields syntax.
4127
  bool ValidateMapEntry(FieldDescriptor* field,
4128
                        const FieldDescriptorProto& proto);
4129
4130
  // Recursively detects naming conflicts with map entry types for a
4131
  // better error message.
4132
  void DetectMapConflicts(const Descriptor* message,
4133
                          const DescriptorProto& proto);
4134
4135
  void ValidateJSType(FieldDescriptor* field,
4136
                      const FieldDescriptorProto& proto);
4137
};
4138
4139
const FileDescriptor* DescriptorPool::BuildFile(
4140
0
    const FileDescriptorProto& proto) {
4141
0
  ABSL_CHECK(fallback_database_ == nullptr)
4142
0
      << "Cannot call BuildFile on a DescriptorPool that uses a "
4143
0
         "DescriptorDatabase.  You must instead find a way to get your file "
4144
0
         "into the underlying database.";
4145
0
  ABSL_CHECK(mutex_ == nullptr);  // Implied by the above ABSL_CHECK.
4146
0
  tables_->known_bad_symbols_.clear();
4147
0
  tables_->known_bad_files_.clear();
4148
0
  return DescriptorBuilder::New(this, tables_.get(), nullptr)->BuildFile(proto);
4149
0
}
4150
4151
const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
4152
0
    const FileDescriptorProto& proto, ErrorCollector* error_collector) {
4153
0
  ABSL_CHECK(fallback_database_ == nullptr)
4154
0
      << "Cannot call BuildFile on a DescriptorPool that uses a "
4155
0
         "DescriptorDatabase.  You must instead find a way to get your file "
4156
0
         "into the underlying database.";
4157
0
  ABSL_CHECK(mutex_ == nullptr);  // Implied by the above ABSL_CHECK.
4158
0
  tables_->known_bad_symbols_.clear();
4159
0
  tables_->known_bad_files_.clear();
4160
0
  return DescriptorBuilder::New(this, tables_.get(), error_collector)
4161
0
      ->BuildFile(proto);
4162
0
}
4163
4164
const FileDescriptor* DescriptorPool::BuildFileFromDatabase(
4165
6
    const FileDescriptorProto& proto) const {
4166
6
  mutex_->AssertHeld();
4167
6
  if (tables_->known_bad_files_.contains(proto.name())) {
4168
0
    return nullptr;
4169
0
  }
4170
6
  const FileDescriptor* result =
4171
6
      DescriptorBuilder::New(this, tables_.get(), default_error_collector_)
4172
6
          ->BuildFile(proto);
4173
6
  if (result == nullptr) {
4174
0
    tables_->known_bad_files_.insert(proto.name());
4175
0
  }
4176
6
  return result;
4177
6
}
4178
4179
DescriptorBuilder::DescriptorBuilder(
4180
    const DescriptorPool* pool, DescriptorPool::Tables* tables,
4181
    DescriptorPool::ErrorCollector* error_collector)
4182
    : pool_(pool),
4183
      tables_(tables),
4184
      error_collector_(error_collector),
4185
      had_errors_(false),
4186
      possible_undeclared_dependency_(nullptr),
4187
6
      undefine_resolved_name_("") {}
4188
4189
6
DescriptorBuilder::~DescriptorBuilder() {}
4190
4191
PROTOBUF_NOINLINE void DescriptorBuilder::AddError(
4192
    const std::string& element_name, const Message& descriptor,
4193
    DescriptorPool::ErrorCollector::ErrorLocation location,
4194
0
    const std::string& error) {
4195
0
  if (error_collector_ == nullptr) {
4196
0
    if (!had_errors_) {
4197
0
      ABSL_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_
4198
0
                      << "\":";
4199
0
    }
4200
0
    ABSL_LOG(ERROR) << "  " << element_name << ": " << error;
4201
0
  } else {
4202
0
    error_collector_->RecordError(filename_, element_name, &descriptor,
4203
0
                                  location, error);
4204
0
  }
4205
0
  had_errors_ = true;
4206
0
}
4207
4208
PROTOBUF_NOINLINE void DescriptorBuilder::AddError(
4209
    const std::string& element_name, const Message& descriptor,
4210
0
    DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) {
4211
0
  AddError(element_name, descriptor, location, std::string(error));
4212
0
}
4213
4214
PROTOBUF_NOINLINE void DescriptorBuilder::AddNotDefinedError(
4215
    const std::string& element_name, const Message& descriptor,
4216
    DescriptorPool::ErrorCollector::ErrorLocation location,
4217
0
    const std::string& undefined_symbol) {
4218
0
  if (possible_undeclared_dependency_ == nullptr &&
4219
0
      undefine_resolved_name_.empty()) {
4220
0
    AddError(element_name, descriptor, location,
4221
0
             absl::StrCat("\"", undefined_symbol, "\" is not defined."));
4222
0
  } else {
4223
0
    if (possible_undeclared_dependency_ != nullptr) {
4224
0
      AddError(element_name, descriptor, location,
4225
0
               absl::StrCat("\"", possible_undeclared_dependency_name_,
4226
0
                            "\" seems to be defined in \"",
4227
0
                            possible_undeclared_dependency_->name(),
4228
0
                            "\", which is not "
4229
0
                            "imported by \"",
4230
0
                            filename_,
4231
0
                            "\".  To use it here, please "
4232
0
                            "add the necessary import."));
4233
0
    }
4234
0
    if (!undefine_resolved_name_.empty()) {
4235
0
      AddError(element_name, descriptor, location,
4236
0
               absl::StrCat(
4237
0
                   "\"", undefined_symbol, "\" is resolved to \"",
4238
0
                   undefine_resolved_name_,
4239
0
                   "\", which is not defined. "
4240
0
                   "The innermost scope is searched first in name resolution. "
4241
0
                   "Consider using a leading '.'(i.e., \".",
4242
0
                   undefined_symbol, "\") to start from the outermost scope."));
4243
0
    }
4244
0
  }
4245
0
}
4246
4247
PROTOBUF_NOINLINE void DescriptorBuilder::AddWarning(
4248
    const std::string& element_name, const Message& descriptor,
4249
    DescriptorPool::ErrorCollector::ErrorLocation location,
4250
0
    const std::string& error) {
4251
0
  if (error_collector_ == nullptr) {
4252
0
    ABSL_LOG(WARNING) << filename_ << " " << element_name << ": " << error;
4253
0
  } else {
4254
0
    error_collector_->RecordWarning(filename_, element_name, &descriptor,
4255
0
                                    location, error);
4256
0
  }
4257
0
}
4258
4259
bool DescriptorBuilder::IsInPackage(const FileDescriptor* file,
4260
0
                                    absl::string_view package_name) {
4261
0
  return absl::StartsWith(file->package(), package_name) &&
4262
0
         (file->package().size() == package_name.size() ||
4263
0
          file->package()[package_name.size()] == '.');
4264
0
}
4265
4266
0
void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
4267
0
  if (file == nullptr || !dependencies_.insert(file).second) return;
4268
0
  for (int i = 0; file != nullptr && i < file->public_dependency_count(); i++) {
4269
0
    RecordPublicDependencies(file->public_dependency(i));
4270
0
  }
4271
0
}
4272
4273
Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
4274
126
    const DescriptorPool* pool, const std::string& name, bool build_it) {
4275
  // If we are looking at an underlay, we must lock its mutex_, since we are
4276
  // accessing the underlay's tables_ directly.
4277
126
  absl::MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_);
4278
4279
126
  Symbol result = pool->tables_->FindSymbol(name);
4280
126
  if (result.IsNull() && pool->underlay_ != nullptr) {
4281
    // Symbol not found; check the underlay.
4282
0
    result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
4283
0
  }
4284
4285
126
  if (result.IsNull()) {
4286
    // With lazily_build_dependencies_, a symbol lookup at cross link time is
4287
    // not guaranteed to be successful. In most cases, build_it will be false,
4288
    // which intentionally prevents us from building an import until it's
4289
    // actually needed. In some cases, like registering an extension, we want
4290
    // to build the file containing the symbol, and build_it will be set.
4291
    // Also, build_it will be true when !lazily_build_dependencies_, to provide
4292
    // better error reporting of missing dependencies.
4293
0
    if (build_it && pool->TryFindSymbolInFallbackDatabase(name)) {
4294
0
      result = pool->tables_->FindSymbol(name);
4295
0
    }
4296
0
  }
4297
4298
126
  return result;
4299
126
}
4300
4301
Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const std::string& name,
4302
126
                                                     bool build_it) {
4303
126
  Symbol result = FindSymbolNotEnforcingDepsHelper(pool_, name, build_it);
4304
  // Only find symbols which were defined in this file or one of its
4305
  // dependencies.
4306
126
  const FileDescriptor* file = result.GetFile();
4307
126
  if (file == file_ || dependencies_.contains(file)) {
4308
126
    unused_dependency_.erase(file);
4309
126
  }
4310
126
  return result;
4311
126
}
4312
4313
126
Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) {
4314
126
  Symbol result = FindSymbolNotEnforcingDeps(name, build_it);
4315
4316
126
  if (result.IsNull()) return result;
4317
4318
126
  if (!pool_->enforce_dependencies_) {
4319
    // Hack for CompilerUpgrader, and also used for lazily_build_dependencies_
4320
126
    return result;
4321
126
  }
4322
4323
  // Only find symbols which were defined in this file or one of its
4324
  // dependencies.
4325
0
  const FileDescriptor* file = result.GetFile();
4326
0
  if (file == file_ || dependencies_.contains(file)) {
4327
0
    return result;
4328
0
  }
4329
4330
0
  if (result.IsPackage()) {
4331
    // Arg, this is overcomplicated.  The symbol is a package name.  It could
4332
    // be that the package was defined in multiple files.  result.GetFile()
4333
    // returns the first file we saw that used this package.  We've determined
4334
    // that that file is not a direct dependency of the file we are currently
4335
    // building, but it could be that some other file which *is* a direct
4336
    // dependency also defines the same package.  We can't really rule out this
4337
    // symbol unless none of the dependencies define it.
4338
0
    if (IsInPackage(file_, name)) return result;
4339
0
    for (const auto* dep : dependencies_) {
4340
      // Note:  A dependency may be nullptr if it was not found or had errors.
4341
0
      if (dep != nullptr && IsInPackage(dep, name)) return result;
4342
0
    }
4343
0
  }
4344
4345
0
  possible_undeclared_dependency_ = file;
4346
0
  possible_undeclared_dependency_name_ = name;
4347
0
  return Symbol();
4348
0
}
4349
4350
Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(
4351
    const std::string& name, const std::string& relative_to,
4352
126
    ResolveMode resolve_mode, bool build_it) {
4353
126
  possible_undeclared_dependency_ = nullptr;
4354
126
  undefine_resolved_name_.clear();
4355
4356
126
  if (!name.empty() && name[0] == '.') {
4357
    // Fully-qualified name.
4358
118
    return FindSymbol(name.substr(1), build_it);
4359
118
  }
4360
4361
  // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
4362
  // defined in multiple parent scopes, we only want to find "Bar.baz" in the
4363
  // innermost one.  E.g., the following should produce an error:
4364
  //   message Bar { message Baz {} }
4365
  //   message Foo {
4366
  //     message Bar {
4367
  //     }
4368
  //     optional Bar.Baz baz = 1;
4369
  //   }
4370
  // So, we look for just "Foo" first, then look for "Bar.baz" within it if
4371
  // found.
4372
8
  std::string::size_type name_dot_pos = name.find_first_of('.');
4373
8
  std::string first_part_of_name;
4374
8
  if (name_dot_pos == std::string::npos) {
4375
8
    first_part_of_name = name;
4376
8
  } else {
4377
0
    first_part_of_name = name.substr(0, name_dot_pos);
4378
0
  }
4379
4380
8
  std::string scope_to_try(relative_to);
4381
4382
8
  while (true) {
4383
    // Chop off the last component of the scope.
4384
8
    std::string::size_type dot_pos = scope_to_try.find_last_of('.');
4385
8
    if (dot_pos == std::string::npos) {
4386
0
      return FindSymbol(name, build_it);
4387
8
    } else {
4388
8
      scope_to_try.erase(dot_pos);
4389
8
    }
4390
4391
    // Append ".first_part_of_name" and try to find.
4392
8
    std::string::size_type old_size = scope_to_try.size();
4393
8
    scope_to_try.append(1, '.');
4394
8
    scope_to_try.append(first_part_of_name);
4395
8
    Symbol result = FindSymbol(scope_to_try, build_it);
4396
8
    if (!result.IsNull()) {
4397
8
      if (first_part_of_name.size() < name.size()) {
4398
        // name is a compound symbol, of which we only found the first part.
4399
        // Now try to look up the rest of it.
4400
0
        if (result.IsAggregate()) {
4401
0
          scope_to_try.append(name, first_part_of_name.size(),
4402
0
                              name.size() - first_part_of_name.size());
4403
0
          result = FindSymbol(scope_to_try, build_it);
4404
0
          if (result.IsNull()) {
4405
0
            undefine_resolved_name_ = scope_to_try;
4406
0
          }
4407
0
          return result;
4408
0
        } else {
4409
          // We found a symbol but it's not an aggregate.  Continue the loop.
4410
0
        }
4411
8
      } else {
4412
8
        if (resolve_mode == LOOKUP_TYPES && !result.IsType()) {
4413
          // We found a symbol but it's not a type.  Continue the loop.
4414
8
        } else {
4415
8
          return result;
4416
8
        }
4417
8
      }
4418
8
    }
4419
4420
    // Not found.  Remove the name so we can try again.
4421
0
    scope_to_try.erase(old_size);
4422
0
  }
4423
8
}
4424
4425
Symbol DescriptorBuilder::LookupSymbol(
4426
    const std::string& name, const std::string& relative_to,
4427
    DescriptorPool::PlaceholderType placeholder_type, ResolveMode resolve_mode,
4428
118
    bool build_it) {
4429
118
  Symbol result =
4430
118
      LookupSymbolNoPlaceholder(name, relative_to, resolve_mode, build_it);
4431
118
  if (result.IsNull() && pool_->allow_unknown_) {
4432
    // Not found, but AllowUnknownDependencies() is enabled.  Return a
4433
    // placeholder instead.
4434
0
    result = pool_->NewPlaceholderWithMutexHeld(name, placeholder_type);
4435
0
  }
4436
118
  return result;
4437
118
}
4438
4439
0
static bool ValidateQualifiedName(absl::string_view name) {
4440
0
  bool last_was_period = false;
4441
4442
0
  for (char character : name) {
4443
    // I don't trust isalnum() due to locales.  :(
4444
0
    if (('a' <= character && character <= 'z') ||
4445
0
        ('A' <= character && character <= 'Z') ||
4446
0
        ('0' <= character && character <= '9') || (character == '_')) {
4447
0
      last_was_period = false;
4448
0
    } else if (character == '.') {
4449
0
      if (last_was_period) return false;
4450
0
      last_was_period = true;
4451
0
    } else {
4452
0
      return false;
4453
0
    }
4454
0
  }
4455
4456
0
  return !name.empty() && !last_was_period;
4457
0
}
4458
4459
Symbol DescriptorPool::NewPlaceholder(absl::string_view name,
4460
0
                                      PlaceholderType placeholder_type) const {
4461
0
  absl::MutexLockMaybe lock(mutex_);
4462
0
  return NewPlaceholderWithMutexHeld(name, placeholder_type);
4463
0
}
4464
4465
Symbol DescriptorPool::NewPlaceholderWithMutexHeld(
4466
0
    absl::string_view name, PlaceholderType placeholder_type) const {
4467
0
  if (mutex_) {
4468
0
    mutex_->AssertHeld();
4469
0
  }
4470
  // Compute names.
4471
0
  absl::string_view placeholder_full_name;
4472
0
  absl::string_view placeholder_name;
4473
0
  const std::string* placeholder_package;
4474
4475
0
  if (!ValidateQualifiedName(name)) return Symbol();
4476
0
  if (name[0] == '.') {
4477
    // Fully-qualified.
4478
0
    placeholder_full_name = name.substr(1);
4479
0
  } else {
4480
0
    placeholder_full_name = name;
4481
0
  }
4482
4483
  // Create the placeholders.
4484
0
  internal::FlatAllocator alloc;
4485
0
  alloc.PlanArray<FileDescriptor>(1);
4486
0
  alloc.PlanArray<std::string>(2);
4487
0
  if (placeholder_type == PLACEHOLDER_ENUM) {
4488
0
    alloc.PlanArray<EnumDescriptor>(1);
4489
0
    alloc.PlanArray<EnumValueDescriptor>(1);
4490
0
    alloc.PlanArray<std::string>(2);  // names for the descriptor.
4491
0
    alloc.PlanArray<std::string>(2);  // names for the value.
4492
0
  } else {
4493
0
    alloc.PlanArray<Descriptor>(1);
4494
0
    alloc.PlanArray<std::string>(2);  // names for the descriptor.
4495
0
    if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
4496
0
      alloc.PlanArray<Descriptor::ExtensionRange>(1);
4497
0
    }
4498
0
  }
4499
0
  alloc.FinalizePlanning(tables_);
4500
4501
0
  const std::string::size_type dotpos = placeholder_full_name.find_last_of('.');
4502
0
  if (dotpos != std::string::npos) {
4503
0
    placeholder_package =
4504
0
        alloc.AllocateStrings(placeholder_full_name.substr(0, dotpos));
4505
0
    placeholder_name = placeholder_full_name.substr(dotpos + 1);
4506
0
  } else {
4507
0
    placeholder_package = alloc.AllocateStrings("");
4508
0
    placeholder_name = placeholder_full_name;
4509
0
  }
4510
4511
0
  FileDescriptor* placeholder_file = NewPlaceholderFileWithMutexHeld(
4512
0
      absl::StrCat(placeholder_full_name, ".placeholder.proto"), alloc);
4513
0
  placeholder_file->package_ = placeholder_package;
4514
4515
0
  if (placeholder_type == PLACEHOLDER_ENUM) {
4516
0
    placeholder_file->enum_type_count_ = 1;
4517
0
    placeholder_file->enum_types_ = alloc.AllocateArray<EnumDescriptor>(1);
4518
4519
0
    EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0];
4520
0
    memset(static_cast<void*>(placeholder_enum), 0, sizeof(*placeholder_enum));
4521
4522
0
    placeholder_enum->all_names_ =
4523
0
        alloc.AllocateStrings(placeholder_name, placeholder_full_name);
4524
0
    placeholder_enum->file_ = placeholder_file;
4525
0
    placeholder_enum->options_ = &EnumOptions::default_instance();
4526
0
    placeholder_enum->is_placeholder_ = true;
4527
0
    placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.');
4528
4529
    // Enums must have at least one value.
4530
0
    placeholder_enum->value_count_ = 1;
4531
0
    placeholder_enum->values_ = alloc.AllocateArray<EnumValueDescriptor>(1);
4532
    // Disable fast-path lookup for this enum.
4533
0
    placeholder_enum->sequential_value_limit_ = -1;
4534
4535
0
    EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0];
4536
0
    memset(static_cast<void*>(placeholder_value), 0,
4537
0
           sizeof(*placeholder_value));
4538
4539
    // Note that enum value names are siblings of their type, not children.
4540
0
    placeholder_value->all_names_ = alloc.AllocateStrings(
4541
0
        "PLACEHOLDER_VALUE",
4542
0
        placeholder_package->empty()
4543
0
            ? "PLACEHOLDER_VALUE"
4544
0
            : absl::StrCat(*placeholder_package, ".PLACEHOLDER_VALUE"));
4545
4546
0
    placeholder_value->number_ = 0;
4547
0
    placeholder_value->type_ = placeholder_enum;
4548
0
    placeholder_value->options_ = &EnumValueOptions::default_instance();
4549
4550
0
    return Symbol(placeholder_enum);
4551
0
  } else {
4552
0
    placeholder_file->message_type_count_ = 1;
4553
0
    placeholder_file->message_types_ = alloc.AllocateArray<Descriptor>(1);
4554
4555
0
    Descriptor* placeholder_message = &placeholder_file->message_types_[0];
4556
0
    memset(static_cast<void*>(placeholder_message), 0,
4557
0
           sizeof(*placeholder_message));
4558
4559
0
    placeholder_message->all_names_ =
4560
0
        alloc.AllocateStrings(placeholder_name, placeholder_full_name);
4561
0
    placeholder_message->file_ = placeholder_file;
4562
0
    placeholder_message->options_ = &MessageOptions::default_instance();
4563
0
    placeholder_message->is_placeholder_ = true;
4564
0
    placeholder_message->is_unqualified_placeholder_ = (name[0] != '.');
4565
4566
0
    if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
4567
0
      placeholder_message->extension_range_count_ = 1;
4568
0
      placeholder_message->extension_ranges_ =
4569
0
          alloc.AllocateArray<Descriptor::ExtensionRange>(1);
4570
0
      placeholder_message->extension_ranges_[0].start = 1;
4571
      // kMaxNumber + 1 because ExtensionRange::end is exclusive.
4572
0
      placeholder_message->extension_ranges_[0].end =
4573
0
          FieldDescriptor::kMaxNumber + 1;
4574
0
      placeholder_message->extension_ranges_[0].options_ = nullptr;
4575
0
    }
4576
4577
0
    return Symbol(placeholder_message);
4578
0
  }
4579
0
}
4580
4581
FileDescriptor* DescriptorPool::NewPlaceholderFile(
4582
0
    absl::string_view name) const {
4583
0
  absl::MutexLockMaybe lock(mutex_);
4584
0
  internal::FlatAllocator alloc;
4585
0
  alloc.PlanArray<FileDescriptor>(1);
4586
0
  alloc.PlanArray<std::string>(1);
4587
0
  alloc.FinalizePlanning(tables_);
4588
4589
0
  return NewPlaceholderFileWithMutexHeld(name, alloc);
4590
0
}
4591
4592
FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld(
4593
0
    absl::string_view name, internal::FlatAllocator& alloc) const {
4594
0
  if (mutex_) {
4595
0
    mutex_->AssertHeld();
4596
0
  }
4597
0
  FileDescriptor* placeholder = alloc.AllocateArray<FileDescriptor>(1);
4598
0
  memset(static_cast<void*>(placeholder), 0, sizeof(*placeholder));
4599
4600
0
  placeholder->name_ = alloc.AllocateStrings(name);
4601
0
  placeholder->package_ = &internal::GetEmptyString();
4602
0
  placeholder->pool_ = this;
4603
0
  placeholder->options_ = &FileOptions::default_instance();
4604
0
  placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance();
4605
0
  placeholder->source_code_info_ = &SourceCodeInfo::default_instance();
4606
0
  placeholder->is_placeholder_ = true;
4607
0
  placeholder->syntax_ = FileDescriptor::SYNTAX_UNKNOWN;
4608
0
  placeholder->finished_building_ = true;
4609
  // All other fields are zero or nullptr.
4610
4611
0
  return placeholder;
4612
0
}
4613
4614
bool DescriptorBuilder::AddSymbol(const std::string& full_name,
4615
                                  const void* parent, const std::string& name,
4616
526
                                  const Message& proto, Symbol symbol) {
4617
  // If the caller passed nullptr for the parent, the symbol is at file scope.
4618
  // Use its file as the parent instead.
4619
526
  if (parent == nullptr) parent = file_;
4620
4621
526
  if (absl::StrContains(full_name, '\0')) {
4622
0
    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4623
0
             absl::StrCat("\"", full_name, "\" contains null character."));
4624
0
    return false;
4625
0
  }
4626
526
  if (tables_->AddSymbol(full_name, symbol)) {
4627
526
    if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
4628
      // This is only possible if there was already an error adding something of
4629
      // the same name.
4630
0
      if (!had_errors_) {
4631
0
        ABSL_DLOG(FATAL) << "\"" << full_name
4632
0
                         << "\" not previously defined in "
4633
0
                            "symbols_by_name_, but was defined in "
4634
0
                            "symbols_by_parent_; this shouldn't be possible.";
4635
0
      }
4636
0
      return false;
4637
0
    }
4638
526
    return true;
4639
526
  } else {
4640
0
    const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile();
4641
0
    if (other_file == file_) {
4642
0
      std::string::size_type dot_pos = full_name.find_last_of('.');
4643
0
      if (dot_pos == std::string::npos) {
4644
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4645
0
                 absl::StrCat("\"", full_name, "\" is already defined."));
4646
0
      } else {
4647
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4648
0
                 absl::StrCat("\"", full_name.substr(dot_pos + 1),
4649
0
                              "\" is already defined in \"",
4650
0
                              full_name.substr(0, dot_pos), "\"."));
4651
0
      }
4652
0
    } else {
4653
      // Symbol seems to have been defined in a different file.
4654
0
      AddError(
4655
0
          full_name, proto, DescriptorPool::ErrorCollector::NAME,
4656
0
          absl::StrCat("\"", full_name, "\" is already defined in file \"",
4657
0
                       (other_file == nullptr ? "null" : other_file->name()),
4658
0
                       "\"."));
4659
0
    }
4660
0
    return false;
4661
0
  }
4662
526
}
4663
4664
void DescriptorBuilder::AddPackage(const std::string& name,
4665
10
                                   const Message& proto, FileDescriptor* file) {
4666
10
  if (name.find('\0') != std::string::npos) {
4667
0
    AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
4668
0
             absl::StrCat("\"", name, "\" contains null character."));
4669
0
    return;
4670
0
  }
4671
4672
10
  Symbol existing_symbol = tables_->FindSymbol(name);
4673
  // It's OK to redefine a package.
4674
10
  if (existing_symbol.IsNull()) {
4675
8
    if (name.data() == file->package().data()) {
4676
      // It is the toplevel package name, so insert the descriptor directly.
4677
4
      tables_->AddSymbol(file->package(), Symbol(file));
4678
4
    } else {
4679
4
      auto* package = tables_->Allocate<Symbol::Subpackage>();
4680
      // If the name is the package name, then it is already in the arena.
4681
      // If not, copy it there. It came from the call to AddPackage below.
4682
4
      package->name_size = static_cast<int>(name.size());
4683
4
      package->file = file;
4684
4
      tables_->AddSymbol(name, Symbol(package));
4685
4
    }
4686
    // Also add parent package, if any.
4687
8
    std::string::size_type dot_pos = name.find_last_of('.');
4688
8
    if (dot_pos == std::string::npos) {
4689
      // No parents.
4690
4
      ValidateSymbolName(name, name, proto);
4691
4
    } else {
4692
      // Has parent.
4693
4
      AddPackage(name.substr(0, dot_pos), proto, file);
4694
4
      ValidateSymbolName(name.substr(dot_pos + 1), name, proto);
4695
4
    }
4696
8
  } else if (!existing_symbol.IsPackage()) {
4697
    // Symbol seems to have been defined in a different file.
4698
0
    const FileDescriptor* other_file = existing_symbol.GetFile();
4699
0
    AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
4700
0
             absl::StrCat("\"", name,
4701
0
                          "\" is already defined (as something other than "
4702
0
                          "a package) in file \"",
4703
0
                          (other_file == nullptr ? "null" : other_file->name()),
4704
0
                          "\"."));
4705
0
  }
4706
10
}
4707
4708
void DescriptorBuilder::ValidateSymbolName(const std::string& name,
4709
                                           const std::string& full_name,
4710
534
                                           const Message& proto) {
4711
534
  if (name.empty()) {
4712
0
    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4713
0
             "Missing name.");
4714
534
  } else {
4715
5.92k
    for (char character : name) {
4716
      // I don't trust isalnum() due to locales.  :(
4717
5.92k
      if ((character < 'a' || 'z' < character) &&
4718
5.92k
          (character < 'A' || 'Z' < character) &&
4719
5.92k
          (character < '0' || '9' < character) && (character != '_')) {
4720
0
        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4721
0
                 absl::StrCat("\"", name, "\" is not a valid identifier."));
4722
0
        return;
4723
0
      }
4724
5.92k
    }
4725
534
  }
4726
534
}
4727
4728
// -------------------------------------------------------------------
4729
4730
// This generic implementation is good for all descriptors except
4731
// FileDescriptor.
4732
template <class DescriptorT>
4733
void DescriptorBuilder::AllocateOptions(
4734
    const typename DescriptorT::OptionsType& orig_options,
4735
    DescriptorT* descriptor, int options_field_tag,
4736
12
    absl::string_view option_name, internal::FlatAllocator& alloc) {
4737
12
  std::vector<int> options_path;
4738
12
  descriptor->GetLocationPath(&options_path);
4739
12
  options_path.push_back(options_field_tag);
4740
12
  AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(),
4741
12
                      orig_options, descriptor, options_path, option_name,
4742
12
                      alloc);
4743
12
}
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::Descriptor>(google::protobuf::Descriptor::OptionsType const&, google::protobuf::Descriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::FieldDescriptor>(google::protobuf::FieldDescriptor::OptionsType const&, google::protobuf::FieldDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Line
Count
Source
4736
12
    absl::string_view option_name, internal::FlatAllocator& alloc) {
4737
12
  std::vector<int> options_path;
4738
12
  descriptor->GetLocationPath(&options_path);
4739
12
  options_path.push_back(options_field_tag);
4740
12
  AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(),
4741
12
                      orig_options, descriptor, options_path, option_name,
4742
12
                      alloc);
4743
12
}
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::OneofDescriptor>(google::protobuf::OneofDescriptor::OptionsType const&, google::protobuf::OneofDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::EnumDescriptor>(google::protobuf::EnumDescriptor::OptionsType const&, google::protobuf::EnumDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::EnumValueDescriptor>(google::protobuf::EnumValueDescriptor::OptionsType const&, google::protobuf::EnumValueDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::ServiceDescriptor>(google::protobuf::ServiceDescriptor::OptionsType const&, google::protobuf::ServiceDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptions<google::protobuf::MethodDescriptor>(google::protobuf::MethodDescriptor::OptionsType const&, google::protobuf::MethodDescriptor*, int, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
4744
4745
// We specialize for FileDescriptor.
4746
void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options,
4747
                                        FileDescriptor* descriptor,
4748
4
                                        internal::FlatAllocator& alloc) {
4749
4
  std::vector<int> options_path;
4750
4
  options_path.push_back(FileDescriptorProto::kOptionsFieldNumber);
4751
  // We add the dummy token so that LookupSymbol does the right thing.
4752
4
  AllocateOptionsImpl(absl::StrCat(descriptor->package(), ".dummy"),
4753
4
                      descriptor->name(), orig_options, descriptor,
4754
4
                      options_path, "google.protobuf.FileOptions", alloc);
4755
4
}
4756
4757
template <class DescriptorT>
4758
void DescriptorBuilder::AllocateOptionsImpl(
4759
    absl::string_view name_scope, absl::string_view element_name,
4760
    const typename DescriptorT::OptionsType& orig_options,
4761
    DescriptorT* descriptor, const std::vector<int>& options_path,
4762
16
    absl::string_view option_name, internal::FlatAllocator& alloc) {
4763
16
  auto* options = alloc.AllocateArray<typename DescriptorT::OptionsType>(1);
4764
4765
16
  if (!orig_options.IsInitialized()) {
4766
0
    AddError(absl::StrCat(name_scope, ".", element_name), orig_options,
4767
0
             DescriptorPool::ErrorCollector::OPTION_NAME,
4768
0
             "Uninterpreted option is missing name or value.");
4769
0
    return;
4770
0
  }
4771
4772
  // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti
4773
  // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the
4774
  // reflection based method, which requires the Descriptor. However, we are in
4775
  // the middle of building the descriptors, thus the deadlock.
4776
16
  options->ParseFromString(orig_options.SerializeAsString());
4777
16
  descriptor->options_ = options;
4778
4779
  // Don't add to options_to_interpret_ unless there were uninterpreted
4780
  // options.  This not only avoids unnecessary work, but prevents a
4781
  // bootstrapping problem when building descriptors for descriptor.proto.
4782
  // descriptor.proto does not contain any uninterpreted options, but
4783
  // attempting to interpret options anyway will cause
4784
  // OptionsType::GetDescriptor() to be called which may then deadlock since
4785
  // we're still trying to build it.
4786
16
  if (options->uninterpreted_option_size() > 0) {
4787
0
    options_to_interpret_.push_back(OptionsToInterpret(
4788
0
        name_scope, element_name, options_path, &orig_options, options));
4789
0
  }
4790
4791
  // If the custom option is in unknown fields, no need to interpret it.
4792
  // Remove the dependency file from unused_dependency.
4793
16
  const UnknownFieldSet& unknown_fields = orig_options.unknown_fields();
4794
16
  if (!unknown_fields.empty()) {
4795
    // Can not use options->GetDescriptor() which may case deadlock.
4796
0
    Symbol msg_symbol = tables_->FindSymbol(option_name);
4797
0
    if (msg_symbol.type() == Symbol::MESSAGE) {
4798
0
      for (int i = 0; i < unknown_fields.field_count(); ++i) {
4799
0
        assert_mutex_held(pool_);
4800
0
        const FieldDescriptor* field =
4801
0
            pool_->InternalFindExtensionByNumberNoLock(
4802
0
                msg_symbol.descriptor(), unknown_fields.field(i).number());
4803
0
        if (field) {
4804
0
          unused_dependency_.erase(field->file());
4805
0
        }
4806
0
      }
4807
0
    }
4808
0
  }
4809
16
}
void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::FileDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::FileDescriptor::OptionsType const&, google::protobuf::FileDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Line
Count
Source
4762
4
    absl::string_view option_name, internal::FlatAllocator& alloc) {
4763
4
  auto* options = alloc.AllocateArray<typename DescriptorT::OptionsType>(1);
4764
4765
4
  if (!orig_options.IsInitialized()) {
4766
0
    AddError(absl::StrCat(name_scope, ".", element_name), orig_options,
4767
0
             DescriptorPool::ErrorCollector::OPTION_NAME,
4768
0
             "Uninterpreted option is missing name or value.");
4769
0
    return;
4770
0
  }
4771
4772
  // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti
4773
  // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the
4774
  // reflection based method, which requires the Descriptor. However, we are in
4775
  // the middle of building the descriptors, thus the deadlock.
4776
4
  options->ParseFromString(orig_options.SerializeAsString());
4777
4
  descriptor->options_ = options;
4778
4779
  // Don't add to options_to_interpret_ unless there were uninterpreted
4780
  // options.  This not only avoids unnecessary work, but prevents a
4781
  // bootstrapping problem when building descriptors for descriptor.proto.
4782
  // descriptor.proto does not contain any uninterpreted options, but
4783
  // attempting to interpret options anyway will cause
4784
  // OptionsType::GetDescriptor() to be called which may then deadlock since
4785
  // we're still trying to build it.
4786
4
  if (options->uninterpreted_option_size() > 0) {
4787
0
    options_to_interpret_.push_back(OptionsToInterpret(
4788
0
        name_scope, element_name, options_path, &orig_options, options));
4789
0
  }
4790
4791
  // If the custom option is in unknown fields, no need to interpret it.
4792
  // Remove the dependency file from unused_dependency.
4793
4
  const UnknownFieldSet& unknown_fields = orig_options.unknown_fields();
4794
4
  if (!unknown_fields.empty()) {
4795
    // Can not use options->GetDescriptor() which may case deadlock.
4796
0
    Symbol msg_symbol = tables_->FindSymbol(option_name);
4797
0
    if (msg_symbol.type() == Symbol::MESSAGE) {
4798
0
      for (int i = 0; i < unknown_fields.field_count(); ++i) {
4799
0
        assert_mutex_held(pool_);
4800
0
        const FieldDescriptor* field =
4801
0
            pool_->InternalFindExtensionByNumberNoLock(
4802
0
                msg_symbol.descriptor(), unknown_fields.field(i).number());
4803
0
        if (field) {
4804
0
          unused_dependency_.erase(field->file());
4805
0
        }
4806
0
      }
4807
0
    }
4808
0
  }
4809
4
}
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::Descriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::Descriptor::OptionsType const&, google::protobuf::Descriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::FieldDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::FieldDescriptor::OptionsType const&, google::protobuf::FieldDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Line
Count
Source
4762
12
    absl::string_view option_name, internal::FlatAllocator& alloc) {
4763
12
  auto* options = alloc.AllocateArray<typename DescriptorT::OptionsType>(1);
4764
4765
12
  if (!orig_options.IsInitialized()) {
4766
0
    AddError(absl::StrCat(name_scope, ".", element_name), orig_options,
4767
0
             DescriptorPool::ErrorCollector::OPTION_NAME,
4768
0
             "Uninterpreted option is missing name or value.");
4769
0
    return;
4770
0
  }
4771
4772
  // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti
4773
  // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the
4774
  // reflection based method, which requires the Descriptor. However, we are in
4775
  // the middle of building the descriptors, thus the deadlock.
4776
12
  options->ParseFromString(orig_options.SerializeAsString());
4777
12
  descriptor->options_ = options;
4778
4779
  // Don't add to options_to_interpret_ unless there were uninterpreted
4780
  // options.  This not only avoids unnecessary work, but prevents a
4781
  // bootstrapping problem when building descriptors for descriptor.proto.
4782
  // descriptor.proto does not contain any uninterpreted options, but
4783
  // attempting to interpret options anyway will cause
4784
  // OptionsType::GetDescriptor() to be called which may then deadlock since
4785
  // we're still trying to build it.
4786
12
  if (options->uninterpreted_option_size() > 0) {
4787
0
    options_to_interpret_.push_back(OptionsToInterpret(
4788
0
        name_scope, element_name, options_path, &orig_options, options));
4789
0
  }
4790
4791
  // If the custom option is in unknown fields, no need to interpret it.
4792
  // Remove the dependency file from unused_dependency.
4793
12
  const UnknownFieldSet& unknown_fields = orig_options.unknown_fields();
4794
12
  if (!unknown_fields.empty()) {
4795
    // Can not use options->GetDescriptor() which may case deadlock.
4796
0
    Symbol msg_symbol = tables_->FindSymbol(option_name);
4797
0
    if (msg_symbol.type() == Symbol::MESSAGE) {
4798
0
      for (int i = 0; i < unknown_fields.field_count(); ++i) {
4799
0
        assert_mutex_held(pool_);
4800
0
        const FieldDescriptor* field =
4801
0
            pool_->InternalFindExtensionByNumberNoLock(
4802
0
                msg_symbol.descriptor(), unknown_fields.field(i).number());
4803
0
        if (field) {
4804
0
          unused_dependency_.erase(field->file());
4805
0
        }
4806
0
      }
4807
0
    }
4808
0
  }
4809
12
}
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::Descriptor::ExtensionRange>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::Descriptor::ExtensionRange::OptionsType const&, google::protobuf::Descriptor::ExtensionRange*, std::__1::vector<int, std::__1::allocator<int> > const&, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::OneofDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::OneofDescriptor::OptionsType const&, google::protobuf::OneofDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::EnumDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::EnumDescriptor::OptionsType const&, google::protobuf::EnumDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::EnumValueDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::EnumValueDescriptor::OptionsType const&, google::protobuf::EnumValueDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::ServiceDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::ServiceDescriptor::OptionsType const&, google::protobuf::ServiceDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
Unexecuted instantiation: void google::protobuf::DescriptorBuilder::AllocateOptionsImpl<google::protobuf::MethodDescriptor>(absl::lts_20230125::string_view, absl::lts_20230125::string_view, google::protobuf::MethodDescriptor::OptionsType const&, google::protobuf::MethodDescriptor*, std::__1::vector<int, std::__1::allocator<int> > const&, absl::lts_20230125::string_view, google::protobuf::internal::FlatAllocator&)
4810
4811
// A common pattern:  We want to convert a repeated field in the descriptor
4812
// to an array of values, calling some method to build each value.
4813
#define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT)               \
4814
592
  OUTPUT->NAME##_count_ = INPUT.NAME##_size();                         \
4815
592
  OUTPUT->NAME##s_ = alloc.AllocateArray<                              \
4816
592
      typename std::remove_pointer<decltype(OUTPUT->NAME##s_)>::type>( \
4817
592
      INPUT.NAME##_size());                                            \
4818
1.15k
  for (int i = 0; i < INPUT.NAME##_size(); i++) {                      \
4819
560
    METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i, alloc);        \
4820
560
  }
4821
4822
PROTOBUF_NOINLINE void DescriptorBuilder::AddRecursiveImportError(
4823
0
    const FileDescriptorProto& proto, int from_here) {
4824
0
  std::string error_message("File recursively imports itself: ");
4825
0
  for (size_t i = from_here; i < tables_->pending_files_.size(); i++) {
4826
0
    error_message.append(tables_->pending_files_[i]);
4827
0
    error_message.append(" -> ");
4828
0
  }
4829
0
  error_message.append(proto.name());
4830
4831
0
  if (static_cast<size_t>(from_here) < tables_->pending_files_.size() - 1) {
4832
0
    AddError(tables_->pending_files_[from_here + 1], proto,
4833
0
             DescriptorPool::ErrorCollector::IMPORT, error_message);
4834
0
  } else {
4835
0
    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::IMPORT,
4836
0
             error_message);
4837
0
  }
4838
0
}
4839
4840
void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto,
4841
0
                                            int index) {
4842
0
  AddError(proto.dependency(index), proto,
4843
0
           DescriptorPool::ErrorCollector::IMPORT,
4844
0
           absl::StrCat("Import \"", proto.dependency(index),
4845
0
                        "\" was listed twice."));
4846
0
}
4847
4848
void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto,
4849
0
                                       int index) {
4850
0
  std::string message;
4851
0
  if (pool_->fallback_database_ == nullptr) {
4852
0
    message = absl::StrCat("Import \"", proto.dependency(index),
4853
0
                           "\" has not been loaded.");
4854
0
  } else {
4855
0
    message = absl::StrCat("Import \"", proto.dependency(index),
4856
0
                           "\" was not found or had errors.");
4857
0
  }
4858
0
  AddError(proto.dependency(index), proto,
4859
0
           DescriptorPool::ErrorCollector::IMPORT, message);
4860
0
}
4861
4862
PROTOBUF_NOINLINE static bool ExistingFileMatchesProto(
4863
0
    const FileDescriptor* existing_file, const FileDescriptorProto& proto) {
4864
0
  FileDescriptorProto existing_proto;
4865
0
  existing_file->CopyTo(&existing_proto);
4866
  // TODO(liujisi): Remove it when CopyTo supports copying syntax params when
4867
  // syntax="proto2".
4868
0
  if (existing_file->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
4869
0
      proto.has_syntax()) {
4870
0
    existing_proto.set_syntax(
4871
0
        existing_file->SyntaxName(existing_file->syntax()));
4872
0
  }
4873
4874
0
  return existing_proto.SerializeAsString() == proto.SerializeAsString();
4875
0
}
4876
4877
// These PlanAllocationSize functions will gather into the FlatAllocator all the
4878
// necessary memory allocations that BuildXXX functions below will do on the
4879
// Tables object.
4880
// They *must* be kept in sync. If we miss some PlanArray call we won't have
4881
// enough memory and will ABSL_CHECK-fail.
4882
static void PlanAllocationSize(
4883
    const RepeatedPtrField<EnumValueDescriptorProto>& values,
4884
18
    internal::FlatAllocator& alloc) {
4885
18
  alloc.PlanArray<EnumValueDescriptor>(values.size());
4886
18
  alloc.PlanArray<std::string>(2 * values.size());  // name + full_name
4887
98
  for (const auto& v : values) {
4888
98
    if (v.has_options()) alloc.PlanArray<EnumValueOptions>(1);
4889
98
  }
4890
18
}
4891
4892
static void PlanAllocationSize(
4893
    const RepeatedPtrField<EnumDescriptorProto>& enums,
4894
82
    internal::FlatAllocator& alloc) {
4895
82
  alloc.PlanArray<EnumDescriptor>(enums.size());
4896
82
  alloc.PlanArray<std::string>(2 * enums.size());  // name + full_name
4897
82
  for (const auto& e : enums) {
4898
18
    if (e.has_options()) alloc.PlanArray<EnumOptions>(1);
4899
18
    PlanAllocationSize(e.value(), alloc);
4900
18
    alloc.PlanArray<EnumDescriptor::ReservedRange>(e.reserved_range_size());
4901
18
    alloc.PlanArray<const std::string*>(e.reserved_name_size());
4902
18
    alloc.PlanArray<std::string>(e.reserved_name_size());
4903
18
  }
4904
82
}
4905
4906
static void PlanAllocationSize(
4907
    const RepeatedPtrField<OneofDescriptorProto>& oneofs,
4908
76
    internal::FlatAllocator& alloc) {
4909
76
  alloc.PlanArray<OneofDescriptor>(oneofs.size());
4910
76
  alloc.PlanArray<std::string>(2 * oneofs.size());  // name + full_name
4911
76
  for (const auto& oneof : oneofs) {
4912
4
    if (oneof.has_options()) alloc.PlanArray<OneofOptions>(1);
4913
4
  }
4914
76
}
4915
4916
static void PlanAllocationSize(
4917
    const RepeatedPtrField<FieldDescriptorProto>& fields,
4918
158
    internal::FlatAllocator& alloc) {
4919
158
  alloc.PlanArray<FieldDescriptor>(fields.size());
4920
330
  for (const auto& field : fields) {
4921
330
    if (field.has_options()) alloc.PlanArray<FieldOptions>(1);
4922
330
    alloc.PlanFieldNames(field.name(),
4923
330
                         field.has_json_name() ? &field.json_name() : nullptr);
4924
330
    if (field.has_default_value() && field.has_type() &&
4925
330
        (field.type() == FieldDescriptorProto::TYPE_STRING ||
4926
52
         field.type() == FieldDescriptorProto::TYPE_BYTES)) {
4927
      // For the default string value.
4928
0
      alloc.PlanArray<std::string>(1);
4929
0
    }
4930
330
  }
4931
158
}
4932
4933
static void PlanAllocationSize(
4934
    const RepeatedPtrField<DescriptorProto::ExtensionRange>& ranges,
4935
76
    internal::FlatAllocator& alloc) {
4936
76
  alloc.PlanArray<Descriptor::ExtensionRange>(ranges.size());
4937
76
  for (const auto& r : ranges) {
4938
18
    if (r.has_options()) alloc.PlanArray<ExtensionRangeOptions>(1);
4939
18
  }
4940
76
}
4941
4942
static void PlanAllocationSize(
4943
    const RepeatedPtrField<DescriptorProto>& messages,
4944
82
    internal::FlatAllocator& alloc) {
4945
82
  alloc.PlanArray<Descriptor>(messages.size());
4946
82
  alloc.PlanArray<std::string>(2 * messages.size());  // name + full_name
4947
4948
82
  for (const auto& message : messages) {
4949
76
    if (message.has_options()) alloc.PlanArray<MessageOptions>(1);
4950
76
    PlanAllocationSize(message.nested_type(), alloc);
4951
76
    PlanAllocationSize(message.field(), alloc);
4952
76
    PlanAllocationSize(message.extension(), alloc);
4953
76
    PlanAllocationSize(message.extension_range(), alloc);
4954
76
    alloc.PlanArray<Descriptor::ReservedRange>(message.reserved_range_size());
4955
76
    alloc.PlanArray<const std::string*>(message.reserved_name_size());
4956
76
    alloc.PlanArray<std::string>(message.reserved_name_size());
4957
76
    PlanAllocationSize(message.enum_type(), alloc);
4958
76
    PlanAllocationSize(message.oneof_decl(), alloc);
4959
76
  }
4960
82
}
4961
4962
static void PlanAllocationSize(
4963
    const RepeatedPtrField<MethodDescriptorProto>& methods,
4964
0
    internal::FlatAllocator& alloc) {
4965
0
  alloc.PlanArray<MethodDescriptor>(methods.size());
4966
0
  alloc.PlanArray<std::string>(2 * methods.size());  // name + full_name
4967
0
  for (const auto& m : methods) {
4968
0
    if (m.has_options()) alloc.PlanArray<MethodOptions>(1);
4969
0
  }
4970
0
}
4971
4972
static void PlanAllocationSize(
4973
    const RepeatedPtrField<ServiceDescriptorProto>& services,
4974
6
    internal::FlatAllocator& alloc) {
4975
6
  alloc.PlanArray<ServiceDescriptor>(services.size());
4976
6
  alloc.PlanArray<std::string>(2 * services.size());  // name + full_name
4977
6
  for (const auto& service : services) {
4978
0
    if (service.has_options()) alloc.PlanArray<ServiceOptions>(1);
4979
0
    PlanAllocationSize(service.method(), alloc);
4980
0
  }
4981
6
}
4982
4983
static void PlanAllocationSize(const FileDescriptorProto& proto,
4984
6
                               internal::FlatAllocator& alloc) {
4985
6
  alloc.PlanArray<FileDescriptor>(1);
4986
6
  alloc.PlanArray<FileDescriptorTables>(1);
4987
6
  alloc.PlanArray<std::string>(2
4988
6
  );  // name + package
4989
6
  if (proto.has_options()) alloc.PlanArray<FileOptions>(1);
4990
6
  if (proto.has_source_code_info()) alloc.PlanArray<SourceCodeInfo>(1);
4991
4992
6
  PlanAllocationSize(proto.service(), alloc);
4993
6
  PlanAllocationSize(proto.message_type(), alloc);
4994
6
  PlanAllocationSize(proto.enum_type(), alloc);
4995
6
  PlanAllocationSize(proto.extension(), alloc);
4996
4997
6
  alloc.PlanArray<int>(proto.weak_dependency_size());
4998
6
  alloc.PlanArray<int>(proto.public_dependency_size());
4999
6
  alloc.PlanArray<const FileDescriptor*>(proto.dependency_size());
5000
6
}
5001
5002
const FileDescriptor* DescriptorBuilder::BuildFile(
5003
6
    const FileDescriptorProto& proto) {
5004
6
  filename_ = proto.name();
5005
5006
  // Check if the file already exists and is identical to the one being built.
5007
  // Note:  This only works if the input is canonical -- that is, it
5008
  //   fully-qualifies all type names, has no UninterpretedOptions, etc.
5009
  //   This is fine, because this idempotency "feature" really only exists to
5010
  //   accommodate one hack in the proto1->proto2 migration layer.
5011
6
  const FileDescriptor* existing_file = tables_->FindFile(filename_);
5012
6
  if (existing_file != nullptr) {
5013
    // File already in pool.  Compare the existing one to the input.
5014
0
    if (ExistingFileMatchesProto(existing_file, proto)) {
5015
      // They're identical.  Return the existing descriptor.
5016
0
      return existing_file;
5017
0
    }
5018
5019
    // Not a match.  The error will be detected and handled later.
5020
0
  }
5021
5022
  // Check to see if this file is already on the pending files list.
5023
  // TODO(kenton):  Allow recursive imports?  It may not work with some
5024
  //   (most?) programming languages.  E.g., in C++, a forward declaration
5025
  //   of a type is not sufficient to allow it to be used even in a
5026
  //   generated header file due to inlining.  This could perhaps be
5027
  //   worked around using tricks involving inserting #include statements
5028
  //   mid-file, but that's pretty ugly, and I'm pretty sure there are
5029
  //   some languages out there that do not allow recursive dependencies
5030
  //   at all.
5031
6
  for (size_t i = 0; i < tables_->pending_files_.size(); i++) {
5032
0
    if (tables_->pending_files_[i] == proto.name()) {
5033
0
      AddRecursiveImportError(proto, i);
5034
0
      return nullptr;
5035
0
    }
5036
0
  }
5037
5038
6
  static const int kMaximumPackageLength = 511;
5039
6
  if (proto.package().size() > kMaximumPackageLength) {
5040
0
    AddError(proto.package(), proto, DescriptorPool::ErrorCollector::NAME,
5041
0
             "Package name is too long");
5042
0
    return nullptr;
5043
0
  }
5044
5045
  // If we have a fallback_database_, and we aren't doing lazy import building,
5046
  // attempt to load all dependencies now, before checkpointing tables_.  This
5047
  // avoids confusion with recursive checkpoints.
5048
6
  if (!pool_->lazily_build_dependencies_) {
5049
0
    if (pool_->fallback_database_ != nullptr) {
5050
0
      tables_->pending_files_.push_back(proto.name());
5051
0
      for (int i = 0; i < proto.dependency_size(); i++) {
5052
0
        if (tables_->FindFile(proto.dependency(i)) == nullptr &&
5053
0
            (pool_->underlay_ == nullptr ||
5054
0
             pool_->underlay_->FindFileByName(proto.dependency(i)) ==
5055
0
                 nullptr)) {
5056
          // We don't care what this returns since we'll find out below anyway.
5057
0
          pool_->TryFindFileInFallbackDatabase(proto.dependency(i));
5058
0
        }
5059
0
      }
5060
0
      tables_->pending_files_.pop_back();
5061
0
    }
5062
0
  }
5063
5064
  // Checkpoint the tables so that we can roll back if something goes wrong.
5065
6
  tables_->AddCheckpoint();
5066
5067
6
  auto alloc = absl::make_unique<internal::FlatAllocator>();
5068
6
  PlanAllocationSize(proto, *alloc);
5069
6
  alloc->FinalizePlanning(tables_);
5070
6
  FileDescriptor* result = BuildFileImpl(proto, *alloc);
5071
5072
6
  file_tables_->FinalizeTables();
5073
6
  if (result) {
5074
6
    tables_->ClearLastCheckpoint();
5075
6
    result->finished_building_ = true;
5076
6
    alloc->ExpectConsumed();
5077
6
  } else {
5078
0
    tables_->RollbackToLastCheckpoint();
5079
0
  }
5080
5081
6
  return result;
5082
6
}
5083
5084
FileDescriptor* DescriptorBuilder::BuildFileImpl(
5085
6
    const FileDescriptorProto& proto, internal::FlatAllocator& alloc) {
5086
6
  FileDescriptor* result = alloc.AllocateArray<FileDescriptor>(1);
5087
6
  file_ = result;
5088
5089
6
  result->is_placeholder_ = false;
5090
6
  result->finished_building_ = false;
5091
6
  SourceCodeInfo* info = nullptr;
5092
6
  if (proto.has_source_code_info()) {
5093
0
    info = alloc.AllocateArray<SourceCodeInfo>(1);
5094
0
    info->CopyFrom(proto.source_code_info());
5095
0
    result->source_code_info_ = info;
5096
6
  } else {
5097
6
    result->source_code_info_ = &SourceCodeInfo::default_instance();
5098
6
  }
5099
5100
6
  file_tables_ = alloc.AllocateArray<FileDescriptorTables>(1);
5101
6
  file_->tables_ = file_tables_;
5102
5103
6
  if (!proto.has_name()) {
5104
0
    AddError("", proto, DescriptorPool::ErrorCollector::OTHER,
5105
0
             "Missing field: FileDescriptorProto.name.");
5106
0
  }
5107
5108
  // TODO(liujisi): Report error when the syntax is empty after all the protos
5109
  // have added the syntax statement.
5110
6
  if (proto.syntax().empty() || proto.syntax() == "proto2") {
5111
4
    file_->syntax_ = FileDescriptor::SYNTAX_PROTO2;
5112
4
  } else if (proto.syntax() == "proto3") {
5113
2
    file_->syntax_ = FileDescriptor::SYNTAX_PROTO3;
5114
2
  } else {
5115
0
    file_->syntax_ = FileDescriptor::SYNTAX_UNKNOWN;
5116
0
    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
5117
0
             absl::StrCat("Unrecognized syntax: ", proto.syntax()));
5118
0
  }
5119
5120
6
  result->name_ = alloc.AllocateStrings(proto.name());
5121
6
  if (proto.has_package()) {
5122
6
    result->package_ = alloc.AllocateStrings(proto.package());
5123
6
  } else {
5124
    // We cannot rely on proto.package() returning a valid string if
5125
    // proto.has_package() is false, because we might be running at static
5126
    // initialization time, in which case default values have not yet been
5127
    // initialized.
5128
0
    result->package_ = alloc.AllocateStrings("");
5129
0
  }
5130
6
  result->pool_ = pool_;
5131
5132
6
  if (result->name().find('\0') != std::string::npos) {
5133
0
    AddError(result->name(), proto, DescriptorPool::ErrorCollector::NAME,
5134
0
             absl::StrCat("\"", result->name(), "\" contains null character."));
5135
0
    return nullptr;
5136
0
  }
5137
5138
  // Add to tables.
5139
6
  if (!tables_->AddFile(result)) {
5140
0
    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
5141
0
             "A file with this name is already in the pool.");
5142
    // Bail out early so that if this is actually the exact same file, we
5143
    // don't end up reporting that every single symbol is already defined.
5144
0
    return nullptr;
5145
0
  }
5146
6
  if (!result->package().empty()) {
5147
6
    if (std::count(result->package().begin(), result->package().end(), '.') >
5148
6
        kPackageLimit) {
5149
0
      AddError(result->package(), proto, DescriptorPool::ErrorCollector::NAME,
5150
0
               "Exceeds Maximum Package Depth");
5151
0
      return nullptr;
5152
0
    }
5153
6
    AddPackage(result->package(), proto, result);
5154
6
  }
5155
5156
  // Make sure all dependencies are loaded.
5157
6
  absl::flat_hash_set<absl::string_view> seen_dependencies;
5158
6
  result->dependency_count_ = proto.dependency_size();
5159
6
  result->dependencies_ =
5160
6
      alloc.AllocateArray<const FileDescriptor*>(proto.dependency_size());
5161
6
  result->dependencies_once_ = nullptr;
5162
6
  unused_dependency_.clear();
5163
6
  absl::flat_hash_set<int> weak_deps;
5164
6
  for (int i = 0; i < proto.weak_dependency_size(); ++i) {
5165
0
    weak_deps.insert(proto.weak_dependency(i));
5166
0
  }
5167
5168
6
  bool need_lazy_deps = false;
5169
6
  for (int i = 0; i < proto.dependency_size(); i++) {
5170
0
    if (!seen_dependencies.insert(proto.dependency(i)).second) {
5171
0
      AddTwiceListedError(proto, i);
5172
0
    }
5173
5174
0
    const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
5175
0
    if (dependency == nullptr && pool_->underlay_ != nullptr) {
5176
0
      dependency = pool_->underlay_->FindFileByName(proto.dependency(i));
5177
0
    }
5178
5179
0
    if (dependency == result) {
5180
      // Recursive import.  dependency/result is not fully initialized, and it's
5181
      // dangerous to try to do anything with it.  The recursive import error
5182
      // will be detected and reported in DescriptorBuilder::BuildFile().
5183
0
      return nullptr;
5184
0
    }
5185
5186
0
    if (dependency == nullptr) {
5187
0
      if (!pool_->lazily_build_dependencies_) {
5188
0
        if (pool_->allow_unknown_ ||
5189
0
            (!pool_->enforce_weak_ && weak_deps.contains(i))) {
5190
0
          internal::FlatAllocator lazy_dep_alloc;
5191
0
          lazy_dep_alloc.PlanArray<FileDescriptor>(1);
5192
0
          lazy_dep_alloc.PlanArray<std::string>(1);
5193
0
          lazy_dep_alloc.FinalizePlanning(tables_);
5194
0
          dependency = pool_->NewPlaceholderFileWithMutexHeld(
5195
0
              proto.dependency(i), lazy_dep_alloc);
5196
0
        } else {
5197
0
          AddImportError(proto, i);
5198
0
        }
5199
0
      }
5200
0
    } else {
5201
      // Add to unused_dependency_ to track unused imported files.
5202
      // Note: do not track unused imported files for public import.
5203
0
      if (pool_->enforce_dependencies_ &&
5204
0
          (pool_->unused_import_track_files_.find(proto.name()) !=
5205
0
           pool_->unused_import_track_files_.end()) &&
5206
0
          (dependency->public_dependency_count() == 0)) {
5207
0
        unused_dependency_.insert(dependency);
5208
0
      }
5209
0
    }
5210
5211
0
    result->dependencies_[i] = dependency;
5212
0
    if (pool_->lazily_build_dependencies_ && !dependency) {
5213
0
      need_lazy_deps = true;
5214
0
    }
5215
0
  }
5216
6
  if (need_lazy_deps) {
5217
0
    int total_char_size = 0;
5218
0
    for (int i = 0; i < proto.dependency_size(); i++) {
5219
0
      if (result->dependencies_[i] == nullptr) {
5220
0
        total_char_size += static_cast<int>(proto.dependency(i).size());
5221
0
      }
5222
0
      ++total_char_size;  // For NUL char
5223
0
    }
5224
5225
0
    void* data = tables_->AllocateBytes(
5226
0
        static_cast<int>(sizeof(absl::once_flag)) + total_char_size);
5227
0
    result->dependencies_once_ = ::new (data) absl::once_flag{};
5228
0
    char* name_data = reinterpret_cast<char*>(result->dependencies_once_ + 1);
5229
5230
0
    for (int i = 0; i < proto.dependency_size(); i++) {
5231
0
      if (result->dependencies_[i] == nullptr) {
5232
0
        memcpy(name_data, proto.dependency(i).c_str(),
5233
0
               proto.dependency(i).size());
5234
0
        name_data += proto.dependency(i).size();
5235
0
      }
5236
0
      *name_data++ = '\0';
5237
0
    }
5238
0
  }
5239
5240
  // Check public dependencies.
5241
6
  int public_dependency_count = 0;
5242
6
  result->public_dependencies_ =
5243
6
      alloc.AllocateArray<int>(proto.public_dependency_size());
5244
6
  for (int i = 0; i < proto.public_dependency_size(); i++) {
5245
    // Only put valid public dependency indexes.
5246
0
    int index = proto.public_dependency(i);
5247
0
    if (index >= 0 && index < proto.dependency_size()) {
5248
0
      result->public_dependencies_[public_dependency_count++] = index;
5249
      // Do not track unused imported files for public import.
5250
      // Calling dependency(i) builds that file when doing lazy imports,
5251
      // need to avoid doing this. Unused dependency detection isn't done
5252
      // when building lazily, anyways.
5253
0
      if (!pool_->lazily_build_dependencies_) {
5254
0
        unused_dependency_.erase(result->dependency(index));
5255
0
      }
5256
0
    } else {
5257
0
      AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
5258
0
               "Invalid public dependency index.");
5259
0
    }
5260
0
  }
5261
6
  result->public_dependency_count_ = public_dependency_count;
5262
5263
  // Build dependency set
5264
6
  dependencies_.clear();
5265
  // We don't/can't do proper dependency error checking when
5266
  // lazily_build_dependencies_, and calling dependency(i) will force
5267
  // a dependency to be built, which we don't want.
5268
6
  if (!pool_->lazily_build_dependencies_) {
5269
0
    for (int i = 0; i < result->dependency_count(); i++) {
5270
0
      RecordPublicDependencies(result->dependency(i));
5271
0
    }
5272
0
  }
5273
5274
  // Check weak dependencies.
5275
6
  int weak_dependency_count = 0;
5276
6
  result->weak_dependencies_ =
5277
6
      alloc.AllocateArray<int>(proto.weak_dependency_size());
5278
6
  for (int i = 0; i < proto.weak_dependency_size(); i++) {
5279
0
    int index = proto.weak_dependency(i);
5280
0
    if (index >= 0 && index < proto.dependency_size()) {
5281
0
      result->weak_dependencies_[weak_dependency_count++] = index;
5282
0
    } else {
5283
0
      AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
5284
0
               "Invalid weak dependency index.");
5285
0
    }
5286
0
  }
5287
6
  result->weak_dependency_count_ = weak_dependency_count;
5288
5289
  // Convert children.
5290
6
  BUILD_ARRAY(proto, result, message_type, BuildMessage, nullptr);
5291
6
  BUILD_ARRAY(proto, result, enum_type, BuildEnum, nullptr);
5292
6
  BUILD_ARRAY(proto, result, service, BuildService, nullptr);
5293
6
  BUILD_ARRAY(proto, result, extension, BuildExtension, nullptr);
5294
5295
  // Copy options.
5296
6
  result->options_ = nullptr;  // Set to default_instance later if necessary.
5297
6
  if (proto.has_options()) {
5298
4
    AllocateOptions(proto.options(), result, alloc);
5299
4
  }
5300
5301
  // Note that the following steps must occur in exactly the specified order.
5302
5303
  // Cross-link.
5304
6
  CrossLinkFile(result, proto);
5305
5306
6
  if (!message_hints_.empty()) {
5307
0
    SuggestFieldNumbers(result, proto);
5308
0
  }
5309
5310
  // Interpret any remaining uninterpreted options gathered into
5311
  // options_to_interpret_ during descriptor building.  Cross-linking has made
5312
  // extension options known, so all interpretations should now succeed.
5313
6
  if (!had_errors_) {
5314
6
    OptionInterpreter option_interpreter(this);
5315
6
    for (std::vector<OptionsToInterpret>::iterator iter =
5316
6
             options_to_interpret_.begin();
5317
6
         iter != options_to_interpret_.end(); ++iter) {
5318
0
      option_interpreter.InterpretOptions(&(*iter));
5319
0
    }
5320
6
    options_to_interpret_.clear();
5321
6
    if (info != nullptr) {
5322
0
      option_interpreter.UpdateSourceCodeInfo(info);
5323
0
    }
5324
6
  }
5325
5326
  // Validate options. See comments at InternalSetLazilyBuildDependencies about
5327
  // error checking and lazy import building.
5328
6
  if (!had_errors_ && !pool_->lazily_build_dependencies_) {
5329
0
    ValidateFileOptions(result, proto);
5330
0
  }
5331
5332
  // Additional naming conflict check for map entry types. Only need to check
5333
  // this if there are already errors.
5334
6
  if (had_errors_) {
5335
0
    for (int i = 0; i < proto.message_type_size(); ++i) {
5336
0
      DetectMapConflicts(result->message_type(i), proto.message_type(i));
5337
0
    }
5338
0
  }
5339
5340
5341
  // Again, see comments at InternalSetLazilyBuildDependencies about error
5342
  // checking. Also, don't log unused dependencies if there were previous
5343
  // errors, since the results might be inaccurate.
5344
6
  if (!had_errors_ && !unused_dependency_.empty() &&
5345
6
      !pool_->lazily_build_dependencies_) {
5346
0
    LogUnusedDependency(proto, result);
5347
0
  }
5348
5349
6
  if (had_errors_) {
5350
0
    return nullptr;
5351
6
  } else {
5352
6
    return result;
5353
6
  }
5354
6
}
5355
5356
5357
const std::string* DescriptorBuilder::AllocateNameStrings(
5358
    const std::string& scope, const std::string& proto_name,
5359
98
    internal::FlatAllocator& alloc) {
5360
98
  if (scope.empty()) {
5361
0
    return alloc.AllocateStrings(proto_name, proto_name);
5362
98
  } else {
5363
98
    return alloc.AllocateStrings(proto_name,
5364
98
                                 absl::StrCat(scope, ".", proto_name));
5365
98
  }
5366
98
}
5367
5368
namespace {
5369
5370
// Helper for BuildMessage below.
5371
struct IncrementWhenDestroyed {
5372
76
  ~IncrementWhenDestroyed() { ++to_increment; }
5373
  int& to_increment;
5374
};
5375
5376
}  // namespace
5377
5378
void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
5379
                                     const Descriptor* parent,
5380
                                     Descriptor* result,
5381
76
                                     internal::FlatAllocator& alloc) {
5382
76
  const std::string& scope =
5383
76
      (parent == nullptr) ? file_->package() : parent->full_name();
5384
76
  result->all_names_ = AllocateNameStrings(scope, proto.name(), alloc);
5385
76
  ValidateSymbolName(proto.name(), result->full_name(), proto);
5386
5387
76
  result->file_ = file_;
5388
76
  result->containing_type_ = parent;
5389
76
  result->is_placeholder_ = false;
5390
76
  result->is_unqualified_placeholder_ = false;
5391
76
  result->well_known_type_ = Descriptor::WELLKNOWNTYPE_UNSPECIFIED;
5392
76
  result->options_ = nullptr;  // Set to default_instance later if necessary.
5393
5394
76
  auto it = pool_->tables_->well_known_types_.find(result->full_name());
5395
76
  if (it != pool_->tables_->well_known_types_.end()) {
5396
2
    result->well_known_type_ = it->second;
5397
2
  }
5398
5399
  // Calculate the continuous sequence of fields.
5400
  // These can be fast-path'd during lookup and don't need to be added to the
5401
  // tables.
5402
  // We use uint16_t to save space for sequential_field_limit_, so stop before
5403
  // overflowing it. Worst case, we are not taking full advantage on huge
5404
  // messages, but it is unlikely.
5405
76
  result->sequential_field_limit_ = 0;
5406
246
  for (int i = 0; i < std::numeric_limits<uint16_t>::max() &&
5407
246
                  i < proto.field_size() && proto.field(i).number() == i + 1;
5408
170
       ++i) {
5409
170
    result->sequential_field_limit_ = i + 1;
5410
170
  }
5411
5412
  // Build oneofs first so that fields and extension ranges can refer to them.
5413
76
  BUILD_ARRAY(proto, result, oneof_decl, BuildOneof, result);
5414
76
  BUILD_ARRAY(proto, result, field, BuildField, result);
5415
76
  BUILD_ARRAY(proto, result, enum_type, BuildEnum, result);
5416
76
  BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result);
5417
76
  BUILD_ARRAY(proto, result, extension, BuildExtension, result);
5418
76
  BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);
5419
5420
  // Before building submessages, check recursion limit.
5421
76
  --recursion_depth_;
5422
76
  IncrementWhenDestroyed revert{recursion_depth_};
5423
76
  if (recursion_depth_ <= 0) {
5424
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::OTHER,
5425
0
             "Reached maximum recursion limit for nested messages.");
5426
0
    result->nested_types_ = nullptr;
5427
0
    result->nested_type_count_ = 0;
5428
0
    return;
5429
0
  }
5430
76
  BUILD_ARRAY(proto, result, nested_type, BuildMessage, result);
5431
5432
  // Copy reserved names.
5433
76
  int reserved_name_count = proto.reserved_name_size();
5434
76
  result->reserved_name_count_ = reserved_name_count;
5435
76
  result->reserved_names_ =
5436
76
      alloc.AllocateArray<const std::string*>(reserved_name_count);
5437
76
  for (int i = 0; i < reserved_name_count; ++i) {
5438
0
    result->reserved_names_[i] =
5439
0
        alloc.AllocateStrings(proto.reserved_name(i));
5440
0
  }
5441
5442
  // Copy options.
5443
76
  if (proto.has_options()) {
5444
0
    AllocateOptions(proto.options(), result,
5445
0
                    DescriptorProto::kOptionsFieldNumber,
5446
0
                    "google.protobuf.MessageOptions", alloc);
5447
0
  }
5448
5449
76
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5450
5451
92
  for (int i = 0; i < proto.reserved_range_size(); i++) {
5452
16
    const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i);
5453
36
    for (int j = i + 1; j < proto.reserved_range_size(); j++) {
5454
20
      const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j);
5455
20
      if (range1.end() > range2.start() && range2.end() > range1.start()) {
5456
0
        AddError(result->full_name(), proto.reserved_range(i),
5457
0
                 DescriptorPool::ErrorCollector::NUMBER,
5458
0
                 absl::Substitute("Reserved range $0 to $1 overlaps with "
5459
0
                                  "already-defined range $2 to $3.",
5460
0
                                  range2.start(), range2.end() - 1,
5461
0
                                  range1.start(), range1.end() - 1));
5462
0
      }
5463
20
    }
5464
16
  }
5465
5466
76
  absl::flat_hash_set<std::string> reserved_name_set;
5467
76
  for (int i = 0; i < proto.reserved_name_size(); i++) {
5468
0
    const std::string& name = proto.reserved_name(i);
5469
0
    if (!reserved_name_set.insert(name).second) {
5470
0
      AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
5471
0
               absl::Substitute("Field name \"$0\" is reserved multiple times.",
5472
0
                                name));
5473
0
    }
5474
0
  }
5475
5476
5477
  // Check that fields aren't using reserved names or numbers and that they
5478
  // aren't using extension numbers.
5479
406
  for (int i = 0; i < result->field_count(); i++) {
5480
330
    const FieldDescriptor* field = result->field(i);
5481
432
    for (int j = 0; j < result->extension_range_count(); j++) {
5482
102
      const Descriptor::ExtensionRange* range = result->extension_range(j);
5483
102
      if (range->start <= field->number() && field->number() < range->end) {
5484
0
        message_hints_[result].RequestHintOnFieldNumbers(
5485
0
            proto.extension_range(j), DescriptorPool::ErrorCollector::NUMBER);
5486
0
        AddError(
5487
0
            field->full_name(), proto.extension_range(j),
5488
0
            DescriptorPool::ErrorCollector::NUMBER,
5489
0
            absl::Substitute(
5490
0
                "Extension range $0 to $1 includes field \"$2\" ($3).",
5491
0
                range->start, range->end - 1, field->name(), field->number()));
5492
0
      }
5493
102
    }
5494
462
    for (int j = 0; j < result->reserved_range_count(); j++) {
5495
132
      const Descriptor::ReservedRange* range = result->reserved_range(j);
5496
132
      if (range->start <= field->number() && field->number() < range->end) {
5497
0
        message_hints_[result].RequestHintOnFieldNumbers(
5498
0
            proto.reserved_range(j), DescriptorPool::ErrorCollector::NUMBER);
5499
0
        AddError(field->full_name(), proto.reserved_range(j),
5500
0
                 DescriptorPool::ErrorCollector::NUMBER,
5501
0
                 absl::Substitute("Field \"$0\" uses reserved number $1.",
5502
0
                                  field->name(), field->number()));
5503
0
      }
5504
132
    }
5505
330
    if (reserved_name_set.find(field->name()) != reserved_name_set.end()) {
5506
0
      AddError(
5507
0
          field->full_name(), proto.field(i),
5508
0
          DescriptorPool::ErrorCollector::NAME,
5509
0
          absl::Substitute("Field name \"$0\" is reserved.", field->name()));
5510
0
    }
5511
5512
330
  }
5513
5514
  // Check that extension ranges don't overlap and don't include
5515
  // reserved field numbers or names.
5516
94
  for (int i = 0; i < result->extension_range_count(); i++) {
5517
18
    const Descriptor::ExtensionRange* range1 = result->extension_range(i);
5518
34
    for (int j = 0; j < result->reserved_range_count(); j++) {
5519
16
      const Descriptor::ReservedRange* range2 = result->reserved_range(j);
5520
16
      if (range1->end > range2->start && range2->end > range1->start) {
5521
0
        AddError(result->full_name(), proto.extension_range(i),
5522
0
                 DescriptorPool::ErrorCollector::NUMBER,
5523
0
                 absl::Substitute("Extension range $0 to $1 overlaps with "
5524
0
                                  "reserved range $2 to $3.",
5525
0
                                  range1->start, range1->end - 1, range2->start,
5526
0
                                  range2->end - 1));
5527
0
      }
5528
16
    }
5529
18
    for (int j = i + 1; j < result->extension_range_count(); j++) {
5530
0
      const Descriptor::ExtensionRange* range2 = result->extension_range(j);
5531
0
      if (range1->end > range2->start && range2->end > range1->start) {
5532
0
        AddError(result->full_name(), proto.extension_range(i),
5533
0
                 DescriptorPool::ErrorCollector::NUMBER,
5534
0
                 absl::Substitute("Extension range $0 to $1 overlaps with "
5535
0
                                  "already-defined range $2 to $3.",
5536
0
                                  range2->start, range2->end - 1, range1->start,
5537
0
                                  range1->end - 1));
5538
0
      }
5539
0
    }
5540
18
  }
5541
76
}
5542
5543
void DescriptorBuilder::CheckFieldJsonNameUniqueness(
5544
0
    const DescriptorProto& proto, const Descriptor* result) {
5545
0
  FileDescriptor::Syntax syntax = result->file()->syntax();
5546
0
  std::string message_name = result->full_name();
5547
0
  if (pool_->deprecated_legacy_json_field_conflicts_ ||
5548
0
      IsLegacyJsonFieldConflictEnabled(result->options())) {
5549
0
    if (syntax == FileDescriptor::SYNTAX_PROTO3) {
5550
      // Only check default JSON names for conflicts in proto3.  This is legacy
5551
      // behavior that will be removed in a later version.
5552
0
      CheckFieldJsonNameUniqueness(message_name, proto, syntax, false);
5553
0
    }
5554
0
  } else {
5555
    // Check both with and without taking json_name into consideration.  This is
5556
    // needed for field masks, which don't use json_name.
5557
0
    CheckFieldJsonNameUniqueness(message_name, proto, syntax, false);
5558
0
    CheckFieldJsonNameUniqueness(message_name, proto, syntax, true);
5559
0
  }
5560
0
}
5561
5562
namespace {
5563
// Helpers for function below
5564
5565
struct JsonNameDetails {
5566
  const FieldDescriptorProto* field;
5567
  std::string orig_name;
5568
  bool is_custom;
5569
};
5570
5571
JsonNameDetails GetJsonNameDetails(const FieldDescriptorProto* field,
5572
0
                                   bool use_custom) {
5573
0
  std::string default_json_name = ToJsonName(field->name());
5574
0
  if (use_custom && field->has_json_name() &&
5575
0
      field->json_name() != default_json_name) {
5576
0
    return {field, field->json_name(), true};
5577
0
  }
5578
0
  return {field, default_json_name, false};
5579
0
}
5580
5581
0
bool JsonNameLooksLikeExtension(std::string name) {
5582
0
  return !name.empty() && name.front() == '[' && name.back() == ']';
5583
0
}
5584
5585
}  // namespace
5586
5587
void DescriptorBuilder::CheckFieldJsonNameUniqueness(
5588
    const std::string& message_name, const DescriptorProto& message,
5589
0
    FileDescriptor::Syntax syntax, bool use_custom_names) {
5590
0
  absl::flat_hash_map<std::string, JsonNameDetails> name_to_field;
5591
0
  for (const FieldDescriptorProto& field : message.field()) {
5592
0
    JsonNameDetails details = GetJsonNameDetails(&field, use_custom_names);
5593
0
    if (details.is_custom && JsonNameLooksLikeExtension(details.orig_name)) {
5594
0
      std::string error_message = absl::StrFormat(
5595
0
          "The custom JSON name of field \"%s\" (\"%s\") is invalid: "
5596
0
          "JSON names may not start with '[' and end with ']'.",
5597
0
          field.name(), details.orig_name);
5598
0
      AddError(message_name, field, DescriptorPool::ErrorCollector::NAME,
5599
0
               error_message);
5600
0
      continue;
5601
0
    }
5602
0
    auto it_inserted = name_to_field.try_emplace(details.orig_name, details);
5603
0
    if (it_inserted.second) {
5604
0
      continue;
5605
0
    }
5606
0
    JsonNameDetails& match = it_inserted.first->second;
5607
0
    if (use_custom_names && !details.is_custom && !match.is_custom) {
5608
      // if this pass is considering custom JSON names, but neither of the
5609
      // names involved in the conflict are custom, don't bother with a
5610
      // message. That will have been reported from other pass (non-custom
5611
      // JSON names).
5612
0
      continue;
5613
0
    }
5614
0
    absl::string_view this_type = details.is_custom ? "custom" : "default";
5615
0
    absl::string_view existing_type = match.is_custom ? "custom" : "default";
5616
    // If the matched name differs (which it can only differ in case), include
5617
    // it in the error message, for maximum clarity to user.
5618
0
    std::string name_suffix = "";
5619
0
    if (details.orig_name != match.orig_name) {
5620
0
      name_suffix = absl::StrCat(" (\"", match.orig_name, "\")");
5621
0
    }
5622
0
    std::string error_message = absl::StrFormat(
5623
0
        "The %s JSON name of field \"%s\" (\"%s\") conflicts "
5624
0
        "with the %s JSON name of field \"%s\"%s.",
5625
0
        this_type, field.name(), details.orig_name, existing_type,
5626
0
        match.field->name(), name_suffix);
5627
5628
0
    bool involves_default = !details.is_custom || !match.is_custom;
5629
0
    if (syntax == FileDescriptor::SYNTAX_PROTO2 && involves_default) {
5630
      // TODO(b/261750676) Upgrade this to an error once downstream protos have
5631
      // been fixed.
5632
0
      AddWarning(message_name, field, DescriptorPool::ErrorCollector::NAME,
5633
0
                 error_message);
5634
0
    } else {
5635
0
      AddError(message_name, field, DescriptorPool::ErrorCollector::NAME,
5636
0
               error_message);
5637
0
    }
5638
0
  }
5639
0
}
5640
5641
void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
5642
                                              Descriptor* parent,
5643
                                              FieldDescriptor* result,
5644
                                              bool is_extension,
5645
330
                                              internal::FlatAllocator& alloc) {
5646
330
  const std::string& scope =
5647
330
      (parent == nullptr) ? file_->package() : parent->full_name();
5648
5649
  // We allocate all names in a single array, and dedup them.
5650
  // We remember the indices for the potentially deduped values.
5651
330
  auto all_names = alloc.AllocateFieldNames(
5652
330
      proto.name(), scope,
5653
330
      proto.has_json_name() ? &proto.json_name() : nullptr);
5654
330
  result->all_names_ = all_names.array;
5655
330
  result->lowercase_name_index_ = all_names.lowercase_index;
5656
330
  result->camelcase_name_index_ = all_names.camelcase_index;
5657
330
  result->json_name_index_ = all_names.json_index;
5658
5659
330
  ValidateSymbolName(proto.name(), result->full_name(), proto);
5660
5661
330
  result->file_ = file_;
5662
330
  result->number_ = proto.number();
5663
330
  result->is_extension_ = is_extension;
5664
330
  result->is_oneof_ = false;
5665
330
  result->proto3_optional_ = proto.proto3_optional();
5666
5667
330
  if (proto.proto3_optional() &&
5668
330
      file_->syntax() != FileDescriptor::SYNTAX_PROTO3) {
5669
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5670
0
             absl::StrCat(
5671
0
                 "The [proto3_optional=true] option may only be set on proto3"
5672
0
                 "fields, not ",
5673
0
                 result->full_name()));
5674
0
  }
5675
5676
330
  result->has_json_name_ = proto.has_json_name();
5677
5678
  // Some compilers do not allow static_cast directly between two enum types,
5679
  // so we must cast to int first.
5680
330
  result->type_ = static_cast<FieldDescriptor::Type>(
5681
330
      absl::implicit_cast<int>(proto.type()));
5682
330
  result->label_ = static_cast<FieldDescriptor::Label>(
5683
330
      absl::implicit_cast<int>(proto.label()));
5684
5685
330
  if (result->label_ == FieldDescriptor::LABEL_REQUIRED) {
5686
    // An extension cannot have a required field (b/13365836).
5687
4
    if (result->is_extension_) {
5688
0
      AddError(result->full_name(), proto,
5689
               // Error location `TYPE`: we would really like to indicate
5690
               // `LABEL`, but the `ErrorLocation` enum has no entry for this,
5691
               // and we don't necessarily know about all implementations of the
5692
               // `ErrorCollector` interface to extend them to handle the new
5693
               // error location type properly.
5694
0
               DescriptorPool::ErrorCollector::TYPE,
5695
0
               absl::StrCat("The extension ", result->full_name(),
5696
0
                            " cannot be required."));
5697
0
    }
5698
4
  }
5699
5700
  // Some of these may be filled in when cross-linking.
5701
330
  result->containing_type_ = nullptr;
5702
330
  result->type_once_ = nullptr;
5703
330
  result->default_value_enum_ = nullptr;
5704
5705
330
  result->has_default_value_ = proto.has_default_value();
5706
330
  if (proto.has_default_value() && result->is_repeated()) {
5707
0
    AddError(result->full_name(), proto,
5708
0
             DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5709
0
             "Repeated fields can't have default values.");
5710
0
  }
5711
5712
330
  if (proto.has_type()) {
5713
330
    if (proto.has_default_value()) {
5714
52
      char* end_pos = nullptr;
5715
52
      switch (result->cpp_type()) {
5716
0
        case FieldDescriptor::CPPTYPE_INT32:
5717
0
          result->default_value_int32_t_ =
5718
0
              std::strtol(proto.default_value().c_str(), &end_pos, 0);
5719
0
          break;
5720
0
        case FieldDescriptor::CPPTYPE_INT64:
5721
0
          static_assert(sizeof(int64_t) == sizeof(long long),
5722
0
                        "sizeof int64_t is not sizeof long long");
5723
0
          result->default_value_int64_t_ =
5724
0
              std::strtoll(proto.default_value().c_str(), &end_pos, 0);
5725
0
          break;
5726
0
        case FieldDescriptor::CPPTYPE_UINT32:
5727
0
          result->default_value_uint32_t_ =
5728
0
              std::strtoul(proto.default_value().c_str(), &end_pos, 0);
5729
0
          break;
5730
0
        case FieldDescriptor::CPPTYPE_UINT64:
5731
0
          static_assert(sizeof(uint64_t) == sizeof(unsigned long long),
5732
0
                        "sizeof uint64_t is not sizeof unsigned long long");
5733
0
          result->default_value_uint64_t_ =
5734
0
              std::strtoull(proto.default_value().c_str(), &end_pos, 0);
5735
0
          break;
5736
0
        case FieldDescriptor::CPPTYPE_FLOAT:
5737
0
          if (proto.default_value() == "inf") {
5738
0
            result->default_value_float_ =
5739
0
                std::numeric_limits<float>::infinity();
5740
0
          } else if (proto.default_value() == "-inf") {
5741
0
            result->default_value_float_ =
5742
0
                -std::numeric_limits<float>::infinity();
5743
0
          } else if (proto.default_value() == "nan") {
5744
0
            result->default_value_float_ =
5745
0
                std::numeric_limits<float>::quiet_NaN();
5746
0
          } else {
5747
0
            result->default_value_float_ = io::SafeDoubleToFloat(
5748
0
                io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos));
5749
0
          }
5750
0
          break;
5751
0
        case FieldDescriptor::CPPTYPE_DOUBLE:
5752
0
          if (proto.default_value() == "inf") {
5753
0
            result->default_value_double_ =
5754
0
                std::numeric_limits<double>::infinity();
5755
0
          } else if (proto.default_value() == "-inf") {
5756
0
            result->default_value_double_ =
5757
0
                -std::numeric_limits<double>::infinity();
5758
0
          } else if (proto.default_value() == "nan") {
5759
0
            result->default_value_double_ =
5760
0
                std::numeric_limits<double>::quiet_NaN();
5761
0
          } else {
5762
0
            result->default_value_double_ =
5763
0
                io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
5764
0
          }
5765
0
          break;
5766
44
        case FieldDescriptor::CPPTYPE_BOOL:
5767
44
          if (proto.default_value() == "true") {
5768
2
            result->default_value_bool_ = true;
5769
42
          } else if (proto.default_value() == "false") {
5770
42
            result->default_value_bool_ = false;
5771
42
          } else {
5772
0
            AddError(result->full_name(), proto,
5773
0
                     DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5774
0
                     "Boolean default must be true or false.");
5775
0
          }
5776
44
          break;
5777
8
        case FieldDescriptor::CPPTYPE_ENUM:
5778
          // This will be filled in when cross-linking.
5779
8
          result->default_value_enum_ = nullptr;
5780
8
          break;
5781
0
        case FieldDescriptor::CPPTYPE_STRING:
5782
0
          if (result->type() == FieldDescriptor::TYPE_BYTES) {
5783
0
            std::string value;
5784
0
            absl::CUnescape(proto.default_value(), &value);
5785
0
            result->default_value_string_ = alloc.AllocateStrings(value);
5786
0
          } else {
5787
0
            result->default_value_string_ =
5788
0
                alloc.AllocateStrings(proto.default_value());
5789
0
          }
5790
0
          break;
5791
0
        case FieldDescriptor::CPPTYPE_MESSAGE:
5792
0
          AddError(result->full_name(), proto,
5793
0
                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5794
0
                   "Messages can't have default values.");
5795
0
          result->has_default_value_ = false;
5796
0
          result->default_generated_instance_ = nullptr;
5797
0
          break;
5798
52
      }
5799
5800
52
      if (end_pos != nullptr) {
5801
        // end_pos is only set non-null by the parsers for numeric types,
5802
        // above. This checks that the default was non-empty and had no extra
5803
        // junk after the end of the number.
5804
0
        if (proto.default_value().empty() || *end_pos != '\0') {
5805
0
          AddError(result->full_name(), proto,
5806
0
                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5807
0
                   absl::StrCat("Couldn't parse default value \"",
5808
0
                                proto.default_value(), "\"."));
5809
0
        }
5810
0
      }
5811
278
    } else {
5812
      // No explicit default value
5813
278
      switch (result->cpp_type()) {
5814
32
        case FieldDescriptor::CPPTYPE_INT32:
5815
32
          result->default_value_int32_t_ = 0;
5816
32
          break;
5817
2
        case FieldDescriptor::CPPTYPE_INT64:
5818
2
          result->default_value_int64_t_ = 0;
5819
2
          break;
5820
2
        case FieldDescriptor::CPPTYPE_UINT32:
5821
2
          result->default_value_uint32_t_ = 0;
5822
2
          break;
5823
2
        case FieldDescriptor::CPPTYPE_UINT64:
5824
2
          result->default_value_uint64_t_ = 0;
5825
2
          break;
5826
0
        case FieldDescriptor::CPPTYPE_FLOAT:
5827
0
          result->default_value_float_ = 0.0f;
5828
0
          break;
5829
2
        case FieldDescriptor::CPPTYPE_DOUBLE:
5830
2
          result->default_value_double_ = 0.0;
5831
2
          break;
5832
20
        case FieldDescriptor::CPPTYPE_BOOL:
5833
20
          result->default_value_bool_ = false;
5834
20
          break;
5835
10
        case FieldDescriptor::CPPTYPE_ENUM:
5836
          // This will be filled in when cross-linking.
5837
10
          result->default_value_enum_ = nullptr;
5838
10
          break;
5839
108
        case FieldDescriptor::CPPTYPE_STRING:
5840
108
          result->default_value_string_ = &internal::GetEmptyString();
5841
108
          break;
5842
100
        case FieldDescriptor::CPPTYPE_MESSAGE:
5843
100
          result->default_generated_instance_ = nullptr;
5844
100
          break;
5845
278
      }
5846
278
    }
5847
330
  }
5848
5849
330
  if (result->number() <= 0) {
5850
0
    message_hints_[parent].RequestHintOnFieldNumbers(
5851
0
        proto, DescriptorPool::ErrorCollector::NUMBER);
5852
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5853
0
             "Field numbers must be positive integers.");
5854
330
  } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) {
5855
    // Only validate that the number is within the valid field range if it is
5856
    // not an extension. Since extension numbers are validated with the
5857
    // extendee's valid set of extension numbers, and those are in turn
5858
    // validated against the max allowed number, the check is unnecessary for
5859
    // extension fields.
5860
    // This avoids cross-linking issues that arise when attempting to check if
5861
    // the extendee is a message_set_wire_format message, which has a higher max
5862
    // on extension numbers.
5863
0
    message_hints_[parent].RequestHintOnFieldNumbers(
5864
0
        proto, DescriptorPool::ErrorCollector::NUMBER);
5865
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5866
0
             absl::Substitute("Field numbers cannot be greater than $0.",
5867
0
                              FieldDescriptor::kMaxNumber));
5868
0
  }
5869
5870
330
  if (is_extension) {
5871
0
    if (!proto.has_extendee()) {
5872
0
      AddError(result->full_name(), proto,
5873
0
               DescriptorPool::ErrorCollector::EXTENDEE,
5874
0
               "FieldDescriptorProto.extendee not set for extension field.");
5875
0
    }
5876
5877
0
    result->scope_.extension_scope = parent;
5878
5879
0
    if (proto.has_oneof_index()) {
5880
0
      AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5881
0
               "FieldDescriptorProto.oneof_index should not be set for "
5882
0
               "extensions.");
5883
0
    }
5884
330
  } else {
5885
330
    if (proto.has_extendee()) {
5886
0
      AddError(result->full_name(), proto,
5887
0
               DescriptorPool::ErrorCollector::EXTENDEE,
5888
0
               "FieldDescriptorProto.extendee set for non-extension field.");
5889
0
    }
5890
5891
330
    result->containing_type_ = parent;
5892
5893
330
    if (proto.has_oneof_index()) {
5894
14
      if (proto.oneof_index() < 0 ||
5895
14
          proto.oneof_index() >= parent->oneof_decl_count()) {
5896
0
        AddError(result->full_name(), proto,
5897
0
                 DescriptorPool::ErrorCollector::TYPE,
5898
0
                 absl::Substitute("FieldDescriptorProto.oneof_index $0 is "
5899
0
                                  "out of range for type \"$1\".",
5900
0
                                  proto.oneof_index(), parent->name()));
5901
14
      } else {
5902
14
        result->is_oneof_ = true;
5903
14
        result->scope_.containing_oneof =
5904
14
            parent->oneof_decl(proto.oneof_index());
5905
14
      }
5906
14
    }
5907
330
  }
5908
5909
  // Copy options.
5910
330
  result->options_ = nullptr;  // Set to default_instance later if necessary.
5911
330
  if (proto.has_options()) {
5912
12
    AllocateOptions(proto.options(), result,
5913
12
                    FieldDescriptorProto::kOptionsFieldNumber,
5914
12
                    "google.protobuf.FieldOptions", alloc);
5915
12
  }
5916
5917
330
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5918
330
}
5919
5920
void DescriptorBuilder::BuildExtensionRange(
5921
    const DescriptorProto::ExtensionRange& proto, const Descriptor* parent,
5922
18
    Descriptor::ExtensionRange* result, internal::FlatAllocator& alloc) {
5923
18
  result->start = proto.start();
5924
18
  result->end = proto.end();
5925
18
  if (result->start <= 0) {
5926
0
    message_hints_[parent].RequestHintOnFieldNumbers(
5927
0
        proto, DescriptorPool::ErrorCollector::NUMBER, result->start,
5928
0
        result->end);
5929
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5930
0
             "Extension numbers must be positive integers.");
5931
0
  }
5932
5933
  // Checking of the upper bound of the extension range is deferred until after
5934
  // options interpreting. This allows messages with message_set_wire_format to
5935
  // have extensions beyond FieldDescriptor::kMaxNumber, since the extension
5936
  // numbers are actually used as int32s in the message_set_wire_format.
5937
5938
18
  if (result->start >= result->end) {
5939
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5940
0
             "Extension range end number must be greater than start number.");
5941
0
  }
5942
5943
18
  result->options_ = nullptr;  // Set to default_instance later if necessary.
5944
18
  if (proto.has_options()) {
5945
0
    std::vector<int> options_path;
5946
0
    parent->GetLocationPath(&options_path);
5947
0
    options_path.push_back(DescriptorProto::kExtensionRangeFieldNumber);
5948
    // find index of this extension range in order to compute path
5949
0
    int index;
5950
0
    for (index = 0; parent->extension_ranges_ + index != result; index++) {
5951
0
    }
5952
0
    options_path.push_back(index);
5953
0
    options_path.push_back(DescriptorProto_ExtensionRange::kOptionsFieldNumber);
5954
0
    AllocateOptionsImpl(parent->full_name(), parent->full_name(),
5955
0
                        proto.options(), result, options_path,
5956
0
                        "google.protobuf.ExtensionRangeOptions", alloc);
5957
0
  }
5958
18
}
5959
5960
void DescriptorBuilder::BuildReservedRange(
5961
    const DescriptorProto::ReservedRange& proto, const Descriptor* parent,
5962
16
    Descriptor::ReservedRange* result, internal::FlatAllocator&) {
5963
16
  result->start = proto.start();
5964
16
  result->end = proto.end();
5965
16
  if (result->start <= 0) {
5966
0
    message_hints_[parent].RequestHintOnFieldNumbers(
5967
0
        proto, DescriptorPool::ErrorCollector::NUMBER, result->start,
5968
0
        result->end);
5969
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5970
0
             "Reserved numbers must be positive integers.");
5971
0
  }
5972
16
}
5973
5974
void DescriptorBuilder::BuildReservedRange(
5975
    const EnumDescriptorProto::EnumReservedRange& proto,
5976
    const EnumDescriptor* parent, EnumDescriptor::ReservedRange* result,
5977
0
    internal::FlatAllocator&) {
5978
0
  result->start = proto.start();
5979
0
  result->end = proto.end();
5980
5981
0
  if (result->start > result->end) {
5982
0
    AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5983
0
             "Reserved range end number must be greater than start number.");
5984
0
  }
5985
0
}
5986
5987
void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
5988
                                   Descriptor* parent, OneofDescriptor* result,
5989
4
                                   internal::FlatAllocator& alloc) {
5990
4
  result->all_names_ =
5991
4
      AllocateNameStrings(parent->full_name(), proto.name(), alloc);
5992
4
  ValidateSymbolName(proto.name(), result->full_name(), proto);
5993
5994
4
  result->containing_type_ = parent;
5995
5996
  // We need to fill these in later.
5997
4
  result->field_count_ = 0;
5998
4
  result->fields_ = nullptr;
5999
4
  result->options_ = nullptr;
6000
6001
  // Copy options.
6002
4
  if (proto.has_options()) {
6003
0
    AllocateOptions(proto.options(), result,
6004
0
                    OneofDescriptorProto::kOptionsFieldNumber,
6005
0
                    "google.protobuf.OneofOptions", alloc);
6006
0
  }
6007
6008
4
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6009
4
}
6010
6011
void DescriptorBuilder::CheckEnumValueUniqueness(
6012
0
    const EnumDescriptorProto& proto, const EnumDescriptor* result) {
6013
6014
  // Check that enum labels are still unique when we remove the enum prefix from
6015
  // values that have it.
6016
  //
6017
  // This will fail for something like:
6018
  //
6019
  //   enum MyEnum {
6020
  //     MY_ENUM_FOO = 0;
6021
  //     FOO = 1;
6022
  //   }
6023
  //
6024
  // By enforcing this reasonable constraint, we allow code generators to strip
6025
  // the prefix and/or PascalCase it without creating conflicts.  This can lead
6026
  // to much nicer language-specific enums like:
6027
  //
6028
  //   enum NameType {
6029
  //     FirstName = 1,
6030
  //     LastName = 2,
6031
  //   }
6032
  //
6033
  // Instead of:
6034
  //
6035
  //   enum NameType {
6036
  //     NAME_TYPE_FIRST_NAME = 1,
6037
  //     NAME_TYPE_LAST_NAME = 2,
6038
  //   }
6039
0
  PrefixRemover remover(result->name());
6040
0
  absl::flat_hash_map<std::string, const EnumValueDescriptor*> values;
6041
0
  for (int i = 0; i < result->value_count(); i++) {
6042
0
    const EnumValueDescriptor* value = result->value(i);
6043
0
    std::string stripped =
6044
0
        EnumValueToPascalCase(remover.MaybeRemove(value->name()));
6045
0
    auto insert_result = values.try_emplace(stripped, value);
6046
0
    bool inserted = insert_result.second;
6047
6048
    // We don't throw the error if the two conflicting symbols are identical, or
6049
    // if they map to the same number.  In the former case, the normal symbol
6050
    // duplication error will fire so we don't need to (and its error message
6051
    // will make more sense). We allow the latter case so users can create
6052
    // aliases which add or remove the prefix (code generators that do prefix
6053
    // stripping should de-dup the labels in this case).
6054
0
    if (!inserted && insert_result.first->second->name() != value->name() &&
6055
0
        insert_result.first->second->number() != value->number()) {
6056
0
      std::string error_message = absl::StrFormat(
6057
0
          "Enum name %s has the same name as %s if you ignore case and strip "
6058
0
          "out the enum name prefix (if any). (If you are using allow_alias, "
6059
0
          "please assign the same numeric value to both enums.)",
6060
0
          value->name(), insert_result.first->second->name());
6061
      // There are proto2 enums out there with conflicting names, so to preserve
6062
      // compatibility we issue only a warning for proto2.
6063
0
      if ((pool_->deprecated_legacy_json_field_conflicts_ ||
6064
0
           IsLegacyJsonFieldConflictEnabled(result->options())) &&
6065
0
          result->file()->syntax() == FileDescriptor::SYNTAX_PROTO2) {
6066
0
        AddWarning(value->full_name(), proto.value(i),
6067
0
                   DescriptorPool::ErrorCollector::NAME, error_message);
6068
0
        continue;
6069
0
      }
6070
0
      AddError(value->full_name(), proto.value(i),
6071
0
               DescriptorPool::ErrorCollector::NAME, error_message);
6072
0
    }
6073
0
  }
6074
0
}
6075
6076
void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
6077
                                  const Descriptor* parent,
6078
                                  EnumDescriptor* result,
6079
18
                                  internal::FlatAllocator& alloc) {
6080
18
  const std::string& scope =
6081
18
      (parent == nullptr) ? file_->package() : parent->full_name();
6082
6083
18
  result->all_names_ = AllocateNameStrings(scope, proto.name(), alloc);
6084
18
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6085
18
  result->file_ = file_;
6086
18
  result->containing_type_ = parent;
6087
18
  result->is_placeholder_ = false;
6088
18
  result->is_unqualified_placeholder_ = false;
6089
6090
18
  if (proto.value_size() == 0) {
6091
    // We cannot allow enums with no values because this would mean there
6092
    // would be no valid default value for fields of this type.
6093
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6094
0
             "Enums must contain at least one value.");
6095
0
  }
6096
6097
  // Calculate the continuous sequence of the labels.
6098
  // These can be fast-path'd during lookup and don't need to be added to the
6099
  // tables.
6100
  // We use uint16_t to save space for sequential_value_limit_, so stop before
6101
  // overflowing it. Worst case, we are not taking full advantage on huge
6102
  // enums, but it is unlikely.
6103
18
  for (int i = 0;
6104
116
       i < std::numeric_limits<uint16_t>::max() && i < proto.value_size() &&
6105
       // We do the math in int64_t to avoid overflows.
6106
116
       proto.value(i).number() ==
6107
98
           static_cast<int64_t>(i) + proto.value(0).number();
6108
98
       ++i) {
6109
98
    result->sequential_value_limit_ = i;
6110
98
  }
6111
6112
18
  BUILD_ARRAY(proto, result, value, BuildEnumValue, result);
6113
18
  BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);
6114
6115
  // Copy reserved names.
6116
18
  int reserved_name_count = proto.reserved_name_size();
6117
18
  result->reserved_name_count_ = reserved_name_count;
6118
18
  result->reserved_names_ =
6119
18
      alloc.AllocateArray<const std::string*>(reserved_name_count);
6120
18
  for (int i = 0; i < reserved_name_count; ++i) {
6121
0
    result->reserved_names_[i] =
6122
0
        alloc.AllocateStrings(proto.reserved_name(i));
6123
0
  }
6124
6125
  // Copy options.
6126
18
  result->options_ = nullptr;  // Set to default_instance later if necessary.
6127
18
  if (proto.has_options()) {
6128
0
    AllocateOptions(proto.options(), result,
6129
0
                    EnumDescriptorProto::kOptionsFieldNumber,
6130
0
                    "google.protobuf.EnumOptions", alloc);
6131
0
  }
6132
6133
18
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6134
6135
18
  for (int i = 0; i < proto.reserved_range_size(); i++) {
6136
0
    const EnumDescriptorProto_EnumReservedRange& range1 =
6137
0
        proto.reserved_range(i);
6138
0
    for (int j = i + 1; j < proto.reserved_range_size(); j++) {
6139
0
      const EnumDescriptorProto_EnumReservedRange& range2 =
6140
0
          proto.reserved_range(j);
6141
0
      if (range1.end() >= range2.start() && range2.end() >= range1.start()) {
6142
0
        AddError(result->full_name(), proto.reserved_range(i),
6143
0
                 DescriptorPool::ErrorCollector::NUMBER,
6144
0
                 absl::Substitute("Reserved range $0 to $1 overlaps with "
6145
0
                                  "already-defined range $2 to $3.",
6146
0
                                  range2.start(), range2.end(), range1.start(),
6147
0
                                  range1.end()));
6148
0
      }
6149
0
    }
6150
0
  }
6151
6152
18
  absl::flat_hash_set<std::string> reserved_name_set;
6153
18
  for (int i = 0; i < proto.reserved_name_size(); i++) {
6154
0
    const std::string& name = proto.reserved_name(i);
6155
0
    if (reserved_name_set.find(name) == reserved_name_set.end()) {
6156
0
      reserved_name_set.insert(name);
6157
0
    } else {
6158
0
      AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
6159
0
               absl::Substitute("Enum value \"$0\" is reserved multiple times.",
6160
0
                                name));
6161
0
    }
6162
0
  }
6163
6164
116
  for (int i = 0; i < result->value_count(); i++) {
6165
98
    const EnumValueDescriptor* value = result->value(i);
6166
98
    for (int j = 0; j < result->reserved_range_count(); j++) {
6167
0
      const EnumDescriptor::ReservedRange* range = result->reserved_range(j);
6168
0
      if (range->start <= value->number() && value->number() <= range->end) {
6169
0
        AddError(value->full_name(), proto.reserved_range(j),
6170
0
                 DescriptorPool::ErrorCollector::NUMBER,
6171
0
                 absl::Substitute("Enum value \"$0\" uses reserved number $1.",
6172
0
                                  value->name(), value->number()));
6173
0
      }
6174
0
    }
6175
98
    if (reserved_name_set.find(value->name()) != reserved_name_set.end()) {
6176
0
      AddError(
6177
0
          value->full_name(), proto.value(i),
6178
0
          DescriptorPool::ErrorCollector::NAME,
6179
0
          absl::Substitute("Enum value \"$0\" is reserved.", value->name()));
6180
0
    }
6181
98
  }
6182
18
}
6183
6184
void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto,
6185
                                       const EnumDescriptor* parent,
6186
                                       EnumValueDescriptor* result,
6187
98
                                       internal::FlatAllocator& alloc) {
6188
  // Note:  full_name for enum values is a sibling to the parent's name, not a
6189
  //   child of it.
6190
98
  std::string full_name;
6191
98
  size_t scope_len = parent->full_name().size() - parent->name().size();
6192
98
  full_name.reserve(scope_len + proto.name().size());
6193
98
  full_name.append(parent->full_name().data(), scope_len);
6194
98
  full_name.append(proto.name());
6195
6196
98
  result->all_names_ =
6197
98
      alloc.AllocateStrings(proto.name(), std::move(full_name));
6198
98
  result->number_ = proto.number();
6199
98
  result->type_ = parent;
6200
6201
98
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6202
6203
  // Copy options.
6204
98
  result->options_ = nullptr;  // Set to default_instance later if necessary.
6205
98
  if (proto.has_options()) {
6206
0
    AllocateOptions(proto.options(), result,
6207
0
                    EnumValueDescriptorProto::kOptionsFieldNumber,
6208
0
                    "google.protobuf.EnumValueOptions", alloc);
6209
0
  }
6210
6211
  // Again, enum values are weird because we makes them appear as siblings
6212
  // of the enum type instead of children of it.  So, we use
6213
  // parent->containing_type() as the value's parent.
6214
98
  bool added_to_outer_scope =
6215
98
      AddSymbol(result->full_name(), parent->containing_type(), result->name(),
6216
98
                proto, Symbol::EnumValue(result, 0));
6217
6218
  // However, we also want to be able to search for values within a single
6219
  // enum type, so we add it as a child of the enum type itself, too.
6220
  // Note:  This could fail, but if it does, the error has already been
6221
  //   reported by the above AddSymbol() call, so we ignore the return code.
6222
98
  bool added_to_inner_scope = file_tables_->AddAliasUnderParent(
6223
98
      parent, result->name(), Symbol::EnumValue(result, 1));
6224
6225
98
  if (added_to_inner_scope && !added_to_outer_scope) {
6226
    // This value did not conflict with any values defined in the same enum,
6227
    // but it did conflict with some other symbol defined in the enum type's
6228
    // scope.  Let's print an additional error to explain this.
6229
0
    std::string outer_scope;
6230
0
    if (parent->containing_type() == nullptr) {
6231
0
      outer_scope = file_->package();
6232
0
    } else {
6233
0
      outer_scope = parent->containing_type()->full_name();
6234
0
    }
6235
6236
0
    if (outer_scope.empty()) {
6237
0
      outer_scope = "the global scope";
6238
0
    } else {
6239
0
      outer_scope = absl::StrCat("\"", outer_scope, "\"");
6240
0
    }
6241
6242
0
    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6243
0
             absl::StrCat(
6244
0
                 "Note that enum values use C++ scoping rules, meaning that "
6245
0
                 "enum values are siblings of their type, not children of it.  "
6246
0
                 "Therefore, \"",
6247
0
                 result->name(), "\" must be unique within ", outer_scope,
6248
0
                 ", not just within \"", parent->name(), "\"."));
6249
0
  }
6250
6251
  // An enum is allowed to define two numbers that refer to the same value.
6252
  // FindValueByNumber() should return the first such value, so we simply
6253
  // ignore AddEnumValueByNumber()'s return code.
6254
98
  file_tables_->AddEnumValueByNumber(result);
6255
98
}
6256
6257
void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
6258
                                     const void* /* dummy */,
6259
                                     ServiceDescriptor* result,
6260
0
                                     internal::FlatAllocator& alloc) {
6261
0
  result->all_names_ =
6262
0
      AllocateNameStrings(file_->package(), proto.name(), alloc);
6263
0
  result->file_ = file_;
6264
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6265
6266
0
  BUILD_ARRAY(proto, result, method, BuildMethod, result);
6267
6268
  // Copy options.
6269
0
  result->options_ = nullptr;  // Set to default_instance later if necessary.
6270
0
  if (proto.has_options()) {
6271
0
    AllocateOptions(proto.options(), result,
6272
0
                    ServiceDescriptorProto::kOptionsFieldNumber,
6273
0
                    "google.protobuf.ServiceOptions", alloc);
6274
0
  }
6275
6276
0
  AddSymbol(result->full_name(), nullptr, result->name(), proto,
6277
0
            Symbol(result));
6278
0
}
6279
6280
void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto,
6281
                                    const ServiceDescriptor* parent,
6282
                                    MethodDescriptor* result,
6283
0
                                    internal::FlatAllocator& alloc) {
6284
0
  result->service_ = parent;
6285
0
  result->all_names_ =
6286
0
      AllocateNameStrings(parent->full_name(), proto.name(), alloc);
6287
6288
0
  ValidateSymbolName(proto.name(), result->full_name(), proto);
6289
6290
  // These will be filled in when cross-linking.
6291
0
  result->input_type_.Init();
6292
0
  result->output_type_.Init();
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
                    MethodDescriptorProto::kOptionsFieldNumber,
6299
0
                    "google.protobuf.MethodOptions", alloc);
6300
0
  }
6301
6302
0
  result->client_streaming_ = proto.client_streaming();
6303
0
  result->server_streaming_ = proto.server_streaming();
6304
6305
0
  AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
6306
0
}
6307
6308
#undef BUILD_ARRAY
6309
6310
// -------------------------------------------------------------------
6311
6312
void DescriptorBuilder::CrossLinkFile(FileDescriptor* file,
6313
6
                                      const FileDescriptorProto& proto) {
6314
6
  if (file->options_ == nullptr) {
6315
2
    file->options_ = &FileOptions::default_instance();
6316
2
  }
6317
6318
70
  for (int i = 0; i < file->message_type_count(); i++) {
6319
64
    CrossLinkMessage(&file->message_types_[i], proto.message_type(i));
6320
64
  }
6321
6322
6
  for (int i = 0; i < file->extension_count(); i++) {
6323
0
    CrossLinkField(&file->extensions_[i], proto.extension(i));
6324
0
  }
6325
6326
6
  for (int i = 0; i < file->enum_type_count(); i++) {
6327
0
    CrossLinkEnum(&file->enum_types_[i], proto.enum_type(i));
6328
0
  }
6329
6330
6
  for (int i = 0; i < file->service_count(); i++) {
6331
0
    CrossLinkService(&file->services_[i], proto.service(i));
6332
0
  }
6333
6
}
6334
6335
void DescriptorBuilder::CrossLinkMessage(Descriptor* message,
6336
76
                                         const DescriptorProto& proto) {
6337
76
  if (message->options_ == nullptr) {
6338
76
    message->options_ = &MessageOptions::default_instance();
6339
76
  }
6340
6341
88
  for (int i = 0; i < message->nested_type_count(); i++) {
6342
12
    CrossLinkMessage(&message->nested_types_[i], proto.nested_type(i));
6343
12
  }
6344
6345
94
  for (int i = 0; i < message->enum_type_count(); i++) {
6346
18
    CrossLinkEnum(&message->enum_types_[i], proto.enum_type(i));
6347
18
  }
6348
6349
406
  for (int i = 0; i < message->field_count(); i++) {
6350
330
    CrossLinkField(&message->fields_[i], proto.field(i));
6351
330
  }
6352
6353
76
  for (int i = 0; i < message->extension_count(); i++) {
6354
0
    CrossLinkField(&message->extensions_[i], proto.extension(i));
6355
0
  }
6356
6357
94
  for (int i = 0; i < message->extension_range_count(); i++) {
6358
18
    CrossLinkExtensionRange(&message->extension_ranges_[i],
6359
18
                            proto.extension_range(i));
6360
18
  }
6361
6362
  // Set up field array for each oneof.
6363
6364
  // First count the number of fields per oneof.
6365
406
  for (int i = 0; i < message->field_count(); i++) {
6366
330
    const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
6367
330
    if (oneof_decl != nullptr) {
6368
      // Make sure fields belonging to the same oneof are defined consecutively.
6369
      // This enables optimizations in codegens and reflection libraries to
6370
      // skip fields in the oneof group, as only one of the field can be set.
6371
      // Note that field_count() returns how many fields in this oneof we have
6372
      // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is
6373
      // safe.
6374
14
      if (oneof_decl->field_count() > 0 &&
6375
14
          message->field(i - 1)->containing_oneof() != oneof_decl) {
6376
0
        AddError(absl::StrCat(message->full_name(), ".",
6377
0
                              message->field(i - 1)->name()),
6378
0
                 proto.field(i - 1), DescriptorPool::ErrorCollector::TYPE,
6379
0
                 absl::Substitute(
6380
0
                     "Fields in the same oneof must be defined consecutively. "
6381
0
                     "\"$0\" cannot be defined before the completion of the "
6382
0
                     "\"$1\" oneof definition.",
6383
0
                     message->field(i - 1)->name(), oneof_decl->name()));
6384
0
      }
6385
      // Must go through oneof_decls_ array to get a non-const version of the
6386
      // OneofDescriptor.
6387
14
      auto& out_oneof_decl = message->oneof_decls_[oneof_decl->index()];
6388
14
      if (out_oneof_decl.field_count_ == 0) {
6389
4
        out_oneof_decl.fields_ = message->field(i);
6390
4
      }
6391
6392
14
      if (!had_errors_) {
6393
        // Verify that they are contiguous.
6394
        // This is assumed by OneofDescriptor::field(i).
6395
        // But only if there are no errors.
6396
14
        ABSL_CHECK_EQ(out_oneof_decl.fields_ + out_oneof_decl.field_count_,
6397
14
                      message->field(i));
6398
14
      }
6399
14
      ++out_oneof_decl.field_count_;
6400
14
    }
6401
330
  }
6402
6403
  // Then verify the sizes.
6404
80
  for (int i = 0; i < message->oneof_decl_count(); i++) {
6405
4
    OneofDescriptor* oneof_decl = &message->oneof_decls_[i];
6406
6407
4
    if (oneof_decl->field_count() == 0) {
6408
0
      AddError(absl::StrCat(message->full_name(), ".", oneof_decl->name()),
6409
0
               proto.oneof_decl(i), DescriptorPool::ErrorCollector::NAME,
6410
0
               "Oneof must have at least one field.");
6411
0
    }
6412
6413
4
    if (oneof_decl->options_ == nullptr) {
6414
4
      oneof_decl->options_ = &OneofOptions::default_instance();
6415
4
    }
6416
4
  }
6417
6418
406
  for (int i = 0; i < message->field_count(); i++) {
6419
330
    const FieldDescriptor* field = message->field(i);
6420
330
    if (field->proto3_optional_) {
6421
0
      if (!field->containing_oneof() ||
6422
0
          !field->containing_oneof()->is_synthetic()) {
6423
0
        AddError(message->full_name(), proto.field(i),
6424
0
                 DescriptorPool::ErrorCollector::OTHER,
6425
0
                 "Fields with proto3_optional set must be "
6426
0
                 "a member of a one-field oneof");
6427
0
      }
6428
0
    }
6429
330
  }
6430
6431
  // Synthetic oneofs must be last.
6432
76
  int first_synthetic = -1;
6433
80
  for (int i = 0; i < message->oneof_decl_count(); i++) {
6434
4
    const OneofDescriptor* oneof = message->oneof_decl(i);
6435
4
    if (oneof->is_synthetic()) {
6436
0
      if (first_synthetic == -1) {
6437
0
        first_synthetic = i;
6438
0
      }
6439
4
    } else {
6440
4
      if (first_synthetic != -1) {
6441
0
        AddError(message->full_name(), proto.oneof_decl(i),
6442
0
                 DescriptorPool::ErrorCollector::OTHER,
6443
0
                 "Synthetic oneofs must be after all other oneofs");
6444
0
      }
6445
4
    }
6446
4
  }
6447
6448
76
  if (first_synthetic == -1) {
6449
76
    message->real_oneof_decl_count_ = message->oneof_decl_count_;
6450
76
  } else {
6451
0
    message->real_oneof_decl_count_ = first_synthetic;
6452
0
  }
6453
76
}
6454
6455
void DescriptorBuilder::CrossLinkExtensionRange(
6456
    Descriptor::ExtensionRange* range,
6457
18
    const DescriptorProto::ExtensionRange& /*proto*/) {
6458
18
  if (range->options_ == nullptr) {
6459
18
    range->options_ = &ExtensionRangeOptions::default_instance();
6460
18
  }
6461
18
}
6462
6463
6464
void DescriptorBuilder::CrossLinkField(FieldDescriptor* field,
6465
330
                                       const FieldDescriptorProto& proto) {
6466
330
  if (field->options_ == nullptr) {
6467
318
    field->options_ = &FieldOptions::default_instance();
6468
318
  }
6469
6470
330
  if (proto.has_extendee()) {
6471
0
    Symbol extendee =
6472
0
        LookupSymbol(proto.extendee(), field->full_name(),
6473
0
                     DescriptorPool::PLACEHOLDER_EXTENDABLE_MESSAGE);
6474
0
    if (extendee.IsNull()) {
6475
0
      AddNotDefinedError(field->full_name(), proto,
6476
0
                         DescriptorPool::ErrorCollector::EXTENDEE,
6477
0
                         proto.extendee());
6478
0
      return;
6479
0
    } else if (extendee.type() != Symbol::MESSAGE) {
6480
0
      AddError(
6481
0
          field->full_name(), proto, DescriptorPool::ErrorCollector::EXTENDEE,
6482
0
          absl::StrCat("\"", proto.extendee(), "\" is not a message type."));
6483
0
      return;
6484
0
    }
6485
0
    field->containing_type_ = extendee.descriptor();
6486
6487
0
    const Descriptor::ExtensionRange* extension_range =
6488
0
        field->containing_type()->FindExtensionRangeContainingNumber(
6489
0
            field->number());
6490
6491
0
    if (extension_range == nullptr) {
6492
      // Set of valid extension numbers for MessageSet is different (< 2^32)
6493
      // from other extendees (< 2^29). If unknown deps are allowed, we may not
6494
      // have that information, and wrongly deem the extension as invalid.
6495
0
      auto skip_check = get_allow_unknown(pool_) &&
6496
0
                        proto.extendee() == "google.protobuf.bridge.MessageSet";
6497
0
      if (!skip_check) {
6498
0
        AddError(field->full_name(), proto,
6499
0
                 DescriptorPool::ErrorCollector::NUMBER,
6500
0
                 absl::Substitute("\"$0\" does not declare $1 as an "
6501
0
                                  "extension number.",
6502
0
                                  field->containing_type()->full_name(),
6503
0
                                  field->number()));
6504
0
      }
6505
0
    }
6506
0
  }
6507
6508
330
  if (field->containing_oneof() != nullptr) {
6509
14
    if (field->label() != FieldDescriptor::LABEL_OPTIONAL) {
6510
      // Note that this error will never happen when parsing .proto files.
6511
      // It can only happen if you manually construct a FileDescriptorProto
6512
      // that is incorrect.
6513
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6514
0
               "Fields of oneofs must themselves have label LABEL_OPTIONAL.");
6515
0
    }
6516
14
  }
6517
6518
330
  if (proto.has_type_name()) {
6519
    // Assume we are expecting a message type unless the proto contains some
6520
    // evidence that it expects an enum type.  This only makes a difference if
6521
    // we end up creating a placeholder.
6522
118
    bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) ||
6523
118
                          proto.has_default_value();
6524
6525
    // In case of weak fields we force building the dependency. We need to know
6526
    // if the type exist or not. If it doesn't exist we substitute Empty which
6527
    // should only be done if the type can't be found in the generated pool.
6528
    // TODO(gerbens) Ideally we should query the database directly to check
6529
    // if weak fields exist or not so that we don't need to force building
6530
    // weak dependencies. However the name lookup rules for symbols are
6531
    // somewhat complicated, so I defer it too another CL.
6532
118
    bool is_weak = !pool_->enforce_weak_ && proto.options().weak();
6533
118
    bool is_lazy = pool_->lazily_build_dependencies_ && !is_weak;
6534
6535
118
    Symbol type =
6536
118
        LookupSymbol(proto.type_name(), field->full_name(),
6537
118
                     expecting_enum ? DescriptorPool::PLACEHOLDER_ENUM
6538
118
                                    : DescriptorPool::PLACEHOLDER_MESSAGE,
6539
118
                     LOOKUP_TYPES, !is_lazy);
6540
6541
118
    if (type.IsNull()) {
6542
0
      if (is_lazy) {
6543
        // Save the symbol names for later for lookup, and allocate the once
6544
        // object needed for the accessors.
6545
0
        const std::string& name = proto.type_name();
6546
6547
0
        int name_sizes = static_cast<int>(name.size() + 1 +
6548
0
                                          proto.default_value().size() + 1);
6549
6550
0
        field->type_once_ = ::new (tables_->AllocateBytes(
6551
0
            static_cast<int>(sizeof(absl::once_flag)) + name_sizes))
6552
0
            absl::once_flag{};
6553
0
        char* names = reinterpret_cast<char*>(field->type_once_ + 1);
6554
6555
0
        memcpy(names, name.c_str(), name.size() + 1);
6556
0
        memcpy(names + name.size() + 1, proto.default_value().c_str(),
6557
0
               proto.default_value().size() + 1);
6558
6559
        // AddFieldByNumber and AddExtension are done later in this function,
6560
        // and can/must be done if the field type was not found. The related
6561
        // error checking is not necessary when in lazily_build_dependencies_
6562
        // mode, and can't be done without building the type's descriptor,
6563
        // which we don't want to do.
6564
0
        file_tables_->AddFieldByNumber(field);
6565
0
        if (field->is_extension()) {
6566
0
          tables_->AddExtension(field);
6567
0
        }
6568
0
        return;
6569
0
      } else {
6570
        // If the type is a weak type, we change the type to a google.protobuf.Empty
6571
        // field.
6572
0
        if (is_weak) {
6573
0
          type = FindSymbol(kNonLinkedWeakMessageReplacementName);
6574
0
        }
6575
0
        if (type.IsNull()) {
6576
0
          AddNotDefinedError(field->full_name(), proto,
6577
0
                             DescriptorPool::ErrorCollector::TYPE,
6578
0
                             proto.type_name());
6579
0
          return;
6580
0
        }
6581
0
      }
6582
0
    }
6583
6584
118
    if (!proto.has_type()) {
6585
      // Choose field type based on symbol.
6586
0
      if (type.type() == Symbol::MESSAGE) {
6587
0
        field->type_ = FieldDescriptor::TYPE_MESSAGE;
6588
0
      } else if (type.type() == Symbol::ENUM) {
6589
0
        field->type_ = FieldDescriptor::TYPE_ENUM;
6590
0
      } else {
6591
0
        AddError(field->full_name(), proto,
6592
0
                 DescriptorPool::ErrorCollector::TYPE,
6593
0
                 absl::StrCat("\"", proto.type_name(), "\" is not a type."));
6594
0
        return;
6595
0
      }
6596
0
    }
6597
6598
118
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
6599
100
      field->type_descriptor_.message_type = type.descriptor();
6600
100
      if (field->type_descriptor_.message_type == nullptr) {
6601
0
        AddError(
6602
0
            field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6603
0
            absl::StrCat("\"", proto.type_name(), "\" is not a message type."));
6604
0
        return;
6605
0
      }
6606
6607
100
      if (field->has_default_value()) {
6608
0
        AddError(field->full_name(), proto,
6609
0
                 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
6610
0
                 "Messages can't have default values.");
6611
0
      }
6612
100
    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
6613
18
      field->type_descriptor_.enum_type = type.enum_descriptor();
6614
18
      if (field->type_descriptor_.enum_type == nullptr) {
6615
0
        AddError(
6616
0
            field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6617
0
            absl::StrCat("\"", proto.type_name(), "\" is not an enum type."));
6618
0
        return;
6619
0
      }
6620
6621
18
      if (field->enum_type()->is_placeholder_) {
6622
        // We can't look up default values for placeholder types.  We'll have
6623
        // to just drop them.
6624
0
        field->has_default_value_ = false;
6625
0
      }
6626
6627
18
      if (field->has_default_value()) {
6628
        // Ensure that the default value is an identifier. Parser cannot always
6629
        // verify this because it does not have complete type information.
6630
        // N.B. that this check yields better error messages but is not
6631
        // necessary for correctness (an enum symbol must be a valid identifier
6632
        // anyway), only for better errors.
6633
8
        if (!io::Tokenizer::IsIdentifier(proto.default_value())) {
6634
0
          AddError(field->full_name(), proto,
6635
0
                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
6636
0
                   "Default value for an enum field must be an identifier.");
6637
8
        } else {
6638
          // We can't just use field->enum_type()->FindValueByName() here
6639
          // because that locks the pool's mutex, which we have already locked
6640
          // at this point.
6641
8
          const EnumValueDescriptor* default_value =
6642
8
              LookupSymbolNoPlaceholder(proto.default_value(),
6643
8
                                        field->enum_type()->full_name())
6644
8
                  .enum_value_descriptor();
6645
6646
8
          if (default_value != nullptr &&
6647
8
              default_value->type() == field->enum_type()) {
6648
8
            field->default_value_enum_ = default_value;
6649
8
          } else {
6650
0
            AddError(
6651
0
                field->full_name(), proto,
6652
0
                DescriptorPool::ErrorCollector::DEFAULT_VALUE,
6653
0
                absl::StrCat("Enum type \"", field->enum_type()->full_name(),
6654
0
                             "\" has no value named \"", proto.default_value(),
6655
0
                             "\"."));
6656
0
          }
6657
8
        }
6658
10
      } else if (field->enum_type()->value_count() > 0) {
6659
        // All enums must have at least one value, or we would have reported
6660
        // an error elsewhere.  We use the first defined value as the default
6661
        // if a default is not explicitly defined.
6662
10
        field->default_value_enum_ = field->enum_type()->value(0);
6663
10
      }
6664
18
    } else {
6665
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6666
0
               "Field with primitive type has type_name.");
6667
0
    }
6668
212
  } else {
6669
212
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
6670
212
        field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
6671
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6672
0
               "Field with message or enum type missing type_name.");
6673
0
    }
6674
212
  }
6675
6676
  // Add the field to the fields-by-number table.
6677
  // Note:  We have to do this *after* cross-linking because extensions do not
6678
  // know their containing type until now. If we're in
6679
  // lazily_build_dependencies_ mode, we're guaranteed there's no errors, so no
6680
  // risk to calling containing_type() or other accessors that will build
6681
  // dependencies.
6682
330
  if (!file_tables_->AddFieldByNumber(field)) {
6683
0
    const FieldDescriptor* conflicting_field = file_tables_->FindFieldByNumber(
6684
0
        field->containing_type(), field->number());
6685
0
    std::string containing_type_name =
6686
0
        field->containing_type() == nullptr
6687
0
            ? "unknown"
6688
0
            : field->containing_type()->full_name();
6689
0
    if (field->is_extension()) {
6690
0
      AddError(field->full_name(), proto,
6691
0
               DescriptorPool::ErrorCollector::NUMBER,
6692
0
               absl::Substitute("Extension number $0 has already been used "
6693
0
                                "in \"$1\" by extension \"$2\".",
6694
0
                                field->number(), containing_type_name,
6695
0
                                conflicting_field->full_name()));
6696
0
    } else {
6697
0
      AddError(field->full_name(), proto,
6698
0
               DescriptorPool::ErrorCollector::NUMBER,
6699
0
               absl::Substitute("Field number $0 has already been used in "
6700
0
                                "\"$1\" by field \"$2\".",
6701
0
                                field->number(), containing_type_name,
6702
0
                                conflicting_field->name()));
6703
0
    }
6704
330
  } else {
6705
330
    if (field->is_extension()) {
6706
0
      if (!tables_->AddExtension(field)) {
6707
0
        const FieldDescriptor* conflicting_field =
6708
0
            tables_->FindExtension(field->containing_type(), field->number());
6709
0
        std::string containing_type_name =
6710
0
            field->containing_type() == nullptr
6711
0
                ? "unknown"
6712
0
                : field->containing_type()->full_name();
6713
0
        std::string error_msg = absl::Substitute(
6714
0
            "Extension number $0 has already been used in \"$1\" by extension "
6715
0
            "\"$2\" defined in $3.",
6716
0
            field->number(), containing_type_name,
6717
0
            conflicting_field->full_name(), conflicting_field->file()->name());
6718
        // Conflicting extension numbers should be an error. However, before
6719
        // turning this into an error we need to fix all existing broken
6720
        // protos first.
6721
        // TODO(xiaofeng): Change this to an error.
6722
0
        AddWarning(field->full_name(), proto,
6723
0
                   DescriptorPool::ErrorCollector::NUMBER, error_msg);
6724
0
      }
6725
0
    }
6726
330
  }
6727
330
}
6728
6729
void DescriptorBuilder::CrossLinkEnum(EnumDescriptor* enum_type,
6730
18
                                      const EnumDescriptorProto& proto) {
6731
18
  if (enum_type->options_ == nullptr) {
6732
18
    enum_type->options_ = &EnumOptions::default_instance();
6733
18
  }
6734
6735
116
  for (int i = 0; i < enum_type->value_count(); i++) {
6736
98
    CrossLinkEnumValue(&enum_type->values_[i], proto.value(i));
6737
98
  }
6738
18
}
6739
6740
void DescriptorBuilder::CrossLinkEnumValue(
6741
    EnumValueDescriptor* enum_value,
6742
98
    const EnumValueDescriptorProto& /* proto */) {
6743
98
  if (enum_value->options_ == nullptr) {
6744
98
    enum_value->options_ = &EnumValueOptions::default_instance();
6745
98
  }
6746
98
}
6747
6748
void DescriptorBuilder::CrossLinkService(ServiceDescriptor* service,
6749
0
                                         const ServiceDescriptorProto& proto) {
6750
0
  if (service->options_ == nullptr) {
6751
0
    service->options_ = &ServiceOptions::default_instance();
6752
0
  }
6753
6754
0
  for (int i = 0; i < service->method_count(); i++) {
6755
0
    CrossLinkMethod(&service->methods_[i], proto.method(i));
6756
0
  }
6757
0
}
6758
6759
void DescriptorBuilder::CrossLinkMethod(MethodDescriptor* method,
6760
0
                                        const MethodDescriptorProto& proto) {
6761
0
  if (method->options_ == nullptr) {
6762
0
    method->options_ = &MethodOptions::default_instance();
6763
0
  }
6764
6765
0
  Symbol input_type =
6766
0
      LookupSymbol(proto.input_type(), method->full_name(),
6767
0
                   DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
6768
0
                   !pool_->lazily_build_dependencies_);
6769
0
  if (input_type.IsNull()) {
6770
0
    if (!pool_->lazily_build_dependencies_) {
6771
0
      AddNotDefinedError(method->full_name(), proto,
6772
0
                         DescriptorPool::ErrorCollector::INPUT_TYPE,
6773
0
                         proto.input_type());
6774
0
    } else {
6775
0
      method->input_type_.SetLazy(proto.input_type(), file_);
6776
0
    }
6777
0
  } else if (input_type.type() != Symbol::MESSAGE) {
6778
0
    AddError(
6779
0
        method->full_name(), proto, DescriptorPool::ErrorCollector::INPUT_TYPE,
6780
0
        absl::StrCat("\"", proto.input_type(), "\" is not a message type."));
6781
0
  } else {
6782
0
    method->input_type_.Set(input_type.descriptor());
6783
0
  }
6784
6785
0
  Symbol output_type =
6786
0
      LookupSymbol(proto.output_type(), method->full_name(),
6787
0
                   DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
6788
0
                   !pool_->lazily_build_dependencies_);
6789
0
  if (output_type.IsNull()) {
6790
0
    if (!pool_->lazily_build_dependencies_) {
6791
0
      AddNotDefinedError(method->full_name(), proto,
6792
0
                         DescriptorPool::ErrorCollector::OUTPUT_TYPE,
6793
0
                         proto.output_type());
6794
0
    } else {
6795
0
      method->output_type_.SetLazy(proto.output_type(), file_);
6796
0
    }
6797
0
  } else if (output_type.type() != Symbol::MESSAGE) {
6798
0
    AddError(
6799
0
        method->full_name(), proto, DescriptorPool::ErrorCollector::OUTPUT_TYPE,
6800
0
        absl::StrCat("\"", proto.output_type(), "\" is not a message type."));
6801
0
  } else {
6802
0
    method->output_type_.Set(output_type.descriptor());
6803
0
  }
6804
0
}
6805
6806
void DescriptorBuilder::SuggestFieldNumbers(FileDescriptor* file,
6807
0
                                            const FileDescriptorProto& proto) {
6808
0
  for (int message_index = 0; message_index < file->message_type_count();
6809
0
       message_index++) {
6810
0
    const Descriptor* message = &file->message_types_[message_index];
6811
0
    auto hints_it = message_hints_.find(message);
6812
0
    if (hints_it == message_hints_.end()) continue;
6813
0
    auto* hints = &hints_it->second;
6814
0
    constexpr int kMaxSuggestions = 3;
6815
0
    int fields_to_suggest = std::min(kMaxSuggestions, hints->fields_to_suggest);
6816
0
    if (fields_to_suggest <= 0) continue;
6817
0
    struct Range {
6818
0
      int from;
6819
0
      int to;
6820
0
    };
6821
0
    std::vector<Range> used_ordinals;
6822
0
    auto add_ordinal = [&](int ordinal) {
6823
0
      if (ordinal <= 0 || ordinal > FieldDescriptor::kMaxNumber) return;
6824
0
      if (!used_ordinals.empty() &&
6825
0
          ordinal == used_ordinals.back().to) {
6826
0
        used_ordinals.back().to = ordinal + 1;
6827
0
      } else {
6828
0
        used_ordinals.push_back({ordinal, ordinal + 1});
6829
0
      }
6830
0
    };
6831
0
    auto add_range = [&](int from, int to) {
6832
0
      from = std::max(0, std::min(FieldDescriptor::kMaxNumber + 1, from));
6833
0
      to = std::max(0, std::min(FieldDescriptor::kMaxNumber + 1, to));
6834
0
      if (from >= to) return;
6835
0
      used_ordinals.push_back({from, to});
6836
0
    };
6837
0
    for (int i = 0; i < message->field_count(); i++) {
6838
0
      add_ordinal(message->field(i)->number());
6839
0
    }
6840
0
    for (int i = 0; i < message->extension_count(); i++) {
6841
0
      add_ordinal(message->extension(i)->number());
6842
0
    }
6843
0
    for (int i = 0; i < message->reserved_range_count(); i++) {
6844
0
      auto range = message->reserved_range(i);
6845
0
      add_range(range->start, range->end);
6846
0
    }
6847
0
    for (int i = 0; i < message->extension_range_count(); i++) {
6848
0
      auto range = message->extension_range(i);
6849
0
      add_range(range->start, range->end);
6850
0
    }
6851
0
    used_ordinals.push_back(
6852
0
        {FieldDescriptor::kMaxNumber, FieldDescriptor::kMaxNumber + 1});
6853
0
    used_ordinals.push_back({FieldDescriptor::kFirstReservedNumber,
6854
0
                             FieldDescriptor::kLastReservedNumber});
6855
0
    std::sort(used_ordinals.begin(), used_ordinals.end(),
6856
0
              [](Range lhs, Range rhs) {
6857
0
                return std::tie(lhs.from, lhs.to) < std::tie(rhs.from, rhs.to);
6858
0
              });
6859
0
    int current_ordinal = 1;
6860
0
    std::stringstream id_list;
6861
0
    id_list << "Suggested field numbers for " << message->full_name() << ": ";
6862
0
    const char* separator = "";
6863
0
    for (auto& current_range : used_ordinals) {
6864
0
      while (current_ordinal < current_range.from && fields_to_suggest > 0) {
6865
0
        id_list << separator << current_ordinal++;
6866
0
        separator = ", ";
6867
0
        fields_to_suggest--;
6868
0
      }
6869
0
      if (fields_to_suggest == 0) break;
6870
0
      current_ordinal = std::max(current_ordinal, current_range.to);
6871
0
    }
6872
0
    if (hints->first_reason) {
6873
0
      AddError(message->full_name(), *hints->first_reason,
6874
0
               hints->first_reason_location, id_list.str());
6875
0
    }
6876
0
  }
6877
0
}
6878
6879
// -------------------------------------------------------------------
6880
6881
#define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type) \
6882
0
  for (int i = 0; i < descriptor->array_name##_count(); ++i) {    \
6883
0
    Validate##type##Options(descriptor->array_name##s_ + i,       \
6884
0
                            proto.array_name(i));                 \
6885
0
  }
6886
6887
// Determine if the file uses optimize_for = LITE_RUNTIME, being careful to
6888
// avoid problems that exist at init time.
6889
0
static bool IsLite(const FileDescriptor* file) {
6890
  // TODO(kenton):  I don't even remember how many of these conditions are
6891
  //   actually possible.  I'm just being super-safe.
6892
0
  return file != nullptr &&
6893
0
         &file->options() != &FileOptions::default_instance() &&
6894
0
         file->options().optimize_for() == FileOptions::LITE_RUNTIME;
6895
0
}
6896
6897
void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
6898
0
                                            const FileDescriptorProto& proto) {
6899
0
  VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
6900
0
  VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
6901
0
  VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
6902
0
  VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field);
6903
6904
  // Lite files can only be imported by other Lite files.
6905
0
  if (!IsLite(file)) {
6906
0
    for (int i = 0; i < file->dependency_count(); i++) {
6907
0
      if (IsLite(file->dependency(i))) {
6908
0
        AddError(
6909
0
            file->dependency(i)->name(), proto,
6910
0
            DescriptorPool::ErrorCollector::IMPORT,
6911
0
            absl::StrCat("Files that do not use optimize_for = LITE_RUNTIME "
6912
0
                         "cannot import files which do use this option.  This "
6913
0
                         "file is not lite, but it imports \"",
6914
0
                         file->dependency(i)->name(), "\" which is."));
6915
0
        break;
6916
0
      }
6917
0
    }
6918
0
  }
6919
0
  if (file->syntax() == FileDescriptor::SYNTAX_PROTO3) {
6920
0
    ValidateProto3(file, proto);
6921
0
  }
6922
0
}
6923
6924
void DescriptorBuilder::ValidateProto3(FileDescriptor* file,
6925
0
                                       const FileDescriptorProto& proto) {
6926
0
  for (int i = 0; i < file->extension_count(); ++i) {
6927
0
    ValidateProto3Field(file->extensions_ + i, proto.extension(i));
6928
0
  }
6929
0
  for (int i = 0; i < file->message_type_count(); ++i) {
6930
0
    ValidateProto3Message(file->message_types_ + i, proto.message_type(i));
6931
0
  }
6932
0
  for (int i = 0; i < file->enum_type_count(); ++i) {
6933
0
    ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i));
6934
0
  }
6935
0
}
6936
6937
void DescriptorBuilder::ValidateProto3Message(Descriptor* message,
6938
0
                                              const DescriptorProto& proto) {
6939
0
  for (int i = 0; i < message->nested_type_count(); ++i) {
6940
0
    ValidateProto3Message(message->nested_types_ + i, proto.nested_type(i));
6941
0
  }
6942
0
  for (int i = 0; i < message->enum_type_count(); ++i) {
6943
0
    ValidateProto3Enum(message->enum_types_ + i, proto.enum_type(i));
6944
0
  }
6945
0
  for (int i = 0; i < message->field_count(); ++i) {
6946
0
    ValidateProto3Field(message->fields_ + i, proto.field(i));
6947
0
  }
6948
0
  for (int i = 0; i < message->extension_count(); ++i) {
6949
0
    ValidateProto3Field(message->extensions_ + i, proto.extension(i));
6950
0
  }
6951
0
  if (message->extension_range_count() > 0) {
6952
0
    AddError(message->full_name(), proto.extension_range(0),
6953
0
             DescriptorPool::ErrorCollector::NUMBER,
6954
0
             "Extension ranges are not allowed in proto3.");
6955
0
  }
6956
0
  if (message->options().message_set_wire_format()) {
6957
    // Using MessageSet doesn't make sense since we disallow extensions.
6958
0
    AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6959
0
             "MessageSet is not supported in proto3.");
6960
0
  }
6961
0
}
6962
6963
void DescriptorBuilder::ValidateProto3Field(FieldDescriptor* field,
6964
0
                                            const FieldDescriptorProto& proto) {
6965
0
  if (field->is_extension() &&
6966
0
      !AllowedExtendeeInProto3(field->containing_type()->full_name())) {
6967
0
    AddError(field->full_name(), proto,
6968
0
             DescriptorPool::ErrorCollector::EXTENDEE,
6969
0
             "Extensions in proto3 are only allowed for defining options.");
6970
0
  }
6971
0
  if (field->is_required()) {
6972
0
    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6973
0
             "Required fields are not allowed in proto3.");
6974
0
  }
6975
0
  if (field->has_default_value()) {
6976
0
    AddError(field->full_name(), proto,
6977
0
             DescriptorPool::ErrorCollector::DEFAULT_VALUE,
6978
0
             "Explicit default values are not allowed in proto3.");
6979
0
  }
6980
0
  if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
6981
0
      field->enum_type() &&
6982
0
      field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 &&
6983
0
      field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_UNKNOWN) {
6984
    // Proto3 messages can only use Proto3 enum types; otherwise we can't
6985
    // guarantee that the default value is zero.
6986
0
    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6987
0
             absl::StrCat("Enum type \"", field->enum_type()->full_name(),
6988
0
                          "\" is not a proto3 enum, but is used in \"",
6989
0
                          field->containing_type()->full_name(),
6990
0
                          "\" which is a proto3 message type."));
6991
0
  }
6992
0
  if (field->type() == FieldDescriptor::TYPE_GROUP) {
6993
0
    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6994
0
             "Groups are not supported in proto3 syntax.");
6995
0
  }
6996
0
}
6997
6998
void DescriptorBuilder::ValidateProto3Enum(EnumDescriptor* enm,
6999
0
                                           const EnumDescriptorProto& proto) {
7000
0
  if (enm->value_count() > 0 && enm->value(0)->number() != 0) {
7001
0
    AddError(enm->full_name(), proto.value(0),
7002
0
             DescriptorPool::ErrorCollector::NUMBER,
7003
0
             "The first enum value must be zero in proto3.");
7004
0
  }
7005
0
}
7006
7007
void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
7008
0
                                               const DescriptorProto& proto) {
7009
0
  VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field);
7010
0
  VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message);
7011
0
  VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum);
7012
0
  VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field);
7013
7014
0
  CheckFieldJsonNameUniqueness(proto, message);
7015
7016
0
  const int64_t max_extension_range =
7017
0
      static_cast<int64_t>(message->options().message_set_wire_format()
7018
0
                               ? std::numeric_limits<int32_t>::max()
7019
0
                               : FieldDescriptor::kMaxNumber);
7020
0
  for (int i = 0; i < message->extension_range_count(); ++i) {
7021
0
    if (message->extension_range(i)->end > max_extension_range + 1) {
7022
0
      AddError(message->full_name(), proto.extension_range(i),
7023
0
               DescriptorPool::ErrorCollector::NUMBER,
7024
0
               absl::Substitute("Extension numbers cannot be greater than $0.",
7025
0
                                max_extension_range));
7026
0
    }
7027
7028
0
    ValidateExtensionRangeOptions(message->full_name(),
7029
0
                                  message->extension_ranges_ + i,
7030
0
                                  proto.extension_range(i));
7031
0
  }
7032
0
}
7033
7034
7035
void DescriptorBuilder::ValidateFieldOptions(
7036
0
    FieldDescriptor* field, const FieldDescriptorProto& proto) {
7037
0
  if (pool_->lazily_build_dependencies_ && (!field || !field->message_type())) {
7038
0
    return;
7039
0
  }
7040
  // Only message type fields may be lazy.
7041
0
  if (field->options().lazy() || field->options().unverified_lazy()) {
7042
0
    if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
7043
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7044
0
               "[lazy = true] can only be specified for submessage fields.");
7045
0
    }
7046
0
  }
7047
7048
  // Only repeated primitive fields may be packed.
7049
0
  if (field->options().packed() && !field->is_packable()) {
7050
0
    AddError(
7051
0
        field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7052
0
        "[packed = true] can only be specified for repeated primitive fields.");
7053
0
  }
7054
7055
  // Note:  Default instance may not yet be initialized here, so we have to
7056
  //   avoid reading from it.
7057
0
  if (field->containing_type_ != nullptr &&
7058
0
      &field->containing_type()->options() !=
7059
0
          &MessageOptions::default_instance() &&
7060
0
      field->containing_type()->options().message_set_wire_format()) {
7061
0
    if (field->is_extension()) {
7062
0
      if (!field->is_optional() ||
7063
0
          field->type() != FieldDescriptor::TYPE_MESSAGE) {
7064
0
        AddError(field->full_name(), proto,
7065
0
                 DescriptorPool::ErrorCollector::TYPE,
7066
0
                 "Extensions of MessageSets must be optional messages.");
7067
0
      }
7068
0
    } else {
7069
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
7070
0
               "MessageSets cannot have fields, only extensions.");
7071
0
    }
7072
0
  }
7073
7074
  // Lite extensions can only be of Lite types.
7075
0
  if (IsLite(field->file()) && field->containing_type_ != nullptr &&
7076
0
      !IsLite(field->containing_type()->file())) {
7077
0
    AddError(field->full_name(), proto,
7078
0
             DescriptorPool::ErrorCollector::EXTENDEE,
7079
0
             "Extensions to non-lite types can only be declared in non-lite "
7080
0
             "files.  Note that you cannot extend a non-lite type to contain "
7081
0
             "a lite type, but the reverse is allowed.");
7082
0
  }
7083
7084
  // Validate map types.
7085
0
  if (field->is_map()) {
7086
0
    if (!ValidateMapEntry(field, proto)) {
7087
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7088
0
               "map_entry should not be set explicitly. Use map<KeyType, "
7089
0
               "ValueType> instead.");
7090
0
    }
7091
0
  }
7092
7093
0
  ValidateJSType(field, proto);
7094
7095
  // json_name option is not allowed on extension fields. Note that the
7096
  // json_name field in FieldDescriptorProto is always populated by protoc
7097
  // when it sends descriptor data to plugins (calculated from field name if
7098
  // the option is not explicitly set) so we can't rely on its presence to
7099
  // determine whether the json_name option is set on the field. Here we
7100
  // compare it against the default calculated json_name value and consider
7101
  // the option set if they are different. This won't catch the case when
7102
  // a user explicitly sets json_name to the default value, but should be
7103
  // good enough to catch common misuses.
7104
0
  if (field->is_extension() &&
7105
0
      (field->has_json_name() &&
7106
0
       field->json_name() != ToJsonName(field->name()))) {
7107
0
    AddError(field->full_name(), proto,
7108
0
             DescriptorPool::ErrorCollector::OPTION_NAME,
7109
0
             "option json_name is not allowed on extension fields.");
7110
0
  }
7111
7112
0
}
7113
7114
void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
7115
0
                                            const EnumDescriptorProto& proto) {
7116
0
  VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue);
7117
7118
0
  CheckEnumValueUniqueness(proto, enm);
7119
7120
0
  if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) {
7121
0
    absl::flat_hash_map<int, std::string> used_values;
7122
0
    for (int i = 0; i < enm->value_count(); ++i) {
7123
0
      const EnumValueDescriptor* enum_value = enm->value(i);
7124
0
      auto insert_result =
7125
0
          used_values.emplace(enum_value->number(), enum_value->full_name());
7126
0
      bool inserted = insert_result.second;
7127
0
      if (!inserted) {
7128
0
        std::string error = absl::StrCat(
7129
0
            "\"", enum_value->full_name(), "\" uses the same enum value as \"",
7130
0
            insert_result.first->second,
7131
0
            "\". If this is intended, set "
7132
0
            "'option allow_alias = true;' to the enum definition.");
7133
0
        if (!enm->options().allow_alias()) {
7134
          // Generate error if duplicated enum values are explicitly disallowed.
7135
0
          AddError(enm->full_name(), proto.value(i),
7136
0
                   DescriptorPool::ErrorCollector::NUMBER, error);
7137
0
        }
7138
0
      }
7139
0
    }
7140
0
  }
7141
0
}
7142
7143
void DescriptorBuilder::ValidateEnumValueOptions(
7144
    EnumValueDescriptor* /* enum_value */,
7145
0
    const EnumValueDescriptorProto& /* proto */) {
7146
  // Nothing to do so far.
7147
0
}
7148
7149
void DescriptorBuilder::ValidateExtensionRangeOptions(
7150
    const std::string& full_name, Descriptor::ExtensionRange* extension_range,
7151
0
    const DescriptorProto_ExtensionRange& proto) {
7152
0
  (void)full_name;        // Parameter is used by Google-internal code.
7153
0
  (void)extension_range;  // Parameter is used by Google-internal code.
7154
0
}
7155
7156
void DescriptorBuilder::ValidateServiceOptions(
7157
0
    ServiceDescriptor* service, const ServiceDescriptorProto& proto) {
7158
0
  if (IsLite(service->file()) &&
7159
0
      (service->file()->options().cc_generic_services() ||
7160
0
       service->file()->options().java_generic_services())) {
7161
0
    AddError(service->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
7162
0
             "Files with optimize_for = LITE_RUNTIME cannot define services "
7163
0
             "unless you set both options cc_generic_services and "
7164
0
             "java_generic_services to false.");
7165
0
  }
7166
7167
0
  VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
7168
0
}
7169
7170
void DescriptorBuilder::ValidateMethodOptions(
7171
0
    MethodDescriptor* /* method */, const MethodDescriptorProto& /* proto */) {
7172
  // Nothing to do so far.
7173
0
}
7174
7175
bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
7176
0
                                         const FieldDescriptorProto& proto) {
7177
0
  const Descriptor* message = field->message_type();
7178
0
  if (  // Must not contain extensions, extension range or nested message or
7179
        // enums
7180
0
      message->extension_count() != 0 ||
7181
0
      field->label() != FieldDescriptor::LABEL_REPEATED ||
7182
0
      message->extension_range_count() != 0 ||
7183
0
      message->nested_type_count() != 0 || message->enum_type_count() != 0 ||
7184
      // Must contain exactly two fields
7185
0
      message->field_count() != 2 ||
7186
      // Field name and message name must match
7187
0
      message->name() !=
7188
0
          absl::StrCat(ToCamelCase(field->name(), false), "Entry") ||
7189
      // Entry message must be in the same containing type of the field.
7190
0
      field->containing_type() != message->containing_type()) {
7191
0
    return false;
7192
0
  }
7193
7194
0
  const FieldDescriptor* key = message->map_key();
7195
0
  const FieldDescriptor* value = message->map_value();
7196
0
  if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 ||
7197
0
      key->name() != "key") {
7198
0
    return false;
7199
0
  }
7200
0
  if (value->label() != FieldDescriptor::LABEL_OPTIONAL ||
7201
0
      value->number() != 2 || value->name() != "value") {
7202
0
    return false;
7203
0
  }
7204
7205
  // Check key types are legal.
7206
0
  switch (key->type()) {
7207
0
    case FieldDescriptor::TYPE_ENUM:
7208
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7209
0
               "Key in map fields cannot be enum types.");
7210
0
      break;
7211
0
    case FieldDescriptor::TYPE_FLOAT:
7212
0
    case FieldDescriptor::TYPE_DOUBLE:
7213
0
    case FieldDescriptor::TYPE_MESSAGE:
7214
0
    case FieldDescriptor::TYPE_GROUP:
7215
0
    case FieldDescriptor::TYPE_BYTES:
7216
0
      AddError(
7217
0
          field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7218
0
          "Key in map fields cannot be float/double, bytes or message types.");
7219
0
      break;
7220
0
    case FieldDescriptor::TYPE_BOOL:
7221
0
    case FieldDescriptor::TYPE_INT32:
7222
0
    case FieldDescriptor::TYPE_INT64:
7223
0
    case FieldDescriptor::TYPE_SINT32:
7224
0
    case FieldDescriptor::TYPE_SINT64:
7225
0
    case FieldDescriptor::TYPE_STRING:
7226
0
    case FieldDescriptor::TYPE_UINT32:
7227
0
    case FieldDescriptor::TYPE_UINT64:
7228
0
    case FieldDescriptor::TYPE_FIXED32:
7229
0
    case FieldDescriptor::TYPE_FIXED64:
7230
0
    case FieldDescriptor::TYPE_SFIXED32:
7231
0
    case FieldDescriptor::TYPE_SFIXED64:
7232
      // Legal cases
7233
0
      break;
7234
      // Do not add a default, so that the compiler will complain when new types
7235
      // are added.
7236
0
  }
7237
7238
0
  if (value->type() == FieldDescriptor::TYPE_ENUM) {
7239
0
    if (value->enum_type()->value(0)->number() != 0) {
7240
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7241
0
               "Enum value in map must define 0 as the first value.");
7242
0
    }
7243
0
  }
7244
7245
0
  return true;
7246
0
}
7247
7248
void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
7249
0
                                           const DescriptorProto& proto) {
7250
0
  absl::flat_hash_map<std::string, const Descriptor*> seen_types;
7251
0
  for (int i = 0; i < message->nested_type_count(); ++i) {
7252
0
    const Descriptor* nested = message->nested_type(i);
7253
0
    auto insert_result = seen_types.emplace(nested->name(), nested);
7254
0
    bool inserted = insert_result.second;
7255
0
    if (!inserted) {
7256
0
      if (insert_result.first->second->options().map_entry() ||
7257
0
          nested->options().map_entry()) {
7258
0
        AddError(
7259
0
            message->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
7260
0
            absl::StrCat("Expanded map entry type ", nested->name(),
7261
0
                         " conflicts with an existing nested message type."));
7262
0
        break;
7263
0
      }
7264
0
    }
7265
    // Recursively test on the nested types.
7266
0
    DetectMapConflicts(message->nested_type(i), proto.nested_type(i));
7267
0
  }
7268
  // Check for conflicted field names.
7269
0
  for (int i = 0; i < message->field_count(); ++i) {
7270
0
    const FieldDescriptor* field = message->field(i);
7271
0
    auto iter = seen_types.find(field->name());
7272
0
    if (iter != seen_types.end() && iter->second->options().map_entry()) {
7273
0
      AddError(message->full_name(), proto,
7274
0
               DescriptorPool::ErrorCollector::NAME,
7275
0
               absl::StrCat("Expanded map entry type ", iter->second->name(),
7276
0
                            " conflicts with an existing field."));
7277
0
    }
7278
0
  }
7279
  // Check for conflicted enum names.
7280
0
  for (int i = 0; i < message->enum_type_count(); ++i) {
7281
0
    const EnumDescriptor* enum_desc = message->enum_type(i);
7282
0
    auto iter = seen_types.find(enum_desc->name());
7283
0
    if (iter != seen_types.end() && iter->second->options().map_entry()) {
7284
0
      AddError(message->full_name(), proto,
7285
0
               DescriptorPool::ErrorCollector::NAME,
7286
0
               absl::StrCat("Expanded map entry type ", iter->second->name(),
7287
0
                            " conflicts with an existing enum type."));
7288
0
    }
7289
0
  }
7290
  // Check for conflicted oneof names.
7291
0
  for (int i = 0; i < message->oneof_decl_count(); ++i) {
7292
0
    const OneofDescriptor* oneof_desc = message->oneof_decl(i);
7293
0
    auto iter = seen_types.find(oneof_desc->name());
7294
0
    if (iter != seen_types.end() && iter->second->options().map_entry()) {
7295
0
      AddError(message->full_name(), proto,
7296
0
               DescriptorPool::ErrorCollector::NAME,
7297
0
               absl::StrCat("Expanded map entry type ", iter->second->name(),
7298
0
                            " conflicts with an existing oneof type."));
7299
0
    }
7300
0
  }
7301
0
}
7302
7303
void DescriptorBuilder::ValidateJSType(FieldDescriptor* field,
7304
0
                                       const FieldDescriptorProto& proto) {
7305
0
  FieldOptions::JSType jstype = field->options().jstype();
7306
  // The default is always acceptable.
7307
0
  if (jstype == FieldOptions::JS_NORMAL) {
7308
0
    return;
7309
0
  }
7310
7311
0
  switch (field->type()) {
7312
    // Integral 64-bit types may be represented as JavaScript numbers or
7313
    // strings.
7314
0
    case FieldDescriptor::TYPE_UINT64:
7315
0
    case FieldDescriptor::TYPE_INT64:
7316
0
    case FieldDescriptor::TYPE_SINT64:
7317
0
    case FieldDescriptor::TYPE_FIXED64:
7318
0
    case FieldDescriptor::TYPE_SFIXED64:
7319
0
      if (jstype == FieldOptions::JS_STRING ||
7320
0
          jstype == FieldOptions::JS_NUMBER) {
7321
0
        return;
7322
0
      }
7323
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7324
0
               absl::StrCat(
7325
0
                   "Illegal jstype for int64, uint64, sint64, fixed64 "
7326
0
                   "or sfixed64 field: ",
7327
0
                   FieldOptions_JSType_descriptor()->value(jstype)->name()));
7328
0
      break;
7329
7330
    // No other types permit a jstype option.
7331
0
    default:
7332
0
      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
7333
0
               "jstype is only allowed on int64, uint64, sint64, fixed64 "
7334
0
               "or sfixed64 fields.");
7335
0
      break;
7336
0
  }
7337
0
}
7338
7339
#undef VALIDATE_OPTIONS_FROM_ARRAY
7340
7341
// -------------------------------------------------------------------
7342
7343
DescriptorBuilder::OptionInterpreter::OptionInterpreter(
7344
    DescriptorBuilder* builder)
7345
6
    : builder_(builder) {
7346
6
  ABSL_CHECK(builder_);
7347
6
}
7348
7349
6
DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {}
7350
7351
bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
7352
0
    OptionsToInterpret* options_to_interpret) {
7353
  // Note that these may be in different pools, so we can't use the same
7354
  // descriptor and reflection objects on both.
7355
0
  Message* options = options_to_interpret->options;
7356
0
  const Message* original_options = options_to_interpret->original_options;
7357
7358
0
  bool failed = false;
7359
0
  options_to_interpret_ = options_to_interpret;
7360
7361
  // Find the uninterpreted_option field in the mutable copy of the options
7362
  // and clear them, since we're about to interpret them.
7363
0
  const FieldDescriptor* uninterpreted_options_field =
7364
0
      options->GetDescriptor()->FindFieldByName("uninterpreted_option");
7365
0
  ABSL_CHECK(uninterpreted_options_field != nullptr)
7366
0
      << "No field named \"uninterpreted_option\" in the Options proto.";
7367
0
  options->GetReflection()->ClearField(options, uninterpreted_options_field);
7368
7369
0
  std::vector<int> src_path = options_to_interpret->element_path;
7370
0
  src_path.push_back(uninterpreted_options_field->number());
7371
7372
  // Find the uninterpreted_option field in the original options.
7373
0
  const FieldDescriptor* original_uninterpreted_options_field =
7374
0
      original_options->GetDescriptor()->FindFieldByName(
7375
0
          "uninterpreted_option");
7376
0
  ABSL_CHECK(original_uninterpreted_options_field != nullptr)
7377
0
      << "No field named \"uninterpreted_option\" in the Options proto.";
7378
7379
0
  const int num_uninterpreted_options =
7380
0
      original_options->GetReflection()->FieldSize(
7381
0
          *original_options, original_uninterpreted_options_field);
7382
0
  for (int i = 0; i < num_uninterpreted_options; ++i) {
7383
0
    src_path.push_back(i);
7384
0
    uninterpreted_option_ = DownCast<const UninterpretedOption*>(
7385
0
        &original_options->GetReflection()->GetRepeatedMessage(
7386
0
            *original_options, original_uninterpreted_options_field, i));
7387
0
    if (!InterpretSingleOption(options, src_path,
7388
0
                               options_to_interpret->element_path)) {
7389
      // Error already added by InterpretSingleOption().
7390
0
      failed = true;
7391
0
      break;
7392
0
    }
7393
0
    src_path.pop_back();
7394
0
  }
7395
  // Reset these, so we don't have any dangling pointers.
7396
0
  uninterpreted_option_ = nullptr;
7397
0
  options_to_interpret_ = nullptr;
7398
7399
0
  if (!failed) {
7400
    // InterpretSingleOption() added the interpreted options in the
7401
    // UnknownFieldSet, in case the option isn't yet known to us.  Now we
7402
    // serialize the options message and deserialize it back.  That way, any
7403
    // option fields that we do happen to know about will get moved from the
7404
    // UnknownFieldSet into the real fields, and thus be available right away.
7405
    // If they are not known, that's OK too. They will get reparsed into the
7406
    // UnknownFieldSet and wait there until the message is parsed by something
7407
    // that does know about the options.
7408
7409
    // Keep the unparsed options around in case the reparsing fails.
7410
0
    std::unique_ptr<Message> unparsed_options(options->New());
7411
0
    options->GetReflection()->Swap(unparsed_options.get(), options);
7412
7413
0
    std::string buf;
7414
0
    if (!unparsed_options->AppendToString(&buf) ||
7415
0
        !options->ParseFromString(buf)) {
7416
0
      builder_->AddError(
7417
0
          options_to_interpret->element_name, *original_options,
7418
0
          DescriptorPool::ErrorCollector::OTHER,
7419
0
          absl::StrCat(
7420
0
              "Some options could not be correctly parsed using the proto "
7421
0
              "descriptors compiled into this binary.\n"
7422
0
              "Unparsed options: ",
7423
0
              unparsed_options->ShortDebugString(),
7424
0
              "\n"
7425
0
              "Parsing attempt:  ",
7426
0
              options->ShortDebugString()));
7427
      // Restore the unparsed options.
7428
0
      options->GetReflection()->Swap(unparsed_options.get(), options);
7429
0
    }
7430
0
  }
7431
7432
0
  return !failed;
7433
0
}
7434
7435
bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
7436
    Message* options, const std::vector<int>& src_path,
7437
0
    const std::vector<int>& options_path) {
7438
  // First do some basic validation.
7439
0
  if (uninterpreted_option_->name_size() == 0) {
7440
    // This should never happen unless the parser has gone seriously awry or
7441
    // someone has manually created the uninterpreted option badly.
7442
0
    return AddNameError("Option must have a name.");
7443
0
  }
7444
0
  if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") {
7445
0
    return AddNameError(
7446
0
        "Option must not use reserved name \"uninterpreted_option\".");
7447
0
  }
7448
7449
0
  const Descriptor* options_descriptor = nullptr;
7450
  // Get the options message's descriptor from the builder's pool, so that we
7451
  // get the version that knows about any extension options declared in the file
7452
  // we're currently building. The descriptor should be there as long as the
7453
  // file we're building imported descriptor.proto.
7454
7455
  // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
7456
  // DescriptorPool::FindMessageTypeByName() because we're already holding the
7457
  // pool's mutex, and the latter method locks it again.  We don't use
7458
  // FindSymbol() because files that use custom options only need to depend on
7459
  // the file that defines the option, not descriptor.proto itself.
7460
0
  Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
7461
0
      options->GetDescriptor()->full_name());
7462
0
  options_descriptor = symbol.descriptor();
7463
0
  if (options_descriptor == nullptr) {
7464
    // The options message's descriptor was not in the builder's pool, so use
7465
    // the standard version from the generated pool. We're not holding the
7466
    // generated pool's mutex, so we can search it the straightforward way.
7467
0
    options_descriptor = options->GetDescriptor();
7468
0
  }
7469
0
  ABSL_CHECK(options_descriptor);
7470
7471
  // We iterate over the name parts to drill into the submessages until we find
7472
  // the leaf field for the option. As we drill down we remember the current
7473
  // submessage's descriptor in |descriptor| and the next field in that
7474
  // submessage in |field|. We also track the fields we're drilling down
7475
  // through in |intermediate_fields|. As we go, we reconstruct the full option
7476
  // name in |debug_msg_name|, for use in error messages.
7477
0
  const Descriptor* descriptor = options_descriptor;
7478
0
  const FieldDescriptor* field = nullptr;
7479
0
  std::vector<const FieldDescriptor*> intermediate_fields;
7480
0
  std::string debug_msg_name = "";
7481
7482
0
  std::vector<int> dest_path = options_path;
7483
7484
0
  for (int i = 0; i < uninterpreted_option_->name_size(); ++i) {
7485
0
    builder_->undefine_resolved_name_.clear();
7486
0
    const std::string& name_part = uninterpreted_option_->name(i).name_part();
7487
0
    if (!debug_msg_name.empty()) {
7488
0
      absl::StrAppend(&debug_msg_name, ".");
7489
0
    }
7490
0
    if (uninterpreted_option_->name(i).is_extension()) {
7491
0
      absl::StrAppend(&debug_msg_name, "(", name_part, ")");
7492
      // Search for the extension's descriptor as an extension in the builder's
7493
      // pool. Note that we use DescriptorBuilder::LookupSymbol(), not
7494
      // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows
7495
      // relative lookups, and 2) because we're already holding the pool's
7496
      // mutex, and the latter method locks it again.
7497
0
      symbol =
7498
0
          builder_->LookupSymbol(name_part, options_to_interpret_->name_scope);
7499
0
      field = symbol.field_descriptor();
7500
      // If we don't find the field then the field's descriptor was not in the
7501
      // builder's pool, but there's no point in looking in the generated
7502
      // pool. We require that you import the file that defines any extensions
7503
      // you use, so they must be present in the builder's pool.
7504
0
    } else {
7505
0
      absl::StrAppend(&debug_msg_name, name_part);
7506
      // Search for the field's descriptor as a regular field.
7507
0
      field = descriptor->FindFieldByName(name_part);
7508
0
    }
7509
7510
0
    if (field == nullptr) {
7511
0
      if (get_allow_unknown(builder_->pool_)) {
7512
        // We can't find the option, but AllowUnknownDependencies() is enabled,
7513
        // so we will just leave it as uninterpreted.
7514
0
        AddWithoutInterpreting(*uninterpreted_option_, options);
7515
0
        return true;
7516
0
      } else if (!(builder_->undefine_resolved_name_).empty()) {
7517
        // Option is resolved to a name which is not defined.
7518
0
        return AddNameError(absl::StrCat(
7519
0
            "Option \"", debug_msg_name, "\" is resolved to \"(",
7520
0
            builder_->undefine_resolved_name_,
7521
0
            ")\", which is not defined. The innermost scope is searched first "
7522
0
            "in name resolution. Consider using a leading '.'(i.e., \"(.",
7523
0
            debug_msg_name.substr(1),
7524
0
            "\") to start from the outermost scope."));
7525
0
      } else {
7526
0
        return AddNameError(absl::StrCat(
7527
0
            "Option \"", debug_msg_name, "\" unknown. Ensure that your proto",
7528
0
            " definition file imports the proto which defines the option."));
7529
0
      }
7530
0
    } else if (field->containing_type() != descriptor) {
7531
0
      if (get_is_placeholder(field->containing_type())) {
7532
        // The field is an extension of a placeholder type, so we can't
7533
        // reliably verify whether it is a valid extension to use here (e.g.
7534
        // we don't know if it is an extension of the correct *Options message,
7535
        // or if it has a valid field number, etc.).  Just leave it as
7536
        // uninterpreted instead.
7537
0
        AddWithoutInterpreting(*uninterpreted_option_, options);
7538
0
        return true;
7539
0
      } else {
7540
        // This can only happen if, due to some insane misconfiguration of the
7541
        // pools, we find the options message in one pool but the field in
7542
        // another. This would probably imply a hefty bug somewhere.
7543
0
        return AddNameError(
7544
0
            absl::StrCat("Option field \"", debug_msg_name,
7545
0
                         "\" is not a field or extension of message \"",
7546
0
                         descriptor->name(), "\"."));
7547
0
      }
7548
0
    } else {
7549
      // accumulate field numbers to form path to interpreted option
7550
0
      dest_path.push_back(field->number());
7551
7552
0
      if (i < uninterpreted_option_->name_size() - 1) {
7553
0
        if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
7554
0
          return AddNameError(
7555
0
              absl::StrCat("Option \"", debug_msg_name,
7556
0
                           "\" is an atomic type, not a message."));
7557
0
        } else if (field->is_repeated()) {
7558
0
          return AddNameError(
7559
0
              absl::StrCat("Option field \"", debug_msg_name,
7560
0
                           "\" is a repeated message. Repeated message "
7561
0
                           "options must be initialized using an "
7562
0
                           "aggregate value."));
7563
0
        } else {
7564
          // Drill down into the submessage.
7565
0
          intermediate_fields.push_back(field);
7566
0
          descriptor = field->message_type();
7567
0
        }
7568
0
      }
7569
0
    }
7570
0
  }
7571
7572
  // We've found the leaf field. Now we use UnknownFieldSets to set its value
7573
  // on the options message. We do so because the message may not yet know
7574
  // about its extension fields, so we may not be able to set the fields
7575
  // directly. But the UnknownFieldSets will serialize to the same wire-format
7576
  // message, so reading that message back in once the extension fields are
7577
  // known will populate them correctly.
7578
7579
  // First see if the option is already set.
7580
0
  if (!field->is_repeated() &&
7581
0
      !ExamineIfOptionIsSet(
7582
0
          intermediate_fields.begin(), intermediate_fields.end(), field,
7583
0
          debug_msg_name,
7584
0
          options->GetReflection()->GetUnknownFields(*options))) {
7585
0
    return false;  // ExamineIfOptionIsSet() already added the error.
7586
0
  }
7587
7588
  // First set the value on the UnknownFieldSet corresponding to the
7589
  // innermost message.
7590
0
  std::unique_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
7591
0
  if (!SetOptionValue(field, unknown_fields.get())) {
7592
0
    return false;  // SetOptionValue() already added the error.
7593
0
  }
7594
7595
  // Now wrap the UnknownFieldSet with UnknownFieldSets corresponding to all
7596
  // the intermediate messages.
7597
0
  for (std::vector<const FieldDescriptor*>::reverse_iterator iter =
7598
0
           intermediate_fields.rbegin();
7599
0
       iter != intermediate_fields.rend(); ++iter) {
7600
0
    std::unique_ptr<UnknownFieldSet> parent_unknown_fields(
7601
0
        new UnknownFieldSet());
7602
0
    switch ((*iter)->type()) {
7603
0
      case FieldDescriptor::TYPE_MESSAGE: {
7604
0
        std::string* outstr =
7605
0
            parent_unknown_fields->AddLengthDelimited((*iter)->number());
7606
0
        ABSL_CHECK(unknown_fields->SerializeToString(outstr))
7607
0
            << "Unexpected failure while serializing option submessage "
7608
0
            << debug_msg_name << "\".";
7609
0
        break;
7610
0
      }
7611
7612
0
      case FieldDescriptor::TYPE_GROUP: {
7613
0
        parent_unknown_fields->AddGroup((*iter)->number())
7614
0
            ->MergeFrom(*unknown_fields);
7615
0
        break;
7616
0
      }
7617
7618
0
      default:
7619
0
        ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: "
7620
0
                        << (*iter)->type();
7621
0
        return false;
7622
0
    }
7623
0
    unknown_fields.reset(parent_unknown_fields.release());
7624
0
  }
7625
7626
  // Now merge the UnknownFieldSet corresponding to the top-level message into
7627
  // the options message.
7628
0
  options->GetReflection()->MutableUnknownFields(options)->MergeFrom(
7629
0
      *unknown_fields);
7630
7631
  // record the element path of the interpreted option
7632
0
  if (field->is_repeated()) {
7633
0
    int index = repeated_option_counts_[dest_path]++;
7634
0
    dest_path.push_back(index);
7635
0
  }
7636
0
  interpreted_paths_[src_path] = dest_path;
7637
7638
0
  return true;
7639
0
}
7640
7641
void DescriptorBuilder::OptionInterpreter::UpdateSourceCodeInfo(
7642
0
    SourceCodeInfo* info) {
7643
0
  if (interpreted_paths_.empty()) {
7644
    // nothing to do!
7645
0
    return;
7646
0
  }
7647
7648
  // We find locations that match keys in interpreted_paths_ and
7649
  // 1) replace the path with the corresponding value in interpreted_paths_
7650
  // 2) remove any subsequent sub-locations (sub-location is one whose path
7651
  //    has the parent path as a prefix)
7652
  //
7653
  // To avoid quadratic behavior of removing interior rows as we go,
7654
  // we keep a copy. But we don't actually copy anything until we've
7655
  // found the first match (so if the source code info has no locations
7656
  // that need to be changed, there is zero copy overhead).
7657
7658
0
  RepeatedPtrField<SourceCodeInfo_Location>* locs = info->mutable_location();
7659
0
  RepeatedPtrField<SourceCodeInfo_Location> new_locs;
7660
0
  bool copying = false;
7661
7662
0
  std::vector<int> pathv;
7663
0
  bool matched = false;
7664
7665
0
  for (RepeatedPtrField<SourceCodeInfo_Location>::iterator loc = locs->begin();
7666
0
       loc != locs->end(); loc++) {
7667
0
    if (matched) {
7668
      // see if this location is in the range to remove
7669
0
      bool loc_matches = true;
7670
0
      if (loc->path_size() < static_cast<int64_t>(pathv.size())) {
7671
0
        loc_matches = false;
7672
0
      } else {
7673
0
        for (size_t j = 0; j < pathv.size(); j++) {
7674
0
          if (loc->path(j) != pathv[j]) {
7675
0
            loc_matches = false;
7676
0
            break;
7677
0
          }
7678
0
        }
7679
0
      }
7680
7681
0
      if (loc_matches) {
7682
        // don't copy this row since it is a sub-location that we're removing
7683
0
        continue;
7684
0
      }
7685
7686
0
      matched = false;
7687
0
    }
7688
7689
0
    pathv.clear();
7690
0
    for (int j = 0; j < loc->path_size(); j++) {
7691
0
      pathv.push_back(loc->path(j));
7692
0
    }
7693
7694
0
    auto entry = interpreted_paths_.find(pathv);
7695
7696
0
    if (entry == interpreted_paths_.end()) {
7697
      // not a match
7698
0
      if (copying) {
7699
0
        *new_locs.Add() = *loc;
7700
0
      }
7701
0
      continue;
7702
0
    }
7703
7704
0
    matched = true;
7705
7706
0
    if (!copying) {
7707
      // initialize the copy we are building
7708
0
      copying = true;
7709
0
      new_locs.Reserve(locs->size());
7710
0
      for (RepeatedPtrField<SourceCodeInfo_Location>::iterator it =
7711
0
               locs->begin();
7712
0
           it != loc; it++) {
7713
0
        *new_locs.Add() = *it;
7714
0
      }
7715
0
    }
7716
7717
    // add replacement and update its path
7718
0
    SourceCodeInfo_Location* replacement = new_locs.Add();
7719
0
    *replacement = *loc;
7720
0
    replacement->clear_path();
7721
0
    for (std::vector<int>::iterator rit = entry->second.begin();
7722
0
         rit != entry->second.end(); rit++) {
7723
0
      replacement->add_path(*rit);
7724
0
    }
7725
0
  }
7726
7727
  // if we made a changed copy, put it in place
7728
0
  if (copying) {
7729
0
    *locs = new_locs;
7730
0
  }
7731
0
}
7732
7733
void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting(
7734
0
    const UninterpretedOption& uninterpreted_option, Message* options) {
7735
0
  const FieldDescriptor* field =
7736
0
      options->GetDescriptor()->FindFieldByName("uninterpreted_option");
7737
0
  ABSL_CHECK(field != nullptr);
7738
7739
0
  options->GetReflection()
7740
0
      ->AddMessage(options, field)
7741
0
      ->CopyFrom(uninterpreted_option);
7742
0
}
7743
7744
bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
7745
    std::vector<const FieldDescriptor*>::const_iterator
7746
        intermediate_fields_iter,
7747
    std::vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
7748
    const FieldDescriptor* innermost_field, const std::string& debug_msg_name,
7749
0
    const UnknownFieldSet& unknown_fields) {
7750
  // We do linear searches of the UnknownFieldSet and its sub-groups.  This
7751
  // should be fine since it's unlikely that any one options structure will
7752
  // contain more than a handful of options.
7753
7754
0
  if (intermediate_fields_iter == intermediate_fields_end) {
7755
    // We're at the innermost submessage.
7756
0
    for (int i = 0; i < unknown_fields.field_count(); i++) {
7757
0
      if (unknown_fields.field(i).number() == innermost_field->number()) {
7758
0
        return AddNameError(
7759
0
            absl::StrCat("Option \"", debug_msg_name, "\" was already set."));
7760
0
      }
7761
0
    }
7762
0
    return true;
7763
0
  }
7764
7765
0
  for (int i = 0; i < unknown_fields.field_count(); i++) {
7766
0
    if (unknown_fields.field(i).number() ==
7767
0
        (*intermediate_fields_iter)->number()) {
7768
0
      const UnknownField* unknown_field = &unknown_fields.field(i);
7769
0
      FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
7770
      // Recurse into the next submessage.
7771
0
      switch (type) {
7772
0
        case FieldDescriptor::TYPE_MESSAGE:
7773
0
          if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
7774
0
            UnknownFieldSet intermediate_unknown_fields;
7775
0
            if (intermediate_unknown_fields.ParseFromString(
7776
0
                    unknown_field->length_delimited()) &&
7777
0
                !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
7778
0
                                      intermediate_fields_end, innermost_field,
7779
0
                                      debug_msg_name,
7780
0
                                      intermediate_unknown_fields)) {
7781
0
              return false;  // Error already added.
7782
0
            }
7783
0
          }
7784
0
          break;
7785
7786
0
        case FieldDescriptor::TYPE_GROUP:
7787
0
          if (unknown_field->type() == UnknownField::TYPE_GROUP) {
7788
0
            if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
7789
0
                                      intermediate_fields_end, innermost_field,
7790
0
                                      debug_msg_name, unknown_field->group())) {
7791
0
              return false;  // Error already added.
7792
0
            }
7793
0
          }
7794
0
          break;
7795
7796
0
        default:
7797
0
          ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type;
7798
0
          return false;
7799
0
      }
7800
0
    }
7801
0
  }
7802
0
  return true;
7803
0
}
7804
7805
namespace {
7806
// Helpers for method below
7807
7808
template <typename T> std::string ValueOutOfRange(
7809
0
    absl::string_view type_name, absl::string_view option_name) {
7810
0
  return absl::StrFormat(
7811
0
    "Value out of range, %d to %d, for %s option \"%s\".", \
7812
0
    std::numeric_limits<T>::min(), std::numeric_limits<T>::max(),
7813
0
    type_name, option_name);
7814
0
}
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueOutOfRange<int>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueOutOfRange<long>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueOutOfRange<unsigned int>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
7815
7816
template <typename T> std::string ValueMustBeInt(
7817
0
    absl::string_view type_name, absl::string_view option_name) {
7818
0
  return absl::StrFormat(
7819
0
    "Value must be integer, from %d to %d, for %s option \"%s\".", \
7820
0
    std::numeric_limits<T>::min(), std::numeric_limits<T>::max(),
7821
0
    type_name, option_name);
7822
0
}
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueMustBeInt<int>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueMustBeInt<long>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueMustBeInt<unsigned int>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
Unexecuted instantiation: descriptor.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > google::protobuf::(anonymous namespace)::ValueMustBeInt<unsigned long>(absl::lts_20230125::string_view, absl::lts_20230125::string_view)
7823
7824
} // namespace
7825
7826
bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
7827
0
    const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
7828
  // We switch on the CppType to validate.
7829
0
  switch (option_field->cpp_type()) {
7830
0
    case FieldDescriptor::CPPTYPE_INT32:
7831
0
      if (uninterpreted_option_->has_positive_int_value()) {
7832
0
        if (uninterpreted_option_->positive_int_value() >
7833
0
            static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
7834
0
          return AddValueError(ValueOutOfRange<int32_t>("int32", option_field->full_name()));
7835
0
        } else {
7836
0
          SetInt32(option_field->number(),
7837
0
                   uninterpreted_option_->positive_int_value(),
7838
0
                   option_field->type(), unknown_fields);
7839
0
        }
7840
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
7841
0
        if (uninterpreted_option_->negative_int_value() <
7842
0
            static_cast<int64_t>(std::numeric_limits<int32_t>::min())) {
7843
0
          return AddValueError(ValueOutOfRange<int32_t>("int32", option_field->full_name()));
7844
0
        } else {
7845
0
          SetInt32(option_field->number(),
7846
0
                   uninterpreted_option_->negative_int_value(),
7847
0
                   option_field->type(), unknown_fields);
7848
0
        }
7849
0
      } else {
7850
0
        return AddValueError(ValueMustBeInt<int32_t>("int32", option_field->full_name()));
7851
0
      }
7852
0
      break;
7853
7854
0
    case FieldDescriptor::CPPTYPE_INT64:
7855
0
      if (uninterpreted_option_->has_positive_int_value()) {
7856
0
        if (uninterpreted_option_->positive_int_value() >
7857
0
            static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
7858
0
          return AddValueError(ValueOutOfRange<int64_t>("int64", option_field->full_name()));
7859
0
        } else {
7860
0
          SetInt64(option_field->number(),
7861
0
                   uninterpreted_option_->positive_int_value(),
7862
0
                   option_field->type(), unknown_fields);
7863
0
        }
7864
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
7865
0
        SetInt64(option_field->number(),
7866
0
                 uninterpreted_option_->negative_int_value(),
7867
0
                 option_field->type(), unknown_fields);
7868
0
      } else {
7869
0
        return AddValueError(ValueMustBeInt<int64_t>("int64", option_field->full_name()));
7870
0
      }
7871
0
      break;
7872
7873
0
    case FieldDescriptor::CPPTYPE_UINT32:
7874
0
      if (uninterpreted_option_->has_positive_int_value()) {
7875
0
        if (uninterpreted_option_->positive_int_value() >
7876
0
            std::numeric_limits<uint32_t>::max()) {
7877
0
          return AddValueError(ValueOutOfRange<uint32_t>("uint32", option_field->full_name()));
7878
0
        } else {
7879
0
          SetUInt32(option_field->number(),
7880
0
                    uninterpreted_option_->positive_int_value(),
7881
0
                    option_field->type(), unknown_fields);
7882
0
        }
7883
0
      } else {
7884
0
        return AddValueError(ValueMustBeInt<uint32_t>("uint32", option_field->full_name()));
7885
0
      }
7886
0
      break;
7887
7888
0
    case FieldDescriptor::CPPTYPE_UINT64:
7889
0
      if (uninterpreted_option_->has_positive_int_value()) {
7890
0
        SetUInt64(option_field->number(),
7891
0
                  uninterpreted_option_->positive_int_value(),
7892
0
                  option_field->type(), unknown_fields);
7893
0
      } else {
7894
0
        return AddValueError(ValueMustBeInt<uint64_t>("uint64", option_field->full_name()));
7895
0
      }
7896
0
      break;
7897
7898
0
    case FieldDescriptor::CPPTYPE_FLOAT: {
7899
0
      float value;
7900
0
      if (uninterpreted_option_->has_double_value()) {
7901
0
        value = uninterpreted_option_->double_value();
7902
0
      } else if (uninterpreted_option_->has_positive_int_value()) {
7903
0
        value = uninterpreted_option_->positive_int_value();
7904
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
7905
0
        value = uninterpreted_option_->negative_int_value();
7906
0
      } else {
7907
0
        return AddValueError(
7908
0
            absl::StrCat("Value must be number for float option \"",
7909
0
                         option_field->full_name(), "\"."));
7910
0
      }
7911
0
      unknown_fields->AddFixed32(option_field->number(),
7912
0
                                 internal::WireFormatLite::EncodeFloat(value));
7913
0
      break;
7914
0
    }
7915
7916
0
    case FieldDescriptor::CPPTYPE_DOUBLE: {
7917
0
      double value;
7918
0
      if (uninterpreted_option_->has_double_value()) {
7919
0
        value = uninterpreted_option_->double_value();
7920
0
      } else if (uninterpreted_option_->has_positive_int_value()) {
7921
0
        value = uninterpreted_option_->positive_int_value();
7922
0
      } else if (uninterpreted_option_->has_negative_int_value()) {
7923
0
        value = uninterpreted_option_->negative_int_value();
7924
0
      } else {
7925
0
        return AddValueError(
7926
0
            absl::StrCat("Value must be number for double option \"",
7927
0
                         option_field->full_name(), "\"."));
7928
0
      }
7929
0
      unknown_fields->AddFixed64(option_field->number(),
7930
0
                                 internal::WireFormatLite::EncodeDouble(value));
7931
0
      break;
7932
0
    }
7933
7934
0
    case FieldDescriptor::CPPTYPE_BOOL:
7935
0
      uint64_t value;
7936
0
      if (!uninterpreted_option_->has_identifier_value()) {
7937
0
        return AddValueError(
7938
0
            absl::StrCat("Value must be identifier for boolean option \"",
7939
0
                         option_field->full_name(), "\"."));
7940
0
      }
7941
0
      if (uninterpreted_option_->identifier_value() == "true") {
7942
0
        value = 1;
7943
0
      } else if (uninterpreted_option_->identifier_value() == "false") {
7944
0
        value = 0;
7945
0
      } else {
7946
0
        return AddValueError(absl::StrCat(
7947
0
            "Value must be \"true\" or \"false\" for boolean option \"",
7948
0
            option_field->full_name(), "\"."));
7949
0
      }
7950
0
      unknown_fields->AddVarint(option_field->number(), value);
7951
0
      break;
7952
7953
0
    case FieldDescriptor::CPPTYPE_ENUM: {
7954
0
      if (!uninterpreted_option_->has_identifier_value()) {
7955
0
        return AddValueError(
7956
0
            absl::StrCat("Value must be identifier for enum-valued option \"",
7957
0
                         option_field->full_name(), "\"."));
7958
0
      }
7959
0
      const EnumDescriptor* enum_type = option_field->enum_type();
7960
0
      const std::string& value_name = uninterpreted_option_->identifier_value();
7961
0
      const EnumValueDescriptor* enum_value = nullptr;
7962
7963
0
      if (enum_type->file()->pool() != DescriptorPool::generated_pool()) {
7964
        // Note that the enum value's fully-qualified name is a sibling of the
7965
        // enum's name, not a child of it.
7966
0
        std::string fully_qualified_name = enum_type->full_name();
7967
0
        fully_qualified_name.resize(fully_qualified_name.size() -
7968
0
                                    enum_type->name().size());
7969
0
        fully_qualified_name += value_name;
7970
7971
        // Search for the enum value's descriptor in the builder's pool. Note
7972
        // that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
7973
        // DescriptorPool::FindEnumValueByName() because we're already holding
7974
        // the pool's mutex, and the latter method locks it again.
7975
0
        Symbol symbol =
7976
0
            builder_->FindSymbolNotEnforcingDeps(fully_qualified_name);
7977
0
        if (auto* candicate_descriptor = symbol.enum_value_descriptor()) {
7978
0
          if (candicate_descriptor->type() != enum_type) {
7979
0
            return AddValueError(absl::StrCat(
7980
0
                "Enum type \"", enum_type->full_name(),
7981
0
                "\" has no value named \"", value_name, "\" for option \"",
7982
0
                option_field->full_name(),
7983
0
                "\". This appears to be a value from a sibling type."));
7984
0
          } else {
7985
0
            enum_value = candicate_descriptor;
7986
0
          }
7987
0
        }
7988
0
      } else {
7989
        // The enum type is in the generated pool, so we can search for the
7990
        // value there.
7991
0
        enum_value = enum_type->FindValueByName(value_name);
7992
0
      }
7993
7994
0
      if (enum_value == nullptr) {
7995
0
        return AddValueError(
7996
0
            absl::StrCat("Enum type \"", option_field->enum_type()->full_name(),
7997
0
                         "\" has no value named \"", value_name,
7998
0
                         "\" for option \"", option_field->full_name(), "\"."));
7999
0
      } else {
8000
        // Sign-extension is not a problem, since we cast directly from int32_t
8001
        // to uint64_t, without first going through uint32_t.
8002
0
        unknown_fields->AddVarint(
8003
0
            option_field->number(),
8004
0
            static_cast<uint64_t>(static_cast<int64_t>(enum_value->number())));
8005
0
      }
8006
0
      break;
8007
0
    }
8008
8009
0
    case FieldDescriptor::CPPTYPE_STRING:
8010
0
      if (!uninterpreted_option_->has_string_value()) {
8011
0
        return AddValueError(
8012
0
            absl::StrCat("Value must be quoted string for string option \"",
8013
0
                         option_field->full_name(), "\"."));
8014
0
      }
8015
      // The string has already been unquoted and unescaped by the parser.
8016
0
      unknown_fields->AddLengthDelimited(option_field->number(),
8017
0
                                         uninterpreted_option_->string_value());
8018
0
      break;
8019
8020
0
    case FieldDescriptor::CPPTYPE_MESSAGE:
8021
0
      if (!SetAggregateOption(option_field, unknown_fields)) {
8022
0
        return false;
8023
0
      }
8024
0
      break;
8025
0
  }
8026
8027
0
  return true;
8028
0
}
8029
8030
class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
8031
    : public TextFormat::Finder {
8032
 public:
8033
  DescriptorBuilder* builder_;
8034
8035
  const Descriptor* FindAnyType(const Message& /*message*/,
8036
                                const std::string& prefix,
8037
0
                                const std::string& name) const override {
8038
0
    if (prefix != internal::kTypeGoogleApisComPrefix &&
8039
0
        prefix != internal::kTypeGoogleProdComPrefix) {
8040
0
      return nullptr;
8041
0
    }
8042
0
    assert_mutex_held(builder_->pool_);
8043
0
    return builder_->FindSymbol(name).descriptor();
8044
0
  }
8045
8046
  const FieldDescriptor* FindExtension(Message* message,
8047
0
                                       const std::string& name) const override {
8048
0
    assert_mutex_held(builder_->pool_);
8049
0
    const Descriptor* descriptor = message->GetDescriptor();
8050
0
    Symbol result =
8051
0
        builder_->LookupSymbolNoPlaceholder(name, descriptor->full_name());
8052
0
    if (auto* field = result.field_descriptor()) {
8053
0
      return field;
8054
0
    } else if (result.type() == Symbol::MESSAGE &&
8055
0
               descriptor->options().message_set_wire_format()) {
8056
0
      const Descriptor* foreign_type = result.descriptor();
8057
      // The text format allows MessageSet items to be specified using
8058
      // the type name, rather than the extension identifier. If the symbol
8059
      // lookup returned a Message, and the enclosing Message has
8060
      // message_set_wire_format = true, then return the message set
8061
      // extension, if one exists.
8062
0
      for (int i = 0; i < foreign_type->extension_count(); i++) {
8063
0
        const FieldDescriptor* extension = foreign_type->extension(i);
8064
0
        if (extension->containing_type() == descriptor &&
8065
0
            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
8066
0
            extension->is_optional() &&
8067
0
            extension->message_type() == foreign_type) {
8068
          // Found it.
8069
0
          return extension;
8070
0
        }
8071
0
      }
8072
0
    }
8073
0
    return nullptr;
8074
0
  }
8075
};
8076
8077
// A custom error collector to record any text-format parsing errors
8078
namespace {
8079
class AggregateErrorCollector : public io::ErrorCollector {
8080
 public:
8081
  std::string error_;
8082
8083
  void RecordError(int /* line */, int /* column */,
8084
0
                   const absl::string_view message) override {
8085
0
    if (!error_.empty()) {
8086
0
      absl::StrAppend(&error_, "; ");
8087
0
    }
8088
0
    absl::StrAppend(&error_, message);
8089
0
  }
8090
8091
  void RecordWarning(int /* line */, int /* column */,
8092
0
                     const absl::string_view /* message */) override {
8093
    // Ignore warnings
8094
0
  }
8095
};
8096
}  // namespace
8097
8098
// We construct a dynamic message of the type corresponding to
8099
// option_field, parse the supplied text-format string into this
8100
// message, and serialize the resulting message to produce the value.
8101
bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
8102
0
    const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
8103
0
  if (!uninterpreted_option_->has_aggregate_value()) {
8104
0
    return AddValueError(
8105
0
        absl::StrCat("Option \"", option_field->full_name(),
8106
0
                     "\" is a message. "
8107
0
                     "To set the entire message, use syntax like \"",
8108
0
                     option_field->name(),
8109
0
                     " = { <proto text format> }\". "
8110
0
                     "To set fields within it, use syntax like \"",
8111
0
                     option_field->name(), ".foo = value\"."));
8112
0
  }
8113
8114
0
  const Descriptor* type = option_field->message_type();
8115
0
  std::unique_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
8116
0
  ABSL_CHECK(dynamic.get() != nullptr)
8117
0
      << "Could not create an instance of " << option_field->DebugString();
8118
8119
0
  AggregateErrorCollector collector;
8120
0
  AggregateOptionFinder finder;
8121
0
  finder.builder_ = builder_;
8122
0
  TextFormat::Parser parser;
8123
0
  parser.RecordErrorsTo(&collector);
8124
0
  parser.SetFinder(&finder);
8125
0
  if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
8126
0
                              dynamic.get())) {
8127
0
    AddValueError(absl::StrCat("Error while parsing option value for \"",
8128
0
                               option_field->name(), "\": ", collector.error_));
8129
0
    return false;
8130
0
  } else {
8131
0
    std::string serial;
8132
0
    dynamic->SerializeToString(&serial);  // Never fails
8133
0
    if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) {
8134
0
      unknown_fields->AddLengthDelimited(option_field->number(), serial);
8135
0
    } else {
8136
0
      ABSL_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP);
8137
0
      UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number());
8138
0
      group->ParseFromString(serial);
8139
0
    }
8140
0
    return true;
8141
0
  }
8142
0
}
8143
8144
void DescriptorBuilder::OptionInterpreter::SetInt32(
8145
    int number, int32_t value, FieldDescriptor::Type type,
8146
0
    UnknownFieldSet* unknown_fields) {
8147
0
  switch (type) {
8148
0
    case FieldDescriptor::TYPE_INT32:
8149
0
      unknown_fields->AddVarint(
8150
0
          number, static_cast<uint64_t>(static_cast<int64_t>(value)));
8151
0
      break;
8152
8153
0
    case FieldDescriptor::TYPE_SFIXED32:
8154
0
      unknown_fields->AddFixed32(number, static_cast<uint32_t>(value));
8155
0
      break;
8156
8157
0
    case FieldDescriptor::TYPE_SINT32:
8158
0
      unknown_fields->AddVarint(
8159
0
          number, internal::WireFormatLite::ZigZagEncode32(value));
8160
0
      break;
8161
8162
0
    default:
8163
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT32: " << type;
8164
0
      break;
8165
0
  }
8166
0
}
8167
8168
void DescriptorBuilder::OptionInterpreter::SetInt64(
8169
    int number, int64_t value, FieldDescriptor::Type type,
8170
0
    UnknownFieldSet* unknown_fields) {
8171
0
  switch (type) {
8172
0
    case FieldDescriptor::TYPE_INT64:
8173
0
      unknown_fields->AddVarint(number, static_cast<uint64_t>(value));
8174
0
      break;
8175
8176
0
    case FieldDescriptor::TYPE_SFIXED64:
8177
0
      unknown_fields->AddFixed64(number, static_cast<uint64_t>(value));
8178
0
      break;
8179
8180
0
    case FieldDescriptor::TYPE_SINT64:
8181
0
      unknown_fields->AddVarint(
8182
0
          number, internal::WireFormatLite::ZigZagEncode64(value));
8183
0
      break;
8184
8185
0
    default:
8186
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT64: " << type;
8187
0
      break;
8188
0
  }
8189
0
}
8190
8191
void DescriptorBuilder::OptionInterpreter::SetUInt32(
8192
    int number, uint32_t value, FieldDescriptor::Type type,
8193
0
    UnknownFieldSet* unknown_fields) {
8194
0
  switch (type) {
8195
0
    case FieldDescriptor::TYPE_UINT32:
8196
0
      unknown_fields->AddVarint(number, static_cast<uint64_t>(value));
8197
0
      break;
8198
8199
0
    case FieldDescriptor::TYPE_FIXED32:
8200
0
      unknown_fields->AddFixed32(number, static_cast<uint32_t>(value));
8201
0
      break;
8202
8203
0
    default:
8204
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT32: " << type;
8205
0
      break;
8206
0
  }
8207
0
}
8208
8209
void DescriptorBuilder::OptionInterpreter::SetUInt64(
8210
    int number, uint64_t value, FieldDescriptor::Type type,
8211
0
    UnknownFieldSet* unknown_fields) {
8212
0
  switch (type) {
8213
0
    case FieldDescriptor::TYPE_UINT64:
8214
0
      unknown_fields->AddVarint(number, value);
8215
0
      break;
8216
8217
0
    case FieldDescriptor::TYPE_FIXED64:
8218
0
      unknown_fields->AddFixed64(number, value);
8219
0
      break;
8220
8221
0
    default:
8222
0
      ABSL_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT64: " << type;
8223
0
      break;
8224
0
  }
8225
0
}
8226
8227
void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto,
8228
0
                                            const FileDescriptor* result) {
8229
0
  (void)result;  // Parameter is used by Google-internal code.
8230
8231
0
  if (!unused_dependency_.empty()) {
8232
0
    auto itr = pool_->unused_import_track_files_.find(proto.name());
8233
0
    bool is_error =
8234
0
        itr != pool_->unused_import_track_files_.end() && itr->second;
8235
0
    for (const auto* unused : unused_dependency_) {
8236
0
      std::string error_message =
8237
0
          absl::StrCat("Import ", unused->name(), " is unused.");
8238
0
      if (is_error) {
8239
0
        AddError(unused->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
8240
0
                 error_message);
8241
0
      } else {
8242
0
        AddWarning(unused->name(), proto,
8243
0
                   DescriptorPool::ErrorCollector::IMPORT, error_message);
8244
0
      }
8245
0
    }
8246
0
  }
8247
0
}
8248
8249
Symbol DescriptorPool::CrossLinkOnDemandHelper(absl::string_view name,
8250
0
                                               bool expecting_enum) const {
8251
0
  (void)expecting_enum;  // Parameter is used by Google-internal code.
8252
0
  auto lookup_name = std::string(name);
8253
0
  if (!lookup_name.empty() && lookup_name[0] == '.') {
8254
0
    lookup_name = lookup_name.substr(1);
8255
0
  }
8256
0
  Symbol result = tables_->FindByNameHelper(this, lookup_name);
8257
0
  return result;
8258
0
}
8259
8260
// Handle the lazy import building for a message field whose type wasn't built
8261
// at cross link time. If that was the case, we saved the name of the type to
8262
// be looked up when the accessor for the type was called. Set type_,
8263
// enum_type_, message_type_, and default_value_enum_ appropriately.
8264
0
void FieldDescriptor::InternalTypeOnceInit() const {
8265
0
  ABSL_CHECK(file()->finished_building_ == true);
8266
0
  const EnumDescriptor* enum_type = nullptr;
8267
0
  const char* lazy_type_name = reinterpret_cast<const char*>(type_once_ + 1);
8268
0
  const char* lazy_default_value_enum_name =
8269
0
      lazy_type_name + strlen(lazy_type_name) + 1;
8270
0
  Symbol result = file()->pool()->CrossLinkOnDemandHelper(
8271
0
      lazy_type_name, type_ == FieldDescriptor::TYPE_ENUM);
8272
0
  if (result.type() == Symbol::MESSAGE) {
8273
0
    type_ = FieldDescriptor::TYPE_MESSAGE;
8274
0
    type_descriptor_.message_type = result.descriptor();
8275
0
  } else if (result.type() == Symbol::ENUM) {
8276
0
    type_ = FieldDescriptor::TYPE_ENUM;
8277
0
    enum_type = type_descriptor_.enum_type = result.enum_descriptor();
8278
0
  }
8279
8280
0
  if (enum_type) {
8281
0
    if (lazy_default_value_enum_name[0] != '\0') {
8282
      // Have to build the full name now instead of at CrossLink time,
8283
      // because enum_type may not be known at the time.
8284
0
      std::string name = enum_type->full_name();
8285
      // Enum values reside in the same scope as the enum type.
8286
0
      std::string::size_type last_dot = name.find_last_of('.');
8287
0
      if (last_dot != std::string::npos) {
8288
0
        name = absl::StrCat(name.substr(0, last_dot), ".",
8289
0
                            lazy_default_value_enum_name);
8290
0
      } else {
8291
0
        name = lazy_default_value_enum_name;
8292
0
      }
8293
0
      Symbol result = file()->pool()->CrossLinkOnDemandHelper(name, true);
8294
0
      default_value_enum_ = result.enum_value_descriptor();
8295
0
    } else {
8296
0
      default_value_enum_ = nullptr;
8297
0
    }
8298
0
    if (!default_value_enum_) {
8299
      // We use the first defined value as the default
8300
      // if a default is not explicitly defined.
8301
0
      ABSL_CHECK(enum_type->value_count());
8302
0
      default_value_enum_ = enum_type->value(0);
8303
0
    }
8304
0
  }
8305
0
}
8306
8307
0
void FieldDescriptor::TypeOnceInit(const FieldDescriptor* to_init) {
8308
0
  to_init->InternalTypeOnceInit();
8309
0
}
8310
8311
// message_type(), enum_type(), default_value_enum(), and type()
8312
// all share the same absl::call_once init path to do lazy
8313
// import building and cross linking of a field of a message.
8314
7.76k
const Descriptor* FieldDescriptor::message_type() const {
8315
7.76k
  if (type_once_) {
8316
0
    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
8317
0
  }
8318
7.76k
  return type_ == TYPE_MESSAGE || type_ == TYPE_GROUP
8319
7.76k
             ? type_descriptor_.message_type
8320
7.76k
             : nullptr;
8321
7.76k
}
8322
8323
54
const EnumDescriptor* FieldDescriptor::enum_type() const {
8324
54
  if (type_once_) {
8325
0
    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
8326
0
  }
8327
54
  return type_ == TYPE_ENUM ? type_descriptor_.enum_type : nullptr;
8328
54
}
8329
8330
0
const EnumValueDescriptor* FieldDescriptor::default_value_enum() const {
8331
0
  if (type_once_) {
8332
0
    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
8333
0
  }
8334
0
  return default_value_enum_;
8335
0
}
8336
8337
0
const std::string& FieldDescriptor::PrintableNameForExtension() const {
8338
0
  const bool is_message_set_extension =
8339
0
      is_extension() &&
8340
0
      containing_type()->options().message_set_wire_format() &&
8341
0
      type() == FieldDescriptor::TYPE_MESSAGE && is_optional() &&
8342
0
      extension_scope() == message_type();
8343
0
  return is_message_set_extension ? message_type()->full_name() : full_name();
8344
0
}
8345
8346
0
void FileDescriptor::InternalDependenciesOnceInit() const {
8347
0
  ABSL_CHECK(finished_building_ == true);
8348
0
  const char* names_ptr = reinterpret_cast<const char*>(dependencies_once_ + 1);
8349
0
  for (int i = 0; i < dependency_count(); i++) {
8350
0
    const char* name = names_ptr;
8351
0
    names_ptr += strlen(name) + 1;
8352
0
    if (name[0] != '\0') {
8353
0
      dependencies_[i] = pool_->FindFileByName(name);
8354
0
    }
8355
0
  }
8356
0
}
8357
8358
0
void FileDescriptor::DependenciesOnceInit(const FileDescriptor* to_init) {
8359
0
  to_init->InternalDependenciesOnceInit();
8360
0
}
8361
8362
0
const FileDescriptor* FileDescriptor::dependency(int index) const {
8363
0
  if (dependencies_once_) {
8364
    // Do once init for all indices, as it's unlikely only a single index would
8365
    // be called, and saves on absl::call_once allocations.
8366
0
    absl::call_once(*dependencies_once_, FileDescriptor::DependenciesOnceInit,
8367
0
                    this);
8368
0
  }
8369
0
  return dependencies_[index];
8370
0
}
8371
8372
0
const Descriptor* MethodDescriptor::input_type() const {
8373
0
  return input_type_.Get(service());
8374
0
}
8375
8376
0
const Descriptor* MethodDescriptor::output_type() const {
8377
0
  return output_type_.Get(service());
8378
0
}
8379
8380
namespace internal {
8381
0
void LazyDescriptor::Set(const Descriptor* descriptor) {
8382
0
  ABSL_CHECK(!once_);
8383
0
  descriptor_ = descriptor;
8384
0
}
8385
8386
void LazyDescriptor::SetLazy(absl::string_view name,
8387
0
                             const FileDescriptor* file) {
8388
  // verify Init() has been called and Set hasn't been called yet.
8389
0
  ABSL_CHECK(!descriptor_);
8390
0
  ABSL_CHECK(!once_);
8391
0
  ABSL_CHECK(file && file->pool_);
8392
0
  ABSL_CHECK(file->pool_->lazily_build_dependencies_);
8393
0
  ABSL_CHECK(!file->finished_building_);
8394
0
  once_ = ::new (file->pool_->tables_->AllocateBytes(static_cast<int>(
8395
0
      sizeof(absl::once_flag) + name.size() + 1))) absl::once_flag{};
8396
0
  char* lazy_name = reinterpret_cast<char*>(once_ + 1);
8397
0
  memcpy(lazy_name, name.data(), name.size());
8398
0
  lazy_name[name.size()] = 0;
8399
0
}
8400
8401
0
void LazyDescriptor::Once(const ServiceDescriptor* service) {
8402
0
  if (once_) {
8403
0
    absl::call_once(*once_, [&] {
8404
0
      auto* file = service->file();
8405
0
      ABSL_CHECK(file->finished_building_);
8406
0
      const char* lazy_name = reinterpret_cast<const char*>(once_ + 1);
8407
0
      descriptor_ =
8408
0
          file->pool_->CrossLinkOnDemandHelper(lazy_name, false).descriptor();
8409
0
    });
8410
0
  }
8411
0
}
8412
8413
namespace cpp {
8414
0
bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) {
8415
0
  return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
8416
0
}
8417
8418
0
bool HasHasbit(const FieldDescriptor* field) {
8419
  // This predicate includes proto3 message fields only if they have "optional".
8420
  //   Foo submsg1 = 1;           // HasHasbit() == false
8421
  //   optional Foo submsg2 = 2;  // HasHasbit() == true
8422
  // This is slightly odd, as adding "optional" to a singular proto3 field does
8423
  // not change the semantics or API. However whenever any field in a message
8424
  // has a hasbit, it forces reflection to include hasbit offsets for *all*
8425
  // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
8426
  // causing a sudden size regression for ~all proto3 messages, we give proto3
8427
  // message fields a hasbit only if "optional" is present. If the user is
8428
  // explicitly writing "optional", it is likely they are writing it on
8429
  // primitive fields also.
8430
0
  return (field->has_optional_keyword() || field->is_required()) &&
8431
0
         !field->options().weak();
8432
0
}
8433
8434
0
static bool FieldEnforceUtf8(const FieldDescriptor* field) {
8435
0
  return true;
8436
0
}
8437
8438
0
static bool FileUtf8Verification(const FileDescriptor* file) {
8439
0
  return true;
8440
0
}
8441
8442
// Which level of UTF-8 enforcemant is placed on this file.
8443
0
Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, bool is_lite) {
8444
0
  if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
8445
0
      FieldEnforceUtf8(field)) {
8446
0
    return Utf8CheckMode::kStrict;
8447
0
  } else if (!is_lite && FileUtf8Verification(field->file())) {
8448
0
    return Utf8CheckMode::kVerify;
8449
0
  } else {
8450
0
    return Utf8CheckMode::kNone;
8451
0
  }
8452
0
}
8453
8454
}  // namespace cpp
8455
}  // namespace internal
8456
8457
}  // namespace protobuf
8458
}  // namespace google
8459
8460
#include "google/protobuf/port_undef.inc"