Mostly Harmless: Welcoming our C++ friends - Mailing list pgsql-hackers

Hi,

Sometimes people would like to call C++ code in the PostgreSQL
backend environment... for example, in user-defined functions,
triggers, access methods.  And there is sometimes a need for
C++ code to call back into PostgreSQL's C functions, such as
the SPI interface.  Many useful software packages and
libraries are written in C++.

The attached series of 4 patches is meant to provide a minimal
level of support for C++ aficionados to easily compile and link
with the PostgreSQL backend.  No new interfaces or wrappers are
provided.  The goal is merely to make the backend a friendlier
place for developing extensions involving C++, with minimal
impact on the existing C code.

The proposed change is divided into 4 patches with the hope
that each will be simple and easy to review.  They can be
reviewed and discussed independently, and I hope some or
all may be judged benign enough to be taken up into 8.5 or
earlier.

The patches are described in more detail below.  They are:

    1.  c++reserved -- changes a few field and parameter
        names which happened to be C++ reserved words

    2.  c++bookends -- adds C linkage declarations to a
        few header files

    3.  c++configure -- adds C++ support to 'configure',
        'make', and 'pg_config'.  A new configure option
        --enable-cplusplus links the C++ runtime library
        in to the postgres backend.

    4.  c++exception -- converts unhandled C++ exceptions to
        PostgreSQL elog(FATAL) errors

Regards,
... kurt


These patches are based on CVS head in which the latest commit was
  user:        petere
  date:        Thu Dec 04 17:51:28 2008 +0000
  summary:     Default values for function arguments


1. c++reserved

    User-defined functions and extensions may need to access
    backend data structures such as parse trees.  A few of the
    relevant header files contain field or parameter names
    which happen to be C++ reserved words.  This makes them
    unusable from C++ because the compiler chokes on the
    reserved word.  It has been suggested that the C++ user
    could surround these #includes with #defines to substitute
    innocuous words for the reserved words; but that would be
    unbearably kludgy, error prone and unmaintainable.  A polite
    host does not demand such things of a guest.

    Fortunately, there are not many instances which are likely
    to be encountered by our C++ guests, and these can easily
    be changed.  In memnodes.h, parsenodes.h, and primnodes.h,
    this patch changes the following field names:

        typename => typeName
        typeid => typeOid
        using => usingClause
        delete => delete_context

    Also, the patch changes a few parameter names in function
    prototypes in makefuncs.h, parse_type.h, and builtins.h:

                 typename => typeName
        typeid => typeOid
        namespace => qualifier

    There's no need to ask PostgreSQL developers to remember to
         avoid C++ reserved words, because C++ users who are affected
    by such occurrences can be asked to submit a corrective patch.

2. c++bookends

    C++ code can call C functions and share global variables with C,
    provided those declarations are surrounded by "bookends":

        extern "C" {
        ...
        };

    Header files can be made bilingual, to declare interfaces which
    look the same to both C and C++ callers.  This is done by
    placing C++ bookends within the header file, guarded by #ifdefs

        #ifdef __cplusplus
        extern "C" {
        #endif
        ...
        #ifdef __cplusplus
        }; /* extern "C" */
        #endif

    This way the C++ caller can just #include the header file without
    worrying whether the interface is implemented in C or C++.

    Usually, extension modules written in C++ will put bookends around
    all of their PostgreSQL #includes.

    However, "postgres.h" usually stands alone as the first #include,
    followed by some system #includes, and then the rest of the
    PostgreSQL #includes.  It is much nicer if a C++ file has just one
    pair of bookends around its main block of PostgreSQL #includes.
    This patch gives postgres.h its own internal bookends, making it
    bilingual, so that its #include can continue to stand alone at the
    head of each file.

    Just a few additional header files are mentioned in the PostgreSQL
    Reference Manual for add-on developers to use: fmgr.h, funcapi.h,
    and spi.h.  This patch adds bookends within those three files for
    the benefit of beginners writing very simple extensions in C++.
    Documentation and learning are simplified because C example code
    can be compiled as C or C++ without change.

3. c++configure

    This patch adds C++ support to the PostgreSQL build system.

    After you have applied the patch, cd to the top of the source
    tree (to the directory containing the file 'configure.in') and
    execute these two commands to regenerate the 'configure' script
    and some related files:
        autoconf
        autoheader

    Much as it already does for the C compiler, the 'configure' script
    will try to find the C++ compiler and set up appropriate command
    line options.  If 'configure' finds a C++ compiler, it will set up
    src/Makefile.global to define the following makefile variables:

        CXX = command for invoking C++ compiler
        CXXCPP = command for invoking C++ preprocessor
        CXXFLAGS = C++ compiler options
        GXX = 'yes' if the C++ compiler is gcc/g++

    Implicit rules are defined so that gmake will automatically invoke
    the C++ compiler using the above variables given a source file name
    suffixed with '.cpp' or '.cc'.  So, to add a file named marvin.cpp
    to the build, just add 'marvin.o' to the OBJS list in the Makefile.

    To C++-compile a file with '.c' suffix, the Makefile should list
    the .o file in both OBJS and CXXOBJS.

    The pg_config utility can be used to display the CXX and CXXFLAGS.

    Most C++ code typically uses some C++ features whose implementation
    makes use of the compiler's runtime library: exceptions, static
    constructors, new/delete, STL containers, stream I/O, etc.  Specify
    the following 'configure' option to link the C++ runtime library
    into the postgres backend:

        --enable-cplusplus

    If --enable-cplusplus is specified, the makefile variable
    'enable_cplusplus' will be set to 'yes', and pg_config.h will
    #define ENABLE_CPLUSPLUS.

    To ensure that the C++ runtime library is properly initialized,
    on some platforms it is necessary for the main() function to be
    compiled as C++.  Therefore, if --enable-cplusplus is configured,
    src/backend/main/main.c will be compiled as C++.  This is
    handled by the following lines in src/backend/main/Makefile:

        ifeq ($(enable_cplusplus),yes)
        CXXOBJS = main.o
        endif

    Fortunately, main.c can be compiled as either C or C++ with no
    difficulty after applying the c++reserved and c++bookends
    patches.  To make main.c bilingual, all that was needed was
    a pair of bookends around its #includes.

    Limitations:

    - I haven't added support for profiling and code coverage for
      C++.  Automatic dependency generation is supported, however.

    - This ought to work on platforms which use GCC, and maybe some
      others.  The only one I have tested is x86_32 Linux with GCC
      4.1.2.  Hopefully some interested hackers will try it on
      platforms to which they have access, and post the results.

4. c++exception

    When C code calls C++ code, all C++ exceptions need to be caught
    and fully contained within the C++ code.  Exceptions should never
    be thrown outward across the C/C++ frontier.

    If an exception is not caught within C++ code, and the search for
    a matching 'catch' bumps into a C stack frame, the result may be
    platform dependent.  On my platform (Linux/GCC), if this happens
    in the postgres backend, the process terminates silently as if
    abort() had been called.

    With this patch, if --enable-cplusplus is configured,
    PostgresMain defines a handler to intercept any uncaught C++
    exception and convert it to a conventional PostgreSQL error of
    FATAL severity.  This allows the backend to clean up and report
    the error before terminating.




















diff -r bd5a52b2681a src/backend/access/common/tupdesc.c
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -532,10 +532,10 @@
         attnum++;

         attname = entry->colname;
-        atttypid = typenameTypeId(NULL, entry->typename, &atttypmod);
-        attdim = list_length(entry->typename->arrayBounds);
+        atttypid = typenameTypeId(NULL, entry->typeName, &atttypmod);
+        attdim = list_length(entry->typeName->arrayBounds);

-        if (entry->typename->setof)
+        if (entry->typeName->setof)
             ereport(ERROR,
                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                      errmsg("column \"%s\" cannot be declared SETOF",
diff -r bd5a52b2681a src/backend/commands/sequence.c
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -141,53 +141,53 @@
         switch (i)
         {
             case SEQ_COL_NAME:
-                coldef->typename = makeTypeNameFromOid(NAMEOID, -1);
+                coldef->typeName = makeTypeNameFromOid(NAMEOID, -1);
                 coldef->colname = "sequence_name";
                 namestrcpy(&name, seq->sequence->relname);
                 value[i - 1] = NameGetDatum(&name);
                 break;
             case SEQ_COL_LASTVAL:
-                coldef->typename = makeTypeNameFromOid(INT8OID, -1);
+                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                 coldef->colname = "last_value";
                 value[i - 1] = Int64GetDatumFast(new.last_value);
                 break;
             case SEQ_COL_STARTVAL:
-                coldef->typename = makeTypeNameFromOid(INT8OID, -1);
+                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                 coldef->colname = "start_value";
                 value[i - 1] = Int64GetDatumFast(new.start_value);
                 break;
             case SEQ_COL_INCBY:
-                coldef->typename = makeTypeNameFromOid(INT8OID, -1);
+                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                 coldef->colname = "increment_by";
                 value[i - 1] = Int64GetDatumFast(new.increment_by);
                 break;
             case SEQ_COL_MAXVALUE:
-                coldef->typename = makeTypeNameFromOid(INT8OID, -1);
+                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                 coldef->colname = "max_value";
                 value[i - 1] = Int64GetDatumFast(new.max_value);
                 break;
             case SEQ_COL_MINVALUE:
-                coldef->typename = makeTypeNameFromOid(INT8OID, -1);
+                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                 coldef->colname = "min_value";
                 value[i - 1] = Int64GetDatumFast(new.min_value);
                 break;
             case SEQ_COL_CACHE:
-                coldef->typename = makeTypeNameFromOid(INT8OID, -1);
+                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                 coldef->colname = "cache_value";
                 value[i - 1] = Int64GetDatumFast(new.cache_value);
                 break;
             case SEQ_COL_LOG:
-                coldef->typename = makeTypeNameFromOid(INT8OID, -1);
+                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                 coldef->colname = "log_cnt";
                 value[i - 1] = Int64GetDatum((int64) 1);
                 break;
             case SEQ_COL_CYCLE:
-                coldef->typename = makeTypeNameFromOid(BOOLOID, -1);
+                coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
                 coldef->colname = "is_cycled";
                 value[i - 1] = BoolGetDatum(new.is_cycled);
                 break;
             case SEQ_COL_CALLED:
-                coldef->typename = makeTypeNameFromOid(BOOLOID, -1);
+                coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
                 coldef->colname = "is_called";
                 value[i - 1] = BoolGetDatum(false);
                 break;
diff -r bd5a52b2681a src/backend/commands/tablecmds.c
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -303,7 +303,7 @@
                       bool recurse, bool recursing,
                       AlterTableCmd *cmd);
 static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
-                      const char *colName, TypeName *typename);
+                      const char *colName, TypeName *typeName);
 static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab);
 static void ATPostAlterTypeParse(char *cmd, List **wqueue);
 static void change_owner_recurse_to_sequences(Oid relationOid,
@@ -1251,7 +1251,7 @@
                         (errmsg("merging multiple inherited definitions of column \"%s\"",
                                 attributeName)));
                 def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
-                defTypeId = typenameTypeId(NULL, def->typename, &deftypmod);
+                defTypeId = typenameTypeId(NULL, def->typeName, &deftypmod);
                 if (defTypeId != attribute->atttypid ||
                     deftypmod != attribute->atttypmod)
                     ereport(ERROR,
@@ -1259,7 +1259,7 @@
                         errmsg("inherited column \"%s\" has a type conflict",
                                attributeName),
                              errdetail("%s versus %s",
-                                       TypeNameToString(def->typename),
+                                       TypeNameToString(def->typeName),
                                        format_type_be(attribute->atttypid))));
                 def->inhcount++;
                 /* Merge of NOT NULL constraints = OR 'em together */
@@ -1274,7 +1274,7 @@
                  */
                 def = makeNode(ColumnDef);
                 def->colname = pstrdup(attributeName);
-                def->typename = makeTypeNameFromOid(attribute->atttypid,
+                def->typeName = makeTypeNameFromOid(attribute->atttypid,
                                                     attribute->atttypmod);
                 def->inhcount = 1;
                 def->is_local = false;
@@ -1409,16 +1409,16 @@
                    (errmsg("merging column \"%s\" with inherited definition",
                            attributeName)));
                 def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
-                defTypeId = typenameTypeId(NULL, def->typename, &deftypmod);
-                newTypeId = typenameTypeId(NULL, newdef->typename, &newtypmod);
+                defTypeId = typenameTypeId(NULL, def->typeName, &deftypmod);
+                newTypeId = typenameTypeId(NULL, newdef->typeName, &newtypmod);
                 if (defTypeId != newTypeId || deftypmod != newtypmod)
                     ereport(ERROR,
                             (errcode(ERRCODE_DATATYPE_MISMATCH),
                              errmsg("column \"%s\" has a type conflict",
                                     attributeName),
                              errdetail("%s versus %s",
-                                       TypeNameToString(def->typename),
-                                       TypeNameToString(newdef->typename))));
+                                       TypeNameToString(def->typeName),
+                                       TypeNameToString(newdef->typeName))));
                 /* Mark the column as locally defined */
                 def->is_local = true;
                 /* Merge of NOT NULL constraints = OR 'em together */
@@ -3480,7 +3480,7 @@
             int32        ctypmod;

             /* Okay if child matches by type */
-            ctypeId = typenameTypeId(NULL, colDef->typename, &ctypmod);
+            ctypeId = typenameTypeId(NULL, colDef->typeName, &ctypmod);
             if (ctypeId != childatt->atttypid ||
                 ctypmod != childatt->atttypmod)
                 ereport(ERROR,
@@ -3535,7 +3535,7 @@
                         MaxHeapAttributeNumber)));
     i = minattnum + 1;

-    typeTuple = typenameType(NULL, colDef->typename, &typmod);
+    typeTuple = typenameType(NULL, colDef->typeName, &typmod);
     tform = (Form_pg_type) GETSTRUCT(typeTuple);
     typeOid = HeapTupleGetOid(typeTuple);

@@ -3551,7 +3551,7 @@
     attribute.atttypmod = typmod;
     attribute.attnum = i;
     attribute.attbyval = tform->typbyval;
-    attribute.attndims = list_length(colDef->typename->arrayBounds);
+    attribute.attndims = list_length(colDef->typeName->arrayBounds);
     attribute.attstorage = tform->typstorage;
     attribute.attalign = tform->typalign;
     attribute.attnotnull = colDef->is_not_null;
@@ -5415,7 +5415,7 @@
                       AlterTableCmd *cmd)
 {
     char       *colName = cmd->name;
-    TypeName   *typename = (TypeName *) cmd->def;
+    TypeName   *typeName = (TypeName *) cmd->def;
     HeapTuple    tuple;
     Form_pg_attribute attTup;
     AttrNumber    attnum;
@@ -5450,7 +5450,7 @@
                         colName)));

     /* Look up the target type */
-    targettype = typenameTypeId(NULL, typename, &targettypmod);
+    targettype = typenameTypeId(NULL, typeName, &targettypmod);

     /* make sure datatype is legal for a column */
     CheckAttributeType(colName, targettype);
@@ -5541,7 +5541,7 @@

 static void
 ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
-                      const char *colName, TypeName *typename)
+                      const char *colName, TypeName *typeName)
 {
     HeapTuple    heapTup;
     Form_pg_attribute attTup;
@@ -5578,7 +5578,7 @@
                         colName)));

     /* Look up the target type (should not fail, since prep found it) */
-    typeTuple = typenameType(NULL, typename, &targettypmod);
+    typeTuple = typenameType(NULL, typeName, &targettypmod);
     tform = (Form_pg_type) GETSTRUCT(typeTuple);
     targettype = HeapTupleGetOid(typeTuple);

@@ -5825,7 +5825,7 @@
      */
     attTup->atttypid = targettype;
     attTup->atttypmod = targettypmod;
-    attTup->attndims = list_length(typename->arrayBounds);
+    attTup->attndims = list_length(typeName->arrayBounds);
     attTup->attlen = tform->typlen;
     attTup->attbyval = tform->typbyval;
     attTup->attalign = tform->typalign;
diff -r bd5a52b2681a src/backend/commands/typecmds.c
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -676,7 +676,7 @@
     bool        saw_default = false;
     bool        typNotNull = false;
     bool        nullDefined = false;
-    int32        typNDims = list_length(stmt->typename->arrayBounds);
+    int32        typNDims = list_length(stmt->typeName->arrayBounds);
     HeapTuple    typeTup;
     List       *schema = stmt->constraints;
     ListCell   *listptr;
@@ -716,7 +716,7 @@
     /*
      * Look up the base type.
      */
-    typeTup = typenameType(NULL, stmt->typename, &basetypeMod);
+    typeTup = typenameType(NULL, stmt->typeName, &basetypeMod);
     baseType = (Form_pg_type) GETSTRUCT(typeTup);
     basetypeoid = HeapTupleGetOid(typeTup);

@@ -732,7 +732,7 @@
         ereport(ERROR,
                 (errcode(ERRCODE_DATATYPE_MISMATCH),
                  errmsg("\"%s\" is not a valid base type for a domain",
-                        TypeNameToString(stmt->typename))));
+                        TypeNameToString(stmt->typeName))));

     /* passed by value */
     byValue = baseType->typbyval;
@@ -1013,7 +1013,7 @@
     Relation    pg_type;

     /* Convert list of names to a name and namespace */
-    enumNamespace = QualifiedNameGetCreationNamespace(stmt->typename,
+    enumNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
                                                       &enumName);

     /* Check we have creation rights in target namespace */
diff -r bd5a52b2681a src/backend/commands/view.c
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -118,7 +118,7 @@
             ColumnDef  *def = makeNode(ColumnDef);

             def->colname = pstrdup(tle->resname);
