]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR c++/17743
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 18 Sep 2007 22:50:03 +0000 (22:50 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 18 Sep 2007 22:50:03 +0000 (22:50 +0000)
        * pt.c (apply_late_template_attributes): Set processing_template_decl.
        (tsubst_decl) [TYPE_DECL]: Preserve naming typedef, pass
        ATTR_FLAG_TYPE_IN_PLACE.
        (tsubst): Do unqualified lookup to find typedefs from current class.
        [ARRAY_TYPE]: Propagate alignment info.
        * decl2.c (is_late_template_attribute): Only defer handling of
        attribute aligned if the expression is dependent.
        (save_template_attributes): If we're deferring any attributes,
        make this a naming typedef.

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

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

index f62266129af570c679feed2393e143430afe5e61..ebf9b3d95ee7b96da94d6384e76915d130640464 100644 (file)
@@ -1,3 +1,16 @@
+2007-09-18  Jason Merrill  <jason@redhat.com>
+
+       PR c++/17743
+       * pt.c (apply_late_template_attributes): Set processing_template_decl.
+       (tsubst_decl) [TYPE_DECL]: Preserve naming typedef, pass
+       ATTR_FLAG_TYPE_IN_PLACE.
+       (tsubst): Do unqualified lookup to find typedefs from current class.
+       [ARRAY_TYPE]: Propagate alignment info.
+       * decl2.c (is_late_template_attribute): Only defer handling of
+       attribute aligned if the expression is dependent.
+       (save_template_attributes): If we're deferring any attributes,
+       make this a naming typedef.
+
 2007-09-18  Paolo Carlini  <pcarlini@suse.de>
 
        PR c++/33462 (again)
 
 2007-09-16  Nathan Sidwell  <nathan@codesourcery.com>
 
-       cp/
        PR c++/32756
        * call.c (maybe_handle_implicit_object): Set this_p, clear
        rvaluedness_matches_p.
        (compare_ics): Do not compare rvaluedness matching when one of the
        operands is an implicit object.
 
-       testsuite/
-       PR c++/32756
-       * g++.dg/overload/operator3.C: New.
-
 2007-09-14  Jason Merrill  <jason@redhat.com>
 
        PR c++/17743, c++/19163
index 0c0961d90d01013d3e9c5a17d34b13625aa890cb..a8c0f9262a092f83259c198317afc0b6f36289e1 100644 (file)
@@ -992,7 +992,10 @@ bool
 is_late_template_attribute (tree attr)
 {
   tree name = TREE_PURPOSE (attr);
-  if (is_attribute_p ("aligned", name))
+  tree args = TREE_VALUE (attr);
+  if (is_attribute_p ("aligned", name)
+      && args
+      && value_dependent_expression_p (TREE_VALUE (args)))
     return true;
   else
     return false;
@@ -1039,6 +1042,19 @@ save_template_attributes (tree *attr_p, tree *decl_p)
   if (!late_attrs)
     return;
 
+  /* Give this type a name so we know to look it up again at instantiation
+     time.  */
+  if (TREE_CODE (*decl_p) == TYPE_DECL
+      && DECL_ORIGINAL_TYPE (*decl_p) == NULL_TREE)
+    {
+      tree oldt = TREE_TYPE (*decl_p);
+      tree newt = build_variant_type_copy (oldt);
+      DECL_ORIGINAL_TYPE (*decl_p) = oldt;
+      TREE_TYPE (*decl_p) = newt;
+      TYPE_NAME (newt) = *decl_p;
+      TREE_USED (newt) = TREE_USED (*decl_p);
+    }
+
   if (DECL_P (*decl_p))
     q = &DECL_ATTRIBUTES (*decl_p);
   else
index d918d86a2f39e59ce163cbef4c095528921b0aa3..e54bc5fba1ed5ad0d57ed482a29d50cae2768daa 100644 (file)
@@ -6493,6 +6493,10 @@ 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))
       late_attrs = tree_cons
@@ -6501,6 +6505,8 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
                      /*integral_constant_expression_p=*/false),
         late_attrs);
 
+  --processing_template_decl;
+
   cplus_decl_attributes (decl_p, late_attrs, attr_flags);
 }
 
@@ -8223,6 +8229,16 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
              }
            determine_visibility (r);
          }
+       /* Preserve a typedef that names a type.  */
+       else if (TREE_CODE (r) == TYPE_DECL
+                && DECL_ORIGINAL_TYPE (t)
+                && type != error_mark_node)
+         {
+           DECL_ORIGINAL_TYPE (r) = tsubst (DECL_ORIGINAL_TYPE (t),
+                                            args, complain, in_decl);
+           TREE_TYPE (r) = type = build_variant_type_copy (type);
+           TYPE_NAME (type) = r;
+         }
 
        if (!local_p)
          {
@@ -8241,7 +8257,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 
        TREE_CHAIN (r) = NULL_TREE;
 
-       apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+       apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
+                                       (int) ATTR_FLAG_TYPE_IN_PLACE,
                                        args, complain, in_decl);
        layout_decl (r, 0);
       }
@@ -8534,6 +8551,43 @@ 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.  */
+  if (TYPE_P (t)
+      && TYPE_NAME (t)
+      && !IS_AGGR_TYPE (t)
+      && current_class_type
+      && CLASSTYPE_TEMPLATE_INFO (current_class_type))
+    {
+      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 (type
       && TREE_CODE (t) != TYPENAME_TYPE
       && TREE_CODE (t) != IDENTIFIER_NODE
@@ -9013,6 +9067,13 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          }
 
        r = build_cplus_array_type (type, domain);
+
+       if (TYPE_USER_ALIGN (t))
+         {
+           TYPE_ALIGN (r) = TYPE_ALIGN (t);
+           TYPE_USER_ALIGN (r) = 1;
+         }
+
        return r;
       }
 
diff --git a/gcc/testsuite/g++.dg/ext/tmplattr3.C b/gcc/testsuite/g++.dg/ext/tmplattr3.C
new file mode 100644 (file)
index 0000000..51f5daf
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/17743
+
+template<typename T>
+struct X {
+  typedef char layout_type[sizeof(T)]
+  __attribute ((aligned(__alignof(double))));
+  layout_type data;
+};
+
+template<typename T>
+struct Y {
+  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;