X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcp%2Fsemantics.c;h=47ff6ea0fedcfec1898b431a15365d6a3060820d;hp=92efe443a6d514fbff97674397f68f368ab45bee;hb=6cf0bc8c8b789cc8045faebeb8ada8697e04e719;hpb=73d4090eb6c0a066cf54827b8264c447f8b31cc0 diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 92efe443a6d..47ff6ea0fed 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1,12 +1,12 @@ /* Perform the semantic phase of parsing, i.e., the process of building tree structure, checking semantic consistency, and building RTL. These routines are used both during actual parsing - and during the instantiation of template functions. + 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. + formerly in parse.y and pt.c. This file is part of GCC. @@ -14,16 +14,16 @@ under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #include "config.h" #include "system.h" @@ -31,10 +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" @@ -45,6 +45,8 @@ #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,6 +57,7 @@ parsing into this file; that will make implementing the new parser much easier since it will be able to make use of these routines. */ +static tree do_poplevel (tree); static tree maybe_convert_cond (tree); static tree simplify_aggr_init_exprs_r (tree *, int *, void *); static void emit_associated_thunks (tree); @@ -73,9 +76,9 @@ static tree finalize_nrv_r (tree *, int *, void *); example: class A { - typedef int X; + typedef int X; public: - X f(); + X f(); }; A::X A::f(); @@ -89,7 +92,7 @@ static tree finalize_nrv_r (tree *, int *, void *); instantiations. Typical use of access checking functions is described here: - + 1. When we enter a context that requires certain access checking mode, the function `push_deferring_access_checks' is called with DEFERRING argument specifying the desired mode. Access checking @@ -112,9 +115,37 @@ static tree finalize_nrv_r (tree *, int *, void *); 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_O (deferred_access); +DEF_VEC_ALLOC_O (deferred_access,gc); + /* 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,gc) *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. */ @@ -122,27 +153,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, gc, 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 @@ -151,8 +173,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. */ @@ -160,8 +183,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 @@ -170,26 +194,25 @@ 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. - The TREE_PURPOSE of each node is the type through which the +/* Returns a TREE_LIST representing the deferred checks. + The TREE_PURPOSE of each node is the type through which the access occurred; the TREE_VALUE is the declaration named. */ 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 @@ -199,27 +222,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; + if (deferred_access_no_check) + deferred_access_no_check--; + else + { + tree checks; + deferred_access *ptr; - /* 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; + checks = (VEC_last (deferred_access, deferred_access_stack) + ->deferred_access_checks); - 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)); + 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; - deferred_access_stack = d1; - d1->next = d2; - d2->next = d3; - pop_deferring_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. @@ -242,11 +286,12 @@ 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. */ - enforce_access (TREE_PURPOSE (deferred_check), + enforce_access (TREE_PURPOSE (deferred_check), TREE_VALUE (deferred_check)); } @@ -257,29 +302,33 @@ void perform_or_defer_access_check (tree binfo, tree decl) { tree check; + deferred_access *ptr; + + /* 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); - my_friendly_assert (TREE_CODE (binfo) == TREE_VEC, 20030623); - /* 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, @@ -292,6 +341,32 @@ stmts_are_full_exprs_p (void) return current_stmt_tree ()->stmts_are_full_exprs_p; } +/* T is a statement. Add it to the statement-tree. This is the C++ + version. The C/ObjC frontends have a slightly different version of + this function. */ + +tree +add_stmt (tree t) +{ + enum tree_code code = TREE_CODE (t); + + if (EXPR_P (t) && code != LABEL_EXPR) + { + if (!EXPR_HAS_LOCATION (t)) + SET_EXPR_LOCATION (t, input_location); + + /* When we expand a statement-tree, we must know whether or not the + statements are full-expressions. We record that fact here. */ + STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p (); + } + + /* Add T to the statement-tree. Non-side-effect statements need to be + recorded during statement expressions. */ + append_to_statement_list_force (t, &cur_stmt_list); + + return t; +} + /* Returns the stmt_tree (if any) to which statements are currently being added. If there is no active statement-tree, NULL is returned. */ @@ -299,8 +374,8 @@ stmts_are_full_exprs_p (void) stmt_tree current_stmt_tree (void) { - return (cfun - ? &cfun->language->base.x_stmt_tree + return (cfun + ? &cfun->language->base.x_stmt_tree : &scope_chain->x_stmt_tree); } @@ -310,18 +385,34 @@ static tree maybe_cleanup_point_expr (tree expr) { if (!processing_template_decl && stmts_are_full_exprs_p ()) - expr = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (expr), expr)); + 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_stmt (tree decl) +add_decl_expr (tree decl) { - tree r = build_stmt (DECL_STMT, decl); - if (DECL_INITIAL (decl)) - r = maybe_cleanup_point_expr (r); + 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); } @@ -346,7 +437,7 @@ do_poplevel (tree stmt_list) block = poplevel (kept_level_p (), 1, 0); stmt_list = pop_stmt_list (stmt_list); - + if (!processing_template_decl) { stmt_list = c_build_bind_expr (block, stmt_list); @@ -356,7 +447,7 @@ do_poplevel (tree stmt_list) return stmt_list; } -/* Begin a new scope. */ +/* Begin a new scope. */ static tree do_pushlevel (scope_kind sk) @@ -383,7 +474,7 @@ push_cleanup (tree decl, tree cleanup, bool eh_only) /* 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_STMT. */ + conditional to be rendered as the raw DECL_EXPR. */ static void begin_cond (tree *cond_p) @@ -400,7 +491,7 @@ finish_cond (tree *cond_p, tree expr) if (processing_template_decl) { tree cond = pop_stmt_list (*cond_p); - if (TREE_CODE (cond) == DECL_STMT) + if (TREE_CODE (cond) == DECL_EXPR) expr = cond; } *cond_p = expr; @@ -408,14 +499,14 @@ finish_cond (tree *cond_p, tree expr) /* If *COND_P specifies a conditional with a declaration, transform the loop such that - while (A x = 42) { } - for (; A x = 42;) { } + while (A x = 42) { } + for (; A x = 42;) { } becomes - while (true) { A x = 42; if (!x) break; } - for (;;) { A x = 42; if (!x) break; } + 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) { @@ -426,7 +517,7 @@ simplify_loop_decl_cond (tree *cond_p, tree body) 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); @@ -458,7 +549,7 @@ finish_goto_stmt (tree destination) addresses, or some such. */ DECL_UNINLINABLE (current_function_decl) = 1; } - + check_goto (destination); return add_stmt (build_stmt (GOTO_EXPR, destination)); @@ -493,17 +584,21 @@ 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"); /* Simplification of inner statement expressions, compound exprs, - etc can result in the us already having an EXPR_STMT. */ + 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 (expr); + expr = maybe_cleanup_point_expr_void (expr); } r = add_stmt (expr); @@ -532,7 +627,7 @@ begin_if_stmt (void) /* Process the COND of an if-statement, which may be given by IF_STMT. */ -void +void finish_if_stmt_cond (tree cond, tree if_stmt) { finish_cond (&IF_COND (if_stmt), maybe_convert_cond (cond)); @@ -569,13 +664,14 @@ finish_else_clause (tree if_stmt) /* Finish an if-statement. */ -void +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 (); + empty_body_warning (THEN_CLAUSE (if_stmt), ELSE_CLAUSE (if_stmt)); } /* Begin a while-statement. Returns a newly created WHILE_STMT if @@ -595,7 +691,7 @@ begin_while_stmt (void) /* Process the COND of a while-statement, which may be given by WHILE_STMT. */ -void +void finish_while_stmt_cond (tree cond, tree while_stmt) { finish_cond (&WHILE_COND (while_stmt), maybe_convert_cond (cond)); @@ -604,7 +700,7 @@ finish_while_stmt_cond (tree cond, tree while_stmt) /* Finish a while-statement, which may be given by WHILE_STMT. */ -void +void finish_while_stmt (tree while_stmt) { WHILE_BODY (while_stmt) = do_poplevel (WHILE_BODY (while_stmt)); @@ -649,22 +745,26 @@ tree finish_return_stmt (tree expr) { tree r; + bool no_warning; - expr = check_return_expr (expr); + expr = check_return_expr (expr, &no_warning); 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 = build_stmt (RETURN_STMT, expr); - r = maybe_cleanup_point_expr (r); + r = build_stmt (RETURN_EXPR, expr); + TREE_NO_WARNING (r) |= no_warning; + r = maybe_cleanup_point_expr_void (r); r = add_stmt (r); finish_stmt (); @@ -678,7 +778,7 @@ begin_for_stmt (void) { tree r; - r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE, + r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); if (flag_new_for_scope > 0) @@ -728,7 +828,15 @@ finish_for_expr (tree expr, tree for_stmt) cxx_incomplete_type_error (expr, TREE_TYPE (expr)); expr = error_mark_node; } - expr = maybe_cleanup_point_expr (expr); + 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; } @@ -749,7 +857,7 @@ finish_for_stmt (tree for_stmt) add_stmt (do_poplevel (scope)); } - finish_stmt (); + finish_stmt (); } /* Finish a break-statement. */ @@ -757,7 +865,7 @@ finish_for_stmt (tree for_stmt) tree finish_break_stmt (void) { - return add_stmt (build_break_stmt ()); + return add_stmt (build_stmt (BREAK_STMT)); } /* Finish a continue-statement. */ @@ -765,7 +873,7 @@ finish_break_stmt (void) tree finish_continue_stmt (void) { - return add_stmt (build_continue_stmt ()); + return add_stmt (build_stmt (CONTINUE_STMT)); } /* Begin a switch-statement. Returns a new SWITCH_STMT if @@ -780,7 +888,7 @@ begin_switch_stmt (void) scope = do_pushlevel (sk_block); TREE_CHAIN (r) = scope; - begin_cond (&SWITCH_COND (r)); + begin_cond (&SWITCH_STMT_COND (r)); return r; } @@ -824,11 +932,11 @@ finish_switch_cond (tree cond, tree switch_stmt) cond = index; } } - finish_cond (&SWITCH_COND (switch_stmt), cond); - 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_BODY (switch_stmt) = push_stmt_list (); + SWITCH_STMT_BODY (switch_stmt) = push_stmt_list (); } /* Finish the body of a switch-statement, which may be given by @@ -839,8 +947,9 @@ finish_switch_stmt (tree switch_stmt) { tree scope; - SWITCH_BODY (switch_stmt) = pop_stmt_list (SWITCH_BODY (switch_stmt)); - pop_switch (); + SWITCH_STMT_BODY (switch_stmt) = + pop_stmt_list (SWITCH_STMT_BODY (switch_stmt)); + pop_switch (); finish_stmt (); scope = TREE_CHAIN (switch_stmt); @@ -983,9 +1092,9 @@ finish_handler (tree handler) } /* Begin a compound statement. FLAGS contains some bits that control the - behaviour and context. If BCS_NO_SCOPE is set, the compound statement + 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 + 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. */ @@ -1002,7 +1111,7 @@ begin_compound_stmt (unsigned int flags) /* 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. */ + *inside* the scopeless block. */ keep_next_level (false); } else @@ -1016,7 +1125,7 @@ begin_compound_stmt (unsigned int flags) processing templates. */ if (processing_template_decl) { - r = build (BIND_EXPR, NULL, NULL, r, NULL); + 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; @@ -1035,7 +1144,13 @@ finish_compound_stmt (tree stmt) else if (STATEMENT_LIST_NO_SCOPE (stmt)) stmt = pop_stmt_list (stmt); else - stmt = do_poplevel (stmt); + { + /* Destroy any ObjC "super" receivers that may have been + created. */ + objc_clear_super_receiver (); + + stmt = do_poplevel (stmt); + } /* ??? See c_end_compound_stmt wrt statement expressions. */ add_stmt (stmt); @@ -1052,72 +1167,109 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, { tree r; tree t; + int ninputs = list_length (input_operands); + int noutputs = list_length (output_operands); if (!processing_template_decl) { + 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)) + 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) { - 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) + 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; + + if (operand != error_mark_node + && (TREE_READONLY (operand) + || CP_TYPE_CONST_P (TREE_TYPE (operand)) + /* Functions are not modifiable, even though they are + lvalues. */ + || TREE_CODE (TREE_TYPE (operand)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (operand)) == METHOD_TYPE + /* If it's an aggregate and any field is const, then it is + effectively const. */ + || (CLASS_TYPE_P (TREE_TYPE (operand)) + && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand))))) + readonly_error (operand, "assignment (via 'asm' output)", 0); + + constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); + oconstraints[i] = constraint; + + if (parse_output_constraint (&constraint, i, ninputs, noutputs, + &allows_mem, &allows_reg, &is_inout)) { - error ("type of asm operand `%E' could not be determined", - TREE_VALUE (t)); - converted_operand = error_mark_node; + /* If the operand is going to end up in memory, + mark it addressable. */ + if (!allows_reg && !cxx_mark_addressable (operand)) + operand = error_mark_node; } - TREE_VALUE (t) = converted_operand; - } + else + operand = error_mark_node; - ninputs = list_length (input_operands); - noutputs = list_length (output_operands); + TREE_VALUE (t) = operand; + } - for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i) + for (i = 0, t = input_operands; t; ++i, t = TREE_CHAIN (t)) { - bool allows_mem; - bool allows_reg; - bool is_inout; - const char *constraint; - tree operand; - constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); - operand = TREE_VALUE (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_output_constraint (&constraint, - i, ninputs, noutputs, - &allows_mem, - &allows_reg, - &is_inout)) + if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0, + oconstraints, &allows_mem, &allows_reg)) { - /* 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 && 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; - /* 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; } } r = build_stmt (ASM_EXPR, string, output_operands, input_operands, clobbers); - ASM_VOLATILE_P (r) = volatile_p; + ASM_VOLATILE_P (r) = volatile_p || noutputs == 0; + r = maybe_cleanup_point_expr_void (r); return add_stmt (r); } @@ -1138,12 +1290,12 @@ 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. */ -void +void finish_decl_cleanup (tree decl, tree cleanup) { push_cleanup (decl, cleanup, false); @@ -1179,14 +1331,18 @@ finish_mem_initializers (tree mem_inits) 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; } @@ -1196,16 +1352,15 @@ 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 + if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) - cp_error_at ("invalid use of member `%D' in static member function", - decl); + error ("invalid use of member %q+D in static member function", decl); else - cp_error_at ("invalid use of non-static data member `%D'", decl); + error ("invalid use of non-static data member %q+D", decl); error ("from this location"); return error_mark_node; @@ -1221,21 +1376,21 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) { /* Set the cv qualifiers. */ int quals = cp_type_quals (TREE_TYPE (current_class_ref)); - + if (DECL_MUTABLE_P (decl)) quals &= ~TYPE_QUAL_CONST; quals |= cp_type_quals (TREE_TYPE (decl)); 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 { tree access_type = TREE_TYPE (object); tree lookup_context = context_for_name_lookup (decl); - + while (!DERIVED_FROM_P (lookup_context, access_type)) { access_type = TYPE_CONTEXT (access_type); @@ -1244,7 +1399,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); + error ("object missing in reference to %q+D", decl); error ("from this location"); return error_mark_node; } @@ -1254,8 +1409,10 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) QUALIFYING_SCOPE is also non-null. Wrap this in a SCOPE_REF for now. */ if (processing_template_decl) - return build_min (SCOPE_REF, TREE_TYPE (decl), - qualifying_scope, DECL_NAME (decl)); + return build_qualified_name (TREE_TYPE (decl), + qualifying_scope, + DECL_NAME (decl), + /*template_p=*/false); perform_or_defer_access_check (TYPE_BINFO (access_type), decl); @@ -1281,27 +1438,31 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) `A::B' then NESTED_NAME_SPECIFIER is `A'. */ void -check_accessibility_of_qualified_id (tree decl, - tree object_type, +check_accessibility_of_qualified_id (tree decl, + tree object_type, tree nested_name_specifier) { 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); /* If the SCOPE is not a type, then DECL is not a member. */ if (!TYPE_P (scope)) return; /* Compute the scope through which DECL is being accessed. */ - if (object_type + if (object_type /* OBJECT_TYPE might not be a class type; consider: class A { typedef int I; }; I *p; p->A::I::~I(); - In this case, we will have "A::I" as the DECL, but "I" as the + In this case, we will have "A::I" as the DECL, but "I" as the OBJECT_TYPE. */ && CLASS_TYPE_P (object_type) && DERIVED_FROM_P (scope, object_type)) @@ -1327,7 +1488,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); } @@ -1335,46 +1498,63 @@ check_accessibility_of_qualified_id (tree decl, class named to the left of the "::" operator. DONE is true if this expression is a complete postfix-expression; it is false if this expression is followed by '->', '[', '(', etc. ADDRESS_P is true - iff this expression is the operand of '&'. */ + iff this expression is the operand of '&'. TEMPLATE_P is true iff + the qualified-id was of the form "A::template B". TEMPLATE_ARG_P + is true iff this qualified name appears as a template argument. */ tree -finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, - bool address_p) +finish_qualified_id_expr (tree qualifying_class, + tree expr, + bool done, + bool address_p, + bool template_p, + bool template_arg_p) { + gcc_assert (TYPE_P (qualifying_class)); + if (error_operand_p (expr)) return error_mark_node; + if (DECL_P (expr) || BASELINK_P (expr)) + mark_used (expr); + + if (template_p) + check_template_keyword (expr); + /* If EXPR occurs as the operand of '&', use special handling that permits a pointer-to-member. */ if (address_p && done) { if (TREE_CODE (expr) == SCOPE_REF) expr = TREE_OPERAND (expr, 1); - expr = build_offset_ref (qualifying_class, expr, + expr = build_offset_ref (qualifying_class, expr, /*address_p=*/true); return expr; } - if (TREE_CODE (expr) == FIELD_DECL) + /* Within the scope of a class, turn references to non-static + members into expression of the form "this->...". */ + if (template_arg_p) + /* But, within a template argument, we do not want make the + transformation, as there is no "this" pointer. */ + ; + else if (TREE_CODE (expr) == FIELD_DECL) expr = finish_non_static_data_member (expr, current_class_ref, 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 + expr = (build_class_member_access_expr (maybe_dummy_object (qualifying_class, NULL), expr, BASELINK_ACCESS_BINFO (expr), @@ -1391,124 +1571,111 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, /* Begin a statement-expression. The value returned must be passed to finish_stmt_expr. */ -tree +tree begin_stmt_expr (void) { return push_stmt_list (); } /* Process the final expression of a statement expression. EXPR can be - NULL, if the final expression is empty. Build up a TARGET_EXPR so - that the result value can be safely returned to the enclosing - expression. */ + NULL, if the final expression is empty. Return a STATEMENT_LIST + containing all the statements in the statement-expression, or + ERROR_MARK_NODE if there was an error. */ tree finish_stmt_expr_expr (tree expr, tree stmt_expr) { - tree result = NULL_TREE; + if (error_operand_p (expr)) + return error_mark_node; + /* If the last statement does not have "void" type, then the value + of the last statement is the value of the entire expression. */ if (expr) { - if (!processing_template_decl && !VOID_TYPE_P (TREE_TYPE (expr))) + tree type; + type = TREE_TYPE (expr); + if (!dependent_type_p (type) && !VOID_TYPE_P (type)) { - 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); - + expr = decay_conversion (expr); + if (error_operand_p (expr)) + return error_mark_node; 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 - expression. */ - if (TREE_CODE (expr) == TARGET_EXPR) - ; - else if (!IS_AGGR_TYPE (type) || TYPE_HAS_TRIVIAL_INIT_REF (type)) - expr = build_target_expr_with_type (expr, type); + } + /* The type of the statement-expression is the type of the last + expression. */ + TREE_TYPE (stmt_expr) = type; + /* We must take particular care if TYPE is a class type. In + particular if EXPR creates a temporary of class type, then it + must be destroyed at the semicolon terminating the last + statement -- but we must make a copy before that happens. + + This problem is solved by using a TARGET_EXPR to initialize a + new temporary variable. The TARGET_EXPR itself is placed + outside the statement-expression. However, the last + statement in the statement-expression is transformed from + EXPR to (approximately) T = EXPR, where T is the new + temporary variable. Thus, the lifetime of the new temporary + extends to the full-expression surrounding the + statement-expression. */ + if (!processing_template_decl && !VOID_TYPE_P (type)) + { + tree target_expr; + if (CLASS_TYPE_P (type) + && !TYPE_HAS_TRIVIAL_INIT_REF (type)) + { + target_expr = build_target_expr_with_type (expr, type); + expr = TARGET_EXPR_INITIAL (target_expr); + } else { - /* Copy construct. */ - expr = build_special_member_call - (NULL_TREE, complete_ctor_identifier, - build_tree_list (NULL_TREE, expr), - TYPE_BINFO (type), LOOKUP_NORMAL); - expr = build_cplus_new (type, expr); - my_friendly_assert (TREE_CODE (expr) == TARGET_EXPR, 20030729); + /* Normally, build_target_expr will not create a + TARGET_EXPR for scalars. However, we need the + temporary here, in order to solve the scoping + problem described above. */ + target_expr = force_target_expr (type, expr); + expr = TARGET_EXPR_INITIAL (target_expr); + expr = build2 (INIT_EXPR, + type, + TARGET_EXPR_SLOT (target_expr), + expr); } - } - - if (expr != error_mark_node) - { - result = build_stmt (EXPR_STMT, expr); - EXPR_STMT_STMT_EXPR_RESULT (result) = 1; - add_stmt (result); + TARGET_EXPR_INITIAL (target_expr) = NULL_TREE; + /* Save away the TARGET_EXPR in the TREE_TYPE field of the + STATEMENT_EXPR. We will retrieve it in + finish_stmt_expr. */ + TREE_TYPE (stmt_expr) = target_expr; } } - - finish_stmt (); - /* Remember the last expression so that finish_stmt_expr - can pull it apart. */ - TREE_TYPE (stmt_expr) = result; - - return result; + /* Having modified EXPR to reflect the extra initialization, we now + treat it just like an ordinary statement. */ + expr = finish_expr_stmt (expr); + + /* Mark the last statement so that we can recognize it as such at + template-instantiation time. */ + if (expr && processing_template_decl) + EXPR_STMT_STMT_EXPR_RESULT (expr) = 1; + + return stmt_expr; } /* Finish a statement-expression. EXPR should be the value returned by the previous begin_stmt_expr. Returns an expression representing the statement-expression. */ -tree +tree finish_stmt_expr (tree stmt_expr, bool has_no_scope) { - tree result, result_stmt, type; - tree *result_stmt_p = NULL; + tree type; + tree result; - result_stmt = TREE_TYPE (stmt_expr); - TREE_TYPE (stmt_expr) = void_type_node; - result = pop_stmt_list (stmt_expr); + if (error_operand_p (stmt_expr)) + return error_mark_node; - if (!result_stmt || VOID_TYPE_P (result_stmt)) - type = void_type_node; - else - { - /* 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) - { - t = *result_stmt_p; - if (t == result_stmt) - break; + gcc_assert (TREE_CODE (stmt_expr) == STATEMENT_LIST); - 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: - abort (); - } - } - type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt)); - } + type = TREE_TYPE (stmt_expr); + result = pop_stmt_list (stmt_expr); if (processing_template_decl) { @@ -1516,45 +1683,12 @@ finish_stmt_expr (tree stmt_expr, bool has_no_scope) TREE_SIDE_EFFECTS (result) = 1; STMT_EXPR_NO_SCOPE (result) = has_no_scope; } - else if (!VOID_TYPE_P (type)) + else if (!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 init, target_expr = EXPR_STMT_EXPR (result_stmt); - my_friendly_assert (TREE_CODE (target_expr) == TARGET_EXPR, 20030729); - - /* 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 if (same_type_p (TREE_TYPE (result), type)) - ; - else - abort (); - } - 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; + gcc_assert (TREE_CODE (type) == TARGET_EXPR); + TARGET_EXPR_INITIAL (type) = result; + TREE_TYPE (result) = void_type_node; + result = type; } return result; @@ -1596,8 +1730,6 @@ perform_koenig_lookup (tree fn, tree args) /* The unqualified name could not be resolved. */ fn = unqualified_fn_lookup_error (identifier); } - else - fn = identifier; return fn; } @@ -1612,7 +1744,7 @@ perform_koenig_lookup (tree fn, tree args) Returns code for the call. */ -tree +tree finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) { tree result; @@ -1623,8 +1755,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; @@ -1678,18 +1809,18 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) 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. + becomes the implied object argument. - This paragraph is unclear about this situation: + 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 + whether "the class of that member function" refers to `A' or to `B'. We believe it refers to `B'. */ - if (current_class_type + if (current_class_type && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)), current_class_type) && current_class_ref) @@ -1714,12 +1845,21 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) } result = build_new_method_call (object, fn, args, NULL_TREE, - (disallow_virtual + (disallow_virtual ? LOOKUP_NONVIRTUAL : 0)); } else if (is_overloaded_fn (fn)) - /* A call to a namespace-scope function. */ - result = build_new_function_call (fn, args); + { + /* If the function is an overloaded builtin, resolve it. */ + if (TREE_CODE (fn) == FUNCTION_DECL + && (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL + || DECL_BUILT_IN_CLASS (fn) == BUILT_IN_MD)) + result = resolve_overloaded_builtin (fn, args); + + if (!result) + /* A call to a namespace-scope function. */ + result = build_new_function_call (fn, args, koenig_p); + } else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR) { if (args) @@ -1736,14 +1876,15 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) have an overloaded `operator ()'. */ 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, NULL_TREE); + result = build3 (CALL_EXPR, TREE_TYPE (result), orig_fn, + orig_args, NULL_TREE); KOENIG_LOOKUP_P (result) = koenig_p; } return result; @@ -1753,15 +1894,15 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) is indicated by CODE, which should be POSTINCREMENT_EXPR or POSTDECREMENT_EXPR.) */ -tree +tree finish_increment_expr (tree expr, enum tree_code code) { - return build_x_unary_op (code, expr); + return build_x_unary_op (code, expr); } /* Finish a use of `this'. Returns an expression for `this'. */ -tree +tree finish_this_expr (void) { tree result; @@ -1773,15 +1914,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; } @@ -1793,13 +1934,13 @@ finish_this_expr (void) the TYPE for the type given. If SCOPE is non-NULL, the expression was of the form `OBJECT.SCOPE::~DESTRUCTOR'. */ -tree +tree 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) { @@ -1808,29 +1949,29 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor) error ("invalid qualifying scope in pseudo-destructor name"); return error_mark_node; } - + /* [expr.pseudo] says both: - The type designated by the pseudo-destructor-name shall be + The type designated by the pseudo-destructor-name shall be the same as the object type. - and: + and: - The cv-unqualified versions of the object type and of the + 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), + 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. */ @@ -1846,7 +1987,12 @@ finish_unary_op_expr (enum tree_code code, tree expr) && TREE_CODE (result) == INTEGER_CST && !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; } @@ -1855,20 +2001,19 @@ finish_unary_op_expr (enum tree_code code, tree expr) the INITIALIZER_LIST is being cast. */ tree -finish_compound_literal (tree type, tree initializer_list) +finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list) { tree compound_literal; /* Build a CONSTRUCTOR for the INITIALIZER_LIST. */ compound_literal = build_constructor (NULL_TREE, initializer_list); - /* Mark it as a compound-literal. */ - TREE_HAS_CONSTRUCTOR (compound_literal) = 1; if (processing_template_decl) TREE_TYPE (compound_literal) = type; else { /* Check the initialization. */ - compound_literal = digest_init (type, compound_literal, NULL); + compound_literal = reshape_init (type, compound_literal); + compound_literal = digest_init (type, compound_literal); /* If the TYPE was an array type with an unknown bound, then we can figure out the dimension now. For example, something like: @@ -1876,9 +2021,13 @@ finish_compound_literal (tree type, tree initializer_list) implies that the array has two elements. */ if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type)) - complete_array_type (type, compound_literal, 1); + cp_complete_array_type (&TREE_TYPE (compound_literal), + compound_literal, 1); } + /* Mark it as a compound-literal. */ + TREE_HAS_CONSTRUCTOR (compound_literal) = 1; + return compound_literal; } @@ -1889,33 +2038,16 @@ tree finish_fname (tree id) { tree decl; - + decl = fname_decl (C_RID_CODE (id), id); if (processing_template_decl) decl = DECL_NAME (decl); 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 +void finish_translation_unit (void) { /* In case there were missing closebraces, @@ -1931,12 +2063,12 @@ finish_translation_unit (void) /* Finish a template type parameter, specified as AGGR IDENTIFIER. Returns the parameter. */ -tree +tree 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; } @@ -1946,7 +2078,7 @@ finish_template_type_parm (tree aggr, tree identifier) /* Finish a template template parameter, specified as AGGR IDENTIFIER. Returns the parameter. */ -tree +tree finish_template_template_parm (tree aggr, tree identifier) { tree decl = build_decl (TYPE_DECL, identifier, NULL_TREE); @@ -1956,7 +2088,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); } @@ -1978,13 +2110,13 @@ check_template_template_default_arg (tree argument) /* Try to emit a slightly smarter error message if we detect that the user is using a template instantiation. */ - if (CLASSTYPE_TEMPLATE_INFO (t) + if (CLASSTYPE_TEMPLATE_INFO (t) && CLASSTYPE_TEMPLATE_INSTANTIATION (t)) - error ("invalid use of type `%T' as a default value for a " - "template template-parameter", t); + 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 " - "template-parameter", argument); + error ("invalid use of %qD as a default value for a template " + "template-parameter", argument); } else error ("invalid default argument for a template template parameter"); @@ -1994,24 +2126,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 @@ -2022,43 +2136,34 @@ 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: template struct A { - template struct A::B ... + template struct A::B ... 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; } if (t == error_mark_node || ! IS_AGGR_TYPE (t)) { t = make_aggr_type (RECORD_TYPE); - 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; + pushtag (make_anon_name (), t, /*tag_scope=*/ts_current); } /* Update the location of the decl. */ DECL_SOURCE_LOCATION (TYPE_NAME (t)) = input_location; - + if (TYPE_BEING_DEFINED (t)) { t = make_aggr_type (TREE_CODE (t)); - pushtag (TYPE_IDENTIFIER (t), t, 0); + pushtag (TYPE_IDENTIFIER (t), t, /*tag_scope=*/ts_current); } maybe_process_partial_specialization (t); pushclass (t); @@ -2078,12 +2183,13 @@ begin_class_definition (tree t) 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(); - + /* Make a declaration for this class in its own scope. */ build_self_reference (); @@ -2104,12 +2210,12 @@ 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) + TREE_PRIVATE (decl) = (current_access_specifier == access_private_node); - TREE_PROTECTED (decl) + TREE_PROTECTED (decl) = (current_access_specifier == access_protected_node); if (TREE_CODE (decl) == TEMPLATE_DECL) { @@ -2130,21 +2236,22 @@ finish_member_declaration (tree decl) /* Put functions on the TYPE_METHODS list and everything else on the TYPE_FIELDS list. Note that these are built up in reverse order. We reverse them (to obtain declaration order) in finish_struct. */ - if (TREE_CODE (decl) == FUNCTION_DECL + if (TREE_CODE (decl) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (decl)) { /* We also need to add this function to the CLASSTYPE_METHOD_VEC. */ - add_method (current_class_type, decl, /*error_p=*/0); - - TREE_CHAIN (decl) = TYPE_METHODS (current_class_type); - TYPE_METHODS (current_class_type) = decl; + if (add_method (current_class_type, decl, NULL_TREE)) + { + TREE_CHAIN (decl) = TYPE_METHODS (current_class_type); + TYPE_METHODS (current_class_type) = decl; - maybe_add_class_template_decl_list (current_class_type, decl, - /*friend_p=*/0); + maybe_add_class_template_decl_list (current_class_type, decl, + /*friend_p=*/0); + } } /* Enter the DECL into the scope of the class. */ - else if ((TREE_CODE (decl) == USING_DECL && TREE_TYPE (decl)) + else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl)) || pushdecl_class_level (decl)) { /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields @@ -2165,7 +2272,7 @@ finish_member_declaration (tree decl) list.) */ if (TREE_CODE (decl) == TYPE_DECL) - TYPE_FIELDS (current_class_type) + TYPE_FIELDS (current_class_type) = chainon (TYPE_FIELDS (current_class_type), decl); else { @@ -2173,39 +2280,29 @@ finish_member_declaration (tree decl) TYPE_FIELDS (current_class_type) = decl; } - maybe_add_class_template_decl_list (current_class_type, 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; - - 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 @@ -2243,9 +2340,10 @@ 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 +tree finish_base_specifier (tree base, tree access, bool virtual_p) { tree result; @@ -2260,65 +2358,49 @@ finish_base_specifier (tree base, tree access, bool virtual_p) else { if (cp_type_quals (base) != 0) - { - error ("base class `%T' has cv qualifiers", base); - base = TYPE_MAIN_VARIANT (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. */ - -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. */ +/* Issue a diagnostic that NAME cannot be found in SCOPE. DECL is + what we found when we tried to do the lookup. */ void -qualified_name_lookup_error (tree scope, tree name) +qualified_name_lookup_error (tree scope, tree name, tree decl) { - if (TYPE_P (scope)) + if (scope == error_mark_node) + ; /* We already complained. */ + else 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, id-expression. (See cp_parser_id_expression for details.) SCOPE, if non-NULL, is the type or namespace used to explicitly qualify ID_EXPRESSION. DECL is the entity to which that name has been - resolved. + resolved. *CONSTANT_EXPRESSION_P is true if we are presently parsing a constant-expression. In that case, *NON_CONSTANT_EXPRESSION_P will @@ -2328,6 +2410,13 @@ qualified_name_lookup_error (tree scope, tree name) constant-expression, but a non-constant expression is also permissible. + DONE is true if this expression is a complete postfix-expression; + it is false if this expression is followed by '->', '[', '(', etc. + ADDRESS_P is true iff this expression is the operand of '&'. + TEMPLATE_P is true iff the qualified-id was of the form + "A::template B". TEMPLATE_ARG_P is true iff this qualified name + appears as a template argument. + If an error occurs, and it is the kind of error that might cause the parser to abort a tentative parse, *ERROR_MSG is filled in. It is the caller's responsibility to issue the message. *ERROR_MSG @@ -2337,19 +2426,22 @@ qualified_name_lookup_error (tree scope, tree name) Return an expression for the entity, after issuing appropriate diagnostics. This function is also responsible for transforming a reference to a non-static member into a COMPONENT_REF that makes - the use of "this" explicit. + the use of "this" explicit. Upon return, *IDK will be filled in appropriately. */ tree -finish_id_expression (tree id_expression, +finish_id_expression (tree id_expression, tree decl, tree scope, cp_id_kind *idk, - tree *qualifying_class, bool integral_constant_expression_p, bool allow_non_integral_constant_expression_p, bool *non_integral_constant_expression_p, + bool template_p, + bool done, + bool address_p, + bool template_arg_p, const char **error_msg) { /* Initialize the output parameters. */ @@ -2365,13 +2457,13 @@ finish_id_expression (tree id_expression, || TREE_CODE (decl) == TYPE_DECL) ; /* Look up the name. */ - else + else { if (decl == error_mark_node) { /* Name lookup failed. */ - if (scope - && (!TYPE_P (scope) + if (scope + && (!TYPE_P (scope) || (!dependent_type_p (scope) && !(TREE_CODE (id_expression) == IDENTIFIER_NODE && IDENTIFIER_TYPENAME_P (id_expression) @@ -2380,7 +2472,7 @@ finish_id_expression (tree 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); + qualified_name_lookup_error (scope, id_expression, decl); return error_mark_node; } else if (!scope) @@ -2404,6 +2496,21 @@ finish_id_expression (tree id_expression, was entirely defined. */ if (!scope && decl != error_mark_node) maybe_note_name_used_in_class (id_expression, decl); + + /* Disallow uses of local variables from containing functions. */ + if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) + { + tree context = decl_function_context (decl); + if (context != NULL_TREE && context != current_function_decl + && ! TREE_STATIC (decl)) + { + error (TREE_CODE (decl) == VAR_DECL + ? "use of % variable from containing function" + : "use of parameter from containing function"); + error (" %q+#D declared here", decl); + return error_mark_node; + } + } } /* If we didn't find anything, or what we found was a type, @@ -2426,22 +2533,26 @@ 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); - if (integral_constant_expression_p + 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 + /* Similarly, we resolve enumeration constants to their underlying values. */ else if (TREE_CODE (decl) == CONST_DECL) { @@ -2457,7 +2568,7 @@ finish_id_expression (tree id_expression, /* If the declaration was explicitly qualified indicate that. The semantics of `A::f(3)' are different than `f(3)' if `f' is virtual. */ - *idk = (scope + *idk = (scope ? CP_ID_KIND_QUALIFIED : (TREE_CODE (decl) == TEMPLATE_ID_EXPR ? CP_ID_KIND_TEMPLATE_ID @@ -2481,13 +2592,13 @@ finish_id_expression (tree id_expression, /* A template-id where the name of the template was not resolved is definitely dependent. */ else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR - && (TREE_CODE (TREE_OPERAND (decl, 0)) + && (TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE)) dependent_p = true; /* For anything except an overloaded function, just check its type. */ else if (!is_overloaded_fn (decl)) - dependent_p + dependent_p = dependent_type_p (TREE_TYPE (decl)); /* For a set of overloaded functions, check each of the functions. */ @@ -2536,78 +2647,90 @@ finish_id_expression (tree id_expression, dependent. */ if (scope) { - if (TYPE_P (scope)) - *qualifying_class = scope; /* 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; - 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); - else - return decl; + if (TYPE_P (scope)) + { + if (address_p && done) + decl = finish_qualified_id_expr (scope, decl, + done, address_p, + template_p, + template_arg_p); + else if (dependent_type_p (scope)) + decl = build_qualified_name (/*type=*/NULL_TREE, + scope, + id_expression, + template_p); + else if (DECL_P (decl)) + decl = build_qualified_name (TREE_TYPE (decl), + scope, + id_expression, + template_p); + } + if (TREE_TYPE (decl)) + decl = convert_from_reference (decl); + return 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 || TREE_CODE (decl) == PARM_DECL) - return 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; @@ -2622,22 +2745,40 @@ finish_id_expression (tree id_expression, if (scope) { - decl = (adjust_result_of_qualified_name_lookup + decl = (adjust_result_of_qualified_name_lookup (decl, scope, current_class_type)); if (TREE_CODE (decl) == FUNCTION_DECL) mark_used (decl); 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); + decl = finish_qualified_id_expr (scope, + decl, + done, + address_p, + template_p, + template_arg_p); + else + { + tree r = convert_from_reference (decl); + + if (processing_template_decl && TYPE_P (scope)) + r = build_qualified_name (TREE_TYPE (r), + scope, decl, + template_p); + 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); @@ -2648,51 +2789,31 @@ finish_id_expression (tree id_expression, if (!really_overloaded_fn (decl)) mark_used (first_fn); - if (TREE_CODE (first_fn) == FUNCTION_DECL - && DECL_FUNCTION_MEMBER_P (first_fn)) + if (!template_arg_p + && TREE_CODE (first_fn) == FUNCTION_DECL + && DECL_FUNCTION_MEMBER_P (first_fn) + && !shared_member_p (decl)) { /* A set of member functions. */ decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0); - return finish_class_member_access_expr (decl, id_expression); + return finish_class_member_access_expr (decl, id_expression, + /*template_p=*/false); } } else { - if (TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == PARM_DECL - || TREE_CODE (decl) == RESULT_DECL) - { - tree context = decl_function_context (decl); - - if (context != NULL_TREE && context != current_function_decl - && ! TREE_STATIC (decl)) - { - error ("use of %s from containing function", - (TREE_CODE (decl) == VAR_DECL - ? "`auto' variable" : "parameter")); - cp_error_at (" `%#D' declared here", decl); - return error_mark_node; - } - } - if (DECL_P (decl) && DECL_NONLOCAL (decl) && DECL_CLASS_SCOPE_P (decl) && DECL_CONTEXT (decl) != current_class_type) { tree path; - + path = currently_open_derived_class (DECL_CONTEXT (decl)); 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 = unshare_expr (DECL_INITIAL (decl)); } if (TREE_DEPRECATED (decl)) @@ -2721,7 +2842,7 @@ 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; } @@ -2732,9 +2853,9 @@ finish_typeof (tree expr) with equivalent CALL_EXPRs. */ static tree -simplify_aggr_init_exprs_r (tree* tp, - int* walk_subtrees, - void* data ATTRIBUTE_UNUSED) +simplify_aggr_init_exprs_r (tree* tp, + int* walk_subtrees, + void* data ATTRIBUTE_UNUSED) { /* We don't need to walk into types; there's nothing in a type that needs simplification. (And, furthermore, there are places we @@ -2780,47 +2901,36 @@ 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) + if (style == ctor) { - /* Pass the address of the slot. If this is a constructor, we - replace the first argument; otherwise, we tack on a new one. */ + /* Replace the first argument to the ctor with the address of the + slot. */ tree addr; - if (style == ctor) - args = TREE_CHAIN (args); - + args = TREE_CHAIN (args); cxx_mark_addressable (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 - 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 - list. */ - CALL_EXPR_HAS_RETURN_SLOT_ADDR (call_expr) = 1; + { + /* Just mark it addressable here, and leave the rest to + expand_call{,_inline}. */ + cxx_mark_addressable (slot); + CALL_EXPR_RETURN_SLOT_OPT (call_expr) = true; + call_expr = build2 (MODIFY_EXPR, TREE_TYPE (call_expr), slot, call_expr); + } else if (style == pcc) { /* If we're using the non-reentrant PCC calling convention, then we @@ -2830,6 +2940,7 @@ simplify_aggr_init_expr (tree *tp) call_expr = build_aggr_init (slot, call_expr, DIRECT_BIND | LOOKUP_ONLYCONVERTING); pop_deferring_access_checks (); + call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot); } *tp = call_expr; @@ -2848,7 +2959,7 @@ emit_associated_thunks (tree fn) if (DECL_VIRTUAL_P (fn)) { tree thunk; - + for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk)) { if (!THUNK_ALIAS (thunk)) @@ -2857,14 +2968,14 @@ emit_associated_thunks (tree fn) if (DECL_RESULT_THUNK_P (thunk)) { tree probe; - + for (probe = DECL_THUNKS (thunk); probe; probe = TREE_CHAIN (probe)) use_thunk (probe, /*emit_p=*/1); } } else - my_friendly_assert (!DECL_THUNKS (thunk), 20031023); + gcc_assert (!DECL_THUNKS (thunk)); } } } @@ -2895,30 +3006,21 @@ expand_body (tree fn) /* Emit any thunks that should be emitted at the same time as FN. */ emit_associated_thunks (fn); - tree_rest_of_compilation (fn, function_depth > 1); + /* 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); - 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); + tree_rest_of_compilation (fn); - /* 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); + current_function_decl = saved_function; if (DECL_CLONED_FUNCTION_P (fn)) { /* If this is a clone, go through the other clones now and mark - their parameters used. We have to do that here, as we don't - know whether any particular clone will be expanded, and - therefore cannot pick one arbitrarily. */ + their parameters used. We have to do that here, as we don't + know whether any particular clone will be expanded, and + therefore cannot pick one arbitrarily. */ tree probe; for (probe = TREE_CHAIN (DECL_CLONED_FUNCTION (fn)); @@ -2946,8 +3048,11 @@ expand_or_defer_fn (tree fn) /* Normally, collection only occurs in rest_of_compilation. So, if we don't collect here, we never collect junk generated during the processing of templates until we hit a - non-template function. */ - ggc_collect (); + non-template function. It's not safe to do this inside a + nested class, though, as the parser may have local state that + is not a GC root. */ + if (!function_depth) + ggc_collect (); return; } @@ -2966,15 +3071,62 @@ 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 (DECL_INTERFACE_KNOWN (fn)) + /* We've already made a decision as to how this function will + be handled. */; + else if (!at_eof) + { + DECL_EXTERNAL (fn) = 1; + DECL_NOT_REALLY_EXTERN (fn) = 1; + note_vague_linkage_fn (fn); + /* 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 (!DECL_IMPLICIT_INSTANTIATION (fn)) + { + /* This function must have external linkage, as + otherwise DECL_INTERFACE_KNOWN would have been + set. */ + gcc_assert (TREE_PUBLIC (fn)); + comdat_linkage (fn); + DECL_INTERFACE_KNOWN (fn) = 1; + } + } + 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. */ @@ -3005,24 +3157,24 @@ finalize_nrv_r (tree* tp, int* walk_subtrees, void* data) /* 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_STMT) - RETURN_STMT_EXPR (*tp) = dp->result; + 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) == dp->var) CLEANUP_EH_ONLY (*tp) = 1; - /* Replace the DECL_STMT for the NRV with an initialization of the + /* Replace the DECL_EXPR for the NRV with an initialization of the RESULT_DECL, if needed. */ - else if (TREE_CODE (*tp) == DECL_STMT - && DECL_STMT_DECL (*tp) == dp->var) + 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 = build (INIT_EXPR, void_type_node, dp->result, - DECL_INITIAL (dp->var)); + init = build2 (INIT_EXPR, void_type_node, dp->result, + DECL_INITIAL (dp->var)); DECL_INITIAL (dp->var) = error_mark_node; } else @@ -3048,7 +3200,7 @@ finalize_nrv_r (tree* tp, int* walk_subtrees, void* data) } /* Called from finish_function to implement the named return value - optimization by overriding all the RETURN_STMTs and pertinent + 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. */ @@ -3059,6 +3211,8 @@ finalize_nrv (tree *tp, tree var, tree result) /* 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. */