===================================================================
@@ -3240,7 +3240,16 @@ build_new_function_call (tree fn, VEC(tr
result = error_mark_node;
}
else
- result = build_over_call (cand, LOOKUP_NORMAL, complain);
+ {
+ int flags = LOOKUP_NORMAL;
+ /* If fn is template_id_expr, the call has explicit template arguments
+ (e.g. func<int>(5)), communicate this info to build_over_call
+ through FLAGS so that later we can use it to decide whether to warn
+ about peculiar null pointer conversion. */
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ flags |= LOOKUP_EXPLICIT_TMPL_ARGS;
+ result = build_over_call (cand, flags, complain);
+ }
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
@@ -4870,10 +4879,16 @@ conversion_null_warnings (tree totype, t
}
/* Issue warnings if "false" is converted to a NULL pointer */
- else if (expr == boolean_false_node && fn && POINTER_TYPE_P (t))
- warning_at (input_location, OPT_Wconversion_null,
- "converting %<false%> to pointer type for argument %P of %qD",
- argnum, fn);
+ else if (expr == boolean_false_node && POINTER_TYPE_P (t))
+ {
+ if (fn)
+ warning_at (input_location, OPT_Wconversion_null,
+ "converting %<false%> to pointer type for
argument %P of %qD",
+ argnum, fn);
+ else
+ warning_at (input_location, OPT_Wconversion_null,
+ "converting %<false%> to pointer type");
+ }
}
/* Perform the conversions in CONVS on the expression EXPR. FN and
@@ -5722,6 +5737,7 @@ build_over_call (struct z_candidate *can
{
tree type = TREE_VALUE (parm);
tree arg = VEC_index (tree, args, arg_index);
+ bool conversion_warning = true;
conv = convs[i];
@@ -5731,6 +5747,32 @@ build_over_call (struct z_candidate *can
&& !TREE_ADDRESSABLE (type))
conv = conv->u.next;
+ /* If the argument is NULL and used to (implicitly) instantiate a
+ template function (and bind one of the template arguments to
+ the type of 'long int'), we don't want to warn about passing NULL
+ to non-pointer argument.
+ For example, if we have this template function:
+
+ template<typename T> void func(T x) {}
+
+ we want to warn (with -Wconversion-null) in this case:
+
+ void foo() {
+ func<int>(NULL);
+ }
+
+ but not in this case:
+
+ void foo() {
+ func(NULL);
+ }
+ */
+ if (arg == null_node
+ && DECL_TEMPLATE_INFO (fn)
+ && cand->template_decl
+ && !(flags & LOOKUP_EXPLICIT_TMPL_ARGS))
+ conversion_warning = false;
+
/* Warn about initializer_list deduction that isn't currently in the
working draft. */
if (cxx_dialect > cxx98
@@ -5761,7 +5803,10 @@ build_over_call (struct z_candidate *can
}
}
- val = convert_like_with_context (conv, arg, fn, i-is_method, complain);
+ val = convert_like_with_context (conv, arg, fn, i-is_method,
+ conversion_warning
+ ? complain
+ : complain & (~tf_warning));
val = convert_for_arg_passing (type, val);
if (val == error_mark_node)
@@ -6501,6 +6546,12 @@ build_new_method_call (tree instance, tr
if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL)
&& resolves_to_fixed_type_p (instance, 0))
flags |= LOOKUP_NONVIRTUAL;
+ /* If this call has explicit template arguments, communicate
+ this info to build_over_call through FLAGS so that later
+ we can use it to decide whether to warn about peculiar null
+ pointer conversion. */
+ if (explicit_targs)
+ flags |= LOOKUP_EXPLICIT_TMPL_ARGS;
/* Now we know what function is being called. */
if (fn_p)
*fn_p = fn;
===================================================================
@@ -4168,6 +4168,8 @@ enum overload_flags { NO_SPECIAL = 0, DT
#define LOOKUP_COPY_PARM (LOOKUP_NO_COPY_CTOR_CONVERSION << 1)
/* We only want to consider list constructors. */
#define LOOKUP_LIST_ONLY (LOOKUP_COPY_PARM << 1)
+/* An instantiation with explicit template arguments. */
+#define LOOKUP_EXPLICIT_TMPL_ARGS (LOOKUP_LIST_ONLY << 1)
#define LOOKUP_NAMESPACES_ONLY(F) \
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
===================================================================
@@ -2,5 +2,5 @@
void x()
{
- int* p = 1==0;
+ int* p = 1==0; // { dg-warning "converting 'false' to pointer" }
}
===================================================================
@@ -44,6 +44,6 @@ int main()
k(NULL); // { dg-warning "" } converting NULL to int
g(NULL); // { dg-warning "" } converting NULL to int
h<NULL>(); // No warning: NULL bound to integer template parameter
- l(NULL); // { dg-warning "" } converting NULL to int
+ l(NULL); // No warning: NULL implicitly instantiated and bound to long
NULL && NULL; // No warning: converting NULL to bool is OK
}
===================================================================
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options "" }
+
+#include <stddef.h>
+
+void func1(int* ptr);
+
+void func2() {
+ int* t = false; // { dg-warning "converting 'false' to pointer" }
+ int* p;
+ p = false; // { dg-warning "converting 'false' to pointer" }
+ int* r = sizeof(char) / 2;
+ func1(false); // { dg-warning "converting 'false' to pointer" }
+ int i = NULL; // { dg-warning "converting to non-pointer" }
+}
===================================================================
@@ -0,0 +1,45 @@
+// { dg-do compile }
+// { dg-options "" }
+
+#include <stddef.h>
+
+class Foo {
+ public:
+ template <typename T1, typename T2>
+ static void Compare(const T1& expected, const T2& actual) { }
+
+ template <typename T1, typename T2>
+ static void Compare(const T1& expected, T2* actual) { }
+
+};
+
+template<typename T1>
+class Foo2 {
+ public:
+ Foo2(int x);
+ template<typename T2> void Bar(T2 y);
+};
+
+template<typename T3> void func(T3 x) { }
+
+typedef Foo2<int> MyFooType;
+
+void func1(long int a) {
+ MyFooType *foo2 = new MyFooType(NULL); // { dg-warning "passing NULL to" }
+ foo2->Bar(a);
+ func(NULL); // Shoud not warn
+ func<int>(NULL); // { dg-warning "passing NULL to" }
+ func<int *>(NULL);
+}
+
+int x = 1;
+
+main()
+{
+ int *p = &x;
+
+ Foo::Compare(0, *p);
+ Foo::Compare<long int, int>(NULL, p); // { dg-warning "passing NULL to" }
+ Foo::Compare(NULL, p); // should not warn
+ func1(NULL); // { dg-warning "passing NULL to" }
+}
===================================================================
@@ -44,6 +44,6 @@ int main()
k(NULL); // converting NULL to int
g(NULL); // converting NULL to int
h<NULL>(); // No warning: NULL bound to integer template parameter
- l(NULL); // converting NULL to int
+ l(NULL); // No warning: NULL implicitly instantiated and bound to long
NULL && NULL; // No warning: converting NULL to bool is OK
}