OSDN Git Service

PR c++/34238
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl2.c
index a1664b8..97b3ee0 100644 (file)
@@ -1,13 +1,13 @@
 /* Process declarations and variables for C++ compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
 /* Process declarations and variables for C++ compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007  Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -16,9 +16,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* Process declarations and symbol lookup for C++ front end.
 
 
 /* Process declarations and symbol lookup for C++ front end.
@@ -136,6 +135,12 @@ cp_build_parm_decl (tree name, tree type)
      sees templates.  */
   if (!processing_template_decl)
     DECL_ARG_TYPE (parm) = type_passed_as (type);
      sees templates.  */
   if (!processing_template_decl)
     DECL_ARG_TYPE (parm) = type_passed_as (type);
+
+  /* If the type is a pack expansion, then we have a function
+     parameter pack. */
+  if (type && TREE_CODE (type) == TYPE_PACK_EXPANSION)
+    FUNCTION_PARAMETER_PACK_P (parm) = 1;
+
   return parm;
 }
 
   return parm;
 }
 
@@ -535,8 +540,8 @@ check_java_method (tree method)
    TEMPLATE_DECL, it can be NULL since the parameters can be extracted
    from the declaration. If the function is not a function template, it
    must be NULL.
    TEMPLATE_DECL, it can be NULL since the parameters can be extracted
    from the declaration. If the function is not a function template, it
    must be NULL.
-   It returns the original declaration for the function, or NULL_TREE
-   if no declaration was found (and an error was emitted).  */
+   It returns the original declaration for the function, NULL_TREE if
+   no declaration was found, error_mark_node if an error was emitted.  */
 
 tree
 check_classfn (tree ctype, tree function, tree template_parms)
 
 tree
 check_classfn (tree ctype, tree function, tree template_parms)
@@ -672,16 +677,9 @@ check_classfn (tree ctype, tree function, tree template_parms)
     error ("no %q#D member function declared in class %qT",
           function, ctype);
 
     error ("no %q#D member function declared in class %qT",
           function, ctype);
 
-  /* If we did not find the method in the class, add it to avoid
-     spurious errors (unless the CTYPE is not yet defined, in which
-     case we'll only confuse ourselves when the function is declared
-     properly within the class.  */
-  if (COMPLETE_TYPE_P (ctype))
-    add_method (ctype, function, NULL_TREE);
-  
   if (pushed_scope)
     pop_scope (pushed_scope);
   if (pushed_scope)
     pop_scope (pushed_scope);
