summaryrefslogtreecommitdiff
path: root/src/util.h
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2017-11-18 15:43:11 +0000
committerPatrick Steinhardt <ps@pks.im>2017-11-18 16:06:14 +0000
commit585b5dacc7f440a163c20117cfa35fb714a7ba7b (patch)
tree7a693d3d5baf786a2497d7d80babfe597aa48ecb /src/util.h
parentfd1492e82783159231d046beb22a20d17029bc61 (diff)
downloadlibgit2-585b5dacc7f440a163c20117cfa35fb714a7ba7b.tar.gz
refcount: make refcounting conform to aliasing rules
Strict aliasing rules dictate that for most data types, you are not allowed to cast them to another data type and then access the casted pointers. While this works just fine for most compilers, technically we end up in undefined behaviour when we hurt that rule. Our current refcounting code makes heavy use of casting and thus violates that rule. While we didn't have any problems with that code, Travis started spitting out a lot of warnings due to a change in their toolchain. In the refcounting case, the code is also easy to fix: as all refcounting-statements are actually macros, we can just access the `rc` field directly instead of casting. There are two outliers in our code where that doesn't work. Both the `git_diff` and `git_patch` structures have specializations for generated and parsed diffs/patches, which directly inherit from them. Because of that, the refcounting code is only part of the base structure and not of the children themselves. We can help that by instead passing their base into `GIT_REFCOUNT_INC`, though.
Diffstat (limited to 'src/util.h')
-rw-r--r--src/util.h10
1 files changed, 5 insertions, 5 deletions
diff --git a/src/util.h b/src/util.h
index b85e03b6d..7c9a54ff1 100644
--- a/src/util.h
+++ b/src/util.h
@@ -297,22 +297,22 @@ typedef struct {
typedef void (*git_refcount_freeptr)(void *r);
#define GIT_REFCOUNT_INC(r) { \
- git_atomic_inc(&((git_refcount *)(r))->refcount); \
+ git_atomic_inc(&(r)->rc.refcount); \
}
#define GIT_REFCOUNT_DEC(_r, do_free) { \
- git_refcount *r = (git_refcount *)(_r); \
+ git_refcount *r = &(_r)->rc; \
int val = git_atomic_dec(&r->refcount); \
if (val <= 0 && r->owner == NULL) { do_free(_r); } \
}
#define GIT_REFCOUNT_OWN(r, o) { \
- ((git_refcount *)(r))->owner = o; \
+ (r)->rc.owner = o; \
}
-#define GIT_REFCOUNT_OWNER(r) (((git_refcount *)(r))->owner)
+#define GIT_REFCOUNT_OWNER(r) ((r)->rc.owner)
-#define GIT_REFCOUNT_VAL(r) git_atomic_get(&((git_refcount *)(r))->refcount)
+#define GIT_REFCOUNT_VAL(r) git_atomic_get((r)->rc.refcount)
static signed char from_hex[] = {