commit c5a86e6c68bd0ca7a225b30b913beb18b9e6fd16
Author: Jeremy Cole <jeremycole@google.com>
Date:   Fri Jul 19 10:44:36 2013 -0700

    Cheap compile-time check for unmatched DBUG_ENTER/LEAVE
    
    Overload "unused variable" warnings to provide cheap compile-time check
    for unmatched DBUG_ENTER and DBUG_{LEAVE,RETURN,VOID_RETURN} by adding a
    variable in the DBUG_ENTER macro which is used only in the DBUG_LEAVE
    macro. When compiled with -Wunused-variable (and especially -Werror)
    this makes it easy to find any missing DBUG_LEAVE variant in any
    function.
    
    Prior to the conversion of DBUG entirely to C, a run-time check existed
    where an object was instantiated for each DBUG_ENTER which would trigger
    an error if it was automatically destructed by falling out of scope prior
    to being disabled by a DBUG_LEAVE. Although currently there is a check in
    _db_return_ which compares cs->framep to the current function's local
    _db_stack_frame_, it does not detect missing DBUG_LEAVE variants in
    functions which are: a. called only from non-instrumented functions,
    b. called only from non-returning functions, or c. called from functions
    who call my_end or my_thread_end (making cs unavailable) before returning.
    
    Note that this only ensures that the function has *some* way to return
    using a matching DBUG_LEAVE variant; it does not do run-time analysis to
    ensure that this is always done correctly.
    
    Note that some functions (such as abort-like ones and ones which are
    used as a thread routine) are not expected to meaningfully return, and
    it may be quite awkward to provide paired DBUG_ENTER/DBUG_RETURN. These
    functions must be marked with the new macro DBUG_ENTER_NO_RETURN, which
    disables this check, in order to avoid spurious unused variable warnings.
    
    In addition to adding the feature, two missing returns were added:
      * DBUG_VOID_RETURN in do_result_format_version in client/mysqltest.cc.
      * DBUG_RETURN(0) in create_dest_frm in storage/myisam/myisampack.c.
    
    All instances of DBUG_ENTER without paired DBUG_LEAVE variants in abort
    functions and thread routines were adjusted to DBUG_ENTER_NO_RETURN.
    
    Change-Id: I7f0eed54ac2c78e3515754bffbbe19203c58bc6a

diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index abf7849..2805cab 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -172,7 +172,7 @@ static void free_used_memory(void)
 static void die(const char *fmt, ...)
 {
   va_list args;
-  DBUG_ENTER("die");
+  DBUG_ENTER_NO_RETURN("die");
 
   /* Print the error message */
   va_start(args, fmt);
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 35a98c9..3d5e643 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1568,7 +1568,7 @@ void report_or_die(const char *fmt, ...)
 void abort_not_supported_test(const char *fmt, ...)
 {
   va_list args;
-  DBUG_ENTER("abort_not_supported_test");
+  DBUG_ENTER_NO_RETURN("abort_not_supported_test");
 
   /* Print include filestack */
   fflush(stdout);
@@ -2732,6 +2732,8 @@ do_result_format_version(struct st_command *command)
   dynstr_append_mem(&ds_res, ds_version.str, ds_version.length);
   dynstr_append(&ds_res, "\n");
   dynstr_free(&ds_version);
+
+  DBUG_VOID_RETURN;
 }
 
 
@@ -8878,7 +8880,7 @@ int main(int argc, char **argv)
   char save_file[FN_REFLEN];
   bool empty_result= FALSE;
   MY_INIT(argv[0]);
-  DBUG_ENTER("main");
+  DBUG_ENTER_NO_RETURN("main");
 
   /* mysqltest has no way to free all its memory correctly */
   sf_leaking_memory= 1;
diff --git a/include/my_dbug.h b/include/my_dbug.h
index bcf2015..f53f175 100644
--- a/include/my_dbug.h
+++ b/include/my_dbug.h
@@ -63,10 +63,34 @@ extern void dbug_swap_code_state(void **code_state_store);
 extern void dbug_free_code_state(void **code_state_store);
 extern  const char* _db_get_func_(void);
 
-#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_; \
+#define DBUG_ENTER_BODY(a) \
+        struct _db_stack_frame_ _db_stack_frame_; \
         _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_)
-#define DBUG_LEAVE _db_return_ (__LINE__, &_db_stack_frame_)
 
