v0.2.2
Pre-releaseAdded
-
__int128andunsigned __int128inrucc-types, as integer kinds of their own rather than as a_BitInt(128)wearing a different name. The two are genuinely different types:__int128is sixteen bytes aligned to sixteen on every target here, a_BitInt(128)is aligned to its granule, which is eight bytes on x86-64, and__int128outrankslong longwhere a_BitIntis ranked by its width alone. So__int128 + unsigned long longis an__int128, which is what both compilers answer and what a program relying on the extension expects. It is available on every target, because all three architectures are 64-bit and GCC has the type on every 64-bit target it supports, and it is deliberately not an extended integer type in the sense the standard means, which is what keepsintmax_tsixty four bits wide the way GCC has it. -
The keyword table in
rucc-lex, which is the first half of phase 7 and what turns an identifier into a word the grammar knows. The spellings are interned before any source is read, so their symbols are one run at the bottom of the interner and recognising a keyword is a subtraction and a bounds check rather than a string comparison or a hash of the text. Which spellings the dialect actually has is resolved once, when the table is built, rather than at every identifier, sorestrictis a keyword from C99 and a variable name in C89 at no cost per token. Which word is a keyword in which dialect was measured rather than recalled, by compiling every candidate as a variable name against gcc 13.3 and clang in each of the ten dialects, with two ordinary identifiers along for the ride to catch a probe that had stopped measuring anything. Two of the answers are not what a reading of the standard suggests:restrictis not a keyword in-std=gnu89althoughinlineis, andasmis still not one in-std=c23, where__asm__has to be written instead. The GNU spellings are keywords in every dialect including-std=c89, which is why headers are written with them, and where two spellings mean the same thing they are one keyword, so a parser never has to know which was typed.__alignof__and_Alignofstay apart, because one asks for the alignment the target prefers and the other for the one the ABI requires. -
Integer constants in
rucc-lex, which is the piece of phase 7 that turns a preprocessing number into a value and a type. The type is the standard's table walk, a candidate list chosen by the base, the suffix and the dialect, walked in order until a type holds the value, and it is not the list a reading of the standard alone would give: C89 hasunsigned longin the list for a decimal constant with no suffix and nothing has it after C89, which is why18446744073709551615is eight bytes under-std=c89and sixteen under-std=c99, and gcc says so in as many words. Pastlong longa decimal constant reaches for__int128rather than for an unsigned type, so9223372036854775808is a signed constant in gcc and an unsigned one in clang, and following gcc is what keeps its negation negative. Only the decimal list is signed types alone, which is the split behind4294967295being alongwhile0xffffffffis anunsigned int. Every row was measured by writing the constant and asking_Genericwhat it is, against gcc 13.3 on x86-64 Linux and clang, rather than recalled, and the type comes from the target description, so the same constant is alongon Linux and along longon Windows without the host having a say. The value is accumulated in a hundred and twenty eight bits with every step checked, which is one deliberate difference from gcc: its accumulator is sixty four bits, so18446744073709551616compiles there to zero of typeintafter a warning, and here it is refused._BitIntconstants get the narrowest type that holds them, which for a signed one counts the sign bit and is never less than two, so1wbis a_BitInt(2)and255uwbis anunsigned _BitInt(8), measured against clang because gcc 13.3 has no such type. A constant that uses a binary prefix, a digit separator, awbsuffix or anllsuffix before the dialect that standardised it is still converted and comes back with a remark, so the caller holding the span decides what-pedanticmakes of it rather than the conversion deciding for it.
What's Changed
- Add the keyword table and the dialect gate by @tamnd in #55
- Add __int128 as an integer kind of its own by @tamnd in #56
- Add integer constants to phase 7 by @tamnd in #57
- Release 0.2.2 by @tamnd in #58
Full Changelog: v0.2.1...v0.2.2