OSDN Git Service

PR c++/19407
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 23 Sep 2007 02:36:34 +0000 (02:36 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 23 Sep 2007 02:36:34 +0000 (02:36 +0000)
        * cp/cp-tree.h (ATTR_IS_DEPENDENT): New macro.
        (MAYBE_TAGGED_TYPE_P): Remove.
        * cp/pt.c (apply_late_template_attributes): Check ATTR_IS_DEPENDENT
        instead of calling is_late_template_attribute again.
        (tsubst_decl) [TYPE_DECL]: Just check if the name is the tag.
        (tsubst): A typedef is a TYPE_NAME != TYPE_MAIN_DECL.
        Don't crash on typedefs from non-template classes.
        * cp/decl2.c (grokfield): Don't sorry about attrs on template parms.
        (is_late_template_attribute): All attributes applied to template
        parms or typename types are dependent.  Static, take decl.
        (splice_template_attributes): Pass decl through.
        (save_template_attributes): Likewise.
        * attribs.c (lookup_attribute_spec): Split out...
        (decl_attributes): From here.
        * tree.h: Declare it.

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

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

index 8593403..2de9c65 100644 (file)
@@ -1,3 +1,10 @@
+2007-09-22  Jason Merrill  <jason@redhat.com>
+
+       PR c++/19407
+       * attribs.c (lookup_attribute_spec): Split out...
+       (decl_attributes): From here.
+       * tree.h: Declare it.
+
 2007-09-22  Richard Sandiford  <rsandifo@nildram.co.uk>
 
        * doc/sourcebuild.texi: Document dg-add-options mips16_attribute.
index feb1c30..31b92ca 100644 (file)
@@ -195,6 +195,20 @@ init_attributes (void)
       }
   attributes_initialized = true;
 }
+
+/* Return the spec for the attribute named NAME.  */
+
+const struct attribute_spec *
+lookup_attribute_spec (tree name)
+{
+  struct substring attr;
+
+  attr.str = IDENTIFIER_POINTER (name);
+  attr.length = IDENTIFIER_LENGTH (name);
+  extract_attribute_substring (&attr);
+  return htab_find_with_hash (attribute_hash, &attr,
+                             substring_hash (attr.str, attr.length));
+}
 \f
 /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
    which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
@@ -221,16 +235,9 @@ decl_attributes (tree *node, tree attributes, int flags)
       tree name = TREE_PURPOSE (a);
       tree args = TREE_VALUE (a);
       tree *anode = node;
-      const struct attribute_spec *spec = NULL;
+      const struct attribute_spec *spec = lookup_attribute_spec (name);
       bool no_add_attrs = 0;
       tree fn_ptr_tmp = NULL_TREE;
-      struct substring attr;
-
-      attr.str = IDENTIFIER_POINTER (name);
-      attr.length = IDENTIFIER_LENGTH (name);
-      extract_attribute_substring (&attr);
-      spec = htab_find_with_hash (attribute_hash, &attr,
-                                 substring_hash (attr.str, attr.length));
 
       if (spec == NULL)
        {
index 5310aa9..4c4e584 100644 (file)
@@ -1,3 +1,19 @@
+2007-09-22  Jason Merrill  <jason@redhat.com>
+
+       PR c++/19407
+       * cp-tree.h (ATTR_IS_DEPENDENT): New macro.
+       (MAYBE_TAGGED_TYPE_P): Remove.
+       * pt.c (apply_late_template_attributes): Check ATTR_IS_DEPENDENT
+       instead of calling is_late_template_attribute again.
+       (tsubst_decl) [TYPE_DECL]: Just check if the name is the tag.
+       (tsubst): A typedef is a TYPE_NAME != TYPE_MAIN_DECL.
+       Don't crash on typedefs from non-template classes.
+       * decl2.c (grokfield): Don't sorry about attrs on template parms.
+       (is_late_template_attribute): All attributes applied to template
+       parms or typename types are dependent.  Static.
+       (splice_template_attributes): Pass decl through.
+       (save_template_attributes): Likewise.
+
 2007-09-20  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/33496
index 1ddf884..fbe1bcc 100644 (file)
@@ -58,6 +58,7 @@ struct diagnostic_context;
       TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
       TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX)
       TYPE_REF_IS_RVALUE (in REFERENCE_TYPE)
+      ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute)
    1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -988,10 +989,6 @@ enum languages { lang_c, lang_cplusplus, lang_java };
   ((T) == RECORD_TYPE || (T) == UNION_TYPE)
 #define TAGGED_TYPE_P(T) \
   (CLASS_TYPE_P (T) || TREE_CODE (T) == ENUMERAL_TYPE)