-            def->typename = makeTypeNameFromOid(exprType((Node *) tle->expr),
+            def->typeName = makeTypeNameFromOid(exprType((Node *) tle->expr),
                                              exprTypmod((Node *) tle->expr));
             def->inhcount = 0;
             def->is_local = true;
diff -r bd5a52b2681a src/backend/nodes/copyfuncs.c
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1491,7 +1491,7 @@
     COPY_SCALAR_FIELD(isNatural);
     COPY_NODE_FIELD(larg);
     COPY_NODE_FIELD(rarg);
-    COPY_NODE_FIELD(using);
+    COPY_NODE_FIELD(usingClause);
     COPY_NODE_FIELD(quals);
     COPY_NODE_FIELD(alias);
     COPY_SCALAR_FIELD(rtindex);
@@ -1915,7 +1915,7 @@
     TypeName   *newnode = makeNode(TypeName);

     COPY_NODE_FIELD(names);
-    COPY_SCALAR_FIELD(typeid);
+    COPY_SCALAR_FIELD(typeOid);
     COPY_SCALAR_FIELD(setof);
     COPY_SCALAR_FIELD(pct_type);
     COPY_NODE_FIELD(typmods);
@@ -1969,7 +1969,7 @@
     TypeCast   *newnode = makeNode(TypeCast);

     COPY_NODE_FIELD(arg);
-    COPY_NODE_FIELD(typename);
+    COPY_NODE_FIELD(typeName);
     COPY_LOCATION_FIELD(location);

     return newnode;
@@ -1995,7 +1995,7 @@
     ColumnDef  *newnode = makeNode(ColumnDef);

     COPY_STRING_FIELD(colname);
-    COPY_NODE_FIELD(typename);
+    COPY_NODE_FIELD(typeName);
     COPY_SCALAR_FIELD(inhcount);
     COPY_SCALAR_FIELD(is_local);
     COPY_SCALAR_FIELD(is_not_null);
@@ -2052,7 +2052,7 @@

     COPY_SCALAR_FIELD(xmloption);
     COPY_NODE_FIELD(expr);
-    COPY_NODE_FIELD(typename);
+    COPY_NODE_FIELD(typeName);
     COPY_LOCATION_FIELD(location);

     return newnode;
@@ -2204,7 +2204,7 @@
     AlterDomainStmt *newnode = makeNode(AlterDomainStmt);

     COPY_SCALAR_FIELD(subtype);
-    COPY_NODE_FIELD(typename);
+    COPY_NODE_FIELD(typeName);
     COPY_STRING_FIELD(name);
     COPY_NODE_FIELD(def);
     COPY_SCALAR_FIELD(behavior);
@@ -2622,7 +2622,7 @@
 {
     CreateEnumStmt *newnode = makeNode(CreateEnumStmt);

-    COPY_NODE_FIELD(typename);
+    COPY_NODE_FIELD(typeName);
     COPY_NODE_FIELD(vals);

     return newnode;
@@ -2657,7 +2657,7 @@
     CreateDomainStmt *newnode = makeNode(CreateDomainStmt);

     COPY_NODE_FIELD(domainname);
-    COPY_NODE_FIELD(typename);
+    COPY_NODE_FIELD(typeName);
     COPY_NODE_FIELD(constraints);

     return newnode;
diff -r bd5a52b2681a src/backend/nodes/equalfuncs.c
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -688,7 +688,7 @@
     COMPARE_SCALAR_FIELD(isNatural);
     COMPARE_NODE_FIELD(larg);
     COMPARE_NODE_FIELD(rarg);
-    COMPARE_NODE_FIELD(using);
+    COMPARE_NODE_FIELD(usingClause);
     COMPARE_NODE_FIELD(quals);
     COMPARE_NODE_FIELD(alias);
     COMPARE_SCALAR_FIELD(rtindex);
@@ -957,7 +957,7 @@
 _equalAlterDomainStmt(AlterDomainStmt *a, AlterDomainStmt *b)
 {
     COMPARE_SCALAR_FIELD(subtype);
-    COMPARE_NODE_FIELD(typename);
+    COMPARE_NODE_FIELD(typeName);
     COMPARE_STRING_FIELD(name);
     COMPARE_NODE_FIELD(def);
     COMPARE_SCALAR_FIELD(behavior);
@@ -1311,7 +1311,7 @@
 static bool
 _equalCreateEnumStmt(CreateEnumStmt *a, CreateEnumStmt *b)
 {
-    COMPARE_NODE_FIELD(typename);
+    COMPARE_NODE_FIELD(typeName);
     COMPARE_NODE_FIELD(vals);

     return true;
@@ -1340,7 +1340,7 @@
 _equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
 {
     COMPARE_NODE_FIELD(domainname);
-    COMPARE_NODE_FIELD(typename);
+    COMPARE_NODE_FIELD(typeName);
     COMPARE_NODE_FIELD(constraints);

     return true;
@@ -1852,7 +1852,7 @@
 _equalTypeName(TypeName *a, TypeName *b)
 {
     COMPARE_NODE_FIELD(names);
-    COMPARE_SCALAR_FIELD(typeid);
+    COMPARE_SCALAR_FIELD(typeOid);
     COMPARE_SCALAR_FIELD(setof);
     COMPARE_SCALAR_FIELD(pct_type);
     COMPARE_NODE_FIELD(typmods);
@@ -1867,7 +1867,7 @@
 _equalTypeCast(TypeCast *a, TypeCast *b)
 {
     COMPARE_NODE_FIELD(arg);
-    COMPARE_NODE_FIELD(typename);
+    COMPARE_NODE_FIELD(typeName);
     COMPARE_LOCATION_FIELD(location);

     return true;
@@ -1920,7 +1920,7 @@
 _equalColumnDef(ColumnDef *a, ColumnDef *b)
 {
     COMPARE_STRING_FIELD(colname);
-    COMPARE_NODE_FIELD(typename);
+    COMPARE_NODE_FIELD(typeName);
     COMPARE_SCALAR_FIELD(inhcount);
     COMPARE_SCALAR_FIELD(is_local);
     COMPARE_SCALAR_FIELD(is_not_null);
@@ -2062,7 +2062,7 @@
 {
     COMPARE_SCALAR_FIELD(xmloption);
     COMPARE_NODE_FIELD(expr);
-    COMPARE_NODE_FIELD(typename);
+    COMPARE_NODE_FIELD(typeName);
     COMPARE_LOCATION_FIELD(location);

     return true;
diff -r bd5a52b2681a src/backend/nodes/makefuncs.c
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -316,11 +316,11 @@
  *    build a TypeName node to represent a type already known by OID/typmod.
  */
 TypeName *
-makeTypeNameFromOid(Oid typeid, int32 typmod)
+makeTypeNameFromOid(Oid typeOid, int32 typmod)
 {
     TypeName   *n = makeNode(TypeName);

-    n->typeid = typeid;
+    n->typeOid = typeOid;
     n->typemod = typmod;
     n->location = -1;
     return n;
diff -r bd5a52b2681a src/backend/nodes/nodeFuncs.c
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -860,7 +860,7 @@
                  * so any of the components might be leftmost.
                  */
                 loc = exprLocation(tc->arg);
-                loc = leftmostLoc(loc, tc->typename->location);
+                loc = leftmostLoc(loc, tc->typeName->location);
                 loc = leftmostLoc(loc, tc->location);
             }
             break;
@@ -2359,7 +2359,7 @@

                 if (walker(tc->arg, context))
                     return true;
-                if (walker(tc->typename, context))
+                if (walker(tc->typeName, context))
                     return true;
             }
             break;
@@ -2400,7 +2400,7 @@
             {
                 ColumnDef *coldef = (ColumnDef *) node;

-                if (walker(coldef->typename, context))
+                if (walker(coldef->typeName, context))
                     return true;
                 if (walker(coldef->raw_default, context))
                     return true;
@@ -2415,7 +2415,7 @@

                 if (walker(xs->expr, context))
                     return true;
-                if (walker(xs->typename, context))
+                if (walker(xs->typeName, context))
                     return true;
             }
             break;
diff -r bd5a52b2681a src/backend/nodes/outfuncs.c
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1207,7 +1207,7 @@
     WRITE_BOOL_FIELD(isNatural);
     WRITE_NODE_FIELD(larg);
     WRITE_NODE_FIELD(rarg);
-    WRITE_NODE_FIELD(using);
+    WRITE_NODE_FIELD(usingClause);
     WRITE_NODE_FIELD(quals);
     WRITE_NODE_FIELD(alias);
     WRITE_INT_FIELD(rtindex);
@@ -1772,7 +1772,7 @@

     WRITE_ENUM_FIELD(xmloption, XmlOptionType);
     WRITE_NODE_FIELD(expr);
-    WRITE_NODE_FIELD(typename);
+    WRITE_NODE_FIELD(typeName);
     WRITE_LOCATION_FIELD(location);
 }

@@ -1782,7 +1782,7 @@
     WRITE_NODE_TYPE("COLUMNDEF");

     WRITE_STRING_FIELD(colname);
-    WRITE_NODE_FIELD(typename);
+    WRITE_NODE_FIELD(typeName);
     WRITE_INT_FIELD(inhcount);
     WRITE_BOOL_FIELD(is_local);
     WRITE_BOOL_FIELD(is_not_null);
@@ -1797,7 +1797,7 @@
     WRITE_NODE_TYPE("TYPENAME");

     WRITE_NODE_FIELD(names);
-    WRITE_OID_FIELD(typeid);
+    WRITE_OID_FIELD(typeOid);
     WRITE_BOOL_FIELD(setof);
     WRITE_BOOL_FIELD(pct_type);
     WRITE_NODE_FIELD(typmods);
@@ -1812,7 +1812,7 @@
     WRITE_NODE_TYPE("TYPECAST");

     WRITE_NODE_FIELD(arg);
-    WRITE_NODE_FIELD(typename);
+    WRITE_NODE_FIELD(typeName);
     WRITE_LOCATION_FIELD(location);
 }

diff -r bd5a52b2681a src/backend/nodes/readfuncs.c
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -984,7 +984,7 @@
     READ_BOOL_FIELD(isNatural);
     READ_NODE_FIELD(larg);
     READ_NODE_FIELD(rarg);
-    READ_NODE_FIELD(using);
+    READ_NODE_FIELD(usingClause);
     READ_NODE_FIELD(quals);
     READ_NODE_FIELD(alias);
     READ_INT_FIELD(rtindex);
diff -r bd5a52b2681a src/backend/parser/gram.y
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -2021,7 +2021,7 @@
                 {
                     ColumnDef *n = makeNode(ColumnDef);
                     n->colname = $1;
-                    n->typename = $2;
+                    n->typeName = $2;
                     n->constraints = $3;
                     n->is_local = true;
                     $$ = (Node *)n;
@@ -2468,7 +2468,7 @@
                 {
                     ColumnDef *n = makeNode(ColumnDef);
                     n->colname = $1;
-                    n->typename = NULL;
+                    n->typeName = NULL;
                     n->inhcount = 0;
                     n->is_local = true;
                     n->is_not_null = false;
@@ -3056,7 +3056,7 @@
             | CREATE TYPE_P any_name AS ENUM_P '(' enum_val_list ')'
                 {
                     CreateEnumStmt *n = makeNode(CreateEnumStmt);
-                    n->typename = $3;
+                    n->typeName = $3;
                     n->vals = $7;
                     $$ = (Node *)n;
                 }
@@ -5622,7 +5622,7 @@
                 {
                     CreateDomainStmt *n = makeNode(CreateDomainStmt);
                     n->domainname = $3;
-                    n->typename = $5;
+                    n->typeName = $5;
                     n->constraints = $6;
                     $$ = (Node *)n;
                 }
@@ -5634,7 +5634,7 @@
                 {
                     AlterDomainStmt *n = makeNode(AlterDomainStmt);
                     n->subtype = 'T';
-                    n->typename = $3;
+                    n->typeName = $3;
                     n->def = $4;
                     $$ = (Node *)n;
                 }
@@ -5643,7 +5643,7 @@
                 {
                     AlterDomainStmt *n = makeNode(AlterDomainStmt);
                     n->subtype = 'N';
-                    n->typename = $3;
+                    n->typeName = $3;
                     $$ = (Node *)n;
                 }
             /* ALTER DOMAIN <domain> SET NOT NULL */
@@ -5651,7 +5651,7 @@
                 {
                     AlterDomainStmt *n = makeNode(AlterDomainStmt);
                     n->subtype = 'O';
-                    n->typename = $3;
+                    n->typeName = $3;
                     $$ = (Node *)n;
                 }
             /* ALTER DOMAIN <domain> ADD CONSTRAINT ... */
@@ -5659,7 +5659,7 @@
                 {
                     AlterDomainStmt *n = makeNode(AlterDomainStmt);
                     n->subtype = 'C';
-                    n->typename = $3;
+                    n->typeName = $3;
                     n->def = $5;
                     $$ = (Node *)n;
                 }
@@ -5668,7 +5668,7 @@
                 {
                     AlterDomainStmt *n = makeNode(AlterDomainStmt);
                     n->subtype = 'X';
-                    n->typename = $3;
+                    n->typeName = $3;
                     n->name = $6;
                     n->behavior = $7;
                     $$ = (Node *)n;
@@ -6920,7 +6920,7 @@
                     n->isNatural = FALSE;
                     n->larg = $1;
                     n->rarg = $4;
-                    n->using = NIL;
+                    n->usingClause = NIL;
                     n->quals = NULL;
                     $$ = n;
                 }
@@ -6932,7 +6932,7 @@
                     n->larg = $1;
                     n->rarg = $4;
                     if ($5 != NULL && IsA($5, List))
-                        n->using = (List *) $5; /* USING clause */
+                        n->usingClause = (List *) $5; /* USING clause */
                     else
                         n->quals = $5; /* ON clause */
                     $$ = n;
@@ -6946,7 +6946,7 @@
                     n->larg = $1;
                     n->rarg = $3;
                     if ($4 != NULL && IsA($4, List))
-                        n->using = (List *) $4; /* USING clause */
+                        n->usingClause = (List *) $4; /* USING clause */
                     else
                         n->quals = $4; /* ON clause */
                     $$ = n;
@@ -6958,7 +6958,7 @@
                     n->isNatural = TRUE;
                     n->larg = $1;
                     n->rarg = $5;
-                    n->using = NIL; /* figure out which columns later... */
+                    n->usingClause = NIL; /* figure out which columns later... */
                     n->quals = NULL; /* fill later */
                     $$ = n;
                 }
@@ -6970,7 +6970,7 @@
                     n->isNatural = TRUE;
                     n->larg = $1;
                     n->rarg = $4;
-                    n->using = NIL; /* figure out which columns later... */
+                    n->usingClause = NIL; /* figure out which columns later... */
                     n->quals = NULL; /* fill later */
                     $$ = n;
                 }
@@ -7135,7 +7135,7 @@
                 {
                     ColumnDef *n = makeNode(ColumnDef);
                     n->colname = $1;
-                    n->typename = $2;
+                    n->typeName = $2;
                     n->constraints = NIL;
                     n->is_local = true;
                     $$ = (Node *)n;
@@ -8694,7 +8694,7 @@
                     XmlSerialize *n = makeNode(XmlSerialize);
                     n->xmloption = $3;
                     n->expr = $4;
-                    n->typename = $6;
+                    n->typeName = $6;
                     n->location = @1;
                     $$ = (Node *)n;
                 }
@@ -9906,7 +9906,7 @@
 {
     TypeCast *n = makeNode(TypeCast);
     n->arg = arg;
-    n->typename = typename;
+    n->typeName = typename;
     n->location = location;
     return (Node *) n;
 }
diff -r bd5a52b2681a src/backend/parser/parse_clause.c
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -772,7 +772,7 @@
             ListCell   *lx,
                        *rx;

-            Assert(j->using == NIL);    /* shouldn't have USING() too */
+            Assert(j->usingClause == NIL);    /* shouldn't have USING() too */

             foreach(lx, l_colnames)
             {
@@ -795,7 +795,7 @@
                     rlist = lappend(rlist, m_name);
             }

-            j->using = rlist;
+            j->usingClause = rlist;
         }

         /*
@@ -804,14 +804,14 @@
         res_colnames = NIL;
         res_colvars = NIL;

-        if (j->using)
+        if (j->usingClause)
         {
             /*
              * JOIN/USING (or NATURAL JOIN, as transformed above). Transform
              * the list into an explicit ON-condition, and generate a list of
              * merged result columns.
              */
-            List       *ucols = j->using;
+            List       *ucols = j->usingClause;
             List       *l_usingvars = NIL;
             List       *r_usingvars = NIL;
             ListCell   *ucol;
diff -r bd5a52b2681a src/backend/parser/parse_expr.c
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -159,7 +159,7 @@
                     Oid            elementType;
                     int32        targetTypmod;

-                    targetType = typenameTypeId(pstate, tc->typename,
+                    targetType = typenameTypeId(pstate, tc->typeName,
                                                 &targetTypmod);
                     elementType = get_element_type(targetType);
                     if (OidIsValid(elementType))
@@ -1770,7 +1770,7 @@
                                                      XMLOID,
                                                      "XMLSERIALIZE"));

-    targetType = typenameTypeId(pstate, xs->typename, &targetTypmod);
+    targetType = typenameTypeId(pstate, xs->typeName, &targetTypmod);

     xexpr->xmloption = xs->xmloption;
     xexpr->location = xs->location;
@@ -1994,7 +1994,7 @@
     int32        targetTypmod;
     int            location;

-    targetType = typenameTypeId(pstate, tc->typename, &targetTypmod);
+    targetType = typenameTypeId(pstate, tc->typeName, &targetTypmod);

     if (inputType == InvalidOid)
         return expr;            /* do nothing if NULL input */
@@ -2006,7 +2006,7 @@
      */
     location = tc->location;
     if (location < 0)
-        location = tc->typename->location;
+        location = tc->typeName->location;

     result = coerce_to_target_type(pstate, expr, inputType,
                                    targetType, targetTypmod,
diff -r bd5a52b2681a src/backend/parser/parse_relation.c
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1067,13 +1067,13 @@
             int32        attrtypmod;

             attrname = pstrdup(n->colname);
-            if (n->typename->setof)
+            if (n->typeName->setof)
                 ereport(ERROR,
                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                          errmsg("column \"%s\" cannot be declared SETOF",
                                 attrname),
-                         parser_errposition(pstate, n->typename->location)));
-            attrtype = typenameTypeId(pstate, n->typename, &attrtypmod);
+                         parser_errposition(pstate, n->typeName->location)));
+            attrtype = typenameTypeId(pstate, n->typeName, &attrtypmod);
             eref->colnames = lappend(eref->colnames, makeString(attrname));
             rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype);
             rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod);
