Update to 4.8.2.
[platform/upstream/gcc48.git] / libcpp / expr.c
index d56e56a..46d9fd3 100644 (file)
@@ -1,6 +1,5 @@
 /* Parse C expressions for cpplib.
-   Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
-   2002, 2004, 2008, 2009, 2010, 2011 Free Software Foundation.
+   Copyright (C) 1987-2013 Free Software Foundation, Inc.
    Contributed by Per Bothner, 1994.
 
 This program is free software; you can redistribute it and/or modify it
@@ -59,10 +58,10 @@ 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 *);
+static cpp_num eval_token (cpp_reader *, const cpp_token *, source_location);
 static struct op *reduce (cpp_reader *, struct op *, enum cpp_ttype);
-static unsigned int interpret_float_suffix (const uchar *, size_t);
-static unsigned int interpret_int_suffix (const uchar *, size_t);
+static unsigned int interpret_float_suffix (cpp_reader *, const uchar *, size_t);
+static unsigned int interpret_int_suffix (cpp_reader *, const uchar *, size_t);
 static void check_promotion (cpp_reader *, const struct op *);
 
 /* Token type abuse to create unary plus and minus operators.  */
@@ -76,12 +75,18 @@ static void check_promotion (cpp_reader *, const struct op *);
 #define SYNTAX_ERROR2(msgid, arg) \
   do { cpp_error (pfile, CPP_DL_ERROR, msgid, arg); goto syntax_error; } \
   while(0)
+#define SYNTAX_ERROR_AT(loc, msgid) \
+  do { cpp_error_with_line (pfile, CPP_DL_ERROR, (loc), 0, msgid); goto syntax_error; } \
+  while(0)
+#define SYNTAX_ERROR2_AT(loc, msgid, arg)                                      \
+  do { cpp_error_with_line (pfile, CPP_DL_ERROR, (loc), 0, msgid, arg); goto syntax_error; } \
+  while(0)
 
 /* 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.  */
 static unsigned int
-interpret_float_suffix (const uchar *s, size_t len)
+interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 {
   size_t flags;
   size_t f, d, l, w, q, i;
@@ -109,54 +114,58 @@ interpret_float_suffix (const uchar *s, size_t len)
       }
     }
 
-  /* Recognize a fixed-point suffix.  */
-  switch (s[len-1])
-    {
-    case 'k': case 'K': flags = CPP_N_ACCUM; break;
-    case 'r': case 'R': flags = CPP_N_FRACT; break;
-    default: break;
-    }
-
-  /* Continue processing a fixed-point suffix.  The suffix is case
-     insensitive except for ll or LL.  Order is significant.  */
-  if (flags)
+  if (CPP_OPTION (pfile, ext_numeric_literals))
     {
-      if (len == 1)
-       return flags;
-      len--;
+      /* Recognize a fixed-point suffix.  */
+      if (len != 0)
+       switch (s[len-1])
+         {
+         case 'k': case 'K': flags = CPP_N_ACCUM; break;
+         case 'r': case 'R': flags = CPP_N_FRACT; break;
+         default: break;
+         }
 
-      if (*s == 'u' || *s == 'U')
+      /* Continue processing a fixed-point suffix.  The suffix is case
+        insensitive except for ll or LL.  Order is significant.  */
+      if (flags)
        {
-         flags |= CPP_N_UNSIGNED;
          if (len == 1)
            return flags;
          len--;
-         s++;
-        }
 
-      switch (*s)
-      {
-      case 'h': case 'H':
-       if (len == 1)
-         return flags |= CPP_N_SMALL;
-       break;
-      case 'l':
-       if (len == 1)
-         return flags |= CPP_N_MEDIUM;
-       if (len == 2 && s[1] == 'l')
-         return flags |= CPP_N_LARGE;
-       break;
-      case 'L':
-       if (len == 1)
-         return flags |= CPP_N_MEDIUM;
-       if (len == 2 && s[1] == 'L')
-         return flags |= CPP_N_LARGE;
-       break;
-      default:
-       break;
-      }
-      /* Anything left at this point is invalid.  */
-      return 0;
+         if (*s == 'u' || *s == 'U')
+           {
+             flags |= CPP_N_UNSIGNED;
+             if (len == 1)
+               return flags;
+             len--;
+             s++;
+            }
+
+         switch (*s)
+         {
+         case 'h': case 'H':
+           if (len == 1)
+             return flags |= CPP_N_SMALL;
+           break;
+         case 'l':
+           if (len == 1)
+             return flags |= CPP_N_MEDIUM;
+           if (len == 2 && s[1] == 'l')
+             return flags |= CPP_N_LARGE;
+           break;
+         case 'L':
+           if (len == 1)
+             return flags |= CPP_N_MEDIUM;
+           if (len == 2 && s[1] == 'L')
+             return flags |= CPP_N_LARGE;
+           break;
+         default:
+           break;
+         }
+         /* Anything left at this point is invalid.  */
+         return 0;
+       }
     }
 
   /* In any remaining valid suffix, the case and order don't matter.  */
