Skip to content

[C23] Add __TYPE_FMTB__ and __TYPE_FMTb__ predefined macros #82361

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

Conversation

AaronBallman
Copy link
Collaborator

This adds predefined formatting macros in C23 mode for printing unsigned integers in binary format (e.g, UINT_FAST64_FMTB). These are used to implement the PRIb (et al) macros in inttypes.h

Fixes #81896

(Was previously reviewed in 82037, this is fixing some failures found post-commit.)

This adds predefined formatting macros in C23 mode for printing
unsigned integers in binary format (e.g, __UINT_FAST64_FMTB__). These
are used to implement the PRIb (et al) macros in inttypes.h

Fixes llvm#81896
...er, removing unrelated changes.
@llvmbot llvmbot added the clang Clang issues not falling into any other category label Feb 20, 2024
@llvmbot
Copy link
Member

llvmbot commented Feb 20, 2024

@llvm/pr-subscribers-clang

Author: Aaron Ballman (AaronBallman)

Changes

This adds predefined formatting macros in C23 mode for printing unsigned integers in binary format (e.g, UINT_FAST64_FMTB). These are used to implement the PRIb (et al) macros in inttypes.h

Fixes #81896

(Was previously reviewed in 82037, this is fixing some failures found post-commit.)


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

3 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+5)
  • (modified) clang/lib/Frontend/InitPreprocessor.cpp (+59-47)
  • (modified) clang/test/Preprocessor/init.c (+64)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 16f79a349c20c8..7083d66ae8f45d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -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
 -------------------------------------------------
 
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 1b250cda42a4dd..9b979d810fa127 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -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,
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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);
 }
 
 
@@ -1120,19 +1130,20 @@ 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);
@@ -1140,7 +1151,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
   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.
@@ -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());
 
diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c
index c3dbd94b2f741b..c4a55efca6f712 100644
--- a/clang/test/Preprocessor/init.c
+++ b/clang/test/Preprocessor/init.c
@@ -93,6 +93,70 @@
 // C99-NOT: __GXX_WEAK__
 // C99-NOT: __cplusplus
 //
+// RUN: %clang_cc1 -std=c17 -triple=x86_64-pc-win32 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C17-FMT %s
+// RUN: %clang_cc1 -std=c23 -triple=x86_64-pc-win32 -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

Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff a4ce870859a2d8b5ce8b92732594089e2a81b4fb eb729828e8052b14ac61a36fe1d3b3965c0ef185 -- clang/lib/Frontend/InitPreprocessor.cpp clang/test/Preprocessor/init.c
View the diff from clang-format here.
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 9b979d810f..17715121f1 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -306,7 +306,6 @@ static void DefineFastIntType(const LangOptions &LangOpts, unsigned TypeWidth,
   DefineFmt(LangOpts, Prefix + Twine(TypeWidth), Ty, TI, Builder);
 }
 
-
 /// Get the value the ATOMIC_*_LOCK_FREE macro should have for a type with
 /// the specified properties.
 static const char *getLockFreeValue(unsigned TypeWidth, const TargetInfo &TI) {

@AaronBallman AaronBallman merged commit 052ee74 into llvm:main Feb 20, 2024
@AaronBallman AaronBallman deleted the aballman-c23-binary-format-macros branch February 20, 2024 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Clang pre-defined macros for C23 binary format?
2 participants