diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 5d4564a..cd1b276 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -8983,7 +8983,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
 	      break;
 	    case RID_COMPLEX:
 	      dupe = specs->complex_p;
-	      if (!flag_isoc99 && !in_system_header)
+	      if (!flag_isoc99 && !in_system_header_at (loc))
 		pedwarn (loc, OPT_pedantic,
 			 "ISO C90 does not support complex types");
 	      if (specs->typespec_word == cts_void)
@@ -9508,10 +9508,12 @@ declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
    specifiers with any other type specifier to determine the resulting
    type.  This is where ISO C checks on complex types are made, since
    "_Complex long" is a prefix of the valid ISO C type "_Complex long
-   double".  */
+   double".  FIRST_TOKEN_LOC is the location of the first token of
+   the first specifier of SPECS.  */
 
 struct c_declspecs *
-finish_declspecs (struct c_declspecs *specs)
+finish_declspecs (struct c_declspecs *specs,
+		  location_t first_token_loc)
 {
   /* If a type was specified as a whole, we have no modifiers and are
      done.  */
@@ -9536,9 +9538,11 @@ finish_declspecs (struct c_declspecs *specs)
     {
       if (specs->saturating_p)
 	{
-	  error ("%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
+	  error_at (first_token_loc,
+		    "%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
 	  if (!targetm.fixed_point_supported_p ())
-	    error ("fixed-point types not supported for this target");
+	    error_at (first_token_loc,
+		      "fixed-point types not supported for this target");
 	  specs->typespec_word = cts_fract;
 	}
       else if (specs->long_p || specs->short_p
@@ -9549,7 +9553,7 @@ finish_declspecs (struct c_declspecs *specs)
       else if (specs->complex_p)
 	{
 	  specs->typespec_word = cts_double;
-	  pedwarn (input_location, OPT_pedantic,
+	  pedwarn (first_token_loc, OPT_pedantic,
 		   "ISO C does not support plain %<complex%> meaning "
 		   "%<double complex%>");
 	}
@@ -9594,7 +9598,7 @@ finish_declspecs (struct c_declspecs *specs)
 	specs->type = char_type_node;
       if (specs->complex_p)
 	{
-	  pedwarn (input_location, OPT_pedantic,
+	  pedwarn (first_token_loc, OPT_pedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
@@ -9607,7 +9611,7 @@ finish_declspecs (struct c_declspecs *specs)
 		     : int128_integer_type_node);
       if (specs->complex_p)
 	{
-	  pedwarn (input_location, OPT_pedantic,
+	  pedwarn (first_token_loc, OPT_pedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
@@ -9633,7 +9637,7 @@ finish_declspecs (struct c_declspecs *specs)
 		       : integer_type_node);
       if (specs->complex_p)
 	{
-	  pedwarn (input_location, OPT_pedantic,
+	  pedwarn (first_token_loc, OPT_pedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index be83b61..ca088a8 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -314,7 +314,7 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
 
     case CPP_NUMBER:
       {
-	unsigned int flags = cpp_classify_number (parse_in, tok);
+	unsigned int flags = cpp_classify_number (parse_in, tok, *loc);
 
 	switch (flags & CPP_N_CATEGORY)
 	  {
@@ -397,7 +397,7 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
 
 	*cpp_spell_token (parse_in, tok, name, true) = 0;
 
-	error ("stray %qs in program", name);
+	error_at (*loc, "stray %qs in program", name);
       }
 
       goto retry;
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index ff376df..3544d87 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -1479,7 +1479,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       c_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
-  finish_declspecs (specs);
+  finish_declspecs (specs, here);
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
       if (empty_ok)
@@ -2579,7 +2579,7 @@ c_parser_struct_declaration (c_parser *parser)
       c_parser_error (parser, "expected specifier-qualifier-list");
       return NULL_TREE;
     }
-  finish_declspecs (specs);
+  finish_declspecs (specs, decl_loc);
   if (c_parser_next_token_is (parser, CPP_SEMICOLON)
       || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
@@ -3242,6 +3242,8 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
   tree prefix_attrs;
   tree postfix_attrs = NULL_TREE;
   bool dummy = false;
+  location_t first_token_loc = c_parser_peek_token (parser)->location;
+
   if (!c_parser_next_token_starts_declspecs (parser))
     {
       c_token *token = c_parser_peek_token (parser);
@@ -3268,7 +3270,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
       attrs = NULL_TREE;
     }
   c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
-  finish_declspecs (specs);
+  finish_declspecs (specs, first_token_loc);
   pending_xref_error ();
   prefix_attrs = specs->attrs;
   specs->attrs = NULL_TREE;
@@ -3561,6 +3563,8 @@ c_parser_type_name (c_parser *parser)
   struct c_declarator *declarator;
   struct c_type_name *ret;
   bool dummy = false;
+  location_t here = c_parser_peek_token (parser)->location;
+
   c_parser_declspecs (parser, specs, false, true, true, cla_prefer_type);
   if (!specs->declspecs_seen_p)
     {
@@ -3570,7 +3574,7 @@ c_parser_type_name (c_parser *parser)
   if (specs->type != error_mark_node)
     {
       pending_xref_error ();
-      finish_declspecs (specs);
+      finish_declspecs (specs, here);
     }
   declarator = c_parser_declarator (parser,
 				    specs->typespec_kind != ctsk_none,
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index cda5d06..79231cb 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -494,7 +494,7 @@ extern struct c_declspecs *declspecs_add_scspec (struct c_declspecs *, tree);
 extern struct c_declspecs *declspecs_add_attrs (struct c_declspecs *, tree);
 extern struct c_declspecs *declspecs_add_addrspace (struct c_declspecs *,
 						    addr_space_t);
-extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
+extern struct c_declspecs *finish_declspecs (struct c_declspecs *, location_t);
 
 /* in c-objc-common.c */
 extern bool c_objc_common_init (void);
diff --git a/gcc/testsuite/gcc.dg/cpp/syshdr3.c b/gcc/testsuite/gcc.dg/cpp/syshdr3.c
new file mode 100644
index 0000000..8850410
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/syshdr3.c
@@ -0,0 +1,16 @@
+/* Contributed by Dodji Seketeli <dodji@redhat.com> */
+/* Origin: PR preprocessor/7263 */
+/* { dg-options "-pedantic -std=c89 -ftrack-macro-expansion=1" } */
+/* { dg-do compile } */
+
+/* This tests the proprer suppression of warning coming from macro
+   defined in system headers and expanded in a non-system header
+   location.  */
+#include "syshdr3.h"
+
+_Complex c = _Complex_I + _Complex_I; /* These macros are defined in
+					 system header so we should
+					 have no warning here.  */
+U_LL u = ONE_ULL; /* Likewise here.  */
+
+unsigned long long v = 1ULL; /* { dg-warning "long long" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/syshdr3.h b/gcc/testsuite/gcc.dg/cpp/syshdr3.h
new file mode 100644
index 0000000..e5d502a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/syshdr3.h
@@ -0,0 +1,7 @@
+#pragma GCC system_header
+
+#define _Complex __complex__
+#define _Complex_I 1.0iF
+
+#define U_LL unsigned long long
+#define ONE_ULL 1ULL
diff --git a/gcc/testsuite/gcc.dg/nofixed-point-2.c b/gcc/testsuite/gcc.dg/nofixed-point-2.c
index 5b2f209..8442a19 100644
--- a/gcc/testsuite/gcc.dg/nofixed-point-2.c
+++ b/gcc/testsuite/gcc.dg/nofixed-point-2.c
@@ -20,10 +20,10 @@ f3 (void)
   return 0k;			/* { dg-error "not supported" "reject fixed-point" } */
 }
 
-_Sat
-f4 (void)			/* { dg-error "not supported" "reject fixed-point" } */
+_Sat                            /* { dg-error "not supported" "reject fixed-point" } */
+f4 (void)
 {
   return 0k;			/* { dg-error "not supported" "reject fixed-point" } */
 }
 
-/* { dg-error "is used without" "" { target *-*-* } 24 } */
+/* { dg-error "is used without" "" { target *-*-* } 23 } */
diff --git a/libcpp/expr.c b/libcpp/expr.c
index 3c36127..b7b4e1a 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -59,7 +59,7 @@ 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);
@@ -76,6 +76,12 @@ 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
@@ -223,7 +229,8 @@ interpret_int_suffix (const uchar *s, size_t len)
    floating point, or invalid), radix (decimal, octal, hexadecimal),
    and type suffixes.  */
 unsigned int
-cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
+cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
+		     source_location virtual_location)
 {
   const uchar *str = token->val.str.text;
   const uchar *limit;
@@ -279,7 +286,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')))
@@ -307,8 +315,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
@@ -321,26 +329,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)
 	{
@@ -349,21 +360,22 @@ 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);
       if (result == 0)
 	{
-	  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;
 	}
 
@@ -371,33 +383,33 @@ 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;
     }
@@ -406,9 +418,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
       result = interpret_int_suffix (str, limit - str);
       if (result == 0)
 	{
-	  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;
 	}
 
@@ -421,9 +433,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
@@ -434,9 +447,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;
@@ -444,11 +459,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;
@@ -736,7 +751,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;
@@ -748,18 +764,18 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
   switch (token->type)
     {
     case CPP_NUMBER:
-      temp = cpp_classify_number (pfile, token);
+      temp = cpp_classify_number (pfile, token, virtual_location);
       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:
@@ -806,8 +822,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;
 
@@ -817,11 +834,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;
@@ -923,6 +941,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;
 
@@ -939,9 +958,10 @@ _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)
 	{
@@ -954,10 +974,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 (virtual_location,
+			      "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, virtual_location);
 	  continue;
 
 	case CPP_NOT:
@@ -974,8 +995,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;
 	}
 
@@ -983,27 +1005,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 (virtual_location,
+			      "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);
@@ -1028,7 +1055,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
@@ -1045,7 +1073,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
@@ -1056,8 +1084,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.  */
     }
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 825bf2f..b88c7d7 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -831,7 +831,8 @@ struct cpp_num
 
 /* Classify a CPP_NUMBER token.  The return value is a combination of
    the flags from the above sets.  */
-extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *);
+extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *,
+				     source_location);
 
 /* Evaluate a token classified as category CPP_N_INTEGER.  */
 extern cpp_num cpp_interpret_integer (cpp_reader *, const cpp_token *,
