diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index e7ecc4ed7e..1235ac8019 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -87,8 +87,10 @@ Oid			binary_upgrade_next_array_pg_type_oid = InvalidOid;
 
 static void makeRangeConstructors(const char *name, Oid namespace,
 					  Oid rangeOid, Oid subtype);
-static Oid	findTypeInputFunction(List *procname, Oid typeOid);
-static Oid	findTypeOutputFunction(List *procname, Oid typeOid);
+static Oid	findTypeInputFunction(List *procname, Oid typeOid,
+								  bool *updatedType);
+static Oid	findTypeOutputFunction(List *procname, Oid typeOid,
+								   bool *updatedType);
 static Oid	findTypeReceiveFunction(List *procname, Oid typeOid);
 static Oid	findTypeSendFunction(List *procname, Oid typeOid);
 static Oid	findTypeTypmodinFunction(List *procname);
@@ -165,6 +167,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 	Oid			resulttype;
 	ListCell   *pl;
 	ObjectAddress address;
+	bool		updated_input = false,
+				updated_output = false;
 
 	/*
 	 * As of Postgres 8.4, we require superuser privilege to create a base
@@ -436,8 +440,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 	/*
 	 * Convert I/O proc names to OIDs
 	 */
-	inputOid = findTypeInputFunction(inputName, typoid);
-	outputOid = findTypeOutputFunction(outputName, typoid);
+	inputOid = findTypeInputFunction(inputName, typoid, &updated_input);
+	outputOid = findTypeOutputFunction(outputName, typoid, &updated_output);
 	if (receiveName)
 		receiveOid = findTypeReceiveFunction(receiveName, typoid);
 	if (sendName)
@@ -457,6 +461,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 				 (errmsg("changing return type of function %s from %s to %s",
 						 NameListToString(inputName), "opaque", typeName)));
 			SetFunctionReturnType(inputOid, typoid);
+			updated_input = true;
 		}
 		else
 			ereport(ERROR,
@@ -474,6 +479,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 				 (errmsg("changing return type of function %s from %s to %s",
 						 NameListToString(outputName), "opaque", "cstring")));
 			SetFunctionReturnType(outputOid, CSTRINGOID);
+			updated_output = true;
 		}
 		else
 			ereport(ERROR,
@@ -679,6 +685,25 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 
 	pfree(array_type);
 
+	/*
+	 * If type of an OPAQUE function has been changed, add cross-dependencies
+	 * with the new type created.
+	 */
+	if (updated_input)
+	{
+		ObjectAddress input_address;
+
+		ObjectAddressSet(input_address, ProcedureRelationId, inputOid);
+		recordDependencyOn(&input_address, &address, DEPENDENCY_NORMAL);
+	}
+	if (updated_output)
+	{
+		ObjectAddress output_address;
+
+		ObjectAddressSet(output_address, ProcedureRelationId, outputOid);
+		recordDependencyOn(&output_address, &address, DEPENDENCY_NORMAL);
+	}
+
 	return address;
 }
 
@@ -1631,11 +1656,12 @@ makeRangeConstructors(const char *name, Oid namespace,
  * Find suitable I/O functions for a type.
  *
  * typeOid is the type's OID (which will already exist, if only as a shell
- * type).
+ * type).  updatedType tracks if the type of the function found has been
+ * changed.
  */
 
 static Oid
-findTypeInputFunction(List *procname, Oid typeOid)
+findTypeInputFunction(List *procname, Oid typeOid, bool *updatedType)
 {
 	Oid			argList[3];
 	Oid			procOid;
@@ -1680,6 +1706,7 @@ findTypeInputFunction(List *procname, Oid typeOid)
 				(errmsg("changing argument type of function %s from \"opaque\" to \"cstring\"",
 						NameListToString(procname))));
 		SetFunctionArgType(procOid, 0, CSTRINGOID);
