[Ada] Consistently use explicit Entity_Id type instead of alias
[gcc.git] / libcpp / expr.c
index 46d9fd386ab7c3a2d71ebed5098063b759b2bbf6..2ba7726d61c4679edca4270eb5d1d4e02cf566be 100644 (file)
@@ -1,5 +1,5 @@
 /* Parse C expressions for cpplib.
-   Copyright (C) 1987-2013 Free Software Foundation, Inc.
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
    Contributed by Per Bothner, 1994.
 
 This program is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@ struct op
 {
   const cpp_token *token;      /* The token forming op (for diagnostics).  */
   cpp_num value;               /* The value logically "right" of op.  */
-  source_location loc;          /* The location of this value.         */
+  location_t loc;          /* The location of this value.         */
   enum cpp_ttype op;
 };
 
@@ -52,13 +52,13 @@ static cpp_num num_equality_op (cpp_reader *, cpp_num, cpp_num,
                                enum cpp_ttype);
 static cpp_num num_mul (cpp_reader *, cpp_num, cpp_num);
 static cpp_num num_div_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype,
-                          source_location);
+                          location_t);
 static cpp_num num_lshift (cpp_num, size_t, size_t);
 static cpp_num num_rshift (cpp_num, size_t, size_t);
 
 static cpp_num append_digit (cpp_num, int, int, size_t);
 static cpp_num parse_defined (cpp_reader *);
-static cpp_num eval_token (cpp_reader *, const cpp_token *, source_location);
+static cpp_num eval_token (cpp_reader *, const cpp_token *, location_t);
 static struct op *reduce (cpp_reader *, struct op *, enum cpp_ttype);
 static unsigned int interpret_float_suffix (cpp_reader *, const uchar *, size_t);
 static unsigned int interpret_int_suffix (cpp_reader *, const uchar *, size_t);
