diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index 63a629fa335ff27595a70c685dec644b2ecb6f6e..dd22ef5586f246ce87545519311856f6b012e37f 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -71,12 +71,8 @@ record_in(PG_FUNCTION_ARGS)
 {
 	char	   *string = PG_GETARG_CSTRING(0);
 	Oid			tupType = PG_GETARG_OID(1);
-
-#ifdef NOT_USED
-	int32		typmod = PG_GETARG_INT32(2);
-#endif
+	int32		tupTypmod = PG_GETARG_INT32(2);
 	HeapTupleHeader result;
-	int32		tupTypmod;
 	TupleDesc	tupdesc;
 	HeapTuple	tuple;
 	RecordIOData *my_extra;
@@ -89,16 +85,17 @@ record_in(PG_FUNCTION_ARGS)
 	StringInfoData buf;
 
 	/*
-	 * Use the passed type unless it's RECORD; we can't support input of
-	 * anonymous types, mainly because there's no good way to figure out which
-	 * anonymous type is wanted.  Note that for RECORD, what we'll probably
-	 * actually get is RECORD's typelem, ie, zero.
+	 * Give a friendly error message if we did not get enough info to identify
+	 * the target record type.  (lookup_rowtype_tupdesc would fail anyway, but
+	 * with a non-user-friendly message.)  In ordinary SQL usage, we'll get -1
+	 * for typmod, since composite types and RECORD have no type modifiers at
+	 * the SQL level, and thus must fail for RECORD.  However some callers can
+	 * supply a valid typmod, and then we can do something useful for RECORD.
 	 */
-	if (tupType == InvalidOid || tupType == RECORDOID)
+	if (tupType == RECORDOID && tupTypmod < 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 		   errmsg("input of anonymous composite types is not implemented")));
-	tupTypmod = -1;				/* for all non-anonymous types */
 
 	/*
 	 * This comes from the composite type's pg_type.oid and stores system oids
@@ -447,12 +444,8 @@ record_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	Oid			tupType = PG_GETARG_OID(1);
-
-#ifdef NOT_USED
-	int32		typmod = PG_GETARG_INT32(2);
-#endif
+	int32		tupTypmod = PG_GETARG_INT32(2);
 	HeapTupleHeader result;
-	int32		tupTypmod;
 	TupleDesc	tupdesc;
 	HeapTuple	tuple;
 	RecordIOData *my_extra;
@@ -464,16 +457,18 @@ record_recv(PG_FUNCTION_ARGS)
 	bool	   *nulls;
 
 	/*
-	 * Use the passed type unless it's RECORD; we can't support input of
-	 * anonymous types, mainly because there's no good way to figure out which
-	 * anonymous type is wanted.  Note that for RECORD, what we'll probably
-	 * actually get is RECORD's typelem, ie, zero.
+	 * Give a friendly error message if we did not get enough info to identify
+	 * the target record type.  (lookup_rowtype_tupdesc would fail anyway, but
+	 * with a non-user-friendly message.)  In ordinary SQL usage, we'll get -1
+	 * for typmod, since composite types and RECORD have no type modifiers at
+	 * the SQL level, and thus must fail for RECORD.  However some callers can
+	 * supply a valid typmod, and then we can do something useful for RECORD.
 	 */
-	if (tupType == InvalidOid || tupType == RECORDOID)
+	if (tupType == RECORDOID && tupTypmod < 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 		   errmsg("input of anonymous composite types is not implemented")));
-	tupTypmod = -1;				/* for all non-anonymous types */
+
 	tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
 	ncolumns = tupdesc->natts;