-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Clang] Add predefined macros for integer constants to implement section 7.18.4 of ISO/IEC 9899:1999 in <stdint.h>
in a safe way
#123514
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
Conversation
…C` and `__UINTMAX_C`
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang Author: Manuel Sainz de Baranda y Goñi (redcode) ChangesThis small PR makes Clang predefine the following macros:
Which improves compatibility with GCC and makes it trivial to implement section 7.18.4 of ISO/IEC 9899:1999. Clang defines Let's say, for example, that minimal-test.c: #if defined(__clang__) & !defined(__INT64_C)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wreserved-identifier"
# define __PSTDC_INT_C_(literal, suffix) literal##suffix
# define __PSTDC_INT_C(literal, suffix) __PSTDC_INT_C_(literal, suffix)
# define INT64_C(literal) __PSTDC_INT_C(literal, __INT64_C_SUFFIX__)
# pragma clang diagnostic pop
#elif defined(__GNUC__)
# define INT64_C __INT64_C
#endif
typedef __INT64_TYPE__ int64_t;
#define L "Make Clang produce an error"
#define LL "Make Clang produce an error"
int main(int argc, char **argv)
{
(void)argc; (void)argv;
int64_t v = INT64_C(9223372036854775807);
(void)v;
return 0;
}
<img width="697" alt="imagen" src="https://github.com/user-attachments/assets/6df97af6-7cfd-4cf9-85b7-d7c854509325" /> test.c: #if defined(__clang__) && !defined(__INT8_C)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wreserved-identifier"
# define __PSTDC_INT_C_(literal, suffix) literal##suffix
# define __PSTDC_INT_C(literal, suffix) __PSTDC_INT_C_(literal, suffix)
# define INT8_C(literal) __PSTDC_INT_C(literal, __INT8_C_SUFFIX__)
# define INT16_C(literal) __PSTDC_INT_C(literal, __INT16_C_SUFFIX__)
# define INT32_C(literal) __PSTDC_INT_C(literal, __INT32_C_SUFFIX__)
# define INT64_C(literal) __PSTDC_INT_C(literal, __INT64_C_SUFFIX__)
# define INTMAX_C(literal) __PSTDC_INT_C(literal, __INTMAX_C_SUFFIX__)
# define UINT8_C(literal) __PSTDC_INT_C(literal, __UINT8_C_SUFFIX__)
# define UINT16_C(literal) __PSTDC_INT_C(literal, __UINT16_C_SUFFIX__)
# define UINT32_C(literal) __PSTDC_INT_C(literal, __UINT32_C_SUFFIX__)
# define UINT64_C(literal) __PSTDC_INT_C(literal, __UINT64_C_SUFFIX__)
# define UINTMAX_C(literal) __PSTDC_INT_C(literal, __UINTMAX_C_SUFFIX__)
# pragma clang diagnostic pop
#else
# define INT8_C __INT8_C
# define INT16_C __INT16_C
# define INT32_C __INT32_C
# define INT64_C __INT64_C
# define INTMAX_C __INTMAX_C
# define UINT8_C __UINT8_C
# define UINT16_C __UINT16_C
# define UINT32_C __UINT32_C
# define UINT64_C __UINT64_C
# define UINTMAX_C __UINTMAX_C
#endif
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
typedef __UINTMAX_TYPE__ uintmax_t;
#define L "Make Clang produce an error"
#define LL "Make Clang produce an error"
#define U "Make Clang produce an error"
#define UL "Make Clang produce an error"
#define ULL "Make Clang produce an error"
int main(int argc, char **argv)
{
(void)argc; (void)argv;
int8_t a = INT8_C (127);
int16_t b = INT16_C (32767);
int32_t c = INT32_C (2147483647);
int64_t d = INT64_C (9223372036854775807);
intmax_t e = INTMAX_C (9223372036854775807);
uint8_t f = UINT8_C (255);
uint16_t g = UINT16_C (65535);
uint32_t h = UINT32_C (4294967295);
uint64_t i = UINT64_C (18446744073709551615);
uintmax_t j = UINTMAX_C(18446744073709551615);
(void)a; (void)b; (void)c; (void)d; (void)e;
(void)f; (void)g; (void)h; (void)i; (void)j;
return 0;
} Full diff: https://github.com/llvm/llvm-project/pull/123514.diff 1 Files Affected:
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 29723b573e771a..17f624e9645395 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -253,6 +253,8 @@ static void DefineExactWidthIntType(const LangOptions &LangOpts,
StringRef ConstSuffix(TI.getTypeConstantSuffix(Ty));
Builder.defineMacro(Prefix + Twine(TypeWidth) + "_C_SUFFIX__", ConstSuffix);
+ Builder.defineMacro(Prefix + Twine(TypeWidth) + "_C(c)",
+ ConstSuffix.size() ? Twine("c##") + ConstSuffix : "c");
}
static void DefineExactWidthIntTypeSize(TargetInfo::IntType Ty,
@@ -1164,12 +1166,16 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Builder);
DefineFmt(LangOpts, "__INTMAX", TI.getIntMaxType(), TI, Builder);
- Builder.defineMacro("__INTMAX_C_SUFFIX__",
- TI.getTypeConstantSuffix(TI.getIntMaxType()));
+ StringRef ConstSuffix(TI.getTypeConstantSuffix(TI.getIntMaxType()));
+ Builder.defineMacro("__INTMAX_C_SUFFIX__", ConstSuffix);
+ Builder.defineMacro("__INTMAX_C(c)",
+ ConstSuffix.size() ? Twine("c##") + ConstSuffix : "c");
DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Builder);
DefineFmt(LangOpts, "__UINTMAX", TI.getUIntMaxType(), TI, Builder);
- Builder.defineMacro("__UINTMAX_C_SUFFIX__",
- TI.getTypeConstantSuffix(TI.getUIntMaxType()));
+ ConstSuffix = TI.getTypeConstantSuffix(TI.getUIntMaxType());
+ Builder.defineMacro("__UINTMAX_C_SUFFIX__", ConstSuffix);
+ Builder.defineMacro("__UINTMAX_C(c)",
+ ConstSuffix.size() ? Twine("c##") + ConstSuffix : "c");
DefineType("__PTRDIFF_TYPE__", TI.getPtrDiffType(LangAS::Default), Builder);
DefineFmt(LangOpts, "__PTRDIFF", TI.getPtrDiffType(LangAS::Default), TI,
Builder);
|
This seems related to #85995. Do you plan to fix that issue together? |
I wasn't planning on fixing Clang's Do you want me to do it? |
Oh, I didn't mean that. It might be better to do that in a separated PR. |
OK, then I'll fix it in a separate PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the fix! Can you also add test coverage for the changes to clang/test/Headers
and a release note so users know about the fix to clang/docs/ReleaseNotes.rst
?
Also, precommit CI found relevant failures:
******************** TEST 'Clang :: Preprocessor/init-aarch64.c' FAILED ********************
Exit Code: 1
Command Output (stderr):
--
RUN: at line 1: /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/build/bin/clang -cc1 -internal-isystem /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/build/lib/clang/20/include -nostdsysteminc -E -dM -triple=aarch64 -xc /dev/null > /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/build/tools/clang/test/Preprocessor/Output/init-aarch64.c.tmp.aarch64
+ /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/build/bin/clang -cc1 -internal-isystem /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/build/lib/clang/20/include -nostdsysteminc -E -dM -triple=aarch64 -xc /dev/null
RUN: at line 2: /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/build/bin/FileCheck --check-prefixes=AARCH64,AARCH64_LE,AARCH64_C /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/clang/test/Preprocessor/init-aarch64.c --match-full-lines < /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/build/tools/clang/test/Preprocessor/Output/init-aarch64.c.tmp.aarch64
+ /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/build/bin/FileCheck --check-prefixes=AARCH64,AARCH64_LE,AARCH64_C /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/clang/test/Preprocessor/init-aarch64.c --match-full-lines
/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/clang/test/Preprocessor/init-aarch64.c:138:18: error: AARCH64-NEXT: is not on the line after the previous match
// AARCH64-NEXT: #define __INT16_C_SUFFIX__
^
<stdin>:124:1: note: 'next' match was here
#define __INT16_C_SUFFIX__
^
<stdin>:122:43: note: previous match ended here
#define __HAVE_FUNCTION_MULTI_VERSIONING 1
^
<stdin>:123:1: note: non-matching line after previous match is here
#define __INT16_C(c) c
^
Input file: <stdin>
Check file: /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-jfggl-1/llvm-project/github-pull-requests/clang/test/Preprocessor/init-aarch64.c
-dump-input=help explains the following input dump.
Input was:
<<<<<<
.
.
.
119: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
120: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
121: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
122: #define __HAVE_FUNCTION_MULTI_VERSIONING 1
123: #define __INT16_C(c) c
124: #define __INT16_C_SUFFIX__
next:138 !~~~~~~~~~~~~~~~~~~~~~~~~~~ error: match on wrong line
125: #define __INT16_FMTd__ "hd"
126: #define __INT16_FMTi__ "hi"
127: #define __INT16_MAX__ 32767
128: #define __INT16_TYPE__ short
129: #define __INT32_C(c) c
.
.
.
>>>>>>
--
********************
(and similar in init.c)
OK, let me work on that. |
OK, I think my work is done. I have added the release note and also updated the preprocessor init tests (with the exception of As for the tests in |
…sor init tests (v7k-compat).
@jrtc27 has explained to me that the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thank you for this!
@redcode Congratulations on having your first Pull Request (PR) merged into the LLVM Project! Your changes will be combined with recent changes from other authors, then tested by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR. Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues. How to do this, and the rest of the post-merge process, is covered in detail here. If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again. If you don't get any reports, no action is required from you. Your changes are working as expected, well done! |
clang recently began providing predefined __INTN_C/__UINTN_C macros resulting in macro redefinition warnings in toolchain/llvm.h. This change was landed in clang in late Jan. 2025 and clang/LLVM 20 is the first official release that has this support (see the PR linked below). Prefer the definitions provided by clang and avoid redefining these macros for clang versions 20 and later to avoid said warnings. Link: llvm/llvm-project#123514 Signed-off-by: Jonathon Penix <[email protected]>
clang recently began providing predefined __INTN_C/__UINTN_C macros resulting in macro redefinition warnings in toolchain/llvm.h. This change was landed in clang in late Jan. 2025 and clang/LLVM 20 is the first official release that has this support (see the PR linked below). Prefer the definitions provided by clang and avoid redefining these macros for clang versions 20 and later to avoid said warnings. Link: llvm/llvm-project#123514 Signed-off-by: Jonathon Penix <[email protected]>
clang recently began providing predefined __INTN_C/__UINTN_C macros resulting in macro redefinition warnings in toolchain/llvm.h. This change was landed in clang in late Jan. 2025 and clang/LLVM 20 is the first official release that has this support (see the PR linked below). Prefer the definitions provided by clang and avoid redefining these macros for clang versions 20 and later to avoid said warnings. Link: llvm/llvm-project#123514 Signed-off-by: Jonathon Penix <[email protected]>
This small PR makes Clang predefine the following macros:
Which improves compatibility with GCC and makes it trivial to implement section 7.18.4 of ISO/IEC 9899:1999.
Clang defines
__INT<N>_C_SUFFIX__
,__UINT<N>_C_SUFFIX__
,__INTAX_C_SUFFIX__
and__UINTMAX_C_SUFFIX__
, but these macros are useless for this purpose.Let's say, for example, that
__INT64_C_SUFFIX__
expands toL
orLL
. If the user defines them as a macros, the compiler will produce errors ifINT64_C
is implemented in<stdint.h>
using__INT64_C_SUFFIX__
:minimal-test.c:
test.c: