git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 1/3] add QSORT

From
Junio C Hamano <gitster@pobox.com>
Date
Sep 29, 2016, 22:36 UTC
Message-ID
<xmqqponmcp07.fsf@gitster.mtv.corp.google.com>
In-Reply-To
<67bddc37-4ee2-fef0-c852-e32645421e4c@web.de>
René Scharfe <l.s.r@web.de> writes:
Show 17 quoted lines
> Add the macro QSORT, a convenient wrapper for qsort(3) that infers the
> size of the array elements and supports the convention of initializing
> empty arrays with a NULL pointer, which we use in some places.
>
> Calling qsort(3) directly with a NULL pointer is undefined -- even with
> an element count of zero -- and allows the compiler to optimize away any
> following NULL checks.  Using the macro avoids such surprises.
>
> Add a semantic patch as well to demonstrate the macro's usage and to
> automate the transformation of trivial cases.
>
> Signed-off-by: Rene Scharfe <l.s.r@web.de>
> ---
>  contrib/coccinelle/qsort.cocci | 19 +++++++++++++++++++
>  git-compat-util.h              |  8 ++++++++
>  2 files changed, 27 insertions(+)
>  create mode 100644 contrib/coccinelle/qsort.cocci

The direct calls to qsort(3) that this series leaves behind are interesting.

1. builtin/index-pack.c has this:
	if (1 < opts->anomaly_nr)
		qsort(opts->anomaly, opts->anomaly_nr, sizeof(uint32_t), cmp_uint32);
where opts->anomaly is coming from pack.h:
    struct pack_idx_option {
            unsigned flags;
            ...
            int anomaly_alloc, anomaly_nr;
            uint32_t *anomaly;
    };

I cannot quite see how the automated conversion misses it? It's not like base and nmemb are type-restricted in the rule (they are both just "expression"s).

2. builtin/shortlog.c has this:
	qsort(log->list.items, log->list.nr, sizeof(struct string_list_item),
	      log->summary ? compare_by_counter : compare_by_list);
where log->list is coming from shortlog.h:
    struct shortlog {
            struct string_list list;
    };
and string-list.h says:
    struct string_list {
            struct string_list_item *items;
            unsigned int nr, alloc;
            ...
    };
which seems to be a good candidate for this rule:
    type T;
    T *base;
    expression nmemb, compar;
    @@
    - qsort(base, nmemb, sizeof(T), compar);
    + QSORT(base, nmemb, compar);
if we take "T == struct string_list_item".
3. builtin/show-branch.c does this:
    qsort(ref_name + bottom, top - bottom, sizeof(ref_name[0]),
          compare_ref_name);
where ref_name[] is a file-scope global:
    static char *ref_name[MAX_REVS + 1];

and top and bottom are plain integers. The sizeof() does not take the size of *base, so it is understandable that this does not get automatically converted.

It seems that some calls to this function _could_ send the same top and bottom, asking for 0 element array to be sorted, by the way.

Thanks for an amusing read.
Previous: René ScharfeNext: René Scharfe
Message 4 of 13 in “add QSORT”
  1. 1/3 add QSORTRené Scharfe, Sep 29, 2016
  2. 2/3 use QSORTRené Scharfe, Sep 29, 2016
  3. 3/3 remove unnecessary check before QSORTRené Scharfe, Sep 29, 2016
  4. Junio C HamanoSep 29, 2016
  5. René ScharfeSep 29, 2016
  6. René ScharfeSep 29, 2016
  7. René ScharfeOct 1, 2016
  8. Kevin BraceyOct 3, 2016
  9. René ScharfeOct 3, 2016
  10. Kevin BraceyOct 4, 2016
  11. René ScharfeOct 4, 2016
  12. Kevin BraceyOct 5, 2016
  13. Kevin BraceyOct 3, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.