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); +}