make error()'s constant return value more visible
authorJeff King <peff@peff.net>
Sat, 15 Dec 2012 17:37:36 +0000 (12:37 -0500)
committerJunio C Hamano <gitster@pobox.com>
Sat, 15 Dec 2012 18:45:58 +0000 (10:45 -0800)
commite208f9cc7574f5980faba498d0aa30b4defeb34f
tree839e808a152da9e260644aa07ad6dcb5f98be4d4
parentbfae342c973b0be3c9e99d3d86ed2e6b152b4a6b
make error()'s constant return value more visible

When git is compiled with "gcc -Wuninitialized -O3", some
inlined calls provide an additional opportunity for the
compiler to do static analysis on variable initialization.
For example, with two functions like this:

  int get_foo(int *foo)
  {
if (something_that_might_fail() < 0)
return error("unable to get foo");
*foo = 0;
return 0;
  }

  void some_fun(void)
  {
  int foo;
  if (get_foo(&foo) < 0)
  return -1;
  printf("foo is %d\n", foo);
  }

If get_foo() is not inlined, then when compiling some_fun,
gcc sees only that a pointer to the local variable is
passed, and must assume that it is an out parameter that
is initialized after get_foo returns.

However, when get_foo() is inlined, the compiler may look at
all of the code together and see that some code paths in
get_foo() do not initialize the variable. As a result, it
prints a warning. But what the compiler can't see is that
error() always returns -1, and therefore we know that either
we return early from some_fun, or foo ends up initialized,
and the code is safe.  The warning is a false positive.

If we can make the compiler aware that error() will always
return -1, it can do a better job of analysis. The simplest
method would be to inline the error() function. However,
this doesn't work, because gcc will not inline a variadc
function. We can work around this by defining a macro. This
relies on two gcc extensions:

  1. Variadic macros (these are present in C99, but we do
     not rely on that).

  2. Gcc treats the "##" paste operator specially between a
     comma and __VA_ARGS__, which lets our variadic macro
     work even if no format parameters are passed to
     error().

Since we are using these extra features, we hide the macro
behind an #ifdef. This is OK, though, because our goal was
just to help gcc.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git-compat-util.h
usage.c