+/*
+  Use DBUG_ENTER for functions that will always return via DBUG_RETURN or
+  DBUG_VOID_RETURN.
+
+  Use DBUG_ENTER_NO_RETURN for functions that are not expected to return
+  meaningfully, such as abort/die functions, and thread routines. This will
+  disable compile-time checking of DBUG_ENTER/DBUG_RETURN pairing via "unused
+  variable" compiler warnings.
+
+  Note: If a compiler warning for _db_line_unused_means_missing_return_ appears
+  claiming that the variable is unused, this normally means that the function
+  in question is missing a DBUG_RETURN or DBUG_VOID_RETURN. This variable is
+  declared in DBUG_ENTER and only used in DBUG_LEAVE in order to allow compile-
+  time validation that DBUG_LEAVE is inserted into each function that uses
+  DBUG_ENTER.
+*/
+#define DBUG_ENTER(a) \
+        uint _db_line_unused_means_missing_return_; \
+        DBUG_ENTER_BODY(a)
+#define DBUG_ENTER_NO_RETURN(a) \
+        DBUG_ENTER_BODY(a)
+#define DBUG_LEAVE \
+        _db_line_unused_means_missing_return_= __LINE__; \
+        _db_return_ (_db_line_unused_means_missing_return_, &_db_stack_frame_)
 #define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0)
 #define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0)
 #define DBUG_EXECUTE(keyword,a1) \
@@ -130,6 +154,7 @@ extern void _db_suicide_();
 #else                                           /* No debugger */
 
 #define DBUG_ENTER(a1)
