>From c9b58a8c5b6be347c84d847c45d4178e61e298e6 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 4 Mar 2020 13:48:26 -0800 Subject: [PATCH] Pacify GCC 9.2.1 20190927 -O3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original problem report by N. Jackson in: https://lists.gnu.org/r/emacs-devel/2020-03/msg00047.html I found some other warnings when I used gcc, and fixed them with this patch. * lib-src/etags.c: Include verify.h. (xnmalloc, xnrealloc): Tell the compiler that NITEMS is nononnegative and ITEM_SIZE is positive. * src/conf_post.h (__has_attribute_returns_nonnull) (ATTRIBUTE_RETURNS_NONNULL): New macros. * src/editfns.c (Fuser_full_name): Don’t assume Fuser_login_name returns non-nil. * src/intervals.c (rotate_right, rotate_left, update_interval): * src/intervals.h (LENGTH, LEFT_TOTAL_LENGTH, RIGHT_TOTAL_LENGTH): Use TOTAL_LENGTH0 or equivalent on intervals that might be null. * src/intervals.h (TOTAL_LENGTH): Assume arg is nonnull. (TOTAL_LENGTH0): New macro, with the old TOTAL_LENGTH meaning. (make_interval, split_interval_right): Add ATTRIBUTE_RETURNS_NONNULL. * src/pdumper.c (dump_check_dump_off): Now returns void, since no caller uses the return value. Redo assert to pacify GCC. (decode_emacs_reloc): Add a seemingly-random eassume to pacify GCC. Ugly, and I suspect due to a bug in GCC. --- lib-src/etags.c | 5 +++++ src/conf_post.h | 7 +++++++ src/editfns.c | 19 +++++++++++-------- src/intervals.c | 12 ++++++------ src/intervals.h | 24 ++++++++++++++---------- src/pdumper.c | 9 ++++----- 6 files changed, 47 insertions(+), 29 deletions(-) diff --git a/lib-src/etags.c b/lib-src/etags.c index 174c33a7a5..eee2c59626 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -124,6 +124,7 @@ Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2020 Free Software #include #include #include +#include #include #include @@ -7310,6 +7311,8 @@ xmalloc (ptrdiff_t size) xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size) { ptrdiff_t nbytes; + assume (0 <= nitems); + assume (0 < item_size); if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes)) memory_full (); return xmalloc (nbytes); @@ -7319,6 +7322,8 @@ xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size) xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) { ptrdiff_t nbytes; + assume (0 <= nitems); + assume (0 < item_size); if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes) memory_full (); void *result = realloc (pa, nbytes); diff --git a/src/conf_post.h b/src/conf_post.h index 2f8d19fdca..eb8fb18c00 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -78,6 +78,7 @@ Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2020 Free Software # define __has_attribute_no_address_safety_analysis false # define __has_attribute_no_sanitize_address GNUC_PREREQ (4, 8, 0) # define __has_attribute_no_sanitize_undefined GNUC_PREREQ (4, 9, 0) +# define __has_attribute_returns_nonnull GNUC_PREREQ (4, 9, 0) # define __has_attribute_warn_unused_result GNUC_PREREQ (3, 4, 0) #endif @@ -321,6 +322,12 @@ #define ATTRIBUTE_SECTION(name) #define ATTRIBUTE_MALLOC_SIZE(args) ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE (args) +#if __has_attribute (returns_nonnull) +# define ATTRIBUTE_RETURNS_NONNULL __attribute__ ((returns_nonnull)) +#else +# define ATTRIBUTE_RETURNS_NONNULL +#endif + /* Work around GCC bug 59600: when a function is inlined, the inlined code may have its addresses sanitized even if the function has the no_sanitize_address attribute. This bug is fixed in GCC 4.9.0 and diff --git a/src/editfns.c b/src/editfns.c index ddf190b175..eb15566fb4 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -1262,14 +1262,17 @@ DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 1, 0, if (q) { Lisp_Object login = Fuser_login_name (INT_TO_INTEGER (pw->pw_uid)); - USE_SAFE_ALLOCA; - char *r = SAFE_ALLOCA (strlen (p) + SBYTES (login) + 1); - memcpy (r, p, q - p); - char *s = lispstpcpy (&r[q - p], login); - r[q - p] = upcase ((unsigned char) r[q - p]); - strcpy (s, q + 1); - full = build_string (r); - SAFE_FREE (); + if (!NILP (login)) + { + USE_SAFE_ALLOCA; + char *r = SAFE_ALLOCA (strlen (p) + SBYTES (login) + 1); + memcpy (r, p, q - p); + char *s = lispstpcpy (&r[q - p], login); + r[q - p] = upcase ((unsigned char) r[q - p]); + strcpy (s, q + 1); + full = build_string (r); + SAFE_FREE (); + } } #endif /* AMPERSAND_FULL_NAME */ diff --git a/src/intervals.c b/src/intervals.c index a66594ceea..594d8924eb 100644 --- a/src/intervals.c +++ b/src/intervals.c @@ -298,7 +298,7 @@ rotate_right (INTERVAL A) set_interval_parent (c, A); /* A's total length is decreased by the length of B and its left child. */ - A->total_length -= B->total_length - TOTAL_LENGTH (c); + A->total_length -= TOTAL_LENGTH (B) - TOTAL_LENGTH0 (c); eassert (TOTAL_LENGTH (A) > 0); eassert (LENGTH (A) > 0); @@ -349,7 +349,7 @@ rotate_left (INTERVAL A) set_interval_parent (c, A); /* A's total length is decreased by the length of B and its right child. */ - A->total_length -= B->total_length - TOTAL_LENGTH (c); + A->total_length -= TOTAL_LENGTH (B) - TOTAL_LENGTH0 (c); eassert (TOTAL_LENGTH (A) > 0); eassert (LENGTH (A) > 0); @@ -723,13 +723,13 @@ #define SET_PARENT_POSITION(i) \ i->position - LEFT_TOTAL_LENGTH (i) \ - LENGTH (INTERVAL_PARENT (i)) -/* Find the interval containing POS, given some non-NULL INTERVAL in +/* Find the interval containing POS, given some interval I in the same tree. Note that we update interval->position in each interval we traverse, assuming it is already correctly set for the argument I. We don't assume that any other interval already has a correctly set ->position. */ INTERVAL -update_interval (register INTERVAL i, ptrdiff_t pos) +update_interval (INTERVAL i, ptrdiff_t pos) { if (!i) return NULL; @@ -739,7 +739,7 @@ update_interval (register INTERVAL i, ptrdiff_t pos) if (pos < i->position) { /* Move left. */ - if (pos >= i->position - TOTAL_LENGTH (i->left)) + if (pos >= i->position - LEFT_TOTAL_LENGTH (i)) { i->left->position = i->position - TOTAL_LENGTH (i->left) + LEFT_TOTAL_LENGTH (i->left); @@ -757,7 +757,7 @@ update_interval (register INTERVAL i, ptrdiff_t pos) else if (pos >= INTERVAL_LAST_POS (i)) { /* Move right. */ - if (pos < INTERVAL_LAST_POS (i) + TOTAL_LENGTH (i->right)) + if (pos < INTERVAL_LAST_POS (i) + RIGHT_TOTAL_LENGTH (i)) { i->right->position = INTERVAL_LAST_POS (i) + LEFT_TOTAL_LENGTH (i->right); diff --git a/src/intervals.h b/src/intervals.h index a93b10e9ff..9a7ba910a1 100644 --- a/src/intervals.h +++ b/src/intervals.h @@ -96,24 +96,27 @@ #define ONLY_INTERVAL_P(i) (ROOT_INTERVAL_P (i) && LEAF_INTERVAL_P (i)) /* True if this interval has both left and right children. */ #define BOTH_KIDS_P(i) ((i)->left != NULL && (i)->right != NULL) -/* The total size of all text represented by this interval and all its - children in the tree. This is zero if the interval is null. */ -#define TOTAL_LENGTH(i) ((i) == NULL ? 0 : (i)->total_length) +/* The total size of all text represented by the nonnull interval I + and all its children in the tree. */ +#define TOTAL_LENGTH(i) ((i)->total_length) + +/* Likewise, but also defined to be zero if I is null. */ +#define TOTAL_LENGTH0(i) ((i) ? TOTAL_LENGTH (i) : 0) /* The size of text represented by this interval alone. */ -#define LENGTH(i) ((i)->total_length \ - - TOTAL_LENGTH ((i)->right) \ - - TOTAL_LENGTH ((i)->left)) +#define LENGTH(i) (TOTAL_LENGTH (i) \ + - RIGHT_TOTAL_LENGTH (i) \ + - LEFT_TOTAL_LENGTH (i)) /* The position of the character just past the end of I. Note that the position cache i->position must be valid for this to work. */ #define INTERVAL_LAST_POS(i) ((i)->position + LENGTH (i)) /* The total size of the left subtree of this interval. */ -#define LEFT_TOTAL_LENGTH(i) ((i)->left ? (i)->left->total_length : 0) +#define LEFT_TOTAL_LENGTH(i) TOTAL_LENGTH0 ((i)->left) /* The total size of the right subtree of this interval. */ -#define RIGHT_TOTAL_LENGTH(i) ((i)->right ? (i)->right->total_length : 0) +#define RIGHT_TOTAL_LENGTH(i) TOTAL_LENGTH0 ((i)->right) /* These macros are for dealing with the interval properties. */ @@ -234,7 +237,7 @@ #define TEXT_PROP_MEANS_INVISIBLE(prop) \ /* Declared in alloc.c. */ -extern INTERVAL make_interval (void); +extern INTERVAL make_interval (void) ATTRIBUTE_RETURNS_NONNULL; /* Declared in intervals.c. */ @@ -246,7 +249,8 @@ #define TEXT_PROP_MEANS_INVISIBLE(prop) \ Lisp_Object); extern void traverse_intervals_noorder (INTERVAL, void (*) (INTERVAL, void *), void *); -extern INTERVAL split_interval_right (INTERVAL, ptrdiff_t); +extern INTERVAL split_interval_right (INTERVAL, ptrdiff_t) + ATTRIBUTE_RETURNS_NONNULL; extern INTERVAL split_interval_left (INTERVAL, ptrdiff_t); extern INTERVAL find_interval (INTERVAL, ptrdiff_t); extern INTERVAL next_interval (INTERVAL); diff --git a/src/pdumper.c b/src/pdumper.c index 4d81203f46..e52163cdae 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -3604,14 +3604,12 @@ dump_unwind_cleanup (void *data) Vprocess_environment = ctx->old_process_environment; } -/* Return DUMP_OFFSET, making sure it is within the heap. */ -static dump_off +/* Check that DUMP_OFFSET is within the heap. */ +static void dump_check_dump_off (struct dump_context *ctx, dump_off dump_offset) { eassert (dump_offset > 0); - if (ctx) - eassert (dump_offset < ctx->end_heap); - return dump_offset; + eassert (!ctx || dump_offset < ctx->end_heap); } static void @@ -3734,6 +3732,7 @@ decode_emacs_reloc (struct dump_context *ctx, Lisp_Object lreloc) } else { + eassume (ctx); /* Pacify GCC 9.2.1 -O3 -Wnull-dereference. */ eassert (!dump_object_emacs_ptr (target_value)); reloc.u.dump_offset = dump_recall_object (ctx, target_value); if (reloc.u.dump_offset <= 0) -- 2.24.1