cp-tree.h (LOOKUP_EXPLICIT_TMPL_ARGS): Define.
authorDiego Novillo <dnovillo@gcc.gnu.org>
Sat, 30 Apr 2011 15:20:58 +0000 (11:20 -0400)
committerDiego Novillo <dnovillo@gcc.gnu.org>
Sat, 30 Apr 2011 15:20:58 +0000 (11:20 -0400)
cp/ChangeLog
2011-04-29  Le-Chun Wu  <lcwu@google.com>

* cp-tree.h (LOOKUP_EXPLICIT_TMPL_ARGS): Define.
* call.c (build_new_function_call): Set it for TEMPLATE_ID_EXPRs.
(build_over_call): Use it to determine whether to emit a NULL
warning for template function instantiations.
(build_new_method_call): Set LOOKUP_EXPLICIT_TMPL_ARGS if
EXPLICIT_TARGS is set.

2011-04-29  Diego Novillo  <dnovillo@google.com>
    Le-Chun Wu  <lcwu@google.com>

* call.c (conversion_null_warnings): Also handle assignments
when warning about NULL conversions.

testsuite/ChangeLog
2011-04-29  Le-Chun Wu  <lcwu@google.com>

* g++.dg/warn/Wnull-conversion-1.C: New.
* g++.dg/warn/Wnull-conversion-2.C: New.

2011-04-29  Le-Chun Wu  <lcwu@google.com>

* g++.dg/warn/Wconversion-null-2.C: Do not expect a NULL
  warning in implicitly instantiated templates.

2011-04-29  Diego Novillo  <dnovillo@google.com>

* g++.old-deja/g++.other/null3.C: Expect warning about converting
boolean to a pointer.

From-SVN: r173217

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wconversion-null-2.C
gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wnull-conversion-2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/null3.C

index 55ba50bf93f6dcd1fe1b107dd51431d5ab47a009..a62cce9720ea4e501be7f3e49866a57f6720a65a 100644 (file)
@@ -4,6 +4,21 @@
        * init.c (perform_member_init): Check build_value_init return
        value for error_mark_node.
 
+2011-04-29  Diego Novillo  <dnovillo@google.com>
+           Le-Chun Wu  <lcwu@google.com>
+
+       * call.c (conversion_null_warnings): Also handle assignments
+       when warning about NULL conversions.
+
+2011-04-29  Le-Chun Wu  <lcwu@google.com>
+
+       * cp-tree.h (LOOKUP_EXPLICIT_TMPL_ARGS): Define.
+       * call.c (build_new_function_call): Set it for TEMPLATE_ID_EXPRs.
+       (build_over_call): Use it to determine whether to emit a NULL
+       warning for template function instantiations.
+       (build_new_method_call): Set LOOKUP_EXPLICIT_TMPL_ARGS if
+       EXPLICIT_TARGS is set.
+
 2011-04-29  Nicola Pero  <nicola.pero@meta-innovation.com>,
            Mike Stump <mikestump@comcast.net>
 
index dcc38595a10f144bad161139e6f310c4f8db86f9..b759c89ca5ce5148e32264567edae0f5514f8ba1 100644 (file)
@@ -3734,7 +3734,16 @@ build_new_function_call (tree fn, VEC(tree,gc) **args, bool koenig_p,
       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);
@@ -5369,10 +5378,16 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
     }
 
   /* 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 %qT", t);
+    }
 }
 
 /* Perform the conversions in CONVS on the expression EXPR.  FN and
@@ -6293,9 +6308,36 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
     {
       tree type = TREE_VALUE (parm);
       tree arg = VEC_index (tree, args, arg_index);
+      bool conversion_warning = true;
 
       conv = convs[i];
 
+      /* 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 (when -Wconversion is enabled) 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
@@ -6326,7 +6368,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
            }
        }
 
-      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)
@@ -7061,6 +7106,8 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
              if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL)
                  && resolves_to_fixed_type_p (instance, 0))
                flags |= LOOKUP_NONVIRTUAL;
+              if (explicit_targs)
+                flags |= LOOKUP_EXPLICIT_TMPL_ARGS;
              /* Now we know what function is being called.  */
              if (fn_p)
                *fn_p = fn;
index a65998d31006beb20dede478d985fe81a53405dc..40a200802dceba534a2e4fab7418a5450b5c89c8 100644 (file)
@@ -4242,6 +4242,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
 /* Used in calls to store_init_value to suppress its usual call to
    digest_init.  */
 #define LOOKUP_ALREADY_DIGESTED (LOOKUP_DEFAULTED << 1)
+/* An instantiation with explicit template arguments.  */
+#define LOOKUP_EXPLICIT_TMPL_ARGS (LOOKUP_ALREADY_DIGESTED << 1)
 
 #define LOOKUP_NAMESPACES_ONLY(F)  \
   (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
index a4599ca9e56a70e03c6a18f04d004c27e740ca94..6f72b8a0f2f9b972fffd34d13897311b1c50cb79 100644 (file)
        PR c++/48606
        * g++.dg/init/ctor10.C: New.
 
+2011-04-29  Le-Chun Wu  <lcwu@google.com>
+
+       * g++.dg/warn/Wconversion-null-2.C: Do not expect a NULL
+         warning in implicitly instantiated templates.
+
+2011-04-29  Le-Chun Wu  <lcwu@google.com>
+
+       * g++.dg/warn/Wnull-conversion-1.C: New.
+       * g++.dg/warn/Wnull-conversion-2.C: New.
+
+2011-04-29  Diego Novillo  <dnovillo@google.com>
+
+       * g++.old-deja/g++.other/null3.C: Expect warning about
+       converting boolean to a pointer.
+
 2011-04-29  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/48462
index c3050f6122be2a87a16cd506cae08fe3febb5f0e..dd498c199d9b3495c3ee41ca3d8ba07371a40970 100644 (file)
@@ -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 is used to implicitly instantiate the template
   NULL && NULL; // No warning: converting NULL to bool is OK
 }
diff --git a/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C b/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C
new file mode 100644 (file)
index 0000000..511f091
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options "-Wconversion-null" }
+
+#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" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wnull-conversion-2.C b/gcc/testsuite/g++.dg/warn/Wnull-conversion-2.C
new file mode 100644 (file)
index 0000000..92a87d1
--- /dev/null
@@ -0,0 +1,45 @@
+// { dg-do compile }
+// { dg-options "-Wconversion-null" }
+
+#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);
+  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);
+  func1(NULL);                           // { dg-warning "passing NULL to" }
+}
index 6228caabd37cae5b0a59661d484fb01461390a53..01071f9297b107b96d3ebd3936bfc8f22c3d743e 100644 (file)
@@ -2,5 +2,5 @@
 
 void x()
 {
- int* p = 1==0;
+ int* p = 1==0;        // { dg-warning "converting 'false' to pointer" }
 }