Index: gcc/java/jcf-parse.c =================================================================== --- gcc/java/jcf-parse.c (revision 138935) +++ gcc/java/jcf-parse.c (working copy) @@ -1193,12 +1193,14 @@ give_name_to_class (JCF *jcf, int i) JPOOL_UTF_LENGTH (jcf, j)); this_class = lookup_class (class_name); { tree source_name = identifier_subst (class_name, "", '.', '/', ".java"); const char *sfname = find_sourcefile (IDENTIFIER_POINTER (source_name)); - linemap_add (line_table, LC_ENTER, false, sfname, 0); - input_location = linemap_line_start (line_table, 0, 1); + /* FIXME CARET: We should add a pointer to the input line + instead of NULL. */ + linemap_add (line_table, LC_ENTER, false, sfname, 0, NULL); + input_location = linemap_line_start (line_table, 0, 1, NULL); file_start_location = input_location; DECL_SOURCE_LOCATION (TYPE_NAME (this_class)) = input_location; if (main_input_filename == NULL && jcf == main_jcf) main_input_filename = sfname; } @@ -1472,11 +1474,11 @@ jcf_parse (JCF* jcf) fatal_error ("error while parsing final attributes"); if (TYPE_REFLECTION_DATA (current_class)) annotation_write_byte (JV_DONE_ATTR); - linemap_add (line_table, LC_LEAVE, false, NULL, 0); + linemap_add (line_table, LC_LEAVE, false, NULL, 0, NULL); /* The fields of class_type_node are already in correct order. */ if (current_class != class_type_node && current_class != object_type_node) TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class)); @@ -1505,12 +1507,12 @@ load_inner_classes (tree cur_class) static void duplicate_class_warning (const char *filename) { location_t warn_loc; - linemap_add (line_table, LC_RENAME, 0, filename, 0); - warn_loc = linemap_line_start (line_table, 0, 1); + linemap_add (line_table, LC_RENAME, 0, filename, 0, NULL); + warn_loc = linemap_line_start (line_table, 0, 1, NULL); warning (0, "%Hduplicate class will only be compiled once", &warn_loc); } static void java_layout_seen_class_methods (void) @@ -1558,11 +1560,11 @@ parse_class_file (void) input_location = DECL_SOURCE_LOCATION (TYPE_NAME (current_class)); { /* Re-enter the current file. */ expanded_location loc = expand_location (input_location); - linemap_add (line_table, LC_ENTER, 0, loc.file, loc.line); + linemap_add (line_table, LC_ENTER, 0, loc.file, loc.line, NULL); } file_start_location = input_location; (*debug_hooks->start_source_file) (input_line, input_filename); java_mark_class_local (current_class); @@ -1625,11 +1627,11 @@ parse_class_file (void) * Needs to be set before init_function_start. */ if (min_line == 0 || line < min_line) min_line = line; } if (min_line != 0) - input_location = linemap_line_start (line_table, min_line, 1); + input_location = linemap_line_start (line_table, min_line, 1, NULL); } else { linenumber_table = NULL; linenumber_count = 0; @@ -1897,18 +1899,18 @@ java_parse_file (int set_yydebug ATTRIBU { main_jcf = GGC_NEW (JCF); JCF_ZERO (main_jcf); main_jcf->read_state = finput; main_jcf->filbuf = jcf_filbuf_from_stdio; - linemap_add (line_table, LC_ENTER, false, filename, 0); - input_location = linemap_line_start (line_table, 0, 1); + linemap_add (line_table, LC_ENTER, false, filename, 0, NULL); + input_location = linemap_line_start (line_table, 0, 1, NULL); if (open_in_zip (main_jcf, filename, NULL, 0) < 0) fatal_error ("bad zip/jar file %s", filename); localToFile = SeenZipFiles; /* Register all the classes defined there. */ process_zip_dir ((FILE *) main_jcf->read_state); - linemap_add (line_table, LC_LEAVE, false, NULL, 0); + linemap_add (line_table, LC_LEAVE, false, NULL, 0, NULL); parse_zip_file_entries (); } else if (magic == (JCF_u4) ZIPEMPTYMAGIC) { /* Ignore an empty input jar. */ @@ -1921,11 +1923,11 @@ java_parse_file (int set_yydebug ATTRIBU java_parser_context_save_global (); parse_source_file_1 (real_file, filename, finput); java_parser_context_restore_global (); java_pop_parser_context (1); - linemap_add (line_table, LC_LEAVE, false, NULL, 0); + linemap_add (line_table, LC_LEAVE, false, NULL, 0, NULL); #endif } } for (node = current_file_list; node; node = TREE_CHAIN (node)) Index: gcc/java/expr.c =================================================================== --- gcc/java/expr.c (revision 138935) +++ gcc/java/expr.c (working copy) @@ -3229,11 +3229,11 @@ expand_byte_code (JCF *jcf, tree method) int pc = GET_u2 (linenumber_pointer); linenumber_pointer += 4; if (pc == PC) { int line = GET_u2 (linenumber_pointer - 2); - input_location = linemap_line_start (line_table, line, 1); + input_location = linemap_line_start (line_table, line, 1, NULL); if (input_location > max_location) max_location = input_location; if (!(instruction_bits[PC] & BCODE_HAS_MULTI_LINENUMBERS)) break; } Index: gcc/java/lang.c =================================================================== --- gcc/java/lang.c (revision 138935) +++ gcc/java/lang.c (working copy) @@ -602,12 +602,12 @@ java_post_options (const char **pfilenam free (buf); } } } } - linemap_add (line_table, LC_ENTER, false, filename, 0); - linemap_add (line_table, LC_RENAME, false, "", 0); + linemap_add (line_table, LC_ENTER, false, filename, 0, NULL); + linemap_add (line_table, LC_RENAME, false, "", 0, NULL); /* Initialize the compiler back end. */ return false; } Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 138935) +++ gcc/tree.c (working copy) @@ -3516,18 +3516,24 @@ expand_location (source_location loc) if (loc == 0) { xloc.file = NULL; xloc.line = 0; xloc.column = 0; +#ifdef USE_CARET_DIAGNOSTICS + xloc.linebuf = NULL; +#endif xloc.sysp = 0; } else { const struct line_map *map = linemap_lookup (line_table, loc); xloc.file = map->to_file; xloc.line = SOURCE_LINE (map, loc); xloc.column = SOURCE_COLUMN (map, loc); +#ifdef USE_CARET_DIAGNOSTICS + xloc.linebuf = SOURCE_LINEBUFFER (map, loc); +#endif xloc.sysp = map->sysp != 0; }; return xloc; } Index: gcc/configure =================================================================== --- gcc/configure (revision 138935) +++ gcc/configure (working copy) @@ -1011,10 +1011,13 @@ Optional Features: --enable-generated-files-in-srcdir put copies of generated files in source dir intended for creating source tarballs for users without texinfo bison or flex. --enable-werror-always enable -Werror despite compiler version + --enable-caret-diagnostics + enable printing the source code causing a diagnostic + with a caret symbol indicating the exact location. --enable-checking=LIST enable expensive run-time checks. With LIST, enable only specific categories of checks. Categories are: yes,no,all,none,release. Flags are: assert,df,fold,gc,gcac,gimple,misc, @@ -7232,10 +7235,26 @@ warn_cflags= if test "x$GCC" = "xyes"; then warn_cflags='$(GCC_WARN_CFLAGS)' fi +# Check whether --enable-caret-diagnostics or --disable-caret-diagnostics was given. +if test "${enable_caret_diagnostics+set}" = set; then + enableval="$enable_caret_diagnostics" + +else + enable_caret_diagnostics=no +fi; + +if test x$enable_caret_diagnostics = xyes ; then + +cat >>confdefs.h <<\_ACEOF +#define USE_CARET_DIAGNOSTICS 1 +_ACEOF + +fi + # Enable expensive internal checks is_release= if test x"`cat $srcdir/DEV-PHASE`" != xexperimental; then is_release=yes fi @@ -14719,17 +14738,17 @@ echo $ECHO_N "checking the name lister ( if test "${lt_cv_nm_interface+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:14724: $ac_compile\"" >&5) + (eval echo "\"\$as_me:14743: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:14727: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:14746: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:14730: output\"" >&5) + (eval echo "\"\$as_me:14749: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* @@ -15780,11 +15799,11 @@ ia64-*-hpux*) fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 15785 "configure"' > conftest.$ac_ext + echo '#line 15804 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then @@ -16400,15 +16419,15 @@ else # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16405: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16424: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16409: \$? = $ac_status" >&5 + echo "$as_me:16428: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 @@ -16722,15 +16741,15 @@ else # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16727: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16746: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16731: \$? = $ac_status" >&5 + echo "$as_me:16750: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 @@ -16827,15 +16846,15 @@ else # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16832: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16851: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:16836: \$? = $ac_status" >&5 + echo "$as_me:16855: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp @@ -16882,15 +16901,15 @@ else # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16887: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16906: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:16891: \$? = $ac_status" >&5 + echo "$as_me:16910: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp @@ -19679,11 +19698,11 @@ else lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 19684 "configure" +#line 19703 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif @@ -19779,11 +19798,11 @@ else lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 19784 "configure" +#line 19803 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif Index: gcc/diagnostic.c =================================================================== --- gcc/diagnostic.c (revision 138935) +++ gcc/diagnostic.c (working copy) @@ -103,10 +103,13 @@ diagnostic_initialize (diagnostic_contex memset (context->diagnostic_count, 0, sizeof context->diagnostic_count); context->issue_warnings_are_errors_message = true; context->warning_as_error_requested = false; memset (context->classify_diagnostic, DK_UNSPECIFIED, sizeof context->classify_diagnostic); +#ifdef USE_CARET_DIAGNOSTICS + context->show_caret = true; +#endif context->show_option_requested = false; context->abort_on_error = false; context->internal_error = NULL; diagnostic_starter (context) = default_diagnostic_starter; diagnostic_finalizer (context) = default_diagnostic_finalizer; @@ -161,10 +164,47 @@ diagnostic_build_prefix (diagnostic_info : flag_show_column && s.column != 0 ? build_message_string ("%s:%d:%d: %s", s.file, s.line, s.column, text) : build_message_string ("%s:%d: %s", s.file, s.line, text)); } +#ifdef USE_CARET_DIAGNOSTICS +static const unsigned char * +get_source_line (expanded_location s) +{ + return s.linebuf; +} + +static void +diagnostic_show_locus (diagnostic_context * context ATTRIBUTE_UNUSED, + diagnostic_info *diagnostic) +{ + const unsigned char *line; + int max_width = 80; + expanded_location s; + + if (!context->show_caret) + return; + + s = expand_location (diagnostic->location); + line = get_source_line (s); + if (line == NULL) + return; + + putchar (' '); + + while (max_width > 0 && *line != '\0' && *line != '\n') + { + max_width--; + putchar (*line); + line++; + } + putchar('\n'); + gcc_assert (s.column > 0); + printf (" %*c\n", s.column, '^'); +} +#endif + /* Take any action which is expected to happen after the diagnostic is written out. This function does not always return. */ static void diagnostic_action_after_output (diagnostic_context *context, diagnostic_info *diagnostic) @@ -402,10 +442,13 @@ diagnostic_report_diagnostic (diagnostic pp_format (context->printer, &diagnostic->message); (*diagnostic_starter (context)) (context, diagnostic); pp_output_formatted_text (context->printer); (*diagnostic_finalizer (context)) (context, diagnostic); pp_flush (context->printer); +#ifdef USE_CARET_DIAGNOSTICS + diagnostic_show_locus (context, diagnostic); +#endif diagnostic_action_after_output (context, diagnostic); diagnostic->message.format_spec = saved_format_spec; diagnostic->abstract_origin = NULL; context->lock--; Index: gcc/diagnostic.h =================================================================== --- gcc/diagnostic.h (revision 138935) +++ gcc/diagnostic.h (working copy) @@ -82,10 +82,16 @@ struct diagnostic_context /* True if we should print the command line option which controls each diagnostic, if known. */ bool show_option_requested; +#ifdef USE_CARET_DIAGNOSTICS + /* True if we should print the source line with a caret indicating + the location. */ + bool show_caret; +#endif + /* True if we should raise a SIGABRT on errors. */ bool abort_on_error; /* This function is called before any message is printed out. It is responsible for preparing message prefix and such. For example, it Index: gcc/input.h =================================================================== --- gcc/input.h (revision 138935) +++ gcc/input.h (working copy) @@ -40,10 +40,15 @@ typedef struct GTY (()) /* The line-location in the source file. */ int line; int column; +#ifdef USE_CARET_DIAGNOSTICS + /* The offset location in the source file. */ + const unsigned char *linebuf; +#endif + /* In a system header?. */ bool sysp; } expanded_location; extern expanded_location expand_location (source_location); Index: gcc/testsuite/lib/gcc.exp =================================================================== --- gcc/testsuite/lib/gcc.exp (revision 138935) +++ gcc/testsuite/lib/gcc.exp (working copy) @@ -148,10 +148,10 @@ proc gcc_target_compile { source dest ty set options [concat "{additional_flags=$TOOL_OPTIONS}" $options] } if [target_info exists gcc,timeout] { lappend options "timeout=[target_info gcc,timeout]" } - lappend options "additional_flags=-fno-show-column" + lappend options "additional_flags=-fno-show-column -fno-diagnostics-show-caret" lappend options "compiler=$GCC_UNDER_TEST" set options [dg-additional-files-options $options $source] return [target_compile $source $dest $type $options] } Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 138935) +++ gcc/cp/decl.c (working copy) @@ -11898,11 +11898,11 @@ finish_function (int flags) #endif /* Hack. We don't want the middle-end to warn that this return is unreachable, so put the statement on the special line 0. */ { - location_t linezero = linemap_line_start (line_table, 0, 1); + location_t linezero = linemap_line_start (line_table, 0, 1, NULL); SET_EXPR_LOCATION (stmt, linezero); } } if (use_eh_spec_block (current_function_decl)) Index: gcc/c-tree.h =================================================================== --- gcc/c-tree.h (revision 138935) +++ gcc/c-tree.h (working copy) @@ -460,11 +460,11 @@ extern void c_init_decl_processing (void extern void c_dup_lang_specific_decl (tree); extern void c_print_identifier (FILE *, tree, int); extern int quals_from_declspecs (const struct c_declspecs *); extern struct c_declarator *build_array_declarator (tree, struct c_declspecs *, bool, bool); -extern tree build_enumerator (struct c_enum_contents *, tree, tree); +extern tree build_enumerator (struct c_enum_contents *, tree, tree, location_t); extern tree check_for_loop_decls (void); extern void mark_forward_parm_decls (void); extern void declare_parm_level (void); extern void undeclared_variable (tree, location_t); extern tree declare_label (tree); Index: gcc/config.in =================================================================== --- gcc/config.in (revision 138935) +++ gcc/config.in (working copy) @@ -375,15 +375,17 @@ /* Define if your assembler supports thread-local storage. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_TLS #endif + /* Define if your assembler supports VSX instructions. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_VSX #endif + /* Define to 1 if you have the `atoll' function. */ #ifndef USED_FOR_TARGET #undef HAVE_ATOLL #endif @@ -1464,10 +1466,17 @@ #ifndef USED_FOR_TARGET #undef USE_AS_TRADITIONAL_FORMAT #endif +/* Define if diagnostics should print source line with caret symbol indicating + exact location. */ +#ifndef USED_FOR_TARGET +#undef USE_CARET_DIAGNOSTICS +#endif + + /* Define to 1 if the 'long long' (or '__int64') is wider than 'long' but still efficiently supported by the host hardware. */ #ifndef USED_FOR_TARGET #undef USE_LONG_LONG_FOR_WIDEST_FAST_INT #endif Index: gcc/c-pch.c =================================================================== --- gcc/c-pch.c (revision 138935) +++ gcc/c-pch.c (working copy) @@ -427,11 +427,11 @@ c_common_read_pch (cpp_reader *pfile, co fclose (f); line_table->trace_includes = saved_trace_includes; cpp_set_line_map (pfile, line_table); - linemap_add (line_table, LC_RENAME, 0, saved_loc.file, saved_loc.line); + linemap_add (line_table, LC_RENAME, 0, saved_loc.file, saved_loc.line, NULL); /* Give the front end a chance to take action after a PCH file has been loaded. */ if (lang_post_pch_load) (*lang_post_pch_load) (); Index: gcc/opts.c =================================================================== --- gcc/opts.c (revision 138935) +++ gcc/opts.c (working copy) @@ -1743,13 +1743,24 @@ common_handle_option (size_t scode, cons else return 0; break; case OPT_fdiagnostics_show_option: - global_dc->show_option_requested = true; + global_dc->show_option_requested = value; break; + case OPT_fdiagnostics_show_caret: +#ifdef USE_CARET_DIAGNOSTICS + global_dc->show_caret = value; +#else + if (value) + error ("-fdiagnostics-show-caret is disabled. " + "Configure GCC with --enable-caret-diagnostics"); +#endif + break; + + case OPT_fdump_: if (!dump_switch_p (arg)) return 0; break; Index: gcc/ada/gcc-interface/trans.c =================================================================== --- gcc/ada/gcc-interface/trans.c (revision 138935) +++ gcc/ada/gcc-interface/trans.c (working copy) @@ -272,14 +272,14 @@ gigi (Node_Id gnat_root, int max_gnat_no /* We rely on the order isomorphism between files and line maps. */ gcc_assert ((int) line_table->used == i); /* We create the line map for a source file at once, with a fixed number of columns chosen to avoid jumping over the next power of 2. */ - linemap_add (line_table, LC_ENTER, 0, filename, 1); - linemap_line_start (line_table, file_info_ptr[i].Num_Source_Lines, 252); + linemap_add (line_table, LC_ENTER, 0, filename, 1, NULL); + linemap_line_start (line_table, file_info_ptr[i].Num_Source_Lines, 252, NULL); linemap_position_for_column (line_table, 252 - 1); - linemap_add (line_table, LC_LEAVE, 0, NULL, 0); + linemap_add (line_table, LC_LEAVE, 0, NULL, 0, NULL); } /* Initialize ourselves. */ init_code_table (); init_gnat_to_gnu (); Index: gcc/c-decl.c =================================================================== --- gcc/c-decl.c (revision 138935) +++ gcc/c-decl.c (working copy) @@ -5931,11 +5931,11 @@ finish_enum (tree enumtype, tree values, current enumeration type (one that was begun with start_enum). Return a tree-list containing the CONST_DECL and its value. Assignment of sequential values by default is handled here. */ tree -build_enumerator (struct c_enum_contents *the_enum, tree name, tree value) +build_enumerator (struct c_enum_contents *the_enum, tree name, tree value, location_t value_loc) { tree decl, type; /* Validate and default VALUE. */ @@ -5968,11 +5968,12 @@ build_enumerator (struct c_enum_contents error ("overflow in enumeration values"); } if (pedantic && !int_fits_type_p (value, integer_type_node)) { - pedwarn (OPT_pedantic, "ISO C restricts enumerator values to range of %"); + pedwarn (OPT_pedantic, "%HISO C restricts enumerator values to range of %", + &value_loc); /* XXX This causes -pedantic to change the meaning of the program. Remove? -zw 2004-03-15 */ value = convert (integer_type_node, value); } Index: gcc/fortran/scanner.c =================================================================== --- gcc/fortran/scanner.c (revision 138935) +++ gcc/fortran/scanner.c (working copy) @@ -1509,11 +1509,11 @@ get_file (const char *name, enum lc_reas f->up = current_file; if (current_file != NULL) f->inclusion_line = current_file->line; - linemap_add (line_table, reason, false, f->filename, 1); + linemap_add (line_table, reason, false, f->filename, 1, NULL); return f; } @@ -1642,11 +1642,11 @@ preprocessor_line (gfc_char_t *c) } add_file_change (NULL, line); current_file = current_file->up; linemap_add (line_table, LC_RENAME, false, current_file->filename, - current_file->line); + current_file->line, NULL); } /* The name of the file can be a temporary file produced by cpp. Replace the name if it is different. */ @@ -1885,11 +1885,11 @@ load_file (const char *realfilename, con b = (gfc_linebuf *) gfc_getmem (gfc_linebuf_header_size + (len + 1) * sizeof (gfc_char_t)); b->location - = linemap_line_start (line_table, current_file->line++, 120); + = linemap_line_start (line_table, current_file->line++, 120, NULL); b->file = current_file; b->truncated = trunc; wide_strcpy (b->line, line); if (line_head == NULL) @@ -1909,11 +1909,11 @@ load_file (const char *realfilename, con fclose (input); if (!initial) add_file_change (NULL, current_file->inclusion_line + 1); current_file = current_file->up; - linemap_add (line_table, LC_LEAVE, 0, NULL, 0); + linemap_add (line_table, LC_LEAVE, 0, NULL, 0, NULL); return SUCCESS; } /* Open a new file and start scanning from that file. Returns SUCCESS Index: gcc/fortran/f95-lang.c =================================================================== --- gcc/fortran/f95-lang.c (revision 138935) +++ gcc/fortran/f95-lang.c (working copy) @@ -250,12 +250,12 @@ gfc_be_parse_file (int set_yydebug ATTRI static bool gfc_init (void) { if (!gfc_cpp_enabled ()) { - linemap_add (line_table, LC_ENTER, false, gfc_source_file, 1); - linemap_add (line_table, LC_RENAME, false, "", 0); + linemap_add (line_table, LC_ENTER, false, gfc_source_file, 1, NULL); + linemap_add (line_table, LC_RENAME, false, "", 0, NULL); } else gfc_cpp_init_0 (); gfc_init_decl_processing (); Index: gcc/configure.ac =================================================================== --- gcc/configure.ac (revision 138935) +++ gcc/configure.ac (working copy) @@ -340,10 +340,21 @@ warn_cflags= if test "x$GCC" = "xyes"; then warn_cflags='$(GCC_WARN_CFLAGS)' fi AC_SUBST(warn_cflags) +AC_ARG_ENABLE(caret-diagnostics, +[ --enable-caret-diagnostics + enable printing the source code causing a diagnostic + with a caret symbol indicating the exact location.], [], +[enable_caret_diagnostics=no]) + +if test x$enable_caret_diagnostics = xyes ; then + AC_DEFINE(USE_CARET_DIAGNOSTICS, 1, + [Define if diagnostics should print source line with caret symbol indicating exact location.]) +fi + # Enable expensive internal checks is_release= if test x"`cat $srcdir/DEV-PHASE`" != xexperimental; then is_release=yes fi Index: gcc/c-opts.c =================================================================== --- gcc/c-opts.c (revision 138935) +++ gcc/c-opts.c (working copy) @@ -1446,11 +1446,11 @@ finish_options (void) { size_t i; cb_file_change (parse_in, linemap_add (line_table, LC_RENAME, 0, - _(""), 0)); + _(""), 0, NULL)); cpp_init_builtins (parse_in, flag_hosted); c_cpp_builtins (parse_in); /* We're about to send user input to cpplib, so make it warn for @@ -1464,11 +1464,11 @@ finish_options (void) their acceptance on the -std= setting. */ cpp_opts->warn_dollars = (cpp_opts->pedantic && !cpp_opts->c99); cb_file_change (parse_in, linemap_add (line_table, LC_RENAME, 0, - _(""), 0)); + _(""), 0, NULL)); for (i = 0; i < deferred_count; i++) { struct deferred_opt *opt = &deferred_opts[i]; Index: gcc/common.opt =================================================================== --- gcc/common.opt (revision 138935) +++ gcc/common.opt (working copy) @@ -445,10 +445,14 @@ Common Joined RejectNegative fdiagnostics-show-option Common Amend appropriate diagnostic messages with the command line option that controls them +fdiagnostics-show-caret +Common +Show the source line with a caret indicating the column + fdump- Common Joined RejectNegative -fdump- Dump various compiler internals to a file fdump-noaddr Index: gcc/c-parser.c =================================================================== --- gcc/c-parser.c (revision 138935) +++ gcc/c-parser.c (working copy) @@ -1639,19 +1639,21 @@ c_parser_enum_specifier (c_parser *parse } token = c_parser_peek_token (parser); enum_id = token->value; /* Set the location in case we create a decl now. */ c_parser_set_source_position_from_token (token); + comma_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_EQ)) { c_parser_consume_token (parser); + enum_value = c_parser_expr_no_commas (parser, NULL).value; } else enum_value = NULL_TREE; - enum_decl = build_enumerator (&the_enum, enum_id, enum_value); + enum_decl = build_enumerator (&the_enum, enum_id, enum_value, comma_loc); TREE_CHAIN (enum_decl) = values; values = enum_decl; seen_comma = false; if (c_parser_next_token_is (parser, CPP_COMMA)) { Index: libcpp/directives.c =================================================================== --- libcpp/directives.c (revision 138935) +++ libcpp/directives.c (working copy) @@ -1011,14 +1011,17 @@ do_linemarker (cpp_reader *pfile) void _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason, const char *to_file, linenum_type file_line, unsigned int sysp) { - const struct line_map *map = linemap_add (pfile->line_table, reason, sysp, - to_file, file_line); + const struct line_map *map; + const unsigned char *linebuf = (pfile->buffer == NULL) ? NULL : pfile->buffer->next_line; + + map = linemap_add (pfile->line_table, reason, sysp, + to_file, file_line, linebuf); if (map != NULL) - linemap_line_start (pfile->line_table, map->to_line, 127); + linemap_line_start (pfile->line_table, map->to_line, 127, linebuf); if (pfile->cb.file_change) pfile->cb.file_change (pfile, map); } Index: libcpp/line-map.c =================================================================== --- libcpp/line-map.c (revision 138935) +++ libcpp/line-map.c (working copy) @@ -83,11 +83,12 @@ linemap_free (struct line_maps *set) function. A call to this function can relocate the previous set of maps, so any stored line_map pointers should not be used. */ const struct line_map * linemap_add (struct line_maps *set, enum lc_reason reason, - unsigned int sysp, const char *to_file, linenum_type to_line) + unsigned int sysp, const char *to_file, linenum_type to_line, + const unsigned char ARG_UNUSED (*linebuf)) { struct line_map *map; source_location start_location = set->highest_location + 1; if (set->used && start_location < set->maps[set->used - 1].start_location) @@ -155,10 +156,12 @@ linemap_add (struct line_maps *set, enum map->reason = reason; map->sysp = sysp; map->start_location = start_location; map->to_file = to_file; map->to_line = to_line; + if (linebuf != NULL) + map->linebuf = linebuf; set->cache = set->used++; map->column_bits = 0; set->highest_location = start_location; set->highest_line = start_location; set->max_column_hint = 0; @@ -181,11 +184,11 @@ linemap_add (struct line_maps *set, enum return map; } source_location linemap_line_start (struct line_maps *set, linenum_type to_line, - unsigned int max_column_hint) + unsigned int max_column_hint, const unsigned char *linebuf) { struct line_map *map = &set->maps[set->used - 1]; source_location highest = set->highest_location; source_location r; linenum_type last_line = SOURCE_LINE (map, set->highest_line); @@ -198,10 +201,11 @@ linemap_line_start (struct line_maps *se { add_map = true; } else max_column_hint = set->max_column_hint; + if (add_map) { int column_bits; if (max_column_hint > 100000 || highest > 0xC0000000) { @@ -223,11 +227,11 @@ linemap_line_start (struct line_maps *se single line we can sometimes just increase its column_bits instead. */ if (line_delta < 0 || last_line != map->to_line || SOURCE_COLUMN (map, highest) >= (1U << column_bits)) map = (struct line_map *) linemap_add (set, LC_RENAME, map->sysp, - map->to_file, to_line); + map->to_file, to_line, linebuf); map->column_bits = column_bits; r = map->start_location + ((to_line - map->to_line) << column_bits); } else r = highest - SOURCE_COLUMN (map, highest) @@ -251,11 +255,12 @@ linemap_position_for_column (struct line return r; } else { struct line_map *map = &set->maps[set->used - 1]; - r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50); + r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50, + SOURCE_LINEBUFFER (map, r)); } } r = r + to_column; if (r >= set->highest_location) set->highest_location = r; Index: libcpp/files.c =================================================================== --- libcpp/files.c (revision 138935) +++ libcpp/files.c (working copy) @@ -1342,11 +1342,12 @@ _cpp_pop_file_buffer (cpp_reader *pfile, /* Invalidate control macros in the #including file. */ pfile->mi_valid = false; if (file->buffer_start) { - free ((void *) file->buffer_start); + /* CARET: We may need to not free this. */ + /* free ((void *) file->buffer_start);*/ file->buffer_start = NULL; file->buffer = NULL; file->buffer_valid = false; } } Index: libcpp/include/line-map.h =================================================================== --- libcpp/include/line-map.h (revision 138935) +++ libcpp/include/line-map.h (working copy) @@ -66,10 +66,12 @@ struct line_map GTY(()) ENUM_BITFIELD (lc_reason) reason : CHAR_BIT; /* The sysp field isn't really needed now that it's in cpp_buffer. */ unsigned char sysp; /* Number of the low-order source_location bits used for a column number. */ unsigned int column_bits : 8; + /* The input line. */ + const unsigned char * linebuf; }; /* A set of chronological line_map structures. */ struct line_maps GTY(()) { @@ -120,11 +122,11 @@ extern void linemap_check_files_exited ( most recent linemap_add). MAX_COLUMN_HINT is the highest column number we expect to use in this line (but it does not change the highest_location). */ extern source_location linemap_line_start -(struct line_maps *set, linenum_type to_line, unsigned int max_column_hint); +(struct line_maps *set, linenum_type to_line, unsigned int max_column_hint, const unsigned char *linebuf); /* Add a mapping of logical source line to physical source file and line number. The text pointed to by TO_FILE must have a lifetime @@ -135,11 +137,11 @@ extern source_location linemap_line_star A call to this function can relocate the previous set of maps, so any stored line_map pointers should not be used. */ extern const struct line_map *linemap_add (struct line_maps *, enum lc_reason, unsigned int sysp, - const char *to_file, linenum_type to_line); + const char *to_file, linenum_type to_line, const unsigned char *linebuf); /* Given a logical line, returns the map from which the corresponding (source file, line) pair can be deduced. */ extern const struct line_map *linemap_lookup (struct line_maps *, source_location); @@ -155,10 +157,30 @@ extern void linemap_print_containing_fil ((((LOC) - (MAP)->start_location) >> (MAP)->column_bits) + (MAP)->to_line) #define SOURCE_COLUMN(MAP, LOC) \ (((LOC) - (MAP)->start_location) & ((1 << (MAP)->column_bits) - 1)) +static inline const unsigned char * +SOURCE_LINEBUFFER (const struct line_map * MAP, source_location LOCATION) +{ + const unsigned char * linebuf = (MAP)->linebuf; + + if (linebuf != NULL) + { + int i = SOURCE_LINE(MAP, LOCATION) - (MAP)->to_line; + for (;;) + { + if (i == 0 || *linebuf == '\0') + break; + if (*linebuf == '\n') + i--; + linebuf++; + } + } + return linebuf; +} + /* Returns the last source line within a map. This is the (last) line of the #include, or other directive, that caused a map change. */ #define LAST_SOURCE_LINE(MAP) \ SOURCE_LINE (MAP, LAST_SOURCE_LINE_LOCATION (MAP)) #define LAST_SOURCE_LINE_LOCATION(MAP) \ Index: libcpp/internal.h =================================================================== --- libcpp/internal.h (revision 138935) +++ libcpp/internal.h (working copy) @@ -67,11 +67,11 @@ struct cset_converter #define CPP_INCREMENT_LINE(PFILE, COLS_HINT) do { \ const struct line_maps *line_table = PFILE->line_table; \ const struct line_map *map = &line_table->maps[line_table->used-1]; \ linenum_type line = SOURCE_LINE (map, line_table->highest_line); \ - linemap_line_start (PFILE->line_table, line + 1, COLS_HINT); \ + linemap_line_start (PFILE->line_table, line + 1, COLS_HINT, PFILE->buffer->cur); \ } while (0) /* Maximum nesting of cpp_buffers. We use a static limit, partly for efficiency, and partly to limit runaway recursion. */ #define CPP_STACK_MAX 200