Commit b4c7ca2e by David Malcolm Committed by David Malcolm

Documentation hyperlinks for [-Wname-of-option] (PR 87488)

This patch uses the support for pretty-printing escaped URLs added in
the previous patch (PR 87488) so that in a sufficiently capable terminal
the [-Wname-of-option] emitted at the end of each diagnostic becomes a
hyperlink to the documentation for that option on the GCC website.

I've tested it with Fedora 30's GNOME Terminal (3.32.2 with VTE 0.56.3);
the option text is printed with a dotted underline, hovering shows the
URL, and on right-clicking it offers menu items to visit/copy the URL.

gcc/ChangeLog:
	PR 87488
	* Makefile.in (CFLAGS-opts.o): Pass in DOCUMENTATION_ROOT_URL via
	-D.
	* configure.ac (--with-documentation-root-url): New option.
	* configure: Regenerate.
	* diagnostic-format-json.cc (json_end_diagnostic): If there is an
	option URL, add it as a new string field of the diagnostic option.
	* diagnostic.c (diagnostic_initialize): Initialize get_option_url.
	(print_option_information): If get_option_url is non-NULL, call
	it, and if the result is non-NULL, potentially emit an escape
	sequence to markup the option text with the resulting URL.
	* diagnostic.h (diagnostic_context::get_option_url): New callback.
	* doc/invoke.texi (-fdiagnostics-format=): Add "option_url" to
	example of JSON output.
	* opts-diagnostic.h (get_option_url): New decl.
	* opts.c (get_option_url): New function.
	* toplev.c (general_init): Initialize the get_option_url callback.

gcc/testsuite/ChangeLog:
	PR 87488
	* c-c++-common/diagnostic-format-json-2.c: Expect an "option_url"
	field.
	* c-c++-common/diagnostic-format-json-3.c: Likewise.
	* gfortran.dg/diagnostic-format-json-2.F90: Likewise.
	* gfortran.dg/diagnostic-format-json-3.F90: Likewise.
	* jit.dg/test-error-array-bounds.c (create_code): Ensure that
	error messages don't contain escaped URLs.

