Skip to main content

rucc_lex/
number.rs

1//! Numeric constants: the value, and the type the standard's table walk gives it.
2//!
3//! Design: `spec/06-lexer-and-parser.md` section 6.1.
4//!
5//! This is the second piece of phase 7. A preprocessing number is a loose thing, deliberately
6//! looser than a constant, so `1.2.3` and `0x1p+3` are both one pp-token and only here does
7//! anyone ask what they mean. What comes back is a value and a type, and both of them are
8//! places a compiler quietly goes wrong.
9//!
10//! There are two entry points, [`integer`] and [`floating`], and either of them hands the
11//! spelling to the other rather than reporting an error when it turns out to belong there. The
12//! split is not where a reader expects it: `1e` is a floating constant with no exponent digits
13//! and `1f` is an integer constant with a suffix that does not exist, and both compilers agree
14//! on that, because the exponent marker is part of a preprocessing number and the suffix letter
15//! is not part of anything.
16//!
17//! The value is accumulated in a `u128` with every step checked, so a constant too large to
18//! represent is a diagnostic rather than a number the program did not write. gcc 13.3 does not
19//! do that: its accumulator is sixty four bits, and `18446744073709551616` compiles to zero of
20//! type `int` after a warning nobody reads. That is not a behaviour worth reproducing, so ours
21//! is the only measured difference here that is deliberate: past a hundred and twenty eight
22//! bits the constant is refused. clang refuses it too, one bit earlier.
23//!
24//! The type is the standard's table walk, 6.4.4.1p5: a candidate list chosen by the base and
25//! the suffix, walked in order, and the first type that holds the value wins. The list is not
26//! the same in every dialect. C89 puts `unsigned long` in the list for a decimal constant with
27//! no suffix, which is what makes `18446744073709551615` an `unsigned long` under `-std=c89`
28//! and something wider under `-std=c99`, and gcc says so in as many words: "this decimal
29//! constant is unsigned only in ISO C90". Both compilers keep `long long` out of the C89 lists
30//! and accept it when the suffix asks for it.
31//!
32//! `__int128` is on the end of every list, which is what gcc does and clang does not.
33//! `9223372036854775808` is an `__int128` in gcc 13.3 and an `unsigned long long` in clang,
34//! and the difference is visible to a program: negate it and gcc gives a negative number.
35//! We follow gcc, because the alternative silently turns a signed constant unsigned.
36//!
37//! The rest was measured the same way, by writing the constant and asking `_Generic` what it
38//! is, on gcc 13.3 on x86-64 Linux and on clang:
39//!
40//! The suffix letters may be in either case but not both, so `1ll` and `1LL` are constants and
41//! `1lL` is not, and the same rule holds for `wb`. The unsigned suffix may come before or after
42//! the length suffix. `wb` does not combine with `l` at all.
43//!
44//! Binary constants are accepted in every dialect by both compilers, as an extension before
45//! C23. Digit separators are C23 only in both. `_BitInt` constants are C23 in the standard,
46//! clang accepts them in every dialect, and gcc 13.3 has no `_BitInt` at all.
47//!
48//! A `wb` constant has the narrowest type that holds it, which for a signed one includes the
49//! sign bit and is never less than two: `1wb` is `_BitInt(2)`, `42wb` is `_BitInt(7)`, `255uwb`
50//! is `unsigned _BitInt(8)` and `0uwb` is `unsigned _BitInt(1)`. Measured against clang, since
51//! gcc 13.3 cannot say.
52//!
53//! # Floating constants
54//!
55//! A floating constant has none of the table walk about it: the suffix names the type outright,
56//! and with no suffix it is a `double`. What it has instead is a list of suffixes that is much
57//! longer than the standard's three, and a conversion that has to be exactly right.
58//!
59//! The conversion is [`rucc_base::float`], correctly rounded and done in software, so that the
60//! bits do not depend on the machine the compiler runs on. The type decides the format and the
61//! target decides what some of the types are: `long double` is the x87 eighty bit format on
62//! x86-64 Linux and true quad precision on AArch64 Linux, and both of them say 128 bits wide,
63//! which is why [`TargetInfo::long_double_format`] exists.
64//!
65//! The suffixes were measured on gcc 13.3 on x86-64 Linux, with `_Generic` for the type and by
66//! printing the bytes for the format. `f` is `float` and `l` is `long double`, and then the
67//! extensions: `q` is `__float128`, `w` is the x87 `__float80`, `d` is a `double` written the
68//! long way, `f16` `f32` `f64` `f128` are the `_FloatN` types and `f32x` `f64x` the `_FloatNx`
69//! ones, and `i` or `j` in either position makes the constant imaginary. `_Float32x` turns out
70//! to be plain `double` and `_Float64x` the x87 format, which is not what the names suggest:
71//! `0.1f32x` is `0x3fb999999999999a` and `0.1f64x` is `0x3ffbcccccccccccccccd`.
72//!
73//! The case rules are their own small grammar. The `f` of a `_FloatN` suffix may be either case
74//! and the trailing `x` may not, so `F64x` is a constant and `f64X` is not. A decimal float
75//! suffix is two letters that have to agree, so `df` and `DF` are constants and `Df` is not.
76//! Every one of these is accepted in every dialect, C89 included, and every one of them is
77//! worth a remark when the dialect did not ask for it.
78//!
79//! Decimal floating constants are refused rather than converted, because there is no decimal
80//! float value anywhere in this compiler to put one in. That is a gap and the error says so.
81
82use rucc_base::float::{Float, Format, ParseError, Status};
83use rucc_session::Std;
84use rucc_target::{Arch, TargetInfo};
85use rucc_types::{IntKind, int_width};
86
87use crate::remarks::Remarks;
88
89/// A converted integer constant.
90#[derive(Debug, Clone, Copy, PartialEq, Eq)]
91pub struct IntConstant {
92    /// The value, which is never negative: a minus sign is an operator and not part of the
93    /// constant, which is why `-2147483648` is a `long` on a 32-bit `int` and the reason
94    /// `INT_MIN` is spelled the way it is in `limits.h`.
95    pub value: u128,
96    /// The type the table walk arrived at.
97    pub ty: IntConstantType,
98    /// What is worth saying about the constant, for the caller that holds the span.
99    pub remarks: Remarks,
100}
101
102/// The type of an integer constant.
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104pub enum IntConstantType {
105    /// One of the integer kinds, chosen by the table walk.
106    Standard(IntKind),
107    /// A `_BitInt` of exactly the width it takes to hold the value.
108    BitInt {
109        /// Whether the `u` suffix was there.
110        signed: bool,
111        /// The width in bits, including the sign bit when there is one.
112        width: u32,
113    },
114}
115
116/// Why a preprocessing number is not an integer constant.
117///
118/// [`IntError::Floating`] is not a diagnostic. It means the spelling belongs to the floating
119/// path, and it is an error here so that the caller cannot forget to ask.
120#[derive(Debug, Clone, Copy, PartialEq, Eq)]
121pub enum IntError {
122    /// This is a floating constant. Nothing is wrong with it.
123    Floating,
124    /// The characters after the digits are not a suffix.
125    InvalidSuffix,
126    /// An `8` or a `9` in a constant that started with `0`.
127    InvalidOctalDigit,
128    /// `0x` or `0b` with no digits after it.
129    NoDigits,
130    /// Larger than any integer type, or than the hundred and twenty eight bits the value is
131    /// accumulated in.
132    TooLarge,
133}
134
135impl IntError {
136    /// What to print, in GCC's words where GCC has any.
137    ///
138    /// The offending character is not in the message, because the caller has the spelling and
139    /// the span and can say `invalid suffix "ux" on integer constant` the way GCC does.
140    #[must_use]
141    pub const fn message(self) -> &'static str {
142        match self {
143            IntError::Floating => "not an integer constant",
144            IntError::InvalidSuffix => "invalid suffix on integer constant",
145            IntError::InvalidOctalDigit => "invalid digit in octal constant",
146            IntError::NoDigits => "no digits in integer constant",
147            IntError::TooLarge => "integer constant is too large to be represented in any type",
148        }
149    }
150}
151
152/// A converted floating constant.
153#[derive(Debug, Clone, Copy, PartialEq, Eq)]
154pub struct FloatConstant {
155    /// The value, correctly rounded into the format of its type.
156    pub value: Float,
157    /// The type the suffix named, which is `double` when there was no suffix.
158    pub ty: FloatConstantType,
159    /// Whether an `i` or a `j` made this the imaginary part of a complex constant. The value is
160    /// the real number that was written either way, so the caller builds the complex one.
161    pub imaginary: bool,
162    /// What is worth saying about the constant, for the caller that holds the span.
163    pub remarks: Remarks,
164}
165
166/// The type of a floating constant.
167///
168/// This is not [`rucc_types::FloatKind`], which has the three types C has. The suffixes reach
169/// further than that, and a constant knows exactly which type it was written as long before
170/// anything has to decide what that type is on this target.
171#[derive(Debug, Clone, Copy, PartialEq, Eq)]
172pub enum FloatConstantType {
173    /// `f` or `F`.
174    Float,
175    /// No suffix, or the `d` and `D` that GCC also accepts for it.
176    Double,
177    /// `l` or `L`.
178    LongDouble,
179    /// `f16` or `F16`, which is `_Float16`.
180    Float16,
181    /// `f32` or `F32`, which is `_Float32` and is the same format as `float`.
182    Float32,
183    /// `f64` or `F64`, which is `_Float64` and is the same format as `double`.
184    Float64,
185    /// `f128` or `F128`, and `q` or `Q`, which is `_Float128` and `__float128`. GCC keeps the
186    /// two spellings as distinct types and they are the same format, which is all this says.
187    Float128,
188    /// `f32x` or `F32x`, which is `_Float32x`. The name suggests something wider than
189    /// `_Float32` and on every target here it is exactly `double`.
190    Float32x,
191    /// `f64x` or `F64x`, which is `_Float64x`: the widest format the target has beyond
192    /// `_Float64`, so the x87 one on x86 and quad precision elsewhere.
193    Float64x,
194    /// `w` or `W`, which is GCC's `__float80`. It is the x87 format whatever `long double` is,
195    /// which is the reason it is not the same thing as [`FloatConstantType::LongDouble`], and
196    /// GCC has it on x86 only.
197    Float80,
198}
199
200impl FloatConstantType {
201    /// The format a constant of this type is converted in.
202    ///
203    /// The two that depend on the target are the two that have to: `long double` is the x87
204    /// format on x86-64 Linux and quad precision on AArch64 Linux, and `_Float64x` is whatever
205    /// the target has above `_Float64`, which is the same split.
206    #[must_use]
207    pub fn format(self, target: &TargetInfo) -> Format {
208        match self {
209            FloatConstantType::Float | FloatConstantType::Float32 => Format::Single,
210            FloatConstantType::Double
211            | FloatConstantType::Float64
212            | FloatConstantType::Float32x => Format::Double,
213            FloatConstantType::LongDouble => target.long_double_format,
214            FloatConstantType::Float16 => Format::Half,
215            FloatConstantType::Float128 => Format::Quad,
216            FloatConstantType::Float64x if target.triple.arch == Arch::X86_64 => {
217                Format::X87Extended
218            }
219            FloatConstantType::Float64x => Format::Quad,
220            FloatConstantType::Float80 => Format::X87Extended,
221        }
222    }
223}
224
225/// Why a preprocessing number is not a floating constant.
226///
227/// [`FloatError::Integer`] is not a diagnostic, in the same way [`IntError::Floating`] is not:
228/// it means the spelling belongs to the other path.
229#[derive(Debug, Clone, Copy, PartialEq, Eq)]
230pub enum FloatError {
231    /// This is an integer constant. Nothing is wrong with it.
232    Integer,
233    /// The characters after the number are not a suffix.
234    InvalidSuffix,
235    /// A hexadecimal floating constant with no `p` exponent. The exponent is required there and
236    /// not optional as it is in a decimal one, because `f` is a hexadecimal digit and there
237    /// would be no way to tell a suffix from the number.
238    MissingExponent,
239    /// An `e` or a `p` with no digits after it.
240    NoExponentDigits,
241    /// A constant with a point and no digits at all.
242    NoDigits,
243    /// More than one point, which is a preprocessing number and not a constant.
244    TooManyPoints,
245    /// A `df`, `dd` or `dl` suffix. The constant is well formed and this compiler has nowhere
246    /// to put a decimal floating value yet.
247    DecimalFloat,
248    /// A suffix naming a type this target does not have, which is `w` anywhere but x86 and
249    /// `f128x` everywhere.
250    UnsupportedType,
251}
252
253impl FloatError {
254    /// What to print, in GCC's words where GCC has any.
255    #[must_use]
256    pub const fn message(self) -> &'static str {
257        match self {
258            FloatError::Integer => "not a floating constant",
259            FloatError::InvalidSuffix => "invalid suffix on floating constant",
260            FloatError::MissingExponent => "hexadecimal floating constants require an exponent",
261            FloatError::NoExponentDigits => "exponent has no digits",
262            FloatError::NoDigits => "no digits in floating constant",
263            FloatError::TooManyPoints => "too many decimal points in number",
264            FloatError::DecimalFloat => "decimal floating constants are not supported yet",
265            FloatError::UnsupportedType => {
266                "the type of this floating constant is not supported on this target"
267            }
268        }
269    }
270}
271
272/// Converts the spelling of a preprocessing number into an integer constant.
273///
274/// # Errors
275///
276/// [`IntError`], one case of which is that the spelling is a floating constant rather than a
277/// malformed integer one.
278pub fn integer(text: &str, std: Std, target: &TargetInfo) -> Result<IntConstant, IntError> {
279    let bytes = text.as_bytes();
280    let (base, start) = base_of(bytes);
281    if is_floating(bytes, base) {
282        return Err(IntError::Floating);
283    }
284    let mut remarks = Remarks::NONE;
285    if base == 2 && std < Std::C23 {
286        remarks = remarks.with(Remarks::BINARY);
287    }
288
289    let mut value: u128 = 0;
290    let mut digits = 0;
291    let mut index = start;
292    while index < bytes.len() {
293        let byte = bytes[index];
294        if byte == b'\'' {
295            // A separator is only a separator between two digits. The scanner keeps one in the
296            // number only when an identifier character follows, so a trailing one arrives here
297            // as a suffix instead and is refused as one.
298            if digits == 0 || index + 1 >= bytes.len() || digit(bytes[index + 1], base).is_none() {
299                return Err(IntError::InvalidSuffix);
300            }
301            if std < Std::C23 {
302                remarks = remarks.with(Remarks::SEPARATORS);
303            }
304            index += 1;
305            continue;
306        }
307        let Some(digit) = digit(byte, base) else {
308            break;
309        };
310        value = value
311            .checked_mul(u128::from(base))
312            .and_then(|shifted| shifted.checked_add(u128::from(digit)))
313            .ok_or(IntError::TooLarge)?;
314        digits += 1;
315        index += 1;
316    }
317    if digits == 0 {
318        // `0x` with nothing after it, which GCC reports as an invalid suffix because it read
319        // the `0` as the constant. The distinction is not worth a worse message than this.
320        return Err(IntError::NoDigits);
321    }
322    if base == 8 && bytes[start..index].iter().any(|&byte| byte == b'8' || byte == b'9') {
323        return Err(IntError::InvalidOctalDigit);
324    }
325
326    let suffix = suffix_of(&bytes[index..])?;
327    if suffix.length == Some(Length::LongLong) && std == Std::C89 {
328        remarks = remarks.with(Remarks::LONG_LONG);
329    }
330    if suffix.length == Some(Length::BitInt) {
331        if std < Std::C23 {
332            remarks = remarks.with(Remarks::BIT_INT);
333        }
334        return Ok(IntConstant { value, ty: bit_int(value, suffix.unsigned), remarks });
335    }
336
337    let candidates = candidates(base, suffix, std);
338    let kind = candidates
339        .iter()
340        .copied()
341        .find(|&kind| fits(value, kind, target))
342        .ok_or(IntError::TooLarge)?;
343    if base == 10 && !suffix.unsigned && !signed_standard(kind) {
344        remarks = remarks.with(Remarks::UNSIGNED);
345    }
346    Ok(IntConstant { value, ty: IntConstantType::Standard(kind), remarks })
347}
348
349/// The base a spelling is written in, and where its digits start.
350///
351/// A leading `0` means octal only when a digit follows, so `0u` is a decimal zero with a
352/// suffix and `08` is an octal constant with a digit that does not exist. That is the split
353/// GCC makes, and it is what turns `08` into a message about octal rather than about a suffix.
354fn base_of(bytes: &[u8]) -> (u32, usize) {
355    match bytes {
356        [b'0', b'x' | b'X', ..] => (16, 2),
357        [b'0', b'b' | b'B', ..] => (2, 2),
358        [b'0', next, ..] if next.is_ascii_digit() => (8, 1),
359        _ => (10, 0),
360    }
361}
362
363/// Whether the spelling is a floating constant rather than an integer one.
364///
365/// A point anywhere, an `e` exponent in a decimal constant, or a `p` exponent in a hexadecimal
366/// one. `1e` and `1e+` are floating constants with no exponent digits, which is a diagnostic
367/// the floating path gives, and `1f` is an integer constant with a suffix that does not exist,
368/// which is one this path gives. Both compilers split them exactly there.
369///
370/// A leading zero does not survive an exponent: `08e5` is the floating constant eight hundred
371/// thousand and not an octal constant with a digit that does not exist.
372fn is_floating(bytes: &[u8], base: u32) -> bool {
373    let exponent = if base == 16 { *b"pP" } else { *b"eE" };
374    bytes.iter().any(|&byte| byte == b'.' || exponent.contains(&byte))
375}
376
377/// The value of a digit in the given base, and [`None`] when the byte is not one.
378///
379/// An octal constant reads `8` and `9` as digits, so that a constant holding one ends at the
380/// suffix and the error can name the digit rather than complain about the suffix.
381fn digit(byte: u8, base: u32) -> Option<u32> {
382    char::from(byte).to_digit(if base == 8 { 10 } else { base })
383}
384
385/// The length part of a suffix.
386#[derive(Debug, Clone, Copy, PartialEq, Eq)]
387enum Length {
388    /// `l` or `L`.
389    Long,
390    /// `ll` or `LL`.
391    LongLong,
392    /// `wb` or `WB`.
393    BitInt,
394}
395
396/// A parsed suffix.
397#[derive(Debug, Clone, Copy, PartialEq, Eq)]
398struct Suffix {
399    /// Whether `u` or `U` was there.
400    unsigned: bool,
401    /// The length part, when there was one.
402    length: Option<Length>,
403}
404
405/// Reads the suffix, which may hold each part once and in either order.
406fn suffix_of(mut rest: &[u8]) -> Result<Suffix, IntError> {
407    let mut suffix = Suffix { unsigned: false, length: None };
408    while let Some(&byte) = rest.first() {
409        let taken = match byte {
410            b'u' | b'U' if !suffix.unsigned => {
411                suffix.unsigned = true;
412                1
413            }
414            // The two letters have to agree about case, so `1ll` and `1LL` are constants and
415            // `1lL` is not. Both compilers refuse the mixed spelling in every dialect.
416            b'l' | b'L' if suffix.length.is_none() => {
417                if rest.get(1) == Some(&byte) {
418                    suffix.length = Some(Length::LongLong);
419                    2
420                } else {
421                    suffix.length = Some(Length::Long);
422                    1
423                }
424            }
425            b'w' | b'W' if suffix.length.is_none() => {
426                let second = if byte == b'w' { b'b' } else { b'B' };
427                if rest.get(1) != Some(&second) {
428                    return Err(IntError::InvalidSuffix);
429                }
430                suffix.length = Some(Length::BitInt);
431                2
432            }
433            _ => return Err(IntError::InvalidSuffix),
434        };
435        rest = &rest[taken..];
436    }
437    Ok(suffix)
438}
439
440/// The type of a `wb` constant, which is the narrowest one that holds the value.
441///
442/// The sign bit counts, so a signed one is never narrower than two bits: `1wb` is
443/// `_BitInt(2)`. An unsigned zero is `unsigned _BitInt(1)`, because a width of zero is not a
444/// type. Measured against clang.
445fn bit_int(value: u128, unsigned: bool) -> IntConstantType {
446    let used = 128 - value.leading_zeros();
447    let width = if unsigned { used.max(1) } else { used + 1 };
448    IntConstantType::BitInt { signed: !unsigned, width: width.max(if unsigned { 1 } else { 2 }) }
449}
450
451/// Whether `kind` is one of the standard signed types, which is what decides the remark about
452/// a decimal constant having gone unsigned.
453fn signed_standard(kind: IntKind) -> bool {
454    matches!(kind, IntKind::Int | IntKind::Long | IntKind::LongLong)
455}
456
457/// Whether the value fits in `kind` on this target.
458fn fits(value: u128, kind: IntKind, target: &TargetInfo) -> bool {
459    let width = int_width(kind, target);
460    // Signedness here never depends on what plain `char` is, because no candidate list holds a
461    // character type.
462    let bits = if kind.is_signed(false) { width - 1 } else { width };
463    // `unsigned __int128` holds every value the accumulator can, and shifting a `u128` by all
464    // of its bits is not a shift, so the widest type is answered without one.
465    bits >= 128 || value >> bits == 0
466}
467
468/// The candidate list for a base and a suffix, in the order the standard walks it.
469///
470/// `__int128` and `unsigned __int128` are on the end of every list, which is what gcc does:
471/// `9223372036854775808` is an `__int128` there and an `unsigned long long` in clang. Both
472/// compilers put `long long` out of reach in C89 unless the suffix asks for it, and C89 is
473/// also the dialect that offers `unsigned long` for a decimal constant with no suffix at all.
474fn candidates(base: u32, suffix: Suffix, std: Std) -> &'static [IntKind] {
475    use IntKind::{Int, Int128, Long, LongLong, UInt, UInt128, ULong, ULongLong};
476
477    let decimal = base == 10;
478    let c89 = std == Std::C89;
479    match (suffix.unsigned, suffix.length) {
480        (false, None) if decimal && c89 => &[Int, Long, ULong, Int128, UInt128],
481        (false, None) if decimal => &[Int, Long, LongLong, Int128],
482        (false, None) if c89 => &[Int, UInt, Long, ULong, Int128, UInt128],
483        (false, None) => &[Int, UInt, Long, ULong, LongLong, ULongLong, Int128, UInt128],
484
485        (true, None) if c89 => &[UInt, ULong, UInt128],
486        (true, None) => &[UInt, ULong, ULongLong, UInt128],
487
488        (false, Some(Length::Long)) if decimal && c89 => &[Long, ULong, Int128, UInt128],
489        (false, Some(Length::Long)) if decimal => &[Long, LongLong, Int128],
490        (false, Some(Length::Long)) if c89 => &[Long, ULong, Int128, UInt128],
491        (false, Some(Length::Long)) => &[Long, ULong, LongLong, ULongLong, Int128, UInt128],
492
493        (true, Some(Length::Long)) if c89 => &[ULong, UInt128],
494        (true, Some(Length::Long)) => &[ULong, ULongLong, UInt128],
495
496        (false, Some(Length::LongLong)) if decimal => &[LongLong, Int128],
497        (false, Some(Length::LongLong)) => &[LongLong, ULongLong, Int128, UInt128],
498        (true, Some(Length::LongLong)) => &[ULongLong, UInt128],
499
500        // A `wb` constant never reaches here: its type comes from the value alone.
501        (_, Some(Length::BitInt)) => &[],
502    }
503}
504
505/// Converts the spelling of a preprocessing number into a floating constant.
506///
507/// # Errors
508///
509/// [`FloatError`], one case of which is that the spelling is an integer constant rather than a
510/// malformed floating one.
511pub fn floating(text: &str, std: Std, target: &TargetInfo) -> Result<FloatConstant, FloatError> {
512    let bytes = text.as_bytes();
513    let (base, _) = base_of(bytes);
514    if !is_floating(bytes, base) {
515        return Err(FloatError::Integer);
516    }
517    // A leading zero means nothing to a floating constant, so there are two bases here and not
518    // four: `08e5` is eight hundred thousand rather than an octal constant with a bad digit.
519    let hex = base == 16;
520    let base = if hex { 16 } else { 10 };
521    let mut remarks = Remarks::NONE;
522    if hex && std < Std::C99 {
523        remarks = remarks.with(Remarks::HEX_FLOAT);
524    }
525
526    let mut index = if hex { 2 } else { 0 };
527    let mut digits = 0;
528    let mut point = false;
529    let mut separators = false;
530    while index < bytes.len() {
531        let byte = bytes[index];
532        if byte == b'\'' {
533            if digits == 0 || !next_is_digit(bytes, index, base) {
534                return Err(FloatError::InvalidSuffix);
535            }
536            separators = true;
537        } else if byte == b'.' {
538            if point {
539                return Err(FloatError::TooManyPoints);
540            }
541            point = true;
542        } else if digit(byte, base).is_some() {
543            digits += 1;
544        } else {
545            break;
546        }
547        index += 1;
548    }
549    if digits == 0 {
550        return Err(FloatError::NoDigits);
551    }
552
553    let marker = if hex { *b"pP" } else { *b"eE" };
554    if index < bytes.len() && marker.contains(&bytes[index]) {
555        index += 1;
556        if matches!(bytes.get(index), Some(b'+' | b'-')) {
557            index += 1;
558        }
559        let mut exponent_digits = 0;
560        while index < bytes.len() {
561            let byte = bytes[index];
562            if byte == b'\'' {
563                if exponent_digits == 0 || !next_is_digit(bytes, index, 10) {
564                    return Err(FloatError::InvalidSuffix);
565                }
566                separators = true;
567            } else if byte.is_ascii_digit() {
568                exponent_digits += 1;
569            } else {
570                break;
571            }
572            index += 1;
573        }
574        if exponent_digits == 0 {
575            return Err(FloatError::NoExponentDigits);
576        }
577    } else if hex {
578        // The exponent is not optional in a hexadecimal constant, because `f` is a digit there
579        // and `0x1.8f` would otherwise be a number and a suffix at the same time.
580        return Err(FloatError::MissingExponent);
581    }
582    if separators && std < Std::C23 {
583        remarks = remarks.with(Remarks::SEPARATORS);
584    }
585
586    let suffix = float_suffix(&bytes[index..], target)?;
587    remarks = remarks.with(suffix.remarks);
588    let (value, status) =
589        Float::parse(&text[..index], suffix.ty.format(target)).map_err(|error| match error {
590            // The scan above has already ruled all three of these out, and mapping them is
591            // still better than an unwrap that a later change could reach.
592            ParseError::NoDigits => FloatError::NoDigits,
593            ParseError::NoExponentDigits => FloatError::NoExponentDigits,
594            ParseError::Invalid => FloatError::InvalidSuffix,
595        })?;
596    if status.has(Status::OVERFLOW) {
597        remarks = remarks.with(Remarks::OUT_OF_RANGE);
598    }
599    // Underflow on its own is a subnormal, which is a number the program can use. Losing the
600    // value entirely is the part worth a word.
601    if status.has(Status::UNDERFLOW) && value.is_zero() {
602        remarks = remarks.with(Remarks::TRUNCATED);
603    }
604    Ok(FloatConstant { value, ty: suffix.ty, imaginary: suffix.imaginary, remarks })
605}
606
607/// Whether the byte after `index` is a digit in `base`, which is what makes a separator one.
608fn next_is_digit(bytes: &[u8], index: usize, base: u32) -> bool {
609    bytes.get(index + 1).is_some_and(|&next| digit(next, base).is_some())
610}
611
612/// A parsed floating suffix.
613struct FloatSuffix {
614    /// The type it named, which is `double` when it named none.
615    ty: FloatConstantType,
616    /// Whether it held an `i` or a `j`.
617    imaginary: bool,
618    /// What the suffix alone is worth saying about.
619    remarks: Remarks,
620}
621
622/// Reads the suffix, which may name a type once and mark the constant imaginary once, in either
623/// order.
624///
625/// Everything past `f` and `l` is an extension, and the extensions are where the case rules stop
626/// being uniform: the `f` of `_FloatN` may be either case and the `x` of `_FloatNx` may not, and
627/// the two letters of a decimal suffix have to agree. All of it measured on gcc 13.3.
628fn float_suffix(mut rest: &[u8], target: &TargetInfo) -> Result<FloatSuffix, FloatError> {
629    let mut ty = None;
630    let mut imaginary = false;
631    let mut remarks = Remarks::NONE;
632    while let Some(&byte) = rest.first() {
633        let taken = match byte {
634            b'i' | b'j' | b'I' | b'J' if !imaginary => {
635                imaginary = true;
636                remarks = remarks.with(Remarks::IMAGINARY);
637                1
638            }
639            // One type per constant, so `1.0fl` is not a constant and neither is `1.0ff`.
640            _ if ty.is_some() => return Err(FloatError::InvalidSuffix),
641            b'f' | b'F' => {
642                let (named, taken, extra) = float_n(rest)?;
643                ty = Some(named);
644                remarks = remarks.with(extra);
645                taken
646            }
647            b'l' | b'L' => {
648                ty = Some(FloatConstantType::LongDouble);
649                1
650            }
651            b'q' | b'Q' => {
652                ty = Some(FloatConstantType::Float128);
653                remarks = remarks.with(Remarks::EXTENDED_SUFFIX);
654                1
655            }
656            b'w' | b'W' => {
657                // `__float80` is the x87 format, which only x86 has.
658                if target.triple.arch != Arch::X86_64 {
659                    return Err(FloatError::UnsupportedType);
660                }
661                ty = Some(FloatConstantType::Float80);
662                remarks = remarks.with(Remarks::EXTENDED_SUFFIX);
663                1
664            }
665            b'd' | b'D' => {
666                let second = rest.get(1).copied();
667                let decimal = if byte == b'd' {
668                    matches!(second, Some(b'f' | b'd' | b'l'))
669                } else {
670                    matches!(second, Some(b'F' | b'D' | b'L'))
671                };
672                if decimal {
673                    return Err(FloatError::DecimalFloat);
674                }
675                ty = Some(FloatConstantType::Double);
676                remarks = remarks.with(Remarks::DOUBLE_SUFFIX);
677                1
678            }
679            _ => return Err(FloatError::InvalidSuffix),
680        };
681        rest = &rest[taken..];
682    }
683    Ok(FloatSuffix { ty: ty.unwrap_or(FloatConstantType::Double), imaginary, remarks })
684}
685
686/// Reads a suffix that starts with `f`, which is `float` on its own and one of the `_FloatN` or
687/// `_FloatNx` types when digits follow.
688///
689/// Returns the type, how many bytes it took and what is worth saying about it.
690fn float_n(rest: &[u8]) -> Result<(FloatConstantType, usize, Remarks), FloatError> {
691    let mut end = 1;
692    while rest.get(end).is_some_and(u8::is_ascii_digit) {
693        end += 1;
694    }
695    if end == 1 {
696        return Ok((FloatConstantType::Float, 1, Remarks::NONE));
697    }
698    // The `x` is lower case in every spelling gcc accepts, so `F64x` is a constant and `f64X`
699    // is not, however odd that looks next to the `F` being free.
700    let extended = rest.get(end) == Some(&b'x');
701    let ty = match (&rest[1..end], extended) {
702        (b"16", false) => FloatConstantType::Float16,
703        (b"32", false) => FloatConstantType::Float32,
704        (b"64", false) => FloatConstantType::Float64,
705        (b"128", false) => FloatConstantType::Float128,
706        (b"32", true) => FloatConstantType::Float32x,
707        (b"64", true) => FloatConstantType::Float64x,
708        // gcc knows the name `_Float128x` and has the type on no target here, and says so
709        // rather than calling the suffix invalid. `_Float16x` is not a type at all.
710        (b"128", true) => return Err(FloatError::UnsupportedType),
711        _ => return Err(FloatError::InvalidSuffix),
712    };
713    Ok((ty, end + usize::from(extended), Remarks::EXTENDED_SUFFIX))
714}
715
716#[cfg(test)]
717mod tests {
718    use rucc_target::Triple;
719
720    use super::*;
721
722    fn linux() -> TargetInfo {
723        TargetInfo::new("x86_64-unknown-linux-gnu".parse::<Triple>().expect("a known triple"))
724    }
725
726    fn aarch64() -> TargetInfo {
727        TargetInfo::new("aarch64-unknown-linux-gnu".parse::<Triple>().expect("a known triple"))
728    }
729
730    /// The value and the type of a constant in the default dialect.
731    fn c23(text: &str) -> Result<IntConstant, IntError> {
732        integer(text, Std::C23, &linux())
733    }
734
735    /// The type of a constant in the given dialect, on x86-64 Linux.
736    fn kind(text: &str, std: Std) -> IntKind {
737        match integer(text, std, &linux()).expect("a valid constant").ty {
738            IntConstantType::Standard(kind) => kind,
739            IntConstantType::BitInt { .. } => panic!("{text} is a _BitInt constant"),
740        }
741    }
742
743    #[test]
744    fn a_constant_in_each_base_has_the_value_it_says() {
745        assert_eq!(c23("0").expect("zero").value, 0);
746        assert_eq!(c23("42").expect("decimal").value, 42);
747        assert_eq!(c23("0777").expect("octal").value, 0o777);
748        assert_eq!(c23("0xdeadBEEF").expect("hex").value, 0xdead_beef);
749        assert_eq!(c23("0b1010").expect("binary").value, 0b1010);
750        assert_eq!(c23("0X10").expect("upper case prefix").value, 16);
751        // A leading zero with nothing after it is a decimal zero rather than an octal one with
752        // no digits, which is the split that lets `0u` through and stops `08`.
753        assert_eq!(c23("0u").expect("zero with a suffix").value, 0);
754    }
755
756    #[test]
757    fn digit_separators_are_stripped_and_reported_before_c23() {
758        let value = c23("1'000'000").expect("a C23 constant");
759        assert_eq!(value.value, 1_000_000);
760        assert!(value.remarks.is_none());
761        assert_eq!(c23("0x1'0").expect("hex with a separator").value, 16);
762
763        let older = integer("1'000", Std::C17, &linux()).expect("still converted");
764        assert!(older.remarks.has(Remarks::SEPARATORS));
765        assert_eq!(older.value, 1000);
766    }
767
768    #[test]
769    fn the_type_of_a_decimal_constant_walks_the_signed_types_only() {
770        // Measured with `_Generic` on gcc 13.3, x86-64 Linux.
771        assert_eq!(kind("2147483647", Std::C23), IntKind::Int);
772        assert_eq!(kind("2147483648", Std::C23), IntKind::Long);
773        assert_eq!(kind("4294967295", Std::C23), IntKind::Long);
774        assert_eq!(kind("9223372036854775807", Std::C23), IntKind::Long);
775        // Past `long long` gcc reaches for `__int128` rather than for an unsigned type, and
776        // says so: the constant is so large that it is unsigned.
777        assert_eq!(kind("9223372036854775808", Std::C23), IntKind::Int128);
778        assert_eq!(kind("18446744073709551615", Std::C23), IntKind::Int128);
779        let large = c23("18446744073709551615").expect("fits __int128");
780        assert!(large.remarks.has(Remarks::UNSIGNED));
781    }
782
783    #[test]
784    fn a_constant_in_another_base_may_be_unsigned_without_saying_so() {
785        // This is the split that surprises people: `4294967295` is a `long` and `0xffffffff`
786        // is an `unsigned int`, because only the decimal list is signed types alone.
787        assert_eq!(kind("0xffffffff", Std::C23), IntKind::UInt);
788        assert_eq!(kind("0x7fffffff", Std::C23), IntKind::Int);
789        assert_eq!(kind("0x80000000", Std::C23), IntKind::UInt);
790        assert_eq!(kind("0x100000000", Std::C23), IntKind::Long);
791        assert_eq!(kind("0xffffffffffffffff", Std::C23), IntKind::ULong);
792        assert_eq!(kind("0777", Std::C23), IntKind::Int);
793        assert_eq!(kind("0b1010", Std::C23), IntKind::Int);
794        // And no remark, because nothing about it is surprising enough to say.
795        assert!(c23("0xffffffff").expect("a constant").remarks.is_none());
796    }
797
798    #[test]
799    fn c89_has_unsigned_long_in_the_decimal_list_and_no_long_long_in_any() {
800        // gcc under `-std=c89 -pedantic`: "this decimal constant is unsigned only in ISO C90",
801        // and eight bytes rather than sixteen.
802        assert_eq!(kind("18446744073709551615", Std::C89), IntKind::ULong);
803        assert_eq!(kind("18446744073709551615", Std::C99), IntKind::Int128);
804        let old = integer("18446744073709551615", Std::C89, &linux()).expect("a C89 constant");
805        assert!(old.remarks.has(Remarks::UNSIGNED));
806        // The suffix still reaches `long long`, with the remark gcc prints for it.
807        let long_long = integer("1ll", Std::C89, &linux()).expect("an extension");
808        assert!(long_long.remarks.has(Remarks::LONG_LONG));
809        assert_eq!(kind("1ll", Std::C89), IntKind::LongLong);
810        assert!(integer("1ll", Std::C99, &linux()).expect("standard").remarks.is_none());
811    }
812
813    #[test]
814    fn a_suffix_narrows_the_list_it_does_not_pick_the_type() {
815        assert_eq!(kind("1u", Std::C23), IntKind::UInt);
816        assert_eq!(kind("1l", Std::C23), IntKind::Long);
817        assert_eq!(kind("1ul", Std::C23), IntKind::ULong);
818        assert_eq!(kind("1ll", Std::C23), IntKind::LongLong);
819        assert_eq!(kind("1llu", Std::C23), IntKind::ULongLong);
820        // The suffix is a floor rather than an answer: `4294967296u` is an `unsigned long`
821        // because `unsigned int` cannot hold it.
822        assert_eq!(kind("4294967296u", Std::C23), IntKind::ULong);
823        assert_eq!(kind("0xffffffffu", Std::C23), IntKind::UInt);
824    }
825
826    #[test]
827    fn the_letters_of_a_suffix_may_be_in_either_case_but_not_both() {
828        for text in ["1u", "1U", "1l", "1L", "1ll", "1LL", "1ul", "1lu", "1uL", "1LLU", "1llu"] {
829            assert!(c23(text).is_ok(), "{text} is a constant in both compilers");
830        }
831        for text in ["1lL", "1Ll", "1uu", "1lul", "1z", "1uz", "1f", "1x", "1_000"] {
832            assert_eq!(c23(text), Err(IntError::InvalidSuffix), "{text} is not");
833        }
834    }
835
836    #[test]
837    fn a_bit_int_constant_has_the_narrowest_type_that_holds_it() {
838        // Measured against clang, which is the only one of the two that has the type.
839        let cases = [
840            ("0wb", true, 2),
841            ("1wb", true, 2),
842            ("3wb", true, 3),
843            ("42wb", true, 7),
844            ("255wb", true, 9),
845            ("0uwb", false, 1),
846            ("1uwb", false, 1),
847            ("255uwb", false, 8),
848            ("256uwb", false, 9),
849            ("0xffffffffffffffffuwb", false, 64),
850        ];
851        for (text, signed, width) in cases {
852            let constant = c23(text).expect("a _BitInt constant");
853            assert_eq!(
854                constant.ty,
855                IntConstantType::BitInt { signed, width },
856                "{text} is the wrong width"
857            );
858        }
859        // Either order, either case, and never with a length suffix.
860        for text in ["1uwb", "1wbu", "1UWB", "1WBu", "1uWB"] {
861            assert!(c23(text).is_ok(), "{text} is a constant in clang");
862        }
863        for text in ["1wB", "1Wb", "1lwb", "1wbl", "1wbwb"] {
864            assert_eq!(c23(text), Err(IntError::InvalidSuffix), "{text} is not");
865        }
866        // Before C23 it is still converted, and still worth a word.
867        let older = integer("1wb", Std::C17, &linux()).expect("clang accepts it everywhere");
868        assert!(older.remarks.has(Remarks::BIT_INT));
869    }
870
871    #[test]
872    fn a_binary_constant_is_an_extension_before_c23() {
873        assert!(c23("0b1").expect("standard in C23").remarks.is_none());
874        let older = integer("0b1", Std::C17, &linux()).expect("both compilers accept it");
875        assert!(older.remarks.has(Remarks::BINARY));
876    }
877
878    #[test]
879    fn an_octal_constant_names_the_digit_that_is_not_one() {
880        assert_eq!(c23("08"), Err(IntError::InvalidOctalDigit));
881        assert_eq!(c23("0778"), Err(IntError::InvalidOctalDigit));
882        assert_eq!(c23("09"), Err(IntError::InvalidOctalDigit));
883        // A `9` elsewhere is fine, and the message is only for constants that began with `0`.
884        assert_eq!(c23("9").expect("decimal").value, 9);
885    }
886
887    #[test]
888    fn a_prefix_with_no_digits_after_it_is_not_a_constant() {
889        assert_eq!(c23("0x"), Err(IntError::NoDigits));
890        assert_eq!(c23("0b"), Err(IntError::NoDigits));
891    }
892
893    #[test]
894    fn a_constant_larger_than_any_type_is_refused_rather_than_wrapped() {
895        // gcc accumulates in sixty four bits and silently gives this the value zero and the
896        // type `int` after a warning. That is the one measured behaviour here we refuse to
897        // reproduce, and clang refuses it too.
898        assert_eq!(c23("340282366920938463463374607431768211456"), Err(IntError::TooLarge));
899        assert_eq!(c23("0x100000000000000000000000000000000"), Err(IntError::TooLarge));
900        // 2^127 fits in the accumulator and in no signed type, and the decimal list has no
901        // unsigned one to fall back to.
902        assert_eq!(c23("170141183460469231731687303715884105728"), Err(IntError::TooLarge));
903        // The same value written in hex reaches `unsigned __int128`, because that list has it.
904        assert_eq!(kind("0x80000000000000000000000000000000", Std::C23), IntKind::UInt128);
905        assert_eq!(kind("0xffffffffffffffffffffffffffffffff", Std::C23), IntKind::UInt128);
906    }
907
908    #[test]
909    fn a_floating_constant_is_handed_back_rather_than_refused() {
910        for text in ["1.0", ".5", "1.", "1e5", "1E-5", "1e", "0x1p3", "0x1.8p+1", "1.5e3"] {
911            assert_eq!(c23(text), Err(IntError::Floating), "{text} belongs to the other path");
912        }
913        // A leading zero does not make this an octal constant with a digit that does not
914        // exist. gcc compiles it, as eight hundred thousand.
915        assert_eq!(c23("08e5"), Err(IntError::Floating));
916        // A hexadecimal `e` is a digit, not an exponent, and `1f` is an integer with a suffix
917        // that does not exist rather than a float. Both compilers split them there.
918        assert_eq!(c23("0xe5").expect("hex digits").value, 0xe5);
919        assert_eq!(c23("1f"), Err(IntError::InvalidSuffix));
920    }
921
922    #[test]
923    fn the_type_comes_from_the_target_and_not_from_the_host() {
924        // `4294967295` is a `long` where `long` is sixty four bits and a `long long` where it
925        // is thirty two. A compiler that asked its own platform gets one of these wrong.
926        let windows =
927            TargetInfo::new("x86_64-pc-windows-msvc".parse::<Triple>().expect("a known triple"));
928        let on_windows = integer("4294967295", Std::C23, &windows).expect("a constant");
929        assert_eq!(on_windows.ty, IntConstantType::Standard(IntKind::LongLong));
930        assert_eq!(kind("4294967295", Std::C23), IntKind::Long);
931    }
932
933    /// A floating constant in the default dialect, on x86-64 Linux.
934    fn float(text: &str) -> Result<FloatConstant, FloatError> {
935        floating(text, Std::C23, &linux())
936    }
937
938    /// The bits of a constant's value, which is the form every measured row here was taken in.
939    fn bits(text: &str) -> u128 {
940        float(text).expect("a valid constant").value.to_bits()
941    }
942
943    #[test]
944    fn a_constant_with_no_suffix_is_a_double() {
945        let constant = float("1.5").expect("a constant");
946        assert_eq!(constant.ty, FloatConstantType::Double);
947        assert!(!constant.imaginary);
948        assert!(constant.remarks.is_none());
949        assert_eq!(constant.value.to_bits(), 0x3ff8_0000_0000_0000);
950        assert_eq!(bits("0.1"), 0x3fb9_9999_9999_999a);
951        assert_eq!(bits(".5"), 0x3fe0_0000_0000_0000);
952        assert_eq!(bits("1."), 0x3ff0_0000_0000_0000);
953        assert_eq!(bits("1e5"), 0x40f8_6a00_0000_0000);
954        assert_eq!(bits("0x1p3"), 0x4020_0000_0000_0000);
955        // A leading zero is not an octal prefix once there is an exponent, so this is eight
956        // hundred thousand and gcc compiles it as one.
957        assert_eq!(bits("08e5"), 0x4128_6a00_0000_0000);
958    }
959
960    #[test]
961    fn the_suffix_names_the_type_rather_than_narrowing_a_list() {
962        // Measured with `_Generic` on gcc 13.3, x86-64 Linux.
963        let cases = [
964            ("1.0", FloatConstantType::Double),
965            ("1.0f", FloatConstantType::Float),
966            ("1.0F", FloatConstantType::Float),
967            ("1.0l", FloatConstantType::LongDouble),
968            ("1.0L", FloatConstantType::LongDouble),
969            ("1.0d", FloatConstantType::Double),
970            ("1.0q", FloatConstantType::Float128),
971            ("1.0w", FloatConstantType::Float80),
972            ("1.0f16", FloatConstantType::Float16),
973            ("1.0F16", FloatConstantType::Float16),
974            ("1.0f32", FloatConstantType::Float32),
975            ("1.0f64", FloatConstantType::Float64),
976            ("1.0f128", FloatConstantType::Float128),
977            ("1.0f32x", FloatConstantType::Float32x),
978            ("1.0F64x", FloatConstantType::Float64x),
979        ];
980        for (text, ty) in cases {
981            assert_eq!(float(text).expect("a constant").ty, ty, "{text} has the wrong type");
982        }
983    }
984
985    #[test]
986    fn each_type_is_converted_in_the_format_the_target_has_for_it() {
987        // Every row measured by printing the bytes of the constant on gcc 13.3, x86-64 Linux.
988        // The two that surprise are `_Float32x`, which is plain `double`, and `_Float64x`,
989        // which is the x87 format and so the same bits as `long double` and `__float80`.
990        assert_eq!(bits("0.1f"), 0x3dcc_cccd);
991        assert_eq!(bits("0.1f16"), 0x2e66);
992        assert_eq!(bits("0.1f32x"), 0x3fb9_9999_9999_999a);
993        assert_eq!(bits("0.1f64x"), 0x3ffb_cccc_cccc_cccc_cccd);
994        assert_eq!(bits("0.1w"), 0x3ffb_cccc_cccc_cccc_cccd);
995        assert_eq!(bits("0.1l"), 0x3ffb_cccc_cccc_cccc_cccd);
996        assert_eq!(bits("0.1q"), 0x3ffb_9999_9999_9999_9999_9999_9999_999a);
997        assert_eq!(bits("0.1f128"), 0x3ffb_9999_9999_9999_9999_9999_9999_999a);
998        assert_eq!(bits("1.0l"), 0x3fff_8000_0000_0000_0000);
999    }
1000
1001    #[test]
1002    fn the_format_comes_from_the_target_and_not_from_the_host() {
1003        // `long double` is 128 bits wide on both of these and it is not the same type on both,
1004        // which is the whole reason the target carries a format and not only a width.
1005        let arm = floating("1.0l", Std::C23, &aarch64()).expect("a constant");
1006        assert_eq!(arm.value.to_bits(), 0x3fff_0000_0000_0000_0000_0000_0000_0000);
1007        assert_eq!(bits("1.0l"), 0x3fff_8000_0000_0000_0000);
1008        // And `_Float64x` follows it, being whatever the target has above `_Float64`.
1009        let arm_wide = floating("0.1f64x", Std::C23, &aarch64()).expect("a constant");
1010        assert_eq!(arm_wide.value.to_bits(), 0x3ffb_9999_9999_9999_9999_9999_9999_999a);
1011        // Where `long double` is `double` the constant is a `double` too.
1012        let windows =
1013            TargetInfo::new("x86_64-pc-windows-msvc".parse::<Triple>().expect("a known triple"));
1014        let on_windows = floating("1.0l", Std::C23, &windows).expect("a constant");
1015        assert_eq!(on_windows.value.to_bits(), 0x3ff0_0000_0000_0000);
1016    }
1017
1018    #[test]
1019    fn the_case_rules_of_a_floating_suffix_are_not_uniform() {
1020        // The `f` of a `_FloatN` suffix is free and the `x` of a `_FloatNx` one is not, and the
1021        // two letters of a decimal suffix have to agree. Measured on gcc 13.3, which accepts
1022        // every one of these in every dialect.
1023        for text in ["1.0f", "1.0F", "1.0L", "1.0Q", "1.0W", "1.0F32", "1.0f64x", "1.0F64x"] {
1024            assert!(float(text).is_ok(), "{text} is a constant in gcc");
1025        }
1026        for text in ["1.0F32X", "1.0f32X", "1.0f16x", "1.0ff", "1.0fl", "1.0lf", "1.0fF", "1.0LL"] {
1027            assert_eq!(float(text), Err(FloatError::InvalidSuffix), "{text} is not");
1028        }
1029    }
1030
1031    #[test]
1032    fn an_imaginary_suffix_may_sit_on_either_side_of_the_type() {
1033        for text in ["1.0i", "1.0j", "1.0I", "1.0J", "1.0if", "1.0fi", "1.0Li", "1.0iL", "1.0f16i"]
1034        {
1035            let constant = float(text).expect("a constant in gcc");
1036            assert!(constant.imaginary, "{text} is imaginary");
1037            assert!(constant.remarks.has(Remarks::IMAGINARY));
1038        }
1039        assert_eq!(float("1.0ii"), Err(FloatError::InvalidSuffix));
1040        assert_eq!(float("1.0ij"), Err(FloatError::InvalidSuffix));
1041        assert!(!float("1.0f").expect("a constant").imaginary);
1042    }
1043
1044    #[test]
1045    fn a_decimal_floating_constant_is_recognised_and_refused() {
1046        // The constant is well formed and there is nowhere in this compiler to put its value.
1047        for text in ["1.0df", "1.0dd", "1.0dl", "1.0DF", "1.0DD", "1.0DL"] {
1048            assert_eq!(float(text), Err(FloatError::DecimalFloat), "{text} is a decimal float");
1049        }
1050        // The letters have to agree about case, so these are not decimal floats and not
1051        // constants either.
1052        for text in ["1.0Df", "1.0dF", "1.0dD", "1.0Dl"] {
1053            assert_eq!(float(text), Err(FloatError::InvalidSuffix), "{text} is neither");
1054        }
1055        // A `d` on its own is a `double` written the long way, which gcc allows everywhere.
1056        let long_way = float("1.0d").expect("a GCC extension");
1057        assert_eq!(long_way.ty, FloatConstantType::Double);
1058        assert!(long_way.remarks.has(Remarks::DOUBLE_SUFFIX));
1059    }
1060
1061    #[test]
1062    fn a_type_the_target_does_not_have_is_refused_by_name() {
1063        // gcc says "'_Float128x' is not supported on this target" rather than calling the
1064        // suffix invalid, and it is supported on no target here.
1065        assert_eq!(float("1.0f128x"), Err(FloatError::UnsupportedType));
1066        // `__float80` is the x87 format, which only x86 has.
1067        assert_eq!(floating("1.0w", Std::C23, &aarch64()), Err(FloatError::UnsupportedType));
1068        assert!(float("1.0w").is_ok());
1069    }
1070
1071    #[test]
1072    fn a_hexadecimal_constant_needs_an_exponent_and_a_decimal_one_does_not() {
1073        // `f` is a hexadecimal digit, so without the exponent there is no telling the number
1074        // from the suffix. Both compilers require it.
1075        assert_eq!(float("0x1.8"), Err(FloatError::MissingExponent));
1076        assert_eq!(bits("0x1.8p0"), 0x3ff8_0000_0000_0000);
1077        assert_eq!(bits("0x.8p1"), 0x3ff0_0000_0000_0000);
1078        assert_eq!(bits("1.5"), 0x3ff8_0000_0000_0000);
1079        for text in ["1.0e", "1e+", "1e-", "0x1p", "0x1p+"] {
1080            assert_eq!(float(text), Err(FloatError::NoExponentDigits), "{text} has no exponent");
1081        }
1082        assert_eq!(float("1.2.3"), Err(FloatError::TooManyPoints));
1083    }
1084
1085    #[test]
1086    fn an_integer_constant_is_handed_back_rather_than_refused() {
1087        for text in ["1", "0", "0x10", "1u", "0777", "1wb", "0b1", "0xe5", "1f"] {
1088            assert_eq!(float(text), Err(FloatError::Integer), "{text} belongs to the other path");
1089        }
1090    }
1091
1092    #[test]
1093    fn a_value_past_the_range_of_its_type_is_still_a_constant() {
1094        let large = float("1e400").expect("a constant gcc compiles");
1095        assert!(large.value.is_infinite());
1096        assert!(large.remarks.has(Remarks::OUT_OF_RANGE));
1097        let small = float("1e-400").expect("a constant gcc compiles");
1098        assert!(small.value.is_zero());
1099        assert!(small.remarks.has(Remarks::TRUNCATED));
1100        // The same two in the format the suffix asked for rather than in `double`.
1101        assert!(float("1e39f").expect("a constant").remarks.has(Remarks::OUT_OF_RANGE));
1102        assert!(float("1e-46f").expect("a constant").remarks.has(Remarks::TRUNCATED));
1103        assert!(float("1e-4951l").expect("a constant").remarks.has(Remarks::TRUNCATED));
1104        // A subnormal is a number the program can use, and gcc says nothing about it.
1105        let subnormal = float("1e-320").expect("a constant");
1106        assert!(!subnormal.value.is_zero());
1107        assert!(subnormal.remarks.is_none());
1108    }
1109
1110    #[test]
1111    fn the_dialect_decides_what_a_constant_is_worth_saying_about() {
1112        // "use of C99 hexadecimal floating constant", which gcc says under C89 and not after.
1113        let old = floating("0x1p3", Std::C89, &linux()).expect("gcc compiles it anyway");
1114        assert!(old.remarks.has(Remarks::HEX_FLOAT));
1115        assert!(floating("0x1p3", Std::C99, &linux()).expect("standard").remarks.is_none());
1116        // Separators are C23 in both compilers, in the number and in the exponent.
1117        assert_eq!(bits("1'0.5"), 0x4025_0000_0000_0000);
1118        assert_eq!(bits("1.0e1'0"), 0x4202_a05f_2000_0000);
1119        assert!(float("0x1'0p0").expect("a C23 constant").remarks.is_none());
1120        let older = floating("1'0.5", Std::C17, &linux()).expect("still converted");
1121        assert!(older.remarks.has(Remarks::SEPARATORS));
1122        // And every extension suffix is accepted in every dialect, with a word about it.
1123        for text in ["1.0q", "1.0w", "1.0f16", "1.0f32x"] {
1124            let constant = floating(text, Std::C89, &linux()).expect("gcc accepts it in C89");
1125            assert!(constant.remarks.has(Remarks::EXTENDED_SUFFIX), "{text} is not standard");
1126        }
1127        assert!(float("1.0f").expect("a constant").remarks.is_none());
1128    }
1129}