@@ -177,6 +186,12 @@ interpret_float_suffix (const uchar *s, size_t len)
   if (f + d + l + w + q > 1 || i > 1)
     return 0;
 
+  if (i && !CPP_OPTION (pfile, ext_numeric_literals))
+    return 0;
+
+  if ((w || q) && !CPP_OPTION (pfile, ext_numeric_literals))
+    return 0;
+
   return ((i ? CPP_N_IMAGINARY : 0)
          | (f ? CPP_N_SMALL :
             d ? CPP_N_MEDIUM :
@@ -187,16 +202,16 @@ interpret_float_suffix (const uchar *s, size_t len)
 
 /* Return the classification flags for a float suffix.  */
 unsigned int
-cpp_interpret_float_suffix (const char *s, size_t len)
+cpp_interpret_float_suffix (cpp_reader *pfile, const char *s, size_t len)
 {
-  return interpret_float_suffix ((const unsigned char *)s, len);
+  return interpret_float_suffix (pfile, (const unsigned char *)s, len);
 }
 
 /* Subroutine of cpp_classify_number.  S points to an integer suffix
    of length LEN, possibly zero. Returns 0 for an invalid suffix, or a
    flag vector describing the suffix.  */
 static unsigned int
-interpret_int_suffix (const uchar *s, size_t len)
+interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 {
   size_t u, l, i;
 
@@ -220,6 +235,9 @@ interpret_int_suffix (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;
+
   return ((i ? CPP_N_IMAGINARY : 0)
          | (u ? CPP_N_UNSIGNED : 0)
          | ((l == 0) ? CPP_N_SMALL
@@ -228,9 +246,9 @@ interpret_int_suffix (const uchar *s, size_t len)
 
 /* Return the classification flags for an int suffix.  */
 unsigned int
-cpp_interpret_int_suffix (const char *s, size_t len)
+cpp_interpret_int_suffix (cpp_reader *pfile, const char *s, size_t len)
 {
-  return interpret_int_suffix ((const unsigned char *)s, len);
+  return interpret_int_suffix (pfile, (const unsigned char *)s, len);
 }
 
 /* Return the string type corresponding to the the input user-defined string
@@ -358,11 +376,18 @@ cpp_get_userdef_suffix (const cpp_token *tok)
 
 /* Categorize numeric constants according to their field (integer,
    floating point, or invalid), radix (decimal, octal, hexadecimal),
-   and type suffixes.  In C++0X if UD_SUFFIX is non null it will be
-   assigned any unrecognized suffix for a user-defined literal.  */
+   and type suffixes.
+
+   TOKEN is the token that represents the numeric constant to
+   classify.
+
+   In C++0X if UD_SUFFIX is non null it will be assigned
+   any unrecognized suffix for a user-defined literal.
+
+   VIRTUAL_LOCATION is the virtual location for TOKEN.  */
 unsigned int
 cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
-                    const char **ud_suffix)
+                    const char **ud_suffix, source_location virtual_location)
 {
   const uchar *str = token->val.str.text;
   const uchar *limit;
@@ -421,7 +446,8 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
          if (float_flag == NOT_FLOAT)
            float_flag = AFTER_POINT;
          else
-           SYNTAX_ERROR ("too many decimal points in number");
+           SYNTAX_ERROR_AT (virtual_location,
+                            "too many decimal points in number");
        }
       else if ((radix <= 10 && (c == 'e' || c == 'E'))
               || (radix == 16 && (c == 'p' || c == 'P')))
@@ -440,7 +466,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
   /* The suffix may be for decimal fixed-point constants without exponent.  */
   if (radix != 16 && float_flag == NOT_FLOAT)
     {
-      result = interpret_float_suffix (str, limit - str);
+      result = interpret_float_suffix (pfile, str, limit - str);
       if ((result & CPP_N_FRACT) || (result & CPP_N_ACCUM))
        {
          result |= CPP_N_FLOATING;
@@ -449,8 +475,8 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
            radix = 10;
 
          if (CPP_PEDANTIC (pfile))
-           cpp_error (pfile, CPP_DL_PEDWARN,
-                      "fixed-point constants are a GCC extension");
+           cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                                "fixed-point constants are a GCC extension");
          goto syntax_ok;
        }
       else
@@ -463,26 +489,29 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
   if (max_digit >= radix)
     {
       if (radix == 2)
-       SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit);
+       SYNTAX_ERROR2_AT (virtual_location,
+                         "invalid digit \"%c\" in binary constant", '0' + max_digit);
       else
-       SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
+       SYNTAX_ERROR2_AT (virtual_location,
+                         "invalid digit \"%c\" in octal constant", '0' + max_digit);
     }
 
   if (float_flag != NOT_FLOAT)
     {
       if (radix == 2)
        {
-         cpp_error (pfile, CPP_DL_ERROR,
-                    "invalid prefix \"0b\" for floating constant");
+         cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+                              "invalid prefix \"0b\" for floating constant");
          return CPP_N_INVALID;
        }
 
       if (radix == 16 && !seen_digit)
-       SYNTAX_ERROR ("no digits in hexadecimal floating constant");
+       SYNTAX_ERROR_AT (virtual_location,
+                        "no digits in hexadecimal floating constant");
 
       if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
-       cpp_error (pfile, CPP_DL_PEDWARN,
-                  "use of C99 hexadecimal floating constant");
+       cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                            "use of C99 hexadecimal floating constant");
 
       if (float_flag == AFTER_EXPON)
        {
@@ -491,16 +520,17 @@ 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 ("exponent has no digits");
+           SYNTAX_ERROR_AT (virtual_location, "exponent has no digits");
 
          do
            str++;
          while (ISDIGIT (*str));
        }
       else if (radix == 16)
-       SYNTAX_ERROR ("hexadecimal floating constants require an exponent");
+       SYNTAX_ERROR_AT (virtual_location,
+                        "hexadecimal floating constants require an exponent");
 
-      result = interpret_float_suffix (str, limit - str);
+      result = interpret_float_suffix (pfile, str, limit - str);
       if (result == 0)
        {
          if (CPP_OPTION (pfile, user_literals))
@@ -511,9 +541,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
            }
          else
            {
-             cpp_error (pfile, CPP_DL_ERROR,
-                        "invalid suffix \"%.*s\" on floating constant",
-                        (int) (limit - str), str);
+             cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+                                  "invalid suffix \"%.*s\" on floating constant",
+                                  (int) (limit - str), str);
              return CPP_N_INVALID;
            }
        }
