diff mbox series

[RFC/PATCH] diagnostics: UX: add doc URLs for attributes

Message ID 20240624220940.1353548-1-dmalcolm@redhat.com
State New
Headers show
Series [RFC/PATCH] diagnostics: UX: add doc URLs for attributes | expand

Commit Message

David Malcolm June 24, 2024, 10:09 p.m. UTC
In r14-5118-gc5db4d8ba5f3de I added a mechanism to automatically add
documentation URLs to quoted strings in diagnostics.
In r14-6920-g9e49746da303b8 I added a mechanism to generate URLs for
mentions of command-line options in quoted strings in diagnostics.

This patch does a similar thing for attributes.  It adds a new Python 3
script to scrape the generated HTML looking for documentation of
attributes, and uses this to (re)generate a new gcc/attr-urls.def file.

Running "make regenerate-attr-urls" after rebuilding the HTML docs will
regenerate gcc/attr-urls.def in the source directory.

The patch uses this to optionally add doc URLs for attributes in any
diagnostic emitted during the lifetime of a auto_urlify_attributes
instance, and adds such instances everywhere that a diagnostic refers
to a diagnostic within quotes (based on grepping the source tree
for references to attributes in strings and in code).

For example, given:

$ ./xgcc -B. -S ../../src/gcc/testsuite/gcc.dg/attr-access-2.c
../../src/gcc/testsuite/gcc.dg/attr-access-2.c:14:16: warning:
attribute ‘access(read_write, 2, 3)’ positional argument 2 conflicts
with previous designation by argument 1 [-Wattributes]

