Cast result of copyObject() to correct type
authorPeter Eisentraut <peter_e@gmx.net>
Thu, 9 Mar 2017 20:18:59 +0000 (15:18 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Wed, 29 Mar 2017 01:59:23 +0000 (21:59 -0400)
copyObject() is declared to return void *, which allows easily assigning
the result independent of the input, but it loses all type checking.

If the compiler supports typeof or something similar, cast the result to
the input type.  This creates a greater amount of type safety.  In some
cases, where the result is assigned to a generic type such as Node * or
Expr *, new casts are now necessary, but in general casts are now
unnecessary in the normal case and indicate that something unusual is
happening.

Reviewed-by: Mark Dilger <hornschnorter@gmail.com>
36 files changed:
config/c-compiler.m4
configure
configure.in
src/backend/bootstrap/bootstrap.c
src/backend/commands/copy.c
src/backend/commands/createas.c
src/backend/commands/event_trigger.c
src/backend/commands/prepare.c
src/backend/commands/view.c
src/backend/nodes/copyfuncs.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/plan/planagg.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/prep/prepjointree.c
src/backend/optimizer/prep/preptlist.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/tlist.c
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/backend/parser/parse_clause.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_relation.c
src/backend/parser/parse_utilcmd.c
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rewriteManip.c
src/backend/tcop/postgres.c
src/backend/utils/cache/plancache.c
src/backend/utils/cache/relcache.c
src/include/nodes/nodes.h
src/include/optimizer/tlist.h
src/include/pg_config.h.in
src/include/pg_config.h.win32

index 3321f226f3e4abd68d679e9a03b0b4fc18fe88e9..b366e40cff0df236af9d2ff2077b8dadbd4ba7f2 100644 (file)
@@ -178,6 +178,33 @@ fi])# PGAC_C_STATIC_ASSERT
 
 
 
+# PGAC_C_TYPEOF
+# -------------
+# Check if the C compiler understands typeof or a variant.  Define
+# HAVE_TYPEOF if so, and define 'typeof' to the actual key word.
+#
+AC_DEFUN([PGAC_C_TYPEOF],
+[AC_CACHE_CHECK(for typeof, pgac_cv_c_typeof,
+[pgac_cv_c_typeof=no
+for pgac_kw in typeof __typeof__ decltype; do
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
+[int x = 0;
+$pgac_kw(x) y;
+y = x;
+return y;])],
+[pgac_cv_c_typeof=$pgac_kw])
+  test "$pgac_cv_c_typeof" != no && break
+done])
+if test "$pgac_cv_c_typeof" != no; then
+  AC_DEFINE(HAVE_TYPEOF, 1,
+            [Define to 1 if your compiler understands `typeof' or something similar.])
+  if test "$pgac_cv_c_typeof" != typeof; then
+    AC_DEFINE(typeof, $pgac_cv_c_typeof, [Define to how the compiler spells `typeof'.])
+  fi
+fi])# PGAC_C_TYPEOF
+
+
+
 # PGAC_C_TYPES_COMPATIBLE
 # -----------------------
 # Check if the C compiler understands __builtin_types_compatible_p,
index 4b8229e959fa9d03eaeb198c63be6b8ba989db42..3c92cabb924de355566a8605f12e02f3d5605008 100755 (executable)
--- a/configure
+++ b/configure
@@ -11667,6 +11667,46 @@ if test x"$pgac_cv__static_assert" = xyes ; then
 
 $as_echo "#define HAVE__STATIC_ASSERT 1" >>confdefs.h
 
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for typeof" >&5
+$as_echo_n "checking for typeof... " >&6; }
+if ${pgac_cv_c_typeof+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_cv_c_typeof=no
+for pgac_kw in typeof __typeof__ decltype; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+int x = 0;
+$pgac_kw(x) y;
+y = x;
+return y;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_c_typeof=$pgac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$pgac_cv_c_typeof" != no && break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_c_typeof" >&5
+$as_echo "$pgac_cv_c_typeof" >&6; }
+if test "$pgac_cv_c_typeof" != no; then
+
+$as_echo "#define HAVE_TYPEOF 1" >>confdefs.h
+
+  if test "$pgac_cv_c_typeof" != typeof; then
+
+$as_echo "#define typeof \$pgac_cv_c_typeof" >>confdefs.h
+
+  fi
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_types_compatible_p" >&5
 $as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
