re PR c++/43407 (Specifying visibility attribute of C++0x enum class emits warning)
authorJason Merrill <jason@redhat.com>
Thu, 21 Jan 2016 20:26:02 +0000 (15:26 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 21 Jan 2016 20:26:02 +0000 (15:26 -0500)
PR c++/43407
* decl.c (start_enum): Add attributes parameter.
* parser.c (cp_parser_enum_specifier): Pass it.
* pt.c (lookup_template_class_1): Pass it.
* cp-tree.h: Adjust.

From-SVN: r232701

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/abi/abi-tag15.C
gcc/testsuite/g++.dg/cpp0x/enum31.C [new file with mode: 0644]

index 45cb0e72a4c6abf3ca101e51739bf3b4cbbaddc1..f516216ab6f12343e67e20fdc6e7b52f02919440 100644 (file)
@@ -1,3 +1,11 @@
+2016-01-21  Jason Merrill  <jason@redhat.com>
+
+       PR c++/43407
+       * decl.c (start_enum): Add attributes parameter.
+       * parser.c (cp_parser_enum_specifier): Pass it.
+       * pt.c (lookup_template_class_1): Pass it.
+       * cp-tree.h: Adjust.
+
 2016-01-19  Jason Merrill  <jason@redhat.com>
 
        PR c++/59759
index 51589c3311b9ba8d038a59e6a47ac70d76056e08..0aeee578f7e5a58be0a1d235fb3efb0079489f97 100644 (file)
@@ -5788,7 +5788,7 @@ extern bool grok_op_properties                    (tree, bool);
 extern tree xref_tag                           (enum tag_types, tree, tag_scope, bool);
 extern tree xref_tag_from_type                 (tree, tree, tag_scope);
 extern bool xref_basetypes                     (tree, tree);
-extern tree start_enum                         (tree, tree, tree, bool, bool *);
+extern tree start_enum                         (tree, tree, tree, tree, bool, bool *);
 extern void finish_enum_value_list             (tree);
 extern void finish_enum                                (tree);
 extern void build_enumerator                   (tree, tree, tree, tree, location_t);
index ceeef6061172361e406fafb85adbc872f558bec8..d995654a3d8b0b0d0ab2c529bd8c0f29baf3b9ec 100644 (file)
@@ -13045,6 +13045,8 @@ copy_type_enum (tree dst, tree src)
    the enumeration type. This should be NULL_TREE if no storage type
    was specified.
 
+   ATTRIBUTES are any attributes specified after the enum-key.
+
    SCOPED_ENUM_P is true if this is a scoped enumeration type.
 
    if IS_NEW is not NULL, gets TRUE iff a new type is created.
@@ -13055,7 +13057,7 @@ copy_type_enum (tree dst, tree src)
 
 tree
 start_enum (tree name, tree enumtype, tree underlying_type,
-           bool scoped_enum_p, bool *is_new)
+           tree attributes, bool scoped_enum_p, bool *is_new)
 {
   tree prevtype = NULL_TREE;
   gcc_assert (identifier_p (name));
@@ -13163,6 +13165,8 @@ start_enum (tree name, tree enumtype, tree underlying_type,
 
   SET_SCOPED_ENUM_P (enumtype, scoped_enum_p);
 
+  cplus_decl_attributes (&enumtype, attributes, (int)ATTR_FLAG_TYPE_IN_PLACE);
+
   if (underlying_type)
     {
       if (CP_INTEGRAL_TYPE_P (underlying_type))
index 8dd7e498f7feb39cb18451d2c3b79e1d71c7e316..33f1df3ca025869788aae0a3be746325b654fde4 100644 (file)
@@ -17132,7 +17132,7 @@ cp_parser_enum_specifier (cp_parser* parser)
        brace so the enum will be recorded as being on the line of its
        tag (or the 'enum' keyword, if there is no tag).  */
     type = start_enum (identifier, type, underlying_type,
-                      scoped_enum_p, &is_new_type);
+                      attributes, scoped_enum_p, &is_new_type);
 
   /* If the next token is not '{' it is an opaque-enum-specifier or an
      elaborated-type-specifier.  */
@@ -17248,7 +17248,6 @@ cp_parser_enum_specifier (cp_parser* parser)
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
       tree trailing_attr = cp_parser_gnu_attributes_opt (parser);
-      trailing_attr = chainon (trailing_attr, attributes);
       cplus_decl_attributes (&type,
                             trailing_attr,
                             (int) ATTR_FLAG_TYPE_IN_PLACE);
index ae60f1c2d0a667d29b8617e97f5baf3462374ab0..7985198d46c6018ea36f3d0529e917fe7da4310e 100644 (file)
@@ -214,6 +214,7 @@ static tree listify_autos (tree, tree);
 static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 static tree instantiate_alias_template (tree, tree, tsubst_flags_t);
 static bool complex_alias_template_p (const_tree tmpl);
+static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -8398,6 +8399,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
              t = start_enum (TYPE_IDENTIFIER (template_type), NULL_TREE,
                              tsubst (ENUM_UNDERLYING_TYPE (template_type),
                                      arglist, complain, in_decl),
+                             tsubst_attributes (TYPE_ATTRIBUTES (template_type),
+                                                arglist, complain, in_decl),
                              SCOPED_ENUM_P (template_type), NULL);
 
              if (t == error_mark_node)
@@ -9540,6 +9543,109 @@ can_complete_type_without_circularity (tree type)
 
 static tree tsubst_omp_clauses (tree, bool, bool, tree, tsubst_flags_t, tree);
 
+/* Instantiate a single dependent attribute T (a TREE_LIST), and return either
+   T or a new TREE_LIST, possibly a chain in the case of a pack expansion.  */
+
+static tree
+tsubst_attribute (tree t, tree *decl_p, tree args,
+                 tsubst_flags_t complain, tree in_decl)
+{
+  gcc_assert (ATTR_IS_DEPENDENT (t));
+
+  tree val = TREE_VALUE (t);
+  if (val == NULL_TREE)
+    /* Nothing to do.  */;
+  else if ((flag_openmp || flag_openmp_simd || flag_cilkplus)
+          && is_attribute_p ("omp declare simd",
+                             get_attribute_name (t)))
+    {
+      tree clauses = TREE_VALUE (val);
+      clauses = tsubst_omp_clauses (clauses, true, false, args,
+                                   complain, in_decl);
+      c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
+      clauses = finish_omp_clauses (clauses, false, true);
+      tree parms = DECL_ARGUMENTS (*decl_p);
+      clauses
+       = c_omp_declare_simd_clauses_to_numbers (parms, clauses);
+      if (clauses)
+       val = build_tree_list (NULL_TREE, clauses);
+      else
+       val = NULL_TREE;
+    }
+  /* If the first attribute argument is an identifier, don't
+     pass it through tsubst.  Attributes like mode, format,
+     cleanup and several target specific attributes expect it
+     unmodified.  */
+  else if (attribute_takes_identifier_p (get_attribute_name (t)))
+    {
+      tree chain
+       = tsubst_expr (TREE_CHAIN (val), args, complain, in_decl,
+                      /*integral_constant_expression_p=*/false);
+      if (chain != TREE_CHAIN (val))
+       val = tree_cons (NULL_TREE, TREE_VALUE (val), chain);
+    }
+  else if (PACK_EXPANSION_P (val))
+    {
+      /* An attribute pack expansion.  */
+      tree purp = TREE_PURPOSE (t);
+      tree pack = tsubst_pack_expansion (val, args, complain, in_decl);
+      int len = TREE_VEC_LENGTH (pack);
+      tree list = NULL_TREE;
+      tree *q = &list;
+      for (int i = 0; i < len; ++i)
+       {
+         tree elt = TREE_VEC_ELT (pack, i);
+         *q = build_tree_list (purp, elt);
+         q = &TREE_CHAIN (*q);
+       }
+      return list;
+    }
+  else
+    val = tsubst_expr (val, args, complain, in_decl,
+                      /*integral_constant_expression_p=*/false);
+
+  if (val != TREE_VALUE (t))
+    return build_tree_list (TREE_PURPOSE (t), val);
+  return t;
+}
+
+/* Instantiate any dependent attributes in ATTRIBUTES, returning either it
+   unchanged or a new TREE_LIST chain.  */
+
+static tree
+tsubst_attributes (tree attributes, tree args,
+                  tsubst_flags_t complain, tree in_decl)
+{
+  tree last_dep = NULL_TREE;
+
+  for (tree t = attributes; t; t = TREE_CHAIN (t))
+    if (ATTR_IS_DEPENDENT (t))
+      {
+       last_dep = t;
+       attributes = copy_list (attributes);
+       break;
+      }
+
+  if (last_dep)
+    for (tree *p = &attributes; *p; p = &TREE_CHAIN (*p))
+      {
+       tree t = *p;
+       if (ATTR_IS_DEPENDENT (t))
+         {
+           tree subst = tsubst_attribute (t, NULL, args, complain, in_decl);
+           if (subst == t)
+             continue;
+           *p = subst;
+           do
+             p = &TREE_CHAIN (*p);
+           while (*p);
+           *p = TREE_CHAIN (t);
+         }
+      }
+
+  return attributes;
+}
+
 /* Apply any attributes which had to be deferred until instantiation
    time.  DECL_P, ATTRIBUTES and ATTR_FLAGS are as cplus_decl_attributes;
    ARGS, COMPLAIN, IN_DECL are as tsubst.  */
@@ -9581,61 +9687,10 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
            {
              *p = TREE_CHAIN (t);
              TREE_CHAIN (t) = NULL_TREE;
-             if ((flag_openmp || flag_openmp_simd || flag_cilkplus)
-                 && is_attribute_p ("omp declare simd",
-                                    get_attribute_name (t))
-                 && TREE_VALUE (t))
-               {
-                 tree clauses = TREE_VALUE (TREE_VALUE (t));
-                 clauses = tsubst_omp_clauses (clauses, true, false, args,
-                                               complain, in_decl);
-                 c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
-                 clauses = finish_omp_clauses (clauses, false, true);
-                 tree parms = DECL_ARGUMENTS (*decl_p);
-                 clauses
-                   = c_omp_declare_simd_clauses_to_numbers (parms, clauses);
-                 if (clauses)
-                   TREE_VALUE (TREE_VALUE (t)) = clauses;
-                 else
-                   TREE_VALUE (t) = NULL_TREE;
-               }
-             /* If the first attribute argument is an identifier, don't
-                pass it through tsubst.  Attributes like mode, format,
-                cleanup and several target specific attributes expect it
-                unmodified.  */
-             else if (attribute_takes_identifier_p (get_attribute_name (t))
-                      && TREE_VALUE (t))
-               {
-                 tree chain
-                   = tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain,
-                                  in_decl,
-                                  /*integral_constant_expression_p=*/false);
-                 if (chain != TREE_CHAIN (TREE_VALUE (t)))
-                   TREE_VALUE (t)
-                     = tree_cons (NULL_TREE, TREE_VALUE (TREE_VALUE (t)),
-                                  chain);
-               }
-             else if (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t)))
-               {
-                 /* An attribute pack expansion.  */
-                 tree purp = TREE_PURPOSE (t);
-                 tree pack = (tsubst_pack_expansion
-                              (TREE_VALUE (t), args, complain, in_decl));
-                 int len = TREE_VEC_LENGTH (pack);
-                 for (int i = 0; i < len; ++i)
-                   {
-                     tree elt = TREE_VEC_ELT (pack, i);
-                     *q = build_tree_list (purp, elt);
-                     q = &TREE_CHAIN (*q);
-                   }
-                 continue;
-               }
-             else
-               TREE_VALUE (t)
-                 = tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
-                                /*integral_constant_expression_p=*/false);
-             *q = t;
-             q = &TREE_CHAIN (t);
+             *q = tsubst_attribute (t, decl_p, args, complain, in_decl);
+             do
+               q = &TREE_CHAIN (*q);
+             while (*q);
            }
          else
            p = &TREE_CHAIN (t);
index bfda3a279ef09bc7835bbebf7ee490a7122e9438..cf9e32fb81740721873d8a588e22b0876bda6e47 100644 (file)
@@ -1,3 +1,3 @@
 // PR c++/66748
 
-enum __attribute__((abi_tag("foo"))) E {}; // { dg-error "redeclaration of" }
+enum __attribute__((abi_tag("foo"))) E {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum31.C b/gcc/testsuite/g++.dg/cpp0x/enum31.C
new file mode 100644 (file)
index 0000000..62d65b4
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++11 } }
+
+enum class __attribute__((__visibility__("default"))) Foobar
+{
+  fratz,
+    nabble
+};