OSDN Git Service

PR c++/17743, c++/19163
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 14 Sep 2007 06:07:25 +0000 (06:07 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 14 Sep 2007 06:07:25 +0000 (06:07 +0000)
        * decl2.c (is_late_template_attribute): New fn.
        (splice_template_attributes, save_template_attributes): New fns.
        (cplus_decl_attributes): Call save_template_attributes.
        * pt.c (apply_late_template_attributes): New fn.
        (instantiate_class_template, tsubst_decl): Use it.
        * cp-tree.h: Declare is_late_template_attribute.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128488 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/ext/tmplattr2.C [new file with mode: 0644]

index dfcbb02..26028a5 100644 (file)
@@ -1,3 +1,13 @@
+2007-09-14  Jason Merrill  <jason@redhat.com>
+
+       PR c++/17743, c++/19163
+       * decl2.c (is_late_template_attribute): New fn.
+       (splice_template_attributes, save_template_attributes): New fns.
+       (cplus_decl_attributes): Call save_template_attributes.
+       * pt.c (apply_late_template_attributes): New fn.
+       (instantiate_class_template, tsubst_decl): Use it.
+       * cp-tree.h: Declare is_late_template_attribute.
+
 2007-09-13  Tom Tromey  <tromey@redhat.com>
 
        * parser.c (cp_lexer_new_main): Don't use
index 5efbdb7..4f1e88c 100644 (file)
@@ -4276,6 +4276,7 @@ extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
                       tree, bool, tree, tree);
 extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
                          tree);
+extern bool is_late_template_attribute         (tree);
 extern void cplus_decl_attributes              (tree *, tree, int);
 extern void finish_anon_union                  (tree);
 extern void cp_write_global_declarations       (void);
index db578d8..0c0961d 100644 (file)
@@ -985,13 +985,87 @@ grokbitfield (const cp_declarator *declarator,
 }
 
 \f
+/* Returns true iff ATTR is an attribute which needs to be applied at
+   instantiation time rather than template definition time.  */
+
+bool
+is_late_template_attribute (tree attr)
+{
+  tree name = TREE_PURPOSE (attr);
+  if (is_attribute_p ("aligned", name))
+    return true;
+  else
+    return false;
+}
+
+/* ATTR_P is a list of attributes.  Remove any attributes which need to be
+   applied at instantiation time and return them.  */
+
+static tree
+splice_template_attributes (tree *attr_p)
+{
+  tree *p = attr_p;
+  tree late_attrs = NULL_TREE;
+  tree *q = &late_attrs;
+
+  if (!p)
+    return NULL_TREE;
+
+  for (; *p; )
+    {
+      if (is_late_template_attribute (*p))
+       {
+         *q = *p;
+         *p = TREE_CHAIN (*p);
+         q = &TREE_CHAIN (*q);
+         *q = NULL_TREE;
+       }
+      else
+       p = &TREE_CHAIN (*p);
+    }
+
+  return late_attrs;
+}
+
+/* Remove any late attributes from the list in ATTR_P and attach them to
+   DECL_P.  */
+
+static void
+save_template_attributes (tree *attr_p, tree *decl_p)
+{
+  tree late_attrs = splice_template_attributes (attr_p);
+  tree *q;
+
+  if (!late_attrs)
+    return;
+
+  if (DECL_P (*decl_p))
+    q = &DECL_ATTRIBUTES (*decl_p);
+  else
+    q = &TYPE_ATTRIBUTES (*decl_p);
+
+  if (*q)
+    q = &TREE_CHAIN (tree_last (*q));
+  *q = late_attrs;
+}
+
+/* Like decl_attributes, but handle C++ complexity.  */
+
 void
 cplus_decl_attributes (tree *decl, tree attributes, int flags)
 {
   if (*decl == NULL_TREE || *decl == void_type_node
-      || *decl == error_mark_node)
+      || *decl == error_mark_node
+      || attributes == NULL_TREE)
     return;
 
+  if (processing_template_decl)
+    {
+      save_template_attributes (&attributes, decl);
+      if (attributes == NULL_TREE)
+       return;
+    }
+
   if (TREE_CODE (*decl) == TEMPLATE_DECL)
     decl = &DECL_TEMPLATE_RESULT (*decl);
 
index e26958c..d918d86 100644 (file)
@@ -6477,6 +6477,33 @@ can_complete_type_without_circularity (tree type)
     return 1;
 }
 
+/* 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.  */
+
+static void
+apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
+                               tree args, tsubst_flags_t complain, tree in_decl)
+{
+  tree late_attrs = NULL_TREE;
+  tree t;
+
+  if (DECL_P (*decl_p))
+    DECL_ATTRIBUTES (*decl_p) = attributes;
+  else
+    TYPE_ATTRIBUTES (*decl_p) = attributes;
+
+  for (t = attributes; t; t = TREE_CHAIN (t))
+    if (is_late_template_attribute (t))
+      late_attrs = tree_cons
+       (TREE_PURPOSE (t),
+        tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
+                     /*integral_constant_expression_p=*/false),
+        late_attrs);
+
+  cplus_decl_attributes (decl_p, late_attrs, attr_flags);
+}
+
 tree
 instantiate_class_template (tree type)
 {
@@ -6647,6 +6674,9 @@ instantiate_class_template (tree type)
      information.  */
   xref_basetypes (type, base_list);
 
+  apply_late_template_attributes (&type, TYPE_ATTRIBUTES (pattern),
+                                 (int) ATTR_FLAG_TYPE_IN_PLACE,
+                                 args, tf_error, NULL_TREE);
 
   /* Now that our base classes are set up, enter the scope of the
      class, so that name lookups into base classes, etc. will work
@@ -7872,6 +7902,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
              = remove_attribute ("visibility", DECL_ATTRIBUTES (r));
          }
        determine_visibility (r);
+
+       apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+                                       args, complain, in_decl);
       }
       break;
 
@@ -7965,6 +7998,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
             if (!DECL_TEMPLATE_PARM_P (r))
               DECL_ARG_TYPE (r) = type_passed_as (type);
 
+           apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+                                           args, complain, in_decl);
+
             /* Keep track of the first new parameter we
                generate. That's what will be returned to the
                caller.  */
@@ -8007,6 +8043,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        TREE_CHAIN (r) = NULL_TREE;
        if (VOID_TYPE_P (type))
          error ("instantiation of %q+D as type %qT", r, type);
+
+       apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+                                       args, complain, in_decl);
       }
       break;
 
@@ -8201,6 +8240,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
          register_local_specialization (r, t);
 
        TREE_CHAIN (r) = NULL_TREE;
+
+       apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+                                       args, complain, in_decl);
        layout_decl (r, 0);
       }
       break;
diff --git a/gcc/testsuite/g++.dg/ext/tmplattr2.C b/gcc/testsuite/g++.dg/ext/tmplattr2.C
new file mode 100644 (file)
index 0000000..4fd651d
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/17743
+
+template <unsigned Len, unsigned Align>
+struct aligned_storage
+{
+  typedef char type[Len] __attribute__((aligned((Align))));
+};
+
+template<typename T>
+struct X
+{
+  typename aligned_storage<sizeof(T),__alignof(T)>::type data;
+};
+
+template<bool> struct StaticAssert;
+template<> struct StaticAssert<true> {};
+
+StaticAssert<__alignof (X<double>) == __alignof (double)> dummy;