changeset 14921:d3db2ba15d00

Removed CONTEXT_TYPE_SAFETY macro and reimplemented its functionality better. gcc/clang now gives a compiler error in many places if callback isn't exactly what was expected. It's also now much easier to add more of these checks.
author Timo Sirainen <tss@iki.fi>
date Sun, 19 Aug 2012 16:17:32 +0300
parents a097ef0a9d6d
children edb1d5babfcd
files src/anvil/anvil-connection.c src/auth/auth-request-handler.h src/auth/db-dict.c src/auth/db-ldap.c src/auth/db-sql.c src/config/config-connection.c src/doveadm/doveadm-mail-mailbox.c src/doveadm/doveadm-stats.c src/doveadm/doveadm.c src/imap/imap-fetch.h src/indexer/indexer-client.c src/lib-dns/dns-lookup.c src/lib-dns/dns-lookup.h src/lib-imap-storage/imap-msgpart.c src/lib-index/mail-index-util.c src/lib-lda/mail-send.c src/lib-mail/istream-header-filter.c src/lib-mail/istream-header-filter.h src/lib-mail/message-header-parser.h src/lib-mail/message-parser.h src/lib-mail/test-istream-header-filter.c src/lib-master/master-service.c src/lib-settings/settings.c src/lib-settings/settings.h src/lib-sql/sql-api.h src/lib-storage/index/dbox-multi/mdbox-purge.c src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c src/lib-storage/index/imapc/imapc-mail-fetch.c src/lib-storage/index/index-mail-binary.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-search.c src/lib-storage/index/index-sort-string.c src/lib-storage/index/index-thread.c src/lib-storage/index/maildir/maildir-mail.c src/lib-storage/index/maildir/maildir-storage.h src/lib-storage/index/maildir/maildir-sync-index.c src/lib-storage/index/mbox/mbox-mail.c src/lib-storage/index/pop3c/pop3c-sync.c src/lib-storage/mail-search.h src/lib-storage/mail-storage.h src/lib-storage/mailbox-header.c src/lib/array.h src/lib/bsearch-insert-pos.c src/lib/bsearch-insert-pos.h src/lib/child-wait.h src/lib/connection.c src/lib/ioloop.h src/lib/istream.h src/lib/macros.h src/lib/module-dir.c src/lib/ostream.h src/lib/strfuncs.c src/lib/strfuncs.h src/lib/test-bsearch-insert-pos.c src/plugins/acl/acl-backend.c src/plugins/fts-squat/squat-uidlist.c src/plugins/pop3-migration/pop3-migration-plugin.c
diffstat 57 files changed, 218 insertions(+), 318 deletions(-) [+]
line wrap: on
line diff
--- a/src/anvil/anvil-connection.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/anvil/anvil-connection.c	Sun Aug 19 16:17:32 2012 +0300
@@ -129,9 +129,8 @@
 	return 0;
 }
 