@@ -522,39 +552,39 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
       if (limit != str
          && CPP_WTRADITIONAL (pfile)
          && ! cpp_sys_macro_p (pfile))
-       cpp_warning (pfile, CPP_W_TRADITIONAL,
-                    "traditional C rejects the \"%.*s\" suffix",
-                    (int) (limit - str), str);
+       cpp_warning_with_line (pfile, CPP_W_TRADITIONAL, virtual_location, 0,
+                              "traditional C rejects the \"%.*s\" suffix",
+                              (int) (limit - str), str);
 
       /* A suffix for double is a GCC extension via decimal float support.
         If the suffix also specifies an imaginary value we'll catch that
         later.  */
       if ((result == CPP_N_MEDIUM) && CPP_PEDANTIC (pfile))
-       cpp_error (pfile, CPP_DL_PEDWARN,
-                  "suffix for double constant is a GCC extension");
+       cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                            "suffix for double constant is a GCC extension");
 
       /* Radix must be 10 for decimal floats.  */
       if ((result & CPP_N_DFLOAT) && radix != 10)
         {
-          cpp_error (pfile, CPP_DL_ERROR,
-                     "invalid suffix \"%.*s\" with hexadecimal floating constant",
-                     (int) (limit - str), str);
+          cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+                              "invalid suffix \"%.*s\" with hexadecimal floating constant",
+                              (int) (limit - str), str);
           return CPP_N_INVALID;
         }
 
       if ((result & (CPP_N_FRACT | CPP_N_ACCUM)) && CPP_PEDANTIC (pfile))
-       cpp_error (pfile, CPP_DL_PEDWARN,
-                  "fixed-point constants are a GCC extension");
+       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 (pfile, CPP_DL_PEDWARN,
-                  "decimal float constants are a GCC extension");
+       cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                            "decimal float constants are a GCC extension");
 
       result |= CPP_N_FLOATING;
     }
   else
     {
-      result = interpret_int_suffix (str, limit - str);
+      result = interpret_int_suffix (pfile, str, limit - str);
       if (result == 0)
        {
          if (CPP_OPTION (pfile, user_literals))
@@ -565,9 +595,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
            }
          else
            {
-             cpp_error (pfile, CPP_DL_ERROR,
-                        "invalid suffix \"%.*s\" on integer constant",
-                        (int) (limit - str), str);
+             cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+                                  "invalid suffix \"%.*s\" on integer constant",
+                                  (int) (limit - str), str);
              return CPP_N_INVALID;
            }
        }
