From 8fe81e6a79f4e661fe0d0d82a781af98c6f45ffb Mon Sep 17 00:00:00 2001
From: Craig Ringer <craig.ringer@2ndquadrant.com>
Date: Thu, 3 Sep 2020 18:33:24 +0800
Subject: [PATCH 5/9] Assert() if returning from inside a PG_TRY() / PG_CATCH()
 block

---
 src/backend/utils/error/elog.c |  9 +++++++++
 src/include/utils/elog.h       | 13 +++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index f9cea36ba1..11de7ebd3c 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -3583,3 +3583,12 @@ check_errcontext_stack_on_return(const ErrorContextCallback * const cb)
 	}
 #endif
 }
+
+/*
+ * Implementation of the return guard checking in PG_TRY() / PG_END_TRY()
+ */
+void
+pg_try_check_return_guard(const bool * const did_return)
+{
+	Assert(!(*did_return)); /* "return" inside PG_TRY() or PG_CATCH() */
+}
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 1552366477..33fd1ca4a9 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -365,12 +365,24 @@ extern void check_errcontext_stack_on_return(const ErrorContextCallback * const
  * warnings are just about entirely useless for catching such oversights.
  *----------
  */
+
+extern void pg_try_check_return_guard(const bool * const returned_from_pg_try);
+#ifdef USE_ASSERT_CHECKING
+#define PG_TRY_SET_RETURN_GUARD \
+	bool _pg_try_returned pg_attribute_cleanup_cassert(pg_try_check_return_guard) = true
+#define PG_TRY_CLEAR_RETURN_GUARD _pg_try_returned = false
+#else
+#define PG_TRY_SET_RETURN_GUARD
+#define PG_TRY_CLEAR_RETURN_GUARD
+#endif
+
 #define PG_TRY()  \
 	do { \
 		sigjmp_buf *_save_exception_stack = PG_exception_stack; \
 		ErrorContextCallback *_save_context_stack = error_context_stack; \
 		sigjmp_buf _local_sigjmp_buf; \
 		bool _do_rethrow = false; \
+		PG_TRY_SET_RETURN_GUARD; \
 		if (sigsetjmp(_local_sigjmp_buf, 0) == 0) \
 		{ \
 			PG_exception_stack = &_local_sigjmp_buf
@@ -396,6 +408,7 @@ extern void check_errcontext_stack_on_return(const ErrorContextCallback * const
 				PG_RE_THROW(); \
 		PG_exception_stack = _save_exception_stack; \
 		error_context_stack = _save_context_stack; \
+		PG_TRY_CLEAR_RETURN_GUARD; \
 	} while (0)
 
 /*
-- 
2.26.2

