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
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
report, and they are assumed to be safe.

View file

@ -21,13 +21,8 @@
#undef sprintf
#undef vsprintf
#ifdef HAVE_VARIADIC_MACROS
#define sprintf(...) BANNED(sprintf)
#define vsprintf(...) BANNED(vsprintf)
#else
#define sprintf(buf,fmt,arg) BANNED(sprintf)
#define vsprintf(buf,fmt,arg) BANNED(vsprintf)
#endif
#undef 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
* gcc with -Wuninitialized analysis. We restrict this trick to gcc, though,
* because some compilers may not support variadic macros. Since we're only
* trying to help gcc, anyway, it's OK; other compilers will fall back to
* using the function as usual.
* because other compilers may be confused by this.
*/
#if defined(__GNUC__)
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
/*
* 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) */
extern int BUG_exit_code;
#ifdef HAVE_VARIADIC_MACROS
__attribute__((format (printf, 3, 4))) NORETURN
void BUG_fl(const char *file, int line, const char *fmt, ...);
#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.

80
trace.c
View file

@ -108,16 +108,11 @@ static int prepare_trace_line(const char *file, int line,
gettimeofday(&tv, NULL);
secs = tv.tv_sec;
localtime_r(&secs, &tm);
strbuf_addf(buf, "%02d:%02d:%02d.%06ld ", tm.tm_hour, tm.tm_min,
tm.tm_sec, (long) tv.tv_usec);
#ifdef HAVE_VARIADIC_MACROS
/* print file:line */
strbuf_addf(buf, "%s:%d ", file, line);
strbuf_addf(buf, "%02d:%02d:%02d.%06ld %s:%d", tm.tm_hour, tm.tm_min,
tm.tm_sec, (long) tv.tv_usec, file, line);
/* align trace output (column 40 catches most files names in git) */
while (buf->len < 40)
strbuf_addch(buf, ' ');
#endif
return 1;
}
@ -229,74 +224,6 @@ static void trace_performance_vprintf_fl(const char *file, int line,
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,
const char *format, ...)
{
@ -342,9 +269,6 @@ void trace_performance_leave_fl(const char *file, int line,
va_end(ap);
}
#endif /* HAVE_VARIADIC_MACROS */
static const char *quote_crnl(const char *path)
{
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);
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
* 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__
#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
* parameter ('format' in this case). Otherwise, a call without variable
* arguments will have a surplus ','. E.g.:
@ -220,6 +158,16 @@ void trace_performance_leave(const char *format, ...);
* 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, ...) \
do { \
if (trace_pass_fl(key)) \
@ -227,8 +175,11 @@ void trace_performance_leave(const char *format, ...);
__VA_ARGS__); \
} 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, ...) \
do { \
if (trace_pass_fl(&trace_default_key)) \
@ -236,12 +187,36 @@ void trace_performance_leave(const char *format, ...);
argv, __VA_ARGS__); \
} 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) \
do { \
if (trace_pass_fl(key)) \
trace_strbuf_fl(TRACE_CONTEXT, __LINE__, key, data);\
} 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, ...) \
do { \
if (trace_pass_fl(&trace_perf_key)) \
@ -249,6 +224,18 @@ void trace_performance_leave(const char *format, ...);
__VA_ARGS__); \
} 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, ...) \
do { \
if (trace_pass_fl(&trace_perf_key)) \
@ -257,6 +244,9 @@ void trace_performance_leave(const char *format, ...);
__VA_ARGS__); \
} while (0)
/**
* trace_performance_leave(), accepts "const char *format, ...".
*/
#define trace_performance_leave(...) \
do { \
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;
}
#endif /* HAVE_VARIADIC_MACROS */
#endif /* TRACE_H */

View file

@ -641,20 +641,6 @@ void trace2_region_enter_printf_fl(const char *file, int line,
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,
const char *category, const char *label,
const struct repository *repo,
@ -717,20 +703,6 @@ void trace2_region_leave_printf_fl(const char *file, int line,
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,
const struct repository *repo, const char *key,
const char *value)
@ -826,17 +798,6 @@ void trace2_printf_fl(const char *file, int line, const char *fmt, ...)
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)
{
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 char *fmt, ...);
#ifdef HAVE_VARIADIC_MACROS
#define trace2_region_enter_printf(category, label, repo, ...) \
trace2_region_enter_printf_fl(__FILE__, __LINE__, (category), (label), \
(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
@ -442,18 +433,9 @@ void trace2_region_leave_printf_fl(const char *file, int line,
const struct repository *repo,
const char *fmt, ...);
#ifdef HAVE_VARIADIC_MACROS
#define trace2_region_leave_printf(category, label, repo, ...) \
trace2_region_leave_printf_fl(__FILE__, __LINE__, (category), (label), \
(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>.
@ -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, ...);
#ifdef HAVE_VARIADIC_MACROS
#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

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);
/* truncation via snprintf is OK here */
if (file)
snprintf(prefix, sizeof(prefix), "BUG: %s:%d: ", file, line);
else
snprintf(prefix, sizeof(prefix), "BUG: ");
snprintf(prefix, sizeof(prefix), "BUG: %s:%d: ", file, line);
vreportf(prefix, fmt, params);
@ -317,7 +314,6 @@ static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_lis
abort();
}
#ifdef HAVE_VARIADIC_MACROS
NORETURN void BUG_fl(const char *file, int line, const char *fmt, ...)
{
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);
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
void unleak_memory(const void *ptr, size_t len)