Re: Convert *GetDatum() and DatumGet*() macros to inline functions - Mailing list pgsql-hackers

From Tom Lane
Subject Re: Convert *GetDatum() and DatumGet*() macros to inline functions
Date
Msg-id 3479938.1664213668@sss.pgh.pa.us
Whole thread Raw
In response to Re: Convert *GetDatum() and DatumGet*() macros to inline functions  (Peter Eisentraut <peter.eisentraut@enterprisedb.com>)
Responses Re: Convert *GetDatum() and DatumGet*() macros to inline functions
List pgsql-hackers
Peter Eisentraut <peter.eisentraut@enterprisedb.com> writes:
>> Ok, it has problems with 32-bit platforms.  I can reproduce it locally.
>> I'll need to take another look at this.  I have reverted the patch for now.

> I have tried to analyze these issues, but I'm quite stuck.  If anyone
> else has any ideas, it would be helpful.

It looks to me like the problem is with the rewrite of Int64GetDatumFast
and Float8GetDatumFast:

+static inline Datum
+Int64GetDatumFast(int64 X)
+{
+#ifdef USE_FLOAT8_BYVAL
+    return Int64GetDatum(X);
+#else
+    return PointerGetDatum(&X);
+#endif
+}

In the by-ref code path, this is going to return the address of the
parameter local variable, which of course is broken as soon as the
function exits.  To test, I reverted the mods to those two macros,
and I got through check-world OK in a 32-bit VM.

I think we can do this while still having reasonable type-safety
by adding AssertVariableIsOfTypeMacro() checks to the macros.
An advantage of that solution is that we verify that the code
will be safe for a 32-bit build even in 64-bit builds.  (Of
course, it's just checking the variable's type not its lifespan,
but this is still a step forward.)

0001 attached is what you committed, 0002 is a proposed delta
to fix the Fast macros.

            regards, tom lane

commit 595836e99bf1ee6d43405b885fb69bb8c6d3ee23
Author: Peter Eisentraut <peter@eisentraut.org>
Date:   Mon Sep 12 17:35:55 2022 +0200

    Convert *GetDatum() and DatumGet*() macros to inline functions

    The previous macro implementations just cast the argument to a target
    type but did not check whether the input type was appropriate.  The
    function implementation can do better type checking of the input type.

    Reviewed-by: Aleksander Alekseev <aleksander@timescale.com>
    Discussion: https://www.postgresql.org/message-id/flat/8528fb7e-0aa2-6b54-85fb-0c0886dbd6ed%40enterprisedb.com

diff --git a/contrib/intarray/_int_gist.c b/contrib/intarray/_int_gist.c
index f1817a6cce..6378aa74b0 100644
--- a/contrib/intarray/_int_gist.c
+++ b/contrib/intarray/_int_gist.c
@@ -51,7 +51,7 @@ g_int_consistent(PG_FUNCTION_ARGS)

     /* Oid        subtype = PG_GETARG_OID(3); */
     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
-    bool        retval;
+    bool        retval = false; /* silence compiler warning */

     /* this is exact except for RTSameStrategyNumber */
     *recheck = (strategy == RTSameStrategyNumber);
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index b8cefb9c2c..cf5810b3c1 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -2763,7 +2763,7 @@ c_overpaid(PG_FUNCTION_ARGS)
      is  null.   <function>GetAttributeByName</function> returns a <type>Datum</type>
      value that you can convert to the proper data type by using the
      appropriate <function>DatumGet<replaceable>XXX</replaceable>()</function>
-     macro.  Note that the return value is meaningless if the null flag is
+     function.  Note that the return value is meaningless if the null flag is
      set; always check the null flag before trying to do anything with the
      result.
     </para>
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index d4bf0c7563..1532462317 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -280,7 +280,7 @@ gistMakeUnionKey(GISTSTATE *giststate, int attno,
 bool
 gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b)
 {
-    bool        result;
+    bool        result = false; /* silence compiler warning */

     FunctionCall3Coll(&giststate->equalFn[attno],
                       giststate->supportCollation[attno],
diff --git a/src/backend/tsearch/ts_parse.c b/src/backend/tsearch/ts_parse.c
index 27b2cca2df..92de1f7141 100644
--- a/src/backend/tsearch/ts_parse.c
+++ b/src/backend/tsearch/ts_parse.c
@@ -354,7 +354,7 @@ void
 parsetext(Oid cfgId, ParsedText *prs, char *buf, int buflen)
 {
     int            type,
-                lenlemm;
+                lenlemm = 0;    /* silence compiler warning */
     char       *lemm = NULL;
     LexizeData    ldata;
     TSLexeme   *norms;
@@ -529,7 +529,7 @@ void
 hlparsetext(Oid cfgId, HeadlineParsedText *prs, TSQuery query, char *buf, int buflen)
 {
     int            type,
-                lenlemm;
+                lenlemm = 0;    /* silence compiler warning */
     char       *lemm = NULL;
     LexizeData    ldata;
     TSLexeme   *norms;
diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index 0543c574c6..474ab476f5 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -409,8 +409,8 @@ pg_do_encoding_conversion(unsigned char *src, int len,
     (void) OidFunctionCall6(proc,
                             Int32GetDatum(src_encoding),
                             Int32GetDatum(dest_encoding),
-                            CStringGetDatum(src),
-                            CStringGetDatum(result),
+                            CStringGetDatum((char *) src),
+                            CStringGetDatum((char *) result),
                             Int32GetDatum(len),
                             BoolGetDatum(false));

@@ -485,8 +485,8 @@ pg_do_encoding_conversion_buf(Oid proc,
     result = OidFunctionCall6(proc,
                               Int32GetDatum(src_encoding),
                               Int32GetDatum(dest_encoding),
-                              CStringGetDatum(src),
-                              CStringGetDatum(dest),
+                              CStringGetDatum((char *) src),
+                              CStringGetDatum((char *) dest),
                               Int32GetDatum(srclen),
                               BoolGetDatum(noError));
     return DatumGetInt32(result);
@@ -910,8 +910,8 @@ pg_unicode_to_server(pg_wchar c, unsigned char *s)
     FunctionCall6(Utf8ToServerConvProc,
                   Int32GetDatum(PG_UTF8),
                   Int32GetDatum(server_encoding),
-                  CStringGetDatum(c_as_utf8),
-                  CStringGetDatum(s),
+                  CStringGetDatum((char *) c_as_utf8),
+                  CStringGetDatum((char *) s),
                   Int32GetDatum(c_as_utf8_len),
                   BoolGetDatum(false));
 }
diff --git a/src/include/access/gin.h b/src/include/access/gin.h
index aacc665fdc..fff861e219 100644
--- a/src/include/access/gin.h
+++ b/src/include/access/gin.h
@@ -62,8 +62,18 @@ typedef char GinTernaryValue;
 #define GIN_MAYBE        2        /* don't know if item is present / don't know
                                  * if matches */

-#define DatumGetGinTernaryValue(X) ((GinTernaryValue)(X))
-#define GinTernaryValueGetDatum(X) ((Datum)(X))
+static inline GinTernaryValue
+DatumGetGinTernaryValue(Datum X)
+{
+    return (GinTernaryValue) X;
+}
+
+static inline Datum
+GinTernaryValueGetDatum(GinTernaryValue X)
+{
+    return (Datum) X;
+}
+
 #define PG_RETURN_GIN_TERNARY_VALUE(x) return GinTernaryValueGetDatum(x)

 /* GUC parameters */
diff --git a/src/include/funcapi.h b/src/include/funcapi.h
index dc3d819a1c..8c2521a591 100644
--- a/src/include/funcapi.h
+++ b/src/include/funcapi.h
@@ -204,7 +204,7 @@ extern TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple);
  * Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple) - convert a
  *        HeapTupleHeader to a Datum.
  *
- * Macro declarations:
+ * Inline declarations:
  * HeapTupleGetDatum(HeapTuple tuple) - convert a HeapTuple to a Datum.
  *
  * Obsolete routines and macros:
@@ -217,10 +217,6 @@ extern TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple);
  *----------
  */

-#define HeapTupleGetDatum(tuple)        HeapTupleHeaderGetDatum((tuple)->t_data)
-/* obsolete version of above */
-#define TupleGetDatum(_slot, _tuple)    HeapTupleGetDatum(_tuple)
-
 extern TupleDesc RelationNameGetTupleDesc(const char *relname);
 extern TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases);

@@ -230,6 +226,14 @@ extern AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc);
 extern HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values);
 extern Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple);

