The fix for 65168 didn't check c_inhibit_evaluation_warnings, which means getting warnings about comparing the address of a reference to NULL in places where we aren't actually interested in the value. This patch corrects that, but this lead to some regressions because cp_truthvalue_conversion was inappropriately setting that flag to avoid -Wzero-as-null-pointer-constant warnings. So now we avoid those warnings by comparing to nullptr rather than 0.
Tested x86_64-cp-linux-gnu, applying to trunk.
commit e274607c02db6d92af948b670cb90d4af452aa77 Author: Jason Merrill <ja...@redhat.com> Date: Wed Jul 20 12:03:48 2016 -0400 PR c++/65168 - -Waddress in unevaluated context. gcc/c-family/ * c-common.c (c_common_truthvalue_conversion): Check c_inhibit_evaluation_warnings for warning about address of reference. gcc/cp/ * typeck.c (cp_truthvalue_conversion): Compare pointers to nullptr. Don't set c_inhibit_evaluation_warnings. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 936ddfb..9900e93 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -4551,6 +4551,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) tree fromtype = TREE_TYPE (TREE_OPERAND (expr, 0)); if (POINTER_TYPE_P (totype) + && !c_inhibit_evaluation_warnings && TREE_CODE (fromtype) == REFERENCE_TYPE) { tree inner = expr; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index f9e45ee..d4bfb11 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5459,21 +5459,10 @@ tree cp_truthvalue_conversion (tree expr) { tree type = TREE_TYPE (expr); - if (TYPE_PTRDATAMEM_P (type) + if (TYPE_PTR_OR_PTRMEM_P (type) /* Avoid ICE on invalid use of non-static member function. */ || TREE_CODE (expr) == FUNCTION_DECL) - return build_binary_op (EXPR_LOCATION (expr), - 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; - } + return build_binary_op (input_location, NE_EXPR, expr, nullptr_node, 1); else return c_common_truthvalue_conversion (input_location, expr); } diff --git a/gcc/testsuite/g++.dg/warn/Waddress-3.C b/gcc/testsuite/g++.dg/warn/Waddress-3.C new file mode 100644 index 0000000..13d7cd2 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Waddress-3.C @@ -0,0 +1,14 @@ +// PR c++/65168 +// { dg-do compile { target c++11 } } +// { dg-options -Waddress } +// We shouldn't warn in unevaluated context about the address of a reference +// always being true. + +template <class T, class U> +auto f(U&& u) -> decltype(T(u)) { } + +int main() +{ + bool ar[4]; + f<bool>(ar); +} diff --git a/gcc/testsuite/g++.dg/warn/Walways-true-1.C b/gcc/testsuite/g++.dg/warn/Walways-true-1.C index ae6f9dc..48b9f72 100644 --- a/gcc/testsuite/g++.dg/warn/Walways-true-1.C +++ b/gcc/testsuite/g++.dg/warn/Walways-true-1.C @@ -12,19 +12,19 @@ void bar (int a) { lab: - if (foo) // { dg-warning "always evaluate as" "correct warning" } + if (foo) // { dg-warning "always evaluate as|never be NULL" "correct warning" } foo (0); if (foo (1)) ; - if (&i) // { dg-warning "always evaluate as" "correct warning" } + if (&i) // { dg-warning "always evaluate as|never be NULL" "correct warning" } foo (2); if (i) foo (3); - if (&a) // { dg-warning "always evaluate as" "correct warning" } + if (&a) // { dg-warning "always evaluate as|never be NULL" "correct warning" } foo (4); if (a) foo (5); - if (&&lab) // { dg-warning "always evaluate as" "correct warning" } + if (&&lab) // { dg-warning "always evaluate as|never be NULL" "correct warning" } foo (6); if (foo == 0) // { dg-warning "never be NULL" "correct warning" } foo (7); diff --git a/gcc/testsuite/g++.dg/warn/Walways-true-2.C b/gcc/testsuite/g++.dg/warn/Walways-true-2.C index f157347..e4b5713 100644 --- a/gcc/testsuite/g++.dg/warn/Walways-true-2.C +++ b/gcc/testsuite/g++.dg/warn/Walways-true-2.C @@ -23,11 +23,11 @@ bar (int a) foo (2); if (i) foo (3); - if (&a) // { dg-warning "always evaluate as" "correct warning" } + if (&a) // { dg-warning "always evaluate as|never be NULL" "correct warning" } foo (4); if (a) foo (5); - if (&&lab) // { dg-warning "always evaluate as" "correct warning" } + if (&&lab) // { dg-warning "always evaluate as|never be NULL" "correct warning" } foo (6); if (foo == 0) foo (7);