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

Re: [PATCH] for_each_string_list_item(): behave correctly for empty list

From
Junio C Hamano <gitster@pobox.com>
Date
Sep 18, 2017, 00:37 UTC
Message-ID
<xmqqfubku9iy.fsf@gitster.mtv.corp.google.com>
In-Reply-To
<5c86b55e-20f6-df8e-b01f-66876c3a5f46@alum.mit.edu>
Michael Haggerty <mhagger@alum.mit.edu> writes:
Show 6 quoted lines
> *sigh* of course you're right. I should know better than to "fire off a
> quick fix to the mailing list".
>
> I guess the two proposals that are still in the running for rescuing
> this macro are Jonathan's and Gábor's. I have no strong preference
> either way.

If somebody is writing this outisde a macro as a one-shot thing, the most natural and readable way I would imagine would be

	if (the list is empty)
        	;
	else
		for (each item in the list)
			work on item

I would think. That "work on item" part may not be a single expression statement and instead be a compound statement inside a pair of braces {}. Making a shorter version, i.e.

	if (!the list is empty)
		for (each item in the list)
			work on item

into a macro probably has syntax issues around cascading if/else chain, e.g.

	if (condition caller cares about)
		for_each_string_list_item() {
			do this thing
		}
	else
		do something else
would expand to
	if (condition caller cares about)
		if (!the list is empty)
			for (each item in the list) {
				do this thing
			}
	else
		do something else

which is wrong. But I couldn't think of a way to break the longer one with the body of the macro in the "else" clause in a similar way. An overly helpful compiler might say

	if (condition caller cares about)
		if (the list is empty)
			;
		else
			for (each item in the list) {
				do this thing
			}
	else
		do something else

that it wants a pair of {} around the then-clause of the outer if; if we can find a way to squelch such warnings only with this construct that comes from the macro, then this solution may be ideal.

If we cannot do that, then
	for (item = (list)->items; /* could be NULL */
	     (list)->items && item < (list)->items + (list)->nr;
	     item++)
		work on item

may be an obvious way to write it without any such syntax worries, but I am unclear how a "undefined behaviour" contaminate the code around it. My naive reading of the termination condition of the above is:

	"(list)->items &&" clearly means that (list)->items is not
	NULL in what follows it, i.e. (list->items + (list)->nr
	cannot be a NULL + 0, so we are not allowed to make demon
	fly out of your nose.
but I wonder if this alternative reading is allowed:
	(list)->items is not assigned to in this expression and is
	used in a subexpression "(list)->items + (list)->nr" here;
	for that subexpression not to be "undefined", it cannot be
	NULL, so we can optimize out "do this only (list)->items is
	not NULL" part.
which takes us back to where we started X-<.  So I dunno.

I am hoping that this last one is not allowed and we can use the "same condition is checked every time we loop" version that hides the uglyness inside the macro.

Previous: Michael HaggertyNext: Stefan Beller
Message 25 of 29 in “for_each_string_list_item(): behave correctly for empty list”
  1. for_each_string_list_item(): behave correctly for empty listMichael Haggerty, Sep 15, 2017
  2. Jonathan NiederSep 15, 2017
  3. Michael HaggertySep 16, 2017
  4. SZEDER GáborSep 16, 2017
  5. Michael HaggertySep 17, 2017
  6. Kaartic SivaraamSep 19, 2017
  7. Junio C HamanoSep 20, 2017
  8. Jonathan NiederSep 20, 2017
  9. Junio C HamanoSep 20, 2017
  10. Jonathan NiederSep 20, 2017
  11. Junio C HamanoSep 20, 2017
  12. for_each_string_list_item: avoid undefined behavior for empty listJonathan Nieder, Sep 20, 2017
  13. Junio C HamanoSep 20, 2017
  14. Michael HaggertySep 20, 2017
  15. Kaartic SivaraamSep 20, 2017
  16. doc: camelCase the config variables to improve readabilityKaartic Sivaraam, Sep 20, 2017
  17. Andreas SchwabSep 20, 2017
  18. Jonathan NiederSep 20, 2017
  19. Andreas SchwabSep 20, 2017
  20. Junio C HamanoSep 21, 2017
  21. Andreas SchwabSep 21, 2017
  22. Kaartic SivaraamSep 20, 2017
  23. Junio C HamanoSep 17, 2017
  24. Michael HaggertySep 17, 2017
  25. Junio C HamanoSep 18, 2017
  26. Stefan BellerSep 19, 2017
  27. Michael HaggertySep 19, 2017
  28. SZEDER GáborSep 19, 2017
  29. SZEDER GáborSep 19, 2017

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.