diff -r bd5a52b2681a src/backend/parser/parse_target.c
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -1355,9 +1355,9 @@
                                              name);
             if (strength <= 1)
             {
-                if (((TypeCast *) node)->typename != NULL)
+                if (((TypeCast *) node)->typeName != NULL)
                 {
-                    *name = strVal(llast(((TypeCast *) node)->typename->names));
+                    *name = strVal(llast(((TypeCast *) node)->typeName->names));
                     return 1;
                 }
             }
diff -r bd5a52b2681a src/backend/parser/parse_type.c
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -27,7 +27,7 @@
 #include "utils/syscache.h"


-static int32 typenameTypeMod(ParseState *pstate, const TypeName *typename,
+static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName,
                 Type typ);


@@ -54,57 +54,57 @@
  * pstate is only used for error location info, and may be NULL.
  */
 Type
-LookupTypeName(ParseState *pstate, const TypeName *typename,
+LookupTypeName(ParseState *pstate, const TypeName *typeName,
                int32 *typmod_p)
 {
     Oid            typoid;
     HeapTuple    tup;
     int32        typmod;

-    if (typename->names == NIL)
+    if (typeName->names == NIL)
     {
         /* We have the OID already if it's an internally generated TypeName */
-        typoid = typename->typeid;
+        typoid = typeName->typeOid;
     }
-    else if (typename->pct_type)
+    else if (typeName->pct_type)
     {
         /* Handle %TYPE reference to type of an existing field */
-        RangeVar   *rel = makeRangeVar(NULL, NULL, typename->location);
+        RangeVar   *rel = makeRangeVar(NULL, NULL, typeName->location);
         char       *field = NULL;
         Oid            relid;
         AttrNumber    attnum;

         /* deconstruct the name list */
-        switch (list_length(typename->names))
+        switch (list_length(typeName->names))
         {
             case 1:
                 ereport(ERROR,
                         (errcode(ERRCODE_SYNTAX_ERROR),
                 errmsg("improper %%TYPE reference (too few dotted names): %s",
-                       NameListToString(typename->names)),
-                         parser_errposition(pstate, typename->location)));
+                       NameListToString(typeName->names)),
+                         parser_errposition(pstate, typeName->location)));
                 break;
             case 2:
-                rel->relname = strVal(linitial(typename->names));
-                field = strVal(lsecond(typename->names));
+                rel->relname = strVal(linitial(typeName->names));
+                field = strVal(lsecond(typeName->names));
                 break;
             case 3:
-                rel->schemaname = strVal(linitial(typename->names));
-                rel->relname = strVal(lsecond(typename->names));
-                field = strVal(lthird(typename->names));
+                rel->schemaname = strVal(linitial(typeName->names));
+                rel->relname = strVal(lsecond(typeName->names));
+                field = strVal(lthird(typeName->names));
                 break;
             case 4:
-                rel->catalogname = strVal(linitial(typename->names));
-                rel->schemaname = strVal(lsecond(typename->names));
-                rel->relname = strVal(lthird(typename->names));
-                field = strVal(lfourth(typename->names));
+                rel->catalogname = strVal(linitial(typeName->names));
+                rel->schemaname = strVal(lsecond(typeName->names));
+                rel->relname = strVal(lthird(typeName->names));
+                field = strVal(lfourth(typeName->names));
                 break;
             default:
                 ereport(ERROR,
                         (errcode(ERRCODE_SYNTAX_ERROR),
                          errmsg("improper %%TYPE reference (too many dotted names): %s",
-                                NameListToString(typename->names)),
-                         parser_errposition(pstate, typename->location)));
+                                NameListToString(typeName->names)),
+                         parser_errposition(pstate, typeName->location)));
                 break;
         }

@@ -116,16 +116,16 @@
                     (errcode(ERRCODE_UNDEFINED_COLUMN),
                      errmsg("column \"%s\" of relation \"%s\" does not exist",
                             field, rel->relname),
-                     parser_errposition(pstate, typename->location)));
+                     parser_errposition(pstate, typeName->location)));
         typoid = get_atttype(relid, attnum);

         /* this construct should never have an array indicator */
-        Assert(typename->arrayBounds == NIL);
+        Assert(typeName->arrayBounds == NIL);

         /* emit nuisance notice (intentionally not errposition'd) */
         ereport(NOTICE,
                 (errmsg("type reference %s converted to %s",
-                        TypeNameToString(typename),
+                        TypeNameToString(typeName),
                         format_type_be(typoid))));
     }
     else
@@ -135,7 +135,7 @@
         char       *typname;

         /* deconstruct the name list */
-        DeconstructQualifiedName(typename->names, &schemaname, &typname);
+        DeconstructQualifiedName(typeName->names, &schemaname, &typname);

         if (schemaname)
         {
@@ -155,7 +155,7 @@
         }

         /* If an array reference, return the array type instead */
-        if (typename->arrayBounds != NIL)
+        if (typeName->arrayBounds != NIL)
             typoid = get_array_type(typoid);
     }

@@ -172,7 +172,7 @@
     if (!HeapTupleIsValid(tup)) /* should not happen */
         elog(ERROR, "cache lookup failed for type %u", typoid);

-    typmod = typenameTypeMod(pstate, typename, (Type) tup);
+    typmod = typenameTypeMod(pstate, typeName, (Type) tup);

     if (typmod_p)
         *typmod_p = typmod;
@@ -188,23 +188,23 @@
  * Callers of this can therefore assume the result is a fully valid type.
  */
 Type
-typenameType(ParseState *pstate, const TypeName *typename, int32 *typmod_p)
+typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
 {
     Type        tup;

-    tup = LookupTypeName(pstate, typename, typmod_p);
+    tup = LookupTypeName(pstate, typeName, typmod_p);
     if (tup == NULL)
         ereport(ERROR,
                 (errcode(ERRCODE_UNDEFINED_OBJECT),
                  errmsg("type \"%s\" does not exist",
-                        TypeNameToString(typename)),
-                 parser_errposition(pstate, typename->location)));
+                        TypeNameToString(typeName)),
+                 parser_errposition(pstate, typeName->location)));
     if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
         ereport(ERROR,
                 (errcode(ERRCODE_UNDEFINED_OBJECT),
                  errmsg("type \"%s\" is only a shell",
-                        TypeNameToString(typename)),
-                 parser_errposition(pstate, typename->location)));
+                        TypeNameToString(typeName)),
+                 parser_errposition(pstate, typeName->location)));
     return tup;
 }

@@ -215,12 +215,12 @@
  * not the syscache entry.
  */
 Oid
