Patchwork Make all usage of "input_location" be explicit

login
register
mail settings
Submitter David Malcolm
Date July 2, 2013, 3:24 p.m.
Message ID <1372778676.6455.34.camel@surprise>
Download mbox | patch
Permalink /patch/256454/
State New
Headers show

Comments

David Malcolm - July 2, 2013, 3:24 p.m.
As discussed in http://gcc.gnu.org/ml/gcc/2013-07/msg00008.html there
are four macros that create implicit uses of the input_location global.

I'm attaching a patch which removes these macros.

The patch converts most uses of the macros to a simple expansion of the
former definition, making the use of the input_location global explicit
(with line-length cleanups as necessary, sometimes introducing a
temporary when the same location is repeatedly used, etc).

In 7 places in c/c-decl.c there was a use of in_system_header where the
location was available in a different variable (or, at least, is used by
appropriately guarded code), allowing the removal of a use of
input_location in the patch.  Specifically:
  * (define_label): use the "location_t location" param
  * (grokdeclarator): use of "location_t loc" local:
    * line 5032: loc is used in the subsequent pedwarn_c99 calls
    * line 5299: loc is used in the directly guarded pedwarn call
    * line 5469: likewise
  * (build_enumerator): conversion of EXPR_LOC_OR_HERE to
    EXPR_LOC_OR_LOC using the "location_t loc" param
  * (store_parm_decls_newstyle):  conversion of in_system_header to use
    DECL_IN_SYSTEM_HEADER (fndecl), given that the guarded warning_at
    call uses DECL_SOURCE_LOCATION (fndecl)
  * (store_parm_decls_oldstyle): likewise.
  * (declspecs_add_type): use the "location_t loc" param

Successfully bootstrapped on x86_64-unknown-linux-gnu, and all testcases
show same results as an unpatched build (relative to r200588), with the
bizarre exception of:

  Tests that now work, but didn't before:

  g++.dg/ext/mv5.C -std=gnu++11 execution test
  g++.dg/ext/mv5.C -std=gnu++98 execution test

which appears to have been some kind of glitch in the *unpatched* build;
upon manually rerunning them they pass (32-core parallel build, maybe
some kind of race in the test harness?)

OK for trunk?

gcc/
2013-07-02  David Malcolm  <dmalcolm@redhat.com>

	* builtins.c (c_strlen): Remove use of EXPR_LOC_OR_HERE macro.
	* config/bfin/bfin.c (output_file_start): Remove use of
	input_filename macro.
	* gimplify.c (internal_get_tmp_var): Remove use of
	EXPR_LOC_OR_HERE macro.
	(shortcut_cond_expr)
	* input.h (input_line): Remove.
	(input_filename): Likewise.
	(in_system_header): Likewise.
	* tree-diagnostic.c (diagnostic_report_current_function): Remove
	use of input_filename macro.
	* tree.c (get_file_function_name): Likewise.
	* tree.h (EXPR_LOC_OR_HERE): Remove.

gcc/ada/
2013-07-02  David Malcolm  <dmalcolm@redhat.com>

	* gcc-interface/utils2.c (build_call_raise): Remove use of
	input_line macro.
	(build_call_raise_range): Likewise.
	(build_call_raise_column): Likewise.

gcc/c-family/
2013-07-02  David Malcolm  <dmalcolm@redhat.com>

	* c-common.c (unsafe_conversion_p): Remove use of
	EXPR_LOC_OR_HERE macro.
	(conversion_warning): Likewise.
	(warnings_for_convert_and_check): Likewise.
	(warn_for_collisions_1): Likewise.
	(shorten_compare): Likewise, and remove use of in_system_header
	macro, using the location from the former.
	* c-lex.c (dump_one_header): Remove use of input_filename macro.
	(cb_def_pragma): Remove use of in_system_header macro.
	(lex_string): Likewise.
	* c-pragma.c (handle_pragma_float_const_decimal64): Likewise.

gcc/c/
2013-07-02  David Malcolm  <dmalcolm@redhat.com>

	* c-decl.c (define_label): Remove use of in_system_header macro.
	(shadow_tag_warned): Likewise.
	(check_bitfield_type_and_width): Likewise.
	(grokdeclarator): Likewise.
	(grokparms): Likewise.
	(build_enumerator): Remove use of EXPR_LOC_OR_HERE macro.
	(store_parm_decls_newstyle): Remove use of in_system_header
	macro.
	(store_parm_decls_oldstyle): Likewise.
	(declspecs_add_type): Likewise.
	* c-parser.c (c_parser_set_source_position_from_token): Update
	comment.
	(c_parser_unary_expression): Remove use of in_system_header
	macro.
	* c-typeck.c: Likewise.

gcc/cp/
2013-07-02  David Malcolm  <dmalcolm@redhat.com>

	* call.c (build_integral_nontype_arg_conv): Remove use of
	EXPR_LOC_OR_HERE macro.
	(convert_like_real): Likewise.
	(convert_arg_to_ellipsis): Likewise.
	(build_cxx_call): Likewise.
	(perform_implicit_conversion_flags): Likewise.
	(initialize_reference): Likewise.
	* cvt.c (cp_convert_to_pointer): Likewise.
	(convert_to_reference): Likewise.
	(ocp_convert): Likewise.
	(convert_to_void): Likewise.
	* decl.c (pop_label): Update comment.
	(pop_switch): Remove use of EXPR_LOC_OR_HERE macro.
	(check_tag_decl): Remove use of in_system_header macro.
	(make_rtl_for_nonlocal_decl): Remove use of input_filename
	macro.
	(compute_array_index_type): Remove use of in_system_header
	macro.
	(grokdeclarator): Likewise.
	* error.c (dump_global_iord): Remove use of input_filename
	macro.
	(location_of): Remove use of EXPR_LOC_OR_HERE macro.
	(maybe_warn_cpp0x): Remove use of in_system_header macro.
	* init.c (build_new_1): Remove use of EXPR_LOC_OR_HERE macro.
	* lex.c (handle_pragma_interface): Remove use of input_filename
	macro.
	(handle_pragma_implementation): Likewise.
	(cxx_make_type): Likewise.
	(in_main_input_context): Likewise.
	* name-lookup.c (push_binding_level): Remove use of
	input_line macro.
	(leave_scope): Likewise.
	(resume_scope): Likewise.
	* parser.c (cp_parser_unqualified_id): Remove use of
	in_system_header macro.
	(cp_parser_cast_expression): Likewise.
	(cp_parser_declaration_seq_opt): Likewise.
	(cp_parser_enumerator_list): Likewise.
	(cp_parser_parameter_declaration_clause): Likewise.
	(cp_parser_exception_specification_opt): Likewise.
	* pt.c (convert_nontype_argument): Remove use of
	EXPR_LOC_OR_HERE macro.
	(push_tinst_level): Remove use of in_system_header macro.
	(tsubst_copy_and_build): Remove use of EXPR_LOC_OR_HERE
	macros.
	(do_decl_instantiation): Remove use of in_system_header macro.
	(do_type_instantiation): Likewise.
	* semantics.c (finish_call_expr): Remove use of EXPR_LOC_OR_HERE
	macro.
	(begin_class_definition): Remove use of input_filename macro.
	(cxx_eval_call_expression): Remove use of EXPR_LOC_OR_HERE
	macro.
	(cxx_eval_constant_expression): Likewise.
	(potential_constant_expression_1): Likewise.
	* typeck.c (decay_conversion): Likewise.
	(rationalize_conditional_expr): Likewise.
	(build_x_compound_expr_from_list): Likewise.
	(convert_for_assignment): Likewise.
	* typeck2.c (check_narrowing): Likewise.

gcc/fortran/
2013-07-02  David Malcolm  <dmalcolm@redhat.com>

	* trans.c (trans_runtime_error_vararg): Remove use of input_line
	macro.

gcc/java/
2013-07-02  David Malcolm  <dmalcolm@redhat.com>

	* class.c (maybe_layout_super_class): Update comment.
	* decl.c (java_add_stmt): Remove use of input_filename macro.
	* jcf-parse.c (set_source_filename): Remove use of
	input_filename macro.
	(parse_class_file): Remove use of input_line and input_filename
	macros.
	(java_parse_file): Remove use of input_filename macro.
Tom Tromey - July 2, 2013, 4:33 p.m.
>>>>> "David" == David Malcolm <dmalcolm@redhat.com> writes:

David> gcc/java/
David> 2013-07-02  David Malcolm  <dmalcolm@redhat.com>
David> 	* class.c (maybe_layout_super_class): Update comment.
David> 	* decl.c (java_add_stmt): Remove use of input_filename macro.
David> 	* jcf-parse.c (set_source_filename): Remove use of
David> 	input_filename macro.
David> 	(parse_class_file): Remove use of input_line and input_filename
David> 	macros.
David> 	(java_parse_file): Remove use of input_filename macro.

