Skip to content

Commit bf7d997

Browse files
committed
Support the *_WIDTH macros in limits.h and stdint.h
This completes the implementation of WG14 N2412 (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2412.pdf), which standardizes C on a twos complement representation for integer types. The only work that remained there was to define the correct macros in the standard headers, which this patch does.
1 parent 7b9f5cb commit bf7d997

File tree

9 files changed

+562
-30
lines changed

9 files changed

+562
-30
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ C Language Changes in Clang
165165
`this thread <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103640>` for more
166166
info.
167167

168+
- Implemented `WG14 N2412 <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2412.pdf>`_,
169+
which adds ``*_WIDTH`` macros to limits.h and stdint.h to report the bit
170+
width of various integer datatypes.
171+
168172
C++ Language Changes in Clang
169173
-----------------------------
170174

clang/lib/Frontend/InitPreprocessor.cpp

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ static void DefineType(const Twine &MacroName, TargetInfo::IntType Ty,
194194
Builder.defineMacro(MacroName, TargetInfo::getTypeName(Ty));
195195
}
196196

197-
static void DefineTypeWidth(StringRef MacroName, TargetInfo::IntType Ty,
197+
static void DefineTypeWidth(const Twine &MacroName, TargetInfo::IntType Ty,
198198
const TargetInfo &TI, MacroBuilder &Builder) {
199199
Builder.defineMacro(MacroName, Twine(TI.getTypeWidth(Ty)));
200200
}
@@ -205,6 +205,16 @@ static void DefineTypeSizeof(StringRef MacroName, unsigned BitWidth,
205205
Twine(BitWidth / TI.getCharWidth()));
206206
}
207207

208+
// This will generate a macro based on the prefix with `_MAX__` as the suffix
209+
// for the max value representable for the type, and a macro with a `_WIDTH__`
210+
// suffix for the width of the type.
211+
static void DefineTypeSizeAndWidth(const Twine &Prefix, TargetInfo::IntType Ty,
212+
const TargetInfo &TI,
213+
MacroBuilder &Builder) {
214+
DefineTypeSize(Prefix + "_MAX__", Ty, TI, Builder);
215+
DefineTypeWidth(Prefix + "_WIDTH__", Ty, TI, Builder);
216+
}
217+
208218
static void DefineExactWidthIntType(TargetInfo::IntType Ty,
209219
const TargetInfo &TI,
210220
MacroBuilder &Builder) {
@@ -241,6 +251,8 @@ static void DefineExactWidthIntTypeSize(TargetInfo::IntType Ty,
241251
if (TypeWidth == 64)
242252
Ty = IsSigned ? TI.getInt64Type() : TI.getUInt64Type();
243253

254+
// We don't need to define a _WIDTH macro for the exact-width types because
255+
// we already know the width.
244256
const char *Prefix = IsSigned ? "__INT" : "__UINT";
245257
DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
246258
}
@@ -254,7 +266,12 @@ static void DefineLeastWidthIntType(unsigned TypeWidth, bool IsSigned,
254266

255267
const char *Prefix = IsSigned ? "__INT_LEAST" : "__UINT_LEAST";
256268
DefineType(Prefix + Twine(TypeWidth) + "_TYPE__", Ty, Builder);
257-
DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
269+
// We only want the *_WIDTH macro for the signed types to avoid too many
270+
// predefined macros (the unsigned width and the signed width are identical.)
271+
if (IsSigned)
272+
DefineTypeSizeAndWidth(Prefix + Twine(TypeWidth), Ty, TI, Builder);
273+
else
274+
DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
258275
DefineFmt(Prefix + Twine(TypeWidth), Ty, TI, Builder);
259276
}
260277

@@ -268,8 +285,12 @@ static void DefineFastIntType(unsigned TypeWidth, bool IsSigned,
268285

269286
const char *Prefix = IsSigned ? "__INT_FAST" : "__UINT_FAST";
270287
DefineType(Prefix + Twine(TypeWidth) + "_TYPE__", Ty, Builder);
271-
DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
272-
288+
// We only want the *_WIDTH macro for the signed types to avoid too many
289+
// predefined macros (the unsigned width and the signed width are identical.)
290+
if (IsSigned)
291+
DefineTypeSizeAndWidth(Prefix + Twine(TypeWidth), Ty, TI, Builder);
292+
else
293+
DefineTypeSize(Prefix + Twine(TypeWidth) + "_MAX__", Ty, TI, Builder);
273294
DefineFmt(Prefix + Twine(TypeWidth), Ty, TI, Builder);
274295
}
275296

@@ -887,20 +908,26 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
887908
assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far");
888909
Builder.defineMacro("__CHAR_BIT__", Twine(TI.getCharWidth()));
889910

911+
Builder.defineMacro("__BOOL_WIDTH__", Twine(TI.getBoolWidth()));
912+
Builder.defineMacro("__SHRT_WIDTH__", Twine(TI.getShortWidth()));
913+
Builder.defineMacro("__INT_WIDTH__", Twine(TI.getIntWidth()));
914+
Builder.defineMacro("__LONG_WIDTH__", Twine(TI.getLongWidth()));
915+
Builder.defineMacro("__LLONG_WIDTH__", Twine(TI.getLongLongWidth()));
916+
890917
DefineTypeSize("__SCHAR_MAX__", TargetInfo::SignedChar, TI, Builder);
891918
DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Builder);
892919
DefineTypeSize("__INT_MAX__", TargetInfo::SignedInt, TI, Builder);
893920
DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Builder);
894921
DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Builder);
895-
DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Builder);
896-
DefineTypeSize("__WINT_MAX__", TI.getWIntType(), TI, Builder);
897-
DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Builder);
898-
DefineTypeSize("__SIZE_MAX__", TI.getSizeType(), TI, Builder);
922+
DefineTypeSizeAndWidth("__WCHAR", TI.getWCharType(), TI, Builder);
923+
DefineTypeSizeAndWidth("__WINT", TI.getWIntType(), TI, Builder);
924+
DefineTypeSizeAndWidth("__INTMAX", TI.getIntMaxType(), TI, Builder);
925+
DefineTypeSizeAndWidth("__SIZE", TI.getSizeType(), TI, Builder);
899926

