This patch adds metadata to some C++ diagnostics, referencing a specific section/anchor within a draft of the C++ standard. For example, this adds a [depr.volatile.type] tag:
standard-ref-1.C:1:12: warning: ‘volatile’-qualified parameter is deprecated [depr.volatile.type] [-Wvolatile] 1 | void test (volatile int); | ^~~~~~~~~~~~ where in a sufficiently capable terminal the [depr.volatile.type] has URL: https://eelis.net/c++draft/depr.volatile.type#3 Arguably cppreference would be a better thing to link people to from a UX perspective. Thoughts? gcc/cp/ChangeLog: * decl.cc: Include "diagnostic-metadata.h". (class cp_standard_ref): New. (duplicate_decls): Add link to dcl.attr.noreturn to mismatched [[noreturn]]. (grokparms): Add link to depr.volatile.type to violation of [dcl.fct] "A parameter with volatile-qualified type is deprecated. gcc/testsuite/ChangeLog: * g++.dg/diagnostic/standard-ref-1.C: New test. * g++.dg/diagnostic/standard-ref-2.C: New test. Signed-off-by: David Malcolm <dmalc...@redhat.com> --- gcc/cp/decl.cc | 62 +++++++++++++++++-- .../g++.dg/diagnostic/standard-ref-1.C | 1 + .../g++.dg/diagnostic/standard-ref-2.C | 4 ++ 3 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/standard-ref-1.C create mode 100644 gcc/testsuite/g++.dg/diagnostic/standard-ref-2.C diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 10c2b2e3ad10..2bef065173eb 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see #include "coroutines.h" #include "diagnostic-highlight-colors.h" #include "pretty-print-markup.h" +#include "diagnostic-metadata.h" /* Possible cases of bad specifiers type used by bad_specifiers. */ enum bad_spec_place { @@ -268,6 +269,48 @@ struct GTY(()) incomplete_var { static GTY(()) vec<incomplete_var, va_gc> *incomplete_vars; + +/* A diagnostic_metadata instance that adds a reference to a particular + section of the (draft) C++ standard, at a given anchor. */ + +class cp_standard_ref : public diagnostic_metadata +{ +public: + cp_standard_ref (const char *section, const char *anchor) + : m_rule (section, anchor) + { + add_rule (m_rule); + } + +private: + class std_rule : public rule + { + public: + std_rule (const char *section, const char *anchor) + : m_section (section), + m_anchor (anchor) + {} + + char *make_description () const final override + { + return xstrdup (m_section); + } + + char *make_url () const final override + { + return concat ("https://eelis.net/c++draft/", + m_section, + "#", + m_anchor, + nullptr); + } + + private: + const char *m_section; + const char *m_anchor; + } m_rule; +}; + /* Returns the kind of template specialization we are currently processing, given that it's declaration contained N_CLASS_SCOPES explicit scope qualifications. */ @@ -2358,8 +2401,12 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) && get_attribute_namespace (a) == NULL_TREE) { auto_diagnostic_group d; - error_at (newdecl_loc, "function %qD declared %<[[noreturn]]%> " - "but its first declaration was not", newdecl); + gcc_rich_location richloc (newdecl_loc); + error_meta (&richloc, + cp_standard_ref ("dcl.attr.noreturn", "1"), + "function %qD declared %<[[noreturn]]%> " + "but its first declaration was not", + newdecl); inform (olddecl_loc, "previous declaration of %qD", olddecl); } } @@ -15795,9 +15842,14 @@ grokparms (tree parmlist, tree *parms) /* [dcl.fct] "A parameter with volatile-qualified type is deprecated." */ if (CP_TYPE_VOLATILE_P (type)) - warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wvolatile, - "%<volatile%>-qualified parameter is " - "deprecated"); + { + gcc_rich_location richloc (DECL_SOURCE_LOCATION (decl)); + warning_meta (&richloc, + cp_standard_ref ("depr.volatile.type", "3"), + OPT_Wvolatile, + "%<volatile%>-qualified parameter is " + "deprecated"); + } /* Top-level qualifiers on the parameters are ignored for function types. */ diff --git a/gcc/testsuite/g++.dg/diagnostic/standard-ref-1.C b/gcc/testsuite/g++.dg/diagnostic/standard-ref-1.C new file mode 100644 index 000000000000..819c6b90e70f --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/standard-ref-1.C @@ -0,0 +1 @@ +void test (volatile int); // { dg-warning "'volatile'-qualified parameter is deprecated \\\[depr.volatile.type\\\] \\\[-Wvolatile\\]" "" { target c++20 } } diff --git a/gcc/testsuite/g++.dg/diagnostic/standard-ref-2.C b/gcc/testsuite/g++.dg/diagnostic/standard-ref-2.C new file mode 100644 index 000000000000..a5407cefde5e --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/standard-ref-2.C @@ -0,0 +1,4 @@ +// { dg-do compile { target c++11 } } + +void my_exit (); // { dg-message "previous declaration" } +[[noreturn]] void my_exit (); // { dg-error "function 'void my_exit\\\(\\\)' declared '\\\[\\\[noreturn\\\]\\\]' but its first declaration was not \\\[dcl.attr.noreturn\\\]" } -- 2.26.3