---
 include/curl/curl.h          |    7 ++--
 include/curl/typecheck-gcc.h |   73 ++++++++++++++++++++++++++++++++++++++-----
 lib/easy.c                   |    1 
 lib/multi.c                  |    1 
 lib/share.c                  |    1 
 5 files changed, 73 insertions(+), 10 deletions(-)

--- include/curl/typecheck-gcc.h.orig
+++ include/curl/typecheck-gcc.h
@@ -76,10 +76,10 @@ __extension__ ({
     if (_curl_is_postfields_option(_curl_opt) && !_curl_is_postfields(value)) \
       _curl_easy_setopt_err_postfields();                                     \
     if ((_curl_opt) == CURLOPT_HTTPPOST &&                                    \
-            !_curl_is_ptr((value), struct curl_httppost))                     \
+            !_curl_is_arr((value), struct curl_httppost))                     \
       _curl_easy_setopt_err_curl_httpost();                                   \
     if (_curl_is_slist_option(_curl_opt) &&                                   \
-            !_curl_is_ptr((value), struct curl_slist))                        \
+            !_curl_is_arr((value), struct curl_slist))                        \
       _curl_easy_setopt_err_curl_slist();                                     \
     if ((_curl_opt) == CURLOPT_SHARE && !_curl_is_ptr((value), CURLSH))       \
       _curl_easy_setopt_err_CURLSH();                                         \
@@ -87,6 +87,33 @@ __extension__ ({
   curl_easy_setopt(handle, _curl_opt, value);                                 \
 })
 
+/* wraps curl_easy_getinfo() with typechecking */
+/* FIXME: don't allow const pointers */
+#define curl_easy_getinfo(handle, info, arg)                                  \
+__extension__ ({                                                              \
+  __typeof__ (info) _curl_info = info;                                        \
+  if (__builtin_constant_p(_curl_info)) {                                     \
+    if (_curl_is_string_info(_curl_info) && !_curl_is_arr((arg), char *))     \
+      _curl_easy_getinfo_err_string();                                        \
+    if (_curl_is_long_info(_curl_info) && !_curl_is_arr((arg), long))         \
+      _curl_easy_getinfo_err_long();                                          \
+    if (_curl_is_double_info(_curl_info) && !_curl_is_arr((arg), double))     \
+      _curl_easy_getinfo_err_double();                                        \
+    if (_curl_is_slist_info(_curl_info) &&                                    \
+           !_curl_is_arr((arg), struct curl_slist *))                         \
+      _curl_easy_getinfo_err_curl_slist();                                    \
+  }                                                                           \
+  curl_easy_getinfo(handle, _curl_info, arg);                                 \
+})
+
+/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
+ * for now just make sure that the functions are called with three
+ * arguments
+ */
+#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+
+
 /* the actual warnings, triggered by calling the _curl_easy_setopt_err*
  * functions */
 
@@ -136,7 +163,16 @@ _CURL_WARNING(_curl_easy_setopt_err_curl
 _CURL_WARNING(_curl_easy_setopt_err_CURLSH,
   "curl_easy_setopt expects a CURLSH* argument for this option")
 
-/* groups of options that take the same type of argument */
+_CURL_WARNING(_curl_easy_getinfo_err_string,
+  "curl_easy_getinfo expects a pointer to char * for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_long,
+  "curl_easy_getinfo expects a pointer to long for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_double,
+  "curl_easy_getinfo expects a pointer to double for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
+  "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
+
+/* groups of curl_easy_setops options that take the same type of argument */
 
 /* To add a new option to one of the groups, just add
  *   (option) == CURLOPT_SOMETHING
@@ -230,13 +266,34 @@ _CURL_WARNING(_curl_easy_setopt_err_CURL
    (option) == CURLOPT_TELNETOPTIONS ||                                       \
    0)
 
+/* groups of curl_easy_getinfo infos that take the same type of argument */
+
+/* evaluates to true if info expects a pointer to char * argument */
+#define _curl_is_string_info(info)                                            \
+  (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
+
+/* evaluates to true if info expects a pointer to long argument */
+#define _curl_is_long_info(info)                                              \
+  (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
+
+/* evaluates to true if info expects a pointer to double argument */
+#define _curl_is_double_info(info)                                            \
+  (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
+
+/* evaluates to true if info expects a pointer to struct curl_slist * argument */
+#define _curl_is_slist_info(info)                                             \
+  (CURLINFO_SLIST < (info))
+
+
 /* typecheck helpers -- check whether given expression has requested type*/
 
-/* For pointers, you can use the _curl_is_ptr macro, otherwise define a new
- * macro. Search for __builtin_types_compatible_p in the GCC manual.  NOTE:
- * these macros MUST NOT EVALUATE their arguments! The argument is the actual
- * expression passed to the curl_easy_setopt macro. This means that you can
- * only apply the sizeof and __typeof__ operators, no == or whatsoever.
+/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
+ * otherwise define a new macro. Search for __builtin_types_compatible_p
+ * in the GCC manual.
+ * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
+ * the actual expression passed to the curl_easy_setopt macro. This
+ * means that you can only apply the sizeof and __typeof__ operators, no
+ * == or whatsoever.
  */
 
 /* XXX: should evaluate to true iff expr is a pointer */
--- lib/easy.c.orig
+++ lib/easy.c
@@ -548,6 +548,7 @@ void Curl_easy_initHandleData(struct Ses
  * curl_easy_getinfo() is an external interface that allows an app to retrieve
  * information from a performed transfer and similar.
  */
+#undef curl_easy_getinfo
 CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
 {
   va_list arg;
--- include/curl/curl.h.orig
+++ include/curl/curl.h
@@ -1798,9 +1798,12 @@ CURL_EXTERN CURLcode curl_easy_pause(CUR
 #else
 #if defined(__STDC__) && (__STDC__ >= 1) 
 /* This preprocessor magic that replaces a call with the exact same call is
-   only done to make sure application authors use exactly three arguments
-   to this function. */
+   only done to make sure application authors pass exactly three arguments
+   to these functions. */
 #define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
+#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
+#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
 #endif /* __STDC__ >= 1 */
 #endif /* gcc >= 4.3 && !__cplusplus */
 
--- lib/multi.c.orig
+++ lib/multi.c
@@ -1778,6 +1778,7 @@ static CURLMcode multi_socket(struct Cur
   return result;
 }
 
+#undef curl_multi_setopt
 CURLMcode curl_multi_setopt(CURLM *multi_handle,
                             CURLMoption option, ...)
 {
--- lib/share.c.orig
+++ lib/share.c
@@ -46,6 +46,7 @@ curl_share_init(void)
   return share;
 }
 
+#undef curl_share_setopt
 CURLSHcode
 curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
 {