-static void anvil_connection_input(void *context)
+static void anvil_connection_input(struct anvil_connection *conn)
 {
-	struct anvil_connection *conn = context;
 	const char *line, *const *args, *error;
 
 	switch (i_stream_read(conn->input)) {
@@ -153,7 +152,7 @@
 			if (anvil_restarted && (conn->master || conn->fifo)) {
 				/* old pending data. ignore input until we get
 				   the handshake. */
-				anvil_connection_input(context);
+				anvil_connection_input(conn);
 				return;
 			}
 			i_error("Anvil client not compatible with this server "
--- a/src/auth/auth-request-handler.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/auth/auth-request-handler.h	Sun Aug 19 16:17:32 2012 +0300
@@ -17,18 +17,14 @@
 struct auth_request_handler *
 auth_request_handler_create(auth_request_callback_t *callback, void *context,
 			    auth_request_callback_t *master_callback);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define auth_request_handler_create(callback, context, master_callback)\
-	({(void)(1 ? 0 : callback((struct auth_stream_reply *)NULL, context)); \
+#define auth_request_handler_create(callback, context, master_callback)\
 	  auth_request_handler_create( \
-		(auth_request_callback_t *)callback, context, \
-		master_callback); })
-#else
-#  define auth_request_handler_create(callback, context, master_callback)\
-	  auth_request_handler_create( \
-		(auth_request_callback_t *)callback, context, \
+		(auth_request_callback_t *)callback, \
+		(void *)((char*)context + \
+			CALLBACK_TYPECHECK(callback, void (*)( \
+				struct auth_stream_reply *, typeof(context)))), \
 		master_callback)
-#endif
+
 void auth_request_handler_destroy(struct auth_request_handler **handler);
 void auth_request_handler_unref(struct auth_request_handler **handler);
 void auth_request_handler_abort_requests(struct auth_request_handler *handler);
--- a/src/auth/db-dict.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/auth/db-dict.c	Sun Aug 19 16:17:32 2012 +0300
@@ -81,8 +81,7 @@
 
 	conn->config_path = p_strdup(pool, config_path);
 	conn->set = default_dict_settings;
-	if (!settings_read(config_path, NULL, parse_setting,
-			   null_settings_section_callback, conn))
+	if (!settings_read_nosection(config_path, parse_setting, conn))
 		exit(FATAL_DEFAULT);
 
 	if (conn->set.uri == NULL)
--- a/src/auth/db-ldap.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/auth/db-ldap.c	Sun Aug 19 16:17:32 2012 +0300
@@ -1402,8 +1402,7 @@
 	conn->fd = -1;
 	conn->config_path = p_strdup(pool, config_path);
 	conn->set = default_ldap_settings;
-	if (!settings_read(config_path, NULL, parse_setting,
-			   null_settings_section_callback, conn))
+	if (!settings_read_nosection(config_path, parse_setting, conn))
 		exit(FATAL_DEFAULT);
 
 	if (conn->set.base == NULL)
--- a/src/auth/db-sql.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/auth/db-sql.c	Sun Aug 19 16:17:32 2012 +0300
@@ -86,8 +86,7 @@
 
 	conn->config_path = p_strdup(pool, config_path);
 	conn->set = default_sql_settings;
-	if (!settings_read(config_path, NULL, parse_setting,
-			   null_settings_section_callback, conn))
+	if (!settings_read_nosection(config_path, parse_setting, conn))
 		exit(FATAL_DEFAULT);
 
 	if (conn->set.password_query == default_sql_settings.password_query)
--- a/src/config/config-connection.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/config/config-connection.c	Sun Aug 19 16:17:32 2012 +0300
@@ -140,9 +140,8 @@
 	return 0;
 }
 
-static void config_connection_input(void *context)
+static void config_connection_input(struct config_connection *conn)
 {
-	struct config_connection *conn = context;
 	const char *const *args, *line;
 
 	switch (i_stream_read(conn->input)) {
--- a/src/doveadm/doveadm-mail-mailbox.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/doveadm/doveadm-mail-mailbox.c	Sun Aug 19 16:17:32 2012 +0300
@@ -261,10 +261,8 @@
 	return &ctx->ctx.ctx;
 }
 
-static int i_strcmp_reverse_p(const void *p1, const void *p2)
+static int i_strcmp_reverse_p(const char *const *s1, const char *const *s2)
 {
-	const char *const *s1 = p1, *const *s2 = p2;
-
 	return -strcmp(*s1, *s2);
 }
 
--- a/src/doveadm/doveadm-stats.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/doveadm/doveadm-stats.c	Sun Aug 19 16:17:32 2012 +0300
@@ -372,7 +372,7 @@
 	stats_drop_stale(ctx);
 
 	sort_ctx = ctx;
-	array_sort(&ctx->lines, ctx->lines_sort);
+	array_sort(&ctx->lines, *ctx->lines_sort);
 	sort_ctx = NULL;
 	return TRUE;
 }
--- a/src/doveadm/doveadm.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/doveadm/doveadm.c	Sun Aug 19 16:17:32 2012 +0300
@@ -55,15 +55,15 @@
 doveadm_usage_compress_lines(FILE *out, const char *str, const char *prefix)
 {
 	const char *cmd, *args, *p, *short_name, *prev_name = "";
-	char **lines;
+	const char **lines;
 	unsigned int i, count, prefix_len = strlen(prefix);
 
 	/* split lines */
-	lines = p_strsplit(pool_datastack_create(), str, "\n");
+	lines = (void *)p_strsplit(pool_datastack_create(), str, "\n");
 	for (count = 0; lines[count] != NULL; count++) ;
 
 	/* sort lines */
-	qsort(lines, count, sizeof(*lines), i_strcmp_p);
+	i_qsort(lines, count, sizeof(*lines), i_strcmp_p);
 
 	/* print lines, compress subcommands into a single line */
 	for (i = 0; i < count; i++) {
--- a/src/imap/imap-fetch.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/imap/imap-fetch.h	Sun Aug 19 16:17:32 2012 +0300
@@ -97,17 +97,12 @@
 			    const char *nil_reply,
 			    imap_fetch_handler_t *handler, void *context)
 	ATTR_NULL(3, 5);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define imap_fetch_add_handler(ctx, flags, nil_reply, handler, context) \
-	({(void)(1 ? 0 : handler((struct imap_fetch_context *)NULL, \
-				 (struct mail *)NULL, context)); \
-	  imap_fetch_add_handler(ctx, flags, nil_reply, \
-		(imap_fetch_handler_t *)handler, context); })
-#else
-#  define imap_fetch_add_handler(ctx, flags, nil_reply, handler, context) \
-	  imap_fetch_add_handler(ctx, flags, nil_reply, \
+#define imap_fetch_add_handler(ctx, flags, nil_reply, handler, context) \
+	  imap_fetch_add_handler(ctx, flags, nil_reply + \
+		CALLBACK_TYPECHECK(handler, int (*)( \
+			struct imap_fetch_context *, struct mail *, \
+			typeof(context))), \
 		(imap_fetch_handler_t *)handler, context)
-#endif
 
 int imap_fetch_att_list_parse(struct client *client, pool_t pool,
 			      const struct imap_arg *list,
--- a/src/indexer/indexer-client.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/indexer/indexer-client.c	Sun Aug 19 16:17:32 2012 +0300
@@ -147,9 +147,8 @@
 	}
 }
 
-static void indexer_client_input(void *context)
+static void indexer_client_input(struct indexer_client *client)
 {
-	struct indexer_client *client = context;
 	const char *line, *const *args, *error;
 
 	switch (i_stream_read(client->input)) {
--- a/src/lib-dns/dns-lookup.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-dns/dns-lookup.c	Sun Aug 19 16:17:32 2012 +0300
@@ -121,8 +121,8 @@
 
 #undef dns_lookup
 int dns_lookup(const char *host, const struct dns_lookup_settings *set,
-	       struct dns_lookup **lookup_r,
-	       dns_lookup_callback_t *callback, void *context)
+	       dns_lookup_callback_t *callback, void *context,
+	       struct dns_lookup **lookup_r)
 {
 	struct dns_lookup *lookup;
 	struct dns_lookup_result result;
--- a/src/lib-dns/dns-lookup.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-dns/dns-lookup.h	Sun Aug 19 16:17:32 2012 +0300
@@ -29,12 +29,13 @@
    When failing with -1, the callback is called before returning from the
    function. */
 int dns_lookup(const char *host, const struct dns_lookup_settings *set,
-	       struct dns_lookup **lookup_r,
-	       dns_lookup_callback_t *callback, void *context) ATTR_NULL(5);
+	       dns_lookup_callback_t *callback, void *context,
+	       struct dns_lookup **lookup_r) ATTR_NULL(4);
 #define dns_lookup(host, set, callback, context, lookup_r) \
-	CONTEXT_CALLBACK2(dns_lookup, dns_lookup_callback_t, \
-			  callback, const struct dns_lookup_result *, \
-			  context, host, set, lookup_r)
+	dns_lookup(host + \
+		CALLBACK_TYPECHECK(callback, void (*)( \
+			const struct dns_lookup_result *, typeof(context))), \
+		set, (dns_lookup_callback_t *)callback, context, lookup_r)
 /* Abort the DNS lookup without calling the callback. */
 void dns_lookup_abort(struct dns_lookup **lookup);
 
--- a/src/lib-imap-storage/imap-msgpart.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-imap-storage/imap-msgpart.c	Sun Aug 19 16:17:32 2012 +0300
@@ -339,14 +339,16 @@
 						      HEADER_FILTER_INCLUDE |
 						      HEADER_FILTER_HIDE_BODY,
 						      hdr_fields, hdr_count,
-						      null_header_filter_callback, NULL);
+						      *null_header_filter_callback,
+						      (void *)NULL);
 	} else {
 		i_assert(msgpart->fetch_type == FETCH_HEADER_FIELDS_NOT);
 		input = i_stream_create_header_filter(mail_input,
 						      HEADER_FILTER_EXCLUDE |
 						      HEADER_FILTER_HIDE_BODY,
 						      hdr_fields, hdr_count,
-						      null_header_filter_callback, NULL);
+						      *null_header_filter_callback,
+						      (void *)NULL);
 	}
 
 	if (message_get_header_size(input, hdr_size_r, &has_nuls) < 0) {
--- a/src/lib-index/mail-index-util.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-index/mail-index-util.c	Sun Aug 19 16:17:32 2012 +0300
@@ -103,23 +103,17 @@
 	return 0;
 }
 
-static int mail_index_seq_record_cmp(const void *key, const void *data)
+static int mail_index_seq_record_cmp(const uint32_t *key_seq,
+				     const uint32_t *data_seq)
 {
-	const uint32_t *seq_p = key;
-	const uint32_t *data_seq = data;
-
-	return *seq_p - *data_seq;
+	return *key_seq - *data_seq;
 }
 
 bool mail_index_seq_array_lookup(const ARRAY_TYPE(seq_array) *array,
 				 uint32_t seq, unsigned int *idx_r)
 {
-	const void *base;
-	unsigned int count;
-
-	base = array_get(array, &count);
-	return bsearch_insert_pos(&seq, base, count, array->arr.element_size,
-				  mail_index_seq_record_cmp, idx_r);
+	return array_bsearch_insert_pos(array, &seq,
+					mail_index_seq_record_cmp, idx_r);
 }
 
 bool mail_index_seq_array_add(ARRAY_TYPE(seq_array) *array, uint32_t seq,
--- a/src/lib-lda/mail-send.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-lda/mail-send.c	Sun Aug 19 16:17:32 2012 +0300
@@ -169,7 +169,7 @@
 	    		HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR |
 			HEADER_FILTER_HIDE_BODY, exclude_headers,
 			N_ELEMENTS(exclude_headers),
-			null_header_filter_callback, NULL);
+			*null_header_filter_callback, (void *)NULL);
 
 	    ret = o_stream_send_istream(output, input);
 	    i_stream_unref(&input);
