diff mbox

C++ PATCH to implement C++17 maybe_unused attribute

Message ID 571E51C8.9060105@redhat.com
State New
Headers show

Commit Message

Jason Merrill April 25, 2016, 5:20 p.m. UTC
The C++17 maybe_unused attribute is mostly equivalent to the GNU unused 
attribute, except that it can also be applied to enumerators.

I was surprised to see that there currently isn't a table of C++ 
standard attributes; all the standard attributes we already support are 
handled by translating them into GNU attributes.  That doesn't work as 
well in this case because the name is different, and it seems to me we 
might as well start a table of standard attributes.  To make that work I 
needed to declare register_scoped_attributes in attribs.h and fix a 
logic error in that function.

Since the semantics are the same, I'm using the same 
handle_unused_attribute function and just allowing it to accept CONST_DECL.

Currently __has_cpp_attribute is implemented using the same hook as 
__has_attribute, so the function doesn't know whether we're asking about 
a GNU attribute or standard attribute.  For now let's leave that alone 
and just handle the special standard values without trying to look up 
the attribute_spec.

Tested x86_64-pc-linux-gnu, applying to trunk.

Comments

Andreas Schwab April 26, 2016, 9:46 a.m. UTC | #1
/usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:5:14: error: size of array 'T1' is negative
/usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:13:14: error: size of array 'T5' is negative
/usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:17:1: error: unknown type name 'T4'
/usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:35:14: error: size of array 'T11' is negative
/usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:43:14: error: size of array 'T15' is negative
/usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:47:1: error: unknown type name 'T14'

Andreas.
Jason Merrill April 26, 2016, 3:55 p.m. UTC | #2
Fixed.

Jason


On Tue, Apr 26, 2016 at 5:46 AM, Andreas Schwab <schwab@linux-m68k.org> wrote:
> /usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:5:14: error: size of array 'T1' is negative
> /usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:13:14: error: size of array 'T5' is negative
> /usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:17:1: error: unknown type name 'T4'
> /usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:35:14: error: size of array 'T11' is negative
> /usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:43:14: error: size of array 'T15' is negative
> /usr/local/gcc/gcc-20160426/gcc/testsuite/c-c++-common/cpp/pr63831-1.c:47:1: error: unknown type name 'T14'
>
> Andreas.
>
> --
> Andreas Schwab, schwab@linux-m68k.org
> GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
> "And now for something completely different."
diff mbox

Patch

commit 0c140407be1dbcb43fa4e2047d5aa65cb5ac5ff8
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Mar 8 16:27:45 2016 -0500

    	Implement C++17 [[maybe_unused]] attribute.
    
    gcc/
    	* attribs.c (register_scoped_attributes): Fix logic.
    	* attribs.h: Declare register_scoped_attributes.
    c-family/
    	* c-common.c (handle_unused_attribute): Accept CONST_DECL.
    	No longer static.
    	* c-common.h: Declare it.
    	* c-lex.c (c_common_has_attribute): Add maybe_unused.
    cp/
    	* tree.c (std_attribute_table): New.
    	(init_tree): Register it.

diff --git a/gcc/attribs.c b/gcc/attribs.c
index 16996e9..9a88621 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -130,7 +130,7 @@  register_scoped_attributes (const struct attribute_spec * attributes,
       /* We don't have any namespace NS yet.  Create one.  */
       scoped_attributes sa;
 
-      if (!attributes_table.is_empty ())
+      if (attributes_table.is_empty ())
 	attributes_table.create (64);
 
       memset (&sa, 0, sizeof (sa));
diff --git a/gcc/attribs.h b/gcc/attribs.h
index 9e64a7a..23d3043 100644
--- a/gcc/attribs.h
+++ b/gcc/attribs.h
@@ -38,4 +38,7 @@  extern tree get_attribute_name (const_tree);
 extern void apply_tm_attr (tree, tree);
 extern tree make_attribute (const char *, const char *, tree);
 
+extern struct scoped_attributes* register_scoped_attributes (const struct attribute_spec *,
+							     const char *);
+
 #endif // GCC_ATTRIBS_H
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index cae2faf..1edc0bc 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -327,7 +327,6 @@  static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
 static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
 static tree handle_error_attribute (tree *, tree, tree, int, bool *);
 static tree handle_used_attribute (tree *, tree, tree, int, bool *);
-static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
 static tree handle_externally_visible_attribute (tree *, tree, tree, int,
 						 bool *);
 static tree handle_no_reorder_attribute (tree *, tree, tree, int,
@@ -7033,7 +7032,7 @@  handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
 /* Handle a "unused" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+tree
 handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
 			 int flags, bool *no_add_attrs)
 {
@@ -7044,6 +7043,7 @@  handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
       if (TREE_CODE (decl) == PARM_DECL
 	  || VAR_OR_FUNCTION_DECL_P (decl)
 	  || TREE_CODE (decl) == LABEL_DECL
+	  || TREE_CODE (decl) == CONST_DECL
 	  || TREE_CODE (decl) == TYPE_DECL)
 	{
 	  TREE_USED (decl) = 1;
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 663e457..4c43a35 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -790,6 +790,7 @@  extern void check_function_arguments_recurse (void (*)
 					      unsigned HOST_WIDE_INT);
 extern bool check_builtin_function_arguments (tree, int, tree *);
 extern void check_function_format (tree, int, tree *);
+extern tree handle_unused_attribute (tree *, tree, tree, int, bool *);
 extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
 extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
 extern bool attribute_takes_identifier_p (const_tree);
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index 96da4fc..6b020a4 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -340,23 +340,26 @@  c_common_has_attribute (cpp_reader *pfile)
 		  attr_name = NULL_TREE;
 		}
 	    }
-	}
-      if (attr_name)
-	{
-	  init_attributes ();
-	  const struct attribute_spec *attr = lookup_attribute_spec (attr_name);
-	  if (attr)
+	  else
 	    {
-	      if (TREE_CODE (attr_name) == TREE_LIST)
-		attr_name = TREE_VALUE (attr_name);
+	      /* Some standard attributes need special handling.  */
 	      if (is_attribute_p ("noreturn", attr_name))
 		result = 200809;
 	      else if (is_attribute_p ("deprecated", attr_name))
 		result = 201309;
-	      else
-		result = 1;
+	      else if (is_attribute_p ("maybe_unused", attr_name))
+		result = 201603;
+	      if (result)
+		attr_name = NULL_TREE;
 	    }
 	}