900-
DefineTypeSize("__UINTMAX_MAX__", TI.getUIntMaxType(), TI, Builder);
901-
DefineTypeSize("__PTRDIFF_MAX__", TI.getPtrDiffType(0), TI, Builder);
902-
DefineTypeSize("__INTPTR_MAX__", TI.getIntPtrType(), TI, Builder);
903-
DefineTypeSize("__UINTPTR_MAX__", TI.getUIntPtrType(), TI, Builder);
927+
DefineTypeSizeAndWidth("__UINTMAX", TI.getUIntMaxType(), TI, Builder);
928+
DefineTypeSizeAndWidth("__PTRDIFF", TI.getPtrDiffType(0), TI, Builder);
929+
DefineTypeSizeAndWidth("__INTPTR", TI.getIntPtrType(), TI, Builder);
930+
DefineTypeSizeAndWidth("__UINTPTR", TI.getUIntPtrType(), TI, Builder);
904931

905932
DefineTypeSizeof("__SIZEOF_DOUBLE__", TI.getDoubleWidth(), TI, Builder);
906933
DefineTypeSizeof("__SIZEOF_FLOAT__", TI.getFloatWidth(), TI, Builder);
@@ -929,29 +956,29 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
929956
DefineFmt("__UINTMAX", TI.getUIntMaxType(), TI, Builder);
930957
Builder.defineMacro("__UINTMAX_C_SUFFIX__",
931958
TI.getTypeConstantSuffix(TI.getUIntMaxType()));
932-
DefineTypeWidth("__INTMAX_WIDTH__", TI.getIntMaxType(), TI, Builder);
933959
DefineType("__PTRDIFF_TYPE__", TI.getPtrDiffType(0), Builder);
934960
DefineFmt("__PTRDIFF", TI.getPtrDiffType(0), TI, Builder);
935-
DefineTypeWidth("__PTRDIFF_WIDTH__", TI.getPtrDiffType(0), TI, Builder);
936961
DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Builder);
937962
DefineFmt("__INTPTR", TI.getIntPtrType(), TI, Builder);
938-
DefineTypeWidth("__INTPTR_WIDTH__", TI.getIntPtrType(), TI, Builder);
939963
DefineType("__SIZE_TYPE__", TI.getSizeType(), Builder);
940964
DefineFmt("__SIZE", TI.getSizeType(), TI, Builder);
941-
DefineTypeWidth("__SIZE_WIDTH__", TI.getSizeType(), TI, Builder);
942965
DefineType("__WCHAR_TYPE__", TI.getWCharType(), Builder);
943-
DefineTypeWidth("__WCHAR_WIDTH__", TI.getWCharType(), TI, Builder);
944966
DefineType("__WINT_TYPE__", TI.getWIntType(), Builder);
945-
DefineTypeWidth("__WINT_WIDTH__", TI.getWIntType(), TI, Builder);
946-
DefineTypeWidth("__SIG_ATOMIC_WIDTH__", TI.getSigAtomicType(), TI, Builder);
947-
DefineTypeSize("__SIG_ATOMIC_MAX__", TI.getSigAtomicType(), TI, Builder);
967+
DefineTypeSizeAndWidth("__SIG_ATOMIC", TI.getSigAtomicType(), TI, Builder);
948968
DefineType("__CHAR16_TYPE__", TI.getChar16Type(), Builder);
949969
DefineType("__CHAR32_TYPE__", TI.getChar32Type(), Builder);
950970