The java parts are ok.  Thanks for doing this.

I was curious about this bit:

David> diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
David> index 087cf6a..2942365 100644
David> --- a/gcc/tree-diagnostic.c
David> +++ b/gcc/tree-diagnostic.c
David> @@ -39,7 +39,8 @@ diagnostic_report_current_function (diagnostic_context *context,
David>  				    diagnostic_info *diagnostic)
David>  {
David>    diagnostic_report_current_module (context, diagnostic->location);
David> -  lang_hooks.print_error_function (context, input_filename, diagnostic);
David> +  lang_hooks.print_error_function (context, LOCATION_FILE (input_location),
David> +				   diagnostic);

I wonder why this needs to use input_location rather than
diagnostic->location.  (I don't actually know this code, maybe it is
obvious to those who do.)

Tom
David Malcolm - July 2, 2013, 7:13 p.m.
On Tue, 2013-07-02 at 10:33 -0600, Tom Tromey wrote:
> >>>>> "David" == David Malcolm <dmalcolm@redhat.com> writes:
> 
> David> gcc/java/
> David> 2013-07-02  David Malcolm  <dmalcolm@redhat.com>
> David> 	* class.c (maybe_layout_super_class): Update comment.
> David> 	* decl.c (java_add_stmt): Remove use of input_filename macro.
> David> 	* jcf-parse.c (set_source_filename): Remove use of
> David> 	input_filename macro.
> David> 	(parse_class_file): Remove use of input_line and input_filename
> David> 	macros.
> David> 	(java_parse_file): Remove use of input_filename macro.
> 
> The java parts are ok.  Thanks for doing this.

Thanks; should I wait a while in the hope of getting acceptance of the
full patch (and commit it all as one), or do it dir-by-dir?

> I was curious about this bit:
> 
> David> diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
> David> index 087cf6a..2942365 100644
> David> --- a/gcc/tree-diagnostic.c
> David> +++ b/gcc/tree-diagnostic.c
> David> @@ -39,7 +39,8 @@ diagnostic_report_current_function (diagnostic_context *context,
> David>  				    diagnostic_info *diagnostic)
> David>  {
> David>    diagnostic_report_current_module (context, diagnostic->location);
> David> -  lang_hooks.print_error_function (context, input_filename, diagnostic);
> David> +  lang_hooks.print_error_function (context, LOCATION_FILE (input_location),
> David> +				   diagnostic);
> 
> I wonder why this needs to use input_location rather than
> diagnostic->location.  (I don't actually know this code, maybe it is
> obvious to those who do.)

I didn't make this change out of conservatism, but I believe it's safe
(not yet tested though).  Here's the result of some archaeology (using
"git blame"):

1999-04-26: In toplev.c, report_error_function began ignoring its "const
char *file" parameter ("as it cannot be relied upon") in r26631 (aka
8f157cdcb53c2138e4cacf4f309b6ff2ac27f257), instead using input_filename,
which at that time was a simple global defined in that file ("char
*input_filename;").

1999-12-18: report_error_function was moved from toplev.c to the then
new diagnostic.c in r31003 (aka
076f8fe18a6ae1eaccafd446bf81351d635f2fae).

2001-06-28: now in diagnostic.c, report_error_function's global
print_error_function callback gained a "diagnostic_context *" param in
r43638 (aka b506dc01ea131f8a9790cc7734fc45c718e9d688), passing it
global_dc.

2002-03-31: the "print_error_function" callback used by
report_error_function was moved into langhooks in r51672 (aka
6c7ff02573fc7155660a0ca60ed96b11963c1271)

2002-06-04:  report_error_function was renamed to
diagnostic_report_current_function in r54291 (aka commit
25e2ffe1cbed24a0896b73bf2ca85571160f4cb1)

2007-09-27: now named diagnostic_report_current_function, the function
gained its 2nd argument (the diagnostic) in r128830 (aka commit
b8c23db329da6afaebde201237f25c583ba61885); the relevant hunk looked like
this:
 void
-diagnostic_report_current_function (diagnostic_context *context)
+diagnostic_report_current_function (diagnostic_context *context,
+                                   diagnostic_info *diagnostic)
 {
   diagnostic_report_current_module (context);
-  lang_hooks.print_error_function (context, input_filename);
+  lang_hooks.print_error_function (context, input_filename,
diagnostic);
 }

2010-05-21: r159685 (aka commit
ce084dfc1cd60d867d38dbed86a914d82fa908d1) moved
diagnostic_report_current_function from diagnostic.c to
tree-diagnostic.c

2011-10-15: now in tree-diagnostic.c, diagnostic_report_current_module
gained its location param in r180083 (aka commit
3de02a0fadcb82dc5ec168ca091a6f47ffe0575b) as part of "Emit macro
expansion related diagnostics":

 diagnostic_report_current_function (diagnostic_context *context,
                                    diagnostic_info *diagnostic)
 {
-  diagnostic_report_current_module (context);
+  diagnostic_report_current_module (context, diagnostic->location);
   lang_hooks.print_error_function (context, input_filename,
diagnostic);
 }

So from my reading of this, that "input_filename" was introduced in
1999-04-26 in r26631 (aka 8f157cdcb53c2138e4cacf4f309b6ff2ac27f257) when
the function was named "report_error_function" and in toplev.c [1]

Echoing Tom's question: given that last 2011 commit for improved macro
diagnostics which appears to assume a diagnostic->location, is it
reasonable to expect every call to diagnostic_report_current_function
call to have the right filename for diagnostic->location for the lang
hook?
David Malcolm - Nov. 22, 2013, 3:31 a.m.
The following patch series eliminates the following macros that
implicitly use input_location:
  input.h:
    #define input_line LOCATION_LINE (input_location)
    #define input_filename LOCATION_FILE (input_location)
    #define in_system_header (in_system_header_at (input_location))
    #define EXPR_LOC_OR_HERE(NODE) (EXPR_HAS_LOCATION (NODE) \
                               ? (NODE)->exp.locus : input_location)

replacing the first three by their expansions inline, and the last by
  EXPR_LOC_OR_LOC(NODE, input_location)

This is a revised version of the single patch I sent as:
  http://gcc.gnu.org/ml/gcc-patches/2013-07/msg00072.html
splitting it up into multiple patches by subdirectory, and trying to be
less clever about picking alternate locations than "input_location"
(removal of uses of "input_location" can wait for another patch, this
series merely makes them explicit).

Successfully bootstrapped&regtested on x86_64-unknown-linux-gnu; my
bootstrap covered c, c++, ada, fortran, but managed to miss java (though
Tom already approved that part in a previous version).

OK for trunk, assuming I can get it to build with Java, and targetting
bfin?

David Malcolm (9):
  java: Convert implicit uses of input_location into explicit uses
  ada: Eliminate uses of input_line macro.
  c-family: Convert implicit uses of input_location into explicit uses
  cp: Convert implicit uses of input_location into explicit uses
  gcc/c: Convert implicit uses of input_location into explicit uses
  fortran: Remove use of input_line macro
  bfin: Remove use of input_filename macro.
  gcc: Convert implicit uses of input_location into explicit uses
  gcc: Remove macros that implicitly use input_location

 gcc/ada/gcc-interface/utils2.c |  7 +++---
 gcc/builtins.c                 |  2 +-
 gcc/c-family/c-common.c        | 12 +++++------
 gcc/c-family/c-lex.c           |  6 +++---
 gcc/c-family/c-pragma.c        |  4 ++--
 gcc/c/c-decl.c                 | 49 +++++++++++++++++++++++++-----------------
 gcc/c/c-parser.c               |  5 ++---
 gcc/c/c-typeck.c               |  6 +++---
 gcc/config/bfin/bfin.c         |  2 +-
 gcc/cp/call.c                  | 12 +++++------
 gcc/cp/cvt.c                   |  8 +++----
 gcc/cp/decl.c                  | 18 +++++++++-------
 gcc/cp/error.c                 |  6 +++---
 gcc/cp/init.c                  |  4 ++--
 gcc/cp/lex.c                   | 13 +++++------
 gcc/cp/name-lookup.c           |  8 ++++---
 gcc/cp/parser.c                | 14 ++++++------
 gcc/cp/pt.c                    | 20 +++++++++--------
 gcc/cp/semantics.c             | 15 +++++++------
 gcc/cp/typeck.c                | 17 +++++++++------
 gcc/cp/typeck2.c               |  4 ++--
 gcc/fortran/trans.c            |  2 +-
 gcc/gimplify.c                 | 10 ++++-----
 gcc/input.h                    |  3 ---
 gcc/java/class.c               |  2 +-
 gcc/java/decl.c                |  2 +-
 gcc/java/jcf-parse.c           | 18 ++++++++++------
 gcc/tree-diagnostic.c          |  3 ++-
 gcc/tree.c                     |  4 ++--
 gcc/tree.h                     |  2 --
 30 files changed, 150 insertions(+), 128 deletions(-)
