pgindent versus struct members and typedefs

Started by Nathan Bossart5 months ago22 messageshackers
Jump to latest
#1Nathan Bossart
nathandbossart@gmail.com

On Mon, Dec 01, 2025 at 05:04:23PM -0600, Nathan Bossart wrote:

On Tue, Dec 02, 2025 at 05:35:34AM +0800, Chao Li wrote:

```
+		else if (entry->type == DSMR_ENTRY_TYPE_DSH &&
+				 entry->dsh.dsa_handle !=DSA_HANDLE_INVALID)
```

Missing a white space after !=.

I agree, but for some reason, pgindent insists on removing that space. I'm
leaving that for another thread.

So, this seems to have something to do with the struct member having the
same name as a typedef. If I rename the member, pgindent adds the space as
expected. Interestingly, changing the != to a == also fixes the spacing.
There are a couple of other examples in the code:

src/backend/storage/ipc/dsm_registry.c: entry->dsh.dsa_handle !=DSA_HANDLE_INVALID)
src/backend/replication/logical/logicalfuncs.c: ctx->options.output_type !=OUTPUT_PLUGIN_TEXTUAL_OUTPUT)
src/bin/pg_basebackup/pg_basebackup.c: if (state.manifest_file !=NULL)
src/bin/pg_basebackup/pg_basebackup.c: state->manifest_file !=NULL)
src/bin/pg_basebackup/pg_basebackup.c: else if (state->manifest_file !=NULL)

I used the following command to find these:

grep -E "!=[A-Za-z]" ./* -rI

AFAICT this is a special case of the note added to pgindent's README by
commit c4133ec:

pgindent will mangle both declaration and definition of a C function whose
name matches a typedef. Currently the best workaround is to choose
non-conflicting names.

I tried to fix pgindent for a few, but the code is basically impenetrable.
I didn't find any fixes upstream [0]https://github.com/freebsd/freebsd-src/tree/main/usr.bin/indent, either. As noted above, we could
also fix it by avoiding the naming conflicts. However, I can't imagine
that's worth the churn, and I've already spent way too much time on this,
so IMHO the best thing to do here is nothing.

[0]: https://github.com/freebsd/freebsd-src/tree/main/usr.bin/indent

--
nathan

#2Chao Li
li.evan.chao@gmail.com
In reply to: Nathan Bossart (#1)
Re: pgindent versus struct members and typedefs

On Dec 3, 2025, at 06:00, Nathan Bossart <nathandbossart@gmail.com> wrote:

On Mon, Dec 01, 2025 at 05:04:23PM -0600, Nathan Bossart wrote:

On Tue, Dec 02, 2025 at 05:35:34AM +0800, Chao Li wrote:

```
+ else if (entry->type == DSMR_ENTRY_TYPE_DSH &&
+ entry->dsh.dsa_handle !=DSA_HANDLE_INVALID)
```

Missing a white space after !=.

I agree, but for some reason, pgindent insists on removing that space. I'm
leaving that for another thread.

So, this seems to have something to do with the struct member having the
same name as a typedef. If I rename the member, pgindent adds the space as
expected. Interestingly, changing the != to a == also fixes the spacing.
There are a couple of other examples in the code:

src/backend/storage/ipc/dsm_registry.c: entry->dsh.dsa_handle !=DSA_HANDLE_INVALID)
src/backend/replication/logical/logicalfuncs.c: ctx->options.output_type !=OUTPUT_PLUGIN_TEXTUAL_OUTPUT)
src/bin/pg_basebackup/pg_basebackup.c: if (state.manifest_file !=NULL)
src/bin/pg_basebackup/pg_basebackup.c: state->manifest_file !=NULL)
src/bin/pg_basebackup/pg_basebackup.c: else if (state->manifest_file !=NULL)

I used the following command to find these:

grep -E "!=[A-Za-z]" ./* -rI

AFAICT this is a special case of the note added to pgindent's README by
commit c4133ec:

pgindent will mangle both declaration and definition of a C function whose
name matches a typedef. Currently the best workaround is to choose
non-conflicting names.

I tried to fix pgindent for a few, but the code is basically impenetrable.
I didn't find any fixes upstream [0], either. As noted above, we could
also fix it by avoiding the naming conflicts. However, I can't imagine
that's worth the churn, and I've already spent way too much time on this,
so IMHO the best thing to do here is nothing.

I think that’s fine.

Actually I see the other problem with pgindent, where if a “else” clause contains a multiple-line comment and a single statement without braces, for example:

```
else
/*
* comment
*/
printf(…);
```

Then pgindent will blindly add an empty line after “else”, so we get:
```
else

