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
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 ();
}
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
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
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. */
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
}
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;
}
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)
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
}
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. */
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;
}
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. */
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;
+ }
+}