postgresql/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
Peter Eisentraut 1887d822f1 Support using copyObject in standard C++
Calling copyObject in C++ without GNU extensions (e.g. when using
-std=c++11 instead of -std=gnu++11) fails with an error like this:

error: use of undeclared identifier 'typeof'; did you mean 'typeid'

This is due to the C compiler used to compile PostgreSQL supporting
typeof, but that function actually not being present in the C++
compiler.  This fixes that by explicitely checking for typeof support
in C++, and then either use that or define typeof ourselves as:

    std::remove_reference_t<decltype(x)>

According to the paper that led to adding typeof to the C standard,
that's the C++ equivalent of the C typeof:
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm#existing-decltype

Author: Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Discussion: https://www.postgresql.org/message-id/flat/DGPW5WCFY7WY.1IHCDNIVVT300%2540jeltef.nl
2026-03-02 11:48:13 +01:00

71 lines
1.6 KiB
C++

/*--------------------------------------------------------------------------
*
* 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"
#include "nodes/pg_list.h"
#include "nodes/primnodes.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(test_cplusplus_add);
}
StaticAssertDecl(sizeof(int32) == 4, "int32 should be 4 bytes");
/*
* 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);
RangeTblRef *node = makeNode(RangeTblRef);
RangeTblRef *copy = copyObject(node);
List *list = list_make1(node);
foreach_ptr(RangeTblRef, rtr, list)
{
(void) rtr;
}
foreach_node(RangeTblRef, rtr, list)
{
(void) rtr;
}
StaticAssertStmt(sizeof(int32) == 4, "int32 should be 4 bytes");
(void) StaticAssertExpr(sizeof(int64) == 8, "int64 should be 8 bytes");
list_free(list);
pfree(node);
pfree(copy);
switch (a)
{
case 1:
elog(DEBUG1, "1");
pg_fallthrough;
case 2:
elog(DEBUG1, "2");
break;
}
PG_RETURN_INT32(a + b);
}