3961. Does chrono::parse check format strings?

Section: 30.13 [time.parse] Status: New Submitter: Jonathan Wakely Opened: 2023-07-28 Last modified: 2023-11-03

Priority: 3

View other active issues in [time.parse].

View all other issues in [time.parse].

View all issues with New status.

Discussion:

30.13 [time.parse] p16 says: "If the type being parsed cannot represent the information that the format flag refers to, is.setstate(ios_base::failbit) is called." Note it says "the format flag" singular. I had interpreted this as meaning that if the entire format string doesn't provide the info needed by the type, it fails. But that's not what it says. It says that parsing fails if the type cannot represent "the information that the format flag refers to". Which format flag? Presumably this rule applies to each of them in turn. So "Monday 13:00" >> parse("%a %R", sec) is required to fail, rather than ignore the %a part and set sec to 13h. I don't think that is the intended design. I think the phrasing of this rule is backwards. It shouldn't be focused on what info is provided by the format flag, but what info is needed by the type.

What should happen when chrono::parse is given a meaningless format string like "%", or "%E", or "%Ea" or "%99a"? Presumably that should set failbit, but I don't think we actually say so. If the implementation should set failbit, is it conforming to do so before extracting any characters?

Is it conforming to set failbit before extracting any characters if the format string can never succeed for the parsable type? Consider:

std::chrono::seconds sec; std::cin >> parse("%a", sec);
The type being parsed (seconds) cannot represent the information that %a (a weekday) refers to, so we should set cin.setstate(ios_base::failbit). But should that happen before extracting any characters, or after extracting a weekday string? If it's unspecified, should we say so explicitly?

Can a conforming implementation validate the format string before extracting any characters, and fail early if parsing the actual istream contents can never succeed? Or is parse("%a", sec) required to try to parse a valid weekday name before setting failbit?

[2023-11-02; Reflector poll]

Set priority to 3 after reflector poll.

Proposed resolution:

This wording is relative to N4950.

  1. Modify 30.13 [time.parse] as indicated:

    -15- All from_stream overloads behave as unformatted input functions, except that they have an unspecified effect on the value returned by subsequent calls to basic_istream<>::is.gcount(). Each overload takes a format string containing ordinary characters and flags which have special meaning. Each flag begins with a %. Some flags can be modified by E or O. During parsing each flag interprets characters as parts of date and time types according to Table 102. Some flags can be modified by a width parameter given as a positive decimal integer called out as N below which governs how many characters are parsed from the stream in interpreting the flag. All characters in the format string that are not represented in Table 102, except for whitespace, are parsed unchanged from the stream. A whitespace character matches zero or more whitespace characters in the input stream.

    -?- If a format string contains a % character that is not part of a flag shown in Table 102, or a modifier that is not allowed for a flag, is.setstate(ios_base::failbit) is called. It is unspecified how many characters (if any) are extracted before the call to is.setstate(ios_base::failbit).

    -16- If a value cannot be determined for the type being parsed from the flags in the format string cannot represent the information that the format flag refers to is.setstate(ios_base::failbit) is called. It is unspecified how many characters (if any) are extracted before the call to is.setstate(ios_base::failbit).

    [Example: A duration cannot represent a weekday weekday, so parse("%a", dur) will always fail if the type of dur is a specialization of duration. Implementations can check the format string and set failbit before extracting any characters. end example]