+static inline Datum
+HeapTupleGetDatum(const HeapTupleData *tuple)
+{
+    return HeapTupleHeaderGetDatum(tuple->t_data);
+}
+/* obsolete version of above */
+#define TupleGetDatum(_slot, _tuple)    HeapTupleGetDatum(_tuple)
+

 /*----------
  *        Support for Set Returning Functions (SRFs)
diff --git a/src/include/postgres.h b/src/include/postgres.h
index 13903fa022..45c9f6563c 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -24,7 +24,7 @@
  *      section    description
  *      -------    ------------------------------------------------
  *        1)        variable-length datatypes (TOAST support)
- *        2)        Datum type + support macros
+ *        2)        Datum type + support functions
  *        3)        miscellaneous
  *
  *     NOTES
@@ -395,7 +395,7 @@ typedef struct


 /* ----------------------------------------------------------------
- *                Section 2:    Datum type + support macros
+ *                Section 2:    Datum type + support functions
  * ----------------------------------------------------------------
  */

@@ -405,7 +405,7 @@ typedef struct
  *
  * sizeof(Datum) == sizeof(void *) == 4 or 8
  *
- * The macros below and the analogous macros for other types should be used to
+ * The functions below and the analogous functions for other types should be used to
  * convert between a Datum and the appropriate C type.
  */

@@ -434,8 +434,11 @@ typedef struct NullableDatum
  *
  * Note: any nonzero value will be considered true.
  */
-
-#define DatumGetBool(X) ((bool) ((X) != 0))
+static inline bool
+DatumGetBool(Datum X)
+{
+    return (X != 0);
+}

 /*
  * BoolGetDatum
@@ -443,162 +446,231 @@ typedef struct NullableDatum
  *
  * Note: any nonzero value will be considered true.
  */
-
-#define BoolGetDatum(X) ((Datum) ((X) ? 1 : 0))
+static inline Datum
+BoolGetDatum(bool X)
+{
+    return (Datum) (X ? 1 : 0);
+}

 /*
  * DatumGetChar
  *        Returns character value of a datum.
  */
-
-#define DatumGetChar(X) ((char) (X))
+static inline char
+DatumGetChar(Datum X)
+{
+    return (char) X;
+}

 /*
  * CharGetDatum
  *        Returns datum representation for a character.
  */
-
-#define CharGetDatum(X) ((Datum) (X))
+static inline Datum
+CharGetDatum(char X)
+{
+    return (Datum) X;
+}

 /*
  * Int8GetDatum
  *        Returns datum representation for an 8-bit integer.
  */
-
-#define Int8GetDatum(X) ((Datum) (X))
+static inline Datum
+Int8GetDatum(int8 X)
+{
+    return (Datum) X;
+}

 /*
  * DatumGetUInt8
  *        Returns 8-bit unsigned integer value of a datum.
  */
-
-#define DatumGetUInt8(X) ((uint8) (X))
+static inline uint8
+DatumGetUInt8(Datum X)
+{
+    return (uint8) X;
+}

 /*
  * UInt8GetDatum
  *        Returns datum representation for an 8-bit unsigned integer.
  */
-
-#define UInt8GetDatum(X) ((Datum) (X))
+static inline Datum
+UInt8GetDatum(uint8 X)
+{
+    return (Datum) X;
+}

 /*
  * DatumGetInt16
  *        Returns 16-bit integer value of a datum.
  */
-
-#define DatumGetInt16(X) ((int16) (X))
+static inline int16
+DatumGetInt16(Datum X)
+{
+    return (int16) X;
+}

 /*
  * Int16GetDatum
  *        Returns datum representation for a 16-bit integer.
  */
-
-#define Int16GetDatum(X) ((Datum) (X))
+static inline Datum
+Int16GetDatum(int16 X)
+{
+    return (Datum) X;
+}

 /*
  * DatumGetUInt16
  *        Returns 16-bit unsigned integer value of a datum.
  */
-
-#define DatumGetUInt16(X) ((uint16) (X))
+static inline uint16
+DatumGetUInt16(Datum X)
+{
+    return (uint16) X;
+}

 /*
  * UInt16GetDatum
  *        Returns datum representation for a 16-bit unsigned integer.
  */
-
-#define UInt16GetDatum(X) ((Datum) (X))
+static inline Datum
+UInt16GetDatum(uint16 X)
+{
+    return (Datum) X;
+}

 /*
  * DatumGetInt32
  *        Returns 32-bit integer value of a datum.
  */
-
-#define DatumGetInt32(X) ((int32) (X))
+static inline int32
+DatumGetInt32(Datum X)
+{
+    return (int32) X;
+}

 /*
  * Int32GetDatum
  *        Returns datum representation for a 32-bit integer.
  */
-
-#define Int32GetDatum(X) ((Datum) (X))
+static inline Datum
+Int32GetDatum(int32 X)
+{
+    return (Datum) X;
+}

 /*
  * DatumGetUInt32
  *        Returns 32-bit unsigned integer value of a datum.
  */
-
-#define DatumGetUInt32(X) ((uint32) (X))
+static inline uint32
+DatumGetUInt32(Datum X)
+{
+    return (uint32) X;
+}

 /*
  * UInt32GetDatum
  *        Returns datum representation for a 32-bit unsigned integer.
  */
-
-#define UInt32GetDatum(X) ((Datum) (X))
+static inline Datum
+UInt32GetDatum(uint32 X)
+{
+    return (Datum) X;
+}

 /*
  * DatumGetObjectId
  *        Returns object identifier value of a datum.
  */
-
-#define DatumGetObjectId(X) ((Oid) (X))
+static inline Oid
+DatumGetObjectId(Datum X)
+{
+    return (Oid) X;
+}

 /*
  * ObjectIdGetDatum
  *        Returns datum representation for an object identifier.
  */
-
-#define ObjectIdGetDatum(X) ((Datum) (X))
+static inline Datum
+ObjectIdGetDatum(Oid X)
+{
+    return (Datum) X;
+}

 /*
  * DatumGetTransactionId
  *        Returns transaction identifier value of a datum.
  */