+#define DBUG_ENTER_NO_RETURN(a1)
 #define DBUG_VIOLATION_HELPER_LEAVE do { } while(0)
 #define DBUG_LEAVE
 #define DBUG_RETURN(a1)                 do { return(a1); } while(0)
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index c4b139c..4554b26 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1890,7 +1890,7 @@ void unireg_end(void)
 
 extern "C" void unireg_abort(int exit_code)
 {
-  DBUG_ENTER("unireg_abort");
+  DBUG_ENTER_NO_RETURN("unireg_abort");
 
   if (opt_help)
     usage();
diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc
index 13deb16..c75b1af 100644
--- a/sql/threadpool_unix.cc
+++ b/sql/threadpool_unix.cc
@@ -479,7 +479,7 @@ static void* timer_thread(void *param)
   pool_timer_t* timer=(pool_timer_t *)param;
 
   my_thread_init();
-  DBUG_ENTER("timer_thread");
+  DBUG_ENTER_NO_RETURN("timer_thread");
   timer->next_timeout_check= ULONGLONG_MAX;
   timer->current_microtime= microsecond_interval_timer();
 
@@ -1450,7 +1450,7 @@ static void *worker_main(void *param)
   pthread_detach_this_thread();
   my_thread_init();
   
-  DBUG_ENTER("worker_main");
+  DBUG_ENTER_NO_RETURN("worker_main");
   
   thread_group_t *thread_group = (thread_group_t *)param;
 
diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c
index 4bc179c..0c38551 100644
--- a/storage/maria/ma_sort.c
+++ b/storage/maria/ma_sort.c
@@ -341,7 +341,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg)
     goto err;
 
   { /* Add extra block since DBUG_ENTER declare variables */
-    DBUG_ENTER("_ma_thr_find_all_keys");
+    DBUG_ENTER_NO_RETURN("_ma_thr_find_all_keys");
     DBUG_PRINT("enter", ("master: %d", sort_param->master));
     if (sort_param->sort_info->got_error)
       goto err;
diff --git a/storage/maria/unittest/ma_pagecache_consist.c b/storage/maria/unittest/ma_pagecache_consist.c
index 6a25a47..0ef7d0f 100644
--- a/storage/maria/unittest/ma_pagecache_consist.c
+++ b/storage/maria/unittest/ma_pagecache_consist.c
@@ -291,7 +291,7 @@ static void *test_thread_reader(void *arg)
   int param=*((int*) arg);
   my_thread_init();
   {
-    DBUG_ENTER("test_reader");
+    DBUG_ENTER_NO_RETURN("test_reader");
     DBUG_PRINT("enter", ("param: %d", param));
 
     reader(param);
@@ -314,7 +314,7 @@ static void *test_thread_writer(void *arg)
   int param=*((int*) arg);
   my_thread_init();
   {
-    DBUG_ENTER("test_writer");
+    DBUG_ENTER_NO_RETURN("test_writer");
     DBUG_PRINT("enter", ("param: %d", param));
 
     writer(param);
@@ -375,7 +375,7 @@ int main(int argc __attribute__((unused)),
 #endif
 
   {
-  DBUG_ENTER("main");
+  DBUG_ENTER_NO_RETURN("main");
   DBUG_PRINT("info", ("Main thread: %s\n", my_thread_name()));
   plan(number_of_writers + number_of_readers);
 
diff --git a/storage/maria/unittest/ma_pagecache_rwconsist.c b/storage/maria/unittest/ma_pagecache_rwconsist.c
index 7afdbfd..6d00ed0 100644
--- a/storage/maria/unittest/ma_pagecache_rwconsist.c
+++ b/storage/maria/unittest/ma_pagecache_rwconsist.c
@@ -161,7 +161,7 @@ static void *test_thread_reader(void *arg)
   int param=*((int*) arg);
   my_thread_init();
   {
-    DBUG_ENTER("test_reader");
+    DBUG_ENTER_NO_RETURN("test_reader");
 
     DBUG_PRINT("enter", ("param: %d", param));
 
@@ -185,7 +185,7 @@ static void *test_thread_writer(void *arg)
   int param=*((int*) arg);
   my_thread_init();
   {
-    DBUG_ENTER("test_writer");
+    DBUG_ENTER_NO_RETURN("test_writer");
 
     writer(param);
 
@@ -246,7 +246,7 @@ int main(int argc __attribute__((unused)),
 #endif
 
   {
-  DBUG_ENTER("main");
+  DBUG_ENTER_NO_RETURN("main");
   DBUG_PRINT("info", ("Main thread: %s\n", my_thread_name()));
   plan(number_of_writers + number_of_readers);
   SKIP_BIG_TESTS(number_of_writers + number_of_readers)
diff --git a/storage/maria/unittest/ma_pagecache_rwconsist2.c b/storage/maria/unittest/ma_pagecache_rwconsist2.c
index 917fddd..d1bf303 100644
--- a/storage/maria/unittest/ma_pagecache_rwconsist2.c
+++ b/storage/maria/unittest/ma_pagecache_rwconsist2.c
@@ -157,7 +157,7 @@ static void *test_thread_reader(void *arg)
   int param=*((int*) arg);
   my_thread_init();
   {
-    DBUG_ENTER("test_reader");
+    DBUG_ENTER_NO_RETURN("test_reader");
 
     DBUG_PRINT("enter", ("param: %d", param));
 
@@ -181,7 +181,7 @@ static void *test_thread_writer(void *arg)
   int param=*((int*) arg);
   my_thread_init();
   {
-    DBUG_ENTER("test_writer");
+    DBUG_ENTER_NO_RETURN("test_writer");
 
     writer(param);
 
@@ -242,7 +242,7 @@ int main(int argc __attribute__((unused)),
 #endif
 
   {
-  DBUG_ENTER("main");
+  DBUG_ENTER_NO_RETURN("main");
   DBUG_PRINT("info", ("Main thread: %s\n", my_thread_name()));
   plan(number_of_writers + number_of_readers);
   SKIP_BIG_TESTS(number_of_writers + number_of_readers)
diff --git a/storage/maria/unittest/ma_pagecache_single.c b/storage/maria/unittest/ma_pagecache_single.c
index d7da87a..6e58592 100644
--- a/storage/maria/unittest/ma_pagecache_single.c
+++ b/storage/maria/unittest/ma_pagecache_single.c
@@ -691,7 +691,7 @@ static void *test_thread(void *arg)
 
   my_thread_init();
   {
-  DBUG_ENTER("test_thread");
+  DBUG_ENTER_NO_RETURN("test_thread");
   DBUG_PRINT("enter", ("param: %d", param));
 
   if (!simple_read_write_test() ||
@@ -716,7 +716,7 @@ static void *test_thread(void *arg)
   pthread_mutex_unlock(&LOCK_thread_count);
   free((uchar*) arg);
   my_thread_end();
-  DBUG_RETURN(0);
+  return 0;
   }
 }
 
@@ -765,7 +765,7 @@ int main(int argc __attribute__((unused)),
   }
 #endif
   {
-  DBUG_ENTER("main");
+  DBUG_ENTER_NO_RETURN("main");
   DBUG_PRINT("info", ("Main thread: %s\n", my_thread_name()));
 
   plan(18);
diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c
index 6ce88db..c7213da 100644
--- a/storage/myisam/myisampack.c
+++ b/storage/myisam/myisampack.c
@@ -783,7 +783,7 @@ static int create_dest_frm(char *source_table, char *dest_table)
   */
   (void) my_copy(source_name, dest_name, MYF(MY_DONT_OVERWRITE_FILE));
   
-  return 0;
+  DBUG_RETURN(0);
 }
 
 
diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c
index 4af45ea..d18412c 100644
--- a/storage/myisam/sort.c
+++ b/storage/myisam/sort.c
@@ -327,7 +327,7 @@ pthread_handler_t thr_find_all_keys(void *arg)
     goto err;
 
   { /* Add extra block since DBUG_ENTER declare variables */
-    DBUG_ENTER("thr_find_all_keys");
+    DBUG_ENTER_NO_RETURN("thr_find_all_keys");
     DBUG_PRINT("enter", ("master: %d", sort_param->master));
     if (sort_param->sort_info->got_error)
       goto err;
