From: Diego Novillo Date: Sat, 30 Apr 2011 15:20:58 +0000 (-0400) Subject: cp-tree.h (LOOKUP_EXPLICIT_TMPL_ARGS): Define. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2e1df0f00b8625beab3858201673d470cae65687;p=gcc.git cp-tree.h (LOOKUP_EXPLICIT_TMPL_ARGS): Define. cp/ChangeLog 2011-04-29 Le-Chun Wu * 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 Le-Chun Wu * call.c (conversion_null_warnings): Also handle assignments when warning about NULL conversions. testsuite/ChangeLog 2011-04-29 Le-Chun Wu * g++.dg/warn/Wnull-conversion-1.C: New. * g++.dg/warn/Wnull-conversion-2.C: New. 2011-04-29 Le-Chun Wu * g++.dg/warn/Wconversion-null-2.C: Do not expect a NULL warning in implicitly instantiated templates. 2011-04-29 Diego Novillo * g++.old-deja/g++.other/null3.C: Expect warning about converting boolean to a pointer. From-SVN: r173217 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 55ba50bf93f..a62cce9720e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -4,6 +4,21 @@ * init.c (perform_member_init): Check build_value_init return value for error_mark_node. +2011-04-29 Diego Novillo + Le-Chun Wu + + * call.c (conversion_null_warnings): Also handle assignments + when warning about NULL conversions. + +2011-04-29 Le-Chun Wu + + * 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 , Mike Stump diff --git a/gcc/cp/call.c b/gcc/cp/call.c index dcc38595a10..b759c89ca5c 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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(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 % 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 % to pointer type for argument %P " + "of %qD", argnum, fn); + else + warning_at (input_location, OPT_Wconversion_null, + "converting % 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 void func(T x) {} + + we want to warn (when -Wconversion is enabled) in this case: + + void foo() { + func(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; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a65998d3100..40a200802dc 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a4599ca9e56..6f72b8a0f2f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -17,6 +17,21 @@ PR c++/48606 * g++.dg/init/ctor10.C: New. +2011-04-29 Le-Chun Wu + + * g++.dg/warn/Wconversion-null-2.C: Do not expect a NULL + warning in implicitly instantiated templates. + +2011-04-29 Le-Chun Wu + + * g++.dg/warn/Wnull-conversion-1.C: New. + * g++.dg/warn/Wnull-conversion-2.C: New. + +2011-04-29 Diego Novillo + + * g++.old-deja/g++.other/null3.C: Expect warning about + converting boolean to a pointer. + 2011-04-29 Paul Thomas PR fortran/48462 diff --git a/gcc/testsuite/g++.dg/warn/Wconversion-null-2.C b/gcc/testsuite/g++.dg/warn/Wconversion-null-2.C index c3050f6122b..dd498c199d9 100644 --- a/gcc/testsuite/g++.dg/warn/Wconversion-null-2.C +++ b/gcc/testsuite/g++.dg/warn/Wconversion-null-2.C @@ -44,6 +44,6 @@ int main() k(NULL); // { dg-warning "" } converting NULL to int g(NULL); // { dg-warning "" } converting NULL to int h(); // 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 index 00000000000..511f091f2cf --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-options "-Wconversion-null" } + +#include + +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 index 00000000000..92a87d1e76c --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wnull-conversion-2.C @@ -0,0 +1,45 @@ +// { dg-do compile } +// { dg-options "-Wconversion-null" } + +#include + +class Foo { + public: + template + static void Compare(const T1& expected, const T2& actual) { } + + template + static void Compare(const T1& expected, T2* actual) { } + +}; + +template +class Foo2 { + public: + Foo2(int x); + template void Bar(T2 y); +}; + +template void func(T3 x) { } + +typedef Foo2 MyFooType; + +void func1(long int a) { + MyFooType *foo2 = new MyFooType(NULL); // { dg-warning "passing NULL to" } + foo2->Bar(a); + func(NULL); + func(NULL); // { dg-warning "passing NULL to" } + func(NULL); +} + +int x = 1; + +main() +{ + int *p = &x; + + Foo::Compare(0, *p); + Foo::Compare(NULL, p); // { dg-warning "passing NULL to" } + Foo::Compare(NULL, p); + func1(NULL); // { dg-warning "passing NULL to" } +} diff --git a/gcc/testsuite/g++.old-deja/g++.other/null3.C b/gcc/testsuite/g++.old-deja/g++.other/null3.C index 6228caabd37..01071f9297b 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/null3.C +++ b/gcc/testsuite/g++.old-deja/g++.other/null3.C @@ -2,5 +2,5 @@ void x() { - int* p = 1==0; + int* p = 1==0; // { dg-warning "converting 'false' to pointer" } }