OSDN Git Service

* lex.c (handle_cp_pragma): Remove #pragma vtable.
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index 3538aa1..2442826 100644 (file)
    02111-1307, USA.  */
 
 #include "config.h"
-#include <stdio.h>
+#include "system.h"
 #include "tree.h"
 #include "cp-tree.h"
 #include "except.h"
 #include "lex.h"
+#include "toplev.h"
 
 /* There routines provide a modular interface to perform many parsing
    operations.  They may therefore be used during actual parsing, or
@@ -65,19 +66,23 @@ void
 finish_expr_stmt (expr)
      tree expr;
 {
-  if (!processing_template_decl)
+  if (expr != NULL_TREE)
     {
-      emit_line_note (input_filename, lineno);
-      /* Do default conversion if safe and possibly important,
-        in case within ({...}).  */
-      if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
-          && lvalue_p (expr))
-         || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
-       expr = default_conversion (expr);
+      if (!processing_template_decl)
+       {
+         emit_line_note (input_filename, lineno);
+         /* Do default conversion if safe and possibly important,
+            in case within ({...}).  */
+         if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
+              && lvalue_p (expr))
+             || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
+           expr = default_conversion (expr);
+       }
+      
+      cplus_expand_expr_stmt (expr);
+      clear_momentary ();
     }
-  
-  cplus_expand_expr_stmt (expr);
-  clear_momentary ();
+
   finish_stmt ();
 }
 
@@ -378,8 +383,8 @@ finish_for_cond (cond, for_stmt)
   else
     {
       emit_line_note (input_filename, lineno);
-      if (cond) 
-       expand_exit_loop_if_false (0, cond);
+      if (cond)
+       expand_exit_loop_if_false (0, condition_conversion (cond));
     }
   
   /* If the cond wasn't a declaration, clear out the
@@ -582,7 +587,9 @@ finish_try_block (try_block)
   if (processing_template_decl)
     RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
   else
-    expand_start_all_catch ();  
+    {
+      expand_start_all_catch ();  
+    }
 }
 
 /* Finish a handler-sequence for a try-block, which may be given by
@@ -595,7 +602,9 @@ finish_handler_sequence (try_block)
   if (processing_template_decl)
     RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
   else
-    expand_end_all_catch ();
+    {
+      expand_end_all_catch ();
+    }
 }
 
 /* Begin a handler.  Returns a HANDLER if appropriate.  */
@@ -761,14 +770,18 @@ finish_parenthesized_expr (expr)
   return expr;
 }
 
-/* Begin a statement-expression.  Returns a new RTL_EXPR if
-   appropriate. */
+/* Begin a statement-expression.  The value returned must be passed to
+   finish_stmt_expr.  */
 
 tree 
 begin_stmt_expr ()
 {
   keep_next_level ();
-  return processing_template_decl ? NULL_TREE : expand_start_stmt_expr(); 
+  /* If we're processing_template_decl, then the upcoming compound
+     statement will be chained onto the tree structure, starting at
+     last_tree.  We return last_tree so that we can later unhook the
+     compound statement.  */
+  return processing_template_decl ? last_tree : expand_start_stmt_expr(); 
 }
 
 /* Finish a statement-expression.  RTL_EXPR should be the value
@@ -807,6 +820,14 @@ finish_stmt_expr (rtl_expr, expr)
     }
   else
     result = expr;
+
+  if (processing_template_decl)
+    {
+      /* Remove the compound statement from the tree structure; it is
+        now saved in the BIND_EXPR.  */
+      last_tree = rtl_expr;
+      TREE_CHAIN (last_tree) = NULL_TREE;
+    }
   
   return result;
 }
@@ -815,11 +836,21 @@ finish_stmt_expr (rtl_expr, expr)
    call.  */
 
 tree 
-finish_call_expr (fn, args)
+finish_call_expr (fn, args, koenig)
      tree fn;
      tree args;
