X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;ds=sidebyside;f=gcc%2Fcp%2Fsemantics.c;h=cbbcf96e2cc6defc0d4f6f70b77223b589af13d0;hb=f302e37ac84681c0c057f25d0137ce23e2e6e50b;hp=c6f921a968d350859d41c3c1a616f53ed51fb9d2;hpb=cc88e3b29444ec74c2e85db1ddb81a96055692ee;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index c6f921a968d..cbbcf96e2cc 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4,7 +4,7 @@ and during the instantiation of template functions. Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008 Free Software Foundation, Inc. + 2008, 2009 Free Software Foundation, Inc. Written by Mark Mitchell (mmitchell@usa.net) based on code found formerly in parse.y and pt.c. @@ -54,8 +54,9 @@ along with GCC; see the file COPYING3. If not see degenerate form of parsing. */ static tree maybe_convert_cond (tree); -static tree simplify_aggr_init_exprs_r (tree *, int *, void *); static tree finalize_nrv_r (tree *, int *, void *); +static tree capture_decltype (tree); +static tree thisify_lambda_field (tree); /* Deferred Access Checking Overview @@ -109,8 +110,7 @@ static tree finalize_nrv_r (tree *, int *, void *); In case of parsing error, we simply call `pop_deferring_access_checks' without `perform_deferred_access_checks'. */ -typedef struct deferred_access GTY(()) -{ +typedef struct GTY(()) deferred_access { /* A VEC representing name-lookups for which we have deferred checking access controls. We cannot check the accessibility of names used in a decl-specifier-seq until we know what is being @@ -422,7 +422,7 @@ maybe_cleanup_point_expr_void (tree expr) void add_decl_expr (tree decl) { - tree r = build_stmt (DECL_EXPR, decl); + tree r = build_stmt (input_location, DECL_EXPR, decl); if (DECL_INITIAL (decl) || (DECL_SIZE (decl) && TREE_SIDE_EFFECTS (DECL_SIZE (decl)))) r = maybe_cleanup_point_expr_void (r); @@ -443,7 +443,7 @@ do_poplevel (tree stmt_list) if (!processing_template_decl) { - stmt_list = c_build_bind_expr (block, stmt_list); + stmt_list = c_build_bind_expr (input_location, block, stmt_list); /* ??? See c_end_compound_stmt re statement expressions. */ } @@ -468,7 +468,7 @@ do_pushlevel (scope_kind sk) void push_cleanup (tree decl, tree cleanup, bool eh_only) { - tree stmt = build_stmt (CLEANUP_STMT, NULL, cleanup, decl); + tree stmt = build_stmt (input_location, CLEANUP_STMT, NULL, cleanup, decl); CLEANUP_EH_ONLY (stmt) = eh_only; add_stmt (stmt); CLEANUP_BODY (stmt) = push_stmt_list (); @@ -546,9 +546,12 @@ finish_goto_stmt (tree destination) TREE_USED (destination) = 1; else { - /* The DESTINATION is being used as an rvalue. */ if (!processing_template_decl) - destination = decay_conversion (destination); + { + destination = cp_convert (ptr_type_node, destination); + if (error_operand_p (destination)) + return NULL_TREE; + } /* We don't inline calls to functions with computed gotos. Those functions are typically up to some funny business, and may be depending on the labels being at particular @@ -558,7 +561,7 @@ finish_goto_stmt (tree destination) check_goto (destination); - return add_stmt (build_stmt (GOTO_EXPR, destination)); + return add_stmt (build_stmt (input_location, GOTO_EXPR, destination)); } /* COND is the condition-expression for an if, while, etc., @@ -607,6 +610,13 @@ finish_expr_stmt (tree expr) { if (warn_sequence_point) verify_sequence_points (expr); + if (TREE_CODE (expr) != MODIFY_EXPR) + /* Expr is not being 'used' here, otherwise we whould have + called mark_{rl}value_use use here, which would have in turn + called mark_exp_read. Rather, we call mark_exp_read directly + to avoid some warnings when + -Wunused-but-set-{variable,parameter} is in effect. */ + mark_exp_read (expr); expr = convert_to_void (expr, "statement", tf_warning_or_error); } else if (!type_dependent_expression_p (expr)) @@ -621,7 +631,7 @@ finish_expr_stmt (tree expr) if (TREE_CODE (expr) != CLEANUP_POINT_EXPR) { if (TREE_CODE (expr) != EXPR_STMT) - expr = build_stmt (EXPR_STMT, expr); + expr = build_stmt (input_location, EXPR_STMT, expr); expr = maybe_cleanup_point_expr_void (expr); } @@ -642,7 +652,7 @@ begin_if_stmt (void) { tree r, scope; scope = do_pushlevel (sk_block); - r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE); + r = build_stmt (input_location, IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE); TREE_CHAIN (r) = scope; begin_cond (&IF_COND (r)); return r; @@ -695,7 +705,6 @@ finish_if_stmt (tree if_stmt) TREE_CHAIN (if_stmt) = NULL; add_stmt (do_poplevel (scope)); finish_stmt (); - empty_if_body_warning (THEN_CLAUSE (if_stmt), ELSE_CLAUSE (if_stmt)); } /* Begin a while-statement. Returns a newly created WHILE_STMT if @@ -705,7 +714,7 @@ tree begin_while_stmt (void) { tree r; - r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE); + r = build_stmt (input_location, WHILE_STMT, NULL_TREE, NULL_TREE); add_stmt (r); WHILE_BODY (r) = do_pushlevel (sk_block); begin_cond (&WHILE_COND (r)); @@ -737,7 +746,7 @@ finish_while_stmt (tree while_stmt) tree begin_do_stmt (void) { - tree r = build_stmt (DO_STMT, NULL_TREE, NULL_TREE); + tree r = build_stmt (input_location, DO_STMT, NULL_TREE, NULL_TREE); add_stmt (r); DO_BODY (r) = push_stmt_list (); return r; @@ -799,7 +808,7 @@ finish_return_stmt (tree expr) } } - r = build_stmt (RETURN_EXPR, expr); + r = build_stmt (input_location, RETURN_EXPR, expr); TREE_NO_WARNING (r) |= no_warning; r = maybe_cleanup_point_expr_void (r); r = add_stmt (r); @@ -815,7 +824,7 @@ begin_for_stmt (void) { tree r; - r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE, + r = build_stmt (input_location, FOR_STMT, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); if (flag_new_for_scope > 0) @@ -906,7 +915,7 @@ finish_for_stmt (tree for_stmt) tree finish_break_stmt (void) { - return add_stmt (build_stmt (BREAK_STMT)); + return add_stmt (build_stmt (input_location, BREAK_STMT)); } /* Finish a continue-statement. */ @@ -914,7 +923,7 @@ finish_break_stmt (void) tree finish_continue_stmt (void) { - return add_stmt (build_stmt (CONTINUE_STMT)); + return add_stmt (build_stmt (input_location, CONTINUE_STMT)); } /* Begin a switch-statement. Returns a new SWITCH_STMT if @@ -925,7 +934,7 @@ begin_switch_stmt (void) { tree r, scope; - r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE); + r = build_stmt (input_location, SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE); scope = do_pushlevel (sk_block); TREE_CHAIN (r) = scope; @@ -942,8 +951,6 @@ finish_switch_cond (tree cond, tree switch_stmt) tree orig_type = NULL; if (!processing_template_decl) { - tree index; - /* Convert the condition to an integer or enumeration type. */ cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, true); if (cond == NULL_TREE) @@ -960,18 +967,6 @@ finish_switch_cond (tree cond, tree switch_stmt) cond = perform_integral_promotions (cond); cond = maybe_cleanup_point_expr (cond); } - - if (cond != error_mark_node) - { - index = get_unwidened (cond, NULL_TREE); - /* We can't strip a conversion from a signed type to an unsigned, - because if we did, int_fits_type_p would do the wrong thing - when checking case values for being in range, - and it's too hard to do the right thing. */ - if (TYPE_UNSIGNED (TREE_TYPE (cond)) - == TYPE_UNSIGNED (TREE_TYPE (index))) - cond = index; - } } if (check_for_bare_parameter_packs (cond)) cond = error_mark_node; @@ -1009,7 +1004,7 @@ finish_switch_stmt (tree switch_stmt) tree begin_try_block (void) { - tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE); + tree r = build_stmt (input_location, TRY_BLOCK, NULL_TREE, NULL_TREE); add_stmt (r); TRY_STMTS (r) = push_stmt_list (); return r; @@ -1099,7 +1094,7 @@ begin_handler (void) { tree r; - r = build_stmt (HANDLER, NULL_TREE, NULL_TREE); + r = build_stmt (input_location, HANDLER, NULL_TREE, NULL_TREE); add_stmt (r); /* Create a binding level for the eh_info and the exception object @@ -1212,12 +1207,13 @@ finish_compound_stmt (tree stmt) } /* Finish an asm-statement, whose components are a STRING, some - OUTPUT_OPERANDS, some INPUT_OPERANDS, and some CLOBBERS. Also note - whether the asm-statement should be considered volatile. */ + OUTPUT_OPERANDS, some INPUT_OPERANDS, some CLOBBERS and some + LABELS. Also note whether the asm-statement should be + considered volatile. */ tree finish_asm_stmt (int volatile_p, tree string, tree output_operands, - tree input_operands, tree clobbers) + tree input_operands, tree clobbers, tree labels) { tree r; tree t; @@ -1235,7 +1231,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, oconstraints = (const char **) alloca (noutputs * sizeof (char *)); string = resolve_asm_operand_names (string, output_operands, - input_operands); + input_operands, labels); for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i) { @@ -1249,6 +1245,8 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, otherwise we'll get an error. Gross, but ... */ STRIP_NOPS (operand); + operand = mark_lvalue_use (operand); + if (!lvalue_or_else (operand, lv_asm, tf_warning_or_error)) operand = error_mark_node; @@ -1263,7 +1261,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, effectively const. */ || (CLASS_TYPE_P (TREE_TYPE (operand)) && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand))))) - readonly_error (operand, "assignment (via 'asm' output)"); + readonly_error (operand, REK_ASSIGNMENT_ASM); constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); oconstraints[i] = constraint; @@ -1319,25 +1317,27 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, } } - r = build_stmt (ASM_EXPR, string, + r = build_stmt (input_location, ASM_EXPR, string, output_operands, input_operands, - clobbers); + clobbers, labels); ASM_VOLATILE_P (r) = volatile_p || noutputs == 0; r = maybe_cleanup_point_expr_void (r); return add_stmt (r); } -/* Finish a label with the indicated NAME. */ +/* Finish a label with the indicated NAME. Returns the new label. */ tree finish_label_stmt (tree name) { tree decl = define_label (input_location, name); - if (decl == error_mark_node) + if (decl == error_mark_node) return error_mark_node; - return add_stmt (build_stmt (LABEL_EXPR, decl)); + add_stmt (build_stmt (input_location, LABEL_EXPR, decl)); + + return decl; } /* Finish a series of declarations for local labels. G++ allows users @@ -1435,6 +1435,17 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) if (!object) { + tree scope = qualifying_scope; + if (scope == NULL_TREE) + scope = context_for_name_lookup (decl); + object = maybe_dummy_object (scope, NULL); + } + + /* DR 613: Can use non-static data members without an associated + object in sizeof/decltype/alignof. */ + if (is_dummy_object (object) && cp_unevaluated_operand == 0 + && (!processing_template_decl || !current_class_ref)) + { if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) error ("invalid use of member %q+D in static member function", decl); @@ -1444,7 +1455,9 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) return error_mark_node; } - TREE_USED (current_class_ptr) = 1; + + if (current_class_ptr) + TREE_USED (current_class_ptr) = 1; if (processing_template_decl && !qualifying_scope) { tree type = TREE_TYPE (decl); @@ -1454,7 +1467,9 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) else { /* Set the cv qualifiers. */ - int quals = cp_type_quals (TREE_TYPE (current_class_ref)); + int quals = (current_class_ref + ? cp_type_quals (TREE_TYPE (current_class_ref)) + : TYPE_UNQUALIFIED); if (DECL_MUTABLE_P (decl)) quals &= ~TYPE_QUAL_CONST; @@ -1465,33 +1480,17 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) return build_min (COMPONENT_REF, type, object, decl, NULL_TREE); } + /* If PROCESSING_TEMPLATE_DECL is nonzero here, then + QUALIFYING_SCOPE is also non-null. Wrap this in a SCOPE_REF + for now. */ + else if (processing_template_decl) + return build_qualified_name (TREE_TYPE (decl), + qualifying_scope, + DECL_NAME (decl), + /*template_p=*/false); 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); - while (access_type && DECL_P (access_type)) - access_type = DECL_CONTEXT (access_type); - - if (!access_type) - { - error ("object missing in reference to %q+D", decl); - error ("from this location"); - return error_mark_node; - } - } - - /* If PROCESSING_TEMPLATE_DECL is nonzero here, then - QUALIFYING_SCOPE is also non-null. Wrap this in a SCOPE_REF - for now. */ - if (processing_template_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, decl); @@ -1512,6 +1511,37 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) } } +/* If we are currently parsing a template and we encountered a typedef + TYPEDEF_DECL that is being accessed though CONTEXT, this function + adds the typedef to a list tied to the current template. + At tempate instantiatin time, that list is walked and access check + performed for each typedef. + LOCATION is the location of the usage point of TYPEDEF_DECL. */ + +void +add_typedef_to_current_template_for_access_check (tree typedef_decl, + tree context, + location_t location) +{ + tree template_info = NULL; + tree cs = current_scope (); + + if (!is_typedef_decl (typedef_decl) + || !context + || !CLASS_TYPE_P (context) + || !cs) + return; + + if (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL) + template_info = get_template_info (cs); + + if (template_info + && TI_TEMPLATE (template_info) + && !currently_open_class (context)) + append_type_to_template_for_access_check (cs, typedef_decl, + context, location); +} + /* DECL was the declaration to which a qualified-id resolved. Issue an error message if it is not accessible. If OBJECT_TYPE is non-NULL, we have just seen `x->' or `x.' and OBJECT_TYPE is the @@ -1526,6 +1556,16 @@ check_accessibility_of_qualified_id (tree decl, tree scope; tree qualifying_type = NULL_TREE; + /* If we are parsing a template declaration and if decl is a typedef, + add it to a list tied to the template. + At template instantiation time, that list will be walked and + access check performed. */ + add_typedef_to_current_template_for_access_check (decl, + nested_name_specifier + ? nested_name_specifier + : DECL_CONTEXT (decl), + input_location); + /* If we're not checking, return immediately. */ if (deferred_access_no_check) return; @@ -1625,25 +1665,21 @@ finish_qualified_id_expr (tree qualifying_class, else if (TREE_CODE (expr) == FIELD_DECL) { push_deferring_access_checks (dk_no_check); - expr = finish_non_static_data_member (expr, current_class_ref, + expr = finish_non_static_data_member (expr, NULL_TREE, qualifying_class); pop_deferring_access_checks (); } else if (BASELINK_P (expr) && !processing_template_decl) { - tree fns; + tree ob; /* 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); - /* If so, the expression may be relative to the current - class. */ - if (!shared_member_p (fns) - && current_class_type - && DERIVED_FROM_P (qualifying_class, current_class_type)) + /* If so, the expression may be relative to 'this'. */ + if (!shared_member_p (expr) + && (ob = maybe_dummy_object (qualifying_class, NULL), + !is_dummy_object (ob))) expr = (build_class_member_access_expr - (maybe_dummy_object (qualifying_class, NULL), + (ob, expr, BASELINK_ACCESS_BINFO (expr), /*preserve_reference=*/false, @@ -1690,7 +1726,7 @@ finish_stmt_expr_expr (tree expr, tree stmt_expr) if (processing_template_decl) { - expr = build_stmt (EXPR_STMT, expr); + expr = build_stmt (input_location, EXPR_STMT, expr); expr = add_stmt (expr); /* Mark the last statement so that we can recognize it as such at template-instantiation time. */ @@ -1788,16 +1824,55 @@ stmt_expr_value_expr (tree stmt_expr) return t; } +/* Return TRUE iff EXPR_STMT is an empty list of + expression statements. */ + +bool +empty_expr_stmt_p (tree expr_stmt) +{ + tree body = NULL_TREE; + + if (expr_stmt == void_zero_node) + return true; + + if (expr_stmt) + { + if (TREE_CODE (expr_stmt) == EXPR_STMT) + body = EXPR_STMT_EXPR (expr_stmt); + else if (TREE_CODE (expr_stmt) == STATEMENT_LIST) + body = expr_stmt; + } + + if (body) + { + if (TREE_CODE (body) == STATEMENT_LIST) + return tsi_end_p (tsi_start (body)); + else + return empty_expr_stmt_p (body); + } + return false; +} + /* Perform Koenig lookup. FN is the postfix-expression representing the function (or functions) to call; ARGS are the arguments to the call. Returns the functions to be considered by overload resolution. */ tree -perform_koenig_lookup (tree fn, tree args) +perform_koenig_lookup (tree fn, VEC(tree,gc) *args) { tree identifier = NULL_TREE; tree functions = NULL_TREE; + tree tmpl_args = NULL_TREE; + bool template_id = false; + + if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) + { + /* Use a separate flag to handle null args. */ + template_id = true; + tmpl_args = TREE_OPERAND (fn, 1); + fn = TREE_OPERAND (fn, 0); + } /* Find the name of the overloaded function. */ if (TREE_CODE (fn) == IDENTIFIER_NODE) @@ -1817,7 +1892,8 @@ perform_koenig_lookup (tree fn, tree args) Do Koenig lookup -- unless any of the arguments are type-dependent. */ - if (!any_type_dependent_arguments_p (args)) + if (!any_type_dependent_arguments_p (args) + && !any_dependent_template_arguments_p (tmpl_args)) { fn = lookup_arg_dependent (identifier, functions, args); if (!fn) @@ -1825,10 +1901,14 @@ perform_koenig_lookup (tree fn, tree args) fn = unqualified_fn_lookup_error (identifier); } + if (fn && template_id) + fn = build2 (TEMPLATE_ID_EXPR, unknown_type_node, fn, tmpl_args); + return fn; } -/* Generate an expression for `FN (ARGS)'. +/* Generate an expression for `FN (ARGS)'. This may change the + contents of ARGS. If DISALLOW_VIRTUAL is true, the call to FN will be not generated as a virtual call, even if FN is virtual. (This flag is set when @@ -1839,29 +1919,26 @@ perform_koenig_lookup (tree fn, tree args) Returns code for the call. */ tree -finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, - tsubst_flags_t complain) +finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual, + bool koenig_p, tsubst_flags_t complain) { tree result; tree orig_fn; - tree orig_args; + VEC(tree,gc) *orig_args = NULL; - if (fn == error_mark_node || args == error_mark_node) + if (fn == error_mark_node) return error_mark_node; - /* ARGS should be a list of arguments. */ - gcc_assert (!args || TREE_CODE (args) == TREE_LIST); gcc_assert (!TYPE_P (fn)); orig_fn = fn; - orig_args = args; if (processing_template_decl) { if (type_dependent_expression_p (fn) - || any_type_dependent_arguments_p (args)) + || any_type_dependent_arguments_p (*args)) { - result = build_nt_call_list (fn, args); + result = build_nt_call_vec (fn, *args); KOENIG_LOOKUP_P (result) = koenig_p; if (cfun) { @@ -1879,11 +1956,12 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, } return result; } + orig_args = make_tree_vector_copy (*args); if (!BASELINK_P (fn) && TREE_CODE (fn) != PSEUDO_DTOR_EXPR && TREE_TYPE (fn) != unknown_type_node) fn = build_non_dependent_expr (fn); - args = build_non_dependent_args (orig_args); + make_args_non_dependent (*args); } if (is_overloaded_fn (fn)) @@ -1903,36 +1981,27 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, . operator.... [Otherwise] a contrived object of type T becomes the implied object argument. - This paragraph is unclear about this situation: + In 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 - to `B'. We believe it refers to `B'. */ - if (current_class_type - && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)), - current_class_type) - && current_class_ref) - object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)), - NULL); - else - { - tree representative_fn; + "the class of that member function" refers to `A'. But 11.2 + [class.access.base] says that we need to convert 'this' to B* as + part of the access, so we pass 'B' to maybe_dummy_object. */ - representative_fn = BASELINK_FUNCTIONS (fn); - if (TREE_CODE (representative_fn) == TEMPLATE_ID_EXPR) - representative_fn = TREE_OPERAND (representative_fn, 0); - representative_fn = get_first_fn (representative_fn); - object = build_dummy_object (DECL_CONTEXT (representative_fn)); - } + object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)), + NULL); if (processing_template_decl) { if (type_dependent_expression_p (object)) - return build_nt_call_list (orig_fn, orig_args); + { + tree ret = build_nt_call_vec (orig_fn, orig_args); + release_tree_vector (orig_args); + return ret; + } object = build_non_dependent_expr (object); } @@ -1948,7 +2017,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, 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); + result = resolve_overloaded_builtin (input_location, fn, *args); if (!result) /* A call to a namespace-scope function. */ @@ -1956,7 +2025,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, } else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR) { - if (args) + if (!VEC_empty (tree, *args)) error ("arguments to destructor are not allowed"); /* Mark the pseudo-destructor call as having side-effects so that we do not issue warnings about its use. */ @@ -1968,18 +2037,19 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, else if (CLASS_TYPE_P (TREE_TYPE (fn))) /* If the "function" is really an object of class type, it might have an overloaded `operator ()'. */ - result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE, - /*overloaded_p=*/NULL, complain); + result = build_op_call (fn, args, complain); if (!result) /* A call where the function is unknown. */ - result = cp_build_function_call (fn, args, complain); + result = cp_build_function_call_vec (fn, args, complain); if (processing_template_decl) { - result = build_call_list (TREE_TYPE (result), orig_fn, orig_args); + result = build_call_vec (TREE_TYPE (result), orig_fn, orig_args); KOENIG_LOOKUP_P (result) = koenig_p; + release_tree_vector (orig_args); } + return result; } @@ -2002,7 +2072,14 @@ finish_this_expr (void) if (current_class_ptr) { - result = current_class_ptr; + tree type = TREE_TYPE (current_class_ref); + + /* In a lambda expression, 'this' refers to the captured 'this'. */ + if (LAMBDA_TYPE_P (type)) + result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type)); + else + result = current_class_ptr; + } else if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) @@ -2094,7 +2171,7 @@ finish_unary_op_expr (enum tree_code code, tree expr) TREE_NEGATED_INT (result) = 1; } if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr)) - overflow_warning (result); + overflow_warning (input_location, result); return result; } @@ -2148,6 +2225,7 @@ finish_compound_literal (tree type, tree compound_literal) tree decl = create_temporary_var (type); DECL_INITIAL (decl) = compound_literal; TREE_STATIC (decl) = 1; + cp_apply_type_quals_to_decl (cp_type_quals (type), decl); decl = pushdecl_top_level (decl); DECL_NAME (decl) = make_anon_name (); SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl)); @@ -2165,7 +2243,7 @@ finish_fname (tree id) { tree decl; - decl = fname_decl (C_RID_CODE (id), id); + decl = fname_decl (input_location, C_RID_CODE (id), id); if (processing_template_decl) decl = DECL_NAME (decl); return decl; @@ -2207,7 +2285,8 @@ finish_template_type_parm (tree aggr, tree identifier) tree finish_template_template_parm (tree aggr, tree identifier) { - tree decl = build_decl (TYPE_DECL, identifier, NULL_TREE); + tree decl = build_decl (input_location, + TYPE_DECL, identifier, NULL_TREE); tree tmpl = build_lang_decl (TEMPLATE_DECL, identifier, NULL_TREE); DECL_TEMPLATE_PARMS (tmpl) = current_template_parms; DECL_TEMPLATE_RESULT (tmpl) = decl; @@ -2258,6 +2337,26 @@ begin_class_definition (tree t, tree attributes) error ("definition of %q#T inside template parameter list", t); return error_mark_node; } + + /* According to the C++ ABI, decimal classes defined in ISO/IEC TR 24733 + are passed the same as decimal scalar types. */ + if (TREE_CODE (t) == RECORD_TYPE + && !processing_template_decl) + { + tree ns = TYPE_CONTEXT (t); + if (ns && TREE_CODE (ns) == NAMESPACE_DECL + && DECL_CONTEXT (ns) == std_node + && DECL_NAME (ns) + && !strcmp (IDENTIFIER_POINTER (DECL_NAME (ns)), "decimal")) + { + const char *n = TYPE_NAME_STRING (t); + if ((strcmp (n, "decimal32") == 0) + || (strcmp (n, "decimal64") == 0) + || (strcmp (n, "decimal128") == 0)) + TYPE_TRANSPARENT_AGGR (t) = 1; + } + } + /* A non-implicit typename comes from code like: template struct A { @@ -2276,9 +2375,6 @@ begin_class_definition (tree t, tree attributes) 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_class_type (TREE_CODE (t)); @@ -2519,20 +2615,21 @@ qualified_name_lookup_error (tree scope, tree name, else if (TYPE_P (scope)) { if (!COMPLETE_TYPE_P (scope)) - error ("%Hincomplete type %qT used in nested name specifier", - &location, scope); + error_at (location, "incomplete type %qT used in nested name specifier", + scope); else if (TREE_CODE (decl) == TREE_LIST) { - error ("%Hreference to %<%T::%D%> is ambiguous", &location, scope, name); + error_at (location, "reference to %<%T::%D%> is ambiguous", + scope, name); print_candidates (decl); } else - error ("%H%qD is not a member of %qT", &location, name, scope); + error_at (location, "%qD is not a member of %qT", name, scope); } else if (scope != global_namespace) - error ("%H%qD is not a member of %qD", &location, name, scope); + error_at (location, "%qD is not a member of %qD", name, scope); else - error ("%H%<::%D%> has not been declared", &location, name); + error_at (location, "%<::%D%> has not been declared", name); } /* If FNS is a member function, a set of member functions, or a @@ -2564,6 +2661,30 @@ baselink_for_fns (tree fns) return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE); } +/* Returns true iff DECL is an automatic variable from a function outside + the current one. */ + +static bool +outer_automatic_var_p (tree decl) +{ + return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) + && DECL_FUNCTION_SCOPE_P (decl) + && !TREE_STATIC (decl) + && DECL_CONTEXT (decl) != current_function_decl); +} + +/* Returns true iff DECL is a capture field from a lambda that is not our + immediate context. */ + +static bool +outer_lambda_capture_p (tree decl) +{ + return (TREE_CODE (decl) == FIELD_DECL + && LAMBDA_TYPE_P (DECL_CONTEXT (decl)) + && (!current_class_type + || !DERIVED_FROM_P (DECL_CONTEXT (decl), current_class_type))); +} + /* 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 @@ -2665,12 +2786,70 @@ finish_id_expression (tree id_expression, 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) + /* Disallow uses of local variables from containing functions, except + within lambda-expressions. */ + if ((outer_automatic_var_p (decl) + || outer_lambda_capture_p (decl)) + /* It's not a use (3.2) if we're in an unevaluated context. */ + && !cp_unevaluated_operand) { - tree context = decl_function_context (decl); - if (context != NULL_TREE && context != current_function_decl - && ! TREE_STATIC (decl)) + tree context = DECL_CONTEXT (decl); + tree containing_function = current_function_decl; + tree lambda_stack = NULL_TREE; + tree lambda_expr = NULL_TREE; + tree initializer = decl; + + /* Core issue 696: "[At the July 2009 meeting] the CWG expressed + support for an approach in which a reference to a local + [constant] automatic variable in a nested class or lambda body + would enter the expression as an rvalue, which would reduce + the complexity of the problem" + + FIXME update for final resolution of core issue 696. */ + if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)) + return integral_constant_value (decl); + + if (TYPE_P (context)) + { + /* Implicit capture of an explicit capture. */ + context = lambda_function (context); + initializer = thisify_lambda_field (decl); + } + + /* If we are in a lambda function, we can move out until we hit + 1. the context, + 2. a non-lambda function, or + 3. a non-default capturing lambda function. */ + while (context != containing_function + && LAMBDA_FUNCTION_P (containing_function)) + { + lambda_expr = CLASSTYPE_LAMBDA_EXPR + (DECL_CONTEXT (containing_function)); + + if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) + == CPLD_NONE) + break; + + lambda_stack = tree_cons (NULL_TREE, + lambda_expr, + lambda_stack); + + containing_function + = decl_function_context (containing_function); + } + + if (context == containing_function) + { + decl = add_default_capture (lambda_stack, + /*id=*/DECL_NAME (decl), + initializer); + } + else if (lambda_expr) + { + error ("%qD is not captured", decl); + return error_mark_node; + } + else { error (TREE_CODE (decl) == VAR_DECL ? "use of % variable from containing function" @@ -2818,11 +2997,6 @@ finish_id_expression (tree id_expression, dependent. */ if (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)) { if (address_p && done) @@ -2830,16 +3004,16 @@ finish_id_expression (tree id_expression, 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); + else + { + tree type = NULL_TREE; + if (DECL_P (decl) && !dependent_scope_p (scope)) + type = TREE_TYPE (decl); + decl = build_qualified_name (type, + scope, + id_expression, + template_p); + } } if (TREE_TYPE (decl)) decl = convert_from_reference (decl); @@ -2865,7 +3039,7 @@ finish_id_expression (tree id_expression, 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, + (decl, NULL_TREE, /*qualifying_scope=*/NULL_TREE); pop_deferring_access_checks (); return decl; @@ -2946,7 +3120,7 @@ finish_id_expression (tree id_expression, 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, + decl = finish_non_static_data_member (decl, NULL_TREE, /*qualifying_scope=*/NULL_TREE); pop_deferring_access_checks (); } @@ -2954,10 +3128,7 @@ finish_id_expression (tree id_expression, { tree first_fn; - first_fn = decl; - if (TREE_CODE (first_fn) == TEMPLATE_ID_EXPR) - first_fn = TREE_OPERAND (first_fn, 0); - first_fn = get_first_fn (first_fn); + first_fn = get_first_fn (decl); if (TREE_CODE (first_fn) == TEMPLATE_DECL) first_fn = DECL_TEMPLATE_RESULT (first_fn); @@ -2997,7 +3168,7 @@ finish_id_expression (tree id_expression, } if (TREE_DEPRECATED (decl)) - warn_deprecated_use (decl); + warn_deprecated_use (decl, NULL_TREE); return decl; } @@ -3019,6 +3190,8 @@ finish_typeof (tree expr) return type; } + expr = mark_type_use (expr); + type = unlowered_expr_type (expr); if (!type || type == unknown_type_node) @@ -3057,34 +3230,6 @@ finish_offsetof (tree expr) return fold_offsetof (expr, NULL_TREE); } -/* Called from expand_body via walk_tree. Replace all AGGR_INIT_EXPRs - with equivalent CALL_EXPRs. */ - -static tree -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 - actively don't want to go. For example, we don't want to wander - into the default arguments for a FUNCTION_DECL that appears in a - CALL_EXPR.) */ - if (TYPE_P (*tp)) - { - *walk_subtrees = 0; - return NULL_TREE; - } - /* Only AGGR_INIT_EXPRs are interesting. */ - else if (TREE_CODE (*tp) != AGGR_INIT_EXPR) - return NULL_TREE; - - simplify_aggr_init_expr (tp); - - /* Keep iterating. */ - return NULL_TREE; -} - /* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR. This function is broken out from the above for the benefit of the tree-ssa project. */ @@ -3114,10 +3259,11 @@ simplify_aggr_init_expr (tree *tp) style = arg; } - call_expr = build_call_array (TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), - fn, - aggr_init_expr_nargs (aggr_init_expr), - AGGR_INIT_EXPR_ARGP (aggr_init_expr)); + call_expr = build_call_array_loc (input_location, + TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), + fn, + aggr_init_expr_nargs (aggr_init_expr), + AGGR_INIT_EXPR_ARGP (aggr_init_expr)); if (style == ctor) { @@ -3133,7 +3279,7 @@ simplify_aggr_init_expr (tree *tp) 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); + call_expr = build2 (INIT_EXPR, TREE_TYPE (call_expr), slot, call_expr); } else if (style == pcc) { @@ -3148,6 +3294,15 @@ simplify_aggr_init_expr (tree *tp) call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot); } + if (AGGR_INIT_ZERO_FIRST (aggr_init_expr)) + { + tree init = build_zero_init (type, NULL_TREE, + /*static_storage_p=*/false); + init = build2 (INIT_EXPR, void_type_node, slot, init); + call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (call_expr), + init, call_expr); + } + *tp = call_expr; } @@ -3161,7 +3316,9 @@ emit_associated_thunks (tree fn) is so that you can know statically the entire set of thunks that will ever be needed for a given virtual function, thereby enabling you to output all the thunks with the function itself. */ - if (DECL_VIRTUAL_P (fn)) + if (DECL_VIRTUAL_P (fn) + /* Do not emit thunks for extern template instantiations. */ + && ! DECL_REALLY_EXTERN (fn)) { tree thunk; @@ -3187,8 +3344,8 @@ emit_associated_thunks (tree fn) /* Generate RTL for FN. */ -void -expand_or_defer_fn (tree fn) +bool +expand_or_defer_fn_1 (tree fn) { /* When the parser calls us after finishing the body of a template function, we don't really want to expand the body. */ @@ -3202,15 +3359,10 @@ expand_or_defer_fn (tree fn) is not a GC root. */ if (!function_depth) ggc_collect (); - return; + return false; } - gcc_assert (gimple_body (fn)); - - /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs. */ - cp_walk_tree_without_duplicates (&DECL_SAVED_TREE (fn), - simplify_aggr_init_exprs_r, - NULL); + gcc_assert (DECL_SAVED_TREE (fn)); /* If this is a constructor or destructor body, we have to clone it. */ @@ -3219,7 +3371,8 @@ expand_or_defer_fn (tree fn) /* We don't want to process FN again, so pretend we've written it out, even though we haven't. */ TREE_ASM_WRITTEN (fn) = 1; - return; + DECL_SAVED_TREE (fn) = NULL_TREE; + return false; } /* We make a decision about linkage for these functions at the end @@ -3256,22 +3409,36 @@ expand_or_defer_fn (tree fn) /* If the user wants us to keep all inline functions, then mark this function as needed so that finish_file will make sure to - output it later. */ - if (flag_keep_inline_functions && DECL_DECLARED_INLINE_P (fn)) + output it later. Similarly, all dllexport'd functions must + be emitted; there may be callers in other DLLs. */ + if ((flag_keep_inline_functions + && DECL_DECLARED_INLINE_P (fn) + && !DECL_REALLY_EXTERN (fn)) + || lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn))) mark_needed (fn); } /* There's no reason to do any of the work here if we're only doing semantic analysis; this code just generates RTL. */ if (flag_syntax_only) - return; + return false; + + return true; +} - function_depth++; +void +expand_or_defer_fn (tree fn) +{ + if (expand_or_defer_fn_1 (fn)) + { + function_depth++; - /* Expand or defer, at the whim of the compilation unit manager. */ - cgraph_finalize_function (fn, function_depth > 1); + /* Expand or defer, at the whim of the compilation unit manager. */ + cgraph_finalize_function (fn, function_depth > 1); + emit_associated_thunks (fn); - function_depth--; + function_depth--; + } } struct nrv_data @@ -3311,14 +3478,12 @@ finalize_nrv_r (tree* tp, int* walk_subtrees, void* data) tree init; if (DECL_INITIAL (dp->var) && DECL_INITIAL (dp->var) != error_mark_node) - { - init = build2 (INIT_EXPR, void_type_node, dp->result, - DECL_INITIAL (dp->var)); - DECL_INITIAL (dp->var) = error_mark_node; - } + init = build2 (INIT_EXPR, void_type_node, dp->result, + DECL_INITIAL (dp->var)); else - init = build_empty_stmt (); - SET_EXPR_LOCUS (init, EXPR_LOCUS (*tp)); + init = build_empty_stmt (EXPR_LOCATION (*tp)); + DECL_INITIAL (dp->var) = NULL_TREE; + SET_EXPR_LOCATION (init, EXPR_LOCATION (*tp)); *tp = init; } /* And replace all uses of the NRV with the RESULT_DECL. */ @@ -3409,18 +3574,23 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor, if (need_default_ctor || (need_copy_ctor && !TYPE_HAS_TRIVIAL_INIT_REF (type))) { + VEC(tree,gc) *vec; + if (need_default_ctor) - t = NULL; + vec = NULL; else { t = build_int_cst (build_pointer_type (type), 0); t = build1 (INDIRECT_REF, type, t); - t = build_tree_list (NULL, t); + vec = make_tree_vector_single (t); } t = build_special_member_call (NULL_TREE, complete_ctor_identifier, - t, type, LOOKUP_NORMAL, + &vec, type, LOOKUP_NORMAL, tf_warning_or_error); + if (vec != NULL) + release_tree_vector (vec); + if (targetm.cxx.cdtor_returns_this () || errorcount) /* Because constructors and destructors return this, the call will have been cast to "void". Remove the @@ -3458,12 +3628,15 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor, if (need_copy_assignment && !TYPE_HAS_TRIVIAL_ASSIGN_REF (type)) { + VEC(tree,gc) *vec; + t = build_int_cst (build_pointer_type (type), 0); t = build1 (INDIRECT_REF, type, t); + vec = make_tree_vector_single (t); t = build_special_member_call (t, ansi_assopname (NOP_EXPR), - build_tree_list (NULL, t), - type, LOOKUP_NORMAL, + &vec, type, LOOKUP_NORMAL, tf_warning_or_error); + release_tree_vector (vec); /* We'll have called convert_from_reference on the call, which may well have added an indirect_ref. It's unneeded here, @@ -3633,7 +3806,7 @@ finish_omp_clauses (tree clauses) for (pc = &clauses, c = clauses; c ; c = *pc) { - enum tree_code c_kind = OMP_CLAUSE_CODE (c); + enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c); bool remove = false; bool need_complete_non_reference = false; bool need_default_ctor = false; @@ -3838,7 +4011,7 @@ finish_omp_threadprivate (tree vars) /* Make sure that DECL_DISCRIMINATOR_P continues to be true after the allocation of the lang_decl structure. */ if (DECL_DISCRIMINATOR_P (v)) - DECL_LANG_SPECIFIC (v)->decl_flags.u2sel = 1; + DECL_LANG_SPECIFIC (v)->u.base.u2sel = 1; } if (! DECL_THREAD_LOCAL_P (v)) @@ -3941,6 +4114,9 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv, case GE_EXPR: case LT_EXPR: case LE_EXPR: + if (TREE_OPERAND (cond, 1) == iter) + cond = build2 (swap_tree_comparison (TREE_CODE (cond)), + TREE_TYPE (cond), iter, TREE_OPERAND (cond, 0)); if (TREE_OPERAND (cond, 0) != iter) cond = error_mark_node; else @@ -3958,7 +4134,7 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv, } if (cond == error_mark_node) { - error ("%Hinvalid controlling predicate", &elocus); + error_at (elocus, "invalid controlling predicate"); return true; } diff = build_x_binary_op (MINUS_EXPR, TREE_OPERAND (cond, 1), @@ -3968,8 +4144,8 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv, return true; if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE) { - error ("%Hdifference between %qE and %qD does not have integer type", - &elocus, TREE_OPERAND (cond, 1), iter); + error_at (elocus, "difference between %qE and %qD does not have integer type", + TREE_OPERAND (cond, 1), iter); return true; } @@ -4063,7 +4239,7 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv, if (incr == error_mark_node) { - error ("%Hinvalid increment expression", &elocus); + error_at (elocus, "invalid increment expression"); return true; } @@ -4107,9 +4283,11 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv, tf_warning_or_error)); *pre_body = pop_stmt_list (*pre_body); - cond = cp_build_binary_op (TREE_CODE (cond), decl, diff, + cond = cp_build_binary_op (elocus, + TREE_CODE (cond), decl, diff, tf_warning_or_error); - incr = build_modify_expr (decl, PLUS_EXPR, incr); + incr = build_modify_expr (elocus, decl, NULL_TREE, PLUS_EXPR, + elocus, incr, NULL_TREE); orig_body = *body; *body = push_stmt_list (); @@ -4188,8 +4366,8 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv, if (decl == NULL) { - error ("%Hexpected iteration declaration or initialization", - &locus); + error_at (locus, + "expected iteration declaration or initialization"); return NULL; } } @@ -4199,13 +4377,13 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv, if (cond == NULL) { - error ("%Hmissing controlling predicate", &elocus); + error_at (elocus, "missing controlling predicate"); return NULL; } if (incr == NULL) { - error ("%Hmissing increment expression", &elocus); + error_at (elocus, "missing increment expression"); return NULL; } @@ -4259,8 +4437,7 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv, if (!DECL_P (decl)) { - error ("%Hexpected iteration declaration or initialization", - &elocus); + error_at (elocus, "expected iteration declaration or initialization"); return NULL; } @@ -4285,20 +4462,36 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv, if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)) && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE) { - error ("%Hinvalid type for iteration variable %qE", &elocus, decl); + error_at (elocus, "invalid type for iteration variable %qE", decl); return NULL; } if (!processing_template_decl) - init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); - init = cp_build_modify_expr (decl, NOP_EXPR, init, tf_warning_or_error); - if (cond && TREE_SIDE_EFFECTS (cond) && COMPARISON_CLASS_P (cond)) { - int n = TREE_SIDE_EFFECTS (TREE_OPERAND (cond, 1)) != 0; - tree t = TREE_OPERAND (cond, n); + init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); + init = cp_build_modify_expr (decl, NOP_EXPR, init, tf_warning_or_error); + } + else + init = build2 (MODIFY_EXPR, void_type_node, decl, init); + if (cond + && TREE_SIDE_EFFECTS (cond) + && COMPARISON_CLASS_P (cond) + && !processing_template_decl) + { + tree t = TREE_OPERAND (cond, 0); + if (TREE_SIDE_EFFECTS (t) + && t != decl + && (TREE_CODE (t) != NOP_EXPR + || TREE_OPERAND (t, 0) != decl)) + TREE_OPERAND (cond, 0) + = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - if (!processing_template_decl) - TREE_OPERAND (cond, n) + t = TREE_OPERAND (cond, 1); + if (TREE_SIDE_EFFECTS (t) + && t != decl + && (TREE_CODE (t) != NOP_EXPR + || TREE_OPERAND (t, 0) != decl)) + TREE_OPERAND (cond, 1) = fold_build_cleanup_point_expr (TREE_TYPE (t), t); } if (decl == error_mark_node || init == error_mark_node) @@ -4322,21 +4515,31 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv, for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)); i++) { - tree incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i); + decl = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), i), 0); + incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i); if (TREE_CODE (incr) != MODIFY_EXPR) continue; if (TREE_SIDE_EFFECTS (TREE_OPERAND (incr, 1)) - && BINARY_CLASS_P (TREE_OPERAND (incr, 1))) + && BINARY_CLASS_P (TREE_OPERAND (incr, 1)) + && !processing_template_decl) { - tree t = TREE_OPERAND (incr, 1); - int n = TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)) != 0; + tree t = TREE_OPERAND (TREE_OPERAND (incr, 1), 0); + if (TREE_SIDE_EFFECTS (t) + && t != decl + && (TREE_CODE (t) != NOP_EXPR + || TREE_OPERAND (t, 0) != decl)) + TREE_OPERAND (TREE_OPERAND (incr, 1), 0) + = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - if (!processing_template_decl) - TREE_OPERAND (t, n) - = fold_build_cleanup_point_expr (TREE_TYPE (TREE_OPERAND (t, n)), - TREE_OPERAND (t, n)); + t = TREE_OPERAND (TREE_OPERAND (incr, 1), 1); + if (TREE_SIDE_EFFECTS (t) + && t != decl + && (TREE_CODE (t) != NOP_EXPR + || TREE_OPERAND (t, 0) != decl)) + TREE_OPERAND (TREE_OPERAND (incr, 1), 1) + = fold_build_cleanup_point_expr (TREE_TYPE (t), t); } if (orig_incr) @@ -4374,7 +4577,7 @@ finish_omp_atomic (enum tree_code code, tree lhs, tree rhs) } if (!dependent_p) { - stmt = c_finish_omp_atomic (code, lhs, rhs); + stmt = c_finish_omp_atomic (input_location, code, lhs, rhs); if (stmt == error_mark_node) return; } @@ -4388,7 +4591,9 @@ void finish_omp_barrier (void) { tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER]; - tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error); + VEC(tree,gc) *vec = make_tree_vector (); + tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); + release_tree_vector (vec); finish_expr_stmt (stmt); } @@ -4396,7 +4601,9 @@ void finish_omp_flush (void) { tree fn = built_in_decls[BUILT_IN_SYNCHRONIZE]; - tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error); + VEC(tree,gc) *vec = make_tree_vector (); + tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); + release_tree_vector (vec); finish_expr_stmt (stmt); } @@ -4404,7 +4611,9 @@ void finish_omp_taskwait (void) { tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT]; - tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error); + VEC(tree,gc) *vec = make_tree_vector (); + tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); + release_tree_vector (vec); finish_expr_stmt (stmt); } @@ -4468,12 +4677,72 @@ finish_static_assert (tree condition, tree message, location_t location, } } +/* Returns the type of EXPR for cases where we can determine it even though + EXPR is a type-dependent expression. */ + +tree +describable_type (tree expr) +{ + tree type = NULL_TREE; + + if (! type_dependent_expression_p (expr) + && ! type_unknown_p (expr)) + { + type = unlowered_expr_type (expr); + if (real_lvalue_p (expr)) + type = build_reference_type (type); + } + + if (type) + return type; + + switch (TREE_CODE (expr)) + { + case VAR_DECL: + case PARM_DECL: + case RESULT_DECL: + case FUNCTION_DECL: + return TREE_TYPE (expr); + break; + + case NEW_EXPR: + case CONST_DECL: + case TEMPLATE_PARM_INDEX: + case CAST_EXPR: + case STATIC_CAST_EXPR: + case REINTERPRET_CAST_EXPR: + case CONST_CAST_EXPR: + case DYNAMIC_CAST_EXPR: + type = TREE_TYPE (expr); + break; + + case INDIRECT_REF: + { + tree ptrtype = describable_type (TREE_OPERAND (expr, 0)); + if (ptrtype && POINTER_TYPE_P (ptrtype)) + type = build_reference_type (TREE_TYPE (ptrtype)); + } + break; + + default: + if (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_constant) + type = TREE_TYPE (expr); + break; + } + + if (type && type_uses_auto (type)) + return NULL_TREE; + else + return type; +} + /* Implements the C++0x decltype keyword. Returns the type of EXPR, suitable for use as a type-specifier. ID_EXPRESSION_OR_MEMBER_ACCESS_P is true when EXPR was parsed as an id-expression or a class member access, FALSE when it was parsed as a full expression. */ + tree finish_decltype_type (tree expr, bool id_expression_or_member_access_p) { @@ -4492,8 +4761,36 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) return error_mark_node; } - if (type_dependent_expression_p (expr)) + if (type_dependent_expression_p (expr) + /* In a template, a COMPONENT_REF has an IDENTIFIER_NODE for op1 even + if it isn't dependent, so that we can check access control at + instantiation time, so defer the decltype as well (PR 42277). */ + || (id_expression_or_member_access_p + && processing_template_decl + && TREE_CODE (expr) == COMPONENT_REF)) { + if (id_expression_or_member_access_p) + { + switch (TREE_CODE (expr)) + { + case VAR_DECL: + case PARM_DECL: + case RESULT_DECL: + case FUNCTION_DECL: + case CONST_DECL: + case TEMPLATE_PARM_INDEX: + type = TREE_TYPE (expr); + break; + + default: + break; + } + } + + if (type && !type_uses_auto (type)) + return type; + + treat_as_dependent: type = cxx_make_type (DECLTYPE_TYPE); DECLTYPE_TYPE_EXPR (type) = expr; DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type) @@ -4505,6 +4802,15 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) /* The type denoted by decltype(e) is defined as follows: */ + expr = resolve_nondeduced_context (expr); + + /* To get the size of a static data member declared as an array of + unknown bound, we need to instantiate it. */ + if (TREE_CODE (expr) == VAR_DECL + && VAR_HAD_UNKNOWN_BOUND (expr) + && DECL_TEMPLATE_INSTANTIATION (expr)) + instantiate_decl (expr, /*defer_ok*/true, /*expl_inst_mem*/false); + if (id_expression_or_member_access_p) { /* If e is an id-expression or a class member access (5.2.5 @@ -4530,9 +4836,13 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) /* See through BASELINK nodes to the underlying functions. */ expr = BASELINK_FUNCTIONS (expr); + if (TREE_CODE (expr) == TEMPLATE_ID_EXPR) + expr = TREE_OPERAND (expr, 0); + if (TREE_CODE (expr) == OVERLOAD) { - if (OVL_CHAIN (expr)) + if (OVL_CHAIN (expr) + || TREE_CODE (OVL_FUNCTION (expr)) == TEMPLATE_DECL) { error ("%qE refers to a set of overloaded functions", orig_expr); return error_mark_node; @@ -4558,6 +4868,8 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) case CONST_DECL: case PARM_DECL: case RESULT_DECL: + case TEMPLATE_PARM_INDEX: + expr = mark_type_use (expr); type = TREE_TYPE (expr); break; @@ -4566,6 +4878,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) break; case COMPONENT_REF: + mark_type_use (expr); type = is_bitfield_expr_with_lowered_type (expr); if (!type) type = TREE_TYPE (TREE_OPERAND (expr, 1)); @@ -4615,6 +4928,11 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) && (TREE_CODE (TREE_TYPE (target_type)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (target_type)) == METHOD_TYPE)) type = TREE_TYPE (TREE_TYPE (target_type)); + else if (processing_template_decl) + /* Within a template finish_call_expr doesn't resolve + CALL_EXPR_FN, so even though this decltype isn't really + dependent let's defer resolving it. */ + goto treat_as_dependent; else sorry ("unable to determine the declared type of expression %<%E%>", expr); @@ -4635,6 +4953,18 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) if (real_lvalue_p (expr)) type = build_reference_type (type); } + /* Within a lambda-expression: + + Every occurrence of decltype((x)) where x is a possibly + parenthesized id-expression that names an entity of + automatic storage duration is treated as if x were + transformed into an access to a corresponding data member + of the closure type that would have been declared if x + were a use of the denoted entity. */ + else if (outer_automatic_var_p (expr) + && current_function_decl + && LAMBDA_FUNCTION_P (current_function_decl)) + type = capture_decltype (expr); else { /* Otherwise, where T is the type of e, if e is an lvalue, @@ -4689,6 +5019,8 @@ classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p) it now. */ if (CLASSTYPE_LAZY_COPY_CTOR (type)) lazily_declare_fn (sfk_copy_constructor, type); + if (CLASSTYPE_LAZY_MOVE_CTOR (type)) + lazily_declare_fn (sfk_move_constructor, type); fns = CLASSTYPE_CONSTRUCTORS (type); } else @@ -4726,6 +5058,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) switch (kind) { case CPTK_HAS_NOTHROW_ASSIGN: + type1 = strip_array_types (type1); return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE && (trait_expr_value (CPTK_HAS_TRIVIAL_ASSIGN, type1, type2) || (CLASS_TYPE_P (type1) @@ -4733,8 +5066,11 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) true)))); case CPTK_HAS_TRIVIAL_ASSIGN: + /* ??? The standard seems to be missing the "or array of such a class + type" wording for this trait. */ + type1 = strip_array_types (type1); return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE - && (pod_type_p (type1) + && (trivial_type_p (type1) || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_ASSIGN_REF (type1)))); @@ -4747,21 +5083,25 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) case CPTK_HAS_TRIVIAL_CONSTRUCTOR: type1 = strip_array_types (type1); - return (pod_type_p (type1) + return (trivial_type_p (type1) || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DFLT (type1))); case CPTK_HAS_NOTHROW_COPY: + type1 = strip_array_types (type1); return (trait_expr_value (CPTK_HAS_TRIVIAL_COPY, type1, type2) || (CLASS_TYPE_P (type1) && classtype_has_nothrow_assign_or_copy_p (type1, false))); case CPTK_HAS_TRIVIAL_COPY: - return (pod_type_p (type1) || type_code1 == REFERENCE_TYPE + /* ??? The standard seems to be missing the "or array of such a class + type" wording for this trait. */ + type1 = strip_array_types (type1); + return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_INIT_REF (type1))); case CPTK_HAS_TRIVIAL_DESTRUCTOR: type1 = strip_array_types (type1); - return (pod_type_p (type1) || type_code1 == REFERENCE_TYPE + return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DESTRUCTOR (type1))); @@ -4795,6 +5135,12 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) case CPTK_IS_POLYMORPHIC: return (CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1)); + case CPTK_IS_STD_LAYOUT: + return (std_layout_type_p (type1)); + + case CPTK_IS_TRIVIAL: + return (trivial_type_p (type1)); + case CPTK_IS_UNION: return (type_code1 == UNION_TYPE); @@ -4804,6 +5150,24 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) } } +/* Returns true if TYPE is a complete type, an array of unknown bound, + or (possibly cv-qualified) void, returns false otherwise. */ + +static bool +check_trait_type (tree type) +{ + if (COMPLETE_TYPE_P (type)) + return true; + + if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)) + return true; + + if (VOID_TYPE_P (type)) + return true; + + return false; +} + /* Process a trait expression. */ tree @@ -4825,6 +5189,8 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2) || kind == CPTK_IS_ENUM || kind == CPTK_IS_POD || kind == CPTK_IS_POLYMORPHIC + || kind == CPTK_IS_STD_LAYOUT + || kind == CPTK_IS_TRIVIAL || kind == CPTK_IS_UNION); if (kind == CPTK_IS_CONVERTIBLE_TO) @@ -4852,18 +5218,782 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2) if (type2) complete_type (type2); - /* The only required diagnostic. */ - if (kind == CPTK_IS_BASE_OF - && NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) - && !same_type_ignoring_top_level_qualifiers_p (type1, type2) - && !COMPLETE_TYPE_P (type2)) + switch (kind) { - error ("incomplete type %qT not allowed", type2); - return error_mark_node; + case CPTK_HAS_NOTHROW_ASSIGN: + case CPTK_HAS_TRIVIAL_ASSIGN: + case CPTK_HAS_NOTHROW_CONSTRUCTOR: + case CPTK_HAS_TRIVIAL_CONSTRUCTOR: + case CPTK_HAS_NOTHROW_COPY: + case CPTK_HAS_TRIVIAL_COPY: + case CPTK_HAS_TRIVIAL_DESTRUCTOR: + case CPTK_HAS_VIRTUAL_DESTRUCTOR: + case CPTK_IS_ABSTRACT: + case CPTK_IS_EMPTY: + case CPTK_IS_POD: + case CPTK_IS_POLYMORPHIC: + case CPTK_IS_STD_LAYOUT: + case CPTK_IS_TRIVIAL: + if (!check_trait_type (type1)) + { + error ("incomplete type %qT not allowed", type1); + return error_mark_node; + } + break; + + case CPTK_IS_BASE_OF: + if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) + && !same_type_ignoring_top_level_qualifiers_p (type1, type2) + && !COMPLETE_TYPE_P (type2)) + { + error ("incomplete type %qT not allowed", type2); + return error_mark_node; + } + break; + + case CPTK_IS_CLASS: + case CPTK_IS_ENUM: + case CPTK_IS_UNION: + break; + + case CPTK_IS_CONVERTIBLE_TO: + default: + gcc_unreachable (); } return (trait_expr_value (kind, type1, type2) ? boolean_true_node : boolean_false_node); } +/* Do-nothing variants of functions to handle pragma FLOAT_CONST_DECIMAL64, + which is ignored for C++. */ + +void +set_float_const_decimal64 (void) +{ +} + +void +clear_float_const_decimal64 (void) +{ +} + +bool +float_const_decimal64_p (void) +{ + return 0; +} + +/* Return true if T is a literal type. */ + +bool +literal_type_p (tree t) +{ + if (SCALAR_TYPE_P (t)) + return true; + if (CLASS_TYPE_P (t)) + return CLASSTYPE_LITERAL_P (t); + if (TREE_CODE (t) == ARRAY_TYPE) + return literal_type_p (strip_array_types (t)); + return false; +} + + +/* If DECL is a variable declared `constexpr', require its type + be literal. Return the DECL if OK, otherwise NULL. */ + +tree +ensure_literal_type_for_constexpr_object (tree decl) +{ + tree type = TREE_TYPE (decl); + if (TREE_CODE (decl) == VAR_DECL && DECL_DECLARED_CONSTEXPR_P (decl) + && !processing_template_decl && !literal_type_p (type)) + { + error ("the type %qT of constexpr variable %qD is not literal", + type, decl); + return NULL; + } + return decl; +} + +/* Return non-null if FUN certainly designates a valid constexpr function + declaration. Otherwise return NULL. Issue appropriate diagnostics + if necessary. Note that we only check the declaration, not the body + of the function. */ + +tree +validate_constexpr_fundecl (tree fun) +{ + tree rettype = NULL; + tree parm = NULL; + + /* Don't bother if FUN is not marked constexpr. */ + if (!DECL_DECLARED_CONSTEXPR_P (fun)) + return NULL; + + /* For a function template, we have absolutely no guarantee that all + instantiations will be constexpr. */ + if (TREE_CODE (fun) == TEMPLATE_DECL) + return NULL; + + parm = FUNCTION_FIRST_USER_PARM (fun); + for (; parm != NULL; parm = TREE_CHAIN (parm)) + { + tree type = TREE_TYPE (parm); + if (dependent_type_p (type)) + return NULL; + if (!literal_type_p (type)) + { + error ("parameter %q#D is not of literal type", parm); + return NULL; + } + } + + if (DECL_CONSTRUCTOR_P (fun)) + return fun; + + rettype = TREE_TYPE (TREE_TYPE (fun)); + if (dependent_type_p (rettype)) + return NULL; + if (!literal_type_p (rettype)) + { + error ("return type %qT of function %qD is not a literal type", + TREE_TYPE (TREE_TYPE (fun)), fun); + return NULL; + } + return fun; +} + + +/* Constructor for a lambda expression. */ + +tree +build_lambda_expr (void) +{ + tree lambda = make_node (LAMBDA_EXPR); + LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) = CPLD_NONE; + LAMBDA_EXPR_CAPTURE_LIST (lambda) = NULL_TREE; + LAMBDA_EXPR_THIS_CAPTURE (lambda) = NULL_TREE; + LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE; + LAMBDA_EXPR_MUTABLE_P (lambda) = false; + return lambda; +} + +/* Create the closure object for a LAMBDA_EXPR. */ + +tree +build_lambda_object (tree lambda_expr) +{ + /* Build aggregate constructor call. + - cp_parser_braced_list + - cp_parser_functional_cast */ + VEC(constructor_elt,gc) *elts = NULL; + tree node, expr, type; + location_t saved_loc; + + if (processing_template_decl) + return lambda_expr; + + /* Make sure any error messages refer to the lambda-introducer. */ + saved_loc = input_location; + input_location = LAMBDA_EXPR_LOCATION (lambda_expr); + + for (node = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); + node; + node = TREE_CHAIN (node)) + { + tree field = TREE_PURPOSE (node); + tree val = TREE_VALUE (node); + + if (DECL_P (val)) + mark_used (val); + + /* Mere mortals can't copy arrays with aggregate initialization, so + do some magic to make it work here. */ + if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE) + val = build_array_copy (val); + else if (DECL_NORMAL_CAPTURE_P (field) + && TREE_CODE (TREE_TYPE (field)) != REFERENCE_TYPE) + { + /* "the entities that are captured by copy are used to + direct-initialize each corresponding non-static data + member of the resulting closure object." + + There's normally no way to express direct-initialization + from an element of a CONSTRUCTOR, so we build up a special + TARGET_EXPR to bypass the usual copy-initialization. */ + val = force_rvalue (val); + if (TREE_CODE (val) == TARGET_EXPR) + TARGET_EXPR_DIRECT_INIT_P (val) = true; + } + + CONSTRUCTOR_APPEND_ELT (elts, DECL_NAME (field), val); + } + + expr = build_constructor (init_list_type_node, elts); + CONSTRUCTOR_IS_DIRECT_INIT (expr) = 1; + + /* N2927: "[The closure] class type is not an aggregate." + But we briefly treat it as an aggregate to make this simpler. */ + type = TREE_TYPE (lambda_expr); + CLASSTYPE_NON_AGGREGATE (type) = 0; + expr = finish_compound_literal (type, expr); + CLASSTYPE_NON_AGGREGATE (type) = 1; + + input_location = saved_loc; + return expr; +} + +/* Return an initialized RECORD_TYPE for LAMBDA. + LAMBDA must have its explicit captures already. */ + +tree +begin_lambda_type (tree lambda) +{ + tree type; + + { + /* Unique name. This is just like an unnamed class, but we cannot use + make_anon_name because of certain checks against TYPE_ANONYMOUS_P. */ + tree name; + name = make_lambda_name (); + + /* Create the new RECORD_TYPE for this lambda. */ + type = xref_tag (/*tag_code=*/record_type, + name, + /*scope=*/ts_within_enclosing_non_class, + /*template_header_p=*/false); + } + + /* Designate it as a struct so that we can use aggregate initialization. */ + CLASSTYPE_DECLARED_CLASS (type) = false; + + /* Clear base types. */ + xref_basetypes (type, /*bases=*/NULL_TREE); + + /* Start the class. */ + type = begin_class_definition (type, /*attributes=*/NULL_TREE); + + /* Cross-reference the expression and the type. */ + TREE_TYPE (lambda) = type; + CLASSTYPE_LAMBDA_EXPR (type) = lambda; + + return type; +} + +/* Returns the type to use for the return type of the operator() of a + closure class. */ + +tree +lambda_return_type (tree expr) +{ + tree type; + if (BRACE_ENCLOSED_INITIALIZER_P (expr)) + { + warning (0, "cannot deduce lambda return type from a braced-init-list"); + return void_type_node; + } + if (type_dependent_expression_p (expr)) + { + type = cxx_make_type (DECLTYPE_TYPE); + DECLTYPE_TYPE_EXPR (type) = expr; + DECLTYPE_FOR_LAMBDA_RETURN (type) = true; + SET_TYPE_STRUCTURAL_EQUALITY (type); + } + else + type = type_decays_to (unlowered_expr_type (expr)); + return type; +} + +/* Given a LAMBDA_EXPR or closure type LAMBDA, return the op() of the + closure type. */ + +tree +lambda_function (tree lambda) +{ + tree type; + if (TREE_CODE (lambda) == LAMBDA_EXPR) + type = TREE_TYPE (lambda); + else + type = lambda; + gcc_assert (LAMBDA_TYPE_P (type)); + /* Don't let debug_tree cause instantiation. */ + if (CLASSTYPE_TEMPLATE_INSTANTIATION (type) && !COMPLETE_TYPE_P (type)) + return NULL_TREE; + lambda = lookup_member (type, ansi_opname (CALL_EXPR), + /*protect=*/0, /*want_type=*/false); + if (lambda) + lambda = BASELINK_FUNCTIONS (lambda); + return lambda; +} + +/* Returns the type to use for the FIELD_DECL corresponding to the + capture of EXPR. + The caller should add REFERENCE_TYPE for capture by reference. */ + +tree +lambda_capture_field_type (tree expr) +{ + tree type; + if (type_dependent_expression_p (expr)) + { + type = cxx_make_type (DECLTYPE_TYPE); + DECLTYPE_TYPE_EXPR (type) = expr; + DECLTYPE_FOR_LAMBDA_CAPTURE (type) = true; + SET_TYPE_STRUCTURAL_EQUALITY (type); + } + else + type = non_reference (unlowered_expr_type (expr)); + return type; +} + +/* Recompute the return type for LAMBDA with body of the form: + { return EXPR ; } */ + +void +apply_lambda_return_type (tree lambda, tree return_type) +{ + tree fco = lambda_function (lambda); + tree result; + + LAMBDA_EXPR_RETURN_TYPE (lambda) = return_type; + + /* If we got a DECLTYPE_TYPE, don't stick it in the function yet, + it would interfere with instantiating the closure type. */ + if (dependent_type_p (return_type)) + return; + if (return_type == error_mark_node) + return; + + /* TREE_TYPE (FUNCTION_DECL) == METHOD_TYPE + TREE_TYPE (METHOD_TYPE) == return-type */ + TREE_TYPE (fco) = change_return_type (return_type, TREE_TYPE (fco)); + + result = DECL_RESULT (fco); + if (result == NULL_TREE) + return; + + /* We already have a DECL_RESULT from start_preparsed_function. + Now we need to redo the work it and allocate_struct_function + did to reflect the new type. */ + result = build_decl (input_location, RESULT_DECL, NULL_TREE, + TYPE_MAIN_VARIANT (return_type)); + DECL_ARTIFICIAL (result) = 1; + DECL_IGNORED_P (result) = 1; + cp_apply_type_quals_to_decl (cp_type_quals (return_type), + result); + + DECL_RESULT (fco) = result; + + if (!processing_template_decl && aggregate_value_p (result, fco)) + { +#ifdef PCC_STATIC_STRUCT_RETURN + cfun->returns_pcc_struct = 1; +#endif + cfun->returns_struct = 1; + } + +} + +/* DECL is a local variable or parameter from the surrounding scope of a + lambda-expression. Returns the decltype for a use of the capture field + for DECL even if it hasn't been captured yet. */ + +static tree +capture_decltype (tree decl) +{ + tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl)); + /* FIXME do lookup instead of list walk? */ + tree cap = value_member (decl, LAMBDA_EXPR_CAPTURE_LIST (lam)); + tree type; + + if (cap) + type = TREE_TYPE (TREE_PURPOSE (cap)); + else + switch (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam)) + { + case CPLD_NONE: + error ("%qD is not captured", decl); + return error_mark_node; + + case CPLD_COPY: + type = TREE_TYPE (decl); + if (TREE_CODE (type) == REFERENCE_TYPE + && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE) + type = TREE_TYPE (type); + break; + + case CPLD_REFERENCE: + type = TREE_TYPE (decl); + if (TREE_CODE (type) != REFERENCE_TYPE) + type = build_reference_type (TREE_TYPE (decl)); + break; + + default: + gcc_unreachable (); + } + + if (TREE_CODE (type) != REFERENCE_TYPE) + { + if (!LAMBDA_EXPR_MUTABLE_P (lam)) + type = cp_build_qualified_type (type, (TYPE_QUALS (type) + |TYPE_QUAL_CONST)); + type = build_reference_type (type); + } + return type; +} + +/* From an ID and INITIALIZER, create a capture (by reference if + BY_REFERENCE_P is true), add it to the capture-list for LAMBDA, + and return it. */ + +tree +add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, + bool explicit_init_p) +{ + tree type; + tree member; + + type = lambda_capture_field_type (initializer); + if (by_reference_p) + { + type = build_reference_type (type); + if (!real_lvalue_p (initializer)) + error ("cannot capture %qE by reference", initializer); + } + + /* Make member variable. */ + member = build_lang_decl (FIELD_DECL, id, type); + if (!explicit_init_p) + /* Normal captures are invisible to name lookup but uses are replaced + with references to the capture field; we implement this by only + really making them invisible in unevaluated context; see + qualify_lookup. For now, let's make explicitly initialized captures + always visible. */ + DECL_NORMAL_CAPTURE_P (member) = true; + + /* Add it to the appropriate closure class if we've started it. */ + if (current_class_type && current_class_type == TREE_TYPE (lambda)) + finish_member_declaration (member); + + LAMBDA_EXPR_CAPTURE_LIST (lambda) + = tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda)); + + if (id == get_identifier ("__this")) + { + if (LAMBDA_EXPR_CAPTURES_THIS_P (lambda)) + error ("already captured % in lambda expression"); + LAMBDA_EXPR_THIS_CAPTURE (lambda) = member; + } + + return member; +} + +/* Register all the capture members on the list CAPTURES, which is the + LAMBDA_EXPR_CAPTURE_LIST for the lambda after the introducer. */ + +void register_capture_members (tree captures) +{ + if (captures) + { + register_capture_members (TREE_CHAIN (captures)); + finish_member_declaration (TREE_PURPOSE (captures)); + } +} + +/* Given a FIELD_DECL decl belonging to a closure type, return a + COMPONENT_REF of it relative to the 'this' parameter of the op() for + that type. */ + +static tree +thisify_lambda_field (tree decl) +{ + tree context = lambda_function (DECL_CONTEXT (decl)); + tree object = cp_build_indirect_ref (DECL_ARGUMENTS (context), + RO_NULL, + tf_warning_or_error); + return finish_non_static_data_member (decl, object, + /*qualifying_scope*/NULL_TREE); +} + +/* Similar to add_capture, except this works on a stack of nested lambdas. + BY_REFERENCE_P in this case is derived from the default capture mode. + Returns the capture for the lambda at the bottom of the stack. */ + +tree +add_default_capture (tree lambda_stack, tree id, tree initializer) +{ + bool this_capture_p = (id == get_identifier ("__this")); + + tree member = NULL_TREE; + + tree saved_class_type = current_class_type; + + tree node; + + for (node = lambda_stack; + node; + node = TREE_CHAIN (node)) + { + tree lambda = TREE_VALUE (node); + + current_class_type = TREE_TYPE (lambda); + member = add_capture (lambda, + id, + initializer, + /*by_reference_p=*/ + (!this_capture_p + && (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) + == CPLD_REFERENCE)), + /*explicit_init_p=*/false); + initializer = thisify_lambda_field (member); + } + + current_class_type = saved_class_type; + + return member; +} + +/* Return the capture pertaining to a use of 'this' in LAMBDA, in the form of an + INDIRECT_REF, possibly adding it through default capturing. */ + +tree +lambda_expr_this_capture (tree lambda) +{ + tree result; + + tree this_capture = LAMBDA_EXPR_THIS_CAPTURE (lambda); + + /* Try to default capture 'this' if we can. */ + if (!this_capture + && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE) + { + tree containing_function = TYPE_CONTEXT (TREE_TYPE (lambda)); + tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE); + tree init = NULL_TREE; + + /* If we are in a lambda function, we can move out until we hit: + 1. a non-lambda function, + 2. a lambda function capturing 'this', or + 3. a non-default capturing lambda function. */ + while (LAMBDA_FUNCTION_P (containing_function)) + { + tree lambda + = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (containing_function)); + + if (LAMBDA_EXPR_THIS_CAPTURE (lambda)) + { + /* An outer lambda has already captured 'this'. */ + tree cap = LAMBDA_EXPR_THIS_CAPTURE (lambda); + init = thisify_lambda_field (cap); + break; + } + + if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_NONE) + /* An outer lambda won't let us capture 'this'. */ + break; + + lambda_stack = tree_cons (NULL_TREE, + lambda, + lambda_stack); + + containing_function = decl_function_context (containing_function); + } + + if (!init && DECL_NONSTATIC_MEMBER_FUNCTION_P (containing_function) + && !LAMBDA_FUNCTION_P (containing_function)) + /* First parameter is 'this'. */ + init = DECL_ARGUMENTS (containing_function); + + if (init) + this_capture = add_default_capture (lambda_stack, + /*id=*/get_identifier ("__this"), + init); + } + + if (!this_capture) + { + error ("% was not captured for this lambda function"); + result = error_mark_node; + } + else + { + /* To make sure that current_class_ref is for the lambda. */ + gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda)); + + result = finish_non_static_data_member (this_capture, + NULL_TREE, + /*qualifying_scope=*/NULL_TREE); + + /* If 'this' is captured, each use of 'this' is transformed into an + access to the corresponding unnamed data member of the closure + type cast (_expr.cast_ 5.4) to the type of 'this'. [ The cast + ensures that the transformed expression is an rvalue. ] */ + result = rvalue (result); + } + + return result; +} + +/* Returns the method basetype of the innermost non-lambda function, or + NULL_TREE if none. */ + +tree +nonlambda_method_basetype (void) +{ + tree fn, type; + if (!current_class_ref) + return NULL_TREE; + + type = current_class_type; + if (!LAMBDA_TYPE_P (type)) + return type; + + /* Find the nearest enclosing non-lambda function. */ + fn = TYPE_NAME (type); + do + fn = decl_function_context (fn); + while (fn && LAMBDA_FUNCTION_P (fn)); + + if (!fn || !DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) + return NULL_TREE; + + return TYPE_METHOD_BASETYPE (TREE_TYPE (fn)); +} + +/* If the closure TYPE has a static op(), also add a conversion to function + pointer. */ + +void +maybe_add_lambda_conv_op (tree type) +{ + bool nested = (current_function_decl != NULL_TREE); + tree callop = lambda_function (type); + tree rettype, name, fntype, fn, body, compound_stmt; + tree thistype, stattype, statfn, convfn, call, arg; + VEC (tree, gc) *argvec; + + if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE) + return; + + stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)), + FUNCTION_ARG_CHAIN (callop)); + + /* First build up the conversion op. */ + + rettype = build_pointer_type (stattype); + name = mangle_conv_op_name_for_type (rettype); + thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST); + fntype = build_method_type_directly (thistype, rettype, void_list_node); + fn = convfn = build_lang_decl (FUNCTION_DECL, name, fntype); + DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop); + + if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn + && DECL_ALIGN (fn) < 2 * BITS_PER_UNIT) + DECL_ALIGN (fn) = 2 * BITS_PER_UNIT; + + SET_OVERLOADED_OPERATOR_CODE (fn, TYPE_EXPR); + grokclassfn (type, fn, NO_SPECIAL); + set_linkage_according_to_type (type, fn); + rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof); + DECL_IN_AGGR_P (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + DECL_NOT_REALLY_EXTERN (fn) = 1; + DECL_DECLARED_INLINE_P (fn) = 1; + DECL_ARGUMENTS (fn) = build_this_parm (fntype, TYPE_QUAL_CONST); + if (nested) + DECL_INTERFACE_KNOWN (fn) = 1; + + add_method (type, fn, NULL_TREE); + + /* Generic thunk code fails for varargs; we'll complain in mark_used if + the conversion op is used. */ + if (varargs_function_p (callop)) + { + DECL_DELETED_FN (fn) = 1; + return; + } + + /* Now build up the thunk to be returned. */ + + name = get_identifier ("_FUN"); + fn = statfn = build_lang_decl (FUNCTION_DECL, name, stattype); + DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop); + if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn + && DECL_ALIGN (fn) < 2 * BITS_PER_UNIT) + DECL_ALIGN (fn) = 2 * BITS_PER_UNIT; + grokclassfn (type, fn, NO_SPECIAL); + set_linkage_according_to_type (type, fn); + rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof); + DECL_IN_AGGR_P (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + DECL_NOT_REALLY_EXTERN (fn) = 1; + DECL_DECLARED_INLINE_P (fn) = 1; + DECL_STATIC_FUNCTION_P (fn) = 1; + DECL_ARGUMENTS (fn) = copy_list (TREE_CHAIN (DECL_ARGUMENTS (callop))); + for (arg = DECL_ARGUMENTS (fn); arg; arg = TREE_CHAIN (arg)) + DECL_CONTEXT (arg) = fn; + if (nested) + DECL_INTERFACE_KNOWN (fn) = 1; + + add_method (type, fn, NULL_TREE); + + if (nested) + push_function_context (); + + /* Generate the body of the thunk. */ + + start_preparsed_function (statfn, NULL_TREE, + SF_PRE_PARSED | SF_INCLASS_INLINE); + if (DECL_ONE_ONLY (statfn)) + { + /* Put the thunk in the same comdat group as the call op. */ + struct cgraph_node *callop_node, *thunk_node; + DECL_COMDAT_GROUP (statfn) = DECL_COMDAT_GROUP (callop); + callop_node = cgraph_node (callop); + thunk_node = cgraph_node (statfn); + gcc_assert (callop_node->same_comdat_group == NULL); + gcc_assert (thunk_node->same_comdat_group == NULL); + callop_node->same_comdat_group = thunk_node; + thunk_node->same_comdat_group = callop_node; + } + body = begin_function_body (); + compound_stmt = begin_compound_stmt (0); + + arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)), + null_pointer_node); + argvec = make_tree_vector (); + VEC_quick_push (tree, argvec, arg); + for (arg = DECL_ARGUMENTS (statfn); arg; arg = TREE_CHAIN (arg)) + VEC_safe_push (tree, gc, argvec, arg); + call = build_call_a (callop, VEC_length (tree, argvec), + VEC_address (tree, argvec)); + CALL_FROM_THUNK_P (call) = 1; + if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call))) + call = build_cplus_new (TREE_TYPE (call), call); + call = convert_from_reference (call); + finish_return_stmt (call); + + finish_compound_stmt (compound_stmt); + finish_function_body (body); + + expand_or_defer_fn (finish_function (2)); + + /* Generate the body of the conversion op. */ + + start_preparsed_function (convfn, NULL_TREE, + SF_PRE_PARSED | SF_INCLASS_INLINE); + body = begin_function_body (); + compound_stmt = begin_compound_stmt (0); + + finish_return_stmt (decay_conversion (statfn)); + + finish_compound_stmt (compound_stmt); + finish_function_body (body); + + expand_or_defer_fn (finish_function (2)); + + if (nested) + pop_function_context (); +} #include "gt-cp-semantics.h"