951-
DefineTypeWidth("__UINTMAX_WIDTH__", TI.getUIntMaxType(), TI, Builder);
952971
DefineType("__UINTPTR_TYPE__", TI.getUIntPtrType(), Builder);
953972
DefineFmt("__UINTPTR", TI.getUIntPtrType(), TI, Builder);
954-
DefineTypeWidth("__UINTPTR_WIDTH__", TI.getUIntPtrType(), TI, Builder);
973+
974+
// The C standard requires the width of uintptr_t and intptr_t to be the same,
975+
// per 7.20.2.4p1. Same for intmax_t and uintmax_t, per 7.20.2.5p1.
976+
assert(TI.getTypeWidth(TI.getUIntPtrType()) ==
977+
TI.getTypeWidth(TI.getIntPtrType()) &&
978+
"uintptr_t and intptr_t have different widths?");
979+
assert(TI.getTypeWidth(TI.getUIntMaxType()) ==
980+
TI.getTypeWidth(TI.getIntMaxType()) &&
981+
"uintmax_t and intmax_t have different widths?");
955982

956983
if (TI.hasFloat16Type())
957984
DefineFloatMacros(Builder, "FLT16", &TI.getHalfFormat(), "F16");

clang/lib/Headers/limits.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,24 @@
6262

6363
#define CHAR_BIT __CHAR_BIT__
6464

65+
/* C2x 5.2.4.2.1 */
66+
/* FIXME: This is using the placeholder dates Clang produces for these macros
67+
in C2x mode; switch to the correct values once they've been published. */
68+
#if __STDC_VERSION__ >= 202000L
69+
#define BOOL_WIDTH __BOOL_WIDTH__
70+
#define CHAR_WIDTH CHAR_BIT
71+
#define SCHAR_WIDTH CHAR_BIT
72+
#define UCHAR_WIDTH CHAR_BIT
73+
#define USHRT_WIDTH __SHRT_WIDTH__
74+
#define SHRT_WIDTH __SHRT_WIDTH__
75+
#define UINT_WIDTH __INT_WIDTH__
76+
#define INT_WIDTH __INT_WIDTH__
77+
#define ULONG_WIDTH __LONG_WIDTH__
78+
#define LONG_WIDTH __LONG_WIDTH__
79+
#define ULLONG_WIDTH __LLONG_WIDTH__
80+
#define LLONG_WIDTH __LLONG_WIDTH__
81+
#endif
82+
6583
#ifdef __CHAR_UNSIGNED__ /* -funsigned-char */
6684
#define CHAR_MIN 0
6785
#define CHAR_MAX UCHAR_MAX

0 commit comments

Comments
 (0)