diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 8cd3d6901c..4b60382778 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -9389,29 +9389,6 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
       </listitem>
      </varlistentry>
 
-     <varlistentry id="guc-operator-precedence-warning" xreflabel="operator_precedence_warning">
-      <term><varname>operator_precedence_warning</varname> (<type>boolean</type>)
-      <indexterm>
-       <primary><varname>operator_precedence_warning</varname> configuration parameter</primary>
-      </indexterm>
-      </term>
-      <listitem>
-       <para>
-        When on, the parser will emit a warning for any construct that might
-        have changed meanings since <productname>PostgreSQL</productname> 9.4 as a result
-        of changes in operator precedence.  This is useful for auditing
-        applications to see if precedence changes have broken anything; but it
-        is not meant to be kept turned on in production, since it will warn
-        about some perfectly valid, standard-compliant SQL code.
-        The default is <literal>off</literal>.
-       </para>
-
-       <para>
-        See <xref linkend="sql-precedence"/> for more information.
-       </para>
-      </listitem>
-     </varlistentry>
-
     <varlistentry id="guc-quote-all-identifiers" xreflabel="quote-all-identifiers">
       <term><varname>quote_all_identifiers</varname> (<type>boolean</type>)
       <indexterm>
diff --git a/doc/src/sgml/syntax.sgml b/doc/src/sgml/syntax.sgml
index 3fdd87823e..d66560b587 100644
--- a/doc/src/sgml/syntax.sgml
+++ b/doc/src/sgml/syntax.sgml
@@ -1121,11 +1121,7 @@ SELECT 3 OPERATOR(pg_catalog.+) 4;
      cases, these changes will result in no behavioral change, or perhaps
      in <quote>no such operator</quote> failures which can be resolved by adding
      parentheses.  However there are corner cases in which a query might
-     change behavior without any parsing error being reported.  If you are
-     concerned about whether these changes have silently broken something,
-     you can test your application with the configuration
-     parameter <xref linkend="guc-operator-precedence-warning"/> turned on
-     to see if any warnings are logged.
+     change behavior without any parsing error being reported.
     </para>
    </note>
   </sect2>
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 9c73c605a4..8f5e4e71b2 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -3264,9 +3264,6 @@ _outAExpr(StringInfo str, const A_Expr *node)
 			appendStringInfoString(str, " NOT_BETWEEN_SYM ");
 			WRITE_NODE_FIELD(name);
 			break;
-		case AEXPR_PAREN:
-			appendStringInfoString(str, " PAREN");
-			break;
 		default:
 			appendStringInfoString(str, " ??");
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ecff4cd2ac..8f341ac006 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -59,7 +59,6 @@
 #include "nodes/nodeFuncs.h"
 #include "parser/gramparse.h"
 #include "parser/parser.h"
-#include "parser/parse_expr.h"
 #include "storage/lmgr.h"
 #include "utils/date.h"
 #include "utils/datetime.h"
@@ -13461,28 +13460,6 @@ c_expr:		columnref								{ $$ = $1; }
 						n->indirection = check_indirection($4, yyscanner);
 						$$ = (Node *)n;
 					}
-					else if (operator_precedence_warning)
-					{
-						/*
-						 * If precedence warnings are enabled, insert
-						 * AEXPR_PAREN nodes wrapping all explicitly
-						 * parenthesized subexpressions; this prevents bogus
-						 * warnings from being issued when the ordering has
-						 * been forced by parentheses.  Take care that an
-						 * AEXPR_PAREN node has the same exprLocation as its
-						 * child, so as not to cause surprising changes in
-						 * error cursor positioning.
-						 *
-						 * In principle we should not be relying on a GUC to
-						 * decide whether to insert AEXPR_PAREN nodes.
-						 * However, since they have no effect except to
-						 * suppress warnings, it's probably safe enough; and
-						 * we'd just as soon not waste cycles on dummy parse
-						 * nodes if we don't have to.
-						 */
-						$$ = (Node *) makeA_Expr(AEXPR_PAREN, NIL, $2, NULL,
-												 exprLocation($2));
-					}
 					else
 						$$ = $2;
 				}
