bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/5] Import idx.h from gnulib


From: Adhemerval Zanella
Subject: [PATCH 2/5] Import idx.h from gnulib
Date: Thu, 24 Dec 2020 12:16:58 -0300

And use to simplify stdlib/canonicalize.c implementation.
---
 include/idx.h         | 113 ++++++++++++++++++++++++++++++++++++++++++
 stdlib/canonicalize.c |   5 +-
 2 files changed, 114 insertions(+), 4 deletions(-)
 create mode 100644 include/idx.h

diff --git a/include/idx.h b/include/idx.h
new file mode 100644
index 0000000000..ad7d31a2bc
--- /dev/null
+++ b/include/idx.h
@@ -0,0 +1,113 @@
+/* A type for indices and sizes.
+
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
+
+#ifndef _IDX_H
+#define _IDX_H
+
+/* Get ptrdiff_t.  */
+#include <stddef.h>
+
+/* Get PTRDIFF_MAX.  */
+#include <stdint.h>
+
+/* The type 'idx_t' holds an (array) index or an (object) size.
+   Its implementation promotes to a signed integer type,
+   which can hold the values
+     0..2^63-1 (on 64-bit platforms) or
+     0..2^31-1 (on 32-bit platforms).
+
+   Why a signed integer type?
+
+     * Security: Signed types can be checked for overflow via
+       '-fsanitize=undefined', but unsigned types cannot.
+
+     * Comparisons without surprises: ISO C99 ?? 6.3.1.8 specifies a few
+       surprising results for comparisons, such as
+
+           (int) -3 < (unsigned long) 7  =>  false
+           (int) -3 < (unsigned int) 7   =>  false
+       and on 32-bit machines:
+           (long) -3 < (unsigned int) 7  =>  false
+
+       This is surprising because the natural comparison order is by
+       value in the realm of infinite-precision signed integers (???).
+
+       The best way to get rid of such surprises is to use signed types
+       for numerical integer values, and use unsigned types only for
+       bit masks and enums.
+
+   Why not use 'size_t' directly?
+
+     * Because 'size_t' is an unsigned type, and a signed type is better.
+       See above.
+
+   Why not use 'ptrdiff_t' directly?
+
+     * Maintainability: When reading and modifying code, it helps to know that
+       a certain variable cannot have negative values.  For example, when you
+       have a loop
+
+         int n = ...;
+         for (int i = 0; i < n; i++) ...
+
+       or
+
+         ptrdiff_t n = ...;
+         for (ptrdiff_t i = 0; i < n; i++) ...
+
+       you have to ask yourself "what if n < 0?".  Whereas in
+
+         idx_t n = ...;
+         for (idx_t i = 0; i < n; i++) ...
+
+       you know that this case cannot happen.
+
+       Similarly, when a programmer writes
+
+         idx_t = ptr2 - ptr1;
+
+       there is an implied assertion that ptr1 and ptr2 point into the same
+       object and that ptr1 <= ptr2.
+
+     * Being future-proof: In the future, range types (integers which are
+       constrained to a certain range of values) may be added to C compilers
+       or to the C standard.  Several programming languages (Ada, Haskell,
+       Common Lisp, Pascal) already have range types.  Such range types may
+       help producing good code and good warnings.  The type 'idx_t' could
+       then be typedef'ed to a range type that is signed after promotion.  */
+
+/* In the future, idx_t could be typedef'ed to a signed range type.
+   The clang "extended integer types", supported in Clang 11 or newer
+   
<https://clang.llvm.org/docs/LanguageExtensions.html#extended-integer-types>,
+   are a special case of range types.  However, these types don't support 
binary
+   operators with plain integer types (e.g. expressions such as x > 1).
+   Therefore, they don't behave like signed types (and not like unsigned types
+   either).  So, we cannot use them here.  */
+
+/* Use the signed type 'ptrdiff_t'.  */
+/* Note: ISO C does not mandate that 'size_t' and 'ptrdiff_t' have the same
+   size, but it is so on all platforms we have seen since 1990.  */
+typedef ptrdiff_t idx_t;
+
+/* IDX_MAX is the maximum value of an idx_t.  */
+#define IDX_MAX PTRDIFF_MAX
+
+/* So far no need has been found for an IDX_WIDTH macro.
+   Perhaps there should be another macro IDX_VALUE_BITS that does not
+   count the sign bit and is therefore one less than PTRDIFF_WIDTH.  */
+
+#endif /* _IDX_H */
diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
index 66685f4526..4b3bd10a9d 100644
--- a/stdlib/canonicalize.c
+++ b/stdlib/canonicalize.c
@@ -35,14 +35,13 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <idx.h>
 
 #include <scratch_buffer.h>
 
 #ifdef _LIBC
 # include <eloop-threshold.h>
 # include <shlib-compat.h>
-typedef ptrdiff_t idx_t;
-# define IDX_MAX PTRDIFF_MAX
 # define FILE_SYSTEM_PREFIX_LEN(name) 0
 # define IS_ABSOLUTE_FILE_NAME(name) ISSLASH(*(name))
 # define ISSLASH(c) ((c) == '/')
@@ -50,7 +49,6 @@ typedef ptrdiff_t idx_t;
 #else
 # define __canonicalize_file_name canonicalize_file_name
 # define __realpath realpath
-# include "idx.h"
 # include "pathmax.h"
 # include "filename.h"
 # if defined _WIN32 && !defined __CYGWIN__
@@ -92,7 +90,6 @@ typedef ptrdiff_t idx_t;
 #endif
 
 #if !FUNC_REALPATH_WORKS || defined _LIBC
-
 static idx_t
 get_path_max (void)
 {
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]