Merge branch 'ab/c99-variadic-macros'

Remove the escape hatch we added when we introduced the weather
balloon to use variadic macros unconditionally, to make it official
that we now have a hard dependency on the feature.

* ab/c99-variadic-macros:
  C99: remove hardcoded-out !HAVE_VARIADIC_MACROS code
  git-compat-util.h: clarify GCC v.s. C99-specific in comment
This commit is contained in:
Junio C Hamano 2022-03-09 13:38:24 -08:00
commit 69a3b75fa6
8 changed files with 65 additions and 246 deletions

View File

@ -217,6 +217,9 @@ For C programs:
. since mid 2017 with 512f41cf, we have been using designated . since mid 2017 with 512f41cf, we have been using designated
initializers for array (e.g. "int array[10] = { [5] = 2 }"). initializers for array (e.g. "int array[10] = { [5] = 2 }").
. since early 2021 with 765dc168882, we have been using variadic
macros, mostly for printf-like trace and debug macros.
These used to be forbidden, but we have not heard any breakage These used to be forbidden, but we have not heard any breakage
report, and they are assumed to be safe. report, and they are assumed to be safe.

View File

@ -21,13 +21,8 @@
#undef sprintf #undef sprintf
#undef vsprintf #undef vsprintf
#ifdef HAVE_VARIADIC_MACROS
#define sprintf(...) BANNED(sprintf) #define sprintf(...) BANNED(sprintf)
#define vsprintf(...) BANNED(vsprintf) #define vsprintf(...) BANNED(vsprintf)
#else
#define sprintf(buf,fmt,arg) BANNED(sprintf)
#define vsprintf(buf,fmt,arg) BANNED(vsprintf)
#endif
#undef gmtime #undef gmtime
#define gmtime(t) BANNED(gmtime) #define gmtime(t) BANNED(gmtime)

View File