@@ -207,7 +207,8 @@
     input = i_stream_create_header_filter(input, HEADER_FILTER_EXCLUDE |
                                           HEADER_FILTER_NO_CR, hide_headers,
                                           N_ELEMENTS(hide_headers),
-					  null_header_filter_callback, NULL);
+					  *null_header_filter_callback,
+					  (void *)NULL);
 
     (void)o_stream_send_istream(output, input);
     i_stream_unref(&input);
--- a/src/lib-mail/istream-header-filter.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-mail/istream-header-filter.c	Sun Aug 19 16:17:32 2012 +0300
@@ -202,10 +202,10 @@
 		}
 
 		matched = mstream->headers_count == 0 ? FALSE :
-			bsearch(hdr->name, mstream->headers,
-				mstream->headers_count,
-				sizeof(*mstream->headers),
-				bsearch_strcasecmp) != NULL;
+			i_bsearch(hdr->name, mstream->headers,
+				  mstream->headers_count,
+				  sizeof(*mstream->headers),
+				  bsearch_strcasecmp) != NULL;
 		if (mstream->callback == NULL) {
 			/* nothing gets excluded */
 		} else if (mstream->cur_line > mstream->parsed_lines) {
--- a/src/lib-mail/istream-header-filter.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-mail/istream-header-filter.h	Sun Aug 19 16:17:32 2012 +0300
@@ -35,20 +35,13 @@
 			      unsigned int headers_count,
 			      header_filter_callback *callback, void *context)
 	ATTR_NULL(6);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define i_stream_create_header_filter(input, flags, headers, headers_count, \
+#define i_stream_create_header_filter(input, flags, headers, headers_count, \
 				        callback, context) \
-	({(void)(1 ? 0 : callback((struct header_filter_istream *)0, \
-				  (struct message_header_line *)0, \
-				  (bool *)0, context)); \
-	  i_stream_create_header_filter(input, flags, headers, headers_count, \
-			(header_filter_callback *)callback, context); })
-#else
-#  define i_stream_create_header_filter(input, flags, headers, headers_count, \
-				        callback, context) \
-	  i_stream_create_header_filter(input, flags, headers, headers_count, \
-			(header_filter_callback *)callback, context)
-#endif
+	  i_stream_create_header_filter(input, flags, headers, headers_count + \
+		CALLBACK_TYPECHECK(callback, void (*)( \
+			struct header_filter_istream *, \
+			struct message_header_line *, bool *, typeof(context))), \
+		(header_filter_callback *)callback, context)
 
 /* Add more data to headers. Should called from the filter callback. */
 void i_stream_header_filter_add(struct header_filter_istream *input,
--- a/src/lib-mail/message-header-parser.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-mail/message-header-parser.h	Sun Aug 19 16:17:32 2012 +0300
@@ -63,15 +63,10 @@
 			  enum message_header_parser_flags flags,
 			  message_header_callback_t *callback, void *context)
 	ATTR_NULL(2);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define message_parse_header(input, hdr_size, flags, callback, context) \
-	({(void)(1 ? 0 : callback((struct message_header_line *)0, context)); \
-	  message_parse_header(input, hdr_size, flags, \
-		(message_header_callback_t *)callback, context); })
-#else
-#  define message_parse_header(input, hdr_size, flags, callback, context) \
-	  message_parse_header(input, hdr_size, flags, \
-		(message_header_callback_t *)callback, context)
-#endif
+#define message_parse_header(input, hdr_size, flags, callback, context) \
+	  message_parse_header(input, hdr_size, flags + \
+		CALLBACK_TYPECHECK(callback, void (*)( \
+			struct message_header_line *hdr, typeof(context))), \
+ 		(message_header_callback_t *)callback, context)
 
 #endif
--- a/src/lib-mail/message-parser.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-mail/message-parser.h	Sun Aug 19 16:17:32 2012 +0300
@@ -98,17 +98,12 @@
 				 struct message_size *hdr_size,
 				 message_part_header_callback_t *callback,
 				 void *context) ATTR_NULL(4);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define message_parser_parse_header(ctx, hdr_size, callback, context) \
-	({(void)(1 ? 0 : callback((struct message_part *)0, \
-				  (struct message_header_line *)0, context)); \
-	  message_parser_parse_header(ctx, hdr_size, \
-		(message_part_header_callback_t *)callback, context); })
-#else
-#  define message_parser_parse_header(ctx, hdr_size, callback, context) \
-	  message_parser_parse_header(ctx, hdr_size, \
+#define message_parser_parse_header(ctx, hdr_size, callback, context) \
+	  message_parser_parse_header(ctx, hdr_size + \
+		CALLBACK_TYPECHECK(callback, void (*)( \
+			struct message_part *, \
+			struct message_header_line *, typeof(context))), \
 		(message_part_header_callback_t *)callback, context)
-#endif
 
 /* Read and parse body. If message is a MIME multipart or message/rfc822
    message, hdr_callback is called for all headers. body_callback is called
@@ -116,16 +111,11 @@
 void message_parser_parse_body(struct message_parser_ctx *ctx,
 			       message_part_header_callback_t *hdr_callback,
 			       void *context) ATTR_NULL(3);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define message_parser_parse_body(ctx, callback, context) \
-	({(void)(1 ? 0 : callback((struct message_part *)0, \
-				  (struct message_header_line *)0, context)); \
+#define message_parser_parse_body(ctx, callback, context) \
 	  message_parser_parse_body(ctx, \
-		(message_part_header_callback_t *)callback, context); })
-#else
-#  define message_parser_parse_body(ctx, callback, context) \
-	  message_parser_parse_body(ctx, \
-		(message_part_header_callback_t *)callback, context)
-#endif
+		(message_part_header_callback_t *)callback, \
+		(void *)((char *)context + CALLBACK_TYPECHECK(callback, \
+			void (*)(struct message_part *, \
+				struct message_header_line *, typeof(context)))))
 
 #endif
--- a/src/lib-mail/test-istream-header-filter.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-mail/test-istream-header-filter.c	Sun Aug 19 16:17:32 2012 +0300
@@ -35,12 +35,13 @@
 					       HEADER_FILTER_EXCLUDE |
 					       HEADER_FILTER_NO_CR,
 					       exclude_headers, 2,
-					       filter_callback, NULL);
+					       filter_callback, (void *)NULL);
 	filter2 = i_stream_create_header_filter(filter,
 						HEADER_FILTER_EXCLUDE |
 						HEADER_FILTER_NO_CR,
 						exclude_headers, 2,
-						null_header_filter_callback, NULL);
+						*null_header_filter_callback,
+						(void *)NULL);
 	i_stream_unref(&filter);
 	filter = filter2;
 
@@ -86,7 +87,8 @@
 					       HEADER_FILTER_NO_CR |
 					       HEADER_FILTER_END_BODY_WITH_LF,
 					       empty_strarray, 0,
-					       null_header_filter_callback, NULL);
+					       *null_header_filter_callback,
+					       (void *)NULL);
 
 	for (i = 1; i < input_len; i++) {
 		test_istream_set_size(istream, i);
--- a/src/lib-master/master-service.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-master/master-service.c	Sun Aug 19 16:17:32 2012 +0300
@@ -397,10 +397,8 @@
 	}
 }
 
-static void master_status_error(void *context)
+static void master_status_error(struct master_service *service)
 {
-	struct master_service *service = context;
-
 	/* status fd is a write-only pipe, so if we're here it means the
 	   master wants us to die (or died itself). don't die until all
 	   service connections are finished. */
--- a/src/lib-settings/settings.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-settings/settings.c	Sun Aug 19 16:17:32 2012 +0300
@@ -386,10 +386,9 @@
 	return errormsg == NULL;
 }
 
