Skip to content

[libc] Fix definition of UINT_MAX in limits.h #95279

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

Merged
merged 1 commit into from
Jun 12, 2024

Conversation

jhuber6
Copy link
Contributor

@jhuber6 jhuber6 commented Jun 12, 2024

Summary:
Currently we use (~0U) for this definition, however the ~ operator
returns a different sign, meaning that preprocessor checks against this
value will fail. See https://godbolt.org/z/TrjaY1d8q where the
preprocessor thinks that it's not 0xffffffff while the static
assertion thinks it is. This is because the latter does implicit
conversion but the preprocessor does not. This is now consistent with
other headers.

Summary:
Currently we use `(~0U)` for this definition, however the ~ operator
returns a different sign, meaning that preprocessor checks against this
value will fail. See https://godbolt.org/z/TrjaY1d8q where the
preprocessor thinks that it's not `0xffffffff` while the static
assertion thinks it is. This is because the latter does implicit
conversion but the preprocessor does not. This is now consistent with
other headers.
@llvmbot
Copy link
Member

llvmbot commented Jun 12, 2024

@llvm/pr-subscribers-libc

Author: Joseph Huber (jhuber6)

Changes

Summary:
Currently we use (~0U) for this definition, however the ~ operator
returns a different sign, meaning that preprocessor checks against this
value will fail. See https://godbolt.org/z/TrjaY1d8q where the
preprocessor thinks that it's not 0xffffffff while the static
assertion thinks it is. This is because the latter does implicit
conversion but the preprocessor does not. This is now consistent with
other headers.


Full diff: https://github.com/llvm/llvm-project/pull/95279.diff

1 Files Affected:

  • (modified) libc/include/llvm-libc-macros/limits-macros.h (+3-3)
diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index 95f0f5f0baa58..3fab996b61ac9 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -148,7 +148,7 @@
 #endif // INT_MAX
 
 #ifndef UINT_MAX
-#define UINT_MAX (~0U)
+#define UINT_MAX (INT_MAX * 2U + 1U)
 #endif // UINT_MAX
 
 #ifndef LONG_MAX
@@ -160,7 +160,7 @@
 #endif // LONG_MAX
 
 #ifndef ULONG_MAX
-#define ULONG_MAX (~0UL)
+#define ULONG_MAX (LONG_MAX * 2UL + 1UL)
 #endif // ULONG_MAX
 
 #ifndef LLONG_MAX
@@ -172,7 +172,7 @@
 #endif // LLONG_MAX
 
 #ifndef ULLONG_MAX
-#define ULLONG_MAX (~0ULL)
+#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
 #endif // ULLONG_MAX
 
 // *_MIN macros

@@ -148,7 +148,7 @@
#endif // INT_MAX

#ifndef UINT_MAX
#define UINT_MAX (~0U)
#define UINT_MAX (INT_MAX * 2U + 1U)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we explicitly cast ((unsigned) INT_MAX)?

Copy link
Contributor Author

@jhuber6 jhuber6 Jun 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be handled by the 2U part, otherwise it would fail in the myriad templates we use in limits.h I believe. This is how Clang's implementation does it at least.

@MaskRay
Copy link
Member

MaskRay commented Jun 12, 2024

What's the issue?

#define UINT_MAX (~0U)
_Static_assert(UINT_MAX == 0xFFFFFFFF, "");

compiles.

@jhuber6
Copy link
Contributor Author

jhuber6 commented Jun 12, 2024

What's the issue?

#define UINT_MAX (~0U)
_Static_assert(UINT_MAX == 0xFFFFFFFF, "");

compiles.

It's explained in the summary, ~0U is not seem as equal to 0xFFFFFFFF by the preprocessor in https://godbolt.org/z/TrjaY1d8q. This causes the situation shown there where the preprocessor says it's not 0xFFFFFFFF but the static assert says it is. I found this while compiling the compiler-rt which checks exactly this, furthermore this is how both GNU and Clang's resource headers seem to do it.

@MaskRay
Copy link
Member

MaskRay commented Jun 12, 2024

I see. Perhaps just #define UINT_MAX 0xffffffffU

@jhuber6
Copy link
Contributor Author

jhuber6 commented Jun 12, 2024

I see. Perhaps just #define UINT_MAX 0xffffffffU

Some targets have UINT_MAX as something other than 32-bits, The compiler defines __INT_MAX__ which tends to tell us the base width of an int, and thus an unsigned is just twice that plus one.

@jhuber6 jhuber6 merged commit d6bbe2e into llvm:main Jun 12, 2024
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants