diff --git a/doc/src/sgml/sources.sgml b/doc/src/sgml/sources.sgml
index 32ca220..283c3e0 100644
--- a/doc/src/sgml/sources.sgml
+++ b/doc/src/sgml/sources.sgml
@@ -103,9 +103,9 @@ less -x4
     message text.  In addition there are optional elements, the most
     common of which is an error identifier code that follows the SQL spec's
     SQLSTATE conventions.
-    <function>ereport</function> itself is just a shell function, that exists
+    <function>ereport</function> itself is just a shell macro, that exists
     mainly for the syntactic convenience of making message generation
-    look like a function call in the C source code.  The only parameter
+    look like a single function call in the C source code.  The only parameter
     accepted directly by <function>ereport</function> is the severity level.
     The primary message text and any optional message elements are
     generated by calling auxiliary functions, such as <function>errmsg</function>,
@@ -116,36 +116,50 @@ less -x4
     A typical call to <function>ereport</function> might look like this:
 <programlisting>
 ereport(ERROR,
-        (errcode(ERRCODE_DIVISION_BY_ZERO),
-         errmsg("division by zero")));
+        errcode(ERRCODE_DIVISION_BY_ZERO),
+        errmsg("division by zero"));
 </programlisting>
     This specifies error severity level <literal>ERROR</literal> (a run-of-the-mill
     error).  The <function>errcode</function> call specifies the SQLSTATE error code
     using a macro defined in <filename>src/include/utils/errcodes.h</filename>.  The
-    <function>errmsg</function> call provides the primary message text.  Notice the
-    extra set of parentheses surrounding the auxiliary function calls &mdash;
-    these are annoying but syntactically necessary.
+    <function>errmsg</function> call provides the primary message text.
+   </para>
+
+   <para>
+    You will also frequently see this older style, with an extra set of
+    parentheses surrounding the auxiliary function calls:
+<programlisting>
+ereport(ERROR,
+        (errcode(ERRCODE_DIVISION_BY_ZERO),
+         errmsg("division by zero")));
+</programlisting>
+    The extra parentheses were required
+    before <productname>PostgreSQL</productname> version 12, but are now
+    optional.
    </para>
 
    <para>
     Here is a more complex example:
 <programlisting>
 ereport(ERROR,
-        (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
-         errmsg("function %s is not unique",
-                func_signature_string(funcname, nargs,
-                                      NIL, actual_arg_types)),
-         errhint("Unable to choose a best candidate function. "
-                 "You might need to add explicit typecasts.")));
+        errcode(ERRCODE_AMBIGUOUS_FUNCTION),
+        errmsg("function %s is not unique",
+               func_signature_string(funcname, nargs,
+                                     NIL, actual_arg_types)),
+        errhint("Unable to choose a best candidate function. "
+                "You might need to add explicit typecasts."));
 </programlisting>
     This illustrates the use of format codes to embed run-time values into
     a message text.  Also, an optional <quote>hint</quote> message is provided.
+    The auxiliary function calls can be written in any order, but
+    conventionally <function>errcode</function>
+    and <function>errmsg</function> appear first.
    </para>
 
    <para>
     If the severity level is <literal>ERROR</literal> or higher,
-    <function>ereport</function> aborts the execution of the user-defined
-    function and does not return to the caller. If the severity level is
+    <function>ereport</function> aborts execution of the current query
+    and does not return to the caller. If the severity level is
     lower than <literal>ERROR</literal>, <function>ereport</function> returns normally.
    </para>
 
@@ -390,7 +404,7 @@ elog(level, "format string", ...);
 </programlisting>
     is exactly equivalent to:
 <programlisting>
-ereport(level, (errmsg_internal("format string", ...)));
+ereport(level, errmsg_internal("format string", ...));
 </programlisting>
     Notice that the SQLSTATE error code is always defaulted, and the message
     string is not subject to translation.
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 00c77b6..cb8c23e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3720,15 +3720,15 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx,
 		/* spell the error message a bit differently depending on context */
 		if (IsUnderPostmaster)
 			ereport(FATAL,
-					(errcode(ERRCODE_SYNTAX_ERROR),
-					 errmsg("invalid command-line argument for server process: %s", argv[optind]),
-					 errhint("Try \"%s --help\" for more information.", progname)));
+					errcode(ERRCODE_SYNTAX_ERROR),
+					errmsg("invalid command-line argument for server process: %s", argv[optind]),
+					errhint("Try \"%s --help\" for more information.", progname));
 		else
 			ereport(FATAL,
-					(errcode(ERRCODE_SYNTAX_ERROR),
-					 errmsg("%s: invalid command-line argument: %s",
-							progname, argv[optind]),
-					 errhint("Try \"%s --help\" for more information.", progname)));
+					errcode(ERRCODE_SYNTAX_ERROR),
+					errmsg("%s: invalid command-line argument: %s",
+						   progname, argv[optind]),
+					errhint("Try \"%s --help\" for more information.", progname));
 	}
 
 	/*
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 62eef7b..a29ccd9 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -438,7 +438,7 @@ matches_backtrace_functions(const char *funcname)
  * See elog.h for the error level definitions.
  */
 void