+     int koenig;
 {
-  tree result = build_x_function_call (fn, args, current_class_ref);
+  tree result;
+
+  if (koenig)
+    {
+      if (TREE_CODE (fn) == BIT_NOT_EXPR)
+       fn = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND (fn, 0));
+      else if (TREE_CODE (fn) != TEMPLATE_ID_EXPR)
+       fn = do_identifier (fn, 2, args);
+    }
+  result = build_x_function_call (fn, args, current_class_ref);
 
   if (TREE_CODE (result) == CALL_EXPR
       && TREE_TYPE (result) != void_type_node)
@@ -896,6 +927,25 @@ finish_object_call_expr (fn, object, args)
   tree real_fn = build_component_ref (object, fn, NULL_TREE, 1);
   return finish_call_expr (real_fn, args);
 #else
+  if (TREE_CODE (fn) == TYPE_DECL)
+    {
+      if (processing_template_decl)
+       /* This can happen on code like:
+
+          class X;
+          template <class T> void f(T t) {
+            t.X();
+          }  
+
+          We just grab the underlying IDENTIFIER.  */
+       fn = DECL_NAME (fn);
+      else
+       {
+         cp_error ("calling type `%T' like a method", fn);
+         return error_mark_node;
+       }
+    }
+
   return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
 #endif
 }
@@ -980,6 +1030,58 @@ finish_label_address_expr (label)
   return result;
 }
 
+/* Finish an expression of the form CODE EXPR.  */
+
+tree
+finish_unary_op_expr (code, expr)
+     enum tree_code code;
+     tree expr;
+{
+  tree result = build_x_unary_op (code, expr);
+  if (code == NEGATE_EXPR && TREE_CODE (expr) == INTEGER_CST)
+    TREE_NEGATED_INT (result) = 1;
+  overflow_warning (result);
+  return result;
+}
+
+/* Finish an id-expression.  */
+
+tree
+finish_id_expr (expr)
+     tree expr;
+{
+  if (TREE_CODE (expr) == IDENTIFIER_NODE)
+    expr = do_identifier (expr, 1, NULL_TREE);
+
+  return expr;
+}
+
+/* Begin a new-placement.  */
+
+int
+begin_new_placement ()
+{
+  /* The arguments to a placement new might be passed to a
+     deallocation function, in the event that the allocation throws an
+     exception.  Since we don't expand exception handlers until the
+     end of a function, we must make sure the arguments stay around
+     that long.  */
+  return suspend_momentary ();
+}
+
+/* Finish a new-placement.  The ARGS are the placement arguments.  The
+   COOKIE is the value returned by the previous call to
+   begin_new_placement.  */
+
+tree
+finish_new_placement (args, cookie)
+     tree args;
+     int cookie;
+{
+  resume_momentary (cookie);
+  return args;
+}
+
 /* Begin a function defniition declared with DECL_SPECS and
    DECLARATOR.  Returns non-zero if the function-declaration is
    legal.  */
@@ -996,6 +1098,10 @@ begin_function_definition (decl_specs, declarator)
     return 0;
   
   reinit_parse_for_function ();
+  /* The things we're about to see are not directly qualified by any
+     template headers we've seen thus far.  */
+  reset_specialization ();
+
   return 1;
 }
 
@@ -1018,6 +1124,35 @@ begin_constructor_declarator (scope, name)
   return result;
 }
 
+/* Finish an init-declarator.  Returns a DECL.  */
+
+tree
+finish_declarator (declarator, declspecs, attributes,
+                  prefix_attributes, initialized)
+     tree declarator;
+     tree declspecs;
+     tree attributes;
+     tree prefix_attributes;
+     int initialized;
+{
+  return start_decl (declarator, declspecs, initialized, attributes,
+                    prefix_attributes); 
+}
+
+/* Finish a translation unit.  */
+
+void 
+finish_translation_unit ()
+{
+  /* In case there were missing closebraces,
+     get us back to the global binding level.  */
+  while (! toplevel_bindings_p ())
+    poplevel (0, 0, 0);
+  while (current_namespace != global_namespace)
+    pop_namespace ();
+  finish_file ();
+}
+
 /* Finish a template type parameter, specified as AGGR IDENTIFIER.
    Returns the parameter.  */
 