-
-#define DatumGetTransactionId(X) ((TransactionId) (X))
+static inline TransactionId
+DatumGetTransactionId(Datum X)
+{
+    return (TransactionId) X;
+}

 /*
  * TransactionIdGetDatum
  *        Returns datum representation for a transaction identifier.
  */
-
-#define TransactionIdGetDatum(X) ((Datum) (X))
+static inline Datum
+TransactionIdGetDatum(TransactionId X)
+{
+    return (Datum) X;
+}

 /*
  * MultiXactIdGetDatum
  *        Returns datum representation for a multixact identifier.
  */
-
-#define MultiXactIdGetDatum(X) ((Datum) (X))
+static inline Datum
+MultiXactIdGetDatum(MultiXactId X)
+{
+    return (Datum) X;
+}

 /*
  * DatumGetCommandId
  *        Returns command identifier value of a datum.
  */
-
-#define DatumGetCommandId(X) ((CommandId) (X))
+static inline CommandId
+DatumGetCommandId(Datum X)
+{
+    return (CommandId) X;
+}

 /*
  * CommandIdGetDatum
  *        Returns datum representation for a command identifier.
  */
-
-#define CommandIdGetDatum(X) ((Datum) (X))
+static inline Datum
+CommandIdGetDatum(CommandId X)
+{
+    return (Datum) X;
+}

 /*
  * DatumGetPointer
  *        Returns pointer value of a datum.
  */
-
-#define DatumGetPointer(X) ((Pointer) (X))
+static inline Pointer
+DatumGetPointer(Datum X)
+{
+    return (Pointer) X;
+}

 /*
  * PointerGetDatum
  *        Returns datum representation for a pointer.
  */
-
-#define PointerGetDatum(X) ((Datum) (X))
+static inline Datum
+PointerGetDatum(const void *X)
+{
+    return (Datum) X;
+}

 /*
  * DatumGetCString
@@ -607,8 +679,11 @@ typedef struct NullableDatum
  * Note: C string is not a full-fledged Postgres type at present,
  * but type input functions use this conversion for their inputs.
  */
-
-#define DatumGetCString(X) ((char *) DatumGetPointer(X))
+static inline char *
+DatumGetCString(Datum X)
+{
+    return (char *) DatumGetPointer(X);
+}

 /*
  * CStringGetDatum
@@ -619,15 +694,21 @@ typedef struct NullableDatum
  * Note: CString is pass-by-reference; caller must ensure the pointed-to
  * value has adequate lifetime.
  */
-
-#define CStringGetDatum(X) PointerGetDatum(X)
+static inline Datum
+CStringGetDatum(const char *X)
+{
+    return PointerGetDatum(X);
+}

 /*
  * DatumGetName
  *        Returns name value of a datum.
  */
-
-#define DatumGetName(X) ((Name) DatumGetPointer(X))
+static inline Name
+DatumGetName(Datum X)
+{
+    return (Name) DatumGetPointer(X);
+}

 /*
  * NameGetDatum
@@ -636,21 +717,27 @@ typedef struct NullableDatum
  * Note: Name is pass-by-reference; caller must ensure the pointed-to
  * value has adequate lifetime.
  */
-
-#define NameGetDatum(X) CStringGetDatum(NameStr(*(X)))
+static inline Datum
+NameGetDatum(const NameData *X)
+{
+    return CStringGetDatum(NameStr(*X));
+}

 /*
  * DatumGetInt64
  *        Returns 64-bit integer value of a datum.
  *
- * Note: this macro hides whether int64 is pass by value or by reference.
+ * Note: this function hides whether int64 is pass by value or by reference.
  */
-
+static inline int64
+DatumGetInt64(Datum X)
+{
 #ifdef USE_FLOAT8_BYVAL
-#define DatumGetInt64(X) ((int64) (X))
+    return (int64) X;
 #else
-#define DatumGetInt64(X) (* ((int64 *) DatumGetPointer(X)))
+    return *((int64 *) DatumGetPointer(X));
 #endif
+}

 /*
  * Int64GetDatum
@@ -659,25 +746,32 @@ typedef struct NullableDatum
  * Note: if int64 is pass by reference, this function returns a reference
  * to palloc'd space.
  */
-
 #ifdef USE_FLOAT8_BYVAL
-#define Int64GetDatum(X) ((Datum) (X))
+static inline Datum
+Int64GetDatum(int64 X)
+{
+    return (Datum) X;
+}
 #else
 extern Datum Int64GetDatum(int64 X);
 #endif

+
 /*
  * DatumGetUInt64
  *        Returns 64-bit unsigned integer value of a datum.
  *
- * Note: this macro hides whether int64 is pass by value or by reference.
+ * Note: this function hides whether int64 is pass by value or by reference.
  */
-
+static inline uint64
+DatumGetUInt64(Datum X)
+{
 #ifdef USE_FLOAT8_BYVAL
-#define DatumGetUInt64(X) ((uint64) (X))
+    return (uint64) X;
 #else
-#define DatumGetUInt64(X) (* ((uint64 *) DatumGetPointer(X)))
+    return *((uint64 *) DatumGetPointer(X));
 #endif
+}

 /*
  * UInt64GetDatum
@@ -686,12 +780,15 @@ extern Datum Int64GetDatum(int64 X);
  * Note: if int64 is pass by reference, this function returns a reference
  * to palloc'd space.
  */
-
+static inline Datum
+UInt64GetDatum(uint64 X)
+{
 #ifdef USE_FLOAT8_BYVAL
-#define UInt64GetDatum(X) ((Datum) (X))
+    return (Datum) X;
 #else
-#define UInt64GetDatum(X) Int64GetDatum((int64) (X))
+    return Int64GetDatum((int64) X);
 #endif
+}

 /*
  * Float <-> Datum conversions
@@ -739,13 +836,12 @@ Float4GetDatum(float4 X)
  * DatumGetFloat8
  *        Returns 8-byte floating point value of a datum.
  *
- * Note: this macro hides whether float8 is pass by value or by reference.
+ * Note: this function hides whether float8 is pass by value or by reference.
  */
-
-#ifdef USE_FLOAT8_BYVAL
 static inline float8
 DatumGetFloat8(Datum X)
 {
+#ifdef USE_FLOAT8_BYVAL
     union
     {
         int64        value;
@@ -754,10 +850,10 @@ DatumGetFloat8(Datum X)

     myunion.value = DatumGetInt64(X);
     return myunion.retval;
-}
 #else
-#define DatumGetFloat8(X) (* ((float8 *) DatumGetPointer(X)))
+    return *((float8 *) DatumGetPointer(X));
 #endif
+}

 /*
  * Float8GetDatum
@@ -766,7 +862,6 @@ DatumGetFloat8(Datum X)
  * Note: if float8 is pass by reference, this function returns a reference
  * to palloc'd space.
  */
-
 #ifdef USE_FLOAT8_BYVAL
 static inline Datum
 Float8GetDatum(float8 X)
@@ -789,22 +884,34 @@ extern Datum Float8GetDatum(float8 X);
  * Int64GetDatumFast
  * Float8GetDatumFast
  *
- * These macros are intended to allow writing code that does not depend on
+ * These functions are intended to allow writing code that does not depend on
  * whether int64 and float8 are pass-by-reference types, while not
  * sacrificing performance when they are.  The argument must be a variable
  * that will exist and have the same value for as long as the Datum is needed.
  * In the pass-by-ref case, the address of the variable is taken to use as
  * the Datum.  In the pass-by-val case, these will be the same as the non-Fast