From-SVN: r276843
parent 3245582f
...@@ -8,6 +8,26 @@ ...@@ -8,6 +8,26 @@
2019-10-10 David Malcolm <dmalcolm@redhat.com> 2019-10-10 David Malcolm <dmalcolm@redhat.com>
PR 87488 PR 87488
* Makefile.in (CFLAGS-opts.o): Pass in DOCUMENTATION_ROOT_URL via
-D.
* configure.ac (--with-documentation-root-url): New option.
* configure: Regenerate.
* diagnostic-format-json.cc (json_end_diagnostic): If there is an
option URL, add it as a new string field of the diagnostic option.
* diagnostic.c (diagnostic_initialize): Initialize get_option_url.
(print_option_information): If get_option_url is non-NULL, call
it, and if the result is non-NULL, potentially emit an escape
sequence to markup the option text with the resulting URL.
* diagnostic.h (diagnostic_context::get_option_url): New callback.
* doc/invoke.texi (-fdiagnostics-format=): Add "option_url" to
example of JSON output.
* opts-diagnostic.h (get_option_url): New decl.
* opts.c (get_option_url): New function.
* toplev.c (general_init): Initialize the get_option_url callback.
2019-10-10 David Malcolm <dmalcolm@redhat.com>
PR 87488
* common.opt (fdiagnostics-urls=): New option. * common.opt (fdiagnostics-urls=): New option.
(diagnostic-url.h): Add SourceInclude. (diagnostic-url.h): Add SourceInclude.
(diagnostic_url_rule): New enum. (diagnostic_url_rule): New enum.
......
...@@ -2142,6 +2142,8 @@ lto-wrapper$(exeext): $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBDEPS) ...@@ -2142,6 +2142,8 @@ lto-wrapper$(exeext): $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBDEPS)
$(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBS) $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBS)
mv -f T$@ $@ mv -f T$@ $@
CFLAGS-opts.o += -DDOCUMENTATION_ROOT_URL=\"@DOCUMENTATION_ROOT_URL@\"
# Files used by all variants of C or by the stand-alone pre-processor. # Files used by all variants of C or by the stand-alone pre-processor.
CFLAGS-c-family/c-opts.o += @TARGET_SYSTEM_ROOT_DEFINE@ CFLAGS-c-family/c-opts.o += @TARGET_SYSTEM_ROOT_DEFINE@
......
...@@ -815,6 +815,7 @@ accel_dir_suffix ...@@ -815,6 +815,7 @@ accel_dir_suffix
real_target_noncanonical real_target_noncanonical
enable_as_accelerator enable_as_accelerator
gnat_install_lib gnat_install_lib
DOCUMENTATION_ROOT_URL
REPORT_BUGS_TEXI REPORT_BUGS_TEXI
REPORT_BUGS_TO REPORT_BUGS_TO
PKGVERSION PKGVERSION
...@@ -960,6 +961,7 @@ enable_gcov ...@@ -960,6 +961,7 @@ enable_gcov
with_specs with_specs
with_pkgversion with_pkgversion
with_bugurl with_bugurl
with_documentation_root_url
enable_languages enable_languages
with_multilib_list with_multilib_list
with_zstd with_zstd
...@@ -1788,6 +1790,8 @@ Optional Packages: ...@@ -1788,6 +1790,8 @@ Optional Packages:
--with-specs=SPECS add SPECS to driver command-line processing --with-specs=SPECS add SPECS to driver command-line processing
--with-pkgversion=PKG Use PKG in the version string in place of "GCC" --with-pkgversion=PKG Use PKG in the version string in place of "GCC"
--with-bugurl=URL Direct users to URL to report a bug --with-bugurl=URL Direct users to URL to report a bug
--with-documentation-root-url=URL
Root for documentation URLs
--with-multilib-list select multilibs (AArch64, SH and x86-64 only) --with-multilib-list select multilibs (AArch64, SH and x86-64 only)
--with-zstd=PATH specify prefix directory for installed zstd library. --with-zstd=PATH specify prefix directory for installed zstd library.
Equivalent to --with-zstd-include=PATH/include plus Equivalent to --with-zstd-include=PATH/include plus
...@@ -7802,6 +7806,23 @@ fi ...@@ -7802,6 +7806,23 @@ fi
# Allow overriding the default URL for documentation
# Check whether --with-documentation-root-url was given.
if test "${with_documentation_root_url+set}" = set; then :
withval=$with_documentation_root_url; case "$withval" in
yes) as_fn_error $? "documentation root URL not specified" "$LINENO" 5 ;;
no) as_fn_error $? "documentation root URL not specified" "$LINENO" 5 ;;
*) DOCUMENTATION_ROOT_URL="$withval"
;;
esac
else
DOCUMENTATION_ROOT_URL="https://gcc.gnu.org/onlinedocs/gcc/"
fi
# Sanity check enable_languages in case someone does not run the toplevel # Sanity check enable_languages in case someone does not run the toplevel
# configure # script. # configure # script.
# Check whether --enable-languages was given. # Check whether --enable-languages was given.
...@@ -18830,7 +18851,7 @@ else ...@@ -18830,7 +18851,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF cat > conftest.$ac_ext <<_LT_EOF
#line 18833 "configure" #line 18854 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
...@@ -18936,7 +18957,7 @@ else ...@@ -18936,7 +18957,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF cat > conftest.$ac_ext <<_LT_EOF
#line 18939 "configure" #line 18960 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
......
...@@ -960,6 +960,20 @@ AC_SUBST(CONFIGURE_SPECS) ...@@ -960,6 +960,20 @@ AC_SUBST(CONFIGURE_SPECS)
ACX_PKGVERSION([GCC]) ACX_PKGVERSION([GCC])
ACX_BUGURL([https://gcc.gnu.org/bugs/]) ACX_BUGURL([https://gcc.gnu.org/bugs/])
# Allow overriding the default URL for documentation
AC_ARG_WITH(documentation-root-url,
AS_HELP_STRING([--with-documentation-root-url=URL],
[Root for documentation URLs]),
[case "$withval" in
yes) AC_MSG_ERROR([documentation root URL not specified]) ;;
no) AC_MSG_ERROR([documentation root URL not specified]) ;;
*) DOCUMENTATION_ROOT_URL="$withval"
;;
esac],
DOCUMENTATION_ROOT_URL="https://gcc.gnu.org/onlinedocs/gcc/"
)
AC_SUBST(DOCUMENTATION_ROOT_URL)
# Sanity check enable_languages in case someone does not run the toplevel # Sanity check enable_languages in case someone does not run the toplevel
# configure # script. # configure # script.
AC_ARG_ENABLE(languages, AC_ARG_ENABLE(languages,
......
...@@ -154,6 +154,17 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, ...@@ -154,6 +154,17 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic,
free (option_text); free (option_text);
} }
if (context->get_option_url)
{
char *option_url = context->get_option_url (context,
diagnostic->option_index);
if (option_url)
{
diag_obj->set ("option_url", new json::string (option_url));
free (option_url);
}
}
/* If we've already emitted a diagnostic within this auto_diagnostic_group, /* If we've already emitted a diagnostic within this auto_diagnostic_group,
then add diag_obj to its "children" array. */ then add diag_obj to its "children" array. */
if (cur_group) if (cur_group)
......
...@@ -200,6 +200,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts) ...@@ -200,6 +200,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
context->option_enabled = NULL; context->option_enabled = NULL;
context->option_state = NULL; context->option_state = NULL;
context->option_name = NULL; context->option_name = NULL;
context->get_option_url = NULL;
context->last_location = UNKNOWN_LOCATION; context->last_location = UNKNOWN_LOCATION;
context->last_module = 0; context->last_module = 0;
context->x_data = NULL; context->x_data = NULL;
...@@ -912,11 +913,22 @@ print_option_information (diagnostic_context *context, ...@@ -912,11 +913,22 @@ print_option_information (diagnostic_context *context,
if (option_text) if (option_text)
{ {
char *option_url = NULL;
if (context->get_option_url)
option_url = context->get_option_url (context,
diagnostic->option_index);
pretty_printer *pp = context->printer; pretty_printer *pp = context->printer;
pp_string (pp, " ["); pp_string (pp, " [");
pp_string (pp, colorize_start (pp_show_color (pp), pp_string (pp, colorize_start (pp_show_color (pp),
diagnostic_kind_color[diagnostic->kind])); diagnostic_kind_color[diagnostic->kind]));
if (option_url)
pp_begin_url (pp, option_url);
pp_string (pp, option_text); pp_string (pp, option_text);
if (option_url)
{
pp_end_url (pp);
free (option_url);
}
pp_string (pp, colorize_stop (pp_show_color (pp))); pp_string (pp, colorize_stop (pp_show_color (pp)));
pp_character (pp, ']'); pp_character (pp, ']');
free (option_text); free (option_text);
......
...@@ -194,6 +194,12 @@ struct diagnostic_context ...@@ -194,6 +194,12 @@ struct diagnostic_context
May be passed 0 as well as the index of a particular option. */ May be passed 0 as well as the index of a particular option. */
char *(*option_name) (diagnostic_context *, int, diagnostic_t, diagnostic_t); char *(*option_name) (diagnostic_context *, int, diagnostic_t, diagnostic_t);
/* Client hook to return a URL describing the option that controls
a diagnostic. Returns malloced memory. May return NULL if no URL
is available. May be passed 0 as well as the index of a
particular option. */
char *(*get_option_url) (diagnostic_context *, int);
/* Auxiliary data for client. */ /* Auxiliary data for client. */
void *x_data; void *x_data;
......
...@@ -4116,6 +4116,7 @@ might be printed in JSON form (after formatting) like this: ...@@ -4116,6 +4116,7 @@ might be printed in JSON form (after formatting) like this:
], ],
"message": "this \u2018if\u2019 clause does not guard...", "message": "this \u2018if\u2019 clause does not guard...",
"option": "-Wmisleading-indentation", "option": "-Wmisleading-indentation",
"option_url": "https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wmisleading-indentation",
"children": [ "children": [
@{ @{
"kind": "note", "kind": "note",
...@@ -22,4 +22,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -22,4 +22,7 @@ along with GCC; see the file COPYING3. If not see
extern char *option_name (diagnostic_context *context, int option_index, extern char *option_name (diagnostic_context *context, int option_index,
diagnostic_t orig_diag_kind, diagnostic_t diag_kind); diagnostic_t orig_diag_kind, diagnostic_t diag_kind);
extern char *get_option_url (diagnostic_context *context, int option_index);
#endif #endif
...@@ -3218,3 +3218,24 @@ option_name (diagnostic_context *context, int option_index, ...@@ -3218,3 +3218,24 @@ option_name (diagnostic_context *context, int option_index,
else else
return NULL; return NULL;
} }
/* Return malloced memory for a URL describing the option OPTION_INDEX
which enabled a diagnostic (context CONTEXT). */
char *
get_option_url (diagnostic_context *, int option_index)
{
if (option_index)
/* DOCUMENTATION_ROOT_URL should be supplied via -D by the Makefile
(see --with-documentation-root-url).
Expect an anchor of the form "index-Wfoo" e.g.
<a name="index-Wformat"></a>, and thus an id within
the URL of "#index-Wformat". */
return concat (DOCUMENTATION_ROOT_URL,
"Warning-Options.html",
"#index", cl_options[option_index].opt_text,
NULL);
else
return NULL;
}
2019-10-10 David Malcolm <dmalcolm@redhat.com> 2019-10-10 David Malcolm <dmalcolm@redhat.com>
PR 87488 PR 87488
* c-c++-common/diagnostic-format-json-2.c: Expect an "option_url"
field.
* c-c++-common/diagnostic-format-json-3.c: Likewise.
* gfortran.dg/diagnostic-format-json-2.F90: Likewise.
* gfortran.dg/diagnostic-format-json-3.F90: Likewise.
* jit.dg/test-error-array-bounds.c (create_code): Ensure that
error messages don't contain escaped URLs.
2019-10-10 David Malcolm <dmalcolm@redhat.com>
PR 87488
* lib/prune.exp (TEST_ALWAYS_FLAGS): Add -fdiagnostics-urls=never. * lib/prune.exp (TEST_ALWAYS_FLAGS): Add -fdiagnostics-urls=never.
2019-10-10 Uroš Bizjak <ubizjak@gmail.com> 2019-10-10 Uroš Bizjak <ubizjak@gmail.com>
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
/* { dg-regexp "\"kind\": \"warning\"" } */ /* { dg-regexp "\"kind\": \"warning\"" } */
/* { dg-regexp "\"message\": \"#warning message\"" } */ /* { dg-regexp "\"message\": \"#warning message\"" } */
/* { dg-regexp "\"option\": \"-Wcpp\"" } */ /* { dg-regexp "\"option\": \"-Wcpp\"" } */
/* { dg-regexp "\"option_url\": \"https:\[^\n\r\"\]*#index-Wcpp\"" } */
/* { dg-regexp "\"caret\": \{" } */ /* { dg-regexp "\"caret\": \{" } */
/* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-2.c\"" } */ /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-2.c\"" } */
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
/* { dg-regexp "\"kind\": \"error\"" } */ /* { dg-regexp "\"kind\": \"error\"" } */
/* { dg-regexp "\"message\": \"#warning message\"" } */ /* { dg-regexp "\"message\": \"#warning message\"" } */
/* { dg-regexp "\"option\": \"-Werror=cpp\"" } */ /* { dg-regexp "\"option\": \"-Werror=cpp\"" } */
/* { dg-regexp "\"option_url\": \"https:\[^\n\r\"\]*#index-Wcpp\"" } */
/* { dg-regexp "\"caret\": \{" } */ /* { dg-regexp "\"caret\": \{" } */
/* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-3.c\"" } */ /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-3.c\"" } */
......
...@@ -30,13 +30,12 @@ int test (void) ...@@ -30,13 +30,12 @@ int test (void)
/* { dg-regexp "\"line\": 8" } */ /* { dg-regexp "\"line\": 8" } */
/* { dg-regexp "\"column\": 10" } */ /* { dg-regexp "\"column\": 10" } */
/* { dg-regexp "\"locations\": \[\[\{\}, \]*\]" } */
/* The outer diagnostic. */ /* The outer diagnostic. */
/* { dg-regexp "\"kind\": \"warning\"" } */ /* { dg-regexp "\"kind\": \"warning\"" } */
/* { dg-regexp "\"message\": \"this 'if' clause does not guard...\"" } */ /* { dg-regexp "\"message\": \"this 'if' clause does not guard...\"" } */
/* { dg-regexp "\"option\": \"-Wmisleading-indentation\"" } */ /* { dg-regexp "\"option\": \"-Wmisleading-indentation\"" } */
/* { dg-regexp "\"option_url\": \"https:\[^\n\r\"\]*#index-Wmisleading-indentation\"" } */
/* { dg-regexp "\"caret\": \{" } */ /* { dg-regexp "\"caret\": \{" } */
/* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-4.c\"" } */ /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-4.c\"" } */
...@@ -48,6 +47,13 @@ int test (void) ...@@ -48,6 +47,13 @@ int test (void)
/* { dg-regexp "\"line\": 6" } */ /* { dg-regexp "\"line\": 6" } */
/* { dg-regexp "\"column\": 4" } */ /* { dg-regexp "\"column\": 4" } */
/* More from the nested diagnostic (we can't guarantee what order the
"file" keys are consumed). */
/* { dg-regexp "\"locations\": \[\[\{\}, \]*\]" } */
/* More from the outer diagnostic. */
/* { dg-regexp "\"locations\": \[\[\{\}, \]*\]" } */ /* { dg-regexp "\"locations\": \[\[\{\}, \]*\]" } */
/* { dg-regexp "\"children\": \[\[\{\}, \]*\]" } */ /* { dg-regexp "\"children\": \[\[\{\}, \]*\]" } */
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
! { dg-regexp "\"kind\": \"warning\"" } ! { dg-regexp "\"kind\": \"warning\"" }
! { dg-regexp "\"message\": \"#warning message\"" } ! { dg-regexp "\"message\": \"#warning message\"" }
! { dg-regexp "\"option\": \"-Wcpp\"" } ! { dg-regexp "\"option\": \"-Wcpp\"" }
! { dg-regexp "\"option_url\": \"\[^\n\r\"\]*#index-Wcpp\"" }
! { dg-regexp "\"caret\": \{" } ! { dg-regexp "\"caret\": \{" }
! { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-2.F90\"" } ! { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-2.F90\"" }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
! { dg-regexp "\"kind\": \"error\"" } ! { dg-regexp "\"kind\": \"error\"" }
! { dg-regexp "\"message\": \"#warning message\"" } ! { dg-regexp "\"message\": \"#warning message\"" }
! { dg-regexp "\"option\": \"-Werror=cpp\"" } ! { dg-regexp "\"option\": \"-Werror=cpp\"" }
! { dg-regexp "\"option_url\": \"\[^\n\r\"\]*#index-Wcpp\"" }
! { dg-regexp "\"caret\": \{" } ! { dg-regexp "\"caret\": \{" }
! { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-3.F90\"" } ! { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-3.F90\"" }
......
...@@ -20,9 +20,10 @@ create_code (gcc_jit_context *ctxt, void *user_data) ...@@ -20,9 +20,10 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_context_add_command_line_option (ctxt, "-Warray-bounds"); gcc_jit_context_add_command_line_option (ctxt, "-Warray-bounds");
gcc_jit_context_add_command_line_option (ctxt, "-ftree-vrp"); gcc_jit_context_add_command_line_option (ctxt, "-ftree-vrp");
/* Ensure that the error message doesn't contain colorization codes, /* Ensure that the error message doesn't contain colorization codes
even if run at a TTY. */ or escaped URLs, even if run at a TTY. */
gcc_jit_context_add_command_line_option (ctxt, "-fdiagnostics-color=never"); gcc_jit_context_add_command_line_option (ctxt, "-fdiagnostics-color=never");
gcc_jit_context_add_command_line_option (ctxt, "-fdiagnostics-urls=never");
gcc_jit_type *char_type = gcc_jit_type *char_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR); gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
......
...@@ -1110,6 +1110,7 @@ general_init (const char *argv0, bool init_signals) ...@@ -1110,6 +1110,7 @@ general_init (const char *argv0, bool init_signals)
global_dc->option_enabled = option_enabled; global_dc->option_enabled = option_enabled;
global_dc->option_state = &global_options; global_dc->option_state = &global_options;
global_dc->option_name = option_name; global_dc->option_name = option_name;
global_dc->get_option_url = get_option_url;
if (init_signals) if (init_signals)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment