llvm / llvm/llvm-project

[libc++] chrono::years/months periods fold to wrong values with GCC on i386 (x87 excess precision)

Open
#223,223 2 comments 0 reactions 0 assignees View on GitHub
chrono floating-point libc++
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.