From 474155f32a871dacff7e2c2e737155bb354ba46c Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 8 Nov 2016 16:39:44 +0100 Subject: [PATCH] Really work around "uninitialized value" warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ever since 457f08a (git-rev-list: add --bisect-vars option., 2007-03-21), Git's source code uses the following trick to fool GCC into *not* warning about uninitialized values: int value = value; We use this trick to silence the "warning: ‘x’ is used uninitialized in this function [-Wuninitialized]" when the variables are not really used uninitialized (but it is hard for the compiler to determine that). This trick works well for GCC, and even Clang seems to appease that workaround. Not so Visual C. It does realize that this is just a trick to fool it, and it simply refuses to be fooled. The only way to silence the warning for Visual C would be to write something like this: #pragma warning(suppress: 4700) int value; Obviously this is not portable, and neither is that trick that fools GCC. So let's just introduce a new macro that continues to fool GCC, but simply initializes the values everywhere else. Signed-off-by: Johannes Schindelin --- builtin/rev-list.c | 3 ++- fast-import.c | 4 ++-- git-compat-util.h | 17 +++++++++++++++++ merge-recursive.c | 2 +- read-cache.c | 2 +- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/builtin/rev-list.c b/builtin/rev-list.c index d5345b6a2e..49325f6f05 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -479,7 +479,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) mark_edges_uninteresting(&revs, show_edge); if (bisect_list) { - int reaches = reaches, all = all; + FAKE_INIT(int, reaches, 0); + FAKE_INIT(int, all, 0); find_bisection(&revs.commits, &reaches, &all, bisect_find_all); diff --git a/fast-import.c b/fast-import.c index b70ac025e0..04023e7c5f 100644 --- a/fast-import.c +++ b/fast-import.c @@ -3003,7 +3003,7 @@ static void cat_blob(struct object_entry *oe, struct object_id *oid) static void parse_get_mark(const char *p) { - struct object_entry *oe = oe; + FAKE_INIT(struct object_entry *, oe, NULL); char output[GIT_MAX_HEXSZ + 2]; /* get-mark SP LF */ @@ -3020,7 +3020,7 @@ static void parse_get_mark(const char *p) static void parse_cat_blob(const char *p) { - struct object_entry *oe = oe; + FAKE_INIT(struct object_entry *, oe, NULL); struct object_id oid; /* cat-blob SP LF */ diff --git a/git-compat-util.h b/git-compat-util.h index bbd92a8627..6069a4bffb 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -51,6 +51,23 @@ #endif #endif +/* + * Under certain circumstances Git's source code is cleverer than the C + * compiler when the latter warns about some "uninitialized value", e.g. when + * a value is both initialized and used under the same condition. + * + * GCC can be fooled to not spit out this warning by using the construct: + * "int value = value;". Other C compilers are not that easily fooled and would + * require a #pragma (which is not portable, and would litter the source code). + * + * To keep things simple, we only fool GCC, and initialize such values instead + * when compiling with other C compilers. + */ +#ifdef __GNUC__ +#define FAKE_INIT(a, b, c) a b = b +#else +#define FAKE_INIT(a, b, c) a b = c +#endif /* * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. diff --git a/merge-recursive.c b/merge-recursive.c index cc5fa0a949..12c968eeaa 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -2070,7 +2070,7 @@ int merge_recursive(struct merge_options *o, { struct commit_list *iter; struct commit *merged_common_ancestors; - struct tree *mrtree = mrtree; + FAKE_INIT(struct tree *, mrtree, NULL); int clean; if (show(o, 4)) { diff --git a/read-cache.c b/read-cache.c index 2eb81a66b9..85e5414777 100644 --- a/read-cache.c +++ b/read-cache.c @@ -2104,7 +2104,7 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce, struct strbuf *previous_name, struct ondisk_cache_entry *ondisk) { int size; - int saved_namelen = saved_namelen; /* compiler workaround */ + FAKE_INIT(int, saved_namelen, 0); int result; static unsigned char padding[8] = { 0x00 };