postgres.git / summary / log / commit / refs
commit 476b35d4e311a3d77a550280d93393e518908b27
Author: Peter Eisentraut <peter@eisentraut.org>
Date: Tue Jan 20 15:24:57 2026 +0000
tests: Add a test C++ extension module
While we already test that our headers are valid C++ using
headerscheck, it turns out that the macros we define might still
expand to invalid C++ code. This adds a minimal test extension that
is compiled using C++ to test that it's actually possible to build and
run extensions written in C++. Future commits will improve C++
compatibility of some of our macros and add usage of them to this
extension make sure that they don't regress in the future.
The test module is for the moment disabled when using MSVC. In
particular, the use of designated initializers in PG_MODULE_MAGIC
would require C++20, for which we are currently not set up. (GCC and
Clang support it as extensions.) It is planned to fix this.
Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Discussion: https://www.postgresql.org/message-id/flat/CAGECzQR21OnnKiZO_1rLWO0-16kg1JBxnVq-wymYW0-_1cUNtg@mail.gmail.com
configure | 8 +++++
configure.ac | 7 ++++
src/Makefile.global.in | 2 ++
src/makefiles/meson.build | 2 ++
src/test/modules/Makefile | 6 ++++
src/test/modules/meson.build | 1 +
src/test/modules/test_cplusplusext/.gitignore | 3 ++
src/test/modules/test_cplusplusext/Makefile | 26 ++++++++++++++
src/test/modules/test_cplusplusext/README | 10 ++++++
.../expected/test_cplusplusext.out | 7 ++++
src/test/modules/test_cplusplusext/meson.build | 42 ++++++++++++++++++++++
.../test_cplusplusext/sql/test_cplusplusext.sql | 3 ++
.../test_cplusplusext/test_cplusplusext--1.0.sql | 8 +++++
.../test_cplusplusext/test_cplusplusext.control | 4 +++
.../test_cplusplusext/test_cplusplusext.cpp | 37 +++++++++++++++++++
15 files changed, 166 insertions(+)
diff --git a/configure b/configure
index fb6a4914b06..04eeb1a741c 100755
--- a/configure
+++ b/configure
@@ -760,6 +760,7 @@ CLANG
LLVM_CONFIG
AWK
with_llvm
+have_cxx
ac_ct_CXX
CXXFLAGS
CXX
@@ -4769,6 +4770,13 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_ct_CXX"; then
+ have_cxx=yes
+else
+ have_cxx=no
+fi
+
+
# 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.
diff --git a/configure.ac b/configure.ac
index d3febfe58f1..13c75170f7a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -387,6 +387,13 @@ fi
AC_PROG_CXX([$pgac_cxx_list])
+if test -n "$ac_ct_CXX"; then
+ have_cxx=yes
+else
+ have_cxx=no
+fi
+AC_SUBST(have_cxx)
+
# 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.
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 371cd7eba2c..947a2d79e29 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -280,6 +280,8 @@ PERMIT_DECLARATION_AFTER_STATEMENT = @PERMIT_DECLARATION_AFTER_STATEMENT@
PERMIT_MISSING_VARIABLE_DECLARATIONS = @PERMIT_MISSING_VARIABLE_DECLARATIONS@
CXXFLAGS = @CXXFLAGS@
+have_cxx = @have_cxx@
+
LLVM_CPPFLAGS = @LLVM_CPPFLAGS@
LLVM_CFLAGS = @LLVM_CFLAGS@
LLVM_CXXFLAGS = @LLVM_CXXFLAGS@
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index aa2f9a87b14..77f7a729cc2 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -118,6 +118,8 @@ pgxs_kv = {
'FLEXFLAGS': ' '.join(flex_flags),
'LIBS': var_libs,
+
+ 'have_cxx': have_cxx ? 'yes' : 'no',
}
if llvm.found()
diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index 4c6d56d97d8..44c7163c1cd 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -75,5 +75,11 @@ else
ALWAYS_SUBDIRS += ldap_password_func
endif
+ifeq ($(have_cxx),yes)
+SUBDIRS += test_cplusplusext
+else
+ALWAYS_SUBDIRS += test_cplusplusext
+endif
+
$(recurse)
$(recurse_always)
diff --git a/src/test/modules/meson.build b/src/test/modules/meson.build
index 1b31c5b98d6..2634a519935 100644
--- a/src/test/modules/meson.build
+++ b/src/test/modules/meson.build
@@ -21,6 +21,7 @@ subdir('test_bitmapset')
subdir('test_bloomfilter')
subdir('test_cloexec')
subdir('test_copy_callbacks')
+subdir('test_cplusplusext')
subdir('test_custom_rmgrs')
subdir('test_custom_stats')
subdir('test_ddl_deparse')
diff --git a/src/test/modules/test_cplusplusext/.gitignore b/src/test/modules/test_cplusplusext/.gitignore
new file mode 100644
index 00000000000..913175ff6e6
--- /dev/null
+++ b/src/test/modules/test_cplusplusext/.gitignore
@@ -0,0 +1,3 @@
+/log/
+/results/
+/tmp_check/
diff --git a/src/test/modules/test_cplusplusext/Makefile b/src/test/modules/test_cplusplusext/Makefile
new file mode 100644
index 00000000000..88cd4403823
--- /dev/null
+++ b/src/test/modules/test_cplusplusext/Makefile
@@ -0,0 +1,26 @@
+# src/test/modules/test_cplusplusext/Makefile
+
+MODULE_big = test_cplusplusext
+OBJS = \
+ $(WIN32RES) \
+ test_cplusplusext.o
+PGFILEDESC = "test_cplusplusext - test C++ compatibility of PostgreSQL headers"
+
+EXTENSION = test_cplusplusext
+DATA = test_cplusplusext--1.0.sql
+
+REGRESS = test_cplusplusext
+
+# Use C++ compiler for linking because this module includes C++ files
+override COMPILER = $(CXX) $(CXXFLAGS)
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_cplusplusext
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_cplusplusext/README b/src/test/modules/test_cplusplusext/README
new file mode 100644
index 00000000000..8e4090edf01
--- /dev/null
+++ b/src/test/modules/test_cplusplusext/README
@@ -0,0 +1,10 @@
+test_cplusplusext - Test C++ Extension Compatibility
+====================================================
+
+This test module verifies that PostgreSQL headers and macros work
+correctly when compiled with a C++ compiler.
+
+While PostgreSQL already tests that headers are syntactically valid
+C++ using headerscheck, the macros defined in those headers might
+still expand to invalid C++ code. This module catches such issues by
+actually compiling and running an extension that's written in C++.
diff --git a/src/test/modules/test_cplusplusext/expected/test_cplusplusext.out b/src/test/modules/test_cplusplusext/expected/test_cplusplusext.out
new file mode 100644
index 00000000000..ab0b04b5c5e
--- /dev/null
+++ b/src/test/modules/test_cplusplusext/expected/test_cplusplusext.out
@@ -0,0 +1,7 @@
+CREATE EXTENSION test_cplusplusext;
+SELECT test_cplusplus_add(1, 2);
+ test_cplusplus_add
+--------------------
+ 3
+(1 row)
+
diff --git a/src/test/modules/test_cplusplusext/meson.build b/src/test/modules/test_cplusplusext/meson.build
new file mode 100644
index 00000000000..d13210ca593
--- /dev/null
+++ b/src/test/modules/test_cplusplusext/meson.build
@@ -0,0 +1,42 @@
+# Copyright (c) 2025-2026, PostgreSQL Global Development Group
+
+if not have_cxx
+ subdir_done()
+endif
+
+# Currently not supported, to be fixed.
+if cc.get_id() == 'msvc'
+ subdir_done()
+endif
+
+test_cplusplusext_sources = files(
+ 'test_cplusplusext.cpp',
+)
+
+if host_system == 'windows'
+ test_cplusplusext_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
+ '--NAME', 'test_cplusplusext',
+ '--FILEDESC', 'test_cplusplusext - test C++ compatibility of PostgreSQL headers',])
+endif
+
+test_cplusplusext = shared_module('test_cplusplusext',
+ test_cplusplusext_sources,
+ kwargs: pg_test_mod_args,
+)
+test_install_libs += test_cplusplusext
+
+test_install_data += files(
+ 'test_cplusplusext.control',
+ 'test_cplusplusext--1.0.sql',
+)
+
+tests += {
+ 'name': 'test_cplusplusext',
+ 'sd': meson.current_source_dir(),
+ 'bd': meson.current_build_dir(),
+ 'regress': {
+ 'sql': [
+ 'test_cplusplusext',
+ ],
+ },
+}
diff --git a/src/test/modules/test_cplusplusext/sql/test_cplusplusext.sql b/src/test/modules/test_cplusplusext/sql/test_cplusplusext.sql
new file mode 100644
index 00000000000..a41682417ae
--- /dev/null
+++ b/src/test/modules/test_cplusplusext/sql/test_cplusplusext.sql
@@ -0,0 +1,3 @@
+CREATE EXTENSION test_cplusplusext;
+
+SELECT test_cplusplus_add(1, 2);
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext--1.0.sql b/src/test/modules/test_cplusplusext/test_cplusplusext--1.0.sql
new file mode 100644
index 00000000000..c54acb76823
--- /dev/null
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext--1.0.sql
@@ -0,0 +1,8 @@
+/* src/test/modules/test_cplusplusext/test_cplusplusext--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_cplusplusext" to load this file. \quit
+
+CREATE FUNCTION test_cplusplus_add(int4, int4) RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.control b/src/test/modules/test_cplusplusext/test_cplusplusext.control
new file mode 100644
index 00000000000..640a0a51f35
--- /dev/null
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.control
@@ -0,0 +1,4 @@
+comment = 'Test module for C++ extension compatibility'
+default_version = '1.0'
+module_pathname = '$libdir/test_cplusplusext'
+relocatable = true
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
new file mode 100644
index 00000000000..435937c00d2
--- /dev/null
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -0,0 +1,37 @@
+/*--------------------------------------------------------------------------
+ *
+ * test_cplusplusext.cpp
+ * Test that PostgreSQL headers compile with a C++ compiler.
+ *
+ * This file is compiled with a C++ compiler to verify that PostgreSQL
+ * headers remain compatible with C++ extensions.
+ *
+ * Copyright (c) 2025-2026, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+ *
+ * -------------------------------------------------------------------------
+ */
+
+extern "C" {
+#include "postgres.h"
+#include "fmgr.h"
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(test_cplusplus_add);
+}
+
+/*
+ * Simple function that returns the sum of two integers. This verifies that
+ * C++ extension modules can be loaded and called correctly at runtime.
+ */
+extern "C" Datum
+test_cplusplus_add(PG_FUNCTION_ARGS)
+{
+ int32 a = PG_GETARG_INT32(0);
+ int32 b = PG_GETARG_INT32(1);
+
+ PG_RETURN_INT32(a + b);
+}
[parent: f1cd34f95272]