This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Emit -Waddress warnings for comparing address of reference against NULL


Implementation is pretty straightforward.  The only catch is that the
middle-end doesn't actually assume that REFERENCE_TYPEs are non-NULL so
code like

    int &a = *(int *)0;
    if (&a != 0)

will warn that &a will never be NULL yet the middle-end will fold the
conditional to false instead of true anyway.  But I guess that's not a
big deal.

Does this look OK after testing?

gcc/c-family/ChangeLog:
	* c-common.c (c_common_truthvalue_conversion): Warn when
	converting an address of a reference to a truth value.

gcc/cp/ChangeLog:
	* typeck.c (cp_build_binary_op): Warn when comparing an address
	of a reference against NULL.

gcc/testsuite/ChangeLog:
	g++.dg/warn/Walways-true-3.C: New test.
---
 gcc/c-family/c-common.c                    | 12 ++++++++++++
 gcc/cp/typeck.c                            | 10 ++++++++--
 gcc/testsuite/g++.dg/warn/Walways-true-3.C | 30 ++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Walways-true-3.C

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 7fe7fa6..89bbdc9 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -4784,6 +4784,18 @@ c_common_truthvalue_conversion (location_t location, tree expr)
 	tree totype = TREE_TYPE (expr);
 	tree fromtype = TREE_TYPE (TREE_OPERAND (expr, 0));
 
+	if (POINTER_TYPE_P (totype)
+	    && TREE_CODE (fromtype) == REFERENCE_TYPE)
+	  {
+	    tree inner = TREE_OPERAND (expr, 0);
+	    if (decl_with_nonnull_addr_p (inner))
+	      warning_at (location,
+			  OPT_Waddress,
+			  "the address of reference %qD may be assumed to "
+			  "always evaluate to %<true%>",
+			  inner);
+	  }
+
 	/* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
 	   since that affects how `default_conversion' will behave.  */
 	if (TREE_CODE (totype) == REFERENCE_TYPE
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 250b5d6..0d177b7 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4415,7 +4415,10 @@ cp_build_binary_op (location_t location,
 	  else
 	    result_type = type0;
 
-	  if (TREE_CODE (op0) == ADDR_EXPR
+	  if ((TREE_CODE (op0) == ADDR_EXPR
+	       || (CONVERT_EXPR_P (op0)
+		   && TREE_CODE (TREE_TYPE (TREE_OPERAND (op0, 0)))
+		      == REFERENCE_TYPE))
 	      && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
 	    {
 	      if ((complain & tf_warning)
@@ -4437,7 +4440,10 @@ cp_build_binary_op (location_t location,
 	  else
 	    result_type = type1;
 
-	  if (TREE_CODE (op1) == ADDR_EXPR 
+	  if ((TREE_CODE (op1) == ADDR_EXPR
+	       || (CONVERT_EXPR_P (op1)
+		   && TREE_CODE (TREE_TYPE (TREE_OPERAND (op1, 0)))
+		      == REFERENCE_TYPE))
 	      && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
 	    {
 	      if ((complain & tf_warning)
diff --git a/gcc/testsuite/g++.dg/warn/Walways-true-3.C b/gcc/testsuite/g++.dg/warn/Walways-true-3.C
new file mode 100644
index 0000000..a145932
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Walways-true-3.C
@@ -0,0 +1,30 @@
+// { dg-options "-Waddress" }
+
+void foo (void);
+
+int d;
+int &c = d;
+
+void
+bar (int &a)
+{
+  int &b = a;
+
+  if (&a) // { dg-warning "address of reference" }
+    foo ();
+
+  if (&b) // { dg-warning "address of reference" }
+    foo ();
+
+  if (&c) // { dg-warning "address of reference" }
+    foo ();
+
+  if (&a == 0) // { dg-warning "never be NULL" }
+    foo ();
+
+  if (&b != 0) // { dg-warning "never be NULL" }
+    foo ();
+
+  if (0 == &c) // { dg-warning "never be NULL" }
+    foo ();
+}
-- 
2.4.0.rc2.31.g7c597ef


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]