C11 / VS 2019

Started by Peter Eisentraut7 months ago33 messages
#1Peter Eisentraut
peter@eisentraut.org

I propose that we raise the baseline C standard for PostgreSQL to C11
for PostgreSQL 19. This will allow us to make use of some new features,
clear away a bunch of backward compatibility cruft, unify use of
compiler-specific extensions, and narrow the range of compatibility
concerns for some efforts like improved threads support. Most compilers
other than older versions of MSVC (about which see below) have supported
C11 for quite some time and most use it by default, so for most
developers and packagers this wouldn't effectively change anything
except removing some restrictions about what features they can use.

(I mentioned some of this in my presentation at pgconf.dev; I will
repeat the relevant points here. You can see my presentation at [0]https://www.pgevents.ca/events/pgconfdev2025/schedule/session/271-what-is-new-in-c-and-posix/.)

[0]: https://www.pgevents.ca/events/pgconfdev2025/schedule/session/271-what-is-new-in-c-and-posix/
https://www.pgevents.ca/events/pgconfdev2025/schedule/session/271-what-is-new-in-c-and-posix/

Here are some of the features we could use. This is just for
inspiration right now, these would all be separate proposals:

- alignas specifier to allow specifying larger alignments more portably,
e.g., for direct I/O
- noreturn, already in use but would allow removing
backwards-compatibility code
- static assertions, we currently have 12(!) different implementations
for this, could maybe cut down to 2
- allow typedef redefinitions, to untangle header files (see for example
recent discussion [1]/messages/by-id/f36c0a45-98cd-40b2-a7cc-f2bf02b12890@eisentraut.org)
- anonymous unions, mostly aesthetic
- generic selection, for some more type safety in certain cases
- threads library (needs separate consideration, see [2]/messages/by-id/CA+hUKGLtmexrpMtxBRLCVePqV_dtWG-ZsEbyPrYc+NBB2TkNsw@mail.gmail.com)
- atomic types, to maybe simplify some of our atomics support

[1]: /messages/by-id/f36c0a45-98cd-40b2-a7cc-f2bf02b12890@eisentraut.org
/messages/by-id/f36c0a45-98cd-40b2-a7cc-f2bf02b12890@eisentraut.org
[2]: /messages/by-id/CA+hUKGLtmexrpMtxBRLCVePqV_dtWG-ZsEbyPrYc+NBB2TkNsw@mail.gmail.com
/messages/by-id/CA+hUKGLtmexrpMtxBRLCVePqV_dtWG-ZsEbyPrYc+NBB2TkNsw@mail.gmail.com

(Note: While the term "threads" appears here, this is independent of any
work on a multithreaded server. It probably wouldn't hurt, but it's not
a hard prerequisite as far as I know.)

The minimum required compiler versions for C11 support among the most
common compilers are:
- gcc 4.6/4.7/4.9 (depending on what feature)
- clang 3.1/3.2/3.3 (depending on what feature)
- Visual Studio (VS) 2019 (2022 for threads)

I have also checked the following less common compilers:
- Oracle Developer Studio 12.6, which is in the buildfarm, supports C11
ok (manually tested)
- Intel ICC 17.0.0 is ok (not in the buildfarm, tested on godbolt)
- AIX xlclang, which is currently not supported but might come back,
also supports C11

I think this covers all relevant compilers.

Visual Studio details: As shown above, C11 would require VS 2019. The
current minimum version required by PostgreSQL 18 is VS 2015. Can we
move forward from that? There isn't much data to extrapolate a VS
version support policy from. When MSVC support was initially added in
PG8.3, it required VS 2005, which was just the latest at the time. Then
it was not changed for a long time, until PG12 required VS 2013, which
was exactly for the C99 support. Then it was changed once more for
PG16, requiring VS 2015; AFAICT, this was just to be able to clean away
some conditional C code. I don't recall any complaints about any of
that. Note that PG12/VS2013 corresponds arithmetically to PG18/VS2019,
so making a move in PG19 would be less restrictive than that previous
change. I'll also note that we haven't had any test coverage for
anything older than VS 2019 for quite some time. I also remember commit
f9f31aa91f8, where we discovered that the code didn't build with VS 2015
after one year, and that was two years ago, so it seems like there isn't
too much interest in trailing edge VS versions in general. So I feel
comfortable moving this forward.

GCC details: The oldest gcc version that we currently need to support is
gcc 4.8, which comes with RHEL 7. As alluded to above, some C11
features came later with gcc 4.9, specifically generic, threads, and
atomics. I think it would still be useful to move forward without those
features. Threads and atomics are out of scope anyway because they
require VS >=2022, which I'm not prepared to require. And generic,
well, we'll just have to do without that for the moment. We can of
course have a separate discussion sometime about when to drop RHEL 7
support, but it doesn't have to be a prerequisite for this.

(Both gcc pre-4.9 and MSVC pre-2019 do support thread-local storage,
just not the C11 spelling, so this is at least on paper not a blocker
for a multithreaded server.)

Clang details: I don't think anyone cares about clang versions that old.
There is a clang 4.0 in the build farm, but I don't think even that
has any practical relevance.

I would also set the minimum supported C++ version to C++11. This is
the level required for, for example, static assertions (and also threads
and atomic types), so it makes some sense to align this with the C side.
Compilers tend to implement C++ features before C features, so this
wouldn't set any additional requirements on compiler versions in practice.

Summary:
1. require VS 2019
2. use C11

Thoughts?

#2Nathan Bossart
nathandbossart@gmail.com
In reply to: Peter Eisentraut (#1)
Re: C11 / VS 2019

On Mon, Jun 02, 2025 at 05:44:12AM +0200, Peter Eisentraut wrote:

Summary:
1. require VS 2019
2. use C11

Thoughts?

+1

--
nathan

#3Michael Paquier
michael@paquier.xyz
In reply to: Nathan Bossart (#2)
Re: C11 / VS 2019

On Mon, Jun 02, 2025 at 08:52:00AM -0500, Nathan Bossart wrote:

On Mon, Jun 02, 2025 at 05:44:12AM +0200, Peter Eisentraut wrote:

Summary:
1. require VS 2019
2. use C11

Thoughts?

+1

+1 to move on for both of these. I got convinced about the benefits
of C11 and the simplifications we could get from it in the Postgres
code base during your presentation at pgconf.dev.

Dropping VS 2015 and going up to VS 2019 brings other benefits,
__VA_ARGS__ coming in mind. I am wondering what's the state of
locales, actually. We've had some pain with VS 2015 as we lacked
locale_name in _locale_t, for example. That may be worth a second
look to see if some simplifications can happen in this area. I don't
think so at quick glance through the VS docs, unfortunately, but I may
be wrong, of course..
--
Michael

#4Yura Sokolov
y.sokolov@postgrespro.ru
In reply to: Michael Paquier (#3)
Re: C11 / VS 2019

03.06.2025 07:51, Michael Paquier wrote:

On Mon, Jun 02, 2025 at 08:52:00AM -0500, Nathan Bossart wrote:

On Mon, Jun 02, 2025 at 05:44:12AM +0200, Peter Eisentraut wrote:

Summary:
1. require VS 2019
2. use C11

Thoughts?

+1

+1 to move on for both of these. I got convinced about the benefits
of C11 and the simplifications we could get from it in the Postgres
code base during your presentation at pgconf.dev.

Dropping VS 2015 and going up to VS 2019 brings other benefits,
__VA_ARGS__ coming in mind. I am wondering what's the state of
locales, actually. We've had some pain with VS 2015 as we lacked
locale_name in _locale_t, for example. That may be worth a second
look to see if some simplifications can happen in this area. I don't
think so at quick glance through the VS docs, unfortunately, but I may
be wrong, of course..

Will it mean we can implement atomics in term of C11 atomics?
Aside for VS 2019, which has no support for. (But VS 2022 already has.)
So instead of numerous variants we could just differ VS2019 vs plain C11.

--
regards
Yura Sokolov aka funny-falcon

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Yura Sokolov (#4)
Re: C11 / VS 2019

Yura Sokolov <y.sokolov@postgrespro.ru> writes:

Will it mean we can implement atomics in term of C11 atomics?

Any such change would have to be supported by extensive performance
testing to verify that there's not a regression on any supported
platform. Yeah, it'd be cool if we could rip out a lot of that
code, but we aren't going to just rip on faith.

regards, tom lane

#6Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#5)
Re: C11 / VS 2019

On Wed, Jun 4, 2025 at 2:02 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Yura Sokolov <y.sokolov@postgrespro.ru> writes:

Will it mean we can implement atomics in term of C11 atomics?

Any such change would have to be supported by extensive performance
testing to verify that there's not a regression on any supported
platform. Yeah, it'd be cool if we could rip out a lot of that
code, but we aren't going to just rip on faith.

FWIW I posted an experimental patch like that at:

/messages/by-id/CA+hUKG+w-2RyyYUte_mSAunoRE00bQUCG44=FiOuyMaN-6uoOw@mail.gmail.com

To make progress down this path, yeah, we'd definitely want to do a
bunch of cross-platform evaluation work, ie performance valuation and
probably reading assembler. Note that in that experiment I just
mapped to the non-_explicit() variants (in other words all the
operations are defaulting to memory_order_seq_cst, which is too strong
in many cases), so we'd also what to think hard about which of the
pg_atomics operations should use _explicit() with a weaker
memory_order. Nearby there are also patches to change our spinlocks
to use pg_atomics, so then that just becomes standard C11 code too.
Assuming all that can be ironed out, AFAIK there is only one piece
that we'll still need to hand-roll, because C11 doesn't provide
anything like it: pg_spin_delay_impl(). (I haven't looked into
whether there is anything standard proposed to deal with that in some
future C.)

#7Peter Eisentraut
peter@eisentraut.org
In reply to: Michael Paquier (#3)
1 attachment(s)
Re: C11 / VS 2019

On 03.06.25 06:51, Michael Paquier wrote:

Dropping VS 2015 and going up to VS 2019 brings other benefits,
__VA_ARGS__ coming in mind.

Yes, this was going to be my next step. As we're already talking about
it, here is my proposed patch.

For an explanation, the background is that MSVC has a "traditional"
preprocessor and a new "conforming" one. The latter is available
starting in VS 2019, but it's not the default. We have some code,
especially around __VA_ARGS__ that specifically caters to this
traditional preprocessor.

Turning on C11 mode in MSVC (/std:c11) automatically turns on the
conforming preprocessor, which would currently break compilation on MSVC
because the code expects it to be in traditional mode.

So my first patch is that we fix that bit and turn on just the
conforming preprocessor (/Zc:preprocessor), without turning on C11 yet.
That way, we get that part out of the way, and we update the
documentation about requiring VS 2019. (And we'd flush out anyone who
might still be running pre-VS-2019 build jobs somewhere.) Later, when
we turn on C11, we can remove the explicit /Zc:preprocessor option again.

(An alternative approach would be to turn on C11 and add another option
to explicitly turn the traditional preprocessor back on, but that seems
pointless, and the documentation also suggests that that combination is
not well supported.)

So the attached patch is my proposal to commit early in PG19.

Attachments:

0001-Enable-MSVC-conforming-preprocessor.patchtext/plain; charset=UTF-8; name=0001-Enable-MSVC-conforming-preprocessor.patchDownload
From 0e2e4f6dd4dc4250f48736ec5a1b9bd40aad4fff Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 4 Jun 2025 07:09:42 +0200
Subject: [PATCH] Enable MSVC conforming preprocessor

Switch MSVC to use the conforming preprocessor, using the
/Zc:preprocessor option.

This allows us to drop the alternative implementation of
VA_ARGS_NARGS() for the previous "traditional" preprocessor.

This also prepares the way for enabling C11 mode in the future, which
enables the conforming preprocessor by default.

This now requires Visual Studio 2019.  The installation documentation
is adjusted accordingly.

Discussion: https://www.postgresql.org/message-id/flat/01a69441-af54-4822-891b-ca28e05b215a%40eisentraut.org
---
 doc/src/sgml/installation.sgml |  8 ++------
 meson.build                    |  4 ++++
 src/include/c.h                | 19 -------------------
 3 files changed, 6 insertions(+), 25 deletions(-)

diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index de19f3ad929..cb53530cc4f 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -3847,17 +3847,13 @@ <title>Visual Studio</title>
    <para>
     Both 32-bit and 64-bit builds are possible with the Microsoft Compiler suite.
     32-bit PostgreSQL builds are possible with
-    <productname>Visual Studio 2015</productname> to
+    <productname>Visual Studio 2019</productname> to
     <productname>Visual Studio 2022</productname>,
     as well as standalone Windows SDK releases 10 and above.
     64-bit PostgreSQL builds are supported with
     <productname>Microsoft Windows SDK</productname> version 10 and above or
-    <productname>Visual Studio 2015</productname> and above.
+    <productname>Visual Studio 2019</productname> and above.
     <!--
-        For 2015 requirements:
-        https://docs.microsoft.com/en-us/visualstudio/productinfo/vs2015-sysrequirements-vs
-        For 2017 requirements:
-        https://docs.microsoft.com/en-us/visualstudio/productinfo/vs2017-system-requirements-vs
         For 2019 requirements:
         https://docs.microsoft.com/en-us/visualstudio/releases/2019/system-requirements
         For 2022 requirements:
diff --git a/meson.build b/meson.build
index d142e3e408b..61cc0236612 100644
--- a/meson.build
+++ b/meson.build
@@ -279,6 +279,10 @@ elif host_system == 'windows'
     # define before including <time.h> for getting localtime_r() etc. on MinGW
     cppflags += '-D_POSIX_C_SOURCE'
   endif
+  if cc.get_id() == 'msvc'
+    # required for VA_ARGS_NARGS() in c.h; requires VS 2019
+    cppflags += '/Zc:preprocessor'
+  endif
 
   export_file_format = 'win'
   export_file_suffix = 'def'
diff --git a/src/include/c.h b/src/include/c.h
index 8cdc16a0f4a..04fd23577de 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -376,25 +376,7 @@
  * pretty trivial: VA_ARGS_NARGS_() returns its 64th argument, and we set up
  * the call so that that is the appropriate one of the list of constants.
  * This idea is due to Laurent Deniau.
- *
- * MSVC has an implementation of __VA_ARGS__ that doesn't conform to the
- * standard unless you use the /Zc:preprocessor compiler flag, but that
- * isn't available before Visual Studio 2019.  For now, use a different
- * definition that also works on older compilers.
  */
-#ifdef _MSC_VER
-#define EXPAND(args) args
-#define VA_ARGS_NARGS(...) \
-	VA_ARGS_NARGS_ EXPAND((__VA_ARGS__, \
-				   63,62,61,60,                   \
-				   59,58,57,56,55,54,53,52,51,50, \
-				   49,48,47,46,45,44,43,42,41,40, \
-				   39,38,37,36,35,34,33,32,31,30, \
-				   29,28,27,26,25,24,23,22,21,20, \
-				   19,18,17,16,15,14,13,12,11,10, \
-				   9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
-#else
-
 #define VA_ARGS_NARGS(...) \
 	VA_ARGS_NARGS_(__VA_ARGS__, \
 				   63,62,61,60,                   \
@@ -404,7 +386,6 @@
 				   29,28,27,26,25,24,23,22,21,20, \
 				   19,18,17,16,15,14,13,12,11,10, \
 				   9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
-#endif
 
 #define VA_ARGS_NARGS_( \
 	_01,_02,_03,_04,_05,_06,_07,_08,_09,_10, \

base-commit: 7f3381c7ee661e552634f06509a3452988a15845
-- 
2.49.0

#8Peter Eisentraut
peter@eisentraut.org
In reply to: Yura Sokolov (#4)
Re: C11 / VS 2019

On 03.06.25 10:01, Yura Sokolov wrote:

Will it mean we can implement atomics in term of C11 atomics?
Aside for VS 2019, which has no support for. (But VS 2022 already has.)
So instead of numerous variants we could just differ VS2019 vs plain C11.

I wrote:

"""
GCC details: The oldest gcc version that we currently need to support is
gcc 4.8, which comes with RHEL 7. As alluded to above, some C11
features came later with gcc 4.9, specifically generic, threads, and
atomics. I think it would still be useful to move forward without those
features.
"""

So there is additional homework to do there.

#9Peter Eisentraut
peter@eisentraut.org
In reply to: Peter Eisentraut (#7)
Re: C11 / VS 2019

On 04.06.25 08:15, Peter Eisentraut wrote:

On 03.06.25 06:51, Michael Paquier wrote:

Dropping VS 2015 and going up to VS 2019 brings other benefits,
__VA_ARGS__ coming in mind.

Yes, this was going to be my next step.  As we're already talking about
it, here is my proposed patch.

For an explanation, the background is that MSVC has a "traditional"
preprocessor and a new "conforming" one.  The latter is available
starting in VS 2019, but it's not the default.  We have some code,
especially around __VA_ARGS__ that specifically caters to this
traditional preprocessor.

Turning on C11 mode in MSVC (/std:c11) automatically turns on the
conforming preprocessor, which would currently break compilation on MSVC
because the code expects it to be in traditional mode.

So my first patch is that we fix that bit and turn on just the
conforming preprocessor (/Zc:preprocessor), without turning on C11 yet.
That way, we get that part out of the way, and we update the
documentation about requiring VS 2019.  (And we'd flush out anyone who
might still be running pre-VS-2019 build jobs somewhere.)  Later, when
we turn on C11, we can remove the explicit /Zc:preprocessor option again.

(An alternative approach would be to turn on C11 and add another option
to explicitly turn the traditional preprocessor back on, but that seems
pointless, and the documentation also suggests that that combination is
not well supported.)

So the attached patch is my proposal to commit early in PG19.

I have committed this.

#10Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#9)
Re: C11 / VS 2019

Peter Eisentraut <peter@eisentraut.org> writes:

On 04.06.25 08:15, Peter Eisentraut wrote:

For an explanation, the background is that MSVC has a "traditional"
preprocessor and a new "conforming" one.  The latter is available
starting in VS 2019, but it's not the default.  We have some code,
especially around __VA_ARGS__ that specifically caters to this
traditional preprocessor.

I have committed this.

Buildfarm member drongo has been failing in initdb since 1 July:

selecting default time zone ... UTC
creating configuration files ... ok
running bootstrap script ...
----------------------------------- stderr -----------------------------------
TRAP: failed Assert("SysCache[cacheId]->cc_nkeys == 2"), File: "../pgsql/src/backend/utils/cache/syscache.c", Line: 237, PID: 2684
child process was terminated by exception 0xC0000409

While there are 19 new commits in the first run that shows this
failure [1]https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=drongo&amp;dt=2025-07-01%2016%3A09%3A21, the only one that looks plausibly related is

8fd9bb1d965 Tue Jul 1 07:41:40 2025 UTC Enable MSVC conforming preprocessor

because that changed our implementation of VA_ARGS_NARGS(), which is
what's used to compute the cc_nkeys fields for syscaches.

My conclusion is that Microsoft's "standards conforming" preprocessor
is not so standards conforming as all that.

regards, tom lane

[1]: https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=drongo&amp;dt=2025-07-01%2016%3A09%3A21

#11Peter Eisentraut
peter@eisentraut.org
In reply to: Tom Lane (#10)
Re: C11 / VS 2019

On 06.07.25 00:27, Tom Lane wrote:

Peter Eisentraut <peter@eisentraut.org> writes:

On 04.06.25 08:15, Peter Eisentraut wrote:

For an explanation, the background is that MSVC has a "traditional"
preprocessor and a new "conforming" one.  The latter is available
starting in VS 2019, but it's not the default.  We have some code,
especially around __VA_ARGS__ that specifically caters to this
traditional preprocessor.

I have committed this.

Buildfarm member drongo has been failing in initdb since 1 July:

selecting default time zone ... UTC
creating configuration files ... ok
running bootstrap script ...
----------------------------------- stderr -----------------------------------
TRAP: failed Assert("SysCache[cacheId]->cc_nkeys == 2"), File: "../pgsql/src/backend/utils/cache/syscache.c", Line: 237, PID: 2684
child process was terminated by exception 0xC0000409

While there are 19 new commits in the first run that shows this
failure [1], the only one that looks plausibly related is

8fd9bb1d965 Tue Jul 1 07:41:40 2025 UTC Enable MSVC conforming preprocessor

because that changed our implementation of VA_ARGS_NARGS(), which is
what's used to compute the cc_nkeys fields for syscaches.

My conclusion is that Microsoft's "standards conforming" preprocessor
is not so standards conforming as all that.

Hmm. We have the (allegedly) same VS version in Cirrus CI, and it's
never shown a problem like this.

I wonder if there could be a local problem on this host. Perhaps the
ccache or pch cache could use a cleaning up?

#12Nazir Bilal Yavuz
byavuz81@gmail.com
In reply to: Peter Eisentraut (#11)
Re: C11 / VS 2019

Hi,

On Mon, 7 Jul 2025 at 13:51, Peter Eisentraut <peter@eisentraut.org> wrote:

On 06.07.25 00:27, Tom Lane wrote:

Peter Eisentraut <peter@eisentraut.org> writes:

On 04.06.25 08:15, Peter Eisentraut wrote:

For an explanation, the background is that MSVC has a "traditional"
preprocessor and a new "conforming" one. The latter is available
starting in VS 2019, but it's not the default. We have some code,
especially around __VA_ARGS__ that specifically caters to this
traditional preprocessor.

I have committed this.

Buildfarm member drongo has been failing in initdb since 1 July:

selecting default time zone ... UTC
creating configuration files ... ok
running bootstrap script ...
----------------------------------- stderr -----------------------------------
TRAP: failed Assert("SysCache[cacheId]->cc_nkeys == 2"), File: "../pgsql/src/backend/utils/cache/syscache.c", Line: 237, PID: 2684
child process was terminated by exception 0xC0000409

While there are 19 new commits in the first run that shows this
failure [1], the only one that looks plausibly related is

8fd9bb1d965 Tue Jul 1 07:41:40 2025 UTC Enable MSVC conforming preprocessor

because that changed our implementation of VA_ARGS_NARGS(), which is
what's used to compute the cc_nkeys fields for syscaches.

My conclusion is that Microsoft's "standards conforming" preprocessor
is not so standards conforming as all that.

Hmm. We have the (allegedly) same VS version in Cirrus CI, and it's
never shown a problem like this.

CI uses the latest VS 2019 (v16.11.48), it looks like buildfarm member
drongo uses VS 2019 v16.3.1. I created a custom Windows VM with the
same VS 2019 version (v16.3.1) at the drongo and CI failed with the
same error [1]https://cirrus-ci.com/task/6271845944524800.

[1]: https://cirrus-ci.com/task/6271845944524800

--
Regards,
Nazir Bilal Yavuz
Microsoft

#13Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nazir Bilal Yavuz (#12)
Re: C11 / VS 2019

Nazir Bilal Yavuz <byavuz81@gmail.com> writes:

On Mon, 7 Jul 2025 at 13:51, Peter Eisentraut <peter@eisentraut.org> wrote:

Hmm. We have the (allegedly) same VS version in Cirrus CI, and it's
never shown a problem like this.

CI uses the latest VS 2019 (v16.11.48), it looks like buildfarm member
drongo uses VS 2019 v16.3.1. I created a custom Windows VM with the
same VS 2019 version (v16.3.1) at the drongo and CI failed with the
same error [1].

Huh. Can we trawl the release notes for VS and see if this was
acknowledged as a bug fix, and if so when did it happen? I think
whether we can say "get a newer compiler" depends in part on how
long it's been fixed.

regards, tom lane

#14Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#13)
Re: C11 / VS 2019

On 2025-07-07 Mo 10:13 AM, Tom Lane wrote:

Nazir Bilal Yavuz<byavuz81@gmail.com> writes:

On Mon, 7 Jul 2025 at 13:51, Peter Eisentraut<peter@eisentraut.org> wrote:

Hmm. We have the (allegedly) same VS version in Cirrus CI, and it's
never shown a problem like this.

CI uses the latest VS 2019 (v16.11.48), it looks like buildfarm member
drongo uses VS 2019 v16.3.1. I created a custom Windows VM with the
same VS 2019 version (v16.3.1) at the drongo and CI failed with the
same error [1].

Huh. Can we trawl the release notes for VS and see if this was
acknowledged as a bug fix, and if so when did it happen? I think
whether we can say "get a newer compiler" depends in part on how
long it's been fixed.

Meanwhile I will update drongo anyway.

cheers

andrew

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

#15Peter Eisentraut
peter@eisentraut.org
In reply to: Tom Lane (#13)
Re: C11 / VS 2019

On 07.07.25 16:13, Tom Lane wrote:

Nazir Bilal Yavuz <byavuz81@gmail.com> writes:

On Mon, 7 Jul 2025 at 13:51, Peter Eisentraut <peter@eisentraut.org> wrote:

Hmm. We have the (allegedly) same VS version in Cirrus CI, and it's
never shown a problem like this.

CI uses the latest VS 2019 (v16.11.48), it looks like buildfarm member
drongo uses VS 2019 v16.3.1. I created a custom Windows VM with the
same VS 2019 version (v16.3.1) at the drongo and CI failed with the
same error [1].

Huh. Can we trawl the release notes for VS and see if this was
acknowledged as a bug fix, and if so when did it happen? I think
whether we can say "get a newer compiler" depends in part on how
long it's been fixed.

I tried doing that now, but didn't find anything fitting.

But this one [0]https://learn.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-170 seems to indicate you might need at least 16.5 for this.

Also, there is the support timeline [1]https://learn.microsoft.com/en-us/visualstudio/releases/2019/servicing-vs2019 that shows that anything older
than 16.11.* is way out of support.

[0]: https://learn.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-170
https://learn.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-170

[1]: https://learn.microsoft.com/en-us/visualstudio/releases/2019/servicing-vs2019
https://learn.microsoft.com/en-us/visualstudio/releases/2019/servicing-vs2019

#16Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#15)
Re: C11 / VS 2019

Peter Eisentraut <peter@eisentraut.org> writes:

On 07.07.25 16:13, Tom Lane wrote:

Huh. Can we trawl the release notes for VS and see if this was
acknowledged as a bug fix, and if so when did it happen?

But this one [0] seems to indicate you might need at least 16.5 for this.

Ah, that says

Starting in Visual Studio 2019 version 16.5, preprocessor support
for the C++20 standard is feature-complete. These changes are
available by using the /Zc:preprocessor compiler switch.

The reference to C++20 is a bit confusing in this context; does C++
really have a different preprocessor? But anyway, the support matrix
seems like a convincing argument that we don't have to support 16.3.
If Andrew is willing to update drongo, I'm content to leave it at
that.

regards, tom lane

#17Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#16)
Re: C11 / VS 2019

On 2025-07-07 Mo 12:01 PM, Tom Lane wrote:

Peter Eisentraut <peter@eisentraut.org> writes:

On 07.07.25 16:13, Tom Lane wrote:

Huh. Can we trawl the release notes for VS and see if this was
acknowledged as a bug fix, and if so when did it happen?

But this one [0] seems to indicate you might need at least 16.5 for this.

Ah, that says

Starting in Visual Studio 2019 version 16.5, preprocessor support
for the C++20 standard is feature-complete. These changes are
available by using the /Zc:preprocessor compiler switch.

The reference to C++20 is a bit confusing in this context; does C++
really have a different preprocessor? But anyway, the support matrix
seems like a convincing argument that we don't have to support 16.3.
If Andrew is willing to update drongo, I'm content to leave it at
that.

It's done and running. Testing before I re-enabled the animal it shows
it was happy.

cheers

andrew

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

#18Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#17)
Re: C11 / VS 2019

Andrew Dunstan <andrew@dunslane.net> writes:

It's done and running. Testing before I re-enabled the animal it shows
it was happy.

In the no-good-deed-goes-unpunished department ... drongo is now spewing
a boatload of these warnings:

C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\um\\winbase.h(9305): warning C5105: macro expansion producing 'defined' has undefined behavior

Looks like this comes out once per .c file -- probably it's
in an inclusion from <windows.h>. Dunno if there's anything
we can do but ignore it. I wonder though why we have not seen
this on other buildfarm animals.

regards, tom lane

#19Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#18)
Re: C11 / VS 2019

On 2025-07-08 Tu 3:45 PM, Tom Lane wrote:

Andrew Dunstan <andrew@dunslane.net> writes:

It's done and running. Testing before I re-enabled the animal it shows
it was happy.

In the no-good-deed-goes-unpunished department ... drongo is now spewing
a boatload of these warnings:

C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\um\\winbase.h(9305): warning C5105: macro expansion producing 'defined' has undefined behavior

Looks like this comes out once per .c file -- probably it's
in an inclusion from <windows.h>. Dunno if there's anything
we can do but ignore it. I wonder though why we have not seen
this on other buildfarm animals.

*sigh*

will investigate.

cheers

andrew

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

#20Andrew Dunstan
andrew@dunslane.net
In reply to: Andrew Dunstan (#19)
Re: C11 / VS 2019

On 2025-07-08 Tu 4:10 PM, Andrew Dunstan wrote:

On 2025-07-08 Tu 3:45 PM, Tom Lane wrote:

Andrew Dunstan <andrew@dunslane.net> writes:

It's done and running. Testing before I re-enabled the animal it shows
it was happy.

In the no-good-deed-goes-unpunished department ... drongo is now spewing
a boatload of these warnings:

C:\\Program Files (x86)\\Windows
Kits\\10\\include\\10.0.18362.0\\um\\winbase.h(9305): warning C5105:
macro expansion producing 'defined' has undefined behavior

Looks like this comes out once per .c file -- probably it's
in an inclusion from <windows.h>.  Dunno if there's anything
we can do but ignore it.  I wonder though why we have not seen
this on other buildfarm animals.

*sigh*

will investigate.

No grand insights yet. I note that this is not occurring on the back
branches.

Here's the MS page describing the error:
https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/c5105?view=msvc-170

The relevant portion of the winbase.h file appears to be:

/*
To turn off/hide the contents of this file:
 #define
MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS 0
*/

#if
!defined(MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS)
#define
MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS
(_WIN32_WINNT >= 0x0502 || !defined(_WINBASE_))
#endif

#if
MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS
/* { */

The last line is 9305.

I don't think we have any other VS 2019 machines in the buildfarm. I can
try installing VS 2022, which hamerkop seems to be running without
producing the error.

cheers

andrew

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

#21Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#20)
Re: C11 / VS 2019

Andrew Dunstan <andrew@dunslane.net> writes:

On 2025-07-08 Tu 4:10 PM, Andrew Dunstan wrote:

On 2025-07-08 Tu 3:45 PM, Tom Lane wrote:

In the no-good-deed-goes-unpunished department ... drongo is now spewing
a boatload of these warnings:

C:\\Program Files (x86)\\Windows
Kits\\10\\include\\10.0.18362.0\\um\\winbase.h(9305): warning C5105:
macro expansion producing 'defined' has undefined behavior

The relevant portion of the winbase.h file appears to be:

#define
MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS
(_WIN32_WINNT >= 0x0502 || !defined(_WINBASE_))

Hmm ... I don't pretend to be enough of a C language lawyer to know
whether this should have undefined behavior per spec, but it surely
does meet the conditions stated in the warning message.

I wonder if we should do what it says here:

/*
To turn off/hide the contents of this file:
 #define
MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS 0
*/

I don't think we have any other VS 2019 machines in the buildfarm. I can
try installing VS 2022, which hamerkop seems to be running without
producing the error.

That would amount to desupporting VS 2019, which I'm not sure we want
to do yet. I don't have a huge problem with ignoring this warning.

regards, tom lane

#22Andres Freund
andres@anarazel.de
In reply to: Tom Lane (#21)
Re: C11 / VS 2019

Hi,

On 2025-07-09 16:10:25 -0400, Tom Lane wrote:

Andrew Dunstan <andrew@dunslane.net> writes:

/*
To turn off/hide the contents of this file:
�#define
MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS 0
*/

I don't think we have any other VS 2019 machines in the buildfarm. I can
try installing VS 2022, which hamerkop seems to be running without
producing the error.

That would amount to desupporting VS 2019, which I'm not sure we want
to do yet. I don't have a huge problem with ignoring this warning.

FWIW, my understanding is that headers like winbase.h aren't part of the
compiler but part of the "SDK". And there are SDKs targetting different OS
versions, and different versions can be installed for the same or different
compiler versions. So it's quite possible that this is a question of the
target SDK version, rather than the OS version.

hamerkop:
C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.22621.0\\\\um\\windows.h

drongo:
C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\um\\windows.h

And with that trail, I found
https://developer.microsoft.com/en-us/windows/downloads/windows-SDK/

which says, about Windows 10 SDK, Version 2104:

SDK headers have been updated to address errors when compiling using the
standard-conformant C preprocessor in the MSVC compiler cl.exe
(/Zc:preprocessor, introduced in VS 2019 v16.6).

Which seems likely to describe precisely what we're seeing?

Greetings,

Andres Freund

PS: Wonder if we should make the SDK version visible in meson setup...

#23Andrew Dunstan
andrew@dunslane.net
In reply to: Andres Freund (#22)
Re: C11 / VS 2019

On 2025-07-09 We 4:51 PM, Andres Freund wrote:

Hi,

On 2025-07-09 16:10:25 -0400, Tom Lane wrote:

Andrew Dunstan<andrew@dunslane.net> writes:

/*
To turn off/hide the contents of this file:
 #define
MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS 0
*/
I don't think we have any other VS 2019 machines in the buildfarm. I can
try installing VS 2022, which hamerkop seems to be running without
producing the error.

That would amount to desupporting VS 2019, which I'm not sure we want
to do yet. I don't have a huge problem with ignoring this warning.

FWIW, my understanding is that headers like winbase.h aren't part of the
compiler but part of the "SDK". And there are SDKs targetting different OS
versions, and different versions can be installed for the same or different
compiler versions. So it's quite possible that this is a question of the
target SDK version, rather than the OS version.

hamerkop:
C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.22621.0\\\\um\\windows.h

drongo:
C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\um\\windows.h

And with that trail, I found
https://developer.microsoft.com/en-us/windows/downloads/windows-SDK/

which says, about Windows 10 SDK, Version 2104:

SDK headers have been updated to address errors when compiling using the
standard-conformant C preprocessor in the MSVC compiler cl.exe
(/Zc:preprocessor, introduced in VS 2019 v16.6).

Which seems likely to describe precisely what we're seeing?

Yeah, installing the latest SDK seems to have done the trick.

PS: Wonder if we should make the SDK version visible in meson setup...

Maybe.

cheers

andrew

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

#24Peter Eisentraut
peter@eisentraut.org
In reply to: Peter Eisentraut (#1)
2 attachment(s)
Re: C11 / VS 2019

Ok, now that we have seemingly stabilized the VS 2019 upgrade, here is
the next patch set to actually raise the compiler requirement to C11.

Viewed from very far away, this just adjusts the existing places that
say C99 and replaces them with a C11 analogue.

The details are a bit of a longer story.

configure.ac previously used AC_PROG_CC_C99 to activate C99. But there
is no AC_PROG_CC_C11 in Autoconf 2.69, because it's too old. Also,
post-2.69, the AC_PROG_CC_Cnn macros were deprecated and AC_PROG_CC
activates the last supported C mode.

So, at this point, we could "just" update the Autoconf version requirement.

But somehow I don't feel like doing that, as it's just another
non-trivial project to negotiate. Instead, I just hand-coded some test
for C11 using some inspiration from later Autoconf versions. But
instead of writing an elaborate test program that exercises many
different features, I kept it simple and just check __STDC_VERSION__,
which should be good enough in practice.

(If someone later wanted to update the Autoconf version, they could just
delete that code again.)

In meson.build, there is an existing hand-coded C99 test that I update
to C11, but again just checking for __STDC_VERSION__.

I also moved the test a bit earlier in meson.build, as a separate patch,
because between the place where the compiler is first set up and the
place where we detected the C99 options, if any, there were already some
tests run that use the compiler. I don't think this was a big problem
in practice, but it seems a bit incorrect, so it makes sense to correct it.

Note, we don't use the "official" way to set the C standard in Meson
using the c_std project option, because that is IMO impossible to use
correctly (see <https://github.com/mesonbuild/meson/issues/14717&gt;).
(Well, that is my reason now. I don't know what the reason was
previously.) The disadvantage is that meson will complain like

meson.build:3013: WARNING: Consider using the built-in option for
language standard version instead of using "/std:c11".

But you will get warnings from meson with MSVC anyway, so, uh, another
one will not make a significant difference. (Also, this issue exists
with the existing C99 detection code as well, except that in practice
you don't need an option, so the warning does not appear.)

Note that gcc and clang switched to C11 by default a long time ago
(gcc-5 and clang-3.6), so for most users all these tests won't need to
do anything. If you want to test it, you could simulate an older
default like

./configure CC='gcc -std=c99'

and then the test should decide that it needs to add another option to
override the C mode.

Attachments:

v1-0001-meson-Move-C99-test-earlier.patchtext/plain; charset=UTF-8; name=v1-0001-meson-Move-C99-test-earlier.patchDownload
From ee5fd55153d5f407b1062e2ce5ff741a7d503c44 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Fri, 18 Jul 2025 13:26:40 +0300
Subject: [PATCH v1 1/2] meson: Move C99 test earlier

That way, if any command-line options are needed, subsequent tests
will also use them.
---
 meson.build | 85 ++++++++++++++++++++++++++---------------------------
 1 file changed, 42 insertions(+), 43 deletions(-)

diff --git a/meson.build b/meson.build
index 5365aaf95e6..0b9d7224cd6 100644
--- a/meson.build
+++ b/meson.build
@@ -550,6 +550,48 @@ dir_doc_extension = dir_doc / 'extension'
 # used, they need to be added to test_c_args as well.
 ###############################################################
 
+# Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
+# unnecessarily, because we optionally rely on newer features.
+c99_test = '''
+#include <stdbool.h>
+#include <complex.h>
+#include <tgmath.h>
+#include <inttypes.h>
+
+struct named_init_test {
+  int a;
+  int b;
+};
+
+extern void structfunc(struct named_init_test);
+
+int main(int argc, char **argv)
+{
+  struct named_init_test nit = {
+    .a = 3,
+    .b = 5,
+  };
+
+  for (int loop_var = 0; loop_var < 3; loop_var++)
+  {
+    nit.a += nit.b;
+  }
+
+  structfunc((struct named_init_test){1, 0});
+
+  return nit.a != 0;
+}
+'''
+
+if not cc.compiles(c99_test, name: 'c99')
+  if cc.compiles(c99_test, name: 'c99 with -std=c99', args: ['-std=c99'])
+    cflags += '-std=c99'
+  else
+    error('C compiler does not support C99')
+  endif
+endif
+
+
 postgres_inc = [include_directories(postgres_inc_d)]
 test_lib_d = postgres_lib_d
 test_c_args = cppflags + cflags
@@ -1704,49 +1746,6 @@ endif
 # Compiler tests
 ###############################################################
 
-# Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
-# unnecessarily, because we optionally rely on newer features.
-c99_test = '''
-#include <stdbool.h>
-#include <complex.h>
-#include <tgmath.h>
-#include <inttypes.h>
-
-struct named_init_test {
-  int a;
-  int b;
-};
-
-extern void structfunc(struct named_init_test);
-
-int main(int argc, char **argv)
-{
-  struct named_init_test nit = {
-    .a = 3,
-    .b = 5,
-  };
-
-  for (int loop_var = 0; loop_var < 3; loop_var++)
-  {
-    nit.a += nit.b;
-  }
-
-  structfunc((struct named_init_test){1, 0});
-
-  return nit.a != 0;
-}
-'''
-
-if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
-  if cc.compiles(c99_test, name: 'c99 with -std=c99',
-        args: test_c_args + ['-std=c99'])
-    test_c_args += '-std=c99'
-    cflags += '-std=c99'
-  else
-    error('C compiler does not support C99')
-  endif
-endif
-
 if host_machine.endian() == 'big'
   cdata.set('WORDS_BIGENDIAN', 1)
 endif

base-commit: 5022ff250eeba2367fb4e74fed8ee65bcddb6c99
-- 
2.50.0

v1-0002-Raise-C-requirement-to-C11.patchtext/plain; charset=UTF-8; name=v1-0002-Raise-C-requirement-to-C11.patchDownload
From 316cf64618bda13706fbc513e76938b4a8946239 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Fri, 18 Jul 2025 13:53:52 +0300
Subject: [PATCH v1 2/2] Raise C requirement to C11

This changes configure and meson.build to require at least C11,
instead of the previous C99.  The installation documentation is
updated accordingly.

configure.ac previously used AC_PROG_CC_C99 to activate C99.  But
there is no AC_PROG_CC_C11 in Autoconf 2.69, because it's too
old.  (Also, post-2.69, the AC_PROG_CC_Cnn macros were deprecated and
AC_PROG_CC activates the last supported C mode.)  We could update the
required Autoconf version, but that might be a separate project that
no one wants to undertake at the moment.  Instead, we open-code the
test for C11 using some inspiration from later Autoconf versions.  But
instead of writing an elaborate test program, we keep it simple and
just check __STDC_VERSION__, which should be good enough in practice.

In meson.build, we update the existing C99 test to C11, but again we
just check for __STDC_VERSION__.

This also removes the separate option for the conforming preprocessor
on MSVC, added by commit 8fd9bb1d965, since that is activated
automatically in C11 mode.

Note, we don't use the "official" way to set the C standard in Meson
using the c_std project option, because that is impossible to use
correctly (see <https://github.com/mesonbuild/meson/issues/14717>).
---
 configure                      | 204 +++++----------------------------
 configure.ac                   |  29 ++++-
 doc/src/sgml/installation.sgml |   7 +-
 doc/src/sgml/sources.sgml      |  12 +-
 meson.build                    |  59 ++++------
 5 files changed, 83 insertions(+), 228 deletions(-)

diff --git a/configure b/configure
index 6d7c22e153f..3dca5fe340a 100755
--- a/configure
+++ b/configure
@@ -4475,190 +4475,49 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
-   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
-$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
-if ${ac_cv_prog_cc_c99+:} false; then :
+
+# Detect option needed for C11
+# loosely modeled after code in later Autoconf versions
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C11" >&5
+$as_echo_n "checking for $CC option to accept ISO C11... " >&6; }
+
+if ${pgac_cv_prog_cc_c11+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  ac_cv_prog_cc_c99=no
-ac_save_CC=$CC
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  pgac_cv_prog_cc_c11=no
+pgac_save_CC=$CC
+for pgac_arg in '' '-std=gnu11' '-std=c11'; do
+  CC="$pgac_save_CC $pgac_arg"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <stdio.h>
-
-// Check varargs macros.  These examples are taken from C99 6.10.3.5.
-#define debug(...) fprintf (stderr, __VA_ARGS__)
-#define showlist(...) puts (#__VA_ARGS__)
-#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
-static void
-test_varargs_macros (void)
-{
-  int x = 1234;
-  int y = 5678;
-  debug ("Flag");
-  debug ("X = %d\n", x);
-  showlist (The first, second, and third items.);
-  report (x>y, "x is %d but y is %d", x, y);
-}
-
-// Check long long types.
-#define BIG64 18446744073709551615ull
-#define BIG32 4294967295ul
-#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
-#if !BIG_OK
-  your preprocessor is broken;
-#endif
-#if BIG_OK
-#else
-  your preprocessor is broken;
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
 #endif
-static long long int bignum = -9223372036854775807LL;
-static unsigned long long int ubignum = BIG64;
-
-struct incomplete_array
-{
-  int datasize;
-  double data[];
-};
-
-struct named_init {
-  int number;
-  const wchar_t *name;
-  double average;
-};
-
-typedef const char *ccp;
-
-static inline int
-test_restrict (ccp restrict text)
-{
-  // See if C++-style comments work.
-  // Iterate through items via the restricted pointer.
-  // Also check for declarations in for loops.
-  for (unsigned int i = 0; *(text+i) != '\0'; ++i)
-    continue;
-  return 0;
-}
-
-// Check varargs and va_copy.
-static void
-test_varargs (const char *format, ...)
-{
-  va_list args;
-  va_start (args, format);
-  va_list args_copy;
-  va_copy (args_copy, args);
-
-  const char *str;
-  int number;
-  float fnumber;
-
-  while (*format)
-    {
-      switch (*format++)
-	{
-	case 's': // string
-	  str = va_arg (args_copy, const char *);
-	  break;
-	case 'd': // int
-	  number = va_arg (args_copy, int);
-	  break;
-	case 'f': // float
-	  fnumber = va_arg (args_copy, double);
-	  break;
-	default:
-	  break;
-	}
-    }
-  va_end (args_copy);
-  va_end (args);
-}
-
-int
-main ()
-{
-
-  // Check bool.
-  _Bool success = false;
-
-  // Check restrict.
-  if (test_restrict ("String literal") == 0)
-    success = true;
-  char *restrict newvar = "Another string";
-
-  // Check varargs.
-  test_varargs ("s, d' f .", "string", 65, 34.234);
-  test_varargs_macros ();
-
-  // Check flexible array members.
-  struct incomplete_array *ia =
-    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
-  ia->datasize = 10;
-  for (int i = 0; i < ia->datasize; ++i)
-    ia->data[i] = i * 1.234;
-
-  // Check named initializers.
-  struct named_init ni = {
-    .number = 34,
-    .name = L"Test wide string",
-    .average = 543.34343,
-  };
-
-  ni.number = 58;
-
-  int dynamic_array[ni.number];
-  dynamic_array[ni.number - 1] = 543;
-
-  // work around unused variable warnings
-  return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
-	  || dynamic_array[ni.number - 1] != 543);
-
-  ;
-  return 0;
-}
 _ACEOF
-for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
-do
-  CC="$ac_save_CC $ac_arg"
-  if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_prog_cc_c99=$ac_arg
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_prog_cc_c11=$pgac_arg
 fi
-rm -f core conftest.err conftest.$ac_objext
-  test "x$ac_cv_prog_cc_c99" != "xno" && break
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test x"$pgac_cv_prog_cc_c11" != x"no" && break
 done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
-
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c99" in
-  x)
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
-  xno)
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
-  *)
-    CC="$CC $ac_cv_prog_cc_c99"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
-$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c99" != xno; then :
-
+CC=$pgac_save_CC
 fi
 
 
-
-# Error out if the compiler does not support C99, as the codebase
-# relies on that.
-if test "$ac_cv_prog_cc_c99" = no; then
-    as_fn_error $? "C compiler \"$CC\" does not support C99" "$LINENO" 5
+if test x"$pgac_cv_prog_cc_c11" = x"no"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; }
+  as_fn_error $? "C compiler \"$CC\" does not support C11" "$LINENO" 5
+elif test x"$pgac_cv_prog_cc_c11" = x""; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_cc_c11" >&5
+$as_echo "$pgac_cv_prog_cc_c11" >&6; }
+  CC="$CC $pgac_cv_prog_cc_c11"
 fi
 
+
 ac_ext=cpp
 ac_cpp='$CXXCPP $CPPFLAGS'
 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -4920,7 +4779,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 # Check if it's Intel's compiler, which (usually) pretends to be gcc,
 # but has idiosyncrasies of its own.  We assume icc will define
 # __INTEL_COMPILER regardless of CFLAGS.
-
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
diff --git a/configure.ac b/configure.ac
index c2877e36935..9d84a410916 100644
--- a/configure.ac
+++ b/configure.ac
@@ -364,14 +364,33 @@ pgac_cc_list="gcc cc"
 pgac_cxx_list="g++ c++"
 
 AC_PROG_CC([$pgac_cc_list])
-AC_PROG_CC_C99()
 
-# Error out if the compiler does not support C99, as the codebase
-# relies on that.
-if test "$ac_cv_prog_cc_c99" = no; then
-    AC_MSG_ERROR([C compiler "$CC" does not support C99])
+# Detect option needed for C11
+# loosely modeled after code in later Autoconf versions
+AC_MSG_CHECKING([for $CC option to accept ISO C11])
+AC_CACHE_VAL([pgac_cv_prog_cc_c11],
+[pgac_cv_prog_cc_c11=no
+pgac_save_CC=$CC
+for pgac_arg in '' '-std=gnu11' '-std=c11'; do
+  CC="$pgac_save_CC $pgac_arg"
+  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif]])], [[pgac_cv_prog_cc_c11=$pgac_arg]])
+  test x"$pgac_cv_prog_cc_c11" != x"no" && break
+done
+CC=$pgac_save_CC])
+
+if test x"$pgac_cv_prog_cc_c11" = x"no"; then
+  AC_MSG_RESULT([unsupported])
+  AC_MSG_ERROR([C compiler "$CC" does not support C11])
+elif test x"$pgac_cv_prog_cc_c11" = x""; then
+  AC_MSG_RESULT([none needed])
+else
+  AC_MSG_RESULT([$pgac_cv_prog_cc_c11])
+  CC="$CC $pgac_cv_prog_cc_c11"
 fi
 
+
 AC_PROG_CXX([$pgac_cxx_list])
 
 # Check if it's Intel's compiler, which (usually) pretends to be gcc,
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 8e5da767c48..a4ad80a6782 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -71,10 +71,9 @@ <title>Requirements</title>
 
     <listitem>
      <para>
-      You need an <acronym>ISO</acronym>/<acronym>ANSI</acronym> C compiler (at least
-      C99-compliant). Recent
-      versions of <productname>GCC</productname> are recommended, but
-      <productname>PostgreSQL</productname> is known to build using a wide variety
+      You need a C compiler that supports at least C11.  Recent versions of
+      <productname>GCC</productname> are recommended, but
+      <productname>PostgreSQL</productname> is known to build using a variety
       of compilers from different vendors.
      </para>
     </listitem>
diff --git a/doc/src/sgml/sources.sgml b/doc/src/sgml/sources.sgml
index fa68d4d024a..261f19b3534 100644
--- a/doc/src/sgml/sources.sgml
+++ b/doc/src/sgml/sources.sgml
@@ -907,12 +907,12 @@ <title>Miscellaneous Coding Conventions</title>
     <title>C Standard</title>
     <para>
      Code in <productname>PostgreSQL</productname> should only rely on language
-     features available in the C99 standard. That means a conforming
-     C99 compiler has to be able to compile postgres, at least aside
+     features available in the C11 standard. That means a conforming
+     C11 compiler has to be able to compile postgres, at least aside
      from a few platform dependent pieces.
     </para>
     <para>
-     A few features included in the C99 standard are, at this time, not
+     A few features included in the C11 standard are, at this time, not
      permitted to be used in core <productname>PostgreSQL</productname>
      code. This currently includes variable length arrays, intermingled
      declarations and code, <literal>//</literal> comments, universal
@@ -924,13 +924,11 @@ <title>C Standard</title>
      features can be used, if a fallback is provided.
     </para>
     <para>
-     For example <literal>_Static_assert()</literal> and
+     For example <literal>typeof()</literal> and
      <literal>__builtin_constant_p</literal> are currently used, even though
      they are from newer revisions of the C standard and a
      <productname>GCC</productname> extension respectively. If not available
-     we respectively fall back to using a C99 compatible replacement that
-     performs the same checks, but emits rather cryptic messages and do not
-     use <literal>__builtin_constant_p</literal>.
+     we do not use them.
     </para>
    </simplesect>
 
diff --git a/meson.build b/meson.build
index 0b9d7224cd6..5713a366464 100644
--- a/meson.build
+++ b/meson.build
@@ -280,10 +280,6 @@ elif host_system == 'windows'
     # define before including <time.h> for getting localtime_r() etc. on MinGW
     cppflags += '-D_POSIX_C_SOURCE'
   endif
-  if cc.get_id() == 'msvc'
-    # required for VA_ARGS_NARGS() in c.h; requires VS 2019
-    cppflags += '/Zc:preprocessor'
-  endif
 
   export_file_format = 'win'
   export_file_suffix = 'def'
@@ -550,44 +546,29 @@ dir_doc_extension = dir_doc / 'extension'
 # used, they need to be added to test_c_args as well.
 ###############################################################
 
-# Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
-# unnecessarily, because we optionally rely on newer features.
-c99_test = '''
-#include <stdbool.h>
-#include <complex.h>
-#include <tgmath.h>
-#include <inttypes.h>
-
-struct named_init_test {
-  int a;
-  int b;
-};
-
-extern void structfunc(struct named_init_test);
-
-int main(int argc, char **argv)
-{
-  struct named_init_test nit = {
-    .a = 3,
-    .b = 5,
-  };
-
-  for (int loop_var = 0; loop_var < 3; loop_var++)
-  {
-    nit.a += nit.b;
-  }
-
-  structfunc((struct named_init_test){1, 0});
-
-  return nit.a != 0;
-}
+# Do we need an option to enable C11?
+c11_test = '''
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
 '''
 
-if not cc.compiles(c99_test, name: 'c99')
-  if cc.compiles(c99_test, name: 'c99 with -std=c99', args: ['-std=c99'])
-    cflags += '-std=c99'
+if not cc.compiles(c11_test, name: 'C11')
+  c11_ok = false
+  if cc.get_id() == 'msvc'
+    c11_test_args = ['/std:c11']
   else
-    error('C compiler does not support C99')
+    c11_test_args = ['-std=gnu11', '-std=c11']
+  endif
+  foreach arg : c11_test_args
+    if cc.compiles(c11_test, name: 'C11 with @0@'.format(arg), args: [arg])
+      c11_ok = true
+      cflags += arg
+      break
+    endif
+  endforeach
+  if not c11_ok
+    error('C compiler does not support C11')
   endif
 endif
 
-- 
2.50.0

#25David Rowley
dgrowleyml@gmail.com
In reply to: Peter Eisentraut (#24)
Re: C11 / VS 2019

On Fri, 18 Jul 2025 at 23:12, Peter Eisentraut <peter@eisentraut.org> wrote:

Note that gcc and clang switched to C11 by default a long time ago
(gcc-5 and clang-3.6), so for most users all these tests won't need to
do anything. If you want to test it, you could simulate an older
default like

./configure CC='gcc -std=c99'

and then the test should decide that it needs to add another option to
override the C mode.

This isn't quite my area of expertise, but I've been reviewing the
patch and testing. I don't see any issues with VS2022.

On Linux, doing a bit more testing using meson and clang, I tried with
CC=clang CFLAGS=-std=c99 . I get:

Checking if "C11" compiles: NO
Checking if "C11 with -std=gnu11" compiles: YES

But later:

FAILED: src/backend/parser/parser.a.p/meson-generated_.._gram.c.o
clang -Isrc/backend/parser/parser.a.p -Isrc/backend/parser
-I../src/backend/parser -Isrc/include -I../src/include
-I/usr/include/libxml2 -fdiagnostics-color=always
-D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O2 -g -std=gnu11
-fno-strict-aliasing -fwrapv -fexcess-precision=standard -D_GNU_SOURCE
-Wmissing-prototypes -Wpointer-arith -Werror=vla
-Werror=unguarded-availability-new -Wendif-labels
-Wmissing-format-attribute -Wcast-function-type -Wformat-security
-Wdeclaration-after-statement -Wmissing-variable-declarations
-Wno-unused-command-line-argument -Wno-compound-token-split-by-macro
-Wno-format-truncation -Wno-cast-function-type-strict -std=c99 -fPIC
-pthread -DBUILDING_DLL -MD -MQ
src/backend/parser/parser.a.p/meson-generated_.._gram.c.o -MF
src/backend/parser/parser.a.p/meson-generated_.._gram.c.o.d -o
src/backend/parser/parser.a.p/meson-generated_.._gram.c.o -c
src/backend/parser/gram.c
../src/backend/parser/gram.y:19362:12: error: call to undeclared
function 'typeof'; ISO C99 and later do not support implicit function
declarations [-Wimplicit-function-declaration]
19362 | result = copyObject(p->argType);

It's not quite clear to me why the C11 test passes but then the build
fails. I assumed the mixed -std=gnu11 then -std=c99 are passed in the
test as well. I don't know how to check.

Strangely, if I swap the order of the c11_test_args so the test tries
and uses -std=c11 first, it works ok.

@@ -558,7 +558,7 @@ if not cc.compiles(c11_test, name: 'C11')
   if cc.get_id() == 'msvc'
     c11_test_args = ['/std:c11']
   else
-    c11_test_args = ['-std=gnu11', '-std=c11']
+    c11_test_args = ['-std=c11', '-std=gnu11']
   endif

Perhaps this isn't an issue. I just did this to try to test what would
happen in a compiler that defaulted to c99. I'm unsure how clang
processes conflicting compiler flags.

David

#26Tom Lane
tgl@sss.pgh.pa.us
In reply to: David Rowley (#25)
Re: C11 / VS 2019

David Rowley <dgrowleyml@gmail.com> writes:

On Fri, 18 Jul 2025 at 23:12, Peter Eisentraut <peter@eisentraut.org> wrote:

Note that gcc and clang switched to C11 by default a long time ago
(gcc-5 and clang-3.6), so for most users all these tests won't need to
do anything. If you want to test it, you could simulate an older
default like
./configure CC='gcc -std=c99'

On Linux, doing a bit more testing using meson and clang, I tried with
CC=clang CFLAGS=-std=c99 . I get:

Note that that's not what Peter suggested. That leads to

FAILED: src/backend/parser/parser.a.p/meson-generated_.._gram.c.o
clang -Isrc/backend/parser/parser.a.p -Isrc/backend/parser
-I../src/backend/parser -Isrc/include -I../src/include
-I/usr/include/libxml2 -fdiagnostics-color=always
-D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O2 -g -std=gnu11

^^^^^^^^^^

-fno-strict-aliasing -fwrapv -fexcess-precision=standard -D_GNU_SOURCE
-Wmissing-prototypes -Wpointer-arith -Werror=vla
-Werror=unguarded-availability-new -Wendif-labels
-Wmissing-format-attribute -Wcast-function-type -Wformat-security
-Wdeclaration-after-statement -Wmissing-variable-declarations
-Wno-unused-command-line-argument -Wno-compound-token-split-by-macro
-Wno-format-truncation -Wno-cast-function-type-strict -std=c99 -fPIC

^^^^^^^^

-pthread -DBUILDING_DLL -MD -MQ
src/backend/parser/parser.a.p/meson-generated_.._gram.c.o -MF
src/backend/parser/parser.a.p/meson-generated_.._gram.c.o.d -o
src/backend/parser/parser.a.p/meson-generated_.._gram.c.o -c
src/backend/parser/gram.c

Apparently we are not being too consistent about the order of
user-specified CFLAGS versus ones added by configuration?
The configuration test must have put the user CFLAGS first.

Strangely, if I swap the order of the c11_test_args so the test tries
and uses -std=c11 first, it works ok.

That is indeed weird.

regards, tom lane

#27David Rowley
dgrowleyml@gmail.com
In reply to: Tom Lane (#26)
Re: C11 / VS 2019

On Wed, 30 Jul 2025 at 00:57, Tom Lane <tgl@sss.pgh.pa.us> wrote:

David Rowley <dgrowleyml@gmail.com> writes:

On Fri, 18 Jul 2025 at 23:12, Peter Eisentraut <peter@eisentraut.org> wrote:

Note that gcc and clang switched to C11 by default a long time ago
(gcc-5 and clang-3.6), so for most users all these tests won't need to
do anything. If you want to test it, you could simulate an older
default like
./configure CC='gcc -std=c99'

On Linux, doing a bit more testing using meson and clang, I tried with
CC=clang CFLAGS=-std=c99 . I get:

Note that that's not what Peter suggested. That leads to

OK, thanks. There are no issues when I use CC="clang -std=c99" meson setup ...

David

#28Peter Eisentraut
peter@eisentraut.org
In reply to: David Rowley (#25)
Re: C11 / VS 2019

On 29.07.25 11:46, David Rowley wrote:

../src/backend/parser/gram.y:19362:12: error: call to undeclared
function 'typeof'; ISO C99 and later do not support implicit function
declarations [-Wimplicit-function-declaration]
19362 | result = copyObject(p->argType);

It's not quite clear to me why the C11 test passes but then the build
fails. I assumed the mixed -std=gnu11 then -std=c99 are passed in the
test as well. I don't know how to check.

The equivalent of config.log is in build/meson-logs/meson-log.txt.

Strangely, if I swap the order of the c11_test_args so the test tries
and uses -std=c11 first, it works ok.

@@ -558,7 +558,7 @@ if not cc.compiles(c11_test, name: 'C11')
if cc.get_id() == 'msvc'
c11_test_args = ['/std:c11']
else
-    c11_test_args = ['-std=gnu11', '-std=c11']
+    c11_test_args = ['-std=c11', '-std=gnu11']
endif

The situation is that with my original code, the C11 test picks the
option -std=gnu11, and the typeof() test is then run with

cc ... -std=c99 ... -std=gnu11

which makes the test for typeof() pass (last option wins), but the
actual build is run with

cc ... -std=gnu11 ... -std=c99

which disables the availability of typeof(), but pg_config.h says it's
available, so the compilation fails.

If you flip the order of the arguments to be tested, then the C11 test
picks -std=c11, and the typeof() test runs with

cc ... -std=c99 ... -std=c11

which will fail to detect typeof() (since it's neither in strict C99 nor
in strict C11), and then later the actual compilation won't see typeof()
at all.

Ideally, the tests should be run with the arguments in the same order as
the actual compilation, but I don't think meson is equipped to support
that. I've been digging around the code and the documentation and don't
find any mention about the *order* of the arguments supplied by various
means like global, project, per-target, tests, environment, etc. So I
don't think there is any hope right now to sanely support "competing"
arguments supplied from different sources.

(One might have valid concerns about -I and -L options, but that's a
different potential topic.)

But since this is not how the patch was supposed to be used anyway, this
shouldn't be a problem in practice. It's not a new problem anyway.

FWIW, if you do this with autoconf, you get an early failure:

./configure CFLAGS='-std=c90'
...
checking for gcc option to accept ISO C89... none needed
checking for gcc option to accept ISO C99... unsupported
configure: error: C compiler "gcc" does not support C99

So putting "-std=" options into CFLAGS was never working.

#29Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#28)
Re: C11 / VS 2019

Peter Eisentraut <peter@eisentraut.org> writes:

Ideally, the tests should be run with the arguments in the same order as
the actual compilation, but I don't think meson is equipped to support
that.

Egad. We are putting our faith in a build system that can't get
that right? Order of switches is frequently critical.

regards, tom lane

#30Andres Freund
andres@anarazel.de
In reply to: Peter Eisentraut (#24)
Re: C11 / VS 2019

Hi,

On 2025-07-18 14:12:34 +0300, Peter Eisentraut wrote:

I also moved the test a bit earlier in meson.build, as a separate patch,
because between the place where the compiler is first set up and the place
where we detected the C99 options, if any, there were already some tests run
that use the compiler. I don't think this was a big problem in practice,
but it seems a bit incorrect, so it makes sense to correct it.

I distinctly dislike this. You mashed a compiler test in the middle of
something else, without updating any comments. We now do one compiler test
earlier, then dependency tests, and then other compiler tests. Doing anything
the order we do it in autoconf is an anti-argument, because the ordering we
use in autoconf is completely unintelligible.

Greetings,

Andres Freund

#31Peter Eisentraut
peter@eisentraut.org
In reply to: Andres Freund (#30)
Re: C11 / VS 2019

On 18.08.25 15:27, Andres Freund wrote:

On 2025-07-18 14:12:34 +0300, Peter Eisentraut wrote:

I also moved the test a bit earlier in meson.build, as a separate patch,
because between the place where the compiler is first set up and the place
where we detected the C99 options, if any, there were already some tests run
that use the compiler. I don't think this was a big problem in practice,
but it seems a bit incorrect, so it makes sense to correct it.

I distinctly dislike this. You mashed a compiler test in the middle of
something else, without updating any comments. We now do one compiler test
earlier, then dependency tests, and then other compiler tests.

I think these are different things. The C99 test is something that
potentially adds a compiler flag and changes the mode of the compiler.
So we need to do this first before we test anything else with the compiler.

The other compiler tests are just checking what the compiler is doing
and record the result. This does not affect subsequent tests. Ok,
there are some tests for warning flags and some -f options, but there
are also arguments to be made that these should be set before checking
external library headers for example.

So calling all of these compiler tests doesn't capture the necessary
distinction. I would think of these maybe as compiler flag tests versus
compiler characteristics tests.

Doing anything
the order we do it in autoconf is an anti-argument, because the ordering we
use in autoconf is completely unintelligible.

The point is that autoconf does the C-standard determination first,
before doing anything else with the compiler. That is clearly the
correct thing to do.

Btw., the ordering is documented at the top of configure.ac, but it has
surely degraded over time.

#32Peter Eisentraut
peter@eisentraut.org
In reply to: David Rowley (#27)
Re: C11 / VS 2019

On 30.07.25 00:11, David Rowley wrote:

On Wed, 30 Jul 2025 at 00:57, Tom Lane <tgl@sss.pgh.pa.us> wrote:

David Rowley <dgrowleyml@gmail.com> writes:

On Fri, 18 Jul 2025 at 23:12, Peter Eisentraut <peter@eisentraut.org> wrote:

Note that gcc and clang switched to C11 by default a long time ago
(gcc-5 and clang-3.6), so for most users all these tests won't need to
do anything. If you want to test it, you could simulate an older
default like
./configure CC='gcc -std=c99'

On Linux, doing a bit more testing using meson and clang, I tried with
CC=clang CFLAGS=-std=c99 . I get:

Note that that's not what Peter suggested. That leads to

OK, thanks. There are no issues when I use CC="clang -std=c99" meson setup ...

This has been committed. C11 is the default mode now.

David: You could rebase your other patch (about emulating
__builtin_constant_p) now.

Tom: You ought to update the configuration on the buildfarm members
longfin and sifaka from

'CC' => 'ccache clang -std=gnu99',

to

'CC' => 'ccache clang -std=gnu11',

for the master branch.

#33Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#32)
Re: C11 / VS 2019

Peter Eisentraut <peter@eisentraut.org> writes:

Tom: You ought to update the configuration on the buildfarm members
longfin and sifaka from
'CC' => 'ccache clang -std=gnu99',
to
'CC' => 'ccache clang -std=gnu11',
for the master branch.

Roger, will do.

regards, tom lane