OSDN Git Service

* cp-tree.h (struct lang_decl): Overhaul.
[pf3gnuchains/gcc-fork.git] / gcc / cp / method.c
index 03f4908..4e22a20 100644 (file)
@@ -1,14 +1,15 @@
 /* Handle the hair of processing (but not expanding) inline functions.
    Also manage function and variable name overloading.
    Copyright (C) 1987, 1989, 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, 2008, 2009
+   Free Software Foundation, Inc.
    Contributed 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,
@@ -17,9 +18,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
-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/>.  */
 
 
 /* Handle method declarations.  */
@@ -38,6 +38,7 @@ Boston, MA 02110-1301, USA.  */
 #include "target.h"
 #include "tree-pass.h"
 #include "diagnostic.h"
+#include "cgraph.h"
 
 /* Various flags to control the mangling process.  */
 
@@ -125,7 +126,8 @@ make_thunk (tree function, bool this_adjusting,
   gcc_assert (TYPE_SIZE (DECL_CONTEXT (function))
              && TYPE_BEING_DEFINED (DECL_CONTEXT (function)));
 
-  thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
+  thunk = build_decl (DECL_SOURCE_LOCATION (function),
+                     FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
   DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
   cxx_dup_lang_specific_decl (thunk);
   DECL_THUNKS (thunk) = NULL_TREE;
@@ -154,7 +156,6 @@ make_thunk (tree function, bool this_adjusting,
   DECL_NO_STATIC_CHAIN (thunk) = 1;
   /* The THUNK is not a pending inline, even if the FUNCTION is.  */
   DECL_PENDING_INLINE_P (thunk) = 0;
-  DECL_INLINE (thunk) = 0;
   DECL_DECLARED_INLINE_P (thunk) = 0;
   /* Nor has it been deferred.  */
   DECL_DEFERRED_FN (thunk) = 0;
@@ -262,7 +263,8 @@ static GTY (()) int thunk_labelno;
 tree
 make_alias_for (tree function, tree newid)
 {
-  tree alias = build_decl (FUNCTION_DECL, newid, TREE_TYPE (function));
+  tree alias = build_decl (DECL_SOURCE_LOCATION (function),
+                          FUNCTION_DECL, newid, TREE_TYPE (function));
   DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);
   cxx_dup_lang_specific_decl (alias);
   DECL_CONTEXT (alias) = NULL;
@@ -275,12 +277,10 @@ make_alias_for (tree function, tree newid)
   DECL_SAVED_FUNCTION_DATA (alias) = NULL;
   DECL_DESTRUCTOR_P (alias) = 0;
   DECL_CONSTRUCTOR_P (alias) = 0;
-  DECL_CLONED_FUNCTION (alias) = NULL_TREE;
   DECL_EXTERNAL (alias) = 0;
   DECL_ARTIFICIAL (alias) = 1;
   DECL_NO_STATIC_CHAIN (alias) = 1;
   DECL_PENDING_INLINE_P (alias) = 0;
-  DECL_INLINE (alias) = 0;
   DECL_DECLARED_INLINE_P (alias) = 0;
   DECL_DEFERRED_FN (alias) = 0;
   DECL_USE_TEMPLATE (alias) = 0;
@@ -382,7 +382,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
   DECL_VISIBILITY_SPECIFIED (thunk_fndecl)
     = DECL_VISIBILITY_SPECIFIED (function);
   if (DECL_ONE_ONLY (function))
-    make_decl_one_only (thunk_fndecl);
+    make_decl_one_only (thunk_fndecl, cxx_comdat_group (thunk_fndecl));
 
   if (flag_syntax_only)
     {
@@ -429,15 +429,16 @@ use_thunk (tree thunk_fndecl, bool emit_p)
       
       current_function_decl = thunk_fndecl;
       DECL_RESULT (thunk_fndecl)
-       = build_decl (RESULT_DECL, 0, integer_type_node);
-      fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
+       = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl),
+                     RESULT_DECL, 0, integer_type_node);
+      fnname = IDENTIFIER_POINTER (DECL_NAME (thunk_fndecl));
       /* The back end expects DECL_INITIAL to contain a BLOCK, so we
         create one.  */
       fn_block = make_node (BLOCK);
       BLOCK_VARS (fn_block) = a;
       DECL_INITIAL (thunk_fndecl) = fn_block;
       init_function_start (thunk_fndecl);
-      current_function_is_thunk = 1;
+      cfun->is_thunk = 1;
       assemble_start_function (thunk_fndecl, fnname);
 
       targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
@@ -446,7 +447,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
       assemble_end_function (thunk_fndecl, fnname);
       init_insn_lengths ();
       current_function_decl = 0;
-      cfun = 0;
+      set_cfun (NULL);
       TREE_ASM_WRITTEN (thunk_fndecl) = 1;
     }
   else
@@ -481,6 +482,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
        argarray[i] = a;
       t = build_call_a (alias, i, argarray);
       CALL_FROM_THUNK_P (t) = 1;
+      CALL_CANNOT_INLINE_P (t) = 1;
 
       if (VOID_TYPE_P (TREE_TYPE (t)))
        finish_expr_stmt (t);
@@ -506,7 +508,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
                t = build3 (COND_EXPR, TREE_TYPE (t), cond, t,
                            cp_convert (TREE_TYPE (t), integer_zero_node));
            }