- * macros.
+ * functions.
  */

+static inline Datum
+Int64GetDatumFast(int64 X)
+{
+#ifdef USE_FLOAT8_BYVAL
+    return Int64GetDatum(X);
+#else
+    return PointerGetDatum(&X);
+#endif
+}
+
+static inline Datum
+Float8GetDatumFast(float8 X)
+{
 #ifdef USE_FLOAT8_BYVAL
-#define Int64GetDatumFast(X)  Int64GetDatum(X)
-#define Float8GetDatumFast(X) Float8GetDatum(X)
+    return Float8GetDatum(X);
 #else
-#define Int64GetDatumFast(X)  PointerGetDatum(&(X))
-#define Float8GetDatumFast(X) PointerGetDatum(&(X))
+    return PointerGetDatum(&X);
 #endif
+}


 /* ----------------------------------------------------------------
diff --git a/src/include/tsearch/ts_type.h b/src/include/tsearch/ts_type.h
index 689b2d1cfb..f1ec84702d 100644
--- a/src/include/tsearch/ts_type.h
+++ b/src/include/tsearch/ts_type.h
@@ -111,12 +111,27 @@ typedef TSVectorData *TSVector;
 #define POSDATAPTR(x,e) (_POSVECPTR(x,e)->pos)

 /*
- * fmgr interface macros
+ * fmgr interface functions
  */

-#define DatumGetTSVector(X)            ((TSVector) PG_DETOAST_DATUM(X))
-#define DatumGetTSVectorCopy(X)        ((TSVector) PG_DETOAST_DATUM_COPY(X))
-#define TSVectorGetDatum(X)            PointerGetDatum(X)
+static inline TSVector
+DatumGetTSVector(Datum X)
+{
+    return (TSVector) PG_DETOAST_DATUM(X);
+}
+
+static inline TSVector
+DatumGetTSVectorCopy(Datum X)
+{
+    return (TSVector) PG_DETOAST_DATUM_COPY(X);
+}
+
+static inline Datum
+TSVectorGetDatum(const TSVectorData *X)
+{
+    return PointerGetDatum(X);
+}
+
 #define PG_GETARG_TSVECTOR(n)        DatumGetTSVector(PG_GETARG_DATUM(n))
 #define PG_GETARG_TSVECTOR_COPY(n)    DatumGetTSVectorCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_TSVECTOR(x)        return TSVectorGetDatum(x)
@@ -227,14 +242,29 @@ typedef TSQueryData *TSQuery;
 #define GETOPERAND(x)    ( (char*)GETQUERY(x) + ((TSQuery)(x))->size * sizeof(QueryItem) )

 /*
- * fmgr interface macros
+ * fmgr interface functions
  * Note, TSQuery type marked as plain storage, so it can't be toasted
  * but PG_DETOAST_DATUM_COPY is used for simplicity
  */

-#define DatumGetTSQuery(X)            ((TSQuery) DatumGetPointer(X))
-#define DatumGetTSQueryCopy(X)        ((TSQuery) PG_DETOAST_DATUM_COPY(X))
-#define TSQueryGetDatum(X)            PointerGetDatum(X)
+static inline TSQuery
+DatumGetTSQuery(Datum X)
+{
+    return (TSQuery) DatumGetPointer(X);
+}
+
+static inline TSQuery
+DatumGetTSQueryCopy(Datum X)
+{
+    return (TSQuery) PG_DETOAST_DATUM_COPY(X);
+}
+
+static inline Datum
+TSQueryGetDatum(const TSQueryData *X)
+{
+    return PointerGetDatum(X);
+}
+
 #define PG_GETARG_TSQUERY(n)        DatumGetTSQuery(PG_GETARG_DATUM(n))
 #define PG_GETARG_TSQUERY_COPY(n)    DatumGetTSQueryCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_TSQUERY(x)        return TSQueryGetDatum(x)
diff --git a/src/include/tsearch/ts_utils.h b/src/include/tsearch/ts_utils.h
index c36c711dae..26cc415aa8 100644
--- a/src/include/tsearch/ts_utils.h
+++ b/src/include/tsearch/ts_utils.h
@@ -243,8 +243,18 @@ typedef uint64 TSQuerySign;

 #define TSQS_SIGLEN  (sizeof(TSQuerySign)*BITS_PER_BYTE)

-#define TSQuerySignGetDatum(X)        Int64GetDatum((int64) (X))
-#define DatumGetTSQuerySign(X)        ((TSQuerySign) DatumGetInt64(X))
+static inline Datum
+TSQuerySignGetDatum(TSQuerySign X)
+{
+    return Int64GetDatum((int64) X);
+}
+
+static inline TSQuerySign
+DatumGetTSQuerySign(Datum X)
+{
+    return (TSQuerySign) DatumGetInt64(X);
+}
+
 #define PG_RETURN_TSQUERYSIGN(X)    return TSQuerySignGetDatum(X)
 #define PG_GETARG_TSQUERYSIGN(n)    DatumGetTSQuerySign(PG_GETARG_DATUM(n))

diff --git a/src/include/utils/cash.h b/src/include/utils/cash.h
index 2e332d83b1..55d45fadd4 100644
--- a/src/include/utils/cash.h
+++ b/src/include/utils/cash.h
@@ -17,8 +17,18 @@
 typedef int64 Cash;

 /* Cash is pass-by-reference if and only if int64 is */
-#define DatumGetCash(X)        ((Cash) DatumGetInt64(X))
-#define CashGetDatum(X)        Int64GetDatum(X)
+static inline Cash
+DatumGetCash(Datum X)
+{
+    return DatumGetInt64(X);
+}
+
+static inline Datum
+CashGetDatum(Cash X)
+{
+    return Int64GetDatum(X);
+}
+
 #define PG_GETARG_CASH(n)    DatumGetCash(PG_GETARG_DATUM(n))
 #define PG_RETURN_CASH(x)    return CashGetDatum(x)

diff --git a/src/include/utils/date.h b/src/include/utils/date.h
index 3991da41f0..0bbe889128 100644
--- a/src/include/utils/date.h
+++ b/src/include/utils/date.h
@@ -45,18 +45,46 @@ typedef struct
 #define MAX_TIME_PRECISION 6

 /*
- * Macros for fmgr-callable functions.
+ * Functions for fmgr-callable functions.
  *
  * For TimeADT, we make use of the same support routines as for int64.
  * Therefore TimeADT is pass-by-reference if and only if int64 is!
  */
-#define DatumGetDateADT(X)      ((DateADT) DatumGetInt32(X))
-#define DatumGetTimeADT(X)      ((TimeADT) DatumGetInt64(X))
-#define DatumGetTimeTzADTP(X) ((TimeTzADT *) DatumGetPointer(X))
+static inline DateADT
+DatumGetDateADT(Datum X)
+{
+    return (DateADT) DatumGetInt32(X);
+}
+
+static inline TimeADT
+DatumGetTimeADT(Datum X)
+{
+    return (TimeADT) DatumGetInt64(X);
+}
+
+static inline TimeTzADT *
+DatumGetTimeTzADTP(Datum X)
+{
+    return (TimeTzADT *) DatumGetPointer(X);
+}

