X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Fsemantics.c;h=47ff6ea0fedcfec1898b431a15365d6a3060820d;hb=6cf0bc8c8b789cc8045faebeb8ada8697e04e719;hp=20e94223b364bbc1e282c4b334b0559ac6b8b02d;hpb=046bfc77364f8647fa26398c54a063d9d7f93022;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 20e94223b36..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, 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" @@ -57,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); @@ -75,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(); @@ -91,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 @@ -121,23 +122,23 @@ typedef struct deferred_access GTY(()) names used in a decl-specifier-seq until we know what is being declared because code like: - class A { - class B {}; - B* f(); + class A { + class B {}; + B* f(); } A::B* A::f() { return 0; } - is valid, even though `A::B' is not generally accessible. + 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); @@ -199,8 +200,8 @@ pop_deferring_access_checks (void) 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. */ @@ -236,8 +237,8 @@ pop_to_parent_deferring_access_checks (void) if (ptr->deferring_access_checks_kind == dk_no_deferred) { /* Check access. */ - for (; checks; checks = TREE_CHAIN (checks)) - enforce_access (TREE_PURPOSE (checks), + for (; checks; checks = TREE_CHAIN (checks)) + enforce_access (TREE_PURPOSE (checks), TREE_VALUE (checks)); } else @@ -245,11 +246,11 @@ pop_to_parent_deferring_access_checks (void) /* 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)) @@ -290,7 +291,7 @@ perform_deferred_access_checks (void) 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)); } @@ -307,18 +308,18 @@ perform_or_defer_access_check (tree binfo, tree decl) */ 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 (ptr->deferring_access_checks_kind == dk_no_deferred) { enforce_access (binfo, decl); return; } - + /* See if we are already going to perform this check. */ for (check = ptr->deferred_access_checks; check; @@ -340,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. */ @@ -347,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); } @@ -410,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); @@ -420,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) @@ -472,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) { @@ -490,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); @@ -522,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)); @@ -600,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)); @@ -637,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 @@ -663,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)); @@ -672,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)); @@ -717,12 +745,13 @@ 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) - || (DECL_CONSTRUCTOR_P (current_function_decl) + || (DECL_CONSTRUCTOR_P (current_function_decl) && targetm.cxx.cdtor_returns_this ())) { /* Similarly, all destructors must run destructors for @@ -734,6 +763,7 @@ finish_return_stmt (tree expr) } 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 (); @@ -748,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) @@ -801,7 +831,7 @@ finish_for_expr (tree expr, tree for_stmt) if (!processing_template_decl) { if (warn_sequence_point) - verify_sequence_points (expr); + verify_sequence_points (expr); expr = convert_to_void (expr, "3rd expression in for"); } else if (!type_dependent_expression_p (expr)) @@ -827,7 +857,7 @@ finish_for_stmt (tree for_stmt) add_stmt (do_poplevel (scope)); } - finish_stmt (); + finish_stmt (); } /* Finish a break-statement. */ @@ -919,7 +949,7 @@ finish_switch_stmt (tree switch_stmt) SWITCH_STMT_BODY (switch_stmt) = pop_stmt_list (SWITCH_STMT_BODY (switch_stmt)); - pop_switch (); + pop_switch (); finish_stmt (); scope = TREE_CHAIN (switch_stmt); @@ -1064,7 +1094,7 @@ finish_handler (tree handler) /* 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 + 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. */ @@ -1081,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 @@ -1137,18 +1167,17 @@ 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) { - int ninputs, noutputs; const char *constraint; const char **oconstraints; bool allows_mem, allows_reg, is_inout; tree operand; int i; - 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, @@ -1169,6 +1198,19 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, 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; @@ -1189,7 +1231,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, 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)); + 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 @@ -1197,8 +1239,8 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, resolve the overloading. */ if (TREE_TYPE (operand) == unknown_type_node) { - error ("type of asm operand %qE could not be determined", - TREE_VALUE (t)); + error ("type of asm operand %qE could not be determined", + TREE_VALUE (t)); operand = error_mark_node; } @@ -1226,7 +1268,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, 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); } @@ -1253,7 +1295,7 @@ finish_label_decl (tree name) /* 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); @@ -1297,10 +1339,10 @@ finish_parenthesized_expr (tree expr) /* [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; } @@ -1314,12 +1356,11 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) if (!object) { - if (current_function_decl + if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) - cp_error_at ("invalid use of member %qD 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 %qD", decl); + error ("invalid use of non-static data member %q+D", decl); error ("from this location"); return error_mark_node; @@ -1335,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, 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); @@ -1358,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 %qD", decl); + error ("object missing in reference to %q+D", decl); error ("from this location"); return error_mark_node; } @@ -1368,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); @@ -1395,8 +1438,8 @@ 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; @@ -1405,21 +1448,21 @@ check_accessibility_of_qualified_id (tree decl, /* 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)) @@ -1455,27 +1498,47 @@ 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) @@ -1489,9 +1552,9 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, /* If so, the expression may be relative to the current class. */ if (!shared_member_p (fns) - && current_class_type + && 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), @@ -1508,126 +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 = 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, LOOKUP_NORMAL); - expr = build_cplus_new (type, expr); - gcc_assert (TREE_CODE (expr) == TARGET_EXPR); + /* 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: - gcc_unreachable (); - } - } - type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt)); - } + type = TREE_TYPE (stmt_expr); + result = pop_stmt_list (stmt_expr); if (processing_template_decl) { @@ -1635,43 +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); - 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; + gcc_assert (TREE_CODE (type) == TARGET_EXPR); + TARGET_EXPR_INITIAL (type) = result; + TREE_TYPE (result) = void_type_node; + result = type; } return result; @@ -1713,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; } @@ -1729,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; @@ -1794,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) @@ -1830,19 +1845,20 @@ 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)) { /* If the function is an overloaded builtin, resolve it. */ if (TREE_CODE (fn) == FUNCTION_DECL - && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL) - result = resolve_overloaded_builtin (fn, args); + && (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); + result = build_new_function_call (fn, args, koenig_p); } else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR) { @@ -1878,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; @@ -1918,7 +1934,7 @@ 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) @@ -1933,21 +1949,21 @@ 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 ("%qE is not of type %qT", object, destructor); @@ -1985,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: @@ -2010,6 +2025,9 @@ finish_compound_literal (tree type, tree initializer_list) compound_literal, 1); } + /* Mark it as a compound-literal. */ + TREE_HAS_CONSTRUCTOR (compound_literal) = 1; + return compound_literal; } @@ -2020,7 +2038,7 @@ tree finish_fname (tree id) { tree decl; - + decl = fname_decl (C_RID_CODE (id), id); if (processing_template_decl) decl = DECL_NAME (decl); @@ -2029,7 +2047,7 @@ finish_fname (tree id) /* Finish a translation unit. */ -void +void finish_translation_unit (void) { /* In case there were missing closebraces, @@ -2045,7 +2063,7 @@ 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) @@ -2060,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); @@ -2092,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 %qT as a default value for a " - "template template-parameter", t); + "template template-parameter", t); else error ("invalid use of %qD as a default value for a template " - "template-parameter", argument); + "template-parameter", argument); } else error ("invalid default argument for a template template parameter"); @@ -2124,7 +2142,7 @@ begin_class_definition (tree t) /* 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) @@ -2141,7 +2159,7 @@ begin_class_definition (tree t) /* 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)); @@ -2171,7 +2189,7 @@ begin_class_definition (tree t) (t, finfo->interface_unknown); } reset_specialization(); - + /* Make a declaration for this class in its own scope. */ build_self_reference (); @@ -2195,9 +2213,9 @@ finish_member_declaration (tree decl) 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) { @@ -2218,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); - - 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 @@ -2253,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 { @@ -2261,7 +2280,7 @@ 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); } @@ -2279,20 +2298,6 @@ note_decl_for_pch (tree decl) { gcc_assert (pch_file); - /* 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; - } - /* 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 @@ -2338,7 +2343,7 @@ finish_template_type (tree name, tree args, int entering_scope) 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; @@ -2353,10 +2358,10 @@ finish_base_specifier (tree base, tree access, bool virtual_p) else { if (cp_type_quals (base) != 0) - { - error ("base class %qT 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); if (virtual_p) TREE_TYPE (result) = integer_type_node; @@ -2371,7 +2376,9 @@ finish_base_specifier (tree base, tree access, bool virtual_p) void 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 %qT used in nested name specifier", scope); @@ -2388,12 +2395,12 @@ qualified_name_lookup_error (tree scope, tree name, tree decl) else 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 @@ -2403,6 +2410,13 @@ qualified_name_lookup_error (tree scope, tree name, tree decl) 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 @@ -2412,19 +2426,22 @@ qualified_name_lookup_error (tree scope, tree name, tree decl) 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. */ @@ -2440,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) @@ -2479,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, @@ -2502,13 +2534,13 @@ finish_id_expression (tree id_expression, || 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 + + if (integral_constant_expression_p && !dependent_type_p (TREE_TYPE (decl)) && !(INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (r)))) { @@ -2520,7 +2552,7 @@ finish_id_expression (tree id_expression, } 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) { @@ -2536,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 @@ -2560,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. */ @@ -2615,20 +2647,32 @@ 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 convert_from_reference - (build2 (SCOPE_REF, TREE_TYPE (decl), scope, id_expression)); - else - return convert_from_reference (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. */ @@ -2659,8 +2703,8 @@ finish_id_expression (tree id_expression, } /* Only certain kinds of names are allowed in constant - expression. Enumerators and template parameters have already - been handled above. */ + 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)) @@ -2672,7 +2716,7 @@ finish_id_expression (tree id_expression, } *non_integral_constant_expression_p = true; } - + if (TREE_CODE (decl) == NAMESPACE_DECL) { error ("use of namespace %qD as expression", decl); @@ -2701,21 +2745,27 @@ 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; + 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 = build2 (SCOPE_REF, TREE_TYPE (r), scope, decl); + + if (processing_template_decl && TYPE_P (scope)) + r = build_qualified_name (TREE_TYPE (r), + scope, decl, + template_p); decl = r; } } @@ -2739,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 + 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 - ? "% variable" : "parameter")); - cp_error_at (" %q#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); } - + 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)) @@ -2823,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 @@ -2877,38 +2907,30 @@ simplify_aggr_init_expr (tree *tp) 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)); - - 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 = build3 (CALL_EXPR, + 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 @@ -2918,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; @@ -2936,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)) @@ -2945,7 +2968,7 @@ 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); @@ -2995,9 +3018,9 @@ expand_body (tree fn) 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)); @@ -3025,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; } @@ -3063,11 +3089,28 @@ expand_or_defer_fn (tree fn) these functions so that it can inline them as appropriate. */ if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn)) { - if (!at_eof) + 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);