[clang] [C99] Fix definitions of INTn_C macros (PR #133916)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 1 15:24:30 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Aaron Ballman (AaronBallman)
<details>
<summary>Changes</summary>
C99 introduced macros of the form `INTn_C(v)` which expand to a signed or unsigned integer constant with the specified value `v` and the type `int_leastN_t`. Clang's initial implementation of these macros used token pasting to form the integer constants, but this means that users cannot define a macro named `L`, `U`, `UL`, etc before including `<stdint.h>` (in freestanding mode, where Clang's header is being used) because that could form invalid token pasting results. The new definitions now use the predefined `__INTn_C` macros instead of using token pasting. This matches the behavior of GCC.
Fixes #<!-- -->85995
---
Full diff: https://github.com/llvm/llvm-project/pull/133916.diff
4 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+3)
- (modified) clang/lib/Headers/stdint.h (+18-129)
- (modified) clang/test/C/drs/dr209.c (+2-4)
- (modified) clang/test/Preprocessor/stdint.c (+39-30)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 75a173a48e67e..e7691c583c616 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -333,6 +333,9 @@ Bug Fixes in This Version
- Fixed a problematic case with recursive deserialization within ``FinishedDeserializing()`` where
``PassInterestingDeclsToConsumer()`` was called before the declarations were safe to be passed. (#GH129982)
- Fixed a modules crash where an explicit Constructor was deserialized. (#GH132794)
+- Defining an integer literal suffix (e.g., ``LL``) before including
+ ``<stdint.h>`` in a freestanding build no longer causes invalid token pasting
+ when using the ``INTn_C`` macros. (#GH85995)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Headers/stdint.h b/clang/lib/Headers/stdint.h
index 01feab7b1ee2c..96c2ccace13d0 100644
--- a/clang/lib/Headers/stdint.h
+++ b/clang/lib/Headers/stdint.h
@@ -317,166 +317,55 @@ typedef __UINTMAX_TYPE__ uintmax_t;
* integer width that the target implements, so corresponding macros are
* defined below, too.
*
- * These macros are defined using the same successive-shrinking approach as
- * the type definitions above. It is likewise important that macros are defined
- * in order of decending width.
- *
* Note that C++ should not check __STDC_CONSTANT_MACROS here, contrary to the
* claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
*/
-#define __int_c_join(a, b) a ## b
-#define __int_c(v, suffix) __int_c_join(v, suffix)
-#define __uint_c(v, suffix) __int_c_join(v##U, suffix)
-
-
-#ifdef __INT64_TYPE__
-# undef __int64_c_suffix
-# undef __int32_c_suffix
-# undef __int16_c_suffix
-# undef __int8_c_suffix
-# ifdef __INT64_C_SUFFIX__
-# define __int64_c_suffix __INT64_C_SUFFIX__
-# define __int32_c_suffix __INT64_C_SUFFIX__
-# define __int16_c_suffix __INT64_C_SUFFIX__
-# define __int8_c_suffix __INT64_C_SUFFIX__
-# endif /* __INT64_C_SUFFIX__ */
-#endif /* __INT64_TYPE__ */
-
#ifdef __int_least64_t
-# ifdef __int64_c_suffix
-# define INT64_C(v) __int_c(v, __int64_c_suffix)
-# define UINT64_C(v) __uint_c(v, __int64_c_suffix)
-# else
-# define INT64_C(v) v
-# define UINT64_C(v) v ## U
-# endif /* __int64_c_suffix */
+#define INT64_C(v) __INT64_C(v)
+#define UINT64_C(v) __UINT64_C(v)
#endif /* __int_least64_t */
#ifdef __INT56_TYPE__
-# undef __int32_c_suffix
-# undef __int16_c_suffix
-# undef __int8_c_suffix
-# ifdef __INT56_C_SUFFIX__
-# define INT56_C(v) __int_c(v, __INT56_C_SUFFIX__)
-# define UINT56_C(v) __uint_c(v, __INT56_C_SUFFIX__)
-# define __int32_c_suffix __INT56_C_SUFFIX__
-# define __int16_c_suffix __INT56_C_SUFFIX__
-# define __int8_c_suffix __INT56_C_SUFFIX__
-# else
-# define INT56_C(v) v
-# define UINT56_C(v) v ## U
-# endif /* __INT56_C_SUFFIX__ */
+#define INT56_C(v) __INT56_C(v)
+#define UINT56_C(v) __UINT56_C(v)
#endif /* __INT56_TYPE__ */
#ifdef __INT48_TYPE__
-# undef __int32_c_suffix
-# undef __int16_c_suffix
-# undef __int8_c_suffix
-# ifdef __INT48_C_SUFFIX__
-# define INT48_C(v) __int_c(v, __INT48_C_SUFFIX__)
-# define UINT48_C(v) __uint_c(v, __INT48_C_SUFFIX__)
-# define __int32_c_suffix __INT48_C_SUFFIX__
-# define __int16_c_suffix __INT48_C_SUFFIX__
-# define __int8_c_suffix __INT48_C_SUFFIX__
-# else
-# define INT48_C(v) v
-# define UINT48_C(v) v ## U
-# endif /* __INT48_C_SUFFIX__ */
+#define INT48_C(v) __INT48_C(v)
+#define UINT48_C(v) __UINT48_C(v)
#endif /* __INT48_TYPE__ */
#ifdef __INT40_TYPE__
-# undef __int32_c_suffix
-# undef __int16_c_suffix
-# undef __int8_c_suffix
-# ifdef __INT40_C_SUFFIX__
-# define INT40_C(v) __int_c(v, __INT40_C_SUFFIX__)
-# define UINT40_C(v) __uint_c(v, __INT40_C_SUFFIX__)
-# define __int32_c_suffix __INT40_C_SUFFIX__
-# define __int16_c_suffix __INT40_C_SUFFIX__
-# define __int8_c_suffix __INT40_C_SUFFIX__
-# else
-# define INT40_C(v) v
-# define UINT40_C(v) v ## U
-# endif /* __INT40_C_SUFFIX__ */
+#define INT40_C(v) __INT40_C(v)
+#define UINT40_C(v) __UINT40_C(v)
#endif /* __INT40_TYPE__ */
-#ifdef __INT32_TYPE__
-# undef __int32_c_suffix
-# undef __int16_c_suffix
-# undef __int8_c_suffix
-# ifdef __INT32_C_SUFFIX__
-# define __int32_c_suffix __INT32_C_SUFFIX__
-# define __int16_c_suffix __INT32_C_SUFFIX__
-# define __int8_c_suffix __INT32_C_SUFFIX__
-# endif /* __INT32_C_SUFFIX__ */
-#endif /* __INT32_TYPE__ */
-
#ifdef __int_least32_t
-# ifdef __int32_c_suffix
-# define INT32_C(v) __int_c(v, __int32_c_suffix)
-# define UINT32_C(v) __uint_c(v, __int32_c_suffix)
-# else
-# define INT32_C(v) v
-# define UINT32_C(v) v ## U
-# endif /* __int32_c_suffix */
+#define INT32_C(v) __INT32_C(v)
+#define UINT32_C(v) __UINT32_C(v)
#endif /* __int_least32_t */
#ifdef __INT24_TYPE__
-# undef __int16_c_suffix
-# undef __int8_c_suffix
-# ifdef __INT24_C_SUFFIX__
-# define INT24_C(v) __int_c(v, __INT24_C_SUFFIX__)
-# define UINT24_C(v) __uint_c(v, __INT24_C_SUFFIX__)
-# define __int16_c_suffix __INT24_C_SUFFIX__
-# define __int8_c_suffix __INT24_C_SUFFIX__
-# else
-# define INT24_C(v) v
-# define UINT24_C(v) v ## U
-# endif /* __INT24_C_SUFFIX__ */
+#define INT24_C(v) __INT24_C(v)
+#define UINT24_C(v) __UINT24_C(v)
#endif /* __INT24_TYPE__ */
-#ifdef __INT16_TYPE__
-# undef __int16_c_suffix
-# undef __int8_c_suffix
-# ifdef __INT16_C_SUFFIX__
-# define __int16_c_suffix __INT16_C_SUFFIX__
-# define __int8_c_suffix __INT16_C_SUFFIX__
-# endif /* __INT16_C_SUFFIX__ */
-#endif /* __INT16_TYPE__ */
-
#ifdef __int_least16_t
-# ifdef __int16_c_suffix
-# define INT16_C(v) __int_c(v, __int16_c_suffix)
-# define UINT16_C(v) __uint_c(v, __int16_c_suffix)
-# else
-# define INT16_C(v) v
-# define UINT16_C(v) v ## U
-# endif /* __int16_c_suffix */
+#define INT16_C(v) __INT16_C(v)
+#define UINT16_C(v) __UINT16_C(v)
#endif /* __int_least16_t */
-#ifdef __INT8_TYPE__
-# undef __int8_c_suffix
-# ifdef __INT8_C_SUFFIX__
-# define __int8_c_suffix __INT8_C_SUFFIX__
-# endif /* __INT8_C_SUFFIX__ */
-#endif /* __INT8_TYPE__ */
-
#ifdef __int_least8_t
-# ifdef __int8_c_suffix
-# define INT8_C(v) __int_c(v, __int8_c_suffix)
-# define UINT8_C(v) __uint_c(v, __int8_c_suffix)
-# else
-# define INT8_C(v) v
-# define UINT8_C(v) v ## U
-# endif /* __int8_c_suffix */
+#define INT8_C(v) __INT8_C(v)
+#define UINT8_C(v) __UINT8_C(v)
#endif /* __int_least8_t */
@@ -938,8 +827,8 @@ typedef __UINTMAX_TYPE__ uintmax_t;
#endif
/* 7.18.4.2 Macros for greatest-width integer constants. */
-#define INTMAX_C(v) __int_c(v, __INTMAX_C_SUFFIX__)
-#define UINTMAX_C(v) __int_c(v, __UINTMAX_C_SUFFIX__)
+#define INTMAX_C(v) __INTMAX_C(v)
+#define UINTMAX_C(v) __UINTMAX_C(v)
/* C23 7.22.3.x Width of other integer types. */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
diff --git a/clang/test/C/drs/dr209.c b/clang/test/C/drs/dr209.c
index d8613669f3277..3bf95376ded39 100644
--- a/clang/test/C/drs/dr209.c
+++ b/clang/test/C/drs/dr209.c
@@ -4,6 +4,7 @@
RUN: %clang_cc1 -std=c17 -ffreestanding -fsyntax-only -verify -pedantic %s
RUN: %clang_cc1 -std=c2x -ffreestanding -fsyntax-only -verify -pedantic %s
*/
+// expected-no-diagnostics
/* WG14 DR209: partial
* Problem implementing INTN_C macros
@@ -33,8 +34,7 @@ void dr209(void) {
(void)_Generic(INT16_C(0), __typeof__(+(int_least16_t){0}) : 1);
(void)_Generic(INT32_C(0), __typeof__(+(int_least32_t){0}) : 1);
(void)_Generic(INT64_C(0), __typeof__(+(int_least64_t){0}) : 1);
- // FIXME: This is not the expected behavior; the type of the expanded value
- // in both of these cases should be 'int',
+ // The type of the expanded value in both of these cases should be 'int',
//
// C99 7.18.4p3: The type of the expression shall have the same type as would
// an expression of the corresponding type converted according to the integer
@@ -53,8 +53,6 @@ void dr209(void) {
//
(void)_Generic(UINT8_C(0), __typeof__(+(uint_least8_t){0}) : 1);
(void)_Generic(UINT16_C(0), __typeof__(+(uint_least16_t){0}) : 1);
- // expected-error at -2 {{controlling expression type 'unsigned int' not compatible with any generic association type}}
- // expected-error at -2 {{controlling expression type 'unsigned int' not compatible with any generic association type}}
(void)_Generic(UINT32_C(0), __typeof__(+(uint_least32_t){0}) : 1);
(void)_Generic(UINT64_C(0), __typeof__(+(uint_least64_t){0}) : 1);
}
diff --git a/clang/test/Preprocessor/stdint.c b/clang/test/Preprocessor/stdint.c
index af1d6983fd995..899ff59bf0b6a 100644
--- a/clang/test/Preprocessor/stdint.c
+++ b/clang/test/Preprocessor/stdint.c
@@ -94,9 +94,9 @@
// ARM:WCHAR_MIN_ 0U
//
// ARM:INT8_C_(0) 0
-// ARM:UINT8_C_(0) 0U
+// ARM:UINT8_C_(0) 0
// ARM:INT16_C_(0) 0
-// ARM:UINT16_C_(0) 0U
+// ARM:UINT16_C_(0) 0
// ARM:INT32_C_(0) 0
// ARM:UINT32_C_(0) 0U
// ARM:INT64_C_(0) 0LL
@@ -201,9 +201,9 @@
// ARM64_32:WCHAR_MIN_ (-2147483647 -1)
//
// ARM64_32:INT8_C_(0) 0
-// ARM64_32:UINT8_C_(0) 0U
+// ARM64_32:UINT8_C_(0) 0
// ARM64_32:INT16_C_(0) 0
-// ARM64_32:UINT16_C_(0) 0U
+// ARM64_32:UINT16_C_(0) 0
// ARM64_32:INT32_C_(0) 0
// ARM64_32:UINT32_C_(0) 0U
// ARM64_32:INT64_C_(0) 0LL
@@ -309,9 +309,9 @@
// I386:WCHAR_MIN_ (-2147483647 -1)
//
// I386:INT8_C_(0) 0
-// I386:UINT8_C_(0) 0U
+// I386:UINT8_C_(0) 0
// I386:INT16_C_(0) 0
-// I386:UINT16_C_(0) 0U
+// I386:UINT16_C_(0) 0
// I386:INT32_C_(0) 0
// I386:UINT32_C_(0) 0U
// I386:INT64_C_(0) 0LL
@@ -416,9 +416,9 @@
// MIPS:WCHAR_MIN_ (-2147483647 -1)
//
// MIPS:INT8_C_(0) 0
-// MIPS:UINT8_C_(0) 0U
+// MIPS:UINT8_C_(0) 0
// MIPS:INT16_C_(0) 0
-// MIPS:UINT16_C_(0) 0U
+// MIPS:UINT16_C_(0) 0
// MIPS:INT32_C_(0) 0
// MIPS:UINT32_C_(0) 0U
// MIPS:INT64_C_(0) 0LL
@@ -523,9 +523,9 @@
// MIPS64:WCHAR_MIN_ (-2147483647 -1)
//
// MIPS64:INT8_C_(0) 0
-// MIPS64:UINT8_C_(0) 0U
+// MIPS64:UINT8_C_(0) 0
// MIPS64:INT16_C_(0) 0
-// MIPS64:UINT16_C_(0) 0U
+// MIPS64:UINT16_C_(0) 0
// MIPS64:INT32_C_(0) 0
// MIPS64:UINT32_C_(0) 0U
// MIPS64:INT64_C_(0) 0L
@@ -623,9 +623,9 @@
// MSP430:WCHAR_MIN_ (-32767 -1)
//
// MSP430:INT8_C_(0) 0
-// MSP430:UINT8_C_(0) 0U
+// MSP430:UINT8_C_(0) 0
// MSP430:INT16_C_(0) 0
-// MSP430:UINT16_C_(0) 0U
+// MSP430:UINT16_C_(0) 0
// MSP430:INT32_C_(0) 0L
// MSP430:UINT32_C_(0) 0UL
// MSP430:INT64_C_(0) 0LL
@@ -730,9 +730,9 @@
// PPC64:WCHAR_MIN_ (-2147483647 -1)
//
// PPC64:INT8_C_(0) 0
-// PPC64:UINT8_C_(0) 0U
+// PPC64:UINT8_C_(0) 0
// PPC64:INT16_C_(0) 0
-// PPC64:UINT16_C_(0) 0U
+// PPC64:UINT16_C_(0) 0
// PPC64:INT32_C_(0) 0
// PPC64:UINT32_C_(0) 0U
// PPC64:INT64_C_(0) 0L
@@ -837,9 +837,9 @@
// PPC64-NETBSD:WCHAR_MIN_ (-2147483647 -1)
//
// PPC64-NETBSD:INT8_C_(0) 0
-// PPC64-NETBSD:UINT8_C_(0) 0U
+// PPC64-NETBSD:UINT8_C_(0) 0
// PPC64-NETBSD:INT16_C_(0) 0
-// PPC64-NETBSD:UINT16_C_(0) 0U
+// PPC64-NETBSD:UINT16_C_(0) 0
// PPC64-NETBSD:INT32_C_(0) 0
// PPC64-NETBSD:UINT32_C_(0) 0U
// PPC64-NETBSD:INT64_C_(0) 0L
@@ -945,9 +945,9 @@
// PPC:WCHAR_MIN_ (-2147483647 -1)
//
// PPC:INT8_C_(0) 0
-// PPC:UINT8_C_(0) 0U
+// PPC:UINT8_C_(0) 0
// PPC:INT16_C_(0) 0
-// PPC:UINT16_C_(0) 0U
+// PPC:UINT16_C_(0) 0
// PPC:INT32_C_(0) 0
// PPC:UINT32_C_(0) 0U
// PPC:INT64_C_(0) 0LL
@@ -1052,9 +1052,9 @@
// S390X:WCHAR_MIN_ (-2147483647 -1)
//
// S390X:INT8_C_(0) 0
-// S390X:UINT8_C_(0) 0U
+// S390X:UINT8_C_(0) 0
// S390X:INT16_C_(0) 0
-// S390X:UINT16_C_(0) 0U
+// S390X:UINT16_C_(0) 0
// S390X:INT32_C_(0) 0
// S390X:UINT32_C_(0) 0U
// S390X:INT64_C_(0) 0L
@@ -1159,9 +1159,9 @@
// SPARC:WCHAR_MIN_ (-2147483647 -1)
//
// SPARC:INT8_C_(0) 0
-// SPARC:UINT8_C_(0) 0U
+// SPARC:UINT8_C_(0) 0
// SPARC:INT16_C_(0) 0
-// SPARC:UINT16_C_(0) 0U
+// SPARC:UINT16_C_(0) 0
// SPARC:INT32_C_(0) 0
// SPARC:UINT32_C_(0) 0U
// SPARC:INT64_C_(0) 0LL
@@ -1259,9 +1259,9 @@
// TCE:WCHAR_MIN_ (-2147483647 -1)
//
// TCE:INT8_C_(0) 0
-// TCE:UINT8_C_(0) 0U
+// TCE:UINT8_C_(0) 0
// TCE:INT16_C_(0) 0
-// TCE:UINT16_C_(0) 0U
+// TCE:UINT16_C_(0) 0
// TCE:INT32_C_(0) 0
// TCE:UINT32_C_(0) 0U
// TCE:INT64_C_(0) INT64_C(0)
@@ -1367,9 +1367,9 @@
// X86_64:WCHAR_MIN_ (-2147483647 -1)
//
// X86_64:INT8_C_(0) 0
-// X86_64:UINT8_C_(0) 0U
+// X86_64:UINT8_C_(0) 0
// X86_64:INT16_C_(0) 0
-// X86_64:UINT16_C_(0) 0U
+// X86_64:UINT16_C_(0) 0
// X86_64:INT32_C_(0) 0
// X86_64:UINT32_C_(0) 0U
// X86_64:INT64_C_(0) 0L
@@ -1487,9 +1487,9 @@
// XCORE:WCHAR_MIN_ 0
//
// XCORE:INT8_C_(0) 0
-// XCORE:UINT8_C_(0) 0U
+// XCORE:UINT8_C_(0) 0
// XCORE:INT16_C_(0) 0
-// XCORE:UINT16_C_(0) 0U
+// XCORE:UINT16_C_(0) 0
// XCORE:INT32_C_(0) 0
// XCORE:UINT32_C_(0) 0U
// XCORE:INT64_C_(0) 0LL
@@ -1594,9 +1594,9 @@
// XTENSA:WCHAR_MIN_ (-2147483647 -1)
//
// XTENSA:INT8_C_(0) 0
-// XTENSA:UINT8_C_(0) 0U
+// XTENSA:UINT8_C_(0) 0
// XTENSA:INT16_C_(0) 0
-// XTENSA:UINT16_C_(0) 0U
+// XTENSA:UINT16_C_(0) 0
// XTENSA:INT32_C_(0) 0
// XTENSA:UINT32_C_(0) 0U
// XTENSA:INT64_C_(0) 0LL
@@ -1640,6 +1640,15 @@
// JOIN:INTMAX_C_(0) 0LL
// JOIN:UINTMAX_C_(0) 0ULL
+// Demonstrate that you can define the integer literal suffixes as a macro and
+// it will not interfere with the definitions in stdint.h due to invalid tokens
+// formed via token pasting. See GH85995 for details.
+#define L %
+#define U %
+#define UL %
+#define LL %
+#define ULL %
+
#include <stdint.h>
INT8_MAX_ INT8_MAX
``````````
</details>
https://github.com/llvm/llvm-project/pull/133916
More information about the cfe-commits
mailing list