OSDN Git Service

2002-08-24 Matt Austern <austern@apple.com>
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index 0f671ae..2737bbe 100644 (file)
@@ -266,7 +266,6 @@ finish_then_clause (if_stmt)
      tree if_stmt;
 {
   RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
-  last_tree = if_stmt;
   return if_stmt;
 }
 
@@ -292,21 +291,8 @@ finish_else_clause (if_stmt)
 void 
 finish_if_stmt ()
 {
-  do_poplevel ();
   finish_stmt ();
-}
-
-void
-clear_out_block ()
-{
-  /* If COND wasn't a declaration, clear out the
-     block we made for it and start a new one here so the
-     optimization in expand_end_loop will work.  */
-  if (getdecls () == NULL_TREE)
-    {
-      do_poplevel ();
-      do_pushlevel ();
-    }
+  do_poplevel ();
 }
 
 /* Begin a while-statement.  Returns a newly created WHILE_STMT if
@@ -331,8 +317,26 @@ finish_while_stmt_cond (cond, while_stmt)
      tree while_stmt;
 {
   cond = maybe_convert_cond (cond);
-  FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt));
-  clear_out_block ();
+  if (getdecls () == NULL_TREE)
+    /* It was a simple condition; install it.  */
+    WHILE_COND (while_stmt) = cond;
+  else
+    {
+      /* If there was a declaration in the condition, we can't leave it
+        there; transform
+           while (A x = 42) { }
+        to
+           while (true) { A x = 42; if (!x) break; }  */
+      tree if_stmt;
+      WHILE_COND (while_stmt) = boolean_true_node;
+
+      if_stmt = begin_if_stmt ();
+      cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
+      finish_if_stmt_cond (cond, if_stmt);
+      finish_break_stmt ();
+      finish_then_clause (if_stmt);
+      finish_if_stmt ();
+    }
 }
 
 /* Finish a while-statement, which may be given by WHILE_STMT.  */
@@ -448,8 +452,26 @@ finish_for_cond (cond, for_stmt)
      tree for_stmt;
 {
   cond = maybe_convert_cond (cond);
-  FINISH_COND (cond, for_stmt, FOR_COND (for_stmt));
-  clear_out_block ();
+  if (getdecls () == NULL_TREE)
+    /* It was a simple condition; install it.  */
+    FOR_COND (for_stmt) = cond;
+  else
+    {
+      /* If there was a declaration in the condition, we can't leave it
+        there; transform
+           for (; A x = 42;) { }
+        to
+           for (;;) { A x = 42; if (!x) break; }  */
+      tree if_stmt;
+      FOR_COND (for_stmt) = NULL_TREE;
+
+      if_stmt = begin_if_stmt ();
+      cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
+      finish_if_stmt_cond (cond, if_stmt);
+      finish_break_stmt ();
+      finish_then_clause (if_stmt);
+      finish_if_stmt ();
+    }
 }
 
 /* Finish the increment-EXPRESSION in a for-statement, which may be
@@ -502,9 +524,9 @@ tree
 begin_switch_stmt ()
 {
   tree r;
+  do_pushlevel ();
   r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
   add_stmt (r);
-  do_pushlevel ();
   return r;
 }
 
@@ -560,8 +582,8 @@ finish_switch_stmt (switch_stmt)
 {
   RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt));
   pop_switch (); 
-  do_poplevel ();
   finish_stmt ();
+  do_poplevel ();
 }
 
 /* Generate the RTL for T, which is a TRY_BLOCK. */
@@ -1063,6 +1085,15 @@ finish_named_return_value (return_id, init)
   DECL_UNINLINABLE (current_function_decl) = 1;
 }
 
+/* Begin processing a mem-initializer-list.  */
+
+void
+begin_mem_initializers ()
+{
+  if (! DECL_CONSTRUCTOR_P (current_function_decl))
+    error ("only constructors take base initializers");
+}
+
 /* The INIT_LIST is a list of mem-initializers, in the order they were
    written by the user.  The TREE_VALUE of each node is a list of
    initializers for a particular subobject.  The TREE_PURPOSE is a
@@ -1233,32 +1264,86 @@ finish_stmt_expr (rtl_expr)
   return result;
 }
 
-/* Finish a call to FN with ARGS.  Returns a representation of the
-   call.  */
+/* Generate an expression for `FN (ARGS)'.
+
+   If DISALLOW_VIRTUAL is true, the call to FN will be not generated
+   as a virtual call, even if FN is virtual.  (This flag is set when
+   encountering an expression where the function name is explicitly
+   qualified.  For example a call to `X::f' never generates a virtual
+   call.)
+
+   Returns code for the call.  */
 
 tree 
