@@ -460,14 +460,6 @@ typedef unsigned long uintmax_t;
# define ckd_mul(r, a, b) __builtin_mul_overflow(a, b, r)
#endif
-#if 3 <= __GNUC__
-# define ATTRIBUTE_MALLOC __attribute__((malloc))
-# define ATTRIBUTE_FORMAT(spec) __attribute__((format spec))
-#else
-# define ATTRIBUTE_MALLOC /* empty */
-# define ATTRIBUTE_FORMAT(spec) /* empty */
-#endif
-
#if (defined __has_c_attribute \
&& (202311 <= __STDC_VERSION__ || !defined __STRICT_ANSI__))
# define HAVE___HAS_C_ATTRIBUTE true
@@ -535,11 +527,7 @@ typedef unsigned long uintmax_t;
# endif
#endif
#ifndef ATTRIBUTE_REPRODUCIBLE
-# if 3 <= __GNUC__
-# define ATTRIBUTE_REPRODUCIBLE __attribute__((pure))
-# else
-# define ATTRIBUTE_REPRODUCIBLE /* empty */
-# endif
+# define ATTRIBUTE_REPRODUCIBLE /* empty */
#endif
#if HAVE___HAS_C_ATTRIBUTE
@@ -548,11 +536,22 @@ typedef unsigned long uintmax_t;
# endif
#endif
#ifndef ATTRIBUTE_UNSEQUENCED
-# if 3 <= __GNUC__
-# define ATTRIBUTE_UNSEQUENCED __attribute__((const))
-# else
-# define ATTRIBUTE_UNSEQUENCED /* empty */
-# endif
+# define ATTRIBUTE_UNSEQUENCED /* empty */
+#endif
+
+/* __attribute__((const)) is stricter than [[unsequenced]] and
+ __attribute__((pure)) is stricter than [[reproducible]],
+ so the latter are adequate substitutes in non-GCC C23 platforms. */
+#if __GNUC__ < 3
+# define ATTRIBUTE_CONST ATTRIBUTE_UNSEQUENCED
+# define ATTRIBUTE_FORMAT(spec) /* empty */
+# define ATTRIBUTE_MALLOC /* empty */
+# define ATTRIBUTE_PURE ATTRIBUTE_REPRODUCIBLE
+#else
+# define ATTRIBUTE_CONST __attribute__((const))
+# define ATTRIBUTE_FORMAT(spec) __attribute__((format spec))
+# define ATTRIBUTE_MALLOC __attribute__((malloc))
+# define ATTRIBUTE_PURE __attribute__((pure))
#endif
#if (__STDC_VERSION__ < 199901 && !defined restrict \
@@ -682,7 +681,7 @@ DEPRECATED_IN_C23 char *asctime(struct tm const *);
char *asctime_r(struct tm const *restrict, char *restrict);
DEPRECATED_IN_C23 char *ctime(time_t const *);
char *ctime_r(time_t const *, char *);
-ATTRIBUTE_UNSEQUENCED double difftime(time_t, time_t);
+ATTRIBUTE_CONST double difftime(time_t, time_t);
size_t strftime(char *restrict, size_t, char const *restrict,
struct tm const *restrict);
# if HAVE_STRFTIME_L
@@ -798,10 +797,10 @@ timezone_t tzalloc(char const *);
void tzfree(timezone_t);
# if STD_INSPIRED
# if TZ_TIME_T || !defined posix2time_z
-ATTRIBUTE_REPRODUCIBLE time_t posix2time_z(timezone_t, time_t);
+ATTRIBUTE_PURE time_t posix2time_z(timezone_t, time_t);
# endif
# if TZ_TIME_T || !defined time2posix_z
-ATTRIBUTE_REPRODUCIBLE time_t time2posix_z(timezone_t, time_t);
+ATTRIBUTE_PURE time_t time2posix_z(timezone_t, time_t);
# endif
# endif
#endif
@@ -89,7 +89,7 @@ static bool warned;
static bool errout;
static char const *abbr(struct tm const *);
-ATTRIBUTE_REPRODUCIBLE static intmax_t delta(struct tm *, struct tm *);
+ATTRIBUTE_PURE static intmax_t delta(struct tm *, struct tm *);
static void dumptime(struct tm const *);
static time_t hunt(timezone_t, time_t, time_t, bool);
static void show(timezone_t, char *, time_t, bool);
@@ -97,7 +97,7 @@ static void showextrema(timezone_t, char *, time_t, struct tm *, time_t);
static void showtrans(char const *, struct tm const *, time_t, char const *,
char const *);
static const char *tformat(void);
-ATTRIBUTE_REPRODUCIBLE static time_t yeartot(intmax_t);
+ATTRIBUTE_PURE static time_t yeartot(intmax_t);
/* Is C an ASCII digit? */
static bool
@@ -134,7 +134,7 @@ size_overflow(void)
/* Return A + B, exiting if the result would overflow either ptrdiff_t
or size_t. A and B are both nonnegative. */
-ATTRIBUTE_REPRODUCIBLE static ptrdiff_t
+ATTRIBUTE_PURE static ptrdiff_t
sumsize(ptrdiff_t a, ptrdiff_t b)
{
#ifdef ckd_add
@@ -470,7 +470,7 @@ size_overflow(void)
memory_exhausted(_("size overflow"));
}
-ATTRIBUTE_REPRODUCIBLE static ptrdiff_t
+ATTRIBUTE_PURE static ptrdiff_t
size_sum(size_t a, size_t b)
{
#ifdef ckd_add
@@ -484,7 +484,7 @@ size_sum(size_t a, size_t b)
size_overflow();
}
-ATTRIBUTE_REPRODUCIBLE static ptrdiff_t
+ATTRIBUTE_PURE static ptrdiff_t
size_product(ptrdiff_t nitems, ptrdiff_t itemsize)
{
#ifdef ckd_mul
@@ -499,7 +499,7 @@ size_product(ptrdiff_t nitems, ptrdiff_t itemsize)
size_overflow();
}
-ATTRIBUTE_REPRODUCIBLE static ptrdiff_t
+ATTRIBUTE_PURE static ptrdiff_t
align_to(ptrdiff_t size, ptrdiff_t alignment)
{
ptrdiff_t lo_bits = alignment - 1, sum = size_sum(size, lo_bits);
@@ -1435,7 +1435,7 @@ relname(char const *target, char const *linkname)
/* Return true if A and B must have the same parent dir if A and B exist.
Return false if this is not necessarily true (though it might be true).
Keep it simple, and do not inspect the file system. */
-static bool
+ATTRIBUTE_PURE static bool
same_parent_dirs(char const *a, char const *b)
{
for (; *a == *b; a++, b++)
@@ -3627,7 +3627,7 @@ lowerit(char a)
}
/* case-insensitive equality */
-ATTRIBUTE_REPRODUCIBLE static bool
+ATTRIBUTE_PURE static bool
ciequal(register const char *ap, register const char *bp)
{
while (lowerit(*ap) == lowerit(*bp++))
@@ -3636,7 +3636,7 @@ ciequal(register const char *ap, register const char *bp)
return false;
}
-ATTRIBUTE_REPRODUCIBLE static bool
+ATTRIBUTE_PURE static bool
itsabbr(register const char *abbr, register const char *word)
{
if (lowerit(*abbr) != lowerit(*word))
@@ -3652,7 +3652,7 @@ itsabbr(register const char *abbr, register const char *word)
/* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */
-ATTRIBUTE_REPRODUCIBLE static bool
+ATTRIBUTE_PURE static bool
ciprefix(char const *abbr, char const *word)
{
do
@@ -3762,7 +3762,7 @@ time_overflow(void)
exit(EXIT_FAILURE);
}
-ATTRIBUTE_REPRODUCIBLE static zic_t
+ATTRIBUTE_PURE static zic_t
oadd(zic_t t1, zic_t t2)
{
#ifdef ckd_add
@@ -3776,7 +3776,7 @@ oadd(zic_t t1, zic_t t2)
time_overflow();
}
-ATTRIBUTE_REPRODUCIBLE static zic_t
+ATTRIBUTE_PURE static zic_t
tadd(zic_t t1, zic_t t2)
{
#ifdef ckd_add