-typenameTypeId(ParseState *pstate, const TypeName *typename, int32 *typmod_p)
+typenameTypeId(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
 {
     Oid            typoid;
     Type        tup;

-    tup = typenameType(pstate, typename, typmod_p);
+    tup = typenameType(pstate, typeName, typmod_p);
     typoid = HeapTupleGetOid(tup);
     ReleaseSysCache(tup);

@@ -239,7 +239,7 @@
  * pstate is only used for error location info, and may be NULL.
  */
 static int32
-typenameTypeMod(ParseState *pstate, const TypeName *typename, Type typ)
+typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ)
 {
     int32        result;
     Oid            typmodin;
@@ -250,8 +250,8 @@
     ParseCallbackState pcbstate;

     /* Return prespecified typmod if no typmod expressions */
-    if (typename->typmods == NIL)
-        return typename->typemod;
+    if (typeName->typmods == NIL)
+        return typeName->typemod;

     /*
      * Else, type had better accept typmods.  We give a special error message
@@ -262,8 +262,8 @@
         ereport(ERROR,
                 (errcode(ERRCODE_SYNTAX_ERROR),
             errmsg("type modifier cannot be specified for shell type \"%s\"",
-                   TypeNameToString(typename)),
-                 parser_errposition(pstate, typename->location)));
+                   TypeNameToString(typeName)),
+                 parser_errposition(pstate, typeName->location)));

     typmodin = ((Form_pg_type) GETSTRUCT(typ))->typmodin;

@@ -271,17 +271,17 @@
         ereport(ERROR,
                 (errcode(ERRCODE_SYNTAX_ERROR),
                  errmsg("type modifier is not allowed for type \"%s\"",
-                        TypeNameToString(typename)),
-                 parser_errposition(pstate, typename->location)));
+                        TypeNameToString(typeName)),
+                 parser_errposition(pstate, typeName->location)));

     /*
      * Convert the list of raw-grammar-output expressions to a cstring array.
      * Currently, we allow simple numeric constants, string literals, and
      * identifiers; possibly this list could be extended.
      */
-    datums = (Datum *) palloc(list_length(typename->typmods) * sizeof(Datum));
+    datums = (Datum *) palloc(list_length(typeName->typmods) * sizeof(Datum));
     n = 0;
-    foreach(l, typename->typmods)
+    foreach(l, typeName->typmods)
     {
         Node       *tm = (Node *) lfirst(l);
         char       *cstr = NULL;
@@ -314,7 +314,7 @@
             ereport(ERROR,
                     (errcode(ERRCODE_SYNTAX_ERROR),
             errmsg("type modifiers must be simple constants or identifiers"),
-                     parser_errposition(pstate, typename->location)));
+                     parser_errposition(pstate, typeName->location)));
         datums[n++] = CStringGetDatum(cstr);
     }

@@ -323,7 +323,7 @@
                                 -2, false, 'c');

     /* arrange to report location if type's typmodin function fails */
-    setup_parser_errposition_callback(&pcbstate, pstate, typename->location);
+    setup_parser_errposition_callback(&pcbstate, pstate, typeName->location);

     result = DatumGetInt32(OidFunctionCall1(typmodin,
                                             PointerGetDatum(arrtypmod)));
@@ -345,16 +345,16 @@
  * it is mostly used for reporting lookup errors.
  */
 static void
-appendTypeNameToBuffer(const TypeName *typename, StringInfo string)
+appendTypeNameToBuffer(const TypeName *typeName, StringInfo string)
 {
-    if (typename->names != NIL)
+    if (typeName->names != NIL)
     {
         /* Emit possibly-qualified name as-is */
         ListCell   *l;

-        foreach(l, typename->names)
+        foreach(l, typeName->names)
         {
-            if (l != list_head(typename->names))
+            if (l != list_head(typeName->names))
                 appendStringInfoChar(string, '.');
             appendStringInfoString(string, strVal(lfirst(l)));
         }
@@ -362,17 +362,17 @@
     else
     {
         /* Look up internally-specified type */
-        appendStringInfoString(string, format_type_be(typename->typeid));
+        appendStringInfoString(string, format_type_be(typeName->typeOid));
     }

     /*
      * Add decoration as needed, but only for fields considered by
      * LookupTypeName
      */
-    if (typename->pct_type)
+    if (typeName->pct_type)
         appendStringInfoString(string, "%TYPE");

-    if (typename->arrayBounds != NIL)
+    if (typeName->arrayBounds != NIL)
         appendStringInfoString(string, "[]");
 }

@@ -384,12 +384,12 @@
  * it is mostly used for reporting lookup errors.
  */
 char *
-TypeNameToString(const TypeName *typename)
+TypeNameToString(const TypeName *typeName)
 {
     StringInfoData string;

     initStringInfo(&string);
-    appendTypeNameToBuffer(typename, &string);
+    appendTypeNameToBuffer(typeName, &string);
     return string.data;
 }

@@ -406,12 +406,12 @@
     initStringInfo(&string);
     foreach(l, typenames)
     {
-        TypeName   *typename = (TypeName *) lfirst(l);
+        TypeName   *typeName = (TypeName *) lfirst(l);

-        Assert(IsA(typename, TypeName));
+        Assert(IsA(typeName, TypeName));
         if (l != list_head(typenames))
             appendStringInfoChar(&string, ',');
-        appendTypeNameToBuffer(typename, &string);
+        appendTypeNameToBuffer(typeName, &string);
     }
     return string.data;
 }
@@ -574,7 +574,7 @@
     SelectStmt *stmt;
     ResTarget  *restarget;
     TypeCast   *typecast;
-    TypeName   *typename;
+    TypeName   *typeName;
     ErrorContextCallback ptserrcontext;

     /* make sure we give useful error for empty input */
@@ -633,14 +633,14 @@
         typecast->arg == NULL ||
         !IsA(typecast->arg, A_Const))
         goto fail;
-    typename = typecast->typename;
-    if (typename == NULL ||
-        !IsA(typename, TypeName))
+    typeName = typecast->typeName;
+    if (typeName == NULL ||
+        !IsA(typeName, TypeName))
         goto fail;
-    if (typename->setof)
+    if (typeName->setof)
         goto fail;

-    *type_id = typenameTypeId(NULL, typename, typmod_p);
+    *type_id = typenameTypeId(NULL, typeName, typmod_p);

     pfree(buf.data);

diff -r bd5a52b2681a src/backend/parser/parse_utilcmd.c
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -266,24 +266,24 @@

     /* Check for SERIAL pseudo-types */
     is_serial = false;
-    if (list_length(column->typename->names) == 1 &&
-        !column->typename->pct_type)
+    if (list_length(column->typeName->names) == 1 &&
+        !column->typeName->pct_type)
     {
-        char       *typname = strVal(linitial(column->typename->names));
+        char       *typname = strVal(linitial(column->typeName->names));

         if (strcmp(typname, "serial") == 0 ||
             strcmp(typname, "serial4") == 0)
         {
             is_serial = true;
-            column->typename->names = NIL;
-            column->typename->typeid = INT4OID;
+            column->typeName->names = NIL;
+            column->typeName->typeOid = INT4OID;
         }
         else if (strcmp(typname, "bigserial") == 0 ||
                  strcmp(typname, "serial8") == 0)
         {
             is_serial = true;
-            column->typename->names = NIL;
-            column->typename->typeid = INT8OID;
+            column->typeName->names = NIL;
+            column->typeName->typeOid = INT8OID;
         }

         /*
@@ -291,7 +291,7 @@
          * set typeid, LookupTypeName won't notice arrayBounds.  We don't
          * need any special coding for serial(typmod) though.
          */
-        if (is_serial && column->typename->arrayBounds != NIL)
+        if (is_serial && column->typeName->arrayBounds != NIL)
             ereport(ERROR,
                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                      errmsg("array of serial is not implemented")));
@@ -382,7 +382,7 @@
         snamenode->val.val.str = qstring;
         snamenode->location = -1;
         castnode = makeNode(TypeCast);
-        castnode->typename = SystemTypeName("regclass");
+        castnode->typeName = SystemTypeName("regclass");
         castnode->arg = (Node *) snamenode;
         castnode->location = -1;
         funccallnode = makeNode(FuncCall);
@@ -622,7 +622,7 @@
          */
         def = makeNode(ColumnDef);
         def->colname = pstrdup(attributeName);
-        def->typename = makeTypeNameFromOid(attribute->atttypid,
+        def->typeName = makeTypeNameFromOid(attribute->atttypid,
                                             attribute->atttypmod);
         def->inhcount = 0;
         def->is_local = true;
@@ -1962,7 +1962,7 @@
     /*
      * All we really need to do here is verify that the type is valid.
      */
-    Type        ctype = typenameType(pstate, column->typename, NULL);
+    Type        ctype = typenameType(pstate, column->typeName, NULL);

     ReleaseSysCache(ctype);
 }
diff -r bd5a52b2681a src/backend/tcop/utility.c
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -602,23 +602,23 @@
                          * Recursively alter column default for table and, if
                          * requested, for descendants
                          */
