From 89401152c4451eec03fb63dad723edcaa89a2bd3 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Tue, 1 Nov 2011 23:28:19 +0000 Subject: [PATCH] re PR c++/44277 ([C++0x] Add warning to facilitate nullptr conversion.) /cp 2011-11-01 Paolo Carlini PR c++/44277 * cvt.c (cp_convert_to_pointer): Warn for zero as null pointer constant. * typeck.c (cp_truthvalue_conversion): Handle pointers and member function pointers under c_inhibit_evaluation_warnings; use nullptr_node for data member pointers. (cp_build_binary_op): Tweak, just forward to cp_convert op1, either a nullptr_node or an integer_zero_node. (build_ptrmemfunc): Use nullptr_node. * init.c (build_zero_init_1): Likewise. /c-family 2011-11-01 Paolo Carlini PR c++/44277 * c.opt: Add Wzero-as-null-pointer-constant. /gcc 2011-11-01 Paolo Carlini PR c++/44277 * doc/invoke.texi: Document -Wzero-as-null-pointer-constant. /testsuite 2011-11-01 Paolo Carlini PR c++/44277 * g++.dg/warn/Wzero-as-null-pointer-constant-1.C: New. * g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C: Likewise. From-SVN: r180750 --- gcc/ChangeLog | 5 + gcc/c-family/ChangeLog | 5 + gcc/c-family/c.opt | 4 + gcc/cp/ChangeLog | 13 ++ gcc/cp/cvt.c | 5 + gcc/cp/init.c | 2 + gcc/cp/typeck.c | 16 +- gcc/doc/invoke.texi | 6 + gcc/testsuite/ChangeLog | 6 + .../cpp0x/Wzero-as-null-pointer-constant-1.C | 161 ++++++++++++++++++ .../warn/Wzero-as-null-pointer-constant-1.C | 100 +++++++++++ 11 files changed, 320 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C create mode 100644 gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-1.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 771a4a2e6b8..9c753189413 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2011-11-01 Paolo Carlini + + PR c++/44277 + * doc/invoke.texi: Document -Wzero-as-null-pointer-constant. + 2011-11-01 Andrew Stubbs * config/arm/bpabi.h (BE8_LINK_SPEC): Recognize generic-armv7 tuning. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 028163ccefb..472ed282d5e 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2011-11-01 Paolo Carlini + + PR c++/44277 + * c.opt: Add Wzero-as-null-pointer-constant. + 2011-10-31 Jason Merrill * c.opt (-fdeduce-init-list): Off by default. diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 6d500975898..438b8b003e9 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -689,6 +689,10 @@ Wpointer-sign C ObjC Var(warn_pointer_sign) Init(-1) Warning Warn when a pointer differs in signedness in an assignment +Wzero-as-null-pointer-constant +C++ ObjC++ Var(warn_zero_as_null_pointer_constant) Warning +Warn when a literal '0' is used as null pointer + ansi C ObjC C++ ObjC++ A synonym for -std=c89 (for C) or -std=c++98 (for C++) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1b40250b421..f7328db2bd1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2011-11-01 Paolo Carlini + + PR c++/44277 + * cvt.c (cp_convert_to_pointer): Warn for zero as null pointer + constant. + * typeck.c (cp_truthvalue_conversion): Handle pointers and member + function pointers under c_inhibit_evaluation_warnings; use + nullptr_node for data member pointers. + (cp_build_binary_op): Tweak, just forward to cp_convert op1, + either a nullptr_node or an integer_zero_node. + (build_ptrmemfunc): Use nullptr_node. + * init.c (build_zero_init_1): Likewise. + 2011-11-01 Jason Merrill PR c++/50500 diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 3e618d320ad..8570e3d4502 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -198,6 +198,11 @@ cp_convert_to_pointer (tree type, tree expr) if (null_ptr_cst_p (expr)) { + if (c_inhibit_evaluation_warnings == 0 + && !NULLPTR_TYPE_P (TREE_TYPE (expr))) + warning (OPT_Wzero_as_null_pointer_constant, + "zero as null pointer constant"); + if (TYPE_PTRMEMFUNC_P (type)) return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0, /*c_cast_p=*/false, tf_warning_or_error); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 9115df3dba6..6b57eb60a65 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -176,6 +176,8 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p, items with static storage duration that are not otherwise initialized are initialized to zero. */ ; + else if (TYPE_PTR_P (type) || TYPE_PTR_TO_MEMBER_P (type)) + init = convert (type, nullptr_node); else if (SCALAR_TYPE_P (type)) init = convert (type, integer_zero_node); else if (CLASS_TYPE_P (type)) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index ec14934a823..8d70df5eb75 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4058,7 +4058,7 @@ cp_build_binary_op (location_t location, else { op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier); - op1 = cp_convert (TREE_TYPE (op0), integer_zero_node); + op1 = cp_convert (TREE_TYPE (op0), op1); } result_type = TREE_TYPE (op0); } @@ -4668,7 +4668,17 @@ cp_truthvalue_conversion (tree expr) tree type = TREE_TYPE (expr); if (TYPE_PTRMEM_P (type)) return build_binary_op (EXPR_LOCATION (expr), - NE_EXPR, expr, integer_zero_node, 1); + NE_EXPR, expr, nullptr_node, 1); + else if (TYPE_PTR_P (type) || TYPE_PTRMEMFUNC_P (type)) + { + /* With -Wzero-as-null-pointer-constant do not warn for an + 'if (p)' or a 'while (!p)', where p is a pointer. */ + tree ret; + ++c_inhibit_evaluation_warnings; + ret = c_common_truthvalue_conversion (input_location, expr); + --c_inhibit_evaluation_warnings; + return ret; + } else return c_common_truthvalue_conversion (input_location, expr); } @@ -7148,7 +7158,7 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p, /* Handle null pointer to member function conversions. */ if (null_ptr_cst_p (pfn)) { - pfn = build_c_cast (input_location, type, integer_zero_node); + pfn = build_c_cast (input_location, type, nullptr_node); return build_ptrmemfunc1 (to_type, integer_zero_node, pfn); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 2836b74cb65..b68f607912e 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -4142,6 +4142,12 @@ unsigned integers are disabled by default in C++ unless Do not warn for conversions between @code{NULL} and non-pointer types. @option{-Wconversion-null} is enabled by default. +@item -Wzero-as-null-pointer-constant @r{(C++ and Objective-C++ only)} +@opindex Wzero-as-null-pointer-constant +@opindex Wno-zero-as-null-pointer-constant +Warn when a literal '0' is used as null pointer constant. This can +be useful to facilitate the conversion to @code{nullptr} in C++11. + @item -Wempty-body @opindex Wempty-body @opindex Wno-empty-body diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a1079322db2..bdbdb8e7b19 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-11-01 Paolo Carlini + + PR c++/44277 + * g++.dg/warn/Wzero-as-null-pointer-constant-1.C: New. + * g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C: Likewise. + 2011-11-01 Tom de Vries PR tree-optimization/50908 diff --git a/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C b/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C new file mode 100644 index 00000000000..aad273792ac --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C @@ -0,0 +1,161 @@ +// { dg-options "-std=c++0x -Wzero-as-null-pointer-constant" } + +struct A; + +typedef int (A::*pointmemfun) (int); +typedef int (A::*pointdmem); +typedef int (*pointfun) (int); + +pointmemfun pmfs; +pointdmem pdms; +pointfun pfs; +int* ps; + +void f() +{ + pointmemfun pmf(0); // { dg-warning "zero as null pointer" } + pointdmem pdm(0); // { dg-warning "zero as null pointer" } + pointfun pf(0); // { dg-warning "zero as null pointer" } + int* p(0); // { dg-warning "zero as null pointer" } + + pointmemfun pmfn(nullptr); + pointdmem pdmn(nullptr); + pointfun pfn(nullptr); + int* pn(nullptr); + + pmf = 0; // { dg-warning "zero as null pointer" } + + pdm = 0; // { dg-warning "zero as null pointer" } + + pf = 0; // { dg-warning "zero as null pointer" } + + p = 0; // { dg-warning "zero as null pointer" } + + pmf = nullptr; + + pdm = nullptr; + + pf = nullptr; + + p = nullptr; + + if (pmf) + ; + + if (pdm) + ; + + if (pf) + ; + + if (p) + ; + + if (!pmf) + ; + + if (!pdm) + ; + + if (!pf) + ; + + if (!p) + ; + + if (pmf == 0) // { dg-warning "zero as null pointer" } + ; + + if (pdm == 0) // { dg-warning "zero as null pointer" } + ; + + if (pf == 0) // { dg-warning "zero as null pointer" } + ; + + if (p == 0) // { dg-warning "zero as null pointer" } + ; + + if (0 == pmf) // { dg-warning "zero as null pointer" } + ; + + if (0 == pdm) // { dg-warning "zero as null pointer" } + ; + + if (0 == pf) // { dg-warning "zero as null pointer" } + ; + + if (0 == p) // { dg-warning "zero as null pointer" } + ; + + if (pmf != 0) // { dg-warning "zero as null pointer" } + ; + + if (pdm != 0) // { dg-warning "zero as null pointer" } + ; + + if (pf != 0) // { dg-warning "zero as null pointer" } + ; + + if (p != 0) // { dg-warning "zero as null pointer" } + ; + + if (0 != pmf) // { dg-warning "zero as null pointer" } + ; + + if (0 != pdm) // { dg-warning "zero as null pointer" } + ; + + if (0 != pf) // { dg-warning "zero as null pointer" } + ; + + if (0 != p) // { dg-warning "zero as null pointer" } + ; + + if (pmf == nullptr) + ; + + if (pdm == nullptr) + ; + + if (pf == nullptr) + ; + + if (p == nullptr) + ; + + if (nullptr == pmf) + ; + + if (nullptr == pdm) + ; + + if (nullptr == pf) + ; + + if (nullptr == p) + ; + + if (pmf != nullptr) + ; + + if (pdm != nullptr) + ; + + if (pf != nullptr) + ; + + if (p != nullptr) + ; + + if (nullptr != pmf) + ; + + if (nullptr != pdm) + ; + + if (nullptr != pf) + ; + + if (nullptr != p) + ; +} diff --git a/gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-1.C b/gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-1.C new file mode 100644 index 00000000000..d0f62b212ec --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-1.C @@ -0,0 +1,100 @@ +// { dg-options "-Wzero-as-null-pointer-constant" } + +struct A; + +typedef int (A::*pointmemfun) (int); +typedef int (A::*pointdmem); +typedef int (*pointfun) (int); + +pointmemfun pmfs; +pointdmem pdms; +pointfun pfs; +int* ps; + +void f() +{ + pointmemfun pmf(0); // { dg-warning "zero as null pointer" } + pointdmem pdm(0); // { dg-warning "zero as null pointer" } + pointfun pf(0); // { dg-warning "zero as null pointer" } + int* p(0); // { dg-warning "zero as null pointer" } + + pmf = 0; // { dg-warning "zero as null pointer" } + + pdm = 0; // { dg-warning "zero as null pointer" } + + pf = 0; // { dg-warning "zero as null pointer" } + + p = 0; // { dg-warning "zero as null pointer" } + + if (pmf) + ; + + if (pdm) + ; + + if (pf) + ; + + if (p) + ; + + if (!pmf) + ; + + if (!pdm) + ; + + if (!pf) + ; + + if (!p) + ; + + if (pmf == 0) // { dg-warning "zero as null pointer" } + ; + + if (pdm == 0) // { dg-warning "zero as null pointer" } + ; + + if (pf == 0) // { dg-warning "zero as null pointer" } + ; + + if (p == 0) // { dg-warning "zero as null pointer" } + ; + + if (0 == pmf) // { dg-warning "zero as null pointer" } + ; + + if (0 == pdm) // { dg-warning "zero as null pointer" } + ; + + if (0 == pf) // { dg-warning "zero as null pointer" } + ; + + if (0 == p) // { dg-warning "zero as null pointer" } + ; + + if (pmf != 0) // { dg-warning "zero as null pointer" } + ; + + if (pdm != 0) // { dg-warning "zero as null pointer" } + ; + + if (pf != 0) // { dg-warning "zero as null pointer" } + ; + + if (p != 0) // { dg-warning "zero as null pointer" } + ; + + if (0 != pmf) // { dg-warning "zero as null pointer" } + ; + + if (0 != pdm) // { dg-warning "zero as null pointer" } + ; + + if (0 != pf) // { dg-warning "zero as null pointer" } + ; + + if (0 != p) // { dg-warning "zero as null pointer" } + ; +}