On 7/20/19 11:29 AM, JeanHeyd Meneide wrote:
Dear GCC Community,

      This patch implements the recently accepted p1301: [[nodiscard("should
have a reason")]]. Aaron Ballman implemented it for Clang in
http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20190715/280158.html
-- this is in preparation for a paper that will soon go to the C Committee
to keep feature-parity with C++ (the C2x draft already has attributes with
syntax exactly like C++).

     Comments welcome: this is my first patch, and probably needs a lot of
help. This is also part of my Google Summer of Code training, to get used
to submitting and sending patches on the gcc-patches list.

Just a few minor notes/suggestions.

...
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "convert.h"
  #include "stringpool.h"
  #include "attribs.h"
+#include "escaped_string.h"

  static tree convert_to_pointer_force (tree, tree, tsubst_flags_t);
  static tree build_type_conversion (tree, tree);
@@ -1029,19 +1030,29 @@ maybe_warn_nodiscard (tree expr, impl_conv_void
implicit)
    if (implicit != ICV_CAST && fn
        && lookup_attribute ("nodiscard", DECL_ATTRIBUTES (fn)))
      {
-      auto_diagnostic_group d;
+      tree attr = DECL_ATTRIBUTES (fn);
+      escaped_string msg;
+      if (attr)
+         msg.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
+      bool has_msg = static_cast<bool>(msg);
+    auto_diagnostic_group d;
        if (warning_at (loc, OPT_Wunused_result,
-      "ignoring return value of %qD, "
-      "declared with attribute nodiscard", fn))
- inform (DECL_SOURCE_LOCATION (fn), "declared here");
+                     "ignoring return value of %qD, "
+                     "declared with attribute nodiscard%s%s", fn, (has_msg
? ": " : ""), (has_msg ? (const char*)msg : "")))
+        inform (DECL_SOURCE_LOCATION (fn), "declared here");

While making changes here, would you mind adding quotes around
nodiscard (i.e., %<nodiscard%>).  Should the text included in
the attribute also be similarly quoted so that it's highlighted
in the diagnostic?

      }
    else if (implicit != ICV_CAST
     && lookup_attribute ("nodiscard", TYPE_ATTRIBUTES (rettype)))
      {
+      tree attr = TYPE_ATTRIBUTES (rettype);
+      escaped_string msg;
+      if (attr)
+         msg.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
+      bool has_msg = static_cast<bool>(msg);
        auto_diagnostic_group d;
        if (warning_at (loc, OPT_Wunused_result,
-      "ignoring returned value of type %qT, "
-      "declared with attribute nodiscard", rettype))
+                      "ignoring returned value of type %qT, "
+                      "declared with attribute nodiscard%s%s", rettype,

Also here.

(has_msg ? ": " : ""), (has_msg ? (const char*)msg : "")))
   {
    if (fn)
      inform (DECL_SOURCE_LOCATION (fn),
...
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 37e24a1669c..8c2d056f3eb 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -4356,9 +4356,27 @@ zero_init_p (const_tree t)
     warn_unused_result attribute.  */

  static tree
-handle_nodiscard_attribute (tree *node, tree name, tree /*args*/,
+handle_nodiscard_attribute (tree *node, tree name, tree args,
      int /*flags*/, bool *no_add_attrs)
  {
+  if (!args)
+    *no_add_attrs = true;
+  else if (cxx_dialect >= cxx2a)
+    {
+      if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+        {
+          error ("nodiscard attribute argument must be a string");

And also here; to reduce the number of format strings that have to
be translated it's best to use:

  error ("%qE attribute argument must be a string constant", name);

+          *no_add_attrs = true;
+        }
+    }
+  else
+    {
+      if (!*no_add_attrs)
+        {
+          error("nodiscard attribute does not take any arguments: use flag
%<-std=c2a%> or better to compile your code");

Also here.  Rather than a colon I think the dominant style is to
use a semicolon but I would suggest:

  error ("%E attribute with an argument only available with "
         "%<-std=c++2a%> or %<-std=gnu++2a%>");

in keeping with other messages like it (see gcc/po/gcc.pot for
examples).  (I assume the option to enable the C++ 2a dialect
is -std=c++2a, not -std=c2a.)

+++ b/gcc/escaped_string.h
@@ -0,0 +1,41 @@
...
+/* A class to handle converting a string that might contain
+   control characters, (eg newline, form-feed, etc), into one
+   in which contains escape sequences instead.  */
+
+class escaped_string
+{
+ public:
+  escaped_string () { m_owned = false; m_str = NULL; };
+  ~escaped_string () { if (m_owned) free (m_str); }
+  operator const char *() const { return (const char *) m_str; }
+  void escape (const char *);
+ private:
+  char *m_str;
+  bool  m_owned;
+};

Since the class isn't safe to copy/assign and it's being moved
to a header, could you please make its copy ctor and assignment
operator private to prevent its objects from accidentally
getting copied and corrupting memory?

...
 +++ b/gcc/testsuite/g++.dg/cpp2a/nodiscard-bad-clause.C
@@ -0,0 +1,12 @@
+/* nodiscard attribute tests  */
+/* { dg-do compile { target c++2a } } */
+/* { dg-options "-O -ftrack-macro-expansion=0" } */
+
+[[nodiscard(123)]] int check1 (void); /* { dg-error "nodiscard attribute
argument.*must be a string" } */

Using .* might be safe in a test with a single line of output but
not in other tests where it might consume newlines.  It's best to

Martin

Reply via email to