@ -534,9 +534,7 @@ void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
/* /*
* Let callers be aware of the constant return value; this can help * Let callers be aware of the constant return value; this can help
* gcc with -Wuninitialized analysis. We restrict this trick to gcc, though, * gcc with -Wuninitialized analysis. We restrict this trick to gcc, though,
* because some compilers may not support variadic macros. Since we're only * because other compilers may be confused by this.
* trying to help gcc, anyway, it's OK; other compilers will fall back to
* using the function as usual.
*/ */
#if defined(__GNUC__) #if defined(__GNUC__)
static inline int const_error(void) static inline int const_error(void)
@ -1258,24 +1256,12 @@ static inline int regexec_buf(const regex_t *preg, const char *buf, size_t size,
#endif #endif
#endif #endif
/*
* This is always defined as a first step towards making the use of variadic
* macros unconditional. If it causes compilation problems on your platform,
* please report it to the Git mailing list at git@vger.kernel.org.
*/
#define HAVE_VARIADIC_MACROS 1
/* usage.c: only to be used for testing BUG() implementation (see test-tool) */ /* usage.c: only to be used for testing BUG() implementation (see test-tool) */
extern int BUG_exit_code; extern int BUG_exit_code;
#ifdef HAVE_VARIADIC_MACROS
__attribute__((format (printf, 3, 4))) NORETURN __attribute__((format (printf, 3, 4))) NORETURN
void BUG_fl(const char *file, int line, const char *fmt, ...); void BUG_fl(const char *file, int line, const char *fmt, ...);
#define BUG(...) BUG_fl(__FILE__, __LINE__, __VA_ARGS__) #define BUG(...) BUG_fl(__FILE__, __LINE__, __VA_ARGS__)
#else
__attribute__((format (printf, 1, 2))) NORETURN
void BUG(const char *fmt, ...);
#endif
/* /*
* Preserves errno, prints a message, but gives no warning for ENOENT. * Preserves errno, prints a message, but gives no warning for ENOENT.

80
trace.c
View File

@ -108,16 +108,11 @@ static int prepare_trace_line(const char *file, int line,
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
secs = tv.tv_sec; secs = tv.tv_sec;
localtime_r(&secs, &tm); localtime_r(&secs, &tm);
strbuf_addf(buf, "%02d:%02d:%02d.%06ld ", tm.tm_hour, tm.tm_min, strbuf_addf(buf, "%02d:%02d:%02d.%06ld %s:%d", tm.tm_hour, tm.tm_min,
tm.tm_sec, (long) tv.tv_usec); tm.tm_sec, (long) tv.tv_usec, file, line);
#ifdef HAVE_VARIADIC_MACROS
/* print file:line */
strbuf_addf(buf, "%s:%d ", file, line);
/* align trace output (column 40 catches most files names in git) */ /* align trace output (column 40 catches most files names in git) */
while (buf->len < 40) while (buf->len < 40)
strbuf_addch(buf, ' '); strbuf_addch(buf, ' ');
#endif
return 1; return 1;
} }
@ -229,74 +224,6 @@ static void trace_performance_vprintf_fl(const char *file, int line,
strbuf_release(&buf); strbuf_release(&buf);
} }
#ifndef HAVE_VARIADIC_MACROS
void trace_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
trace_vprintf_fl(NULL, 0, &trace_default_key, format, ap);
va_end(ap);
}
void trace_printf_key(struct trace_key *key, const char *format, ...)
{
va_list ap;
va_start(ap, format);
trace_vprintf_fl(NULL, 0, key, format, ap);
va_end(ap);
}
void trace_argv_printf(const char **argv, const char *format, ...)
{
va_list ap;
va_start(ap, format);
trace_argv_vprintf_fl(NULL, 0, argv, format, ap);
va_end(ap);
}
void trace_strbuf(struct trace_key *key, const struct strbuf *data)
{
trace_strbuf_fl(NULL, 0, key, data);
}
void trace_performance(uint64_t nanos, const char *format, ...)
{
va_list ap;
va_start(ap, format);
trace_performance_vprintf_fl(NULL, 0, nanos, format, ap);
va_end(ap);
}
void trace_performance_since(uint64_t start, const char *format, ...)
{
va_list ap;
va_start(ap, format);
trace_performance_vprintf_fl(NULL, 0, getnanotime() - start,
format, ap);
va_end(ap);
}
void trace_performance_leave(const char *format, ...)
{
va_list ap;
uint64_t since;
if (perf_indent)
perf_indent--;
if (!format) /* Allow callers to leave without tracing anything */
return;
since = perf_start_times[perf_indent];
va_start(ap, format);
trace_performance_vprintf_fl(NULL, 0, getnanotime() - since,
format, ap);
va_end(ap);
}
#else
void trace_printf_key_fl(const char *file, int line, struct trace_key *key, void trace_printf_key_fl(const char *file, int line, struct trace_key *key,
const char *format, ...) const char *format, ...)
{ {
@ -342,9 +269,6 @@ void trace_performance_leave_fl(const char *file, int line,
va_end(ap); va_end(ap);
} }
#endif /* HAVE_VARIADIC_MACROS */
static const char *quote_crnl(const char *path) static const char *quote_crnl(const char *path)
{ {
static struct strbuf new_path = STRBUF_INIT; static struct strbuf new_path = STRBUF_INIT;

128
trace.h
View File

@ -126,71 +126,6 @@ void trace_command_performance(const char **argv);
void trace_verbatim(struct trace_key *key, const void *buf, unsigned len); void trace_verbatim(struct trace_key *key, const void *buf, unsigned len);
uint64_t trace_performance_enter(void); uint64_t trace_performance_enter(void);
#ifndef HAVE_VARIADIC_MACROS
/**
* Prints a formatted message, similar to printf.
*/
__attribute__((format (printf, 1, 2)))
void trace_printf(const char *format, ...);
__attribute__((format (printf, 2, 3)))
void trace_printf_key(struct trace_key *key, const char *format, ...);
/**
* Prints a formatted message, followed by a quoted list of arguments.
*/
__attribute__((format (printf, 2, 3)))
void trace_argv_printf(const char **argv, const char *format, ...);
/**
* Prints the strbuf, without additional formatting (i.e. doesn't
* choke on `%` or even `\0`).
*/
void trace_strbuf(struct trace_key *key, const struct strbuf *data);
/**
* Prints elapsed time (in nanoseconds) if GIT_TRACE_PERFORMANCE is enabled.
*
* Example:
* ------------
* uint64_t t = 0;
* for (;;) {
* // ignore
* t -= getnanotime();
* // code section to measure
* t += getnanotime();
* // ignore
* }
* trace_performance(t, "frotz");
* ------------
*/
__attribute__((format (printf, 2, 3)))
void trace_performance(uint64_t nanos, const char *format, ...);
/**
* Prints elapsed time since 'start' if GIT_TRACE_PERFORMANCE is enabled.
*
* Example:
* ------------
* uint64_t start = getnanotime();
* // code section to measure
* trace_performance_since(start, "foobar");
* ------------
*/
__attribute__((format (printf, 2, 3)))
void trace_performance_since(uint64_t start, const char *format, ...);
__attribute__((format (printf, 1, 2)))
void trace_performance_leave(const char *format, ...);
#else
/*
* Macros to add file:line - see above for C-style declarations of how these
* should be used.
*/
/* /*
* TRACE_CONTEXT may be set to __FUNCTION__ if the compiler supports it. The * TRACE_CONTEXT may be set to __FUNCTION__ if the compiler supports it. The
* default is __FILE__, as it is consistent with assert(), and static function * default is __FILE__, as it is consistent with assert(), and static function
@ -204,7 +139,10 @@ void trace_performance_leave(const char *format, ...);
# define TRACE_CONTEXT __FILE__ # define TRACE_CONTEXT __FILE__
#endif #endif
/* /**
* Macros to add the file:line of the calling code, instead of that of
* the trace function itself.
*
* Note: with C99 variadic macros, __VA_ARGS__ must include the last fixed * Note: with C99 variadic macros, __VA_ARGS__ must include the last fixed
* parameter ('format' in this case). Otherwise, a call without variable * parameter ('format' in this case). Otherwise, a call without variable
* arguments will have a surplus ','. E.g.: * arguments will have a surplus ','. E.g.:
@ -220,6 +158,16 @@ void trace_performance_leave(const char *format, ...);
* comma, but this is non-standard. * comma, but this is non-standard.
*/ */
/**
* trace_printf(), accepts "const char *format, ...".
*
* Prints a formatted message, similar to printf.
*/
#define trace_printf(...) trace_printf_key(&trace_default_key, __VA_ARGS__)
/**
* trace_printf_key(), accepts "struct trace_key *key, const char *format, ...".
*/
#define trace_printf_key(key, ...) \ #define trace_printf_key(key, ...) \
do { \ do { \
if (trace_pass_fl(key)) \ if (trace_pass_fl(key)) \
@ -227,8 +175,11 @@ void trace_performance_leave(const char *format, ...);
__VA_ARGS__); \ __VA_ARGS__); \
} while (0) } while (0)
#define trace_printf(...) trace_printf_key(&trace_default_key, __VA_ARGS__) /**
* trace_argv_printf(), accepts "struct trace_key *key, const char *format, ...)".
*
* Prints a formatted message, followed by a quoted list of arguments.
*/
#define trace_argv_printf(argv, ...) \ #define trace_argv_printf(argv, ...) \
do { \ do { \
if (trace_pass_fl(&trace_default_key)) \ if (trace_pass_fl(&trace_default_key)) \
@ -236,12 +187,36 @@ void trace_performance_leave(const char *format, ...);
argv, __VA_ARGS__); \ argv, __VA_ARGS__); \
} while (0) } while (0)
/**
* trace_strbuf(), accepts "struct trace_key *key, const struct strbuf *data".
*
* Prints the strbuf, without additional formatting (i.e. doesn't
* choke on `%` or even `\0`).
*/
#define trace_strbuf(key, data) \ #define trace_strbuf(key, data) \
do { \ do { \
if (trace_pass_fl(key)) \ if (trace_pass_fl(key)) \
trace_strbuf_fl(TRACE_CONTEXT, __LINE__, key, data);\ trace_strbuf_fl(TRACE_CONTEXT, __LINE__, key, data);\
} while (0) } while (0)
/**
* trace_performance(), accepts "uint64_t nanos, const char *format, ...".
*
* Prints elapsed time (in nanoseconds) if GIT_TRACE_PERFORMANCE is enabled.
*
* Example:
* ------------
* uint64_t t = 0;
* for (;;) {
* // ignore
* t -= getnanotime();
* // code section to measure
* t += getnanotime();
* // ignore
* }
* trace_performance(t, "frotz");
* ------------
*/
#define trace_performance(nanos, ...) \ #define trace_performance(nanos, ...) \
do { \ do { \
if (trace_pass_fl(&trace_perf_key)) \ if (trace_pass_fl(&trace_perf_key)) \
@ -249,6 +224,18 @@ void trace_performance_leave(const char *format, ...);
__VA_ARGS__); \ __VA_ARGS__); \
} while (0) } while (0)
/**
* trace_performance_since(), accepts "uint64_t start, const char *format, ...".
*
* Prints elapsed time since 'start' if GIT_TRACE_PERFORMANCE is enabled.
*
* Example:
* ------------
* uint64_t start = getnanotime();
* // code section to measure
* trace_performance_since(start, "foobar");
* ------------
*/
#define trace_performance_since(start, ...) \ #define trace_performance_since(start, ...) \
do { \ do { \
if (trace_pass_fl(&trace_perf_key)) \ if (trace_pass_fl(&trace_perf_key)) \
@ -257,6 +244,9 @@ void trace_performance_leave(const char *format, ...);
__VA_ARGS__); \ __VA_ARGS__); \
} while (0) } while (0)
/**
* trace_performance_leave(), accepts "const char *format, ...".
*/
#define trace_performance_leave(...) \ #define trace_performance_leave(...) \
do { \ do { \
if (trace_pass_fl(&trace_perf_key)) \ if (trace_pass_fl(&trace_perf_key)) \
@ -285,6 +275,4 @@ static inline int trace_pass_fl(struct trace_key *key)
return key->fd || !key->initialized; return key->fd || !key->initialized;
} }
#endif /* HAVE_VARIADIC_MACROS */
#endif /* TRACE_H */ #endif /* TRACE_H */