-#define DateADTGetDatum(X)      Int32GetDatum(X)
-#define TimeADTGetDatum(X)      Int64GetDatum(X)
-#define TimeTzADTPGetDatum(X) PointerGetDatum(X)
+static inline Datum
+DateADTGetDatum(DateADT X)
+{
+    return Int32GetDatum(X);
+}
+
+static inline Datum
+TimeADTGetDatum(TimeADT X)
+{
+    return Int64GetDatum(X);
+}
+
+static inline Datum
+TimeTzADTPGetDatum(const TimeTzADT *X)
+{
+    return PointerGetDatum(X);
+}

 #define PG_GETARG_DATEADT(n)     DatumGetDateADT(PG_GETARG_DATUM(n))
 #define PG_GETARG_TIMEADT(n)     DatumGetTimeADT(PG_GETARG_DATUM(n))
diff --git a/src/include/utils/expandeddatum.h b/src/include/utils/expandeddatum.h
index ffdb0c45bd..c4818eb054 100644
--- a/src/include/utils/expandeddatum.h
+++ b/src/include/utils/expandeddatum.h
@@ -133,8 +133,17 @@ struct ExpandedObjectHeader
  * (More of these might be worth inlining later.)
  */

-#define EOHPGetRWDatum(eohptr)    PointerGetDatum((eohptr)->eoh_rw_ptr)
-#define EOHPGetRODatum(eohptr)    PointerGetDatum((eohptr)->eoh_ro_ptr)
+static inline Datum
+EOHPGetRWDatum(const struct ExpandedObjectHeader *eohptr)
+{
+    return PointerGetDatum(eohptr->eoh_rw_ptr);
+}
+
+static inline Datum
+EOHPGetRODatum(const struct ExpandedObjectHeader *eohptr)
+{
+    return PointerGetDatum(eohptr->eoh_ro_ptr);
+}

 /* Does the Datum represent a writable expanded object? */
 #define DatumIsReadWriteExpandedObject(d, isnull, typlen) \
diff --git a/src/include/utils/expandedrecord.h b/src/include/utils/expandedrecord.h
index be60e2ce53..aaf5b6bfd1 100644
--- a/src/include/utils/expandedrecord.h
+++ b/src/include/utils/expandedrecord.h
@@ -138,10 +138,20 @@ typedef struct ExpandedRecordHeader
     MemoryContextCallback er_mcb;
 } ExpandedRecordHeader;

-/* fmgr macros for expanded record objects */
+/* fmgr functions and macros for expanded record objects */
+static inline Datum
+ExpandedRecordGetDatum(const ExpandedRecordHeader *erh)
+{
+    return EOHPGetRWDatum(&erh->hdr);
+}
+
+static inline Datum
+ExpandedRecordGetRODatum(const ExpandedRecordHeader *erh)
+{
+    return EOHPGetRODatum(&erh->hdr);
+}
+
 #define PG_GETARG_EXPANDED_RECORD(n)  DatumGetExpandedRecord(PG_GETARG_DATUM(n))
-#define ExpandedRecordGetDatum(erh)   EOHPGetRWDatum(&(erh)->hdr)
-#define ExpandedRecordGetRODatum(erh) EOHPGetRODatum(&(erh)->hdr)
 #define PG_RETURN_EXPANDED_RECORD(x)  PG_RETURN_DATUM(ExpandedRecordGetDatum(x))

 /* assorted other macros */
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index 719030777e..05726778ad 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -166,48 +166,112 @@ typedef struct
 } CIRCLE;

 /*
- * fmgr interface macros
+ * fmgr interface functions
  *
  * Path and Polygon are toastable varlena types, the others are just
  * fixed-size pass-by-reference types.
  */

-#define DatumGetPointP(X)     ((Point *) DatumGetPointer(X))
-#define PointPGetDatum(X)     PointerGetDatum(X)
+static inline Point *
+DatumGetPointP(Datum X)
+{
+    return (Point *) DatumGetPointer(X);
+}
+static inline Datum
+PointPGetDatum(const Point *X)
+{
+    return PointerGetDatum(X);
+}
 #define PG_GETARG_POINT_P(n) DatumGetPointP(PG_GETARG_DATUM(n))
 #define PG_RETURN_POINT_P(x) return PointPGetDatum(x)

-#define DatumGetLsegP(X)    ((LSEG *) DatumGetPointer(X))
-#define LsegPGetDatum(X)    PointerGetDatum(X)
+static inline LSEG *
+DatumGetLsegP(Datum X)
+{
+    return (LSEG *) DatumGetPointer(X);
+}
+static inline Datum
+LsegPGetDatum(const LSEG *X)
+{
+    return PointerGetDatum(X);
+}
 #define PG_GETARG_LSEG_P(n) DatumGetLsegP(PG_GETARG_DATUM(n))
 #define PG_RETURN_LSEG_P(x) return LsegPGetDatum(x)

-#define DatumGetPathP(X)         ((PATH *) PG_DETOAST_DATUM(X))
-#define DatumGetPathPCopy(X)     ((PATH *) PG_DETOAST_DATUM_COPY(X))
-#define PathPGetDatum(X)         PointerGetDatum(X)
+static inline PATH *
+DatumGetPathP(Datum X)
+{
+    return (PATH *) PG_DETOAST_DATUM(X);
+}
+static inline PATH *
+DatumGetPathPCopy(Datum X)
+{
+    return (PATH *) PG_DETOAST_DATUM_COPY(X);
+}
+static inline Datum
+PathPGetDatum(const PATH *X)
+{
+    return PointerGetDatum(X);
+}
 #define PG_GETARG_PATH_P(n)         DatumGetPathP(PG_GETARG_DATUM(n))
 #define PG_GETARG_PATH_P_COPY(n) DatumGetPathPCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_PATH_P(x)         return PathPGetDatum(x)

-#define DatumGetLineP(X)    ((LINE *) DatumGetPointer(X))
-#define LinePGetDatum(X)    PointerGetDatum(X)
+static inline LINE *
+DatumGetLineP(Datum X)
+{
+    return (LINE *) DatumGetPointer(X);
+}
+static inline Datum
+LinePGetDatum(const LINE *X)
+{
+    return PointerGetDatum(X);
+}
 #define PG_GETARG_LINE_P(n) DatumGetLineP(PG_GETARG_DATUM(n))
 #define PG_RETURN_LINE_P(x) return LinePGetDatum(x)

-#define DatumGetBoxP(X)    ((BOX *) DatumGetPointer(X))
-#define BoxPGetDatum(X)    PointerGetDatum(X)
+static inline BOX *
+DatumGetBoxP(Datum X)
+{
+    return (BOX *) DatumGetPointer(X);
+}
+static inline Datum
+BoxPGetDatum(const BOX *X)
+{
+    return PointerGetDatum(X);
+}
 #define PG_GETARG_BOX_P(n) DatumGetBoxP(PG_GETARG_DATUM(n))
 #define PG_RETURN_BOX_P(x) return BoxPGetDatum(x)