-  return NULL_TREE;
+  return error_mark_node;
 }
 
 /* DECL is a function with vague linkage.  Remember it so that at the
 }
 
 /* DECL is a function with vague linkage.  Remember it so that at the
@@ -802,16 +800,7 @@ grokfield (const cp_declarator *declarator,
        value = push_template_decl (value);
 
       if (attrlist)
        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;
     }
 
       return value;
     }
@@ -987,13 +976,127 @@ grokbitfield (const cp_declarator *declarator,
 }
 
 \f
 }
 
 \f
+/* Returns true iff ATTR is an attribute which needs to be applied at
+   instantiation time rather than template definition time.  */
+
+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 (!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.  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, tree decl)
+{
+  tree *p = attr_p;
+  tree late_attrs = NULL_TREE;
+  tree *q = &late_attrs;
+
+  if (!p)
+    return NULL_TREE;
+
+  for (; *p; )
+    {
+      if (is_late_template_attribute (*p, decl))
+       {
+         ATTR_IS_DEPENDENT (*p) = 1;
+         *q = *p;
+         *p = TREE_CHAIN (*p);
+         q = &TREE_CHAIN (*q);
+         *q = NULL_TREE;
+       }
+      else
+       p = &TREE_CHAIN (*p);
+    }
+
+  return late_attrs;
+}
+
+/* Remove any late attributes from the list in ATTR_P and attach them to
+   DECL_P.  */
+
+static void
+save_template_attributes (tree *attr_p, tree *decl_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
+    q = &TYPE_ATTRIBUTES (*decl_p);
+
+  if (*q)
+    q = &TREE_CHAIN (tree_last (*q));
+  *q = late_attrs;
+}
+
+/* Like decl_attributes, but handle C++ complexity.  */
+
 void
 cplus_decl_attributes (tree *decl, tree attributes, int flags)
 {
   if (*decl == NULL_TREE || *decl == void_type_node
 void
 cplus_decl_attributes (tree *decl, tree attributes, int flags)
 {
   if (*decl == NULL_TREE || *decl == void_type_node
-      || *decl == error_mark_node)
+      || *decl == error_mark_node
+      || attributes == NULL_TREE)
     return;
 
     return;
 
+  if (processing_template_decl)
+    {
+      save_template_attributes (&attributes, decl);
+      if (attributes == NULL_TREE)
+       return;
+    }
+
   if (TREE_CODE (*decl) == TEMPLATE_DECL)
     decl = &DECL_TEMPLATE_RESULT (*decl);
 
   if (TREE_CODE (*decl) == TEMPLATE_DECL)
     decl = &DECL_TEMPLATE_RESULT (*decl);
 
@@ -1051,6 +1154,7 @@ build_anon_union_vars (tree type, tree object)
          tree base;
 
          decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
          tree base;
 
          decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
+         DECL_ANON_UNION_VAR_P (decl) = 1;
 
          base = get_base_address (object);
          TREE_PUBLIC (decl) = TREE_PUBLIC (base);
 
          base = get_base_address (object);
          TREE_PUBLIC (decl) = TREE_PUBLIC (base);
@@ -1147,15 +1251,33 @@ coerce_new_type (tree type)
       error ("%<operator new%> must return type %qT", ptr_type_node);
     }
 
       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:
   switch (e)
   {
     case 2:
@@ -1210,6 +1332,9 @@ coerce_delete_type (tree type)
   return type;
 }
 \f
   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)
 {
 static void
 mark_vtable_entries (tree decl)
 {
@@ -1562,7 +1687,7 @@ static int
 type_visibility (tree type)
 {
   int vis = VISIBILITY_DEFAULT;
 type_visibility (tree type)
 {
   int vis = VISIBILITY_DEFAULT;
-  walk_tree_without_duplicates (&type, min_vis_r, &vis);
+  cp_walk_tree_without_duplicates (&type, min_vis_r, &vis);
   return vis;
 }
 
   return vis;
 }
 
@@ -1579,6 +1704,7 @@ constrain_visibility (tree decl, int visibility)
       if (!DECL_EXTERN_C_P (decl))
        {
          TREE_PUBLIC (decl) = 0;
       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;
          DECL_INTERFACE_KNOWN (decl) = 1;
          if (DECL_LANG_SPECIFIC (decl))
            DECL_NOT_REALLY_EXTERN (decl) = 1;
@@ -1677,25 +1803,10 @@ determine_visibility (tree decl)
   else
     use_template = 0;
 
   else
     use_template = 0;
 
-  /* Anything that is exported must have default visibility.  */
-  if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
-      && lookup_attribute ("dllexport",
-                          TREE_CODE (decl) == TYPE_DECL
-                          ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
-                          : DECL_ATTRIBUTES (decl)))
-    {
-      DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
-      DECL_VISIBILITY_SPECIFIED (decl) = 1;
-    }
-
   /* If DECL is a member of a class, visibility specifiers on the
      class can influence the visibility of the DECL.  */
   if (DECL_CLASS_SCOPE_P (decl))
     class_type = DECL_CONTEXT (decl);
   /* If DECL is a member of a class, visibility specifiers on the
      class can influence the visibility of the DECL.  */
   if (DECL_CLASS_SCOPE_P (decl))
     class_type = DECL_CONTEXT (decl);
-  else if (TREE_CODE (decl) == VAR_DECL
-          && DECL_TINFO_P (decl)
-          && CLASS_TYPE_P (TREE_TYPE (DECL_NAME (decl))))
-    class_type = TREE_TYPE (DECL_NAME (decl));
   else
     {
       /* Not a class member.  */
   else
     {
       /* Not a class member.  */
@@ -1724,6 +1835,19 @@ determine_visibility (tree decl)
             but have no TEMPLATE_INFO, so don't try to check it.  */
          use_template = 0;
        }
             but have no TEMPLATE_INFO, so don't try to check it.  */
          use_template = 0;
        }
+      else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl)
+              && flag_visibility_ms_compat)
+       {
+         /* Under -fvisibility-ms-compat, types are visible by default,
+            even though their contents aren't.  */
+         tree underlying_type = TREE_TYPE (DECL_NAME (decl));
+         int underlying_vis = type_visibility (underlying_type);
+         if (underlying_vis == VISIBILITY_ANON
+             || CLASSTYPE_VISIBILITY_SPECIFIED (underlying_type))
+           constrain_visibility (decl, underlying_vis);
+         else
+           DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+       }
       else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl))
        {
          /* tinfo visibility is based on the type it's for.  */
       else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl))
        {
          /* tinfo visibility is based on the type it's for.  */
@@ -1781,7 +1905,8 @@ determine_visibility (tree decl)
     {
       /* Propagate anonymity from type to decl.  */
       int tvis = type_visibility (TREE_TYPE (decl));
     {
       /* Propagate anonymity from type to decl.  */
       int tvis = type_visibility (TREE_TYPE (decl));
-      if (tvis == VISIBILITY_ANON)
+      if (tvis == VISIBILITY_ANON
+         || ! DECL_VISIBILITY_SPECIFIED (decl))
        constrain_visibility (decl, tvis);
     }
 }
        constrain_visibility (decl, tvis);
     }
 }
