cpp_helpers.cc 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014
  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. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. #include <google/protobuf/compiler/cpp/cpp_helpers.h>
  34. #include <functional>
  35. #include <limits>
  36. #include <map>
  37. #include <queue>
  38. #include <unordered_set>
  39. #include <vector>
  40. #include <google/protobuf/stubs/common.h>
  41. #include <google/protobuf/stubs/logging.h>
  42. #include <google/protobuf/compiler/cpp/cpp_options.h>
  43. #include <google/protobuf/descriptor.pb.h>
  44. #include <google/protobuf/descriptor.h>
  45. #include <google/protobuf/compiler/scc.h>
  46. #include <google/protobuf/io/printer.h>
  47. #include <google/protobuf/io/zero_copy_stream.h>
  48. #include <google/protobuf/dynamic_message.h>
  49. #include <google/protobuf/wire_format.h>
  50. #include <google/protobuf/wire_format_lite.h>
  51. #include <google/protobuf/stubs/strutil.h>
  52. #include <google/protobuf/stubs/substitute.h>
  53. #include <google/protobuf/stubs/hash.h>
  54. #include <google/protobuf/port_def.inc>
  55. namespace google {
  56. namespace protobuf {
  57. namespace compiler {
  58. namespace cpp {
  59. namespace {
  60. static const char kAnyMessageName[] = "Any";
  61. static const char kAnyProtoFile[] = "google/protobuf/any.proto";
  62. std::string DotsToColons(const std::string& name) {
  63. return StringReplace(name, ".", "::", true);
  64. }
  65. static const char* const kKeywordList[] = { //
  66. "NULL",
  67. "alignas",
  68. "alignof",
  69. "and",
  70. "and_eq",
  71. "asm",
  72. "auto",
  73. "bitand",
  74. "bitor",
  75. "bool",
  76. "break",
  77. "case",
  78. "catch",
  79. "char",
  80. "class",
  81. "compl",
  82. "const",
  83. "constexpr",
  84. "const_cast",
  85. "continue",
  86. "decltype",
  87. "default",
  88. "delete",
  89. "do",
  90. "double",
  91. "dynamic_cast",
  92. "else",
  93. "enum",
  94. "explicit",
  95. "export",
  96. "extern",
  97. "false",
  98. "float",
  99. "for",
  100. "friend",
  101. "goto",
  102. "if",
  103. "inline",
  104. "int",
  105. "long",
  106. "mutable",
  107. "namespace",
  108. "new",
  109. "noexcept",
  110. "not",
  111. "not_eq",
  112. "nullptr",
  113. "operator",
  114. "or",
  115. "or_eq",
  116. "private",
  117. "protected",
  118. "public",
  119. "register",
  120. "reinterpret_cast",
  121. "return",
  122. "short",
  123. "signed",
  124. "sizeof",
  125. "static",
  126. "static_assert",
  127. "static_cast",
  128. "struct",
  129. "switch",
  130. "template",
  131. "this",
  132. "thread_local",
  133. "throw",
  134. "true",
  135. "try",
  136. "typedef",
  137. "typeid",
  138. "typename",
  139. "union",
  140. "unsigned",
  141. "using",
  142. "virtual",
  143. "void",
  144. "volatile",
  145. "wchar_t",
  146. "while",
  147. "xor",
  148. "xor_eq"};
  149. static std::unordered_set<std::string>* MakeKeywordsMap() {
  150. auto* result = new std::unordered_set<std::string>();
  151. for (const auto keyword : kKeywordList) {
  152. result->emplace(keyword);
  153. }
  154. return result;
  155. }
  156. static std::unordered_set<std::string>& kKeywords = *MakeKeywordsMap();
  157. // Encode [0..63] as 'A'-'Z', 'a'-'z', '0'-'9', '_'
  158. char Base63Char(int value) {
  159. GOOGLE_CHECK_GE(value, 0);
  160. if (value < 26) return 'A' + value;
  161. value -= 26;
  162. if (value < 26) return 'a' + value;
  163. value -= 26;
  164. if (value < 10) return '0' + value;
  165. GOOGLE_CHECK_EQ(value, 10);
  166. return '_';
  167. }
  168. // Given a c identifier has 63 legal characters we can't implement base64
  169. // encoding. So we return the k least significant "digits" in base 63.
  170. template <typename I>
  171. std::string Base63(I n, int k) {
  172. std::string res;
  173. while (k-- > 0) {
  174. res += Base63Char(static_cast<int>(n % 63));
  175. n /= 63;
  176. }
  177. return res;
  178. }
  179. std::string IntTypeName(const Options& options, const std::string& type) {
  180. if (options.opensource_runtime) {
  181. return "::PROTOBUF_NAMESPACE_ID::" + type;
  182. } else {
  183. return "::" + type;
  184. }
  185. }
  186. void SetIntVar(const Options& options, const std::string& type,
  187. std::map<std::string, std::string>* variables) {
  188. (*variables)[type] = IntTypeName(options, type);
  189. }
  190. bool HasInternalAccessors(const FieldOptions::CType ctype) {
  191. return ctype == FieldOptions::STRING || ctype == FieldOptions::CORD;
  192. }
  193. } // namespace
  194. void SetCommonVars(const Options& options,
  195. std::map<std::string, std::string>* variables) {
  196. (*variables)["proto_ns"] = ProtobufNamespace(options);
  197. // Warning: there is some clever naming/splitting here to avoid extract script
  198. // rewrites. The names of these variables must not be things that the extract
  199. // script will rewrite. That's why we use "CHK" (for example) instead of
  200. // "GOOGLE_CHECK".
  201. if (options.opensource_runtime) {
  202. (*variables)["GOOGLE_PROTOBUF"] = "GOOGLE_PROTOBUF";
  203. (*variables)["CHK"] = "GOOGLE_CHECK";
  204. (*variables)["DCHK"] = "GOOGLE_DCHECK";
  205. } else {
  206. // These values are things the extract script would rewrite if we did not
  207. // split them. It might not strictly matter since we don't generate google3
  208. // code in open-source. But it's good to prevent surprising things from
  209. // happening.
  210. (*variables)["GOOGLE_PROTOBUF"] =
  211. "GOOGLE3"
  212. "_PROTOBUF";
  213. (*variables)["CHK"] =
  214. "CH"
  215. "ECK";
  216. (*variables)["DCHK"] =
  217. "DCH"
  218. "ECK";
  219. }
  220. SetIntVar(options, "int8", variables);
  221. SetIntVar(options, "uint8", variables);
  222. SetIntVar(options, "uint32", variables);
  223. SetIntVar(options, "uint64", variables);
  224. SetIntVar(options, "int32", variables);
  225. SetIntVar(options, "int64", variables);
  226. (*variables)["string"] = "std::string";
  227. }
  228. void SetUnknkownFieldsVariable(const Descriptor* descriptor,
  229. const Options& options,
  230. std::map<std::string, std::string>* variables) {
  231. std::string proto_ns = ProtobufNamespace(options);
  232. std::string unknown_fields_type;
  233. if (UseUnknownFieldSet(descriptor->file(), options)) {
  234. unknown_fields_type = "::" + proto_ns + "::UnknownFieldSet";
  235. (*variables)["unknown_fields"] =
  236. "_internal_metadata_.unknown_fields<" + unknown_fields_type + ">(" +
  237. unknown_fields_type + "::default_instance)";
  238. } else {
  239. unknown_fields_type =
  240. PrimitiveTypeName(options, FieldDescriptor::CPPTYPE_STRING);
  241. (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields<" +
  242. unknown_fields_type + ">(::" + proto_ns +
  243. "::internal::GetEmptyString)";
  244. }
  245. (*variables)["unknown_fields_type"] = unknown_fields_type;
  246. (*variables)["have_unknown_fields"] =
  247. "_internal_metadata_.have_unknown_fields()";
  248. (*variables)["mutable_unknown_fields"] =
  249. "_internal_metadata_.mutable_unknown_fields<" + unknown_fields_type +
  250. ">()";
  251. }
  252. std::string UnderscoresToCamelCase(const std::string& input,
  253. bool cap_next_letter) {
  254. std::string result;
  255. // Note: I distrust ctype.h due to locales.
  256. for (int i = 0; i < input.size(); i++) {
  257. if ('a' <= input[i] && input[i] <= 'z') {
  258. if (cap_next_letter) {
  259. result += input[i] + ('A' - 'a');
  260. } else {
  261. result += input[i];
  262. }
  263. cap_next_letter = false;
  264. } else if ('A' <= input[i] && input[i] <= 'Z') {
  265. // Capital letters are left as-is.
  266. result += input[i];
  267. cap_next_letter = false;
  268. } else if ('0' <= input[i] && input[i] <= '9') {
  269. result += input[i];
  270. cap_next_letter = true;
  271. } else {
  272. cap_next_letter = true;
  273. }
  274. }
  275. return result;
  276. }
  277. const char kThickSeparator[] =
  278. "// ===================================================================\n";
  279. const char kThinSeparator[] =
  280. "// -------------------------------------------------------------------\n";
  281. bool CanInitializeByZeroing(const FieldDescriptor* field) {
  282. if (field->is_repeated() || field->is_extension()) return false;
  283. switch (field->cpp_type()) {
  284. case FieldDescriptor::CPPTYPE_ENUM:
  285. return field->default_value_enum()->number() == 0;
  286. case FieldDescriptor::CPPTYPE_INT32:
  287. return field->default_value_int32() == 0;
  288. case FieldDescriptor::CPPTYPE_INT64:
  289. return field->default_value_int64() == 0;
  290. case FieldDescriptor::CPPTYPE_UINT32:
  291. return field->default_value_uint32() == 0;
  292. case FieldDescriptor::CPPTYPE_UINT64:
  293. return field->default_value_uint64() == 0;
  294. case FieldDescriptor::CPPTYPE_FLOAT:
  295. return field->default_value_float() == 0;
  296. case FieldDescriptor::CPPTYPE_DOUBLE:
  297. return field->default_value_double() == 0;
  298. case FieldDescriptor::CPPTYPE_BOOL:
  299. return field->default_value_bool() == false;
  300. default:
  301. return false;
  302. }
  303. }
  304. std::string ClassName(const Descriptor* descriptor) {
  305. const Descriptor* parent = descriptor->containing_type();
  306. std::string res;
  307. if (parent) res += ClassName(parent) + "_";
  308. res += descriptor->name();
  309. if (IsMapEntryMessage(descriptor)) res += "_DoNotUse";
  310. return ResolveKeyword(res);
  311. }
  312. std::string ClassName(const EnumDescriptor* enum_descriptor) {
  313. if (enum_descriptor->containing_type() == nullptr) {
  314. return ResolveKeyword(enum_descriptor->name());
  315. } else {
  316. return ClassName(enum_descriptor->containing_type()) + "_" +
  317. enum_descriptor->name();
  318. }
  319. }
  320. std::string QualifiedClassName(const Descriptor* d, const Options& options) {
  321. return QualifiedFileLevelSymbol(d->file(), ClassName(d), options);
  322. }
  323. std::string QualifiedClassName(const EnumDescriptor* d,
  324. const Options& options) {
  325. return QualifiedFileLevelSymbol(d->file(), ClassName(d), options);
  326. }
  327. std::string QualifiedClassName(const Descriptor* d) {
  328. return QualifiedClassName(d, Options());
  329. }
  330. std::string QualifiedClassName(const EnumDescriptor* d) {
  331. return QualifiedClassName(d, Options());
  332. }
  333. std::string QualifiedExtensionName(const FieldDescriptor* d,
  334. const Options& options) {
  335. GOOGLE_DCHECK(d->is_extension());
  336. return QualifiedFileLevelSymbol(d->file(), FieldName(d), options);
  337. }
  338. std::string QualifiedExtensionName(const FieldDescriptor* d) {
  339. return QualifiedExtensionName(d, Options());
  340. }
  341. std::string Namespace(const std::string& package) {
  342. if (package.empty()) return "";
  343. return "::" + DotsToColons(package);
  344. }
  345. std::string Namespace(const FileDescriptor* d, const Options& options) {
  346. std::string ret = Namespace(d->package());
  347. if (IsWellKnownMessage(d) && options.opensource_runtime) {
  348. // Written with string concatenation to prevent rewriting of
  349. // ::google::protobuf.
  350. ret = StringReplace(ret,
  351. "::google::"
  352. "protobuf",
  353. "PROTOBUF_NAMESPACE_ID", false);
  354. }
  355. return ret;
  356. }
  357. std::string Namespace(const Descriptor* d, const Options& options) {
  358. return Namespace(d->file(), options);
  359. }
  360. std::string Namespace(const FieldDescriptor* d, const Options& options) {
  361. return Namespace(d->file(), options);
  362. }
  363. std::string Namespace(const EnumDescriptor* d, const Options& options) {
  364. return Namespace(d->file(), options);
  365. }
  366. std::string DefaultInstanceType(const Descriptor* descriptor,
  367. const Options& options) {
  368. return ClassName(descriptor) + "DefaultTypeInternal";
  369. }
  370. std::string DefaultInstanceName(const Descriptor* descriptor,
  371. const Options& options) {
  372. return "_" + ClassName(descriptor, false) + "_default_instance_";
  373. }
  374. std::string DefaultInstancePtr(const Descriptor* descriptor,
  375. const Options& options) {
  376. return DefaultInstanceName(descriptor, options) + "ptr_";
  377. }
  378. std::string QualifiedDefaultInstanceName(const Descriptor* descriptor,
  379. const Options& options) {
  380. return QualifiedFileLevelSymbol(
  381. descriptor->file(), DefaultInstanceName(descriptor, options), options);
  382. }
  383. std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor,
  384. const Options& options) {
  385. return QualifiedDefaultInstanceName(descriptor, options) + "ptr_";
  386. }
  387. std::string DescriptorTableName(const FileDescriptor* file,
  388. const Options& options) {
  389. return UniqueName("descriptor_table", file, options);
  390. }
  391. std::string FileDllExport(const FileDescriptor* file, const Options& options) {
  392. return UniqueName("PROTOBUF_INTERNAL_EXPORT", file, options);
  393. }
  394. std::string SuperClassName(const Descriptor* descriptor,
  395. const Options& options) {
  396. return "::" + ProtobufNamespace(options) +
  397. (HasDescriptorMethods(descriptor->file(), options) ? "::Message"
  398. : "::MessageLite");
  399. }
  400. std::string ResolveKeyword(const std::string& name) {
  401. if (kKeywords.count(name) > 0) {
  402. return name + "_";
  403. }
  404. return name;
  405. }
  406. std::string FieldName(const FieldDescriptor* field) {
  407. std::string result = field->name();
  408. LowerString(&result);
  409. if (kKeywords.count(result) > 0) {
  410. result.append("_");
  411. }
  412. return result;
  413. }
  414. std::string EnumValueName(const EnumValueDescriptor* enum_value) {
  415. std::string result = enum_value->name();
  416. if (kKeywords.count(result) > 0) {
  417. result.append("_");
  418. }
  419. return result;
  420. }
  421. int EstimateAlignmentSize(const FieldDescriptor* field) {
  422. if (field == nullptr) return 0;
  423. if (field->is_repeated()) return 8;
  424. switch (field->cpp_type()) {
  425. case FieldDescriptor::CPPTYPE_BOOL:
  426. return 1;
  427. case FieldDescriptor::CPPTYPE_INT32:
  428. case FieldDescriptor::CPPTYPE_UINT32:
  429. case FieldDescriptor::CPPTYPE_ENUM:
  430. case FieldDescriptor::CPPTYPE_FLOAT:
  431. return 4;
  432. case FieldDescriptor::CPPTYPE_INT64:
  433. case FieldDescriptor::CPPTYPE_UINT64:
  434. case FieldDescriptor::CPPTYPE_DOUBLE:
  435. case FieldDescriptor::CPPTYPE_STRING:
  436. case FieldDescriptor::CPPTYPE_MESSAGE:
  437. return 8;
  438. }
  439. GOOGLE_LOG(FATAL) << "Can't get here.";
  440. return -1; // Make compiler happy.
  441. }
  442. std::string FieldConstantName(const FieldDescriptor* field) {
  443. std::string field_name = UnderscoresToCamelCase(field->name(), true);
  444. std::string result = "k" + field_name + "FieldNumber";
  445. if (!field->is_extension() &&
  446. field->containing_type()->FindFieldByCamelcaseName(
  447. field->camelcase_name()) != field) {
  448. // This field's camelcase name is not unique. As a hack, add the field
  449. // number to the constant name. This makes the constant rather useless,
  450. // but what can we do?
  451. result += "_" + StrCat(field->number());
  452. }
  453. return result;
  454. }
  455. std::string FieldMessageTypeName(const FieldDescriptor* field,
  456. const Options& options) {
  457. // Note: The Google-internal version of Protocol Buffers uses this function
  458. // as a hook point for hacks to support legacy code.
  459. return QualifiedClassName(field->message_type(), options);
  460. }
  461. std::string StripProto(const std::string& filename) {
  462. if (HasSuffixString(filename, ".protodevel")) {
  463. return StripSuffixString(filename, ".protodevel");
  464. } else {
  465. return StripSuffixString(filename, ".proto");
  466. }
  467. }
  468. const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
  469. switch (type) {
  470. case FieldDescriptor::CPPTYPE_INT32:
  471. return "::google::protobuf::int32";
  472. case FieldDescriptor::CPPTYPE_INT64:
  473. return "::google::protobuf::int64";
  474. case FieldDescriptor::CPPTYPE_UINT32:
  475. return "::google::protobuf::uint32";
  476. case FieldDescriptor::CPPTYPE_UINT64:
  477. return "::google::protobuf::uint64";
  478. case FieldDescriptor::CPPTYPE_DOUBLE:
  479. return "double";
  480. case FieldDescriptor::CPPTYPE_FLOAT:
  481. return "float";
  482. case FieldDescriptor::CPPTYPE_BOOL:
  483. return "bool";
  484. case FieldDescriptor::CPPTYPE_ENUM:
  485. return "int";
  486. case FieldDescriptor::CPPTYPE_STRING:
  487. return "std::string";
  488. case FieldDescriptor::CPPTYPE_MESSAGE:
  489. return nullptr;
  490. // No default because we want the compiler to complain if any new
  491. // CppTypes are added.
  492. }
  493. GOOGLE_LOG(FATAL) << "Can't get here.";
  494. return nullptr;
  495. }
  496. std::string PrimitiveTypeName(const Options& options,
  497. FieldDescriptor::CppType type) {
  498. switch (type) {
  499. case FieldDescriptor::CPPTYPE_INT32:
  500. return IntTypeName(options, "int32");
  501. case FieldDescriptor::CPPTYPE_INT64:
  502. return IntTypeName(options, "int64");
  503. case FieldDescriptor::CPPTYPE_UINT32:
  504. return IntTypeName(options, "uint32");
  505. case FieldDescriptor::CPPTYPE_UINT64:
  506. return IntTypeName(options, "uint64");
  507. case FieldDescriptor::CPPTYPE_DOUBLE:
  508. return "double";
  509. case FieldDescriptor::CPPTYPE_FLOAT:
  510. return "float";
  511. case FieldDescriptor::CPPTYPE_BOOL:
  512. return "bool";
  513. case FieldDescriptor::CPPTYPE_ENUM:
  514. return "int";
  515. case FieldDescriptor::CPPTYPE_STRING:
  516. return "std::string";
  517. case FieldDescriptor::CPPTYPE_MESSAGE:
  518. return "";
  519. // No default because we want the compiler to complain if any new
  520. // CppTypes are added.
  521. }
  522. GOOGLE_LOG(FATAL) << "Can't get here.";
  523. return "";
  524. }
  525. const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
  526. switch (type) {
  527. case FieldDescriptor::TYPE_INT32:
  528. return "Int32";
  529. case FieldDescriptor::TYPE_INT64:
  530. return "Int64";
  531. case FieldDescriptor::TYPE_UINT32:
  532. return "UInt32";
  533. case FieldDescriptor::TYPE_UINT64:
  534. return "UInt64";
  535. case FieldDescriptor::TYPE_SINT32:
  536. return "SInt32";
  537. case FieldDescriptor::TYPE_SINT64:
  538. return "SInt64";
  539. case FieldDescriptor::TYPE_FIXED32:
  540. return "Fixed32";
  541. case FieldDescriptor::TYPE_FIXED64:
  542. return "Fixed64";
  543. case FieldDescriptor::TYPE_SFIXED32:
  544. return "SFixed32";
  545. case FieldDescriptor::TYPE_SFIXED64:
  546. return "SFixed64";
  547. case FieldDescriptor::TYPE_FLOAT:
  548. return "Float";
  549. case FieldDescriptor::TYPE_DOUBLE:
  550. return "Double";
  551. case FieldDescriptor::TYPE_BOOL:
  552. return "Bool";
  553. case FieldDescriptor::TYPE_ENUM:
  554. return "Enum";
  555. case FieldDescriptor::TYPE_STRING:
  556. return "String";
  557. case FieldDescriptor::TYPE_BYTES:
  558. return "Bytes";
  559. case FieldDescriptor::TYPE_GROUP:
  560. return "Group";
  561. case FieldDescriptor::TYPE_MESSAGE:
  562. return "Message";
  563. // No default because we want the compiler to complain if any new
  564. // types are added.
  565. }
  566. GOOGLE_LOG(FATAL) << "Can't get here.";
  567. return "";
  568. }
  569. std::string Int32ToString(int number) {
  570. if (number == kint32min) {
  571. // This needs to be special-cased, see explanation here:
  572. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661
  573. return StrCat(number + 1, " - 1");
  574. } else {
  575. return StrCat(number);
  576. }
  577. }
  578. std::string Int64ToString(const std::string& macro_prefix, int64 number) {
  579. if (number == kint64min) {
  580. // This needs to be special-cased, see explanation here:
  581. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661
  582. return StrCat(macro_prefix, "_LONGLONG(", number + 1, ") - 1");
  583. }
  584. return StrCat(macro_prefix, "_LONGLONG(", number, ")");
  585. }
  586. std::string UInt64ToString(const std::string& macro_prefix, uint64 number) {
  587. return StrCat(macro_prefix, "_ULONGLONG(", number, ")");
  588. }
  589. std::string DefaultValue(const FieldDescriptor* field) {
  590. switch (field->cpp_type()) {
  591. case FieldDescriptor::CPPTYPE_INT64:
  592. return Int64ToString("GG", field->default_value_int64());
  593. case FieldDescriptor::CPPTYPE_UINT64:
  594. return UInt64ToString("GG", field->default_value_uint64());
  595. default:
  596. return DefaultValue(Options(), field);
  597. }
  598. }
  599. std::string DefaultValue(const Options& options, const FieldDescriptor* field) {
  600. switch (field->cpp_type()) {
  601. case FieldDescriptor::CPPTYPE_INT32:
  602. return Int32ToString(field->default_value_int32());
  603. case FieldDescriptor::CPPTYPE_UINT32:
  604. return StrCat(field->default_value_uint32()) + "u";
  605. case FieldDescriptor::CPPTYPE_INT64:
  606. return Int64ToString("PROTOBUF", field->default_value_int64());
  607. case FieldDescriptor::CPPTYPE_UINT64:
  608. return UInt64ToString("PROTOBUF", field->default_value_uint64());
  609. case FieldDescriptor::CPPTYPE_DOUBLE: {
  610. double value = field->default_value_double();
  611. if (value == std::numeric_limits<double>::infinity()) {
  612. return "std::numeric_limits<double>::infinity()";
  613. } else if (value == -std::numeric_limits<double>::infinity()) {
  614. return "-std::numeric_limits<double>::infinity()";
  615. } else if (value != value) {
  616. return "std::numeric_limits<double>::quiet_NaN()";
  617. } else {
  618. return SimpleDtoa(value);
  619. }
  620. }
  621. case FieldDescriptor::CPPTYPE_FLOAT: {
  622. float value = field->default_value_float();
  623. if (value == std::numeric_limits<float>::infinity()) {
  624. return "std::numeric_limits<float>::infinity()";
  625. } else if (value == -std::numeric_limits<float>::infinity()) {
  626. return "-std::numeric_limits<float>::infinity()";
  627. } else if (value != value) {
  628. return "std::numeric_limits<float>::quiet_NaN()";
  629. } else {
  630. std::string float_value = SimpleFtoa(value);
  631. // If floating point value contains a period (.) or an exponent
  632. // (either E or e), then append suffix 'f' to make it a float
  633. // literal.
  634. if (float_value.find_first_of(".eE") != std::string::npos) {
  635. float_value.push_back('f');
  636. }
  637. return float_value;
  638. }
  639. }
  640. case FieldDescriptor::CPPTYPE_BOOL:
  641. return field->default_value_bool() ? "true" : "false";
  642. case FieldDescriptor::CPPTYPE_ENUM:
  643. // Lazy: Generate a static_cast because we don't have a helper function
  644. // that constructs the full name of an enum value.
  645. return strings::Substitute(
  646. "static_cast< $0 >($1)", ClassName(field->enum_type(), true),
  647. Int32ToString(field->default_value_enum()->number()));
  648. case FieldDescriptor::CPPTYPE_STRING:
  649. return "\"" +
  650. EscapeTrigraphs(CEscape(field->default_value_string())) +
  651. "\"";
  652. case FieldDescriptor::CPPTYPE_MESSAGE:
  653. return "*" + FieldMessageTypeName(field, options) +
  654. "::internal_default_instance()";
  655. }
  656. // Can't actually get here; make compiler happy. (We could add a default
  657. // case above but then we wouldn't get the nice compiler warning when a
  658. // new type is added.)
  659. GOOGLE_LOG(FATAL) << "Can't get here.";
  660. return "";
  661. }
  662. // Convert a file name into a valid identifier.
  663. std::string FilenameIdentifier(const std::string& filename) {
  664. std::string result;
  665. for (int i = 0; i < filename.size(); i++) {
  666. if (ascii_isalnum(filename[i])) {
  667. result.push_back(filename[i]);
  668. } else {
  669. // Not alphanumeric. To avoid any possibility of name conflicts we
  670. // use the hex code for the character.
  671. StrAppend(&result, "_", strings::Hex(static_cast<uint8>(filename[i])));
  672. }
  673. }
  674. return result;
  675. }
  676. std::string UniqueName(const std::string& name, const std::string& filename,
  677. const Options& options) {
  678. return name + "_" + FilenameIdentifier(filename);
  679. }
  680. // Return the qualified C++ name for a file level symbol.
  681. std::string QualifiedFileLevelSymbol(const FileDescriptor* file,
  682. const std::string& name,
  683. const Options& options) {
  684. if (file->package().empty()) {
  685. return StrCat("::", name);
  686. }
  687. return StrCat(Namespace(file, options), "::", name);
  688. }
  689. // Escape C++ trigraphs by escaping question marks to \?
  690. std::string EscapeTrigraphs(const std::string& to_escape) {
  691. return StringReplace(to_escape, "?", "\\?", true);
  692. }
  693. // Escaped function name to eliminate naming conflict.
  694. std::string SafeFunctionName(const Descriptor* descriptor,
  695. const FieldDescriptor* field,
  696. const std::string& prefix) {
  697. // Do not use FieldName() since it will escape keywords.
  698. std::string name = field->name();
  699. LowerString(&name);
  700. std::string function_name = prefix + name;
  701. if (descriptor->FindFieldByName(function_name)) {
  702. // Single underscore will also make it conflicting with the private data
  703. // member. We use double underscore to escape function names.
  704. function_name.append("__");
  705. } else if (kKeywords.count(name) > 0) {
  706. // If the field name is a keyword, we append the underscore back to keep it
  707. // consistent with other function names.
  708. function_name.append("_");
  709. }
  710. return function_name;
  711. }
  712. bool IsStringInlined(const FieldDescriptor* descriptor,
  713. const Options& options) {
  714. if (options.opensource_runtime) return false;
  715. // TODO(ckennelly): Handle inlining for any.proto.
  716. if (IsAnyMessage(descriptor->containing_type(), options)) return false;
  717. if (descriptor->containing_type()->options().map_entry()) return false;
  718. // We rely on has bits to distinguish field presence for release_$name$. When
  719. // there is no hasbit, we cannot use the address of the string instance when
  720. // the field has been inlined.
  721. if (!HasHasbit(descriptor)) return false;
  722. if (options.access_info_map) {
  723. if (descriptor->is_required()) return true;
  724. }
  725. return false;
  726. }
  727. static bool HasLazyFields(const Descriptor* descriptor,
  728. const Options& options) {
  729. for (int field_idx = 0; field_idx < descriptor->field_count(); field_idx++) {
  730. if (IsLazy(descriptor->field(field_idx), options)) {
  731. return true;
  732. }
  733. }
  734. for (int idx = 0; idx < descriptor->extension_count(); idx++) {
  735. if (IsLazy(descriptor->extension(idx), options)) {
  736. return true;
  737. }
  738. }
  739. for (int idx = 0; idx < descriptor->nested_type_count(); idx++) {
  740. if (HasLazyFields(descriptor->nested_type(idx), options)) {
  741. return true;
  742. }
  743. }
  744. return false;
  745. }
  746. // Does the given FileDescriptor use lazy fields?
  747. bool HasLazyFields(const FileDescriptor* file, const Options& options) {
  748. for (int i = 0; i < file->message_type_count(); i++) {
  749. const Descriptor* descriptor(file->message_type(i));
  750. if (HasLazyFields(descriptor, options)) {
  751. return true;
  752. }
  753. }
  754. for (int field_idx = 0; field_idx < file->extension_count(); field_idx++) {
  755. if (IsLazy(file->extension(field_idx), options)) {
  756. return true;
  757. }
  758. }
  759. return false;
  760. }
  761. static bool HasRepeatedFields(const Descriptor* descriptor) {
  762. for (int i = 0; i < descriptor->field_count(); ++i) {
  763. if (descriptor->field(i)->label() == FieldDescriptor::LABEL_REPEATED) {
  764. return true;
  765. }
  766. }
  767. for (int i = 0; i < descriptor->nested_type_count(); ++i) {
  768. if (HasRepeatedFields(descriptor->nested_type(i))) return true;
  769. }
  770. return false;
  771. }
  772. bool HasRepeatedFields(const FileDescriptor* file) {
  773. for (int i = 0; i < file->message_type_count(); ++i) {
  774. if (HasRepeatedFields(file->message_type(i))) return true;
  775. }
  776. return false;
  777. }
  778. static bool IsStringPieceField(const FieldDescriptor* field,
  779. const Options& options) {
  780. return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
  781. EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE;
  782. }
  783. static bool HasStringPieceFields(const Descriptor* descriptor,
  784. const Options& options) {
  785. for (int i = 0; i < descriptor->field_count(); ++i) {
  786. if (IsStringPieceField(descriptor->field(i), options)) return true;
  787. }
  788. for (int i = 0; i < descriptor->nested_type_count(); ++i) {
  789. if (HasStringPieceFields(descriptor->nested_type(i), options)) return true;
  790. }
  791. return false;
  792. }
  793. bool HasStringPieceFields(const FileDescriptor* file, const Options& options) {
  794. for (int i = 0; i < file->message_type_count(); ++i) {
  795. if (HasStringPieceFields(file->message_type(i), options)) return true;
  796. }
  797. return false;
  798. }
  799. static bool IsCordField(const FieldDescriptor* field, const Options& options) {
  800. return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
  801. EffectiveStringCType(field, options) == FieldOptions::CORD;
  802. }
  803. static bool HasCordFields(const Descriptor* descriptor,
  804. const Options& options) {
  805. for (int i = 0; i < descriptor->field_count(); ++i) {
  806. if (IsCordField(descriptor->field(i), options)) return true;
  807. }
  808. for (int i = 0; i < descriptor->nested_type_count(); ++i) {
  809. if (HasCordFields(descriptor->nested_type(i), options)) return true;
  810. }
  811. return false;
  812. }
  813. bool HasCordFields(const FileDescriptor* file, const Options& options) {
  814. for (int i = 0; i < file->message_type_count(); ++i) {
  815. if (HasCordFields(file->message_type(i), options)) return true;
  816. }
  817. return false;
  818. }
  819. static bool HasExtensionsOrExtendableMessage(const Descriptor* descriptor) {
  820. if (descriptor->extension_range_count() > 0) return true;
  821. if (descriptor->extension_count() > 0) return true;
  822. for (int i = 0; i < descriptor->nested_type_count(); ++i) {
  823. if (HasExtensionsOrExtendableMessage(descriptor->nested_type(i))) {
  824. return true;
  825. }
  826. }
  827. return false;
  828. }
  829. bool HasExtensionsOrExtendableMessage(const FileDescriptor* file) {
  830. if (file->extension_count() > 0) return true;
  831. for (int i = 0; i < file->message_type_count(); ++i) {
  832. if (HasExtensionsOrExtendableMessage(file->message_type(i))) return true;
  833. }
  834. return false;
  835. }
  836. static bool HasMapFields(const Descriptor* descriptor) {
  837. for (int i = 0; i < descriptor->field_count(); ++i) {
  838. if (descriptor->field(i)->is_map()) {
  839. return true;
  840. }
  841. }
  842. for (int i = 0; i < descriptor->nested_type_count(); ++i) {
  843. if (HasMapFields(descriptor->nested_type(i))) return true;
  844. }
  845. return false;
  846. }
  847. bool HasMapFields(const FileDescriptor* file) {
  848. for (int i = 0; i < file->message_type_count(); ++i) {
  849. if (HasMapFields(file->message_type(i))) return true;
  850. }
  851. return false;
  852. }
  853. static bool HasEnumDefinitions(const Descriptor* message_type) {
  854. if (message_type->enum_type_count() > 0) return true;
  855. for (int i = 0; i < message_type->nested_type_count(); ++i) {
  856. if (HasEnumDefinitions(message_type->nested_type(i))) return true;
  857. }
  858. return false;
  859. }
  860. bool HasEnumDefinitions(const FileDescriptor* file) {
  861. if (file->enum_type_count() > 0) return true;
  862. for (int i = 0; i < file->message_type_count(); ++i) {
  863. if (HasEnumDefinitions(file->message_type(i))) return true;
  864. }
  865. return false;
  866. }
  867. bool IsStringOrMessage(const FieldDescriptor* field) {
  868. switch (field->cpp_type()) {
  869. case FieldDescriptor::CPPTYPE_INT32:
  870. case FieldDescriptor::CPPTYPE_INT64:
  871. case FieldDescriptor::CPPTYPE_UINT32:
  872. case FieldDescriptor::CPPTYPE_UINT64:
  873. case FieldDescriptor::CPPTYPE_DOUBLE:
  874. case FieldDescriptor::CPPTYPE_FLOAT:
  875. case FieldDescriptor::CPPTYPE_BOOL:
  876. case FieldDescriptor::CPPTYPE_ENUM:
  877. return false;
  878. case FieldDescriptor::CPPTYPE_STRING:
  879. case FieldDescriptor::CPPTYPE_MESSAGE:
  880. return true;
  881. }
  882. GOOGLE_LOG(FATAL) << "Can't get here.";
  883. return false;
  884. }
  885. FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field,
  886. const Options& options) {
  887. GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
  888. if (options.opensource_runtime) {
  889. // Open-source protobuf release only supports STRING ctype.
  890. return FieldOptions::STRING;
  891. } else {
  892. // Google-internal supports all ctypes.
  893. return field->options().ctype();
  894. }
  895. }
  896. bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options) {
  897. return descriptor->name() == kAnyProtoFile;
  898. }
  899. bool IsAnyMessage(const Descriptor* descriptor, const Options& options) {
  900. return descriptor->name() == kAnyMessageName &&
  901. IsAnyMessage(descriptor->file(), options);
  902. }
  903. bool IsWellKnownMessage(const FileDescriptor* file) {
  904. static const std::unordered_set<std::string> well_known_files{
  905. "google/protobuf/any.proto",
  906. "google/protobuf/api.proto",
  907. "google/protobuf/compiler/plugin.proto",
  908. "google/protobuf/descriptor.proto",
  909. "google/protobuf/duration.proto",
  910. "google/protobuf/empty.proto",
  911. "google/protobuf/field_mask.proto",
  912. "google/protobuf/source_context.proto",
  913. "google/protobuf/struct.proto",
  914. "google/protobuf/timestamp.proto",
  915. "google/protobuf/type.proto",
  916. "google/protobuf/wrappers.proto",
  917. };
  918. return well_known_files.find(file->name()) != well_known_files.end();
  919. }
  920. static bool FieldEnforceUtf8(const FieldDescriptor* field,
  921. const Options& options) {
  922. return true;
  923. }
  924. static bool FileUtf8Verification(const FileDescriptor* file,
  925. const Options& options) {
  926. return true;
  927. }
  928. // Which level of UTF-8 enforcemant is placed on this file.
  929. Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
  930. const Options& options) {
  931. if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
  932. FieldEnforceUtf8(field, options)) {
  933. return STRICT;
  934. } else if (GetOptimizeFor(field->file(), options) !=
  935. FileOptions::LITE_RUNTIME &&
  936. FileUtf8Verification(field->file(), options)) {
  937. return VERIFY;
  938. } else {
  939. return NONE;
  940. }
  941. }
  942. static void GenerateUtf8CheckCode(const FieldDescriptor* field,
  943. const Options& options, bool for_parse,
  944. const char* parameters,
  945. const char* strict_function,
  946. const char* verify_function,
  947. const Formatter& format) {
  948. switch (GetUtf8CheckMode(field, options)) {
  949. case STRICT: {
  950. if (for_parse) {
  951. format("DO_(");
  952. }
  953. format("::$proto_ns$::internal::WireFormatLite::$1$(\n", strict_function);
  954. format.Indent();
  955. format(parameters);
  956. if (for_parse) {
  957. format("::$proto_ns$::internal::WireFormatLite::PARSE,\n");
  958. } else {
  959. format("::$proto_ns$::internal::WireFormatLite::SERIALIZE,\n");
  960. }
  961. format("\"$1$\")", field->full_name());
  962. if (for_parse) {
  963. format(")");
  964. }
  965. format(";\n");
  966. format.Outdent();
  967. break;
  968. }
  969. case VERIFY: {
  970. format("::$proto_ns$::internal::WireFormat::$1$(\n", verify_function);
  971. format.Indent();
  972. format(parameters);
  973. if (for_parse) {
  974. format("::$proto_ns$::internal::WireFormat::PARSE,\n");
  975. } else {
  976. format("::$proto_ns$::internal::WireFormat::SERIALIZE,\n");
  977. }
  978. format("\"$1$\");\n", field->full_name());
  979. format.Outdent();
  980. break;
  981. }
  982. case NONE:
  983. break;
  984. }
  985. }
  986. void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
  987. const Options& options, bool for_parse,
  988. const char* parameters,
  989. const Formatter& format) {
  990. GenerateUtf8CheckCode(field, options, for_parse, parameters,
  991. "VerifyUtf8String", "VerifyUTF8StringNamedField",
  992. format);
  993. }
  994. void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
  995. const Options& options, bool for_parse,
  996. const char* parameters,
  997. const Formatter& format) {
  998. GenerateUtf8CheckCode(field, options, for_parse, parameters, "VerifyUtf8Cord",
  999. "VerifyUTF8CordNamedField", format);
  1000. }
  1001. namespace {
  1002. void Flatten(const Descriptor* descriptor,
  1003. std::vector<const Descriptor*>* flatten) {
  1004. for (int i = 0; i < descriptor->nested_type_count(); i++)
  1005. Flatten(descriptor->nested_type(i), flatten);
  1006. flatten->push_back(descriptor);
  1007. }
  1008. } // namespace
  1009. void FlattenMessagesInFile(const FileDescriptor* file,
  1010. std::vector<const Descriptor*>* result) {
  1011. for (int i = 0; i < file->message_type_count(); i++) {
  1012. Flatten(file->message_type(i), result);
  1013. }
  1014. }
  1015. bool HasWeakFields(const Descriptor* descriptor, const Options& options) {
  1016. for (int i = 0; i < descriptor->field_count(); i++) {
  1017. if (IsWeak(descriptor->field(i), options)) return true;
  1018. }
  1019. return false;
  1020. }
  1021. bool HasWeakFields(const FileDescriptor* file, const Options& options) {
  1022. for (int i = 0; i < file->message_type_count(); ++i) {
  1023. if (HasWeakFields(file->message_type(i), options)) return true;
  1024. }
  1025. return false;
  1026. }
  1027. bool UsingImplicitWeakFields(const FileDescriptor* file,
  1028. const Options& options) {
  1029. return options.lite_implicit_weak_fields &&
  1030. GetOptimizeFor(file, options) == FileOptions::LITE_RUNTIME;
  1031. }
  1032. bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
  1033. MessageSCCAnalyzer* scc_analyzer) {
  1034. return UsingImplicitWeakFields(field->file(), options) &&
  1035. field->type() == FieldDescriptor::TYPE_MESSAGE &&
  1036. !field->is_required() && !field->is_map() && !field->is_extension() &&
  1037. !field->real_containing_oneof() &&
  1038. !IsWellKnownMessage(field->message_type()->file()) &&
  1039. field->message_type()->file()->name() !=
  1040. "net/proto2/proto/descriptor.proto" &&
  1041. // We do not support implicit weak fields between messages in the same
  1042. // strongly-connected component.
  1043. scc_analyzer->GetSCC(field->containing_type()) !=
  1044. scc_analyzer->GetSCC(field->message_type());
  1045. }
  1046. MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
  1047. if (analysis_cache_.count(scc)) return analysis_cache_[scc];
  1048. MessageAnalysis result{};
  1049. for (int i = 0; i < scc->descriptors.size(); i++) {
  1050. const Descriptor* descriptor = scc->descriptors[i];
  1051. if (descriptor->extension_range_count() > 0) {
  1052. result.contains_extension = true;
  1053. // Extensions are found by looking up default_instance and extension
  1054. // number in a map. So you'd maybe expect here
  1055. // result.constructor_requires_initialization = true;
  1056. // However the extension registration mechanism already makes sure
  1057. // the default will be initialized.
  1058. }
  1059. for (int i = 0; i < descriptor->field_count(); i++) {
  1060. const FieldDescriptor* field = descriptor->field(i);
  1061. if (field->is_required()) {
  1062. result.contains_required = true;
  1063. }
  1064. switch (field->type()) {
  1065. case FieldDescriptor::TYPE_STRING:
  1066. case FieldDescriptor::TYPE_BYTES: {
  1067. result.constructor_requires_initialization = true;
  1068. if (field->options().ctype() == FieldOptions::CORD) {
  1069. result.contains_cord = true;
  1070. }
  1071. break;
  1072. }
  1073. case FieldDescriptor::TYPE_GROUP:
  1074. case FieldDescriptor::TYPE_MESSAGE: {
  1075. result.constructor_requires_initialization = true;
  1076. const SCC* child = analyzer_.GetSCC(field->message_type());
  1077. if (child != scc) {
  1078. MessageAnalysis analysis = GetSCCAnalysis(child);
  1079. result.contains_cord |= analysis.contains_cord;
  1080. result.contains_extension |= analysis.contains_extension;
  1081. if (!ShouldIgnoreRequiredFieldCheck(field, options_)) {
  1082. result.contains_required |= analysis.contains_required;
  1083. }
  1084. } else {
  1085. // This field points back into the same SCC hence the messages
  1086. // in the SCC are recursive. Note if SCC contains more than two
  1087. // nodes it has to be recursive, however this test also works for
  1088. // a single node that is recursive.
  1089. result.is_recursive = true;
  1090. }
  1091. break;
  1092. }
  1093. default:
  1094. break;
  1095. }
  1096. }
  1097. }
  1098. // We deliberately only insert the result here. After we contracted the SCC
  1099. // in the graph, the graph should be a DAG. Hence we shouldn't need to mark
  1100. // nodes visited as we can never return to them. By inserting them here
  1101. // we will go in an infinite loop if the SCC is not correct.
  1102. return analysis_cache_[scc] = result;
  1103. }
  1104. void ListAllFields(const Descriptor* d,
  1105. std::vector<const FieldDescriptor*>* fields) {
  1106. // Collect sub messages
  1107. for (int i = 0; i < d->nested_type_count(); i++) {
  1108. ListAllFields(d->nested_type(i), fields);
  1109. }
  1110. // Collect message level extensions.
  1111. for (int i = 0; i < d->extension_count(); i++) {
  1112. fields->push_back(d->extension(i));
  1113. }
  1114. // Add types of fields necessary
  1115. for (int i = 0; i < d->field_count(); i++) {
  1116. fields->push_back(d->field(i));
  1117. }
  1118. }
  1119. void ListAllFields(const FileDescriptor* d,
  1120. std::vector<const FieldDescriptor*>* fields) {
  1121. // Collect file level message.
  1122. for (int i = 0; i < d->message_type_count(); i++) {
  1123. ListAllFields(d->message_type(i), fields);
  1124. }
  1125. // Collect message level extensions.
  1126. for (int i = 0; i < d->extension_count(); i++) {
  1127. fields->push_back(d->extension(i));
  1128. }
  1129. }
  1130. void ListAllTypesForServices(const FileDescriptor* fd,
  1131. std::vector<const Descriptor*>* types) {
  1132. for (int i = 0; i < fd->service_count(); i++) {
  1133. const ServiceDescriptor* sd = fd->service(i);
  1134. for (int j = 0; j < sd->method_count(); j++) {
  1135. const MethodDescriptor* method = sd->method(j);
  1136. types->push_back(method->input_type());
  1137. types->push_back(method->output_type());
  1138. }
  1139. }
  1140. }
  1141. bool GetBootstrapBasename(const Options& options, const std::string& basename,
  1142. std::string* bootstrap_basename) {
  1143. if (options.opensource_runtime) {
  1144. return false;
  1145. }
  1146. std::unordered_map<std::string, std::string> bootstrap_mapping{
  1147. {"net/proto2/proto/descriptor",
  1148. "net/proto2/internal/descriptor"},
  1149. {"net/proto2/compiler/proto/plugin",
  1150. "net/proto2/compiler/proto/plugin"},
  1151. {"net/proto2/compiler/proto/profile",
  1152. "net/proto2/compiler/proto/profile_bootstrap"},
  1153. };
  1154. auto iter = bootstrap_mapping.find(basename);
  1155. if (iter == bootstrap_mapping.end()) {
  1156. *bootstrap_basename = basename;
  1157. return false;
  1158. } else {
  1159. *bootstrap_basename = iter->second;
  1160. return true;
  1161. }
  1162. }
  1163. bool IsBootstrapProto(const Options& options, const FileDescriptor* file) {
  1164. std::string my_name = StripProto(file->name());
  1165. return GetBootstrapBasename(options, my_name, &my_name);
  1166. }
  1167. bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context,
  1168. bool bootstrap_flag, std::string* basename) {
  1169. std::string bootstrap_basename;
  1170. if (!GetBootstrapBasename(options, *basename, &bootstrap_basename)) {
  1171. return false;
  1172. }
  1173. if (bootstrap_flag) {
  1174. // Adjust basename, but don't abort code generation.
  1175. *basename = bootstrap_basename;
  1176. return false;
  1177. } else {
  1178. std::string forward_to_basename = bootstrap_basename;
  1179. // Generate forwarding headers and empty .pb.cc.
  1180. {
  1181. std::unique_ptr<io::ZeroCopyOutputStream> output(
  1182. generator_context->Open(*basename + ".pb.h"));
  1183. io::Printer printer(output.get(), '$', nullptr);
  1184. printer.Print(
  1185. "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n"
  1186. "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n"
  1187. "#include \"$forward_to_basename$.pb.h\" // IWYU pragma: export\n"
  1188. "#endif // PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n",
  1189. "forward_to_basename", forward_to_basename, "filename_identifier",
  1190. FilenameIdentifier(*basename));
  1191. if (!options.opensource_runtime) {
  1192. // HACK HACK HACK, tech debt from the deeps of proto1 and SWIG
  1193. // protocoltype is SWIG'ed and we need to forward
  1194. if (*basename == "net/proto/protocoltype") {
  1195. printer.Print(
  1196. "#ifdef SWIG\n"
  1197. "%include \"$forward_to_basename$.pb.h\"\n"
  1198. "#endif // SWIG\n",
  1199. "forward_to_basename", forward_to_basename);
  1200. }
  1201. }
  1202. }
  1203. {
  1204. std::unique_ptr<io::ZeroCopyOutputStream> output(
  1205. generator_context->Open(*basename + ".proto.h"));
  1206. io::Printer printer(output.get(), '$', nullptr);
  1207. printer.Print(
  1208. "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n"
  1209. "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n"
  1210. "#include \"$forward_to_basename$.proto.h\" // IWYU pragma: "
  1211. "export\n"
  1212. "#endif // "
  1213. "PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n",
  1214. "forward_to_basename", forward_to_basename, "filename_identifier",
  1215. FilenameIdentifier(*basename));
  1216. }
  1217. {
  1218. std::unique_ptr<io::ZeroCopyOutputStream> output(
  1219. generator_context->Open(*basename + ".pb.cc"));
  1220. io::Printer printer(output.get(), '$', nullptr);
  1221. printer.Print("\n");
  1222. }
  1223. {
  1224. std::unique_ptr<io::ZeroCopyOutputStream> output(
  1225. generator_context->Open(*basename + ".pb.h.meta"));
  1226. }
  1227. {
  1228. std::unique_ptr<io::ZeroCopyOutputStream> output(
  1229. generator_context->Open(*basename + ".proto.h.meta"));
  1230. }
  1231. // Abort code generation.
  1232. return true;
  1233. }
  1234. }
  1235. class ParseLoopGenerator {
  1236. public:
  1237. ParseLoopGenerator(int num_hasbits, const Options& options,
  1238. MessageSCCAnalyzer* scc_analyzer, io::Printer* printer)
  1239. : scc_analyzer_(scc_analyzer),
  1240. options_(options),
  1241. format_(printer),
  1242. num_hasbits_(num_hasbits) {}
  1243. void GenerateParserLoop(const Descriptor* descriptor) {
  1244. format_.Set("classname", ClassName(descriptor));
  1245. format_.Set("p_ns", "::" + ProtobufNamespace(options_));
  1246. format_.Set("pi_ns",
  1247. StrCat("::", ProtobufNamespace(options_), "::internal"));
  1248. format_.Set("GOOGLE_PROTOBUF", MacroPrefix(options_));
  1249. std::map<std::string, std::string> vars;
  1250. SetCommonVars(options_, &vars);
  1251. SetUnknkownFieldsVariable(descriptor, options_, &vars);
  1252. format_.AddMap(vars);
  1253. std::vector<const FieldDescriptor*> ordered_fields;
  1254. for (auto field : FieldRange(descriptor)) {
  1255. if (IsFieldUsed(field, options_)) {
  1256. ordered_fields.push_back(field);
  1257. }
  1258. }
  1259. std::sort(ordered_fields.begin(), ordered_fields.end(),
  1260. [](const FieldDescriptor* a, const FieldDescriptor* b) {
  1261. return a->number() < b->number();
  1262. });
  1263. format_(
  1264. "const char* $classname$::_InternalParse(const char* ptr, "
  1265. "$pi_ns$::ParseContext* ctx) {\n"
  1266. "#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure\n");
  1267. format_.Indent();
  1268. int hasbits_size = 0;
  1269. if (num_hasbits_ > 0) {
  1270. hasbits_size = (num_hasbits_ + 31) / 32;
  1271. }
  1272. // For now only optimize small hasbits.
  1273. if (hasbits_size != 1) hasbits_size = 0;
  1274. if (hasbits_size) {
  1275. format_("_Internal::HasBits has_bits{};\n");
  1276. format_.Set("has_bits", "has_bits");
  1277. } else {
  1278. format_.Set("has_bits", "_has_bits_");
  1279. }
  1280. if (descriptor->file()->options().cc_enable_arenas()) {
  1281. format_("$p_ns$::Arena* arena = GetArena(); (void)arena;\n");
  1282. }
  1283. GenerateParseLoop(descriptor, ordered_fields);
  1284. format_.Outdent();
  1285. format_("success:\n");
  1286. if (hasbits_size) format_(" _has_bits_.Or(has_bits);\n");
  1287. format_(
  1288. " return ptr;\n"
  1289. "failure:\n"
  1290. " ptr = nullptr;\n"
  1291. " goto success;\n"
  1292. "#undef CHK_\n"
  1293. "}\n");
  1294. }
  1295. private:
  1296. MessageSCCAnalyzer* scc_analyzer_;
  1297. const Options& options_;
  1298. Formatter format_;
  1299. int num_hasbits_;
  1300. using WireFormat = internal::WireFormat;
  1301. using WireFormatLite = internal::WireFormatLite;
  1302. void GenerateArenaString(const FieldDescriptor* field) {
  1303. if (HasHasbit(field)) {
  1304. format_("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
  1305. }
  1306. std::string default_string =
  1307. field->default_value_string().empty()
  1308. ? "::" + ProtobufNamespace(options_) +
  1309. "::internal::GetEmptyStringAlreadyInited()"
  1310. : QualifiedClassName(field->containing_type(), options_) +
  1311. "::" + MakeDefaultName(field) + ".get()";
  1312. format_(
  1313. "if (arena != nullptr) {\n"
  1314. " ptr = ctx->ReadArenaString(ptr, &$1$_, arena);\n"
  1315. "} else {\n"
  1316. " ptr = "
  1317. "$pi_ns$::InlineGreedyStringParser($1$_.MutableNoArenaNoDefault(&$2$"
  1318. "), ptr, ctx);"
  1319. "\n}\n"
  1320. "const std::string* str = &$1$_.Get(); (void)str;\n",
  1321. FieldName(field), default_string);
  1322. }
  1323. void GenerateStrings(const FieldDescriptor* field, bool check_utf8) {
  1324. FieldOptions::CType ctype = FieldOptions::STRING;
  1325. if (!options_.opensource_runtime) {
  1326. // Open source doesn't support other ctypes;
  1327. ctype = field->options().ctype();
  1328. }
  1329. if (field->file()->options().cc_enable_arenas() && !field->is_repeated() &&
  1330. !options_.opensource_runtime &&
  1331. GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME &&
  1332. // For now only use arena string for strings with empty defaults.
  1333. field->default_value_string().empty() &&
  1334. !IsStringInlined(field, options_) && !field->real_containing_oneof() &&
  1335. ctype == FieldOptions::STRING) {
  1336. GenerateArenaString(field);
  1337. } else {
  1338. std::string name;
  1339. switch (ctype) {
  1340. case FieldOptions::STRING:
  1341. name = "GreedyStringParser";
  1342. break;
  1343. case FieldOptions::CORD:
  1344. name = "CordParser";
  1345. break;
  1346. case FieldOptions::STRING_PIECE:
  1347. name = "StringPieceParser";
  1348. break;
  1349. }
  1350. format_(
  1351. "auto str = $1$$2$_$3$();\n"
  1352. "ptr = $pi_ns$::Inline$4$(str, ptr, ctx);\n",
  1353. HasInternalAccessors(ctype) ? "_internal_" : "",
  1354. field->is_repeated() && !field->is_packable() ? "add" : "mutable",
  1355. FieldName(field), name);
  1356. }
  1357. if (!check_utf8) return; // return if this is a bytes field
  1358. auto level = GetUtf8CheckMode(field, options_);
  1359. switch (level) {
  1360. case NONE:
  1361. return;
  1362. case VERIFY:
  1363. format_("#ifndef NDEBUG\n");
  1364. break;
  1365. case STRICT:
  1366. format_("CHK_(");
  1367. break;
  1368. }
  1369. std::string field_name;
  1370. field_name = "nullptr";
  1371. if (HasDescriptorMethods(field->file(), options_)) {
  1372. field_name = StrCat("\"", field->full_name(), "\"");
  1373. }
  1374. format_("$pi_ns$::VerifyUTF8(str, $1$)", field_name);
  1375. switch (level) {
  1376. case NONE:
  1377. return;
  1378. case VERIFY:
  1379. format_(
  1380. ";\n"
  1381. "#endif // !NDEBUG\n");
  1382. break;
  1383. case STRICT:
  1384. format_(");\n");
  1385. break;
  1386. }
  1387. }
  1388. void GenerateLengthDelim(const FieldDescriptor* field) {
  1389. if (field->is_packable()) {
  1390. std::string enum_validator;
  1391. if (field->type() == FieldDescriptor::TYPE_ENUM &&
  1392. !HasPreservingUnknownEnumSemantics(field)) {
  1393. enum_validator =
  1394. StrCat(", ", QualifiedClassName(field->enum_type(), options_),
  1395. "_IsValid, &_internal_metadata_, ", field->number());
  1396. format_(
  1397. "ptr = "
  1398. "$pi_ns$::Packed$1$Parser<$unknown_fields_type$>(_internal_mutable_"
  1399. "$2$(), ptr, "
  1400. "ctx$3$);\n",
  1401. DeclaredTypeMethodName(field->type()), FieldName(field),
  1402. enum_validator);
  1403. } else {
  1404. format_(
  1405. "ptr = $pi_ns$::Packed$1$Parser(_internal_mutable_$2$(), ptr, "
  1406. "ctx$3$);\n",
  1407. DeclaredTypeMethodName(field->type()), FieldName(field),
  1408. enum_validator);
  1409. }
  1410. } else {
  1411. auto field_type = field->type();
  1412. switch (field_type) {
  1413. case FieldDescriptor::TYPE_STRING:
  1414. GenerateStrings(field, true /* utf8 */);
  1415. break;
  1416. case FieldDescriptor::TYPE_BYTES:
  1417. GenerateStrings(field, false /* utf8 */);
  1418. break;
  1419. case FieldDescriptor::TYPE_MESSAGE: {
  1420. if (field->is_map()) {
  1421. const FieldDescriptor* val =
  1422. field->message_type()->FindFieldByName("value");
  1423. GOOGLE_CHECK(val);
  1424. if (val->type() == FieldDescriptor::TYPE_ENUM &&
  1425. !HasPreservingUnknownEnumSemantics(field)) {
  1426. format_(
  1427. "auto object = "
  1428. "::$proto_ns$::internal::InitEnumParseWrapper<$unknown_"
  1429. "fields_type$>("
  1430. "&$1$_, $2$_IsValid, $3$, &_internal_metadata_);\n"
  1431. "ptr = ctx->ParseMessage(&object, ptr);\n",
  1432. FieldName(field), QualifiedClassName(val->enum_type()),
  1433. field->number());
  1434. } else {
  1435. format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n",
  1436. FieldName(field));
  1437. }
  1438. } else if (IsLazy(field, options_)) {
  1439. if (field->real_containing_oneof()) {
  1440. format_(
  1441. "if (!_internal_has_$1$()) {\n"
  1442. " clear_$2$();\n"
  1443. " $2$_.$1$_ = ::$proto_ns$::Arena::CreateMessage<\n"
  1444. " $pi_ns$::LazyField>(GetArena());\n"
  1445. " set_has_$1$();\n"
  1446. "}\n"
  1447. "ptr = ctx->ParseMessage($2$_.$1$_, ptr);\n",
  1448. FieldName(field), field->containing_oneof()->name());
  1449. } else if (HasHasbit(field)) {
  1450. format_(
  1451. "_Internal::set_has_$1$(&$has_bits$);\n"
  1452. "ptr = ctx->ParseMessage(&$1$_, ptr);\n",
  1453. FieldName(field));
  1454. } else {
  1455. format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n",
  1456. FieldName(field));
  1457. }
  1458. } else if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
  1459. if (!field->is_repeated()) {
  1460. format_(
  1461. "ptr = ctx->ParseMessage(_Internal::mutable_$1$(this), "
  1462. "ptr);\n",
  1463. FieldName(field));
  1464. } else {
  1465. format_(
  1466. "ptr = ctx->ParseMessage($1$_.AddWeak(reinterpret_cast<const "
  1467. "::$proto_ns$::MessageLite*>($2$::_$3$_default_instance_ptr_)"
  1468. "), ptr);\n",
  1469. FieldName(field), Namespace(field->message_type(), options_),
  1470. ClassName(field->message_type()));
  1471. }
  1472. } else if (IsWeak(field, options_)) {
  1473. format_(
  1474. "ptr = ctx->ParseMessage(_weak_field_map_.MutableMessage($1$,"
  1475. " _$classname$_default_instance_.$2$_), ptr);\n",
  1476. field->number(), FieldName(field));
  1477. } else {
  1478. format_("ptr = ctx->ParseMessage(_internal_$1$_$2$(), ptr);\n",
  1479. field->is_repeated() ? "add" : "mutable", FieldName(field));
  1480. }
  1481. break;
  1482. }
  1483. default:
  1484. GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype "
  1485. << " filed type is " << field->type();
  1486. }
  1487. }
  1488. }
  1489. // Convert a 1 or 2 byte varint into the equivalent value upon a direct load.
  1490. static uint32 SmallVarintValue(uint32 x) {
  1491. GOOGLE_DCHECK(x < 128 * 128);
  1492. if (x >= 128) x += (x & 0xFF80) + 128;
  1493. return x;
  1494. }
  1495. static bool ShouldRepeat(const FieldDescriptor* descriptor,
  1496. internal::WireFormatLite::WireType wiretype) {
  1497. constexpr int kMaxTwoByteFieldNumber = 16 * 128;
  1498. return descriptor->number() < kMaxTwoByteFieldNumber &&
  1499. descriptor->is_repeated() &&
  1500. (!descriptor->is_packable() ||
  1501. wiretype != internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
  1502. }
  1503. void GenerateFieldBody(internal::WireFormatLite::WireType wiretype,
  1504. const FieldDescriptor* field) {
  1505. uint32 tag = WireFormatLite::MakeTag(field->number(), wiretype);
  1506. switch (wiretype) {
  1507. case WireFormatLite::WIRETYPE_VARINT: {
  1508. std::string type = PrimitiveTypeName(options_, field->cpp_type());
  1509. std::string prefix = field->is_repeated() ? "add" : "set";
  1510. if (field->type() == FieldDescriptor::TYPE_ENUM) {
  1511. format_(
  1512. "$uint64$ val = $pi_ns$::ReadVarint64(&ptr);\n"
  1513. "CHK_(ptr);\n");
  1514. if (!HasPreservingUnknownEnumSemantics(field)) {
  1515. format_("if (PROTOBUF_PREDICT_TRUE($1$_IsValid(val))) {\n",
  1516. QualifiedClassName(field->enum_type(), options_));
  1517. format_.Indent();
  1518. }
  1519. format_("_internal_$1$_$2$(static_cast<$3$>(val));\n", prefix,
  1520. FieldName(field),
  1521. QualifiedClassName(field->enum_type(), options_));
  1522. if (!HasPreservingUnknownEnumSemantics(field)) {
  1523. format_.Outdent();
  1524. format_(
  1525. "} else {\n"
  1526. " $pi_ns$::WriteVarint($1$, val, mutable_unknown_fields());\n"
  1527. "}\n",
  1528. field->number());
  1529. }
  1530. } else {
  1531. std::string size = (field->type() == FieldDescriptor::TYPE_SINT32 ||
  1532. field->type() == FieldDescriptor::TYPE_UINT32)
  1533. ? "32"
  1534. : "64";
  1535. std::string zigzag;
  1536. if ((field->type() == FieldDescriptor::TYPE_SINT32 ||
  1537. field->type() == FieldDescriptor::TYPE_SINT64)) {
  1538. zigzag = "ZigZag";
  1539. }
  1540. if (field->is_repeated() || field->real_containing_oneof()) {
  1541. std::string prefix = field->is_repeated() ? "add" : "set";
  1542. format_(
  1543. "_internal_$1$_$2$($pi_ns$::ReadVarint$3$$4$(&ptr));\n"
  1544. "CHK_(ptr);\n",
  1545. prefix, FieldName(field), zigzag, size);
  1546. } else {
  1547. if (HasHasbit(field)) {
  1548. format_("_Internal::set_has_$1$(&$has_bits$);\n",
  1549. FieldName(field));
  1550. }
  1551. format_(
  1552. "$1$_ = $pi_ns$::ReadVarint$2$$3$(&ptr);\n"
  1553. "CHK_(ptr);\n",
  1554. FieldName(field), zigzag, size);
  1555. }
  1556. }
  1557. break;
  1558. }
  1559. case WireFormatLite::WIRETYPE_FIXED32:
  1560. case WireFormatLite::WIRETYPE_FIXED64: {
  1561. std::string type = PrimitiveTypeName(options_, field->cpp_type());
  1562. if (field->is_repeated() || field->real_containing_oneof()) {
  1563. std::string prefix = field->is_repeated() ? "add" : "set";
  1564. format_(
  1565. "_internal_$1$_$2$($pi_ns$::UnalignedLoad<$3$>(ptr));\n"
  1566. "ptr += sizeof($3$);\n",
  1567. prefix, FieldName(field), type);
  1568. } else {
  1569. if (HasHasbit(field)) {
  1570. format_("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
  1571. }
  1572. format_(
  1573. "$1$_ = $pi_ns$::UnalignedLoad<$2$>(ptr);\n"
  1574. "ptr += sizeof($2$);\n",
  1575. FieldName(field), type);
  1576. }
  1577. break;
  1578. }
  1579. case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
  1580. GenerateLengthDelim(field);
  1581. format_("CHK_(ptr);\n");
  1582. break;
  1583. }
  1584. case WireFormatLite::WIRETYPE_START_GROUP: {
  1585. format_(
  1586. "ptr = ctx->ParseGroup(_internal_$1$_$2$(), ptr, $3$);\n"
  1587. "CHK_(ptr);\n",
  1588. field->is_repeated() ? "add" : "mutable", FieldName(field), tag);
  1589. break;
  1590. }
  1591. case WireFormatLite::WIRETYPE_END_GROUP: {
  1592. GOOGLE_LOG(FATAL) << "Can't have end group field\n";
  1593. break;
  1594. }
  1595. } // switch (wire_type)
  1596. }
  1597. // Returns the tag for this field and in case of repeated packable fields,
  1598. // sets a fallback tag in fallback_tag_ptr.
  1599. static uint32 ExpectedTag(const FieldDescriptor* field,
  1600. uint32* fallback_tag_ptr) {
  1601. uint32 expected_tag;
  1602. if (field->is_packable()) {
  1603. auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type());
  1604. expected_tag =
  1605. WireFormatLite::MakeTag(field->number(), expected_wiretype);
  1606. GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
  1607. auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
  1608. uint32 fallback_tag =
  1609. WireFormatLite::MakeTag(field->number(), fallback_wiretype);
  1610. if (field->is_packed()) std::swap(expected_tag, fallback_tag);
  1611. *fallback_tag_ptr = fallback_tag;
  1612. } else {
  1613. auto expected_wiretype = WireFormat::WireTypeForField(field);
  1614. expected_tag =
  1615. WireFormatLite::MakeTag(field->number(), expected_wiretype);
  1616. }
  1617. return expected_tag;
  1618. }
  1619. void GenerateParseLoop(
  1620. const Descriptor* descriptor,
  1621. const std::vector<const FieldDescriptor*>& ordered_fields) {
  1622. format_(
  1623. "while (!ctx->Done(&ptr)) {\n"
  1624. " $uint32$ tag;\n"
  1625. " ptr = $pi_ns$::ReadTag(ptr, &tag);\n"
  1626. " CHK_(ptr);\n");
  1627. if (!ordered_fields.empty()) format_(" switch (tag >> 3) {\n");
  1628. format_.Indent();
  1629. format_.Indent();
  1630. for (const auto* field : ordered_fields) {
  1631. PrintFieldComment(format_, field);
  1632. format_("case $1$:\n", field->number());
  1633. format_.Indent();
  1634. uint32 fallback_tag = 0;
  1635. uint32 expected_tag = ExpectedTag(field, &fallback_tag);
  1636. format_(
  1637. "if (PROTOBUF_PREDICT_TRUE(static_cast<$uint8$>(tag) == $1$)) {\n",
  1638. expected_tag & 0xFF);
  1639. format_.Indent();
  1640. auto wiretype = WireFormatLite::GetTagWireType(expected_tag);
  1641. uint32 tag = WireFormatLite::MakeTag(field->number(), wiretype);
  1642. int tag_size = io::CodedOutputStream::VarintSize32(tag);
  1643. bool is_repeat = ShouldRepeat(field, wiretype);
  1644. if (is_repeat) {
  1645. format_(
  1646. "ptr -= $1$;\n"
  1647. "do {\n"
  1648. " ptr += $1$;\n",
  1649. tag_size);
  1650. format_.Indent();
  1651. }
  1652. GenerateFieldBody(wiretype, field);
  1653. if (is_repeat) {
  1654. format_.Outdent();
  1655. format_(
  1656. " if (!ctx->DataAvailable(ptr)) break;\n"
  1657. "} while ($pi_ns$::ExpectTag<$1$>(ptr));\n",
  1658. tag);
  1659. }
  1660. format_.Outdent();
  1661. if (fallback_tag) {
  1662. format_("} else if (static_cast<$uint8$>(tag) == $1$) {\n",
  1663. fallback_tag & 0xFF);
  1664. format_.Indent();
  1665. GenerateFieldBody(WireFormatLite::GetTagWireType(fallback_tag), field);
  1666. format_.Outdent();
  1667. }
  1668. format_.Outdent();
  1669. format_(
  1670. " } else goto handle_unusual;\n"
  1671. " continue;\n");
  1672. } // for loop over ordered fields
  1673. // Default case
  1674. if (!ordered_fields.empty()) format_("default: {\n");
  1675. if (!ordered_fields.empty()) format_("handle_unusual:\n");
  1676. format_(
  1677. " if ((tag & 7) == 4 || tag == 0) {\n"
  1678. " ctx->SetLastTag(tag);\n"
  1679. " goto success;\n"
  1680. " }\n");
  1681. if (IsMapEntryMessage(descriptor)) {
  1682. format_(" continue;\n");
  1683. } else {
  1684. if (descriptor->extension_range_count() > 0) {
  1685. format_("if (");
  1686. for (int i = 0; i < descriptor->extension_range_count(); i++) {
  1687. const Descriptor::ExtensionRange* range =
  1688. descriptor->extension_range(i);
  1689. if (i > 0) format_(" ||\n ");
  1690. uint32 start_tag = WireFormatLite::MakeTag(
  1691. range->start, static_cast<WireFormatLite::WireType>(0));
  1692. uint32 end_tag = WireFormatLite::MakeTag(
  1693. range->end, static_cast<WireFormatLite::WireType>(0));
  1694. if (range->end > FieldDescriptor::kMaxNumber) {
  1695. format_("($1$u <= tag)", start_tag);
  1696. } else {
  1697. format_("($1$u <= tag && tag < $2$u)", start_tag, end_tag);
  1698. }
  1699. }
  1700. format_(") {\n");
  1701. format_(
  1702. " ptr = _extensions_.ParseField(tag, ptr,\n"
  1703. " internal_default_instance(), &_internal_metadata_, ctx);\n"
  1704. " CHK_(ptr != nullptr);\n"
  1705. " continue;\n"
  1706. "}\n");
  1707. }
  1708. format_(
  1709. " ptr = UnknownFieldParse(tag,\n"
  1710. " _internal_metadata_.mutable_unknown_fields<$unknown_"
  1711. "fields_type$>(),\n"
  1712. " ptr, ctx);\n"
  1713. " CHK_(ptr != nullptr);\n"
  1714. " continue;\n");
  1715. }
  1716. if (!ordered_fields.empty()) format_("}\n"); // default case
  1717. format_.Outdent();
  1718. format_.Outdent();
  1719. if (!ordered_fields.empty()) format_(" } // switch\n");
  1720. format_("} // while\n");
  1721. }
  1722. };
  1723. void GenerateParserLoop(const Descriptor* descriptor, int num_hasbits,
  1724. const Options& options,
  1725. MessageSCCAnalyzer* scc_analyzer,
  1726. io::Printer* printer) {
  1727. ParseLoopGenerator generator(num_hasbits, options, scc_analyzer, printer);
  1728. generator.GenerateParserLoop(descriptor);
  1729. }
  1730. static bool HasExtensionFromFile(const Message& msg, const FileDescriptor* file,
  1731. const Options& options,
  1732. bool* has_opt_codesize_extension) {
  1733. std::vector<const FieldDescriptor*> fields;
  1734. auto reflection = msg.GetReflection();
  1735. reflection->ListFields(msg, &fields);
  1736. for (auto field : fields) {
  1737. const auto* field_msg = field->message_type();
  1738. if (field_msg == nullptr) {
  1739. // It so happens that enums Is_Valid are still generated so enums work.
  1740. // Only messages have potential problems.
  1741. continue;
  1742. }
  1743. // If this option has an extension set AND that extension is defined in the
  1744. // same file we have bootstrap problem.
  1745. if (field->is_extension()) {
  1746. const auto* msg_extension_file = field->message_type()->file();
  1747. if (msg_extension_file == file) return true;
  1748. if (has_opt_codesize_extension &&
  1749. GetOptimizeFor(msg_extension_file, options) ==
  1750. FileOptions::CODE_SIZE) {
  1751. *has_opt_codesize_extension = true;
  1752. }
  1753. }
  1754. // Recurse in this field to see if there is a problem in there
  1755. if (field->is_repeated()) {
  1756. for (int i = 0; i < reflection->FieldSize(msg, field); i++) {
  1757. if (HasExtensionFromFile(reflection->GetRepeatedMessage(msg, field, i),
  1758. file, options, has_opt_codesize_extension)) {
  1759. return true;
  1760. }
  1761. }
  1762. } else {
  1763. if (HasExtensionFromFile(reflection->GetMessage(msg, field), file,
  1764. options, has_opt_codesize_extension)) {
  1765. return true;
  1766. }
  1767. }
  1768. }
  1769. return false;
  1770. }
  1771. static bool HasBootstrapProblem(const FileDescriptor* file,
  1772. const Options& options,
  1773. bool* has_opt_codesize_extension) {
  1774. static auto& cache = *new std::unordered_map<const FileDescriptor*, bool>;
  1775. auto it = cache.find(file);
  1776. if (it != cache.end()) return it->second;
  1777. // In order to build the data structures for the reflective parse, it needs
  1778. // to parse the serialized descriptor describing all the messages defined in
  1779. // this file. Obviously this presents a bootstrap problem for descriptor
  1780. // messages.
  1781. if (file->name() == "net/proto2/proto/descriptor.proto" ||
  1782. file->name() == "google/protobuf/descriptor.proto") {
  1783. return true;
  1784. }
  1785. // Unfortunately we're not done yet. The descriptor option messages allow
  1786. // for extensions. So we need to be able to parse these extensions in order
  1787. // to parse the file descriptor for a file that has custom options. This is a
  1788. // problem when these custom options extensions are defined in the same file.
  1789. FileDescriptorProto linkedin_fd_proto;
  1790. const DescriptorPool* pool = file->pool();
  1791. const Descriptor* fd_proto_descriptor =
  1792. pool->FindMessageTypeByName(linkedin_fd_proto.GetTypeName());
  1793. // Not all pools have descriptor.proto in them. In these cases there for sure
  1794. // are no custom options.
  1795. if (fd_proto_descriptor == nullptr) return false;
  1796. // It's easier to inspect file as a proto, because we can use reflection on
  1797. // the proto to iterate over all content.
  1798. file->CopyTo(&linkedin_fd_proto);
  1799. // linkedin_fd_proto is a generated proto linked in the proto compiler. As
  1800. // such it doesn't know the extensions that are potentially present in the
  1801. // descriptor pool constructed from the protos that are being compiled. These
  1802. // custom options are therefore in the unknown fields.
  1803. // By building the corresponding FileDescriptorProto in the pool constructed
  1804. // by the protos that are being compiled, ie. file's pool, the unknown fields
  1805. // are converted to extensions.
  1806. DynamicMessageFactory factory(pool);
  1807. Message* fd_proto = factory.GetPrototype(fd_proto_descriptor)->New();
  1808. fd_proto->ParseFromString(linkedin_fd_proto.SerializeAsString());
  1809. bool& res = cache[file];
  1810. res = HasExtensionFromFile(*fd_proto, file, options,
  1811. has_opt_codesize_extension);
  1812. delete fd_proto;
  1813. return res;
  1814. }
  1815. FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
  1816. const Options& options,
  1817. bool* has_opt_codesize_extension) {
  1818. if (has_opt_codesize_extension) *has_opt_codesize_extension = false;
  1819. switch (options.enforce_mode) {
  1820. case EnforceOptimizeMode::kSpeed:
  1821. return FileOptions::SPEED;
  1822. case EnforceOptimizeMode::kLiteRuntime:
  1823. return FileOptions::LITE_RUNTIME;
  1824. case EnforceOptimizeMode::kCodeSize:
  1825. if (file->options().optimize_for() == FileOptions::LITE_RUNTIME) {
  1826. return FileOptions::LITE_RUNTIME;
  1827. }
  1828. if (HasBootstrapProblem(file, options, has_opt_codesize_extension)) {
  1829. return FileOptions::SPEED;
  1830. }
  1831. return FileOptions::CODE_SIZE;
  1832. case EnforceOptimizeMode::kNoEnforcement:
  1833. if (file->options().optimize_for() == FileOptions::CODE_SIZE) {
  1834. if (HasBootstrapProblem(file, options, has_opt_codesize_extension)) {
  1835. GOOGLE_LOG(WARNING) << "Proto states optimize_for = CODE_SIZE, but we "
  1836. "cannot honor that because it contains custom option "
  1837. "extensions defined in the same proto.";
  1838. return FileOptions::SPEED;
  1839. }
  1840. }
  1841. return file->options().optimize_for();
  1842. }
  1843. GOOGLE_LOG(FATAL) << "Unknown optimization enforcement requested.";
  1844. // The phony return below serves to silence a warning from GCC 8.
  1845. return FileOptions::SPEED;
  1846. }
  1847. } // namespace cpp
  1848. } // namespace compiler
  1849. } // namespace protobuf
  1850. } // namespace google