-#define DatumGetPolygonP(X)            ((POLYGON *) PG_DETOAST_DATUM(X))
-#define DatumGetPolygonPCopy(X)        ((POLYGON *) PG_DETOAST_DATUM_COPY(X))
-#define PolygonPGetDatum(X)            PointerGetDatum(X)
+static inline POLYGON *
+DatumGetPolygonP(Datum X)
+{
+    return (POLYGON *) PG_DETOAST_DATUM(X);
+}
+static inline POLYGON *
+DatumGetPolygonPCopy(Datum X)
+{
+    return (POLYGON *) PG_DETOAST_DATUM_COPY(X);
+}
+static inline Datum
+PolygonPGetDatum(const POLYGON *X)
+{
+    return PointerGetDatum(X);
+}
 #define PG_GETARG_POLYGON_P(n)        DatumGetPolygonP(PG_GETARG_DATUM(n))
 #define PG_GETARG_POLYGON_P_COPY(n) DatumGetPolygonPCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_POLYGON_P(x)        return PolygonPGetDatum(x)

-#define DatumGetCircleP(X)      ((CIRCLE *) DatumGetPointer(X))
-#define CirclePGetDatum(X)      PointerGetDatum(X)
+static inline CIRCLE *
+DatumGetCircleP(Datum X)
+{
+    return (CIRCLE *) DatumGetPointer(X);
+}
+static inline Datum
+CirclePGetDatum(const CIRCLE *X)
+{
+    return PointerGetDatum(X);
+}
 #define PG_GETARG_CIRCLE_P(n) DatumGetCircleP(PG_GETARG_DATUM(n))
 #define PG_RETURN_CIRCLE_P(x) return CirclePGetDatum(x)

diff --git a/src/include/utils/inet.h b/src/include/utils/inet.h
index b1ec9723df..5438cfaba5 100644
--- a/src/include/utils/inet.h
+++ b/src/include/utils/inet.h
@@ -119,23 +119,58 @@ typedef struct macaddr8
 /*
  * fmgr interface macros
  */
-#define DatumGetInetPP(X)    ((inet *) PG_DETOAST_DATUM_PACKED(X))
-#define InetPGetDatum(X)    PointerGetDatum(X)
+static inline inet *
+DatumGetInetPP(Datum X)
+{
+    return (inet *) PG_DETOAST_DATUM_PACKED(X);
+}
+
+static inline Datum
+InetPGetDatum(const inet *X)
+{
+    return PointerGetDatum(X);
+}
+
 #define PG_GETARG_INET_PP(n) DatumGetInetPP(PG_GETARG_DATUM(n))
 #define PG_RETURN_INET_P(x) return InetPGetDatum(x)
+
 /* obsolescent variants */
-#define DatumGetInetP(X)    ((inet *) PG_DETOAST_DATUM(X))
+static inline inet *
+DatumGetInetP(Datum X)
+{
+    return (inet *) PG_DETOAST_DATUM(X);
+}
 #define PG_GETARG_INET_P(n) DatumGetInetP(PG_GETARG_DATUM(n))

 /* macaddr is a fixed-length pass-by-reference datatype */
-#define DatumGetMacaddrP(X)    ((macaddr *) DatumGetPointer(X))
-#define MacaddrPGetDatum(X)    PointerGetDatum(X)
+static inline macaddr *
+DatumGetMacaddrP(Datum X)
+{
+    return (macaddr *) DatumGetPointer(X);
+}
+
+static inline Datum
+MacaddrPGetDatum(const macaddr *X)
+{
+    return PointerGetDatum(X);
+}
+
 #define PG_GETARG_MACADDR_P(n) DatumGetMacaddrP(PG_GETARG_DATUM(n))
 #define PG_RETURN_MACADDR_P(x) return MacaddrPGetDatum(x)

 /* macaddr8 is a fixed-length pass-by-reference datatype */
-#define DatumGetMacaddr8P(X)    ((macaddr8 *) DatumGetPointer(X))
-#define Macaddr8PGetDatum(X)    PointerGetDatum(X)
+static inline macaddr8 *
+DatumGetMacaddr8P(Datum X)
+{
+    return (macaddr8 *) DatumGetPointer(X);
+}
+
+static inline Datum
+Macaddr8PGetDatum(const macaddr8 *X)
+{
+    return PointerGetDatum(X);
+}
+
 #define PG_GETARG_MACADDR8_P(n) DatumGetMacaddr8P(PG_GETARG_DATUM(n))
 #define PG_RETURN_MACADDR8_P(x) return Macaddr8PGetDatum(x)

diff --git a/src/include/utils/jsonb.h b/src/include/utils/jsonb.h
index 4cbe6edf21..bdd1c9c75d 100644
--- a/src/include/utils/jsonb.h
+++ b/src/include/utils/jsonb.h
@@ -67,14 +67,6 @@ typedef enum
 #define JGINFLAG_HASHED 0x10    /* OR'd into flag if value was hashed */
 #define JGIN_MAXLENGTH    125        /* max length of text part before hashing */

-/* Convenience macros */
-#define DatumGetJsonbP(d)    ((Jsonb *) PG_DETOAST_DATUM(d))
-#define DatumGetJsonbPCopy(d)    ((Jsonb *) PG_DETOAST_DATUM_COPY(d))
-#define JsonbPGetDatum(p)    PointerGetDatum(p)
-#define PG_GETARG_JSONB_P(x)    DatumGetJsonbP(PG_GETARG_DATUM(x))
-#define PG_GETARG_JSONB_P_COPY(x)    DatumGetJsonbPCopy(PG_GETARG_DATUM(x))
-#define PG_RETURN_JSONB_P(x)    PG_RETURN_POINTER(x)
-
 typedef struct JsonbPair JsonbPair;
 typedef struct JsonbValue JsonbValue;

@@ -375,6 +367,29 @@ typedef struct JsonbIterator
 } JsonbIterator;


+/* Convenience macros */
+static inline Jsonb *
+DatumGetJsonbP(Datum d)
+{
+    return (Jsonb *) PG_DETOAST_DATUM(d);
+}
+
+static inline Jsonb *
+DatumGetJsonbPCopy(Datum d)
+{
+    return (Jsonb *) PG_DETOAST_DATUM_COPY(d);
+}
+
+static inline Datum
+JsonbPGetDatum(const Jsonb *p)
+{
+    return PointerGetDatum(p);
+}
+
+#define PG_GETARG_JSONB_P(x)    DatumGetJsonbP(PG_GETARG_DATUM(x))
+#define PG_GETARG_JSONB_P_COPY(x)    DatumGetJsonbPCopy(PG_GETARG_DATUM(x))
+#define PG_RETURN_JSONB_P(x)    PG_RETURN_POINTER(x)
+
 /* Support functions */
 extern uint32 getJsonbOffset(const JsonbContainer *jc, int index);
 extern uint32 getJsonbLength(const JsonbContainer *jc, int index);
diff --git a/src/include/utils/jsonpath.h b/src/include/utils/jsonpath.h
index cd0b5d5b61..13f60cdc09 100644
--- a/src/include/utils/jsonpath.h
+++ b/src/include/utils/jsonpath.h
@@ -29,8 +29,18 @@ typedef struct
 #define JSONPATH_LAX        (0x80000000)
 #define JSONPATH_HDRSZ        (offsetof(JsonPath, data))

