X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcp%2Fsemantics.c;h=2daff6f02e0e863d04378ad42660f3b153aba427;hp=5b1b1ef4d1cbed7ee34e0a1693d0a3add90e442e;hb=4cbba981b3d1de4043ae5570ed552382a24a939f;hpb=2c584053e7a50135ab299115a5d7b909bd65355f diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 5b1b1ef4d1c..2daff6f02e0 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3,8 +3,8 @@ building RTL. These routines are used both during actual parsing and during the instantiation of template functions. - Copyright (C) 1998, 1999, 2000, 2001, 2002, - 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. Written by Mark Mitchell (mmitchell@usa.net) based on code found formerly in parse.y and pt.c. @@ -31,9 +31,10 @@ #include "tm.h" #include "tree.h" #include "cp-tree.h" +#include "c-common.h" #include "tree-inline.h" +#include "tree-mudflap.h" #include "except.h" -#include "lex.h" #include "toplev.h" #include "flags.h" #include "rtl.h" @@ -41,7 +42,11 @@ #include "output.h" #include "timevar.h" #include "debug.h" +#include "diagnostic.h" #include "cgraph.h" +#include "tree-iterator.h" +#include "vec.h" +#include "target.h" /* There routines provide a modular interface to perform many parsing operations. They may therefore be used during actual parsing, or @@ -55,28 +60,8 @@ static tree maybe_convert_cond (tree); static tree simplify_aggr_init_exprs_r (tree *, int *, void *); static void emit_associated_thunks (tree); -static void genrtl_try_block (tree); -static void genrtl_eh_spec_block (tree); -static void genrtl_handler (tree); -static void cp_expand_stmt (tree); - - -/* Finish processing the COND, the SUBSTMT condition for STMT. */ - -#define FINISH_COND(COND, STMT, SUBSTMT) \ - do { \ - if (last_tree != (STMT)) \ - { \ - RECHAIN_STMTS (STMT, SUBSTMT); \ - if (!processing_template_decl) \ - { \ - (COND) = build_tree_list (SUBSTMT, COND); \ - (SUBSTMT) = (COND); \ - } \ - } \ - else \ - (SUBSTMT) = (COND); \ - } while (0) +static tree finalize_nrv_r (tree *, int *, void *); + /* Deferred Access Checking Overview --------------------------------- @@ -129,9 +114,36 @@ static void cp_expand_stmt (tree); In case of parsing error, we simply call `pop_deferring_access_checks' without `perform_deferred_access_checks'. */ +typedef struct deferred_access GTY(()) +{ + /* A TREE_LIST representing name-lookups for which we have deferred + checking access controls. We cannot check the accessibility of + names used in a decl-specifier-seq until we know what is being + declared because code like: + + class A { + class B {}; + B* f(); + } + + A::B* A::f() { return 0; } + + is valid, even though `A::B' is not generally accessible. + + The TREE_PURPOSE of each node is the scope used to qualify the + name being looked up; the TREE_VALUE is the DECL to which the + name was resolved. */ + tree deferred_access_checks; + + /* The current mode of access checks. */ + enum deferring_kind deferring_access_checks_kind; + +} deferred_access; +DEF_VEC_GC_O (deferred_access); + /* Data for deferred access checking. */ -static GTY(()) deferred_access *deferred_access_stack; -static GTY(()) deferred_access *deferred_access_free_list; +static GTY(()) VEC (deferred_access) *deferred_access_stack; +static GTY(()) unsigned deferred_access_no_check; /* Save the current deferred access states and start deferred access checking iff DEFER_P is true. */ @@ -139,27 +151,18 @@ static GTY(()) deferred_access *deferred_access_free_list; void push_deferring_access_checks (deferring_kind deferring) { - deferred_access *d; - /* For context like template instantiation, access checking disabling applies to all nested context. */ - if (deferred_access_stack - && deferred_access_stack->deferring_access_checks_kind == dk_no_check) - deferring = dk_no_check; - - /* Recycle previously used free store if available. */ - if (deferred_access_free_list) - { - d = deferred_access_free_list; - deferred_access_free_list = d->next; - } + if (deferred_access_no_check || deferring == dk_no_check) + deferred_access_no_check++; else - d = ggc_alloc (sizeof (deferred_access)); + { + deferred_access *ptr; - d->next = deferred_access_stack; - d->deferred_access_checks = NULL_TREE; - d->deferring_access_checks_kind = deferring; - deferred_access_stack = d; + ptr = VEC_safe_push (deferred_access, deferred_access_stack, NULL); + ptr->deferred_access_checks = NULL_TREE; + ptr->deferring_access_checks_kind = deferring; + } } /* Resume deferring access checks again after we stopped doing @@ -168,8 +171,9 @@ push_deferring_access_checks (deferring_kind deferring) void resume_deferring_access_checks (void) { - if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred) - deferred_access_stack->deferring_access_checks_kind = dk_deferred; + if (!deferred_access_no_check) + VEC_last (deferred_access, deferred_access_stack) + ->deferring_access_checks_kind = dk_deferred; } /* Stop deferring access checks. */ @@ -177,8 +181,9 @@ resume_deferring_access_checks (void) void stop_deferring_access_checks (void) { - if (deferred_access_stack->deferring_access_checks_kind == dk_deferred) - deferred_access_stack->deferring_access_checks_kind = dk_no_deferred; + if (!deferred_access_no_check) + VEC_last (deferred_access, deferred_access_stack) + ->deferring_access_checks_kind = dk_no_deferred; } /* Discard the current deferred access checks and restore the @@ -187,15 +192,10 @@ stop_deferring_access_checks (void) void pop_deferring_access_checks (void) { - deferred_access *d = deferred_access_stack; - deferred_access_stack = d->next; - - /* Remove references to access checks TREE_LIST. */ - d->deferred_access_checks = NULL_TREE; - - /* Store in free list for later use. */ - d->next = deferred_access_free_list; - deferred_access_free_list = d; + if (deferred_access_no_check) + deferred_access_no_check--; + else + VEC_pop (deferred_access, deferred_access_stack); } /* Returns a TREE_LIST representing the deferred checks. @@ -206,7 +206,11 @@ pop_deferring_access_checks (void) tree get_deferred_access_checks (void) { - return deferred_access_stack->deferred_access_checks; + if (deferred_access_no_check) + return NULL; + else + return (VEC_last (deferred_access, deferred_access_stack) + ->deferred_access_checks); } /* Take current deferred checks and combine with the @@ -216,27 +220,48 @@ get_deferred_access_checks (void) void pop_to_parent_deferring_access_checks (void) { - tree deferred_check = get_deferred_access_checks (); - deferred_access *d1 = deferred_access_stack; - deferred_access *d2 = deferred_access_stack->next; - deferred_access *d3 = deferred_access_stack->next->next; - - /* Temporary swap the order of the top two states, just to make - sure the garbage collector will not reclaim the memory during - processing below. */ - deferred_access_stack = d2; - d2->next = d1; - d1->next = d3; + if (deferred_access_no_check) + deferred_access_no_check--; + else + { + tree checks; + deferred_access *ptr; - for ( ; deferred_check; deferred_check = TREE_CHAIN (deferred_check)) - /* Perform deferred check if required. */ - perform_or_defer_access_check (TREE_PURPOSE (deferred_check), - TREE_VALUE (deferred_check)); + checks = (VEC_last (deferred_access, deferred_access_stack) + ->deferred_access_checks); - deferred_access_stack = d1; - d1->next = d2; - d2->next = d3; - pop_deferring_access_checks (); + VEC_pop (deferred_access, deferred_access_stack); + ptr = VEC_last (deferred_access, deferred_access_stack); + if (ptr->deferring_access_checks_kind == dk_no_deferred) + { + /* Check access. */ + for (; checks; checks = TREE_CHAIN (checks)) + enforce_access (TREE_PURPOSE (checks), + TREE_VALUE (checks)); + } + else + { + /* Merge with parent. */ + tree next; + tree original = ptr->deferred_access_checks; + + for (; checks; checks = next) + { + tree probe; + + next = TREE_CHAIN (checks); + + for (probe = original; probe; probe = TREE_CHAIN (probe)) + if (TREE_VALUE (probe) == TREE_VALUE (checks) + && TREE_PURPOSE (probe) == TREE_PURPOSE (checks)) + goto found; + /* Insert into parent's checks. */ + TREE_CHAIN (checks) = ptr->deferred_access_checks; + ptr->deferred_access_checks = checks; + found:; + } + } + } } /* Perform the deferred access checks. @@ -259,7 +284,8 @@ void perform_deferred_access_checks (void) { tree deferred_check; - for (deferred_check = deferred_access_stack->deferred_access_checks; + + for (deferred_check = get_deferred_access_checks (); deferred_check; deferred_check = TREE_CHAIN (deferred_check)) /* Check access. */ @@ -274,29 +300,33 @@ void perform_or_defer_access_check (tree binfo, tree decl) { tree check; + deferred_access *ptr; - my_friendly_assert (TREE_CODE (binfo) == TREE_VEC, 20030623); + /* Exit if we are in a context that no access checking is performed. + */ + if (deferred_access_no_check) + return; + + gcc_assert (TREE_CODE (binfo) == TREE_BINFO); + + ptr = VEC_last (deferred_access, deferred_access_stack); /* If we are not supposed to defer access checks, just check now. */ - if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred) + if (ptr->deferring_access_checks_kind == dk_no_deferred) { enforce_access (binfo, decl); return; } - /* Exit if we are in a context that no access checking is performed. */ - else if (deferred_access_stack->deferring_access_checks_kind == dk_no_check) - return; - + /* See if we are already going to perform this check. */ - for (check = deferred_access_stack->deferred_access_checks; + for (check = ptr->deferred_access_checks; check; check = TREE_CHAIN (check)) if (TREE_VALUE (check) == decl && TREE_PURPOSE (check) == binfo) return; /* If not, record the check. */ - deferred_access_stack->deferred_access_checks - = tree_cons (binfo, decl, - deferred_access_stack->deferred_access_checks); + ptr->deferred_access_checks + = tree_cons (binfo, decl, ptr->deferred_access_checks); } /* Returns nonzero if the current statement is a full expression, @@ -321,6 +351,43 @@ current_stmt_tree (void) : &scope_chain->x_stmt_tree); } +/* If statements are full expressions, wrap STMT in a CLEANUP_POINT_EXPR. */ + +static tree +maybe_cleanup_point_expr (tree expr) +{ + if (!processing_template_decl && stmts_are_full_exprs_p ()) + expr = fold_build_cleanup_point_expr (TREE_TYPE (expr), expr); + return expr; +} + +/* Like maybe_cleanup_point_expr except have the type of the new expression be + void so we don't need to create a temporary variable to hold the inner + expression. The reason why we do this is because the original type might be + an aggregate and we cannot create a temporary variable for that type. */ + +static tree +maybe_cleanup_point_expr_void (tree expr) +{ + if (!processing_template_decl && stmts_are_full_exprs_p ()) + expr = fold_build_cleanup_point_expr (void_type_node, expr); + return expr; +} + + + +/* Create a declaration statement for the declaration given by the DECL. */ + +void +add_decl_expr (tree decl) +{ + tree r = build_stmt (DECL_EXPR, decl); + if (DECL_INITIAL (decl) + || (DECL_SIZE (decl) && TREE_SIDE_EFFECTS (DECL_SIZE (decl)))) + r = maybe_cleanup_point_expr_void (r); + add_stmt (r); +} + /* Nonzero if TYPE is an anonymous union or struct type. We have to use a flag for this because "A union for which objects or pointers are declared is not an anonymous union" [class.union]. */ @@ -333,43 +400,102 @@ anon_aggr_type_p (tree node) /* Finish a scope. */ -tree -do_poplevel (void) +static tree +do_poplevel (tree stmt_list) { - tree block = NULL_TREE; + tree block = NULL; if (stmts_are_full_exprs_p ()) - { - tree scope_stmts = NULL_TREE; + block = poplevel (kept_level_p (), 1, 0); - block = poplevel (kept_level_p (), 1, 0); - if (!processing_template_decl) - { - /* This needs to come after the poplevel so that partial scopes - are properly nested. */ - scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); - if (block) - { - SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block; - SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block; - } - } + stmt_list = pop_stmt_list (stmt_list); + + if (!processing_template_decl) + { + stmt_list = c_build_bind_expr (block, stmt_list); + /* ??? See c_end_compound_stmt re statement expressions. */ } - return block; + return stmt_list; } /* Begin a new scope. */ -void +static tree do_pushlevel (scope_kind sk) { + tree ret = push_stmt_list (); if (stmts_are_full_exprs_p ()) + begin_scope (sk, NULL); + return ret; +} + +/* Queue a cleanup. CLEANUP is an expression/statement to be executed + when the current scope is exited. EH_ONLY is true when this is not + meant to apply to normal control flow transfer. */ + +void +push_cleanup (tree decl, tree cleanup, bool eh_only) +{ + tree stmt = build_stmt (CLEANUP_STMT, NULL, cleanup, decl); + CLEANUP_EH_ONLY (stmt) = eh_only; + add_stmt (stmt); + CLEANUP_BODY (stmt) = push_stmt_list (); +} + +/* Begin a conditional that might contain a declaration. When generating + normal code, we want the declaration to appear before the statement + containing the conditional. When generating template code, we want the + conditional to be rendered as the raw DECL_EXPR. */ + +static void +begin_cond (tree *cond_p) +{ + if (processing_template_decl) + *cond_p = push_stmt_list (); +} + +/* Finish such a conditional. */ + +static void +finish_cond (tree *cond_p, tree expr) +{ + if (processing_template_decl) { - if (!processing_template_decl) - add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0); - begin_scope (sk, NULL); + tree cond = pop_stmt_list (*cond_p); + if (TREE_CODE (cond) == DECL_EXPR) + expr = cond; } + *cond_p = expr; +} + +/* If *COND_P specifies a conditional with a declaration, transform the + loop such that + while (A x = 42) { } + for (; A x = 42;) { } + becomes + while (true) { A x = 42; if (!x) break; } + for (;;) { A x = 42; if (!x) break; } + The statement list for BODY will be empty if the conditional did + not declare anything. */ + +static void +simplify_loop_decl_cond (tree *cond_p, tree body) +{ + tree cond, if_stmt; + + if (!TREE_SIDE_EFFECTS (body)) + return; + + cond = *cond_p; + *cond_p = 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 (if_stmt); } /* Finish a goto-statement. */ @@ -398,7 +524,7 @@ finish_goto_stmt (tree destination) check_goto (destination); - return add_stmt (build_stmt (GOTO_STMT, destination)); + return add_stmt (build_stmt (GOTO_EXPR, destination)); } /* COND is the condition-expression for an if, while, etc., @@ -430,11 +556,24 @@ finish_expr_stmt (tree expr) if (expr != NULL_TREE) { if (!processing_template_decl) - expr = convert_to_void (expr, "statement"); + { + if (warn_sequence_point) + verify_sequence_points (expr); + expr = convert_to_void (expr, "statement"); + } else if (!type_dependent_expression_p (expr)) convert_to_void (build_non_dependent_expr (expr), "statement"); - - r = add_stmt (build_stmt (EXPR_STMT, expr)); + + /* Simplification of inner statement expressions, compound exprs, + etc can result in us already having an EXPR_STMT. */ + if (TREE_CODE (expr) != CLEANUP_POINT_EXPR) + { + if (TREE_CODE (expr) != EXPR_STMT) + expr = build_stmt (EXPR_STMT, expr); + expr = maybe_cleanup_point_expr_void (expr); + } + + r = add_stmt (expr); } finish_stmt (); @@ -449,10 +588,11 @@ finish_expr_stmt (tree expr) tree begin_if_stmt (void) { - tree r; - do_pushlevel (sk_block); + tree r, scope; + scope = do_pushlevel (sk_block); r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE); - add_stmt (r); + TREE_CHAIN (r) = scope; + begin_cond (&IF_COND (r)); return r; } @@ -462,8 +602,9 @@ begin_if_stmt (void) void finish_if_stmt_cond (tree cond, tree if_stmt) { - cond = maybe_convert_cond (cond); - FINISH_COND (cond, if_stmt, IF_COND (if_stmt)); + finish_cond (&IF_COND (if_stmt), maybe_convert_cond (cond)); + add_stmt (if_stmt); + THEN_CLAUSE (if_stmt) = push_stmt_list (); } /* Finish the then-clause of an if-statement, which may be given by @@ -472,15 +613,16 @@ finish_if_stmt_cond (tree cond, tree if_stmt) tree finish_then_clause (tree if_stmt) { - RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt)); + THEN_CLAUSE (if_stmt) = pop_stmt_list (THEN_CLAUSE (if_stmt)); return if_stmt; } /* Begin the else-clause of an if-statement. */ -void -begin_else_clause (void) +void +begin_else_clause (tree if_stmt) { + ELSE_CLAUSE (if_stmt) = push_stmt_list (); } /* Finish the else-clause of an if-statement, which may be given by @@ -489,16 +631,18 @@ begin_else_clause (void) void finish_else_clause (tree if_stmt) { - RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt)); + ELSE_CLAUSE (if_stmt) = pop_stmt_list (ELSE_CLAUSE (if_stmt)); } /* Finish an if-statement. */ void -finish_if_stmt (void) +finish_if_stmt (tree if_stmt) { + tree scope = TREE_CHAIN (if_stmt); + TREE_CHAIN (if_stmt) = NULL; + add_stmt (do_poplevel (scope)); finish_stmt (); - do_poplevel (); } /* Begin a while-statement. Returns a newly created WHILE_STMT if @@ -510,7 +654,8 @@ begin_while_stmt (void) tree r; r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE); add_stmt (r); - do_pushlevel (sk_block); + WHILE_BODY (r) = do_pushlevel (sk_block); + begin_cond (&WHILE_COND (r)); return r; } @@ -520,30 +665,8 @@ begin_while_stmt (void) void finish_while_stmt_cond (tree cond, tree while_stmt) { - cond = maybe_convert_cond (cond); - if (processing_template_decl) - /* Don't mess with condition decls in a template. */ - FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt)); - else 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_cond (&WHILE_COND (while_stmt), maybe_convert_cond (cond)); + simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt)); } /* Finish a while-statement, which may be given by WHILE_STMT. */ @@ -551,8 +674,7 @@ finish_while_stmt_cond (tree cond, tree while_stmt) void finish_while_stmt (tree while_stmt) { - do_poplevel (); - RECHAIN_STMTS (while_stmt, WHILE_BODY (while_stmt)); + WHILE_BODY (while_stmt) = do_poplevel (WHILE_BODY (while_stmt)); finish_stmt (); } @@ -564,6 +686,7 @@ begin_do_stmt (void) { tree r = build_stmt (DO_STMT, NULL_TREE, NULL_TREE); add_stmt (r); + DO_BODY (r) = push_stmt_list (); return r; } @@ -572,7 +695,7 @@ begin_do_stmt (void) void finish_do_body (tree do_stmt) { - RECHAIN_STMTS (do_stmt, DO_BODY (do_stmt)); + DO_BODY (do_stmt) = pop_stmt_list (DO_BODY (do_stmt)); } /* Finish a do-statement, which may be given by DO_STMT, and whose @@ -597,16 +720,21 @@ finish_return_stmt (tree expr) expr = check_return_expr (expr); if (!processing_template_decl) { - if (DECL_DESTRUCTOR_P (current_function_decl)) + if (DECL_DESTRUCTOR_P (current_function_decl) + || (DECL_CONSTRUCTOR_P (current_function_decl) + && targetm.cxx.cdtor_returns_this ())) { /* Similarly, all destructors must run destructors for base-classes before returning. So, all returns in a destructor get sent to the DTOR_LABEL; finish_function emits code to return a value there. */ - return finish_goto_stmt (dtor_label); + return finish_goto_stmt (cdtor_label); } } - r = add_stmt (build_stmt (RETURN_STMT, expr)); + + r = build_stmt (RETURN_EXPR, expr); + r = maybe_cleanup_point_expr_void (r); + r = add_stmt (r); finish_stmt (); return r; @@ -621,10 +749,12 @@ begin_for_stmt (void) r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); - NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0; - if (NEW_FOR_SCOPE_P (r)) - do_pushlevel (sk_for); - add_stmt (r); + + if (flag_new_for_scope > 0) + TREE_CHAIN (r) = do_pushlevel (sk_for); + + if (processing_template_decl) + FOR_INIT_STMT (r) = push_stmt_list (); return r; } @@ -635,9 +765,11 @@ begin_for_stmt (void) void finish_for_init_stmt (tree for_stmt) { - if (last_tree != for_stmt) - RECHAIN_STMTS (for_stmt, FOR_INIT_STMT (for_stmt)); - do_pushlevel (sk_block); + if (processing_template_decl) + FOR_INIT_STMT (for_stmt) = pop_stmt_list (FOR_INIT_STMT (for_stmt)); + add_stmt (for_stmt); + FOR_BODY (for_stmt) = do_pushlevel (sk_block); + begin_cond (&FOR_COND (for_stmt)); } /* Finish the COND of a for-statement, which may be given by @@ -646,30 +778,8 @@ finish_for_init_stmt (tree for_stmt) void finish_for_cond (tree cond, tree for_stmt) { - cond = maybe_convert_cond (cond); - if (processing_template_decl) - /* Don't mess with condition decls in a template. */ - FINISH_COND (cond, for_stmt, FOR_COND (for_stmt)); - else 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_cond (&FOR_COND (for_stmt), maybe_convert_cond (cond)); + simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt)); } /* Finish the increment-EXPRESSION in a for-statement, which may be @@ -678,13 +788,24 @@ finish_for_cond (tree cond, tree for_stmt) void finish_for_expr (tree expr, tree for_stmt) { + if (!expr) + return; /* If EXPR is an overloaded function, issue an error; there is no context available to use to perform overload resolution. */ - if (expr && type_unknown_p (expr)) + if (type_unknown_p (expr)) { cxx_incomplete_type_error (expr, TREE_TYPE (expr)); expr = error_mark_node; } + if (!processing_template_decl) + { + if (warn_sequence_point) + verify_sequence_points (expr); + expr = convert_to_void (expr, "3rd expression in for"); + } + else if (!type_dependent_expression_p (expr)) + convert_to_void (build_non_dependent_expr (expr), "3rd expression in for"); + expr = maybe_cleanup_point_expr_void (expr); FOR_EXPR (for_stmt) = expr; } @@ -695,11 +816,16 @@ finish_for_expr (tree expr, tree for_stmt) void finish_for_stmt (tree for_stmt) { + FOR_BODY (for_stmt) = do_poplevel (FOR_BODY (for_stmt)); + /* Pop the scope for the body of the loop. */ - do_poplevel (); - RECHAIN_STMTS (for_stmt, FOR_BODY (for_stmt)); - if (NEW_FOR_SCOPE_P (for_stmt)) - do_poplevel (); + if (flag_new_for_scope > 0) + { + tree scope = TREE_CHAIN (for_stmt); + TREE_CHAIN (for_stmt) = NULL; + add_stmt (do_poplevel (scope)); + } + finish_stmt (); } @@ -725,10 +851,14 @@ finish_continue_stmt (void) tree begin_switch_stmt (void) { - tree r; - do_pushlevel (sk_block); + tree r, scope; + r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE); - add_stmt (r); + + scope = do_pushlevel (sk_block); + TREE_CHAIN (r) = scope; + begin_cond (&SWITCH_STMT_COND (r)); + return r; } @@ -756,7 +886,7 @@ finish_switch_cond (tree cond, tree switch_stmt) Integral promotions are performed. */ cond = perform_integral_promotions (cond); - cond = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (cond), cond)); + cond = maybe_cleanup_point_expr (cond); } if (cond != error_mark_node) @@ -766,14 +896,16 @@ finish_switch_cond (tree cond, tree switch_stmt) because if we did, int_fits_type_p would do the wrong thing when checking case values for being in range, and it's too hard to do the right thing. */ - if (TREE_UNSIGNED (TREE_TYPE (cond)) - == TREE_UNSIGNED (TREE_TYPE (index))) + if (TYPE_UNSIGNED (TREE_TYPE (cond)) + == TYPE_UNSIGNED (TREE_TYPE (index))) cond = index; } } - FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt)); - SWITCH_TYPE (switch_stmt) = orig_type; + finish_cond (&SWITCH_STMT_COND (switch_stmt), cond); + SWITCH_STMT_TYPE (switch_stmt) = orig_type; + add_stmt (switch_stmt); push_switch (switch_stmt); + SWITCH_STMT_BODY (switch_stmt) = push_stmt_list (); } /* Finish the body of a switch-statement, which may be given by @@ -782,60 +914,16 @@ finish_switch_cond (tree cond, tree switch_stmt) void finish_switch_stmt (tree switch_stmt) { - RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt)); + tree scope; + + SWITCH_STMT_BODY (switch_stmt) = + pop_stmt_list (SWITCH_STMT_BODY (switch_stmt)); pop_switch (); finish_stmt (); - do_poplevel (); -} - -/* Generate the RTL for T, which is a TRY_BLOCK. */ - -static void -genrtl_try_block (tree t) -{ - if (CLEANUP_P (t)) - { - expand_eh_region_start (); - expand_stmt (TRY_STMTS (t)); - expand_eh_region_end_cleanup (TRY_HANDLERS (t)); - } - else - { - if (!FN_TRY_BLOCK_P (t)) - emit_line_note (input_location); - - expand_eh_region_start (); - expand_stmt (TRY_STMTS (t)); - if (FN_TRY_BLOCK_P (t)) - { - expand_start_all_catch (); - in_function_try_handler = 1; - expand_stmt (TRY_HANDLERS (t)); - in_function_try_handler = 0; - expand_end_all_catch (); - } - else - { - expand_start_all_catch (); - expand_stmt (TRY_HANDLERS (t)); - expand_end_all_catch (); - } - } -} - -/* Generate the RTL for T, which is an EH_SPEC_BLOCK. */ - -static void -genrtl_eh_spec_block (tree t) -{ - expand_eh_region_start (); - expand_stmt (EH_SPEC_STMTS (t)); - expand_eh_region_end_allowed (EH_SPEC_RAISES (t), - build_call (call_unexpected_node, - tree_cons (NULL_TREE, - build_exc_ptr (), - NULL_TREE))); + scope = TREE_CHAIN (switch_stmt); + TREE_CHAIN (switch_stmt) = NULL; + add_stmt (do_poplevel (scope)); } /* Begin a try-block. Returns a newly-created TRY_BLOCK if @@ -846,6 +934,7 @@ begin_try_block (void) { tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE); add_stmt (r); + TRY_STMTS (r) = push_stmt_list (); return r; } @@ -854,9 +943,8 @@ begin_try_block (void) tree begin_function_try_block (void) { - tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE); + tree r = begin_try_block (); FN_TRY_BLOCK_P (r) = 1; - add_stmt (r); return r; } @@ -865,7 +953,8 @@ begin_function_try_block (void) void finish_try_block (tree try_block) { - RECHAIN_STMTS (try_block, TRY_STMTS (try_block)); + TRY_STMTS (try_block) = pop_stmt_list (TRY_STMTS (try_block)); + TRY_HANDLERS (try_block) = push_stmt_list (); } /* Finish the body of a cleanup try-block, which may be given by @@ -874,7 +963,7 @@ finish_try_block (tree try_block) void finish_cleanup_try_block (tree try_block) { - RECHAIN_STMTS (try_block, TRY_STMTS (try_block)); + TRY_STMTS (try_block) = pop_stmt_list (TRY_STMTS (try_block)); } /* Finish an implicitly generated try-block, with a cleanup is given @@ -892,16 +981,9 @@ finish_cleanup (tree cleanup, tree try_block) void finish_function_try_block (tree try_block) { - if (TREE_CHAIN (try_block) - && TREE_CODE (TREE_CHAIN (try_block)) == CTOR_INITIALIZER) - { - /* Chain the compound statement after the CTOR_INITIALIZER. */ - TREE_CHAIN (TREE_CHAIN (try_block)) = last_tree; - /* And make the CTOR_INITIALIZER the body of the try-block. */ - RECHAIN_STMTS (try_block, TRY_STMTS (try_block)); - } - else - RECHAIN_STMTS (try_block, TRY_STMTS (try_block)); + finish_try_block (try_block); + /* FIXME : something queer about CTOR_INITIALIZER somehow following + the try block, but moving it inside. */ in_function_try_handler = 1; } @@ -911,7 +993,7 @@ finish_function_try_block (tree try_block) void finish_handler_sequence (tree try_block) { - RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block)); + TRY_HANDLERS (try_block) = pop_stmt_list (TRY_HANDLERS (try_block)); check_handlers (TRY_HANDLERS (try_block)); } @@ -921,21 +1003,7 @@ void finish_function_handler_sequence (tree try_block) { in_function_try_handler = 0; - RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block)); - check_handlers (TRY_HANDLERS (try_block)); -} - -/* Generate the RTL for T, which is a HANDLER. */ - -static void -genrtl_handler (tree t) -{ - genrtl_do_pushlevel (); - if (!processing_template_decl) - expand_start_catch (HANDLER_TYPE (t)); - expand_stmt (HANDLER_BODY (t)); - if (!processing_template_decl) - expand_end_catch (); + finish_handler_sequence (try_block); } /* Begin a handler. Returns a HANDLER if appropriate. */ @@ -944,11 +1012,14 @@ tree begin_handler (void) { tree r; + r = build_stmt (HANDLER, NULL_TREE, NULL_TREE); add_stmt (r); + /* Create a binding level for the eh_info and the exception object cleanup. */ - do_pushlevel (sk_catch); + HANDLER_BODY (r) = do_pushlevel (sk_catch); + return r; } @@ -966,8 +1037,7 @@ finish_handler_parms (tree decl, tree handler) { decl = pushdecl (decl); decl = push_template_decl (decl); - add_decl_stmt (decl); - RECHAIN_STMTS (handler, HANDLER_PARMS (handler)); + HANDLER_PARMS (handler) = decl; type = TREE_TYPE (decl); } } @@ -987,155 +1057,176 @@ finish_handler (tree handler) { if (!processing_template_decl) expand_end_catch_block (); - do_poplevel (); - RECHAIN_STMTS (handler, HANDLER_BODY (handler)); + HANDLER_BODY (handler) = do_poplevel (HANDLER_BODY (handler)); } -/* Begin a compound-statement. If HAS_NO_SCOPE is true, the - compound-statement does not define a scope. Returns a new - COMPOUND_STMT. */ +/* Begin a compound statement. FLAGS contains some bits that control the + behavior and context. If BCS_NO_SCOPE is set, the compound statement + does not define a scope. If BCS_FN_BODY is set, this is the outermost + block of a function. If BCS_TRY_BLOCK is set, this is the block + created on behalf of a TRY statement. Returns a token to be passed to + finish_compound_stmt. */ tree -begin_compound_stmt (bool has_no_scope) +begin_compound_stmt (unsigned int flags) { - tree r; - int is_try = 0; - - r = build_stmt (COMPOUND_STMT, NULL_TREE); - - if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK) - is_try = 1; - - add_stmt (r); - if (has_no_scope) - COMPOUND_STMT_NO_SCOPE (r) = 1; + tree r; - last_expr_type = NULL_TREE; + if (flags & BCS_NO_SCOPE) + { + r = push_stmt_list (); + STATEMENT_LIST_NO_SCOPE (r) = 1; - if (!has_no_scope) - do_pushlevel (is_try ? sk_try : sk_block); + /* Normally, we try hard to keep the BLOCK for a statement-expression. + But, if it's a statement-expression with a scopeless block, there's + nothing to keep, and we don't want to accidentally keep a block + *inside* the scopeless block. */ + keep_next_level (false); + } else - /* Normally, we try hard to keep the BLOCK for a - statement-expression. But, if it's a statement-expression with - a scopeless block, there's nothing to keep, and we don't want - to accidentally keep a block *inside* the scopeless block. */ - keep_next_level (false); + r = do_pushlevel (flags & BCS_TRY_BLOCK ? sk_try : sk_block); + + /* When processing a template, we need to remember where the braces were, + so that we can set up identical scopes when instantiating the template + later. BIND_EXPR is a handy candidate for this. + Note that do_poplevel won't create a BIND_EXPR itself here (and thus + result in nested BIND_EXPRs), since we don't build BLOCK nodes when + processing templates. */ + if (processing_template_decl) + { + r = build3 (BIND_EXPR, NULL, NULL, r, NULL); + BIND_EXPR_TRY_BLOCK (r) = (flags & BCS_TRY_BLOCK) != 0; + BIND_EXPR_BODY_BLOCK (r) = (flags & BCS_FN_BODY) != 0; + TREE_SIDE_EFFECTS (r) = 1; + } return r; } -/* Finish a compound-statement, which is given by COMPOUND_STMT. */ +/* Finish a compound-statement, which is given by STMT. */ -tree -finish_compound_stmt (tree compound_stmt) +void +finish_compound_stmt (tree stmt) { - tree r; - tree t; - - if (COMPOUND_STMT_NO_SCOPE (compound_stmt)) - r = NULL_TREE; + if (TREE_CODE (stmt) == BIND_EXPR) + BIND_EXPR_BODY (stmt) = do_poplevel (BIND_EXPR_BODY (stmt)); + else if (STATEMENT_LIST_NO_SCOPE (stmt)) + stmt = pop_stmt_list (stmt); else - r = do_poplevel (); + { + /* Destroy any ObjC "super" receivers that may have been + created. */ + objc_clear_super_receiver (); - RECHAIN_STMTS (compound_stmt, COMPOUND_BODY (compound_stmt)); + stmt = do_poplevel (stmt); + } - /* When we call finish_stmt we will lose LAST_EXPR_TYPE. But, since - the precise purpose of that variable is store the type of the - last expression statement within the last compound statement, we - preserve the value. */ - t = last_expr_type; + /* ??? See c_end_compound_stmt wrt statement expressions. */ + add_stmt (stmt); finish_stmt (); - last_expr_type = t; - - return r; } -/* Finish an asm-statement, whose components are a CV_QUALIFIER, a - STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some - CLOBBERS. */ +/* Finish an asm-statement, whose components are a STRING, some + OUTPUT_OPERANDS, some INPUT_OPERANDS, and some CLOBBERS. Also note + whether the asm-statement should be considered volatile. */ tree -finish_asm_stmt (tree cv_qualifier, - tree string, - tree output_operands, - tree input_operands, - tree clobbers) +finish_asm_stmt (int volatile_p, tree string, tree output_operands, + tree input_operands, tree clobbers) { tree r; tree t; - if (cv_qualifier != NULL_TREE - && cv_qualifier != ridpointers[(int) RID_VOLATILE]) - { - warning ("%s qualifier ignored on asm", - IDENTIFIER_POINTER (cv_qualifier)); - cv_qualifier = NULL_TREE; - } - if (!processing_template_decl) { + int ninputs, noutputs; + const char *constraint; + const char **oconstraints; + bool allows_mem, allows_reg, is_inout; + tree operand; int i; - int ninputs; - int noutputs; - - for (t = input_operands; t; t = TREE_CHAIN (t)) - { - tree converted_operand - = decay_conversion (TREE_VALUE (t)); - - /* If the type of the operand hasn't been determined (e.g., - because it involves an overloaded function), then issue - an error message. There's no context available to - resolve the overloading. */ - if (TREE_TYPE (converted_operand) == unknown_type_node) - { - error ("type of asm operand `%E' could not be determined", - TREE_VALUE (t)); - converted_operand = error_mark_node; - } - TREE_VALUE (t) = converted_operand; - } ninputs = list_length (input_operands); noutputs = list_length (output_operands); + oconstraints = (const char **) alloca (noutputs * sizeof (char *)); + + string = resolve_asm_operand_names (string, output_operands, + input_operands); for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i) { - bool allows_mem; - bool allows_reg; - bool is_inout; - const char *constraint; - tree operand; + operand = TREE_VALUE (t); + + /* ??? Really, this should not be here. Users should be using a + proper lvalue, dammit. But there's a long history of using + casts in the output operands. In cases like longlong.h, this + becomes a primitive form of typechecking -- if the cast can be + removed, then the output operand had a type of the proper width; + otherwise we'll get an error. Gross, but ... */ + STRIP_NOPS (operand); + + if (!lvalue_or_else (operand, lv_asm)) + operand = error_mark_node; constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); - operand = TREE_VALUE (t); + oconstraints[i] = constraint; - if (!parse_output_constraint (&constraint, - i, ninputs, noutputs, - &allows_mem, - &allows_reg, - &is_inout)) + if (parse_output_constraint (&constraint, i, ninputs, noutputs, + &allows_mem, &allows_reg, &is_inout)) { - /* By marking this operand as erroneous, we will not try - to process this operand again in expand_asm_operands. */ - TREE_VALUE (t) = error_mark_node; - continue; + /* If the operand is going to end up in memory, + mark it addressable. */ + if (!allows_reg && !cxx_mark_addressable (operand)) + operand = error_mark_node; } + else + operand = error_mark_node; - /* If the operand is a DECL that is going to end up in - memory, assume it is addressable. This is a bit more - conservative than it would ideally be; the exact test is - buried deep in expand_asm_operands and depends on the - DECL_RTL for the OPERAND -- which we don't have at this - point. */ - if (!allows_reg && DECL_P (operand)) - cxx_mark_addressable (operand); + TREE_VALUE (t) = operand; + } + + for (i = 0, t = input_operands; t; ++i, t = TREE_CHAIN (t)) + { + constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); + operand = decay_conversion (TREE_VALUE (t)); + + /* If the type of the operand hasn't been determined (e.g., + because it involves an overloaded function), then issue + an error message. There's no context available to + resolve the overloading. */ + if (TREE_TYPE (operand) == unknown_type_node) + { + error ("type of asm operand %qE could not be determined", + TREE_VALUE (t)); + operand = error_mark_node; + } + + if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0, + oconstraints, &allows_mem, &allows_reg)) + { + /* If the operand is going to end up in memory, + mark it addressable. */ + if (!allows_reg && allows_mem) + { + /* Strip the nops as we allow this case. FIXME, this really + should be rejected or made deprecated. */ + STRIP_NOPS (operand); + if (!cxx_mark_addressable (operand)) + operand = error_mark_node; + } + } + else + operand = error_mark_node; + + TREE_VALUE (t) = operand; } } - r = build_stmt (ASM_STMT, cv_qualifier, string, + r = build_stmt (ASM_EXPR, string, output_operands, input_operands, clobbers); + ASM_VOLATILE_P (r) = volatile_p; + r = maybe_cleanup_point_expr_void (r); return add_stmt (r); } @@ -1145,7 +1236,7 @@ tree finish_label_stmt (tree name) { tree decl = define_label (input_location, name); - return add_stmt (build_stmt (LABEL_STMT, decl)); + return add_stmt (build_stmt (LABEL_EXPR, decl)); } /* Finish a series of declarations for local labels. G++ allows users @@ -1156,7 +1247,7 @@ void finish_label_decl (tree name) { tree decl = declare_local_label (name); - add_decl_stmt (decl); + add_decl_expr (decl); } /* When DECL goes out of scope, make sure that CLEANUP is executed. */ @@ -1164,7 +1255,7 @@ finish_label_decl (tree name) void finish_decl_cleanup (tree decl, tree cleanup) { - add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup)); + push_cleanup (decl, cleanup, false); } /* If the current scope exits with an exception, run CLEANUP. */ @@ -1172,9 +1263,7 @@ finish_decl_cleanup (tree decl, tree cleanup) void finish_eh_cleanup (tree cleanup) { - tree r = build_stmt (CLEANUP_STMT, NULL_TREE, cleanup); - CLEANUP_EH_ONLY (r) = 1; - add_stmt (r); + push_cleanup (NULL, cleanup, true); } /* The MEM_INITS is a list of mem-initializers, in reverse of the @@ -1194,27 +1283,23 @@ finish_mem_initializers (tree mem_inits) emit_mem_initializers (mem_inits); } -/* Returns the stack of SCOPE_STMTs for the current function. */ - -tree * -current_scope_stmt_stack (void) -{ - return &cfun->language->base.x_scope_stmt_stack; -} - /* Finish a parenthesized expression EXPR. */ tree finish_parenthesized_expr (tree expr) { - if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expr)))) + if (EXPR_P (expr)) /* This inhibits warnings in c_common_truthvalue_conversion. */ - C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK); + TREE_NO_WARNING (expr) = 1; if (TREE_CODE (expr) == OFFSET_REF) /* [expr.unary.op]/3 The qualified id of a pointer-to-member must not be enclosed in parentheses. */ PTRMEM_OK_P (expr) = 0; + + if (TREE_CODE (expr) == STRING_CST) + PAREN_STRING_LITERAL_P (expr) = 1; + return expr; } @@ -1224,16 +1309,16 @@ finish_parenthesized_expr (tree expr) tree finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) { - my_friendly_assert (TREE_CODE (decl) == FIELD_DECL, 20020909); + gcc_assert (TREE_CODE (decl) == FIELD_DECL); if (!object) { if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) - cp_error_at ("invalid use of member `%D' in static member function", + cp_error_at ("invalid use of member %qD in static member function", decl); else - cp_error_at ("invalid use of non-static data member `%D'", decl); + cp_error_at ("invalid use of non-static data member %qD", decl); error ("from this location"); return error_mark_node; @@ -1257,7 +1342,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) type = cp_build_qualified_type (type, quals); } - return build_min (COMPONENT_REF, type, object, decl); + return build_min (COMPONENT_REF, type, object, decl, NULL_TREE); } else { @@ -1272,7 +1357,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) if (!access_type) { - cp_error_at ("object missing in reference to `%D'", decl); + cp_error_at ("object missing in reference to %qD", decl); error ("from this location"); return error_mark_node; } @@ -1315,6 +1400,10 @@ check_accessibility_of_qualified_id (tree decl, { tree scope; tree qualifying_type = NULL_TREE; + + /* If we're not checking, return immediately. */ + if (deferred_access_no_check) + return; /* Determine the SCOPE of DECL. */ scope = context_for_name_lookup (decl); @@ -1355,7 +1444,9 @@ check_accessibility_of_qualified_id (tree decl, its bases. */ qualifying_type = currently_open_derived_class (scope); - if (qualifying_type) + if (qualifying_type && IS_AGGR_TYPE_CODE (TREE_CODE (qualifying_type))) + /* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM + or similar in a default argument value. */ perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl); } @@ -1388,19 +1479,16 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, qualifying_class); else if (BASELINK_P (expr) && !processing_template_decl) { - tree fn; tree fns; /* See if any of the functions are non-static members. */ fns = BASELINK_FUNCTIONS (expr); if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) fns = TREE_OPERAND (fns, 0); - for (fn = fns; fn; fn = OVL_NEXT (fn)) - if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) - break; /* If so, the expression may be relative to the current class. */ - if (fn && current_class_type + if (!shared_member_p (fns) + && current_class_type && DERIVED_FROM_P (qualifying_class, current_class_type)) expr = (build_class_member_access_expr (maybe_dummy_object (qualifying_class, NULL), @@ -1422,17 +1510,7 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, tree begin_stmt_expr (void) { - /* If we're outside a function, we won't have a statement-tree to - work with. But, if we see a statement-expression we need to - create one. */ - if (! cfun && !last_tree) - begin_stmt_tree (&scope_chain->x_saved_tree); - - last_expr_type = NULL_TREE; - - keep_next_level (true); - - return last_tree; + return push_stmt_list (); } /* Process the final expression of a statement expression. EXPR can be @@ -1441,24 +1519,24 @@ begin_stmt_expr (void) expression. */ tree -finish_stmt_expr_expr (tree expr) +finish_stmt_expr_expr (tree expr, tree stmt_expr) { tree result = NULL_TREE; - tree type = void_type_node; if (expr) { - type = TREE_TYPE (expr); - if (!processing_template_decl && !VOID_TYPE_P (TREE_TYPE (expr))) { + tree type = TREE_TYPE (expr); + if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == FUNCTION_TYPE) expr = decay_conversion (expr); - expr = convert_from_reference (expr); expr = require_complete_type (expr); + type = TREE_TYPE (expr); + /* Build a TARGET_EXPR for this aggregate. finish_stmt_expr will then pull it apart so the lifetime of the target is within the scope of the expression containing this statement @@ -1473,24 +1551,25 @@ finish_stmt_expr_expr (tree expr) expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), - TYPE_BINFO (type), LOOKUP_NORMAL); + type, LOOKUP_NORMAL); expr = build_cplus_new (type, expr); - my_friendly_assert (TREE_CODE (expr) == TARGET_EXPR, 20030729); + gcc_assert (TREE_CODE (expr) == TARGET_EXPR); } } if (expr != error_mark_node) { result = build_stmt (EXPR_STMT, expr); + EXPR_STMT_STMT_EXPR_RESULT (result) = 1; add_stmt (result); } } finish_stmt (); - /* Remember the last expression so that finish_stmt_expr can pull it - apart. */ - last_expr_type = result ? result : void_type_node; + /* Remember the last expression so that finish_stmt_expr + can pull it apart. */ + TREE_TYPE (stmt_expr) = result; return result; } @@ -1500,58 +1579,97 @@ finish_stmt_expr_expr (tree expr) representing the statement-expression. */ tree -finish_stmt_expr (tree rtl_expr, bool has_no_scope) +finish_stmt_expr (tree stmt_expr, bool has_no_scope) { - tree result; - tree result_stmt = last_expr_type; - tree type; - - if (!last_expr_type) + tree result, result_stmt, type; + tree *result_stmt_p = NULL; + + result_stmt = TREE_TYPE (stmt_expr); + TREE_TYPE (stmt_expr) = void_type_node; + result = pop_stmt_list (stmt_expr); + + if (!result_stmt || VOID_TYPE_P (result_stmt)) type = void_type_node; else { - if (result_stmt == void_type_node) + /* We need to search the statement expression for the result_stmt, + since we'll need to replace it entirely. */ + tree t; + result_stmt_p = &result; + while (1) { - type = void_type_node; - result_stmt = NULL_TREE; + t = *result_stmt_p; + if (t == result_stmt) + break; + + switch (TREE_CODE (t)) + { + case STATEMENT_LIST: + { + tree_stmt_iterator i = tsi_last (t); + result_stmt_p = tsi_stmt_ptr (i); + break; + } + case BIND_EXPR: + result_stmt_p = &BIND_EXPR_BODY (t); + break; + case TRY_FINALLY_EXPR: + case TRY_CATCH_EXPR: + case CLEANUP_STMT: + result_stmt_p = &TREE_OPERAND (t, 0); + break; + default: + gcc_unreachable (); + } } - else - type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt)); + type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt)); } - - result = build_min (STMT_EXPR, type, last_tree); - TREE_SIDE_EFFECTS (result) = 1; - STMT_EXPR_NO_SCOPE (result) = has_no_scope; - - last_expr_type = NULL_TREE; - - /* Remove the compound statement from the tree structure; it is - now saved in the STMT_EXPR. */ - last_tree = rtl_expr; - TREE_CHAIN (last_tree) = NULL_TREE; - - /* If we created a statement-tree for this statement-expression, - remove it now. */ - if (! cfun - && TREE_CHAIN (scope_chain->x_saved_tree) == NULL_TREE) - finish_stmt_tree (&scope_chain->x_saved_tree); if (processing_template_decl) - return result; - - if (!VOID_TYPE_P (type)) + { + result = build_min (STMT_EXPR, type, result); + TREE_SIDE_EFFECTS (result) = 1; + STMT_EXPR_NO_SCOPE (result) = has_no_scope; + } + else if (!VOID_TYPE_P (type)) { /* Pull out the TARGET_EXPR that is the final expression. Put the target's init_expr as the final expression and then put the statement expression itself as the target's init expr. Finally, return the target expression. */ - tree last_expr = EXPR_STMT_EXPR (result_stmt); - - my_friendly_assert (TREE_CODE (last_expr) == TARGET_EXPR, 20030729); - EXPR_STMT_EXPR (result_stmt) = TREE_OPERAND (last_expr, 1); - TREE_OPERAND (last_expr, 1) = result; - result = last_expr; + tree init, target_expr = EXPR_STMT_EXPR (result_stmt); + gcc_assert (TREE_CODE (target_expr) == TARGET_EXPR); + + /* The initializer will be void if the initialization is done by + AGGR_INIT_EXPR; propagate that out to the statement-expression as + a whole. */ + init = TREE_OPERAND (target_expr, 1); + type = TREE_TYPE (init); + + init = maybe_cleanup_point_expr (init); + *result_stmt_p = init; + + if (VOID_TYPE_P (type)) + /* No frobbing needed. */; + else if (TREE_CODE (result) == BIND_EXPR) + { + /* The BIND_EXPR created in finish_compound_stmt is void; if we're + returning a value directly, give it the appropriate type. */ + if (VOID_TYPE_P (TREE_TYPE (result))) + TREE_TYPE (result) = type; + else + gcc_assert (same_type_p (TREE_TYPE (result), type)); + } + else if (TREE_CODE (result) == STATEMENT_LIST) + /* We need to wrap a STATEMENT_LIST in a BIND_EXPR so it can have a + type other than void. FIXME why can't we just return a value + from STATEMENT_LIST? */ + result = build3 (BIND_EXPR, type, NULL, result, NULL); + + TREE_OPERAND (target_expr, 1) = result; + result = target_expr; } + return result; } @@ -1618,8 +1736,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) return error_mark_node; /* ARGS should be a list of arguments. */ - my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST, - 20020712); + gcc_assert (!args || TREE_CODE (args) == TREE_LIST); orig_fn = fn; orig_args = args; @@ -1629,7 +1746,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) if (type_dependent_expression_p (fn) || any_type_dependent_arguments_p (args)) { - result = build_nt (CALL_EXPR, fn, args); + result = build_nt (CALL_EXPR, fn, args, NULL_TREE); KOENIG_LOOKUP_P (result) = koenig_p; return result; } @@ -1704,7 +1821,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) if (processing_template_decl) { if (type_dependent_expression_p (object)) - return build_nt (CALL_EXPR, orig_fn, orig_args); + return build_nt (CALL_EXPR, orig_fn, orig_args, NULL_TREE); object = build_non_dependent_expr (object); } @@ -1729,14 +1846,16 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) else if (CLASS_TYPE_P (TREE_TYPE (fn))) /* If the "function" is really an object of class type, it might have an overloaded `operator ()'. */ - result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE); + result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE, + /*overloaded_p=*/NULL); if (!result) /* A call where the function is unknown. */ result = build_function_call (fn, args); if (processing_template_decl) { - result = build (CALL_EXPR, TREE_TYPE (result), orig_fn, orig_args); + result = build3 (CALL_EXPR, TREE_TYPE (result), orig_fn, + orig_args, NULL_TREE); KOENIG_LOOKUP_P (result) = koenig_p; } return result; @@ -1766,15 +1885,15 @@ finish_this_expr (void) else if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) { - error ("`this' is unavailable for static member functions"); + error ("% is unavailable for static member functions"); result = error_mark_node; } else { if (current_function_decl) - error ("invalid use of `this' in non-member function"); + error ("invalid use of % in non-member function"); else - error ("invalid use of `this' at top level"); + error ("invalid use of % at top level"); result = error_mark_node; } @@ -1792,7 +1911,7 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor) if (destructor == error_mark_node) return error_mark_node; - my_friendly_assert (TYPE_P (destructor), 20010905); + gcc_assert (TYPE_P (destructor)); if (!processing_template_decl) { @@ -1802,14 +1921,28 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor) return error_mark_node; } - if (!same_type_p (TREE_TYPE (object), destructor)) + /* [expr.pseudo] says both: + + The type designated by the pseudo-destructor-name shall be + the same as the object type. + + and: + + The cv-unqualified versions of the object type and of the + type designated by the pseudo-destructor-name shall be the + same type. + + We implement the more generous second sentence, since that is + what most other compilers do. */ + if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object), + destructor)) { - error ("`%E' is not of type `%T'", object, destructor); + error ("%qE is not of type %qT", object, destructor); return error_mark_node; } } - return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope, destructor); + return build3 (PSEUDO_DTOR_EXPR, void_type_node, object, scope, destructor); } /* Finish an expression of the form CODE EXPR. */ @@ -1823,9 +1956,14 @@ finish_unary_op_expr (enum tree_code code, tree expr) setting TREE_NEGATED_INT. */ if (code == NEGATE_EXPR && TREE_CODE (expr) == INTEGER_CST && TREE_CODE (result) == INTEGER_CST - && !TREE_UNSIGNED (TREE_TYPE (result)) + && !TYPE_UNSIGNED (TREE_TYPE (result)) && INT_CST_LT (result, integer_zero_node)) - TREE_NEGATED_INT (result) = 1; + { + /* RESULT may be a cached INTEGER_CST, so we must copy it before + setting TREE_NEGATED_INT. */ + result = copy_node (result); + TREE_NEGATED_INT (result) = 1; + } overflow_warning (result); return result; } @@ -1875,23 +2013,6 @@ finish_fname (tree id) return decl; } -/* Begin a function definition declared with DECL_SPECS, ATTRIBUTES, - and DECLARATOR. Returns nonzero if the function-declaration is - valid. */ - -int -begin_function_definition (tree decl_specs, tree attributes, tree declarator) -{ - if (!start_function (decl_specs, declarator, attributes, SF_DEFAULT)) - return 0; - - /* The things we're about to see are not directly qualified by any - template headers we've seen thus far. */ - reset_specialization (); - - return 1; -} - /* Finish a translation unit. */ void @@ -1915,7 +2036,7 @@ finish_template_type_parm (tree aggr, tree identifier) { if (aggr != class_type_node) { - pedwarn ("template type parameters must use the keyword `class' or `typename'"); + pedwarn ("template type parameters must use the keyword % or %"); aggr = class_type_node; } @@ -1935,7 +2056,7 @@ finish_template_template_parm (tree aggr, tree identifier) DECL_ARTIFICIAL (decl) = 1; end_template_decl (); - my_friendly_assert (DECL_TEMPLATE_PARMS (tmpl), 20010110); + gcc_assert (DECL_TEMPLATE_PARMS (tmpl)); return finish_template_type_parm (aggr, tmpl); } @@ -1959,10 +2080,10 @@ check_template_template_default_arg (tree argument) that the user is using a template instantiation. */ if (CLASSTYPE_TEMPLATE_INFO (t) && CLASSTYPE_TEMPLATE_INSTANTIATION (t)) - error ("invalid use of type `%T' as a default value for a " + error ("invalid use of type %qT as a default value for a " "template template-parameter", t); else - error ("invalid use of `%D' as a default value for a template " + error ("invalid use of %qD as a default value for a template " "template-parameter", argument); } else @@ -1973,24 +2094,6 @@ check_template_template_default_arg (tree argument) return argument; } -/* Finish a parameter list, indicated by PARMS. If ELLIPSIS is - nonzero, the parameter list was terminated by a `...'. */ - -tree -finish_parmlist (tree parms, int ellipsis) -{ - if (parms) - { - /* We mark the PARMS as a parmlist so that declarator processing can - disambiguate certain constructs. */ - TREE_PARMLIST (parms) = 1; - /* We do not append void_list_node here, but leave it to grokparms - to do that. */ - PARMLIST_ELLIPSIS_P (parms) = ellipsis; - } - return parms; -} - /* Begin a class definition, as indicated by T. */ tree @@ -2001,7 +2104,7 @@ begin_class_definition (tree t) if (processing_template_parmlist) { - error ("definition of `%#T' inside template parameter list", t); + error ("definition of %q#T inside template parameter list", t); return error_mark_node; } /* A non-implicit typename comes from code like: @@ -2012,7 +2115,7 @@ begin_class_definition (tree t) This is erroneous. */ else if (TREE_CODE (t) == TYPENAME_TYPE) { - error ("invalid definition of qualified type `%T'", t); + error ("invalid definition of qualified type %qT", t); t = error_mark_node; } @@ -2022,15 +2125,6 @@ begin_class_definition (tree t) pushtag (make_anon_name (), t, 0); } - /* If this type was already complete, and we see another definition, - that's an error. */ - if (COMPLETE_TYPE_P (t)) - { - error ("redefinition of `%#T'", t); - cp_error_at ("previous definition of `%#T'", t); - return error_mark_node; - } - /* Update the location of the decl. */ DECL_SOURCE_LOCATION (TYPE_NAME (t)) = input_location; @@ -2042,15 +2136,25 @@ begin_class_definition (tree t) maybe_process_partial_specialization (t); pushclass (t); TYPE_BEING_DEFINED (t) = 1; - TYPE_PACKED (t) = flag_pack_struct; + if (flag_pack_struct) + { + tree v; + TYPE_PACKED (t) = 1; + /* Even though the type is being defined for the first time + here, there might have been a forward declaration, so there + might be cv-qualified variants of T. */ + for (v = TYPE_NEXT_VARIANT (t); v; v = TYPE_NEXT_VARIANT (v)) + TYPE_PACKED (v) = 1; + } /* Reset the interface data, at the earliest possible moment, as it might have been set via a class foo; before. */ if (! TYPE_ANONYMOUS_P (t)) { - CLASSTYPE_INTERFACE_ONLY (t) = interface_only; + struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename)); + CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only; SET_CLASSTYPE_INTERFACE_UNKNOWN_X - (t, interface_unknown); + (t, finfo->interface_unknown); } reset_specialization(); @@ -2074,7 +2178,7 @@ finish_member_declaration (tree decl) return; /* We should see only one DECL at a time. */ - my_friendly_assert (TREE_CHAIN (decl) == NULL_TREE, 0); + gcc_assert (TREE_CHAIN (decl) == NULL_TREE); /* Set up access control for DECL. */ TREE_PRIVATE (decl) @@ -2105,7 +2209,7 @@ finish_member_declaration (tree decl) { /* We also need to add this function to the CLASSTYPE_METHOD_VEC. */ - add_method (current_class_type, decl, /*error_p=*/0); + add_method (current_class_type, decl); TREE_CHAIN (decl) = TYPE_METHODS (current_class_type); TYPE_METHODS (current_class_type) = decl; @@ -2146,36 +2250,40 @@ finish_member_declaration (tree decl) maybe_add_class_template_decl_list (current_class_type, decl, /*friend_p=*/0); } + + if (pch_file) + note_decl_for_pch (decl); } -/* Finish processing the declaration of a member class template - TYPES whose template parameters are given by PARMS. */ +/* DECL has been declared while we are building a PCH file. Perform + actions that we might normally undertake lazily, but which can be + performed now so that they do not have to be performed in + translation units which include the PCH file. */ -tree -finish_member_class_template (tree types) +void +note_decl_for_pch (tree decl) { - tree t; + gcc_assert (pch_file); - /* 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)); - - grok_x_components (types); - 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; + /* A non-template inline function with external linkage will always + be COMDAT. As we must eventually determine the linkage of all + functions, and as that causes writes to the data mapped in from + the PCH file, it's advantageous to mark the functions at this + point. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && TREE_PUBLIC (decl) + && DECL_DECLARED_INLINE_P (decl) + && !DECL_IMPLICIT_INSTANTIATION (decl)) + { + comdat_linkage (decl); + DECL_INTERFACE_KNOWN (decl) = 1; + } - finish_member_template_decl (types); - - /* As with other component type declarations, we do - not store the new DECL on the list of - component_decls. */ - return NULL_TREE; + /* There's a good chance that we'll have to mangle names at some + point, even if only for emission in debugging information. */ + if (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL) + mangle_decl (decl); } /* Finish processing a complete template declaration. The PARMS are @@ -2213,7 +2321,8 @@ finish_template_type (tree name, tree args, int entering_scope) Return a TREE_LIST containing the ACCESS_SPECIFIER and the BASE_CLASS, or NULL_TREE if an error occurred. The ACCESS_SPECIFIER is one of - access_{default,public,protected_private}[_virtual]_node.*/ + access_{default,public,protected_private}_node. For a virtual base + we set TREE_TYPE. */ tree finish_base_specifier (tree base, tree access, bool virtual_p) @@ -2231,57 +2340,39 @@ finish_base_specifier (tree base, tree access, bool virtual_p) { if (cp_type_quals (base) != 0) { - error ("base class `%T' has cv qualifiers", base); + error ("base class %qT has cv qualifiers", base); base = TYPE_MAIN_VARIANT (base); } result = build_tree_list (access, base); - TREE_VIA_VIRTUAL (result) = virtual_p; + if (virtual_p) + TREE_TYPE (result) = integer_type_node; } return result; } -/* Called when multiple declarators are processed. If that is not - permitted in this context, an error is issued. */ +/* Issue a diagnostic that NAME cannot be found in SCOPE. DECL is + what we found when we tried to do the lookup. */ void -check_multiple_declarators (void) -{ - /* [temp] - - In a template-declaration, explicit specialization, or explicit - instantiation the init-declarator-list in the declaration shall - contain at most one declarator. - - We don't just use PROCESSING_TEMPLATE_DECL for the first - condition since that would disallow the perfectly valid code, - like `template struct S { int i, j; };'. */ - if (at_function_scope_p ()) - /* It's OK to write `template void f() { int i, j;}'. */ - return; - - if (PROCESSING_REAL_TEMPLATE_DECL_P () - || processing_explicit_instantiation - || processing_specialization) - error ("multiple declarators in template declaration"); -} - -/* Issue a diagnostic that NAME cannot be found in SCOPE. */ - -void -qualified_name_lookup_error (tree scope, tree name) +qualified_name_lookup_error (tree scope, tree name, tree decl) { if (TYPE_P (scope)) { if (!COMPLETE_TYPE_P (scope)) - error ("incomplete type `%T' used in nested name specifier", scope); + error ("incomplete type %qT used in nested name specifier", scope); + else if (TREE_CODE (decl) == TREE_LIST) + { + error ("reference to %<%T::%D%> is ambiguous", scope, name); + print_candidates (decl); + } else - error ("`%D' is not a member of `%T'", name, scope); + error ("%qD is not a member of %qT", name, scope); } else if (scope != global_namespace) - error ("`%D' is not a member of `%D'", name, scope); + error ("%qD is not a member of %qD", name, scope); else - error ("`::%D' has not been declared", name); + error ("%<::%D%> has not been declared", name); } /* ID_EXPRESSION is a representation of parsed, but unprocessed, @@ -2340,12 +2431,17 @@ finish_id_expression (tree id_expression, if (decl == error_mark_node) { /* Name lookup failed. */ - if (scope && (!TYPE_P (scope) || !dependent_type_p (scope))) + if (scope + && (!TYPE_P (scope) + || (!dependent_type_p (scope) + && !(TREE_CODE (id_expression) == IDENTIFIER_NODE + && IDENTIFIER_TYPENAME_P (id_expression) + && dependent_type_p (TREE_TYPE (id_expression)))))) { - /* Qualified name lookup failed, and the qualifying name - was not a dependent type. That is always an - error. */ - qualified_name_lookup_error (scope, id_expression); + /* If the qualifying type is non-dependent (and the name + does not name a conversion operator to a dependent + type), issue an error. */ + qualified_name_lookup_error (scope, id_expression, decl); return error_mark_node; } else if (!scope) @@ -2354,6 +2450,8 @@ finish_id_expression (tree id_expression, *idk = CP_ID_KIND_UNQUALIFIED; return id_expression; } + else + decl = id_expression; } /* If DECL is a variable that would be out of scope under ANSI/ISO rules, but in scope in the ARM, name lookup @@ -2389,20 +2487,24 @@ finish_id_expression (tree id_expression, if ((TREE_CODE (decl) == CONST_DECL && DECL_TEMPLATE_PARM_P (decl)) || TREE_CODE (decl) == TEMPLATE_PARM_INDEX) { + tree r; + *idk = CP_ID_KIND_NONE; if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX) decl = TEMPLATE_PARM_DECL (decl); + r = convert_from_reference (DECL_INITIAL (decl)); + if (integral_constant_expression_p && !dependent_type_p (TREE_TYPE (decl)) - && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))) + && !(INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (r)))) { if (!allow_non_integral_constant_expression_p) - error ("template parameter `%D' of type `%T' is not allowed in " + error ("template parameter %qD of type %qT is not allowed in " "an integral constant expression because it is not of " "integral or enumeration type", decl, TREE_TYPE (decl)); *non_integral_constant_expression_p = true; } - return DECL_INITIAL (decl); + return r; } /* Similarly, we resolve enumeration constants to their underlying values. */ @@ -2509,67 +2611,68 @@ finish_id_expression (tree id_expression, if (TYPE_P (scope) && dependent_type_p (scope)) return build_nt (SCOPE_REF, scope, id_expression); else if (TYPE_P (scope) && DECL_P (decl)) - return build (SCOPE_REF, TREE_TYPE (decl), scope, - id_expression); + return convert_from_reference + (build2 (SCOPE_REF, TREE_TYPE (decl), scope, id_expression)); else - return decl; + return convert_from_reference (decl); } /* A TEMPLATE_ID already contains all the information we need. */ if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR) return id_expression; - /* Since this name was dependent, the expression isn't - constant -- yet. No error is issued because it might be - constant when things are instantiated. */ - if (integral_constant_expression_p) - *non_integral_constant_expression_p = true; *idk = CP_ID_KIND_UNQUALIFIED_DEPENDENT; /* If we found a variable, then name lookup during the instantiation will always resolve to the same VAR_DECL (or an instantiation thereof). */ - if (TREE_CODE (decl) == VAR_DECL) - return decl; + if (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL) + return convert_from_reference (decl); + /* The same is true for FIELD_DECL, but we also need to + make sure that the syntax is correct. */ + else if (TREE_CODE (decl) == FIELD_DECL) + { + /* Since SCOPE is NULL here, this is an unqualified name. + Access checking has been performed during name lookup + already. Turn off checking to avoid duplicate errors. */ + push_deferring_access_checks (dk_no_check); + decl = finish_non_static_data_member + (decl, current_class_ref, + /*qualifying_scope=*/NULL_TREE); + pop_deferring_access_checks (); + return decl; + } return id_expression; } /* Only certain kinds of names are allowed in constant - expression. Enumerators and template parameters - have already been handled above. */ - if (integral_constant_expression_p) + expression. Enumerators and template parameters have already + been handled above. */ + if (integral_constant_expression_p + && ! DECL_INTEGRAL_CONSTANT_VAR_P (decl) + && ! builtin_valid_in_constant_expr_p (decl)) { - /* Const variables or static data members of integral or - enumeration types initialized with constant expressions - are OK. */ - if (TREE_CODE (decl) == VAR_DECL - && CP_TYPE_CONST_P (TREE_TYPE (decl)) - && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)) - && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) - ; - else + if (!allow_non_integral_constant_expression_p) { - if (!allow_non_integral_constant_expression_p) - { - error ("`%D' cannot appear in a constant-expression", decl); - return error_mark_node; - } - *non_integral_constant_expression_p = true; + error ("%qD cannot appear in a constant-expression", decl); + return error_mark_node; } + *non_integral_constant_expression_p = true; } if (TREE_CODE (decl) == NAMESPACE_DECL) { - error ("use of namespace `%D' as expression", decl); + error ("use of namespace %qD as expression", decl); return error_mark_node; } else if (DECL_CLASS_TEMPLATE_P (decl)) { - error ("use of class template `%T' as expression", decl); + error ("use of class template %qT as expression", decl); return error_mark_node; } else if (TREE_CODE (decl) == TREE_LIST) { /* Ambiguous reference to base members. */ - error ("request for member `%D' is ambiguous in " + error ("request for member %qD is ambiguous in " "multiple inheritance lattice", id_expression); print_candidates (decl); return error_mark_node; @@ -2592,14 +2695,26 @@ finish_id_expression (tree id_expression, if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl)) *qualifying_class = scope; - else if (!processing_template_decl) - decl = convert_from_reference (decl); - else if (TYPE_P (scope)) - decl = build (SCOPE_REF, TREE_TYPE (decl), scope, decl); + else + { + tree r = convert_from_reference (decl); + + if (processing_template_decl + && TYPE_P (scope)) + r = build2 (SCOPE_REF, TREE_TYPE (r), scope, decl); + decl = r; + } } else if (TREE_CODE (decl) == FIELD_DECL) - decl = finish_non_static_data_member (decl, current_class_ref, - /*qualifying_scope=*/NULL_TREE); + { + /* Since SCOPE is NULL here, this is an unqualified name. + Access checking has been performed during name lookup + already. Turn off checking to avoid duplicate errors. */ + push_deferring_access_checks (dk_no_check); + decl = finish_non_static_data_member (decl, current_class_ref, + /*qualifying_scope=*/NULL_TREE); + pop_deferring_access_checks (); + } else if (is_overloaded_fn (decl)) { tree first_fn = OVL_CURRENT (decl); @@ -2611,7 +2726,8 @@ finish_id_expression (tree id_expression, mark_used (first_fn); if (TREE_CODE (first_fn) == FUNCTION_DECL - && DECL_FUNCTION_MEMBER_P (first_fn)) + && DECL_FUNCTION_MEMBER_P (first_fn) + && !shared_member_p (decl)) { /* A set of member functions. */ decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0); @@ -2631,8 +2747,8 @@ finish_id_expression (tree id_expression, { error ("use of %s from containing function", (TREE_CODE (decl) == VAR_DECL - ? "`auto' variable" : "parameter")); - cp_error_at (" `%#D' declared here", decl); + ? "% variable" : "parameter")); + cp_error_at (" %q#D declared here", decl); return error_mark_node; } } @@ -2647,14 +2763,13 @@ finish_id_expression (tree id_expression, perform_or_defer_access_check (TYPE_BINFO (path), decl); } - if (! processing_template_decl) - decl = convert_from_reference (decl); + decl = convert_from_reference (decl); } /* Resolve references to variables of anonymous unions into COMPONENT_REFs. */ if (TREE_CODE (decl) == ALIAS_DECL) - decl = DECL_INITIAL (decl); + decl = unshare_expr (DECL_INITIAL (decl)); } if (TREE_DEPRECATED (decl)) @@ -2674,7 +2789,7 @@ finish_typeof (tree expr) if (type_dependent_expression_p (expr)) { type = make_aggr_type (TYPEOF_TYPE); - TYPE_FIELDS (type) = expr; + TYPEOF_TYPE_EXPR (type) = expr; return type; } @@ -2683,44 +2798,15 @@ finish_typeof (tree expr) if (!type || type == unknown_type_node) { - error ("type of `%E' is unknown", expr); + error ("type of %qE is unknown", expr); return error_mark_node; } return type; } -/* Generate RTL for the statement T, and its substatements, and any - other statements at its nesting level. */ - -static void -cp_expand_stmt (tree t) -{ - switch (TREE_CODE (t)) - { - case TRY_BLOCK: - genrtl_try_block (t); - break; - - case EH_SPEC_BLOCK: - genrtl_eh_spec_block (t); - break; - - case HANDLER: - genrtl_handler (t); - break; - - case USING_STMT: - break; - - default: - abort (); - break; - } -} - /* Called from expand_body via walk_tree. Replace all AGGR_INIT_EXPRs - will equivalent CALL_EXPRs. */ + with equivalent CALL_EXPRs. */ static tree simplify_aggr_init_exprs_r (tree* tp, @@ -2760,7 +2846,7 @@ simplify_aggr_init_expr (tree *tp) tree fn = TREE_OPERAND (aggr_init_expr, 0); tree args = TREE_OPERAND (aggr_init_expr, 1); tree slot = TREE_OPERAND (aggr_init_expr, 2); - tree type = TREE_TYPE (aggr_init_expr); + tree type = TREE_TYPE (slot); tree call_expr; enum style_t { ctor, arg, pcc } style; @@ -2771,12 +2857,11 @@ simplify_aggr_init_expr (tree *tp) else if (1) style = pcc; #endif - else if (TREE_ADDRESSABLE (type)) - style = arg; else - /* We shouldn't build an AGGR_INIT_EXPR if we don't need any special - handling. See build_cplus_new. */ - abort (); + { + gcc_assert (TREE_ADDRESSABLE (type)); + style = arg; + } if (style == ctor || style == arg) { @@ -2788,25 +2873,23 @@ simplify_aggr_init_expr (tree *tp) args = TREE_CHAIN (args); cxx_mark_addressable (slot); - addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (slot)), slot); + addr = build1 (ADDR_EXPR, build_pointer_type (type), slot); if (style == arg) { /* The return type might have different cv-quals from the slot. */ tree fntype = TREE_TYPE (TREE_TYPE (fn)); -#ifdef ENABLE_CHECKING - if (TREE_CODE (fntype) != FUNCTION_TYPE - && TREE_CODE (fntype) != METHOD_TYPE) - abort (); -#endif + + gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE + || TREE_CODE (fntype) == METHOD_TYPE); addr = convert (build_pointer_type (TREE_TYPE (fntype)), addr); } args = tree_cons (NULL_TREE, addr, args); } - call_expr = build (CALL_EXPR, - TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), - fn, args, NULL_TREE); + call_expr = build3 (CALL_EXPR, + TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), + fn, args, NULL_TREE); if (style == arg) /* Tell the backend that we've added our return slot to the argument @@ -2823,13 +2906,6 @@ simplify_aggr_init_expr (tree *tp) pop_deferring_access_checks (); } - /* We want to use the value of the initialized location as the - result. */ - call_expr = build (COMPOUND_EXPR, type, - call_expr, slot); - - /* Replace the AGGR_INIT_EXPR with the CALL_EXPR. */ - TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr); *tp = call_expr; } @@ -2862,7 +2938,7 @@ emit_associated_thunks (tree fn) } } else - my_friendly_assert (!DECL_THUNKS (thunk), 20031023); + gcc_assert (!DECL_THUNKS (thunk)); } } } @@ -2873,7 +2949,7 @@ void expand_body (tree fn) { tree saved_function; - + /* Compute the appropriate object-file linkage for inline functions. */ if (DECL_DECLARED_INLINE_P (fn)) @@ -2893,28 +2969,15 @@ expand_body (tree fn) /* Emit any thunks that should be emitted at the same time as FN. */ emit_associated_thunks (fn); - timevar_push (TV_INTEGRATION); - optimize_function (fn); - timevar_pop (TV_INTEGRATION); + /* This function is only called from cgraph, or recursively from + emit_associated_thunks. In neither case should we be currently + generating trees for a function. */ + gcc_assert (function_depth == 0); - tree_rest_of_compilation (fn, function_depth > 1); + tree_rest_of_compilation (fn); current_function_decl = saved_function; - extract_interface_info (); - - /* If this function is marked with the constructor attribute, add it - to the list of functions to be called along with constructors - from static duration objects. */ - if (DECL_STATIC_CONSTRUCTOR (fn)) - static_ctors = tree_cons (NULL_TREE, fn, static_ctors); - - /* If this function is marked with the destructor attribute, add it - to the list of functions to be called along with destructors from - static duration objects. */ - if (DECL_STATIC_DESTRUCTOR (fn)) - static_dtors = tree_cons (NULL_TREE, fn, static_dtors); - if (DECL_CLONED_FUNCTION_P (fn)) { /* If this is a clone, go through the other clones now and mark @@ -2968,15 +3031,45 @@ expand_or_defer_fn (tree fn) return; } + /* If this function is marked with the constructor attribute, add it + to the list of functions to be called along with constructors + from static duration objects. */ + if (DECL_STATIC_CONSTRUCTOR (fn)) + static_ctors = tree_cons (NULL_TREE, fn, static_ctors); + + /* If this function is marked with the destructor attribute, add it + to the list of functions to be called along with destructors from + static duration objects. */ + if (DECL_STATIC_DESTRUCTOR (fn)) + static_dtors = tree_cons (NULL_TREE, fn, static_dtors); + + /* We make a decision about linkage for these functions at the end + of the compilation. Until that point, we do not want the back + end to output them -- but we do want it to see the bodies of + these functions so that it can inline them as appropriate. */ + if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn)) + { + if (!at_eof) + { + DECL_EXTERNAL (fn) = 1; + DECL_NOT_REALLY_EXTERN (fn) = 1; + note_vague_linkage_fn (fn); + } + else + import_export_decl (fn); + + /* If the user wants us to keep all inline functions, then mark + this function as needed so that finish_file will make sure to + output it later. */ + if (flag_keep_inline_functions && DECL_DECLARED_INLINE_P (fn)) + mark_needed (fn); + } + /* There's no reason to do any of the work here if we're only doing semantic analysis; this code just generates RTL. */ if (flag_syntax_only) return; - /* Compute the appropriate object-file linkage for inline functions. */ - if (DECL_DECLARED_INLINE_P (fn)) - import_export_decl (fn); - function_depth++; /* Expand or defer, at the whim of the compilation unit manager. */ @@ -2985,37 +3078,94 @@ expand_or_defer_fn (tree fn) function_depth--; } -/* Helper function for walk_tree, used by finish_function to override all - the RETURN_STMTs and pertinent CLEANUP_STMTs for the named return - value optimization. */ +struct nrv_data +{ + tree var; + tree result; + htab_t visited; +}; -tree -nullify_returns_r (tree* tp, int* walk_subtrees, void* data) +/* Helper function for walk_tree, used by finalize_nrv below. */ + +static tree +finalize_nrv_r (tree* tp, int* walk_subtrees, void* data) { - tree nrv = (tree) data; + struct nrv_data *dp = (struct nrv_data *)data; + void **slot; /* No need to walk into types. There wouldn't be any need to walk into non-statements, except that we have to consider STMT_EXPRs. */ if (TYPE_P (*tp)) *walk_subtrees = 0; - else if (TREE_CODE (*tp) == RETURN_STMT) - RETURN_STMT_EXPR (*tp) = NULL_TREE; + /* Change all returns to just refer to the RESULT_DECL; this is a nop, + but differs from using NULL_TREE in that it indicates that we care + about the value of the RESULT_DECL. */ + else if (TREE_CODE (*tp) == RETURN_EXPR) + TREE_OPERAND (*tp, 0) = dp->result; + /* Change all cleanups for the NRV to only run when an exception is + thrown. */ else if (TREE_CODE (*tp) == CLEANUP_STMT - && CLEANUP_DECL (*tp) == nrv) + && CLEANUP_DECL (*tp) == dp->var) CLEANUP_EH_ONLY (*tp) = 1; + /* Replace the DECL_EXPR for the NRV with an initialization of the + RESULT_DECL, if needed. */ + else if (TREE_CODE (*tp) == DECL_EXPR + && DECL_EXPR_DECL (*tp) == dp->var) + { + tree init; + if (DECL_INITIAL (dp->var) + && DECL_INITIAL (dp->var) != error_mark_node) + { + init = build2 (INIT_EXPR, void_type_node, dp->result, + DECL_INITIAL (dp->var)); + DECL_INITIAL (dp->var) = error_mark_node; + } + else + init = build_empty_stmt (); + SET_EXPR_LOCUS (init, EXPR_LOCUS (*tp)); + *tp = init; + } + /* And replace all uses of the NRV with the RESULT_DECL. */ + else if (*tp == dp->var) + *tp = dp->result; + + /* Avoid walking into the same tree more than once. Unfortunately, we + can't just use walk_tree_without duplicates because it would only call + us for the first occurrence of dp->var in the function body. */ + slot = htab_find_slot (dp->visited, *tp, INSERT); + if (*slot) + *walk_subtrees = 0; + else + *slot = *tp; /* Keep iterating. */ return NULL_TREE; } -/* Start generating the RTL for FN. */ +/* Called from finish_function to implement the named return value + optimization by overriding all the RETURN_EXPRs and pertinent + CLEANUP_STMTs and replacing all occurrences of VAR with RESULT, the + RESULT_DECL for the function. */ void -cxx_expand_function_start (void) +finalize_nrv (tree *tp, tree var, tree result) { - /* Give our named return value the same RTL as our RESULT_DECL. */ - if (current_function_return_value) - COPY_DECL_RTL (DECL_RESULT (cfun->decl), current_function_return_value); + struct nrv_data data; + + /* Copy debugging information from VAR to RESULT. */ + DECL_NAME (result) = DECL_NAME (var); + DECL_ARTIFICIAL (result) = DECL_ARTIFICIAL (var); + DECL_IGNORED_P (result) = DECL_IGNORED_P (var); + DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (var); + DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (var); + /* Don't forget that we take its address. */ + TREE_ADDRESSABLE (result) = TREE_ADDRESSABLE (var); + + data.var = var; + data.result = result; + data.visited = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL); + walk_tree (tp, finalize_nrv_r, &data, 0); + htab_delete (data.visited); } /* Perform initialization related to this module. */ @@ -3023,7 +3173,6 @@ cxx_expand_function_start (void) void init_cp_semantics (void) { - lang_expand_stmt = cp_expand_stmt; } #include "gt-cp-semantics.h"