-finish_call_expr (fn, args, koenig)
-     tree fn;
-     tree args;
-     int koenig;
+finish_call_expr (tree fn, tree args, bool disallow_virtual)
 {
-  tree result;
+  if (fn == error_mark_node || args == error_mark_node)
+    return error_mark_node;
 
-  if (koenig)
+  if (processing_template_decl)
+    return build_nt (CALL_EXPR, fn, args, NULL_TREE);
+
+  /* ARGS should be a list of arguments.  */
+  my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
+                     20020712);
+
+  if (BASELINK_P (fn))
     {
-      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);
+      tree object;
+
+      /* A call to a member function.  From [over.call.func]:
+
+          If the keyword this is in scope and refers to the class of
+          that member function, or a derived class thereof, then the
+          function call is transformed into a qualified function call
+          using (*this) as the postfix-expression to the left of the
+          . operator.... [Otherwise] a contrived object of type T
+          becomes the implied object argument.  
+
+        This paragraph is unclear about this situation:
+
+         struct A { void f(); };
+         struct B : public A {};
+         struct C : public A { void g() { B::f(); }};
+
+       In particular, for `B::f', this paragraph does not make clear
+       whether "the class of that member function" refers to `A' or 
+       to `B'.  We believe it refers to `B'.  */
+      if (current_class_type 
+         && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
+                            current_class_type)
+         && current_class_ref)
+       object = current_class_ref;
+      else
+       {
+         tree representative_fn;
 
-  if (TREE_CODE (result) == CALL_EXPR
-      && (! TREE_TYPE (result)
-          || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE))
-    result = require_complete_type (result);
+         representative_fn = BASELINK_FUNCTIONS (fn);
+         if (TREE_CODE (representative_fn) == TEMPLATE_ID_EXPR)
+           representative_fn = TREE_OPERAND (representative_fn, 0);
+         representative_fn = get_first_fn (representative_fn);
+         object = build_dummy_object (DECL_CONTEXT (representative_fn));
+       }
 
-  return result;
+      return build_new_method_call (object, fn, args, NULL_TREE,
+                                   (disallow_virtual 
+                                    ? LOOKUP_NONVIRTUAL : 0));
+    }
+  else if (is_overloaded_fn (fn))
+    /* A call to a namespace-scope function.  */
+    return build_new_function_call (fn, args);
+  else if (CLASS_TYPE_P (TREE_TYPE (fn)))
+    {
+      /* If the "function" is really an object of class type, it might
+        have an overloaded `operator ()'.  */
+      tree result;
+      result = build_opfncall (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
+      if (result)
+       return result;
+    }
+
+  /* A call where the function is unknown.  */
+  return build_function_call (fn, args);
 }
 
 /* Finish a call to a postfix increment or decrement or EXPR.  (Which
@@ -1318,14 +1403,6 @@ finish_object_call_expr (fn, object, args)
      tree object;
      tree args;
 {
-#if 0
-  /* This is a future direction of this code, but because
-     build_x_function_call cannot always undo what is done in
-     build_component_ref entirely yet, we cannot do this.  */
-
-  tree real_fn = build_component_ref (object, fn, NULL_TREE, 1);
-  return finish_call_expr (real_fn, args);
-#else
   if (DECL_DECLARES_TYPE_P (fn))
     {
       if (processing_template_decl)
@@ -1344,9 +1421,11 @@ finish_object_call_expr (fn, object, args)
          return error_mark_node;
        }
     }
-
-  return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
-#endif
+  
+  if (name_p (fn))
+    return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
+  else
+    return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
 }
 
 /* Finish a qualified member function call using OBJECT and ARGS as
@@ -1387,22 +1466,6 @@ finish_pseudo_destructor_call_expr (object, scope, destructor)
   return cp_convert (void_type_node, object);
 }
 
-/* Finish a call to a globally qualified member function FN using
-   ARGS.  Returns an expression for the call.  */
-
-tree 
-finish_qualified_call_expr (fn, args)
-     tree fn;
-     tree args;
-{
-  if (processing_template_decl)
-    return build_min_nt (CALL_EXPR, fn, args, NULL_TREE);
-  else
-    return build_member_call (TREE_OPERAND (fn, 0),
-                             TREE_OPERAND (fn, 1),
-                             args);
-}
-
 /* Finish an expression of the form CODE EXPR.  */
 
 tree
@@ -1508,20 +1571,17 @@ reset_type_access_control ()
   current_type_lookups = NULL_TREE;
 }
 
-/* Begin a function definition declared with DECL_SPECS and
-   DECLARATOR.  Returns non-zero if the function-declaration is
-   legal.  */
+/* Begin a function definition declared with DECL_SPECS, ATTRIBUTES,
+   and DECLARATOR.  Returns non-zero if the function-declaration is
+   valid.  */
 
 int
-begin_function_definition (decl_specs, declarator)
+begin_function_definition (decl_specs, attributes, declarator)
      tree decl_specs;
+     tree attributes;
      tree declarator;
 {
-  tree specs;
-  tree attrs;
-
-  split_specs_attrs (decl_specs, &specs, &attrs);
-  if (!start_function (specs, declarator, attrs, SF_DEFAULT))
+  if (!start_function (decl_specs, declarator, attributes, SF_DEFAULT))
     return 0;
 
   deferred_type_access_control ();
@@ -1616,6 +1676,25 @@ finish_template_template_parm (aggr, identifier)
   return finish_template_type_parm (aggr, tmpl);
 }
 