-#define DatumGetJsonPathP(d)            ((JsonPath *) DatumGetPointer(PG_DETOAST_DATUM(d)))
-#define DatumGetJsonPathPCopy(d)        ((JsonPath *) DatumGetPointer(PG_DETOAST_DATUM_COPY(d)))
+static inline JsonPath *
+DatumGetJsonPathP(Datum d)
+{
+    return (JsonPath *) PG_DETOAST_DATUM(d);
+}
+
+static inline JsonPath *
+DatumGetJsonPathPCopy(Datum d)
+{
+    return (JsonPath *) PG_DETOAST_DATUM_COPY(d);
+}
+
 #define PG_GETARG_JSONPATH_P(x)            DatumGetJsonPathP(PG_GETARG_DATUM(x))
 #define PG_GETARG_JSONPATH_P_COPY(x)    DatumGetJsonPathPCopy(PG_GETARG_DATUM(x))
 #define PG_RETURN_JSONPATH_P(p)            PG_RETURN_POINTER(p)
diff --git a/src/include/utils/multirangetypes.h b/src/include/utils/multirangetypes.h
index 915330f990..23bce0005f 100644
--- a/src/include/utils/multirangetypes.h
+++ b/src/include/utils/multirangetypes.h
@@ -42,11 +42,26 @@ typedef struct
 #define MultirangeIsEmpty(mr)  ((mr)->rangeCount == 0)

 /*
- * fmgr macros for multirange type objects
+ * fmgr functions for multirange type objects
  */
-#define DatumGetMultirangeTypeP(X)        ((MultirangeType *) PG_DETOAST_DATUM(X))
-#define DatumGetMultirangeTypePCopy(X)    ((MultirangeType *) PG_DETOAST_DATUM_COPY(X))
-#define MultirangeTypePGetDatum(X)        PointerGetDatum(X)
+static inline MultirangeType *
+DatumGetMultirangeTypeP(Datum X)
+{
+    return (MultirangeType *) PG_DETOAST_DATUM(X);
+}
+
+static inline MultirangeType *
+DatumGetMultirangeTypePCopy(Datum X)
+{
+    return (MultirangeType *) PG_DETOAST_DATUM_COPY(X);
+}
+
+static inline Datum
+MultirangeTypePGetDatum(const MultirangeType *X)
+{
+    return PointerGetDatum(X);
+}
+
 #define PG_GETARG_MULTIRANGE_P(n)        DatumGetMultirangeTypeP(PG_GETARG_DATUM(n))
 #define PG_GETARG_MULTIRANGE_P_COPY(n)    DatumGetMultirangeTypePCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_MULTIRANGE_P(x)        return MultirangeTypePGetDatum(x)
diff --git a/src/include/utils/numeric.h b/src/include/utils/numeric.h
index 3caa74dfe7..88c62c5348 100644
--- a/src/include/utils/numeric.h
+++ b/src/include/utils/numeric.h
@@ -56,9 +56,24 @@ typedef struct NumericData *Numeric;
  * fmgr interface macros
  */

-#define DatumGetNumeric(X)          ((Numeric) PG_DETOAST_DATUM(X))
-#define DatumGetNumericCopy(X)      ((Numeric) PG_DETOAST_DATUM_COPY(X))
-#define NumericGetDatum(X)          PointerGetDatum(X)
+static inline Numeric
+DatumGetNumeric(Datum X)
+{
+    return (Numeric) PG_DETOAST_DATUM(X);
+}
+
+static inline Numeric
+DatumGetNumericCopy(Datum X)
+{
+    return (Numeric) PG_DETOAST_DATUM_COPY(X);
+}
+
+static inline Datum
+NumericGetDatum(Numeric X)
+{
+    return PointerGetDatum(X);
+}
+
 #define PG_GETARG_NUMERIC(n)      DatumGetNumeric(PG_GETARG_DATUM(n))
 #define PG_GETARG_NUMERIC_COPY(n) DatumGetNumericCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_NUMERIC(x)      return NumericGetDatum(x)
diff --git a/src/include/utils/pg_lsn.h b/src/include/utils/pg_lsn.h
index 7b708f1073..5313afbfe2 100644
--- a/src/include/utils/pg_lsn.h
+++ b/src/include/utils/pg_lsn.h
@@ -18,8 +18,17 @@
 #include "access/xlogdefs.h"
 #include "fmgr.h"

-#define DatumGetLSN(X) ((XLogRecPtr) DatumGetInt64(X))
-#define LSNGetDatum(X) (Int64GetDatum((int64) (X)))
+static inline XLogRecPtr
+DatumGetLSN(Datum X)
+{
+    return (XLogRecPtr) DatumGetInt64(X);
+}
+
+static inline Datum
+LSNGetDatum(XLogRecPtr X)
+{
+    return Int64GetDatum((int64) X);
+}

 #define PG_GETARG_LSN(n)     DatumGetLSN(PG_GETARG_DATUM(n))
 #define PG_RETURN_LSN(x)     return LSNGetDatum(x)
diff --git a/src/include/utils/rangetypes.h b/src/include/utils/rangetypes.h
index 993fad4fc2..661e4892ec 100644
--- a/src/include/utils/rangetypes.h
+++ b/src/include/utils/rangetypes.h
@@ -68,11 +68,26 @@ typedef struct
 } RangeBound;

 /*
- * fmgr macros for range type objects
+ * fmgr functions for range type objects
  */
-#define DatumGetRangeTypeP(X)        ((RangeType *) PG_DETOAST_DATUM(X))
-#define DatumGetRangeTypePCopy(X)    ((RangeType *) PG_DETOAST_DATUM_COPY(X))
-#define RangeTypePGetDatum(X)        PointerGetDatum(X)
+static inline RangeType *
+DatumGetRangeTypeP(Datum X)
+{
+    return (RangeType *) PG_DETOAST_DATUM(X);
+}
+
+static inline RangeType *
+DatumGetRangeTypePCopy(Datum X)
+{
+    return (RangeType *) PG_DETOAST_DATUM_COPY(X);
+}
+
+static inline Datum
+RangeTypePGetDatum(const RangeType *X)
+{
+    return PointerGetDatum(X);
+}
+
 #define PG_GETARG_RANGE_P(n)        DatumGetRangeTypeP(PG_GETARG_DATUM(n))
 #define PG_GETARG_RANGE_P_COPY(n)    DatumGetRangeTypePCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_RANGE_P(x)        return RangeTypePGetDatum(x)
diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h
index edf3a97318..3602638bdc 100644
--- a/src/include/utils/timestamp.h
+++ b/src/include/utils/timestamp.h
@@ -19,18 +19,46 @@


 /*
- * Macros for fmgr-callable functions.
+ * Functions for fmgr-callable functions.
  *
  * For Timestamp, we make use of the same support routines as for int64.
  * Therefore Timestamp is pass-by-reference if and only if int64 is!
  */
-#define DatumGetTimestamp(X)  ((Timestamp) DatumGetInt64(X))
-#define DatumGetTimestampTz(X)    ((TimestampTz) DatumGetInt64(X))
-#define DatumGetIntervalP(X)  ((Interval *) DatumGetPointer(X))
-
-#define TimestampGetDatum(X) Int64GetDatum(X)
-#define TimestampTzGetDatum(X) Int64GetDatum(X)
-#define IntervalPGetDatum(X) PointerGetDatum(X)
+static inline Timestamp
+DatumGetTimestamp(Datum X)
+{
+    return (Timestamp) DatumGetInt64(X);
+}
+
+static inline TimestampTz
+DatumGetTimestampTz(Datum X)
+{
+    return (TimestampTz) DatumGetInt64(X);
+}
+
+static inline Interval *
+DatumGetIntervalP(Datum X)
+{
+    return (Interval *) DatumGetPointer(X);
+}
+
+static inline Datum
+TimestampGetDatum(Timestamp X)
+{
+    return Int64GetDatum(X);
+}
+
+static inline Datum
+TimestampTzGetDatum(TimestampTz X)
+{
+    return Int64GetDatum(X);
+}
+
+static inline Datum
+IntervalPGetDatum(const Interval *X)
+{
+    return PointerGetDatum(X);
+}

 #define PG_GETARG_TIMESTAMP(n) DatumGetTimestamp(PG_GETARG_DATUM(n))
 #define PG_GETARG_TIMESTAMPTZ(n) DatumGetTimestampTz(PG_GETARG_DATUM(n))