@@ -84,15 +84,54 @@ static void check_promotion (cpp_reader *, const struct op *);
 
 /* Subroutine of cpp_classify_number.  S points to a float suffix of
    length LEN, possibly zero.  Returns 0 for an invalid suffix, or a
-   flag vector describing the suffix.  */
+   flag vector (of CPP_N_* bits) describing the suffix.  */
 static unsigned int
 interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 {
+  size_t orig_len = len;
+  const uchar *orig_s = s;
   size_t flags;
-  size_t f, d, l, w, q, i;
+  size_t f, d, l, w, q, i, fn, fnx, fn_bits;
 
   flags = 0;
-  f = d = l = w = q = i = 0;
+  f = d = l = w = q = i = fn = fnx = fn_bits = 0;
+
+  /* The following decimal float suffixes, from TR 24732:2009, TS
+     18661-2:2015 and C2X, are supported:
+
+     df, DF - _Decimal32.
+     dd, DD - _Decimal64.
+     dl, DL - _Decimal128.
+
+     The dN and DN suffixes for _DecimalN, and dNx and DNx for
+     _DecimalNx, defined in TS 18661-3:2015, are not supported.
+
+     Fixed-point suffixes, from TR 18037:2008, are supported.  They
+     consist of three parts, in order:
+
+     (i) An optional u or U, for unsigned types.
+
+     (ii) An optional h or H, for short types, or l or L, for long
+     types, or ll or LL, for long long types.  Use of ll or LL is a
+     GNU extension.
+
+     (iii) r or R, for _Fract types, or k or K, for _Accum types.
+
+     Otherwise the suffix is for a binary or standard floating-point
+     type.  Such a suffix, or the absence of a suffix, may be preceded
+     or followed by i, I, j or J, to indicate an imaginary number with
+     the corresponding complex type.  The following suffixes for
+     binary or standard floating-point types are supported:
+
+     f, F - float (ISO C and C++).
+     l, L - long double (ISO C and C++).
+     d, D - double, even with the FLOAT_CONST_DECIMAL64 pragma in
+           operation (from TR 24732:2009; the pragma and the suffix
+           are not included in TS 18661-2:2015).
+     w, W - machine-specific type such as __float80 (GNU extension).
+     q, Q - machine-specific type such as __float128 (GNU extension).
+     fN, FN - _FloatN (TS 18661-3:2015).
+     fNx, FNx - _FloatNx (TS 18661-3:2015).  */
 
   /* Process decimal float suffixes, which are two letters starting
      with d or D.  Order and case are significant.  */
@@ -170,24 +209,81 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 
   /* In any remaining valid suffix, the case and order don't matter.  */
   while (len--)
-    switch (s[len])
-      {
-      case 'f': case 'F': f++; break;
-      case 'd': case 'D': d++; break;
-      case 'l': case 'L': l++; break;
-      case 'w': case 'W': w++; break;
-      case 'q': case 'Q': q++; break;
-      case 'i': case 'I':
-      case 'j': case 'J': i++; break;
-      default:
-       return 0;
-      }
+    {
+      switch (s[0])
+       {
+       case 'f': case 'F':
+         f++;
+         if (len > 0
+             && !CPP_OPTION (pfile, cplusplus)
+             && s[1] >= '1'
+             && s[1] <= '9'
+             && fn_bits == 0)
+           {
+             f--;
+             while (len > 0
+                    && s[1] >= '0'
+                    && s[1] <= '9'
+                    && fn_bits < CPP_FLOATN_MAX)
+               {
+                 fn_bits = fn_bits * 10 + (s[1] - '0');
+                 len--;
+                 s++;
+               }
+             if (len > 0 && s[1] == 'x')
+               {
+                 fnx++;
+                 len--;
+                 s++;
+               }
+             else
+               fn++;
+           }
+         break;
+       case 'd': case 'D': d++; break;
+       case 'l': case 'L': l++; break;
+       case 'w': case 'W': w++; break;
+       case 'q': case 'Q': q++; break;
+       case 'i': case 'I':
+       case 'j': case 'J': i++; break;
+       default:
+         return 0;
+       }
+      s++;
+    }
 
-  if (f + d + l + w + q > 1 || i > 1)
+  /* Reject any case of multiple suffixes specifying types, multiple
+     suffixes specifying an imaginary constant, _FloatN or _FloatNx
+     suffixes for invalid values of N, and _FloatN suffixes for values
+     of N larger than can be represented in the return value.  The
+     caller is responsible for rejecting _FloatN suffixes where
+     _FloatN is not supported on the chosen target.  */
+  if (f + d + l + w + q + fn + fnx > 1 || i > 1)
     return 0;
-
-  if (i && !CPP_OPTION (pfile, ext_numeric_literals))
+  if (fn_bits > CPP_FLOATN_MAX)
+    return 0;
+  if (fnx && fn_bits != 32 && fn_bits != 64 && fn_bits != 128)
     return 0;
+  if (fn && fn_bits != 16 && fn_bits % 32 != 0)
+    return 0;
+  if (fn && fn_bits == 96)
+    return 0;
+
+  if (i)
+    {
+      if (!CPP_OPTION (pfile, ext_numeric_literals))
+       return 0;
+
+      /* In C++14 and up these suffixes are in the standard library, so treat
+        them as user-defined literals.  */
+      if (CPP_OPTION (pfile, cplusplus)
+         && CPP_OPTION (pfile, lang) > CLK_CXX11
+         && orig_s[0] == 'i'
+         && (orig_len == 1
+             || (orig_len == 2
+                 && (orig_s[1] == 'f' || orig_s[1] == 'l'))))
+       return 0;
+    }
 
   if ((w || q) && !CPP_OPTION (pfile, ext_numeric_literals))
     return 0;
@@ -197,7 +293,10 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
             d ? CPP_N_MEDIUM :
             l ? CPP_N_LARGE :
             w ? CPP_N_MD_W :
-            q ? CPP_N_MD_Q : CPP_N_DEFAULT));
+            q ? CPP_N_MD_Q :
+            fn ? CPP_N_FLOATN | (fn_bits << CPP_FLOATN_SHIFT) :
+            fnx ? CPP_N_FLOATNX | (fn_bits << CPP_FLOATN_SHIFT) :
+            CPP_N_DEFAULT));
 }
 
 /* Return the classification flags for a float suffix.  */