@@ -581,9 +611,10 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
                       && CPP_OPTION (pfile, cpp_warn_long_long);
 
          if (u_or_i || large)
-           cpp_warning (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL,
-                        "traditional C rejects the \"%.*s\" suffix",
-                        (int) (limit - str), str);
+           cpp_warning_with_line (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL,
+                                  virtual_location, 0,
+                                  "traditional C rejects the \"%.*s\" suffix",
+                                  (int) (limit - str), str);
        }
 
       if ((result & CPP_N_WIDTH) == CPP_N_LARGE
@@ -594,9 +625,11 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
                                : N_("use of C99 long long integer constant");
 
          if (CPP_OPTION (pfile, c99))
-            cpp_warning (pfile, CPP_W_LONG_LONG, message);
+            cpp_warning_with_line (pfile, CPP_W_LONG_LONG, virtual_location,
+                                  0, message);
           else
-            cpp_pedwarning (pfile, CPP_W_LONG_LONG, message);
+            cpp_pedwarning_with_line (pfile, CPP_W_LONG_LONG,
+                                     virtual_location, 0, message);
         }
 
       result |= CPP_N_INTEGER;
@@ -604,11 +637,11 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
 
  syntax_ok:
   if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
-    cpp_error (pfile, CPP_DL_PEDWARN,
-              "imaginary constants are a GCC extension");
+    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 (pfile, CPP_DL_PEDWARN,
-              "binary constants are a GCC extension");
+    cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                        "binary constants are a GCC extension");
 
   if (radix == 10)
     result |= CPP_N_DECIMAL;
@@ -896,7 +929,8 @@ parse_defined (cpp_reader *pfile)
    number or character constant, or the result of the "defined" or "#"
    operators).  */
 static cpp_num
-eval_token (cpp_reader *pfile, const cpp_token *token)
+eval_token (cpp_reader *pfile, const cpp_token *token,
+           source_location virtual_location)
 {
   cpp_num result;
   unsigned int temp;
@@ -908,21 +942,21 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
   switch (token->type)
     {
     case CPP_NUMBER:
-      temp = cpp_classify_number (pfile, token, NULL);
+      temp = cpp_classify_number (pfile, token, NULL, virtual_location);
       if (temp & CPP_N_USERDEF)
        cpp_error (pfile, CPP_DL_ERROR,
                   "user-defined literal in preprocessor expression");
       switch (temp & CPP_N_CATEGORY)
        {
        case CPP_N_FLOATING:
-         cpp_error (pfile, CPP_DL_ERROR,
-                    "floating constant in preprocessor expression");
+         cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+                              "floating constant in preprocessor expression");
          break;
        case CPP_N_INTEGER:
          if (!(temp & CPP_N_IMAGINARY))
            return cpp_interpret_integer (pfile, token, temp);
-         cpp_error (pfile, CPP_DL_ERROR,
-                    "imaginary number in preprocessor expression");
+         cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+                              "imaginary number in preprocessor expression");
          break;
 
        case CPP_N_INVALID:
@@ -969,8 +1003,9 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
          result.high = 0;
          result.low = 0;
          if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
-           cpp_warning (pfile, CPP_W_UNDEF, "\"%s\" is not defined",
-                        NODE_NAME (token->val.node.node));
+           cpp_warning_with_line (pfile, CPP_W_UNDEF, virtual_location, 0,
+                                  "\"%s\" is not defined",
+                                  NODE_NAME (token->val.node.node));
        }
       break;
 
@@ -980,11 +1015,12 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
          /* A pedantic warning takes precedence over a deprecated
             warning here.  */
          if (CPP_PEDANTIC (pfile))
-           cpp_error (pfile, CPP_DL_PEDWARN,
-                      "assertions are a GCC extension");
+           cpp_error_with_line (pfile, CPP_DL_PEDWARN,
+                                virtual_location, 0,
+                                "assertions are a GCC extension");
          else if (CPP_OPTION (pfile, cpp_warn_deprecated))