-         if (IS_AGGR_TYPE (TREE_TYPE (t)))
+         if (MAYBE_CLASS_TYPE_P (TREE_TYPE (t)))
            t = build_cplus_new (TREE_TYPE (t), t);
          finish_return_stmt (t);
        }
@@ -522,8 +524,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
       pop_deferring_access_checks ();
 
       thunk_fndecl = finish_function (0);
-      tree_lowering_passes (thunk_fndecl);
-      expand_body (thunk_fndecl);
+      cgraph_add_new_function (thunk_fndecl, false);
     }
 
   pop_from_top_level ();
@@ -662,18 +663,21 @@ do_build_assign_ref (tree fndecl)
           BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
        {
          tree converted_parm;
+         VEC(tree,gc) *parmvec;
 
          /* We must convert PARM directly to the base class
             explicitly since the base class may be ambiguous.  */
          converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
          /* Call the base class assignment operator.  */
+         parmvec = make_tree_vector_single (converted_parm);
          finish_expr_stmt
            (build_special_member_call (current_class_ref,
                                        ansi_assopname (NOP_EXPR),
-                                       build_tree_list (NULL_TREE,
-                                                        converted_parm),
+                                       &parmvec,
                                        base_binfo,
-                                       LOOKUP_NORMAL | LOOKUP_NONVIRTUAL));
+                                       LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
+                                        tf_warning_or_error));
+         release_tree_vector (parmvec);
        }
 
       /* Assign to each of the non-static data members.  */
@@ -728,7 +732,8 @@ do_build_assign_ref (tree fndecl)
          init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
 
          if (DECL_NAME (field))
-           init = build_modify_expr (comp, NOP_EXPR, init);
+           init = cp_build_modify_expr (comp, NOP_EXPR, init, 
+                                        tf_warning_or_error);
          else
            init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init);
          finish_expr_stmt (init);
@@ -769,7 +774,7 @@ synthesize_method (tree fndecl)
   if (! context)
     push_to_top_level ();
   else if (nested)
-    push_function_context_to (context);
+    push_function_context ();
 
   input_location = DECL_SOURCE_LOCATION (fndecl);
 
@@ -807,13 +812,13 @@ synthesize_method (tree fndecl)
   if (! context)
     pop_from_top_level ();
   else if (nested)
-    pop_function_context_from (context);
+    pop_function_context ();
 
   pop_deferring_access_checks ();
 
   if (error_count != errorcount || warning_count != warningcount)
-    inform ("%Hsynthesized method %qD first required here ",
-           &input_location, fndecl);
+    inform (input_location, "synthesized method %qD first required here ",
+           fndecl);
 }
 
 /* Use EXTRACTOR to locate the relevant function called for each base &
@@ -1078,6 +1083,14 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
       DECL_ASSIGNMENT_OPERATOR_P (fn) = 1;
       SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
     }
+  
+  /* If pointers to member functions use the least significant bit to
+     indicate whether a function is virtual, ensure a pointer
+     to this function will have that bit clear.  */
+  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
+      && DECL_ALIGN (fn) < 2 * BITS_PER_UNIT)
+    DECL_ALIGN (fn) = 2 * BITS_PER_UNIT;
+
   /* Create the explicit arguments.  */
   if (rhs_parm_type)
     {
@@ -1097,9 +1110,9 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
   rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
   DECL_IN_AGGR_P (fn) = 1;
   DECL_ARTIFICIAL (fn) = 1;
+  DECL_DEFAULTED_FN (fn) = 1;
   DECL_NOT_REALLY_EXTERN (fn) = 1;
   DECL_DECLARED_INLINE_P (fn) = 1;
-  DECL_INLINE (fn) = 1;
   gcc_assert (!TREE_USED (fn));
 
   /* Restore PROCESSING_TEMPLATE_DECL.  */
@@ -1177,7 +1190,7 @@ lazily_declare_fn (special_function_kind sfk, tree type)
    as there are artificial parms in FN.  */
 
 tree
-skip_artificial_parms_for (tree fn, tree list)
+skip_artificial_parms_for (const_tree fn, tree list)
 {
   if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
     list = TREE_CHAIN (list);
@@ -1195,7 +1208,7 @@ skip_artificial_parms_for (tree fn, tree list)
    artificial parms in FN.  */
 
 int
-num_artificial_parms_for (tree fn)
+num_artificial_parms_for (const_tree fn)
 {
   int count = 0;