@@ -213,6 +312,7 @@ cpp_interpret_float_suffix (cpp_reader *pfile, const char *s, size_t len)
 static unsigned int
 interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 {
+  size_t orig_len = len;
   size_t u, l, i;
 
   u = l = i = 0;
@@ -235,8 +335,19 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
   if (l > 2 || u > 1 || i > 1)
     return 0;
 
-  if (i && !CPP_OPTION (pfile, ext_numeric_literals))
-    return 0;
+  if (i)
+    {
+      if (!CPP_OPTION (pfile, ext_numeric_literals))
+       return 0;
+
+      /* In C++14 and up these suffixes are in the standard library, so treat
+        them as user-defined literals.  */
+      if (CPP_OPTION (pfile, cplusplus)
+         && CPP_OPTION (pfile, lang) > CLK_CXX11
+         && s[0] == 'i'
+         && (orig_len == 1 || (orig_len == 2 && s[1] == 'l')))
+       return 0;
+    }
 
   return ((i ? CPP_N_IMAGINARY : 0)
          | (u ? CPP_N_UNSIGNED : 0)
@@ -305,6 +416,8 @@ cpp_userdef_char_remove_type (enum cpp_ttype type)
     return CPP_CHAR16;
   else if (type == CPP_CHAR32_USERDEF)
     return CPP_CHAR32;
+  else if (type == CPP_UTF8CHAR_USERDEF)
+    return CPP_UTF8CHAR;
   else
     return type;
 }
@@ -323,6 +436,8 @@ cpp_userdef_char_add_type (enum cpp_ttype type)
     return CPP_CHAR16_USERDEF;
   else if (type == CPP_CHAR32)
     return CPP_CHAR32_USERDEF;
+  else if (type == CPP_UTF8CHAR)
+    return CPP_UTF8CHAR_USERDEF;
   else
     return type;
 }
@@ -348,7 +463,8 @@ cpp_userdef_char_p (enum cpp_ttype type)
   if (type == CPP_CHAR_USERDEF
    || type == CPP_WCHAR_USERDEF
    || type == CPP_CHAR16_USERDEF
-   || type == CPP_CHAR32_USERDEF)
+   || type == CPP_CHAR32_USERDEF
+   || type == CPP_UTF8CHAR_USERDEF)
     return true;
   else
     return false;
@@ -387,13 +503,14 @@ cpp_get_userdef_suffix (const cpp_token *tok)
    VIRTUAL_LOCATION is the virtual location for TOKEN.  */
 unsigned int
 cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
-                    const char **ud_suffix, source_location virtual_location)
+                    const char **ud_suffix, location_t virtual_location)
 {
   const uchar *str = token->val.str.text;
   const uchar *limit;
   unsigned int max_digit, result, radix;
   enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag;
   bool seen_digit;
+  bool seen_digit_sep;
 
   if (ud_suffix)
     *ud_suffix = NULL;
@@ -408,6 +525,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
   max_digit = 0;
   radix = 10;
   seen_digit = false;
+  seen_digit_sep = false;
 
   /* First, interpret the radix.  */
   if (*str == '0')
@@ -416,16 +534,27 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
       str++;
 
       /* Require at least one hex digit to classify it as hex.  */
-      if ((*str == 'x' || *str == 'X')
-         && (str[1] == '.' || ISXDIGIT (str[1])))
+      if (*str == 'x' || *str == 'X')
        {
-         radix = 16;
-         str++;
+         if (str[1] == '.' || ISXDIGIT (str[1]))
+           {
+             radix = 16;
+             str++;
+           }
+         else if (DIGIT_SEP (str[1]))
+           SYNTAX_ERROR_AT (virtual_location,
+                            "digit separator after base indicator");
        }
-      else if ((*str == 'b' || *str == 'B') && (str[1] == '0' || str[1] == '1'))
+      else if (*str == 'b' || *str == 'B')
        {
-         radix = 2;
-         str++;
+         if (str[1] == '0' || str[1] == '1')
+           {
+             radix = 2;
+             str++;
+           }
+         else if (DIGIT_SEP (str[1]))
+           SYNTAX_ERROR_AT (virtual_location,
+                            "digit separator after base indicator");
        }
     }
 
