diff options
author | Martin Sebor <msebor@redhat.com> | 2016-04-02 17:14:48 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2016-04-02 11:14:48 -0600 |
commit | abdc16c867080c5bd4dbbce2caf0d08e729255a0 (patch) | |
tree | f504219a5a11f02c14411065cc894e05404ff4ce /gcc/fold-const.c | |
parent | 7d9979e629a54f0d7e3378c90c7eb1adfd76196e (diff) | |
download | gcc-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.c | 60 |
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) |