-/* A tagged type or a dependent type that might be a tagged type when
-   instantiated.  Like IS_AGGR_TYPE, but include enums as well.  */
-#define MAYBE_TAGGED_TYPE_P(T) \
-  (IS_AGGR_TYPE(T) || TREE_CODE (T) == ENUMERAL_TYPE)
 #define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T)
 
 /* True if this a "Java" type, defined in 'extern "Java"'.  */
@@ -2134,6 +2131,10 @@ struct lang_decl GTY(())
    directives  */
 #define TREE_INDIRECT_USING(NODE) (TREE_LIST_CHECK (NODE)->base.lang_flag_0)
 
+/* In a TREE_LIST in an attribute list, indicates that the attribute
+   must be applied at instantiation time.  */
+#define ATTR_IS_DEPENDENT(NODE) (TREE_LIST_CHECK (NODE)->base.lang_flag_0)
+
 extern tree decl_shadowed_for_var_lookup (tree);
 extern void decl_shadowed_for_var_insert (tree, tree);
 
@@ -4280,7 +4281,6 @@ 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 a8c0f92..d581942 100644 (file)
@@ -800,16 +800,7 @@ grokfield (const cp_declarator *declarator,
        value = push_template_decl (value);
 
       if (attrlist)
-       {
-         /* Avoid storing attributes in template parameters:
-            tsubst is not ready to handle them.  */
-         tree type = TREE_TYPE (value);
-         if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
-             || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
-           sorry ("applying attributes to template parameters is not implemented");
-         else
-           cplus_decl_attributes (&value, attrlist, 0);
-       }
+       cplus_decl_attributes (&value, attrlist, 0);
 
       return value;
     }
@@ -988,24 +979,43 @@ grokbitfield (const cp_declarator *declarator,
 /* 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)
+static bool
+is_late_template_attribute (tree attr, tree decl)
 {
   tree name = TREE_PURPOSE (attr);
   tree args = TREE_VALUE (attr);
+  const struct attribute_spec *spec = lookup_attribute_spec (name);
+
   if (is_attribute_p ("aligned", name)
       && args
       && value_dependent_expression_p (TREE_VALUE (args)))
+    /* Can't apply this until we know the desired alignment.  */
     return true;
+  else if (TREE_CODE (decl) == TYPE_DECL || spec->type_required)
+    {
+      tree type = TYPE_P (decl) ? decl : TREE_TYPE (decl);
+
+      /* We can't apply any attributes to a completely unknown type until
+        instantiation time.  */
+      enum tree_code code = TREE_CODE (type);
+      if (code == TEMPLATE_TYPE_PARM
+         || code == BOUND_TEMPLATE_TEMPLATE_PARM
+         || code == TYPENAME_TYPE)
+       return true;
+      else
+       return false;
+    }
   else
     return false;
 }
 
 /* ATTR_P is a list of attributes.  Remove any attributes which need to be
-   applied at instantiation time and return them.  */
+   applied at instantiation time and return them.  If IS_DEPENDENT is true,
+   the declaration itself is dependent, so all attributes should be applied
+   at instantiation time.  */
 
 static tree
