Skip to content

[C23] Add __TYPE_FMTB__ and __TYPE_FMTb__ predefined macros #82037

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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ C23 Feature Support

Fixes (`#81472 <https://github.com/llvm/llvm-project/issues/81472>`_).

- Clang now generates predefined macros of the form ``__TYPE_FMTB__`` and
``__TYPE_FMTb__`` (e.g., ``__UINT_FAST64_FMTB__``) in C23 mode for use with
macros typically exposed from ``<inttypes.h>``, such as ``PRIb8``.
(`#81896: <https://github.com/llvm/llvm-project/issues/81896>`_).

Non-comprehensive list of changes in this release
-------------------------------------------------

Expand Down
106 changes: 59 additions & 47 deletions clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,21 @@ static void DefineTypeSize(const Twine &MacroName, TargetInfo::IntType Ty,
TI.isTypeSigned(Ty), Builder);
}

static void DefineFmt(const Twine &Prefix, TargetInfo::IntType Ty,
const TargetInfo &TI, MacroBuilder &Builder) {
bool IsSigned = TI.isTypeSigned(Ty);
static void DefineFmt(const LangOptions &LangOpts, const Twine &Prefix,
TargetInfo::IntType Ty, const TargetInfo &TI,
MacroBuilder &Builder) {
StringRef FmtModifier = TI.getTypeFormatModifier(Ty);
for (const char *Fmt = IsSigned ? "di" : "ouxX"; *Fmt; ++Fmt) {
Builder.defineMacro(Prefix + "_FMT" + Twine(*Fmt) + "__",
Twine("\"") + FmtModifier + Twine(*Fmt) + "\"");
}
auto Emitter = [&](char Fmt) {
Builder.defineMacro(Prefix + "_FMT" + Twine(Fmt) + "__",
Twine("\"") + FmtModifier + Twine(Fmt) + "\"");
};
bool IsSigned = TI.isTypeSigned(Ty);
llvm::for_each(StringRef(IsSigned ? "di" : "ouxX"), Emitter);

// C23 added the b and B modifiers for printing binary output of unsigned
// integers. Conditionally define those if compiling in C23 mode.
if (LangOpts.C23 && !IsSigned)
llvm::for_each(StringRef("bB"), Emitter);
}

static void DefineType(const Twine &MacroName, TargetInfo::IntType Ty,
Expand Down Expand Up @@ -217,7 +224,8 @@ static void DefineTypeSizeAndWidth(const Twine &Prefix, TargetInfo::IntType Ty,
DefineTypeWidth(Prefix + "_WIDTH__", Ty, TI, Builder);
}

static void DefineExactWidthIntType(TargetInfo::IntType Ty,
static void DefineExactWidthIntType(const LangOptions &LangOpts,
TargetInfo::IntType Ty,
const TargetInfo &TI,
MacroBuilder &Builder) {
int TypeWidth = TI.getTypeWidth(Ty);
Expand All @@ -236,7 +244,7 @@ static void DefineExactWidthIntType(TargetInfo::IntType Ty,
const char *Prefix = IsSigned ? "__INT" : "__UINT";

DefineType(Prefix + Twine(TypeWidth) + "_TYPE__", Ty, Builder);
DefineFmt(Prefix + Twine(TypeWidth), Ty, TI, Builder);
DefineFmt(LangOpts, Prefix + Twine(TypeWidth), Ty, TI, Builder);

StringRef ConstSuffix(TI.getTypeConstantSuffix(Ty));
Builder.defineMacro(Prefix + Twine(TypeWidth) + "_C_SUFFIX__", ConstSuffix);
Expand All @@ -259,7 +267,8 @@ static void DefineExactWidthIntTypeSize(TargetInfo::IntType Ty,
DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
}

static void DefineLeastWidthIntType(unsigned TypeWidth, bool IsSigned,
static void DefineLeastWidthIntType(const LangOptions &LangOpts,
unsigned TypeWidth, bool IsSigned,
const TargetInfo &TI,
MacroBuilder &Builder) {
TargetInfo::IntType Ty = TI.getLeastIntTypeByWidth(TypeWidth, IsSigned);
Expand All @@ -274,11 +283,12 @@ static void DefineLeastWidthIntType(unsigned TypeWidth, bool IsSigned,
DefineTypeSizeAndWidth(Prefix + Twine(TypeWidth), Ty, TI, Builder);
else
DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
DefineFmt(Prefix + Twine(TypeWidth), Ty, TI, Builder);
DefineFmt(LangOpts, Prefix + Twine(TypeWidth), Ty, TI, Builder);
}

static void DefineFastIntType(unsigned TypeWidth, bool IsSigned,
const TargetInfo &TI, MacroBuilder &Builder) {
static void DefineFastIntType(const LangOptions &LangOpts, unsigned TypeWidth,
bool IsSigned, const TargetInfo &TI,
MacroBuilder &Builder) {
// stdint.h currently defines the fast int types as equivalent to the least
// types.
TargetInfo::IntType Ty = TI.getLeastIntTypeByWidth(TypeWidth, IsSigned);
Expand All @@ -293,7 +303,7 @@ static void DefineFastIntType(unsigned TypeWidth, bool IsSigned,
DefineTypeSizeAndWidth(Prefix + Twine(TypeWidth), Ty, TI, Builder);
else
DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
DefineFmt(Prefix + Twine(TypeWidth), Ty, TI, Builder);
DefineFmt(LangOpts, Prefix + Twine(TypeWidth), Ty, TI, Builder);
}


Expand Down Expand Up @@ -1120,27 +1130,28 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineTypeSizeof("__SIZEOF_INT128__", 128, TI, Builder);

DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Builder);
DefineFmt("__INTMAX", TI.getIntMaxType(), TI, Builder);
DefineFmt(LangOpts, "__INTMAX", TI.getIntMaxType(), TI, Builder);
Builder.defineMacro("__INTMAX_C_SUFFIX__",
TI.getTypeConstantSuffix(TI.getIntMaxType()));
DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Builder);
DefineFmt("__UINTMAX", TI.getUIntMaxType(), TI, Builder);
DefineFmt(LangOpts, "__UINTMAX", TI.getUIntMaxType(), TI, Builder);
Builder.defineMacro("__UINTMAX_C_SUFFIX__",
TI.getTypeConstantSuffix(TI.getUIntMaxType()));
DefineType("__PTRDIFF_TYPE__", TI.getPtrDiffType(LangAS::Default), Builder);
DefineFmt("__PTRDIFF", TI.getPtrDiffType(LangAS::Default), TI, Builder);
DefineFmt(LangOpts, "__PTRDIFF", TI.getPtrDiffType(LangAS::Default), TI,
Builder);
DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Builder);
DefineFmt("__INTPTR", TI.getIntPtrType(), TI, Builder);
DefineFmt(LangOpts, "__INTPTR", TI.getIntPtrType(), TI, Builder);
DefineType("__SIZE_TYPE__", TI.getSizeType(), Builder);
DefineFmt("__SIZE", TI.getSizeType(), TI, Builder);
DefineFmt(LangOpts, "__SIZE", TI.getSizeType(), TI, Builder);
DefineType("__WCHAR_TYPE__", TI.getWCharType(), Builder);
DefineType("__WINT_TYPE__", TI.getWIntType(), Builder);
DefineTypeSizeAndWidth("__SIG_ATOMIC", TI.getSigAtomicType(), TI, Builder);
DefineType("__CHAR16_TYPE__", TI.getChar16Type(), Builder);
DefineType("__CHAR32_TYPE__", TI.getChar32Type(), Builder);

DefineType("__UINTPTR_TYPE__", TI.getUIntPtrType(), Builder);
DefineFmt("__UINTPTR", TI.getUIntPtrType(), TI, Builder);
DefineFmt(LangOpts, "__UINTPTR", TI.getUIntPtrType(), TI, Builder);

// The C standard requires the width of uintptr_t and intptr_t to be the same,
// per 7.20.2.4p1. Same for intmax_t and uintmax_t, per 7.20.2.5p1.
Expand Down Expand Up @@ -1216,65 +1227,66 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__WINT_UNSIGNED__");

// Define exact-width integer types for stdint.h
DefineExactWidthIntType(TargetInfo::SignedChar, TI, Builder);
DefineExactWidthIntType(LangOpts, TargetInfo::SignedChar, TI, Builder);

if (TI.getShortWidth() > TI.getCharWidth())
DefineExactWidthIntType(TargetInfo::SignedShort, TI, Builder);
DefineExactWidthIntType(LangOpts, TargetInfo::SignedShort, TI, Builder);

if (TI.getIntWidth() > TI.getShortWidth())
DefineExactWidthIntType(TargetInfo::SignedInt, TI, Builder);
DefineExactWidthIntType(LangOpts, TargetInfo::SignedInt, TI, Builder);

if (TI.getLongWidth() > TI.getIntWidth())
DefineExactWidthIntType(TargetInfo::SignedLong, TI, Builder);
DefineExactWidthIntType(LangOpts, TargetInfo::SignedLong, TI, Builder);

if (TI.getLongLongWidth() > TI.getLongWidth())
DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Builder);
DefineExactWidthIntType(LangOpts, TargetInfo::SignedLongLong, TI, Builder);

DefineExactWidthIntType(TargetInfo::UnsignedChar, TI, Builder);
DefineExactWidthIntType(LangOpts, TargetInfo::UnsignedChar, TI, Builder);
DefineExactWidthIntTypeSize(TargetInfo::UnsignedChar, TI, Builder);
DefineExactWidthIntTypeSize(TargetInfo::SignedChar, TI, Builder);

if (TI.getShortWidth() > TI.getCharWidth()) {
DefineExactWidthIntType(TargetInfo::UnsignedShort, TI, Builder);
DefineExactWidthIntType(LangOpts, TargetInfo::UnsignedShort, TI, Builder);
DefineExactWidthIntTypeSize(TargetInfo::UnsignedShort, TI, Builder);
DefineExactWidthIntTypeSize(TargetInfo::SignedShort, TI, Builder);
}

if (TI.getIntWidth() > TI.getShortWidth()) {
DefineExactWidthIntType(TargetInfo::UnsignedInt, TI, Builder);
DefineExactWidthIntType(LangOpts, TargetInfo::UnsignedInt, TI, Builder);
DefineExactWidthIntTypeSize(TargetInfo::UnsignedInt, TI, Builder);
DefineExactWidthIntTypeSize(TargetInfo::SignedInt, TI, Builder);
}

if (TI.getLongWidth() > TI.getIntWidth()) {
DefineExactWidthIntType(TargetInfo::UnsignedLong, TI, Builder);
DefineExactWidthIntType(LangOpts, TargetInfo::UnsignedLong, TI, Builder);
DefineExactWidthIntTypeSize(TargetInfo::UnsignedLong, TI, Builder);
DefineExactWidthIntTypeSize(TargetInfo::SignedLong, TI, Builder);
}

if (TI.getLongLongWidth() > TI.getLongWidth()) {
DefineExactWidthIntType(TargetInfo::UnsignedLongLong, TI, Builder);
DefineExactWidthIntType(LangOpts, TargetInfo::UnsignedLongLong, TI,
Builder);
DefineExactWidthIntTypeSize(TargetInfo::UnsignedLongLong, TI, Builder);
DefineExactWidthIntTypeSize(TargetInfo::SignedLongLong, TI, Builder);
}

DefineLeastWidthIntType(8, true, TI, Builder);
DefineLeastWidthIntType(8, false, TI, Builder);
DefineLeastWidthIntType(16, true, TI, Builder);
DefineLeastWidthIntType(16, false, TI, Builder);
DefineLeastWidthIntType(32, true, TI, Builder);
DefineLeastWidthIntType(32, false, TI, Builder);
DefineLeastWidthIntType(64, true, TI, Builder);
DefineLeastWidthIntType(64, false, TI, Builder);

DefineFastIntType(8, true, TI, Builder);
DefineFastIntType(8, false, TI, Builder);
DefineFastIntType(16, true, TI, Builder);
DefineFastIntType(16, false, TI, Builder);
DefineFastIntType(32, true, TI, Builder);
DefineFastIntType(32, false, TI, Builder);
DefineFastIntType(64, true, TI, Builder);
DefineFastIntType(64, false, TI, Builder);
DefineLeastWidthIntType(LangOpts, 8, true, TI, Builder);
DefineLeastWidthIntType(LangOpts, 8, false, TI, Builder);
DefineLeastWidthIntType(LangOpts, 16, true, TI, Builder);
DefineLeastWidthIntType(LangOpts, 16, false, TI, Builder);
DefineLeastWidthIntType(LangOpts, 32, true, TI, Builder);
DefineLeastWidthIntType(LangOpts, 32, false, TI, Builder);
DefineLeastWidthIntType(LangOpts, 64, true, TI, Builder);
DefineLeastWidthIntType(LangOpts, 64, false, TI, Builder);

DefineFastIntType(LangOpts, 8, true, TI, Builder);
DefineFastIntType(LangOpts, 8, false, TI, Builder);
DefineFastIntType(LangOpts, 16, true, TI, Builder);
DefineFastIntType(LangOpts, 16, false, TI, Builder);
DefineFastIntType(LangOpts, 32, true, TI, Builder);
DefineFastIntType(LangOpts, 32, false, TI, Builder);
DefineFastIntType(LangOpts, 64, true, TI, Builder);
DefineFastIntType(LangOpts, 64, false, TI, Builder);

Builder.defineMacro("__USER_LABEL_PREFIX__", TI.getUserLabelPrefix());

Expand Down
64 changes: 64 additions & 0 deletions clang/test/Preprocessor/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,70 @@
// C99-NOT: __GXX_WEAK__
// C99-NOT: __cplusplus
//
// RUN: %clang_cc1 -std=c17 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C17-FMT %s
// RUN: %clang_cc1 -std=c23 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C23-FMT %s
//
// C17-FMT-NOT: __SIZE_FMTB__
// C17-FMT-NOT: __SIZE_FMTb__
// C17-FMT-NOT: __UINT8_FMTB__
// C17-FMT-NOT: __UINT8_FMTb__
// C17-FMT-NOT: __UINT16_FMTB__
// C17-FMT-NOT: __UINT16_FMTb__
// C17-FMT-NOT: __UINT32_FMTB__
// C17-FMT-NOT: __UINT32_FMTb__
// C17-FMT-NOT: __UINT64_FMTB__
// C17-FMT-NOT: __UINT64_FMTb__
// C17-FMT-NOT: __UINTMAX_FMTB__
// C17-FMT-NOT: __UINTMAX_FMTb__
// C17-FMT-NOT: __UINTPTR_FMTB__
// C17-FMT-NOT: __UINTPTR_FMTb__
// C17-FMT-NOT: __UINT_FAST16_FMTB__
// C17-FMT-NOT: __UINT_FAST16_FMTb__
// C17-FMT-NOT: __UINT_FAST32_FMTB__
// C17-FMT-NOT: __UINT_FAST32_FMTb__
// C17-FMT-NOT: __UINT_FAST64_FMTB__
// C17-FMT-NOT: __UINT_FAST64_FMTb__
// C17-FMT-NOT: __UINT_FAST8_FMTB__
// C17-FMT-NOT: __UINT_FAST8_FMTb__
// C17-FMT-NOT: __UINT_LEAST16_FMTB__
// C17-FMT-NOT: __UINT_LEAST16_FMTb__
// C17-FMT-NOT: __UINT_LEAST32_FMTB__
// C17-FMT-NOT: __UINT_LEAST32_FMTb__
// C17-FMT-NOT: __UINT_LEAST64_FMTB__
// C17-FMT-NOT: __UINT_LEAST64_FMTb__
// C17-FMT-NOT: __UINT_LEAST8_FMTB__
// C17-FMT-NOT: __UINT_LEAST8_FMTb__
// C23-FMT: #define __SIZE_FMTB__ "llB"
// C23-FMT: #define __SIZE_FMTb__ "llb"
// C23-FMT: #define __UINT16_FMTB__ "hB"
// C23-FMT: #define __UINT16_FMTb__ "hb"
// C23-FMT: #define __UINT32_FMTB__ "B"
// C23-FMT: #define __UINT32_FMTb__ "b"
// C23-FMT: #define __UINT64_FMTB__ "llB"
// C23-FMT: #define __UINT64_FMTb__ "llb"
// C23-FMT: #define __UINT8_FMTB__ "hhB"
// C23-FMT: #define __UINT8_FMTb__ "hhb"
// C23-FMT: #define __UINTMAX_FMTB__ "llB"
// C23-FMT: #define __UINTMAX_FMTb__ "llb"
// C23-FMT: #define __UINTPTR_FMTB__ "llB"
// C23-FMT: #define __UINTPTR_FMTb__ "llb"
// C23-FMT: #define __UINT_FAST16_FMTB__ "hB"
// C23-FMT: #define __UINT_FAST16_FMTb__ "hb"
// C23-FMT: #define __UINT_FAST32_FMTB__ "B"
// C23-FMT: #define __UINT_FAST32_FMTb__ "b"
// C23-FMT: #define __UINT_FAST64_FMTB__ "llB"
// C23-FMT: #define __UINT_FAST64_FMTb__ "llb"
// C23-FMT: #define __UINT_FAST8_FMTB__ "hhB"
// C23-FMT: #define __UINT_FAST8_FMTb__ "hhb"
// C23-FMT: #define __UINT_LEAST16_FMTB__ "hB"
// C23-FMT: #define __UINT_LEAST16_FMTb__ "hb"
// C23-FMT: #define __UINT_LEAST32_FMTB__ "B"
// C23-FMT: #define __UINT_LEAST32_FMTb__ "b"
// C23-FMT: #define __UINT_LEAST64_FMTB__ "llB"
// C23-FMT: #define __UINT_LEAST64_FMTb__ "llb"
// C23-FMT: #define __UINT_LEAST8_FMTB__ "hhB"
// C23-FMT: #define __UINT_LEAST8_FMTb__ "hhb"
//
//
// RUN: %clang_cc1 -std=c11 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
// RUN: %clang_cc1 -std=c1x -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
Expand Down