@@ -436,13 +565,24 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
 
       if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
        {
+         seen_digit_sep = false;
          seen_digit = true;
          c = hex_value (c);
          if (c > max_digit)
            max_digit = c;
        }
+      else if (DIGIT_SEP (c))
+       {
+         if (seen_digit_sep)
+           SYNTAX_ERROR_AT (virtual_location, "adjacent digit separators");
+         seen_digit_sep = true;
+       }
       else if (c == '.')
        {
+         if (seen_digit_sep || DIGIT_SEP (*str))
+           SYNTAX_ERROR_AT (virtual_location,
+                            "digit separator adjacent to decimal point");
+         seen_digit_sep = false;
          if (float_flag == NOT_FLOAT)
            float_flag = AFTER_POINT;
          else
@@ -452,6 +592,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
       else if ((radix <= 10 && (c == 'e' || c == 'E'))
               || (radix == 16 && (c == 'p' || c == 'P')))
        {
+         if (seen_digit_sep || DIGIT_SEP (*str))
+           SYNTAX_ERROR_AT (virtual_location,
+                            "digit separator adjacent to exponent");
          float_flag = AFTER_EXPON;
          break;
        }
@@ -463,6 +606,10 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
        }
     }
 
+  if (seen_digit_sep && float_flag != AFTER_EXPON)
+    SYNTAX_ERROR_AT (virtual_location,
+                    "digit separator outside digit sequence");
+
   /* The suffix may be for decimal fixed-point constants without exponent.  */
   if (radix != 16 && float_flag == NOT_FLOAT)
     {
@@ -509,9 +656,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
        SYNTAX_ERROR_AT (virtual_location,
                         "no digits in hexadecimal floating constant");
 
-      if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
-       cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
-                            "use of C99 hexadecimal floating constant");
+      if (radix == 16 && CPP_PEDANTIC (pfile)
+         && !CPP_OPTION (pfile, extended_numbers))
+       {
+         if (CPP_OPTION (pfile, cplusplus))
+           cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                                "use of C++17 hexadecimal floating constant");
+         else
+           cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                                "use of C99 hexadecimal floating constant");
+       }
 
       if (float_flag == AFTER_EXPON)
        {
@@ -520,16 +674,28 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
 
          /* Exponent is decimal, even if string is a hex float.  */
          if (!ISDIGIT (*str))
-           SYNTAX_ERROR_AT (virtual_location, "exponent has no digits");
-
+           {
+             if (DIGIT_SEP (*str))
+               SYNTAX_ERROR_AT (virtual_location,
+                                "digit separator adjacent to exponent");
+             else
+               SYNTAX_ERROR_AT (virtual_location, "exponent has no digits");
+           }
          do
-           str++;
-         while (ISDIGIT (*str));
+           {
+             seen_digit_sep = DIGIT_SEP (*str);
+             str++;
+           }
+         while (ISDIGIT (*str) || DIGIT_SEP (*str));
        }
       else if (radix == 16)
        SYNTAX_ERROR_AT (virtual_location,
                         "hexadecimal floating constants require an exponent");
 
+      if (seen_digit_sep)
+       SYNTAX_ERROR_AT (virtual_location,
+                        "digit separator outside digit sequence");
+
       result = interpret_float_suffix (pfile, str, limit - str);
       if (result == 0)
        {
@@ -576,9 +742,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
        cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
                             "fixed-point constants are a GCC extension");
 