+		*updatedType = true;
 
 		/*
 		 * Need CommandCounterIncrement since DefineType will likely try to
@@ -1702,7 +1729,7 @@ findTypeInputFunction(List *procname, Oid typeOid)
 }
 
 static Oid
-findTypeOutputFunction(List *procname, Oid typeOid)
+findTypeOutputFunction(List *procname, Oid typeOid, bool *updatedType)
 {
 	Oid			argList[1];
 	Oid			procOid;
@@ -1731,6 +1758,7 @@ findTypeOutputFunction(List *procname, Oid typeOid)
 		(errmsg("changing argument type of function %s from \"opaque\" to %s",
 				NameListToString(procname), format_type_be(typeOid))));
 		SetFunctionArgType(procOid, 0, typeOid);
+		*updatedType = true;
 
 		/*
 		 * Need CommandCounterIncrement since DefineType will likely try to
diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out
index 7bdad4e9bb..ed539ec6d7 100644
--- a/src/test/regress/expected/create_type.out
+++ b/src/test/regress/expected/create_type.out
@@ -115,6 +115,76 @@ CREATE TYPE not_existing_type (INPUT = array_in,
     ELEMENT = int,
     INTERNALLENGTH = 32);
 ERROR:  function array_out(not_existing_type) does not exist
+-- Check dependency transfer of opaque functions when creating a new type
+CREATE FUNCTION type_arg_opaque_in(opaque) RETURNS opaque AS 'boolin'
+    LANGUAGE internal IMMUTABLE STRICT;
+CREATE FUNCTION type_arg_opaque_out(opaque) RETURNS cstring AS 'boolout'
+    LANGUAGE internal IMMUTABLE STRICT;
+CREATE FUNCTION type_return_opaque_in(cstring) RETURNS opaque AS 'boolin'
+    LANGUAGE internal IMMUTABLE STRICT;
+CREATE FUNCTION type_return_opaque_out(opaque) RETURNS opaque AS 'boolout'
+    LANGUAGE internal IMMUTABLE STRICT;
+CREATE TYPE type_arg_opaque(INPUT = type_arg_opaque_in,
+    OUTPUT = type_arg_opaque_out);
+WARNING:  changing argument type of function type_arg_opaque_in from "opaque" to "cstring"
+WARNING:  changing argument type of function type_arg_opaque_out from "opaque" to type_arg_opaque
+WARNING:  changing return type of function type_arg_opaque_in from opaque to type_arg_opaque
+CREATE TYPE type_return_opaque(INPUT = type_return_opaque_in,
+    OUTPUT = type_return_opaque_out);
+WARNING:  changing argument type of function type_return_opaque_out from "opaque" to type_return_opaque
+WARNING:  changing return type of function type_return_opaque_in from opaque to type_return_opaque
+WARNING:  changing return type of function type_return_opaque_out from opaque to cstring
+DROP FUNCTION type_arg_opaque_in; -- error
+ERROR:  cannot drop function type_arg_opaque_in(cstring) because other objects depend on it
+DETAIL:  type type_arg_opaque depends on function type_arg_opaque_in(cstring)
+function type_arg_opaque_out(type_arg_opaque) depends on type type_arg_opaque
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+DROP FUNCTION type_arg_opaque_out; -- error
+ERROR:  cannot drop function type_arg_opaque_out(type_arg_opaque) because other objects depend on it
+DETAIL:  type type_arg_opaque depends on function type_arg_opaque_out(type_arg_opaque)
+function type_arg_opaque_in(cstring) depends on type type_arg_opaque
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+DROP FUNCTION type_return_opaque_in; -- error
+ERROR:  cannot drop function type_return_opaque_in(cstring) because other objects depend on it
+DETAIL:  type type_return_opaque depends on function type_return_opaque_in(cstring)
+function type_return_opaque_out(type_return_opaque) depends on type type_return_opaque
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+DROP FUNCTION type_return_opaque_out; -- error
+ERROR:  cannot drop function type_return_opaque_out(type_return_opaque) because other objects depend on it
+DETAIL:  type type_return_opaque depends on function type_return_opaque_out(type_return_opaque)
+function type_return_opaque_in(cstring) depends on type type_return_opaque
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+DROP TYPE type_arg_opaque; -- error
+ERROR:  cannot drop type type_arg_opaque because other objects depend on it
+DETAIL:  function type_arg_opaque_in(cstring) depends on type type_arg_opaque
+function type_arg_opaque_out(type_arg_opaque) depends on type type_arg_opaque
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+DROP TYPE type_return_opaque; -- error
+ERROR:  cannot drop type type_return_opaque because other objects depend on it
+DETAIL:  function type_return_opaque_in(cstring) depends on type type_return_opaque
+function type_return_opaque_out(type_return_opaque) depends on type type_return_opaque
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+DROP TYPE type_arg_opaque CASCADE;
+NOTICE:  drop cascades to 2 other objects
+DETAIL:  drop cascades to function type_arg_opaque_in(cstring)
+drop cascades to function type_arg_opaque_out(type_arg_opaque)
+DROP TYPE type_return_opaque CASCADE;
+NOTICE:  drop cascades to 2 other objects
+DETAIL:  drop cascades to function type_return_opaque_in(cstring)
+drop cascades to function type_return_opaque_out(type_return_opaque)
+-- both should report no objects and work
+\df type_arg*
+                       List of functions
+ Schema | Name | Result data type | Argument data types | Type 
+--------+------+------------------+---------------------+------
+(0 rows)
+
+\df type_return*
+                       List of functions
+ Schema | Name | Result data type | Argument data types | Type 
+--------+------+------------------+---------------------+------
+(0 rows)
+
 -- Check usage of typmod with a user-defined type
 -- (we have borrowed numeric's typmod functions)
 CREATE TEMP TABLE mytab (foo widget(42,13,7));     -- should fail
diff --git a/src/test/regress/sql/create_type.sql b/src/test/regress/sql/create_type.sql
index a1839ef9e7..2c62fffbda 100644
--- a/src/test/regress/sql/create_type.sql
+++ b/src/test/regress/sql/create_type.sql
@@ -115,6 +115,31 @@ CREATE TYPE not_existing_type (INPUT = array_in,
     ELEMENT = int,
     INTERNALLENGTH = 32);
 
+-- Check dependency transfer of opaque functions when creating a new type
+CREATE FUNCTION type_arg_opaque_in(opaque) RETURNS opaque AS 'boolin'
+    LANGUAGE internal IMMUTABLE STRICT;
+CREATE FUNCTION type_arg_opaque_out(opaque) RETURNS cstring AS 'boolout'
+    LANGUAGE internal IMMUTABLE STRICT;
+CREATE FUNCTION type_return_opaque_in(cstring) RETURNS opaque AS 'boolin'
+    LANGUAGE internal IMMUTABLE STRICT;
+CREATE FUNCTION type_return_opaque_out(opaque) RETURNS opaque AS 'boolout'
+    LANGUAGE internal IMMUTABLE STRICT;
+CREATE TYPE type_arg_opaque(INPUT = type_arg_opaque_in,
+    OUTPUT = type_arg_opaque_out);
+CREATE TYPE type_return_opaque(INPUT = type_return_opaque_in,
+    OUTPUT = type_return_opaque_out);
+DROP FUNCTION type_arg_opaque_in; -- error
+DROP FUNCTION type_arg_opaque_out; -- error
+DROP FUNCTION type_return_opaque_in; -- error
+DROP FUNCTION type_return_opaque_out; -- error
+DROP TYPE type_arg_opaque; -- error
+DROP TYPE type_return_opaque; -- error
+DROP TYPE type_arg_opaque CASCADE;
+DROP TYPE type_return_opaque CASCADE;
+-- both should report no objects and work
+\df type_arg*
+\df type_return*
+
 -- Check usage of typmod with a user-defined type
 -- (we have borrowed numeric's typmod functions)
 