-                        AlterDomainDefault(stmt->typename,
+                        AlterDomainDefault(stmt->typeName,
                                            stmt->def);
                         break;
                     case 'N':    /* ALTER DOMAIN DROP NOT NULL */
-                        AlterDomainNotNull(stmt->typename,
+                        AlterDomainNotNull(stmt->typeName,
                                            false);
                         break;
                     case 'O':    /* ALTER DOMAIN SET NOT NULL */
-                        AlterDomainNotNull(stmt->typename,
+                        AlterDomainNotNull(stmt->typeName,
                                            true);
                         break;
                     case 'C':    /* ADD CONSTRAINT */
-                        AlterDomainAddConstraint(stmt->typename,
+                        AlterDomainAddConstraint(stmt->typeName,
                                                  stmt->def);
                         break;
                     case 'X':    /* DROP CONSTRAINT */
-                        AlterDomainDropConstraint(stmt->typename,
+                        AlterDomainDropConstraint(stmt->typeName,
                                                   stmt->name,
                                                   stmt->behavior);
                         break;
diff -r bd5a52b2681a src/backend/utils/adt/ruleutils.c
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -5539,14 +5539,14 @@

         if (!j->isNatural)
         {
-            if (j->using)
+            if (j->usingClause)
             {
                 ListCell   *col;

                 appendStringInfo(buf, " USING (");
-                foreach(col, j->using)
-                {
-                    if (col != list_head(j->using))
+                foreach(col, j->usingClause)
+                {
+                    if (col != list_head(j->usingClause))
                         appendStringInfo(buf, ", ");
                     appendStringInfoString(buf,
                                       quote_identifier(strVal(lfirst(col))));
@@ -5878,18 +5878,18 @@
 /*
  * quote_qualified_identifier    - Quote a possibly-qualified identifier
  *
- * Return a name of the form namespace.ident, or just ident if namespace
+ * Return a name of the form qualifier.ident, or just ident if qualifier
  * is NULL, quoting each component if necessary.  The result is palloc'd.
  */
 char *
-quote_qualified_identifier(const char *namespace,
+quote_qualified_identifier(const char *qualifier,
                            const char *ident)
 {
     StringInfoData buf;

     initStringInfo(&buf);
-    if (namespace)
-        appendStringInfo(&buf, "%s.", quote_identifier(namespace));
+    if (qualifier)
+        appendStringInfo(&buf, "%s.", quote_identifier(qualifier));
     appendStringInfoString(&buf, quote_identifier(ident));
     return buf.data;
 }
diff -r bd5a52b2681a src/backend/utils/misc/guc.c
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -5370,7 +5370,7 @@
     {
         Node       *arg = (Node *) lfirst(l);
         char       *val;
-        TypeName   *typename = NULL;
+        TypeName   *typeName = NULL;
         A_Const       *con;

         if (l != list_head(args))
@@ -5381,7 +5381,7 @@
             TypeCast *tc = (TypeCast *) arg;

             arg = tc->arg;
-            typename = tc->typename;
+            typeName = tc->typeName;
         }

         if (!IsA(arg, A_Const))
@@ -5399,7 +5399,7 @@
                 break;
             case T_String:
                 val = strVal(&con->val);
-                if (typename != NULL)
+                if (typeName != NULL)
                 {
                     /*
                      * Must be a ConstInterval argument for TIME ZONE. Coerce
@@ -5411,7 +5411,7 @@
                     Datum        interval;
                     char       *intervalout;

-                    typoid = typenameTypeId(NULL, typename, &typmod);
+                    typoid = typenameTypeId(NULL, typeName, &typmod);
                     Assert(typoid == INTERVALOID);

                     interval =
diff -r bd5a52b2681a src/backend/utils/mmgr/mcxt.c
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -193,7 +193,7 @@
             }
         }
     }
-    (*context->methods->delete) (context);
+    (*context->methods->delete_context) (context);
     pfree(context);
 }

diff -r bd5a52b2681a src/include/c.h
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -150,7 +150,7 @@
  * dummyret is used to set return values in macros that use ?: to make
  * assignments.  gcc wants these to be void, other compilers like char
  */
-#ifdef __GNUC__                    /* GNU cc */
+#if defined(__GNUC__) && !defined(__cplusplus)    /* GNU cc */
 #define dummyret    void
 #else
 #define dummyret    char
diff -r bd5a52b2681a src/include/nodes/makefuncs.h
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -60,7 +60,7 @@

 extern TypeName *makeTypeName(char *typnam);
 extern TypeName *makeTypeNameFromNameList(List *names);
-extern TypeName *makeTypeNameFromOid(Oid typeid, int32 typmod);
+extern TypeName *makeTypeNameFromOid(Oid typeOid, int32 typmod);

 extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype,
              List *args, CoercionForm fformat);
diff -r bd5a52b2681a src/include/nodes/memnodes.h
--- a/src/include/nodes/memnodes.h
+++ b/src/include/nodes/memnodes.h
@@ -41,7 +41,7 @@
     void       *(*realloc) (MemoryContext context, void *pointer, Size size);
     void        (*init) (MemoryContext context);
     void        (*reset) (MemoryContext context);
-    void        (*delete) (MemoryContext context);
+    void        (*delete_context) (MemoryContext context);
     Size        (*get_chunk_space) (MemoryContext context, void *pointer);
     bool        (*is_empty) (MemoryContext context);
     void        (*stats) (MemoryContext context, int level);
diff -r bd5a52b2681a src/include/nodes/parsenodes.h
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -157,7 +157,7 @@
  *
  * For TypeName structures generated internally, it is often easier to
  * specify the type by OID than by name.  If "names" is NIL then the
- * actual type OID is given by typeid, otherwise typeid is unused.
+ * actual type OID is given by typeOid, otherwise typeOid is unused.
  * Similarly, if "typmods" is NIL then the actual typmod is expected to
  * be prespecified in typemod, otherwise typemod is unused.
  *
@@ -169,7 +169,7 @@
 {
     NodeTag        type;
     List       *names;            /* qualified name (list of Value strings) */
-    Oid            typeid;            /* type identified by OID */
+    Oid            typeOid;        /* type identified by OID */
     bool        setof;            /* is a set? */
     bool        pct_type;        /* %TYPE specified? */
     List       *typmods;        /* type modifier expression(s) */
@@ -252,7 +252,7 @@
 {
     NodeTag        type;
     Node       *arg;            /* the expression being casted */
-    TypeName   *typename;        /* the target type */
+    TypeName   *typeName;        /* the target type */
     int            location;        /* token location, or -1 if unknown */
 } TypeCast;

@@ -409,7 +409,7 @@
 {
     NodeTag        type;
     char       *colname;        /* name of column */
-    TypeName   *typename;        /* type of column */
+    TypeName   *typeName;        /* type of column */
     int            inhcount;        /* number of times column is inherited */
     bool        is_local;        /* column has local (non-inherited) def'n */
     bool        is_not_null;    /* NOT NULL constraint specified? */
@@ -490,7 +490,7 @@
     NodeTag        type;
     XmlOptionType xmloption;    /* DOCUMENT or CONTENT */
     Node       *expr;
-    TypeName   *typename;
+    TypeName   *typeName;
     int            location;        /* token location, or -1 if unknown */
 } XmlSerialize;

@@ -1059,7 +1059,7 @@
                                  *    X = drop constraint
                                  *------------
                                  */
-    List       *typename;        /* domain to work on */
+    List       *typeName;        /* domain to work on */
     char       *name;            /* column or constraint name to act on */
     Node       *def;            /* definition of default or constraint */
     DropBehavior behavior;        /* RESTRICT or CASCADE for DROP cases */
@@ -1459,7 +1459,7 @@
 {
     NodeTag        type;
     List       *domainname;        /* qualified name (list of Value strings) */
-    TypeName   *typename;        /* the base type */
+    TypeName   *typeName;        /* the base type */
     List       *constraints;    /* constraints (list of Constraint nodes) */
 } CreateDomainStmt;

@@ -1872,7 +1872,7 @@
 typedef struct CreateEnumStmt
 {
     NodeTag        type;
-    List       *typename;        /* qualified name (list of Value strings) */
+    List       *typeName;        /* qualified name (list of Value strings) */
     List       *vals;            /* enum values (list of Value strings) */
 } CreateEnumStmt;

diff -r bd5a52b2681a src/include/nodes/primnodes.h
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -1107,8 +1107,8 @@
 /*----------
  * JoinExpr - for SQL JOIN expressions
  *
- * isNatural, using, and quals are interdependent.    The user can write only
- * one of NATURAL, USING(), or ON() (this is enforced by the grammar).
+ * isNatural, usingClause, and quals are interdependent.  The user can write
+ * only one of NATURAL, USING(), or ON() (this is enforced by the grammar).
  * If he writes NATURAL then parse analysis generates the equivalent USING()
  * list, and from that fills in "quals" with the right equality comparisons.
  * If he writes USING() then "quals" is filled with equality comparisons.
@@ -1132,7 +1132,7 @@
     bool        isNatural;        /* Natural join? Will need to shape table */
     Node       *larg;            /* left subtree */
     Node       *rarg;            /* right subtree */
-    List       *using;            /* USING clause, if any (list of String) */
+    List       *usingClause;    /* USING clause, if any (list of String) */
     Node       *quals;            /* qualifiers on join, if any */
     Alias       *alias;            /* user-written alias clause, if any */
     int            rtindex;        /* RT index assigned for join */
diff -r bd5a52b2681a src/include/parser/parse_type.h
--- a/src/include/parser/parse_type.h
+++ b/src/include/parser/parse_type.h
@@ -19,14 +19,14 @@

 typedef HeapTuple Type;

-extern Type LookupTypeName(ParseState *pstate, const TypeName *typename,
+extern Type LookupTypeName(ParseState *pstate, const TypeName *typeName,
                int32 *typmod_p);
-extern Type typenameType(ParseState *pstate, const TypeName *typename,
+extern Type typenameType(ParseState *pstate, const TypeName *typeName,
              int32 *typmod_p);
-extern Oid typenameTypeId(ParseState *pstate, const TypeName *typename,
+extern Oid typenameTypeId(ParseState *pstate, const TypeName *typeName,
                int32 *typmod_p);

-extern char *TypeNameToString(const TypeName *typename);
+extern char *TypeNameToString(const TypeName *typeName);
 extern char *TypeNameListToString(List *typenames);

 extern Type typeidType(Oid id);
diff -r bd5a52b2681a src/include/utils/builtins.h
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -560,7 +560,7 @@
 extern List *deparse_context_for_plan(Node *plan, Node *outer_plan,
                          List *rtable, List *subplans);
 extern const char *quote_identifier(const char *ident);
-extern char *quote_qualified_identifier(const char *namespace,
+extern char *quote_qualified_identifier(const char *qualifier,
                            const char *ident);

 /* tid.c */
diff -r 55d732d0fbcd src/include/executor/spi.h
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -18,6 +18,10 @@
  * included postgres.h
  */
 #include "postgres.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif

 /*
  *    Most of these are not needed by this file, but may be used by
@@ -156,4 +160,8 @@
 extern void AtEOXact_SPI(bool isCommit);
 extern void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid);

+#ifdef __cplusplus
+}   /* extern "C" */
+#endif
+
 #endif   /* SPI_H */
diff -r 55d732d0fbcd src/include/fmgr.h
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -17,6 +17,10 @@
  */
 #ifndef FMGR_H
 #define FMGR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif

 /* We don't want to include primnodes.h here, so make a stub reference */
 typedef struct Node *fmNodePtr;
@@ -544,4 +548,8 @@
  */
 extern char *fmgr(Oid procedureId,...);

+#ifdef __cplusplus
+}   /* extern "C" */
+#endif
+
 #endif   /* FMGR_H */
diff -r 55d732d0fbcd src/include/funcapi.h
--- a/src/include/funcapi.h
+++ b/src/include/funcapi.h
@@ -16,11 +16,14 @@
 #ifndef FUNCAPI_H
 #define FUNCAPI_H

+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include "fmgr.h"
 #include "access/tupdesc.h"
 #include "executor/executor.h"
 #include "executor/tuptable.h"
-

 /*-------------------------------------------------------------------------
  *    Support to ease writing Functions returning composite types
@@ -299,4 +302,8 @@
         PG_RETURN_NULL(); \
     } while (0)

+#ifdef __cplusplus
+}   /* extern "C" */
+#endif
+
 #endif   /* FUNCAPI_H */
diff -r 55d732d0fbcd src/include/postgres.h
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -44,7 +44,12 @@
 #ifndef POSTGRES_H
 #define POSTGRES_H

+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include "c.h"
+
 #include "utils/elog.h"
 #include "utils/palloc.h"

@@ -693,4 +698,8 @@
                      const char *errorType,
                      const char *fileName, int lineNumber);

+#ifdef __cplusplus
+}   /* extern "C" */
+#endif
+
 #endif   /* POSTGRES_H */
diff -r 257c0be599ab config/c-compiler.m4
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -103,6 +103,7 @@
 # command-line option. If it does, add the string to CFLAGS.
 AC_DEFUN([PGAC_PROG_CC_CFLAGS_OPT],
 [AC_MSG_CHECKING([if $CC supports $1])
+AC_LANG_ASSERT([C])
 pgac_save_CFLAGS=$CFLAGS
 CFLAGS="$pgac_save_CFLAGS $1"
 _AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
@@ -110,6 +111,23 @@
                    [CFLAGS="$pgac_save_CFLAGS"
                     AC_MSG_RESULT(no)])
 ])# PGAC_PROG_CC_CFLAGS_OPT
+
+
+
+# PGAC_PROG_CXX_CXXFLAGS_OPT
+# -----------------------
+# Given a string, check if the C++ compiler supports the string as a
+# command-line option. If it does, add the string to CXXFLAGS.
+AC_DEFUN([PGAC_PROG_CXX_CXXFLAGS_OPT],
+[AC_MSG_CHECKING([if $CXX supports $1])
+AC_LANG_ASSERT([C++])
+pgac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="$pgac_save_CXXFLAGS $1"
+_AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+                   AC_MSG_RESULT(yes),
+                   [CXXFLAGS="$pgac_save_CXXFLAGS"
+                    AC_MSG_RESULT(no)])
+])# PGAC_PROG_CXX_CXXFLAGS_OPT



diff -r 257c0be599ab configure.in
--- a/configure.in
+++ b/configure.in
@@ -195,6 +195,14 @@
 PGAC_ARG_BOOL(enable, debug, no,
               [build with debugging symbols (-g)])
 AC_SUBST(enable_debug)
+
+#
+# --enable-cplusplus links the postgres backend with the C++ runtime library
+#
+PGAC_ARG_BOOL(enable, cplusplus, no, [build with C++ runtime library],
+              [AC_DEFINE([ENABLE_CPLUSPLUS], 1,
+                         [Define to 1 for mixed C/C++ build. (--enable-cplusplus)])])
+AC_SUBST(enable_cplusplus)

 #
 # --enable-profiling enables gcc profiling
@@ -365,9 +373,9 @@
 PGAC_ARG_REQ(with, CC, [CMD], [set compiler (deprecated)], [CC=$with_CC])

 case $template in
-  aix) pgac_cc_list="gcc xlc";;
- irix) pgac_cc_list="cc";; # no gcc
-    *) pgac_cc_list="gcc cc";;
+  aix) pgac_cc_list="gcc xlc";  pgac_cxx_list="g++ xlC";;
+ irix) pgac_cc_list="cc";       pgac_cxx_list="CC";;            # no gcc
+    *) pgac_cc_list="gcc cc";   pgac_cxx_list="g++ CC";;
 esac

 AC_PROG_CC([$pgac_cc_list])
@@ -387,7 +395,15 @@

 AC_SUBST(SUN_STUDIO_CC)

+#
+# C++ compiler
+#
+AC_PROG_CXX([$pgac_cxx_list])
+AC_PROG_CXXCPP
+AC_SUBST(GXX)
+
 unset CFLAGS
+unset CXXFLAGS

 #
 # Read the template
@@ -421,9 +437,8 @@
 # ICC pretends to be GCC but it's lying; it doesn't support these options.

 if test "$GCC" = yes -a "$ICC" = no; then
-  CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -Wpointer-arith"
+  CFLAGS="$CFLAGS -Wall -Wpointer-arith"
   # These work in some but not all gcc versions
-  PGAC_PROG_CC_CFLAGS_OPT([-Wdeclaration-after-statement])
   PGAC_PROG_CC_CFLAGS_OPT([-Wendif-labels])
   # Disable strict-aliasing rules; needed for gcc 3.3+
   PGAC_PROG_CC_CFLAGS_OPT([-fno-strict-aliasing])
@@ -470,12 +485,53 @@
   CPPFLAGS="$CPPFLAGS -I$srcdir/src/include/port/win32 -DEXEC_BACKEND"
 fi

+#
+# Initialize C++ flags from CFLAGS unless overridden in environment or template
+#
+if test "$ac_env_CXXFLAGS_set" = set; then
+  CXXFLAGS=$ac_env_CXXFLAGS_value
+elif test "${CXXFLAGS+set}" = set; then
+  : # (keep what template set)
+else
+  CXXFLAGS="$CFLAGS"
+fi
+
+# Some CXXFLAGS are only valid for C++, not for C.  Add them here.
+if test "$GXX" = yes -a "$ICC" = no; then
+  AC_LANG_PUSH([C++])
+  CXXFLAGS="$CXXFLAGS -Wabi"
+  PGAC_PROG_CXX_CXXFLAGS_OPT([-fno-enforce-eh-specs])
+  PGAC_PROG_CXX_CXXFLAGS_OPT([-fno-threadsafe-statics])
+  AC_LANG_POP([C++])
+fi
+
+# Some CFLAGS are only valid for C, not for C++.  Add them here.
+if test "$GCC" = yes -a "$ICC" = no; then
+  CFLAGS="$CFLAGS -Wmissing-prototypes"
+  # These work in some but not all gcc versions
+  PGAC_PROG_CC_CFLAGS_OPT([-Wdeclaration-after-statement])
+fi
+
+
+#
 # Check if the compiler still works with the template settings
+#
 AC_MSG_CHECKING([whether the C compiler still works])
 AC_TRY_LINK([], [return 0;],
   [AC_MSG_RESULT(yes)],
   [AC_MSG_RESULT(no)
    AC_MSG_ERROR([cannot proceed])])
+
+if test "$enable_cplusplus" = yes; then
+  AC_LANG_PUSH([C++])
+  AC_MSG_CHECKING([whether the C++ compiler still works])
+  AC_TRY_LINK([class X {public: bool b; X(bool bb){this->b = bb;}};],
+    [X* x = new X(true);],
+    [AC_MSG_RESULT(yes)],
+    [AC_MSG_RESULT(no)
+     AC_MSG_ERROR([cannot proceed])])
+  AC_LANG_POP([C++])
+fi

 # Defend against gcc -ffast-math
 if test "$GCC" = yes; then
@@ -1765,6 +1821,7 @@
 # Begin output steps

 AC_MSG_NOTICE([using CFLAGS=$CFLAGS])
+AC_MSG_NOTICE([using CXXFLAGS=$CXXFLAGS])
 AC_MSG_NOTICE([using CPPFLAGS=$CPPFLAGS])
 AC_MSG_NOTICE([using LDFLAGS=$LDFLAGS])

diff -r 257c0be599ab doc/src/sgml/installation.sgml
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -1261,6 +1261,17 @@
          can be profiled.  On backend exit, a subdirectory will be created
          that contains the <filename>gmon.out</> file for use in profiling.
          This option is for use only with GCC and when doing development work.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>--enable-cplusplus</option></term>
+       <listitem>
+        <para>
+         Compiles the <filename>postgres</> server with C++ runtime
+         library support.  Specify this option only if you intend to use or
+         develop server extensions or modifications in the C++ language.
         </para>
        </listitem>
       </varlistentry>
diff -r 257c0be599ab doc/src/sgml/ref/pg_config-ref.sgml
--- a/doc/src/sgml/ref/pg_config-ref.sgml
+++ b/doc/src/sgml/ref/pg_config-ref.sgml
@@ -223,6 +223,27 @@
     </varlistentry>

     <varlistentry>
+     <term><option>--cxx</option></>
+     <listitem>
+      <para>
+       Print the value of the <varname>CXX</varname> variable showing the C++
+       compiler that was used for building C++ modules (if any) in the
+       <productname>PostgreSQL</> backend.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><option>--cxxflags</option></>
+     <listitem>
+      <para>
+       Print the value of the <varname>CXXFLAGS</varname> variable that was used for building
+       <productname>PostgreSQL</>.  This shows C++ compiler switches.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
      <term><option>--ldflags</option></>
      <listitem>
       <para>
diff -r 257c0be599ab src/Makefile.global.in
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -164,6 +164,7 @@
 enable_debug    = @enable_debug@
 enable_dtrace    = @enable_dtrace@
 enable_coverage    = @enable_coverage@
+enable_cplusplus    = @enable_cplusplus@
 enable_thread_safety    = @enable_thread_safety@

 python_includespec    = @python_includespec@
@@ -214,6 +215,21 @@
 GCC = @GCC@
 SUN_STUDIO_CC = @SUN_STUDIO_CC@
 CFLAGS = @CFLAGS@
+
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXFLAGS = @CXXFLAGS@
+GXX = @GXX@
+
+# gmake predefines these and uses them in its predefined implicit rules.
+# We include them here just in case someone uses a version of gmake which
+# doesn't have them built in.  These are as defined by gmake 3.81.
+COMPILE.c   ?= $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
+LINK.c      ?= $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
+COMPILE.cc  ?= $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
+LINK.cc     ?= $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
+COMPILE.cpp ?= $(COMPILE.cc)
+LINK.cpp    ?= $(LINK.cc)

 # Kind-of compilers

@@ -545,18 +561,25 @@

 ifeq ($(autodepend), yes)

-ifndef COMPILE.c
-COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c
-endif
-
 DEPDIR = .deps
+DEPMKDIR = @if test ! -d $(DEPDIR); then mkdir -p $(DEPDIR); fi

 ifeq ($(GCC), yes)

 # GCC allows us to create object and dependency file in one invocation.
+DEPFLAGS = -MMD -MP -MF $(DEPDIR)/$(*F).Po
+
 %.o : %.c
-    @if test ! -d $(DEPDIR); then mkdir -p $(DEPDIR); fi
-    $(COMPILE.c) -o $@ $< -MMD -MP -MF $(DEPDIR)/$(*F).Po
+    $(DEPMKDIR)
+    $(COMPILE.c) $(DEPFLAGS) -o $@ $<
+
+%.o : %.cc
+    $(DEPMKDIR)
+    $(COMPILE.cc) $(DEPFLAGS) -o $@ $<
+
+%.o: %.cpp
+    $(DEPMKDIR)
+    $(COMPILE.cpp) $(DEPFLAGS) -o $@ $<

 endif # GCC

diff -r 257c0be599ab src/backend/Makefile
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -43,7 +43,12 @@
 ifneq ($(PORTNAME), aix)

 postgres: $(OBJS)
+ifeq ($(enable_cplusplus), yes)
+    # Link with C++ runtime support
+    $(CXX) $(CXXFLAGS) $(LDFLAGS) $(export_dynamic) $(call expand_subsys,$^) $(LIBS) -o $@
+else
     $(CC) $(CFLAGS) $(LDFLAGS) $(export_dynamic) $(call expand_subsys,$^) $(LIBS) -o $@
+endif

 endif
 endif
@@ -111,7 +116,12 @@
 # The postgres.o target is needed by the rule in Makefile.global that
 # creates the exports file when MAKE_EXPORTS = true.
 postgres.o: $(OBJS)
+ifeq ($(enable_cplusplus), yes)
+    # Link with C++ runtime support
+    $(CXX) $(LDREL) $(LDFLAGS) $(call expand_subsys,$^) $(LIBS) -o $@
+else
     $(CC) $(LDREL) $(LDFLAGS) $(call expand_subsys,$^) $(LIBS) -o $@
+endif


 # The following targets are specified in make commands that appear in
@@ -268,4 +278,9 @@
 # are up to date.  It saves the time of doing all the submakes.
 .PHONY: quick
 quick: $(OBJS)
+ifeq ($(enable_cplusplus), yes)
+    # Link with C++ runtime support
+    $(CXX) $(CXXFLAGS) $(LDFLAGS) $(export_dynamic) $(call expand_subsys,$^) $(LIBS) -o postgres
+else
     $(CC) $(CFLAGS) $(LDFLAGS) $(export_dynamic) $(call expand_subsys,$^) $(LIBS) -o postgres
+endif
diff -r 257c0be599ab src/backend/common.mk
--- a/src/backend/common.mk
+++ b/src/backend/common.mk
@@ -6,7 +6,7 @@

 # When including this file, set OBJS to the object files created in
 # this directory and SUBDIRS to subdirectories containing more things
-# to build.
+# to build.  Set CXXOBJS to the subset of OBJS which are to be C++ compiled.

 ifdef PARTIAL_LINKING
 # old style: linking using SUBSYS.o
@@ -36,6 +36,11 @@
 # Parallel make trickery
 $(SUBDIROBJS): $(SUBDIRS:%=%-recursive) ;

+# For .o files listed in CXXOBJS, use C++ compiler to make .o from .c
+$(CXXOBJS) : %.o: %.c
+    $(DEPMKDIR)
+    $(COMPILE.cc) $(DEPFLAGS) -o $@ $<
+
 .PHONY: $(SUBDIRS:%=%-recursive)
 $(SUBDIRS:%=%-recursive):
     $(MAKE) -C $(subst -recursive,,$@) all
diff -r 257c0be599ab src/backend/main/Makefile
--- a/src/backend/main/Makefile
+++ b/src/backend/main/Makefile
@@ -14,4 +14,11 @@

 OBJS = main.o

+# If "configure --enable-cplusplus" was specified, make list of modules
+# which are to be compiled as C++.  The main() function should be compiled as
+# C++ to ensure proper initialization of the mixed C/C++ runtime environment.
+ifeq ($(enable_cplusplus),yes)
+CXXOBJS = main.o
+endif
+
 include $(top_srcdir)/src/backend/common.mk
diff -r 257c0be599ab src/backend/main/main.c
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -34,6 +34,14 @@
 #include <sys/param.h>
 #endif

+#if defined(ENABLE_CPLUSPLUS) && !defined(__cplusplus)
+#error --enable-cplusplus configure option specified; this file should be compiled as C++
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include "bootstrap/bootstrap.h"
 #include "postmaster/postmaster.h"
 #include "tcop/tcopprot.h"
@@ -42,6 +50,10 @@
 #include "utils/ps_status.h"
 #ifdef WIN32
 #include "libpq/pqsignal.h"
+#endif
+
+#ifdef __cplusplus
+}   /* extern "C" */
 #endif


diff -r 257c0be599ab src/bin/pg_config/Makefile
--- a/src/bin/pg_config/Makefile
+++ b/src/bin/pg_config/Makefile
@@ -24,6 +24,8 @@
 override CPPFLAGS += -DVAL_CPPFLAGS="\"$(STD_CPPFLAGS)\""
 override CPPFLAGS += -DVAL_CFLAGS="\"$(CFLAGS)\""
 override CPPFLAGS += -DVAL_CFLAGS_SL="\"$(CFLAGS_SL)\""
+override CPPFLAGS += -DVAL_CXX="\"$(CXX)\""
+override CPPFLAGS += -DVAL_CXXFLAGS="\"$(CXXFLAGS)\""
 override CPPFLAGS += -DVAL_LDFLAGS="\"$(STD_LDFLAGS)\""
 override CPPFLAGS += -DVAL_LDFLAGS_SL="\"$(LDFLAGS_SL)\""
 override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\""
diff -r 257c0be599ab src/bin/pg_config/pg_config.c
--- a/src/bin/pg_config/pg_config.c
+++ b/src/bin/pg_config/pg_config.c
@@ -311,6 +311,38 @@
 }

 static void
+show_cxx(bool all)
+{
+#ifdef VAL_CXX
+    if (all)
+        printf("CXX = ");
+    printf("%s\n", VAL_CXX);
+#else
+    if (!all)
+    {
+        fprintf(stderr, _("not recorded\n"));
+        exit(1);
+    }
+#endif
+}
+
+static void
+show_cxxflags(bool all)
+{
+#ifdef VAL_CXXFLAGS
+    if (all)
+        printf("CXXFLAGS = ");
+    printf("%s\n", VAL_CXXFLAGS);
+#else
+    if (!all)
+    {
+        fprintf(stderr, _("not recorded\n"));
+        exit(1);
+    }
+#endif
+}
+
+static void
 show_ldflags(bool all)
 {
 #ifdef VAL_LDFLAGS
@@ -397,6 +429,8 @@
     {"--cppflags", show_cppflags},
     {"--cflags", show_cflags},
     {"--cflags_sl", show_cflags_sl},
+    {"--cxx", show_cxx},
+    {"--cxxflags", show_cxxflags},
     {"--ldflags", show_ldflags},
     {"--ldflags_sl", show_ldflags_sl},
     {"--libs", show_libs},
@@ -432,6 +466,8 @@
     printf(_("  --cppflags            show CPPFLAGS value used when PostgreSQL was built\n"));
     printf(_("  --cflags              show CFLAGS value used when PostgreSQL was built\n"));
     printf(_("  --cflags_sl           show CFLAGS_SL value used when PostgreSQL was built\n"));
+    printf(_("  --cxx                 show CXX value used when PostgreSQL was built\n"));
+    printf(_("  --cxxflags            show CXXFLAGS value used when PostgreSQL was built\n"));
     printf(_("  --ldflags             show LDFLAGS value used when PostgreSQL was built\n"));
     printf(_("  --ldflags_sl          show LDFLAGS_SL value used when PostgreSQL was built\n"));
     printf(_("  --libs                show LIBS value used when PostgreSQL was built\n"));
diff -r 257c0be599ab src/include/pg_config.h.in
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -44,6 +44,9 @@

 /* Define to the default TCP port number as a string constant. */
 #undef DEF_PGPORT_STR
+
+/* Define to 1 for mixed C/C++ build. (--enable-cplusplus) */
+#undef ENABLE_CPLUSPLUS

 /* Define to 1 to enable DTrace support. (--enable-dtrace) */
 #undef ENABLE_DTRACE
diff -r 9b2c774a6b05 src/backend/tcop/Makefile
--- a/src/backend/tcop/Makefile
+++ b/src/backend/tcop/Makefile
@@ -14,6 +14,11 @@

 OBJS= dest.o fastpath.o postgres.o pquery.o utility.o

+# Designate modules to be compiled as C++ when 'configure --enable-cplusplus'
+ifeq ($(enable_cplusplus),yes)
+CXXOBJS = postgres.o
+endif
+
 ifneq (,$(filter $(PORTNAME),cygwin win32))
 override CPPFLAGS += -DWIN32_STACK_RLIMIT=$(WIN32_STACK_RLIMIT)
 endif
diff -r 9b2c774a6b05 src/backend/tcop/postgres.c
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -33,6 +33,17 @@
 #endif
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
+#endif
+
+#ifdef ENABLE_CPLUSPLUS
+#ifndef __cplusplus
+#error --enable-cplusplus configure option specified; this file should be compiled as C++
+#endif
+#include <exception>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
 #endif

 #ifndef HAVE_GETRUSAGE
@@ -163,6 +174,11 @@
 #endif   /* TCOP_DONTUSENEWLINE */


+#ifdef __cplusplus
+}                               /* extern "C" */
+#endif
+
+
 /* ----------------------------------------------------------------
  *        decls for routines only used in this file
  * ----------------------------------------------------------------
@@ -1212,7 +1228,7 @@
         if (log_parser_stats)
             ResetUsage();

-        query = parse_analyze_varparams(copyObject(raw_parse_tree),
+        query = parse_analyze_varparams((Node *)copyObject(raw_parse_tree),
                                         query_string,
                                         ¶mTypes,
                                         &numParams);
@@ -1679,7 +1695,7 @@
          * we have to make a copy of the parse trees.  FIXME someday.
          */
         oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
-        query_list = copyObject(cplan->stmt_list);
+        query_list = (List *)copyObject(cplan->stmt_list);
         plan_list = pg_plan_queries(query_list, 0, params, true);
         MemoryContextSwitchTo(oldContext);

@@ -2791,6 +2807,29 @@

     return NULL;
 }
+
+
+#ifdef ENABLE_CPLUSPLUS
+/*
+ * PostgresMainUncaught
+ *      Called when C++ code throws an exception which is not caught.
+ *
+ * NB: On some platforms when C++ code calls C code, and the C code calls
+ * a deeper layer of C++ code, the outer C++ code can't catch exceptions
+ * thrown by the inner C++ code.  The search for a matching 'catch' is
+ * abandoned upon encountering an intervening C stack frame, and the
+ * exception is considered uncaught.
+ */
+static void
+PostgresMainUncaught()
+{
+    /* Context callbacks might not work right if call stack has been unwound */
+    error_context_stack = NULL;
+
+    elog(FATAL, "Unexpected internal error: Unhandled C++ exception");
+    abort();                                /* not reached */
+}
+#endif  /* ENABLE_CPLUSPLUS */


 /* ----------------------------------------------------------------
@@ -2850,6 +2889,11 @@
     /* Set up reference point for stack depth checking */
     stack_base_ptr = &stack_base;

+#ifdef ENABLE_CPLUSPLUS
+    /* Any unhandled C++ exception is to be treated as a FATAL error. */
+    std::set_terminate(PostgresMainUncaught);
+#endif
+
     /* Compute paths, if we didn't inherit them from postmaster */
     if (my_exec_path[0] == '\0')
     {
@@ -3108,10 +3152,10 @@
             char       *name;
             char       *value;

-            name = lfirst(gucopts);
+            name = (char *)lfirst(gucopts);
             gucopts = lnext(gucopts);

-            value = lfirst(gucopts);
+            value = (char *)lfirst(gucopts);
             gucopts = lnext(gucopts);

             if (IsSuperuserConfigOption(name))

pgsql-hackers by date:

Previous
From: Greg Smith
Date:
Subject: Re: [patch] pg_upgrade script for 8.3->8.4
Next
From: Greg Smith
Date:
Subject: Re: contrib/pg_stat_statements 1202