Richard Guenther - Nov. 22, 2013, 11:57 a.m.
On Fri, Nov 22, 2013 at 4:31 AM, David Malcolm <dmalcolm@redhat.com> wrote:
> The following patch series eliminates the following macros that
> implicitly use input_location:
>   input.h:
>     #define input_line LOCATION_LINE (input_location)
>     #define input_filename LOCATION_FILE (input_location)
>     #define in_system_header (in_system_header_at (input_location))
>     #define EXPR_LOC_OR_HERE(NODE) (EXPR_HAS_LOCATION (NODE) \
>                                ? (NODE)->exp.locus : input_location)
>
> replacing the first three by their expansions inline, and the last by
>   EXPR_LOC_OR_LOC(NODE, input_location)
>
> This is a revised version of the single patch I sent as:
>   http://gcc.gnu.org/ml/gcc-patches/2013-07/msg00072.html
> splitting it up into multiple patches by subdirectory, and trying to be
> less clever about picking alternate locations than "input_location"
> (removal of uses of "input_location" can wait for another patch, this
> series merely makes them explicit).
>
> Successfully bootstrapped&regtested on x86_64-unknown-linux-gnu; my
> bootstrap covered c, c++, ada, fortran, but managed to miss java (though
> Tom already approved that part in a previous version).
>
> OK for trunk, assuming I can get it to build with Java, and targetting
> bfin?

Ok.

Thanks,
Richard.

> David Malcolm (9):
>   java: Convert implicit uses of input_location into explicit uses
>   ada: Eliminate uses of input_line macro.
>   c-family: Convert implicit uses of input_location into explicit uses
>   cp: Convert implicit uses of input_location into explicit uses
>   gcc/c: Convert implicit uses of input_location into explicit uses
>   fortran: Remove use of input_line macro
>   bfin: Remove use of input_filename macro.
>   gcc: Convert implicit uses of input_location into explicit uses
>   gcc: Remove macros that implicitly use input_location
>
>  gcc/ada/gcc-interface/utils2.c |  7 +++---
>  gcc/builtins.c                 |  2 +-
>  gcc/c-family/c-common.c        | 12 +++++------
>  gcc/c-family/c-lex.c           |  6 +++---
>  gcc/c-family/c-pragma.c        |  4 ++--
>  gcc/c/c-decl.c                 | 49 +++++++++++++++++++++++++-----------------
>  gcc/c/c-parser.c               |  5 ++---
>  gcc/c/c-typeck.c               |  6 +++---
>  gcc/config/bfin/bfin.c         |  2 +-
>  gcc/cp/call.c                  | 12 +++++------
>  gcc/cp/cvt.c                   |  8 +++----
>  gcc/cp/decl.c                  | 18 +++++++++-------
>  gcc/cp/error.c                 |  6 +++---
>  gcc/cp/init.c                  |  4 ++--
>  gcc/cp/lex.c                   | 13 +++++------
>  gcc/cp/name-lookup.c           |  8 ++++---
>  gcc/cp/parser.c                | 14 ++++++------
>  gcc/cp/pt.c                    | 20 +++++++++--------
>  gcc/cp/semantics.c             | 15 +++++++------
>  gcc/cp/typeck.c                | 17 +++++++++------
>  gcc/cp/typeck2.c               |  4 ++--
>  gcc/fortran/trans.c            |  2 +-
>  gcc/gimplify.c                 | 10 ++++-----
>  gcc/input.h                    |  3 ---
>  gcc/java/class.c               |  2 +-
>  gcc/java/decl.c                |  2 +-
>  gcc/java/jcf-parse.c           | 18 ++++++++++------
>  gcc/tree-diagnostic.c          |  3 ++-
>  gcc/tree.c                     |  4 ++--
>  gcc/tree.h                     |  2 --
>  30 files changed, 150 insertions(+), 128 deletions(-)
>
> --
> 1.7.11.7
>
David Malcolm - Nov. 22, 2013, 2:19 p.m.
On Fri, 2013-11-22 at 12:57 +0100, Richard Biener wrote:
> On Fri, Nov 22, 2013 at 4:31 AM, David Malcolm <dmalcolm@redhat.com> wrote:
> > The following patch series eliminates the following macros that
> > implicitly use input_location:
> >   input.h:
> >     #define input_line LOCATION_LINE (input_location)
> >     #define input_filename LOCATION_FILE (input_location)
> >     #define in_system_header (in_system_header_at (input_location))
> >     #define EXPR_LOC_OR_HERE(NODE) (EXPR_HAS_LOCATION (NODE) \
> >                                ? (NODE)->exp.locus : input_location)
> >
> > replacing the first three by their expansions inline, and the last by
> >   EXPR_LOC_OR_LOC(NODE, input_location)
> >
> > This is a revised version of the single patch I sent as:
> >   http://gcc.gnu.org/ml/gcc-patches/2013-07/msg00072.html
> > splitting it up into multiple patches by subdirectory, and trying to be
> > less clever about picking alternate locations than "input_location"
> > (removal of uses of "input_location" can wait for another patch, this
> > series merely makes them explicit).
> >
> > Successfully bootstrapped&regtested on x86_64-unknown-linux-gnu; my
> > bootstrap covered c, c++, ada, fortran, but managed to miss java (though
> > Tom already approved that part in a previous version).
> >
> > OK for trunk, assuming I can get it to build with Java, and targetting
> > bfin?
> 
> Ok.

Thanks; committed to trunk as r205262, having verified the java and bfin
builds.

Patch

diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index 3f39a43..181bf10 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -1698,7 +1698,8 @@  build_call_raise (int msg, Node_Id gnat_node, char kind)
   filename = build_string (len, str);
   line_number
     = (gnat_node != Empty && Sloc (gnat_node) != No_Location)
-      ? Get_Logical_Line_Number (Sloc(gnat_node)) : input_line;
+      ? Get_Logical_Line_Number (Sloc(gnat_node))
+      : LOCATION_LINE (input_location);
 
   TREE_TYPE (filename) = build_array_type (unsigned_char_type_node,
 					   build_index_type (size_int (len)));
@@ -1744,7 +1745,7 @@  build_call_raise_range (int msg, Node_Id gnat_node,
     }
   else
     {
-      line_number = input_line;
+      line_number = LOCATION_LINE (input_location);
       column_number = 0;
     }
 
@@ -1794,7 +1795,7 @@  build_call_raise_column (int msg, Node_Id gnat_node)
     }
   else
     {
-      line_number = input_line;
+      line_number = LOCATION_LINE (input_location);
       column_number = 0;
     }
 
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 402bb1f..84cfe68 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -590,7 +590,7 @@  c_strlen (tree src, int only_value)
       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
     return c_strlen (TREE_OPERAND (src, 1), only_value);
 