-#undef settings_read
-bool settings_read(const char *path, const char *section,
-		   settings_callback_t *callback,
-		   settings_section_callback_t *sect_callback, void *context)
+bool settings_read_i(const char *path, const char *section,
+		     settings_callback_t *callback,
+		     settings_section_callback_t *sect_callback, void *context)
 {
 	bool ret;
 
--- a/src/lib-settings/settings.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-settings/settings.h	Sun Aug 19 16:17:32 2012 +0300
@@ -40,21 +40,23 @@
 parse_setting_from_defs(pool_t pool, const struct setting_def *defs, void *base,
 			const char *key, const char *value);
 
-bool settings_read(const char *path, const char *section,
-		   settings_callback_t *callback,
-		   settings_section_callback_t *sect_callback, void *context)
+bool settings_read_i(const char *path, const char *section,
+		     settings_callback_t *callback,
+		     settings_section_callback_t *sect_callback, void *context)
 	ATTR_NULL(2, 4, 5);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define settings_read(path, section, callback, sect_callback, context) \
-	({(void)(1 ? 0 : callback((const char *)0, (const char *)0, context)); \
-	  (void)(1 ? 0 : sect_callback((const char *)0, (const char *)0, \
-				       context, (const char **)0)); \
-	  settings_read(path, section, (settings_callback_t *)callback, \
-		(settings_section_callback_t *)sect_callback, context); })
-#else
-#  define settings_read(path, section, callback, sect_callback, context) \
-	  settings_read(path, section, (settings_callback_t *)callback, \
+#define settings_read(path, section, callback, sect_callback, context) \
+	  settings_read_i(path + \
+		CALLBACK_TYPECHECK(callback, const char *(*)( \
+			const char *, const char *, typeof(context))) + \
+		CALLBACK_TYPECHECK(sect_callback, bool (*)( \
+			const char *, const char *, typeof(context), \
+			const char **)), \
+		section, (settings_callback_t *)callback, \
 		(settings_section_callback_t *)sect_callback, context)
-#endif
+#define settings_read_nosection(path, callback, context) \
+	  settings_read_i(path + \
+		CALLBACK_TYPECHECK(callback, const char *(*)( \
+			const char *, const char *, typeof(context))), \
+		NULL, (settings_callback_t *)callback, NULL, context)
 
 #endif
--- a/src/lib-sql/sql-api.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-sql/sql-api.h	Sun Aug 19 16:17:32 2012 +0300
@@ -78,15 +78,11 @@
    sql_result_next_row_get() */
 void sql_query(struct sql_db *db, const char *query,
 	       sql_query_callback_t *callback, void *context);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define sql_query(db, query, callback, context) \
-	({(void)(1 ? 0 : callback((struct sql_result *)NULL, context)); \
-	  sql_query(db, query, \
-		(sql_query_callback_t *)callback, context); })
-#else
-#  define sql_query(db, query, callback, context) \
-	sql_query(db, query, (sql_query_callback_t *)callback, context)
-#endif
+#define sql_query(db, query, callback, context) \
+	sql_query(db, query + \
+		CALLBACK_TYPECHECK(callback, void (*)( \
+			struct sql_result *, typeof(context))), \
+		(sql_query_callback_t *)callback, context)
 /* Execute blocking SQL query and return result. */
 struct sql_result *sql_query_s(struct sql_db *db, const char *query);
 
@@ -131,16 +127,11 @@
 /* Commit transaction. */
 void sql_transaction_commit(struct sql_transaction_context **ctx,
 			    sql_commit_callback_t *callback, void *context);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define sql_transaction_commit(ctx, callback, context) \
-	({(void)(1 ? 0 : callback((const char *)NULL, context)); \
-	  sql_transaction_commit(ctx, \
-		(sql_commit_callback_t *)callback, context); })
-#else
-#  define sql_transaction_commit(ctx, callback, context) \
-	  sql_transaction_commit(ctx, \
+#define sql_transaction_commit(ctx, callback, context) \
+	  sql_transaction_commit(ctx + \
+		CALLBACK_TYPECHECK(callback, void (*)( \
+			const char *, typeof(context))), \
 		(sql_commit_callback_t *)callback, context)
-#endif
 /* Synchronous commit. Returns 0 if ok, -1 if error. */
 int sql_transaction_commit_s(struct sql_transaction_context **ctx,
 			     const char **error_r);
--- a/src/lib-storage/index/dbox-multi/mdbox-purge.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/dbox-multi/mdbox-purge.c	Sun Aug 19 16:17:32 2012 +0300
@@ -51,10 +51,9 @@
 	struct mdbox_map_append_context *append_ctx;
 };
 
-static int mdbox_map_file_msg_offset_cmp(const void *p1, const void *p2)
+static int mdbox_map_file_msg_offset_cmp(const struct mdbox_map_file_msg *m1,
+					 const struct mdbox_map_file_msg *m2)
 {
-	const struct mdbox_map_file_msg *m1 = p1, *m2 = p2;
-
 	if (m1->offset < m2->offset)
 		return -1;
 	else if (m1->offset > m2->offset)
--- a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c	Sun Aug 19 16:17:32 2012 +0300
@@ -92,10 +92,10 @@
 	i_free(ctx);
 }
 
-static int mdbox_rebuild_msg_offset_cmp(const void *p1, const void *p2)
+static int
+mdbox_rebuild_msg_offset_cmp(struct mdbox_rebuild_msg *const *m1,
+			     struct mdbox_rebuild_msg *const *m2)
 {
-	const struct mdbox_rebuild_msg *const *m1 = p1, *const *m2 = p2;
-
 	if ((*m1)->file_id < (*m2)->file_id)
 		return -1;
 	if ((*m1)->file_id > (*m2)->file_id)
@@ -307,17 +307,15 @@
 {
 	struct mdbox_map *map = ctx->storage->map;
 	const struct mail_index_header *hdr;
-	struct mdbox_rebuild_msg *const *msgs, **pos;
+	struct mdbox_rebuild_msg **pos;
 	struct mdbox_rebuild_msg search_msg, *search_msgp = &search_msg;
 	struct dbox_mail_lookup_rec rec;
 	uint32_t seq;
-	unsigned int count;
 
 	array_sort(&ctx->msgs, mdbox_rebuild_msg_offset_cmp);
 	/* msgs now contains a list of all messages that exists in m.* files,
 	   sorted by file_id,offset */
 
-	msgs = array_get_modifiable(&ctx->msgs, &count);
 	hdr = mail_index_get_header(ctx->atomic->sync_view);
 	for (seq = 1; seq <= hdr->messages_count; seq++) {
 		if (mdbox_map_view_lookup_rec(map, ctx->atomic->sync_view,
@@ -329,8 +327,8 @@
 		search_msg.file_id = rec.rec.file_id;
 		search_msg.offset = rec.rec.offset;
 		search_msg.size = rec.rec.size;
-		pos = bsearch(&search_msgp, msgs, count, sizeof(*msgs),
-			      mdbox_rebuild_msg_offset_cmp);
+		pos = array_bsearch(&ctx->msgs, &search_msgp,
+				    mdbox_rebuild_msg_offset_cmp);
 		if (pos == NULL || (*pos)->map_uid != 0) {
 			/* map record points to nonexistent or
 			   a duplicate message. */
--- a/src/lib-storage/index/imapc/imapc-mail-fetch.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c	Sun Aug 19 16:17:32 2012 +0300
@@ -267,7 +267,7 @@
 	filter_input = i_stream_create_header_filter(*input,
 		HEADER_FILTER_EXCLUDE,
 		imapc_hide_headers, N_ELEMENTS(imapc_hide_headers),
-		null_header_filter_callback, NULL);
+		*null_header_filter_callback, (void *)NULL);
 	i_stream_unref(input);
 	*input = filter_input;
 }
--- a/src/lib-storage/index/index-mail-binary.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/index-mail-binary.c	Sun Aug 19 16:17:32 2012 +0300
@@ -138,7 +138,7 @@
 		block->input = i_stream_create_header_filter(linput,
 				HEADER_FILTER_EXCLUDE | HEADER_FILTER_HIDE_BODY,
 				filter_headers, N_ELEMENTS(filter_headers),
-				binary_cte_filter_callback, ctx);
+				binary_cte_filter_callback, (void *)NULL);
 		i_stream_unref(&linput);
 	} else {
 		/* copy everything as-is until the end of this header */
--- a/src/lib-storage/index/index-mail.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/index-mail.c	Sun Aug 19 16:17:32 2012 +0300
@@ -839,7 +839,7 @@
 		data->parsed_bodystructure = TRUE;
 	} else {
 		message_parser_parse_body(data->parser_ctx,
-			null_message_part_header_callback, NULL);
+			*null_message_part_header_callback, (void *)NULL);
 	}
 	ret = index_mail_stream_check_failure(mail);
 	if (index_mail_parse_body_finish(mail, field) < 0)
--- a/src/lib-storage/index/index-search.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/index-search.c	Sun Aug 19 16:17:32 2012 +0300
@@ -59,8 +59,7 @@
 				     uint32_t *seq1_r, uint32_t *seq2_r);
 
 static void ATTR_NULL(2)
-search_none(struct mail_search_arg *arg ATTR_UNUSED,
-	    struct search_body_context *ctx ATTR_UNUSED)
+search_none(struct mail_search_arg *arg ATTR_UNUSED, void *ctx ATTR_UNUSED)
 {
 }
 
@@ -542,7 +541,7 @@
 }
 
 static void search_header_unmatch(struct mail_search_arg *arg,
-				  void *context ATTR_UNUSED)
+				  struct search_header_context *ctx ATTR_UNUSED)
 {
 	switch (arg->type) {
 	case SEARCH_BEFORE:
@@ -698,7 +697,7 @@
 
 	if (have_headers) {
 		/* see if the header search succeeded in finishing the search */
-		ret = mail_search_args_foreach(args, search_none, NULL);
+		ret = mail_search_args_foreach(args, search_none, (void *)NULL);
 		if (ret >= 0 || !have_body)
 			return ret;
 	}
--- a/src/lib-storage/index/index-sort-string.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/index-sort-string.c	Sun Aug 19 16:17:32 2012 +0300
@@ -91,10 +91,9 @@
 	i_array_init(&ctx->nonzero_nodes, 128);
 }
 
-static int sort_node_seq_cmp(const void *p1, const void *p2)
+static int sort_node_seq_cmp(const struct mail_sort_node *n1,
+			     const struct mail_sort_node *n2)
 {
-	const struct mail_sort_node *n1 = p1, *n2 = p2;
-
 	if (n1->seq < n2->seq)
 		return -1;
 	if (n1->seq > n2->seq)
--- a/src/lib-storage/index/index-thread.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/index-thread.c	Sun Aug 19 16:17:32 2012 +0300
@@ -352,11 +352,9 @@
 	return ret;
 }
 
-static int msgid_map_cmp(const void *key, const void *value)
+static int msgid_map_cmp(const uint32_t *uid,
+			 const struct mail_index_strmap_rec *rec)
 {
-	const uint32_t *uid = key;
-	const struct mail_index_strmap_rec *rec = value;
-
 	return *uid < rec->uid ? -1 :
 		(*uid > rec->uid ? 1 : 0);
 }
--- a/src/lib-storage/index/maildir/maildir-mail.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/maildir/maildir-mail.c	Sun Aug 19 16:17:32 2012 +0300
@@ -628,8 +628,7 @@
 }
 
 static int