-      if ((result & CPP_N_DFLOAT) && CPP_PEDANTIC (pfile))
-       cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
-                            "decimal float constants are a GCC extension");
+      if (result & CPP_N_DFLOAT)
+       {
+         if (CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, dfp_constants))
+           cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                                "decimal float constants are a C2X feature");
+         else if (CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) > 0)
+           cpp_warning_with_line (pfile, CPP_W_C11_C2X_COMPAT,
+                                  virtual_location, 0,
+                                  "decimal float constants are a C2X feature");
+       }
 
       result |= CPP_N_FLOATING;
     }
@@ -621,7 +794,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
          && CPP_OPTION (pfile, cpp_warn_long_long))
         {
           const char *message = CPP_OPTION (pfile, cplusplus) 
-                               ? N_("use of C++0x long long integer constant")
+                               ? N_("use of C++11 long long integer constant")
                                : N_("use of C99 long long integer constant");
 
          if (CPP_OPTION (pfile, c99))
@@ -639,9 +812,21 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
   if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
     cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
                         "imaginary constants are a GCC extension");
-  if (radix == 2 && CPP_PEDANTIC (pfile))
-    cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
-                        "binary constants are a GCC extension");
+  if (radix == 2)
+    {
+      if (!CPP_OPTION (pfile, binary_constants)
+         && CPP_PEDANTIC (pfile))
+       cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                            CPP_OPTION (pfile, cplusplus)
+                            ? N_("binary constants are a C++14 feature "
+                                 "or GCC extension")
+                            : N_("binary constants are a C2X feature "
+                                 "or GCC extension"));
+      else if (CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) > 0)
+       cpp_warning_with_line (pfile, CPP_W_C11_C2X_COMPAT,
+                              virtual_location, 0,
+                              "binary constants are a C2X feature");
+    }
 
   if (radix == 10)
     result |= CPP_N_DECIMAL;
@@ -718,6 +903,8 @@ cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
 
          if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c)))
            c = hex_value (c);
+         else if (DIGIT_SEP (c))
+           continue;
          else
            break;
 
@@ -881,30 +1068,19 @@ parse_defined (cpp_reader *pfile)
        }
     }
 
+  bool is_defined = false;
   if (node)
     {
-      if (pfile->context != initial_context && CPP_PEDANTIC (pfile))
-       cpp_error (pfile, CPP_DL_WARNING,
-                  "this use of \"defined\" may not be portable");
-
+      if ((pfile->context != initial_context
+          || initial_context != &pfile->base_context)
+         && CPP_OPTION (pfile, warn_expansion_to_defined))
+        cpp_pedwarning (pfile, CPP_W_EXPANSION_TO_DEFINED,
+                       "this use of \"defined\" may not be portable");
+      is_defined = _cpp_defined_macro_p (node);
+      if (!_cpp_maybe_notify_macro_use (pfile, node, token->src_loc))
+       /* It wasn't a macro after all.  */
+       is_defined = false;
       _cpp_mark_macro_used (node);
-      if (!(node->flags & NODE_USED))
-       {
-         node->flags |= NODE_USED;
-         if (node->type == NT_MACRO)
-           {
-             if ((node->flags & NODE_BUILTIN)
-                 && pfile->cb.user_builtin_macro)
-               pfile->cb.user_builtin_macro (pfile, node);
-             if (pfile->cb.used_define)
-               pfile->cb.used_define (pfile, pfile->directive_line, node);
-           }
-         else
-           {
-             if (pfile->cb.used_undef)
-               pfile->cb.used_undef (pfile, pfile->directive_line, node);
-           }
-       }
 
       /* A possible controlling macro of the form #if !defined ().
         _cpp_parse_expr checks there was no other junk on the line.  */
@@ -914,14 +1090,13 @@ parse_defined (cpp_reader *pfile)
   pfile->state.prevent_expansion--;
 
   /* Do not treat conditional macros as being defined.  This is due to the
-     powerpc and spu ports using conditional macros for 'vector', 'bool', and
-     'pixel' to act as conditional keywords.  This messes up tests like #ifndef
+     powerpc port using conditional macros for 'vector', 'bool', and 'pixel'
+     to act as conditional keywords.  This messes up tests like #ifndef
      bool.  */
   result.unsignedp = false;
   result.high = 0;
   result.overflow = false;
-  result.low = (node && node->type == NT_MACRO
-               && (node->flags & NODE_CONDITIONAL) == 0);
+  result.low = is_defined;
   return result;
 }
 