-  loc = EXPR_LOC_OR_HERE (src);
+  loc = EXPR_LOC_OR_LOC (src, input_location);
 
   src = string_constant (src, &offset_node);
   if (src == 0)
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 8f7f5e5..f396fa6 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -2494,7 +2494,7 @@  unsafe_conversion_p (tree type, tree expr, bool produce_warns)
 {
   bool give_warning = false;
   tree expr_type = TREE_TYPE (expr);
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
     {
@@ -2660,7 +2660,7 @@  static void
 conversion_warning (tree type, tree expr)
 {
   tree expr_type = TREE_TYPE (expr);
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (!warn_conversion && !warn_sign_conversion)
     return;
@@ -2722,7 +2722,7 @@  conversion_warning (tree type, tree expr)
 void
 warnings_for_convert_and_check (tree type, tree expr, tree result)
 {
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (TREE_CODE (expr) == INTEGER_CST
       && (TREE_CODE (type) == INTEGER_TYPE
@@ -2932,7 +2932,7 @@  warn_for_collisions_1 (tree written, tree writer, struct tlist *list,
 	  && (!only_writes || list->writer))
 	{
 	  warned_ids = new_tlist (warned_ids, written, NULL_TREE);
-	  warning_at (EXPR_LOC_OR_HERE (writer),
+	  warning_at (EXPR_LOC_OR_LOC (writer, input_location),
 		      OPT_Wsequence_point, "operation on %qE may be undefined",
 		      list->expr);
 	}
@@ -3930,7 +3930,7 @@  shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
   int real1, real2;
   tree primop0, primop1;
   enum tree_code code = *rescode_ptr;
-  location_t loc = EXPR_LOC_OR_HERE (op0);
+  location_t loc = EXPR_LOC_OR_LOC (op0, input_location);
 
   /* Throw away any conversions to wider types
      already present in the operands.  */
@@ -4228,7 +4228,7 @@  shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
 	     the comparison isn't an issue, so suppress the
 	     warning.  */
 	  bool warn = 
-	    warn_type_limits && !in_system_header
+	    warn_type_limits && !in_system_header_at (loc)
 	    && c_inhibit_evaluation_warnings == 0
 	    && !(TREE_CODE (primop0) == INTEGER_CST
 		 && !TREE_OVERFLOW (convert (c_common_signed_type (type),
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index 819e9d5..84e781e 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -145,7 +145,7 @@  dump_one_header (splay_tree_node n, void * ARG_UNUSED (dummy))
 void
 dump_time_statistics (void)
 {
-  struct c_fileinfo *file = get_fileinfo (input_filename);
+  struct c_fileinfo *file = get_fileinfo (LOCATION_FILE (input_location));
   int this_time = get_run_time ();
   file->time += this_time - body_time;
 
@@ -241,7 +241,7 @@  cb_def_pragma (cpp_reader *pfile, source_location loc)
   /* Issue a warning message if we have been asked to do so.  Ignore
      unknown pragmas in system headers unless an explicit
      -Wunknown-pragmas has been given.  */
-  if (warn_unknown_pragmas > in_system_header)
+  if (warn_unknown_pragmas > in_system_header_at (input_location))
     {
       const unsigned char *space, *name;
       const cpp_token *s;
@@ -1060,7 +1060,7 @@  lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate)
   if (concats)
     strs = XOBFINISH (&str_ob, cpp_string *);
 
-  if (concats && !objc_string && !in_system_header)
+  if (concats && !objc_string && !in_system_header_at (input_location))
     warning (OPT_Wtraditional,
 	     "traditional C rejects string constant concatenation");
 
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 309859f..7b36e3d 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1117,7 +1117,7 @@  handle_pragma_float_const_decimal64 (cpp_reader *ARG_UNUSED (dummy))
 {
   if (c_dialect_cxx ())
     {
-      if (warn_unknown_pragmas > in_system_header)
+      if (warn_unknown_pragmas > in_system_header_at (input_location))
 	warning (OPT_Wunknown_pragmas,
 		 "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
 		 " for C++");
@@ -1126,7 +1126,7 @@  handle_pragma_float_const_decimal64 (cpp_reader *ARG_UNUSED (dummy))
 
   if (!targetm.decimal_float_supported_p ())
     {
-      if (warn_unknown_pragmas > in_system_header)
+      if (warn_unknown_pragmas > in_system_header_at (input_location))
 	warning (OPT_Wunknown_pragmas,
 		 "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
 		 " on this target");
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 8170a80..b0acb21 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -3311,7 +3311,7 @@  define_label (location_t location, tree name)
       bind_label (name, label, current_function_scope, label_vars);
     }
 
-  if (!in_system_header && lookup_name (name))
+  if (!in_system_header_at (location) && lookup_name (name))
     warning_at (location, OPT_Wtraditional,
 		"traditional C lacks a separate namespace "
 		"for labels, identifier %qE conflicts", name);
@@ -3747,7 +3747,7 @@  shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
 	}
       else
 	{
-	  if (warned != 1 && !in_system_header)
+	  if (warned != 1 && !in_system_header_at (input_location))
 	    {
 	      pedwarn (input_location, 0,
 		       "useless type name in empty declaration");
@@ -3755,7 +3755,8 @@  shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
 	    }
 	}
     }
-  else if (warned != 1 && !in_system_header && declspecs->typedef_p)
+  else if (warned != 1 && !in_system_header_at (input_location)
+	   && declspecs->typedef_p)
     {
       pedwarn (input_location, 0, "useless type name in empty declaration");
       warned = 1;
@@ -3787,28 +3788,33 @@  shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
       warned = 1;
     }
 
-  if (!warned && !in_system_header && declspecs->storage_class != csc_none)
+  if (!warned && !in_system_header_at (input_location)
+      && declspecs->storage_class != csc_none)
     {
       warning (0, "useless storage class specifier in empty declaration");
       warned = 2;
     }
 
-  if (!warned && !in_system_header && declspecs->thread_p)
+  if (!warned && !in_system_header_at (input_location)
+      && declspecs->thread_p)
     {
       warning (0, "useless %<__thread%> in empty declaration");
       warned = 2;
     }
 
-  if (!warned && !in_system_header && (declspecs->const_p
-				       || declspecs->volatile_p
-				       || declspecs->restrict_p
-				       || declspecs->address_space))
+  if (!warned
+      && !in_system_header_at (input_location)
+      && (declspecs->const_p
+	  || declspecs->volatile_p
+	  || declspecs->restrict_p
+	  || declspecs->address_space))
     {
       warning (0, "useless type qualifier in empty declaration");
       warned = 2;
     }
 
-  if (!warned && !in_system_header && declspecs->alignas_p)
+  if (!warned && !in_system_header_at (input_location)
+      && declspecs->alignas_p)
     {
       warning (0, "useless %<_Alignas%> in empty declaration");
       warned = 2;
@@ -4774,7 +4780,7 @@  check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
     }
 
   type_mv = TYPE_MAIN_VARIANT (*type);
-  if (!in_system_header
+  if (!in_system_header_at (input_location)
       && type_mv != integer_type_node
       && type_mv != unsigned_type_node
       && type_mv != boolean_type_node)
@@ -5023,7 +5029,7 @@  grokdeclarator (const struct c_declarator *declarator,
 
   /* Diagnose defaulting to "int".  */
 
-  if (declspecs->default_int_p && !in_system_header)
+  if (declspecs->default_int_p && !in_system_header_at (loc))
     {
       /* Issue a warning if this is an ISO C 99 program or if
 	 -Wreturn-type and this is a function, or if -Wimplicit;
@@ -5290,7 +5296,8 @@  grokdeclarator (const struct c_declarator *declarator,
 		type = error_mark_node;
 	      }
 
-	    if (pedantic && !in_system_header && flexible_array_type_p (type))
+	    if (pedantic && !in_system_header_at (loc)
+		&& flexible_array_type_p (type))
 	      pedwarn (loc, OPT_Wpedantic,
 		       "invalid use of structure with flexible array member");
 
@@ -5458,7 +5465,8 @@  grokdeclarator (const struct c_declarator *declarator,
 		    flexible_array_member = (t->kind == cdk_id);
 		  }
 		if (flexible_array_member
-		    && pedantic && !flag_isoc99 && !in_system_header)
+		    && pedantic && !flag_isoc99
+		    && !in_system_header_at (loc))
 		  pedwarn (loc, OPT_Wpedantic,
 			   "ISO C90 does not support flexible array members");
 
@@ -6267,7 +6275,8 @@  grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
       error ("%<[*]%> not allowed in other than function prototype scope");
     }
 
-  if (arg_types == 0 && !funcdef_flag && !in_system_header)
+  if (arg_types == 0 && !funcdef_flag
+      && !in_system_header_at (input_location))
     warning (OPT_Wstrict_prototypes,
 	     "function declaration isn%'t a prototype");
 
@@ -7661,7 +7670,7 @@  build_enumerator (location_t decl_loc, location_t loc,
 
   /* Set basis for default for next value.  */
   the_enum->enum_next_value
-    = build_binary_op (EXPR_LOC_OR_HERE (value),
+    = build_binary_op (EXPR_LOC_OR_LOC (value, loc),
 		       PLUS_EXPR, value, integer_one_node, 0);
   the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
 
@@ -7935,7 +7944,8 @@  store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
      warning if we got here because ARG_INFO_TYPES was error_mark_node
      (this happens when a function definition has just an ellipsis in
      its parameter list).  */
-  else if (!in_system_header && !current_function_scope
+  else if (!DECL_IN_SYSTEM_HEADER (fndecl)
+	   && !current_function_scope
 	   && arg_info->types != error_mark_node)
     warning_at (DECL_SOURCE_LOCATION (fndecl), OPT_Wtraditional,
 		"traditional C rejects ISO C style function definitions");
@@ -7989,7 +7999,7 @@  store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
   tree parmids = arg_info->parms;
   struct pointer_set_t *seen_args = pointer_set_create ();
 
-  if (!in_system_header)
+  if (!DECL_IN_SYSTEM_HEADER (fndecl))
     warning_at (DECL_SOURCE_LOCATION (fndecl),
 		OPT_Wold_style_definition, "old-style function definition");
 
@@ -9236,7 +9246,7 @@  declspecs_add_type (location_t loc, struct c_declspecs *specs,
 		  error_at (loc, "%<__int128%> is not supported for this target");
 		  return specs;
 		}
-	      if (!in_system_header)
+	      if (!in_system_header_at (loc))
 		pedwarn (loc, OPT_Wpedantic,
 			 "ISO C does not support %<__int128%> type");
 
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index c7846ce..8190598 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -756,8 +756,7 @@  c_parser_consume_pragma (c_parser *parser)
   parser->in_pragma = true;
 }
 
-/* Update the globals input_location and in_system_header from
-   TOKEN.  */
+/* Update the global input_location from TOKEN.  */
 static inline void
 c_parser_set_source_position_from_token (c_token *token)
 {
@@ -5964,7 +5963,7 @@  c_parser_unary_expression (c_parser *parser)
       ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
       return ret;
     case CPP_PLUS:
-      if (!c_dialect_objc () && !in_system_header)
+      if (!c_dialect_objc () && !in_system_header_at (input_location))
 	warning_at (op_loc,
 		    OPT_Wtraditional,
 		    "traditional C rejects the unary plus operator");
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 3a92311..a376001 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -5773,7 +5773,7 @@  store_init_value (location_t init_loc, tree decl, tree init, tree origtype)
 
   /* Store the expression if valid; else report error.  */
 
-  if (!in_system_header
+  if (!in_system_header_at (input_location)
       && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl))
     warning (OPT_Wtraditional, "traditional C rejects automatic "
 	     "aggregate initialization");
@@ -8265,7 +8265,7 @@  process_init_element (struct c_expr value, bool implicit,
 	     again on the assumption that this must be conditional on
 	     __STDC__ anyway (and we've already complained about the
 	     member-designator already).  */
-	  if (!in_system_header && !constructor_designated
+	  if (!in_system_header_at (input_location) && !constructor_designated
 	      && !(value.value && (integer_zerop (value.value)
 				   || real_zerop (value.value))))
 	    warning (OPT_Wtraditional, "traditional C rejects initialization "
@@ -8860,7 +8860,7 @@  c_start_case (location_t switch_loc,
 	{
 	  tree type = TYPE_MAIN_VARIANT (orig_type);
 
-	  if (!in_system_header
+	  if (!in_system_header_at (input_location)
 	      && (type == long_integer_type_node
 		  || type == long_unsigned_type_node))
 	    warning_at (switch_cond_loc,
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 7fab975..56c7e55 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -102,7 +102,7 @@  output_file_start (void)
   FILE *file = asm_out_file;
   int i;
 
-  fprintf (file, ".file \"%s\";\n", input_filename);
+  fprintf (file, ".file \"%s\";\n", LOCATION_FILE (input_location));
   
   for (i = 0; arg_regs[i] >= 0; i++)
     ;
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 425ef9b..1c5af60 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3683,7 +3683,7 @@  build_integral_nontype_arg_conv (tree type, tree expr, tsubst_flags_t complain)
   conversion *conv;
   void *p;
   tree t;
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (error_operand_p (expr))
     return error_mark_node;
@@ -5799,7 +5799,7 @@  convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
   tree totype = convs->type;
   diagnostic_t diag_kind;
   int flags;
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (convs->bad_p && !(complain & tf_error))
     return error_mark_node;
@@ -6212,7 +6212,7 @@  tree
 convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
 {
   tree arg_type;
-  location_t loc = EXPR_LOC_OR_HERE (arg);
+  location_t loc = EXPR_LOC_OR_LOC (arg, input_location);
 
   /* [expr.call]
 
@@ -7116,7 +7116,7 @@  build_cxx_call (tree fn, int nargs, tree *argarray,
   int optimize_sav;
 
   /* Remember roughly where this call is.  */
-  location_t loc = EXPR_LOC_OR_HERE (fn);
+  location_t loc = EXPR_LOC_OR_LOC (fn, input_location);
   fn = build_call_a (fn, nargs, argarray);
   SET_EXPR_LOCATION (fn, loc);
 
@@ -8878,7 +8878,7 @@  perform_implicit_conversion_flags (tree type, tree expr,
 {
   conversion *conv;
   void *p;
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (error_operand_p (expr))
     return error_mark_node;
@@ -9191,7 +9191,7 @@  initialize_reference (tree type, tree expr,
 {
   conversion *conv;
   void *p;
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (type == error_mark_node || error_operand_p (expr))
     return error_mark_node;
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index d9e905e..76951a0 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -77,7 +77,7 @@  cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
   tree intype = TREE_TYPE (expr);
   enum tree_code form;
   tree rval;
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (intype == error_mark_node)
     return error_mark_node;
@@ -412,7 +412,7 @@  convert_to_reference (tree reftype, tree expr, int convtype,
   tree rval = NULL_TREE;
   tree rval_as_conversion = NULL_TREE;
   bool can_convert_intype_to_type;
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (TREE_CODE (type) == FUNCTION_TYPE
       && TREE_TYPE (expr) == unknown_type_node)
@@ -654,7 +654,7 @@  ocp_convert (tree type, tree expr, int convtype, int flags,
   enum tree_code code = TREE_CODE (type);
   const char *invalid_conv_diag;
   tree e1;
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (error_operand_p (e) || type == error_mark_node)
     return error_mark_node;
@@ -910,7 +910,7 @@  ocp_convert (tree type, tree expr, int convtype, int flags,
 tree
 convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
 {
-  location_t loc = EXPR_LOC_OR_HERE (expr);
+  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (expr == error_mark_node
       || TREE_TYPE (expr) == error_mark_node)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 047fd77..e895563 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -370,7 +370,8 @@  pop_label (tree label, tree old_value)
 	  location_t location;
 
 	  error ("label %q+D used but not defined", label);
-	  location = input_location; /* FIXME want (input_filename, (line)0) */
+	  location = input_location;
+	    /* FIXME want (LOCATION_FILE (input_location), (line)0) */
 	  /* Avoid crashing later.  */
 	  define_label (location, DECL_NAME (label));
 	}
@@ -3068,7 +3069,7 @@  pop_switch (void)
   location_t switch_location;
 
   /* Emit warnings as needed.  */
-  switch_location = EXPR_LOC_OR_HERE (cs->switch_stmt);
+  switch_location = EXPR_LOC_OR_LOC (cs->switch_stmt, input_location);
   if (!processing_template_decl)
     c_do_switch_warnings (cs->cases, switch_location,
 			  SWITCH_STMT_TYPE (cs->switch_stmt),
@@ -4224,7 +4225,7 @@  check_tag_decl (cp_decl_specifier_seq *declspecs,
     error ("multiple types in one declaration");
   else if (declspecs->redefined_builtin_type)
     {
-      if (!in_system_header)
+      if (!in_system_header_at (input_location))
 	permerror (declspecs->locations[ds_redefined_builtin_type_spec],
 		   "redeclaration of C++ built-in type %qT",
 		   declspecs->redefined_builtin_type);
@@ -4275,7 +4276,8 @@  check_tag_decl (cp_decl_specifier_seq *declspecs,
       /* Anonymous unions are objects, so they can have specifiers.  */;
       SET_ANON_AGGR_TYPE_P (declared_type);
 
-      if (TREE_CODE (declared_type) != UNION_TYPE && !in_system_header)
+      if (TREE_CODE (declared_type) != UNION_TYPE
+	  && !in_system_header_at (input_location))
 	pedwarn (input_location, OPT_Wpedantic, "ISO C++ prohibits anonymous structs");
     }
 
@@ -5829,7 +5831,7 @@  make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
 
   /* We try to defer namespace-scope static constants so that they are
      not emitted into the object file unnecessarily.  */
-  filename = input_filename;
+  filename = LOCATION_FILE (input_location);
   if (!DECL_VIRTUAL_P (decl)
       && TREE_READONLY (decl)
       && DECL_INITIAL (decl) != NULL_TREE
@@ -8266,7 +8268,7 @@  compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
 	       indicated by the state of complain), so that
 	       another substitution can be found.  */
 	    return error_mark_node;
-	  else if (in_system_header)
+	  else if (in_system_header_at (input_location))
 	    /* Allow them in system headers because glibc uses them.  */;
 	  else if (name)
 	    pedwarn (input_location, OPT_Wpedantic, "ISO C++ forbids zero-size array %qD", name);
@@ -9026,7 +9028,7 @@  grokdeclarator (const cp_declarator *declarator,
 
       if (type_was_error_mark_node)
 	/* We've already issued an error, don't complain more.  */;
-      else if (in_system_header || flag_ms_extensions)
+      else if (in_system_header_at (input_location) || flag_ms_extensions)
 	/* Allow it, sigh.  */;
       else if (! is_main)
 	permerror (input_location, "ISO C++ forbids declaration of %qs with no type", name);
@@ -9049,7 +9051,7 @@  grokdeclarator (const cp_declarator *declarator,
 	  error ("%<__int128%> is not supported by this target");
 	  explicit_int128 = false;
 	}
-      else if (pedantic && ! in_system_header)
+      else if (pedantic && ! in_system_header_at (input_location))
 	pedwarn (input_location, OPT_Wpedantic,
 		 "ISO C++ does not support %<__int128%> for %qs", name);
     }
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index a8f52cd..5c62ee6 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -918,7 +918,7 @@  dump_global_iord (tree t)
   else
     gcc_unreachable ();
 
-  pp_printf (pp_base (cxx_pp), p, input_filename);
+  pp_printf (pp_base (cxx_pp), p, LOCATION_FILE (input_location));
 }
 
 static void
@@ -2748,7 +2748,7 @@  location_of (tree t)
 
   if (DECL_P (t))
     return DECL_SOURCE_LOCATION (t);
-  return EXPR_LOC_OR_HERE (t);
+  return EXPR_LOC_OR_LOC (t, input_location);
 }
 
 /* Now the interfaces from error et al to dump_type et al. Each takes an
@@ -3398,7 +3398,7 @@  cp_printer (pretty_printer *pp, text_info *text, const char *spec,
 void
 maybe_warn_cpp0x (cpp0x_warn_str str)
 {
-  if ((cxx_dialect == cxx98) && !in_system_header)
+  if ((cxx_dialect == cxx98) && !in_system_header_at (input_location))
     /* We really want to suppress this warning in system headers,
        because libstdc++ uses variadic templates even when we aren't
        in C++0x mode. */
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 4edd150..79ff6ac 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2283,7 +2283,7 @@  build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	{
 	  if (complain & tf_error)
 	    {
-	      error_at (EXPR_LOC_OR_HERE (inner_nelts),
+	      error_at (EXPR_LOC_OR_LOC (inner_nelts, input_location),
 			"array size in operator new must be constant");
 	      cxx_constant_value(inner_nelts);
 	    }
@@ -2311,7 +2311,7 @@  build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
       && !TREE_CONSTANT (maybe_constant_value (outer_nelts)))
     {
       if (complain & tf_warning_or_error)
-	pedwarn(EXPR_LOC_OR_HERE (outer_nelts), OPT_Wvla,
+	pedwarn(EXPR_LOC_OR_LOC (outer_nelts, input_location), OPT_Wvla,
 		"ISO C++ does not support variable-length array types");
       else
 	return error_mark_node;
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index d6ed809..e5afa2f 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -351,18 +351,18 @@  handle_pragma_interface (cpp_reader* /*dfile*/)
   if (fname == error_mark_node)
     return;
   else if (fname == 0)
-    filename = lbasename (input_filename);
+    filename = lbasename (LOCATION_FILE (input_location));
   else
     filename = TREE_STRING_POINTER (fname);
 
-  finfo = get_fileinfo (input_filename);
+  finfo = get_fileinfo (LOCATION_FILE (input_location));
 
   if (impl_file_chain == 0)
     {
       /* If this is zero at this point, then we are
 	 auto-implementing.  */
       if (main_input_filename == 0)
-	main_input_filename = input_filename;
+	main_input_filename = LOCATION_FILE (input_location);
     }
 
   finfo->interface_only = interface_strcmp (filename);
@@ -396,7 +396,7 @@  handle_pragma_implementation (cpp_reader* /*dfile*/)
       if (main_input_filename)
 	filename = main_input_filename;
       else
-	filename = input_filename;
+	filename = LOCATION_FILE (input_location);
       filename = lbasename (filename);
     }
   else
@@ -682,7 +682,8 @@  cxx_make_type (enum tree_code code)
   /* Set up some flags that give proper default behavior.  */
   if (RECORD_OR_UNION_CODE_P (code))
     {
-      struct c_fileinfo *finfo = get_fileinfo (input_filename);
+      struct c_fileinfo *finfo = \
+	get_fileinfo (LOCATION_FILE (input_location));
       SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, finfo->interface_unknown);
       CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
     }
@@ -710,5 +711,5 @@  in_main_input_context (void)
     return filename_cmp (main_input_filename,
 			 LOCATION_FILE (tl->locus)) == 0;
   else
-    return filename_cmp (main_input_filename, input_filename) == 0;
+    return filename_cmp (main_input_filename, LOCATION_FILE (input_location)) == 0;
 }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 2b1f9fb..a7b193b 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1490,7 +1490,8 @@  push_binding_level (cp_binding_level *scope)
     {
       scope->binding_depth = binding_depth;
       indent (binding_depth);
-      cp_binding_level_debug (scope, input_line, "push");
+      cp_binding_level_debug (scope, LOCATION_LINE (input_location),
+			      "push");
       binding_depth++;
     }
 }
@@ -1576,7 +1577,8 @@  leave_scope (void)
   if (ENABLE_SCOPE_CHECKING)
     {
       indent (--binding_depth);
-      cp_binding_level_debug (scope, input_line, "leave");
+      cp_binding_level_debug (scope, LOCATION_LINE (input_location),
+			      "leave");
     }
 
   /* Move one nesting level up.  */
@@ -1625,7 +1627,7 @@  resume_scope (cp_binding_level* b)
     {
       b->binding_depth = binding_depth;
       indent (binding_depth);
-      cp_binding_level_debug (b, input_line, "resume");
+      cp_binding_level_debug (b, LOCATION_LINE (input_location), "resume");
       binding_depth++;
     }
 }
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6e8293b..677fec6 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5000,7 +5000,8 @@  cp_parser_unqualified_id (cp_parser* parser,
 	    {
 	      /* 17.6.3.3.5  */
 	      const char *name = UDLIT_OP_SUFFIX (id);
-	      if (name[0] != '_' && !in_system_header && declarator_p)
+	      if (name[0] != '_' && !in_system_header_at (input_location)
+		  && declarator_p)
 		warning (0, "literal operator suffixes not preceded by %<_%>"
 			    " are reserved for future standardization");
 	    }
@@ -7559,7 +7560,7 @@  cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
 
 	  /* Warn about old-style casts, if so requested.  */
 	  if (warn_old_style_cast
-	      && !in_system_header
+	      && !in_system_header_at (input_location)
 	      && !VOID_TYPE_P (type)
 	      && current_lang_name != lang_name_c)
 	    warning (OPT_Wold_style_cast, "use of old-style cast");
@@ -10571,7 +10572,7 @@  cp_parser_declaration_seq_opt (cp_parser* parser)
 	  /* A declaration consisting of a single semicolon is
 	     invalid.  Allow it unless we're being pedantic.  */
 	  cp_lexer_consume_token (parser->lexer);
-	  if (!in_system_header)
+	  if (!in_system_header_at (input_location))
 	    pedwarn (input_location, OPT_Wpedantic, "extra %<;%>");
 	  continue;
 	}
@@ -15300,7 +15301,7 @@  cp_parser_enumerator_list (cp_parser* parser, tree type)
       /* If the next token is a `}', there is a trailing comma.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
 	{
-	  if (cxx_dialect < cxx11 && !in_system_header)
+	  if (cxx_dialect < cxx11 && !in_system_header_at (input_location))
 	    pedwarn (input_location, OPT_Wpedantic,
                      "comma at end of enumerator list");
 	  break;
@@ -17775,7 +17776,8 @@  cp_parser_parameter_declaration_clause (cp_parser* parser)
     /* There are no parameters.  */
     {
 #ifndef NO_IMPLICIT_EXTERN_C
-      if (in_system_header && current_class_type == NULL
+      if (in_system_header_at (input_location)
+	  && current_class_type == NULL
 	  && current_lang_name == lang_name_c)
 	return NULL_TREE;
       else
@@ -20463,7 +20465,7 @@  cp_parser_exception_specification_opt (cp_parser* parser)
 
 #if 0
   /* Enable this once a lot of code has transitioned to noexcept?  */
-  if (cxx_dialect >= cxx11 && !in_system_header)
+  if (cxx_dialect >= cxx11 && !in_system_header_at (input_location))
     warning (OPT_Wdeprecated, "dynamic exception specifications are "
 	     "deprecated in C++0x; use %<noexcept%> instead");
 #endif
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3847a1d..2575280 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5608,7 +5608,7 @@  convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 		return NULL_TREE;
 	      expr = cxx_constant_value (expr);
 	      if (errorcount > errs || warningcount + werrorcount > warns)
-		inform (EXPR_LOC_OR_HERE (expr),
+		inform (EXPR_LOC_OR_LOC (expr, input_location),
 			"in template argument for type %qT ", type);
 	      if (expr == error_mark_node)
 		return NULL_TREE;
@@ -7974,7 +7974,7 @@  push_tinst_level (tree d)
   new_level->decl = d;
   new_level->locus = input_location;
   new_level->errors = errorcount+sorrycount;
-  new_level->in_system_header_p = in_system_header;
+  new_level->in_system_header_p = in_system_header_at (input_location);
   new_level->next = current_tinst_level;
   current_tinst_level = new_level;
 
@@ -14090,7 +14090,7 @@  tsubst_copy_and_build (tree t,
 		      fn = TREE_OPERAND (fn, 1);
 		    if (is_overloaded_fn (fn))
 		      fn = get_first_fn (fn);
-		    if (permerror (EXPR_LOC_OR_HERE (t),
+		    if (permerror (EXPR_LOC_OR_LOC (t, input_location),
 				   "%qD was not declared in this scope, "
 				   "and no declarations were found by "
 				   "argument-dependent lookup at the point "
@@ -14100,15 +14100,17 @@  tsubst_copy_and_build (tree t,
 			  /* Can't say anything more.  */;
 			else if (DECL_CLASS_SCOPE_P (fn))
 			  {
-			    inform (EXPR_LOC_OR_HERE (t),
+			    location_t loc = EXPR_LOC_OR_LOC (t,
+							      input_location);
+			    inform (loc,
 				    "declarations in dependent base %qT are "
 				    "not found by unqualified lookup",
 				    DECL_CLASS_CONTEXT (fn));
 			    if (current_class_ptr)
-			      inform (EXPR_LOC_OR_HERE (t),
+			      inform (loc,
 				      "use %<this->%D%> instead", function);
 			    else
-			      inform (EXPR_LOC_OR_HERE (t),
+			      inform (loc,
 				      "use %<%T::%D%> instead",
 				      current_class_name, function);
 			  }
@@ -18341,7 +18343,7 @@  do_decl_instantiation (tree decl, tree storage)
     ;
   else if (storage == ridpointers[(int) RID_EXTERN])
     {
-      if (!in_system_header && (cxx_dialect == cxx98))
+      if (!in_system_header_at (input_location) && (cxx_dialect == cxx98))
 	pedwarn (input_location, OPT_Wpedantic, 
 		 "ISO C++ 1998 forbids the use of %<extern%> on explicit "
 		 "instantiations");
@@ -18434,7 +18436,7 @@  do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
 
   if (storage != NULL_TREE)
     {
-      if (!in_system_header)
+      if (!in_system_header_at (input_location))
 	{
 	  if (storage == ridpointers[(int) RID_EXTERN])
 	    {
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index f821754..905830c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2120,7 +2120,7 @@  finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
 	      && type_dependent_expression_p (current_class_ref)))
 	{
 	  result = build_nt_call_vec (fn, *args);
-	  SET_EXPR_LOCATION (result, EXPR_LOC_OR_HERE (fn));
+	  SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location));
 	  KOENIG_LOOKUP_P (result) = koenig_p;
 	  if (cfun)
 	    {
@@ -2682,7 +2682,8 @@  begin_class_definition (tree t)
      before.  */
   if (! TYPE_ANONYMOUS_P (t))
     {
-      struct c_fileinfo *finfo = get_fileinfo (input_filename);
+      struct c_fileinfo *finfo = \
+	get_fileinfo (LOCATION_FILE (input_location));
       CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
       SET_CLASSTYPE_INTERFACE_UNKNOWN_X
 	(t, finfo->interface_unknown);
@@ -6756,7 +6757,7 @@  cxx_eval_call_expression (const constexpr_call *old_call, tree t,
 			  bool allow_non_constant, bool addr,
 			  bool *non_constant_p, bool *overflow_p)
 {
-  location_t loc = EXPR_LOC_OR_HERE (t);
+  location_t loc = EXPR_LOC_OR_LOC (t, input_location);
   tree fun = get_function_named_in_call (t);
   tree result;
   constexpr_call new_call = { NULL, NULL, NULL, 0 };
@@ -8130,7 +8131,7 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
 	    && !integer_zerop (op))
 	  {
 	    if (!allow_non_constant)
-	      error_at (EXPR_LOC_OR_HERE (t),
+	      error_at (EXPR_LOC_OR_LOC (t, input_location),
 			"reinterpret_cast from integer to pointer");
 	    *non_constant_p = true;
 	    return t;
@@ -8176,7 +8177,7 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
     case EXPR_STMT:
     case OFFSET_REF:
       if (!allow_non_constant)
-        error_at (EXPR_LOC_OR_HERE (t),
+        error_at (EXPR_LOC_OR_LOC (t, input_location),
 		  "expression %qE is not a constant-expression", t);
       *non_constant_p = true;
       break;
@@ -8448,7 +8449,7 @@  potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 		  {
 		    if (flags & tf_error)
 		      {
-			error_at (EXPR_LOC_OR_HERE (t),
+			error_at (EXPR_LOC_OR_LOC (t, input_location),
 				  "call to non-constexpr function %qD", fun);
 			explain_invalid_constexpr_fn (fun);
 		      }
@@ -8540,7 +8541,7 @@  potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	    && !integer_zerop (from))
 	  {
 	    if (flags & tf_error)
-	      error_at (EXPR_LOC_OR_HERE (t),
+	      error_at (EXPR_LOC_OR_LOC (t, input_location),
 			"reinterpret_cast from integer to pointer");
 	    return false;
 	  }
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 462abdd..4576269 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1879,7 +1879,7 @@  decay_conversion (tree exp, tsubst_flags_t complain)
 {
   tree type;
   enum tree_code code;
-  location_t loc = EXPR_LOC_OR_HERE (exp);
+  location_t loc = EXPR_LOC_OR_LOC (exp, input_location);
 
   type = TREE_TYPE (exp);
   if (type == error_mark_node)
@@ -2129,6 +2129,8 @@  static tree
 rationalize_conditional_expr (enum tree_code code, tree t,
                               tsubst_flags_t complain)
 {
+  location_t loc = EXPR_LOC_OR_LOC (t, input_location);
+
   /* For MIN_EXPR or MAX_EXPR, fold-const.c has arranged things so that
      the first operand is always the one to be used if both operands
      are equal, so we know what conditional expression this used to be.  */
@@ -2141,8 +2143,8 @@  rationalize_conditional_expr (enum tree_code code, tree t,
       gcc_assert (!TREE_SIDE_EFFECTS (op0)
 		  && !TREE_SIDE_EFFECTS (op1));
       return
-	build_conditional_expr (EXPR_LOC_OR_HERE (t),
-				build_x_binary_op (EXPR_LOC_OR_HERE (t),
+	build_conditional_expr (loc,
+				build_x_binary_op (loc,
 						   (TREE_CODE (t) == MIN_EXPR
 						    ? LE_EXPR : GE_EXPR),
 						   op0, TREE_CODE (op0),
@@ -2155,7 +2157,7 @@  rationalize_conditional_expr (enum tree_code code, tree t,
     }
 
   return
-    build_conditional_expr (EXPR_LOC_OR_HERE (t), TREE_OPERAND (t, 0),
+    build_conditional_expr (loc, TREE_OPERAND (t, 0),
 			    cp_build_unary_op (code, TREE_OPERAND (t, 1), 0,
                                                complain),
 			    cp_build_unary_op (code, TREE_OPERAND (t, 2), 0,
@@ -5964,8 +5966,9 @@  build_x_compound_expr_from_list (tree list, expr_list_kind exp,
       && !CONSTRUCTOR_IS_DIRECT_INIT (expr))
     {
       if (complain & tf_error)
-	pedwarn (EXPR_LOC_OR_HERE (expr), 0, "list-initializer for "
-		 "non-class type must not be parenthesized");
+	pedwarn (EXPR_LOC_OR_LOC (expr, input_location), 0,
+		 "list-initializer for non-class type must not "
+		 "be parenthesized");
       else
 	return error_mark_node;
     }
@@ -8023,7 +8026,7 @@  convert_for_assignment (tree type, tree rhs,
       && TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE
       && (complain & tf_warning))
     {
-      location_t loc = EXPR_LOC_OR_HERE (rhs);
+      location_t loc = EXPR_LOC_OR_LOC (rhs, input_location);
 
       warning_at (loc, OPT_Wparentheses,
 		  "suggest parentheses around assignment used as truth value");
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 7932939..00ca317 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -892,11 +892,11 @@  check_narrowing (tree type, tree init)
   if (!ok)
     {
       if (cxx_dialect >= cxx11)
-	pedwarn (EXPR_LOC_OR_HERE (init), OPT_Wnarrowing,
+	pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
 		 "narrowing conversion of %qE from %qT to %qT inside { }",
 		 init, ftype, type);
       else
-	warning_at (EXPR_LOC_OR_HERE (init), OPT_Wnarrowing,
+	warning_at (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
 		    "narrowing conversion of %qE from %qT to %qT inside { } "
 		    "is ill-formed in C++11", init, ftype, type);
     }
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index f17eaca..9a61b81 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -422,7 +422,7 @@  trans_runtime_error_vararg (bool error, locus* where, const char* msgid,
     }
   else
     asprintf (&message, "In file '%s', around line %d",
-	      gfc_source_file, input_line + 1);
+	      gfc_source_file, LOCATION_LINE (input_location) + 1);
 
   arg = gfc_build_addr_expr (pchar_type_node,
 			     gfc_build_localized_cstring_const (message));
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index e2ae893..16b327e 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -586,7 +586,7 @@  internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
 
   mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
 
-  SET_EXPR_LOCATION (mod, EXPR_LOC_OR_HERE (val));
+  SET_EXPR_LOCATION (mod, EXPR_LOC_OR_LOC (val, input_location));
 
   /* gimplify_modify_expr might want to reduce this further.  */
   gimplify_and_add (mod, pre_p);
@@ -2840,7 +2840,7 @@  shortcut_cond_expr (tree expr)
       while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
 	{
 	  /* Keep the original source location on the first 'if'.  */
-	  location_t locus = EXPR_LOC_OR_HERE (expr);
+	  location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
 	  TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
 	  /* Set the source location of the && on the second 'if'.  */
 	  if (EXPR_HAS_LOCATION (pred))
@@ -2862,7 +2862,7 @@  shortcut_cond_expr (tree expr)
       while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
 	{
 	  /* Keep the original source location on the first 'if'.  */
-	  location_t locus = EXPR_LOC_OR_HERE (expr);
+	  location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
 	  TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
 	  /* Set the source location of the || on the second 'if'.  */
 	  if (EXPR_HAS_LOCATION (pred))
@@ -2926,7 +2926,7 @@  shortcut_cond_expr (tree expr)
   /* If there was nothing else in our arms, just forward the label(s).  */
   if (!then_se && !else_se)
     return shortcut_cond_r (pred, true_label_p, false_label_p,
-			    EXPR_LOC_OR_HERE (expr));
+			    EXPR_LOC_OR_LOC (expr, input_location));
 
   /* If our last subexpression already has a terminal label, reuse it.  */
   if (else_se)
@@ -2958,7 +2958,7 @@  shortcut_cond_expr (tree expr)
   jump_over_else = block_may_fallthru (then_);
 
   pred = shortcut_cond_r (pred, true_label_p, false_label_p,
-			  EXPR_LOC_OR_HERE (expr));
+			  EXPR_LOC_OR_LOC (expr, input_location));
 
   expr = NULL;
   append_to_statement_list (pred, &expr);
diff --git a/gcc/input.h b/gcc/input.h
index 56f6de0..e0a09d4 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -56,11 +56,8 @@  extern location_t input_location;
   ((tree) ((IS_ADHOC_LOC (LOC)) ? get_data_from_adhoc_loc (line_table, (LOC)) \
   : NULL))
 
-#define input_line LOCATION_LINE (input_location)
-#define input_filename LOCATION_FILE (input_location)
 #define in_system_header_at(LOC) \
   ((linemap_location_in_system_header_p (line_table, LOC)))
-#define in_system_header (in_system_header_at (input_location))
 
 void dump_line_table_statistics (void);
 
diff --git a/gcc/java/class.c b/gcc/java/class.c
index cb67896..8cd7e8e 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -2412,7 +2412,7 @@  maybe_layout_super_class (tree super_class, tree this_class ATTRIBUTE_UNUSED)
 }
 
 /* safe_layout_class just makes sure that we can load a class without
-   disrupting the current_class, input_file, input_line, etc, information
+   disrupting the current_class, input_location, etc, information
    about the class processed currently.  */
 
 void
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index c5a654d..7013a8a 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -2015,7 +2015,7 @@  java_add_stmt (tree new_stmt)
   tree stmts = current_binding_level->stmts;
   tree_stmt_iterator i;
 
-  if (input_filename)
+  if (LOCATION_FILE (input_location))
     walk_tree (&new_stmt, set_input_location, NULL, NULL);
 
   if (stmts == NULL)
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index fbd4e00..cec9943 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -312,13 +312,14 @@  set_source_filename (JCF *jcf, int index)
 {
   tree sfname_id = get_name_constant (jcf, index);
   const char *sfname = IDENTIFIER_POINTER (sfname_id);
-  const char *old_filename = input_filename;
+  const char *old_filename = LOCATION_FILE (input_location);
   int new_len = IDENTIFIER_LENGTH (sfname_id);
   if (old_filename != NULL)
     {
       int old_len = strlen (old_filename);
-      /* Use the current input_filename (derived from the class name)
-	 if it has a directory prefix, but otherwise matches sfname. */
+      /* Use the filename from current input_location (derived from the
+	 class name) if it has a directory prefix, but otherwise matches
+	 sfname.  */
       if (old_len > new_len
 	  && filename_cmp (sfname, old_filename + old_len - new_len) == 0
 	  && (old_filename[old_len - new_len - 1] == '/'
@@ -1559,7 +1560,8 @@  parse_class_file (void)
     linemap_add (line_table, LC_ENTER, 0, loc.file, loc.line);
   }
   file_start_location = input_location;
-  (*debug_hooks->start_source_file) (input_line, input_filename);
+  (*debug_hooks->start_source_file) (LOCATION_LINE (input_location),
+				     LOCATION_FILE (input_location));
 
   java_mark_class_local (current_class);
 
@@ -1617,7 +1619,8 @@  parse_class_file (void)
 	  for (ptr += 2; --i >= 0; ptr += 4)
 	    {
 	      int line = GET_u2 (ptr);
-	      /* Set initial input_line to smallest linenumber.
+	      /* Set initial line of input_location to smallest
+	       * linenumber.
 	       * Needs to be set before init_function_start. */
 	      if (min_line == 0 || line < min_line)
 		min_line = line;
@@ -1747,7 +1750,7 @@  java_parse_file (void)
       int avail = 2000;
       finput = fopen (main_input_filename, "r");
       if (finput == NULL)
-	fatal_error ("can%'t open %s: %m", input_filename);
+	fatal_error ("can%'t open %s: %m", LOCATION_FILE (input_location));
       list = XNEWVEC (char, avail);
       next = list;
       for (;;)
@@ -1766,7 +1769,8 @@  java_parse_file (void)
 	  if (count == 0)
 	    {
 	      if (! feof (finput))
-		fatal_error ("error closing %s: %m", input_filename);
+		fatal_error ("error closing %s: %m",
+			     LOCATION_FILE (input_location));
 	      *next = '\0';
 	      break;
 	    }
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index 087cf6a..2942365 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -39,7 +39,8 @@  diagnostic_report_current_function (diagnostic_context *context,
 				    diagnostic_info *diagnostic)
 {
   diagnostic_report_current_module (context, diagnostic->location);
-  lang_hooks.print_error_function (context, input_filename, diagnostic);
+  lang_hooks.print_error_function (context, LOCATION_FILE (input_location),
+				   diagnostic);
 }
 
 static void
diff --git a/gcc/tree.c b/gcc/tree.c
index ab11735..aab1cd9 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9080,7 +9080,7 @@  get_file_function_name (const char *type)
     {
       const char *file = main_input_filename;
       if (! file)
-	file = input_filename;
+	file = LOCATION_FILE (input_location);
       /* Just use the file's basename, because the full pathname
 	 might be quite long.  */
       p = q = ASTRDUP (lbasename (file));
@@ -9097,7 +9097,7 @@  get_file_function_name (const char *type)
       if (! name)
 	name = "";
       if (! file)
-	file = input_filename;
+	file = LOCATION_FILE (input_location);
 
       len = strlen (file);
       q = (char *) alloca (9 + 17 + len + 1);
diff --git a/gcc/tree.h b/gcc/tree.h
index b444517..f94b2d9 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1623,8 +1623,6 @@  struct GTY(()) tree_constructor {
   != UNKNOWN_LOCATION)
 /* The location to be used in a diagnostic about this expression.  Do not
    use this macro if the location will be assigned to other expressions.  */
-#define EXPR_LOC_OR_HERE(NODE) (EXPR_HAS_LOCATION (NODE) \
-				? (NODE)->exp.locus : input_location)
 #define EXPR_LOC_OR_LOC(NODE, LOCUS) (EXPR_HAS_LOCATION (NODE) \
 				      ? (NODE)->exp.locus : (LOCUS))
 #define EXPR_FILENAME(NODE) LOCATION_FILE (EXPR_CHECK ((NODE))->exp.locus)