YAMLTraits.h 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_SUPPORT_YAMLTRAITS_H
  14. #define LLVM_SUPPORT_YAMLTRAITS_H
  15. #include "llvm/ADT/ArrayRef.h"
  16. #include "llvm/ADT/BitVector.h"
  17. #include "llvm/ADT/SmallVector.h"
  18. #include "llvm/ADT/StringExtras.h"
  19. #include "llvm/ADT/StringMap.h"
  20. #include "llvm/ADT/StringRef.h"
  21. #include "llvm/ADT/Twine.h"
  22. #include "llvm/Support/AlignOf.h"
  23. #include "llvm/Support/Allocator.h"
  24. #include "llvm/Support/Endian.h"
  25. #include "llvm/Support/SMLoc.h"
  26. #include "llvm/Support/SourceMgr.h"
  27. #include "llvm/Support/YAMLParser.h"
  28. #include "llvm/Support/raw_ostream.h"
  29. #include <cassert>
  30. #include <map>
  31. #include <memory>
  32. #include <new>
  33. #include <optional>
  34. #include <string>
  35. #include <system_error>
  36. #include <type_traits>
  37. #include <vector>
  38. namespace llvm {
  39. class VersionTuple;
  40. namespace yaml {
  41. enum class NodeKind : uint8_t {
  42. Scalar,
  43. Map,
  44. Sequence,
  45. };
  46. struct EmptyContext {};
  47. /// This class should be specialized by any type that needs to be converted
  48. /// to/from a YAML mapping. For example:
  49. ///
  50. /// struct MappingTraits<MyStruct> {
  51. /// static void mapping(IO &io, MyStruct &s) {
  52. /// io.mapRequired("name", s.name);
  53. /// io.mapRequired("size", s.size);
  54. /// io.mapOptional("age", s.age);
  55. /// }
  56. /// };
  57. template<class T>
  58. struct MappingTraits {
  59. // Must provide:
  60. // static void mapping(IO &io, T &fields);
  61. // Optionally may provide:
  62. // static std::string validate(IO &io, T &fields);
  63. // static void enumInput(IO &io, T &value);
  64. //
  65. // The optional flow flag will cause generated YAML to use a flow mapping
  66. // (e.g. { a: 0, b: 1 }):
  67. // static const bool flow = true;
  68. };
  69. /// This class is similar to MappingTraits<T> but allows you to pass in
  70. /// additional context for each map operation. For example:
  71. ///
  72. /// struct MappingContextTraits<MyStruct, MyContext> {
  73. /// static void mapping(IO &io, MyStruct &s, MyContext &c) {
  74. /// io.mapRequired("name", s.name);
  75. /// io.mapRequired("size", s.size);
  76. /// io.mapOptional("age", s.age);
  77. /// ++c.TimesMapped;
  78. /// }
  79. /// };
  80. template <class T, class Context> struct MappingContextTraits {
  81. // Must provide:
  82. // static void mapping(IO &io, T &fields, Context &Ctx);
  83. // Optionally may provide:
  84. // static std::string validate(IO &io, T &fields, Context &Ctx);
  85. //
  86. // The optional flow flag will cause generated YAML to use a flow mapping
  87. // (e.g. { a: 0, b: 1 }):
  88. // static const bool flow = true;
  89. };
  90. /// This class should be specialized by any integral type that converts
  91. /// to/from a YAML scalar where there is a one-to-one mapping between
  92. /// in-memory values and a string in YAML. For example:
  93. ///
  94. /// struct ScalarEnumerationTraits<Colors> {
  95. /// static void enumeration(IO &io, Colors &value) {
  96. /// io.enumCase(value, "red", cRed);
  97. /// io.enumCase(value, "blue", cBlue);
  98. /// io.enumCase(value, "green", cGreen);
  99. /// }
  100. /// };
  101. template <typename T, typename Enable = void> struct ScalarEnumerationTraits {
  102. // Must provide:
  103. // static void enumeration(IO &io, T &value);
  104. };
  105. /// This class should be specialized by any integer type that is a union
  106. /// of bit values and the YAML representation is a flow sequence of
  107. /// strings. For example:
  108. ///
  109. /// struct ScalarBitSetTraits<MyFlags> {
  110. /// static void bitset(IO &io, MyFlags &value) {
  111. /// io.bitSetCase(value, "big", flagBig);
  112. /// io.bitSetCase(value, "flat", flagFlat);
  113. /// io.bitSetCase(value, "round", flagRound);
  114. /// }
  115. /// };
  116. template <typename T, typename Enable = void> struct ScalarBitSetTraits {
  117. // Must provide:
  118. // static void bitset(IO &io, T &value);
  119. };
  120. /// Describe which type of quotes should be used when quoting is necessary.
  121. /// Some non-printable characters need to be double-quoted, while some others
  122. /// are fine with simple-quoting, and some don't need any quoting.
  123. enum class QuotingType { None, Single, Double };
  124. /// This class should be specialized by type that requires custom conversion
  125. /// to/from a yaml scalar. For example:
  126. ///
  127. /// template<>
  128. /// struct ScalarTraits<MyType> {
  129. /// static void output(const MyType &val, void*, llvm::raw_ostream &out) {
  130. /// // stream out custom formatting
  131. /// out << llvm::format("%x", val);
  132. /// }
  133. /// static StringRef input(StringRef scalar, void*, MyType &value) {
  134. /// // parse scalar and set `value`
  135. /// // return empty string on success, or error string
  136. /// return StringRef();
  137. /// }
  138. /// static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
  139. /// };
  140. template <typename T, typename Enable = void> struct ScalarTraits {
  141. // Must provide:
  142. //
  143. // Function to write the value as a string:
  144. // static void output(const T &value, void *ctxt, llvm::raw_ostream &out);
  145. //
  146. // Function to convert a string to a value. Returns the empty
  147. // StringRef on success or an error string if string is malformed:
  148. // static StringRef input(StringRef scalar, void *ctxt, T &value);
  149. //
  150. // Function to determine if the value should be quoted.
  151. // static QuotingType mustQuote(StringRef);
  152. };
  153. /// This class should be specialized by type that requires custom conversion
  154. /// to/from a YAML literal block scalar. For example:
  155. ///
  156. /// template <>
  157. /// struct BlockScalarTraits<MyType> {
  158. /// static void output(const MyType &Value, void*, llvm::raw_ostream &Out)
  159. /// {
  160. /// // stream out custom formatting
  161. /// Out << Value;
  162. /// }
  163. /// static StringRef input(StringRef Scalar, void*, MyType &Value) {
  164. /// // parse scalar and set `value`
  165. /// // return empty string on success, or error string
  166. /// return StringRef();
  167. /// }
  168. /// };
  169. template <typename T>
  170. struct BlockScalarTraits {
  171. // Must provide:
  172. //
  173. // Function to write the value as a string:
  174. // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out);
  175. //
  176. // Function to convert a string to a value. Returns the empty
  177. // StringRef on success or an error string if string is malformed:
  178. // static StringRef input(StringRef Scalar, void *ctxt, T &Value);
  179. //
  180. // Optional:
  181. // static StringRef inputTag(T &Val, std::string Tag)
  182. // static void outputTag(const T &Val, raw_ostream &Out)
  183. };
  184. /// This class should be specialized by type that requires custom conversion
  185. /// to/from a YAML scalar with optional tags. For example:
  186. ///
  187. /// template <>
  188. /// struct TaggedScalarTraits<MyType> {
  189. /// static void output(const MyType &Value, void*, llvm::raw_ostream
  190. /// &ScalarOut, llvm::raw_ostream &TagOut)
  191. /// {
  192. /// // stream out custom formatting including optional Tag
  193. /// Out << Value;
  194. /// }
  195. /// static StringRef input(StringRef Scalar, StringRef Tag, void*, MyType
  196. /// &Value) {
  197. /// // parse scalar and set `value`
  198. /// // return empty string on success, or error string
  199. /// return StringRef();
  200. /// }
  201. /// static QuotingType mustQuote(const MyType &Value, StringRef) {
  202. /// return QuotingType::Single;
  203. /// }
  204. /// };
  205. template <typename T> struct TaggedScalarTraits {
  206. // Must provide:
  207. //
  208. // Function to write the value and tag as strings:
  209. // static void output(const T &Value, void *ctx, llvm::raw_ostream &ScalarOut,
  210. // llvm::raw_ostream &TagOut);
  211. //
  212. // Function to convert a string to a value. Returns the empty
  213. // StringRef on success or an error string if string is malformed:
  214. // static StringRef input(StringRef Scalar, StringRef Tag, void *ctxt, T
  215. // &Value);
  216. //
  217. // Function to determine if the value should be quoted.
  218. // static QuotingType mustQuote(const T &Value, StringRef Scalar);
  219. };
  220. /// This class should be specialized by any type that needs to be converted
  221. /// to/from a YAML sequence. For example:
  222. ///
  223. /// template<>
  224. /// struct SequenceTraits<MyContainer> {
  225. /// static size_t size(IO &io, MyContainer &seq) {
  226. /// return seq.size();
  227. /// }
  228. /// static MyType& element(IO &, MyContainer &seq, size_t index) {
  229. /// if ( index >= seq.size() )
  230. /// seq.resize(index+1);
  231. /// return seq[index];
  232. /// }
  233. /// };
  234. template<typename T, typename EnableIf = void>
  235. struct SequenceTraits {
  236. // Must provide:
  237. // static size_t size(IO &io, T &seq);
  238. // static T::value_type& element(IO &io, T &seq, size_t index);
  239. //
  240. // The following is option and will cause generated YAML to use
  241. // a flow sequence (e.g. [a,b,c]).
  242. // static const bool flow = true;
  243. };
  244. /// This class should be specialized by any type for which vectors of that
  245. /// type need to be converted to/from a YAML sequence.
  246. template<typename T, typename EnableIf = void>
  247. struct SequenceElementTraits {
  248. // Must provide:
  249. // static const bool flow;
  250. };
  251. /// This class should be specialized by any type that needs to be converted
  252. /// to/from a list of YAML documents.
  253. template<typename T>
  254. struct DocumentListTraits {
  255. // Must provide:
  256. // static size_t size(IO &io, T &seq);
  257. // static T::value_type& element(IO &io, T &seq, size_t index);
  258. };
  259. /// This class should be specialized by any type that needs to be converted
  260. /// to/from a YAML mapping in the case where the names of the keys are not known
  261. /// in advance, e.g. a string map.
  262. template <typename T>
  263. struct CustomMappingTraits {
  264. // static void inputOne(IO &io, StringRef key, T &elem);
  265. // static void output(IO &io, T &elem);
  266. };
  267. /// This class should be specialized by any type that can be represented as
  268. /// a scalar, map, or sequence, decided dynamically. For example:
  269. ///
  270. /// typedef std::unique_ptr<MyBase> MyPoly;
  271. ///
  272. /// template<>
  273. /// struct PolymorphicTraits<MyPoly> {
  274. /// static NodeKind getKind(const MyPoly &poly) {
  275. /// return poly->getKind();
  276. /// }
  277. /// static MyScalar& getAsScalar(MyPoly &poly) {
  278. /// if (!poly || !isa<MyScalar>(poly))
  279. /// poly.reset(new MyScalar());
  280. /// return *cast<MyScalar>(poly.get());
  281. /// }
  282. /// // ...
  283. /// };
  284. template <typename T> struct PolymorphicTraits {
  285. // Must provide:
  286. // static NodeKind getKind(const T &poly);
  287. // static scalar_type &getAsScalar(T &poly);
  288. // static map_type &getAsMap(T &poly);
  289. // static sequence_type &getAsSequence(T &poly);
  290. };
  291. // Only used for better diagnostics of missing traits
  292. template <typename T>
  293. struct MissingTrait;
  294. // Test if ScalarEnumerationTraits<T> is defined on type T.
  295. template <class T>
  296. struct has_ScalarEnumerationTraits
  297. {
  298. using Signature_enumeration = void (*)(class IO&, T&);
  299. template <typename U>
  300. static char test(SameType<Signature_enumeration, &U::enumeration>*);
  301. template <typename U>
  302. static double test(...);
  303. static bool const value =
  304. (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1);
  305. };
  306. // Test if ScalarBitSetTraits<T> is defined on type T.
  307. template <class T>
  308. struct has_ScalarBitSetTraits
  309. {
  310. using Signature_bitset = void (*)(class IO&, T&);
  311. template <typename U>
  312. static char test(SameType<Signature_bitset, &U::bitset>*);
  313. template <typename U>
  314. static double test(...);
  315. static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1);
  316. };
  317. // Test if ScalarTraits<T> is defined on type T.
  318. template <class T>
  319. struct has_ScalarTraits
  320. {
  321. using Signature_input = StringRef (*)(StringRef, void*, T&);
  322. using Signature_output = void (*)(const T&, void*, raw_ostream&);
  323. using Signature_mustQuote = QuotingType (*)(StringRef);
  324. template <typename U>
  325. static char test(SameType<Signature_input, &U::input> *,
  326. SameType<Signature_output, &U::output> *,
  327. SameType<Signature_mustQuote, &U::mustQuote> *);
  328. template <typename U>
  329. static double test(...);
  330. static bool const value =
  331. (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
  332. };
  333. // Test if BlockScalarTraits<T> is defined on type T.
  334. template <class T>
  335. struct has_BlockScalarTraits
  336. {
  337. using Signature_input = StringRef (*)(StringRef, void *, T &);
  338. using Signature_output = void (*)(const T &, void *, raw_ostream &);
  339. template <typename U>
  340. static char test(SameType<Signature_input, &U::input> *,
  341. SameType<Signature_output, &U::output> *);
  342. template <typename U>
  343. static double test(...);
  344. static bool const value =
  345. (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
  346. };
  347. // Test if TaggedScalarTraits<T> is defined on type T.
  348. template <class T> struct has_TaggedScalarTraits {
  349. using Signature_input = StringRef (*)(StringRef, StringRef, void *, T &);
  350. using Signature_output = void (*)(const T &, void *, raw_ostream &,
  351. raw_ostream &);
  352. using Signature_mustQuote = QuotingType (*)(const T &, StringRef);
  353. template <typename U>
  354. static char test(SameType<Signature_input, &U::input> *,
  355. SameType<Signature_output, &U::output> *,
  356. SameType<Signature_mustQuote, &U::mustQuote> *);
  357. template <typename U> static double test(...);
  358. static bool const value =
  359. (sizeof(test<TaggedScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
  360. };
  361. // Test if MappingContextTraits<T> is defined on type T.
  362. template <class T, class Context> struct has_MappingTraits {
  363. using Signature_mapping = void (*)(class IO &, T &, Context &);
  364. template <typename U>
  365. static char test(SameType<Signature_mapping, &U::mapping>*);
  366. template <typename U>
  367. static double test(...);
  368. static bool const value =
  369. (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
  370. };
  371. // Test if MappingTraits<T> is defined on type T.
  372. template <class T> struct has_MappingTraits<T, EmptyContext> {
  373. using Signature_mapping = void (*)(class IO &, T &);
  374. template <typename U>
  375. static char test(SameType<Signature_mapping, &U::mapping> *);
  376. template <typename U> static double test(...);
  377. static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
  378. };
  379. // Test if MappingContextTraits<T>::validate() is defined on type T.
  380. template <class T, class Context> struct has_MappingValidateTraits {
  381. using Signature_validate = std::string (*)(class IO &, T &, Context &);
  382. template <typename U>
  383. static char test(SameType<Signature_validate, &U::validate>*);
  384. template <typename U>
  385. static double test(...);
  386. static bool const value =
  387. (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
  388. };
  389. // Test if MappingTraits<T>::validate() is defined on type T.
  390. template <class T> struct has_MappingValidateTraits<T, EmptyContext> {
  391. using Signature_validate = std::string (*)(class IO &, T &);
  392. template <typename U>
  393. static char test(SameType<Signature_validate, &U::validate> *);
  394. template <typename U> static double test(...);
  395. static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
  396. };
  397. // Test if MappingContextTraits<T>::enumInput() is defined on type T.
  398. template <class T, class Context> struct has_MappingEnumInputTraits {
  399. using Signature_validate = void (*)(class IO &, T &);
  400. template <typename U>
  401. static char test(SameType<Signature_validate, &U::enumInput> *);
  402. template <typename U> static double test(...);
  403. static bool const value =
  404. (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
  405. };
  406. // Test if MappingTraits<T>::enumInput() is defined on type T.
  407. template <class T> struct has_MappingEnumInputTraits<T, EmptyContext> {
  408. using Signature_validate = void (*)(class IO &, T &);
  409. template <typename U>
  410. static char test(SameType<Signature_validate, &U::enumInput> *);
  411. template <typename U> static double test(...);
  412. static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
  413. };
  414. // Test if SequenceTraits<T> is defined on type T.
  415. template <class T>
  416. struct has_SequenceMethodTraits
  417. {
  418. using Signature_size = size_t (*)(class IO&, T&);
  419. template <typename U>
  420. static char test(SameType<Signature_size, &U::size>*);
  421. template <typename U>
  422. static double test(...);
  423. static bool const value = (sizeof(test<SequenceTraits<T>>(nullptr)) == 1);
  424. };
  425. // Test if CustomMappingTraits<T> is defined on type T.
  426. template <class T>
  427. struct has_CustomMappingTraits
  428. {
  429. using Signature_input = void (*)(IO &io, StringRef key, T &v);
  430. template <typename U>
  431. static char test(SameType<Signature_input, &U::inputOne>*);
  432. template <typename U>
  433. static double test(...);
  434. static bool const value =
  435. (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1);
  436. };
  437. // has_FlowTraits<int> will cause an error with some compilers because
  438. // it subclasses int. Using this wrapper only instantiates the
  439. // real has_FlowTraits only if the template type is a class.
  440. template <typename T, bool Enabled = std::is_class<T>::value>
  441. class has_FlowTraits
  442. {
  443. public:
  444. static const bool value = false;
  445. };
  446. // Some older gcc compilers don't support straight forward tests
  447. // for members, so test for ambiguity cause by the base and derived
  448. // classes both defining the member.
  449. template <class T>
  450. struct has_FlowTraits<T, true>
  451. {
  452. struct Fallback { bool flow; };
  453. struct Derived : T, Fallback { };
  454. template<typename C>
  455. static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
  456. template<typename C>
  457. static char (&f(...))[2];
  458. static bool const value = sizeof(f<Derived>(nullptr)) == 2;
  459. };
  460. // Test if SequenceTraits<T> is defined on type T
  461. template<typename T>
  462. struct has_SequenceTraits : public std::integral_constant<bool,
  463. has_SequenceMethodTraits<T>::value > { };
  464. // Test if DocumentListTraits<T> is defined on type T
  465. template <class T>
  466. struct has_DocumentListTraits
  467. {
  468. using Signature_size = size_t (*)(class IO &, T &);
  469. template <typename U>
  470. static char test(SameType<Signature_size, &U::size>*);
  471. template <typename U>
  472. static double test(...);
  473. static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1);
  474. };
  475. template <class T> struct has_PolymorphicTraits {
  476. using Signature_getKind = NodeKind (*)(const T &);
  477. template <typename U>
  478. static char test(SameType<Signature_getKind, &U::getKind> *);
  479. template <typename U> static double test(...);
  480. static bool const value = (sizeof(test<PolymorphicTraits<T>>(nullptr)) == 1);
  481. };
  482. inline bool isNumeric(StringRef S) {
  483. const auto skipDigits = [](StringRef Input) {
  484. return Input.ltrim("0123456789");
  485. };
  486. // Make S.front() and S.drop_front().front() (if S.front() is [+-]) calls
  487. // safe.
  488. if (S.empty() || S.equals("+") || S.equals("-"))
  489. return false;
  490. if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
  491. return true;
  492. // Infinity and decimal numbers can be prefixed with sign.
  493. StringRef Tail = (S.front() == '-' || S.front() == '+') ? S.drop_front() : S;
  494. // Check for infinity first, because checking for hex and oct numbers is more
  495. // expensive.
  496. if (Tail.equals(".inf") || Tail.equals(".Inf") || Tail.equals(".INF"))
  497. return true;
  498. // Section 10.3.2 Tag Resolution
  499. // YAML 1.2 Specification prohibits Base 8 and Base 16 numbers prefixed with
  500. // [-+], so S should be used instead of Tail.
  501. if (S.startswith("0o"))
  502. return S.size() > 2 &&
  503. S.drop_front(2).find_first_not_of("01234567") == StringRef::npos;
  504. if (S.startswith("0x"))
  505. return S.size() > 2 && S.drop_front(2).find_first_not_of(
  506. "0123456789abcdefABCDEF") == StringRef::npos;
  507. // Parse float: [-+]? (\. [0-9]+ | [0-9]+ (\. [0-9]* )?) ([eE] [-+]? [0-9]+)?
  508. S = Tail;
  509. // Handle cases when the number starts with '.' and hence needs at least one
  510. // digit after dot (as opposed by number which has digits before the dot), but
  511. // doesn't have one.
  512. if (S.startswith(".") &&
  513. (S.equals(".") ||
  514. (S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr)))
  515. return false;
  516. if (S.startswith("E") || S.startswith("e"))
  517. return false;
  518. enum ParseState {
  519. Default,
  520. FoundDot,
  521. FoundExponent,
  522. };
  523. ParseState State = Default;
  524. S = skipDigits(S);
  525. // Accept decimal integer.
  526. if (S.empty())
  527. return true;
  528. if (S.front() == '.') {
  529. State = FoundDot;
  530. S = S.drop_front();
  531. } else if (S.front() == 'e' || S.front() == 'E') {
  532. State = FoundExponent;
  533. S = S.drop_front();
  534. } else {
  535. return false;
  536. }
  537. if (State == FoundDot) {
  538. S = skipDigits(S);
  539. if (S.empty())
  540. return true;
  541. if (S.front() == 'e' || S.front() == 'E') {
  542. State = FoundExponent;
  543. S = S.drop_front();
  544. } else {
  545. return false;
  546. }
  547. }
  548. assert(State == FoundExponent && "Should have found exponent at this point.");
  549. if (S.empty())
  550. return false;
  551. if (S.front() == '+' || S.front() == '-') {
  552. S = S.drop_front();
  553. if (S.empty())
  554. return false;
  555. }
  556. return skipDigits(S).empty();
  557. }
  558. inline bool isNull(StringRef S) {
  559. return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
  560. S.equals("~");
  561. }
  562. inline bool isBool(StringRef S) {
  563. // FIXME: using parseBool is causing multiple tests to fail.
  564. return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
  565. S.equals("false") || S.equals("False") || S.equals("FALSE");
  566. }
  567. // 5.1. Character Set
  568. // The allowed character range explicitly excludes the C0 control block #x0-#x1F
  569. // (except for TAB #x9, LF #xA, and CR #xD which are allowed), DEL #x7F, the C1
  570. // control block #x80-#x9F (except for NEL #x85 which is allowed), the surrogate
  571. // block #xD800-#xDFFF, #xFFFE, and #xFFFF.
  572. inline QuotingType needsQuotes(StringRef S) {
  573. if (S.empty())
  574. return QuotingType::Single;
  575. QuotingType MaxQuotingNeeded = QuotingType::None;
  576. if (isSpace(static_cast<unsigned char>(S.front())) ||
  577. isSpace(static_cast<unsigned char>(S.back())))
  578. MaxQuotingNeeded = QuotingType::Single;
  579. if (isNull(S))
  580. MaxQuotingNeeded = QuotingType::Single;
  581. if (isBool(S))
  582. MaxQuotingNeeded = QuotingType::Single;
  583. if (isNumeric(S))
  584. MaxQuotingNeeded = QuotingType::Single;
  585. // 7.3.3 Plain Style
  586. // Plain scalars must not begin with most indicators, as this would cause
  587. // ambiguity with other YAML constructs.
  588. if (std::strchr(R"(-?:\,[]{}#&*!|>'"%@`)", S[0]) != nullptr)
  589. MaxQuotingNeeded = QuotingType::Single;
  590. for (unsigned char C : S) {
  591. // Alphanum is safe.
  592. if (isAlnum(C))
  593. continue;
  594. switch (C) {
  595. // Safe scalar characters.
  596. case '_':
  597. case '-':
  598. case '^':
  599. case '.':
  600. case ',':
  601. case ' ':
  602. // TAB (0x9) is allowed in unquoted strings.
  603. case 0x9:
  604. continue;
  605. // LF(0xA) and CR(0xD) may delimit values and so require at least single
  606. // quotes. LLVM YAML parser cannot handle single quoted multiline so use
  607. // double quoting to produce valid YAML.
  608. case 0xA:
  609. case 0xD:
  610. return QuotingType::Double;
  611. // DEL (0x7F) are excluded from the allowed character range.
  612. case 0x7F:
  613. return QuotingType::Double;
  614. // Forward slash is allowed to be unquoted, but we quote it anyway. We have
  615. // many tests that use FileCheck against YAML output, and this output often
  616. // contains paths. If we quote backslashes but not forward slashes then
  617. // paths will come out either quoted or unquoted depending on which platform
  618. // the test is run on, making FileCheck comparisons difficult.
  619. case '/':
  620. default: {
  621. // C0 control block (0x0 - 0x1F) is excluded from the allowed character
  622. // range.
  623. if (C <= 0x1F)
  624. return QuotingType::Double;
  625. // Always double quote UTF-8.
  626. if ((C & 0x80) != 0)
  627. return QuotingType::Double;
  628. // The character is not safe, at least simple quoting needed.
  629. MaxQuotingNeeded = QuotingType::Single;
  630. }
  631. }
  632. }
  633. return MaxQuotingNeeded;
  634. }
  635. template <typename T, typename Context>
  636. struct missingTraits
  637. : public std::integral_constant<bool,
  638. !has_ScalarEnumerationTraits<T>::value &&
  639. !has_ScalarBitSetTraits<T>::value &&
  640. !has_ScalarTraits<T>::value &&
  641. !has_BlockScalarTraits<T>::value &&
  642. !has_TaggedScalarTraits<T>::value &&
  643. !has_MappingTraits<T, Context>::value &&
  644. !has_SequenceTraits<T>::value &&
  645. !has_CustomMappingTraits<T>::value &&
  646. !has_DocumentListTraits<T>::value &&
  647. !has_PolymorphicTraits<T>::value> {};
  648. template <typename T, typename Context>
  649. struct validatedMappingTraits
  650. : public std::integral_constant<
  651. bool, has_MappingTraits<T, Context>::value &&
  652. has_MappingValidateTraits<T, Context>::value> {};
  653. template <typename T, typename Context>
  654. struct unvalidatedMappingTraits
  655. : public std::integral_constant<
  656. bool, has_MappingTraits<T, Context>::value &&
  657. !has_MappingValidateTraits<T, Context>::value> {};
  658. // Base class for Input and Output.
  659. class IO {
  660. public:
  661. IO(void *Ctxt = nullptr);
  662. virtual ~IO();
  663. virtual bool outputting() const = 0;
  664. virtual unsigned beginSequence() = 0;
  665. virtual bool preflightElement(unsigned, void *&) = 0;
  666. virtual void postflightElement(void*) = 0;
  667. virtual void endSequence() = 0;
  668. virtual bool canElideEmptySequence() = 0;
  669. virtual unsigned beginFlowSequence() = 0;
  670. virtual bool preflightFlowElement(unsigned, void *&) = 0;
  671. virtual void postflightFlowElement(void*) = 0;
  672. virtual void endFlowSequence() = 0;
  673. virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
  674. virtual void beginMapping() = 0;
  675. virtual void endMapping() = 0;
  676. virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
  677. virtual void postflightKey(void*) = 0;
  678. virtual std::vector<StringRef> keys() = 0;
  679. virtual void beginFlowMapping() = 0;
  680. virtual void endFlowMapping() = 0;
  681. virtual void beginEnumScalar() = 0;
  682. virtual bool matchEnumScalar(const char*, bool) = 0;
  683. virtual bool matchEnumFallback() = 0;
  684. virtual void endEnumScalar() = 0;
  685. virtual bool beginBitSetScalar(bool &) = 0;
  686. virtual bool bitSetMatch(const char*, bool) = 0;
  687. virtual void endBitSetScalar() = 0;
  688. virtual void scalarString(StringRef &, QuotingType) = 0;
  689. virtual void blockScalarString(StringRef &) = 0;
  690. virtual void scalarTag(std::string &) = 0;
  691. virtual NodeKind getNodeKind() = 0;
  692. virtual void setError(const Twine &) = 0;
  693. virtual void setAllowUnknownKeys(bool Allow);
  694. template <typename T>
  695. void enumCase(T &Val, const char* Str, const T ConstVal) {
  696. if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
  697. Val = ConstVal;
  698. }
  699. }
  700. // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
  701. template <typename T>
  702. void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
  703. if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
  704. Val = ConstVal;
  705. }
  706. }
  707. template <typename FBT, typename T>
  708. void enumFallback(T &Val) {
  709. if (matchEnumFallback()) {
  710. EmptyContext Context;
  711. // FIXME: Force integral conversion to allow strong typedefs to convert.
  712. FBT Res = static_cast<typename FBT::BaseType>(Val);
  713. yamlize(*this, Res, true, Context);
  714. Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
  715. }
  716. }
  717. template <typename T>
  718. void bitSetCase(T &Val, const char* Str, const T ConstVal) {
  719. if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
  720. Val = static_cast<T>(Val | ConstVal);
  721. }
  722. }
  723. // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
  724. template <typename T>
  725. void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
  726. if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
  727. Val = static_cast<T>(Val | ConstVal);
  728. }
  729. }
  730. template <typename T>
  731. void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
  732. if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
  733. Val = Val | ConstVal;
  734. }
  735. template <typename T>
  736. void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
  737. uint32_t Mask) {
  738. if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
  739. Val = Val | ConstVal;
  740. }
  741. void *getContext() const;
  742. void setContext(void *);
  743. template <typename T> void mapRequired(const char *Key, T &Val) {
  744. EmptyContext Ctx;
  745. this->processKey(Key, Val, true, Ctx);
  746. }
  747. template <typename T, typename Context>
  748. void mapRequired(const char *Key, T &Val, Context &Ctx) {
  749. this->processKey(Key, Val, true, Ctx);
  750. }
  751. template <typename T> void mapOptional(const char *Key, T &Val) {
  752. EmptyContext Ctx;
  753. mapOptionalWithContext(Key, Val, Ctx);
  754. }
  755. template <typename T, typename DefaultT>
  756. void mapOptional(const char *Key, T &Val, const DefaultT &Default) {
  757. EmptyContext Ctx;
  758. mapOptionalWithContext(Key, Val, Default, Ctx);
  759. }
  760. template <typename T, typename Context>
  761. std::enable_if_t<has_SequenceTraits<T>::value, void>
  762. mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
  763. // omit key/value instead of outputting empty sequence
  764. if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
  765. return;
  766. this->processKey(Key, Val, false, Ctx);
  767. }
  768. template <typename T, typename Context>
  769. void mapOptionalWithContext(const char *Key, std::optional<T> &Val,
  770. Context &Ctx) {
  771. this->processKeyWithDefault(Key, Val, std::optional<T>(),
  772. /*Required=*/false, Ctx);
  773. }
  774. template <typename T, typename Context>
  775. std::enable_if_t<!has_SequenceTraits<T>::value, void>
  776. mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
  777. this->processKey(Key, Val, false, Ctx);
  778. }
  779. template <typename T, typename Context, typename DefaultT>
  780. void mapOptionalWithContext(const char *Key, T &Val, const DefaultT &Default,
  781. Context &Ctx) {
  782. static_assert(std::is_convertible<DefaultT, T>::value,
  783. "Default type must be implicitly convertible to value type!");
  784. this->processKeyWithDefault(Key, Val, static_cast<const T &>(Default),
  785. false, Ctx);
  786. }
  787. private:
  788. template <typename T, typename Context>
  789. void processKeyWithDefault(const char *Key, std::optional<T> &Val,
  790. const std::optional<T> &DefaultValue,
  791. bool Required, Context &Ctx);
  792. template <typename T, typename Context>
  793. void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
  794. bool Required, Context &Ctx) {
  795. void *SaveInfo;
  796. bool UseDefault;
  797. const bool sameAsDefault = outputting() && Val == DefaultValue;
  798. if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
  799. SaveInfo) ) {
  800. yamlize(*this, Val, Required, Ctx);
  801. this->postflightKey(SaveInfo);
  802. }
  803. else {
  804. if ( UseDefault )
  805. Val = DefaultValue;
  806. }
  807. }
  808. template <typename T, typename Context>
  809. void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
  810. void *SaveInfo;
  811. bool UseDefault;
  812. if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
  813. yamlize(*this, Val, Required, Ctx);
  814. this->postflightKey(SaveInfo);
  815. }
  816. }
  817. private:
  818. void *Ctxt;
  819. };
  820. namespace detail {
  821. template <typename T, typename Context>
  822. void doMapping(IO &io, T &Val, Context &Ctx) {
  823. MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
  824. }
  825. template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
  826. MappingTraits<T>::mapping(io, Val);
  827. }
  828. } // end namespace detail
  829. template <typename T>
  830. std::enable_if_t<has_ScalarEnumerationTraits<T>::value, void>
  831. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  832. io.beginEnumScalar();
  833. ScalarEnumerationTraits<T>::enumeration(io, Val);
  834. io.endEnumScalar();
  835. }
  836. template <typename T>
  837. std::enable_if_t<has_ScalarBitSetTraits<T>::value, void>
  838. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  839. bool DoClear;
  840. if ( io.beginBitSetScalar(DoClear) ) {
  841. if ( DoClear )
  842. Val = T();
  843. ScalarBitSetTraits<T>::bitset(io, Val);
  844. io.endBitSetScalar();
  845. }
  846. }
  847. template <typename T>
  848. std::enable_if_t<has_ScalarTraits<T>::value, void> yamlize(IO &io, T &Val, bool,
  849. EmptyContext &Ctx) {
  850. if ( io.outputting() ) {
  851. SmallString<128> Storage;
  852. raw_svector_ostream Buffer(Storage);
  853. ScalarTraits<T>::output(Val, io.getContext(), Buffer);
  854. StringRef Str = Buffer.str();
  855. io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
  856. }
  857. else {
  858. StringRef Str;
  859. io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
  860. StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
  861. if ( !Result.empty() ) {
  862. io.setError(Twine(Result));
  863. }
  864. }
  865. }
  866. template <typename T>
  867. std::enable_if_t<has_BlockScalarTraits<T>::value, void>
  868. yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
  869. if (YamlIO.outputting()) {
  870. std::string Storage;
  871. raw_string_ostream Buffer(Storage);
  872. BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
  873. StringRef Str = Buffer.str();
  874. YamlIO.blockScalarString(Str);
  875. } else {
  876. StringRef Str;
  877. YamlIO.blockScalarString(Str);
  878. StringRef Result =
  879. BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
  880. if (!Result.empty())
  881. YamlIO.setError(Twine(Result));
  882. }
  883. }
  884. template <typename T>
  885. std::enable_if_t<has_TaggedScalarTraits<T>::value, void>
  886. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  887. if (io.outputting()) {
  888. std::string ScalarStorage, TagStorage;
  889. raw_string_ostream ScalarBuffer(ScalarStorage), TagBuffer(TagStorage);
  890. TaggedScalarTraits<T>::output(Val, io.getContext(), ScalarBuffer,
  891. TagBuffer);
  892. io.scalarTag(TagBuffer.str());
  893. StringRef ScalarStr = ScalarBuffer.str();
  894. io.scalarString(ScalarStr,
  895. TaggedScalarTraits<T>::mustQuote(Val, ScalarStr));
  896. } else {
  897. std::string Tag;
  898. io.scalarTag(Tag);
  899. StringRef Str;
  900. io.scalarString(Str, QuotingType::None);
  901. StringRef Result =
  902. TaggedScalarTraits<T>::input(Str, Tag, io.getContext(), Val);
  903. if (!Result.empty()) {
  904. io.setError(Twine(Result));
  905. }
  906. }
  907. }
  908. template <typename T, typename Context>
  909. std::enable_if_t<validatedMappingTraits<T, Context>::value, void>
  910. yamlize(IO &io, T &Val, bool, Context &Ctx) {
  911. if (has_FlowTraits<MappingTraits<T>>::value)
  912. io.beginFlowMapping();
  913. else
  914. io.beginMapping();
  915. if (io.outputting()) {
  916. std::string Err = MappingTraits<T>::validate(io, Val);
  917. if (!Err.empty()) {
  918. errs() << Err << "\n";
  919. assert(Err.empty() && "invalid struct trying to be written as yaml");
  920. }
  921. }
  922. detail::doMapping(io, Val, Ctx);
  923. if (!io.outputting()) {
  924. std::string Err = MappingTraits<T>::validate(io, Val);
  925. if (!Err.empty())
  926. io.setError(Err);
  927. }
  928. if (has_FlowTraits<MappingTraits<T>>::value)
  929. io.endFlowMapping();
  930. else
  931. io.endMapping();
  932. }
  933. template <typename T, typename Context>
  934. std::enable_if_t<!has_MappingEnumInputTraits<T, Context>::value, bool>
  935. yamlizeMappingEnumInput(IO &io, T &Val) {
  936. return false;
  937. }
  938. template <typename T, typename Context>
  939. std::enable_if_t<has_MappingEnumInputTraits<T, Context>::value, bool>
  940. yamlizeMappingEnumInput(IO &io, T &Val) {
  941. if (io.outputting())
  942. return false;
  943. io.beginEnumScalar();
  944. MappingTraits<T>::enumInput(io, Val);
  945. bool Matched = !io.matchEnumFallback();
  946. io.endEnumScalar();
  947. return Matched;
  948. }
  949. template <typename T, typename Context>
  950. std::enable_if_t<unvalidatedMappingTraits<T, Context>::value, void>
  951. yamlize(IO &io, T &Val, bool, Context &Ctx) {
  952. if (yamlizeMappingEnumInput<T, Context>(io, Val))
  953. return;
  954. if (has_FlowTraits<MappingTraits<T>>::value) {
  955. io.beginFlowMapping();
  956. detail::doMapping(io, Val, Ctx);
  957. io.endFlowMapping();
  958. } else {
  959. io.beginMapping();
  960. detail::doMapping(io, Val, Ctx);
  961. io.endMapping();
  962. }
  963. }
  964. template <typename T>
  965. std::enable_if_t<has_CustomMappingTraits<T>::value, void>
  966. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  967. if ( io.outputting() ) {
  968. io.beginMapping();
  969. CustomMappingTraits<T>::output(io, Val);
  970. io.endMapping();
  971. } else {
  972. io.beginMapping();
  973. for (StringRef key : io.keys())
  974. CustomMappingTraits<T>::inputOne(io, key, Val);
  975. io.endMapping();
  976. }
  977. }
  978. template <typename T>
  979. std::enable_if_t<has_PolymorphicTraits<T>::value, void>
  980. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  981. switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
  982. : io.getNodeKind()) {
  983. case NodeKind::Scalar:
  984. return yamlize(io, PolymorphicTraits<T>::getAsScalar(Val), true, Ctx);
  985. case NodeKind::Map:
  986. return yamlize(io, PolymorphicTraits<T>::getAsMap(Val), true, Ctx);
  987. case NodeKind::Sequence:
  988. return yamlize(io, PolymorphicTraits<T>::getAsSequence(Val), true, Ctx);
  989. }
  990. }
  991. template <typename T>
  992. std::enable_if_t<missingTraits<T, EmptyContext>::value, void>
  993. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  994. char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
  995. }
  996. template <typename T, typename Context>
  997. std::enable_if_t<has_SequenceTraits<T>::value, void>
  998. yamlize(IO &io, T &Seq, bool, Context &Ctx) {
  999. if ( has_FlowTraits< SequenceTraits<T>>::value ) {
  1000. unsigned incnt = io.beginFlowSequence();
  1001. unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
  1002. for(unsigned i=0; i < count; ++i) {
  1003. void *SaveInfo;
  1004. if ( io.preflightFlowElement(i, SaveInfo) ) {
  1005. yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
  1006. io.postflightFlowElement(SaveInfo);
  1007. }
  1008. }
  1009. io.endFlowSequence();
  1010. }
  1011. else {
  1012. unsigned incnt = io.beginSequence();
  1013. unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
  1014. for(unsigned i=0; i < count; ++i) {
  1015. void *SaveInfo;
  1016. if ( io.preflightElement(i, SaveInfo) ) {
  1017. yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
  1018. io.postflightElement(SaveInfo);
  1019. }
  1020. }
  1021. io.endSequence();
  1022. }
  1023. }
  1024. template<>
  1025. struct ScalarTraits<bool> {
  1026. static void output(const bool &, void* , raw_ostream &);
  1027. static StringRef input(StringRef, void *, bool &);
  1028. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1029. };
  1030. template<>
  1031. struct ScalarTraits<StringRef> {
  1032. static void output(const StringRef &, void *, raw_ostream &);
  1033. static StringRef input(StringRef, void *, StringRef &);
  1034. static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
  1035. };
  1036. template<>
  1037. struct ScalarTraits<std::string> {
  1038. static void output(const std::string &, void *, raw_ostream &);
  1039. static StringRef input(StringRef, void *, std::string &);
  1040. static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
  1041. };
  1042. template<>
  1043. struct ScalarTraits<uint8_t> {
  1044. static void output(const uint8_t &, void *, raw_ostream &);
  1045. static StringRef input(StringRef, void *, uint8_t &);
  1046. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1047. };
  1048. template<>
  1049. struct ScalarTraits<uint16_t> {
  1050. static void output(const uint16_t &, void *, raw_ostream &);
  1051. static StringRef input(StringRef, void *, uint16_t &);
  1052. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1053. };
  1054. template<>
  1055. struct ScalarTraits<uint32_t> {
  1056. static void output(const uint32_t &, void *, raw_ostream &);
  1057. static StringRef input(StringRef, void *, uint32_t &);
  1058. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1059. };
  1060. template<>
  1061. struct ScalarTraits<uint64_t> {
  1062. static void output(const uint64_t &, void *, raw_ostream &);
  1063. static StringRef input(StringRef, void *, uint64_t &);
  1064. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1065. };
  1066. template<>
  1067. struct ScalarTraits<int8_t> {
  1068. static void output(const int8_t &, void *, raw_ostream &);
  1069. static StringRef input(StringRef, void *, int8_t &);
  1070. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1071. };
  1072. template<>
  1073. struct ScalarTraits<int16_t> {
  1074. static void output(const int16_t &, void *, raw_ostream &);
  1075. static StringRef input(StringRef, void *, int16_t &);
  1076. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1077. };
  1078. template<>
  1079. struct ScalarTraits<int32_t> {
  1080. static void output(const int32_t &, void *, raw_ostream &);
  1081. static StringRef input(StringRef, void *, int32_t &);
  1082. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1083. };
  1084. template<>
  1085. struct ScalarTraits<int64_t> {
  1086. static void output(const int64_t &, void *, raw_ostream &);
  1087. static StringRef input(StringRef, void *, int64_t &);
  1088. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1089. };
  1090. template<>
  1091. struct ScalarTraits<float> {
  1092. static void output(const float &, void *, raw_ostream &);
  1093. static StringRef input(StringRef, void *, float &);
  1094. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1095. };
  1096. template<>
  1097. struct ScalarTraits<double> {
  1098. static void output(const double &, void *, raw_ostream &);
  1099. static StringRef input(StringRef, void *, double &);
  1100. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1101. };
  1102. // For endian types, we use existing scalar Traits class for the underlying
  1103. // type. This way endian aware types are supported whenever the traits are
  1104. // defined for the underlying type.
  1105. template <typename value_type, support::endianness endian, size_t alignment>
  1106. struct ScalarTraits<support::detail::packed_endian_specific_integral<
  1107. value_type, endian, alignment>,
  1108. std::enable_if_t<has_ScalarTraits<value_type>::value>> {
  1109. using endian_type =
  1110. support::detail::packed_endian_specific_integral<value_type, endian,
  1111. alignment>;
  1112. static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
  1113. ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
  1114. }
  1115. static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
  1116. value_type V;
  1117. auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
  1118. E = static_cast<endian_type>(V);
  1119. return R;
  1120. }
  1121. static QuotingType mustQuote(StringRef Str) {
  1122. return ScalarTraits<value_type>::mustQuote(Str);
  1123. }
  1124. };
  1125. template <typename value_type, support::endianness endian, size_t alignment>
  1126. struct ScalarEnumerationTraits<
  1127. support::detail::packed_endian_specific_integral<value_type, endian,
  1128. alignment>,
  1129. std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> {
  1130. using endian_type =
  1131. support::detail::packed_endian_specific_integral<value_type, endian,
  1132. alignment>;
  1133. static void enumeration(IO &io, endian_type &E) {
  1134. value_type V = E;
  1135. ScalarEnumerationTraits<value_type>::enumeration(io, V);
  1136. E = V;
  1137. }
  1138. };
  1139. template <typename value_type, support::endianness endian, size_t alignment>
  1140. struct ScalarBitSetTraits<
  1141. support::detail::packed_endian_specific_integral<value_type, endian,
  1142. alignment>,
  1143. std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> {
  1144. using endian_type =
  1145. support::detail::packed_endian_specific_integral<value_type, endian,
  1146. alignment>;
  1147. static void bitset(IO &io, endian_type &E) {
  1148. value_type V = E;
  1149. ScalarBitSetTraits<value_type>::bitset(io, V);
  1150. E = V;
  1151. }
  1152. };
  1153. // Utility for use within MappingTraits<>::mapping() method
  1154. // to [de]normalize an object for use with YAML conversion.
  1155. template <typename TNorm, typename TFinal>
  1156. struct MappingNormalization {
  1157. MappingNormalization(IO &i_o, TFinal &Obj)
  1158. : io(i_o), BufPtr(nullptr), Result(Obj) {
  1159. if ( io.outputting() ) {
  1160. BufPtr = new (&Buffer) TNorm(io, Obj);
  1161. }
  1162. else {
  1163. BufPtr = new (&Buffer) TNorm(io);
  1164. }
  1165. }
  1166. ~MappingNormalization() {
  1167. if ( ! io.outputting() ) {
  1168. Result = BufPtr->denormalize(io);
  1169. }
  1170. BufPtr->~TNorm();
  1171. }
  1172. TNorm* operator->() { return BufPtr; }
  1173. private:
  1174. using Storage = AlignedCharArrayUnion<TNorm>;
  1175. Storage Buffer;
  1176. IO &io;
  1177. TNorm *BufPtr;
  1178. TFinal &Result;
  1179. };
  1180. // Utility for use within MappingTraits<>::mapping() method
  1181. // to [de]normalize an object for use with YAML conversion.
  1182. template <typename TNorm, typename TFinal>
  1183. struct MappingNormalizationHeap {
  1184. MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
  1185. : io(i_o), Result(Obj) {
  1186. if ( io.outputting() ) {
  1187. BufPtr = new (&Buffer) TNorm(io, Obj);
  1188. }
  1189. else if (allocator) {
  1190. BufPtr = allocator->Allocate<TNorm>();
  1191. new (BufPtr) TNorm(io);
  1192. } else {
  1193. BufPtr = new TNorm(io);
  1194. }
  1195. }
  1196. ~MappingNormalizationHeap() {
  1197. if ( io.outputting() ) {
  1198. BufPtr->~TNorm();
  1199. }
  1200. else {
  1201. Result = BufPtr->denormalize(io);
  1202. }
  1203. }
  1204. TNorm* operator->() { return BufPtr; }
  1205. private:
  1206. using Storage = AlignedCharArrayUnion<TNorm>;
  1207. Storage Buffer;
  1208. IO &io;
  1209. TNorm *BufPtr = nullptr;
  1210. TFinal &Result;
  1211. };
  1212. ///
  1213. /// The Input class is used to parse a yaml document into in-memory structs
  1214. /// and vectors.
  1215. ///
  1216. /// It works by using YAMLParser to do a syntax parse of the entire yaml
  1217. /// document, then the Input class builds a graph of HNodes which wraps
  1218. /// each yaml Node. The extra layer is buffering. The low level yaml
  1219. /// parser only lets you look at each node once. The buffering layer lets
  1220. /// you search and interate multiple times. This is necessary because
  1221. /// the mapRequired() method calls may not be in the same order
  1222. /// as the keys in the document.
  1223. ///
  1224. class Input : public IO {
  1225. public:
  1226. // Construct a yaml Input object from a StringRef and optional
  1227. // user-data. The DiagHandler can be specified to provide
  1228. // alternative error reporting.
  1229. Input(StringRef InputContent,
  1230. void *Ctxt = nullptr,
  1231. SourceMgr::DiagHandlerTy DiagHandler = nullptr,
  1232. void *DiagHandlerCtxt = nullptr);
  1233. Input(MemoryBufferRef Input,
  1234. void *Ctxt = nullptr,
  1235. SourceMgr::DiagHandlerTy DiagHandler = nullptr,
  1236. void *DiagHandlerCtxt = nullptr);
  1237. ~Input() override;
  1238. // Check if there was an syntax or semantic error during parsing.
  1239. std::error_code error();
  1240. private:
  1241. bool outputting() const override;
  1242. bool mapTag(StringRef, bool) override;
  1243. void beginMapping() override;
  1244. void endMapping() override;
  1245. bool preflightKey(const char *, bool, bool, bool &, void *&) override;
  1246. void postflightKey(void *) override;
  1247. std::vector<StringRef> keys() override;
  1248. void beginFlowMapping() override;
  1249. void endFlowMapping() override;
  1250. unsigned beginSequence() override;
  1251. void endSequence() override;
  1252. bool preflightElement(unsigned index, void *&) override;
  1253. void postflightElement(void *) override;
  1254. unsigned beginFlowSequence() override;
  1255. bool preflightFlowElement(unsigned , void *&) override;
  1256. void postflightFlowElement(void *) override;
  1257. void endFlowSequence() override;
  1258. void beginEnumScalar() override;
  1259. bool matchEnumScalar(const char*, bool) override;
  1260. bool matchEnumFallback() override;
  1261. void endEnumScalar() override;
  1262. bool beginBitSetScalar(bool &) override;
  1263. bool bitSetMatch(const char *, bool ) override;
  1264. void endBitSetScalar() override;
  1265. void scalarString(StringRef &, QuotingType) override;
  1266. void blockScalarString(StringRef &) override;
  1267. void scalarTag(std::string &) override;
  1268. NodeKind getNodeKind() override;
  1269. void setError(const Twine &message) override;
  1270. bool canElideEmptySequence() override;
  1271. class HNode {
  1272. virtual void anchor();
  1273. public:
  1274. HNode(Node *n) : _node(n) { }
  1275. virtual ~HNode() = default;
  1276. static bool classof(const HNode *) { return true; }
  1277. Node *_node;
  1278. };
  1279. class EmptyHNode : public HNode {
  1280. void anchor() override;
  1281. public:
  1282. EmptyHNode(Node *n) : HNode(n) { }
  1283. static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
  1284. static bool classof(const EmptyHNode *) { return true; }
  1285. };
  1286. class ScalarHNode : public HNode {
  1287. void anchor() override;
  1288. public:
  1289. ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
  1290. StringRef value() const { return _value; }
  1291. static bool classof(const HNode *n) {
  1292. return ScalarNode::classof(n->_node) ||
  1293. BlockScalarNode::classof(n->_node);
  1294. }
  1295. static bool classof(const ScalarHNode *) { return true; }
  1296. protected:
  1297. StringRef _value;
  1298. };
  1299. class MapHNode : public HNode {
  1300. void anchor() override;
  1301. public:
  1302. MapHNode(Node *n) : HNode(n) { }
  1303. static bool classof(const HNode *n) {
  1304. return MappingNode::classof(n->_node);
  1305. }
  1306. static bool classof(const MapHNode *) { return true; }
  1307. using NameToNodeAndLoc =
  1308. StringMap<std::pair<std::unique_ptr<HNode>, SMRange>>;
  1309. NameToNodeAndLoc Mapping;
  1310. SmallVector<std::string, 6> ValidKeys;
  1311. };
  1312. class SequenceHNode : public HNode {
  1313. void anchor() override;
  1314. public:
  1315. SequenceHNode(Node *n) : HNode(n) { }
  1316. static bool classof(const HNode *n) {
  1317. return SequenceNode::classof(n->_node);
  1318. }
  1319. static bool classof(const SequenceHNode *) { return true; }
  1320. std::vector<std::unique_ptr<HNode>> Entries;
  1321. };
  1322. std::unique_ptr<Input::HNode> createHNodes(Node *node);
  1323. void setError(HNode *hnode, const Twine &message);
  1324. void setError(Node *node, const Twine &message);
  1325. void setError(const SMRange &Range, const Twine &message);
  1326. void reportWarning(HNode *hnode, const Twine &message);
  1327. void reportWarning(Node *hnode, const Twine &message);
  1328. void reportWarning(const SMRange &Range, const Twine &message);
  1329. public:
  1330. // These are only used by operator>>. They could be private
  1331. // if those templated things could be made friends.
  1332. bool setCurrentDocument();
  1333. bool nextDocument();
  1334. /// Returns the current node that's being parsed by the YAML Parser.
  1335. const Node *getCurrentNode() const;
  1336. void setAllowUnknownKeys(bool Allow) override;
  1337. private:
  1338. SourceMgr SrcMgr; // must be before Strm
  1339. std::unique_ptr<llvm::yaml::Stream> Strm;
  1340. std::unique_ptr<HNode> TopNode;
  1341. std::error_code EC;
  1342. BumpPtrAllocator StringAllocator;
  1343. document_iterator DocIterator;
  1344. llvm::BitVector BitValuesUsed;
  1345. HNode *CurrentNode = nullptr;
  1346. bool ScalarMatchFound = false;
  1347. bool AllowUnknownKeys = false;
  1348. };
  1349. ///
  1350. /// The Output class is used to generate a yaml document from in-memory structs
  1351. /// and vectors.
  1352. ///
  1353. class Output : public IO {
  1354. public:
  1355. Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
  1356. ~Output() override;
  1357. /// Set whether or not to output optional values which are equal
  1358. /// to the default value. By default, when outputting if you attempt
  1359. /// to write a value that is equal to the default, the value gets ignored.
  1360. /// Sometimes, it is useful to be able to see these in the resulting YAML
  1361. /// anyway.
  1362. void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
  1363. bool outputting() const override;
  1364. bool mapTag(StringRef, bool) override;
  1365. void beginMapping() override;
  1366. void endMapping() override;
  1367. bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
  1368. void postflightKey(void *) override;
  1369. std::vector<StringRef> keys() override;
  1370. void beginFlowMapping() override;
  1371. void endFlowMapping() override;
  1372. unsigned beginSequence() override;
  1373. void endSequence() override;
  1374. bool preflightElement(unsigned, void *&) override;
  1375. void postflightElement(void *) override;
  1376. unsigned beginFlowSequence() override;
  1377. bool preflightFlowElement(unsigned, void *&) override;
  1378. void postflightFlowElement(void *) override;
  1379. void endFlowSequence() override;
  1380. void beginEnumScalar() override;
  1381. bool matchEnumScalar(const char*, bool) override;
  1382. bool matchEnumFallback() override;
  1383. void endEnumScalar() override;
  1384. bool beginBitSetScalar(bool &) override;
  1385. bool bitSetMatch(const char *, bool ) override;
  1386. void endBitSetScalar() override;
  1387. void scalarString(StringRef &, QuotingType) override;
  1388. void blockScalarString(StringRef &) override;
  1389. void scalarTag(std::string &) override;
  1390. NodeKind getNodeKind() override;
  1391. void setError(const Twine &message) override;
  1392. bool canElideEmptySequence() override;
  1393. // These are only used by operator<<. They could be private
  1394. // if that templated operator could be made a friend.
  1395. void beginDocuments();
  1396. bool preflightDocument(unsigned);
  1397. void postflightDocument();
  1398. void endDocuments();
  1399. private:
  1400. void output(StringRef s);
  1401. void outputUpToEndOfLine(StringRef s);
  1402. void newLineCheck(bool EmptySequence = false);
  1403. void outputNewLine();
  1404. void paddedKey(StringRef key);
  1405. void flowKey(StringRef Key);
  1406. enum InState {
  1407. inSeqFirstElement,
  1408. inSeqOtherElement,
  1409. inFlowSeqFirstElement,
  1410. inFlowSeqOtherElement,
  1411. inMapFirstKey,
  1412. inMapOtherKey,
  1413. inFlowMapFirstKey,
  1414. inFlowMapOtherKey
  1415. };
  1416. static bool inSeqAnyElement(InState State);
  1417. static bool inFlowSeqAnyElement(InState State);
  1418. static bool inMapAnyKey(InState State);
  1419. static bool inFlowMapAnyKey(InState State);
  1420. raw_ostream &Out;
  1421. int WrapColumn;
  1422. SmallVector<InState, 8> StateStack;
  1423. int Column = 0;
  1424. int ColumnAtFlowStart = 0;
  1425. int ColumnAtMapFlowStart = 0;
  1426. bool NeedBitValueComma = false;
  1427. bool NeedFlowSequenceComma = false;
  1428. bool EnumerationMatchFound = false;
  1429. bool WriteDefaultValues = false;
  1430. StringRef Padding;
  1431. StringRef PaddingBeforeContainer;
  1432. };
  1433. template <typename T, typename Context>
  1434. void IO::processKeyWithDefault(const char *Key, std::optional<T> &Val,
  1435. const std::optional<T> &DefaultValue,
  1436. bool Required, Context &Ctx) {
  1437. assert(!DefaultValue && "std::optional<T> shouldn't have a value!");
  1438. void *SaveInfo;
  1439. bool UseDefault = true;
  1440. const bool sameAsDefault = outputting() && !Val;
  1441. if (!outputting() && !Val)
  1442. Val = T();
  1443. if (Val &&
  1444. this->preflightKey(Key, Required, sameAsDefault, UseDefault, SaveInfo)) {
  1445. // When reading an std::optional<X> key from a YAML description, we allow
  1446. // the special "<none>" value, which can be used to specify that no value
  1447. // was requested, i.e. the DefaultValue will be assigned. The DefaultValue
  1448. // is usually None.
  1449. bool IsNone = false;
  1450. if (!outputting())
  1451. if (const auto *Node =
  1452. dyn_cast<ScalarNode>(((Input *)this)->getCurrentNode()))
  1453. // We use rtrim to ignore possible white spaces that might exist when a
  1454. // comment is present on the same line.
  1455. IsNone = Node->getRawValue().rtrim(' ') == "<none>";
  1456. if (IsNone)
  1457. Val = DefaultValue;
  1458. else
  1459. yamlize(*this, *Val, Required, Ctx);
  1460. this->postflightKey(SaveInfo);
  1461. } else {
  1462. if (UseDefault)
  1463. Val = DefaultValue;
  1464. }
  1465. }
  1466. /// YAML I/O does conversion based on types. But often native data types
  1467. /// are just a typedef of built in intergral types (e.g. int). But the C++
  1468. /// type matching system sees through the typedef and all the typedefed types
  1469. /// look like a built in type. This will cause the generic YAML I/O conversion
  1470. /// to be used. To provide better control over the YAML conversion, you can
  1471. /// use this macro instead of typedef. It will create a class with one field
  1472. /// and automatic conversion operators to and from the base type.
  1473. /// Based on BOOST_STRONG_TYPEDEF
  1474. #define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \
  1475. struct _type { \
  1476. _type() = default; \
  1477. _type(const _base v) : value(v) {} \
  1478. _type(const _type &v) = default; \
  1479. _type &operator=(const _type &rhs) = default; \
  1480. _type &operator=(const _base &rhs) { value = rhs; return *this; } \
  1481. operator const _base & () const { return value; } \
  1482. bool operator==(const _type &rhs) const { return value == rhs.value; } \
  1483. bool operator==(const _base &rhs) const { return value == rhs; } \
  1484. bool operator<(const _type &rhs) const { return value < rhs.value; } \
  1485. _base value; \
  1486. using BaseType = _base; \
  1487. };
  1488. ///
  1489. /// Use these types instead of uintXX_t in any mapping to have
  1490. /// its yaml output formatted as hexadecimal.
  1491. ///
  1492. LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
  1493. LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
  1494. LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
  1495. LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
  1496. template<>
  1497. struct ScalarTraits<Hex8> {
  1498. static void output(const Hex8 &, void *, raw_ostream &);
  1499. static StringRef input(StringRef, void *, Hex8 &);
  1500. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1501. };
  1502. template<>
  1503. struct ScalarTraits<Hex16> {
  1504. static void output(const Hex16 &, void *, raw_ostream &);
  1505. static StringRef input(StringRef, void *, Hex16 &);
  1506. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1507. };
  1508. template<>
  1509. struct ScalarTraits<Hex32> {
  1510. static void output(const Hex32 &, void *, raw_ostream &);
  1511. static StringRef input(StringRef, void *, Hex32 &);
  1512. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1513. };
  1514. template<>
  1515. struct ScalarTraits<Hex64> {
  1516. static void output(const Hex64 &, void *, raw_ostream &);
  1517. static StringRef input(StringRef, void *, Hex64 &);
  1518. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1519. };
  1520. template <> struct ScalarTraits<VersionTuple> {
  1521. static void output(const VersionTuple &Value, void *, llvm::raw_ostream &Out);
  1522. static StringRef input(StringRef, void *, VersionTuple &);
  1523. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1524. };
  1525. // Define non-member operator>> so that Input can stream in a document list.
  1526. template <typename T>
  1527. inline std::enable_if_t<has_DocumentListTraits<T>::value, Input &>
  1528. operator>>(Input &yin, T &docList) {
  1529. int i = 0;
  1530. EmptyContext Ctx;
  1531. while ( yin.setCurrentDocument() ) {
  1532. yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
  1533. if ( yin.error() )
  1534. return yin;
  1535. yin.nextDocument();
  1536. ++i;
  1537. }
  1538. return yin;
  1539. }
  1540. // Define non-member operator>> so that Input can stream in a map as a document.
  1541. template <typename T>
  1542. inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Input &>
  1543. operator>>(Input &yin, T &docMap) {
  1544. EmptyContext Ctx;
  1545. yin.setCurrentDocument();
  1546. yamlize(yin, docMap, true, Ctx);
  1547. return yin;
  1548. }
  1549. // Define non-member operator>> so that Input can stream in a sequence as
  1550. // a document.
  1551. template <typename T>
  1552. inline std::enable_if_t<has_SequenceTraits<T>::value, Input &>
  1553. operator>>(Input &yin, T &docSeq) {
  1554. EmptyContext Ctx;
  1555. if (yin.setCurrentDocument())
  1556. yamlize(yin, docSeq, true, Ctx);
  1557. return yin;
  1558. }
  1559. // Define non-member operator>> so that Input can stream in a block scalar.
  1560. template <typename T>
  1561. inline std::enable_if_t<has_BlockScalarTraits<T>::value, Input &>
  1562. operator>>(Input &In, T &Val) {
  1563. EmptyContext Ctx;
  1564. if (In.setCurrentDocument())
  1565. yamlize(In, Val, true, Ctx);
  1566. return In;
  1567. }
  1568. // Define non-member operator>> so that Input can stream in a string map.
  1569. template <typename T>
  1570. inline std::enable_if_t<has_CustomMappingTraits<T>::value, Input &>
  1571. operator>>(Input &In, T &Val) {
  1572. EmptyContext Ctx;
  1573. if (In.setCurrentDocument())
  1574. yamlize(In, Val, true, Ctx);
  1575. return In;
  1576. }
  1577. // Define non-member operator>> so that Input can stream in a polymorphic type.
  1578. template <typename T>
  1579. inline std::enable_if_t<has_PolymorphicTraits<T>::value, Input &>
  1580. operator>>(Input &In, T &Val) {
  1581. EmptyContext Ctx;
  1582. if (In.setCurrentDocument())
  1583. yamlize(In, Val, true, Ctx);
  1584. return In;
  1585. }
  1586. // Provide better error message about types missing a trait specialization
  1587. template <typename T>
  1588. inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Input &>
  1589. operator>>(Input &yin, T &docSeq) {
  1590. char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
  1591. return yin;
  1592. }
  1593. // Define non-member operator<< so that Output can stream out document list.
  1594. template <typename T>
  1595. inline std::enable_if_t<has_DocumentListTraits<T>::value, Output &>
  1596. operator<<(Output &yout, T &docList) {
  1597. EmptyContext Ctx;
  1598. yout.beginDocuments();
  1599. const size_t count = DocumentListTraits<T>::size(yout, docList);
  1600. for(size_t i=0; i < count; ++i) {
  1601. if ( yout.preflightDocument(i) ) {
  1602. yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
  1603. Ctx);
  1604. yout.postflightDocument();
  1605. }
  1606. }
  1607. yout.endDocuments();
  1608. return yout;
  1609. }
  1610. // Define non-member operator<< so that Output can stream out a map.
  1611. template <typename T>
  1612. inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Output &>
  1613. operator<<(Output &yout, T &map) {
  1614. EmptyContext Ctx;
  1615. yout.beginDocuments();
  1616. if ( yout.preflightDocument(0) ) {
  1617. yamlize(yout, map, true, Ctx);
  1618. yout.postflightDocument();
  1619. }
  1620. yout.endDocuments();
  1621. return yout;
  1622. }
  1623. // Define non-member operator<< so that Output can stream out a sequence.
  1624. template <typename T>
  1625. inline std::enable_if_t<has_SequenceTraits<T>::value, Output &>
  1626. operator<<(Output &yout, T &seq) {
  1627. EmptyContext Ctx;
  1628. yout.beginDocuments();
  1629. if ( yout.preflightDocument(0) ) {
  1630. yamlize(yout, seq, true, Ctx);
  1631. yout.postflightDocument();
  1632. }
  1633. yout.endDocuments();
  1634. return yout;
  1635. }
  1636. // Define non-member operator<< so that Output can stream out a block scalar.
  1637. template <typename T>
  1638. inline std::enable_if_t<has_BlockScalarTraits<T>::value, Output &>
  1639. operator<<(Output &Out, T &Val) {
  1640. EmptyContext Ctx;
  1641. Out.beginDocuments();
  1642. if (Out.preflightDocument(0)) {
  1643. yamlize(Out, Val, true, Ctx);
  1644. Out.postflightDocument();
  1645. }
  1646. Out.endDocuments();
  1647. return Out;
  1648. }
  1649. // Define non-member operator<< so that Output can stream out a string map.
  1650. template <typename T>
  1651. inline std::enable_if_t<has_CustomMappingTraits<T>::value, Output &>
  1652. operator<<(Output &Out, T &Val) {
  1653. EmptyContext Ctx;
  1654. Out.beginDocuments();
  1655. if (Out.preflightDocument(0)) {
  1656. yamlize(Out, Val, true, Ctx);
  1657. Out.postflightDocument();
  1658. }
  1659. Out.endDocuments();
  1660. return Out;
  1661. }
  1662. // Define non-member operator<< so that Output can stream out a polymorphic
  1663. // type.
  1664. template <typename T>
  1665. inline std::enable_if_t<has_PolymorphicTraits<T>::value, Output &>
  1666. operator<<(Output &Out, T &Val) {
  1667. EmptyContext Ctx;
  1668. Out.beginDocuments();
  1669. if (Out.preflightDocument(0)) {
  1670. // FIXME: The parser does not support explicit documents terminated with a
  1671. // plain scalar; the end-marker is included as part of the scalar token.
  1672. assert(PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && "plain scalar documents are not supported");
  1673. yamlize(Out, Val, true, Ctx);
  1674. Out.postflightDocument();
  1675. }
  1676. Out.endDocuments();
  1677. return Out;
  1678. }
  1679. // Provide better error message about types missing a trait specialization
  1680. template <typename T>
  1681. inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Output &>
  1682. operator<<(Output &yout, T &seq) {
  1683. char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
  1684. return yout;
  1685. }
  1686. template <bool B> struct IsFlowSequenceBase {};
  1687. template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
  1688. template <typename T, typename U = void>
  1689. struct IsResizable : std::false_type {};
  1690. template <typename T>
  1691. struct IsResizable<T, std::void_t<decltype(std::declval<T>().resize(0))>>
  1692. : public std::true_type {};
  1693. template <typename T, bool B> struct IsResizableBase {
  1694. using type = typename T::value_type;
  1695. static type &element(IO &io, T &seq, size_t index) {
  1696. if (index >= seq.size())
  1697. seq.resize(index + 1);
  1698. return seq[index];
  1699. }
  1700. };
  1701. template <typename T> struct IsResizableBase<T, false> {
  1702. using type = typename T::value_type;
  1703. static type &element(IO &io, T &seq, size_t index) {
  1704. if (index >= seq.size()) {
  1705. io.setError(Twine("value sequence extends beyond static size (") +
  1706. Twine(seq.size()) + ")");
  1707. return seq[0];
  1708. }
  1709. return seq[index];
  1710. }
  1711. };
  1712. template <typename T, bool Flow>
  1713. struct SequenceTraitsImpl
  1714. : IsFlowSequenceBase<Flow>, IsResizableBase<T, IsResizable<T>::value> {
  1715. static size_t size(IO &io, T &seq) { return seq.size(); }
  1716. };
  1717. // Simple helper to check an expression can be used as a bool-valued template
  1718. // argument.
  1719. template <bool> struct CheckIsBool { static const bool value = true; };
  1720. // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
  1721. // SequenceTraits that do the obvious thing.
  1722. template <typename T>
  1723. struct SequenceTraits<
  1724. std::vector<T>,
  1725. std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
  1726. : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
  1727. template <typename T, unsigned N>
  1728. struct SequenceTraits<
  1729. SmallVector<T, N>,
  1730. std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
  1731. : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
  1732. template <typename T>
  1733. struct SequenceTraits<
  1734. SmallVectorImpl<T>,
  1735. std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
  1736. : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
  1737. template <typename T>
  1738. struct SequenceTraits<
  1739. MutableArrayRef<T>,
  1740. std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
  1741. : SequenceTraitsImpl<MutableArrayRef<T>, SequenceElementTraits<T>::flow> {};
  1742. // Sequences of fundamental types use flow formatting.
  1743. template <typename T>
  1744. struct SequenceElementTraits<T,
  1745. std::enable_if_t<std::is_fundamental<T>::value>> {
  1746. static const bool flow = true;
  1747. };
  1748. // Sequences of strings use block formatting.
  1749. template<> struct SequenceElementTraits<std::string> {
  1750. static const bool flow = false;
  1751. };
  1752. template<> struct SequenceElementTraits<StringRef> {
  1753. static const bool flow = false;
  1754. };
  1755. template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
  1756. static const bool flow = false;
  1757. };
  1758. /// Implementation of CustomMappingTraits for std::map<std::string, T>.
  1759. template <typename T> struct StdMapStringCustomMappingTraitsImpl {
  1760. using map_type = std::map<std::string, T>;
  1761. static void inputOne(IO &io, StringRef key, map_type &v) {
  1762. io.mapRequired(key.str().c_str(), v[std::string(key)]);
  1763. }
  1764. static void output(IO &io, map_type &v) {
  1765. for (auto &p : v)
  1766. io.mapRequired(p.first.c_str(), p.second);
  1767. }
  1768. };
  1769. } // end namespace yaml
  1770. } // end namespace llvm
  1771. #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW) \
  1772. namespace llvm { \
  1773. namespace yaml { \
  1774. static_assert( \
  1775. !std::is_fundamental_v<TYPE> && !std::is_same_v<TYPE, std::string> && \
  1776. !std::is_same_v<TYPE, llvm::StringRef>, \
  1777. "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"); \
  1778. template <> struct SequenceElementTraits<TYPE> { \
  1779. static const bool flow = FLOW; \
  1780. }; \
  1781. } \
  1782. }
  1783. /// Utility for declaring that a std::vector of a particular type
  1784. /// should be considered a YAML sequence.
  1785. #define LLVM_YAML_IS_SEQUENCE_VECTOR(type) \
  1786. LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
  1787. /// Utility for declaring that a std::vector of a particular type
  1788. /// should be considered a YAML flow sequence.
  1789. #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type) \
  1790. LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
  1791. #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
  1792. namespace llvm { \
  1793. namespace yaml { \
  1794. template <> struct MappingTraits<Type> { \
  1795. static void mapping(IO &IO, Type &Obj); \
  1796. }; \
  1797. } \
  1798. }
  1799. #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type) \
  1800. namespace llvm { \
  1801. namespace yaml { \
  1802. template <> struct ScalarEnumerationTraits<Type> { \
  1803. static void enumeration(IO &io, Type &Value); \
  1804. }; \
  1805. } \
  1806. }
  1807. #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type) \
  1808. namespace llvm { \
  1809. namespace yaml { \
  1810. template <> struct ScalarBitSetTraits<Type> { \
  1811. static void bitset(IO &IO, Type &Options); \
  1812. }; \
  1813. } \
  1814. }
  1815. #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote) \
  1816. namespace llvm { \
  1817. namespace yaml { \
  1818. template <> struct ScalarTraits<Type> { \
  1819. static void output(const Type &Value, void *ctx, raw_ostream &Out); \
  1820. static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \
  1821. static QuotingType mustQuote(StringRef) { return MustQuote; } \
  1822. }; \
  1823. } \
  1824. }
  1825. /// Utility for declaring that a std::vector of a particular type
  1826. /// should be considered a YAML document list.
  1827. #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \
  1828. namespace llvm { \
  1829. namespace yaml { \
  1830. template <unsigned N> \
  1831. struct DocumentListTraits<SmallVector<_type, N>> \
  1832. : public SequenceTraitsImpl<SmallVector<_type, N>, false> {}; \
  1833. template <> \
  1834. struct DocumentListTraits<std::vector<_type>> \
  1835. : public SequenceTraitsImpl<std::vector<_type>, false> {}; \
  1836. } \
  1837. }
  1838. /// Utility for declaring that std::map<std::string, _type> should be considered
  1839. /// a YAML map.
  1840. #define LLVM_YAML_IS_STRING_MAP(_type) \
  1841. namespace llvm { \
  1842. namespace yaml { \
  1843. template <> \
  1844. struct CustomMappingTraits<std::map<std::string, _type>> \
  1845. : public StdMapStringCustomMappingTraitsImpl<_type> {}; \
  1846. } \
  1847. }
  1848. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
  1849. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32)
  1850. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex16)
  1851. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8)
  1852. #endif // LLVM_SUPPORT_YAMLTRAITS_H
  1853. #ifdef __GNUC__
  1854. #pragma GCC diagnostic pop
  1855. #endif