-           cpp_warning (pfile, CPP_W_DEPRECATED,
-                        "assertions are a deprecated extension");
+           cpp_warning_with_line (pfile, CPP_W_DEPRECATED, virtual_location, 0,
+                                  "assertions are a deprecated extension");
        }
       _cpp_test_assertion (pfile, &temp);
       result.high = 0;
@@ -1086,6 +1122,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;
 
   pfile->state.skip_eval = 0;
 
@@ -1102,9 +1139,9 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
       struct op op;
 
       lex_count++;
-      op.token = cpp_get_token (pfile);
+      op.token = cpp_get_token_with_location (pfile, &virtual_location);
       op.op = op.token->type;
-      op.loc = op.token->src_loc;
+      op.loc = virtual_location;
 
       switch (op.op)
        {
@@ -1117,10 +1154,11 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
        case CPP_NAME:
        case CPP_HASH:
          if (!want_value)
-           SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
-                          cpp_token_as_text (pfile, op.token));
+           SYNTAX_ERROR2_AT (op.loc,
+                             "missing binary operator before token \"%s\"",
+                             cpp_token_as_text (pfile, op.token));
          want_value = false;
-         top->value = eval_token (pfile, op.token);
+         top->value = eval_token (pfile, op.token, op.loc);
          continue;
 
        case CPP_NOT:
@@ -1137,8 +1175,9 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
 
        default:
          if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ)
-           SYNTAX_ERROR2 ("token \"%s\" is not valid in preprocessor expressions",
-                          cpp_token_as_text (pfile, op.token));
+           SYNTAX_ERROR2_AT (op.loc,
+                             "token \"%s\" is not valid in preprocessor expressions",
+                             cpp_token_as_text (pfile, op.token));
          break;
        }
 
@@ -1146,27 +1185,32 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
       if (optab[op.op].flags & NO_L_OPERAND)
        {
          if (!want_value)
-           SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
-                          cpp_token_as_text (pfile, op.token));
+           SYNTAX_ERROR2_AT (op.loc,
+                             "missing binary operator before token \"%s\"",
+                             cpp_token_as_text (pfile, op.token));
        }
       else if (want_value)
        {
          /* We want a number (or expression) and haven't got one.
             Try to emit a specific diagnostic.  */
          if (op.op == CPP_CLOSE_PAREN && top->op == CPP_OPEN_PAREN)
-           SYNTAX_ERROR ("missing expression between '(' and ')'");
+           SYNTAX_ERROR_AT (op.loc,
+                            "missing expression between '(' and ')'");
 
          if (op.op == CPP_EOF && top->op == CPP_EOF)
-           SYNTAX_ERROR2 ("%s with no expression", is_if ? "#if" : "#elif");
+           SYNTAX_ERROR2_AT (op.loc,
+                             "%s with no expression", is_if ? "#if" : "#elif");
 
          if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
-           SYNTAX_ERROR2 ("operator '%s' has no right operand",
-                          cpp_token_as_text (pfile, top->token));
+           SYNTAX_ERROR2_AT (op.loc,
+                             "operator '%s' has no right operand",
+                             cpp_token_as_text (pfile, top->token));
          else if (op.op == CPP_CLOSE_PAREN || op.op == CPP_EOF)
            /* Complain about missing paren during reduction.  */;
          else
-           SYNTAX_ERROR2 ("operator '%s' has no left operand",
-                          cpp_token_as_text (pfile, op.token));
+           SYNTAX_ERROR2_AT (op.loc,
+                             "operator '%s' has no left operand",
+                             cpp_token_as_text (pfile, op.token));
        }
 
       top = reduce (pfile, top, op.op);
@@ -1191,7 +1235,8 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
          break;
        case CPP_COLON:
          if (top->op != CPP_QUERY)
-           SYNTAX_ERROR (" ':' without preceding '?'");
+           SYNTAX_ERROR_AT (op.loc,
+                            " ':' without preceding '?'");
          if (!num_zerop (top[-1].value)) /* Was '?' condition true?  */
            pfile->state.skip_eval++;
          else
@@ -1208,7 +1253,7 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
 
       top->op = op.op;
       top->token = op.token;
-      top->loc = op.token->src_loc;
+      top->loc = op.loc;
     }
 
   /* The controlling macro expression is only valid if we called lex 3
@@ -1219,8 +1264,9 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
 
   if (top != pfile->op_stack)
     {
-      cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in %s",
-                is_if ? "#if" : "#elif");
+      cpp_error_with_line (pfile, CPP_DL_ICE, top->loc, 0,
+                          "unbalanced stack in %s",
+                          is_if ? "#if" : "#elif");
     syntax_error:
       return false;  /* Return false on syntax error.  */
     }