On Fri, Mar 10, 2017 at 01:14:16AM +0100, René Scharfe wrote:

> >   2. Ones which just copy a single object, like:
> > 
> >        memcpy(&dst, &src, sizeof(dst));
> > 
> >      Perhaps we should be using struct assignment like:
> > 
> >        dst = src;
> > 
> >      here. It's safer and it should give the compiler more room to
> >      optimize. The only downside is that if you have pointers, it is
> >      easy to write "dst = src" when you meant "*dst = *src".
> 
> Compilers can usually inline memcpy(3) calls, but assignments are
> shorter and more pleasing to the eye, and we get a type check for
> free.  How about this?

Yeah, I mostly wasn't sure how people felt about "shorter and more
pleasing". It _is_ shorter and there's less to get wrong. But the
memcpy() screams "hey, I am making a copy" and is idiomatic to at least
a certain generation of C programmers.

I guess something like COPY(dst, src) removes the part that you can get
wrong, while still screaming copy. It's not idiomatic either, but at
least it stands out. I dunno.

> diff --git a/contrib/coccinelle/copy.cocci b/contrib/coccinelle/copy.cocci
> new file mode 100644
> index 0000000000..f0d883932a
> --- /dev/null
> +++ b/contrib/coccinelle/copy.cocci
> @@ -0,0 +1,31 @@
> +@@
> +type T;
> +T dst;
> +T src;
> [...]
> +type T;
> +T dst;
> +T *src;

I think this misses the other two cases: (*dst, src) and (*dst, *src).

Perhaps squash this in?

---
 builtin/blame.c               |  2 +-
 builtin/pack-redundant.c      |  4 ++--
 contrib/coccinelle/copy.cocci | 32 ++++++++++++++++++++++++++++++++
 diff.c                        |  4 ++--
 dir.c                         |  2 +-
 fast-import.c                 |  6 +++---
 line-log.c                    |  2 +-
 7 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/builtin/blame.c b/builtin/blame.c
index f7aa95f4b..d0d917b37 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -680,7 +680,7 @@ static void dup_entry(struct blame_entry ***queue,
 {
        origin_incref(src->suspect);
        origin_decref(dst->suspect);
-       memcpy(dst, src, sizeof(*src));
+       *dst = *src;
        dst->next = **queue;
        **queue = dst;
        *queue = &dst->next;
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index 72c815844..ac1d8111e 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -207,7 +207,7 @@ static inline struct pack_list * pack_list_insert(struct 
pack_list **pl,
                                           struct pack_list *entry)
 {
        struct pack_list *p = xmalloc(sizeof(struct pack_list));
-       memcpy(p, entry, sizeof(struct pack_list));
+       *p = *entry;
        p->next = *pl;
        *pl = p;
        return p;
@@ -451,7 +451,7 @@ static void minimize(struct pack_list **min)
                while (perm) {
                        if (is_superset(perm->pl, missing)) {
                                new_perm = xmalloc(sizeof(struct pll));
-                               memcpy(new_perm, perm, sizeof(struct pll));
+                               *new_perm = *perm;
                                new_perm->next = perm_ok;
                                perm_ok = new_perm;
                        }
diff --git a/contrib/coccinelle/copy.cocci b/contrib/coccinelle/copy.cocci
index f0d883932..da9969c84 100644
--- a/contrib/coccinelle/copy.cocci
+++ b/contrib/coccinelle/copy.cocci
@@ -29,3 +29,35 @@ T *src;
 - memcpy(&dst, src, sizeof(T));
 + dst = *src;
 )
+
+@@
+type T;
+T *dst;
+T src;
+@@
+(
+- memcpy(dst, &src, sizeof(*dst));
++ *dst = src;
+|
+- memcpy(dst, &src, sizeof(src));
++ *dst = src;
+|
+- memcpy(dst, &src, sizeof(T));
++ *dst = src;
+)
+
+@@
+type T;
+T *dst;
+T *src;
+@@
+(
+- memcpy(dst, src, sizeof(*dst));
++ *dst = *src;
+|
+- memcpy(dst, src, sizeof(*src));
++ *dst = *src;
+|
+- memcpy(dst, src, sizeof(T));
++ *dst = *src;
+)
diff --git a/diff.c b/diff.c
index 051761be4..fbd68ecd0 100644
--- a/diff.c
+++ b/diff.c
@@ -1169,7 +1169,7 @@ static void init_diff_words_data(struct emit_callback 
*ecbdata,
 {
        int i;
        struct diff_options *o = xmalloc(sizeof(struct diff_options));
-       memcpy(o, orig_opts, sizeof(struct diff_options));
+       *o = *orig_opts;
 
        ecbdata->diff_words =
                xcalloc(1, sizeof(struct diff_words_data));
@@ -3359,7 +3359,7 @@ static void run_checkdiff(struct diff_filepair *p, struct 
diff_options *o)
 
 void diff_setup(struct diff_options *options)
 {
-       memcpy(options, &default_diff_options, sizeof(*options));
+       *options = default_diff_options;
 
        options->file = stdout;
 
diff --git a/dir.c b/dir.c
index 4541f9e14..d3d0039bf 100644
--- a/dir.c
+++ b/dir.c
@@ -2499,7 +2499,7 @@ static int read_one_dir(struct untracked_cache_dir 
**untracked_,
        if (next > rd->end)
                return -1;
        *untracked_ = untracked = xmalloc(st_add(sizeof(*untracked), len));
-       memcpy(untracked, &ud, sizeof(ud));
+       *untracked = ud;
        memcpy(untracked->name, data, len + 1);
        data = next;
 
diff --git a/fast-import.c b/fast-import.c
index 6c13472c4..3e294c2b5 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -875,7 +875,7 @@ static struct tree_content *dup_tree_content(struct 
tree_content *s)
        for (i = 0; i < s->entry_count; i++) {
                a = s->entries[i];
                b = new_tree_entry();
-               memcpy(b, a, sizeof(*a));
+               *b = *a;
                if (a->tree && is_null_sha1(b->versions[1].sha1))
                        b->tree = dup_tree_content(a->tree);
                else
@@ -1685,7 +1685,7 @@ static int tree_content_remove(
 
 del_entry:
        if (backup_leaf)
-               memcpy(backup_leaf, e, sizeof(*backup_leaf));
+               *backup_leaf = *e;
        else if (e->tree)
                release_tree_content_recursive(e->tree);
        e->tree = NULL;
@@ -1735,7 +1735,7 @@ static int tree_content_get(
        return 0;
 
 found_entry:
-       memcpy(leaf, e, sizeof(*leaf));
+       *leaf = *e;
        if (e->tree && is_null_sha1(e->versions[1].sha1))
                leaf->tree = dup_tree_content(e->tree);
        else
diff --git a/line-log.c b/line-log.c
index 64f141e20..de5bbb5bd 100644
--- a/line-log.c
+++ b/line-log.c
@@ -765,7 +765,7 @@ static void move_diff_queue(struct diff_queue_struct *dst,
                            struct diff_queue_struct *src)
 {
        assert(src != dst);
-       memcpy(dst, src, sizeof(struct diff_queue_struct));
+       *dst = *src;
        DIFF_QUEUE_CLEAR(src);
 }
 

Reply via email to