From 5ae0d167048b27d56805080770deaf8c58ed344c Mon Sep 17 00:00:00 2001
From: Jonas Oreland <jonaso@google.com>
Date: Fri, 7 Nov 2014 09:20:17 +0000
Subject: [PATCH] InnoDB - fix attribute(nonnull) debug problems

This patch fixes inconsistencies with arguments
marked with attribute(nonnull) still being checked
with ut_ad(arg). We introduce a new ut_nonnulld(arg)
which avoids these problems.
---
 storage/innobase/btr/btr0btr.cc       |  6 ++++--
 storage/innobase/btr/btr0cur.cc       |  6 +++---
 storage/innobase/data/data0data.cc    |  3 ++-
 storage/innobase/fsp/fsp0fsp.cc       |  3 ++-
 storage/innobase/include/btr0btr.ic   |  9 ++++++---
 storage/innobase/include/data0data.ic |  6 ++++--
 storage/innobase/include/dict0dict.ic |  3 ++-
 storage/innobase/include/fts0ast.h    |  2 +-
 storage/innobase/include/rem0rec.ic   |  3 ++-
 storage/innobase/include/ut0dbg.h     |  9 +++++++++
 storage/innobase/lock/lock0lock.cc    |  3 ++-
 storage/innobase/page/page0zip.cc     |  3 ++-
 storage/innobase/rem/rem0cmp.cc       |  9 +++++++--
 storage/innobase/rem/rem0rec.cc       |  4 +++-
 storage/innobase/row/row0mysql.cc     |  6 ++++--
 storage/innobase/row/row0purge.cc     |  3 ++-
 storage/innobase/row/row0row.cc       | 16 ++++++++++++----
 storage/innobase/row/row0umod.cc      |  3 ++-
 storage/innobase/row/row0undo.cc      |  3 ++-
 storage/innobase/row/row0upd.cc       |  3 ++-
 storage/innobase/trx/trx0undo.cc      |  4 +++-
 21 files changed, 76 insertions(+), 31 deletions(-)

diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 99bb424..d93021c 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -2033,7 +2033,8 @@ btr_parse_page_reorganize(
 {
 	ulint	level;
 
-	ut_ad(ptr && end_ptr);
+	ut_nonnulld(ptr);
+	ut_nonnulld(end_ptr);
 
 	/* If dealing with a compressed page the record has the
 	compression level used during original compression written in
@@ -3371,7 +3372,8 @@ btr_level_list_remove_func(
 	ulint	prev_page_no;
 	ulint	next_page_no;
 
-	ut_ad(page && mtr);
+	ut_nonnulld(page);
+	ut_nonnulld(mtr);
 	ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
 	ut_ad(space == page_get_space_id(page));
 	/* Get the previous and next page numbers of page */
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index c60542a..7589000 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -1654,7 +1654,7 @@ btr_cur_pessimistic_insert(
 /*************************************************************//**
 For an update, checks the locks and does the undo logging.
 @return	DB_SUCCESS, DB_WAIT_LOCK, or error number */
-UNIV_INLINE __attribute__((warn_unused_result, nonnull(2,3,6,7)))
+UNIV_INLINE __attribute__((warn_unused_result, nonnull(2,3,7)))
 dberr_t
 btr_cur_upd_lock_and_undo(
 /*======================*/
@@ -2962,7 +2962,7 @@ btr_cur_del_mark_set_clust_rec(
 	ut_ad(page_is_leaf(page_align(rec)));
 
 #ifdef UNIV_DEBUG
-	if (btr_cur_print_record_ops && thr) {
+	if (btr_cur_print_record_ops) {
 		btr_cur_trx_report(thr_get_trx(thr)->id, index, "del mark ");
 		rec_print_new(stderr, rec, offsets);
 	}
@@ -3110,7 +3110,7 @@ btr_cur_del_mark_set_sec_rec(
 	rec = btr_cur_get_rec(cursor);
 
 #ifdef UNIV_DEBUG
-	if (btr_cur_print_record_ops && thr) {
+	if (btr_cur_print_record_ops) {
 		btr_cur_trx_report(thr_get_trx(thr)->id, cursor->index,
 				   "del mark ");
 		rec_print(stderr, rec, cursor->index);
diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc
index 179de79..c195cb9 100644
--- a/storage/innobase/data/data0data.cc
+++ b/storage/innobase/data/data0data.cc
@@ -67,7 +67,8 @@ dtuple_coll_cmp(
 	ulint	n_fields;
 	ulint	i;
 
-	ut_ad(tuple1 && tuple2);
+	ut_nonnulld(tuple1);
+	ut_nonnulld(tuple2);
 	ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
 	ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
 	ut_ad(dtuple_check_typed(tuple1));
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index bdd0243..bec6460 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -1064,7 +1064,8 @@ fsp_fill_free_list(
 	ulint	i;
 	mtr_t	ibuf_mtr;
 
-	ut_ad(header && mtr);
+	ut_nonnulld(header);
+	ut_nonnulld(mtr);
 	ut_ad(page_offset(header) == FSP_HEADER_OFFSET);
 
 	/* Check if we can fill free list from above the free list limit */
diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic
index 00f50b5..8204200 100644
--- a/storage/innobase/include/btr0btr.ic
+++ b/storage/innobase/include/btr0btr.ic
@@ -162,7 +162,8 @@ btr_page_get_next(
 	mtr_t*		mtr __attribute__((unused)))
 				/*!< in: mini-transaction handle */
 {
-	ut_ad(page && mtr);
+	ut_nonnulld(page);
+	ut_nonnulld(mtr);
 	ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)
 	      || mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_S_FIX));
 
@@ -181,7 +182,8 @@ btr_page_set_next(
 	ulint		next,	/*!< in: next page number */
 	mtr_t*		mtr)	/*!< in: mini-transaction handle */
 {
-	ut_ad(page && mtr);
+	ut_nonnulld(page);
+	ut_nonnulld(mtr);
 
 	if (page_zip) {
 		mach_write_to_4(page + FIL_PAGE_NEXT, next);
@@ -201,7 +203,8 @@ btr_page_get_prev(
 	const page_t*	page,	/*!< in: index page */
 	mtr_t*	mtr __attribute__((unused))) /*!< in: mini-transaction handle */
 {
-	ut_ad(page && mtr);
+	ut_nonnulld(page);
+	ut_nonnulld(mtr);
 
 	return(mach_read_from_4(page + FIL_PAGE_PREV));
 }
diff --git a/storage/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic
index 6937d55..e802adf 100644
--- a/storage/innobase/include/data0data.ic
+++ b/storage/innobase/include/data0data.ic
@@ -56,7 +56,8 @@ dfield_set_type(
 	dfield_t*	field,	/*!< in: SQL data field */
 	const dtype_t*	type)	/*!< in: pointer to data type struct */
 {
-	ut_ad(field && type);
+	ut_nonnulld(field);
+	ut_nonnulld(type);
 
 	field->type = *type;
 }
@@ -194,7 +195,8 @@ dfield_copy_data(
 	dfield_t*	field1,	/*!< out: field to copy to */
 	const dfield_t*	field2)	/*!< in: field to copy from */
 {
-	ut_ad(field1 && field2);
+	ut_nonnulld(field1);
+	ut_nonnulld(field2);
 
 	field1->data = field2->data;
 	field1->len = field2->len;
diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic
index fac54d9..fe9375a 100644
--- a/storage/innobase/include/dict0dict.ic
+++ b/storage/innobase/include/dict0dict.ic
@@ -80,7 +80,8 @@ dict_col_copy_type(
 	const dict_col_t*	col,	/*!< in: column */
 	dtype_t*		type)	/*!< out: data type */
 {
-	ut_ad(col && type);
+	ut_nonnulld(col);
+	ut_nonnulld(type);
 
 	type->mtype = col->mtype;
 	type->prtype = col->prtype;
diff --git a/storage/innobase/include/fts0ast.h b/storage/innobase/include/fts0ast.h
index b2380f7..80232d6 100644
--- a/storage/innobase/include/fts0ast.h
+++ b/storage/innobase/include/fts0ast.h
@@ -200,7 +200,7 @@ fts_ast_visit(
 						and ignored processing an
 						operator, currently we only
 						ignore FTS_IGNORE operator */
-	__attribute__((nonnull, warn_unused_result));
+	__attribute__((warn_unused_result));
 /*****************************************************************//**
 Process (nested) sub-expression, create a new result set to store the
 sub-expression result by processing nodes under current sub-expression
diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic
index a539320..4a58d0b 100644
--- a/storage/innobase/include/rem0rec.ic
+++ b/storage/innobase/include/rem0rec.ic
@@ -1540,7 +1540,8 @@ rec_copy(
 	ulint	extra_len;
 	ulint	data_len;
 
-	ut_ad(rec && buf);
+	ut_nonnulld(rec);
+	ut_nonnulld(buf);
 	ut_ad(rec_offs_validate(rec, NULL, offsets));
 	ut_ad(rec_validate(rec, offsets));
 
diff --git a/storage/innobase/include/ut0dbg.h b/storage/innobase/include/ut0dbg.h
index 6a4afe9..b71c4f7 100644
--- a/storage/innobase/include/ut0dbg.h
+++ b/storage/innobase/include/ut0dbg.h
@@ -85,11 +85,20 @@ ut_dbg_assertion_failed(
 #define ut_ad(EXPR)	ut_a(EXPR)
 /** Debug statement. Does nothing unless UNIV_DEBUG is defined. */
 #define ut_d(EXPR)	do {EXPR;} while (0)
+/** Debug assert that V is not null
+ *
+ * note: obfuscate code a bit to avoid warnings when compiler (llvm)
+ * has already detected that pointer can't be null, and emits
+ * warning about unreachable code
+ */
+#define ut_nonnulld(V)  ut_a((((ib_uint64_t)V) + 1) != 1)
 #else
 /** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */
 #define ut_ad(EXPR)
 /** Debug statement. Does nothing unless UNIV_DEBUG is defined. */
 #define ut_d(EXPR)
+/** Debug assert that V is not null. */
+#define ut_nonnulld(V)
 #endif
 
 /** Silence warnings about an unused variable by doing a null assignment.
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 91173b9..c14c7a8 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -4543,7 +4543,8 @@ lock_table(
 	dberr_t		err;
 	const lock_t*	wait_for;
 
-	ut_ad(table && thr);
+	ut_nonnulld(table);
+	ut_nonnulld(thr);
 
 	if (flags & BTR_NO_LOCKING_FLAG) {
 
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 9f0af1a..9331a98 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -4807,7 +4807,8 @@ page_zip_parse_compress(
 	ulint	size;
 	ulint	trailer_size;
 
-	ut_ad(ptr && end_ptr);
+	ut_nonnulld(ptr);
+	ut_nonnulld(end_ptr);
 	ut_ad(!page == !page_zip);
 
 	if (UNIV_UNLIKELY(ptr + (2 + 2) > end_ptr)) {
diff --git a/storage/innobase/rem/rem0cmp.cc b/storage/innobase/rem/rem0cmp.cc
index 426cf9e..fde9c31 100644
--- a/storage/innobase/rem/rem0cmp.cc
+++ b/storage/innobase/rem/rem0cmp.cc
@@ -659,7 +659,10 @@ cmp_dtuple_rec_with_match_low(
 					in current field */
 	int		ret;		/* return value */
 
-	ut_ad(dtuple && rec && matched_fields && matched_bytes);
+	ut_nonnulld(dtuple);
+	ut_nonnulld(rec);
+	ut_nonnulld(matched_fields);
+	ut_nonnulld(matched_bytes);
 	ut_ad(dtuple_check_typed(dtuple));
 	ut_ad(rec_offs_validate(rec, NULL, offsets));
 
@@ -1375,7 +1378,9 @@ cmp_debug_dtuple_rec_with_match(
 	int		ret;		/* return value */
 	ulint		cur_field;	/* current field number */
 
-	ut_ad(dtuple && rec && matched_fields);
+	ut_nonnulld(dtuple);
+	ut_nonnulld(rec);
+	ut_nonnulld(matched_fields);
 	ut_ad(dtuple_check_typed(dtuple));
 	ut_ad(rec_offs_validate(rec, NULL, offsets));
 
diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc
index 0d7b7c1..547f7e3 100644
--- a/storage/innobase/rem/rem0rec.cc
+++ b/storage/innobase/rem/rem0rec.cc
@@ -1338,7 +1338,9 @@ rec_convert_dtuple_to_rec(
 {
 	rec_t*	rec;
 
-	ut_ad(buf && index && dtuple);
+	ut_nonnulld(buf);
+	ut_nonnulld(index);
+	ut_nonnulld(dtuple);
 	ut_ad(dtuple_validate(dtuple));
 	ut_ad(dtuple_check_typed(dtuple));
 
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 05287d2..dd3406a 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1690,7 +1690,8 @@ row_update_for_mysql(
 	trx_t*		trx		= prebuilt->trx;
 	ulint		fk_depth	= 0;
 
-	ut_ad(prebuilt && trx);
+	ut_nonnulld(prebuilt);
+	ut_nonnulld(trx);
 	UT_NOT_USED(mysql_rec);
 
 	if (prebuilt->table->ibd_file_missing) {
@@ -1900,7 +1901,8 @@ row_unlock_for_mysql(
 	btr_pcur_t*	clust_pcur	= &prebuilt->clust_pcur;
 	trx_t*		trx		= prebuilt->trx;
 
-	ut_ad(prebuilt && trx);
+	ut_nonnulld(prebuilt);
+	ut_nonnulld(trx);
 
 	if (UNIV_UNLIKELY
 	    (!srv_locks_unsafe_for_binlog
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index b26ba97..2acb515 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -69,7 +69,8 @@ row_purge_node_create(
 {
 	purge_node_t*	node;
 
-	ut_ad(parent && heap);
+	ut_nonnulld(parent);
+	ut_nonnulld(heap);
 
 	node = static_cast<purge_node_t*>(
 		mem_heap_zalloc(heap, sizeof(*node)));
diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc
index be786f9..1913cfd 100644
--- a/storage/innobase/row/row0row.cc
+++ b/storage/innobase/row/row0row.cc
@@ -240,7 +240,9 @@ row_build(
 	ulint			offsets_[REC_OFFS_NORMAL_SIZE];
 	rec_offs_init(offsets_);
 
-	ut_ad(index && rec && heap);
+	ut_nonnulld(index);
+	ut_nonnulld(rec);
+	ut_nonnulld(heap);
 	ut_ad(dict_index_is_clust(index));
 	ut_ad(!mutex_own(&trx_sys->mutex));
 	ut_ad(!col_map || col_table);
@@ -409,7 +411,9 @@ row_rec_to_index_entry_low(
 	ulint		len;
 	ulint		rec_len;
 
-	ut_ad(rec && heap && index);
+	ut_nonnulld(rec);
+	ut_nonnulld(heap);
+	ut_nonnulld(index);
 	/* Because this function may be invoked by row0merge.cc
 	on a record whose header is in different format, the check
 	rec_offs_validate(rec, index, offsets) must be avoided here. */
@@ -464,7 +468,9 @@ row_rec_to_index_entry(
 	byte*		buf;
 	const rec_t*	copy_rec;
 
-	ut_ad(rec && heap && index);
+	ut_nonnulld(rec);
+	ut_nonnulld(heap);
+	ut_nonnulld(index);
 	ut_ad(rec_offs_validate(rec, index, offsets));
 
 	/* Take a copy of rec to heap */
@@ -523,7 +529,9 @@ row_build_row_ref(
 	ulint*		offsets		= offsets_;
 	rec_offs_init(offsets_);
 
-	ut_ad(index && rec && heap);
+	ut_nonnulld(index);
+	ut_nonnulld(rec);
+	ut_nonnulld(heap);
 	ut_ad(!dict_index_is_clust(index));
 
 	offsets = rec_get_offsets(rec, index, offsets,
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index 8580aa4..bcf306a 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -1135,7 +1135,8 @@ row_undo_mod(
 	dberr_t	err;
 	ibool	dict_locked;
 
-	ut_ad(node && thr);
+	ut_nonnulld(node);
+	ut_nonnulld(thr);
 	ut_ad(node->state == UNDO_NODE_MODIFY);
 
 	dict_locked = thr_get_trx(thr)->dict_operation_lock_mode == RW_X_LATCH;
diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc
index 9977a1e..48dc928 100644
--- a/storage/innobase/row/row0undo.cc
+++ b/storage/innobase/row/row0undo.cc
@@ -257,7 +257,8 @@ row_undo(
 	roll_ptr_t	roll_ptr;
 	ibool		locked_data_dict;
 
-	ut_ad(node && thr);
+	ut_nonnulld(node);
+	ut_nonnulld(thr);
 
 	trx = node->trx;
 
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index a8c2eaa..20a5a35 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -2497,7 +2497,8 @@ row_upd(
 {
 	dberr_t		err	= DB_SUCCESS;
 
-	ut_ad(node && thr);
+	ut_nonnulld(node);
+	ut_nonnulld(thr);
 
 	if (UNIV_LIKELY(node->in_mysql_interface)) {
 
diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc
index edb85a8..e5ec60d 100644
--- a/storage/innobase/trx/trx0undo.cc
+++ b/storage/innobase/trx/trx0undo.cc
@@ -443,7 +443,9 @@ trx_undo_seg_create(
 	ibool		success;
 	dberr_t		err = DB_SUCCESS;
 
-	ut_ad(mtr && id && rseg_hdr);
+	ut_nonnulld(mtr);
+	ut_nonnulld(id);
+	ut_nonnulld(rseg_hdr);
 	ut_ad(mutex_own(&(rseg->mutex)));
 
 	/*	fputs(type == TRX_UNDO_INSERT
-- 
2.8.0.rc3.226.g39d4020