-splice_template_attributes (tree *attr_p)
+splice_template_attributes (tree *attr_p, tree decl)
 {
   tree *p = attr_p;
   tree late_attrs = NULL_TREE;
@@ -1016,8 +1026,9 @@ splice_template_attributes (tree *attr_p)
 
   for (; *p; )
     {
-      if (is_late_template_attribute (*p))
+      if (is_late_template_attribute (*p, decl))
        {
+         ATTR_IS_DEPENDENT (*p) = 1;
          *q = *p;
          *p = TREE_CHAIN (*p);
          q = &TREE_CHAIN (*q);
@@ -1036,7 +1047,7 @@ splice_template_attributes (tree *attr_p)
 static void
 save_template_attributes (tree *attr_p, tree *decl_p)
 {
-  tree late_attrs = splice_template_attributes (attr_p);
+  tree late_attrs = splice_template_attributes (attr_p, *decl_p);
   tree *q;
 
   if (!late_attrs)
index 8accea4..c9ec370 100644 (file)
@@ -6494,20 +6494,14 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
   else
     TYPE_ATTRIBUTES (*decl_p) = attributes;
 
-  /* Set processing_template_decl so we can check for dependent
-     expressions.  */
-  ++processing_template_decl;
-
   for (t = attributes; t; t = TREE_CHAIN (t))
-    if (is_late_template_attribute (t))
+    if (ATTR_IS_DEPENDENT (t))
       late_attrs = tree_cons
        (TREE_PURPOSE (t),
         tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
                      /*integral_constant_expression_p=*/false),
         late_attrs);
 
-  --processing_template_decl;
-
   cplus_decl_attributes (decl_p, late_attrs, attr_flags);
 }
 
@@ -8085,20 +8079,16 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        bool local_p;
 
        if (TREE_CODE (t) == TYPE_DECL
-           && MAYBE_TAGGED_TYPE_P (TREE_TYPE (t)))
+           && t == TYPE_MAIN_DECL (TREE_TYPE (t)))
          {
+           /* If this is the canonical decl, we don't have to
+              mess with instantiations, and often we can't (for
+              typename, template type parms and such).  Note that
+              TYPE_NAME is not correct for the above test if
+              we've copied the type for a typedef.  */
            type = tsubst (TREE_TYPE (t), args, complain, in_decl);
-           if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
-               || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
-             {
-               /* If this is the canonical decl, we don't have to
-                  mess with instantiations, and often we can't (for
-                  typename, template type parms and such).  Note that
-                  TYPE_NAME is not correct for the above test if
-                  we've copied the type for a typedef.  */
-               r = TYPE_NAME (type);
-               break;
-             }
+           r = TYPE_NAME (type);
+           break;
          }
 
        /* Check to see if we already have the specialization we
@@ -8555,16 +8545,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   gcc_assert (type != unknown_type_node);
 
   /* Reuse typedefs.  We need to do this to handle dependent attributes,
-     specifically attribute aligned.  */
+     such as attribute aligned.  */
   if (TYPE_P (t)
       && TYPE_NAME (t)
-      && !MAYBE_TAGGED_TYPE_P (t)
-      && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
-      && TREE_CODE (t) != UNBOUND_CLASS_TEMPLATE)
+      && TYPE_NAME (t) != TYPE_MAIN_DECL (t))
     {
       tree decl = TYPE_NAME (t);
       
-      if (DECL_CLASS_SCOPE_P (decl))
+      if (DECL_CLASS_SCOPE_P (decl)
+         && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl)))
        {
          tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
          tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
index e46e8ae..25b27f3 100644 (file)
@@ -7,8 +7,8 @@ template <typename T>
 struct BVector
 {
   typedef T T2;
-  typedef T value_type __attribute__ ((aligned(8)));    // { dg-bogus "attribute" "attribute" { xfail *-*-* } }
-  typedef T2 value_type2 __attribute__ ((aligned(8)));  // { dg-bogus "attribute" "attribute" { xfail *-*-* } }
+  typedef T value_type __attribute__ ((aligned(8)));    // { dg-bogus "attribute" "attribute" }
+  typedef T2 value_type2 __attribute__ ((aligned(8)));  // { dg-bogus "attribute" "attribute" }
   value_type v;
 };
 BVector<int> m;
@@ -16,7 +16,7 @@ BVector<int> m;
 template <template <class> class T>
 struct BV2
 {
-  typedef T<float> value_type __attribute__((aligned(8))); // { dg-bogus "attribute" "attribute" { xfail *-*-* } }
+  typedef T<float> value_type __attribute__((aligned(8))); // { dg-bogus "attribute" "attribute" }
   value_type v;
 };
 BV2<BVector> m2;
diff --git a/gcc/testsuite/g++.dg/ext/tmplattr5.C b/gcc/testsuite/g++.dg/ext/tmplattr5.C
new file mode 100644 (file)
index 0000000..30138d4
--- /dev/null
@@ -0,0 +1,33 @@
+// PR c++/19407
+// { dg-do run }
+
+typedef float global_vector_type __attribute__((vector_size(16)));
+
+template <class T> struct A
+{
+  typedef T type;
+};
+
+template < typename Val > struct S
+{
+  typedef typename A<Val>::type vector_type __attribute__((vector_size(16)));
+  typedef Val vector_type2 __attribute__((vector_size(16)));
+  int pr_size() { return sizeof(vector_type); }
+  int pr_size2() { return sizeof(vector_type2); }
+};
+
+int main()
+{
+  if (sizeof (S<float>::vector_type) != sizeof (global_vector_type))
+    return 1;
+  if (sizeof (S<float>::vector_type2) != sizeof (global_vector_type))
+    return 2;
+
+  S<float> x;
+  if (x.pr_size() != sizeof (global_vector_type))
+    return 3;
+  if (x.pr_size2() != sizeof (global_vector_type))
+    return 4;
+  
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef7.C b/gcc/testsuite/g++.dg/template/typedef7.C
new file mode 100644 (file)
index 0000000..2d39c90
--- /dev/null
@@ -0,0 +1,15 @@
+// An intermediate version of the fix for c++/19407 broke this example.
+
+struct A
+{
+  typedef struct { int i; } S;
+};
+
+template <class T>
+struct B: public A
+{
+  template <class U>
+  static S f ();
+};
+
+template struct B<int>;
index d7ca0b2..e893dea 100644 (file)
@@ -5002,6 +5002,8 @@ extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, const_tree);
 
 /* In attribs.c.  */
 
+extern const struct attribute_spec *lookup_attribute_spec (tree);
+
 /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
    which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
    it should be modified in place; if a TYPE, a copy should be created