+/* ARGUMENT is the default-argument value for a template template
+   parameter.  If ARGUMENT is invalid, issue error messages and return
+   the ERROR_MARK_NODE.  Otherwise, ARGUMENT itself is returned.  */
+
+tree
+check_template_template_default_arg (tree argument)
+{
+  if (TREE_CODE (argument) != TEMPLATE_DECL
+      && TREE_CODE (argument) != TEMPLATE_TEMPLATE_PARM
+      && TREE_CODE (argument) != TYPE_DECL
+      && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
+    {
+      error ("invalid default template argument");
+      return error_mark_node;
+    }
+
+  return argument;
+}
+
 /* Finish a parameter list, indicated by PARMS.  If ELLIPSIS is
    non-zero, the parameter list was terminated by a `...'.  */
 
@@ -1820,7 +1899,7 @@ finish_member_declaration (decl)
           struct S { enum E { }; int E } s;
           s.E = 3;
 
-        is legal.  In addition, the FIELD_DECLs must be maintained in
+        is valid.  In addition, the FIELD_DECLs must be maintained in
         declaration order so that class layout works as expected.
         However, we don't need that order until class layout, so we
         save a little time by putting FIELD_DECLs on in reverse order
@@ -2037,7 +2116,7 @@ check_multiple_declarators ()
      contain at most one declarator.  
 
      We don't just use PROCESSING_TEMPLATE_DECL for the first
-     condition since that would disallow the perfectly legal code, 
+     condition since that would disallow the perfectly valid code, 
      like `template <class T> struct S { int i, j; };'.  */
   if (at_function_scope_p ())
     /* It's OK to write `template <class T> void f() { int i, j;}'.  */
@@ -2081,7 +2160,7 @@ finish_sizeof (t)
   if (processing_template_decl)
     return build_min_nt (SIZEOF_EXPR, t);
 
-  return TYPE_P (t) ? c_sizeof (t) : expr_sizeof (t);
+  return TYPE_P (t) ? cxx_sizeof (t) : expr_sizeof (t);
 }
 
 /* Implement the __alignof keyword: Return the minimum required
@@ -2094,7 +2173,7 @@ finish_alignof (t)
   if (processing_template_decl)
     return build_min_nt (ALIGNOF_EXPR, t);
 
-  return TYPE_P (t) ? c_alignof (t) : c_alignof_expr (t);
+  return TYPE_P (t) ? cxx_alignof (t) : c_alignof_expr (t);
 }
 
 /* Generate RTL for the statement T, and its substatements, and any
@@ -2272,6 +2351,7 @@ expand_body (fn)
 {
   int saved_lineno;
   const char *saved_input_filename;
+  tree saved_function;
 
   /* When the parser calls us after finishing the body of a template
      function, we don't really want to expand the body.  When we're
@@ -2349,21 +2429,23 @@ expand_body (fn)
   if (DECL_EXTERNAL (fn))
     return;
 
-  timevar_push (TV_INTEGRATION);
-
-  /* Optimize the body of the function before expanding it.  */
-  optimize_function (fn);
-
-  timevar_pop (TV_INTEGRATION);
-  timevar_push (TV_EXPAND);
-
   /* Save the current file name and line number.  When we expand the
      body of the function, we'll set LINENO and INPUT_FILENAME so that
      error-mesages come out in the right places.  */
   saved_lineno = lineno;
   saved_input_filename = input_filename;
+  saved_function = current_function_decl;
   lineno = DECL_SOURCE_LINE (fn);
   input_filename = DECL_SOURCE_FILE (fn);
+  current_function_decl = fn;
+
+  timevar_push (TV_INTEGRATION);
+
+  /* Optimize the body of the function before expanding it.  */
+  optimize_function (fn);
+
+  timevar_pop (TV_INTEGRATION);
+  timevar_push (TV_EXPAND);
 
   genrtl_start_function (fn);
   current_function_is_thunk = DECL_THUNK_P (fn);
@@ -2396,6 +2478,7 @@ expand_body (fn)
     DECL_SAVED_TREE (fn) = NULL_TREE;
 
   /* And restore the current source position.  */
+  current_function_decl = saved_function;
   lineno = saved_lineno;
   input_filename = saved_input_filename;
   extract_interface_info ();
@@ -2423,7 +2506,7 @@ nullify_returns_r (tp, walk_subtrees, data)
   if (TYPE_P (*tp))
     *walk_subtrees = 0;
   else if (TREE_CODE (*tp) == RETURN_STMT)
-    RETURN_EXPR (*tp) = NULL_TREE;
+    RETURN_STMT_EXPR (*tp) = NULL_TREE;
   else if (TREE_CODE (*tp) == CLEANUP_STMT
           && CLEANUP_DECL (*tp) == nrv)
     CLEANUP_EH_ONLY (*tp) = 1;