mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Remove dependence on -fwrapv semantics in a few places.
This commit attempts to update a few places, such as the money, numeric, and timestamp types, to no longer rely on signed integer wrapping for correctness. This is intended to move us closer towards removing -fwrapv, which may enable some compiler optimizations. However, there is presently no plan to actually remove that compiler option in the near future. Besides using some of the existing overflow-aware routines in int.h, this commit introduces and makes use of some new ones. Specifically, it adds functions that accept a signed integer and return its absolute value as an unsigned integer with the same width (e.g., pg_abs_s64()). It also adds functions that accept an unsigned integer, store the result of negating that integer in a signed integer with the same width, and return whether the negation overflowed (e.g., pg_neg_u64_overflow()). Finally, this commit adds a couple of tests for timestamps near POSTGRES_EPOCH_JDATE. Author: Joseph Koshakow Reviewed-by: Tom Lane, Heikki Linnakangas, Jian He Discussion: https://postgr.es/m/CAAvxfHdBPOyEGS7s%2Bxf4iaW0-cgiq25jpYdWBqQqvLtLe_t6tw%40mail.gmail.com
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "common/int.h"
|
||||
#include "port/pg_bitutils.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
@@ -131,6 +132,7 @@ pg_strtoint16_safe(const char *s, Node *escontext)
|
||||
uint16 tmp = 0;
|
||||
bool neg = false;
|
||||
unsigned char digit;
|
||||
int16 result;
|
||||
|
||||
/*
|
||||
* The majority of cases are likely to be base-10 digits without any
|
||||
@@ -190,10 +192,9 @@ pg_strtoint16_safe(const char *s, Node *escontext)
|
||||
|
||||
if (neg)
|
||||
{
|
||||
/* check the negative equivalent will fit without overflowing */
|
||||
if (unlikely(tmp > (uint16) (-(PG_INT16_MIN + 1)) + 1))
|
||||
if (unlikely(pg_neg_u16_overflow(tmp, &result)))
|
||||
goto out_of_range;
|
||||
return -((int16) tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (unlikely(tmp > PG_INT16_MAX))
|
||||
@@ -333,10 +334,9 @@ slow:
|
||||
|
||||
if (neg)
|
||||
{
|
||||
/* check the negative equivalent will fit without overflowing */
|
||||
if (tmp > (uint16) (-(PG_INT16_MIN + 1)) + 1)
|
||||
if (unlikely(pg_neg_u16_overflow(tmp, &result)))
|
||||
goto out_of_range;
|
||||
return -((int16) tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (tmp > PG_INT16_MAX)
|
||||
@@ -393,6 +393,7 @@ pg_strtoint32_safe(const char *s, Node *escontext)
|
||||
uint32 tmp = 0;
|
||||
bool neg = false;
|
||||
unsigned char digit;
|
||||
int32 result;
|
||||
|
||||
/*
|
||||
* The majority of cases are likely to be base-10 digits without any
|
||||
@@ -452,10 +453,9 @@ pg_strtoint32_safe(const char *s, Node *escontext)
|
||||
|
||||
if (neg)
|
||||
{
|
||||
/* check the negative equivalent will fit without overflowing */
|
||||
if (unlikely(tmp > (uint32) (-(PG_INT32_MIN + 1)) + 1))
|
||||
if (unlikely(pg_neg_u32_overflow(tmp, &result)))
|
||||
goto out_of_range;
|
||||
return -((int32) tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (unlikely(tmp > PG_INT32_MAX))
|
||||
@@ -595,10 +595,9 @@ slow:
|
||||
|
||||
if (neg)
|
||||
{
|
||||
/* check the negative equivalent will fit without overflowing */
|
||||
if (tmp > (uint32) (-(PG_INT32_MIN + 1)) + 1)
|
||||
if (unlikely(pg_neg_u32_overflow(tmp, &result)))
|
||||
goto out_of_range;
|
||||
return -((int32) tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (tmp > PG_INT32_MAX)
|
||||
@@ -655,6 +654,7 @@ pg_strtoint64_safe(const char *s, Node *escontext)
|
||||
uint64 tmp = 0;
|
||||
bool neg = false;
|
||||
unsigned char digit;
|
||||
int64 result;
|
||||
|
||||
/*
|
||||
* The majority of cases are likely to be base-10 digits without any
|
||||
@@ -714,10 +714,9 @@ pg_strtoint64_safe(const char *s, Node *escontext)
|
||||
|
||||
if (neg)
|
||||
{
|
||||
/* check the negative equivalent will fit without overflowing */
|
||||
if (unlikely(tmp > (uint64) (-(PG_INT64_MIN + 1)) + 1))
|
||||
if (unlikely(pg_neg_u64_overflow(tmp, &result)))
|
||||
goto out_of_range;
|
||||
return -((int64) tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (unlikely(tmp > PG_INT64_MAX))
|
||||
@@ -857,10 +856,9 @@ slow:
|
||||
|
||||
if (neg)
|
||||
{
|
||||
/* check the negative equivalent will fit without overflowing */
|
||||
if (tmp > (uint64) (-(PG_INT64_MIN + 1)) + 1)
|
||||
if (unlikely(pg_neg_u64_overflow(tmp, &result)))
|
||||
goto out_of_range;
|
||||
return -((int64) tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (tmp > PG_INT64_MAX)
|
||||
|
||||
Reference in New Issue
Block a user