Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fmt::vformat() throws an exception on Clang in x86 mode during chrono formatting. #4244

Open
TheStormN opened this issue Nov 25, 2024 · 6 comments

Comments

@TheStormN
Copy link

TheStormN commented Nov 25, 2024

Hello,

I believe I've discovered a bug in latest version of fmt when compiled using Clang in x86 targeting mode. We have a legacy codebase with some Time functions wrappers which we try to refactor by using more modern tooling. We use fmt as polyfill for platforms which still don't have proper std:;format() support.

The current issue is reproducible only on our Clang x86 targeting pipeline, on all other mobile and desktop platforms the code works as expected. The exception being thrown is fmt::v11::format_error. I've managed to strip down the code to a small reproducible example. Here's the CompilerExplorer link: https://godbolt.org/z/v1Mezdd8T

The moment you remove the -m32 flag the program executes successfully.

#include <chrono>
#include <iostream>

#include <cassert>

#include <fmt/format.h>
#include <fmt/chrono.h>

template <class Clock, class Duration = typename Clock::duration>
std::string formatTime(const std::string& format, const std::chrono::time_point<Clock, Duration>& time)
{
    return fmt::vformat("{:" + format + '}', fmt::make_format_args(time));
}

std::string fromUnixEpochToRFC1123(const int64_t epoch)
{
    std::chrono::system_clock::time_point timePoint{ std::chrono::seconds(epoch / 1000) };

    return formatTime("%a, %d %b %Y %H:%M:%S GMT", std::chrono::floor<std::chrono::seconds>(timePoint));
}

int main() {
    auto result = fromUnixEpochToRFC1123(32536850400000);
    bool isResultExpected = result == "Mon, 19 Jan 3001 22:00:00 GMT";
    assert(isResultExpected);
    std::cout << result << std::endl;
}

EDIT: Switching from fmt to std works on the same compiler with same flags: https://godbolt.org/z/v8EnYzaWq

@vitaut
Copy link
Contributor

vitaut commented Dec 7, 2024

The error is expected: 19 Jan 3001 is not representable as 32-bit time_t, see https://en.wikipedia.org/wiki/Year_2038_problem.

@vitaut vitaut closed this as completed Dec 7, 2024
@vitaut vitaut added the question label Dec 7, 2024
@TheStormN
Copy link
Author

@vitaut Ok then, how the std::vformat handles that without an issue: https://godbolt.org/z/v8EnYzaWq
Same compiler version and flags as in the original example, just switched from fmt to std.

@vitaut
Copy link
Contributor

vitaut commented Dec 14, 2024

I am not sure how they avoid conversion to time_t but if their method is implementable in {fmt} a PR would be welcome.

@TheStormN
Copy link
Author

@vitaut Ok, could you at least reopen the issue, so it is known that some work can be done here.

@vitaut
Copy link
Contributor

vitaut commented Dec 18, 2024

Sure, we can keep it open in case anyone is interested in investigating this further.

@vitaut vitaut reopened this Dec 18, 2024
@TheStormN TheStormN changed the title fmt::vformat() throws an exception on Android x86 during chrono formatting. fmt::vformat() throws an exception on Clang in x86 mode during chrono formatting. Dec 18, 2024
@TheStormN
Copy link
Author

Thanks, I've updated the title and description a bit, because it it seems to be a generic issue with Clang in x86 targeting mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants