@@ -208,11 +208,185 @@ struct TypeInfoCommonBase : TypeInfo
208208 }
209209};
210210
211+ /* * Categorically describes a fundamental type.
212+
213+ @see https://en.cppreference.com/w/cpp/language/types
214+ */
215+ enum class FundamentalTypeKind
216+ {
217+ // void
218+ Void,
219+ // std::nullptr_t
220+ Nullptr,
221+ // bool
222+ Bool,
223+ // char
224+ Char,
225+ // signed char
226+ SignedChar,
227+ // unsigned char
228+ UnsignedChar,
229+ // char8_t
230+ Char8,
231+ // char16_t
232+ Char16,
233+ // char32_t
234+ Char32,
235+ // wchar_t
236+ WChar,
237+ // short / short int / signed short / signed short int
238+ Short,
239+ // unsigned short / unsigned short int
240+ UnsignedShort,
241+ // int / signed / signed int
242+ Int,
243+ // unsigned / unsigned int
244+ UnsignedInt,
245+ // long / long int / signed long / signed long int
246+ Long,
247+ // unsigned long / unsigned long int
248+ UnsignedLong,
249+ // long long / long long int / signed long long / signed long long int
250+ LongLong,
251+ // unsigned long long / unsigned long long int
252+ UnsignedLongLong,
253+ // float
254+ Float,
255+ // double
256+ Double,
257+ // long double
258+ LongDouble
259+ };
260+
261+ /* * Convert a FundamentalTypeKind to a string.
262+
263+ This function converts a FundamentalTypeKind to
264+ the shortest canonical string representing the type.
265+
266+ @return The string representation of the kind
267+ */
268+ MRDOCS_DECL
269+ std::string_view
270+ toString (FundamentalTypeKind kind) noexcept ;
271+
272+ /* * Convert a string to a FundamentalTypeKind.
273+
274+ This function converts a string to a FundamentalTypeKind.
275+
276+ All variations of the type specifiers are supported.
277+
278+ However, the "long long" specifier cannot be split
279+ into two separate specifiers.
280+
281+ @return true if the string was successfully converted
282+ */
283+ MRDOCS_DECL
284+ bool
285+ fromString (std::string_view str, FundamentalTypeKind& kind) noexcept ;
286+
287+ /* * Apply the "long" specifier to the type
288+
289+ If applying "long" the specifier is a valid operation
290+ the function changes the type and returns true.
291+
292+ For instance, applying "long" to
293+ `FundamentalTypeKind::Int` ("int") results in
294+ `FundamentalTypeKind::Long` ("long int").
295+
296+ @param[in/out] kind The type to modify
297+ @return Whether the operation was successful
298+ */
299+ MRDOCS_DECL
300+ bool
301+ makeLong (FundamentalTypeKind& kind) noexcept ;
302+
303+ /* * Apply the "short" specifier to the type
304+
305+ If applying "short" the specifier is a valid operation
306+ the function changes the type and returns true.
307+
308+ For instance, applying "short" to
309+ `FundamentalTypeKind::Int` ("int") results in
310+ `FundamentalTypeKind::Short` ("short int").
311+
312+ @param[in/out] kind The type to modify
313+ @return Whether the operation was successful
314+ */
315+ MRDOCS_DECL
316+ bool
317+ makeShort (FundamentalTypeKind& kind) noexcept ;
318+
319+ /* * Apply the "signed" specifier to the type
320+
321+ If applying the "signed" specifier is a valid operation
322+ the function changes the type and returns true.
323+
324+ For instance, applying "signed" to
325+ `FundamentalTypeKind::Char` ("char") results in
326+ `FundamentalTypeKind::SignedChar` ("signed char").
327+
328+ It also returns true if applying the "signed" specifier
329+ is a valid operation but doesn't affect the
330+ type.
331+
332+ For instance, applying "signed" to
333+ `FundamentalTypeKind::Int` ("int") doesn't change the type
334+ but returns `true`, even though `FundamentalTypeKind::Int`
335+ could be declared as "int" or "signed" and multiple
336+ "signed" specifiers are not allowed.
337+
338+ @param[in/out] kind The type to modify
339+ @return Whether the operation was successful
340+ */
341+ MRDOCS_DECL
342+ bool
343+ makeSigned (FundamentalTypeKind& kind) noexcept ;
344+
345+ /* * Apply the "unsigned" specifier to the type
346+
347+ If applying the "unsigned" specifier is a valid operation
348+ the function changes the type and returns true.
349+
350+ For instance, applying "unsigned" to
351+ `FundamentalTypeKind::Char` ("char") results in
352+ `FundamentalTypeKind::UnsignedChar` ("unsigned char")
353+ and applying "unsigned" to
354+ `FundamentalTypeKind::Int` ("int") results in
355+ `FundamentalTypeKind::UnsignedInt` ("unsigned int").
356+
357+ @param[in/out] kind The type to modify
358+ @return Whether the operation was successful
359+ */
360+ MRDOCS_DECL
361+ bool
362+ makeUnsigned (FundamentalTypeKind& kind) noexcept ;
363+
364+ /* * Apply the "char" specifier to the type
365+
366+ If applying the "char" specifier to a type
367+ that might have been declared only with "signed/unsigned"
368+ or "short/long" specifiers, the function changes the type
369+ and returns true.
370+
371+ For instance, applying "char" to
372+ `FundamentalTypeKind::Int` ("int", which could be declared
373+ as "signed") results in
374+ `FundamentalTypeKind::SignedChar` ("signed char").
375+
376+ @param[in/out] kind The type to modify
377+ @return Whether the operation was successful
378+ */
379+ MRDOCS_DECL
380+ bool
381+ makeChar (FundamentalTypeKind& kind) noexcept ;
382+
211383struct NamedTypeInfo final
212384 : TypeInfoCommonBase<TypeKind::Named>
213385{
214386 Polymorphic<NameInfo> Name;
215387
388+ std::optional<FundamentalTypeKind> FundamentalType;
389+
216390 std::strong_ordering
217391 operator <=>(NamedTypeInfo const & other) const ;
218392};
0 commit comments