View File

@ -641,20 +641,6 @@ void trace2_region_enter_printf_fl(const char *file, int line,
va_end(ap); va_end(ap);
} }
#ifndef HAVE_VARIADIC_MACROS
void trace2_region_enter_printf(const char *category, const char *label,
const struct repository *repo, const char *fmt,
...)
{
va_list ap;
va_start(ap, fmt);
trace2_region_enter_printf_va_fl(NULL, 0, category, label, repo, fmt,
ap);
va_end(ap);
}
#endif
void trace2_region_leave_printf_va_fl(const char *file, int line, void trace2_region_leave_printf_va_fl(const char *file, int line,
const char *category, const char *label, const char *category, const char *label,
const struct repository *repo, const struct repository *repo,
@ -717,20 +703,6 @@ void trace2_region_leave_printf_fl(const char *file, int line,
va_end(ap); va_end(ap);
} }
#ifndef HAVE_VARIADIC_MACROS
void trace2_region_leave_printf(const char *category, const char *label,
const struct repository *repo, const char *fmt,
...)
{
va_list ap;
va_start(ap, fmt);
trace2_region_leave_printf_va_fl(NULL, 0, category, label, repo, fmt,
ap);
va_end(ap);
}
#endif
void trace2_data_string_fl(const char *file, int line, const char *category, void trace2_data_string_fl(const char *file, int line, const char *category,
const struct repository *repo, const char *key, const struct repository *repo, const char *key,
const char *value) const char *value)
@ -826,17 +798,6 @@ void trace2_printf_fl(const char *file, int line, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
#ifndef HAVE_VARIADIC_MACROS
void trace2_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
trace2_printf_va_fl(NULL, 0, fmt, ap);
va_end(ap);
}
#endif
const char *trace2_session_id(void) const char *trace2_session_id(void)
{ {
return tr2_sid_get(); return tr2_sid_get();

View File

@ -397,18 +397,9 @@ void trace2_region_enter_printf_fl(const char *file, int line,
const struct repository *repo, const struct repository *repo,
const char *fmt, ...); const char *fmt, ...);
#ifdef HAVE_VARIADIC_MACROS
#define trace2_region_enter_printf(category, label, repo, ...) \ #define trace2_region_enter_printf(category, label, repo, ...) \
trace2_region_enter_printf_fl(__FILE__, __LINE__, (category), (label), \ trace2_region_enter_printf_fl(__FILE__, __LINE__, (category), (label), \
(repo), __VA_ARGS__) (repo), __VA_ARGS__)
#else
/* clang-format off */
__attribute__((format (region_enter_printf, 4, 5)))
void trace2_region_enter_printf(const char *category, const char *label,
const struct repository *repo, const char *fmt,
...);
/* clang-format on */
#endif
/** /**
* Emit a 'region_leave' event for <category>.<label> with optional * Emit a 'region_leave' event for <category>.<label> with optional
@ -442,18 +433,9 @@ void trace2_region_leave_printf_fl(const char *file, int line,
const struct repository *repo, const struct repository *repo,
const char *fmt, ...); const char *fmt, ...);
#ifdef HAVE_VARIADIC_MACROS
#define trace2_region_leave_printf(category, label, repo, ...) \ #define trace2_region_leave_printf(category, label, repo, ...) \
trace2_region_leave_printf_fl(__FILE__, __LINE__, (category), (label), \ trace2_region_leave_printf_fl(__FILE__, __LINE__, (category), (label), \
(repo), __VA_ARGS__) (repo), __VA_ARGS__)
#else
/* clang-format off */
__attribute__((format (region_leave_printf, 4, 5)))
void trace2_region_leave_printf(const char *category, const char *label,
const struct repository *repo, const char *fmt,
...);
/* clang-format on */
#endif
/** /**
* Emit a key-value pair 'data' event of the form <category>.<key> = <value>. * Emit a key-value pair 'data' event of the form <category>.<key> = <value>.
@ -506,14 +488,7 @@ void trace2_printf_va_fl(const char *file, int line, const char *fmt,
void trace2_printf_fl(const char *file, int line, const char *fmt, ...); void trace2_printf_fl(const char *file, int line, const char *fmt, ...);
#ifdef HAVE_VARIADIC_MACROS
#define trace2_printf(...) trace2_printf_fl(__FILE__, __LINE__, __VA_ARGS__) #define trace2_printf(...) trace2_printf_fl(__FILE__, __LINE__, __VA_ARGS__)
#else
/* clang-format off */
__attribute__((format (printf, 1, 2)))
void trace2_printf(const char *fmt, ...);
/* clang-format on */
#endif
/* /*
* Optional platform-specific code to dump information about the * Optional platform-specific code to dump information about the

15
usage.c
View File

@ -299,10 +299,7 @@ static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_lis
va_copy(params_copy, params); va_copy(params_copy, params);
/* truncation via snprintf is OK here */ /* truncation via snprintf is OK here */
if (file) snprintf(prefix, sizeof(prefix), "BUG: %s:%d: ", file, line);
snprintf(prefix, sizeof(prefix), "BUG: %s:%d: ", file, line);
else
snprintf(prefix, sizeof(prefix), "BUG: ");
vreportf(prefix, fmt, params); vreportf(prefix, fmt, params);
@ -317,7 +314,6 @@ static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_lis
abort(); abort();
} }
#ifdef HAVE_VARIADIC_MACROS
NORETURN void BUG_fl(const char *file, int line, const char *fmt, ...) NORETURN void BUG_fl(const char *file, int line, const char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -325,15 +321,6 @@ NORETURN void BUG_fl(const char *file, int line, const char *fmt, ...)
BUG_vfl(file, line, fmt, ap); BUG_vfl(file, line, fmt, ap);
va_end(ap); va_end(ap);
} }
#else
NORETURN void BUG(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
BUG_vfl(NULL, 0, fmt, ap);
va_end(ap);
}
#endif
#ifdef SUPPRESS_ANNOTATED_LEAKS #ifdef SUPPRESS_ANNOTATED_LEAKS
void unleak_memory(const void *ptr, size_t len) void unleak_memory(const void *ptr, size_t len)