@@ -930,7 +1105,7 @@ parse_defined (cpp_reader *pfile)
    operators).  */
 static cpp_num
 eval_token (cpp_reader *pfile, const cpp_token *token,
-           source_location virtual_location)
+           location_t virtual_location)
 {
   cpp_num result;
   unsigned int temp;
@@ -970,6 +1145,7 @@ eval_token (cpp_reader *pfile, const cpp_token *token,
     case CPP_CHAR:
     case CPP_CHAR16:
     case CPP_CHAR32:
+    case CPP_UTF8CHAR:
       {
        cppchar_t cc = cpp_interpret_charconst (pfile, token,
                                                &temp, &unsignedp);
@@ -1004,7 +1180,7 @@ eval_token (cpp_reader *pfile, const cpp_token *token,
          result.low = 0;
          if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
            cpp_warning_with_line (pfile, CPP_W_UNDEF, virtual_location, 0,
-                                  "\"%s\" is not defined",
+                                  "\"%s\" is not defined, evaluates to 0",
                                   NODE_NAME (token->val.node.node));
        }
       break;
@@ -1122,7 +1298,7 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
   struct op *top = pfile->op_stack;
   unsigned int lex_count;
   bool saw_leading_not, want_value = true;
-  source_location virtual_location = 0;
+  location_t virtual_location = 0;
 
   pfile->state.skip_eval = 0;
 
@@ -1151,6 +1327,7 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
        case CPP_WCHAR:
        case CPP_CHAR16:
        case CPP_CHAR32:
+       case CPP_UTF8CHAR:
        case CPP_NAME:
        case CPP_HASH:
          if (!want_value)
@@ -1786,7 +1963,22 @@ num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
 
       /* Arithmetic.  */
     case CPP_MINUS:
-      rhs = num_negate (rhs, precision);
+      result.low = lhs.low - rhs.low;
+      result.high = lhs.high - rhs.high;
+      if (result.low > lhs.low)
+       result.high--;
+      result.unsignedp = lhs.unsignedp || rhs.unsignedp;
+      result.overflow = false;
+
+      result = num_trim (result, precision);
+      if (!result.unsignedp)
+       {
+         bool lhsp = num_positive (lhs, precision);
+         result.overflow = (lhsp != num_positive (rhs, precision)
+                            && lhsp != num_positive (result, precision));
+       }
+      return result;
+
     case CPP_PLUS:
       result.low = lhs.low + rhs.low;
       result.high = lhs.high + rhs.high;
@@ -1808,8 +2000,8 @@ num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
     default: /* case CPP_COMMA: */
       if (CPP_PEDANTIC (pfile) && (!CPP_OPTION (pfile, c99)
                                   || !pfile->state.skip_eval))
-       cpp_error (pfile, CPP_DL_PEDWARN,
-                  "comma operator in operand of #if");
+       cpp_pedwarning (pfile, CPP_W_PEDANTIC,
+                       "comma operator in operand of #if");
       lhs = rhs;
       break;
     }
@@ -1904,7 +2096,7 @@ num_mul (cpp_reader *pfile, cpp_num lhs, cpp_num rhs)
 
 static cpp_num
 num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op,
-           source_location location)
+           location_t location)
 {
   cpp_num result, sub;
   cpp_num_part mask;
@@ -2000,3 +2192,4 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op,
 
   return lhs;
 }
+