/*
* comment
*/
printf(…);

```

I tried to fix but failed. For that problem, a solution is to add braces to the “else” clause.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Chao Li (#2)
Re: pgindent versus struct members and typedefs

Chao Li <li.evan.chao@gmail.com> writes:

On Dec 3, 2025, at 06:00, Nathan Bossart <nathandbossart@gmail.com> wrote:

I tried to fix pgindent for a few, but the code is basically impenetrable.
I didn't find any fixes upstream [0], either. As noted above, we could
also fix it by avoiding the naming conflicts. However, I can't imagine
that's worth the churn, and I've already spent way too much time on this,
so IMHO the best thing to do here is nothing.

I think that’s fine.

Agreed, not worth the trouble to fool with.

Actually I see the other problem with pgindent, where if a “else” clause contains a multiple-line comment and a single statement without braces, for example:
...
I tried to fix but failed. For that problem, a solution is to add braces to the “else” clause.

In this case, I think pgindent is indirectly enforcing good style.
I do not like omitting braces around anything that's more than one
line; readers have to pay close attention to whether the code is
doing what it was intended to.

regards, tom lane

#4Chao Li
li.evan.chao@gmail.com
In reply to: Tom Lane (#3)
Re: pgindent versus struct members and typedefs

On Dec 3, 2025, at 06:51, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Chao Li <li.evan.chao@gmail.com> writes:

On Dec 3, 2025, at 06:00, Nathan Bossart <nathandbossart@gmail.com> wrote:

I tried to fix pgindent for a few, but the code is basically impenetrable.
I didn't find any fixes upstream [0], either. As noted above, we could
also fix it by avoiding the naming conflicts. However, I can't imagine
that's worth the churn, and I've already spent way too much time on this,
so IMHO the best thing to do here is nothing.

I think that’s fine.

Agreed, not worth the trouble to fool with.

Actually I see the other problem with pgindent, where if a “else” clause contains a multiple-line comment and a single statement without braces, for example:
...
I tried to fix but failed. For that problem, a solution is to add braces to the “else” clause.

In this case, I think pgindent is indirectly enforcing good style.
I do not like omitting braces around anything that's more than one
line; readers have to pay close attention to whether the code is
doing what it was intended to.

For “one line”, do you mean only a single line of statement or one line statement plus one line comment?

To clarify the pgindnet problem, if we have a one-line comment plus one-line statement, for example:
```
else
/* one line comment */
printf(…);
```

In this case, pgindent will not add an empty line after “else”.

But I totally agree with you, when there is a multiple-line comment and a single statement, it's a good habit to add braces.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Chao Li (#4)
Re: pgindent versus struct members and typedefs

Chao Li <li.evan.chao@gmail.com> writes:

On Dec 3, 2025, at 06:51, Tom Lane <tgl@sss.pgh.pa.us> wrote:
In this case, I think pgindent is indirectly enforcing good style.
I do not like omitting braces around anything that's more than one
line; readers have to pay close attention to whether the code is
doing what it was intended to.

For “one line”, do you mean only a single line of statement or one line statement plus one line comment?

In my head, a comment and a statement are two lines, and so need
wrapping braces as much as two statements would do. I realize that
C compilers think differently, but for readability and modifiability
reasons that's the approach I take.

regards, tom lane

#6Chao Li
li.evan.chao@gmail.com
In reply to: Tom Lane (#5)
Re: pgindent versus struct members and typedefs

On Dec 3, 2025, at 07:13, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Chao Li <li.evan.chao@gmail.com> writes:

On Dec 3, 2025, at 06:51, Tom Lane <tgl@sss.pgh.pa.us> wrote:
In this case, I think pgindent is indirectly enforcing good style.
I do not like omitting braces around anything that's more than one
line; readers have to pay close attention to whether the code is
doing what it was intended to.

For “one line”, do you mean only a single line of statement or one line statement plus one line comment?

In my head, a comment and a statement are two lines, and so need
wrapping braces as much as two statements would do. I realize that
C compilers think differently, but for readability and modifiability
reasons that's the approach I take.

Totally agreed. In my first job at Lucent Technologies, the coding standard was that braces should always be added even if a clause has only one line of code. I remember one of the explanations was like, if braces has been added, then later when a new line of code is added to the clause, there is only one line of diff, otherwise braces need to be added, so it would be 3 lines of diffs.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

#7Andrew Dunstan
andrew@dunslane.net
In reply to: Chao Li (#6)
Re: pgindent versus struct members and typedefs

On 2025-12-02 Tu 6:31 PM, Chao Li wrote:

On Dec 3, 2025, at 07:13, Tom Lane<tgl@sss.pgh.pa.us> wrote:

Chao Li<li.evan.chao@gmail.com> writes:

On Dec 3, 2025, at 06:51, Tom Lane<tgl@sss.pgh.pa.us> wrote:
In this case, I think pgindent is indirectly enforcing good style.
I do not like omitting braces around anything that's more than one
line; readers have to pay close attention to whether the code is
doing what it was intended to.

For “one line”, do you mean only a single line of statement or one line statement plus one line comment?

In my head, a comment and a statement are two lines, and so need
wrapping braces as much as two statements would do. I realize that
C compilers think differently, but for readability and modifiability
reasons that's the approach I take.

Totally agreed. In my first job at Lucent Technologies, the coding standard was that braces should always be added even if a clause has only one line of code. I remember one of the explanations was like, if braces has been added, then later when a new line of code is added to the clause, there is only one line of diff, otherwise braces need to be added, so it would be 3 lines of diffs.

+1. One of the things I find particularly un-aesthetic is having some
branches of an if statement with braces and some without. We have lots
of cases of that, but I try to avoid it.

cheers

andrew

--
Andrew Dunstan
EDB:https://www.enterprisedb.com

#8Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Andrew Dunstan (#7)
Re: pgindent versus struct members and typedefs

On 2025-Dec-03, Andrew Dunstan wrote:

+1. One of the things I find particularly un-aesthetic is having some
branches of an if statement with braces and some without. We have lots of
cases of that, but I try to avoid it.

I actually prefer that style: when there are only two branches, and the
other branch of the if is long, I put the short one first without
braces, and then braces around the long "else" one.

--
Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
"The eagle never lost so much time, as
when he submitted to learn of the crow." (William Blake)

#9Nathan Bossart
nathandbossart@gmail.com
In reply to: Tom Lane (#3)
Re: pgindent versus struct members and typedefs

On Tue, Dec 02, 2025 at 05:51:15PM -0500, Tom Lane wrote:

Chao Li <li.evan.chao@gmail.com> writes:

On Dec 3, 2025, at 06:00, Nathan Bossart <nathandbossart@gmail.com> wrote:

I tried to fix pgindent for a few, but the code is basically impenetrable.
I didn't find any fixes upstream [0], either. As noted above, we could
also fix it by avoiding the naming conflicts. However, I can't imagine
that's worth the churn, and I've already spent way too much time on this,
so IMHO the best thing to do here is nothing.

I think that’s fine.

Agreed, not worth the trouble to fool with.

For fun, I spent some time with an AI tool to develop the attached fix for
this problem. The explanation seems reasonable to me, although I am by no
means a pgindent expert. When I looked at this in December, I did find
this similar commit from upstream [0]https://github.com/pstef/freebsd_indent/commit/afa2239, but I failed to make the connection
with last_u_d. 0002 is the result of a pgindent run after applying 0001.
You'll notice that it fixes the exact set of cases I found with grep
upthread.

[0]: https://github.com/pstef/freebsd_indent/commit/afa2239

--
nathan

Attachments:

v1-0001-pgindent-Fix-spacing-after-when-member-name-match.patchtext/plain; charset=us-asciiDownload+2-2
v1-0002-run-pgindent.patchtext/plain; charset=us-asciiDownload+5-6
#10Chao Li
li.evan.chao@gmail.com
In reply to: Nathan Bossart (#9)
Re: pgindent versus struct members and typedefs

On May 6, 2026, at 05:47, Nathan Bossart <nathandbossart@gmail.com> wrote:

On Tue, Dec 02, 2025 at 05:51:15PM -0500, Tom Lane wrote:

Chao Li <li.evan.chao@gmail.com> writes:

On Dec 3, 2025, at 06:00, Nathan Bossart <nathandbossart@gmail.com> wrote:

I tried to fix pgindent for a few, but the code is basically impenetrable.
I didn't find any fixes upstream [0], either. As noted above, we could
also fix it by avoiding the naming conflicts. However, I can't imagine
that's worth the churn, and I've already spent way too much time on this,
so IMHO the best thing to do here is nothing.

I think that’s fine.

Agreed, not worth the trouble to fool with.

For fun, I spent some time with an AI tool to develop the attached fix for
this problem. The explanation seems reasonable to me, although I am by no
means a pgindent expert. When I looked at this in December, I did find
this similar commit from upstream [0], but I failed to make the connection
with last_u_d. 0002 is the result of a pgindent run after applying 0001.
You'll notice that it fixes the exact set of cases I found with grep
upthread.

[0] https://github.com/pstef/freebsd_indent/commit/afa2239

--
nathan
<v1-0001-pgindent-Fix-spacing-after-when-member-name-match.patch><v1-0002-run-pgindent.patch>

From 0002, the fix looks good. I tried to run the patched pgindent against all .c and .h files under src/ and contrib/, the result is exactly the same as 0002.

So, maybe worthy pushing before Tom running the annual pgindent.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

#11Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nathan Bossart (#9)
Re: pgindent versus struct members and typedefs

Nathan Bossart <nathandbossart@gmail.com> writes:

For fun, I spent some time with an AI tool to develop the attached fix for
this problem. The explanation seems reasonable to me, although I am by no
means a pgindent expert. When I looked at this in December, I did find
this similar commit from upstream [0], but I failed to make the connection
with last_u_d. 0002 is the result of a pgindent run after applying 0001.
You'll notice that it fixes the exact set of cases I found with grep
upthread.

Those changes are clearly improvements. I'm too tired to investigate
right now, but I wonder if we should adopt the upstream fix you
mention? (Or more generally, other changes they made since we forked?)

regards, tom lane

#12Nathan Bossart
nathandbossart@gmail.com
In reply to: Tom Lane (#11)
Re: pgindent versus struct members and typedefs

On Tue, May 05, 2026 at 11:43:39PM -0400, Tom Lane wrote:

Nathan Bossart <nathandbossart@gmail.com> writes:

For fun, I spent some time with an AI tool to develop the attached fix for
this problem. The explanation seems reasonable to me, although I am by no
means a pgindent expert. When I looked at this in December, I did find
this similar commit from upstream [0], but I failed to make the connection
with last_u_d. 0002 is the result of a pgindent run after applying 0001.
You'll notice that it fixes the exact set of cases I found with grep
upthread.

Those changes are clearly improvements. I'm too tired to investigate
right now, but I wonder if we should adopt the upstream fix you
mention? (Or more generally, other changes they made since we forked?)

The upstream fix is from before we forked, it just didn't fix this
particular case. I don't see any missing changes from
pstef/freebsd_indent, but there have been a number of changes in the
FreeBSD version:

https://cgit.freebsd.org/src/log/usr.bin/indent

Some of our changes to pg_bsd_indent bumped INDENT_VERSION. Should we do
that here?

--
nathan

#13Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nathan Bossart (#12)
Re: pgindent versus struct members and typedefs

Nathan Bossart <nathandbossart@gmail.com> writes:

Some of our changes to pg_bsd_indent bumped INDENT_VERSION. Should we do
that here?

We already have an INDENT_VERSION bump queued for the
space-between-comma-and-period change. I don't think we need two
bumps in this cycle, as long as we coordinate pushing these changes.

regards, tom lane

#14Nathan Bossart
nathandbossart@gmail.com
In reply to: Tom Lane (#13)
Re: pgindent versus struct members and typedefs

On Wed, May 06, 2026 at 11:02:35AM -0400, Tom Lane wrote:

Nathan Bossart <nathandbossart@gmail.com> writes:

Some of our changes to pg_bsd_indent bumped INDENT_VERSION. Should we do
that here?

We already have an INDENT_VERSION bump queued for the
space-between-comma-and-period change. I don't think we need two
bumps in this cycle, as long as we coordinate pushing these changes.

Okay. I'll go ahead and commit the patches for $subject then, leaving out
the version bump.

--
nathan

#15Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nathan Bossart (#14)
Re: pgindent versus struct members and typedefs

Nathan Bossart <nathandbossart@gmail.com> writes:

On Wed, May 06, 2026 at 11:02:35AM -0400, Tom Lane wrote:

We already have an INDENT_VERSION bump queued for the
space-between-comma-and-period change. I don't think we need two
bumps in this cycle, as long as we coordinate pushing these changes.

Okay. I'll go ahead and commit the patches for $subject then, leaving out
the version bump.

No, *don't* do it right now. You'll break anyone using the
in-tree version, or if you also commit the ensuing code changes,
you'll break anyone using an out-of-tree copy. This stuff all
needs to go in at once.

regards, tom lane

#16Nathan Bossart
nathandbossart@gmail.com
In reply to: Tom Lane (#15)
Re: pgindent versus struct members and typedefs

On Wed, May 06, 2026 at 11:17:17AM -0400, Tom Lane wrote:

Nathan Bossart <nathandbossart@gmail.com> writes:

On Wed, May 06, 2026 at 11:02:35AM -0400, Tom Lane wrote:

We already have an INDENT_VERSION bump queued for the
space-between-comma-and-period change. I don't think we need two
bumps in this cycle, as long as we coordinate pushing these changes.

Okay. I'll go ahead and commit the patches for $subject then, leaving out
the version bump.

No, *don't* do it right now. You'll break anyone using the
in-tree version, or if you also commit the ensuing code changes,
you'll break anyone using an out-of-tree copy. This stuff all
needs to go in at once.

Alright. I'll just prepare the patches and post them here for when that
time comes, then.

--
nathan

#17Nathan Bossart
nathandbossart@gmail.com
In reply to: Nathan Bossart (#16)
Re: pgindent versus struct members and typedefs

On Wed, May 06, 2026 at 10:20:26AM -0500, Nathan Bossart wrote:

Alright. I'll just prepare the patches and post them here for when that
time comes, then.

Here's a new version of 0001 with a cleaned-up commit message. I've
omitted 0002, since it's just the result of running pgindent after apply
the first one.

--
nathan

Attachments:

v2-0001-pgindent-Fix-spacing-after-when-member-name-match.patchtext/plain; charset=us-asciiDownload+2-2
#18Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nathan Bossart (#17)
Re: pgindent versus struct members and typedefs

Nathan Bossart <nathandbossart@gmail.com> writes:

Here's a new version of 0001 with a cleaned-up commit message. I've
omitted 0002, since it's just the result of running pgindent after apply
the first one.

I think we're about ready to roll on doing the pgindent run.
Do you want to push your patch tomorrow AM, and then I'll get
on with the rest?

regards, tom lane

#19Nathan Bossart
nathandbossart@gmail.com
In reply to: Tom Lane (#18)
Re: pgindent versus struct members and typedefs

On Tue, May 12, 2026 at 05:33:50PM -0400, Tom Lane wrote:

Nathan Bossart <nathandbossart@gmail.com> writes:

Here's a new version of 0001 with a cleaned-up commit message. I've
omitted 0002, since it's just the result of running pgindent after apply
the first one.

I think we're about ready to roll on doing the pgindent run.
Do you want to push your patch tomorrow AM, and then I'll get
on with the rest?

Sounds good. We won't be back-patching any of this, right?

--
nathan

#20Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nathan Bossart (#19)
Re: pgindent versus struct members and typedefs

Nathan Bossart <nathandbossart@gmail.com> writes:

On Tue, May 12, 2026 at 05:33:50PM -0400, Tom Lane wrote:

I think we're about ready to roll on doing the pgindent run.
Do you want to push your patch tomorrow AM, and then I'll get
on with the rest?

Sounds good. We won't be back-patching any of this, right?

Right, just HEAD.

regards, tom lane

#21Nathan Bossart
nathandbossart@gmail.com
In reply to: Tom Lane (#20)
#22Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nathan Bossart (#21)