@@ -1792,18 +1917,20 @@ determine_visibility (tree decl)
 static void
 determine_visibility_from_class (tree decl, tree class_type)
 {
 static void
 determine_visibility_from_class (tree decl, tree class_type)
 {
+  if (DECL_VISIBILITY_SPECIFIED (decl))
+    return;
+
   if (visibility_options.inlines_hidden
       /* Don't do this for inline templates; specializations might not be
         inline, and we don't want them to inherit the hidden
         visibility.  We'll set it here for all inline instantiations.  */
       && !processing_template_decl
   if (visibility_options.inlines_hidden
       /* Don't do this for inline templates; specializations might not be
         inline, and we don't want them to inherit the hidden
         visibility.  We'll set it here for all inline instantiations.  */
       && !processing_template_decl
-      && ! DECL_VISIBILITY_SPECIFIED (decl)
       && TREE_CODE (decl) == FUNCTION_DECL
       && DECL_DECLARED_INLINE_P (decl)
       && (! DECL_LANG_SPECIFIC (decl)
          || ! DECL_EXPLICIT_INSTANTIATION (decl)))
     DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
       && TREE_CODE (decl) == FUNCTION_DECL
       && DECL_DECLARED_INLINE_P (decl)
       && (! DECL_LANG_SPECIFIC (decl)
          || ! DECL_EXPLICIT_INSTANTIATION (decl)))
     DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
-  else if (!DECL_VISIBILITY_SPECIFIED (decl))
+  else
     {
       /* Default to the class visibility.  */
       DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
     {
       /* Default to the class visibility.  */
       DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
@@ -1822,7 +1949,6 @@ determine_visibility_from_class (tree decl, tree class_type)
              && !DECL_CONSTRUCTION_VTABLE_P (decl)))
       && TREE_PUBLIC (decl)
       && !DECL_REALLY_EXTERN (decl)
              && !DECL_CONSTRUCTION_VTABLE_P (decl)))
       && TREE_PUBLIC (decl)
       && !DECL_REALLY_EXTERN (decl)
