[libc++] chrono::years/months periods fold to wrong values with GCC on i386 (x87 excess precision)
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
With #178182, `<__chrono/duration.h>` defines the `years` and `months` aliases via a floating-point constant expression:
```cpp
typedef duration(365.2425 * 60 * 60 * 24)>> years;
typedef duration(365.2425 * 60 * 60 * 24) / 12>> months;
```
The intended values are 31556952 and 2629746. `365.2425` is not exactly representable in binary so when GCC targets i386 it evaluates the constant expression with x87 extended precision (C++ defaults to `-fexcess-precision=standard`) and comes up as 31556951.
Sample Reproducer
```cpp
#include
constexpr long years = static_cast(365.2425 * 60 * 60 * 24);
constexpr long months = static_cast(365.2425 * 60 * 60 * 24) / 12;
int main() { std::printf("years=%ld months=%ld\n", years, months); }
```
| Command | Output |
|---|---|
| `g++ -std=c++20` (x86_64) | `years=31556952 months=2629746` |
| `g++ -m32 -std=c++20` | `years=31556951 months=2629745` |
| `g++ -m32 -std=c++20 -fexcess-precision=fast` | `years=31556952 months=2629746` |
| `clang++ -m32 -std=c++20` | `years=31556952 months=2629746` |
GCC 16.2.1, clang 22.1.8, Arch Linux x86_64.
Relates: #178182
Contributor guide
Research direction
Start by reading <__chrono/duration.h> around the years and months aliases, then reproduce the issue with g++ -m32 -std=c++20 using the sample program. Done when the i386 results match the intended values, 31556952 for years and 2629746 for months, without relying on excess-precision compiler flags.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100