tree if_stmt;
{
RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
- last_tree = if_stmt;
return 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
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. */
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
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;
}
{
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. */
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
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
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)
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
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
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 ();
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 `...'. */
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
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;}'. */
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
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
{
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
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);
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 ();
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;