@@ -1054,3 +1189,250 @@ finish_template_template_parm (aggr, identifier)
 
   return finish_template_type_parm (aggr, tmpl);
 }
+
+/* Finish a parameter list, indicated by PARMS.  If ELLIPSIS is
+   non-zero, the parameter list was terminated by a `...'.  */
+
+tree
+finish_parmlist (parms, ellipsis)
+     tree parms;
+     int ellipsis;
+{
+  if (!ellipsis)
+    chainon (parms, void_list_node);
+  /* We mark the PARMS as a parmlist so that declarator processing can
+     disambiguate certain constructs.  */
+  if (parms != NULL_TREE)
+    TREE_PARMLIST (parms) = 1;
+
+  return parms;
+}
+
+/* Begin a class definition, as indicated by T.  */
+
+tree
+begin_class_definition (t)
+     tree t;
+{
+  tree new_type = t;
+
+  push_obstacks_nochange ();
+  end_temporary_allocation ();
+  
+  if (t == error_mark_node
+      || ! IS_AGGR_TYPE (t))
+    {
+      t = new_type = make_lang_type (RECORD_TYPE);
+      pushtag (make_anon_name (), t, 0);
+    }
+  if (TYPE_SIZE (t))
+    duplicate_tag_error (t);
+  if (TYPE_SIZE (t) || TYPE_BEING_DEFINED (t))
+    {
+      t = make_lang_type (TREE_CODE (t));
+      pushtag (TYPE_IDENTIFIER (t), t, 0);
+      new_type = t;
+    }
+  if (processing_template_decl && TYPE_CONTEXT (t)
+      && TREE_CODE (TYPE_CONTEXT (t)) != NAMESPACE_DECL
+      && ! current_class_type)
+    push_template_decl (TYPE_STUB_DECL (t));
+  pushclass (t, 0);
+  TYPE_BEING_DEFINED (t) = 1;
+  maybe_process_partial_specialization (t);
+  /* Reset the interface data, at the earliest possible
+     moment, as it might have been set via a class foo;
+     before.  */
+  /* Don't change signatures.  */
+  if (! IS_SIGNATURE (t))
+    {
+      int needs_writing;
+      tree name = TYPE_IDENTIFIER (t);
+      
+      if (! ANON_AGGRNAME_P (name))
+       {
+         CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
+         SET_CLASSTYPE_INTERFACE_UNKNOWN_X
+           (t, interface_unknown);
+       }
+      
+      /* Record how to set the access of this class's
+        virtual functions.  If write_virtuals == 3, then
+        inline virtuals are ``extern inline''.  */
+      if (write_virtuals == 3)
+       needs_writing = ! CLASSTYPE_INTERFACE_ONLY (t)
+         && CLASSTYPE_INTERFACE_KNOWN (t);
+      else
+       needs_writing = 1;
+      CLASSTYPE_VTABLE_NEEDS_WRITING (t) = needs_writing;
+    }
+#if 0
+  t = TYPE_IDENTIFIER ($<ttype>0);
+  if (t && IDENTIFIER_TEMPLATE (t))
+    overload_template_name (t, 1);
+#endif
+  reset_specialization();
+  
+  /* In case this is a local class within a template
+     function, we save the current tree structure so
+     that we can get it back later.  */
+  begin_tree ();
+
+  return new_type;
+}
+
+/* Finish a class definition T, with the indicated COMPONENTS, and
+   with the indicate ATTRIBUTES.  If SEMI, the definition is
+   immediately followed by a semicolon.  Returns the type.  */
+
+tree
+finish_class_definition (t, components, attributes, semi)
+     tree t;
+     tree components;
+     tree attributes;
+     int semi;
+{
+#if 0
+  /* Need to rework class nesting in the presence of nested classes,
+     etc.  */
+  shadow_tag (CLASSTYPE_AS_LIST (t)); */
+#endif
+
+  /* finish_struct nukes this anyway; if finish_exception does too,
+     then it can go.  */
+  if (semi)
+    note_got_semicolon (t);
+
+  /* If we got any attributes in class_head, xref_tag will stick them in
+     TREE_TYPE of the type.  Grab them now.  */
+  attributes = chainon (TREE_TYPE (t), attributes);
+  TREE_TYPE (t) = NULL_TREE;
+
+  if (TREE_CODE (t) == ENUMERAL_TYPE)
+    ;
+  else
+    {
+      t = finish_struct (t, components, attributes, semi);
+      if (semi) 
+       note_got_semicolon (t);
+    }
+
+  pop_obstacks ();
+
+  if (! semi)
+    check_for_missing_semicolon (t); 
+  if (current_scope () == current_function_decl)
+    do_pending_defargs ();
+
+  return t;
+}
+
+/* Finish processing the default argument expressions cached during
+   the processing of a class definition.  */
+
+void
+finish_default_args ()
+{
+  if (pending_inlines 
+      && current_scope () == current_function_decl)
+    do_pending_inlines ();
+}
+
+/* Finish processing the inline function definitions cached during the
+   processing of a class definition.  */
+
+void
+begin_inline_definitions ()
+{
+  if (current_class_type == NULL_TREE)
+    clear_inline_text_obstack (); 
+  
+  /* Undo the begin_tree in begin_class_definition.  */
+  end_tree ();
+}
+
+/* Finish processing the declaration of a member class template
+   TYPES whose template parameters are given by PARMS.  */
+
+tree
+finish_member_class_template (parms, types)
+     tree parms;
+     tree types;
+{
+  tree t;
+
+  /* If there are declared, but undefined, partial specializations
+     mixed in with the typespecs they will not yet have passed through
+     maybe_process_partial_specialization, so we do that here.  */
+  for (t = types; t != NULL_TREE; t = TREE_CHAIN (t))
+    if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_VALUE (t))))
+      maybe_process_partial_specialization (TREE_VALUE (t));
+
+  note_list_got_semicolon (types);
+  grok_x_components (types, NULL_TREE); 
+  if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
+    /* The component was in fact a friend declaration.  We avoid
+       finish_member_template_decl performing certain checks by
+       unsetting TYPES.  */
+    types = NULL_TREE;
+  finish_member_template_decl (parms, types);
+  /* As with other component type declarations, we do
+     not store the new DECL on the list of
+     component_decls.  */
+  return NULL_TREE;
+}
+
+/* Finish processsing a complete template declaration.  The PARMS are
+   the template parameters.  */
+
+void
+finish_template_decl (parms)
+     tree parms;
+{
+  if (parms)
+    end_template_decl ();
+  else
+    end_specialization ();
+}
+
+/* Finish processing a a template-id (which names a type) of the form
+   NAME < ARGS >.  Return the TYPE_DECL for the type named by the
+   template-id.  If ENTERING_SCOPE is non-zero we are about to enter
+   the scope of template-id indicated.  */
+
+tree
+finish_template_type (name, args, entering_scope)
+     tree name;
+     tree args;
+     int entering_scope;
+{
+  tree decl;
+
+  decl = lookup_template_class (name, args,
+                               NULL_TREE, NULL_TREE, entering_scope);
+  if (decl != error_mark_node)
+    decl = TYPE_STUB_DECL (decl);
+
+  return decl;
+}
+
+/* SR is a SCOPE_REF node.  Enter the scope of SR, whether it is a
+   namespace scope or a class scope.  */
+
+void
+enter_scope_of (sr)
+     tree sr;
+{
+  tree scope = TREE_OPERAND (sr, 0);
+
+  if (TREE_CODE (scope) == NAMESPACE_DECL)
+    {
+      push_decl_namespace (scope);
+      TREE_COMPLEXITY (sr) = -1;
+    }
+  else if (scope != current_class_type)
+    {
+      push_nested_class (scope, 3);
+      TREE_COMPLEXITY (sr) = current_class_depth;
+    }
+}