index 6c7421417112bbb971f7076b7a0c43e09507d802..d7c501af6a546175483f85a6f34ab116f201e1ab 100644 (file)
@@ -1330,6 +1330,7 @@ AC_C_FLEXIBLE_ARRAY_MEMBER
 PGAC_C_SIGNED
 PGAC_C_FUNCNAME_SUPPORT
 PGAC_C_STATIC_ASSERT
+PGAC_C_TYPEOF
 PGAC_C_TYPES_COMPATIBLE
 PGAC_C_BUILTIN_BSWAP32
 PGAC_C_BUILTIN_BSWAP64
index d8efdb5ed3d1a98dc6b714a4030b517747ab3d40..46c207c86c8fd6d8feaf7ab36c0f2647bb7d6da8 100644 (file)
@@ -1082,11 +1082,11 @@ index_register(Oid heap,
 
        memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
        /* expressions will likely be null, but may as well copy it */
-       newind->il_info->ii_Expressions = (List *)
+       newind->il_info->ii_Expressions =
                copyObject(indexInfo->ii_Expressions);
        newind->il_info->ii_ExpressionsState = NIL;
        /* predicate will likely be null, but may as well copy it */
-       newind->il_info->ii_Predicate = (List *)
+       newind->il_info->ii_Predicate =
                copyObject(indexInfo->ii_Predicate);
        newind->il_info->ii_PredicateState = NULL;
        /* no exclusion constraints at bootstrap time, so no need to copy */
index ab59be8455261d85dcbd5af751b0976965fa1cac..0158eda591772434aacab9d38248077fc225df25 100644 (file)
@@ -1470,7 +1470,7 @@ BeginCopy(ParseState *pstate,
                 * function and is executed repeatedly.  (See also the same hack in
                 * DECLARE CURSOR and PREPARE.)  XXX FIXME someday.
                 */
-               rewritten = pg_analyze_and_rewrite((RawStmt *) copyObject(raw_query),
+               rewritten = pg_analyze_and_rewrite(copyObject(raw_query),
                                                                                   pstate->p_sourcetext, NULL, 0);
 
                /* check that we got back something we can work with */
index 3daffc894a1669db37830a2dd39d819cc4b029e2..20cb64661a6944b31e3d7a29fbc7e3e8ed5381de 100644 (file)
@@ -315,7 +315,7 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
                 * and is executed repeatedly.  (See also the same hack in EXPLAIN and
                 * PREPARE.)
                 */
-               rewritten = QueryRewrite((Query *) copyObject(query));
+               rewritten = QueryRewrite(copyObject(query));
 
                /* SELECT should never rewrite to more or less than one SELECT query */
                if (list_length(rewritten) != 1)
index 7366fc74bec757ab727ffc81e0c8857ca831c333..d7c199f3144288d786d06922b1c0b259e6eb469c 100644 (file)
@@ -1869,7 +1869,7 @@ EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
                                         OperatorFamilyRelationId, opfamoid);
        command->d.opfam.operators = operators;
        command->d.opfam.procedures = procedures;
-       command->parsetree = copyObject(stmt);
+       command->parsetree = (Node *) copyObject(stmt);
 
        currentEventTriggerState->commandList =
                lappend(currentEventTriggerState->commandList, command);
@@ -1902,7 +1902,7 @@ EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt, Oid opcoid,
                                         OperatorClassRelationId, opcoid);
        command->d.createopc.operators = operators;
        command->d.createopc.procedures = procedures;
-       command->parsetree = copyObject(stmt);
+       command->parsetree = (Node *) copyObject(stmt);
 
        currentEventTriggerState->commandList =
                lappend(currentEventTriggerState->commandList, command);
@@ -1937,7 +1937,7 @@ EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId,
        command->d.atscfg.dictIds = palloc(sizeof(Oid) * ndicts);
        memcpy(command->d.atscfg.dictIds, dictIds, sizeof(Oid) * ndicts);
        command->d.atscfg.ndicts = ndicts;
-       command->parsetree = copyObject(stmt);
+       command->parsetree = (Node *) copyObject(stmt);
 
        currentEventTriggerState->commandList =
                lappend(currentEventTriggerState->commandList, command);
@@ -1967,7 +1967,7 @@ EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt)
        command->type = SCT_AlterDefaultPrivileges;
        command->d.defprivs.objtype = stmt->action->objtype;
        command->in_extension = creating_extension;