+      if (attr_name)
+	{
+	  init_attributes ();
+	  const struct attribute_spec *attr = lookup_attribute_spec (attr_name);
+	  if (attr)
+	    result = 1;
+	}
     }
   else
     {
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 112c8c7..381c24f 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -3548,6 +3548,16 @@  const struct attribute_spec cxx_attribute_table[] =
   { NULL,	      0, 0, false, false, false, NULL, false }
 };
 
+/* Table of C++ standard attributes.  */
+const struct attribute_spec std_attribute_table[] =
+{
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       affects_type_identity } */
+  { "maybe_unused", 0, 0, false, false, false,
+    handle_unused_attribute, false },
+  { NULL,	      0, 0, false, false, false, NULL, false }
+};
+
 /* Handle a "java_interface" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
@@ -4026,6 +4036,7 @@  void
 init_tree (void)
 {
   list_hash_table = hash_table<list_hasher>::create_ggc (61);
+  register_scoped_attributes (std_attribute_table, NULL);
 }
 
 /* Returns the kind of special function that DECL (a FUNCTION_DECL)
diff --git a/gcc/testsuite/c-c++-common/attributes-enum-2.c b/gcc/testsuite/c-c++-common/attributes-enum-2.c
index f143f15..131dd54 100644
--- a/gcc/testsuite/c-c++-common/attributes-enum-2.c
+++ b/gcc/testsuite/c-c++-common/attributes-enum-2.c
@@ -6,7 +6,7 @@  enum E {
   A __attribute__((foo)),	/* { dg-warning "ignored" } */
   B __attribute__((cold)),	/* { dg-warning "ignored" } */
   C __attribute__((const)),	/* { dg-warning "ignored" } */
-  D __attribute__((unused)),	/* { dg-warning "ignored" } */
+  D __attribute__((unused)),
   E __attribute__((flatten)),	/* { dg-warning "ignored" } */
   F __attribute__((tm)),	/* { dg-warning "ignored" } */
   G __attribute__((common)),	/* { dg-warning "ignored" } */
diff --git a/gcc/testsuite/c-c++-common/cpp/pr63831-1.c b/gcc/testsuite/c-c++-common/cpp/pr63831-1.c
index c9e7756..c7cad04 100644
--- a/gcc/testsuite/c-c++-common/cpp/pr63831-1.c
+++ b/gcc/testsuite/c-c++-common/cpp/pr63831-1.c
@@ -17,10 +17,10 @@  T3 t3;
 T4 t4;
 T5 t5;
 #ifdef __cplusplus
-typedef char T6[__has_attribute (gnu::__noreturn__) == 200809 ? 1 : -1];
+typedef char T6[__has_attribute (gnu::__noreturn__) ? 1 : -1];
 typedef char T7[__has_attribute (gnu::alloc_size) == 1 ? 1 : -1];
 typedef char T8[__has_attribute (gnu::non_existent_attribuuuute) == 0 ? 1 : -1];
-#if __has_attribute (gnu::noreturn) == 200809
+#if __has_attribute (gnu::noreturn)
 typedef char T9;
 #endif
 #define d2 gnu::deprecated
@@ -47,10 +47,10 @@  T13 t13;
 T14 t14;
 T15 t15;
 #ifdef __cplusplus
-typedef char T16[__has_cpp_attribute (gnu::__noreturn__) == 200809 ? 1 : -1];
+typedef char T16[__has_cpp_attribute (gnu::__noreturn__) ? 1 : -1];
 typedef char T17[__has_cpp_attribute (gnu::alloc_size) == 1 ? 1 : -1];
 typedef char T18[__has_cpp_attribute (gnu::non_existent_attribuuuute) == 0 ? 1 : -1];
-#if __has_cpp_attribute (gnu::noreturn) == 200809
+#if __has_cpp_attribute (gnu::noreturn)
 typedef char T19;
 #endif
 #define d2 gnu::deprecated
diff --git a/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C b/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
index 74c6f29..fe7a4c2 100644
--- a/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
+++ b/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
@@ -343,3 +343,13 @@ 
 #elif __cpp_hex_float != 201603
 #  error "__cpp_hex_float != 201603"
 #endif
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(maybe_unused)
+#    error "__has_cpp_attribute(maybe_unused)"
+#  elif __has_cpp_attribute(maybe_unused) != 201603
+#    error "__has_cpp_attribute(maybe_unused) != 201603"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp1z/maybe_unused1.C b/gcc/testsuite/g++.dg/cpp1z/maybe_unused1.C
new file mode 100644
index 0000000..eb8b51e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/maybe_unused1.C
@@ -0,0 +1,17 @@ 
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wunused -Wextra" }
+
+[[maybe_unused]] static void f() { }
+
+enum [[maybe_unused]] E {
+  e [[maybe_unused]]
+};
+
+struct [[maybe_unused]] A {
+  [[maybe_unused]] static int i;
+};
+
+void g([[maybe_unused]] int i) {
+  [[maybe_unused]] typedef int T;
+  [[maybe_unused]] int j;
+}