-      && !DECL_VISIBILITY_SPECIFIED (decl)
       && !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))
     targetm.cxx.determine_class_data_visibility (decl);
 }
       && !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))
     targetm.cxx.determine_class_data_visibility (decl);
 }
@@ -1850,13 +1976,16 @@ constrain_class_visibility (tree type)
   for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
     if (TREE_CODE (t) == FIELD_DECL && TREE_TYPE (t) != error_mark_node)
       {
   for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
     if (TREE_CODE (t) == FIELD_DECL && TREE_TYPE (t) != error_mark_node)
       {
-       tree ftype = strip_array_types (TREE_TYPE (t));
+       tree ftype = strip_pointer_or_array_types (TREE_TYPE (t));
        int subvis = type_visibility (ftype);
 
        if (subvis == VISIBILITY_ANON)
        int subvis = type_visibility (ftype);
 
        if (subvis == VISIBILITY_ANON)
-         warning (0, "\
+         {
+           if (!in_main_input_context ())
+             warning (0, "\
 %qT has a field %qD whose type uses the anonymous namespace",
 %qT has a field %qD whose type uses the anonymous namespace",
-                  type, t);
+                      type, t);
+         }
        else if (IS_AGGR_TYPE (ftype)
                 && vis < VISIBILITY_HIDDEN
                 && subvis >= VISIBILITY_HIDDEN)
        else if (IS_AGGR_TYPE (ftype)
                 && vis < VISIBILITY_HIDDEN
                 && subvis >= VISIBILITY_HIDDEN)
@@ -1871,9 +2000,12 @@ constrain_class_visibility (tree type)
       int subvis = type_visibility (TREE_TYPE (t));
 
       if (subvis == VISIBILITY_ANON)
       int subvis = type_visibility (TREE_TYPE (t));
 
       if (subvis == VISIBILITY_ANON)
-       warning (0, "\
+        {
+         if (!in_main_input_context())
+           warning (0, "\
 %qT has a base %qT whose type uses the anonymous namespace",
 %qT has a base %qT whose type uses the anonymous namespace",
-                type, TREE_TYPE (t));
+                    type, TREE_TYPE (t));
+       }
       else if (vis < VISIBILITY_HIDDEN
               && subvis >= VISIBILITY_HIDDEN)
        warning (OPT_Wattributes, "\
       else if (vis < VISIBILITY_HIDDEN
               && subvis >= VISIBILITY_HIDDEN)
        warning (OPT_Wattributes, "\
@@ -2098,7 +2230,8 @@ import_export_decl (tree decl)
     {
       /* DECL is an implicit instantiation of a function or static
         data member.  */
     {
       /* DECL is an implicit instantiation of a function or static
         data member.  */
-      if (flag_implicit_templates
+      if ((flag_implicit_templates
+          && !flag_use_repository)
          || (flag_implicit_inline_templates
              && TREE_CODE (decl) == FUNCTION_DECL
              && DECL_DECLARED_INLINE_P (decl)))
          || (flag_implicit_inline_templates
              && TREE_CODE (decl) == FUNCTION_DECL
              && DECL_DECLARED_INLINE_P (decl)))
@@ -2176,10 +2309,7 @@ build_cleanup (tree decl)
   if (TREE_CODE (type) == ARRAY_TYPE)
     temp = decl;
   else
   if (TREE_CODE (type) == ARRAY_TYPE)
     temp = decl;
   else
-    {
-      cxx_mark_addressable (decl);
-      temp = build1 (ADDR_EXPR, build_pointer_type (type), decl);
-    }
+    temp = build_address (decl);
   temp = build_delete (TREE_TYPE (temp), temp,
                       sfk_complete_destructor,
                       LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
   temp = build_delete (TREE_TYPE (temp), temp,
                       sfk_complete_destructor,
                       LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
@@ -2213,6 +2343,8 @@ get_guard (tree decl)
       DECL_ONE_ONLY (guard) = DECL_ONE_ONLY (decl);
       if (TREE_PUBLIC (decl))
        DECL_WEAK (guard) = DECL_WEAK (decl);
       DECL_ONE_ONLY (guard) = DECL_ONE_ONLY (decl);
       if (TREE_PUBLIC (decl))
        DECL_WEAK (guard) = DECL_WEAK (decl);
+      DECL_VISIBILITY (guard) = DECL_VISIBILITY (decl);
+      DECL_VISIBILITY_SPECIFIED (guard) = DECL_VISIBILITY_SPECIFIED (decl);
 
       DECL_ARTIFICIAL (guard) = 1;
       DECL_IGNORED_P (guard) = 1;
 
       DECL_ARTIFICIAL (guard) = 1;
       DECL_IGNORED_P (guard) = 1;
@@ -2319,9 +2451,11 @@ start_objects (int method_type, int initp)
                                                 void_list_node));
   start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
 
                                                 void_list_node));
   start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
 
-  /* It can be a static function as long as collect2 does not have
-     to scan the object file to find its ctor/dtor routine.  */
-  TREE_PUBLIC (current_function_decl) = ! targetm.have_ctors_dtors;
+  TREE_PUBLIC (current_function_decl) = 0;
+
+  /* Mark as artificial because it's not explicitly in the user's
+     source code.  */
+  DECL_ARTIFICIAL (current_function_decl) = 1;
 
   /* Mark this declaration as used to avoid spurious warnings.  */
   TREE_USED (current_function_decl) = 1;
 
   /* Mark this declaration as used to avoid spurious warnings.  */
   TREE_USED (current_function_decl) = 1;
@@ -2349,23 +2483,19 @@ finish_objects (int method_type, int initp, tree body)
   /* Finish up.  */
   finish_compound_stmt (body);
   fn = finish_function (0);
   /* Finish up.  */
   finish_compound_stmt (body);
   fn = finish_function (0);
-  expand_or_defer_fn (fn);
 
 
-  /* When only doing semantic analysis, and no RTL generation, we
-     can't call functions that directly emit assembly code; there is
-     no assembly file in which to put the code.  */
-  if (flag_syntax_only)
-    return;
-
-  if (targetm.have_ctors_dtors)
+  if (method_type == 'I')
     {
     {
-      rtx fnsym = XEXP (DECL_RTL (fn), 0);
-      cgraph_mark_needed_node (cgraph_node (fn));
-      if (method_type == 'I')
-       (* targetm.asm_out.constructor) (fnsym, initp);
-      else
-       (* targetm.asm_out.destructor) (fnsym, initp);
+      DECL_STATIC_CONSTRUCTOR (fn) = 1;
+      decl_init_priority_insert (fn, initp);
+    }
+  else
+    {
+      DECL_STATIC_DESTRUCTOR (fn) = 1;
+      decl_fini_priority_insert (fn, initp);
     }
     }
+
+  expand_or_defer_fn (fn);
 }
 
 /* The names of the parameters to the function created to handle
 }
 
 /* The names of the parameters to the function created to handle
@@ -2898,8 +3028,7 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
    Here we must deal with member pointers.  */
 
 tree
    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;
 
 {
   tree t = *tp;
 
@@ -3289,8 +3418,6 @@ cp_write_global_declarations (void)
   if (priority_info_map)
     splay_tree_delete (priority_info_map);
 
   if (priority_info_map)
     splay_tree_delete (priority_info_map);
 
-  c_build_cdtor_fns ();
-
   /* Generate any missing aliases.  */
   maybe_apply_pending_pragma_weaks ();
 
   /* Generate any missing aliases.  */
   maybe_apply_pending_pragma_weaks ();
 
@@ -3373,9 +3500,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);
         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);
       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);
       args = tree_cons (NULL_TREE, object, args);
       /* Now that the arguments are done, transform FN.  */
       fn = build_non_dependent_expr (fn);