-do_fix_size(struct maildir_mailbox *mbox, const char *path,
-	    const char *wrong_key_p)
+do_fix_size(struct maildir_mailbox *mbox, const char *path, char *wrong_key_p)
 {
 	const char *fname, *newpath, *extra, *info, *dir;
 	struct stat st;
--- a/src/lib-storage/index/maildir/maildir-storage.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Sun Aug 19 16:17:32 2012 +0300
@@ -101,16 +101,11 @@
 
 int maildir_file_do(struct maildir_mailbox *mbox, uint32_t uid,
 		    maildir_file_do_func *callback, void *context);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define maildir_file_do(mbox, seq, callback, context) \
-	({(void)(1 ? 0 : callback((struct maildir_mailbox *)NULL, \
-				  (const char *)NULL, context)); \
-	  maildir_file_do(mbox, seq, \
-		(maildir_file_do_func *)callback, context); })
-#else
-#  define maildir_file_do(mbox, seq, callback, context) \
-	maildir_file_do(mbox, seq, (maildir_file_do_func *)callback, context)
-#endif
+#define maildir_file_do(mbox, seq, callback, context) \
+	maildir_file_do(mbox, seq + \
+		CALLBACK_TYPECHECK(callback, int (*)( \
+			struct maildir_mailbox *, const char *, typeof(context))), \
+		(maildir_file_do_func *)callback, context)
 
 bool maildir_set_deleted(struct mailbox *box);
 uint32_t maildir_get_uidvalidity_next(struct mailbox_list *list);
--- a/src/lib-storage/index/maildir/maildir-sync-index.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c	Sun Aug 19 16:17:32 2012 +0300
@@ -356,10 +356,8 @@
 	(void)maildir_sync_index_finish(ctx, FALSE);
 }
 
-static int uint_cmp(const void *p1, const void *p2)
+static int uint_cmp(const unsigned int *i1, const unsigned int *i2)
 {
-	const unsigned int *i1 = p1, *i2 = p2;
-
 	if (*i1 < *i2)
 		return -1;
 	else if (*i1 > *i2)
--- a/src/lib-storage/index/mbox/mbox-mail.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/mbox/mbox-mail.c	Sun Aug 19 16:17:32 2012 +0300
@@ -359,7 +359,7 @@
 		i_stream_create_header_filter(raw_stream,
 				HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR,
 				mbox_hide_headers, mbox_hide_headers_count,
-				null_header_filter_callback, NULL);
+				*null_header_filter_callback, (void *)NULL);
 	i_stream_unref(&raw_stream);
 	return 0;
 }
--- a/src/lib-storage/index/pop3c/pop3c-sync.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/index/pop3c/pop3c-sync.c	Sun Aug 19 16:17:32 2012 +0300
@@ -189,10 +189,8 @@
 		index_mailbox_set_recent_seq(&mbox->box, sync_view, seq1, seq2);
 }
 
