aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2016-04-02 17:14:48 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2016-04-02 11:14:48 -0600
commitabdc16c867080c5bd4dbbce2caf0d08e729255a0 (patch)
treef504219a5a11f02c14411065cc894e05404ff4ce /gcc/fold-const.c
parent7d9979e629a54f0d7e3378c90c7eb1adfd76196e (diff)
downloadgcc-abdc16c867080c5bd4dbbce2caf0d08e729255a0.zip
gcc-abdc16c867080c5bd4dbbce2caf0d08e729255a0.tar.gz
gcc-abdc16c867080c5bd4dbbce2caf0d08e729255a0.tar.bz2
PR c++/67376 - [5/6 regression] Comparison with pointer to past-the-end
PR c++/67376 - [5/6 regression] Comparison with pointer to past-the-end of array fails inside constant expression PR c++/70170 - [6 regression] bogus not a constant expression error comparing pointer to array to null PR c++/70172 - incorrect reinterpret_cast from integer to pointer error on invalid constexpr initialization PR c++/70228 - insufficient detail in diagnostics for a constexpr out of bounds array subscript gcc/testsuite/ChangeLog: 2016-04-02 Martin Sebor <msebor@redhat.com> PR c++/67376 PR c++/70170 PR c++/70172 PR c++/70228 * g++.dg/cpp0x/constexpr-array-ptr10.C: New test. * g++.dg/cpp0x/constexpr-array-ptr9.C: New test. * g++.dg/cpp0x/constexpr-nullptr-1.C: New test. * g++.dg/cpp0x/constexpr-array5.C: Adjust text of expected diagnostic. * g++.dg/cpp0x/constexpr-string.C: Same. * g++.dg/cpp0x/constexpr-wstring2.C: Same. * g++.dg/cpp0x/pr65398.C: Same. * g++.dg/ext/constexpr-vla1.C: Same. * g++.dg/ext/constexpr-vla2.C: Same. * g++.dg/ext/constexpr-vla3.C: Same. * g++.dg/ubsan/pr63956.C: Same. gcc/cp/ChangeLog: 2016-04-02 Martin Sebor <msebor@redhat.com> PR c++/67376 PR c++/70170 PR c++/70172 PR c++/70228 * constexpr.c (diag_array_subscript): New function. (cxx_eval_array_reference): Detect out of bounds array indices. gcc/ChangeLog: 2016-04-02 Martin Sebor <msebor@redhat.com> PR c++/67376 * fold-const.c (maybe_nonzero_address): New function. (fold_comparison): Call it. Fold equality and relational expressions involving null pointers. (tree_single_nonzero_warnv_p): Call maybe_nonzero_address. From-SVN: r234698
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c60
1 files changed, 50 insertions, 10 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 788ecc3..0f4bf7e 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8338,6 +8338,20 @@ pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
return total.to_uhwi () > (unsigned HOST_WIDE_INT) size;
}
+/* Return a positive integer when the symbol DECL is known to have
+ a nonzero address, zero when it's known not to (e.g., it's a weak
+ symbol), and a negative integer when the symbol is not yet in the
+ symbol table and so whether or not its address is zero is unknown. */
+static int
+maybe_nonzero_address (tree decl)
+{
+ if (DECL_P (decl) && decl_in_symtab_p (decl))
+ if (struct symtab_node *symbol = symtab_node::get_create (decl))
+ return symbol->nonzero_address ();
+
+ return -1;
+}
+
/* Subroutine of fold_binary. This routine performs all of the
transformations that are common to the equality/inequality
operators (EQ_EXPR and NE_EXPR) and the ordering operators
@@ -8638,6 +8652,39 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
base1 = build_fold_addr_expr_loc (loc, base1);
return fold_build2_loc (loc, code, type, base0, base1);
}
+ /* Comparison between an ordinary (non-weak) symbol and a null
+ pointer can be eliminated since such symbols must have a non
+ null address. In C, relational expressions between pointers
+ to objects and null pointers are undefined. The results
+ below follow the C++ rules with the additional property that
+ every object pointer compares greater than a null pointer.
+ */
+ else if (DECL_P (base0)
+ && maybe_nonzero_address (base0) > 0
+ /* Avoid folding references to struct members at offset 0 to
+ prevent tests like '&ptr->firstmember == 0' from getting
+ eliminated. When ptr is null, although the -> expression
+ is strictly speaking invalid, GCC retains it as a matter
+ of QoI. See PR c/44555. */
+ && (offset0 == NULL_TREE && bitpos0 != 0)
+ /* The caller guarantees that when one of the arguments is
+ constant (i.e., null in this case) it is second. */
+ && integer_zerop (arg1))
+ {
+ switch (code)
+ {
+ case EQ_EXPR:
+ case LE_EXPR:
+ case LT_EXPR:
+ return boolean_false_node;
+ case GE_EXPR:
+ case GT_EXPR:
+ case NE_EXPR:
+ return boolean_true_node;
+ default:
+ gcc_unreachable ();
+ }
+ }
}
/* Transform comparisons of the form X +- C1 CMP Y +- C2 to
@@ -13508,16 +13555,9 @@ tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
/* For objects in symbol table check if we know they are non-zero.
Don't do anything for variables and functions before symtab is built;
it is quite possible that they will be declared weak later. */
- if (DECL_P (base) && decl_in_symtab_p (base))
- {
- struct symtab_node *symbol;
-
- symbol = symtab_node::get_create (base);
- if (symbol)
- return symbol->nonzero_address ();
- else
- return false;
- }
+ int nonzero_addr = maybe_nonzero_address (base);
+ if (nonzero_addr >= 0)
+ return nonzero_addr;
/* Function local objects are never NULL. */
if (DECL_P (base)