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 <[email protected]>
---
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