This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: C++ PATCH for c++/17743, 19163 (attribute align in templates)


And here's the patch for using a typedef from the same class. I didn't need to mess around with dependency, I just make sure that if a type comes from a typedef in the same class, we look up the new type of that typedef rather than assuming we can tsubst the type directly.

The code for finding the new typedef really strikes me as ugly, so any alternative suggestions would be welcome. It seems like there ought to be an easier way. But I'm pretty sure it's correct.

One thing that struck me as odd about our existing handling of typedefs: We don't have any indication that a type comes from a typedef unless there's something else different about the type (like an attribute). I suppose that reduces memory consumption, but also probably makes error messages less helpful.

Tested x86_64-pc-linux-gnu, applied to trunk.

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.

Index: cp/pt.c
===================================================================
*** cp/pt.c	(revision 128577)
--- cp/pt.c	(working copy)
*************** apply_late_template_attributes (tree *de
*** 6493,6498 ****
--- 6493,6502 ----
    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
*************** apply_late_template_attributes (tree *de
*** 6501,6506 ****
--- 6505,6512 ----
  		      /*integral_constant_expression_p=*/false),
  	 late_attrs);
  
+   --processing_template_decl;
+ 
    cplus_decl_attributes (decl_p, late_attrs, attr_flags);
  }
  
*************** tsubst_decl (tree t, tree args, tsubst_f
*** 8223,8228 ****
--- 8229,8244 ----
  	      }
  	    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)
  	  {
*************** tsubst_decl (tree t, tree args, tsubst_f
*** 8241,8247 ****
  
  	TREE_CHAIN (r) = NULL_TREE;
  
! 	apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
  					args, complain, in_decl);
  	layout_decl (r, 0);
        }
--- 8257,8264 ----
  
  	TREE_CHAIN (r) = NULL_TREE;
  
! 	apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
! 					(int) ATTR_FLAG_TYPE_IN_PLACE,
  					args, complain, in_decl);
  	layout_decl (r, 0);
        }
*************** tsubst (tree t, tree args, tsubst_flags_
*** 8534,8539 ****
--- 8551,8593 ----
  
    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
*************** tsubst (tree t, tree args, tsubst_flags_
*** 9013,9018 ****
--- 9067,9079 ----
  	  }
  
  	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;
        }
  
Index: cp/decl2.c
===================================================================
*** cp/decl2.c	(revision 128577)
--- cp/decl2.c	(working copy)
*************** bool
*** 992,998 ****
  is_late_template_attribute (tree attr)
  {
    tree name = TREE_PURPOSE (attr);
!   if (is_attribute_p ("aligned", name))
      return true;
    else
      return false;
--- 992,1001 ----
  is_late_template_attribute (tree attr)
  {
    tree name = TREE_PURPOSE (attr);
!   tree args = TREE_VALUE (attr);
!   if (is_attribute_p ("aligned", name)
!       && args
!       && value_dependent_expression_p (TREE_VALUE (args)))
      return true;
    else
      return false;
*************** save_template_attributes (tree *attr_p, 
*** 1039,1044 ****
--- 1042,1060 ----
    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: testsuite/g++.dg/ext/tmplattr3.C
===================================================================
*** testsuite/g++.dg/ext/tmplattr3.C	(revision 0)
--- testsuite/g++.dg/ext/tmplattr3.C	(revision 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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]