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
pull/269/head
Peter Eisentraut 2 months ago
parent f1cd34f952
commit 476b35d4e3
  1. 8
      configure
  2. 7
      configure.ac
  3. 2
      src/Makefile.global.in
  4. 2
      src/makefiles/meson.build
  5. 6
      src/test/modules/Makefile
  6. 1
      src/test/modules/meson.build
  7. 3
      src/test/modules/test_cplusplusext/.gitignore
  8. 26
      src/test/modules/test_cplusplusext/Makefile
  9. 10
      src/test/modules/test_cplusplusext/README
  10. 7
      src/test/modules/test_cplusplusext/expected/test_cplusplusext.out
  11. 42
      src/test/modules/test_cplusplusext/meson.build
  12. 3
      src/test/modules/test_cplusplusext/sql/test_cplusplusext.sql
  13. 8
      src/test/modules/test_cplusplusext/test_cplusplusext--1.0.sql
  14. 4
      src/test/modules/test_cplusplusext/test_cplusplusext.control
  15. 37
      src/test/modules/test_cplusplusext/test_cplusplusext.cpp

8
configure vendored

@ -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.

@ -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.

@ -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@

@ -118,6 +118,8 @@ pgxs_kv = {
'FLEXFLAGS': ' '.join(flex_flags),
'LIBS': var_libs,
'have_cxx': have_cxx ? 'yes' : 'no',
}
if llvm.found()

@ -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)

@ -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')

@ -0,0 +1,3 @@
/log/
/results/
/tmp_check/

@ -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

@ -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++.

@ -0,0 +1,7 @@
CREATE EXTENSION test_cplusplusext;
SELECT test_cplusplus_add(1, 2);
test_cplusplus_add
--------------------
3
(1 row)

@ -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',
],
},
}

@ -0,0 +1,3 @@
CREATE EXTENSION test_cplusplusext;
SELECT test_cplusplus_add(1, 2);

@ -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;

@ -0,0 +1,4 @@
comment = 'Test module for C++ extension compatibility'
default_version = '1.0'
module_pathname = '$libdir/test_cplusplusext'
relocatable = true

@ -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);
}
Loading…
Cancel
Save