-       command->parsetree = copyObject(stmt);
+       command->parsetree = (Node *) copyObject(stmt);
 
        currentEventTriggerState->commandList =
                lappend(currentEventTriggerState->commandList, command);
index a92461097748f5ce5957eee5e1945b579344a8aa..dc6d43ec6d688c22820424cf814968749f735a25 100644 (file)
@@ -352,7 +352,7 @@ EvaluateParams(PreparedStatement *pstmt, List *params,
         * We have to run parse analysis for the expressions.  Since the parser is
         * not cool about scribbling on its input, copy first.
         */
-       params = (List *) copyObject(params);
+       params = copyObject(params);
 
        pstate = make_parsestate(NULL);
        pstate->p_sourcetext = queryString;
@@ -554,7 +554,7 @@ FetchPreparedStatementTargetList(PreparedStatement *stmt)
        tlist = CachedPlanGetTargetList(stmt->plansource);
 
        /* Copy into caller's context in case plan gets invalidated */
-       return (List *) copyObject(tlist);
+       return copyObject(tlist);
 }
 
 /*
index 7d76f567a8e5dd663b2822338d85ea84559778b4..35e25db7dca6f686e442a9a718376d8c1d052e72 100644 (file)
@@ -373,7 +373,7 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
         * Var node twice.  copyObject will expand any multiply-referenced subtree
         * into multiple copies.
         */
-       viewParse = (Query *) copyObject(viewParse);
+       viewParse = copyObject(viewParse);
 
        /* Create a dummy ParseState for addRangeTableEntryForRelation */
        pstate = make_parsestate(NULL);
index c23d5c52851eea5bf29bb194709b19973d034bdf..1c88d601bd1c30479699badb3e33a6c7fcc7baa8 100644 (file)
@@ -43,7 +43,7 @@
 
 /* Copy a field that is a pointer to some kind of Node or Node tree */
 #define COPY_NODE_FIELD(fldname) \
-       (newnode->fldname = copyObject(from->fldname))
+       (newnode->fldname = copyObjectImpl(from->fldname))
 
 /* Copy a field that is a pointer to a Bitmapset */
 #define COPY_BITMAPSET_FIELD(fldname) \
@@ -4507,7 +4507,7 @@ _copyDropSubscriptionStmt(const DropSubscriptionStmt *from)
  */
 #define COPY_NODE_CELL(new, old)                                       \
        (new) = (ListCell *) palloc(sizeof(ListCell));  \
-       lfirst(new) = copyObject(lfirst(old));
+       lfirst(new) = copyObjectImpl(lfirst(old));
 
 static List *
 _copyList(const List *from)
@@ -4610,13 +4610,13 @@ _copyForeignKeyCacheInfo(const ForeignKeyCacheInfo *from)
 
 
 /*
- * copyObject
+ * copyObjectImpl -- implementation of copyObject(); see nodes/nodes.h
  *
  * Create a copy of a Node tree or list.  This is a "deep" copy: all
  * substructure is copied too, recursively.
  */
 void *
-copyObject(const void *from)
+copyObjectImpl(const void *from)
 {
        void       *retval;
 
index c2b72d410af0a916f5b782064f1dc53b49813f64..a5d19f9b1c58b212994730f69ab9306ae8c1991f 100644 (fi