diff --git a/src/include/utils/uuid.h b/src/include/utils/uuid.h
index 0029da4e7f..69f4332d0f 100644
--- a/src/include/utils/uuid.h
+++ b/src/include/utils/uuid.h
@@ -23,9 +23,20 @@ typedef struct pg_uuid_t
 } pg_uuid_t;

 /* fmgr interface macros */
-#define UUIDPGetDatum(X)        PointerGetDatum(X)
+static inline Datum
+UUIDPGetDatum(const pg_uuid_t *X)
+{
+    return PointerGetDatum(X);
+}
+
 #define PG_RETURN_UUID_P(X)        return UUIDPGetDatum(X)
-#define DatumGetUUIDP(X)        ((pg_uuid_t *) DatumGetPointer(X))
+
+static inline pg_uuid_t *
+DatumGetUUIDP(Datum X)
+{
+    return (pg_uuid_t *) DatumGetPointer(X);
+}
+
 #define PG_GETARG_UUID_P(X)        DatumGetUUIDP(PG_GETARG_DATUM(X))

 #endif                            /* UUID_H */
diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h
index 039ba860cf..e65e7f65e7 100644
--- a/src/include/utils/varbit.h
+++ b/src/include/utils/varbit.h
@@ -41,9 +41,24 @@ typedef struct
  * BIT and BIT VARYING are toastable varlena types.  They are the same
  * as far as representation goes, so we just have one set of macros.
  */
-#define DatumGetVarBitP(X)           ((VarBit *) PG_DETOAST_DATUM(X))
-#define DatumGetVarBitPCopy(X)       ((VarBit *) PG_DETOAST_DATUM_COPY(X))
-#define VarBitPGetDatum(X)           PointerGetDatum(X)
+static inline VarBit *
+DatumGetVarBitP(Datum X)
+{
+    return (VarBit *) PG_DETOAST_DATUM(X);
+}
+
+static inline VarBit *
+DatumGetVarBitPCopy(Datum X)
+{
+    return (VarBit *) PG_DETOAST_DATUM_COPY(X);
+}
+
+static inline Datum
+VarBitPGetDatum(const VarBit *X)
+{
+    return PointerGetDatum(X);
+}
+
 #define PG_GETARG_VARBIT_P(n)       DatumGetVarBitP(PG_GETARG_DATUM(n))
 #define PG_GETARG_VARBIT_P_COPY(n) DatumGetVarBitPCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_VARBIT_P(x)       return VarBitPGetDatum(x)
diff --git a/src/include/utils/xid8.h b/src/include/utils/xid8.h
index b702fc1a91..9c5ce241db 100644
--- a/src/include/utils/xid8.h
+++ b/src/include/utils/xid8.h
@@ -14,8 +14,18 @@

 #include "access/transam.h"

-#define DatumGetFullTransactionId(X) (FullTransactionIdFromU64(DatumGetUInt64(X)))
-#define FullTransactionIdGetDatum(X) (UInt64GetDatum(U64FromFullTransactionId(X)))
+static inline FullTransactionId
+DatumGetFullTransactionId(Datum X)
+{
+    return FullTransactionIdFromU64(DatumGetUInt64(X));
+}
+
+static inline Datum
+FullTransactionIdGetDatum(FullTransactionId X)
+{
+    return UInt64GetDatum(U64FromFullTransactionId(X));
+}
+
 #define PG_GETARG_FULLTRANSACTIONID(X) DatumGetFullTransactionId(PG_GETARG_DATUM(X))
 #define PG_RETURN_FULLTRANSACTIONID(X) return FullTransactionIdGetDatum(X)

diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h
index 6620a62619..c71174d204 100644
--- a/src/include/utils/xml.h
+++ b/src/include/utils/xml.h
@@ -47,8 +47,17 @@ typedef enum
 /* struct PgXmlErrorContext is private to xml.c */
 typedef struct PgXmlErrorContext PgXmlErrorContext;

-#define DatumGetXmlP(X)        ((xmltype *) PG_DETOAST_DATUM(X))
-#define XmlPGetDatum(X)        PointerGetDatum(X)
+static inline xmltype *
+DatumGetXmlP(Datum X)
+{
+    return (xmltype *) PG_DETOAST_DATUM(X);
+}
+
+static inline Datum
+XmlPGetDatum(const xmltype *X)
+{
+    return PointerGetDatum(X);
+}

 #define PG_GETARG_XML_P(n)    DatumGetXmlP(PG_GETARG_DATUM(n))
 #define PG_RETURN_XML_P(x)    PG_RETURN_POINTER(x)
diff --git a/src/include/postgres.h b/src/include/postgres.h
index 45c9f6563c..5f6a1e3d5a 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -884,34 +884,26 @@ extern Datum Float8GetDatum(float8 X);
  * Int64GetDatumFast
  * Float8GetDatumFast
  *
- * These functions are intended to allow writing code that does not depend on
+ * These macros are intended to allow writing code that does not depend on
  * whether int64 and float8 are pass-by-reference types, while not
  * sacrificing performance when they are.  The argument must be a variable
  * that will exist and have the same value for as long as the Datum is needed.
  * In the pass-by-ref case, the address of the variable is taken to use as
- * the Datum.  In the pass-by-val case, these will be the same as the non-Fast
- * functions.
+ * the Datum.  In the pass-by-val case, these are the same as the non-Fast
+ * functions, except for asserting that the variable is of the correct type.
  */

-static inline Datum
-Int64GetDatumFast(int64 X)
-{
-#ifdef USE_FLOAT8_BYVAL
-    return Int64GetDatum(X);
-#else
-    return PointerGetDatum(&X);
-#endif
-}
-
-static inline Datum
-Float8GetDatumFast(float8 X)
-{
 #ifdef USE_FLOAT8_BYVAL
-    return Float8GetDatum(X);
+#define Int64GetDatumFast(X) \
+    (AssertVariableIsOfTypeMacro(X, int64), Int64GetDatum(X))
+#define Float8GetDatumFast(X) \
+    (AssertVariableIsOfTypeMacro(X, double), Float8GetDatum(X))
 #else
-    return PointerGetDatum(&X);
+#define Int64GetDatumFast(X) \
+    (AssertVariableIsOfTypeMacro(X, int64), PointerGetDatum(&(X)))
+#define Float8GetDatumFast(X) \
+    (AssertVariableIsOfTypeMacro(X, double), PointerGetDatum(&(X)))
 #endif
-}


 /* ----------------------------------------------------------------

pgsql-hackers by date:

Previous
From: Robert Haas
Date:
Subject: Re: has_privs_of_role vs. is_member_of_role, redux
Next
From: Tom Lane
Date:
Subject: Re: kerberos/001_auth test fails on arm CPU darwin