-errfinish(int dummy,...)
+errfinish(void)
 {
 	ErrorData  *edata = &errordata[errordata_stack_depth];
 	int			elevel;
@@ -1463,7 +1463,7 @@ elog_finish(int elevel, const char *fmt,...)
 	/*
 	 * And let errfinish() finish up.
 	 */
-	errfinish(0);
+	errfinish();
 }
 
 
@@ -1749,7 +1749,7 @@ ThrowErrorData(ErrorData *edata)
 	recursion_depth--;
 
 	/* Process the error. */
-	errfinish(0);
+	errfinish();
 }
 
 /*
@@ -1863,7 +1863,7 @@ pg_re_throw(void)
 		 */
 		error_context_stack = NULL;
 
-		errfinish(0);
+		errfinish();
 	}
 
 	/* Doesn't return ... */
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 0a4ef02..73d84d1 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -91,9 +91,9 @@
 /*----------
  * New-style error reporting API: to be used in this way:
  *		ereport(ERROR,
- *				(errcode(ERRCODE_UNDEFINED_CURSOR),
- *				 errmsg("portal \"%s\" not found", stmt->portalname),
- *				 ... other errxxx() fields as needed ...));
+ *				errcode(ERRCODE_UNDEFINED_CURSOR),
+ *				errmsg("portal \"%s\" not found", stmt->portalname),
+ *				... other errxxx() fields as needed ...);
  *
  * The error level is required, and so is a primary error message (errmsg
  * or errmsg_internal).  All else is optional.  errcode() defaults to
@@ -101,6 +101,9 @@
  * if elevel is WARNING, or ERRCODE_SUCCESSFUL_COMPLETION if elevel is
  * NOTICE or below.
  *
+ * Before v12, extra parentheses were required around the support routine
+ * calls; that's now optional.
+ *
  * ereport_domain() allows a message domain to be specified, for modules that
  * wish to use a different message catalog from the backend's.  To avoid having
  * one copy of the default text domain per .o file, we define it as NULL here
@@ -118,34 +121,34 @@
  *----------
  */
 #ifdef HAVE__BUILTIN_CONSTANT_P
-#define ereport_domain(elevel, domain, rest)	\
+#define ereport_domain(elevel, domain, ...)	\
 	do { \
 		pg_prevent_errno_in_scope(); \
 		if (errstart(elevel, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain)) \
-			errfinish rest; \
+			__VA_ARGS__, errfinish(); \
 		if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \
 			pg_unreachable(); \
 	} while(0)
 #else							/* !HAVE__BUILTIN_CONSTANT_P */
-#define ereport_domain(elevel, domain, rest)	\
+#define ereport_domain(elevel, domain, ...)	\
 	do { \
 		const int elevel_ = (elevel); \
 		pg_prevent_errno_in_scope(); \
 		if (errstart(elevel_, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain)) \
-			errfinish rest; \
+			__VA_ARGS__, errfinish(); \
 		if (elevel_ >= ERROR) \
 			pg_unreachable(); \
 	} while(0)
 #endif							/* HAVE__BUILTIN_CONSTANT_P */
 
-#define ereport(elevel, rest)	\
-	ereport_domain(elevel, TEXTDOMAIN, rest)
+#define ereport(elevel, ...)	\
+	ereport_domain(elevel, TEXTDOMAIN, __VA_ARGS__)
 
 #define TEXTDOMAIN NULL
 
 extern bool errstart(int elevel, const char *filename, int lineno,
 					 const char *funcname, const char *domain);
-extern void errfinish(int dummy,...);
+extern void errfinish(void);
 
 extern int	errcode(int sqlerrcode);
 