with this patch the quoted text `access(read_write, 2, 3)'
automatically gains the URL for our docs for "access":
  https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-access-function-attribute
in a sufficiently modern terminal.

Two points I'm not sure about:

- like r14-6920-g9e49746da303b8 this avoids the Makefile target
depending on the generated HTML, since a missing URL is a minor
problem, whereas requiring all users to build HTML docs seems more
involved.  Doing so also avoids Python 3 as a build requirement for
everyone, but instead just for developers addding attributes.
Like the options, we could add a CI test for this.  Is this the right
approach?

- the patch currently gathers target-specific attributes, but doesn't
select the appropriate one; it just picks the first one it sees.  For
example, the function attribute "interrupt" has 19 URLs within our docs:
one common, and 18 target-specific ones.  I'm not sure what the best
approach here is; perhaps some kind of new target hook for identifying
target-specific documentation?

Thoughts?

gcc/ChangeLog:
	* Makefile.in (ATTR_URLS_HTML_DEPS): New.
	(regenerate-attr-urls): New.
	(regenerate-attr-urls-unit-test): New.
	* attr-urls.def: New file.
	* attribs.cc: Include "gcc-urlifier.h".
	(decl_attributes): Use auto_urlify_attributes.
	* diagnostic.cc (diagnostic_context::override_urlifier): New.
	* diagnostic.h (diagnostic_context::override_urlifier): New decl.
	(diagnostic_context::get_urlifier): New accessor.
	* gcc-urlifier.cc: Include "diagnostic.h" and "attr-urls.def".
	(gcc_urlifier::make_doc): Convert to...
	(make_doc_url): ...this.
	(auto_override_urlifier::auto_override_urlifier): New.
	(auto_override_urlifier::~auto_override_urlifier): New.
	(struct attr_url_entry): New.
	(find_attr_url_entry): New.
	(attribute_urlifier::get_url_for_quoted_text): New.
	(attribute_urlifier::get_url_suffix_for_quoted_text): New.
	(selftest::gcc_urlifier_cc_tests): Split out body into...
	(selftest::test_gcc_urlifier): ...this, and also call...
	(selftest::test_attribute_urlifier): ...this new function.
	* gcc-urlifier.h: Include "pretty-print-urlifier.h" and "label-text.h".
	(class auto_override_urlifier): New.
	(class attribute_urlifier): New.
	(class auto_urlify_attributes): New.
	* gimple-ssa-warn-access.cc: Include "gcc-urlifier.h".
	(pass_waccess::execute): Use auto_urlify_attributes.
	* gimplify.cc: Include "gcc-urlifier.h".
	(expand_FALLTHROUGH): Use auto_urlify_attributes.
	* internal-fn.cc: Include "gcc-urlifier.h.
	(expand_FALLTHROUGH): Use auto_urlify_attributes.
	* ipa-pure-const.cc: Include "gcc-urlifier.h.
	(suggest_attribute): Use auto_urlify_attributes.
	* ipa-strub.cc: Include "gcc-urlifier.h.
	(can_strub_p): Use auto_urlify_attributes.
	* regenerate-attr-urls.py: New file.
	* tree-cfg.cc: Include "gcc-urlifier.h.
	(do_warn_unused_result): Use auto_urlify_attributes.
	* tree-ssa-uninit.cc: Include "gcc-urlifier.h.
	(maybe_warn_read_write_only): Use auto_urlify_attributes.
	(maybe_warn_pass_by_reference): Likewise.

gcc/analyzer/ChangeLog:
	* region-model.cc: Include "gcc-urlifier.h".
	(reason_attr_access::emit): Use auto_urlify_attributes.
	* sm-taint.cc: Include "gcc-urlifier.h".
	(tainted_access_attrib_size::emit): Use auto_urlify_attributes.

gcc/c-family/ChangeLog:
	* c-attribs.cc: Include "gcc-urlifier.h".
	(positional_argument): Use auto_urlify_attributes.
	* c-common.cc: Include "gcc-urlifier.h".
	(parse_optimize_options): Use auto_urlify_attributes with
	OPT_Wattributes.
	(attribute_fallthrough_p): Use auto_urlify_attributes.
	* c-warn.cc: Include "gcc-urlifier.h".
	(diagnose_mismatched_attributes): Use auto_urlify_attributes.

gcc/c/ChangeLog:
	* c-decl.cc: Include "gcc-urlifier.h".
	(start_decl): Use auto_urlify_attributes with OPT_Wattributes.
	(start_function): Likewise.
	* c-parser.cc: Include "gcc-urlifier.h".
	(c_parser_statement_after_labels): Use auto_urlify_attributes with
	OPT_Wattributes.
	* c-typeck.cc: Include "gcc-urlifier.h".
	(maybe_warn_nodiscard): Use auto_urlify_attributes with
	OPT_Wunused_result.

gcc/cp/ChangeLog:
	* cp-gimplify.cc: Include "gcc-urlifier.h".
	(process_stmt_hotness_attribute): Use auto_urlify_attributes with
	OPT_Wattributes.
	* cvt.cc: Include "gcc-urlifier.h".
	(maybe_warn_nodiscard): Use auto_urlify_attributes with
	OPT_Wunused_result.
	* decl.cc: Include "gcc-urlifier.h".
	(start_decl): Use auto_urlify_attributes.
	(start_preparsed_function): Likewise.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/Makefile.in               |  12 ++
 gcc/analyzer/region-model.cc  |   2 +
 gcc/analyzer/sm-taint.cc      |   2 +
 gcc/attr-urls.def             | 372 ++++++++++++++++++++++++++++++++++
 gcc/attribs.cc                |   3 +
 gcc/c-family/c-attribs.cc     |   3 +
 gcc/c-family/c-common.cc      |  18 +-
 gcc/c-family/c-warn.cc        |   2 +
 gcc/c/c-decl.cc               |  17 +-
 gcc/c/c-parser.cc             |  20 +-
 gcc/c/c-typeck.cc             |   3 +
 gcc/cp/cp-gimplify.cc         |   8 +-
 gcc/cp/cvt.cc                 |   4 +
 gcc/cp/decl.cc                |  15 +-
 gcc/diagnostic.cc             |   8 +
 gcc/diagnostic.h              |   3 +
 gcc/gcc-urlifier.cc           | 182 +++++++++++++++--
 gcc/gcc-urlifier.h            |  50 +++++
 gcc/gimple-ssa-warn-access.cc |   3 +
 gcc/gimplify.cc               |   3 +
 gcc/internal-fn.cc            |   2 +
 gcc/ipa-pure-const.cc         |   2 +
 gcc/ipa-strub.cc              |   3 +
 gcc/regenerate-attr-urls.py   | 209 +++++++++++++++++++
 gcc/tree-cfg.cc               |   3 +
 gcc/tree-ssa-uninit.cc        |   3 +
 26 files changed, 914 insertions(+), 38 deletions(-)
 create mode 100644 gcc/attr-urls.def
 create mode 100755 gcc/regenerate-attr-urls.py
diff mbox series

Patch

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 9eacb21bf543..f864539450f2 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3655,6 +3655,18 @@  regenerate-opt-urls: $(srcdir)/regenerate-opt-urls.py $(OPT_URLS_HTML_DEPS)
 regenerate-opt-urls-unit-test: $(OPT_URLS_HTML_DEPS)
 	$(srcdir)/regenerate-opt-urls.py $(build_htmldir) $(shell dirname $(srcdir)) --unit-test
 
+# Regenerate attr-urls.def from the generated html.
+.PHONY: regenerate-attr-urls
+ATTR_URLS_HTML_DEPS = $(build_htmldir)/gcc/Concept-and-Symbol-Index.html
+
+regenerate-attr-urls: $(srcdir)/regenerate-attr-urls.py $(ATTR_URLS_HTML_DEPS)
+	$(srcdir)/regenerate-attr-urls.py $(build_htmldir) $(shell dirname $(srcdir))
+
+# Run the unit tests for regenerate-attr-urls.py
+.PHONY: regenerate-attr-urls-unit-test
+regenerate-attr-urls-unit-test: $(ATTR_URLS_HTML_DEPS)
+	$(srcdir)/regenerate-attr-urls.py $(build_htmldir) $(shell dirname $(srcdir)) --unit-test
+
 MANFILES = doc/gcov.1 doc/cpp.1 doc/gcc.1 doc/gfdl.7 doc/gpl.7 \
            doc/fsf-funding.7 doc/gcov-tool.1 doc/gcov-dump.1 \
 	   $(if $(filter yes,@enable_lto@),doc/lto-dump.1)
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 4d6e16cf0f4d..72ad702219ea 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -82,6 +82,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "analyzer/record-layout.h"
 #include "diagnostic-format-sarif.h"
 #include "text-art/tree-widget.h"
+#include "gcc-urlifier.h"
 
 #if ENABLE_ANALYZER
 
@@ -2037,6 +2038,7 @@  public:
 
   void emit () const final override
   {
+    auto_urlify_attributes sentinel;
     inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
 	    "parameter %i of %qD marked with attribute %qs",
 	    m_ptr_argno + 1, m_callee_fndecl, m_access_str);
diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index 3bd050f96352..87fa3769156e 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -52,6 +52,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "analyzer/pending-diagnostic.h"
 #include "analyzer/constraint-manager.h"
 #include "diagnostic-format-sarif.h"
+#include "gcc-urlifier.h"
 
 #if ENABLE_ANALYZER
 
@@ -581,6 +582,7 @@  public:
     bool warned = tainted_size::emit (ctxt);
     if (warned)
       {
+	auto_urlify_attributes sentinel;
 	inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
 		"parameter %i of %qD marked as a size via attribute %qs",
 		m_size_argno + 1, m_callee_fndecl, m_access_str);
diff --git a/gcc/attr-urls.def b/gcc/attr-urls.def
new file mode 100644
index 000000000000..fcb2ee0719d0
--- /dev/null
+++ b/gcc/attr-urls.def
@@ -0,0 +1,372 @@ 
+/* Autogenerated by regenerate-attr-urls.py.  */
+
+const attr_url_entry enumerator_attrs[] = {
+ { "deprecated", "gcc/Enumerator-Attributes.html#index-deprecated-enumerator-attribute", "", 10},
+ { "unavailable", "gcc/Enumerator-Attributes.html#index-unavailable-enumerator-attribute", "", 11},
+};
+
+const attr_url_entry function_attrs[] = {
+ { "OS_main", "gcc/AVR-Function-Attributes.html#index-OS_005fmain-function-attribute_002c-AVR", "AVR", 7},
+ { "OS_task", "gcc/AVR-Function-Attributes.html#index-OS_005ftask-function-attribute_002c-AVR", "AVR", 7},
+ { "abi_tag", "gcc/C_002b_002b-Attributes.html#index-abi_005ftag-function-attribute", "", 7},
+ { "access", "gcc/Common-Function-Attributes.html#index-access-function-attribute", "", 6},
+ { "alias", "gcc/Common-Function-Attributes.html#index-alias-function-attribute", "", 5},
+ { "aligned", "gcc/Common-Function-Attributes.html#index-aligned-function-attribute", "", 7},
+ { "alloc_align", "gcc/Common-Function-Attributes.html#index-alloc_005falign-function-attribute", "", 11},
+ { "alloc_size", "gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute", "", 10},
+ { "always_inline", "gcc/Common-Function-Attributes.html#index-always_005finline-function-attribute", "", 13},
+ { "amdgpu_hsa_kernel", "gcc/AMD-GCN-Function-Attributes.html#index-amdgpu_005fhsa_005fkernel-function-attribute_002c-AMD-GCN", "AMD GCN", 17},
+ { "arch=", "gcc/AArch64-Function-Attributes.html#index-arch_003d-function-attribute_002c-AArch64", "AArch64", 5},
+ { "arch=", "gcc/ARM-Function-Attributes.html#index-arch_003d-function-attribute_002c-ARM", "ARM", 5},
+ { "arch=", "gcc/RISC-V-Function-Attributes.html#index-arch_003d-function-attribute_002c-RISC-V", "RISC-V", 5},
+ { "artificial", "gcc/Common-Function-Attributes.html#index-artificial-function-attribute", "", 10},
+ { "assume_aligned", "gcc/Common-Function-Attributes.html#index-assume_005faligned-function-attribute", "", 14},
+ { "bank_switch", "gcc/M32C-Function-Attributes.html#index-bank_005fswitch-function-attribute_002c-M32C", "M32C", 11},
+ { "branch-protection", "gcc/AArch64-Function-Attributes.html#index-branch-protection-function-attribute_002c-AArch64", "AArch64", 17},
+ { "break_handler", "gcc/MicroBlaze-Function-Attributes.html#index-break_005fhandler-function-attribute_002c-MicroBlaze", "MicroBlaze", 13},
+ { "brk_interrupt", "gcc/RL78-Function-Attributes.html#index-brk_005finterrupt-function-attribute_002c-RL78", "RL78", 13},
+ { "callee_pop_aggregate_return", "gcc/x86-Function-Attributes.html#index-callee_005fpop_005faggregate_005freturn-function-attribute_002c-x86", "x86", 27},
+ { "cdecl", "gcc/x86-Function-Attributes.html#index-cdecl-function-attribute_002c-x86-32", "x86-32", 5},
+ { "cf_check", "gcc/x86-Function-Attributes.html#index-cf_005fcheck-function-attribute_002c-x86", "x86", 8},
+ { "cmodel=", "gcc/AArch64-Function-Attributes.html#index-cmodel_003d-function-attribute_002c-AArch64", "AArch64", 7},
+ { "code_readable", "gcc/MIPS-Function-Attributes.html#index-code_005freadable-function-attribute_002c-MIPS", "MIPS", 13},
+ { "cold", "gcc/Common-Function-Attributes.html#index-cold-function-attribute", "", 4},
+ { "const", "gcc/Common-Function-Attributes.html#index-const-function-attribute", "", 5},
+ { "constructor", "gcc/Common-Function-Attributes.html#index-constructor-function-attribute", "", 11},
+ { "copy", "gcc/Common-Function-Attributes.html#index-copy-function-attribute", "", 4},
+ { "cpu=", "gcc/AArch64-Function-Attributes.html#index-cpu_003d-function-attribute_002c-AArch64", "AArch64", 4},
+ { "cpu=", "gcc/RISC-V-Function-Attributes.html#index-cpu_003d-function-attribute_002c-RISC-V", "RISC-V", 4},
+ { "critical", "gcc/MSP430-Function-Attributes.html#index-critical-function-attribute_002c-MSP430", "MSP430", 8},
+ { "deprecated", "gcc/Common-Function-Attributes.html#index-deprecated-function-attribute", "", 10},
+ { "destructor", "gcc/Common-Function-Attributes.html#index-destructor-function-attribute", "", 10},
+ { "disinterrupt", "gcc/Epiphany-Function-Attributes.html#index-disinterrupt-function-attribute_002c-Epiphany", "Epiphany", 12},
+ { "dllexport", "gcc/Microsoft-Windows-Function-Attributes.html#index-dllexport-function-attribute", "", 9},
+ { "dllimport", "gcc/Microsoft-Windows-Function-Attributes.html#index-dllimport-function-attribute", "", 9},
+ { "either", "gcc/MSP430-Function-Attributes.html#index-either-function-attribute_002c-MSP430", "MSP430", 6},
+ { "error", "gcc/Common-Function-Attributes.html#index-error-function-attribute", "", 5},
+ { "exception", "gcc/NDS32-Function-Attributes.html#index-exception-function-attribute", "", 9},
+ { "exception_handler", "gcc/Blackfin-Function-Attributes.html#index-exception_005fhandler-function-attribute", "", 17},
+ { "expected_throw", "gcc/Common-Function-Attributes.html#index-expected_005fthrow-function-attribute", "", 14},
+ { "externally_visible", "gcc/Common-Function-Attributes.html#index-externally_005fvisible-function-attribute", "", 18},
+ { "far", "gcc/MIPS-Function-Attributes.html#index-far-function-attribute_002c-MIPS", "MIPS", 3},
+ { "fast_interrupt", "gcc/M32C-Function-Attributes.html#index-fast_005finterrupt-function-attribute_002c-M32C", "M32C", 14},
+ { "fast_interrupt", "gcc/MicroBlaze-Function-Attributes.html#index-fast_005finterrupt-function-attribute_002c-MicroBlaze", "MicroBlaze", 14},
+ { "fast_interrupt", "gcc/RX-Function-Attributes.html#index-fast_005finterrupt-function-attribute_002c-RX", "RX", 14},
+ { "fastcall", "gcc/x86-Function-Attributes.html#index-fastcall-function-attribute_002c-x86-32", "x86-32", 8},
+ { "fd_arg", "gcc/Common-Function-Attributes.html#index-fd_005farg-function-attribute", "", 6},
+ { "fd_arg_read", "gcc/Common-Function-Attributes.html#index-fd_005farg_005fread-function-attribute", "", 11},
+ { "fd_arg_write", "gcc/Common-Function-Attributes.html#index-fd_005farg_005fwrite-function-attribute", "", 12},
+ { "fentry_name", "gcc/x86-Function-Attributes.html#index-fentry_005fname-function-attribute_002c-x86", "x86", 11},
+ { "fentry_section", "gcc/x86-Function-Attributes.html#index-fentry_005fsection-function-attribute_002c-x86", "x86", 14},
+ { "fix-cortex-a53-835769", "gcc/AArch64-Function-Attributes.html#index-fix-cortex-a53-835769-function-attribute_002c-AArch64", "AArch64", 21},
+ { "flatten", "gcc/Common-Function-Attributes.html#index-flatten-function-attribute", "", 7},
+ { "force_align_arg_pointer", "gcc/x86-Function-Attributes.html#index-force_005falign_005farg_005fpointer-function-attribute_002c-x86", "x86", 23},
+ { "format", "gcc/Common-Function-Attributes.html#index-format-function-attribute", "", 6},
+ { "format_arg", "gcc/Common-Function-Attributes.html#index-format_005farg-function-attribute", "", 10},
+ { "forwarder_section", "gcc/Epiphany-Function-Attributes.html#index-forwarder_005fsection-function-attribute_002c-Epiphany", "Epiphany", 17},
+ { "function_return", "gcc/x86-Function-Attributes.html#index-function_005freturn-function-attribute_002c-x86", "x86", 15},
+ { "function_vector", "gcc/H8_002f300-Function-Attributes.html#index-function_005fvector-function-attribute_002c-H8_002f300", "H8/300", 15},
+ { "function_vector", "gcc/M32C-Function-Attributes.html#index-function_005fvector-function-attribute_002c-M16C_002fM32C", "M16C/M32C", 15},
+ { "function_vector", "gcc/SH-Function-Attributes.html#index-function_005fvector-function-attribute_002c-SH", "SH", 15},
+ { "general-regs-only", "gcc/AArch64-Function-Attributes.html#index-general-regs-only-function-attribute_002c-AArch64", "AArch64", 17},
+ { "general-regs-only", "gcc/ARM-Function-Attributes.html#index-general-regs-only-function-attribute_002c-ARM", "ARM", 17},
+ { "gnu_inline", "gcc/Common-Function-Attributes.html#index-gnu_005finline-function-attribute", "", 10},
+ { "hot", "gcc/Common-Function-Attributes.html#index-hot-function-attribute", "", 3},
+ { "hotpatch", "gcc/S_002f390-Function-Attributes.html#index-hotpatch-function-attribute_002c-S_002f390", "S/390", 8},
+ { "ifunc", "gcc/Common-Function-Attributes.html#index-ifunc-function-attribute", "", 5},
+ { "indirect_branch", "gcc/x86-Function-Attributes.html#index-indirect_005fbranch-function-attribute_002c-x86", "x86", 15},
+ { "indirect_return", "gcc/x86-Function-Attributes.html#index-indirect_005freturn-function-attribute_002c-x86", "x86", 15},
+ { "interrupt", "gcc/ARC-Function-Attributes.html#index-interrupt-function-attribute_002c-ARC", "ARC", 9},
+ { "interrupt", "gcc/ARM-Function-Attributes.html#index-interrupt-function-attribute_002c-ARM", "ARM", 9},
+ { "interrupt", "gcc/AVR-Function-Attributes.html#index-interrupt-function-attribute_002c-AVR", "AVR", 9},
+ { "interrupt", "gcc/C-SKY-Function-Attributes.html#index-interrupt-function-attribute_002c-C-SKY", "C-SKY", 9},
+ { "interrupt", "gcc/Common-Function-Attributes.html#index-interrupt-function-attribute", "", 9},
+ { "interrupt", "gcc/Epiphany-Function-Attributes.html#index-interrupt-function-attribute_002c-Epiphany", "Epiphany", 9},
+ { "interrupt", "gcc/M32C-Function-Attributes.html#index-interrupt-function-attribute_002c-M32C", "M32C", 9},
+ { "interrupt", "gcc/M32R_002fD-Function-Attributes.html#index-interrupt-function-attribute_002c-M32R_002fD", "M32R/D", 9},
+ { "interrupt", "gcc/MIPS-Function-Attributes.html#index-interrupt-function-attribute_002c-MIPS", "MIPS", 9},
+ { "interrupt", "gcc/MSP430-Function-Attributes.html#index-interrupt-function-attribute_002c-MSP430", "MSP430", 9},
+ { "interrupt", "gcc/NDS32-Function-Attributes.html#index-interrupt-function-attribute_002c-NDS32", "NDS32", 9},
+ { "interrupt", "gcc/RISC-V-Function-Attributes.html#index-interrupt-function-attribute_002c-RISC-V", "RISC-V", 9},
+ { "interrupt", "gcc/RL78-Function-Attributes.html#index-interrupt-function-attribute_002c-RL78", "RL78", 9},
+ { "interrupt", "gcc/RX-Function-Attributes.html#index-interrupt-function-attribute_002c-RX", "RX", 9},
+ { "interrupt", "gcc/V850-Function-Attributes.html#index-interrupt-function-attribute_002c-V850", "V850", 9},
+ { "interrupt", "gcc/Visium-Function-Attributes.html#index-interrupt-function-attribute_002c-Visium", "Visium", 9},
+ { "interrupt", "gcc/Xstormy16-Function-Attributes.html#index-interrupt-function-attribute_002c-Xstormy16", "Xstormy16", 9},
+ { "interrupt", "gcc/m68k-Function-Attributes.html#index-interrupt-function-attribute_002c-m68k", "m68k", 9},
+ { "interrupt", "gcc/x86-Function-Attributes.html#index-interrupt-function-attribute_002c-x86", "x86", 9},
+ { "interrupt_handler", "gcc/Blackfin-Function-Attributes.html#index-interrupt_005fhandler-function-attribute_002c-Blackfin", "Blackfin", 17},
+ { "interrupt_handler", "gcc/Common-Function-Attributes.html#index-interrupt_005fhandler-function-attribute", "", 17},
+ { "interrupt_handler", "gcc/H8_002f300-Function-Attributes.html#index-interrupt_005fhandler-function-attribute_002c-H8_002f300", "H8/300", 17},
+ { "interrupt_handler", "gcc/MicroBlaze-Function-Attributes.html#index-interrupt_005fhandler-function-attribute_002c-MicroBlaze", "MicroBlaze", 17},
+ { "interrupt_handler", "gcc/SH-Function-Attributes.html#index-interrupt_005fhandler-function-attribute_002c-SH", "SH", 17},
+ { "interrupt_handler", "gcc/V850-Function-Attributes.html#index-interrupt_005fhandler-function-attribute_002c-V850", "V850", 17},
+ { "interrupt_handler", "gcc/m68k-Function-Attributes.html#index-interrupt_005fhandler-function-attribute_002c-m68k", "m68k", 17},
+ { "interrupt_thread", "gcc/m68k-Function-Attributes.html#index-interrupt_005fthread-function-attribute_002c-fido", "fido", 16},
+ { "isr", "gcc/ARM-Function-Attributes.html#index-isr-function-attribute_002c-ARM", "ARM", 3},
+ { "isr", "gcc/C-SKY-Function-Attributes.html#index-isr-function-attribute_002c-C-SKY", "C-SKY", 3},
+ { "jli_always", "gcc/ARC-Function-Attributes.html#index-jli_005falways-function-attribute_002c-ARC", "ARC", 10},
+ { "jli_fixed", "gcc/ARC-Function-Attributes.html#index-jli_005ffixed-function-attribute_002c-ARC", "ARC", 9},
+ { "keep_interrupts_masked", "gcc/MIPS-Function-Attributes.html#index-keep_005finterrupts_005fmasked-function-attribute_002c-MIPS", "MIPS", 22},
+ { "kspisusp", "gcc/Blackfin-Function-Attributes.html#index-kspisusp-function-attribute_002c-Blackfin", "Blackfin", 8},
+ { "l1_text", "gcc/Blackfin-Function-Attributes.html#index-l1_005ftext-function-attribute_002c-Blackfin", "Blackfin", 7},
+ { "l2", "gcc/Blackfin-Function-Attributes.html#index-l2-function-attribute_002c-Blackfin", "Blackfin", 2},
+ { "leaf", "gcc/Common-Function-Attributes.html#index-leaf-function-attribute", "", 4},
+ { "long_call", "gcc/ARC-Function-Attributes.html#index-long_005fcall-function-attribute_002c-ARC", "ARC", 9},
+ { "long_call", "gcc/ARM-Function-Attributes.html#index-long_005fcall-function-attribute_002c-ARM", "ARM", 9},
+ { "long_call", "gcc/Epiphany-Function-Attributes.html#index-long_005fcall-function-attribute_002c-Epiphany", "Epiphany", 9},
+ { "long_call", "gcc/MIPS-Function-Attributes.html#index-long_005fcall-function-attribute_002c-MIPS", "MIPS", 9},
+ { "longcall", "gcc/Blackfin-Function-Attributes.html#index-longcall-function-attribute_002c-Blackfin", "Blackfin", 8},
+ { "longcall", "gcc/PowerPC-Function-Attributes.html#index-longcall-function-attribute_002c-PowerPC", "PowerPC", 8},
+ { "lower", "gcc/MSP430-Function-Attributes.html#index-lower-function-attribute_002c-MSP430", "MSP430", 5},
+ { "malloc", "gcc/Common-Function-Attributes.html#index-malloc-function-attribute", "", 6},
+ { "medium_call", "gcc/ARC-Function-Attributes.html#index-medium_005fcall-function-attribute_002c-ARC", "ARC", 11},
+ { "micromips", "gcc/MIPS-Function-Attributes.html#index-micromips-function-attribute", "", 9},
+ { "mips16", "gcc/MIPS-Function-Attributes.html#index-mips16-function-attribute_002c-MIPS", "MIPS", 6},
+ { "model", "gcc/M32R_002fD-Function-Attributes.html#index-model-function-attribute_002c-M32R_002fD", "M32R/D", 5},
+ { "ms_abi", "gcc/x86-Function-Attributes.html#index-ms_005fabi-function-attribute_002c-x86", "x86", 6},
+ { "ms_hook_prologue", "gcc/x86-Function-Attributes.html#index-ms_005fhook_005fprologue-function-attribute_002c-x86", "x86", 16},
+ { "naked", "gcc/ARC-Function-Attributes.html#index-naked-function-attribute_002c-ARC", "ARC", 5},
+ { "naked", "gcc/ARM-Function-Attributes.html#index-naked-function-attribute_002c-ARM", "ARM", 5},
+ { "naked", "gcc/AVR-Function-Attributes.html#index-naked-function-attribute_002c-AVR", "AVR", 5},
+ { "naked", "gcc/BPF-Function-Attributes.html#index-naked-function-attribute_002c-BPF", "BPF", 5},
+ { "naked", "gcc/C-SKY-Function-Attributes.html#index-naked-function-attribute_002c-C-SKY", "C-SKY", 5},
+ { "naked", "gcc/MCORE-Function-Attributes.html#index-naked-function-attribute_002c-MCORE", "MCORE", 5},
+ { "naked", "gcc/MSP430-Function-Attributes.html#index-naked-function-attribute_002c-MSP430", "MSP430", 5},
+ { "naked", "gcc/NDS32-Function-Attributes.html#index-naked-function-attribute_002c-NDS32", "NDS32", 5},
+ { "naked", "gcc/RISC-V-Function-Attributes.html#index-naked-function-attribute_002c-RISC-V", "RISC-V", 5},
+ { "naked", "gcc/RL78-Function-Attributes.html#index-naked-function-attribute_002c-RL78", "RL78", 5},
+ { "naked", "gcc/RX-Function-Attributes.html#index-naked-function-attribute_002c-RX", "RX", 5},
+ { "naked", "gcc/x86-Function-Attributes.html#index-naked-function-attribute_002c-x86", "x86", 5},
+ { "near", "gcc/MIPS-Function-Attributes.html#index-near-function-attribute_002c-MIPS", "MIPS", 4},
+ { "nested", "gcc/NDS32-Function-Attributes.html#index-nested-function-attribute_002c-NDS32", "NDS32", 6},
+ { "nested_ready", "gcc/NDS32-Function-Attributes.html#index-nested_005fready-function-attribute_002c-NDS32", "NDS32", 12},
+ { "nesting", "gcc/Blackfin-Function-Attributes.html#index-nesting-function-attribute_002c-Blackfin", "Blackfin", 7},
+ { "nmi", "gcc/NDS32-Function-Attributes.html#index-nmi-function-attribute_002c-NDS32", "NDS32", 3},
+ { "nmi_handler", "gcc/Blackfin-Function-Attributes.html#index-nmi_005fhandler-function-attribute_002c-Blackfin", "Blackfin", 11},
+ { "no_callee_saved_registers", "gcc/x86-Function-Attributes.html#index-no_005fcallee_005fsaved_005fregisters-function-attribute_002c-x86", "x86", 25},
+ { "no_caller_saved_registers", "gcc/x86-Function-Attributes.html#index-no_005fcaller_005fsaved_005fregisters-function-attribute_002c-x86", "x86", 25},
+ { "no_dangling", "gcc/C_002b_002b-Attributes.html#index-no_005fdangling-function-attribute", "", 11},
+ { "no_gccisr", "gcc/AVR-Function-Attributes.html#index-no_005fgccisr-function-attribute_002c-AVR", "AVR", 9},
+ { "no_icf", "gcc/Common-Function-Attributes.html#index-no_005ficf-function-attribute", "", 6},
+ { "no_instrument_function", "gcc/Common-Function-Attributes.html#index-no_005finstrument_005ffunction-function-attribute", "", 22},
+ { "no_profile_instrument_function", "gcc/Common-Function-Attributes.html#index-no_005fprofile_005finstrument_005ffunction-function-attribute", "", 30},
+ { "no_reorder", "gcc/Common-Function-Attributes.html#index-no_005freorder-function-attribute", "", 10},
+ { "no_sanitize", "gcc/Common-Function-Attributes.html#index-no_005fsanitize-function-attribute", "", 11},
+ { "no_sanitize_address", "gcc/Common-Function-Attributes.html#index-no_005fsanitize_005faddress-function-attribute", "", 19},
+ { "no_sanitize_coverage", "gcc/Common-Function-Attributes.html#index-no_005fsanitize_005fcoverage-function-attribute", "", 20},
+ { "no_sanitize_thread", "gcc/Common-Function-Attributes.html#index-no_005fsanitize_005fthread-function-attribute", "", 18},
+ { "no_sanitize_undefined", "gcc/Common-Function-Attributes.html#index-no_005fsanitize_005fundefined-function-attribute", "", 21},
+ { "no_split_stack", "gcc/Common-Function-Attributes.html#index-no_005fsplit_005fstack-function-attribute", "", 14},
+ { "no_stack_limit", "gcc/Common-Function-Attributes.html#index-no_005fstack_005flimit-function-attribute", "", 14},
+ { "no_stack_protector", "gcc/Common-Function-Attributes.html#index-no_005fstack_005fprotector-function-attribute", "", 18},
+ { "nocf_check", "gcc/x86-Function-Attributes.html#index-nocf_005fcheck-function-attribute", "", 10},
+ { "noclone", "gcc/Common-Function-Attributes.html#index-noclone-function-attribute", "", 7},
+ { "nocompression", "gcc/MIPS-Function-Attributes.html#index-nocompression-function-attribute_002c-MIPS", "MIPS", 13},
+ { "nodirect_extern_access", "gcc/x86-Function-Attributes.html#index-nodirect_005fextern_005faccess-function-attribute", "", 22},
+ { "noinline", "gcc/Common-Function-Attributes.html#index-noinline-function-attribute", "", 8},
+ { "noipa", "gcc/Common-Function-Attributes.html#index-noipa-function-attribute", "", 5},
+ { "nomicromips", "gcc/MIPS-Function-Attributes.html#index-nomicromips-function-attribute", "", 11},
+ { "nomips16", "gcc/MIPS-Function-Attributes.html#index-nomips16-function-attribute_002c-MIPS", "MIPS", 8},
+ { "nonnull", "gcc/Common-Function-Attributes.html#index-nonnull-function-attribute", "", 7},
+ { "noplt", "gcc/Common-Function-Attributes.html#index-noplt-function-attribute", "", 5},
+ { "noreturn", "gcc/Common-Function-Attributes.html#index-noreturn-function-attribute", "", 8},
+ { "nosave_low_regs", "gcc/SH-Function-Attributes.html#index-nosave_005flow_005fregs-function-attribute_002c-SH", "SH", 15},
+ { "not_nested", "gcc/NDS32-Function-Attributes.html#index-not_005fnested-function-attribute_002c-NDS32", "NDS32", 10},
+ { "nothrow", "gcc/Common-Function-Attributes.html#index-nothrow-function-attribute", "", 7},
+ { "null_terminated_string_arg", "gcc/Common-Function-Attributes.html#index-null_005fterminated_005fstring_005farg-function-attribute", "", 26},
+ { "omit-leaf-frame-pointer", "gcc/AArch64-Function-Attributes.html#index-omit-leaf-frame-pointer-function-attribute_002c-AArch64", "AArch64", 23},
+ { "optimize", "gcc/Common-Function-Attributes.html#index-optimize-function-attribute", "", 8},
+ { "outline-atomics", "gcc/AArch64-Function-Attributes.html#index-outline-atomics-function-attribute_002c-AArch64", "AArch64", 15},
+ { "partial_save", "gcc/NDS32-Function-Attributes.html#index-partial_005fsave-function-attribute_002c-NDS32", "NDS32", 12},
+ { "patchable_function_entry", "gcc/Common-Function-Attributes.html#index-patchable_005ffunction_005fentry-function-attribute", "", 24},
+ { "pcs", "gcc/ARM-Function-Attributes.html#index-pcs-function-attribute_002c-ARM", "ARM", 3},
+ { "prefer-vector-width", "gcc/x86-Function-Attributes.html#index-prefer-vector-width-function-attribute_002c-x86", "x86", 19},
+ { "pure", "gcc/Common-Function-Attributes.html#index-pure-function-attribute", "", 4},
+ { "reentrant", "gcc/MSP430-Function-Attributes.html#index-reentrant-function-attribute_002c-MSP430", "MSP430", 9},
+ { "regparm", "gcc/x86-Function-Attributes.html#index-regparm-function-attribute_002c-x86", "x86", 7},
+ { "renesas", "gcc/SH-Function-Attributes.html#index-renesas-function-attribute_002c-SH", "SH", 7},
+ { "resbank", "gcc/SH-Function-Attributes.html#index-resbank-function-attribute_002c-SH", "SH", 7},
+ { "reset", "gcc/NDS32-Function-Attributes.html#index-reset-function-attribute_002c-NDS32", "NDS32", 5},
+ { "retain", "gcc/Common-Function-Attributes.html#index-retain-function-attribute", "", 6},
+ { "returns_nonnull", "gcc/Common-Function-Attributes.html#index-returns_005fnonnull-function-attribute", "", 15},
+ { "returns_twice", "gcc/Common-Function-Attributes.html#index-returns_005ftwice-function-attribute", "", 13},
+ { "riscv_vector_cc", "gcc/RISC-V-Function-Attributes.html#index-riscv_005fvector_005fcc-function-attribute_002c-RISC-V", "RISC-V", 15},
+ { "save_all", "gcc/NDS32-Function-Attributes.html#index-save_005fall-function-attribute_002c-NDS32", "NDS32", 8},
+ { "save_volatiles", "gcc/MicroBlaze-Function-Attributes.html#index-save_005fvolatiles-function-attribute_002c-MicroBlaze", "MicroBlaze", 14},
+ { "saveall", "gcc/Blackfin-Function-Attributes.html#index-saveall-function-attribute_002c-Blackfin", "Blackfin", 7},
+ { "saveall", "gcc/H8_002f300-Function-Attributes.html#index-saveall-function-attribute_002c-H8_002f300", "H8/300", 7},
+ { "section", "gcc/Common-Function-Attributes.html#index-section-function-attribute", "", 7},
+ { "secure_call", "gcc/ARC-Function-Attributes.html#index-secure_005fcall-function-attribute_002c-ARC", "ARC", 11},
+ { "sentinel", "gcc/Common-Function-Attributes.html#index-sentinel-function-attribute", "", 8},
+ { "short_call", "gcc/ARC-Function-Attributes.html#index-short_005fcall-function-attribute_002c-ARC", "ARC", 10},
+ { "short_call", "gcc/ARM-Function-Attributes.html#index-short_005fcall-function-attribute_002c-ARM", "ARM", 10},
+ { "short_call", "gcc/Epiphany-Function-Attributes.html#index-short_005fcall-function-attribute_002c-Epiphany", "Epiphany", 10},
+ { "short_call", "gcc/MIPS-Function-Attributes.html#index-short_005fcall-function-attribute_002c-MIPS", "MIPS", 10},
+ { "shortcall", "gcc/Blackfin-Function-Attributes.html#index-shortcall-function-attribute_002c-Blackfin", "Blackfin", 9},
+ { "shortcall", "gcc/PowerPC-Function-Attributes.html#index-shortcall-function-attribute_002c-PowerPC", "PowerPC", 9},
+ { "sign-return-address", "gcc/AArch64-Function-Attributes.html#index-sign-return-address-function-attribute_002c-AArch64", "AArch64", 19},
+ { "signal", "gcc/AVR-Function-Attributes.html#index-signal-function-attribute_002c-AVR", "AVR", 6},
+ { "simd", "gcc/Common-Function-Attributes.html#index-simd-function-attribute", "", 4},
+ { "sp_switch", "gcc/SH-Function-Attributes.html#index-sp_005fswitch-function-attribute_002c-SH", "SH", 9},
+ { "sseregparm", "gcc/x86-Function-Attributes.html#index-sseregparm-function-attribute_002c-x86", "x86", 10},
+ { "stack_protect", "gcc/Common-Function-Attributes.html#index-stack_005fprotect-function-attribute", "", 13},
+ { "stdcall", "gcc/x86-Function-Attributes.html#index-stdcall-function-attribute_002c-x86-32", "x86-32", 7},
+ { "strict-align", "gcc/AArch64-Function-Attributes.html#index-strict-align-function-attribute_002c-AArch64", "AArch64", 12},
+ { "symver", "gcc/Common-Function-Attributes.html#index-symver-function-attribute", "", 6},
+ { "syscall_linkage", "gcc/IA-64-Function-Attributes.html#index-syscall_005flinkage-function-attribute_002c-IA-64", "IA-64", 15},
+ { "sysv_abi", "gcc/x86-Function-Attributes.html#index-sysv_005fabi-function-attribute_002c-x86", "x86", 8},
+ { "tainted_args", "gcc/Common-Function-Attributes.html#index-tainted_005fargs-function-attribute", "", 12},
+ { "target", "gcc/ARM-Function-Attributes.html#index-target-function-attribute-1", "", 6},
+ { "target", "gcc/Common-Function-Attributes.html#index-target-function-attribute", "", 6},
+ { "target", "gcc/Nios-II-Function-Attributes.html#index-target-function-attribute-2", "", 6},
+ { "target", "gcc/PowerPC-Function-Attributes.html#index-target-function-attribute-3", "", 6},
+ { "target", "gcc/S_002f390-Function-Attributes.html#index-target-function-attribute-4", "", 6},
+ { "target", "gcc/x86-Function-Attributes.html#index-target-function-attribute-5", "", 6},
+ { "target_clones", "gcc/Common-Function-Attributes.html#index-target_005fclones-function-attribute", "", 13},
+ { "thiscall", "gcc/x86-Function-Attributes.html#index-thiscall-function-attribute_002c-x86-32", "x86-32", 8},
+ { "tls-dialect=", "gcc/AArch64-Function-Attributes.html#index-tls-dialect_003d-function-attribute_002c-AArch64", "AArch64", 12},
+ { "trap_exit", "gcc/SH-Function-Attributes.html#index-trap_005fexit-function-attribute_002c-SH", "SH", 9},
+ { "trapa_handler", "gcc/SH-Function-Attributes.html#index-trapa_005fhandler-function-attribute_002c-SH", "SH", 13},
+ { "tune=", "gcc/AArch64-Function-Attributes.html#index-tune_003d-function-attribute_002c-AArch64", "AArch64", 5},
+ { "tune=", "gcc/RISC-V-Function-Attributes.html#index-tune_003d-function-attribute_002c-RISC-V", "RISC-V", 5},
+ { "unavailable", "gcc/Common-Function-Attributes.html#index-unavailable-function-attribute", "", 11},
+ { "unused", "gcc/Common-Function-Attributes.html#index-unused-function-attribute", "", 6},
+ { "upper", "gcc/MSP430-Function-Attributes.html#index-upper-function-attribute_002c-MSP430", "MSP430", 5},
+ { "use_debug_exception_return", "gcc/MIPS-Function-Attributes.html#index-use_005fdebug_005fexception_005freturn-function-attribute_002c-MIPS", "MIPS", 26},
+ { "use_hazard_barrier_return", "gcc/MIPS-Function-Attributes.html#index-use_005fhazard_005fbarrier_005freturn-function-attribute_002c-MIPS", "MIPS", 25},
+ { "use_shadow_register_set", "gcc/MIPS-Function-Attributes.html#index-use_005fshadow_005fregister_005fset-function-attribute_002c-MIPS", "MIPS", 23},
+ { "used", "gcc/Common-Function-Attributes.html#index-used-function-attribute", "", 4},
+ { "vector", "gcc/RX-Function-Attributes.html#index-vector-function-attribute_002c-RX", "RX", 6},
+ { "version_id", "gcc/IA-64-Function-Attributes.html#index-version_005fid-function-attribute_002c-IA-64", "IA-64", 10},
+ { "visibility", "gcc/Common-Function-Attributes.html#index-visibility-function-attribute", "", 10},
+ { "wakeup", "gcc/MSP430-Function-Attributes.html#index-wakeup-function-attribute_002c-MSP430", "MSP430", 6},
+ { "warm", "gcc/NDS32-Function-Attributes.html#index-warm-function-attribute_002c-NDS32", "NDS32", 4},
+ { "warn_unused_result", "gcc/Common-Function-Attributes.html#index-warn_005funused_005fresult-function-attribute", "", 18},
+ { "warning", "gcc/Common-Function-Attributes.html#index-warning-function-attribute", "", 7},
+ { "weak", "gcc/Common-Function-Attributes.html#index-weak-function-attribute", "", 4},
+ { "weakref", "gcc/Common-Function-Attributes.html#index-weakref-function-attribute", "", 7},
+ { "zero_call_used_regs", "gcc/Common-Function-Attributes.html#index-zero_005fcall_005fused_005fregs-function-attribute", "", 19},
+};
+
+const attr_url_entry label_attrs[] = {
+ { "cold", "gcc/Label-Attributes.html#index-cold-label-attribute", "", 4},
+ { "hot", "gcc/Label-Attributes.html#index-hot-label-attribute", "", 3},
+ { "unused", "gcc/Label-Attributes.html#index-unused-label-attribute", "", 6},
+};
+
+const attr_url_entry statement_attrs[] = {
+ { "assume", "gcc/Statement-Attributes.html#index-assume-statement-attribute", "", 6},
+ { "fallthrough", "gcc/Statement-Attributes.html#index-fallthrough-statement-attribute", "", 11},
+};
+
+const attr_url_entry type_attrs[] = {
+ { "abi_tag", "gcc/C_002b_002b-Attributes.html#index-abi_005ftag-type-attribute", "", 7},
+ { "aligned", "gcc/Common-Type-Attributes.html#index-aligned-type-attribute", "", 7},
+ { "alloc_size", "gcc/Common-Type-Attributes.html#index-alloc_005fsize-type-attribute", "", 10},
+ { "altivec", "gcc/PowerPC-Type-Attributes.html#index-altivec-type-attribute_002c-PowerPC", "PowerPC", 7},
+ { "cold", "gcc/C_002b_002b-Attributes.html#index-cold-type-attribute", "", 4},
+ { "copy", "gcc/Common-Type-Attributes.html#index-copy-type-attribute", "", 4},
+ { "deprecated", "gcc/Common-Type-Attributes.html#index-deprecated-type-attribute", "", 10},
+ { "designated_init", "gcc/Common-Type-Attributes.html#index-designated_005finit-type-attribute", "", 15},
+ { "gcc_struct", "gcc/PowerPC-Type-Attributes.html#index-gcc_005fstruct-type-attribute_002c-PowerPC", "PowerPC", 10},
+ { "gcc_struct", "gcc/x86-Type-Attributes.html#index-gcc_005fstruct-type-attribute_002c-x86", "x86", 10},
+ { "hardbool", "gcc/Common-Type-Attributes.html#index-hardbool-type-attribute", "", 8},
+ { "hot", "gcc/C_002b_002b-Attributes.html#index-hot-type-attribute", "", 3},
+ { "may_alias", "gcc/Common-Type-Attributes.html#index-may_005falias-type-attribute", "", 9},
+ { "mode", "gcc/Common-Type-Attributes.html#index-mode-type-attribute", "", 4},
+ { "ms_struct", "gcc/PowerPC-Type-Attributes.html#index-ms_005fstruct-type-attribute_002c-PowerPC", "PowerPC", 9},
+ { "ms_struct", "gcc/x86-Type-Attributes.html#index-ms_005fstruct-type-attribute_002c-x86", "x86", 9},
+ { "no_dangling", "gcc/C_002b_002b-Attributes.html#index-no_005fdangling-type-attribute", "", 11},
+ { "notshared", "gcc/ARM-Type-Attributes.html#index-notshared-type-attribute_002c-ARM", "ARM", 9},
+ { "objc_root_class", "gcc/Common-Type-Attributes.html#index-objc_005froot_005fclass-type-attribute", "", 15},
+ { "packed", "gcc/Common-Type-Attributes.html#index-packed-type-attribute", "", 6},
+ { "preserve_access_index", "gcc/BPF-Type-Attributes.html#index-preserve_005faccess_005findex-type-attribute_002c-BPF", "BPF", 21},
+ { "scalar_storage_order", "gcc/Common-Type-Attributes.html#index-scalar_005fstorage_005forder-type-attribute", "", 20},
+ { "strub", "gcc/Common-Type-Attributes.html#index-strub-type-attribute", "", 5},
+ { "transparent_union", "gcc/Common-Type-Attributes.html#index-transparent_005funion-type-attribute", "", 17},
+ { "unavailable", "gcc/Common-Type-Attributes.html#index-unavailable-type-attribute", "", 11},
+ { "uncached", "gcc/ARC-Type-Attributes.html#index-uncached-type-attribute_002c-ARC", "ARC", 8},
+ { "unused", "gcc/Common-Type-Attributes.html#index-unused-type-attribute", "", 6},
+ { "vector_size", "gcc/Common-Type-Attributes.html#index-vector_005fsize-type-attribute", "", 11},
+ { "visibility", "gcc/Common-Type-Attributes.html#index-visibility-type-attribute", "", 10},
+ { "warn_if_not_aligned", "gcc/Common-Type-Attributes.html#index-warn_005fif_005fnot_005faligned-type-attribute", "", 19},
+ { "warn_unused", "gcc/C_002b_002b-Attributes.html#index-warn_005funused-type-attribute", "", 11},
+};
+
+const attr_url_entry variable_attrs[] = {
+ { "abi_tag", "gcc/C_002b_002b-Attributes.html#index-abi_005ftag-variable-attribute", "", 7},
+ { "absdata", "gcc/AVR-Variable-Attributes.html#index-absdata-variable-attribute_002c-AVR", "AVR", 7},
+ { "address", "gcc/AVR-Variable-Attributes.html#index-address-variable-attribute_002c-AVR", "AVR", 7},
+ { "alias", "gcc/Common-Variable-Attributes.html#index-alias-variable-attribute", "", 5},
+ { "aligned", "gcc/Common-Variable-Attributes.html#index-aligned-variable-attribute", "", 7},
+ { "alloc_size", "gcc/Common-Variable-Attributes.html#index-alloc_005fsize-variable-attribute", "", 10},
+ { "altivec", "gcc/PowerPC-Variable-Attributes.html#index-altivec-variable-attribute_002c-PowerPC", "PowerPC", 7},
+ { "aux", "gcc/ARC-Variable-Attributes.html#index-aux-variable-attribute_002c-ARC", "ARC", 3},
+ { "below100", "gcc/Xstormy16-Variable-Attributes.html#index-below100-variable-attribute_002c-Xstormy16", "Xstormy16", 8},
+ { "cleanup", "gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute", "", 7},
+ { "common", "gcc/Common-Variable-Attributes.html#index-common-variable-attribute", "", 6},
+ { "copy", "gcc/Common-Variable-Attributes.html#index-copy-variable-attribute", "", 4},
+ { "counted_by", "gcc/Common-Variable-Attributes.html#index-counted_005fby-variable-attribute", "", 10},
+ { "deprecated", "gcc/Common-Variable-Attributes.html#index-deprecated-variable-attribute", "", 10},
+ { "dllexport", "gcc/Microsoft-Windows-Variable-Attributes.html#index-dllexport-variable-attribute", "", 9},
+ { "dllimport", "gcc/Microsoft-Windows-Variable-Attributes.html#index-dllimport-variable-attribute", "", 9},
+ { "eightbit_data", "gcc/H8_002f300-Variable-Attributes.html#index-eightbit_005fdata-variable-attribute_002c-H8_002f300", "H8/300", 13},
+ { "either", "gcc/MSP430-Variable-Attributes.html#index-either-variable-attribute_002c-MSP430", "MSP430", 6},
+ { "gcc_struct", "gcc/PowerPC-Variable-Attributes.html#index-gcc_005fstruct-variable-attribute_002c-PowerPC", "PowerPC", 10},
+ { "gcc_struct", "gcc/x86-Variable-Attributes.html#index-gcc_005fstruct-variable-attribute_002c-x86", "x86", 10},
+ { "init_priority", "gcc/C_002b_002b-Attributes.html#index-init_005fpriority-variable-attribute", "", 13},
+ { "io", "gcc/AVR-Variable-Attributes.html#index-io-variable-attribute_002c-AVR", "AVR", 2},
+ { "io_low", "gcc/AVR-Variable-Attributes.html#index-io_005flow-variable-attribute_002c-AVR", "AVR", 6},
+ { "l1_data", "gcc/Blackfin-Variable-Attributes.html#index-l1_005fdata-variable-attribute_002c-Blackfin", "Blackfin", 7},
+ { "l1_data_A", "gcc/Blackfin-Variable-Attributes.html#index-l1_005fdata_005fA-variable-attribute_002c-Blackfin", "Blackfin", 9},
+ { "l1_data_B", "gcc/Blackfin-Variable-Attributes.html#index-l1_005fdata_005fB-variable-attribute_002c-Blackfin", "Blackfin", 9},
+ { "l2", "gcc/Blackfin-Variable-Attributes.html#index-l2-variable-attribute_002c-Blackfin", "Blackfin", 2},
+ { "lower", "gcc/MSP430-Variable-Attributes.html#index-lower-variable-attribute_002c-MSP430", "MSP430", 5},
+ { "mode", "gcc/Common-Variable-Attributes.html#index-mode-variable-attribute", "", 4},
+ { "model", "gcc/IA-64-Variable-Attributes.html#index-model-variable-attribute_002c-IA-64", "IA-64", 5},
+ { "model", "gcc/LoongArch-Variable-Attributes.html#index-model-variable-attribute_002c-LoongArch", "LoongArch", 5},
+ { "model-name", "gcc/M32R_002fD-Variable-Attributes.html#index-model-name-variable-attribute_002c-M32R_002fD", "M32R/D", 10},
+ { "ms_struct", "gcc/PowerPC-Variable-Attributes.html#index-ms_005fstruct-variable-attribute_002c-PowerPC", "PowerPC", 9},
+ { "ms_struct", "gcc/x86-Variable-Attributes.html#index-ms_005fstruct-variable-attribute_002c-x86", "x86", 9},
+ { "no_icf", "gcc/Common-Variable-Attributes.html#index-no_005ficf-variable-attribute", "", 6},
+ { "nocommon", "gcc/Common-Variable-Attributes.html#index-nocommon-variable-attribute", "", 8},
+ { "noinit", "gcc/Common-Variable-Attributes.html#index-noinit-variable-attribute", "", 6},
+ { "nonstring", "gcc/Common-Variable-Attributes.html#index-nonstring-variable-attribute", "", 9},
+ { "objc_nullability", "gcc/Common-Variable-Attributes.html#index-objc_005fnullability-variable-attribute", "", 16},
+ { "packed", "gcc/Common-Variable-Attributes.html#index-packed-variable-attribute", "", 6},
+ { "persistent", "gcc/Common-Variable-Attributes.html#index-persistent-variable-attribute", "", 10},
+ { "progmem", "gcc/AVR-Variable-Attributes.html#index-progmem-variable-attribute_002c-AVR", "AVR", 7},
+ { "retain", "gcc/Common-Variable-Attributes.html#index-retain-variable-attribute", "", 6},
+ { "saddr", "gcc/RL78-Variable-Attributes.html#index-saddr-variable-attribute_002c-RL78", "RL78", 5},
+ { "sda", "gcc/V850-Variable-Attributes.html#index-sda-variable-attribute_002c-V850", "V850", 3},
+ { "section", "gcc/Common-Variable-Attributes.html#index-section-variable-attribute", "", 7},
+ { "selectany", "gcc/Microsoft-Windows-Variable-Attributes.html#index-selectany-variable-attribute", "", 9},
+ { "shared", "gcc/Microsoft-Windows-Variable-Attributes.html#index-shared-variable-attribute", "", 6},
+ { "strict_flex_array", "gcc/Common-Variable-Attributes.html#index-strict_005fflex_005farray-variable-attribute", "", 17},
+ { "tda", "gcc/V850-Variable-Attributes.html#index-tda-variable-attribute_002c-V850", "V850", 3},
+ { "tiny_data", "gcc/H8_002f300-Variable-Attributes.html#index-tiny_005fdata-variable-attribute_002c-H8_002f300", "H8/300", 9},
+ { "tls_model", "gcc/Common-Variable-Attributes.html#index-tls_005fmodel-variable-attribute", "", 9},
+ { "unavailable", "gcc/Common-Variable-Attributes.html#index-unavailable-variable-attribute", "", 11},
+ { "uninitialized", "gcc/Common-Variable-Attributes.html#index-uninitialized-variable-attribute", "", 13},
+ { "unused", "gcc/Common-Variable-Attributes.html#index-unused-variable-attribute", "", 6},
+ { "upper", "gcc/MSP430-Variable-Attributes.html#index-upper-variable-attribute_002c-MSP430", "MSP430", 5},
+ { "used", "gcc/Common-Variable-Attributes.html#index-used-variable-attribute", "", 4},
+ { "vector_size", "gcc/Common-Variable-Attributes.html#index-vector_005fsize-variable-attribute", "", 11},
+ { "visibility", "gcc/Common-Variable-Attributes.html#index-visibility-variable-attribute", "", 10},
+ { "warn_if_not_aligned", "gcc/Common-Variable-Attributes.html#index-warn_005fif_005fnot_005faligned-variable-attribute", "", 19},
+ { "weak", "gcc/Common-Variable-Attributes.html#index-weak-variable-attribute", "", 4},
+ { "zda", "gcc/V850-Variable-Attributes.html#index-zda-variable-attribute_002c-V850", "V850", 3},
+};
+
+static const struct attr_url_table {
+  const attr_url_entry *m_table;
+  const size_t m_table_sz;
+} attr_url_tables[] = {
+  { enumerator_attrs, ARRAY_SIZE (enumerator_attrs) },
+  { function_attrs, ARRAY_SIZE (function_attrs) },
+  { label_attrs, ARRAY_SIZE (label_attrs) },
+  { statement_attrs, ARRAY_SIZE (statement_attrs) },
+  { type_attrs, ARRAY_SIZE (type_attrs) },
+  { variable_attrs, ARRAY_SIZE (variable_attrs) },
+};
diff --git a/gcc/attribs.cc b/gcc/attribs.cc
index 3ab0b0fd87a4..5ef6884f4163 100644
--- a/gcc/attribs.cc
+++ b/gcc/attribs.cc
@@ -37,6 +37,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "pretty-print.h"
 #include "tree-pretty-print.h"
 #include "intl.h"
+#include "gcc-urlifier.h"
 
 /* Table of the tables of attributes (common, language, format, machine)
    searched.  */
@@ -630,6 +631,8 @@  decl_attributes (tree *node, tree attributes, int flags,
   if (!attributes_initialized)
     init_attributes ();
 
+  auto_urlify_attributes sentinel;
+
   /* If this is a function and the user used #pragma GCC optimize, add the
      options to the attribute((optimize(...))) list.  */
   if (TREE_CODE (*node) == FUNCTION_DECL && current_optimize_pragma)
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index f9b229aba7fc..390eebfbd05f 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -48,6 +48,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "gimplify.h"
 #include "tree-pretty-print.h"
 #include "gcc-rich-location.h"
+#include "gcc-urlifier.h"
 
 static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
 static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
@@ -686,6 +687,8 @@  positional_argument (const_tree fn, const_tree atname, tree &pos,
 		     tree_code code, int argno /* = 0 */,
 		     int flags /* = posargflags () */)
 {
+  auto_urlify_attributes sentinel;
+
   const_tree fndecl = TYPE_P (fn) ? NULL_TREE : fn;
   const_tree fntype = TYPE_P (fn) ? fn : TREE_TYPE (fn);
   if (pos && TREE_CODE (pos) != IDENTIFIER_NODE
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 7d752acd430c..959982cf0194 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -53,6 +53,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "debug.h"
 #include "tree-vector-builder.h"
 #include "vec-perm-indices.h"
+#include "gcc-urlifier.h"
 
 cpp_reader *parse_in;		/* Declared in c-pragma.h.  */
 
@@ -6022,8 +6023,11 @@  parse_optimize_options (tree args, bool attr_p)
 		{
 		  ret = false;
 		  if (attr_p)
-		    warning (OPT_Wattributes,
-			     "bad option %qs to attribute %<optimize%>", p);
+		    {
+		      auto_urlify_attributes sentinel;
+		      warning (OPT_Wattributes,
+			       "bad option %qs to attribute %<optimize%>", p);
+		    }
 		  else
 		    warning (OPT_Wpragmas,
 			     "bad option %qs to pragma %<optimize%>", p);
@@ -6072,9 +6076,12 @@  parse_optimize_options (tree args, bool attr_p)
 	{
 	  ret = false;
 	  if (attr_p)
-	    warning (OPT_Wattributes,
-		     "bad option %qs to attribute %<optimize%>",
-		     decoded_options[i].orig_option_with_args_text);
+	    {
+	      auto_urlify_attributes sentinel;
+	      warning (OPT_Wattributes,
+		       "bad option %qs to attribute %<optimize%>",
+		       decoded_options[i].orig_option_with_args_text);
+	    }
 	  else
 	    warning (OPT_Wpragmas,
 		     "bad option %qs to pragma %<optimize%>",
@@ -6122,6 +6129,7 @@  attribute_fallthrough_p (tree attr)
   tree t = lookup_attribute ("", "fallthrough", attr);
   if (t == NULL_TREE)
     return false;
+  auto_urlify_attributes sentinel;
   /* It is no longer true that "this attribute shall appear at most once in
      each attribute-list", but we still give a warning.  */
   if (lookup_attribute ("", "fallthrough", TREE_CHAIN (t)))
diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index 5e4fb7f0f0a9..c40388bfb086 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -40,6 +40,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 #include "tree-pretty-print.h"
 #include "langhooks.h"
+#include "gcc-urlifier.h"
 
 /* Print a warning if a constant expression had overflow in folding.
    Invoke this function on every expression that the language
@@ -2668,6 +2669,7 @@  warn_duplicated_cond_add_or_warn (location_t loc, tree cond, vec<tree> **chain)
 bool
 diagnose_mismatched_attributes (tree olddecl, tree newdecl)
 {
+  auto_urlify_attributes sentinel;
   bool warned = false;
 
   tree a1 = lookup_attribute ("optimize", DECL_ATTRIBUTES (olddecl));
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 01326570e2b2..25c23786fca7 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -62,6 +62,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "omp-general.h"
 #include "omp-offload.h"  /* For offload_vars.  */
 #include "c-parser.h"
+#include "gcc-urlifier.h"
 
 #include "tree-pretty-print.h"
 
@@ -5683,8 +5684,11 @@  start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
-    warning (OPT_Wattributes, "inline function %q+D given attribute %qs",
-	     decl, "noinline");
+    {
+      auto_urlify_attributes sentinel;
+      warning (OPT_Wattributes, "inline function %q+D given attribute %qs",
+	       decl, "noinline");
+    }
 
   /* C99 6.7.4p3: An inline definition of a function with external
      linkage shall not contain a definition of a modifiable object
@@ -10587,9 +10591,12 @@  start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
   if (DECL_DECLARED_INLINE_P (decl1)
       && DECL_UNINLINABLE (decl1)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
-    warning_at (loc, OPT_Wattributes,
-		"inline function %qD given attribute %qs",
-		decl1, "noinline");
+    {
+      auto_urlify_attributes sentinel;
+      warning_at (loc, OPT_Wattributes,
+		  "inline function %qD given attribute %qs",
+		  decl1, "noinline");
+    }
 
   /* Handle gnu_inline attribute.  */
   if (declspecs->inline_p
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index e83e9c683f75..8ed5cbe16bcf 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -74,6 +74,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "bitmap.h"
 #include "analyzer/analyzer-language.h"
 #include "toplev.h"
+#include "gcc-urlifier.h"
 
 /* We need to walk over decls with incomplete struct/union/enum types
    after parsing the whole translation unit.
@@ -7750,6 +7751,7 @@  c_parser_statement_after_labels (c_parser *parser, bool *if_p,
 		  attrs = handle_assume_attribute (loc, attrs, true);
 		else
 		  {
+		    auto_urlify_attributes sentinel;
 		    warning_at (loc, OPT_Wattributes,
 				"%<assume%> attribute not followed by %<;%>");
 		    has_assume = false;
@@ -7767,17 +7769,23 @@  c_parser_statement_after_labels (c_parser *parser, bool *if_p,
 		    c_parser_consume_token (parser);
 		  }
 		else
-		  warning_at (loc, OPT_Wattributes,
-			      "%<fallthrough%> attribute not followed "
-			      "by %<;%>");
+		  {
+		    auto_urlify_attributes sentinel;
+		    warning_at (loc, OPT_Wattributes,
+				"%<fallthrough%> attribute not followed "
+				"by %<;%>");
+		  }
 	      }
 	    else if (has_assume)
 	      /* Eat the ';'.  */
 	      c_parser_consume_token (parser);
 	    else if (attrs != NULL_TREE)
-	      warning_at (loc, OPT_Wattributes,
-			  "only attribute %<fallthrough%> or %<assume%> can "
-			  "be applied to a null statement");
+	      {
+		auto_urlify_attributes sentinel;
+		warning_at (loc, OPT_Wattributes,
+			    "only attribute %<fallthrough%> or %<assume%> can "
+			    "be applied to a null statement");
+	      }
 	    break;
 	  }
 	default:
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index ffcab7df4d3b..f1089308dba4 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -53,6 +53,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "attribs.h"
 #include "asan.h"
 #include "realmpfr.h"
+#include "gcc-urlifier.h"
 
 /* Possible cases of implicit conversions.  Used to select diagnostic messages
    and control folding initializers in convert_for_assignment.  */
@@ -6092,6 +6093,7 @@  maybe_warn_nodiscard (location_t loc, tree expr)
       if (args)
 	args = TREE_VALUE (args);
       auto_diagnostic_group d;
+      auto_urlify_attributes sentinel;
       int warned;
       if (args)
 	warned = warning_at (loc, OPT_Wunused_result,
@@ -6114,6 +6116,7 @@  maybe_warn_nodiscard (location_t loc, tree expr)
       if (args)
 	args = TREE_VALUE (args);
       auto_diagnostic_group d;
+      auto_urlify_attributes sentinel;
       int warned;
       if (args)
 	warned = warning_at (loc, OPT_Wunused_result,
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index e6629dea5fdc..4aadb1bebcf2 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -42,6 +42,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "omp-general.h"
 #include "opts.h"
+#include "gcc-urlifier.h"
 
 /* Keep track of forward references to immediate-escalating functions in
    case they become consteval.  This vector contains ADDR_EXPRs and
@@ -3628,8 +3629,11 @@  process_stmt_hotness_attribute (tree std_attrs, location_t attrs_loc)
       SET_EXPR_LOCATION (pred, attrs_loc);
       add_stmt (pred);
       if (tree other = lookup_hotness_attribute (TREE_CHAIN (attr)))
-	warning (OPT_Wattributes, "ignoring attribute %qE after earlier %qE",
-		 get_attribute_name (other), name);
+	{
+	  auto_urlify_attributes sentinel;
+	  warning (OPT_Wattributes, "ignoring attribute %qE after earlier %qE",
+		   get_attribute_name (other), name);
+	}
       std_attrs = remove_hotness_attribute (std_attrs);
     }
   return std_attrs;
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index db086c017e89..05db602066a3 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -36,6 +36,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "escaped_string.h"
+#include "gcc-urlifier.h"
 
 static tree convert_to_pointer_force (tree, tree, tsubst_flags_t);
 static tree build_type_conversion (tree, tree);
@@ -1091,6 +1092,7 @@  maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
 		"declared with attribute %<nodiscard%>%s"));
       const char *raw_msg = msg ? (const char *) msg : "";
       auto_diagnostic_group d;
+      auto_urlify_attributes sentinel;
       if (warning_at (loc, OPT_Wunused_result, format, fn, raw_msg))
 	inform (DECL_SOURCE_LOCATION (fn), "declared here");
     }
@@ -1109,6 +1111,7 @@  maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
 		"declared with attribute %<nodiscard%>%s"));
       const char *raw_msg = msg ? (const char *) msg : "";
       auto_diagnostic_group d;
+      auto_urlify_attributes sentinel;
       if (warning_at (loc, OPT_Wunused_result, format, rettype, raw_msg))
 	{
 	  if (fn)
@@ -1123,6 +1126,7 @@  maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
     {
       /* The TARGET_EXPR confuses do_warn_unused_result into thinking that the
 	 result is used, so handle that case here.  */
+      auto_urlify_attributes sentinel;
       if (fn)
 	{
 	  auto_diagnostic_group d;
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 03deb1493a43..f756d6df13ee 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -60,6 +60,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "omp-offload.h"  /* For offload_vars.  */
 #include "opts.h"
 #include "langhooks-def.h"  /* For lhd_simulate_record_decl  */
+#include "gcc-urlifier.h"
 
 /* Possible cases of bad specifiers type used by bad_specifiers. */
 enum bad_spec_place {
@@ -5991,8 +5992,11 @@  start_decl (const cp_declarator *declarator,
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
-    warning_at (DECL_SOURCE_LOCATION (decl), 0,
-		"inline function %qD given attribute %qs", decl, "noinline");
+    {
+      auto_urlify_attributes sentinel;
+      warning_at (DECL_SOURCE_LOCATION (decl), 0,
+		  "inline function %qD given attribute %qs", decl, "noinline");
+    }
 
   if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
     {
@@ -17840,8 +17844,11 @@  start_preparsed_function (tree decl1, tree attrs, int flags)
 
   if (DECL_DECLARED_INLINE_P (decl1)
       && lookup_attribute ("noinline", attrs))
-    warning_at (DECL_SOURCE_LOCATION (decl1), 0,
-		"inline function %qD given attribute %qs", decl1, "noinline");
+    {
+      auto_urlify_attributes sentinel;
+      warning_at (DECL_SOURCE_LOCATION (decl1), 0,
+		  "inline function %qD given attribute %qs", decl1, "noinline");
+    }
 
   /* Handle gnu_inline attribute.  */
   if (GNU_INLINE_P (decl1))
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 8fc22466b928..d3fd21d57f25 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -443,6 +443,14 @@  diagnostic_context::set_urlifier (urlifier *urlifier)
   m_urlifier = urlifier;
 }
 
+/* Set the urlifier without deleting the existing one.  */
+
+void
+diagnostic_context::override_urlifier (urlifier *urlifier)
+{
+  m_urlifier = urlifier;
+}
+
 void
 diagnostic_context::create_edit_context ()
 {
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 4969f07836cc..6306f0874404 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -454,6 +454,7 @@  public:
   void set_text_art_charset (enum diagnostic_text_art_charset charset);
   void set_client_data_hooks (diagnostic_client_data_hooks *hooks);
   void set_urlifier (urlifier *);
+  void override_urlifier (urlifier *);
   void create_edit_context ();
   void set_warning_as_error_requested (bool val)
   {
@@ -509,6 +510,8 @@  public:
   {
     return m_client_data_hooks;
   }
+  urlifier *get_urlifier () const { return m_urlifier; }
+
   text_art::theme *get_diagram_theme () const { return m_diagrams.m_theme; }
 
   int converted_column (expanded_location s) const;
diff --git a/gcc/gcc-urlifier.cc b/gcc/gcc-urlifier.cc
index be6459e8d7c1..2b1504c092cd 100644
--- a/gcc/gcc-urlifier.cc
+++ b/gcc/gcc-urlifier.cc
@@ -26,10 +26,20 @@  along with GCC; see the file COPYING3.  If not see
 #include "gcc-urlifier.h"
 #include "opts.h"
 #include "options.h"
+#include "diagnostic.h"
 #include "selftest.h"
 
 namespace {
 
+static char *
+make_doc_url (const char *doc_url_suffix)
+{
+  if (!doc_url_suffix)
+    return nullptr;
+
+  return concat (DOCUMENTATION_ROOT_URL, doc_url_suffix, nullptr);
+}
+
 /* Concrete subclass of urlifier for generating links into
    GCC's HTML documentation.  */
 
@@ -49,9 +59,6 @@  public:
 private:
   label_text get_url_suffix_for_option (const char *p, size_t sz) const;
 
-  static char *
-  make_doc_url (const char *doc_url_suffix);
-
   unsigned int m_lang_mask;
 };
 
@@ -202,15 +209,6 @@  gcc_urlifier::get_url_suffix_for_option (const char *p, size_t sz) const
   return get_option_url_suffix (opt, m_lang_mask);
 }
 
-char *
-gcc_urlifier::make_doc_url (const char *doc_url_suffix)
-{
-  if (!doc_url_suffix)
-    return nullptr;
-
-  return concat (DOCUMENTATION_ROOT_URL, doc_url_suffix, nullptr);
-}
-
 } // anonymous namespace
 
 urlifier *
@@ -219,16 +217,112 @@  make_gcc_urlifier (unsigned int lang_mask)
   return new gcc_urlifier (lang_mask);
 }
 
+/* class auto_override_urlifier.  */
+
+auto_override_urlifier::auto_override_urlifier (urlifier *new_urlifier)
+: m_old_urlifier (global_dc->get_urlifier ())
+{
+  global_dc->override_urlifier (new_urlifier);
+}
+
+auto_override_urlifier::~auto_override_urlifier ()
+{
+  global_dc->override_urlifier (m_old_urlifier);
+}
+
+/* class attribute_urlifier : public urlifier.  */
+
+struct attr_url_entry
+{
+  const char *m_name;
+  const char *m_url_suffix;
+  const char *m_extra;
+  size_t m_name_len;
+};
+
+#include "attr-urls.def"
+
+/* Search for STR, LEN in the given TABLE.  */
+
+static const attr_url_entry *
+find_attr_url_entry (const char *str,
+		     size_t str_len,
+		     const attr_url_entry *table,
+		     size_t table_sz)
+{
+  /* This is linear search, but TABLE_SZ ought not to be very large.  */
+  for (size_t i = 0; i < table_sz; i++)
+    if (str_len == table[i].m_name_len)
+      if (0 == strncmp (str, table[i].m_name, str_len))
+	return &table[i];
+
+  return nullptr;
+}
+
+/* Search for STR, LEN in all of the attribute tables, in order.  */
+
+static const attr_url_entry *
+find_attr_url_entry (const char *str,
+		     size_t str_len)
+{
+  for (size_t table_idx = 0; table_idx < ARRAY_SIZE (attr_url_tables);
+       table_idx++)
+    if (const attr_url_entry *entry
+	  = find_attr_url_entry (str, str_len,
+				 attr_url_tables[table_idx].m_table,
+				 attr_url_tables[table_idx].m_table_sz))
+      return entry;
+
+  return nullptr;
+}
+
+char *
+attribute_urlifier::get_url_for_quoted_text (const char *p,
+					     size_t sz) const
+{
+  label_text url_suffix = get_url_suffix_for_quoted_text (p, sz);
+  if (url_suffix.get ())
+    return make_doc_url (url_suffix.get ());
+  return nullptr;
+}
+
+label_text
+attribute_urlifier::get_url_suffix_for_quoted_text (const char *p,
+						    size_t sz) const
+{
+  /* Skip any text after a non-identifier character, so that
+     e.g. given "access(read_write, 2, 3)" we only compare
+     against "access".  */
+  for (size_t i = 0; i < sz; i++)
+    if (!ISIDNUM (p[i]))
+      {
+	/* Truncate to p[0..i).  */
+	sz = i;
+	break;
+      }
+
+  // TODO: how to handle target-specific variants?
+
+  if (const attr_url_entry *entry = find_attr_url_entry (p, sz))
+    return label_text::borrow (entry->m_url_suffix);
+
+  return label_text ();
+}
+
+label_text
+attribute_urlifier::get_url_suffix_for_quoted_text (const char *p) const
+{
+  return get_url_suffix_for_quoted_text (p, strlen (p));
+}
+
 #if CHECKING_P
 
 namespace selftest {
 
 /* Selftests.  */
 
-/* Run all of the selftests within this file.  */
-
-void
-gcc_urlifier_cc_tests ()
+static void
+test_gcc_urlifier ()
 {
   /* Check that doc_urls.quoted_text is sorted.  */
   for (size_t idx = 1; idx < ARRAY_SIZE (doc_urls); idx++)
@@ -262,6 +356,62 @@  gcc_urlifier_cc_tests ()
 		"gcc/Optimize-Options.html#index-finline");
 }
 
+static void
+test_attribute_urlifier ()
+{
+  attribute_urlifier u;
+
+  ASSERT_EQ (u.get_url_suffix_for_quoted_text ("").get (), nullptr);
+  ASSERT_EQ (u.get_url_suffix_for_quoted_text (")").get (), nullptr);
+
+  /* Examples of function attributes.  */
+  ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("alias").get (),
+		"gcc/Common-Function-Attributes.html"
+		"#index-alias-function-attribute");
+
+  ASSERT_STREQ (u.get_url_suffix_for_quoted_text
+		  ("access(read_write, 2, 3)").get (),
+		"gcc/Common-Function-Attributes.html"
+		"#index-access-function-attribute");
+
+  /* Example of enumerator attribute.  */
+  ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("deprecated").get (),
+		"gcc/Enumerator-Attributes.html"
+		"#index-deprecated-enumerator-attribute");
+
+  /* We don't yet have an example of a label attribute, since all
+     label attributes have a matching function attribute of the same
+     name, which is found first.  */
+
+  /* Example of statement attribute.  */
+  ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("assume").get (),
+		"gcc/Statement-Attributes.html"
+		"#index-assume-statement-attribute");
+
+  /* Examples of type attributes.  */
+  ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("hardbool").get (),
+		"gcc/Common-Type-Attributes.html"
+		"#index-hardbool-type-attribute");
+  ASSERT_STREQ (u.get_url_suffix_for_quoted_text
+		  ("packed").get (),
+		"gcc/Common-Type-Attributes.html"
+		"#index-packed-type-attribute");
+
+  /* Example of variable attribute.  */
+  ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("nonstring").get (),
+		"gcc/Common-Variable-Attributes.html"
+		"#index-nonstring-variable-attribute");
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+gcc_urlifier_cc_tests ()
+{
+  test_gcc_urlifier ();
+  test_attribute_urlifier ();
+}
+
 } // namespace selftest
 
 #endif /* #if CHECKING_P */
diff --git a/gcc/gcc-urlifier.h b/gcc/gcc-urlifier.h
index 660d4f8828e7..88cec6661a0c 100644
--- a/gcc/gcc-urlifier.h
+++ b/gcc/gcc-urlifier.h
@@ -21,6 +21,56 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_GCC_URLIFIER_H
 #define GCC_GCC_URLIFIER_H
 
+#include "pretty-print-urlifier.h"
+#include "label-text.h"
+
 extern urlifier *make_gcc_urlifier (unsigned int lang_mask);
 
+/* RAII class to temporarily override global_dc's urlifier
+   with another one (possibly nullptr).  */
+
+class auto_override_urlifier
+{
+public:
+  auto_override_urlifier (urlifier *new_urlifier);
+  ~auto_override_urlifier ();
+
+protected:
+  urlifier * const m_old_urlifier;
+};
+
+/* Subclass of urlifier that attempts to add URLs to quoted strings
+   containing names of attributes.  */
+
+class attribute_urlifier : public urlifier
+{
+public:
+  char *
+  get_url_for_quoted_text (const char *p, size_t sz) const final override;
+
+  label_text
+  get_url_suffix_for_quoted_text (const char *p, size_t sz) const;
+
+  /* We use ATTRIBUTE_UNUSED as this helper is called only from ASSERTs.  */
+  label_text
+  get_url_suffix_for_quoted_text (const char *p) const ATTRIBUTE_UNUSED;
+};
+
+/* RAII class: during the lifetime of instances, global_dc will attempt
+   to auto-generate documentation links for any attributes mentioned in
+   quotes in diagnostics .  */
+
+class auto_urlify_attributes
+{
+public:
+  auto_urlify_attributes ()
+  : m_override (&m_urlifier)
+  {
+  }
+
+private:
+  attribute_urlifier m_urlifier;
+  auto_override_urlifier m_override;
+};
+
 #endif /* GCC_GCC_URLIFIER_H */
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 61f9f0f3d310..3aede7207d18 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -55,6 +55,7 @@ 
 #include "demangle.h"
 #include "attr-fnspec.h"
 #include "pointer-query.h"
+#include "gcc-urlifier.h"
 
 /* Return true if tree node X has an associated location.  */
 
@@ -4750,6 +4751,8 @@  pass_waccess::check_call_dangling (gcall *call)
 unsigned
 pass_waccess::execute (function *fun)
 {
+  auto_urlify_attributes sentinel;
+
   calculate_dominance_info (CDI_DOMINATORS);
   calculate_dominance_info (CDI_POST_DOMINATORS);
 
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 622c51d5c3fa..2945f4f0ac8e 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -70,6 +70,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "omp-offload.h"
 #include "context.h"
 #include "tree-nested.h"
+#include "gcc-urlifier.h"
 
 /* Identifier for a basic condition, mapping it to other basic conditions of
    its Boolean expression.  Basic conditions given the same uid (in the same
@@ -2905,6 +2906,8 @@  expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
 static void
 expand_FALLTHROUGH (gimple_seq *seq_p)
 {
+  auto_urlify_attributes sentinel;
+
   struct walk_stmt_info wi;
   location_t loc[2];
   memset (&wi, 0, sizeof (wi));
diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index 4948b48bde81..9285c0496b47 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -55,6 +55,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "fold-const-call.h"
 #include "tree-ssa-live.h"
 #include "tree-outof-ssa.h"
+#include "gcc-urlifier.h"
 
 /* For lang_hooks.types.type_for_mode.  */
 #include "langhooks.h"
@@ -839,6 +840,7 @@  expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
 static void
 expand_FALLTHROUGH (internal_fn, gcall *call)
 {
+  auto_urlify_attributes sentinel;
   error_at (gimple_location (call),
 	    "invalid use of attribute %<fallthrough%>");
 }
diff --git a/gcc/ipa-pure-const.cc b/gcc/ipa-pure-const.cc
index d285462b6cf1..b39c2cf15f59 100644
--- a/gcc/ipa-pure-const.cc
+++ b/gcc/ipa-pure-const.cc
@@ -65,6 +65,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "ipa-fnsummary.h"
 #include "symtab-thunks.h"
 #include "dbgcnt.h"
+#include "gcc-urlifier.h"
 
 /* Lattice values for const and pure functions.  Everything starts out
    being const, then may drop to pure and then neither depending on
@@ -214,6 +215,7 @@  suggest_attribute (int option, tree decl, bool known_finite,
   if (warned_about->contains (decl))
     return warned_about;
   warned_about->add (decl);
+  auto_urlify_attributes sentinel;
   warning_at (DECL_SOURCE_LOCATION (decl),
 	      option,
 	      known_finite
diff --git a/gcc/ipa-strub.cc b/gcc/ipa-strub.cc
index 8fa7bdf53002..f6e09cd50b6d 100644
--- a/gcc/ipa-strub.cc
+++ b/gcc/ipa-strub.cc
@@ -63,6 +63,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "symtab-thunks.h"
 #include "attr-fnspec.h"
 #include "target.h"
+#include "gcc-urlifier.h"
 
 /* This file introduces two passes that, together, implement
    machine-independent stack scrubbing, strub for short.  It arranges
@@ -675,6 +676,8 @@  can_strub_p (cgraph_node *node, bool report = false)
   if (!report && (!result || strub_always_inline_p (node)))
     return result;
 
+  auto_urlify_attributes sentinel;
+
   if (flag_split_stack)
     {
       result = false;
diff --git a/gcc/regenerate-attr-urls.py b/gcc/regenerate-attr-urls.py
new file mode 100755
index 000000000000..04a04b863507
--- /dev/null
+++ b/gcc/regenerate-attr-urls.py
@@ -0,0 +1,209 @@ 
+#!/usr/bin/env python3
+
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
+#
+# Script to regenerate attr-urls.def from generated HTML.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 3, or (at your option) any later
+# version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.  */
+
+DESCRIPTION = """
+Parses the generated HTML (from "make html") to locate anchors
+for attributes, and generates a gcc/attr-urls.def file in the source tree,
+giving URLs for each attribute, where it can.
+
+Usage (from build/gcc subdirectory):
+  ../../src/gcc/regenerate-attr-urls.py HTML/gcc-15.0.0/ ../../src
+
+To run unit tests:
+  ../../src/gcc/regenerate-attr-urls.py HTML/gcc-15.0.0/ ../../src --unit-test
+"""
+
+import argparse
+import json
+import os
+from pathlib import Path
+from pprint import pprint
+import sys
+import re
+import unittest
+
+class Index:
+    def __init__(self):
+        self.entries = []
+        self.entries_by_kind = {}
+
+    def add_entry(self, url_suffix, name, kind, extra_text, verbose=False):
+        #if len(self.entries) > 5:
+        #    return
+        self.entries.append( (url_suffix, name, kind, extra_text) )
+
+        if kind in self.entries_by_kind:
+            by_kind = self.entries_by_kind[kind]
+        else:
+            by_kind = []
+            self.entries_by_kind[kind] = by_kind
+        by_kind.append( (name, url_suffix, extra_text) )
+
+    def parse_attribute_index(self, input_filename, verbose=False):
+        with open(input_filename) as f:
+            for line in f:
+                self.parse_html_line_attribute_index(line, verbose)
+
+    def parse_html_line_attribute_index(self, line, verbose=False):
+        if verbose:
+            print(repr(line))
+
+        # Update for this in the GCC website's bin/preprocess process_html_file:
+        #   | sed -e 's/_002d/-/g' -e 's/_002a/*/g' \
+        line = line.replace('_002d', '-')
+        line = line.replace('_002a', '*')
+
+        # e.g. <a href="Common-Function-Attributes.html#index-access-function-attribute"><code>access</code> function attribute</a>
+        # e.g. <a href="MIPS-Function-Attributes.html#index-nocompression-function-attribute_002c-MIPS"><code class="code">nocompression</code> function attribute, MIPS</a>
+        m = re.search(r'<a href="([\S]+)"><code[^>]*>([\S]+)</code> (\S+) attribute([^<]*)</a>', line)
+        if not m:
+            return
+        if verbose:
+            print(m.groups())
+
+        url_suffix, name, kind, extra_text = m.groups()
+
+        if extra_text.startswith(', '):
+            extra_text = extra_text[2:]
+
+        # Reject anchors where the name contains a paren
+        # e.g. 'target(&quot;3dnowa&quot;)':
+        if '(' in name:
+            return
+
+        self.add_entry(url_suffix, name, kind, extra_text)
+
+    def generate_file(self, dstpath):
+        with open(dstpath, 'w') as outf:
+            self.write_file(outf)
+
+    def write_file(self, outf):
+        outf.write("/* Autogenerated by regenerate-attr-urls.py.  */\n\n")
+
+        for kind in sorted(self.entries_by_kind.keys()):
+            by_kind = self.entries_by_kind[kind]
+            outf.write("const attr_url_entry %s_attrs[] = {\n" % kind)
+            for name, url_suffix, extra_text in sorted(self.entries_by_kind[kind]):
+                outf.write(' { "%s", "gcc/%s", "%s", %i},\n'
+                           % (name, url_suffix, extra_text, len(name)))
+            outf.write("};\n\n")
+
+        outf.write('static const struct attr_url_table {\n')
+        outf.write('  const attr_url_entry *m_table;\n')
+        outf.write('  const size_t m_table_sz;\n')
+        outf.write('} attr_url_tables[] = {\n')
+        for kind in sorted(self.entries_by_kind.keys()):
+            outf.write("  { %s_attrs, ARRAY_SIZE (%s_attrs) },\n" % (kind, kind))
+        outf.write("};\n")
+
+INDEX_REL_PATH = 'gcc/Concept-and-Symbol-Index.html'
+
+class TestParsingIndex(unittest.TestCase):
+    def test_function_attribute(self):
+        index = Index()
+        index.parse_html_line_attribute_index('<a href="Common-Function-Attributes.html#index-access-function-attribute"><code>access</code> function attribute</a>')
+        self.assertEqual(index.entries, [('Common-Function-Attributes.html#index-access-function-attribute',
+                                          'access',
+                                          'function',
+                                          '')])
+
+    def test_function_attribute_with_target(self):
+        index = Index()
+        index.parse_html_line_attribute_index('<a href="MIPS-Function-Attributes.html#index-nocompression-function-attribute_002c-MIPS"><code class="code">nocompression</code> function attribute, MIPS</a>')
+        self.assertEqual(index.entries, [('MIPS-Function-Attributes.html#index-nocompression-function-attribute_002c-MIPS',
+                                          'nocompression',
+                                          'function',
+                                          'MIPS')])
+
+    def test_reject_parens(self):
+        index = Index()
+        index.parse_html_line_attribute_index('<a href="x86-Function-Attributes.html#index-target_0028_00223dnow_0022_0029-function-attribute_002c-x86"><code>target(&quot;3dnow&quot;)</code> function attribute, x86</a>')
+        self.assertEqual(len(index.entries), 0)
+
+    def test_type_attribute(self):
+        index = Index()
+        index.parse_html_line_attribute_index('<a href="Common-Type-Attributes.html#index-aligned-type-attribute"><code>aligned</code> type attribute</a>')
+        self.assertEqual(index.entries, [('Common-Type-Attributes.html#index-aligned-type-attribute',
+                                          'aligned',
+                                          'type',
+                                          '')])
+
+    def test_enumerator_attribute(self):
+        index = Index()
+        index.parse_html_line_attribute_index('<a href="Enumerator-Attributes.html#index-deprecated-enumerator-attribute"><code>deprecated</code> enumerator attribute</a>')
+        self.assertEqual(index.entries, [('Enumerator-Attributes.html#index-deprecated-enumerator-attribute',
+                                          'deprecated',
+                                          'enumerator',
+                                          '')])
+    def test_label_attribute(self):
+        index = Index()
+        index.parse_html_line_attribute_index('<a href="Label-Attributes.html#index-cold-label-attribute"><code>cold</code> label attribute</a>')
+        self.assertEqual(index.entries, [('Label-Attributes.html#index-cold-label-attribute',
+                                          'cold',
+                                          'label',
+                                          '')])
+
+    def test_statement_attribute(self):
+        index = Index()
+        index.parse_html_line_attribute_index('<a href="Statement-Attributes.html#index-assume-statement-attribute"><code>assume</code> statement attribute</a>')
+        self.assertEqual(index.entries, [('Statement-Attributes.html#index-assume-statement-attribute',
+                                          'assume',
+                                          'statement',
+                                          '')])
+
+    def test_variable_attribute(self):
+        index = Index()
+        index.parse_html_line_attribute_index('<a href="AVR-Variable-Attributes.html#index-absdata-variable-attribute_002c-AVR"><code>absdata</code> variable attribute, AVR</a>')
+        self.assertEqual(index.entries, [('AVR-Variable-Attributes.html#index-absdata-variable-attribute_002c-AVR',
+                                          'absdata',
+                                          'variable',
+                                          'AVR')])
+
+    def test_parse_attribute_index(self):
+        index = Index()
+        index.parse_attribute_index(INPUT_HTML_PATH / INDEX_REL_PATH)
+        self.assertEqual(index.entries_by_kind['enumerator'][0],
+                         ('deprecated',
+                          'Enumerator-Attributes.html#index-deprecated-enumerator-attribute',
+                          ''))
+        self.assertEqual(index.entries_by_kind['label'][0],
+                         ('cold', 'Label-Attributes.html#index-cold-label-attribute', ''))
+
+def main(args):
+    index = Index()
+    index.parse_attribute_index(args.base_html_dir / INDEX_REL_PATH)
+    dstpath = args.src_gcc_dir / 'gcc' / 'attr-urls.def'
+    index.generate_file(dstpath)
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description=DESCRIPTION,
+                                     formatter_class=argparse.RawDescriptionHelpFormatter)
+    parser.add_argument('base_html_dir', type=Path)
+    parser.add_argument('src_gcc_dir', type=Path)
+    parser.add_argument('--unit-test', action='store_true')
+    args = parser.parse_args()
+
+    if args.unit_test:
+        INPUT_HTML_PATH = args.base_html_dir
+        unittest.main(argv=[sys.argv[0], '-v'])
+    else:
+        main(args)
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index 7fb7b92966be..35cbe0dd30f7 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -65,6 +65,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "asan.h"
 #include "profile.h"
 #include "sreal.h"
+#include "gcc-urlifier.h"
 
 /* This file contains functions for building the Control Flow Graph (CFG)
    for a function tree.  */
@@ -9934,6 +9935,8 @@  do_warn_unused_result (gimple_seq seq)
 
 	  if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
 	    {
+	      auto_urlify_attributes sentinel;
+
 	      location_t loc = gimple_location (g);
 
 	      if (fdecl)
diff --git a/gcc/tree-ssa-uninit.cc b/gcc/tree-ssa-uninit.cc
index 726684e472aa..8b00bab92630 100644
--- a/gcc/tree-ssa-uninit.cc
+++ b/gcc/tree-ssa-uninit.cc
@@ -42,6 +42,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "domwalk.h"
 #include "tree-ssa-sccvn.h"
 #include "cfganal.h"
+#include "gcc-urlifier.h"
 
 /* This implements the pass that does predicate aware warning on uses of
    possibly uninitialized variables.  The pass first collects the set of
@@ -455,6 +456,7 @@  maybe_warn_read_write_only (tree fndecl, gimple *stmt, tree arg, tree ptr)
       const char* const access_str =
 	TREE_STRING_POINTER (access->to_external_string ());
 
+      auto_urlify_attributes sentinel;
       location_t parmloc = DECL_SOURCE_LOCATION (parm);
       inform (parmloc, "accessing argument %u of a function declared with "
 	      "attribute %<%s%>",
@@ -876,6 +878,7 @@  maybe_warn_pass_by_reference (gcall *stmt, wlimits &wlims)
 	  const char* const access_str =
 	    TREE_STRING_POINTER (access->to_external_string ());
 
+	  auto_urlify_attributes sentinel;
 	  if (fndecl)
 	    {
 	      location_t loc = DECL_SOURCE_LOCATION (fndecl);