-static int uint32_cmp(const void *p1, const void *p2)
+static int uint32_cmp(const uint32_t *u1, const uint32_t *u2)
 {
-	const uint32_t *u1 = p1, *u2 = p2;
-
 	return *u1 < *u2 ? -1 :
 		(*u1 > *u2 ? 1 : 0);
 }
--- a/src/lib-storage/mail-search.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/mail-search.h	Sun Aug 19 16:17:32 2012 +0300
@@ -151,16 +151,11 @@
 int mail_search_args_foreach(struct mail_search_arg *args,
 			     mail_search_foreach_callback_t *callback,
 			     void *context) ATTR_NULL(3);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define mail_search_args_foreach(args, callback, context) \
-	({(void)(1 ? 0 : callback((struct mail_search_arg *)NULL, context)); \
-	  mail_search_args_foreach(args, \
-		(mail_search_foreach_callback_t *)callback, context); })
-#else
-#  define mail_search_args_foreach(args, callback, context) \
-	  mail_search_args_foreach(args, \
+#define mail_search_args_foreach(args, callback, context) \
+	  mail_search_args_foreach(args + \
+		CALLBACK_TYPECHECK(callback, void (*)( \
+			struct mail_search_arg *, typeof(context))), \
 		(mail_search_foreach_callback_t *)callback, context)
-#endif
 
 /* Fills have_headers and have_body based on if such search argument exists
    that needs to be checked. Returns the headers that we're searching for, or
--- a/src/lib-storage/mail-storage.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/mail-storage.h	Sun Aug 19 16:17:32 2012 +0300
@@ -502,16 +502,10 @@
 void mailbox_notify_changes(struct mailbox *box,
 			    mailbox_notify_callback_t *callback, void *context)
 	ATTR_NULL(3);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define mailbox_notify_changes(box, callback, context) \
-	({(void)(1 ? 0 : callback((struct mailbox *)NULL, context)); \
-	  mailbox_notify_changes(box, \
-		(mailbox_notify_callback_t *)callback, context); })
-#else
-#  define mailbox_notify_changes(box, callback, context) \
-	  mailbox_notify_changes(box, \
-		(mailbox_notify_callback_t *)callback, context)
-#endif
+#define mailbox_notify_changes(box, callback, context) \
+	  mailbox_notify_changes(box, (mailbox_notify_callback_t *)callback, \
+		(void *)((char *)context + CALLBACK_TYPECHECK(callback, \
+			void (*)(struct mailbox *, typeof(context)))))
 void mailbox_notify_changes_stop(struct mailbox *box);
 
 struct mailbox_transaction_context *
--- a/src/lib-storage/mailbox-header.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib-storage/mailbox-header.c	Sun Aug 19 16:17:32 2012 +0300
@@ -28,7 +28,7 @@
 	/* @UNSAFE: headers need to be sorted for filter stream. */
 	sorted_headers = t_new(const char *, count);
 	memcpy(sorted_headers, headers, count * sizeof(*sorted_headers));
-	qsort(sorted_headers, count, sizeof(*sorted_headers), i_strcasecmp_p);
+	i_qsort(sorted_headers, count, sizeof(*sorted_headers), i_strcasecmp_p);
 	headers = sorted_headers;
 
 	/* @UNSAFE */
--- a/src/lib/array.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/array.h	Sun Aug 19 16:17:32 2012 +0300
@@ -264,29 +264,18 @@
 	array_reverse_i(&(array)->arr)
 
 void array_sort_i(struct array *array, int (*cmp)(const void *, const void *));
-#ifdef CONTEXT_TYPE_SAFETY
 #define array_sort(array, cmp) \
-	({(void)(1 ? 0 : cmp(ARRAY_TYPE_CAST_CONST(array)NULL, \
-			     ARRAY_TYPE_CAST_CONST(array)NULL)); \
-	array_sort_i(&(array)->arr, \
-		(int (*)(const void *, const void *))cmp); })
-#else
-#define array_sort(array, cmp) \
-	array_sort_i(&(array)->arr, (int (*)(const void *, const void *))cmp)
-#endif
+	array_sort_i(&(array)->arr + \
+		CALLBACK_TYPECHECK(cmp, int (*)(typeof(*(array)->v), \
+						typeof(*(array)->v))), \
+		(int (*)(const void *, const void *))cmp)
 
 void *array_bsearch_i(struct array *array, const void *key,
 		      int (*cmp)(const void *, const void *));
-#ifdef CONTEXT_TYPE_SAFETY
 #define array_bsearch(array, key, cmp) \
-	ARRAY_TYPE_CAST_MODIFIABLE(array) \
-	({(void)(1 ? 0 : cmp(key, ARRAY_TYPE_CAST_CONST(array)NULL)); \
-	array_bsearch_i(&(array)->arr, (const void *)key, \
-		(int (*)(const void *, const void *))cmp); })
-#else
-#define array_bsearch(array, key, cmp) \
-	array_bsearch_i(&(array)->arr, (const void *)key, \
-		(int (*)(const void *, const void *))cmp)
-#endif
+	ARRAY_TYPE_CAST_MODIFIABLE(array)array_bsearch_i(&(array)->arr + \
+		CALLBACK_TYPECHECK(cmp, int (*)(typeof(const typeof(*key) *), \
+						typeof(*(array)->v))), \
+		(const void *)key, (int (*)(const void *, const void *))cmp)
 
 #endif
--- a/src/lib/bsearch-insert-pos.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/bsearch-insert-pos.c	Sun Aug 19 16:17:32 2012 +0300
@@ -4,6 +4,7 @@
 #include "array.h"
 #include "bsearch-insert-pos.h"
 
+#undef bsearch_insert_pos
 bool bsearch_insert_pos(const void *key, const void *base, unsigned int nmemb,
 			size_t size, int (*cmp)(const void *, const void *),
 			unsigned int *idx_r)
--- a/src/lib/bsearch-insert-pos.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/bsearch-insert-pos.h	Sun Aug 19 16:17:32 2012 +0300
@@ -25,22 +25,22 @@
    where the key should be inserted. */
 bool ATTR_NOWARN_UNUSED_RESULT
 bsearch_insert_pos(const void *key, const void *base, unsigned int nmemb,
-			size_t size, int (*cmp)(const void *, const void *),
-			unsigned int *idx_r);
+		   size_t size, int (*cmp)(const void *, const void *),
+		   unsigned int *idx_r);
+#define bsearch_insert_pos(key, base, nmemb, size, cmp, idx_r) \
+	bsearch_insert_pos(key, base, nmemb, size + \
+		CALLBACK_TYPECHECK(cmp, int (*)(typeof(const typeof(*key) *), \
+						typeof(const typeof(*base) *))), \
+		(int (*)(const void *, const void *))cmp, idx_r)
 
 bool ATTR_NOWARN_UNUSED_RESULT
 array_bsearch_insert_pos_i(const struct array *array, const void *key,
 			   int (*cmp)(const void *, const void *),
 			   unsigned int *idx_r);
-#ifdef CONTEXT_TYPE_SAFETY
 #define array_bsearch_insert_pos(array, key, cmp, idx_r) \
-	({(void)(1 ? 0 : cmp(key, ARRAY_TYPE_CAST_CONST(array)NULL)); \
-	array_bsearch_insert_pos_i(&(array)->arr, (const void *)key, \
-		(int (*)(const void *, const void *))cmp, idx_r); })
-#else
-#define array_bsearch_insert_pos(array, key, cmp, idx_r) \
-	array_bsearch_insert_pos_i(&(array)->arr, (const void *)key, \
-		(int (*)(const void *, const void *))cmp, idx_r)
-#endif
+	array_bsearch_insert_pos_i(&(array)->arr + \
+		CALLBACK_TYPECHECK(cmp, int (*)(typeof(const typeof(*key) *), \
+						typeof(*(array)->v))), \
+		(const void *)key, (int (*)(const void *, const void *))cmp, idx_r)
 
 #endif
--- a/src/lib/child-wait.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/child-wait.h	Sun Aug 19 16:17:32 2012 +0300
@@ -14,15 +14,11 @@
 struct child_wait *
 child_wait_new_with_pid(pid_t pid, child_wait_callback_t *callback,
 			void *context) ATTR_NULL(3);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define child_wait_new_with_pid(pid, callback, context) \
-	({(void)(1 ? 0 : callback((const struct child_wait_status *)0, \
-				  context)); \
-	  child_wait_new_with_pid(pid, (child_wait_callback_t *)callback, context); })
-#else
-#  define child_wait_new_with_pid(pid, callback, context) \
-	  child_wait_new_with_pid(pid, (child_wait_callback_t *)callback, context)
-#endif
+#define child_wait_new_with_pid(pid, callback, context) \
+	child_wait_new_with_pid(pid + \
+		CALLBACK_TYPECHECK(callback, void (*)( \
+			const struct child_wait_status *status, typeof(context))), \
+	(child_wait_callback_t *)callback, context)
 #define child_wait_new(callback, context) \
 	child_wait_new_with_pid((pid_t)-1, callback, context)
 void child_wait_free(struct child_wait **wait);
--- a/src/lib/connection.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/connection.c	Sun Aug 19 16:17:32 2012 +0300
@@ -122,7 +122,7 @@
 						  set->output_max_size, FALSE);
 		o_stream_set_no_error_handling(conn->output, TRUE);
 	}
-	conn->io = io_add(conn->fd_in, IO_READ, conn->list->v.input, conn);
+	conn->io = io_add(conn->fd_in, IO_READ, *conn->list->v.input, conn);
 	if (set->input_idle_timeout_secs != 0) {
 		conn->to = timeout_add(set->input_idle_timeout_secs*1000,
 				       connection_idle_timeout, conn);
--- a/src/lib/ioloop.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/ioloop.h	Sun Aug 19 16:17:32 2012 +0300
@@ -49,19 +49,16 @@
 		  unsigned int source_linenum,
 		  io_callback_t *callback, void *context) ATTR_NULL(5);
 #define io_add(fd, condition, callback, context) \
-	CONTEXT_CALLBACK(io_add, io_callback_t, \
-			 callback, context, fd, condition, __LINE__)
+	io_add(fd, condition, __LINE__ + \
+		CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
+		(io_callback_t *)callback, context)
 enum io_notify_result
 io_add_notify(const char *path, io_callback_t *callback,
 	      void *context, struct io **io_r) ATTR_NULL(3);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define io_add_notify(path, callback, context, io_r) \
-	({(void)(1 ? 0 : callback(context)); \
-	io_add_notify(path, (io_callback_t *)callback, context, io_r); })
-#else
-#  define io_add_notify(path, callback, context, io_r) \
-	io_add_notify(path, (io_callback_t *)callback, context, io_r)
-#endif
+#define io_add_notify(path, callback, context, io_r) \
+	io_add_notify(path + \
+		CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
+		(io_callback_t *)callback, context, io_r)
 
 /* Remove I/O handler, and set io pointer to NULL. */
 void io_remove(struct io **io);
@@ -74,15 +71,18 @@
 timeout_add(unsigned int msecs, unsigned int source_linenum,
 	    timeout_callback_t *callback, void *context) ATTR_NULL(4);
 #define timeout_add(msecs, callback, context) \
-	CONTEXT_CALLBACK(timeout_add, timeout_callback_t, \
-			 callback, context, msecs, __LINE__), \
-	(void)COMPILE_ERROR_IF_TRUE(__builtin_constant_p(msecs) && (msecs > 0 && msecs < 1000))
+	timeout_add(msecs, __LINE__ + \
+		CALLBACK_TYPECHECK(callback, void (*)(typeof(context))) + \
+		COMPILE_ERROR_IF_TRUE(__builtin_constant_p(msecs) && \
+				      (msecs > 0 && msecs < 1000)), \
+		(io_callback_t *)callback, context)
 struct timeout *
 timeout_add_short(unsigned int msecs, unsigned int source_linenum,
 		  timeout_callback_t *callback, void *context) ATTR_NULL(4);
 #define timeout_add_short(msecs, callback, context) \
-	CONTEXT_CALLBACK(timeout_add_short, timeout_callback_t, \
-			 callback, context, msecs, __LINE__)
+	timeout_add_short(msecs, __LINE__ + \
+		CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
+		(io_callback_t *)callback, context)
 /* Remove timeout handler, and set timeout pointer to NULL. */
 void timeout_remove(struct timeout **timeout);
 /* Reset timeout so it's next run after now+msecs. */
--- a/src/lib/istream.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/istream.h	Sun Aug 19 16:17:32 2012 +0300
@@ -53,8 +53,9 @@
 				   istream_callback_t *callback, void *context)
 	ATTR_NULL(3);
 #define i_stream_set_destroy_callback(stream, callback, context) \
-	CONTEXT_CALLBACK(i_stream_set_destroy_callback, istream_callback_t, \
-			 callback, context, stream)
+	i_stream_set_destroy_callback(stream + \
+		CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
+		(istream_callback_t *)callback, context)
 /* Remove the destroy callback. */
 void i_stream_unset_destroy_callback(struct istream *stream);
 
--- a/src/lib/macros.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/macros.h	Sun Aug 19 16:17:32 2012 +0300
@@ -143,20 +143,11 @@
 
 /* Macros to provide type safety for callback functions' context parameters */
 #ifdef __GNUC__
-#  define CONTEXT_TYPE_SAFETY
-#endif
-#ifdef CONTEXT_TYPE_SAFETY
-#  define CONTEXT_CALLBACK(name, callback_type, callback, context, ...) \
-	({(void)(1 ? 0 : callback(context)); \
-	name(__VA_ARGS__, (callback_type *)callback, context); })
-#  define CONTEXT_CALLBACK2(name, callback_type, callback, arg1_type, context, ...) \
-	({(void)(1 ? 0 : callback((arg1_type)0, context)); \
-	name(__VA_ARGS__, (callback_type *)callback, context); })
+#  define CALLBACK_TYPECHECK(callback, type) \
+	(COMPILE_ERROR_IF_TRUE(!__builtin_types_compatible_p( \
+		typeof(&callback), type)) ? 1 : 0)
 #else
-#  define CONTEXT_CALLBACK(name, callback_type, callback, context, ...) \
-	name(__VA_ARGS__, (callback_type *)callback, context)
-#  define CONTEXT_CALLBACK2(name, callback_type, callback, arg1_type, context, ...) \
-	name(__VA_ARGS__, (callback_type *)callback, context)
+#  define CALLBACK_TYPECHECK(callback, type) 0
 #endif
 
 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)) && !defined(__cplusplus)
--- a/src/lib/module-dir.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/module-dir.c	Sun Aug 19 16:17:32 2012 +0300
@@ -327,7 +327,7 @@
 		module_names[i] = module_file_get_name(module_names[i]);
 
 	/* @UNSAFE: drop duplicates */
-	qsort(module_names, i, sizeof(*module_names), i_strcmp_p);
+	i_qsort(module_names, i, sizeof(*module_names), i_strcmp_p);
 	for (i = j = 1; module_names[i] != NULL; i++) {
 		if (strcmp(module_names[i-1], module_names[i]) != 0)
 			module_names[j++] = module_names[i];
--- a/src/lib/ostream.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/ostream.h	Sun Aug 19 16:17:32 2012 +0300
@@ -62,8 +62,9 @@
 				 stream_flush_callback_t *callback,
 				 void *context) ATTR_NULL(3);
 #define o_stream_set_flush_callback(stream, callback, context) \
-	CONTEXT_CALLBACK(o_stream_set_flush_callback, stream_flush_callback_t, \
-			 callback, context, stream)
+	o_stream_set_flush_callback(stream + \
+		CALLBACK_TYPECHECK(callback, int (*)(typeof(context))), \
+		(stream_flush_callback_t *)callback, context)
 void o_stream_unset_flush_callback(struct ostream *stream);
 /* Change the maximum size for stream's output buffer to grow. */
 void o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size);
--- a/src/lib/strfuncs.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/strfuncs.c	Sun Aug 19 16:17:32 2012 +0300
@@ -354,33 +354,23 @@
         return 0;
 }
 
-int bsearch_strcmp(const void *p1, const void *p2)
+int bsearch_strcmp(const char *key, const char *const *member)
 {
-	const char *key = p1;
-	const char *const *member = p2;
-
 	return strcmp(key, *member);
 }
 
-int i_strcmp_p(const void *p1, const void *p2)
+int i_strcmp_p(const char *const *s1, const char *const *s2)
 {
-	const char *const *s1 = p1, *const *s2 = p2;
-
 	return strcmp(*s1, *s2);
 }
 
-int bsearch_strcasecmp(const void *p1, const void *p2)
+int bsearch_strcasecmp(const char *key, const char *const *member)
 {
-	const char *key = p1;
-	const char *const *member = p2;
-
 	return strcasecmp(key, *member);
 }
 
-int i_strcasecmp_p(const void *p1, const void *p2)
+int i_strcasecmp_p(const char *const *s1, const char *const *s2)
 {
-	const char *const *s1 = p1, *const *s2 = p2;
-
 	return strcasecmp(*s1, *s2);
 }
 
--- a/src/lib/strfuncs.h	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/strfuncs.h	Sun Aug 19 16:17:32 2012 +0300
@@ -50,11 +50,11 @@
 const char *t_str_ucase(const char *str);
 
 int null_strcmp(const char *s1, const char *s2) ATTR_PURE;
-int bsearch_strcmp(const void *p1, const void *p2) ATTR_PURE;
-int bsearch_strcasecmp(const void *p1, const void *p2) ATTR_PURE;
+int bsearch_strcmp(const char *p1, const char *const *member) ATTR_PURE;
+int bsearch_strcasecmp(const char *key, const char *const *member) ATTR_PURE;
 int i_memcasecmp(const void *p1, const void *p2, size_t size) ATTR_PURE;
-int i_strcmp_p(const void *p1, const void *p2) ATTR_PURE;
-int i_strcasecmp_p(const void *p1, const void *p2) ATTR_PURE;
+int i_strcmp_p(const char *const *p1, const char *const *p2) ATTR_PURE;
+int i_strcasecmp_p(const char *const *p1, const char *const *p2) ATTR_PURE;
 
 /* separators is an array of separator characters, not a separator string. */
 char **p_strsplit(pool_t pool, const char *data, const char *separators)
@@ -88,6 +88,18 @@
    return value. */
 const char **p_strarray_dup(pool_t pool, const char *const *arr);
 
+#define i_qsort(base, nmemb, size, cmp) \
+	qsort(base, nmemb, size + \
+		CALLBACK_TYPECHECK(cmp, int (*)(typeof(const typeof(*base) *), \
+						typeof(const typeof(*base) *))), \
+		(int (*)(const void *, const void *))cmp)
+#define i_bsearch(key, base, nmemb, size, cmp) \
+	bsearch(key, base, nmemb, size + \
+		CALLBACK_TYPECHECK(cmp, int (*)(typeof(const typeof(*key) *), \
+						typeof(const typeof(*base) *))), \
+		(int (*)(const void *, const void *))cmp)
+
+
 /* INTERNAL */
 char *t_noalloc_strdup_vprintf(const char *format, va_list args,
 			       unsigned int *size_r) ATTR_FORMAT(1, 0);
--- a/src/lib/test-bsearch-insert-pos.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/lib/test-bsearch-insert-pos.c	Sun Aug 19 16:17:32 2012 +0300
@@ -3,10 +3,8 @@
 #include "test-lib.h"
 #include "bsearch-insert-pos.h"
 
-static int cmp_uint(const void *p1, const void *p2)
+static int cmp_uint(const unsigned int *i1, const unsigned int *i2)
 {
-	const unsigned int *i1 = p1, *i2 = p2;
-
 	return *i1 - *i2;
 }
 
--- a/src/plugins/acl/acl-backend.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/plugins/acl/acl-backend.c	Sun Aug 19 16:17:32 2012 +0300
@@ -67,8 +67,8 @@
 			p_new(backend->pool, const char *, group_count);
 		for (i = 0; i < group_count; i++)
 			backend->groups[i] = p_strdup(backend->pool, groups[i]);
-		qsort(backend->groups, group_count, sizeof(const char *),
-		      i_strcmp_p);
+		i_qsort(backend->groups, group_count, sizeof(const char *),
+			i_strcmp_p);
 	}
 
 	T_BEGIN {
@@ -127,8 +127,8 @@
 bool acl_backend_user_is_in_group(struct acl_backend *backend,
 				  const char *group_name)
 {
-	return bsearch(group_name, backend->groups, backend->group_count,
-		       sizeof(const char *), bsearch_strcmp) != NULL;
+	return i_bsearch(group_name, backend->groups, backend->group_count,
+			 sizeof(const char *), bsearch_strcmp) != NULL;
 }
 
 bool acl_backend_rights_match_me(struct acl_backend *backend,
--- a/src/plugins/fts-squat/squat-uidlist.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/plugins/fts-squat/squat-uidlist.c	Sun Aug 19 16:17:32 2012 +0300
@@ -1385,11 +1385,9 @@
 	return 0;
 }
 
-static int uint32_cmp(const void *key, const void *data)
+static int uint32_cmp(const uint32_t *key, const uint32_t *data)
 {
-	const uint32_t *i1 = key, *i2 = data;
-
-	return (int)*i1 - (int)*i2;
+	return (int)*key - (int)*data;
 }
 
 static int
--- a/src/plugins/pop3-migration/pop3-migration-plugin.c	Sun Aug 19 14:21:37 2012 +0300
+++ b/src/plugins/pop3-migration/pop3-migration-plugin.c	Sun Aug 19 16:17:32 2012 +0300
@@ -130,7 +130,7 @@
 				HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR,
 				hdr_hash_skip_headers,
 				N_ELEMENTS(hdr_hash_skip_headers),
-				null_header_filter_callback, NULL);
+				*null_header_filter_callback, (void *)NULL);
 	i_stream_unref(&input2);
 
 	sha1_init(&sha1_ctx);