OSDN Git Service

2007-11-05 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl2.c
index 0c0961d..d3ca117 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,21 +979,47 @@ 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);
-  if (is_attribute_p ("aligned", name))
+  tree args = TREE_VALUE (attr);
+  const struct attribute_spec *spec = lookup_attribute_spec (name);
+
+  if (!spec)
+    /* Unknown attribute.  */
+    return false;
+
+  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;
@@ -1013,8 +1030,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);
@@ -1033,12 +1051,25 @@ 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)
     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
@@ -1220,15 +1251,33 @@ coerce_new_type (tree type)
       error ("%<operator new%> must return type %qT", ptr_type_node);
     }
 
-  if (!args || args == void_list_node
-      || !same_type_p (TREE_VALUE (args), size_type_node))
+  if (args && args != void_list_node)
     {
-      e = 2;
-      if (args && args != void_list_node)
-       args = TREE_CHAIN (args);
-      pedwarn ("%<operator new%> takes type %<size_t%> (%qT) "
-              "as first parameter", size_type_node);
+      if (TREE_PURPOSE (args))
+       {
+         /* [basic.stc.dynamic.allocation]
+            
+            The first parameter shall not have an associated default
+            argument.  */
+         error ("the first parameter of %<operator new%> cannot "
+                "have a default argument");
+         /* Throw away the default argument.  */
+         TREE_PURPOSE (args) = NULL_TREE;
+       }
+
+      if (!same_type_p (TREE_VALUE (args), size_type_node))
+       {
+         e = 2;
+         args = TREE_CHAIN (args);
+       }
     }
+  else
+    e = 2;
+
+  if (e == 2)
+    pedwarn ("%<operator new%> takes type %<size_t%> (%qT) "
+            "as first parameter", size_type_node);
+
   switch (e)
   {
     case 2:
@@ -1283,6 +1332,9 @@ coerce_delete_type (tree type)
   return type;
 }
 \f
+/* DECL is a VAR_DECL for a vtable: walk through the entries in the vtable
+   and mark them as needed.  */
+
 static void
 mark_vtable_entries (tree decl)
 {
@@ -1652,6 +1704,7 @@ constrain_visibility (tree decl, int visibility)
       if (!DECL_EXTERN_C_P (decl))
        {
          TREE_PUBLIC (decl) = 0;
+         DECL_ONE_ONLY (decl) = 0;
          DECL_INTERFACE_KNOWN (decl) = 1;
          if (DECL_LANG_SPECIFIC (decl))
            DECL_NOT_REALLY_EXTERN (decl) = 1;
@@ -2974,8 +3027,7 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
    Here we must deal with member pointers.  */
 
 tree
-cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
-                           tree from ATTRIBUTE_UNUSED)
+cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED)
 {
   tree t = *tp;
 
@@ -3447,9 +3499,9 @@ build_offset_ref_call_from_tree (tree fn, tree args)
         parameter.  That must be done before the FN is transformed
         because we depend on the form of FN.  */
       args = build_non_dependent_args (args);
+      object = build_non_dependent_expr (object);
       if (TREE_CODE (fn) == DOTSTAR_EXPR)
        object = build_unary_op (ADDR_EXPR, object, 0);
-      object = build_non_dependent_expr (object);
       args = tree_cons (NULL_TREE, object, args);
       /* Now that the arguments are done, transform FN.  */
       fn = build_non_dependent_expr (fn);