@@ -16516,16 +16493,10 @@ doNegateFloat(Value *v)
 static Node *
 makeAndExpr(Node *lexpr, Node *rexpr, int location)
 {
-	Node	   *lexp = lexpr;
-
-	/* Look through AEXPR_PAREN nodes so they don't affect flattening */
-	while (IsA(lexp, A_Expr) &&
-		   ((A_Expr *) lexp)->kind == AEXPR_PAREN)
-		lexp = ((A_Expr *) lexp)->lexpr;
 	/* Flatten "a AND b AND c ..." to a single BoolExpr on sight */
-	if (IsA(lexp, BoolExpr))
+	if (IsA(lexpr, BoolExpr))
 	{
-		BoolExpr *blexpr = (BoolExpr *) lexp;
+		BoolExpr *blexpr = (BoolExpr *) lexpr;
 
 		if (blexpr->boolop == AND_EXPR)
 		{
@@ -16539,16 +16510,10 @@ makeAndExpr(Node *lexpr, Node *rexpr, int location)
 static Node *
 makeOrExpr(Node *lexpr, Node *rexpr, int location)
 {
-	Node	   *lexp = lexpr;
-
-	/* Look through AEXPR_PAREN nodes so they don't affect flattening */
-	while (IsA(lexp, A_Expr) &&
-		   ((A_Expr *) lexp)->kind == AEXPR_PAREN)
-		lexp = ((A_Expr *) lexp)->lexpr;
 	/* Flatten "a OR b OR c ..." to a single BoolExpr on sight */
-	if (IsA(lexp, BoolExpr))
+	if (IsA(lexpr, BoolExpr))
 	{
-		BoolExpr *blexpr = (BoolExpr *) lexp;
+		BoolExpr *blexpr = (BoolExpr *) lexpr;
 
 		if (blexpr->boolop == OR_EXPR)
 		{
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 36002f059d..1e62d31aca 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -39,53 +39,8 @@
 #include "utils/xml.h"
 
 /* GUC parameters */
-bool		operator_precedence_warning = false;
 bool		Transform_null_equals = false;
 
-/*
- * Node-type groups for operator precedence warnings
- * We use zero for everything not otherwise classified
- */
-#define PREC_GROUP_POSTFIX_IS	1	/* postfix IS tests (NullTest, etc) */
-#define PREC_GROUP_INFIX_IS		2	/* infix IS (IS DISTINCT FROM, etc) */
-#define PREC_GROUP_LESS			3	/* < > */
-#define PREC_GROUP_EQUAL		4	/* = */
-#define PREC_GROUP_LESS_EQUAL	5	/* <= >= <> */
-#define PREC_GROUP_LIKE			6	/* LIKE ILIKE SIMILAR */
-#define PREC_GROUP_BETWEEN		7	/* BETWEEN */
-#define PREC_GROUP_IN			8	/* IN */
-#define PREC_GROUP_NOT_LIKE		9	/* NOT LIKE/ILIKE/SIMILAR */
-#define PREC_GROUP_NOT_BETWEEN	10	/* NOT BETWEEN */
-#define PREC_GROUP_NOT_IN		11	/* NOT IN */
-#define PREC_GROUP_ANY_ALL		12	/* ANY/ALL */
-#define PREC_GROUP_INFIX_OP		13	/* generic infix operators */
-#define PREC_GROUP_PREFIX_OP	14	/* generic prefix operators */
-
-/*
- * Map precedence groupings to old precedence ordering
- *
- * Old precedence order:
- * 1. NOT
- * 2. =
- * 3. < >
- * 4. LIKE ILIKE SIMILAR
- * 5. BETWEEN
- * 6. IN
- * 7. ANY ALL
- * 8. generic Op, including <= => <>
- * 9. generic prefix Op
- * 10. IS tests (NullTest, BooleanTest, etc)
- *
- * NOT BETWEEN etc map to BETWEEN etc when considered as being on the left,
- * but to NOT when considered as being on the right, because of the buggy
- * precedence handling of those productions in the old grammar.
- */
-static const int oldprecedence_l[] = {
-	0, 10, 10, 3, 2, 8, 4, 5, 6, 4, 5, 6, 7, 8, 9
-};
-static const int oldprecedence_r[] = {
-	0, 10, 10, 3, 2, 8, 4, 5, 6, 1, 1, 1, 7, 8, 9
-};
 
 static Node *transformExprRecurse(ParseState *pstate, Node *expr);
 static Node *transformParamRef(ParseState *pstate, ParamRef *pref);
@@ -127,11 +82,6 @@ static Expr *make_distinct_op(ParseState *pstate, List *opname,
 							  Node *ltree, Node *rtree, int location);
 static Node *make_nulltest_from_distinct(ParseState *pstate,
 										 A_Expr *distincta, Node *arg);
-static int	operator_precedence_group(Node *node, const char **nodename);
-static void emit_precedence_warnings(ParseState *pstate,
-									 int opgroup, const char *opname,
-									 Node *lchild, Node *rchild,
-									 int location);
 
 
 /*
@@ -242,9 +192,6 @@ transformExprRecurse(ParseState *pstate, Node *expr)
 					case AEXPR_NOT_BETWEEN_SYM:
 						result = transformAExprBetween(pstate, a);
 						break;
-					case AEXPR_PAREN:
-						result = transformExprRecurse(pstate, a->lexpr);
-						break;
 					default:
 						elog(ERROR, "unrecognized A_Expr kind: %d", a->kind);
 						result = NULL;	/* keep compiler quiet */
@@ -315,11 +262,6 @@ transformExprRecurse(ParseState *pstate, Node *expr)
 			{
 				NullTest   *n = (NullTest *) expr;
 
-				if (operator_precedence_warning)
-					emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS",
-											 (Node *) n->arg, NULL,
-											 n->location);
-
 				n->arg = (Expr *) transformExprRecurse(pstate, (Node *) n->arg);
 				/* the argument can be any type, so don't coerce it */
 				n->argisrow = type_is_rowtype(exprType((Node *) n->arg));
@@ -926,26 +868,6 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
 	Node	   *rexpr = a->rexpr;
 	Node	   *result;
 
-	if (operator_precedence_warning)
-	{
-		int			opgroup;
-		const char *opname;
-
-		opgroup = operator_precedence_group((Node *) a, &opname);
-		if (opgroup > 0)
-			emit_precedence_warnings(pstate, opgroup, opname,
-									 lexpr, rexpr,
-									 a->location);
-
-		/* Look through AEXPR_PAREN nodes so they don't affect tests below */
-		while (lexpr && IsA(lexpr, A_Expr) &&
-			   ((A_Expr *) lexpr)->kind == AEXPR_PAREN)
-			lexpr = ((A_Expr *) lexpr)->lexpr;
-		while (rexpr && IsA(rexpr, A_Expr) &&
-			   ((A_Expr *) rexpr)->kind == AEXPR_PAREN)
-			rexpr = ((A_Expr *) rexpr)->lexpr;
-	}
-
 	/*
 	 * Special-case "foo = NULL" and "NULL = foo" for compatibility with
 	 * standards-broken products (like Microsoft's).  Turn these into IS NULL
@@ -1023,17 +945,8 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
 static Node *
 transformAExprOpAny(ParseState *pstate, A_Expr *a)
 {
-	Node	   *lexpr = a->lexpr;
-	Node	   *rexpr = a->rexpr;
-
-	if (operator_precedence_warning)
-		emit_precedence_warnings(pstate, PREC_GROUP_ANY_ALL,
-								 strVal(llast(a->name)),
-								 lexpr, NULL,
-								 a->location);
-
-	lexpr = transformExprRecurse(pstate, lexpr);
-	rexpr = transformExprRecurse(pstate, rexpr);
+	Node	   *lexpr = transformExprRecurse(pstate, a->lexpr);
+	Node	   *rexpr = transformExprRecurse(pstate, a->rexpr);
 
 	return (Node *) make_scalar_array_op(pstate,
 										 a->name,
@@ -1046,17 +959,8 @@ transformAExprOpAny(ParseState *pstate, A_Expr *a)
 static Node *
 transformAExprOpAll(ParseState *pstate, A_Expr *a)
 {
-	Node	   *lexpr = a->lexpr;
-	Node	   *rexpr = a->rexpr;
-
-	if (operator_precedence_warning)
-		emit_precedence_warnings(pstate, PREC_GROUP_ANY_ALL,
-								 strVal(llast(a->name)),
-								 lexpr, NULL,
-								 a->location);
-
-	lexpr = transformExprRecurse(pstate, lexpr);
-	rexpr = transformExprRecurse(pstate, rexpr);
+	Node	   *lexpr = transformExprRecurse(pstate, a->lexpr);
+	Node	   *rexpr = transformExprRecurse(pstate, a->rexpr);
 
 	return (Node *) make_scalar_array_op(pstate,
 										 a->name,
@@ -1073,11 +977,6 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a)
 	Node	   *rexpr = a->rexpr;
 	Node	   *result;
 
-	if (operator_precedence_warning)
-		emit_precedence_warnings(pstate, PREC_GROUP_INFIX_IS, "IS",
-								 lexpr, rexpr,
-								 a->location);
-
 	/*
 	 * If either input is an undecorated NULL literal, transform to a NullTest
 	 * on the other input. That's simpler to process than a full DistinctExpr,
@@ -1183,13 +1082,6 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
 	else
 		useOr = true;
 
-	if (operator_precedence_warning)
-		emit_precedence_warnings(pstate,
-								 useOr ? PREC_GROUP_IN : PREC_GROUP_NOT_IN,
-								 "IN",
-								 a->lexpr, NULL,
-								 a->location);
-
 	/*
 	 * We try to generate a ScalarArrayOpExpr from IN/NOT IN, but this is only
 	 * possible if there is a suitable array type available.  If not, we fall
@@ -1342,22 +1234,6 @@ transformAExprBetween(ParseState *pstate, A_Expr *a)
 	bexpr = (Node *) linitial(args);
 	cexpr = (Node *) lsecond(args);
 
-	if (operator_precedence_warning)
-	{
-		int			opgroup;
-		const char *opname;
-
-		opgroup = operator_precedence_group((Node *) a, &opname);
-		emit_precedence_warnings(pstate, opgroup, opname,
-								 aexpr, cexpr,
-								 a->location);
-		/* We can ignore bexpr thanks to syntactic restrictions */
-		/* Wrap subexpressions to prevent extra warnings */
-		aexpr = (Node *) makeA_Expr(AEXPR_PAREN, NIL, aexpr, NULL, -1);
-		bexpr = (Node *) makeA_Expr(AEXPR_PAREN, NIL, bexpr, NULL, -1);
-		cexpr = (Node *) makeA_Expr(AEXPR_PAREN, NIL, cexpr, NULL, -1);
-	}
-
 	/*
 	 * Build the equivalent comparison expression.  Make copies of
 	 * multiply-referenced subexpressions for safety.  (XXX this is really
@@ -1964,19 +1840,6 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
 		List	   *right_list;
 		ListCell   *l;
 
-		if (operator_precedence_warning)
-		{
-			if (sublink->operName == NIL)
-				emit_precedence_warnings(pstate, PREC_GROUP_IN, "IN",
-										 sublink->testexpr, NULL,
-										 sublink->location);
-			else
-				emit_precedence_warnings(pstate, PREC_GROUP_ANY_ALL,
-										 strVal(llast(sublink->operName)),
-										 sublink->testexpr, NULL,
-										 sublink->location);
-		}
-
 		/*
 		 * If the source was "x IN (select)", convert to "x = ANY (select)".
 		 */
@@ -2076,11 +1939,6 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
 		Node	   *e = (Node *) lfirst(element);
 		Node	   *newe;
 
-		/* Look through AEXPR_PAREN nodes so they don't affect test below */
-		while (e && IsA(e, A_Expr) &&
-			   ((A_Expr *) e)->kind == AEXPR_PAREN)
-			e = ((A_Expr *) e)->lexpr;
-
 		/*
 		 * If an element is itself an A_ArrayExpr, recurse directly so that we
 		 * can pass down any target type we were given.
@@ -2389,11 +2247,6 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
 	ListCell   *lc;
 	int			i;
 
-	if (operator_precedence_warning && x->op == IS_DOCUMENT)
-		emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS",
-								 (Node *) linitial(x->args), NULL,
-								 x->location);
-
 	newx = makeNode(XmlExpr);
 	newx->op = x->op;
 	if (x->name)
@@ -2564,11 +2417,6 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
 {
 	const char *clausename;
 
-	if (operator_precedence_warning)
-		emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS",
-								 (Node *) b->arg, NULL,
-								 b->location);
-
 	switch (b->booltesttype)
 	{
 		case IS_TRUE:
@@ -2702,15 +2550,6 @@ transformTypeCast(ParseState *pstate, TypeCast *tc)
 	/* Look up the type name first */
 	typenameTypeIdAndMod(pstate, tc->typeName, &targetType, &targetTypmod);
 
-	/*
-	 * Look through any AEXPR_PAREN nodes that may have been inserted thanks
-	 * to operator_precedence_warning.  Otherwise, ARRAY[]::foo[] behaves
-	 * differently from (ARRAY[])::foo[].
-	 */
-	while (arg && IsA(arg, A_Expr) &&
-		   ((A_Expr *) arg)->kind == AEXPR_PAREN)
-		arg = ((A_Expr *) arg)->lexpr;
-
 	/*
 	 * If the subject of the typecast is an ARRAY[] construct and the target
 	 * type is an array type, we invoke transformArrayExpr() directly so that
@@ -3117,287 +2956,6 @@ make_nulltest_from_distinct(ParseState *pstate, A_Expr *distincta, Node *arg)
 	return (Node *) nt;
 }
 
-/*
- * Identify node's group for operator precedence warnings
- *
- * For items in nonzero groups, also return a suitable node name into *nodename
- *
- * Note: group zero is used for nodes that are higher or lower precedence
- * than everything that changed precedence; we need never issue warnings
- * related to such nodes.
- */
-static int
-operator_precedence_group(Node *node, const char **nodename)
-{
-	int			group = 0;
-
-	*nodename = NULL;
-	if (node == NULL)
-		return 0;
-
-	if (IsA(node, A_Expr))
-	{
-		A_Expr	   *aexpr = (A_Expr *) node;
-
-		if (aexpr->kind == AEXPR_OP &&
-			aexpr->lexpr != NULL &&
-			aexpr->rexpr != NULL)
-		{
-			/* binary operator */
-			if (list_length(aexpr->name) == 1)
-			{
-				*nodename = strVal(linitial(aexpr->name));
-				/* Ignore if op was always higher priority than IS-tests */
-				if (strcmp(*nodename, "+") == 0 ||
-					strcmp(*nodename, "-") == 0 ||
-					strcmp(*nodename, "*") == 0 ||
-					strcmp(*nodename, "/") == 0 ||
-					strcmp(*nodename, "%") == 0 ||
-					strcmp(*nodename, "^") == 0)
-					group = 0;
-				else if (strcmp(*nodename, "<") == 0 ||
-						 strcmp(*nodename, ">") == 0)
-					group = PREC_GROUP_LESS;
-				else if (strcmp(*nodename, "=") == 0)
-					group = PREC_GROUP_EQUAL;
-				else if (strcmp(*nodename, "<=") == 0 ||
-						 strcmp(*nodename, ">=") == 0 ||
-						 strcmp(*nodename, "<>") == 0)
-					group = PREC_GROUP_LESS_EQUAL;
-				else
-					group = PREC_GROUP_INFIX_OP;
-			}
-			else
-			{
-				/* schema-qualified operator syntax */
-				*nodename = "OPERATOR()";
-				group = PREC_GROUP_INFIX_OP;
-			}
-		}
-		else if (aexpr->kind == AEXPR_OP &&
-				 aexpr->lexpr == NULL &&
-				 aexpr->rexpr != NULL)
-		{
-			/* prefix operator */
-			if (list_length(aexpr->name) == 1)
-			{
-				*nodename = strVal(linitial(aexpr->name));
-				/* Ignore if op was always higher priority than IS-tests */
-				if (strcmp(*nodename, "+") == 0 ||
-					strcmp(*nodename, "-") == 0)
-					group = 0;
-				else
-					group = PREC_GROUP_PREFIX_OP;
-			}
-			else
-			{
-				/* schema-qualified operator syntax */
-				*nodename = "OPERATOR()";
-				group = PREC_GROUP_PREFIX_OP;
-			}
-		}
-		else if (aexpr->kind == AEXPR_OP_ANY ||
-				 aexpr->kind == AEXPR_OP_ALL)
-		{
-			*nodename = strVal(llast(aexpr->name));
-			group = PREC_GROUP_ANY_ALL;
-		}
-		else if (aexpr->kind == AEXPR_DISTINCT ||
-				 aexpr->kind == AEXPR_NOT_DISTINCT)
-		{
-			*nodename = "IS";
-			group = PREC_GROUP_INFIX_IS;
-		}
-		else if (aexpr->kind == AEXPR_IN)
-		{
-			*nodename = "IN";
-			if (strcmp(strVal(linitial(aexpr->name)), "=") == 0)
-				group = PREC_GROUP_IN;
-			else
-				group = PREC_GROUP_NOT_IN;
-		}
-		else if (aexpr->kind == AEXPR_LIKE)
-		{
-			*nodename = "LIKE";
-			if (strcmp(strVal(linitial(aexpr->name)), "~~") == 0)
-				group = PREC_GROUP_LIKE;
-			else
-				group = PREC_GROUP_NOT_LIKE;
-		}
-		else if (aexpr->kind == AEXPR_ILIKE)
-		{
-			*nodename = "ILIKE";
-			if (strcmp(strVal(linitial(aexpr->name)), "~~*") == 0)
-				group = PREC_GROUP_LIKE;
-			else
-				group = PREC_GROUP_NOT_LIKE;
-		}
-		else if (aexpr->kind == AEXPR_SIMILAR)
-		{
-			*nodename = "SIMILAR";
-			if (strcmp(strVal(linitial(aexpr->name)), "~") == 0)
-				group = PREC_GROUP_LIKE;
-			else
-				group = PREC_GROUP_NOT_LIKE;
-		}
-		else if (aexpr->kind == AEXPR_BETWEEN ||
-				 aexpr->kind == AEXPR_BETWEEN_SYM)
-		{
-			Assert(list_length(aexpr->name) == 1);
-			*nodename = strVal(linitial(aexpr->name));
-			group = PREC_GROUP_BETWEEN;
-		}
-		else if (aexpr->kind == AEXPR_NOT_BETWEEN ||
-				 aexpr->kind == AEXPR_NOT_BETWEEN_SYM)
-		{
-			Assert(list_length(aexpr->name) == 1);
-			*nodename = strVal(linitial(aexpr->name));
-			group = PREC_GROUP_NOT_BETWEEN;
-		}
-	}
-	else if (IsA(node, NullTest) ||
-			 IsA(node, BooleanTest))
-	{
-		*nodename = "IS";
-		group = PREC_GROUP_POSTFIX_IS;
-	}
-	else if (IsA(node, XmlExpr))
-	{
-		XmlExpr    *x = (XmlExpr *) node;
-
-		if (x->op == IS_DOCUMENT)
-		{
-			*nodename = "IS";
-			group = PREC_GROUP_POSTFIX_IS;
-		}
-	}
-	else if (IsA(node, SubLink))
-	{
-		SubLink    *s = (SubLink *) node;
-
-		if (s->subLinkType == ANY_SUBLINK ||
-			s->subLinkType == ALL_SUBLINK)
-		{
-			if (s->operName == NIL)
-			{
-				*nodename = "IN";
-				group = PREC_GROUP_IN;
-			}
-			else
-			{
-				*nodename = strVal(llast(s->operName));
-				group = PREC_GROUP_ANY_ALL;
-			}
-		}
-	}
-	else if (IsA(node, BoolExpr))
-	{
-		/*
-		 * Must dig into NOTs to see if it's IS NOT DOCUMENT or NOT IN.  This
-		 * opens us to possibly misrecognizing, eg, NOT (x IS DOCUMENT) as a
-		 * problematic construct.  We can tell the difference by checking
-		 * whether the parse locations of the two nodes are identical.
-		 *
-		 * Note that when we are comparing the child node to its own children,
-		 * we will not know that it was a NOT.  Fortunately, that doesn't
-		 * matter for these cases.
-		 */
-		BoolExpr   *b = (BoolExpr *) node;
-
-		if (b->boolop == NOT_EXPR)
-		{
-			Node	   *child = (Node *) linitial(b->args);
-
-			if (IsA(child, XmlExpr))
-			{
-				XmlExpr    *x = (XmlExpr *) child;
-
-				if (x->op == IS_DOCUMENT &&
-					x->location == b->location)
-				{
-					*nodename = "IS";
-					group = PREC_GROUP_POSTFIX_IS;
-				}
-			}
-			else if (IsA(child, SubLink))
-			{
-				SubLink    *s = (SubLink *) child;
-
-				if (s->subLinkType == ANY_SUBLINK && s->operName == NIL &&
-					s->location == b->location)
-				{
-					*nodename = "IN";
-					group = PREC_GROUP_NOT_IN;
-				}
-			}
-		}
-	}
-	return group;
-}
-
-/*
- * helper routine for delivering 9.4-to-9.5 operator precedence warnings
- *
- * opgroup/opname/location represent some parent node
- * lchild, rchild are its left and right children (either could be NULL)
- *
- * This should be called before transforming the child nodes, since if a
- * precedence-driven parsing change has occurred in a query that used to work,
- * it's quite possible that we'll get a semantic failure while analyzing the
- * child expression.  We want to produce the warning before that happens.
- * In any case, operator_precedence_group() expects untransformed input.
- */
-static void
-emit_precedence_warnings(ParseState *pstate,
-						 int opgroup, const char *opname,
-						 Node *lchild, Node *rchild,
-						 int location)
-{
-	int			cgroup;
-	const char *copname;
-
-	Assert(opgroup > 0);
-
-	/*
-	 * Complain if left child, which should be same or higher precedence
-	 * according to current rules, used to be lower precedence.
-	 *
-	 * Exception to precedence rules: if left child is IN or NOT IN the
-	 * grouping is syntactically forced regardless of precedence.
-	 */
-	cgroup = operator_precedence_group(lchild, &copname);
-	if (cgroup > 0)
-	{
-		if (oldprecedence_l[cgroup] < oldprecedence_r[opgroup] &&
-			cgroup != PREC_GROUP_IN &&
-			cgroup != PREC_GROUP_NOT_IN &&
-			cgroup != PREC_GROUP_ANY_ALL &&
-			cgroup != PREC_GROUP_POSTFIX_IS)
-			ereport(WARNING,
-					(errmsg("operator precedence change: %s is now lower precedence than %s",
-							opname, copname),
-					 parser_errposition(pstate, location)));
-	}
-
-	/*
-	 * Complain if right child, which should be higher precedence according to
-	 * current rules, used to be same or lower precedence.
-	 *
-	 * Exception to precedence rules: if right child is a prefix operator, the
-	 * grouping is syntactically forced regardless of precedence.
-	 */
-	cgroup = operator_precedence_group(rchild, &copname);
-	if (cgroup > 0)
-	{
-		if (oldprecedence_r[cgroup] <= oldprecedence_l[opgroup] &&
-			cgroup != PREC_GROUP_PREFIX_OP)
-			ereport(WARNING,
-					(errmsg("operator precedence change: %s is now lower precedence than %s",
-							opname, copname),
-					 parser_errposition(pstate, location)));
-	}
-}
-
 /*
  * Produce a string identifying an expression by kind.
  *
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 9de0cff833..ce68663cc2 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -1755,11 +1755,6 @@ FigureColnameInternal(Node *node, char **name)
 				*name = "nullif";
 				return 2;
 			}
-			if (((A_Expr *) node)->kind == AEXPR_PAREN)
-			{
-				/* look through dummy parenthesis node */
-				return FigureColnameInternal(((A_Expr *) node)->lexpr, name);
-			}
 			break;
 		case T_TypeCast:
 			strength = FigureColnameInternal(((TypeCast *) node)->arg,
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 635d91d50a..dabcbb0736 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1878,16 +1878,6 @@ static struct config_bool ConfigureNamesBool[] =
 		NULL, NULL, NULL
 	},
 
-	{
-		{"operator_precedence_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
-			gettext_noop("Emit a warning for constructs that changed meaning since PostgreSQL 9.4."),
-			NULL,
-		},
-		&operator_precedence_warning,
-		false,
-		NULL, NULL, NULL
-	},
-
 	{
 		{"quote_all_identifiers", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("When generating SQL fragments, quote all identifiers."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 9c9091e601..b7fb2ec1fe 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -740,7 +740,6 @@
 #backslash_quote = safe_encoding	# on, off, or safe_encoding
 #escape_string_warning = on
 #lo_compat_privileges = off
-#operator_precedence_warning = off
 #quote_all_identifiers = off
 #standard_conforming_strings = on
 #synchronize_seqscans = on
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ec14fc2036..48a79a7657 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -265,8 +265,7 @@ typedef enum A_Expr_Kind
 	AEXPR_BETWEEN,				/* name must be "BETWEEN" */
 	AEXPR_NOT_BETWEEN,			/* name must be "NOT BETWEEN" */
 	AEXPR_BETWEEN_SYM,			/* name must be "BETWEEN SYMMETRIC" */
-	AEXPR_NOT_BETWEEN_SYM,		/* name must be "NOT BETWEEN SYMMETRIC" */
-	AEXPR_PAREN					/* nameless dummy node for parentheses */
+	AEXPR_NOT_BETWEEN_SYM		/* name must be "NOT BETWEEN SYMMETRIC" */
 } A_Expr_Kind;
 
 typedef struct A_Expr
diff --git a/src/include/parser/parse_expr.h b/src/include/parser/parse_expr.h
index b01d3b7dec..5668f88302 100644
--- a/src/include/parser/parse_expr.h
+++ b/src/include/parser/parse_expr.h
@@ -16,7 +16,6 @@
 #include "parser/parse_node.h"
 
 /* GUC parameters */
-extern bool operator_precedence_warning;
 extern bool Transform_null_equals;
 
 extern Node *transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind);
