]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR c++/7586
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 20 Sep 2007 14:13:00 +0000 (14:13 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 20 Sep 2007 14:13:00 +0000 (14:13 +0000)
        * pt.c (tsubst): Handle typedefs by looking for the specialization.
        (retrieve_specialization): Only tagged types use
        DECL_TEMPLATE_INSTANTIATIONS.
        (instantiate_class_template): Push nested classes too.
        (tsubst_decl) [TYPE_DECL]: Only check for canonical decl for
        tagged types.
        * cp-tree.h (MAYBE_TAGGED_TYPE_P): New macro.
        * init.c (is_aggr_type): Remove redundant tests.
        * class.c (push_nested_class): Use CLASS_TYPE_P.

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

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

index ebcd865e9b37fdeb801a2db998bd667f4176f12e..efad3f3e59ae9b084e3ced2e43200db565797ec3 100644 (file)
@@ -1,3 +1,16 @@
+2007-09-19  Jason Merrill  <jason@redhat.com>
+
+       PR c++/7586
+       * pt.c (tsubst): Handle typedefs by looking for the specialization.
+       (retrieve_specialization): Only tagged types use 
+       DECL_TEMPLATE_INSTANTIATIONS.
+       (instantiate_class_template): Push nested classes too.
+       (tsubst_decl) [TYPE_DECL]: Only check for canonical decl for
+       tagged types.
+       * cp-tree.h (MAYBE_TAGGED_TYPE_P): New macro.
+       * init.c (is_aggr_type): Remove redundant tests.
+       * class.c (push_nested_class): Use CLASS_TYPE_P.
+
 2007-09-20  Paolo Carlini  <pcarlini@suse.de>
 
        PR c++/33459
index 9e0502fd1fb27b4e2d4a5ce63d87d2fcae337da0..5c3e0548044fd3f863e4a3ab5b3ff68af7aab148 100644 (file)
@@ -5645,21 +5645,13 @@ currently_open_derived_class (tree t)
 void
 push_nested_class (tree type)
 {
-  tree context;
-
   /* A namespace might be passed in error cases, like A::B:C.  */
   if (type == NULL_TREE
-      || type == error_mark_node
-      || TREE_CODE (type) == NAMESPACE_DECL
-      || ! IS_AGGR_TYPE (type)
-      || TREE_CODE (type) == TEMPLATE_TYPE_PARM
-      || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+      || !CLASS_TYPE_P (type))
     return;
 
-  context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
+  push_nested_class (DECL_CONTEXT (TYPE_MAIN_DECL (type)));
 
-  if (context && CLASS_TYPE_P (context))
-    push_nested_class (context);
   pushclass (type);
 }
 
index 4f1e88c931e5827fbec67854019c478e61f4844b..1ddf88492c6495170cb319e14b374482d5170d1f 100644 (file)
@@ -988,6 +988,10 @@ 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"'.  */
index 247879cc5a03d29e39d4387b140eb4b364bd7326..c5c17b1a9e15a8928a9651b490be19fcb630a2b2 100644 (file)
@@ -1281,9 +1281,7 @@ is_aggr_type (tree type, int or_else)
   if (type == error_mark_node)
     return 0;
 
-  if (! IS_AGGR_TYPE (type)
-      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
-      && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM)
+  if (! IS_AGGR_TYPE (type))
     {
       if (or_else)
        error ("%qT is not an aggregate type", type);
index e54bc5fba1ed5ad0d57ed482a29d50cae2768daa..17acbaf220d3e859a26864df53bf15318e840de6 100644 (file)
@@ -930,7 +930,8 @@ retrieve_specialization (tree tmpl, tree args,
         DECL_TEMPLATE_INSTANTIATIONS list; other templates use the
         DECL_TEMPLATE_SPECIALIZATIONS list.  */
       if (!class_specializations_p
-         && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL)
+         && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL
+         && TAGGED_TYPE_P (TREE_TYPE (tmpl)))
        sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
       else
        sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
@@ -6688,8 +6689,8 @@ instantiate_class_template (tree type)
      class, so that name lookups into base classes, etc. will work
      correctly.  This is precisely analogous to what we do in
      begin_class_definition when defining an ordinary non-template
-     class.  */
-  pushclass (type);
+     class, except we also need to push the enclosing classes.  */
+  push_nested_class (type);
 
   /* Now members are processed in the order of declaration.  */
   for (member = CLASSTYPE_DECL_LIST (pattern);
@@ -6986,7 +6987,7 @@ instantiate_class_template (tree type)
          && DECL_TEMPLATE_INFO (t))
        tsubst_default_arguments (t);
 
-  popclass ();
+  pop_nested_class ();
   pop_from_top_level ();
   pop_deferring_access_checks ();
   pop_tinst_level ();
@@ -8083,7 +8084,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        tree type = NULL_TREE;
        bool local_p;
 
-       if (TREE_CODE (t) == TYPE_DECL)
+       if (TREE_CODE (t) == TYPE_DECL
+           && MAYBE_TAGGED_TYPE_P (TREE_TYPE (t)))
          {
            type = tsubst (TREE_TYPE (t), args, complain, in_decl);
            if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
@@ -8158,6 +8160,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 
        /* Create a new node for the specialization we need.  */
        r = copy_decl (t);
+       if (type == NULL_TREE)
+         type = tsubst (TREE_TYPE (t), args, complain, in_decl);
        if (TREE_CODE (r) == VAR_DECL)
          {
            /* Even if the original location is out of scope, the
@@ -8165,7 +8169,6 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            DECL_DEAD_FOR_LOCAL (r) = 0;
            DECL_INITIALIZED_P (r) = 0;
            DECL_TEMPLATE_INSTANTIATED (r) = 0;
-           type = tsubst (TREE_TYPE (t), args, complain, in_decl);
            if (type == error_mark_node)
              return error_mark_node;
            if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -8551,41 +8554,36 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
   gcc_assert (type != unknown_type_node);
 
-  /* Reuse typedefs.  This is a rather complicated way to check whether the
-     type is a typedef from the same class template as the current scope,
-     but I can't think of a better one.
-
-     We need to do this to handle dependent attributes, specifically
-     attribute aligned.  */
+  /* Reuse typedefs.  We need to do this to handle dependent attributes,
+     specifically attribute aligned.  */
   if (TYPE_P (t)
       && TYPE_NAME (t)
-      && !IS_AGGR_TYPE (t)
-      && current_class_type
-      && CLASSTYPE_TEMPLATE_INFO (current_class_type))
+      && !MAYBE_TAGGED_TYPE_P (t)
+      && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
+      && TREE_CODE (t) != UNBOUND_CLASS_TEMPLATE)
     {
       tree decl = TYPE_NAME (t);
-      tree context = DECL_CONTEXT (decl);
-      if (context
-         && CLASS_TYPE_P (context)
-         && CLASSTYPE_TEMPLATE_INFO (context)
-         && (CLASSTYPE_TI_TEMPLATE (context)
-             == CLASSTYPE_TI_TEMPLATE (current_class_type))
-         && (tsubst_aggr_type (context, args, complain, in_decl,
-                               /*entering_scope=*/0)
-             == current_class_type))
-           {
-             r = lookup_name (DECL_NAME (decl));
-             if (r && TREE_CODE (r) == TYPE_DECL
-                 && DECL_CONTEXT (r) == current_class_type)
-               {
-                 r = TREE_TYPE (r);
-                 r = cp_build_qualified_type_real
-                   (r, cp_type_quals (t) | cp_type_quals (r),
-                    complain | tf_ignore_bad_quals);
-                 return r;
-                 /* Else we're instantiating the typedef, so fall through.  */
-               }
-           }
+      
+      if (DECL_CLASS_SCOPE_P (decl))
+       {
+         tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
+         tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
+         r = retrieve_specialization (tmpl, gen_args, false);
+       }
+      else if (DECL_FUNCTION_SCOPE_P (decl))
+       r = retrieve_local_specialization (decl);
+      else
+       r = NULL_TREE;
+       
+      if (r)
+       {
+         r = TREE_TYPE (r);
+         r = cp_build_qualified_type_real
+           (r, cp_type_quals (t) | cp_type_quals (r),
+            complain | tf_ignore_bad_quals);
+         return r;
+       }
+      /* Else we must be instantiating the typedef, so fall through.  */
     }
 
   if (type
index 51f5daf19b1576941737312cf46bd0a725a3a4cb..f8d3c162072f238d67bf327969bc977469465354 100644 (file)
@@ -14,8 +14,29 @@ struct Y {
   layout_type data;
 };
 
+template<typename T>
+struct Z {
+  typedef char layout_type[sizeof(T)]
+  __attribute ((aligned(__alignof(T))));
+  struct Z2 {
+    layout_type data;
+  } in;
+};
+
+template<typename T>
+struct A;
+
+template <typename T>
+struct A<T*> {
+  typedef char layout_type[sizeof(T)]
+  __attribute ((aligned(__alignof(T))));
+  layout_type data;
+};
+
 template<bool> struct StaticAssert;
 template<> struct StaticAssert<true> {};
 
 StaticAssert<__alignof(X<double>) == __alignof(double)> d1;
 StaticAssert<__alignof(Y<double>) == __alignof(double)> d2;
+StaticAssert<__alignof(Z<double>) == __alignof(double)> d3;
+StaticAssert<__alignof(A<double*>) == __alignof(double)> d4;
diff --git a/gcc/testsuite/g++.dg/ext/tmplattr4.C b/gcc/testsuite/g++.dg/ext/tmplattr4.C
new file mode 100644 (file)
index 0000000..3d5c6b7
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/7586
+// { dg-do run }
+
+template<typename T>
+int f()
+{
+  typedef unsigned char type[sizeof (T)]
+    __attribute((aligned(__alignof(T))));
+
+  return __alignof (type);
+}
+
+int main()
+{
+  if (f<int>() == __alignof (int))
+    return 0;
+  else
+    return 1;
+}