X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fcp%2Fsemantics.c;h=95387e13bc3a32b5f283a44783638eaac73d495b;hb=b77fe7b45f5a162d5d0f3cc64044281220076c04;hp=a6aea7be3c5cfb8f07c44eef44f8a83f0a770544;hpb=50bc768da122bde65bc31bf4054f29603893455a;p=gcc.git diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index a6aea7be3c5..95387e13bc3 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 + 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,6 +31,7 @@ #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" @@ -74,9 +75,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(); @@ -90,7 +91,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 @@ -120,28 +121,29 @@ 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); /* Data for deferred access checking. */ -static GTY(()) VEC (deferred_access) *deferred_access_stack; +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 @@ -158,7 +160,7 @@ push_deferring_access_checks (deferring_kind deferring) { deferred_access *ptr; - ptr = VEC_safe_push (deferred_access, deferred_access_stack, NULL); + ptr = VEC_safe_push (deferred_access, gc, deferred_access_stack, NULL); ptr->deferred_access_checks = NULL_TREE; ptr->deferring_access_checks_kind = deferring; } @@ -197,8 +199,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. */ @@ -234,8 +236,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 @@ -243,11 +245,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)) @@ -284,12 +286,11 @@ perform_deferred_access_checks (void) { tree deferred_check; - for (deferred_check = (VEC_last (deferred_access, 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)); } @@ -306,18 +307,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; @@ -339,6 +340,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. */ @@ -346,8 +373,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); } @@ -357,18 +384,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_expr (tree decl) { tree r = build_stmt (DECL_EXPR, decl); - if (DECL_INITIAL (decl)) - r = maybe_cleanup_point_expr (r); + if (DECL_INITIAL (decl) + || (DECL_SIZE (decl) && TREE_SIDE_EFFECTS (DECL_SIZE (decl)))) + r = maybe_cleanup_point_expr_void (r); add_stmt (r); } @@ -384,7 +427,7 @@ anon_aggr_type_p (tree node) /* Finish a scope. */ -static tree +tree do_poplevel (tree stmt_list) { tree block = NULL; @@ -393,7 +436,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); @@ -403,7 +446,7 @@ do_poplevel (tree stmt_list) return stmt_list; } -/* Begin a new scope. */ +/* Begin a new scope. */ static tree do_pushlevel (scope_kind sk) @@ -455,14 +498,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) { @@ -473,7 +516,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); @@ -505,7 +548,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)); @@ -549,12 +592,12 @@ finish_expr_stmt (tree 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); @@ -583,7 +626,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)); @@ -620,7 +663,7 @@ finish_else_clause (tree if_stmt) /* Finish an if-statement. */ -void +void finish_if_stmt (tree if_stmt) { tree scope = TREE_CHAIN (if_stmt); @@ -646,7 +689,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)); @@ -655,7 +698,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)); @@ -700,12 +743,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 @@ -717,7 +761,8 @@ finish_return_stmt (tree expr) } r = build_stmt (RETURN_EXPR, expr); - r = maybe_cleanup_point_expr (r); + TREE_NO_WARNING (r) |= no_warning; + r = maybe_cleanup_point_expr_void (r); r = add_stmt (r); finish_stmt (); @@ -731,7 +776,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) @@ -781,7 +826,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; } @@ -802,7 +855,7 @@ finish_for_stmt (tree for_stmt) add_stmt (do_poplevel (scope)); } - finish_stmt (); + finish_stmt (); } /* Finish a break-statement. */ @@ -810,7 +863,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. */ @@ -818,7 +871,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 @@ -833,7 +886,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; } @@ -877,11 +930,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 @@ -892,8 +945,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); @@ -1036,9 +1090,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. */ @@ -1055,7 +1109,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 @@ -1088,7 +1142,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); @@ -1105,72 +1165,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 (!parse_output_constraint (&constraint, - i, ninputs, noutputs, - &allows_mem, - &allows_reg, - &is_inout)) + /* 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) { - /* 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; + error ("type of asm operand %qE could not be determined", + TREE_VALUE (t)); + 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); + if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0, + oconstraints, &allows_mem, &allows_reg)) + { + /* If the operand is going to end up in memory, + mark it addressable. */ + if (!allows_reg && allows_mem) + { + /* Strip the nops as we allow this case. FIXME, this really + should be rejected or made deprecated. */ + STRIP_NOPS (operand); + if (!cxx_mark_addressable (operand)) + operand = error_mark_node; + } + } + else + operand = error_mark_node; + + TREE_VALUE (t) = operand; } } r = build_stmt (ASM_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); } @@ -1196,7 +1293,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); @@ -1232,7 +1329,7 @@ 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. */ TREE_NO_WARNING (expr) = 1; @@ -1240,6 +1337,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; } @@ -1253,12 +1354,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 `%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; @@ -1274,21 +1374,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); @@ -1297,7 +1397,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; } @@ -1307,8 +1407,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); @@ -1334,31 +1436,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 imediately. */ + /* 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)) @@ -1394,46 +1496,58 @@ 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) { if (error_operand_p (expr)) return error_mark_node; + 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), @@ -1450,124 +1564,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, 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: - abort (); - } - } - type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt)); - } + type = TREE_TYPE (stmt_expr); + result = pop_stmt_list (stmt_expr); if (processing_template_decl) { @@ -1575,45 +1676,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 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; @@ -1655,8 +1723,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; } @@ -1671,7 +1737,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; @@ -1736,18 +1802,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) @@ -1772,12 +1838,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) @@ -1794,6 +1869,7 @@ 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); @@ -1811,15 +1887,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; @@ -1831,15 +1907,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; } @@ -1851,7 +1927,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) @@ -1866,24 +1942,24 @@ 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; } } @@ -1904,7 +1980,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; } @@ -1913,20 +1994,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 = 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: @@ -1934,9 +2014,11 @@ 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); } + TREE_HAS_CONSTRUCTOR (compound_literal) = 1; return compound_literal; } @@ -1947,7 +2029,7 @@ tree finish_fname (tree id) { tree decl; - + decl = fname_decl (C_RID_CODE (id), id); if (processing_template_decl) decl = DECL_NAME (decl); @@ -1956,7 +2038,7 @@ finish_fname (tree id) /* Finish a translation unit. */ -void +void finish_translation_unit (void) { /* In case there were missing closebraces, @@ -1972,12 +2054,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; } @@ -1987,7 +2069,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); @@ -2019,13 +2101,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"); @@ -2045,43 +2127,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); @@ -2101,12 +2174,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 (); @@ -2130,9 +2204,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) { @@ -2153,21 +2227,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 @@ -2188,7 +2263,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 { @@ -2196,9 +2271,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); +} + +/* 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. */ + +void +note_decl_for_pch (tree decl) +{ + gcc_assert (pch_file); + + /* 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 @@ -2239,7 +2334,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; @@ -2254,10 +2349,10 @@ 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); if (virtual_p) TREE_TYPE (result) = integer_type_node; @@ -2266,60 +2361,37 @@ finish_base_specifier (tree base, tree access, bool virtual_p) 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. DECL is what we found when we tried to do the lookup. */ 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 `%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); + 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 @@ -2329,6 +2401,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 @@ -2338,19 +2417,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. */ @@ -2366,13 +2448,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) @@ -2405,6 +2487,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, @@ -2427,22 +2524,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) { @@ -2458,7 +2559,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 @@ -2482,13 +2583,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. */ @@ -2537,68 +2638,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 build2 (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. */ + expression. Enumerators and template parameters have already + been handled above. */ if (integral_constant_expression_p - && !DECL_INTEGRAL_CONSTANT_VAR_P (decl)) + && ! DECL_INTEGRAL_CONSTANT_VAR_P (decl) + && ! builtin_valid_in_constant_expr_p (decl)) { if (!allow_non_integral_constant_expression_p) { - error ("`%D' cannot appear in a constant-expression", decl); + 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; @@ -2613,22 +2736,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 = build2 (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); @@ -2639,51 +2780,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)) @@ -2712,7 +2833,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; } @@ -2723,9 +2844,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 @@ -2771,47 +2892,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 = 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 @@ -2821,6 +2931,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 = build (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot); } *tp = call_expr; @@ -2839,7 +2950,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)) @@ -2848,7 +2959,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); @@ -2886,18 +2997,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; + tree_rest_of_compilation (fn); - extract_interface_info (); + 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)); @@ -2925,8 +3039,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; } @@ -2963,11 +3080,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);