Submitted By: Bruce Dubbs Date: 2016-02-16 Initial Package Version: 5.3.0 Upstream Status: Committed Origin: Upstream Description: Fix various issues identified upstream. --- a/gcc/alias.c 2015-11-18 13:23:14.000000000 +0100 +++ b/gcc/alias.c 2016-02-16 15:42:07.862357854 +0100 @@ -1880,7 +1880,7 @@ } /* Return TRUE if EXPR refers to a VALUE whose uid is greater than - that of V. */ + (or equal to) that of V. */ static bool refs_newer_value_p (const_rtx expr, rtx v) @@ -1888,14 +1888,14 @@ int minuid = CSELIB_VAL_PTR (v)->uid; subrtx_iterator::array_type array; FOR_EACH_SUBRTX (iter, array, expr, NONCONST) - if (GET_CODE (*iter) == VALUE && CSELIB_VAL_PTR (*iter)->uid > minuid) + if (GET_CODE (*iter) == VALUE && CSELIB_VAL_PTR (*iter)->uid >= minuid) return true; return false; } /* Convert the address X into something we can use. This is done by returning - it unchanged unless it is a value; in the latter case we call cselib to get - a more useful rtx. */ + it unchanged unless it is a VALUE or VALUE +/- constant; for VALUE + we call cselib to get a more useful rtx. */ rtx get_addr (rtx x) @@ -1904,7 +1904,23 @@ struct elt_loc_list *l; if (GET_CODE (x) != VALUE) - return x; + { + if ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS) + && GET_CODE (XEXP (x, 0)) == VALUE + && CONST_SCALAR_INT_P (XEXP (x, 1))) + { + rtx op0 = get_addr (XEXP (x, 0)); + if (op0 != XEXP (x, 0)) + { + if (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 1)) == CONST_INT) + return plus_constant (GET_MODE (x), op0, INTVAL (XEXP (x, 1))); + return simplify_gen_binary (GET_CODE (x), GET_MODE (x), + op0, XEXP (x, 1)); + } + } + return x; + } v = CSELIB_VAL_PTR (x); if (v) { --- a/gcc/builtins.c 2015-10-08 18:54:23.000000000 +0200 +++ b/gcc/builtins.c 2016-02-16 15:12:17.980963965 +0100 @@ -497,6 +497,10 @@ { *bitposp = ptr_misalign * BITS_PER_UNIT; *alignp = ptr_align * BITS_PER_UNIT; + /* Make sure to return a sensible alignment when the multiplication + by BITS_PER_UNIT overflowed. */ + if (*alignp == 0) + *alignp = 1u << (HOST_BITS_PER_INT - 1); /* We cannot really tell whether this result is an approximation. */ return true; } --- a/gcc/c/c-decl.c 2015-09-09 09:30:42.000000000 +0200 +++ b/gcc/c/c-decl.c 2016-02-16 15:42:15.294482080 +0100 @@ -5366,6 +5366,8 @@ tree returned_attrs = NULL_TREE; bool bitfield = width != NULL; tree element_type; + tree orig_qual_type = NULL; + size_t orig_qual_indirect = 0; struct c_arg_info *arg_info = 0; addr_space_t as1, as2, address_space; location_t loc = UNKNOWN_LOCATION; @@ -5404,9 +5406,9 @@ case cdk_function: case cdk_pointer: funcdef_syntax = (decl->kind == cdk_function); - decl = decl->declarator; if (first_non_attr_kind == cdk_attrs) first_non_attr_kind = decl->kind; + decl = decl->declarator; break; case cdk_attrs: @@ -5528,12 +5530,17 @@ if ((TREE_CODE (type) == ARRAY_TYPE || first_non_attr_kind == cdk_array) && TYPE_QUALS (element_type)) - type = TYPE_MAIN_VARIANT (type); + { + orig_qual_type = type; + type = TYPE_MAIN_VARIANT (type); + } type_quals = ((constp ? TYPE_QUAL_CONST : 0) | (restrictp ? TYPE_QUAL_RESTRICT : 0) | (volatilep ? TYPE_QUAL_VOLATILE : 0) | (atomicp ? TYPE_QUAL_ATOMIC : 0) | ENCODE_QUAL_ADDR_SPACE (address_space)); + if (type_quals != TYPE_QUALS (element_type)) + orig_qual_type = NULL_TREE; /* Applying the _Atomic qualifier to an array type (through the use of typedefs or typeof) must be detected here. If the qualifier @@ -6024,6 +6031,7 @@ array_ptr_attrs = NULL_TREE; array_parm_static = 0; } + orig_qual_indirect++; break; } case cdk_function: @@ -6033,6 +6041,7 @@ attributes. */ bool really_funcdef = false; tree arg_types; + orig_qual_type = NULL_TREE; if (funcdef_flag) { const struct c_declarator *t = declarator->declarator; @@ -6133,7 +6142,9 @@ pedwarn (loc, OPT_Wpedantic, "ISO C forbids qualified function types"); if (type_quals) - type = c_build_qualified_type (type, type_quals); + type = c_build_qualified_type (type, type_quals, orig_qual_type, + orig_qual_indirect); + orig_qual_type = NULL_TREE; size_varies = false; /* When the pointed-to type involves components of variable size, @@ -6331,7 +6342,8 @@ pedwarn (loc, OPT_Wpedantic, "ISO C forbids qualified function types"); if (type_quals) - type = c_build_qualified_type (type, type_quals); + type = c_build_qualified_type (type, type_quals, orig_qual_type, + orig_qual_indirect); decl = build_decl (declarator->id_loc, TYPE_DECL, declarator->u.id, type); if (declspecs->explicit_signed_p) @@ -6384,7 +6396,8 @@ pedwarn (loc, OPT_Wpedantic, "ISO C forbids const or volatile function types"); if (type_quals) - type = c_build_qualified_type (type, type_quals); + type = c_build_qualified_type (type, type_quals, orig_qual_type, + orig_qual_indirect); return type; } @@ -6431,8 +6444,16 @@ { /* Transfer const-ness of array into that of type pointed to. */ type = TREE_TYPE (type); + if (orig_qual_type != NULL_TREE) + { + if (orig_qual_indirect == 0) + orig_qual_type = TREE_TYPE (orig_qual_type); + else + orig_qual_indirect--; + } if (type_quals) - type = c_build_qualified_type (type, type_quals); + type = c_build_qualified_type (type, type_quals, orig_qual_type, + orig_qual_indirect); type = c_build_pointer_type (type); type_quals = array_ptr_quals; if (type_quals) @@ -6523,7 +6544,8 @@ TYPE_DOMAIN (type) = build_range_type (sizetype, size_zero_node, NULL_TREE); } - type = c_build_qualified_type (type, type_quals); + type = c_build_qualified_type (type, type_quals, orig_qual_type, + orig_qual_indirect); decl = build_decl (declarator->id_loc, FIELD_DECL, declarator->u.id, type); DECL_NONADDRESSABLE_P (decl) = bitfield; @@ -6635,7 +6657,8 @@ /* An uninitialized decl with `extern' is a reference. */ int extern_ref = !initialized && storage_class == csc_extern; - type = c_build_qualified_type (type, type_quals); + type = c_build_qualified_type (type, type_quals, orig_qual_type, + orig_qual_indirect); /* C99 6.2.2p7: It is invalid (compile-time undefined behavior) to create an 'extern' declaration for a @@ -7996,7 +8019,22 @@ precision = MAX (tree_int_cst_min_precision (minnode, sign), tree_int_cst_min_precision (maxnode, sign)); - if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node)) + /* If the precision of the type was specified with an attribute and it + was too small, give an error. Otherwise, use it. */ + if (TYPE_PRECISION (enumtype)) + { + if (precision > TYPE_PRECISION (enumtype)) + { + TYPE_PRECISION (enumtype) = 0; + error ("specified mode too small for enumeral values"); + } + else + precision = TYPE_PRECISION (enumtype); + } + + if (TYPE_PACKED (enumtype) + || precision > TYPE_PRECISION (integer_type_node) + || TYPE_PRECISION (enumtype)) { tem = c_common_type_for_size (precision, sign == UNSIGNED ? 1 : 0); if (tem == NULL) @@ -8012,16 +8050,7 @@ TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem); TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem); TYPE_SIZE (enumtype) = 0; - - /* If the precision of the type was specific with an attribute and it - was too small, give an error. Otherwise, use it. */ - if (TYPE_PRECISION (enumtype)) - { - if (precision > TYPE_PRECISION (enumtype)) - error ("specified mode too small for enumeral values"); - } - else - TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem); + TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem); layout_type (enumtype); --- a/gcc/c/c-typeck.c 2015-10-05 14:35:20.000000000 +0200 +++ b/gcc/c/c-typeck.c 2016-02-16 15:33:24.580979081 +0100 @@ -10754,6 +10754,20 @@ return error_mark_node; } + /* It's not precisely specified how the usual arithmetic + conversions apply to the vector types. Here, we use + the unsigned type if one of the operands is signed and + the other one is unsigned. */ + if (TYPE_UNSIGNED (type0) != TYPE_UNSIGNED (type1)) + { + if (!TYPE_UNSIGNED (type0)) + op0 = build1 (VIEW_CONVERT_EXPR, type1, op0); + else + op1 = build1 (VIEW_CONVERT_EXPR, type0, op1); + warning_at (location, OPT_Wsign_compare, "comparison between " + "types %qT and %qT", type0, type1); + } + /* Always construct signed integer vector type. */ intt = c_common_type_for_size (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type0))), 0); @@ -10896,6 +10910,20 @@ return error_mark_node; } + /* It's not precisely specified how the usual arithmetic + conversions apply to the vector types. Here, we use + the unsigned type if one of the operands is signed and + the other one is unsigned. */ + if (TYPE_UNSIGNED (type0) != TYPE_UNSIGNED (type1)) + { + if (!TYPE_UNSIGNED (type0)) + op0 = build1 (VIEW_CONVERT_EXPR, type1, op0); + else + op1 = build1 (VIEW_CONVERT_EXPR, type0, op1); + warning_at (location, OPT_Wsign_compare, "comparison between " + "types %qT and %qT", type0, type1); + } + /* Always construct signed integer vector type. */ intt = c_common_type_for_size (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type0))), 0); @@ -12578,10 +12606,15 @@ } /* Make a variant type in the proper way for C/C++, propagating qualifiers - down to the element type of an array. */ + down to the element type of an array. If ORIG_QUAL_TYPE is not + NULL, then it should be used as the qualified type + ORIG_QUAL_INDIRECT levels down in array type derivation (to + preserve information about the typedef name from which an array + type was derived). */ tree -c_build_qualified_type (tree type, int type_quals) +c_build_qualified_type (tree type, int type_quals, tree orig_qual_type, + size_t orig_qual_indirect) { if (type == error_mark_node) return type; @@ -12590,18 +12623,22 @@ { tree t; tree element_type = c_build_qualified_type (TREE_TYPE (type), - type_quals); + type_quals, orig_qual_type, + orig_qual_indirect - 1); /* See if we already have an identically qualified type. */ - for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) - { - if (TYPE_QUALS (strip_array_types (t)) == type_quals - && TYPE_NAME (t) == TYPE_NAME (type) - && TYPE_CONTEXT (t) == TYPE_CONTEXT (type) - && attribute_list_equal (TYPE_ATTRIBUTES (t), - TYPE_ATTRIBUTES (type))) - break; - } + if (orig_qual_type && orig_qual_indirect == 0) + t = orig_qual_type; + else + for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) + { + if (TYPE_QUALS (strip_array_types (t)) == type_quals + && TYPE_NAME (t) == TYPE_NAME (type) + && TYPE_CONTEXT (t) == TYPE_CONTEXT (type) + && attribute_list_equal (TYPE_ATTRIBUTES (t), + TYPE_ATTRIBUTES (type))) + break; + } if (!t) { tree domain = TYPE_DOMAIN (type); @@ -12639,7 +12676,10 @@ type_quals &= ~TYPE_QUAL_RESTRICT; } - return build_qualified_type (type, type_quals); + tree var_type = (orig_qual_type && orig_qual_indirect == 0 + ? orig_qual_type + : build_qualified_type (type, type_quals)); + return var_type; } /* Build a VA_ARG_EXPR for the C parser. */ --- a/gcc/calls.c 2015-11-26 12:36:40.000000000 +0100 +++ b/gcc/calls.c 2016-02-16 15:03:58.694956366 +0100 @@ -576,12 +576,9 @@ /* We assume that alloca will always be called by name. It makes no sense to pass it as a pointer-to-function to anything that does not understand its behavior. */ - if (((IDENTIFIER_LENGTH (name_decl) == 6 - && name[0] == 'a' - && ! strcmp (name, "alloca")) - || (IDENTIFIER_LENGTH (name_decl) == 16 - && name[0] == '_' - && ! strcmp (name, "__builtin_alloca")))) + if (IDENTIFIER_LENGTH (name_decl) == 6 + && name[0] == 'a' + && ! strcmp (name, "alloca")) flags |= ECF_MAY_BE_ALLOCA; /* Disregard prefix _, __, __x or __builtin_. */ @@ -627,6 +624,17 @@ flags |= ECF_NORETURN; } + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_ALLOCA: + case BUILT_IN_ALLOCA_WITH_ALIGN: + flags |= ECF_MAY_BE_ALLOCA; + break; + default: + break; + } + return flags; } --- a/gcc/c-family/c-common.h 2015-04-10 09:54:46.000000000 +0200 +++ b/gcc/c-family/c-common.h 2016-02-16 15:13:32.726521859 +0100 @@ -850,7 +850,7 @@ bool = true); /* Add qualifiers to a type, in the fashion for C. */ -extern tree c_build_qualified_type (tree, int); +extern tree c_build_qualified_type (tree, int, tree = NULL_TREE, size_t = 0); /* Build tree nodes and builtin functions common to both C and C++ language frontends. */ --- a/gcc/c-family/c-ppoutput.c 2015-01-09 21:18:42.000000000 +0100 +++ b/gcc/c-family/c-ppoutput.c 2016-02-16 15:41:59.150212479 +0100 @@ -43,11 +43,11 @@ const cpp_token *prev; /* Previous token. */ const cpp_token *source; /* Source token for spacing. */ int src_line; /* Line number currently being written. */ - unsigned char printed; /* Nonzero if something output at line. */ + bool printed; /* True if something output at line. */ bool first_time; /* pp_file_change hasn't been called yet. */ - const char *src_file; /* Current source file. */ bool prev_was_system_token; /* True if the previous token was a system token.*/ + const char *src_file; /* Current source file. */ } print; /* Defined and undefined macros being queued for output with -dU at @@ -165,7 +165,7 @@ /* Initialize the print structure. */ print.src_line = 1; - print.printed = 0; + print.printed = false; print.prev = 0; print.outf = out_stream; print.first_time = 1; @@ -218,12 +218,16 @@ { line_marker_emitted = do_line_change (pfile, token, loc, false); putc (' ', print.outf); + print.printed = true; } else if (print.source->flags & PREV_WHITE || (print.prev && cpp_avoid_paste (pfile, print.prev, token)) || (print.prev == NULL && token->type == CPP_HASH)) - putc (' ', print.outf); + { + putc (' ', print.outf); + print.printed = true; + } } else if (token->flags & PREV_WHITE) { @@ -234,6 +238,7 @@ && !in_pragma) line_marker_emitted = do_line_change (pfile, token, loc, false); putc (' ', print.outf); + print.printed = true; } avoid_paste = false; @@ -251,7 +256,7 @@ fprintf (print.outf, "%s %s", space, name); else fprintf (print.outf, "%s", name); - print.printed = 1; + print.printed = true; in_pragma = true; } else if (token->type == CPP_PRAGMA_EOL) @@ -262,23 +267,23 @@ else { if (cpp_get_options (parse_in)->debug) - linemap_dump_location (line_table, token->src_loc, - print.outf); + linemap_dump_location (line_table, token->src_loc, print.outf); if (do_line_adjustments && !in_pragma && !line_marker_emitted - && print.prev_was_system_token != !!in_system_header_at(loc) + && print.prev_was_system_token != !!in_system_header_at (loc) && !is_location_from_builtin_token (loc)) /* The system-ness of this token is different from the one of the previous token. Let's emit a line change to mark the new system-ness before we emit the token. */ { do_line_change (pfile, token, loc, false); - print.prev_was_system_token = !!in_system_header_at(loc); + print.prev_was_system_token = !!in_system_header_at (loc); } cpp_output_token (token, print.outf); line_marker_emitted = false; + print.printed = true; } /* CPP_COMMENT tokens and raw-string literal tokens can @@ -328,7 +333,7 @@ size_t len = pfile->out.cur - pfile->out.base; maybe_print_line (pfile->out.first_line); fwrite (pfile->out.base, 1, len, print.outf); - print.printed = 1; + print.printed = true; if (!CPP_OPTION (pfile, discard_comments)) account_for_newlines (pfile->out.base, len); } @@ -351,7 +356,7 @@ { putc ('\n', stream); print.src_line++; - print.printed = 0; + print.printed = false; } if (!flag_no_line_commands @@ -397,7 +402,7 @@ /* End any previous line of text. */ if (print.printed) putc ('\n', stream); - print.printed = 0; + print.printed = false; if (!flag_no_line_commands) { @@ -472,7 +477,7 @@ if (!CPP_OPTION (pfile, traditional)) { int spaces = LOCATION_COLUMN (src_loc) - 2; - print.printed = 1; + print.printed = true; while (-- spaces >= 0) putc (' ', print.outf); @@ -515,6 +520,7 @@ fputs ((const char *) NODE_NAME (node), print.outf); putc ('\n', print.outf); + print.printed = false; linemap_resolve_location (line_table, line, LRK_MACRO_DEFINITION_LOCATION, &map); @@ -566,7 +572,7 @@ { putc ('\n', print.outf); print.src_line++; - print.printed = 0; + print.printed = false; } for (q = define_queue; q;) @@ -575,6 +581,7 @@ fputs ("#define ", print.outf); fputs (q->macro, print.outf); putc ('\n', print.outf); + print.printed = false; print.src_line++; oq = q; q = q->next; @@ -618,6 +625,7 @@ } putc ('\n', print.outf); + print.printed = false; print.src_line++; } @@ -683,6 +691,7 @@ maybe_print_line (line); fputs ("#pragma ", print.outf); cpp_output_line (pfile, print.outf); + print.printed = false; print.src_line++; } @@ -696,6 +705,7 @@ fputs ((const char *) cpp_macro_definition (pfile, node), print.outf); putc ('\n', print.outf); + print.printed = false; print.src_line++; } --- a/gcc/cfgexpand.c 2015-07-23 12:39:26.000000000 +0200 +++ b/gcc/cfgexpand.c 2016-02-16 15:06:16.880571076 +0100 @@ -3367,6 +3367,12 @@ { tree result = DECL_RESULT (current_function_decl); + /* Mark we have return statement with missing bounds. */ + if (!bnd + && chkp_function_instrumented_p (cfun->decl) + && !DECL_P (op0)) + bnd = error_mark_node; + /* If we are not returning the current function's RESULT_DECL, build an assignment to it. */ if (op0 != result) @@ -3383,9 +3389,6 @@ op0 = build2 (MODIFY_EXPR, TREE_TYPE (result), result, op0); } - /* Mark we have return statement with missing bounds. */ - if (!bnd && chkp_function_instrumented_p (cfun->decl)) - bnd = error_mark_node; } if (!op0) --- a/gcc/cgraph.c 2015-06-17 09:42:39.000000000 +0200 +++ b/gcc/cgraph.c 2016-02-16 15:20:15.734660357 +0100 @@ -2609,7 +2609,8 @@ if (avail > AVAIL_INTERPOSABLE) for (cs = node->callers; cs != NULL; cs = cs->next_caller) - if (!cs->indirect_inlining_edge) + if (!cs->indirect_inlining_edge + && !cs->caller->thunk.thunk_p) redirect_callers->safe_push (cs); return false; } --- a/gcc/cgraphclones.c 2015-04-02 07:14:26.000000000 +0200 +++ b/gcc/cgraphclones.c 2016-02-16 15:23:15.365194538 +0100 @@ -367,6 +367,7 @@ new_thunk = cgraph_node::create (new_decl); set_new_clone_decl_and_node_flags (new_thunk); new_thunk->definition = true; + new_thunk->local.can_change_signature = node->local.can_change_signature; new_thunk->thunk = thunk->thunk; new_thunk->unique_name = in_lto_p; new_thunk->former_clone_of = thunk->decl; --- a/gcc/cgraph.h 2015-04-01 09:41:17.000000000 +0200 +++ b/gcc/cgraph.h 2016-02-16 15:20:15.735660377 +0100 @@ -1028,7 +1028,7 @@ cgraph_edge *get_edge (gimple call_stmt); /* Collect all callers of cgraph_node and its aliases that are known to lead - to NODE (i.e. are not overwritable). */ + to NODE (i.e. are not overwritable) and that are not thunks. */ vec collect_callers (void); /* Remove all callers from the node. */ --- a/gcc/cgraphunit.c 2015-11-16 16:01:01.000000000 +0100 +++ b/gcc/cgraphunit.c 2016-02-16 15:12:32.756273515 +0100 @@ -585,6 +585,7 @@ cgraph_node *t = cgraph_node::get (thunk.alias); create_edge (t, NULL, 0, CGRAPH_FREQ_BASE); + callees->can_throw_external = !TREE_NOTHROW (t->decl); /* Target code in expand_thunk may need the thunk's target to be analyzed, so recurse here. */ if (!t->analyzed) --- a/gcc/combine.c 2015-11-02 22:04:33.000000000 +0100 +++ b/gcc/combine.c 2016-02-16 15:44:42.280974494 +0100 @@ -7227,6 +7227,10 @@ if (len >= HOST_BITS_PER_WIDE_INT) break; + /* Don't try to compute in too wide unsupported modes. */ + if (!targetm.scalar_mode_supported_p (compute_mode)) + break; + /* Now compute the equivalent expression. Make a copy of INNER for the SET_DEST in case it is a MEM into which we will substitute; we don't want shared RTL in that case. */ @@ -13781,10 +13785,10 @@ break; tem_insn = i3; /* If the new I2 sets the same register that is marked dead - in the note, the note now should not be put on I2, as the - note refers to a previous incarnation of the reg. */ + in the note, we do not know where to put the note. + Give up. */ if (i2 != 0 && reg_set_p (XEXP (note, 0), PATTERN (i2))) - tem_insn = i2; + break; } if (place == 0) --- a/gcc/common.opt 2015-07-01 19:06:52.000000000 +0200 +++ b/gcc/common.opt 2016-02-16 15:22:53.030757235 +0100 @@ -1845,7 +1845,7 @@ frandom-seed= Common Joined RejectNegative Var(common_deferred_options) Defer --frandom-seed= Make compile reproducible using +-frandom-seed= Make compile reproducible using ; This switch causes the command line that was used to create an ; object file to be recorded into the object file. The exact format --- a/gcc/config/i386/constraints.md 2015-01-05 13:33:28.000000000 +0100 +++ b/gcc/config/i386/constraints.md 2016-02-16 15:34:07.740807135 +0100 @@ -149,6 +149,7 @@ ;; s Sibcall memory operand, not valid for TARGET_X32 ;; w Call memory operand, not valid for TARGET_X32 ;; z Constant call address operand. +;; C SSE constant operand. (define_constraint "Bs" "@internal Sibcall memory operand." @@ -164,6 +165,10 @@ "@internal Constant call address operand." (match_operand 0 "constant_call_address_operand")) +(define_constraint "BC" + "@internal SSE constant operand." + (match_test "standard_sse_constant_p (op)")) + ;; Integer constant constraints. (define_constraint "I" "Integer constant in the range 0 @dots{} 31, for 32-bit shifts." @@ -214,8 +219,8 @@ ;; This can theoretically be any mode's CONST0_RTX. (define_constraint "C" - "Standard SSE floating point constant." - (match_test "standard_sse_constant_p (op)")) + "SSE constant zero operand." + (match_test "standard_sse_constant_p (op) == 1")) ;; Constant-or-symbol-reference constraints. --- a/gcc/config/i386/i386.c 2015-11-18 16:45:26.000000000 +0100 +++ b/gcc/config/i386/i386.c 2016-02-16 15:42:11.482418338 +0100 @@ -115,6 +115,7 @@ #include "tree-iterator.h" #include "tree-chkp.h" #include "rtl-chkp.h" +#include "dojump.h" static rtx legitimize_dllimport_symbol (rtx, bool); static rtx legitimize_pe_coff_extern_decl (rtx, bool); @@ -562,17 +563,17 @@ {4, 6, 6}, /* cost of storing fp registers in SFmode, DFmode and XFmode */ - 1, /* cost of moving MMX register */ - {1, 1}, /* cost of loading MMX registers + 2, /* cost of moving MMX register */ + {2, 2}, /* cost of loading MMX registers in SImode and DImode */ - {1, 1}, /* cost of storing MMX registers + {2, 2}, /* cost of storing MMX registers in SImode and DImode */ - 1, /* cost of moving SSE register */ - {1, 1, 1}, /* cost of loading SSE registers + 2, /* cost of moving SSE register */ + {2, 2, 8}, /* cost of loading SSE registers in SImode, DImode and TImode */ - {1, 1, 1}, /* cost of storing SSE registers + {2, 2, 8}, /* cost of storing SSE registers in SImode, DImode and TImode */ - 1, /* MMX or SSE register to integer */ + 3, /* MMX or SSE register to integer */ 64, /* size of l1 cache. */ 128, /* size of l2 cache. */ 32, /* size of prefetch block */ @@ -4150,6 +4151,17 @@ opts->x_target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS; } + /* Stack realignment without -maccumulate-outgoing-args requires %ebp, + so enable -maccumulate-outgoing-args when %ebp is fixed. */ + if (fixed_regs[BP_REG] + && !(opts->x_target_flags & MASK_ACCUMULATE_OUTGOING_ARGS)) + { + if (opts_set->x_target_flags & MASK_ACCUMULATE_OUTGOING_ARGS) + warning (0, "fixed ebp register requires %saccumulate-outgoing-args%s", + prefix, suffix); + opts->x_target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS; + } + /* Figure out what ASM_GENERATE_INTERNAL_LABEL builds as a prefix. */ { char *p; @@ -4982,12 +4994,14 @@ /* If we are using the default tune= or arch=, undo the string assigned, and use the default. */ if (option_strings[IX86_FUNCTION_SPECIFIC_ARCH]) - opts->x_ix86_arch_string = option_strings[IX86_FUNCTION_SPECIFIC_ARCH]; + opts->x_ix86_arch_string + = ggc_strdup (option_strings[IX86_FUNCTION_SPECIFIC_ARCH]); else if (!orig_arch_specified) opts->x_ix86_arch_string = NULL; if (option_strings[IX86_FUNCTION_SPECIFIC_TUNE]) - opts->x_ix86_tune_string = option_strings[IX86_FUNCTION_SPECIFIC_TUNE]; + opts->x_ix86_tune_string + = ggc_strdup (option_strings[IX86_FUNCTION_SPECIFIC_TUNE]); else if (orig_tune_defaulted) opts->x_ix86_tune_string = NULL; @@ -9677,6 +9691,10 @@ if (TARGET_64BIT_MS_ABI && get_frame_size () > SEH_MAX_FRAME_SIZE) return true; + /* SSE saves require frame-pointer when stack is misaligned. */ + if (TARGET_64BIT_MS_ABI && ix86_incoming_stack_boundary < 128) + return true; + /* In ix86_option_override_internal, TARGET_OMIT_LEAF_FRAME_POINTER turns off the frame pointer by default. Turn it back on now if we've not got a leaf function. */ @@ -10114,18 +10132,6 @@ crtl->preferred_stack_boundary = 128; crtl->stack_alignment_needed = 128; } - /* preferred_stack_boundary is never updated for call - expanded from tls descriptor. Update it here. We don't update it in - expand stage because according to the comments before - ix86_current_function_calls_tls_descriptor, tls calls may be optimized - away. */ - else if (ix86_current_function_calls_tls_descriptor - && crtl->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY) - { - crtl->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY; - if (crtl->stack_alignment_needed < PREFERRED_STACK_BOUNDARY) - crtl->stack_alignment_needed = PREFERRED_STACK_BOUNDARY; - } stack_alignment_needed = crtl->stack_alignment_needed / BITS_PER_UNIT; preferred_alignment = crtl->preferred_stack_boundary / BITS_PER_UNIT; @@ -10799,6 +10805,11 @@ && cfun->stdarg && crtl->stack_alignment_estimated < 128) crtl->stack_alignment_estimated = 128; + + /* __tls_get_addr needs to be called with 16-byte aligned stack. */ + if (ix86_tls_descriptor_calls_expanded_in_cfun + && crtl->preferred_stack_boundary < 128) + crtl->preferred_stack_boundary = 128; } /* Handle the TARGET_GET_DRAP_RTX hook. Return NULL if no DRAP is @@ -11258,10 +11269,11 @@ unsigned int incoming_stack_boundary = (crtl->parm_stack_boundary > ix86_incoming_stack_boundary ? crtl->parm_stack_boundary : ix86_incoming_stack_boundary); - unsigned int stack_realign = (incoming_stack_boundary - < (crtl->is_leaf - ? crtl->max_used_stack_slot_alignment - : crtl->stack_alignment_needed)); + unsigned int stack_realign + = (incoming_stack_boundary + < (crtl->is_leaf && !ix86_current_function_calls_tls_descriptor + ? crtl->max_used_stack_slot_alignment + : crtl->stack_alignment_needed)); if (crtl->stack_realign_finalized) { @@ -24365,7 +24377,7 @@ if (DYNAMIC_CHECK) Round COUNT down to multiple of SIZE << optional caller supplied zero size guard is here >> - << optional caller suppplied dynamic check is here >> + << optional caller supplied dynamic check is here >> << caller supplied main copy loop is here >> } done_label: @@ -24539,8 +24551,8 @@ else *min_size = 0; - /* Our loops always round down the bock size, but for dispatch to library - we need precise value. */ + /* Our loops always round down the block size, but for dispatch to + library we need precise value. */ if (dynamic_check) *count = expand_simple_binop (GET_MODE (*count), AND, *count, GEN_INT (-size), *count, 1, OPTAB_DIRECT); @@ -25118,6 +25130,13 @@ size_needed = GET_MODE_SIZE (move_mode) * unroll_factor; epilogue_size_needed = size_needed; + /* If we are going to call any library calls conditionally, make sure any + pending stack adjustment happen before the first conditional branch, + otherwise they will be emitted before the library call only and won't + happen from the other branches. */ + if (dynamic_check != -1) + do_pending_stack_adjust (); + desired_align = decide_alignment (align, alg, expected_size, move_mode); if (!TARGET_ALIGN_STRINGOPS || noalign) align = desired_align; @@ -38246,7 +38265,11 @@ memory = 0; break; case VOID_FTYPE_PV8DF_V8DF_QI: + case VOID_FTYPE_PV4DF_V4DF_QI: + case VOID_FTYPE_PV2DF_V2DF_QI: case VOID_FTYPE_PV16SF_V16SF_HI: + case VOID_FTYPE_PV8SF_V8SF_QI: + case VOID_FTYPE_PV4SF_V4SF_QI: case VOID_FTYPE_PV8DI_V8DI_QI: case VOID_FTYPE_PV4DI_V4DI_QI: case VOID_FTYPE_PV2DI_V2DI_QI: @@ -38306,10 +38329,6 @@ case VOID_FTYPE_PV16QI_V16QI_HI: case VOID_FTYPE_PV32QI_V32QI_SI: case VOID_FTYPE_PV64QI_V64QI_DI: - case VOID_FTYPE_PV4DF_V4DF_QI: - case VOID_FTYPE_PV2DF_V2DF_QI: - case VOID_FTYPE_PV8SF_V8SF_QI: - case VOID_FTYPE_PV4SF_V4SF_QI: nargs = 2; klass = store; /* Reserve memory operand for target. */ @@ -40246,13 +40265,12 @@ op0 = fixup_modeless_constant (op0, mode0); - if (GET_MODE (op0) == mode0 - || (GET_MODE (op0) == VOIDmode && op0 != constm1_rtx)) + if (GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode) { if (!insn_data[icode].operand[0].predicate (op0, mode0)) op0 = copy_to_mode_reg (mode0, op0); } - else if (op0 != constm1_rtx) + else { op0 = copy_to_reg (op0); op0 = simplify_gen_subreg (mode0, op0, GET_MODE (op0), 0); @@ -45078,6 +45096,7 @@ { /* For SSE1, we have to reuse the V4SF code. */ rtx t = gen_reg_rtx (V4SFmode); + emit_move_insn (t, gen_lowpart (V4SFmode, target)); ix86_expand_vector_set (false, t, gen_lowpart (SFmode, val), elt); emit_move_insn (target, gen_lowpart (mode, t)); } --- a/gcc/config/i386/sse.md 2015-10-12 13:03:56.000000000 +0200 +++ b/gcc/config/i386/sse.md 2016-02-16 15:36:06.040607163 +0100 @@ -804,7 +804,7 @@ (define_insn "*mov_internal" [(set (match_operand:VMOVE 0 "nonimmediate_operand" "=v,v ,m") - (match_operand:VMOVE 1 "nonimmediate_or_sse_const_operand" "C ,vm,v"))] + (match_operand:VMOVE 1 "nonimmediate_or_sse_const_operand" "BC,vm,v"))] "TARGET_SSE && (register_operand (operands[0], mode) || register_operand (operands[1], mode))" @@ -1022,7 +1022,7 @@ sse_suffix = ""; } - if (misaligned_operand (operands[1], mode)) + if (misaligned_operand (operands[0], mode)) align = "u"; else align = "a"; @@ -2605,7 +2605,7 @@ (match_operator: 3 "sse_comparison_operator" [(match_operand:VF 1 "register_operand" "v") (match_operand:VF 2 "nonimmediate_operand" "vm")]))] - "TARGET_SSE" + "TARGET_AVX512F" "vcmp%D3\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ssecmp") (set_attr "length_immediate" "1") @@ -3855,7 +3855,7 @@ "@ cvtsi2ss\t{%2, %0|%0, %2} cvtsi2ss\t{%2, %0|%0, %2} - vcvtsi2ss\t{%2, %1, %0|%0, %1, %2}" + vcvtsi2ss\t{%2, %1, %0|%0, %1, %2}" [(set_attr "isa" "noavx,noavx,avx") (set_attr "type" "sseicvt") (set_attr "athlon_decode" "vector,double,*") @@ -3876,7 +3876,7 @@ "@ cvtsi2ssq\t{%2, %0|%0, %2} cvtsi2ssq\t{%2, %0|%0, %2} - vcvtsi2ssq\t{%2, %1, %0|%0, %1, %2}" + vcvtsi2ssq\t{%2, %1, %0|%0, %1, %2}" [(set_attr "isa" "noavx,noavx,avx") (set_attr "type" "sseicvt") (set_attr "athlon_decode" "vector,double,*") @@ -3989,7 +3989,7 @@ (match_operand:VF_128 1 "register_operand" "v") (const_int 1)))] "TARGET_AVX512F && " - "vcvtusi2\t{%2, %1, %0|%0, %1, %2}" + "vcvtusi2\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "sseicvt") (set_attr "prefix" "evex") (set_attr "mode" "")]) @@ -4003,7 +4003,7 @@ (match_operand:VF_128 1 "register_operand" "v") (const_int 1)))] "TARGET_AVX512F && TARGET_64BIT" - "vcvtusi2\t{%2, %1, %0|%0, %1, %2}" + "vcvtusi2\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "sseicvt") (set_attr "prefix" "evex") (set_attr "mode" "")]) @@ -4268,7 +4268,7 @@ "@ cvtsi2sdq\t{%2, %0|%0, %2} cvtsi2sdq\t{%2, %0|%0, %2} - vcvtsi2sdq\t{%2, %1, %0|%0, %1, %2}" + vcvtsi2sdq\t{%2, %1, %0|%0, %1, %2}" [(set_attr "isa" "noavx,noavx,avx") (set_attr "type" "sseicvt") (set_attr "athlon_decode" "double,direct,*") @@ -7018,28 +7018,50 @@ DONE; }) -(define_insn "vec_extract_hi_" - [(set (match_operand: 0 "" "=v,") +(define_insn "vec_extract_hi__maskm" + [(set (match_operand: 0 "memory_operand" "=m") + (vec_merge: + (vec_select: + (match_operand:VI8F_256 1 "register_operand" "v") + (parallel [(const_int 2) (const_int 3)])) + (match_operand: 2 "memory_operand" "0") + (match_operand: 3 "register_operand" "k")))] + "TARGET_AVX512DQ && TARGET_AVX512VL + && rtx_equal_p (operands[2], operands[0])" + "vextract64x2\t{$0x1, %1, %0%{%3%}|%0%{%3%}, %1, 0x1}" + [(set_attr "type" "sselog1") + (set_attr "length_immediate" "1") + (set_attr "prefix" "evex") + (set_attr "mode" "")]) + +(define_insn "vec_extract_hi__mask" + [(set (match_operand: 0 "register_operand" "=v") + (vec_merge: + (vec_select: + (match_operand:VI8F_256 1 "register_operand" "v") + (parallel [(const_int 2) (const_int 3)])) + (match_operand: 2 "vector_move_operand" "0C") + (match_operand: 3 "register_operand" "Yk")))] + "TARGET_AVX512VL && TARGET_AVX512DQ" + "vextract64x2\t{$0x1, %1, %0%{%3%}%N2|%0%{%3%}%N2, %1, 0x1}" + [(set_attr "type" "sselog1") + (set_attr "length_immediate" "1") + (set_attr "prefix" "evex") + (set_attr "mode" "")]) + +(define_insn "vec_extract_hi_" + [(set (match_operand: 0 "nonimmediate_operand" "=xm, vm") (vec_select: - (match_operand:VI8F_256 1 "register_operand" "v,v") + (match_operand:VI8F_256 1 "register_operand" "x, v") (parallel [(const_int 2) (const_int 3)])))] - "TARGET_AVX && && " -{ - if (TARGET_AVX512VL) - { - if (TARGET_AVX512DQ) - return "vextract64x2\t{$0x1, %1, %0|%0, %1, 0x1}"; - else - return "vextract32x4\t{$0x1, %1, %0|%0, %1, 0x1}"; - } - else - return "vextract\t{$0x1, %1, %0|%0, %1, 0x1}"; -} - [(set_attr "type" "sselog") - (set_attr "prefix_extra" "1") + "TARGET_AVX" + "@ + vextract\t{$0x1, %1, %0|%0, %1, 0x1} + vextract64x2\t{$0x1, %1, %0|%0, %1, 0x1}" + [(set_attr "isa" "*, avx512dq") + (set_attr "prefix" "vex, evex") + (set_attr "type" "sselog1") (set_attr "length_immediate" "1") - (set_attr "memory" "none,store") - (set_attr "prefix" "vex") (set_attr "mode" "")]) (define_split @@ -15188,7 +15210,7 @@ (define_expand "avx512pf_gatherpfsf" [(unspec - [(match_operand: 0 "register_or_constm1_operand") + [(match_operand: 0 "register_operand") (mem: (match_par_dup 5 [(match_operand 2 "vsib_address_operand") @@ -15230,37 +15252,10 @@ (set_attr "prefix" "evex") (set_attr "mode" "XI")]) -(define_insn "*avx512pf_gatherpfsf" - [(unspec - [(const_int -1) - (match_operator: 4 "vsib_mem_operator" - [(unspec:P - [(match_operand:P 1 "vsib_address_operand" "Tv") - (match_operand:VI48_512 0 "register_operand" "v") - (match_operand:SI 2 "const1248_operand" "n")] - UNSPEC_VSIBADDR)]) - (match_operand:SI 3 "const_2_to_3_operand" "n")] - UNSPEC_GATHER_PREFETCH)] - "TARGET_AVX512PF" -{ - switch (INTVAL (operands[3])) - { - case 3: - return "vgatherpf0ps\t{%4|%4}"; - case 2: - return "vgatherpf1ps\t{%4|%4}"; - default: - gcc_unreachable (); - } -} - [(set_attr "type" "sse") - (set_attr "prefix" "evex") - (set_attr "mode" "XI")]) - ;; Packed double variants (define_expand "avx512pf_gatherpfdf" [(unspec - [(match_operand: 0 "register_or_constm1_operand") + [(match_operand: 0 "register_operand") (mem:V8DF (match_par_dup 5 [(match_operand 2 "vsib_address_operand") @@ -15302,37 +15297,10 @@ (set_attr "prefix" "evex") (set_attr "mode" "XI")]) -(define_insn "*avx512pf_gatherpfdf" - [(unspec - [(const_int -1) - (match_operator:V8DF 4 "vsib_mem_operator" - [(unspec:P - [(match_operand:P 1 "vsib_address_operand" "Tv") - (match_operand:VI4_256_8_512 0 "register_operand" "v") - (match_operand:SI 2 "const1248_operand" "n")] - UNSPEC_VSIBADDR)]) - (match_operand:SI 3 "const_2_to_3_operand" "n")] - UNSPEC_GATHER_PREFETCH)] - "TARGET_AVX512PF" -{ - switch (INTVAL (operands[3])) - { - case 3: - return "vgatherpf0pd\t{%4|%4}"; - case 2: - return "vgatherpf1pd\t{%4|%4}"; - default: - gcc_unreachable (); - } -} - [(set_attr "type" "sse") - (set_attr "prefix" "evex") - (set_attr "mode" "XI")]) - ;; Packed float variants (define_expand "avx512pf_scatterpfsf" [(unspec - [(match_operand: 0 "register_or_constm1_operand") + [(match_operand: 0 "register_operand") (mem: (match_par_dup 5 [(match_operand 2 "vsib_address_operand") @@ -15376,39 +15344,10 @@ (set_attr "prefix" "evex") (set_attr "mode" "XI")]) -(define_insn "*avx512pf_scatterpfsf" - [(unspec - [(const_int -1) - (match_operator: 4 "vsib_mem_operator" - [(unspec:P - [(match_operand:P 1 "vsib_address_operand" "Tv") - (match_operand:VI48_512 0 "register_operand" "v") - (match_operand:SI 2 "const1248_operand" "n")] - UNSPEC_VSIBADDR)]) - (match_operand:SI 3 "const2367_operand" "n")] - UNSPEC_SCATTER_PREFETCH)] - "TARGET_AVX512PF" -{ - switch (INTVAL (operands[3])) - { - case 3: - case 7: - return "vscatterpf0ps\t{%4|%4}"; - case 2: - case 6: - return "vscatterpf1ps\t{%4|%4}"; - default: - gcc_unreachable (); - } -} - [(set_attr "type" "sse") - (set_attr "prefix" "evex") - (set_attr "mode" "XI")]) - ;; Packed double variants (define_expand "avx512pf_scatterpfdf" [(unspec - [(match_operand: 0 "register_or_constm1_operand") + [(match_operand: 0 "register_operand") (mem:V8DF (match_par_dup 5 [(match_operand 2 "vsib_address_operand") @@ -15452,35 +15391,6 @@ (set_attr "prefix" "evex") (set_attr "mode" "XI")]) -(define_insn "*avx512pf_scatterpfdf" - [(unspec - [(const_int -1) - (match_operator:V8DF 4 "vsib_mem_operator" - [(unspec:P - [(match_operand:P 1 "vsib_address_operand" "Tv") - (match_operand:VI4_256_8_512 0 "register_operand" "v") - (match_operand:SI 2 "const1248_operand" "n")] - UNSPEC_VSIBADDR)]) - (match_operand:SI 3 "const2367_operand" "n")] - UNSPEC_SCATTER_PREFETCH)] - "TARGET_AVX512PF" -{ - switch (INTVAL (operands[3])) - { - case 3: - case 7: - return "vscatterpf0pd\t{%4|%4}"; - case 2: - case 6: - return "vscatterpf1pd\t{%4|%4}"; - default: - gcc_unreachable (); - } -} - [(set_attr "type" "sse") - (set_attr "prefix" "evex") - (set_attr "mode" "XI")]) - (define_insn "avx512er_exp2" [(set (match_operand:VF_512 0 "register_operand" "=v") (unspec:VF_512 @@ -16907,20 +16817,21 @@ (set_attr "mode" "")]) (define_insn "vec_dup" - [(set (match_operand:AVX_VEC_DUP_MODE 0 "register_operand" "=x,x,v,x") + [(set (match_operand:AVX_VEC_DUP_MODE 0 "register_operand" "=x,x,x,v,x") (vec_duplicate:AVX_VEC_DUP_MODE - (match_operand: 1 "nonimmediate_operand" "m,m,v,?x")))] + (match_operand: 1 "nonimmediate_operand" "m,m,x,v,?x")))] "TARGET_AVX" "@ vbroadcast\t{%1, %0|%0, %1} vbroadcast\t{%1, %0|%0, %1} vbroadcast\t{%x1, %0|%0, %x1} + vbroadcast\t{%x1, %g0|%g0, %x1} #" [(set_attr "type" "ssemov") (set_attr "prefix_extra" "1") (set_attr "prefix" "maybe_evex") - (set_attr "isa" "avx2,noavx2,avx2,noavx2") - (set_attr "mode" ",V8SF,,V8SF")]) + (set_attr "isa" "avx2,noavx2,avx2,avx512f,noavx2") + (set_attr "mode" ",V8SF,,,V8SF")]) (define_split [(set (match_operand:AVX2_VEC_DUP_MODE 0 "register_operand") @@ -18524,7 +18435,7 @@ (match_operand:SI 3 "const_0_to_15_operand")] UNSPEC_RANGE))] "TARGET_AVX512DQ && " - "vrange\t{%3, %2, %1, %0|%0, %1, %2, %3}" + "vrange\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "sse") (set_attr "prefix" "evex") (set_attr "mode" "")]) @@ -18540,7 +18451,7 @@ (match_dup 1) (const_int 1)))] "TARGET_AVX512DQ" - "vrange\t{%3, %2, %1, %0|%0, %1, %2, %3}" + "vrange\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "sse") (set_attr "prefix" "evex") (set_attr "mode" "")]) --- a/gcc/cp/call.c 2015-10-21 11:27:12.000000000 +0200 +++ b/gcc/cp/call.c 2016-02-16 15:43:40.979927276 +0100 @@ -213,7 +213,6 @@ tree, int, tsubst_flags_t); static conversion *implicit_conversion (tree, tree, tree, bool, int, tsubst_flags_t); -static conversion *standard_conversion (tree, tree, tree, bool, int); static conversion *reference_binding (tree, tree, tree, bool, int, tsubst_flags_t); static conversion *build_conv (conversion_kind, tree, conversion *); @@ -1106,7 +1105,7 @@ static conversion * standard_conversion (tree to, tree from, tree expr, bool c_cast_p, - int flags) + int flags, tsubst_flags_t complain) { enum tree_code fcode, tcode; conversion *conv; @@ -1136,7 +1135,7 @@ else if (TREE_CODE (to) == BOOLEAN_TYPE) { /* Necessary for eg, TEMPLATE_ID_EXPRs (c++/50961). */ - expr = resolve_nondeduced_context (expr); + expr = resolve_nondeduced_context (expr, complain); from = TREE_TYPE (expr); } } @@ -1175,7 +1174,8 @@ the standard conversion sequence to perform componentwise conversion. */ conversion *part_conv = standard_conversion - (TREE_TYPE (to), TREE_TYPE (from), NULL_TREE, c_cast_p, flags); + (TREE_TYPE (to), TREE_TYPE (from), NULL_TREE, c_cast_p, flags, + complain); if (part_conv) { @@ -1814,7 +1814,7 @@ if (TREE_CODE (to) == REFERENCE_TYPE) conv = reference_binding (to, from, expr, c_cast_p, flags, complain); else - conv = standard_conversion (to, from, expr, c_cast_p, flags); + conv = standard_conversion (to, from, expr, c_cast_p, flags, complain); if (conv) return conv; @@ -7031,6 +7031,9 @@ && resolves_to_fixed_type_p (target, NULL)) return false; tree init = TARGET_EXPR_INITIAL (exp); + /* build_compound_expr pushes COMPOUND_EXPR inside TARGET_EXPR. */ + while (TREE_CODE (init) == COMPOUND_EXPR) + init = TREE_OPERAND (init, 1); return (TREE_CODE (init) == AGGR_INIT_EXPR && !AGGR_INIT_VIA_CTOR_P (init)); } --- a/gcc/cp/constexpr.c 2015-11-25 20:56:06.000000000 +0100 +++ b/gcc/cp/constexpr.c 2016-02-16 15:44:57.410234482 +0100 @@ -2110,7 +2110,8 @@ gcc_assert (ctx->ctor); gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (ctx->ctor))); - gcc_assert (CONSTRUCTOR_NELTS (ctx->ctor) == 0); + /* We used to check that ctx->ctor was empty, but that isn't the case when + the object is zero-initialized before calling the constructor. */ if (ctx->object) gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (ctx->object))); @@ -3114,7 +3115,8 @@ r = TARGET_EXPR_INITIAL (r); if (TREE_CODE (r) == VAR_DECL) if (tree *p = ctx->values->get (r)) - r = *p; + if (*p != NULL_TREE) + r = *p; if (DECL_P (r)) { if (!ctx->quiet) --- a/gcc/cp/cp-tree.h 2015-11-26 11:21:42.000000000 +0100 +++ b/gcc/cp/cp-tree.h 2016-02-16 15:43:40.980927293 +0100 @@ -5792,7 +5792,7 @@ extern tree get_template_innermost_arguments (const_tree); extern tree get_template_argument_pack_elems (const_tree); extern tree get_function_template_decl (const_tree); -extern tree resolve_nondeduced_context (tree); +extern tree resolve_nondeduced_context (tree, tsubst_flags_t); extern hashval_t iterative_hash_template_arg (tree arg, hashval_t val); /* in repo.c */ --- a/gcc/cp/cvt.c 2015-08-14 18:33:10.000000000 +0200 +++ b/gcc/cp/cvt.c 2016-02-16 15:43:40.980927293 +0100 @@ -1260,7 +1260,7 @@ default:; } - expr = resolve_nondeduced_context (expr); + expr = resolve_nondeduced_context (expr, complain); { tree probe = expr; --- a/gcc/cp/decl2.c 2015-11-25 22:13:00.000000000 +0100 +++ b/gcc/cp/decl2.c 2016-02-16 15:16:42.697404077 +0100 @@ -4197,6 +4197,9 @@ return false; if (DECL_DECLARED_CONSTEXPR_P (decl)) return true; + if (DECL_HAS_VALUE_EXPR_P (decl)) + /* A proxy isn't constant. */ + return false; return (CP_TYPE_CONST_NON_VOLATILE_P (type) && INTEGRAL_OR_ENUMERATION_TYPE_P (type)); } --- a/gcc/cp/decl.c 2015-11-19 17:34:32.000000000 +0100 +++ b/gcc/cp/decl.c 2016-02-16 15:43:40.982927327 +0100 @@ -6436,7 +6436,7 @@ if (TREE_CODE (d_init) == TREE_LIST) d_init = build_x_compound_expr_from_list (d_init, ELK_INIT, tf_warning_or_error); - d_init = resolve_nondeduced_context (d_init); + d_init = resolve_nondeduced_context (d_init, tf_warning_or_error); type = TREE_TYPE (decl) = do_auto_deduction (type, d_init, auto_node); if (type == error_mark_node) @@ -7360,7 +7360,8 @@ /* Don't get confused by a CONSTRUCTOR for some other type. */ if (initial_value && TREE_CODE (initial_value) == CONSTRUCTOR - && !BRACE_ENCLOSED_INITIALIZER_P (initial_value)) + && !BRACE_ENCLOSED_INITIALIZER_P (initial_value) + && TREE_CODE (TREE_TYPE (initial_value)) != ARRAY_TYPE) return 1; if (initial_value) --- a/gcc/cp/init.c 2015-10-21 11:27:18.000000000 +0200 +++ b/gcc/cp/init.c 2016-02-16 15:43:40.983927344 +0100 @@ -2079,6 +2079,11 @@ && (TREE_CODE (init) == CONSTRUCTOR || TREE_CODE (init) == STRING_CST))) break; + /* Don't return a CONSTRUCTOR for a variable with partial run-time + initialization, since it doesn't represent the entire value. */ + if (TREE_CODE (init) == CONSTRUCTOR + && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) + break; decl = unshare_expr (init); } return decl; @@ -3026,7 +3031,7 @@ if (auto_node) { tree d_init = (**init)[0]; - d_init = resolve_nondeduced_context (d_init); + d_init = resolve_nondeduced_context (d_init, complain); type = do_auto_deduction (type, d_init, auto_node); } } --- a/gcc/cp/mangle.c 2015-11-25 22:13:00.000000000 +0100 +++ b/gcc/cp/mangle.c 2016-02-16 15:00:40.480184751 +0100 @@ -1160,7 +1160,7 @@ So, for the example above, `Outer::Inner' is represented as a substitution candidate by a TREE_LIST whose purpose is `Outer' and whose value is `Outer::Inner'. */ - if (TYPE_P (context)) + if (context && TYPE_P (context)) substitution = build_tree_list (context, templ); else substitution = templ; --- a/gcc/cp/method.c 2015-02-10 17:38:31.000000000 +0100 +++ b/gcc/cp/method.c 2016-02-16 15:32:09.458536344 +0100 @@ -1118,7 +1118,7 @@ static void process_subob_fn (tree fn, tree *spec_p, bool *trivial_p, bool *deleted_p, bool *constexpr_p, - bool diag, tree arg) + bool diag, tree arg, bool dtor_from_ctor = false) { if (!fn || fn == error_mark_node) goto bad; @@ -1130,7 +1130,7 @@ *spec_p = merge_exception_specifiers (*spec_p, raises); } - if (!trivial_fn_p (fn)) + if (!trivial_fn_p (fn) && !dtor_from_ctor) { if (trivial_p) *trivial_p = false; @@ -1163,14 +1163,17 @@ } /* Subroutine of synthesized_method_walk to allow recursion into anonymous - aggregates. */ + aggregates. If DTOR_FROM_CTOR is true, we're walking subobject destructors + called from a synthesized constructor, in which case we don't consider + the triviality of the subobject destructor. */ static void walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, int quals, bool copy_arg_p, bool move_p, bool assign_p, tree *spec_p, bool *trivial_p, bool *deleted_p, bool *constexpr_p, - bool diag, int flags, tsubst_flags_t complain) + bool diag, int flags, tsubst_flags_t complain, + bool dtor_from_ctor) { tree field; for (field = fields; field; field = DECL_CHAIN (field)) @@ -1287,7 +1290,7 @@ walk_field_subobs (TYPE_FIELDS (mem_type), fnname, sfk, quals, copy_arg_p, move_p, assign_p, spec_p, trivial_p, deleted_p, constexpr_p, - diag, flags, complain); + diag, flags, complain, dtor_from_ctor); continue; } @@ -1304,7 +1307,7 @@ rval = locate_fn_flags (mem_type, fnname, argtype, flags, complain); process_subob_fn (rval, spec_p, trivial_p, deleted_p, - constexpr_p, diag, field); + constexpr_p, diag, field, dtor_from_ctor); } } @@ -1487,7 +1490,7 @@ dtors would be a double-fault). */ process_subob_fn (rval, NULL, NULL, deleted_p, NULL, false, - basetype); + basetype, /*dtor_from_ctor*/true); } if (check_vdtor && type_has_virtual_destructor (basetype)) @@ -1534,7 +1537,7 @@ NULL_TREE, flags, complain); process_subob_fn (rval, NULL, NULL, deleted_p, NULL, false, - basetype); + basetype, /*dtor_from_ctor*/true); } } } @@ -1543,13 +1546,13 @@ walk_field_subobs (TYPE_FIELDS (ctype), fnname, sfk, quals, copy_arg_p, move_p, assign_p, spec_p, trivial_p, deleted_p, constexpr_p, - diag, flags, complain); + diag, flags, complain, /*dtor_from_ctor*/false); if (ctor_p) walk_field_subobs (TYPE_FIELDS (ctype), complete_dtor_identifier, sfk_destructor, TYPE_UNQUALIFIED, false, false, false, NULL, NULL, deleted_p, NULL, - false, flags, complain); + false, flags, complain, /*dtor_from_ctor*/true); pop_scope (scope); --- a/gcc/cp/optimize.c 2015-11-25 22:13:00.000000000 +0100 +++ b/gcc/cp/optimize.c 2016-02-16 15:32:24.480825007 +0100 @@ -670,6 +670,8 @@ { if (expand_or_defer_fn_1 (clone)) emit_associated_thunks (clone); + /* We didn't generate a body, so remove the empty one. */ + DECL_SAVED_TREE (clone) = NULL_TREE; } else expand_or_defer_fn (clone); --- a/gcc/cp/parser.c 2015-11-25 20:56:12.000000000 +0100 +++ b/gcc/cp/parser.c 2016-02-16 15:42:16.245497989 +0100 @@ -15682,7 +15682,7 @@ { /* Indicate whether this class was declared as a `class' or as a `struct'. */ - if (TREE_CODE (type) == RECORD_TYPE) + if (CLASS_TYPE_P (type)) CLASSTYPE_DECLARED_CLASS (type) = (tag_type == class_type); cp_parser_check_class_key (tag_type, type); } @@ -32359,6 +32359,7 @@ DECL_DECLARED_INLINE_P (fndecl) = 1; DECL_IGNORED_P (fndecl) = 1; DECL_OMP_DECLARE_REDUCTION_P (fndecl) = 1; + SET_DECL_ASSEMBLER_NAME (fndecl, get_identifier ("")); DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("gnu_inline"), NULL_TREE, DECL_ATTRIBUTES (fndecl)); --- a/gcc/cp/pt.c 2015-11-25 20:56:12.000000000 +0100 +++ b/gcc/cp/pt.c 2016-02-16 15:43:40.985927378 +0100 @@ -10095,12 +10095,16 @@ if (PACK_EXPANSION_LOCAL_P (t)) arg_pack = retrieve_local_specialization (parm_pack); else + /* We can't rely on local_specializations for a parameter + name used later in a function declaration (such as in a + late-specified return type). Even if it exists, it might + have the wrong value for a recursive call. */ + need_local_specializations = true; + + if (!arg_pack) { - /* We can't rely on local_specializations for a parameter - name used later in a function declaration (such as in a - late-specified return type). Even if it exists, it might - have the wrong value for a recursive call. Just make a - dummy decl, since it's only used for its type. */ + /* This parameter pack was used in an unevaluated context. Just + make a dummy decl, since it's only used for its type. */ arg_pack = tsubst_decl (parm_pack, args, complain); if (arg_pack && DECL_PACK_P (arg_pack)) /* Partial instantiation of the parm_pack, we can't build @@ -10108,7 +10112,6 @@ arg_pack = NULL_TREE; else arg_pack = make_fnparm_pack (arg_pack); - need_local_specializations = true; } } else if (TREE_CODE (parm_pack) == FIELD_DECL) @@ -13245,7 +13248,12 @@ --c_inhibit_evaluation_warnings; if (TREE_CODE (expanded) == TREE_VEC) - len = TREE_VEC_LENGTH (expanded); + { + len = TREE_VEC_LENGTH (expanded); + /* Set TREE_USED for the benefit of -Wunused. */ + for (int i = 0; i < len; i++) + TREE_USED (TREE_VEC_ELT (expanded, i)) = true; + } if (expanded == error_mark_node) return error_mark_node; @@ -17344,7 +17352,7 @@ lvalue for the function template specialization. */ tree -resolve_nondeduced_context (tree orig_expr) +resolve_nondeduced_context (tree orig_expr, tsubst_flags_t complain) { tree expr, offset, baselink; bool addr; @@ -17427,16 +17435,16 @@ { tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (offset, 0))); - expr = build_offset_ref (base, expr, addr, tf_warning_or_error); + expr = build_offset_ref (base, expr, addr, complain); } if (addr) - expr = cp_build_addr_expr (expr, tf_warning_or_error); + expr = cp_build_addr_expr (expr, complain); return expr; } - else if (good == 0 && badargs) + else if (good == 0 && badargs && (complain & tf_error)) /* There were no good options and at least one bad one, so let the user know what the problem is. */ - instantiate_template (badfn, badargs, tf_warning_or_error); + instantiate_template (badfn, badargs, complain); } return orig_expr; } @@ -19469,6 +19477,38 @@ return decl; } +/* True iff the TEMPLATE_DECL tmpl is a partial specialization. */ + +static bool +partial_specialization_p (tree tmpl) +{ + /* Any specialization has DECL_TEMPLATE_SPECIALIZATION. */ + if (!DECL_TEMPLATE_SPECIALIZATION (tmpl)) + return false; + if (!VAR_P (DECL_TEMPLATE_RESULT (tmpl))) + return false; + tree t = DECL_TI_TEMPLATE (tmpl); + /* A specialization that fully specializes one of the containing classes is + not a partial specialization. */ + return (list_length (DECL_TEMPLATE_PARMS (tmpl)) + == list_length (DECL_TEMPLATE_PARMS (t))); +} + +/* If TMPL is a partial specialization, return the arguments for its primary + template. */ + +static tree +impartial_args (tree tmpl, tree args) +{ + if (!partial_specialization_p (tmpl)) + return args; + + /* If TMPL is a partial specialization, we need to substitute to get + the args for the primary template. */ + return tsubst_template_args (DECL_TI_ARGS (tmpl), args, + tf_warning_or_error, tmpl); +} + /* Return the most specialized of the template partial specializations which can produce TARGET, a specialization of some class or variable template. The value returned is actually a TREE_LIST; the TREE_VALUE is @@ -20283,7 +20323,7 @@ return d; gen_tmpl = most_general_template (tmpl); - gen_args = DECL_TI_ARGS (d); + gen_args = impartial_args (tmpl, DECL_TI_ARGS (d)); if (tmpl != gen_tmpl) /* We should already have the extra args. */ @@ -22341,7 +22381,7 @@ } } - init = resolve_nondeduced_context (init); + init = resolve_nondeduced_context (init, tf_warning_or_error); targs = make_tree_vec (1); if (AUTO_IS_DECLTYPE (auto_node)) --- a/gcc/cp/rtti.c 2015-01-09 21:18:42.000000000 +0100 +++ b/gcc/cp/rtti.c 2016-02-16 15:43:40.986927395 +0100 @@ -255,7 +255,7 @@ if (error_operand_p (exp)) return error_mark_node; - exp = resolve_nondeduced_context (exp); + exp = resolve_nondeduced_context (exp, complain); /* peel back references, so they match. */ type = non_reference (TREE_TYPE (exp)); @@ -345,7 +345,7 @@ /* So we need to look into the vtable of the type of exp. Make sure it isn't a null lvalue. */ exp = cp_build_addr_expr (exp, complain); - exp = stabilize_reference (exp); + exp = save_expr (exp); cond = cp_convert (boolean_type_node, exp, complain); exp = cp_build_indirect_ref (exp, RO_NULL, complain); } --- a/gcc/cp/semantics.c 2015-09-10 09:40:59.000000000 +0200 +++ b/gcc/cp/semantics.c 2016-02-16 15:43:40.987927412 +0100 @@ -4104,9 +4104,8 @@ /* 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; - /* If this is an instantiation of a constexpr function, keep - DECL_SAVED_TREE for explain_invalid_constexpr_fn. */ - if (!is_instantiation_of_constexpr (fn)) + /* If this is a constexpr function, keep DECL_SAVED_TREE. */ + if (!DECL_DECLARED_CONSTEXPR_P (fn)) DECL_SAVED_TREE (fn) = NULL_TREE; return false; } @@ -7248,7 +7247,7 @@ /* The type denoted by decltype(e) is defined as follows: */ - expr = resolve_nondeduced_context (expr); + expr = resolve_nondeduced_context (expr, complain); if (invalid_nonstatic_memfn_p (expr, complain)) return error_mark_node; --- a/gcc/cp/tree.c 2015-07-16 15:25:25.000000000 +0200 +++ b/gcc/cp/tree.c 2016-02-16 15:13:32.730521942 +0100 @@ -1007,7 +1007,8 @@ the C version of this function does not properly maintain canonical types (which are not used in C). */ tree -c_build_qualified_type (tree type, int type_quals) +c_build_qualified_type (tree type, int type_quals, tree /* orig_qual_type */, + size_t /* orig_qual_indirect */) { return cp_build_qualified_type (type, type_quals); } --- a/gcc/cp/typeck.c 2015-11-26 11:21:42.000000000 +0100 +++ b/gcc/cp/typeck.c 2016-02-16 15:43:40.988927429 +0100 @@ -1926,7 +1926,7 @@ exp = mark_rvalue_use (exp); - exp = resolve_nondeduced_context (exp); + exp = resolve_nondeduced_context (exp, complain); if (type_unknown_p (exp)) { if (complain & tf_error) @@ -4672,6 +4672,20 @@ return error_mark_node; } + /* It's not precisely specified how the usual arithmetic + conversions apply to the vector types. Here, we use + the unsigned type if one of the operands is signed and + the other one is unsigned. */ + if (TYPE_UNSIGNED (type0) != TYPE_UNSIGNED (type1)) + { + if (!TYPE_UNSIGNED (type0)) + op0 = build1 (VIEW_CONVERT_EXPR, type1, op0); + else + op1 = build1 (VIEW_CONVERT_EXPR, type0, op1); + warning_at (location, OPT_Wsign_compare, "comparison between " + "types %qT and %qT", type0, type1); + } + /* Always construct signed integer vector type. */ intt = c_common_type_for_size (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type0))), 0); --- a/gcc/dse.c 2015-01-22 18:59:23.000000000 +0100 +++ b/gcc/dse.c 2016-02-16 15:42:07.863357871 +0100 @@ -1571,14 +1571,9 @@ mem_addr = base->val_rtx; else { - group_info_t group - = rtx_group_vec[group_id]; + group_info_t group = rtx_group_vec[group_id]; mem_addr = group->canon_base_addr; } - /* get_addr can only handle VALUE but cannot handle expr like: - VALUE + OFFSET, so call get_addr to get original addr for - mem_addr before plus_constant. */ - mem_addr = get_addr (mem_addr); if (offset) mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); } @@ -2188,14 +2183,9 @@ mem_addr = base->val_rtx; else { - group_info_t group - = rtx_group_vec[group_id]; + group_info_t group = rtx_group_vec[group_id]; mem_addr = group->canon_base_addr; } - /* get_addr can only handle VALUE but cannot handle expr like: - VALUE + OFFSET, so call get_addr to get original addr for - mem_addr before plus_constant. */ - mem_addr = get_addr (mem_addr); if (offset) mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); } --- a/gcc/dwarf2out.c 2015-11-09 19:27:43.000000000 +0100 +++ b/gcc/dwarf2out.c 2016-02-16 15:12:17.984964048 +0100 @@ -20290,9 +20290,10 @@ /* We are going to output a DIE to represent the unqualified version of this type (i.e. without any const or volatile qualifiers) so get the main variant (i.e. the unqualified version) of this type - now. (Vectors are special because the debugging info is in the + now. (Vectors and arrays are special because the debugging info is in the cloned type itself). */ - if (TREE_CODE (type) != VECTOR_TYPE) + if (TREE_CODE (type) != VECTOR_TYPE + && TREE_CODE (type) != ARRAY_TYPE) type = type_main_variant (type); /* If this is an array type with hidden descriptor, handle it first. */ --- a/gcc/emit-rtl.c 2015-08-05 13:20:59.000000000 +0200 +++ b/gcc/emit-rtl.c 2016-02-16 15:16:05.601653486 +0100 @@ -5256,7 +5256,8 @@ { case REG_EQUAL: case REG_EQUIV: - if (!set_for_reg_notes (insn)) + /* We need to support the REG_EQUAL on USE trick of find_reloads. */ + if (!set_for_reg_notes (insn) && GET_CODE (PATTERN (insn)) != USE) return NULL_RTX; /* Don't add ASM_OPERAND REG_EQUAL/REG_EQUIV notes. --- a/gcc/fold-const.c 2015-11-23 09:32:28.000000000 +0100 +++ b/gcc/fold-const.c 2016-02-16 15:42:00.259230970 +0100 @@ -8731,20 +8731,6 @@ return total.to_uhwi () > (unsigned HOST_WIDE_INT) size; } -/* Return the HOST_WIDE_INT least significant bits of T, a sizetype - kind INTEGER_CST. This makes sure to properly sign-extend the - constant. */ - -static HOST_WIDE_INT -size_low_cst (const_tree t) -{ - HOST_WIDE_INT w = TREE_INT_CST_ELT (t, 0); - int prec = TYPE_PRECISION (TREE_TYPE (t)); - if (prec < HOST_BITS_PER_WIDE_INT) - return sext_hwi (w, prec); - return w; -} - /* Subroutine of fold_binary. This routine performs all of the transformations that are common to the equality/inequality operators (EQ_EXPR and NE_EXPR) and the ordering operators @@ -8889,18 +8875,29 @@ STRIP_SIGN_NOPS (base0); if (TREE_CODE (base0) == ADDR_EXPR) { - base0 = TREE_OPERAND (base0, 0); - indirect_base0 = true; + base0 + = get_inner_reference (TREE_OPERAND (base0, 0), + &bitsize, &bitpos0, &offset0, &mode, + &unsignedp, &volatilep, false); + if (TREE_CODE (base0) == INDIRECT_REF) + base0 = TREE_OPERAND (base0, 0); + else + indirect_base0 = true; } - offset0 = TREE_OPERAND (arg0, 1); - if (tree_fits_shwi_p (offset0)) - { - HOST_WIDE_INT off = size_low_cst (offset0); - if ((HOST_WIDE_INT) (((unsigned HOST_WIDE_INT) off) - * BITS_PER_UNIT) - / BITS_PER_UNIT == (HOST_WIDE_INT) off) + if (offset0 == NULL_TREE || integer_zerop (offset0)) + offset0 = TREE_OPERAND (arg0, 1); + else + offset0 = size_binop (PLUS_EXPR, offset0, + TREE_OPERAND (arg0, 1)); + if (TREE_CODE (offset0) == INTEGER_CST) + { + offset_int tem = wi::sext (wi::to_offset (offset0), + TYPE_PRECISION (sizetype)); + tem = wi::lshift (tem, LOG2_BITS_PER_UNIT); + tem += bitpos0; + if (wi::fits_shwi_p (tem)) { - bitpos0 = off * BITS_PER_UNIT; + bitpos0 = tem.to_shwi (); offset0 = NULL_TREE; } } @@ -8923,18 +8920,29 @@ STRIP_SIGN_NOPS (base1); if (TREE_CODE (base1) == ADDR_EXPR) { - base1 = TREE_OPERAND (base1, 0); - indirect_base1 = true; + base1 + = get_inner_reference (TREE_OPERAND (base1, 0), + &bitsize, &bitpos1, &offset1, &mode, + &unsignedp, &volatilep, false); + if (TREE_CODE (base1) == INDIRECT_REF) + base1 = TREE_OPERAND (base1, 0); + else + indirect_base1 = true; } - offset1 = TREE_OPERAND (arg1, 1); - if (tree_fits_shwi_p (offset1)) + if (offset1 == NULL_TREE || integer_zerop (offset1)) + offset1 = TREE_OPERAND (arg1, 1); + else + offset1 = size_binop (PLUS_EXPR, offset1, + TREE_OPERAND (arg1, 1)); + if (TREE_CODE (offset1) == INTEGER_CST) { - HOST_WIDE_INT off = size_low_cst (offset1); - if ((HOST_WIDE_INT) (((unsigned HOST_WIDE_INT) off) - * BITS_PER_UNIT) - / BITS_PER_UNIT == (HOST_WIDE_INT) off) + offset_int tem = wi::sext (wi::to_offset (offset1), + TYPE_PRECISION (sizetype)); + tem = wi::lshift (tem, LOG2_BITS_PER_UNIT); + tem += bitpos1; + if (wi::fits_shwi_p (tem)) { - bitpos1 = off * BITS_PER_UNIT; + bitpos1 = tem.to_shwi (); offset1 = NULL_TREE; } } @@ -12375,12 +12383,27 @@ || POINTER_TYPE_P (TREE_TYPE (arg0)))) { tree val = TREE_OPERAND (arg0, 1); - return omit_two_operands_loc (loc, type, - fold_build2_loc (loc, code, type, - val, - build_int_cst (TREE_TYPE (val), - 0)), - TREE_OPERAND (arg0, 0), arg1); + val = fold_build2_loc (loc, code, type, val, + build_int_cst (TREE_TYPE (val), 0)); + return omit_two_operands_loc (loc, type, val, + TREE_OPERAND (arg0, 0), arg1); + } + + /* Transform comparisons of the form X CMP X +- Y to Y CMP 0. */ + if ((TREE_CODE (arg1) == PLUS_EXPR + || TREE_CODE (arg1) == POINTER_PLUS_EXPR + || TREE_CODE (arg1) == MINUS_EXPR) + && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg1, + 0)), + arg0, 0) + && (INTEGRAL_TYPE_P (TREE_TYPE (arg1)) + || POINTER_TYPE_P (TREE_TYPE (arg1)))) + { + tree val = TREE_OPERAND (arg1, 1); + val = fold_build2_loc (loc, code, type, val, + build_int_cst (TREE_TYPE (val), 0)); + return omit_two_operands_loc (loc, type, val, + TREE_OPERAND (arg1, 0), arg0); } /* Transform comparisons of the form C - X CMP X if C % 2 == 1. */ @@ -12390,12 +12413,22 @@ 1)), arg1, 0) && wi::extract_uhwi (TREE_OPERAND (arg0, 0), 0, 1) == 1) - { - return omit_two_operands_loc (loc, type, - code == NE_EXPR - ? boolean_true_node : boolean_false_node, - TREE_OPERAND (arg0, 1), arg1); - } + return omit_two_operands_loc (loc, type, + code == NE_EXPR + ? boolean_true_node : boolean_false_node, + TREE_OPERAND (arg0, 1), arg1); + + /* Transform comparisons of the form X CMP C - X if C % 2 == 1. */ + if (TREE_CODE (arg1) == MINUS_EXPR + && TREE_CODE (TREE_OPERAND (arg1, 0)) == INTEGER_CST + && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg1, + 1)), + arg0, 0) + && wi::extract_uhwi (TREE_OPERAND (arg1, 0), 0, 1) == 1) + return omit_two_operands_loc (loc, type, + code == NE_EXPR + ? boolean_true_node : boolean_false_node, + TREE_OPERAND (arg1, 1), arg0); /* Convert ABS_EXPR == 0 or ABS_EXPR != 0 to x == 0 or x != 0. */ if (TREE_CODE (arg0) == ABS_EXPR --- a/gcc/fortran/check.c 2015-11-24 21:40:10.000000000 +0100 +++ b/gcc/fortran/check.c 2016-02-16 15:44:29.774760024 +0100 @@ -1157,6 +1157,59 @@ return true; } +bool +gfc_check_event_query (gfc_expr *event, gfc_expr *count, gfc_expr *stat) +{ + if (event->ts.type != BT_DERIVED + || event->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV + || event->ts.u.derived->intmod_sym_id != ISOFORTRAN_EVENT_TYPE) + { + gfc_error ("EVENT argument at %L to the intrinsic EVENT_QUERY " + "shall be of type EVENT_TYPE", &event->where); + return false; + } + + if (!scalar_check (event, 0)) + return false; + + if (!gfc_check_vardef_context (count, false, false, false, NULL)) + { + gfc_error ("COUNT argument of the EVENT_QUERY intrinsic function at %L " + "shall be definable", &count->where); + return false; + } + + if (!type_check (count, 1, BT_INTEGER)) + return false; + + int i = gfc_validate_kind (BT_INTEGER, count->ts.kind, false); + int j = gfc_validate_kind (BT_INTEGER, gfc_default_integer_kind, false); + + if (gfc_integer_kinds[i].range < gfc_integer_kinds[j].range) + { + gfc_error ("COUNT argument of the EVENT_QUERY intrinsic function at %L " + "shall have at least the range of the default integer", + &count->where); + return false; + } + + if (stat != NULL) + { + if (!type_check (stat, 2, BT_INTEGER)) + return false; + if (!scalar_check (stat, 2)) + return false; + if (!variable_check (stat, 2, false)) + return false; + + if (!gfc_notify_std (GFC_STD_F2008_TS, "STAT= argument to %s at %L", + gfc_current_intrinsic, &stat->where)) + return false; + } + + return true; +} + bool gfc_check_atomic_fetch_op (gfc_expr *atom, gfc_expr *value, gfc_expr *old, --- a/gcc/fortran/decl.c 2015-11-13 22:28:10.000000000 +0100 +++ b/gcc/fortran/decl.c 2016-02-16 15:32:51.220338624 +0100 @@ -6454,9 +6454,16 @@ prev_ns = ns; ns = ns->sibling; } - - gfc_free_namespace (gfc_current_ns); - gfc_current_ns = parent_ns; + + if (parent_ns) + { + /* Free the current namespace only when the parent one exists. This + prevents an ICE when more END BLOCK then BLOCK statements are + present. It does not mean any further harm, because we already + have errored. */ + gfc_free_namespace (gfc_current_ns); + gfc_current_ns = parent_ns; + } } return MATCH_ERROR; --- a/gcc/fortran/dump-parse-tree.c 2015-01-15 21:11:12.000000000 +0100 +++ b/gcc/fortran/dump-parse-tree.c 2016-02-16 15:44:29.774760024 +0100 @@ -1659,6 +1659,33 @@ } break; + case EXEC_EVENT_POST: + case EXEC_EVENT_WAIT: + if (c->op == EXEC_EVENT_POST) + fputs ("EVENT POST ", dumpfile); + else + fputs ("EVENT WAIT ", dumpfile); + + fputs ("event-variable=", dumpfile); + if (c->expr1 != NULL) + show_expr (c->expr1); + if (c->expr4 != NULL) + { + fputs (" until_count=", dumpfile); + show_expr (c->expr4); + } + if (c->expr2 != NULL) + { + fputs (" stat=", dumpfile); + show_expr (c->expr2); + } + if (c->expr3 != NULL) + { + fputs (" errmsg=", dumpfile); + show_expr (c->expr3); + } + break; + case EXEC_LOCK: case EXEC_UNLOCK: if (c->op == EXEC_LOCK) --- a/gcc/fortran/expr.c 2015-11-18 17:29:58.000000000 +0100 +++ b/gcc/fortran/expr.c 2016-02-16 15:44:29.775760041 +0100 @@ -4864,6 +4864,19 @@ return false; } + /* TS18508, C702/C203. */ + if (!alloc_obj + && (attr.lock_comp + || (e->ts.type == BT_DERIVED + && e->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV + && e->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE))) + { + if (context) + gfc_error ("LOCK_EVENT in variable definition context (%s) at %L", + context, &e->where); + return false; + } + /* INTENT(IN) dummy argument. Check this, unless the object itself is the component of sub-component of a pointer; we need to distinguish assignment to a pointer component from pointer-assignment to a pointer --- a/gcc/fortran/gfortran.h 2015-04-10 13:29:53.000000000 +0200 +++ b/gcc/fortran/gfortran.h 2016-02-16 15:44:29.775760041 +0100 @@ -253,7 +253,8 @@ ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD, ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD, ST_PROCEDURE, ST_GENERIC, ST_CRITICAL, ST_END_CRITICAL, - ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_NONE + ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_EVENT_POST, + ST_EVENT_WAIT,ST_NONE } gfc_statement; @@ -413,6 +414,7 @@ GFC_ISYM_ERFC, GFC_ISYM_ERFC_SCALED, GFC_ISYM_ETIME, + GFC_ISYM_EVENT_QUERY, GFC_ISYM_EXECUTE_COMMAND_LINE, GFC_ISYM_EXIT, GFC_ISYM_EXP, @@ -847,7 +849,7 @@ entities. */ unsigned alloc_comp:1, pointer_comp:1, proc_pointer_comp:1, private_comp:1, zero_comp:1, coarray_comp:1, lock_comp:1, - defined_assign_comp:1, unlimited_polymorphic:1; + event_comp:1, defined_assign_comp:1, unlimited_polymorphic:1; /* This is a temporary selector for SELECT TYPE or an associate variable for SELECT_TYPE or ASSOCIATE. */ @@ -2330,7 +2332,7 @@ EXEC_OPEN, EXEC_CLOSE, EXEC_WAIT, EXEC_READ, EXEC_WRITE, EXEC_IOLENGTH, EXEC_TRANSFER, EXEC_DT_END, EXEC_BACKSPACE, EXEC_ENDFILE, EXEC_INQUIRE, EXEC_REWIND, EXEC_FLUSH, - EXEC_LOCK, EXEC_UNLOCK, + EXEC_LOCK, EXEC_UNLOCK, EXEC_EVENT_POST, EXEC_EVENT_WAIT, EXEC_OACC_KERNELS_LOOP, EXEC_OACC_PARALLEL_LOOP, EXEC_OACC_PARALLEL, EXEC_OACC_KERNELS, EXEC_OACC_DATA, EXEC_OACC_HOST_DATA, EXEC_OACC_LOOP, EXEC_OACC_UPDATE, EXEC_OACC_WAIT, EXEC_OACC_CACHE, --- a/gcc/fortran/interface.c 2015-10-30 17:58:20.000000000 +0100 +++ b/gcc/fortran/interface.c 2016-02-16 15:44:29.777760075 +0100 @@ -2144,6 +2144,21 @@ formal->name, &actual->where); return 0; } + + /* TS18508, C702/C703. */ + if (formal->attr.intent != INTENT_INOUT + && (((formal->ts.type == BT_DERIVED || formal->ts.type == BT_CLASS) + && formal->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV + && formal->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE) + || formal->attr.event_comp)) + + { + if (where) + gfc_error ("Actual argument to non-INTENT(INOUT) dummy %qs at %L, " + "which is EVENT_TYPE or has a EVENT_TYPE component", + formal->name, &actual->where); + return 0; + } } /* F2008, C1239/C1240. */ @@ -3375,6 +3390,19 @@ "component at %L requires an explicit interface for " "procedure %qs", &a->expr->where, sym->name); break; + } + + if (a->expr + && (a->expr->ts.type == BT_DERIVED || a->expr->ts.type == BT_CLASS) + && ((a->expr->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV + && a->expr->ts.u.derived->intmod_sym_id + == ISOFORTRAN_EVENT_TYPE) + || gfc_expr_attr (a->expr).event_comp)) + { + gfc_error ("Actual argument of EVENT_TYPE or with EVENT_TYPE " + "component at %L requires an explicit interface for " + "procedure %qs", &a->expr->where, sym->name); + break; } if (a->expr && a->expr->expr_type == EXPR_NULL --- a/gcc/fortran/intrinsic.c 2015-02-01 01:29:54.000000000 +0100 +++ b/gcc/fortran/intrinsic.c 2016-02-16 15:44:29.777760075 +0100 @@ -3128,6 +3128,13 @@ GFC_STD_F95, gfc_check_cpu_time, NULL, gfc_resolve_cpu_time, tm, BT_REAL, dr, REQUIRED, INTENT_OUT); + add_sym_3s ("event_query", GFC_ISYM_EVENT_QUERY, CLASS_ATOMIC, + BT_UNKNOWN, 0, GFC_STD_F2008_TS, + gfc_check_event_query, NULL, gfc_resolve_event_query, + "event", BT_INTEGER, di, REQUIRED, INTENT_IN, + c, BT_INTEGER, di, OPTIONAL, INTENT_IN, + stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT); + /* More G77 compatibility garbage. */ add_sym_2s ("ctime", GFC_ISYM_CTIME, CLASS_IMPURE, BT_UNKNOWN, 0, GFC_STD_GNU, gfc_check_ctime_sub, NULL, gfc_resolve_ctime_sub, --- a/gcc/fortran/intrinsic.h 2015-01-05 13:33:28.000000000 +0100 +++ b/gcc/fortran/intrinsic.h 2016-02-16 15:44:29.778760092 +0100 @@ -70,6 +70,7 @@ bool gfc_check_dshift (gfc_expr *, gfc_expr *, gfc_expr *); bool gfc_check_eoshift (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *); bool gfc_check_dtime_etime (gfc_expr *); +bool gfc_check_event_query (gfc_expr *, gfc_expr *, gfc_expr *); bool gfc_check_fgetputc (gfc_expr *, gfc_expr *); bool gfc_check_fgetput (gfc_expr *); bool gfc_check_float (gfc_expr *); @@ -462,6 +463,7 @@ void gfc_resolve_eoshift (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *); void gfc_resolve_etime_sub (gfc_code *); +void gfc_resolve_event_query (gfc_code *); void gfc_resolve_exp (gfc_expr *, gfc_expr *); void gfc_resolve_exponent (gfc_expr *, gfc_expr *); void gfc_resolve_extends_type_of (gfc_expr *, gfc_expr *, gfc_expr *); --- a/gcc/fortran/iresolve.c 2015-01-09 21:18:42.000000000 +0100 +++ b/gcc/fortran/iresolve.c 2016-02-16 15:44:29.778760092 +0100 @@ -2955,6 +2955,12 @@ c->resolved_sym = gfc_get_intrinsic_sub_symbol (name); } +void +gfc_resolve_event_query (gfc_code *c) +{ + const char *name = "event_query"; + c->resolved_sym = gfc_get_intrinsic_sub_symbol (name); +} void gfc_resolve_mvbits (gfc_code *c) --- a/gcc/fortran/iso-fortran-env.def 2015-01-05 13:33:28.000000000 +0100 +++ b/gcc/fortran/iso-fortran-env.def 2016-02-16 15:44:29.778760092 +0100 @@ -123,6 +123,11 @@ NAMED_DERIVED_TYPE (ISOFORTRAN_LOCK_TYPE, "lock_type", \ get_int_kind_from_node (ptr_type_node), GFC_STD_F2008) +NAMED_DERIVED_TYPE (ISOFORTRAN_EVENT_TYPE, "event_type", \ + flag_coarray == GFC_FCOARRAY_LIB + ? get_int_kind_from_node (ptr_type_node) + : gfc_default_integer_kind, GFC_STD_F2008_TS) + #undef NAMED_INTCST #undef NAMED_KINDARRAY #undef NAMED_FUNCTION --- a/gcc/fortran/match.c 2015-11-13 22:28:10.000000000 +0100 +++ b/gcc/fortran/match.c 2016-02-16 15:44:29.779760109 +0100 @@ -1474,6 +1474,8 @@ match ("deallocate", gfc_match_deallocate, ST_DEALLOCATE) match ("end file", gfc_match_endfile, ST_END_FILE) match ("error stop", gfc_match_error_stop, ST_ERROR_STOP) + match ("event post", gfc_match_event_post, ST_EVENT_POST) + match ("event wait", gfc_match_event_wait, ST_EVENT_WAIT) match ("exit", gfc_match_exit, ST_EXIT) match ("flush", gfc_match_flush, ST_FLUSH) match ("forall", match_simple_forall, ST_FORALL) @@ -2758,6 +2760,202 @@ return gfc_match_stopcode (ST_ERROR_STOP); } +/* Match EVENT POST/WAIT statement. Syntax: + EVENT POST ( event-variable [, sync-stat-list] ) + EVENT WAIT ( event-variable [, wait-spec-list] ) + with + wait-spec-list is sync-stat-list or until-spec + until-spec is UNTIL_COUNT = scalar-int-expr + sync-stat is STAT= or ERRMSG=. */ + +static match +event_statement (gfc_statement st) +{ + match m; + gfc_expr *tmp, *eventvar, *until_count, *stat, *errmsg; + bool saw_until_count, saw_stat, saw_errmsg; + + tmp = eventvar = until_count = stat = errmsg = NULL; + saw_until_count = saw_stat = saw_errmsg = false; + + if (gfc_pure (NULL)) + { + gfc_error ("Image control statement EVENT %s at %C in PURE procedure", + st == ST_EVENT_POST ? "POST" : "WAIT"); + return MATCH_ERROR; + } + + gfc_unset_implicit_pure (NULL); + + if (flag_coarray == GFC_FCOARRAY_NONE) + { + gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to enable"); + return MATCH_ERROR; + } + + if (gfc_find_state (COMP_CRITICAL)) + { + gfc_error ("Image control statement EVENT %s at %C in CRITICAL block", + st == ST_EVENT_POST ? "POST" : "WAIT"); + return MATCH_ERROR; + } + + if (gfc_find_state (COMP_DO_CONCURRENT)) + { + gfc_error ("Image control statement EVENT %s at %C in DO CONCURRENT " + "block", st == ST_EVENT_POST ? "POST" : "WAIT"); + return MATCH_ERROR; + } + + if (gfc_match_char ('(') != MATCH_YES) + goto syntax; + + if (gfc_match ("%e", &eventvar) != MATCH_YES) + goto syntax; + m = gfc_match_char (','); + if (m == MATCH_ERROR) + goto syntax; + if (m == MATCH_NO) + { + m = gfc_match_char (')'); + if (m == MATCH_YES) + goto done; + goto syntax; + } + + for (;;) + { + m = gfc_match (" stat = %v", &tmp); + if (m == MATCH_ERROR) + goto syntax; + if (m == MATCH_YES) + { + if (saw_stat) + { + gfc_error ("Redundant STAT tag found at %L ", &tmp->where); + goto cleanup; + } + stat = tmp; + saw_stat = true; + + m = gfc_match_char (','); + if (m == MATCH_YES) + continue; + + tmp = NULL; + break; + } + + m = gfc_match (" errmsg = %v", &tmp); + if (m == MATCH_ERROR) + goto syntax; + if (m == MATCH_YES) + { + if (saw_errmsg) + { + gfc_error ("Redundant ERRMSG tag found at %L ", &tmp->where); + goto cleanup; + } + errmsg = tmp; + saw_errmsg = true; + + m = gfc_match_char (','); + if (m == MATCH_YES) + continue; + + tmp = NULL; + break; + } + + m = gfc_match (" until_count = %e", &tmp); + if (m == MATCH_ERROR || st == ST_EVENT_POST) + goto syntax; + if (m == MATCH_YES) + { + if (saw_until_count) + { + gfc_error ("Redundant UNTIL_COUNT tag found at %L ", + &tmp->where); + goto cleanup; + } + until_count = tmp; + saw_until_count = true; + + m = gfc_match_char (','); + if (m == MATCH_YES) + continue; + + tmp = NULL; + break; + } + + break; + } + + if (m == MATCH_ERROR) + goto syntax; + + if (gfc_match (" )%t") != MATCH_YES) + goto syntax; + +done: + switch (st) + { + case ST_EVENT_POST: + new_st.op = EXEC_EVENT_POST; + break; + case ST_EVENT_WAIT: + new_st.op = EXEC_EVENT_WAIT; + break; + default: + gcc_unreachable (); + } + + new_st.expr1 = eventvar; + new_st.expr2 = stat; + new_st.expr3 = errmsg; + new_st.expr4 = until_count; + + return MATCH_YES; + +syntax: + gfc_syntax_error (st); + +cleanup: + if (until_count != tmp) + gfc_free_expr (until_count); + if (errmsg != tmp) + gfc_free_expr (errmsg); + if (stat != tmp) + gfc_free_expr (stat); + + gfc_free_expr (tmp); + gfc_free_expr (eventvar); + + return MATCH_ERROR; + +} + + +match +gfc_match_event_post (void) +{ + if (!gfc_notify_std (GFC_STD_F2008_TS, "EVENT POST statement at %C")) + return MATCH_ERROR; + + return event_statement (ST_EVENT_POST); +} + + +match +gfc_match_event_wait (void) +{ + if (!gfc_notify_std (GFC_STD_F2008_TS, "EVENT WAIT statement at %C")) + return MATCH_ERROR; + + return event_statement (ST_EVENT_WAIT); +} + /* Match LOCK/UNLOCK statement. Syntax: LOCK ( lock-variable [ , lock-stat-list ] ) --- a/gcc/fortran/match.h 2015-01-15 21:11:12.000000000 +0100 +++ b/gcc/fortran/match.h 2016-02-16 15:44:29.779760109 +0100 @@ -69,6 +69,8 @@ match gfc_match_if (gfc_statement *); match gfc_match_else (void); match gfc_match_elseif (void); +match gfc_match_event_post (void); +match gfc_match_event_wait (void); match gfc_match_critical (void); match gfc_match_block (void); match gfc_match_associate (void); --- a/gcc/fortran/module.c 2015-06-05 22:40:35.000000000 +0200 +++ b/gcc/fortran/module.c 2016-02-16 15:44:29.780760126 +0100 @@ -1889,7 +1889,7 @@ AB_ELEMENTAL, AB_PURE, AB_RECURSIVE, AB_GENERIC, AB_ALWAYS_EXPLICIT, AB_CRAY_POINTER, AB_CRAY_POINTEE, AB_THREADPRIVATE, AB_ALLOC_COMP, AB_POINTER_COMP, AB_PROC_POINTER_COMP, AB_PRIVATE_COMP, - AB_VALUE, AB_VOLATILE, AB_PROTECTED, AB_LOCK_COMP, + AB_VALUE, AB_VOLATILE, AB_PROTECTED, AB_LOCK_COMP, AB_EVENT_COMP, AB_IS_BIND_C, AB_IS_C_INTEROP, AB_IS_ISO_C, AB_ABSTRACT, AB_ZERO_COMP, AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION, AB_COARRAY_COMP, AB_VTYPE, AB_VTAB, AB_CONTIGUOUS, AB_CLASS_POINTER, @@ -1935,6 +1935,7 @@ minit ("ALLOC_COMP", AB_ALLOC_COMP), minit ("COARRAY_COMP", AB_COARRAY_COMP), minit ("LOCK_COMP", AB_LOCK_COMP), + minit ("EVENT_COMP", AB_EVENT_COMP), minit ("POINTER_COMP", AB_POINTER_COMP), minit ("PROC_POINTER_COMP", AB_PROC_POINTER_COMP), minit ("PRIVATE_COMP", AB_PRIVATE_COMP), @@ -2117,6 +2118,8 @@ MIO_NAME (ab_attribute) (AB_COARRAY_COMP, attr_bits); if (attr->lock_comp) MIO_NAME (ab_attribute) (AB_LOCK_COMP, attr_bits); + if (attr->event_comp) + MIO_NAME (ab_attribute) (AB_EVENT_COMP, attr_bits); if (attr->zero_comp) MIO_NAME (ab_attribute) (AB_ZERO_COMP, attr_bits); if (attr->is_class) @@ -2269,6 +2272,9 @@ case AB_LOCK_COMP: attr->lock_comp = 1; break; + case AB_EVENT_COMP: + attr->event_comp = 1; + break; case AB_POINTER_COMP: attr->pointer_comp = 1; break; --- a/gcc/fortran/parse.c 2015-09-26 00:45:27.000000000 +0200 +++ b/gcc/fortran/parse.c 2016-02-16 15:44:29.780760126 +0100 @@ -457,6 +457,8 @@ match ("entry% ", gfc_match_entry, ST_ENTRY); match ("equivalence", gfc_match_equivalence, ST_EQUIVALENCE); match ("external", gfc_match_external, ST_ATTR_DECL); + match ("event post", gfc_match_event_post, ST_EVENT_POST); + match ("event wait", gfc_match_event_wait, ST_EVENT_WAIT); break; case 'f': @@ -1323,6 +1325,7 @@ case ST_OMP_CANCEL: case ST_OMP_CANCELLATION_POINT: \ case ST_OMP_TARGET_UPDATE: case ST_ERROR_STOP: case ST_SYNC_ALL: \ case ST_SYNC_IMAGES: case ST_SYNC_MEMORY: case ST_LOCK: case ST_UNLOCK: \ + case ST_EVENT_POST: case ST_EVENT_WAIT: \ case ST_OACC_UPDATE: case ST_OACC_WAIT: case ST_OACC_CACHE: \ case ST_OACC_ENTER_DATA: case ST_OACC_EXIT_DATA @@ -1628,6 +1631,12 @@ case ST_ELSEWHERE: p = "ELSEWHERE"; break; + case ST_EVENT_POST: + p = "EVENT POST"; + break; + case ST_EVENT_WAIT: + p = "EVENT WAIT"; + break; case ST_END_ASSOCIATE: p = "END ASSOCIATE"; break; @@ -2608,7 +2617,7 @@ gfc_statement st; gfc_state_data s; gfc_symbol *sym; - gfc_component *c, *lock_comp = NULL; + gfc_component *c, *lock_comp = NULL, *event_comp = NULL; accept_statement (ST_DERIVED_DECL); push_state (&s, COMP_DERIVED, gfc_new_block); @@ -2716,8 +2725,8 @@ sym = gfc_current_block (); for (c = sym->components; c; c = c->next) { - bool coarray, lock_type, allocatable, pointer; - coarray = lock_type = allocatable = pointer = false; + bool coarray, lock_type, event_type, allocatable, pointer; + coarray = lock_type = event_type = allocatable = pointer = false; /* Look for allocatable components. */ if (c->attr.allocatable @@ -2779,6 +2788,23 @@ sym->attr.lock_comp = 1; } + /* Looking for event_type components. */ + if ((c->ts.type == BT_DERIVED + && c->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV + && c->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE) + || (c->ts.type == BT_CLASS && c->attr.class_ok + && CLASS_DATA (c)->ts.u.derived->from_intmod + == INTMOD_ISO_FORTRAN_ENV + && CLASS_DATA (c)->ts.u.derived->intmod_sym_id + == ISOFORTRAN_EVENT_TYPE) + || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.event_comp + && !allocatable && !pointer)) + { + event_type = 1; + event_comp = c; + sym->attr.event_comp = 1; + } + /* Check for F2008, C1302 - and recall that pointers may not be coarrays (5.3.14) and that subobjects of coarray are coarray themselves (2.4.7), unless there are nondirect [allocatable or pointer] components @@ -2819,6 +2845,43 @@ "coarray subcomponent)", lock_comp->name, &lock_comp->loc, sym->name, c->name, &c->loc); + /* Similarly for EVENT TYPE. */ + + if (pointer && !coarray && event_type) + gfc_error ("Component %s at %L of type EVENT_TYPE must have a " + "codimension or be a subcomponent of a coarray, " + "which is not possible as the component has the " + "pointer attribute", c->name, &c->loc); + else if (pointer && !coarray && c->ts.type == BT_DERIVED + && c->ts.u.derived->attr.event_comp) + gfc_error ("Pointer component %s at %L has a noncoarray subcomponent " + "of type EVENT_TYPE, which must have a codimension or be a " + "subcomponent of a coarray", c->name, &c->loc); + + if (event_type && allocatable && !coarray) + gfc_error ("Allocatable component %s at %L of type EVENT_TYPE must have " + "a codimension", c->name, &c->loc); + else if (event_type && allocatable && c->ts.type == BT_DERIVED + && c->ts.u.derived->attr.event_comp) + gfc_error ("Allocatable component %s at %L must have a codimension as " + "it has a noncoarray subcomponent of type EVENT_TYPE", + c->name, &c->loc); + + if (sym->attr.coarray_comp && !coarray && event_type) + gfc_error ("Noncoarray component %s at %L of type EVENT_TYPE or with " + "subcomponent of type EVENT_TYPE must have a codimension or " + "be a subcomponent of a coarray. (Variables of type %s may " + "not have a codimension as already a coarray " + "subcomponent exists)", c->name, &c->loc, sym->name); + + if (sym->attr.event_comp && coarray && !event_type) + gfc_error ("Noncoarray component %s at %L of type EVENT_TYPE or with " + "subcomponent of type EVENT_TYPE must have a codimension or " + "be a subcomponent of a coarray. (Variables of type %s may " + "not have a codimension as %s at %L has a codimension or a " + "coarray subcomponent)", event_comp->name, &event_comp->loc, + sym->name, c->name, &c->loc); + /* Look for private components. */ if (sym->component_access == ACCESS_PRIVATE || c->attr.access == ACCESS_PRIVATE --- a/gcc/fortran/primary.c 2015-10-26 18:25:03.000000000 +0100 +++ b/gcc/fortran/primary.c 2016-02-16 15:30:54.152087966 +0100 @@ -2142,7 +2142,7 @@ symbol_attribute gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts) { - int dimension, codimension, pointer, allocatable, target, n; + int dimension, codimension, pointer, allocatable, target; symbol_attribute attr; gfc_ref *ref; gfc_symbol *sym; @@ -2201,22 +2201,9 @@ case AR_UNKNOWN: /* If any of start, end or stride is not integer, there will already have been an error issued. */ - for (n = 0; n < ref->u.ar.as->rank; n++) - { - int errors; - gfc_get_errors (NULL, &errors); - if (((ref->u.ar.start[n] - && ref->u.ar.start[n]->ts.type == BT_UNKNOWN) - || - (ref->u.ar.end[n] - && ref->u.ar.end[n]->ts.type == BT_UNKNOWN) - || - (ref->u.ar.stride[n] - && ref->u.ar.stride[n]->ts.type == BT_UNKNOWN)) - && errors > 0) - break; - } - if (n == ref->u.ar.as->rank) + int errors; + gfc_get_errors (NULL, &errors); + if (errors == 0) gfc_internal_error ("gfc_variable_attr(): Bad array reference"); } --- a/gcc/fortran/resolve.c 2015-10-20 02:45:48.000000000 +0200 +++ b/gcc/fortran/resolve.c 2016-02-16 15:44:29.782760161 +0100 @@ -1,5 +1,5 @@ /* Perform type resolution on the various structures. - Copyright (C) 2001-2015 Free Software Foundation, Inc. + Copyright (C) 2001-2016 Free Software Foundation, Inc. Contributed by Andy Vaught This file is part of GCC. @@ -6977,6 +6977,21 @@ &code->expr3->where, &e->where); goto failure; } + + /* Check TS18508, C702/C703. */ + if (code->expr3->ts.type == BT_DERIVED + && ((codimension && gfc_expr_attr (code->expr3).event_comp) + || (code->expr3->ts.u.derived->from_intmod + == INTMOD_ISO_FORTRAN_ENV + && code->expr3->ts.u.derived->intmod_sym_id + == ISOFORTRAN_EVENT_TYPE))) + { + gfc_error ("The source-expr at %L shall neither be of type " + "EVENT_TYPE nor have a EVENT_TYPE component if " + "allocate-object at %L is a coarray", + &code->expr3->where, &e->where); + goto failure; + } } /* Check F08:C629. */ @@ -7028,6 +7043,13 @@ no SOURCE exists by setting expr3. */ code->expr3 = gfc_default_initializer (&code->ext.alloc.ts); } + else if (flag_coarray != GFC_FCOARRAY_LIB && e->ts.type == BT_DERIVED + && e->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV + && e->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE) + { + /* We have to zero initialize the integer variable. */ + code->expr3 = gfc_get_int_expr (gfc_default_integer_kind, &e->where, 0); + } else if (!code->expr3) { /* Set up default initializer if needed. */ @@ -8494,7 +8516,7 @@ return; } } - + if (exp->expr_type == EXPR_STRUCTURE) return; @@ -8545,21 +8567,40 @@ static void -resolve_lock_unlock (gfc_code *code) +resolve_lock_unlock_event (gfc_code *code) { if (code->expr1->expr_type == EXPR_FUNCTION && code->expr1->value.function.isym && code->expr1->value.function.isym->id == GFC_ISYM_CAF_GET) remove_caf_get_intrinsic (code->expr1); - if (code->expr1->ts.type != BT_DERIVED - || code->expr1->expr_type != EXPR_VARIABLE - || code->expr1->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV - || code->expr1->ts.u.derived->intmod_sym_id != ISOFORTRAN_LOCK_TYPE - || code->expr1->rank != 0 - || (!gfc_is_coarray (code->expr1) && !gfc_is_coindexed (code->expr1))) + if ((code->op == EXEC_LOCK || code->op == EXEC_UNLOCK) + && (code->expr1->ts.type != BT_DERIVED + || code->expr1->expr_type != EXPR_VARIABLE + || code->expr1->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV + || code->expr1->ts.u.derived->intmod_sym_id != ISOFORTRAN_LOCK_TYPE + || code->expr1->rank != 0 + || (!gfc_is_coarray (code->expr1) && + !gfc_is_coindexed (code->expr1)))) gfc_error ("Lock variable at %L must be a scalar of type LOCK_TYPE", &code->expr1->where); + else if ((code->op == EXEC_EVENT_POST || code->op == EXEC_EVENT_WAIT) + && (code->expr1->ts.type != BT_DERIVED + || code->expr1->expr_type != EXPR_VARIABLE + || code->expr1->ts.u.derived->from_intmod + != INTMOD_ISO_FORTRAN_ENV + || code->expr1->ts.u.derived->intmod_sym_id + != ISOFORTRAN_EVENT_TYPE + || code->expr1->rank != 0)) + gfc_error ("Event variable at %L must be a scalar of type EVENT_TYPE", + &code->expr1->where); + else if (code->op == EXEC_EVENT_POST && !gfc_is_coarray (code->expr1) + && !gfc_is_coindexed (code->expr1)) + gfc_error ("Event variable argument at %L must be a coarray or coindexed", + &code->expr1->where); + else if (code->op == EXEC_EVENT_WAIT && !gfc_is_coarray (code->expr1)) + gfc_error ("Event variable argument at %L must be a coarray but not " + "coindexed", &code->expr1->where); /* Check STAT. */ if (code->expr2 @@ -8585,17 +8626,23 @@ _("ERRMSG variable"))) return; - /* Check ACQUIRED_LOCK. */ - if (code->expr4 + /* Check for LOCK the ACQUIRED_LOCK. */ + if (code->op != EXEC_EVENT_WAIT && code->expr4 && (code->expr4->ts.type != BT_LOGICAL || code->expr4->rank != 0 || code->expr4->expr_type != EXPR_VARIABLE)) gfc_error ("ACQUIRED_LOCK= argument at %L must be a scalar LOGICAL " "variable", &code->expr4->where); - if (code->expr4 + if (code->op != EXEC_EVENT_WAIT && code->expr4 && !gfc_check_vardef_context (code->expr4, false, false, false, _("ACQUIRED_LOCK variable"))) return; + + /* Check for EVENT WAIT the UNTIL_COUNT. */ + if (code->op == EXEC_EVENT_WAIT && code->expr4 + && (code->expr4->ts.type != BT_INTEGER || code->expr4->rank != 0)) + gfc_error ("UNTIL_COUNT= argument at %L must be a scalar INTEGER " + "expression", &code->expr4->where); } @@ -8643,6 +8690,7 @@ symtree->n.sym->as->cotype = AS_EXPLICIT; symtree->n.sym->as->lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1); + gfc_commit_symbols(); } @@ -9992,6 +10040,50 @@ } +/* Deferred character length assignments from an operator expression + require a temporary because the character length of the lhs can + change in the course of the assignment. */ + +static bool +deferred_op_assign (gfc_code **code, gfc_namespace *ns) +{ + gfc_expr *tmp_expr; + gfc_code *this_code; + + if (!((*code)->expr1->ts.type == BT_CHARACTER + && (*code)->expr1->ts.deferred && (*code)->expr1->rank + && (*code)->expr2->expr_type == EXPR_OP)) + return false; + + if (!gfc_check_dependency ((*code)->expr1, (*code)->expr2, 1)) + return false; + + tmp_expr = get_temp_from_expr ((*code)->expr1, ns); + tmp_expr->where = (*code)->loc; + + /* A new charlen is required to ensure that the variable string + length is different to that of the original lhs. */ + tmp_expr->ts.u.cl = gfc_get_charlen(); + tmp_expr->symtree->n.sym->ts.u.cl = tmp_expr->ts.u.cl; + tmp_expr->ts.u.cl->next = (*code)->expr2->ts.u.cl->next; + (*code)->expr2->ts.u.cl->next = tmp_expr->ts.u.cl; + + tmp_expr->symtree->n.sym->ts.deferred = 1; + + this_code = build_assignment (EXEC_ASSIGN, + (*code)->expr1, + gfc_copy_expr (tmp_expr), + NULL, NULL, (*code)->loc); + + (*code)->expr1 = tmp_expr; + + this_code->next = (*code)->next; + (*code)->next = this_code; + + return true; +} + + /* Given a block of code, recursively resolve everything pointed to by this code block. */ @@ -10128,7 +10220,9 @@ case EXEC_LOCK: case EXEC_UNLOCK: - resolve_lock_unlock (code); + case EXEC_EVENT_POST: + case EXEC_EVENT_WAIT: + resolve_lock_unlock_event (code); break; case EXEC_ENTRY: @@ -10189,6 +10283,11 @@ goto call; } + /* Check for dependencies in deferred character length array + assignments and generate a temporary, if necessary. */ + if (code->op == EXEC_ASSIGN && deferred_op_assign (&code, ns)) + break; + /* F03 7.4.1.3 for non-allocatable, non-pointer components. */ if (code->op != EXEC_CALL && code->expr1->ts.type == BT_DERIVED && code->expr1->ts.u.derived->attr.defined_assign_comp) @@ -10561,7 +10660,7 @@ sym->binding_label = NULL; } - else if (sym->attr.flavor == FL_VARIABLE && module + else if (sym->attr.flavor == FL_VARIABLE && module && (strcmp (module, gsym->mod_name) != 0 || strcmp (sym->name, gsym->sym_name) != 0)) { @@ -13613,6 +13712,19 @@ return; } + /* TS18508, C702/C703. */ + if (sym->ts.type == BT_DERIVED + && ((sym->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV + && sym->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE) + || sym->ts.u.derived->attr.event_comp) + && !sym->attr.codimension && !sym->ts.u.derived->attr.coarray_comp) + { + gfc_error ("Variable %s at %L of type EVENT_TYPE or with subcomponent of " + "type LOCK_TYPE must be a coarray", sym->name, + &sym->declared_at); + return; + } + /* An assumed-size array with INTENT(OUT) shall not be of a type for which default initialization is defined (5.1.2.4.4). */ if (sym->ts.type == BT_DERIVED @@ -13641,6 +13753,15 @@ "INTENT(OUT)", sym->name, &sym->declared_at); return; } + + /* TS18508. */ + if (sym->ts.type == BT_DERIVED && sym->attr.dummy + && sym->attr.intent == INTENT_OUT && sym->attr.event_comp) + { + gfc_error ("Dummy argument %qs at %L of EVENT_TYPE shall not be " + "INTENT(OUT)", sym->name, &sym->declared_at); + return; + } /* F2008, C525. */ if ((((sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp) --- a/gcc/fortran/st.c 2015-01-15 21:11:12.000000000 +0100 +++ b/gcc/fortran/st.c 2016-02-16 15:44:29.782760161 +0100 @@ -118,6 +118,8 @@ case EXEC_SYNC_MEMORY: case EXEC_LOCK: case EXEC_UNLOCK: + case EXEC_EVENT_POST: + case EXEC_EVENT_WAIT: break; case EXEC_BLOCK: --- a/gcc/fortran/symbol.c 2015-05-19 19:01:25.000000000 +0200 +++ b/gcc/fortran/symbol.c 2016-02-16 15:34:33.988269947 +0100 @@ -3121,49 +3121,49 @@ FOR_EACH_VEC_ELT (latest_undo_chgset->syms, i, p) { - if (p->gfc_new) + /* Symbol was new. Or was old and just put in common */ + if ((p->gfc_new + || (p->attr.in_common && !p->old_symbol->attr.in_common )) + && p->attr.in_common && p->common_block && p->common_block->head) { - /* Symbol was new. */ - if (p->attr.in_common && p->common_block && p->common_block->head) - { - /* If the symbol was added to any common block, it - needs to be removed to stop the resolver looking - for a (possibly) dead symbol. */ + /* If the symbol was added to any common block, it + needs to be removed to stop the resolver looking + for a (possibly) dead symbol. */ - if (p->common_block->head == p && !p->common_next) + if (p->common_block->head == p && !p->common_next) + { + gfc_symtree st, *st0; + st0 = find_common_symtree (p->ns->common_root, + p->common_block); + if (st0) { - gfc_symtree st, *st0; - st0 = find_common_symtree (p->ns->common_root, - p->common_block); - if (st0) - { - st.name = st0->name; - gfc_delete_bbt (&p->ns->common_root, &st, compare_symtree); - free (st0); - } + st.name = st0->name; + gfc_delete_bbt (&p->ns->common_root, &st, compare_symtree); + free (st0); } + } - if (p->common_block->head == p) - p->common_block->head = p->common_next; - else - { - gfc_symbol *cparent, *csym; - - cparent = p->common_block->head; - csym = cparent->common_next; - - while (csym != p) - { - cparent = csym; - csym = csym->common_next; - } + if (p->common_block->head == p) + p->common_block->head = p->common_next; + else + { + gfc_symbol *cparent, *csym; - gcc_assert(cparent->common_next == p); + cparent = p->common_block->head; + csym = cparent->common_next; - cparent->common_next = csym->common_next; + while (csym != p) + { + cparent = csym; + csym = csym->common_next; } - } + gcc_assert(cparent->common_next == p); + cparent->common_next = csym->common_next; + } + } + if (p->gfc_new) + { /* The derived type is saved in the symtree with the first letter capitalized; the all lower-case version to the derived type contains its associated generic function. */ --- a/gcc/fortran/trans-array.c 2015-11-27 15:08:23.000000000 +0100 +++ b/gcc/fortran/trans-array.c 2016-02-16 15:42:04.613303608 +0100 @@ -1,5 +1,5 @@ /* Array translation routines - Copyright (C) 2002-2015 Free Software Foundation, Inc. + Copyright (C) 2002-2016 Free Software Foundation, Inc. Contributed by Paul Brook and Steven Bosscher @@ -3112,7 +3112,8 @@ index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, index, info->offset); - if (expr && is_subref_array (expr)) + if (expr && (is_subref_array (expr) + || (expr->ts.deferred && expr->expr_type == EXPR_VARIABLE))) decl = expr->symtree->n.sym->backend_decl; tmp = build_fold_indirect_ref_loc (input_location, info->data); @@ -3532,7 +3533,8 @@ tree init; tree incr; - if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)) + if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS + | OMPWS_SCALARIZER_BODY)) == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS) && n == loop->dimen - 1) { @@ -4409,7 +4411,7 @@ if (!nDepend && dest_expr->rank > 0 && dest_expr->ts.type == BT_CHARACTER && ss_expr->expr_type == EXPR_VARIABLE) - + nDepend = gfc_check_dependency (dest_expr, ss_expr, false); continue; @@ -6945,7 +6947,7 @@ gfc_array_index_type, stride, info->stride[n]); - if (se->direct_byref + if ((se->direct_byref || se->use_offset) && ((info->ref && info->ref->u.ar.type != AR_FULL) || (expr->expr_type == EXPR_ARRAY && se->use_offset))) { @@ -7191,6 +7193,17 @@ if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp) { gfc_conv_expr_descriptor (se, expr); + /* Deallocate the allocatable components of structures that are + not variable. */ + if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS) + && expr->ts.u.derived->attr.alloc_comp + && expr->expr_type != EXPR_VARIABLE) + { + tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se->expr, expr->rank); + + /* The components shall be deallocated before their containing entity. */ + gfc_prepend_expr_to_block (&se->post, tmp); + } if (expr->ts.type == BT_CHARACTER) se->string_length = expr->ts.u.cl->backend_decl; if (size) @@ -7226,10 +7239,11 @@ } /* Deallocate the allocatable components of structures that are - not variable. */ - if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS) - && expr->ts.u.derived->attr.alloc_comp - && expr->expr_type != EXPR_VARIABLE) + not variable, for descriptorless arguments. + Arguments with a descriptor are handled in gfc_conv_procedure_call. */ + if (g77 && (expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS) + && expr->ts.u.derived->attr.alloc_comp + && expr->expr_type != EXPR_VARIABLE) { tmp = build_fold_indirect_ref_loc (input_location, se->expr); tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank); @@ -8269,6 +8283,75 @@ } +static tree +concat_str_length (gfc_expr* expr) +{ + tree type; + tree len1; + tree len2; + gfc_se se; + + type = gfc_typenode_for_spec (&expr->value.op.op1->ts); + len1 = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); + if (len1 == NULL_TREE) + { + if (expr->value.op.op1->expr_type == EXPR_OP) + len1 = concat_str_length (expr->value.op.op1); + else if (expr->value.op.op1->expr_type == EXPR_CONSTANT) + len1 = build_int_cst (gfc_charlen_type_node, + expr->value.op.op1->value.character.length); + else if (expr->value.op.op1->ts.u.cl->length) + { + gfc_init_se (&se, NULL); + gfc_conv_expr (&se, expr->value.op.op1->ts.u.cl->length); + len1 = se.expr; + } + else + { + /* Last resort! */ + gfc_init_se (&se, NULL); + se.want_pointer = 1; + se.descriptor_only = 1; + gfc_conv_expr (&se, expr->value.op.op1); + len1 = se.string_length; + } + } + + type = gfc_typenode_for_spec (&expr->value.op.op2->ts); + len2 = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); + if (len2 == NULL_TREE) + { + if (expr->value.op.op2->expr_type == EXPR_OP) + len2 = concat_str_length (expr->value.op.op2); + else if (expr->value.op.op2->expr_type == EXPR_CONSTANT) + len2 = build_int_cst (gfc_charlen_type_node, + expr->value.op.op2->value.character.length); + else if (expr->value.op.op2->ts.u.cl->length) + { + gfc_init_se (&se, NULL); + gfc_conv_expr (&se, expr->value.op.op2->ts.u.cl->length); + len2 = se.expr; + } + else + { + /* Last resort! */ + gfc_init_se (&se, NULL); + se.want_pointer = 1; + se.descriptor_only = 1; + gfc_conv_expr (&se, expr->value.op.op2); + len2 = se.string_length; + } + } + + gcc_assert(len1 && len2); + len1 = fold_convert (gfc_charlen_type_node, len1); + len2 = fold_convert (gfc_charlen_type_node, len2); + + return fold_build2_loc (input_location, PLUS_EXPR, + gfc_charlen_type_node, len1, len2); +} + + /* Allocate the lhs of an assignment to an allocatable array, otherwise reallocate it. */ @@ -8366,6 +8449,12 @@ /* Allocate if data is NULL. */ cond_null = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, array1, build_int_cst (TREE_TYPE (array1), 0)); + + if (expr1->ts.deferred) + cond_null = gfc_evaluate_now (boolean_true_node, &fblock); + else + cond_null= gfc_evaluate_now (cond_null, &fblock); + tmp = build3_v (COND_EXPR, cond_null, build1_v (GOTO_EXPR, jump_label1), build_empty_stmt (input_location)); @@ -8454,7 +8543,13 @@ cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, size1, size2); - neq_size = gfc_evaluate_now (cond, &fblock); + + /* If the lhs is deferred length, assume that the element size + changes and force a reallocation. */ + if (expr1->ts.deferred) + neq_size = gfc_evaluate_now (boolean_true_node, &fblock); + else + neq_size = gfc_evaluate_now (cond, &fblock); /* Deallocation of allocatable components will have to occur on reallocation. Fix the old descriptor now. */ @@ -8559,6 +8654,12 @@ else { tmp = expr2->ts.u.cl->backend_decl; + if (!tmp && expr2->expr_type == EXPR_OP + && expr2->value.op.op == INTRINSIC_CONCAT) + { + tmp = concat_str_length (expr2); + expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock); + } tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp); } @@ -8586,6 +8687,22 @@ size2, size_one_node); size2 = gfc_evaluate_now (size2, &fblock); + /* For deferred character length, the 'size' field of the dtype might + have changed so set the dtype. */ + if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)) + && expr1->ts.type == BT_CHARACTER && expr1->ts.deferred) + { + tree type; + tmp = gfc_conv_descriptor_dtype (desc); + if (expr2->ts.u.cl->backend_decl) + type = gfc_typenode_for_spec (&expr2->ts); + else + type = gfc_typenode_for_spec (&expr1->ts); + + gfc_add_modify (&fblock, tmp, + gfc_get_dtype_rank_type (expr1->rank,type)); + } + /* Realloc expression. Note that the scalarizer uses desc.data in the array reference - (*desc.data)[]. */ gfc_init_block (&realloc_block); @@ -8628,8 +8745,16 @@ 1, size2); gfc_conv_descriptor_data_set (&alloc_block, desc, tmp); - tmp = gfc_conv_descriptor_dtype (desc); - gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc))); + + /* We already set the dtype in the case of deferred character + length arrays. */ + if (!(GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)) + && expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)) + { + tmp = gfc_conv_descriptor_dtype (desc); + gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc))); + } + if ((expr1->ts.type == BT_DERIVED) && expr1->ts.u.derived->attr.alloc_comp) { --- a/gcc/fortran/trans.c 2015-04-10 14:03:35.000000000 +0200 +++ b/gcc/fortran/trans.c 2016-02-16 15:44:29.788760264 +0100 @@ -1,5 +1,5 @@ /* Code translation -- generate GCC trees from gfc_code. - Copyright (C) 2002-2015 Free Software Foundation, Inc. + Copyright (C) 2002-2016 Free Software Foundation, Inc. Contributed by Paul Brook This file is part of GCC. @@ -344,6 +344,18 @@ type = TREE_TYPE (type); + /* Use pointer arithmetic for deferred character length array + references. */ + if (type && TREE_CODE (type) == ARRAY_TYPE + && TYPE_MAXVAL (TYPE_DOMAIN (type)) != NULL_TREE + && TREE_CODE (TYPE_MAXVAL (TYPE_DOMAIN (type))) == VAR_DECL + && decl + && DECL_CONTEXT (TYPE_MAXVAL (TYPE_DOMAIN (type))) + == DECL_CONTEXT (decl)) + span = TYPE_MAXVAL (TYPE_DOMAIN (type)); + else + span = NULL_TREE; + if (DECL_P (base)) TREE_ADDRESSABLE (base) = 1; @@ -358,7 +370,8 @@ || TREE_CODE (decl) == PARM_DECL) && ((GFC_DECL_SUBREF_ARRAY_P (decl) && !integer_zerop (GFC_DECL_SPAN(decl))) - || GFC_DECL_CLASS (decl))) + || GFC_DECL_CLASS (decl) + || span != NULL_TREE)) { if (GFC_DECL_CLASS (decl)) { @@ -377,6 +390,8 @@ } else if (GFC_DECL_SUBREF_ARRAY_P (decl)) span = GFC_DECL_SPAN(decl); + else if (span) + span = fold_convert (gfc_array_index_type, span); else gcc_unreachable (); @@ -701,7 +716,7 @@ static void gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size, tree token, tree status, tree errmsg, tree errlen, - bool lock_var) + bool lock_var, bool event_var) { tree tmp, pstat; @@ -732,13 +747,24 @@ build_int_cst (size_type_node, 1)), build_int_cst (integer_type_node, lock_var ? GFC_CAF_LOCK_ALLOC - : GFC_CAF_COARRAY_ALLOC), + : event_var ? GFC_CAF_EVENT_ALLOC + : GFC_CAF_COARRAY_ALLOC), token, pstat, errmsg, errlen); tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (pointer), pointer, fold_convert ( TREE_TYPE (pointer), tmp)); gfc_add_expr_to_block (block, tmp); + + /* It guarantees memory consistency within the same segment */ + tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), + tmp = build5_loc (input_location, ASM_EXPR, void_type_node, + gfc_build_string_const (1, ""), + NULL_TREE, NULL_TREE, + tree_cons (NULL_TREE, tmp, NULL_TREE), + NULL_TREE); + ASM_VOLATILE_P (tmp) = 1; + gfc_add_expr_to_block (block, tmp); } @@ -794,6 +820,11 @@ == INTMOD_ISO_FORTRAN_ENV && expr->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE; + bool event_var = expr->ts.type == BT_DERIVED + && expr->ts.u.derived->from_intmod + == INTMOD_ISO_FORTRAN_ENV + && expr->ts.u.derived->intmod_sym_id + == ISOFORTRAN_EVENT_TYPE; /* In the front end, we represent the lock variable as pointer. However, the FE only passes the pointer around and leaves the actual representation to the library. Hence, we have to convert back to the @@ -803,7 +834,7 @@ size, TYPE_SIZE_UNIT (ptr_type_node)); gfc_allocate_using_lib (&alloc_block, mem, size, token, status, - errmsg, errlen, lock_var); + errmsg, errlen, lock_var, event_var); if (status != NULL_TREE) { @@ -1360,6 +1391,16 @@ token, pstat, errmsg, errlen); gfc_add_expr_to_block (&non_null, tmp); + /* It guarantees memory consistency within the same segment */ + tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), + tmp = build5_loc (input_location, ASM_EXPR, void_type_node, + gfc_build_string_const (1, ""), + NULL_TREE, NULL_TREE, + tree_cons (NULL_TREE, tmp, NULL_TREE), + NULL_TREE); + ASM_VOLATILE_P (tmp) = 1; + gfc_add_expr_to_block (&non_null, tmp); + if (status != NULL_TREE) { tree stat = build_fold_indirect_ref_loc (input_location, status); @@ -1647,6 +1688,7 @@ gfc_add_expr_to_block (&block, res); } + gfc_current_locus = code->loc; gfc_set_backend_locus (&code->loc); switch (code->op) @@ -1808,6 +1850,11 @@ res = gfc_trans_lock_unlock (code, code->op); break; + case EXEC_EVENT_POST: + case EXEC_EVENT_WAIT: + res = gfc_trans_event_post_wait (code, code->op); + break; + case EXEC_FORALL: res = gfc_trans_forall (code); break; --- a/gcc/fortran/trans-decl.c 2015-10-29 20:52:56.000000000 +0100 +++ b/gcc/fortran/trans-decl.c 2016-02-16 15:44:29.784760195 +0100 @@ -163,6 +163,9 @@ tree gfor_fndecl_caf_atomic_op; tree gfor_fndecl_caf_lock; tree gfor_fndecl_caf_unlock; +tree gfor_fndecl_caf_event_post; +tree gfor_fndecl_caf_event_wait; +tree gfor_fndecl_caf_event_query; tree gfor_fndecl_co_broadcast; tree gfor_fndecl_co_max; tree gfor_fndecl_co_min; @@ -3505,6 +3508,21 @@ void_type_node, 6, pvoid_type_node, size_type_node, integer_type_node, pint_type, pchar_type_node, integer_type_node); + gfor_fndecl_caf_event_post = gfc_build_library_function_decl_with_spec ( + get_identifier (PREFIX("caf_event_post")), "R..WW", + void_type_node, 6, pvoid_type_node, size_type_node, integer_type_node, + pint_type, pchar_type_node, integer_type_node); + + gfor_fndecl_caf_event_wait = gfc_build_library_function_decl_with_spec ( + get_identifier (PREFIX("caf_event_wait")), "R..WW", + void_type_node, 6, pvoid_type_node, size_type_node, integer_type_node, + pint_type, pchar_type_node, integer_type_node); + + gfor_fndecl_caf_event_query = gfc_build_library_function_decl_with_spec ( + get_identifier (PREFIX("caf_event_query")), "R..WW", + void_type_node, 5, pvoid_type_node, size_type_node, integer_type_node, + pint_type, pint_type); + gfor_fndecl_co_broadcast = gfc_build_library_function_decl_with_spec ( get_identifier (PREFIX("caf_co_broadcast")), "W.WW", void_type_node, 5, pvoid_type_node, integer_type_node, @@ -4784,7 +4802,7 @@ generate_coarray_sym_init (gfc_symbol *sym) { tree tmp, size, decl, token; - bool is_lock_type; + bool is_lock_type, is_event_type; int reg_type; if (sym->attr.dummy || sym->attr.allocatable || !sym->attr.codimension @@ -4800,13 +4818,17 @@ && sym->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV && sym->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE; + is_event_type = sym->ts.type == BT_DERIVED + && sym->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV + && sym->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE; + /* FIXME: Workaround for PR middle-end/49106, cf. also PR middle-end/49108 to make sure the variable is not optimized away. */ DECL_PRESERVE_P (DECL_CONTEXT (decl)) = 1; /* For lock types, we pass the array size as only the library knows the size of the variable. */ - if (is_lock_type) + if (is_lock_type || is_event_type) size = gfc_index_one_node; else size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (decl))); @@ -4828,6 +4850,8 @@ GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE(decl))); if (is_lock_type) reg_type = sym->attr.artificial ? GFC_CAF_CRITICAL : GFC_CAF_LOCK_STATIC; + else if (is_event_type) + reg_type = GFC_CAF_EVENT_STATIC; else reg_type = GFC_CAF_COARRAY_STATIC; tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_register, 6, size, --- a/gcc/fortran/trans-expr.c 2015-11-04 21:00:19.000000000 +0100 +++ b/gcc/fortran/trans-expr.c 2016-02-16 15:44:29.785760212 +0100 @@ -1,5 +1,5 @@ /* Expression translation - Copyright (C) 2002-2015 Free Software Foundation, Inc. + Copyright (C) 2002-2016 Free Software Foundation, Inc. Contributed by Paul Brook and Steven Bosscher @@ -1019,6 +1019,7 @@ tree fcn; tree fcn_type; tree from_data; + tree from_class_base = NULL; tree from_len; tree to_data; tree to_len; @@ -1035,21 +1036,41 @@ from_len = to_len = NULL_TREE; if (from != NULL_TREE) - fcn = gfc_class_vtab_copy_get (from); + { + /* Check that from is a class. When the class is part of a coarray, + then from is a common pointer and is to be used as is. */ + tmp = POINTER_TYPE_P (TREE_TYPE (from)) && !DECL_P (from) + ? TREE_OPERAND (from, 0) : from; + if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)) + || (DECL_P (tmp) && GFC_DECL_CLASS (tmp))) + { + from_class_base = from; + from_data = gfc_class_data_get (from_class_base); + } + else + { + /* For arrays two component_refs can be present. */ + if (TREE_CODE (tmp) == COMPONENT_REF) + tmp = TREE_OPERAND (tmp, 0); + if (TREE_CODE (tmp) == COMPONENT_REF) + tmp = TREE_OPERAND (tmp, 0); + from_class_base = tmp; + from_data = from; + } + fcn = gfc_class_vtab_copy_get (from_class_base); + } else - fcn = gfc_class_vtab_copy_get (to); + { + fcn = gfc_class_vtab_copy_get (to); + from_data = gfc_class_vtab_def_init_get (to); + } fcn_type = TREE_TYPE (TREE_TYPE (fcn)); - if (from != NULL_TREE) - from_data = gfc_class_data_get (from); - else - from_data = gfc_class_vtab_def_init_get (to); - if (unlimited) { - if (from != NULL_TREE && unlimited) - from_len = gfc_class_len_get (from); + if (from_class_base != NULL_TREE) + from_len = gfc_class_len_get (from_class_base); else from_len = integer_zero_node; } @@ -4398,6 +4419,62 @@ } +/* This function tells whether the middle-end representation of the expression + E given as input may point to data otherwise accessible through a variable + (sub-)reference. + It is assumed that the only expressions that may alias are variables, + and array constructors if ARRAY_MAY_ALIAS is true and some of its elements + may alias. + This function is used to decide whether freeing an expression's allocatable + components is safe or should be avoided. + + If ARRAY_MAY_ALIAS is true, an array constructor may alias if some of + its elements are copied from a variable. This ARRAY_MAY_ALIAS trick + is necessary because for array constructors, aliasing depends on how + the array is used: + - If E is an array constructor used as argument to an elemental procedure, + the array, which is generated through shallow copy by the scalarizer, + is used directly and can alias the expressions it was copied from. + - If E is an array constructor used as argument to a non-elemental + procedure,the scalarizer is used in gfc_conv_expr_descriptor to generate + the array as in the previous case, but then that array is used + to initialize a new descriptor through deep copy. There is no alias + possible in that case. + Thus, the ARRAY_MAY_ALIAS flag is necessary to distinguish the two cases + above. */ + +static bool +expr_may_alias_variables (gfc_expr *e, bool array_may_alias) +{ + gfc_constructor *c; + + if (e->expr_type == EXPR_VARIABLE) + return true; + else if (e->expr_type == EXPR_FUNCTION) + { + gfc_symbol *proc_ifc = gfc_get_proc_ifc_for_expr (e); + + if ((proc_ifc->result->ts.type == BT_CLASS + && proc_ifc->result->ts.u.derived->attr.is_class + && CLASS_DATA (proc_ifc->result)->attr.class_pointer) + || proc_ifc->result->attr.pointer) + return true; + else + return false; + } + else if (e->expr_type != EXPR_ARRAY || !array_may_alias) + return false; + + for (c = gfc_constructor_first (e->value.constructor); + c; c = gfc_constructor_next (c)) + if (c->expr + && expr_may_alias_variables (c->expr, array_may_alias)) + return true; + + return false; +} + + /* Generate code for a procedure call. Note can return se->post != NULL. If se->direct_byref is set then se->expr contains the return parameter. Return nonzero, if the call has alternate specifiers. @@ -4448,9 +4525,15 @@ comp = gfc_get_proc_ptr_comp (expr); + bool elemental_proc = (comp + && comp->ts.interface + && comp->ts.interface->attr.elemental) + || (comp && comp->attr.elemental) + || sym->attr.elemental; + if (se->ss != NULL) { - if (!sym->attr.elemental && !(comp && comp->attr.elemental)) + if (!elemental_proc) { gcc_assert (se->ss->info->type == GFC_SS_FUNCTION); if (se->ss->info->useflags) @@ -4501,6 +4584,23 @@ fsym = formal ? formal->sym : NULL; parm_kind = MISSING; + /* If the procedure requires an explicit interface, the actual + argument is passed according to the corresponding formal + argument. If the corresponding formal argument is a POINTER, + ALLOCATABLE or assumed shape, we do not use g77's calling + convention, and pass the address of the array descriptor + instead. Otherwise we use g77's calling convention, in other words + pass the array data pointer without descriptor. */ + bool nodesc_arg = fsym != NULL + && !(fsym->attr.pointer || fsym->attr.allocatable) + && fsym->as + && fsym->as->type != AS_ASSUMED_SHAPE + && fsym->as->type != AS_ASSUMED_RANK; + if (comp) + nodesc_arg = nodesc_arg || !comp->attr.always_explicit; + else + nodesc_arg = nodesc_arg || !sym->attr.always_explicit; + /* Class array expressions are sometimes coming completely unadorned with either arrayspec or _data component. Correct that here. OOP-TODO: Move this to the frontend. */ @@ -5020,22 +5120,6 @@ } else { - /* If the procedure requires an explicit interface, the actual - argument is passed according to the corresponding formal - argument. If the corresponding formal argument is a POINTER, - ALLOCATABLE or assumed shape, we do not use g77's calling - convention, and pass the address of the array descriptor - instead. Otherwise we use g77's calling convention. */ - bool f; - f = (fsym != NULL) - && !(fsym->attr.pointer || fsym->attr.allocatable) - && fsym->as && fsym->as->type != AS_ASSUMED_SHAPE - && fsym->as->type != AS_ASSUMED_RANK; - if (comp) - f = f || !comp->attr.always_explicit; - else - f = f || !sym->attr.always_explicit; - /* If the argument is a function call that may not create a temporary for the result, we have to check that we can do it, i.e. that there is no alias between this @@ -5080,7 +5164,7 @@ array of derived types. In this case, the argument is converted to a temporary, which is passed and then written back after the procedure call. */ - gfc_conv_subref_array_arg (&parmse, e, f, + gfc_conv_subref_array_arg (&parmse, e, nodesc_arg, fsym ? fsym->attr.intent : INTENT_INOUT, fsym && fsym->attr.pointer); else if (gfc_is_class_array_ref (e, NULL) @@ -5092,7 +5176,7 @@ OOP-TODO: Insert code so that if the dynamic type is the same as the declared type, copy-in/copy-out does not occur. */ - gfc_conv_subref_array_arg (&parmse, e, f, + gfc_conv_subref_array_arg (&parmse, e, nodesc_arg, fsym ? fsym->attr.intent : INTENT_INOUT, fsym && fsym->attr.pointer); @@ -5103,12 +5187,13 @@ intent in. */ { e->must_finalize = 1; - gfc_conv_subref_array_arg (&parmse, e, f, + gfc_conv_subref_array_arg (&parmse, e, nodesc_arg, INTENT_IN, fsym && fsym->attr.pointer); } else - gfc_conv_array_parameter (&parmse, e, f, fsym, sym->name, NULL); + gfc_conv_array_parameter (&parmse, e, nodesc_arg, fsym, + sym->name, NULL); /* If an ALLOCATABLE dummy argument has INTENT(OUT) and is allocated on entry, it must be deallocated. */ @@ -5150,7 +5235,7 @@ but do not always set fsym. */ if (e->expr_type == EXPR_VARIABLE && e->symtree->n.sym->attr.optional - && ((e->rank != 0 && sym->attr.elemental) + && ((e->rank != 0 && elemental_proc) || e->representation.length || e->ts.type == BT_CHARACTER || (e->rank != 0 && (fsym == NULL @@ -5185,13 +5270,16 @@ gfc_add_block_to_block (&post, &parmse.post); /* Allocated allocatable components of derived types must be - deallocated for non-variable scalars. Non-variable arrays are - dealt with in trans-array.c(gfc_conv_array_parameter). */ + deallocated for non-variable scalars, array arguments to elemental + procedures, and array arguments with descriptor to non-elemental + procedures. As bounds information for descriptorless arrays is no + longer available here, they are dealt with in trans-array.c + (gfc_conv_array_parameter). */ if (e && (e->ts.type == BT_DERIVED || e->ts.type == BT_CLASS) && e->ts.u.derived->attr.alloc_comp - && !(e->symtree && e->symtree->n.sym->attr.pointer) - && (e->expr_type != EXPR_VARIABLE && !e->rank)) - { + && (e->rank == 0 || elemental_proc || !nodesc_arg) + && !expr_may_alias_variables (e, elemental_proc)) + { int parm_rank; tmp = build_fold_indirect_ref_loc (input_location, parmse.expr); @@ -5343,7 +5431,8 @@ else { tmp = parmse.string_length; - if (TREE_CODE (tmp) != VAR_DECL) + if (TREE_CODE (tmp) != VAR_DECL + && TREE_CODE (tmp) != COMPONENT_REF) tmp = gfc_evaluate_now (parmse.string_length, &se->pre); parmse.string_length = gfc_build_addr_expr (NULL_TREE, tmp); } @@ -5527,8 +5616,9 @@ len = cl.backend_decl; } - byref = (comp && (comp->attr.dimension || comp->ts.type == BT_CHARACTER)) - || (!comp && gfc_return_by_reference (sym)); + byref = (comp && (comp->attr.dimension + || (comp->ts.type == BT_CHARACTER && !sym->attr.is_bind_c))) + || (!comp && gfc_return_by_reference (sym)); if (byref) { if (se->direct_byref) @@ -6354,6 +6444,11 @@ { gfc_se se; + if (flag_coarray != GFC_FCOARRAY_LIB && ts->type == BT_DERIVED + && ts->u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV + && ts->u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE) + return build_constructor (type, NULL); + if (!(expr || pointer || procptr)) return NULL_TREE; @@ -6518,7 +6613,7 @@ gfc_conv_expr (&rse, expr); - tmp = gfc_trans_scalar_assign (&lse, &rse, cm->ts, true, false, true); + tmp = gfc_trans_scalar_assign (&lse, &rse, cm->ts, true, true, true); gfc_add_expr_to_block (&body, tmp); gcc_assert (rse.ss == gfc_ss_terminator); @@ -7403,20 +7498,6 @@ /* Take the address of that value. */ se->expr = gfc_build_addr_expr (NULL_TREE, var); - if (expr->ts.type == BT_DERIVED && expr->rank - && !gfc_is_finalizable (expr->ts.u.derived, NULL) - && expr->ts.u.derived->attr.alloc_comp - && expr->expr_type != EXPR_VARIABLE) - { - tree tmp; - - tmp = build_fold_indirect_ref_loc (input_location, se->expr); - tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank); - - /* The components shall be deallocated before - their containing entity. */ - gfc_prepend_expr_to_block (&se->post, tmp); - } } @@ -8901,6 +8982,7 @@ bool scalar_to_array; tree string_length; int n; + bool maybe_workshare = false; /* Assignment of the form lhs = rhs. */ gfc_start_block (&block); @@ -8975,8 +9057,13 @@ } /* Allow the scalarizer to workshare array assignments. */ - if ((ompws_flags & OMPWS_WORKSHARE_FLAG) && loop.temp_ss == NULL) - ompws_flags |= OMPWS_SCALARIZER_WS; + if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY)) + == OMPWS_WORKSHARE_FLAG + && loop.temp_ss == NULL) + { + maybe_workshare = true; + ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY; + } /* Start the scalarized loop body. */ gfc_start_scalarized_body (&loop, &body); @@ -8998,8 +9085,10 @@ } /* Stabilize a string length for temporaries. */ - if (expr2->ts.type == BT_CHARACTER) + if (expr2->ts.type == BT_CHARACTER && !expr2->ts.deferred) string_length = gfc_evaluate_now (rse.string_length, &rse.pre); + else if (expr2->ts.type == BT_CHARACTER) + string_length = rse.string_length; else string_length = NULL_TREE; @@ -9033,8 +9122,14 @@ the function call must happen before the (re)allocation of the lhs - otherwise the character length of the result is not known. NOTE: This relies on having the exact dependence of the length type - parameter available to the caller; gfortran saves it in the .mod files. */ - if (flag_realloc_lhs && expr2->ts.type == BT_CHARACTER && expr1->ts.deferred) + parameter available to the caller; gfortran saves it in the .mod files. + NOTE ALSO: The concatenation operation generates a temporary pointer, + whose allocation must go to the innermost loop. */ + if (flag_realloc_lhs + && expr2->ts.type == BT_CHARACTER && expr1->ts.deferred + && !(lss != gfc_ss_terminator + && expr2->expr_type == EXPR_OP + && expr2->value.op.op == INTRINSIC_CONCAT)) gfc_add_block_to_block (&block, &rse.pre); /* Nullify the allocatable components corresponding to those of the lhs @@ -9117,6 +9212,9 @@ gfc_add_expr_to_block (&loop.code[expr1->rank - 1], tmp); } + if (maybe_workshare) + ompws_flags &= ~OMPWS_SCALARIZER_BODY; + /* Generate the copying loops. */ gfc_trans_scalarizing_loops (&loop, &body); --- a/gcc/fortran/trans.h 2015-03-24 11:28:48.000000000 +0100 +++ b/gcc/fortran/trans.h 2016-02-16 15:44:29.788760264 +0100 @@ -109,7 +109,9 @@ GFC_CAF_COARRAY_ALLOC, GFC_CAF_LOCK_STATIC, GFC_CAF_LOCK_ALLOC, - GFC_CAF_CRITICAL + GFC_CAF_CRITICAL, + GFC_CAF_EVENT_STATIC, + GFC_CAF_EVENT_ALLOC } gfc_coarray_type; @@ -756,6 +758,9 @@ extern GTY(()) tree gfor_fndecl_caf_atomic_op; extern GTY(()) tree gfor_fndecl_caf_lock; extern GTY(()) tree gfor_fndecl_caf_unlock; +extern GTY(()) tree gfor_fndecl_caf_event_post; +extern GTY(()) tree gfor_fndecl_caf_event_wait; +extern GTY(()) tree gfor_fndecl_caf_event_query; extern GTY(()) tree gfor_fndecl_co_broadcast; extern GTY(()) tree gfor_fndecl_co_max; extern GTY(()) tree gfor_fndecl_co_min; @@ -1027,7 +1032,9 @@ construct is not workshared. */ #define OMPWS_SCALARIZER_WS 4 /* Set if scalarizer should attempt to create parallel loops. */ -#define OMPWS_NOWAIT 8 /* Use NOWAIT on OMP_FOR. */ +#define OMPWS_SCALARIZER_BODY 8 /* Set if handling body of potential + parallel loop. */ +#define OMPWS_NOWAIT 16 /* Use NOWAIT on OMP_FOR. */ extern int ompws_flags; #endif /* GFC_TRANS_H */ --- a/gcc/fortran/trans-intrinsic.c 2015-10-26 18:25:03.000000000 +0100 +++ b/gcc/fortran/trans-intrinsic.c 2016-02-16 15:44:29.786760229 +0100 @@ -1221,12 +1221,22 @@ /* No overlap possible as we have generated a temporary. */ if (lhs == NULL_TREE) may_require_tmp = boolean_false_node; + + /* It guarantees memory consistency within the same segment */ + tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), + tmp = build5_loc (input_location, ASM_EXPR, void_type_node, + gfc_build_string_const (1, ""), + NULL_TREE, NULL_TREE, + tree_cons (NULL_TREE, tmp, NULL_TREE), + NULL_TREE); + ASM_VOLATILE_P (tmp) = 1; + gfc_add_expr_to_block (&se->pre, tmp); tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 9, token, offset, image_index, argse.expr, vec, dst_var, kind, lhs_kind, may_require_tmp); gfc_add_expr_to_block (&se->pre, tmp); - + if (se->ss) gfc_advance_se_ss_chain (se); @@ -1386,6 +1396,16 @@ { tree rhs_token, rhs_offset, rhs_image_index; + /* It guarantees memory consistency within the same segment */ + tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), + tmp = build5_loc (input_location, ASM_EXPR, void_type_node, + gfc_build_string_const (1, ""), + NULL_TREE, NULL_TREE, + tree_cons (NULL_TREE, tmp, NULL_TREE), + NULL_TREE); + ASM_VOLATILE_P (tmp) = 1; + gfc_add_expr_to_block (&block, tmp); + caf_decl = gfc_get_tree_for_caf_expr (rhs_expr); if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE) caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl); @@ -1401,6 +1421,17 @@ gfc_add_expr_to_block (&block, tmp); gfc_add_block_to_block (&block, &lhs_se.post); gfc_add_block_to_block (&block, &rhs_se.post); + + /* It guarantees memory consistency within the same segment */ + tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), + tmp = build5_loc (input_location, ASM_EXPR, void_type_node, + gfc_build_string_const (1, ""), + NULL_TREE, NULL_TREE, + tree_cons (NULL_TREE, tmp, NULL_TREE), + NULL_TREE); + ASM_VOLATILE_P (tmp) = 1; + gfc_add_expr_to_block (&block, tmp); + return gfc_finish_block (&block); } @@ -9243,6 +9274,154 @@ return gfc_finish_block (&block); } +static tree +conv_intrinsic_event_query (gfc_code *code) +{ + gfc_se se, argse; + tree stat = NULL_TREE, stat2 = NULL_TREE; + tree count = NULL_TREE, count2 = NULL_TREE; + + gfc_expr *event_expr = code->ext.actual->expr; + + if (code->ext.actual->next->next->expr) + { + gcc_assert (code->ext.actual->next->next->expr->expr_type + == EXPR_VARIABLE); + gfc_init_se (&argse, NULL); + gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr); + stat = argse.expr; + } + else if (flag_coarray == GFC_FCOARRAY_LIB) + stat = null_pointer_node; + + if (code->ext.actual->next->expr) + { + gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE); + gfc_init_se (&argse, NULL); + gfc_conv_expr_val (&argse, code->ext.actual->next->expr); + count = argse.expr; + } + + gfc_start_block (&se.pre); + if (flag_coarray == GFC_FCOARRAY_LIB) + { + tree tmp, token, image_index; + tree index = size_zero_node; + + if (event_expr->expr_type == EXPR_FUNCTION + && event_expr->value.function.isym + && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET) + event_expr = event_expr->value.function.actual->expr; + + tree caf_decl = gfc_get_tree_for_caf_expr (event_expr); + + if (event_expr->symtree->n.sym->ts.type != BT_DERIVED + || event_expr->symtree->n.sym->ts.u.derived->from_intmod + != INTMOD_ISO_FORTRAN_ENV + || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id + != ISOFORTRAN_EVENT_TYPE) + { + gfc_error ("Sorry, the event component of derived type at %L is not " + "yet supported", &event_expr->where); + return NULL_TREE; + } + + if (gfc_is_coindexed (event_expr)) + { + gfc_error ("The event variable at %L shall not be coindexed ", + &event_expr->where); + return NULL_TREE; + } + + image_index = integer_zero_node; + + gfc_get_caf_token_offset (&token, NULL, caf_decl, NULL_TREE, event_expr); + + /* For arrays, obtain the array index. */ + if (gfc_expr_attr (event_expr).dimension) + { + tree desc, tmp, extent, lbound, ubound; + gfc_array_ref *ar, ar2; + int i; + + /* TODO: Extend this, once DT components are supported. */ + ar = &event_expr->ref->u.ar; + ar2 = *ar; + memset (ar, '\0', sizeof (*ar)); + ar->as = ar2.as; + ar->type = AR_FULL; + + gfc_init_se (&argse, NULL); + argse.descriptor_only = 1; + gfc_conv_expr_descriptor (&argse, event_expr); + gfc_add_block_to_block (&se.pre, &argse.pre); + desc = argse.expr; + *ar = ar2; + + extent = integer_one_node; + for (i = 0; i < ar->dimen; i++) + { + gfc_init_se (&argse, NULL); + gfc_conv_expr_type (&argse, ar->start[i], integer_type_node); + gfc_add_block_to_block (&argse.pre, &argse.pre); + lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]); + tmp = fold_build2_loc (input_location, MINUS_EXPR, + integer_type_node, argse.expr, + fold_convert(integer_type_node, lbound)); + tmp = fold_build2_loc (input_location, MULT_EXPR, + integer_type_node, extent, tmp); + index = fold_build2_loc (input_location, PLUS_EXPR, + integer_type_node, index, tmp); + if (i < ar->dimen - 1) + { + ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]); + tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL); + tmp = fold_convert (integer_type_node, tmp); + extent = fold_build2_loc (input_location, MULT_EXPR, + integer_type_node, extent, tmp); + } + } + } + + if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node) + { + count2 = count; + count = gfc_create_var (integer_type_node, "count"); + } + + if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node) + { + stat2 = stat; + stat = gfc_create_var (integer_type_node, "stat"); + } + + tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5, + token, index, image_index, count + ? gfc_build_addr_expr (NULL, count) : count, + stat != null_pointer_node + ? gfc_build_addr_expr (NULL, stat) : stat); + gfc_add_expr_to_block (&se.pre, tmp); + + if (count2 != NULL_TREE) + gfc_add_modify (&se.pre, count2, + fold_convert (TREE_TYPE (count2), count)); + + if (stat2 != NULL_TREE) + gfc_add_modify (&se.pre, stat2, + fold_convert (TREE_TYPE (stat2), stat)); + + return gfc_finish_block (&se.pre); + } + + gfc_init_se (&argse, NULL); + gfc_conv_expr_val (&argse, code->ext.actual->expr); + gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr)); + + if (stat != NULL_TREE) + gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0)); + + return gfc_finish_block (&se.pre); +} static tree conv_intrinsic_move_alloc (gfc_code *code) @@ -9539,6 +9718,10 @@ res = conv_intrinsic_atomic_ref (code); break; + case GFC_ISYM_EVENT_QUERY: + res = conv_intrinsic_event_query (code); + break; + case GFC_ISYM_C_F_POINTER: case GFC_ISYM_C_F_PROCPOINTER: res = conv_isocbinding_subroutine (code); --- a/gcc/fortran/trans-openmp.c 2015-10-18 17:01:03.000000000 +0200 +++ b/gcc/fortran/trans-openmp.c 2016-02-16 15:42:04.615303641 +0100 @@ -4255,7 +4255,7 @@ /* By default, every gfc_code is a single unit of work. */ ompws_flags |= OMPWS_CURR_SINGLEUNIT; - ompws_flags &= ~OMPWS_SCALARIZER_WS; + ompws_flags &= ~(OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY); switch (code->op) { --- a/gcc/fortran/trans-stmt.c 2015-10-22 20:05:21.000000000 +0200 +++ b/gcc/fortran/trans-stmt.c 2016-02-16 15:44:29.787760247 +0100 @@ -1,5 +1,5 @@ /* Statement translation -- generate GCC trees from gfc_code. - Copyright (C) 2002-2015 Free Software Foundation, Inc. + Copyright (C) 2002-2016 Free Software Foundation, Inc. Contributed by Paul Brook and Steven Bosscher @@ -788,6 +788,7 @@ if (code->expr3) { gfc_init_se (&argse, NULL); + argse.want_pointer = 1; gfc_conv_expr (&argse, code->expr3); gfc_add_block_to_block (&se.pre, &argse.pre); errmsg = argse.expr; @@ -829,6 +830,17 @@ errmsg, errmsg_len); gfc_add_expr_to_block (&se.pre, tmp); + /* It guarantees memory consistency within the same segment */ + tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), + tmp = build5_loc (input_location, ASM_EXPR, void_type_node, + gfc_build_string_const (1, ""), + NULL_TREE, NULL_TREE, + tree_cons (NULL_TREE, tmp, NULL_TREE), + NULL_TREE); + ASM_VOLATILE_P (tmp) = 1; + + gfc_add_expr_to_block (&se.pre, tmp); + if (stat2 != NULL_TREE) gfc_add_modify (&se.pre, stat2, fold_convert (TREE_TYPE (stat2), stat)); @@ -852,6 +864,165 @@ return gfc_finish_block (&se.pre); } +tree +gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op) +{ + gfc_se se, argse; + tree stat = NULL_TREE, stat2 = NULL_TREE; + tree until_count = NULL_TREE; + + if (code->expr2) + { + gcc_assert (code->expr2->expr_type == EXPR_VARIABLE); + gfc_init_se (&argse, NULL); + gfc_conv_expr_val (&argse, code->expr2); + stat = argse.expr; + } + else if (flag_coarray == GFC_FCOARRAY_LIB) + stat = null_pointer_node; + + if (code->expr4) + { + gfc_init_se (&argse, NULL); + gfc_conv_expr_val (&argse, code->expr4); + until_count = fold_convert (integer_type_node, argse.expr); + } + else + until_count = integer_one_node; + + if (flag_coarray != GFC_FCOARRAY_LIB) + { + gfc_start_block (&se.pre); + gfc_init_se (&argse, NULL); + gfc_conv_expr_val (&argse, code->expr1); + + if (op == EXEC_EVENT_POST) + gfc_add_modify (&se.pre, argse.expr, + fold_build2_loc (input_location, PLUS_EXPR, + TREE_TYPE (argse.expr), argse.expr, + build_int_cst (TREE_TYPE (argse.expr), 1))); + else + gfc_add_modify (&se.pre, argse.expr, + fold_build2_loc (input_location, MINUS_EXPR, + TREE_TYPE (argse.expr), argse.expr, + fold_convert (TREE_TYPE (argse.expr), + until_count))); + if (stat != NULL_TREE) + gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0)); + + return gfc_finish_block (&se.pre); + } + + gfc_start_block (&se.pre); + tree tmp, token, image_index, errmsg, errmsg_len; + tree index = size_zero_node; + tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1); + + if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED + || code->expr1->symtree->n.sym->ts.u.derived->from_intmod + != INTMOD_ISO_FORTRAN_ENV + || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id + != ISOFORTRAN_EVENT_TYPE) + { + gfc_error ("Sorry, the event component of derived type at %L is not " + "yet supported", &code->expr1->where); + return NULL_TREE; + } + + gfc_get_caf_token_offset (&token, NULL, caf_decl, NULL_TREE, code->expr1); + + if (gfc_is_coindexed (code->expr1)) + image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl); + else + image_index = integer_zero_node; + + /* For arrays, obtain the array index. */ + if (gfc_expr_attr (code->expr1).dimension) + { + tree desc, tmp, extent, lbound, ubound; + gfc_array_ref *ar, ar2; + int i; + + /* TODO: Extend this, once DT components are supported. */ + ar = &code->expr1->ref->u.ar; + ar2 = *ar; + memset (ar, '\0', sizeof (*ar)); + ar->as = ar2.as; + ar->type = AR_FULL; + + gfc_init_se (&argse, NULL); + argse.descriptor_only = 1; + gfc_conv_expr_descriptor (&argse, code->expr1); + gfc_add_block_to_block (&se.pre, &argse.pre); + desc = argse.expr; + *ar = ar2; + + extent = integer_one_node; + for (i = 0; i < ar->dimen; i++) + { + gfc_init_se (&argse, NULL); + gfc_conv_expr_type (&argse, ar->start[i], integer_type_node); + gfc_add_block_to_block (&argse.pre, &argse.pre); + lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]); + tmp = fold_build2_loc (input_location, MINUS_EXPR, + integer_type_node, argse.expr, + fold_convert(integer_type_node, lbound)); + tmp = fold_build2_loc (input_location, MULT_EXPR, + integer_type_node, extent, tmp); + index = fold_build2_loc (input_location, PLUS_EXPR, + integer_type_node, index, tmp); + if (i < ar->dimen - 1) + { + ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]); + tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL); + tmp = fold_convert (integer_type_node, tmp); + extent = fold_build2_loc (input_location, MULT_EXPR, + integer_type_node, extent, tmp); + } + } + } + + /* errmsg. */ + if (code->expr3) + { + gfc_init_se (&argse, NULL); + argse.want_pointer = 1; + gfc_conv_expr (&argse, code->expr3); + gfc_add_block_to_block (&se.pre, &argse.pre); + errmsg = argse.expr; + errmsg_len = fold_convert (integer_type_node, argse.string_length); + } + else + { + errmsg = null_pointer_node; + errmsg_len = integer_zero_node; + } + + if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node) + { + stat2 = stat; + stat = gfc_create_var (integer_type_node, "stat"); + } + + if (op == EXEC_EVENT_POST) + tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_post, 6, + token, index, image_index, + stat != null_pointer_node + ? gfc_build_addr_expr (NULL, stat) : stat, + errmsg, errmsg_len); + else + tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_wait, 6, + token, index, until_count, + stat != null_pointer_node + ? gfc_build_addr_expr (NULL, stat) : stat, + errmsg, errmsg_len); + gfc_add_expr_to_block (&se.pre, tmp); + + if (stat2 != NULL_TREE) + gfc_add_modify (&se.pre, stat2, fold_convert (TREE_TYPE (stat2), stat)); + + return gfc_finish_block (&se.pre); +} tree gfc_trans_sync (gfc_code *code, gfc_exec_op type) @@ -891,6 +1062,7 @@ { gcc_assert (code->expr3->expr_type == EXPR_VARIABLE); gfc_init_se (&argse, NULL); + argse.want_pointer = 1; gfc_conv_expr (&argse, code->expr3); gfc_conv_string_parameter (&argse); errmsg = gfc_build_addr_expr (NULL, argse.expr); @@ -931,6 +1103,20 @@ fold_convert (integer_type_node, images)); } + /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the + image control statements SYNC IMAGES and SYNC ALL. */ + if (flag_coarray == GFC_FCOARRAY_LIB) + { + tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), + tmp = build5_loc (input_location, ASM_EXPR, void_type_node, + gfc_build_string_const (1, ""), + NULL_TREE, NULL_TREE, + tree_cons (NULL_TREE, tmp, NULL_TREE), + NULL_TREE); + ASM_VOLATILE_P (tmp) = 1; + gfc_add_expr_to_block (&se.pre, tmp); + } + if (flag_coarray != GFC_FCOARRAY_LIB) { /* Set STAT to zero. */ @@ -1250,6 +1436,17 @@ null_pointer_node, null_pointer_node, null_pointer_node, integer_zero_node); gfc_add_expr_to_block (&block, tmp); + + /* It guarantees memory consistency within the same segment */ + tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), + tmp = build5_loc (input_location, ASM_EXPR, void_type_node, + gfc_build_string_const (1, ""), + NULL_TREE, NULL_TREE, + tree_cons (NULL_TREE, tmp, NULL_TREE), + NULL_TREE); + ASM_VOLATILE_P (tmp) = 1; + + gfc_add_expr_to_block (&block, tmp); } tmp = gfc_trans_code (code->block->next); @@ -1262,8 +1459,18 @@ null_pointer_node, null_pointer_node, integer_zero_node); gfc_add_expr_to_block (&block, tmp); - } + /* It guarantees memory consistency within the same segment */ + tmp = gfc_build_string_const (strlen ("memory")+1, "memory"), + tmp = build5_loc (input_location, ASM_EXPR, void_type_node, + gfc_build_string_const (1, ""), + NULL_TREE, NULL_TREE, + tree_cons (NULL_TREE, tmp, NULL_TREE), + NULL_TREE); + ASM_VOLATILE_P (tmp) = 1; + + gfc_add_expr_to_block (&block, tmp); + } return gfc_finish_block (&block); } @@ -4839,10 +5046,15 @@ gfc_loopinfo loop; gfc_ss *edss = 0; gfc_ss *esss = 0; + bool maybe_workshare = false; /* Allow the scalarizer to workshare simple where loops. */ - if (ompws_flags & OMPWS_WORKSHARE_FLAG) - ompws_flags |= OMPWS_SCALARIZER_WS; + if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY)) + == OMPWS_WORKSHARE_FLAG) + { + maybe_workshare = true; + ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY; + } cond = cblock->expr1; tdst = cblock->next->expr1; @@ -4942,6 +5154,8 @@ gfc_add_expr_to_block (&body, tmp); gfc_add_block_to_block (&body, &cse.post); + if (maybe_workshare) + ompws_flags &= ~OMPWS_SCALARIZER_BODY; gfc_trans_scalarizing_loops (&loop, &body); gfc_add_block_to_block (&block, &loop.pre); gfc_add_block_to_block (&block, &loop.post); @@ -5062,7 +5276,7 @@ gfc_trans_allocate (gfc_code * code) { gfc_alloc *al; - gfc_expr *expr; + gfc_expr *expr, *e3rhs = NULL; gfc_se se, se_sz; tree tmp; tree parm; @@ -5073,6 +5287,7 @@ tree label_finish; tree memsz; tree al_vptr, al_len; + tree def_str_len = NULL_TREE; /* If an expr3 is present, then store the tree for accessing its _vptr, and _len components in the variables, respectively. The element size, i.e. _vptr%size, is stored in expr3_esize. Any of @@ -5083,6 +5298,7 @@ stmtblock_t post; tree nelems; bool upoly_expr, tmp_expr3_len_flag = false, al_len_needs_set; + gfc_symtree *newsym = NULL; if (!code->ext.alloc.list) return NULL_TREE; @@ -5132,7 +5348,7 @@ _vptr, _len and element_size for expr3. */ if (code->expr3) { - bool vtab_needed = false; + bool vtab_needed = false, is_coarray = gfc_is_coarray (code->expr3); /* expr3_tmp gets the tree when code->expr3.mold is set, i.e., the expression is only needed to get the _vptr, _len a.s.o. */ tree expr3_tmp = NULL_TREE; @@ -5192,16 +5408,29 @@ false, false); gfc_add_block_to_block (&block, &se.pre); gfc_add_block_to_block (&post, &se.post); - /* Prevent aliasing, i.e., se.expr may be already a - variable declaration. */ + if (!VAR_P (se.expr)) { - tmp = build_fold_indirect_ref_loc (input_location, + tree var; + + tmp = is_coarray ? se.expr + : build_fold_indirect_ref_loc (input_location, se.expr); - tmp = gfc_evaluate_now (tmp, &block); + + /* We need a regular (non-UID) symbol here, therefore give a + prefix. */ + var = gfc_create_var (TREE_TYPE (tmp), "source"); + if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp))) + { + gfc_allocate_lang_decl (var); + GFC_DECL_SAVED_DESCRIPTOR (var) = GFC_DECL_SAVED_DESCRIPTOR (tmp); + } + gfc_add_modify_loc (input_location, &block, var, tmp); + tmp = var; } else tmp = se.expr; + if (!code->expr3->mold) expr3 = tmp; else @@ -5237,6 +5466,16 @@ else if (expr3_tmp != NULL_TREE && (VAR_P (expr3_tmp) ||!code->expr3->ref)) tmp = gfc_class_vptr_get (expr3_tmp); + else if (is_coarray && expr3 != NULL_TREE) + { + /* Get the ref to coarray's data. May be wrapped in a + NOP_EXPR. */ + tmp = POINTER_TYPE_P (TREE_TYPE (expr3)) ? TREE_OPERAND (expr3, 0) + : tmp; + /* Get to the base variable, i.e., strip _data.data. */ + tmp = TREE_OPERAND (TREE_OPERAND (tmp, 0), 0); + tmp = gfc_class_vptr_get (tmp); + } else { rhs = gfc_find_and_cut_at_last_class_ref (code->expr3); @@ -5310,6 +5549,71 @@ else expr3_esize = TYPE_SIZE_UNIT ( gfc_typenode_for_spec (&code->expr3->ts)); + + /* The routine gfc_trans_assignment () already implements all + techniques needed. Unfortunately we may have a temporary + variable for the source= expression here. When that is the + case convert this variable into a temporary gfc_expr of type + EXPR_VARIABLE and used it as rhs for the assignment. The + advantage is, that we get scalarizer support for free, + don't have to take care about scalar to array treatment and + will benefit of every enhancements gfc_trans_assignment () + gets. + Exclude variables since the following block does not handle + array sections. In any case, there is no harm in sending + variables to gfc_trans_assignment because there is no + evaluation of variables. */ + if (code->expr3->expr_type != EXPR_VARIABLE + && code->expr3->mold != 1 && expr3 != NULL_TREE + && DECL_P (expr3) && DECL_ARTIFICIAL (expr3)) + { + /* Build a temporary symtree and symbol. Do not add it to + the current namespace to prevent accidently modifying + a colliding symbol's as. */ + newsym = XCNEW (gfc_symtree); + /* The name of the symtree should be unique, because + gfc_create_var () took care about generating the + identifier. */ + newsym->name = gfc_get_string (IDENTIFIER_POINTER ( + DECL_NAME (expr3))); + newsym->n.sym = gfc_new_symbol (newsym->name, NULL); + /* The backend_decl is known. It is expr3, which is inserted + here. */ + newsym->n.sym->backend_decl = expr3; + e3rhs = gfc_get_expr (); + e3rhs->ts = code->expr3->ts; + e3rhs->rank = code->expr3->rank; + e3rhs->symtree = newsym; + /* Mark the symbol referenced or gfc_trans_assignment will + bug. */ + newsym->n.sym->attr.referenced = 1; + e3rhs->expr_type = EXPR_VARIABLE; + e3rhs->where = code->expr3->where; + /* Set the symbols type, upto it was BT_UNKNOWN. */ + newsym->n.sym->ts = e3rhs->ts; + /* Check whether the expr3 is array valued. */ + if (e3rhs->rank) + { + gfc_array_spec *arr; + arr = gfc_get_array_spec (); + arr->rank = e3rhs->rank; + arr->type = AS_DEFERRED; + /* Set the dimension and pointer attribute for arrays + to be on the safe side. */ + newsym->n.sym->attr.dimension = 1; + newsym->n.sym->attr.pointer = 1; + newsym->n.sym->as = arr; + gfc_add_full_array_ref (e3rhs, arr); + } + else if (POINTER_TYPE_P (TREE_TYPE (expr3))) + newsym->n.sym->attr.pointer = 1; + /* The string length is known to. Set it for char arrays. */ + if (e3rhs->ts.type == BT_CHARACTER) + newsym->n.sym->ts.u.cl->backend_decl = expr3_len; + gfc_commit_symbol (newsym->n.sym); + } + else + e3rhs = gfc_copy_expr (code->expr3); } gcc_assert (expr3_esize); expr3_esize = fold_convert (sizetype, expr3_esize); @@ -5335,6 +5639,7 @@ expr3_esize = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (se_sz.expr), tmp, se_sz.expr); + def_str_len = gfc_evaluate_now (se_sz.expr, &block); } } @@ -5386,6 +5691,17 @@ se.want_pointer = 1; se.descriptor_only = 1; + + if (expr->ts.type == BT_CHARACTER + && expr->ts.deferred + && TREE_CODE (expr->ts.u.cl->backend_decl) == VAR_DECL + && def_str_len != NULL_TREE) + { + tmp = expr->ts.u.cl->backend_decl; + gfc_add_modify (&block, tmp, + fold_convert (TREE_TYPE (tmp), def_str_len)); + } + gfc_conv_expr (&se, expr); if (expr->ts.type == BT_CHARACTER && expr->ts.deferred) /* se.string_length now stores the .string_length variable of expr @@ -5615,7 +5931,6 @@ { /* Initialization via SOURCE block (or static default initializer). */ - gfc_expr *rhs = gfc_copy_expr (code->expr3); if (expr3 != NULL_TREE && ((POINTER_TYPE_P (TREE_TYPE (expr3)) && TREE_CODE (expr3) != POINTER_PLUS_EXPR) @@ -5629,25 +5944,13 @@ tmp = gfc_copy_class_to_class (expr3, to, nelems, upoly_expr); } - else if (code->expr3->ts.type == BT_CHARACTER - && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))) - { - tmp = INDIRECT_REF_P (se.expr) ? - se.expr : - build_fold_indirect_ref_loc (input_location, - se.expr); - gfc_trans_string_copy (&block, al_len, tmp, - code->expr3->ts.kind, - expr3_len, expr3, - code->expr3->ts.kind); - tmp = NULL_TREE; - } else if (al->expr->ts.type == BT_CLASS) { gfc_actual_arglist *actual, *last_arg; gfc_expr *ppc; gfc_code *ppc_code; gfc_ref *ref, *dataref; + gfc_expr *rhs = e3rhs ? e3rhs : gfc_copy_expr (code->expr3); /* Do a polymorphic deep copy. */ actual = gfc_get_actual_arglist (); @@ -5759,6 +6062,8 @@ void_type_node, tmp, extcopy, stdcopy); } gfc_free_statements (ppc_code); + if (rhs != e3rhs) + gfc_free_expr (rhs); } else { @@ -5767,10 +6072,9 @@ int realloc_lhs = flag_realloc_lhs; flag_realloc_lhs = 0; tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr), - rhs, false, false); + e3rhs, false, false); flag_realloc_lhs = realloc_lhs; } - gfc_free_expr (rhs); gfc_add_expr_to_block (&block, tmp); } else if (code->expr3 && code->expr3->mold @@ -5788,6 +6092,15 @@ gfc_free_expr (expr); } // for-loop + if (e3rhs) + { + if (newsym) + { + gfc_free_symbol (newsym->n.sym); + XDELETE (newsym); + } + gfc_free_expr (e3rhs); + } /* STAT. */ if (code->expr1) { --- a/gcc/fortran/trans-stmt.h 2015-01-15 21:11:12.000000000 +0100 +++ b/gcc/fortran/trans-stmt.h 2016-02-16 15:44:29.787760247 +0100 @@ -55,6 +55,7 @@ tree gfc_trans_select (gfc_code *); tree gfc_trans_sync (gfc_code *, gfc_exec_op); tree gfc_trans_lock_unlock (gfc_code *, gfc_exec_op); +tree gfc_trans_event_post_wait (gfc_code *, gfc_exec_op); tree gfc_trans_forall (gfc_code *); tree gfc_trans_where (gfc_code *); tree gfc_trans_allocate (gfc_code *); --- a/gcc/fortran/trans-types.c 2015-11-24 21:40:10.000000000 +0100 +++ b/gcc/fortran/trans-types.c 2016-02-16 15:44:29.787760247 +0100 @@ -1,5 +1,5 @@ /* Backend support for Fortran 95 basic types and derived types. - Copyright (C) 2002-2015 Free Software Foundation, Inc. + Copyright (C) 2002-2016 Free Software Foundation, Inc. Contributed by Paul Brook and Steven Bosscher @@ -2383,6 +2383,11 @@ && derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)) return ptr_type_node; + if (flag_coarray != GFC_FCOARRAY_LIB + && derived->from_intmod == INTMOD_ISO_FORTRAN_ENV + && derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE) + return gfc_get_int_type (gfc_default_integer_kind); + if (derived && derived->attr.flavor == FL_PROCEDURE && derived->attr.generic) derived = gfc_find_dt_in_generic (derived); --- a/gcc/genpreds.c 2015-01-09 21:18:42.000000000 +0100 +++ b/gcc/genpreds.c 2016-02-16 15:23:33.706553265 +0100 @@ -640,12 +640,14 @@ const char *regclass; /* for register constraints */ rtx exp; /* for other constraints */ unsigned int lineno; /* line of definition */ - unsigned int is_register : 1; - unsigned int is_const_int : 1; - unsigned int is_const_dbl : 1; - unsigned int is_extra : 1; - unsigned int is_memory : 1; - unsigned int is_address : 1; + unsigned int is_register : 1; + unsigned int is_const_int : 1; + unsigned int is_const_dbl : 1; + unsigned int is_extra : 1; + unsigned int is_memory : 1; + unsigned int is_address : 1; + unsigned int maybe_allows_reg : 1; + unsigned int maybe_allows_mem : 1; }; /* Overview of all constraints beginning with a given letter. */ @@ -691,6 +693,9 @@ static unsigned int const_int_start, const_int_end; static unsigned int memory_start, memory_end; static unsigned int address_start, address_end; +static unsigned int maybe_allows_none_start, maybe_allows_none_end; +static unsigned int maybe_allows_reg_start, maybe_allows_reg_end; +static unsigned int maybe_allows_mem_start, maybe_allows_mem_end; /* Convert NAME, which contains angle brackets and/or underscores, to a string that can be used as part of a C identifier. The string @@ -711,6 +716,34 @@ return XOBFINISH (rtl_obstack, const char *); } +/* Return a bitmask, bit 1 if EXP maybe allows a REG/SUBREG, 2 if EXP + maybe allows a MEM. Bits should be clear only when we are sure it + will not allow a REG/SUBREG or a MEM. */ +static int +compute_maybe_allows (rtx exp) +{ + switch (GET_CODE (exp)) + { + case IF_THEN_ELSE: + /* Conservative answer is like IOR, of the THEN and ELSE branches. */ + return compute_maybe_allows (XEXP (exp, 1)) + | compute_maybe_allows (XEXP (exp, 2)); + case AND: + return compute_maybe_allows (XEXP (exp, 0)) + & compute_maybe_allows (XEXP (exp, 1)); + case IOR: + return compute_maybe_allows (XEXP (exp, 0)) + | compute_maybe_allows (XEXP (exp, 1)); + case MATCH_CODE: + if (*XSTR (exp, 1) == '\0') + return (strstr (XSTR (exp, 0), "reg") != NULL ? 1 : 0) + | (strstr (XSTR (exp, 0), "mem") != NULL ? 2 : 0); + /* FALLTHRU */ + default: + return 3; + } +} + /* Add one constraint, of any sort, to the tables. NAME is its name; REGCLASS is the register class, if any; EXP is the expression to test, if any; IS_MEMORY and IS_ADDRESS indicate memory and address @@ -866,6 +899,11 @@ c->is_extra = !(regclass || is_const_int || is_const_dbl); c->is_memory = is_memory; c->is_address = is_address; + int maybe_allows = 3; + if (exp) + maybe_allows = compute_maybe_allows (exp); + c->maybe_allows_reg = (maybe_allows & 1) != 0; + c->maybe_allows_mem = (maybe_allows & 2) != 0; c->next_this_letter = *slot; *slot = c; @@ -940,8 +978,30 @@ enum_order[next++] = c; address_end = next; + maybe_allows_none_start = next; + FOR_ALL_CONSTRAINTS (c) + if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address + && !c->maybe_allows_reg && !c->maybe_allows_mem) + enum_order[next++] = c; + maybe_allows_none_end = next; + + maybe_allows_reg_start = next; + FOR_ALL_CONSTRAINTS (c) + if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address + && c->maybe_allows_reg && !c->maybe_allows_mem) + enum_order[next++] = c; + maybe_allows_reg_end = next; + + maybe_allows_mem_start = next; + FOR_ALL_CONSTRAINTS (c) + if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address + && !c->maybe_allows_reg && c->maybe_allows_mem) + enum_order[next++] = c; + maybe_allows_mem_end = next; + FOR_ALL_CONSTRAINTS (c) - if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address) + if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address + && c->maybe_allows_reg && c->maybe_allows_mem) enum_order[next++] = c; gcc_assert (next == num_constraints); } @@ -1229,6 +1289,41 @@ "}\n\n", name); } +/* Write a definition for insn_extra_constraint_allows_reg_mem function. */ +static void +write_allows_reg_mem_function (void) +{ + printf ("static inline void\n" + "insn_extra_constraint_allows_reg_mem (enum constraint_num c,\n" + "\t\t\t\t bool *allows_reg, bool *allows_mem)\n" + "{\n"); + if (maybe_allows_none_start != maybe_allows_none_end) + printf (" if (c >= CONSTRAINT_%s && c <= CONSTRAINT_%s)\n" + " return;\n", + enum_order[maybe_allows_none_start]->c_name, + enum_order[maybe_allows_none_end - 1]->c_name); + if (maybe_allows_reg_start != maybe_allows_reg_end) + printf (" if (c >= CONSTRAINT_%s && c <= CONSTRAINT_%s)\n" + " {\n" + " *allows_reg = true;\n" + " return;\n" + " }\n", + enum_order[maybe_allows_reg_start]->c_name, + enum_order[maybe_allows_reg_end - 1]->c_name); + if (maybe_allows_mem_start != maybe_allows_mem_end) + printf (" if (c >= CONSTRAINT_%s && c <= CONSTRAINT_%s)\n" + " {\n" + " *allows_mem = true;\n" + " return;\n" + " }\n", + enum_order[maybe_allows_mem_start]->c_name, + enum_order[maybe_allows_mem_end - 1]->c_name); + printf (" (void) c;\n" + " *allows_reg = true;\n" + " *allows_mem = true;\n" + "}\n\n"); +} + /* VEC is a list of key/value pairs, with the keys being lower bounds of a range. Output a decision tree that handles the keys covered by [VEC[START], VEC[END]), returning FALLBACK for keys lower then VEC[START]'s. @@ -1326,6 +1421,7 @@ memory_start, memory_end); write_range_function ("insn_extra_address_constraint", address_start, address_end); + write_allows_reg_mem_function (); if (constraint_max_namelen > 1) { --- a/gcc/gimple.c 2015-02-04 21:28:49.000000000 +0100 +++ b/gcc/gimple.c 2016-02-16 15:43:57.774213147 +0100 @@ -1953,6 +1953,11 @@ && TYPE_OVERFLOW_TRAPS (t)), div)); + case GIMPLE_COND: + t = TREE_TYPE (gimple_cond_lhs (s)); + return operation_could_trap_p (gimple_cond_code (s), + FLOAT_TYPE_P (t), false, NULL_TREE); + default: break; } --- a/gcc/gimple-expr.c 2015-01-09 21:18:42.000000000 +0100 +++ b/gcc/gimple-expr.c 2016-02-16 15:42:03.476284633 +0100 @@ -387,6 +387,11 @@ TREE_USED (copy) = 1; DECL_SEEN_IN_BIND_EXPR_P (copy) = 1; DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var); + if (DECL_USER_ALIGN (var)) + { + DECL_ALIGN (copy) = DECL_ALIGN (var); + DECL_USER_ALIGN (copy) = 1; + } return copy; } --- a/gcc/gimple-ssa-strength-reduction.c 2015-01-15 14:28:42.000000000 +0100 +++ b/gcc/gimple-ssa-strength-reduction.c 2016-02-16 15:26:35.604094164 +0100 @@ -2267,7 +2267,7 @@ slsr_cand_t basis = lookup_cand (c->basis); int nargs = gimple_phi_num_args (from_phi); basic_block phi_bb = gimple_bb (from_phi); - slsr_cand_t phi_cand = base_cand_from_table (gimple_phi_result (from_phi)); + slsr_cand_t phi_cand = *stmt_cand_map->get (from_phi); phi_args.create (nargs); /* Process each argument of the existing phi that represents @@ -2376,7 +2376,7 @@ { unsigned i; int cost = 0; - slsr_cand_t phi_cand = base_cand_from_table (gimple_phi_result (phi)); + slsr_cand_t phi_cand = *stmt_cand_map->get (phi); /* If we work our way back to a phi that isn't dominated by the hidden basis, this isn't a candidate for replacement. Indicate this by @@ -2587,7 +2587,7 @@ record_phi_increments (slsr_cand_t basis, gimple phi) { unsigned i; - slsr_cand_t phi_cand = base_cand_from_table (gimple_phi_result (phi)); + slsr_cand_t phi_cand = *stmt_cand_map->get (phi); for (i = 0; i < gimple_phi_num_args (phi); i++) { @@ -2658,7 +2658,7 @@ unsigned i; int cost = 0; slsr_cand_t basis = lookup_cand (c->basis); - slsr_cand_t phi_cand = base_cand_from_table (gimple_phi_result (phi)); + slsr_cand_t phi_cand = *stmt_cand_map->get (phi); for (i = 0; i < gimple_phi_num_args (phi); i++) { @@ -3002,7 +3002,7 @@ { unsigned i; slsr_cand_t basis = lookup_cand (c->basis); - slsr_cand_t phi_cand = base_cand_from_table (gimple_phi_result (phi)); + slsr_cand_t phi_cand = *stmt_cand_map->get (phi); for (i = 0; i < gimple_phi_num_args (phi); i++) { @@ -3212,7 +3212,7 @@ { unsigned i; slsr_cand_t basis = lookup_cand (c->basis); - slsr_cand_t phi_cand = base_cand_from_table (gimple_phi_result (phi)); + slsr_cand_t phi_cand = *stmt_cand_map->get (phi); for (i = 0; i < gimple_phi_num_args (phi); i++) { --- a/gcc/gimplify.c 2015-09-10 09:41:34.000000000 +0200 +++ b/gcc/gimplify.c 2016-02-16 15:42:10.088395040 +0100 @@ -5208,12 +5208,38 @@ TREE_VALUE (link) = error_mark_node; tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p, is_gimple_lvalue, fb_lvalue | fb_mayfail); + if (tret != GS_ERROR) + { + /* Unlike output operands, memory inputs are not guaranteed + to be lvalues by the FE, and while the expressions are + marked addressable there, if it is e.g. a statement + expression, temporaries in it might not end up being + addressable. They might be already used in the IL and thus + it is too late to make them addressable now though. */ + tree x = TREE_VALUE (link); + while (handled_component_p (x)) + x = TREE_OPERAND (x, 0); + if (TREE_CODE (x) == MEM_REF + && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR) + x = TREE_OPERAND (TREE_OPERAND (x, 0), 0); + if ((TREE_CODE (x) == VAR_DECL + || TREE_CODE (x) == PARM_DECL + || TREE_CODE (x) == RESULT_DECL) + && !TREE_ADDRESSABLE (x) + && is_gimple_reg (x)) + { + warning_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), + input_location), 0, + "memory input %d is not directly addressable", + i); + prepare_gimple_addressable (&TREE_VALUE (link), pre_p); + } + } mark_addressable (TREE_VALUE (link)); if (tret == GS_ERROR) { - if (EXPR_HAS_LOCATION (TREE_VALUE (link))) - input_location = EXPR_LOCATION (TREE_VALUE (link)); - error ("memory input %d is not directly addressable", i); + error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location), + "memory input %d is not directly addressable", i); ret = tret; } } --- a/gcc/ifcvt.c 2015-11-19 09:53:52.000000000 +0100 +++ b/gcc/ifcvt.c 2016-02-16 15:42:01.325248748 +0100 @@ -2152,45 +2152,22 @@ Note that these rtx constants are known to be CONST_INT, and therefore imply integer comparisons. The one_cmpl case is more complicated, as we want to handle - only x < 0 ? ~x : x or x >= 0 ? ~x : x but not - x <= 0 ? ~x : x or x > 0 ? ~x : x, as the latter two - have different result for x == 0. */ + only x < 0 ? ~x : x or x >= 0 ? x : ~x to one_cmpl_abs (x) + and x < 0 ? x : ~x or x >= 0 ? ~x : x to ~one_cmpl_abs (x), + but not other cases (x > -1 is equivalent of x >= 0). */ if (c == constm1_rtx && GET_CODE (cond) == GT) - { - if (one_cmpl && negate) - return FALSE; - } + ; else if (c == const1_rtx && GET_CODE (cond) == LT) { - if (one_cmpl && !negate) + if (one_cmpl) return FALSE; } else if (c == CONST0_RTX (GET_MODE (b))) { - if (one_cmpl) - switch (GET_CODE (cond)) - { - case GT: - if (!negate) - return FALSE; - break; - case GE: - /* >= 0 is the same case as above > -1. */ - if (negate) - return FALSE; - break; - case LT: - if (negate) - return FALSE; - break; - case LE: - /* <= 0 is the same case as above < 1. */ - if (!negate) - return FALSE; - break; - default: - return FALSE; - } + if (one_cmpl + && GET_CODE (cond) != GE + && GET_CODE (cond) != LT) + return FALSE; } else return FALSE; @@ -3847,8 +3824,11 @@ return FALSE; /* If the conditional jump is more than just a conditional jump, then - we can not do if-conversion on this block. */ - if (! onlyjump_p (jump)) + we can not do if-conversion on this block. Give up for returnjump_p, + changing a conditional return followed by unconditional trap for + conditional trap followed by unconditional return is likely not + beneficial and harder to handle. */ + if (! onlyjump_p (jump) || returnjump_p (jump)) return FALSE; /* We must be comparing objects whose modes imply the size. */ --- a/gcc/ipa-cp.c 2015-04-06 17:58:37.000000000 +0200 +++ b/gcc/ipa-cp.c 2016-02-16 15:10:15.351360293 +0100 @@ -1787,6 +1787,18 @@ return ret; } +/* Return true if on the way cfrom CS->caller to the final (non-alias and + non-thunk) destination, the call passes through a thunk. */ + +static bool +call_passes_through_thunk_p (cgraph_edge *cs) +{ + cgraph_node *alias_or_thunk = cs->callee; + while (alias_or_thunk->alias) + alias_or_thunk = alias_or_thunk->get_alias_target (); + return alias_or_thunk->thunk.thunk_p; +} + /* Propagate constants from the caller to the callee of CS. INFO describes the caller. */ @@ -1795,7 +1807,7 @@ { struct ipa_node_params *callee_info; enum availability availability; - struct cgraph_node *callee, *alias_or_thunk; + cgraph_node *callee; struct ipa_edge_args *args; bool ret = false; int i, args_count, parms_count; @@ -1833,10 +1845,7 @@ /* If this call goes through a thunk we must not propagate to the first (0th) parameter. However, we might need to uncover a thunk from below a series of aliases first. */ - alias_or_thunk = cs->callee; - while (alias_or_thunk->alias) - alias_or_thunk = alias_or_thunk->get_alias_target (); - if (alias_or_thunk->thunk.thunk_p) + if (call_passes_through_thunk_p (cs)) { ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, 0)); @@ -3404,7 +3413,11 @@ struct ipa_jump_func *jump_func; tree t; - if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))) + if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) + || (i == 0 + && call_passes_through_thunk_p (cs)) + || (!cs->callee->instrumentation_clone + && cs->callee->function_symbol ()->instrumentation_clone)) { newval = NULL_TREE; break; --- a/gcc/ipa-devirt.c 2015-07-27 21:53:53.000000000 +0200 +++ b/gcc/ipa-devirt.c 2016-02-16 15:06:04.485336932 +0100 @@ -1536,6 +1536,7 @@ break; } case VOID_TYPE: + case NULLPTR_TYPE: break; default: --- a/gcc/ipa-icf.c 2015-11-23 14:58:40.000000000 +0100 +++ b/gcc/ipa-icf.c 2016-02-16 15:05:10.672319553 +0100 @@ -444,7 +444,7 @@ sem_function::param_used_p (unsigned int i) { if (ipa_node_params_sum == NULL) - return false; + return true; struct ipa_node_params *parms_info = IPA_NODE_REF (get_node ()); --- a/gcc/lra-remat.c 2015-11-06 18:33:01.000000000 +0100 +++ b/gcc/lra-remat.c 2016-02-16 15:33:47.218413468 +0100 @@ -112,6 +112,9 @@ /* Bitmap used for different calculations. */ static bitmap_head temp_bitmap; +/* Registers accessed via subreg_p. */ +static bitmap_head subreg_regs; + typedef struct cand *cand_t; typedef const struct cand *const_cand_t; @@ -418,30 +421,30 @@ return -1; /* First find a pseudo which can be rematerialized. */ for (reg = id->regs; reg != NULL; reg = reg->next) - /* True FRAME_POINTER_NEEDED might be because we can not follow - changing sp offsets, e.g. alloca is used. If the insn contains - stack pointer in such case, we can not rematerialize it as we - can not know sp offset at a rematerialization place. */ - if (reg->regno == STACK_POINTER_REGNUM && frame_pointer_needed) - return -1; - else if (reg->type == OP_OUT && ! reg->subreg_p - && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL) - { - /* We permits only one spilled reg. */ - if (found_reg != NULL) - return -1; - found_reg = reg; - } - /* IRA calculates conflicts separately for subregs of two words - pseudo. Even if the pseudo lives, e.g. one its subreg can be - used lately, another subreg hard register can be already used - for something else. In such case, it is not safe to - rematerialize the insn. */ - else if (reg->type == OP_IN && reg->subreg_p - && reg->regno >= FIRST_PSEUDO_REGISTER - && (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno)) - == 2 * UNITS_PER_WORD)) - return -1; + { + /* True FRAME_POINTER_NEEDED might be because we can not follow + changing sp offsets, e.g. alloca is used. If the insn contains + stack pointer in such case, we can not rematerialize it as we + can not know sp offset at a rematerialization place. */ + if (reg->regno == STACK_POINTER_REGNUM && frame_pointer_needed) + return -1; + else if (reg->type == OP_OUT && ! reg->subreg_p + && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL) + { + /* We permits only one spilled reg. */ + if (found_reg != NULL) + return -1; + found_reg = reg; + } + /* IRA calculates conflicts separately for subregs of two words + pseudo. Even if the pseudo lives, e.g. one its subreg can be + used lately, another subreg hard register can be already used + for something else. In such case, it is not safe to + rematerialize the insn. */ + if (reg->regno >= FIRST_PSEUDO_REGISTER + && bitmap_bit_p (&subreg_regs, reg->regno)) + return -1; + } if (found_reg == NULL) return -1; if (found_reg->regno < FIRST_PSEUDO_REGISTER) @@ -668,6 +671,9 @@ lra_dump_bitmap_with_title ("avout cands in BB", &get_remat_bb_data (bb)->avout_cands, bb->index); } + fprintf (lra_dump_file, "subreg regs:"); + dump_regset (&subreg_regs, lra_dump_file); + putc ('\n', lra_dump_file); } /* Free all BB data. */ @@ -692,21 +698,24 @@ -/* Update changed_regs and dead_regs of BB from INSN. */ +/* Update changed_regs, dead_regs, subreg_regs of BB from INSN. */ static void set_bb_regs (basic_block bb, rtx_insn *insn) { lra_insn_recog_data_t id = lra_get_insn_recog_data (insn); + remat_bb_data_t bb_info = get_remat_bb_data (bb); struct lra_insn_reg *reg; for (reg = id->regs; reg != NULL; reg = reg->next) - if (reg->type != OP_IN) - bitmap_set_bit (&get_remat_bb_data (bb)->changed_regs, reg->regno); - else - { - if (find_regno_note (insn, REG_DEAD, (unsigned) reg->regno) != NULL) - bitmap_set_bit (&get_remat_bb_data (bb)->dead_regs, reg->regno); - } + { + unsigned regno = reg->regno; + if (reg->type != OP_IN) + bitmap_set_bit (&bb_info->changed_regs, regno); + else if (find_regno_note (insn, REG_DEAD, regno) != NULL) + bitmap_set_bit (&bb_info->dead_regs, regno); + if (regno >= FIRST_PSEUDO_REGISTER && reg->subreg_p) + bitmap_set_bit (&subreg_regs, regno); + } if (CALL_P (insn)) for (int i = 0; i < call_used_regs_arr_len; i++) bitmap_set_bit (&get_remat_bb_data (bb)->dead_regs, @@ -722,7 +731,7 @@ FOR_EACH_BB_FN (bb, cfun) FOR_BB_INSNS (bb, insn) - if (INSN_P (insn)) + if (NONDEBUG_INSN_P (insn)) set_bb_regs (bb, insn); } @@ -1321,10 +1330,11 @@ if (call_used_regs[i]) call_used_regs_arr[call_used_regs_arr_len++] = i; initiate_cand_table (); - create_cands (); create_remat_bb_data (); bitmap_initialize (&temp_bitmap, ®_obstack); + bitmap_initialize (&subreg_regs, ®_obstack); calculate_local_reg_remat_bb_data (); + create_cands (); calculate_livein_cands (); calculate_gen_cands (); bitmap_initialize (&all_blocks, ®_obstack); @@ -1335,6 +1345,7 @@ result = do_remat (); all_cands.release (); bitmap_clear (&temp_bitmap); + bitmap_clear (&subreg_regs); finish_remat_bb_data (); finish_cand_table (); bitmap_clear (&all_blocks); --- a/gcc/match.pd 2015-06-03 09:39:06.000000000 +0200 +++ b/gcc/match.pd 2016-02-16 15:28:40.239506131 +0100 @@ -382,12 +382,15 @@ (bit_not (bit_not @0)) @0) +/* Disable on GENERIC because of PR68513. */ +#if GIMPLE /* (x & ~m) | (y & m) -> ((x ^ y) & m) ^ x */ (simplify (bit_ior:c (bit_and:c@3 @0 (bit_not @2)) (bit_and:c@4 @1 @2)) (if ((TREE_CODE (@3) != SSA_NAME || has_single_use (@3)) && (TREE_CODE (@4) != SSA_NAME || has_single_use (@4))) (bit_xor (bit_and (bit_xor @0 @1) @2) @0))) +#endif /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */ --- a/gcc/shrink-wrap.c 2015-01-15 14:28:42.000000000 +0100 +++ b/gcc/shrink-wrap.c 2016-02-16 15:42:08.881374875 +0100 @@ -79,6 +79,7 @@ #include "shrink-wrap.h" #include "regcprop.h" #include "rtl-iter.h" +#include "valtrack.h" #ifdef HAVE_simple_return @@ -191,7 +192,8 @@ move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn, const HARD_REG_SET uses, const HARD_REG_SET defs, - bool *split_p) + bool *split_p, + struct dead_debug_local *debug) { rtx set, src, dest; bitmap live_out, live_in, bb_uses, bb_defs; @@ -200,6 +202,8 @@ unsigned int end_sregno = FIRST_PSEUDO_REGISTER; basic_block next_block; edge live_edge; + rtx_insn *dinsn; + df_ref def; /* Look for a simple register assignment. We don't use single_set here because we can't deal with any CLOBBERs, USEs, or REG_UNUSED secondary @@ -344,6 +348,20 @@ move it as far as we can. */ do { + if (MAY_HAVE_DEBUG_INSNS) + { + FOR_BB_INSNS_REVERSE (bb, dinsn) + if (DEBUG_INSN_P (dinsn)) + { + df_ref use; + FOR_EACH_INSN_USE (use, dinsn) + if (refers_to_regno_p (dregno, end_dregno, + DF_REF_REG (use), (rtx *) NULL)) + dead_debug_add (debug, use, DF_REF_REGNO (use)); + } + else if (dinsn == insn) + break; + } live_out = df_get_live_out (bb); live_in = df_get_live_in (next_block); bb = next_block; @@ -426,6 +444,12 @@ SET_REGNO_REG_SET (bb_uses, i); } + /* Insert debug temps for dead REGs used in subsequent debug insns. */ + if (debug->used && !bitmap_empty_p (debug->used)) + FOR_EACH_INSN_DEF (def, insn) + dead_debug_insert_temp (debug, DF_REF_REGNO (def), insn, + DEBUG_TEMP_BEFORE_WITH_VALUE); + emit_insn_after (PATTERN (insn), bb_note (bb)); delete_insn (insn); return true; @@ -446,6 +470,8 @@ HARD_REG_SET uses, defs; df_ref def, use; bool split_p = false; + unsigned int i; + struct dead_debug_local debug; if (JUMP_P (BB_END (entry_block))) { @@ -456,19 +482,22 @@ copyprop_hardreg_forward_bb_without_debug_insn (entry_block); } + dead_debug_local_init (&debug, NULL, NULL); CLEAR_HARD_REG_SET (uses); CLEAR_HARD_REG_SET (defs); + FOR_BB_INSNS_REVERSE_SAFE (entry_block, insn, curr) if (NONDEBUG_INSN_P (insn) && !move_insn_for_shrink_wrap (entry_block, insn, uses, defs, - &split_p)) + &split_p, &debug)) { /* Add all defined registers to DEFs. */ FOR_EACH_INSN_DEF (def, insn) { x = DF_REF_REG (def); if (REG_P (x) && HARD_REGISTER_P (x)) - SET_HARD_REG_BIT (defs, REGNO (x)); + for (i = REGNO (x); i < END_REGNO (x); i++) + SET_HARD_REG_BIT (defs, i); } /* Add all used registers to USESs. */ @@ -476,9 +505,12 @@ { x = DF_REF_REG (use); if (REG_P (x) && HARD_REGISTER_P (x)) - SET_HARD_REG_BIT (uses, REGNO (x)); + for (i = REGNO (x); i < END_REGNO (x); i++) + SET_HARD_REG_BIT (uses, i); } } + + dead_debug_local_finish (&debug, NULL); } /* Create a copy of BB instructions and insert at BEFORE. Redirect --- a/gcc/stmt.c 2015-02-13 15:42:30.000000000 +0100 +++ b/gcc/stmt.c 2016-02-16 15:23:33.706553265 +0100 @@ -342,13 +342,7 @@ else if (insn_extra_memory_constraint (cn)) *allows_mem = true; else - { - /* Otherwise we can't assume anything about the nature of - the constraint except that it isn't purely registers. - Treat it like "g" and hope for the best. */ - *allows_reg = true; - *allows_mem = true; - } + insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem); break; } @@ -465,13 +459,7 @@ else if (insn_extra_memory_constraint (cn)) *allows_mem = true; else - { - /* Otherwise we can't assume anything about the nature of - the constraint except that it isn't purely registers. - Treat it like "g" and hope for the best. */ - *allows_reg = true; - *allows_mem = true; - } + insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem); break; } --- a/gcc/tree.c 2015-10-27 17:55:03.000000000 +0100 +++ b/gcc/tree.c 2016-02-16 15:15:16.624657302 +0100 @@ -1221,11 +1221,9 @@ get_int_cst_ext_nunits (tree type, const wide_int &cst) { gcc_checking_assert (cst.get_precision () == TYPE_PRECISION (type)); - /* We need an extra zero HWI if CST is an unsigned integer with its - upper bit set, and if CST occupies a whole number of HWIs. */ - if (TYPE_UNSIGNED (type) - && wi::neg_p (cst) - && (cst.get_precision () % HOST_BITS_PER_WIDE_INT) == 0) + /* We need extra HWIs if CST is an unsigned integer with its + upper bit set. */ + if (TYPE_UNSIGNED (type) && wi::neg_p (cst)) return cst.get_precision () / HOST_BITS_PER_WIDE_INT + 1; return cst.get_len (); } @@ -1242,7 +1240,8 @@ if (len < ext_len) { --ext_len; - TREE_INT_CST_ELT (nt, ext_len) = 0; + TREE_INT_CST_ELT (nt, ext_len) + = zext_hwi (-1, cst.get_precision () % HOST_BITS_PER_WIDE_INT); for (unsigned int i = len; i < ext_len; ++i) TREE_INT_CST_ELT (nt, i) = -1; } --- a/gcc/tree-chrec.c 2015-03-20 13:39:32.000000000 +0100 +++ b/gcc/tree-chrec.c 2016-02-16 15:43:57.776213181 +0100 @@ -746,12 +746,12 @@ /* There is no evolution in this loop. */ return initial_condition (chrec); + else if (flow_loop_nested_p (loop, chloop)) + return hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), + loop_num); + else - { - gcc_assert (flow_loop_nested_p (loop, chloop)); - return hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), - loop_num); - } + return chrec_dont_know; default: return chrec; --- a/gcc/tree-data-ref.c 2015-06-03 09:39:06.000000000 +0200 +++ b/gcc/tree-data-ref.c 2016-02-16 15:31:27.080721566 +0100 @@ -1534,13 +1534,14 @@ /* The case where the references are exactly the same. */ if (operand_equal_p (DR_REF (a), DR_REF (b), 0)) { - if (loop_nest.exists () - && !object_address_invariant_in_loop_p (loop_nest[0], - DR_BASE_OBJECT (a))) - { - DDR_ARE_DEPENDENT (res) = chrec_dont_know; - return res; - } + if ((loop_nest.exists () + && !object_address_invariant_in_loop_p (loop_nest[0], + DR_BASE_OBJECT (a))) + || DR_NUM_DIMENSIONS (a) == 0) + { + DDR_ARE_DEPENDENT (res) = chrec_dont_know; + return res; + } DDR_AFFINE_P (res) = true; DDR_ARE_DEPENDENT (res) = NULL_TREE; DDR_SUBSCRIPTS (res).create (DR_NUM_DIMENSIONS (a)); @@ -1572,9 +1573,9 @@ /* If the base of the object is not invariant in the loop nest, we cannot analyze it. TODO -- in fact, it would suffice to record that there may be arbitrary dependences in the loops where the base object varies. */ - if (loop_nest.exists () - && !object_address_invariant_in_loop_p (loop_nest[0], - DR_BASE_OBJECT (a))) + if ((loop_nest.exists () + && !object_address_invariant_in_loop_p (loop_nest[0], DR_BASE_OBJECT (a))) + || DR_NUM_DIMENSIONS (a) == 0) { DDR_ARE_DEPENDENT (res) = chrec_dont_know; return res; --- a/gcc/tree-parloops.c 2015-03-21 11:14:10.000000000 +0100 +++ b/gcc/tree-parloops.c 2016-02-16 15:30:32.881678443 +0100 @@ -741,6 +741,7 @@ } else if (gimple_clobber_p (stmt)) { + unlink_stmt_vdef (stmt); stmt = gimple_build_nop (); gsi_replace (gsi, stmt, false); dta.changed = true; --- a/gcc/tree-sra.c 2015-10-27 13:23:24.000000000 +0100 +++ b/gcc/tree-sra.c 2016-02-16 15:33:02.984564516 +0100 @@ -2329,7 +2329,7 @@ if (covered_to < limit) hole = true; - if (scalar) + if (scalar || !allow_replacements) root->grp_total_scalarization = 0; } --- a/gcc/tree-ssa.c 2015-02-06 15:37:59.000000000 +0100 +++ b/gcc/tree-ssa.c 2016-02-16 15:43:57.777213198 +0100 @@ -1448,7 +1448,8 @@ tree lhs = gimple_get_lhs (stmt); if (lhs && TREE_CODE (lhs) != SSA_NAME - && non_rewritable_lvalue_p (lhs)) + && ((code == GIMPLE_CALL && ! DECL_P (lhs)) + || non_rewritable_lvalue_p (lhs))) { decl = get_base_address (lhs); if (DECL_P (decl)) --- a/gcc/tree-ssa-loop-ivcanon.c 2015-06-22 16:12:24.000000000 +0200 +++ b/gcc/tree-ssa-loop-ivcanon.c 2016-02-16 15:43:57.776213181 +0100 @@ -1237,7 +1237,9 @@ tree result = gimple_phi_result (phi); tree arg = gimple_phi_arg_def (phi, 0); - if (gimple_phi_num_args (phi) == 1 && TREE_CODE (arg) == INTEGER_CST) + if (! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (result) + && gimple_phi_num_args (phi) == 1 + && TREE_CODE (arg) == INTEGER_CST) { propagate_into_all_uses (result, arg); gsi_remove (&gsi, true); --- a/gcc/tree-ssa-math-opts.c 2015-08-11 09:58:07.000000000 +0200 +++ b/gcc/tree-ssa-math-opts.c 2016-02-16 15:43:57.777213198 +0100 @@ -2141,6 +2141,8 @@ static gimple find_bswap_or_nop (gimple stmt, struct symbolic_number *n, bool *bswap) { + unsigned rsize; + uint64_t tmpn, mask; /* The number which the find_bswap_or_nop_1 result should match in order to have a full byte swap. The number is shifted to the right according to the size of the symbolic number before using it. */ @@ -2164,24 +2166,38 @@ /* Find real size of result (highest non-zero byte). */ if (n->base_addr) - { - int rsize; - uint64_t tmpn; - - for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++); - n->range = rsize; - } + for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++); + else + rsize = n->range; - /* Zero out the extra bits of N and CMP*. */ + /* Zero out the bits corresponding to untouched bytes in original gimple + expression. */ if (n->range < (int) sizeof (int64_t)) { - uint64_t mask; - mask = ((uint64_t) 1 << (n->range * BITS_PER_MARKER)) - 1; cmpxchg >>= (64 / BITS_PER_MARKER - n->range) * BITS_PER_MARKER; cmpnop &= mask; } + /* Zero out the bits corresponding to unused bytes in the result of the + gimple expression. */ + if (rsize < n->range) + { + if (BYTES_BIG_ENDIAN) + { + mask = ((uint64_t) 1 << (rsize * BITS_PER_MARKER)) - 1; + cmpxchg &= mask; + cmpnop >>= (n->range - rsize) * BITS_PER_MARKER; + } + else + { + mask = ((uint64_t) 1 << (rsize * BITS_PER_MARKER)) - 1; + cmpxchg >>= (n->range - rsize) * BITS_PER_MARKER; + cmpnop &= mask; + } + n->range = rsize; + } + /* A complete byte swap should make the symbolic number to start with the largest digit in the highest order byte. Unchanged symbolic number indicates a read with same endianness as target architecture. */ @@ -2297,6 +2313,8 @@ /* Move cur_stmt just before one of the load of the original to ensure it has the same VUSE. See PR61517 for what could go wrong. */ + if (gimple_bb (cur_stmt) != gimple_bb (src_stmt)) + reset_flow_sensitive_info (gimple_assign_lhs (cur_stmt)); gsi_move_before (&gsi, &gsi_ins); gsi = gsi_for_stmt (cur_stmt); --- a/gcc/tree-ssa-reassoc.c 2015-11-18 11:31:51.000000000 +0100 +++ b/gcc/tree-ssa-reassoc.c 2016-02-16 15:03:33.024469457 +0100 @@ -3286,7 +3286,7 @@ any_changes = optimize_range_tests (ERROR_MARK, &ops); if (any_changes) { - unsigned int idx; + unsigned int idx, max_idx = 0; /* update_ops relies on has_single_use predicates returning the same values as it did during get_ops earlier. Additionally it never removes statements, only adds new ones and it should walk @@ -3302,6 +3302,7 @@ { tree new_op; + max_idx = idx; stmt = last_stmt (bb); new_op = update_ops (bbinfo[idx].op, (enum tree_code) @@ -3371,6 +3372,10 @@ && ops[bbinfo[idx].first_idx]->op != NULL_TREE) { gcond *cond_stmt = as_a (last_stmt (bb)); + + if (idx > max_idx) + max_idx = idx; + if (integer_zerop (ops[bbinfo[idx].first_idx]->op)) gimple_cond_make_false (cond_stmt); else if (integer_onep (ops[bbinfo[idx].first_idx]->op)) @@ -3387,6 +3392,17 @@ if (bb == first_bb) break; } + + /* The above changes could result in basic blocks after the first + modified one, up to and including last_bb, to be executed even if + they would not be in the original program. If the value ranges of + assignment lhs' in those bbs were dependent on the conditions + guarding those basic blocks which now can change, the VRs might + be incorrect. As no_side_effect_bb should ensure those SSA_NAMEs + are only used within the same bb, it should be not a big deal if + we just reset all the VRs in those bbs. See PR68671. */ + for (bb = last_bb, idx = 0; idx < max_idx; bb = single_pred (bb), idx++) + reset_flow_sensitive_info_in_bb (bb); } } --- a/gcc/tree-ssa-threadupdate.c 2015-03-25 23:49:47.000000000 +0100 +++ b/gcc/tree-ssa-threadupdate.c 2016-02-16 15:28:13.647992332 +0100 @@ -254,6 +254,11 @@ /* Blocks duplicated for the thread. */ bitmap duplicate_blocks; + + /* When we have multiple paths through a joiner which reach different + final destinations, then we may need to correct for potential + profile insanities. */ + bool need_profile_correction; }; /* Passes which use the jump threading code register jump threading @@ -827,7 +832,8 @@ So ensure that this path's path_out_count is at least the difference between elast->count and nonpath_count. Otherwise the edge counts after threading will not be sane. */ - if (has_joiner && path_out_count < elast->count - nonpath_count) + if (local_info->need_profile_correction + && has_joiner && path_out_count < elast->count - nonpath_count) { path_out_count = elast->count - nonpath_count; /* But neither can we go above the minimum count along the path @@ -1496,6 +1502,7 @@ ssa_local_info_t local_info; local_info.duplicate_blocks = BITMAP_ALLOC (NULL); + local_info.need_profile_correction = false; /* To avoid scanning a linear array for the element we need we instead use a hash table. For normal code there should be no noticeable @@ -1506,6 +1513,7 @@ /* Record each unique threaded destination into a hash table for efficient lookups. */ + edge last = NULL; FOR_EACH_EDGE (e, ei, bb->preds) { if (e->aux == NULL) @@ -1559,6 +1567,17 @@ /* Insert the outgoing edge into the hash table if it is not already in the hash table. */ lookup_redirection_data (e, INSERT); + + /* When we have thread paths through a common joiner with different + final destinations, then we may need corrections to deal with + profile insanities. See the big comment before compute_path_counts. */ + if ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK) + { + if (!last) + last = e2; + else if (e2 != last) + local_info.need_profile_correction = true; + } } /* We do not update dominance info. */ --- a/gcc/tree-ssa-uninit.c 2015-09-09 19:14:29.000000000 +0200 +++ b/gcc/tree-ssa-uninit.c 2016-02-16 15:25:13.776504748 +0100 @@ -1118,14 +1118,16 @@ edge opnd_edge; unsigned uninit_opnds2 = compute_uninit_opnds_pos (opnd_def_phi); - gcc_assert (!MASK_EMPTY (uninit_opnds2)); - opnd_edge = gimple_phi_arg_edge (phi, i); - if (!is_use_properly_guarded (phi, - opnd_edge->src, - opnd_def_phi, - uninit_opnds2, - visited_phis)) - return false; + if (!MASK_EMPTY (uninit_opnds2)) + { + opnd_edge = gimple_phi_arg_edge (phi, i); + if (!is_use_properly_guarded (phi, + opnd_edge->src, + opnd_def_phi, + uninit_opnds2, + visited_phis)) + return false; + } } else return false; --- a/gcc/tree-vrp.c 2015-04-27 14:21:17.000000000 +0200 +++ b/gcc/tree-vrp.c 2016-02-16 15:42:05.696321686 +0100 @@ -9534,7 +9534,8 @@ innerop = gimple_assign_rhs1 (def_stmt); if (TREE_CODE (innerop) == SSA_NAME - && !POINTER_TYPE_P (TREE_TYPE (innerop))) + && !POINTER_TYPE_P (TREE_TYPE (innerop)) + && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)) { value_range_t *vr = get_value_range (innerop); @@ -9565,8 +9566,8 @@ else location = gimple_location (stmt); warning_at (location, OPT_Wstrict_overflow, - "assuming signed overflow does not occur when " - "simplifying conditional"); + "assuming signed overflow does not occur when " + "simplifying conditional"); } tree newconst = fold_convert (TREE_TYPE (innerop), op1); --- a/gcc/ubsan.c 2015-05-04 21:53:35.000000000 +0200 +++ b/gcc/ubsan.c 2016-02-16 15:42:02.435267264 +0100 @@ -1611,6 +1611,7 @@ fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); else { + initialize_sanitizer_builtins (); /* Create the __ubsan_handle_float_cast_overflow fn call. */ tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0, NULL, ubsan_type_descriptor (expr_type), --- a/gcc/varasm.c 2015-10-20 11:50:58.000000000 +0200 +++ b/gcc/varasm.c 2016-02-16 15:36:55.475350695 +0100 @@ -1434,6 +1434,9 @@ specifications. */ SET_DECL_ASSEMBLER_NAME (decl, NULL_TREE); DECL_HARD_REGISTER (decl) = 0; + /* Also avoid SSA inconsistencies by pretending this is an external + decl now. */ + DECL_EXTERNAL (decl) = 1; return; } /* Now handle ordinary static variables and functions (in memory). --- a/gcc/var-tracking.c 2015-03-26 14:19:00.000000000 +0100 +++ b/gcc/var-tracking.c 2016-02-16 15:09:41.212623196 +0100 @@ -5833,11 +5833,6 @@ return; } ret = simplify_gen_binary (code, GET_MODE (val), val, arg); - if (ret == val) - /* Ensure ret isn't VALUE itself (which can happen e.g. for - (plus (reg1) (reg2)) when reg2 is known to be 0), as that - breaks a lot of routines during var-tracking. */ - ret = gen_rtx_fmt_ee (PLUS, GET_MODE (val), val, const0_rtx); break; default: gcc_unreachable (); --- a/gcc/wide-int.cc 2015-10-17 05:55:03.000000000 +0200 +++ b/gcc/wide-int.cc 2016-02-16 15:42:14.394467025 +0100 @@ -1808,15 +1808,32 @@ { unsigned HOST_WIDE_INT o0 = dividend.to_uhwi (); unsigned HOST_WIDE_INT o1 = divisor.to_uhwi (); + unsigned int quotient_len = 1; if (quotient) - quotient[0] = o0 / o1; + { + quotient[0] = o0 / o1; + if (o1 == 1 + && (HOST_WIDE_INT) o0 < 0 + && dividend_prec > HOST_BITS_PER_WIDE_INT) + { + quotient[1] = 0; + quotient_len = 2; + } + } if (remainder) { remainder[0] = o0 % o1; - *remainder_len = 1; + if ((HOST_WIDE_INT) remainder[0] < 0 + && dividend_prec > HOST_BITS_PER_WIDE_INT) + { + remainder[1] = 0; + *remainder_len = 2; + } + else + *remainder_len = 1; } - return 1; + return quotient_len; } /* Make the divisor and dividend positive and remember what we --- a/gcc/wide-int.h 2015-10-19 21:44:58.000000000 +0200 +++ b/gcc/wide-int.h 2016-02-16 15:42:12.511435538 +0100 @@ -2892,7 +2892,9 @@ For variable-precision integers like wide_int, handle HWI and sub-HWI integers inline. */ if (STATIC_CONSTANT_P (xi.precision > HOST_BITS_PER_WIDE_INT) - ? xi.len == 1 && xi.val[0] >= 0 + ? (shift < HOST_BITS_PER_WIDE_INT + && xi.len == 1 + && xi.val[0] >= 0) : xi.precision <= HOST_BITS_PER_WIDE_INT) { val[0] = xi.to_uhwi () >> shift; --- a/libcpp/files.c 2015-11-19 09:28:43.000000000 +0100 +++ b/libcpp/files.c 2016-02-16 15:42:13.466451505 +0100 @@ -522,7 +522,10 @@ return entry->u.file; file = make_cpp_file (pfile, start_dir, fname); - file->implicit_preinclude = implicit_preinclude; + file->implicit_preinclude + = (implicit_preinclude + || (pfile->buffer + && pfile->buffer->file->implicit_preinclude)); /* Try each path in the include chain. */ for (; !fake ;) --- a/libgcc/config/i386/morestack.S 2015-01-05 13:33:28.000000000 +0100 +++ b/libgcc/config/i386/morestack.S 2016-02-16 15:37:28.955863253 +0100 @@ -732,6 +732,7 @@ leal -16000(%esp),%eax # We should have at least 16K. movl %eax,%gs:0x30 + subl $4,%esp # Align stack. pushl $16000 pushl %esp #ifdef __PIC__ @@ -739,13 +740,14 @@ #else call __generic_morestack_set_initial_sp #endif - addl $8,%esp + addl $12,%esp ret #else /* defined(__x86_64__) */ leaq -16000(%rsp),%rax # We should have at least 16K. X86_64_SAVE_NEW_STACK_BOUNDARY (ax) + subq $8,%rsp # Align stack. movq %rsp,%rdi movq $16000,%rsi #ifdef __PIC__ @@ -753,6 +755,7 @@ #else call __generic_morestack_set_initial_sp #endif + addq $8,%rsp ret #endif /* defined(__x86_64__) */ --- a/libgfortran/caf/libcaf.h 2015-03-10 18:58:01.000000000 +0100 +++ b/libgfortran/caf/libcaf.h 2016-02-16 15:44:29.789760281 +0100 @@ -57,7 +57,9 @@ CAF_REGTYPE_COARRAY_ALLOC, CAF_REGTYPE_LOCK_STATIC, CAF_REGTYPE_LOCK_ALLOC, - CAF_REGTYPE_CRITICAL + CAF_REGTYPE_CRITICAL, + CAF_REGTYPE_EVENT_STATIC, + CAF_REGTYPE_EVENT_ALLOC } caf_register_t; @@ -133,5 +135,8 @@ void _gfortran_caf_lock (caf_token_t, size_t, int, int *, int *, char *, int); void _gfortran_caf_unlock (caf_token_t, size_t, int, int *, char *, int); +void _gfortran_caf_event_post (caf_token_t, size_t, int, int *, char *, int); +void _gfortran_caf_event_wait (caf_token_t, size_t, int, int *, char *, int); +void _gfortran_caf_event_query (caf_token_t, size_t, int, int *, int *); #endif /* LIBCAF_H */ --- a/libgfortran/caf/single.c 2015-03-11 22:42:56.000000000 +0100 +++ b/libgfortran/caf/single.c 2016-02-16 15:44:29.789760281 +0100 @@ -101,7 +101,8 @@ void *local; if (type == CAF_REGTYPE_LOCK_STATIC || type == CAF_REGTYPE_LOCK_ALLOC - || type == CAF_REGTYPE_CRITICAL) + || type == CAF_REGTYPE_CRITICAL || type == CAF_REGTYPE_EVENT_STATIC + || type == CAF_REGTYPE_EVENT_ALLOC) local = calloc (size, sizeof (bool)); else local = malloc (size); @@ -133,7 +134,8 @@ *stat = 0; if (type == CAF_REGTYPE_COARRAY_STATIC || type == CAF_REGTYPE_LOCK_STATIC - || type == CAF_REGTYPE_CRITICAL) + || type == CAF_REGTYPE_CRITICAL || type == CAF_REGTYPE_EVENT_STATIC + || type == CAF_REGTYPE_EVENT_ALLOC) { caf_static_t *tmp = malloc (sizeof (caf_static_t)); tmp->prev = caf_static_list; @@ -1071,6 +1073,45 @@ *stat = 0; } +void +_gfortran_caf_event_post (caf_token_t token, size_t index, + int image_index __attribute__ ((unused)), + int *stat, char *errmsg __attribute__ ((unused)), + int errmsg_len __attribute__ ((unused))) +{ + uint32_t value = 1; + uint32_t *event = (uint32_t *) ((char *) TOKEN (token) + index*sizeof(uint32_t)); + __atomic_fetch_add (event, (uint32_t) value, __ATOMIC_RELAXED); + + if(stat) + *stat = 0; +} + +void +_gfortran_caf_event_wait (caf_token_t token, size_t index, + int until_count, int *stat, + char *errmsg __attribute__ ((unused)), + int errmsg_len __attribute__ ((unused))) +{ + uint32_t *event = (uint32_t *) ((char *) TOKEN (token) + index*sizeof(uint32_t)); + uint32_t value = (uint32_t)-until_count; + __atomic_fetch_add (event, (uint32_t) value, __ATOMIC_RELAXED); + + if(stat) + *stat = 0; +} + +void +_gfortran_caf_event_query (caf_token_t token, size_t index, + int image_index __attribute__ ((unused)), + int *count, int *stat) +{ + uint32_t *event = (uint32_t *) ((char *) TOKEN (token) + index*sizeof(uint32_t)); + __atomic_load (event, (uint32_t *) count, __ATOMIC_RELAXED); + + if(stat) + *stat = 0; +} void _gfortran_caf_lock (caf_token_t token, size_t index, --- a/libgfortran/io/format.c 2015-11-07 19:13:17.000000000 +0100 +++ b/libgfortran/io/format.c 2016-02-16 15:18:46.431886288 +0100 @@ -1171,26 +1171,6 @@ *p++ = '^'; *p = '\0'; - /* Cleanup any left over memory allocations before calling generate - error. */ - if (is_internal_unit (dtp)) - { - if (dtp->format != NULL) - { - free (dtp->format); - dtp->format = NULL; - } - - /* Leave these alone if IOSTAT was given because execution will - return from generate error in those cases. */ - if (!(dtp->common.flags & IOPARM_HAS_IOSTAT)) - { - free (dtp->u.p.fmt); - free_format_hash_table (dtp->u.p.current_unit); - free_internal_unit (dtp); - } - } - generate_error (&dtp->common, LIBERROR_FORMAT, buffer); } --- a/libgfortran/io/list_read.c 2015-02-07 16:13:15.000000000 +0100 +++ b/libgfortran/io/list_read.c 2016-02-16 15:45:10.693463219 +0100 @@ -58,7 +58,8 @@ /* This macro assumes that we're operating on a variable. */ #define is_separator(c) (c == '/' || c == ',' || c == '\n' || c == ' ' \ - || c == '\t' || c == '\r' || c == ';') + || c == '\t' || c == '\r' || c == ';' || \ + (dtp->u.p.namelist_mode && c == '!')) /* Maximum repeat count. Less than ten times the maximum signed int32. */ @@ -75,7 +76,7 @@ /* Worker function to save a default KIND=1 character to a string buffer, enlarging it as necessary. */ - + static void push_char_default (st_parameter_dt *dtp, int c) { @@ -92,13 +93,8 @@ if (dtp->u.p.saved_used >= dtp->u.p.saved_length) { dtp->u.p.saved_length = 2 * dtp->u.p.saved_length; - dtp->u.p.saved_string = + dtp->u.p.saved_string = xrealloc (dtp->u.p.saved_string, dtp->u.p.saved_length); - - // Also this should not be necessary. - memset (dtp->u.p.saved_string + dtp->u.p.saved_used, 0, - dtp->u.p.saved_length - dtp->u.p.saved_used); - } dtp->u.p.saved_string[dtp->u.p.saved_used++] = (char) c; @@ -107,11 +103,10 @@ /* Worker function to save a KIND=4 character to a string buffer, enlarging the buffer as necessary. */ - static void push_char4 (st_parameter_dt *dtp, int c) { - gfc_char4_t *new, *p = (gfc_char4_t *) dtp->u.p.saved_string; + gfc_char4_t *p = (gfc_char4_t *) dtp->u.p.saved_string; if (p == NULL) { @@ -125,9 +120,6 @@ { dtp->u.p.saved_length = 2 * dtp->u.p.saved_length; p = xrealloc (p, dtp->u.p.saved_length * sizeof (gfc_char4_t)); - - memset4 (new + dtp->u.p.saved_used, 0, - dtp->u.p.saved_length - dtp->u.p.saved_used); } p[dtp->u.p.saved_used++] = c; @@ -168,7 +160,7 @@ /* Unget saves the last character so when reading the next character, we need to check to see if there is a character waiting. Similar, if the line buffer is being used to read_logical, check it too. */ - + static int check_buffers (st_parameter_dt *dtp) { @@ -200,7 +192,7 @@ dtp->u.p.line_buffer_pos = 0; dtp->u.p.line_buffer_enabled = 0; } - + done: dtp->u.p.at_eol = (c == '\n' || c == EOF); return c; @@ -254,7 +246,7 @@ record = next_array_record (dtp, dtp->u.p.current_unit->ls, &finished); - /* Check for "end-of-file" condition. */ + /* Check for "end-of-file" condition. */ if (finished) { dtp->u.p.at_eof = 1; @@ -289,17 +281,17 @@ if (is_array_io (dtp)) { - /* Check whether we hit EOF. */ + /* Check whether we hit EOF. */ if (unlikely (length == 0)) { generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL); return '\0'; - } + } dtp->u.p.current_unit->bytes_left--; } else { - if (dtp->u.p.at_eof) + if (dtp->u.p.at_eof) return EOF; if (length == 0) { @@ -316,7 +308,7 @@ /* Worker function for UTF encoded files. */ static int -next_char_utf8 (st_parameter_dt *dtp) +next_char_utf8 (st_parameter_dt *dtp) { static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 }; static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; @@ -336,7 +328,7 @@ if ((c & ~masks[nb-1]) == patns[nb-1]) goto found; goto invalid; - + found: c = (c & masks[nb-1]); @@ -363,7 +355,7 @@ utf_done: dtp->u.p.at_eol = (c == '\n' || c == (gfc_char4_t) EOF); return (int) c; - + invalid: generate_error (&dtp->common, LIBERROR_READ_VALUE, "Invalid UTF-8 encoding"); return (gfc_char4_t) '?'; @@ -457,7 +449,7 @@ separator, we stop reading. If there are more input items, we continue reading the separator with finish_separator() which takes care of the fact that we may or may not have seen a comma as part - of the separator. + of the separator. Returns 0 for success, and non-zero error code otherwise. */ @@ -521,12 +513,12 @@ break; case '!': + /* Eat a namelist comment. */ if (dtp->u.p.namelist_mode) - { /* Eat a namelist comment. */ + { err = eat_line (dtp); if (err) return err; - break; } @@ -786,7 +778,7 @@ /* To read a logical we have to look ahead in the input stream to make sure - there is not an equal sign indicating a variable name. To do this we use + there is not an equal sign indicating a variable name. To do this we use line_buffer to point to a temporary buffer, pushing characters there for possible later reading. */ @@ -852,6 +844,10 @@ break; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad_logical; + CASE_SEPARATORS: case EOF: unget_char (dtp, c); @@ -900,7 +896,7 @@ goto logical_done; } } - + l_push_char (dtp, c); if (c == '=') { @@ -909,7 +905,7 @@ dtp->u.p.line_buffer_pos = 0; return; } - + } bad_logical: @@ -971,6 +967,10 @@ goto bad_integer; goto get_integer; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad_integer; + CASE_SEPARATORS: /* Single null. */ unget_char (dtp, c); eat_separator (dtp); @@ -999,6 +999,10 @@ push_char (dtp, '\0'); goto repeat; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad_integer; + CASE_SEPARATORS: /* Not a repeat count. */ case EOF: goto done; @@ -1021,6 +1025,10 @@ CASE_DIGITS: break; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad_integer; + CASE_SEPARATORS: unget_char (dtp, c); eat_separator (dtp); @@ -1049,6 +1057,10 @@ push_char (dtp, c); break; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad_integer; + CASE_SEPARATORS: case EOF: goto done; @@ -1063,7 +1075,7 @@ if (nml_bad_return (dtp, c)) return; - free_saved (dtp); + free_saved (dtp); if (c == EOF) { free_line (dtp); @@ -1128,21 +1140,6 @@ default: if (dtp->u.p.namelist_mode) { - if (dtp->u.p.current_unit->delim_status == DELIM_NONE) - { - /* No delimiters so finish reading the string now. */ - int i; - push_char (dtp, c); - for (i = dtp->u.p.ionml->string_length; i > 1; i--) - { - if ((c = next_char (dtp)) == EOF) - goto done_eof; - push_char (dtp, c); - } - dtp->u.p.saved_type = BT_CHARACTER; - free_line (dtp); - return; - } unget_char (dtp, c); return; } @@ -1216,10 +1213,10 @@ push_char (dtp, c); break; } - + /* See if we have a doubled quote character or the end of the string. */ - + if ((c = next_char (dtp)) == EOF) goto done_eof; if (c == quote) @@ -1227,21 +1224,21 @@ push_char (dtp, quote); break; } - + unget_char (dtp, c); goto done; - + CASE_SEPARATORS: if (quote == ' ') { unget_char (dtp, c); goto done; } - + if (c != '\n' && c != '\r') push_char (dtp, c); break; - + default: push_char (dtp, c); break; @@ -1253,13 +1250,13 @@ done: c = next_char (dtp); done_eof: - if (is_separator (c) || c == '!' || c == EOF) + if (is_separator (c) || c == EOF) { unget_char (dtp, c); eat_separator (dtp); dtp->u.p.saved_type = BT_CHARACTER; } - else + else { free_saved (dtp); snprintf (message, MSGLEN, "Invalid string input in item %d", @@ -1287,7 +1284,7 @@ if ((c = next_char (dtp)) == EOF) goto bad; - + if (c == '-' || c == '+') { push_char (dtp, c); @@ -1297,7 +1294,7 @@ if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA) c = '.'; - + if (!isdigit (c) && c != '.') { if (c == 'i' || c == 'I' || c == 'n' || c == 'N') @@ -1347,6 +1344,10 @@ goto bad; goto exp2; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad; + CASE_SEPARATORS: case EOF: goto done; @@ -1383,6 +1384,10 @@ push_char (dtp, c); break; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad; + CASE_SEPARATORS: case EOF: unget_char (dtp, c); @@ -1443,7 +1448,7 @@ push_char (dtp, 'n'); push_char (dtp, 'a'); push_char (dtp, 'n'); - + /* Match "NAN(alphanum)". */ if (c == '(') { @@ -1500,6 +1505,10 @@ case '(': break; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad_complex; + CASE_SEPARATORS: case EOF: unget_char (dtp, c); @@ -1543,7 +1552,7 @@ if (parse_real (dtp, dest + size / 2, kind)) return; - + eol_4: eat_spaces (dtp); c = next_char (dtp); @@ -1578,7 +1587,7 @@ hit_eof (dtp); return; } - else if (c != '\n') + else if (c != '\n') eat_line (dtp); snprintf (message, MSGLEN, "Bad complex value in item %d of list input", @@ -1618,6 +1627,10 @@ case '-': goto got_sign; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad_real; + CASE_SEPARATORS: unget_char (dtp, c); /* Single null. */ eat_separator (dtp); @@ -1673,6 +1686,10 @@ push_char (dtp, '\0'); goto got_repeat; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad_real; + CASE_SEPARATORS: case EOF: if (c != '\n' && c != ',' && c != '\r' && c != ';') @@ -1742,6 +1759,10 @@ push_char (dtp, c); break; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad_real; + CASE_SEPARATORS: case EOF: goto done; @@ -1802,6 +1823,10 @@ push_char (dtp, c); break; + case '!': + if (!dtp->u.p.namelist_mode) + goto bad_real; + CASE_SEPARATORS: case EOF: goto done; @@ -1899,7 +1924,7 @@ goto unwind; if (dtp->u.p.namelist_mode) - { + { if (c == ' ' || c =='\n' || c == '\r') { do @@ -2058,7 +2083,7 @@ dtp->u.p.input_complete = 0; dtp->u.p.repeat_count = 1; dtp->u.p.at_eol = 0; - + if ((c = eat_spaces (dtp)) == EOF) { err = LIBERROR_END; @@ -2092,7 +2117,7 @@ return err; goto set_value; } - + if (dtp->u.p.input_complete) goto cleanup; @@ -2231,7 +2256,7 @@ for (elem = 0; elem < nelems; elem++) { dtp->u.p.item_count++; - err = list_formatted_read_scalar (dtp, type, tmp + stride*elem, + err = list_formatted_read_scalar (dtp, type, tmp + stride*elem, kind, size); if (err) break; @@ -2374,10 +2399,10 @@ || (c==')' && dim < rank -1)) { if (is_char) - snprintf (parse_err_msg, parse_err_msg_size, + snprintf (parse_err_msg, parse_err_msg_size, "Bad substring qualifier"); else - snprintf (parse_err_msg, parse_err_msg_size, + snprintf (parse_err_msg, parse_err_msg_size, "Bad number of index fields"); goto err_ret; } @@ -2396,7 +2421,7 @@ snprintf (parse_err_msg, parse_err_msg_size, "Bad character in substring qualifier"); else - snprintf (parse_err_msg, parse_err_msg_size, + snprintf (parse_err_msg, parse_err_msg_size, "Bad character in index"); goto err_ret; } @@ -2405,10 +2430,10 @@ && dtp->u.p.saved_string == 0) { if (is_char) - snprintf (parse_err_msg, parse_err_msg_size, + snprintf (parse_err_msg, parse_err_msg_size, "Null substring qualifier"); else - snprintf (parse_err_msg, parse_err_msg_size, + snprintf (parse_err_msg, parse_err_msg_size, "Null index field"); goto err_ret; } @@ -2417,7 +2442,7 @@ || (indx == 2 && dtp->u.p.saved_string == 0)) { if (is_char) - snprintf (parse_err_msg, parse_err_msg_size, + snprintf (parse_err_msg, parse_err_msg_size, "Bad substring qualifier"); else snprintf (parse_err_msg, parse_err_msg_size, @@ -2506,10 +2531,10 @@ || (ls[dim].end < GFC_DIMENSION_LBOUND(ad[dim]))) { if (is_char) - snprintf (parse_err_msg, parse_err_msg_size, + snprintf (parse_err_msg, parse_err_msg_size, "Substring out of range"); else - snprintf (parse_err_msg, parse_err_msg_size, + snprintf (parse_err_msg, parse_err_msg_size, "Index %d out of range", dim + 1); goto err_ret; } @@ -2517,7 +2542,7 @@ if (((ls[dim].end - ls[dim].start ) * ls[dim].step < 0) || (ls[dim].step == 0)) { - snprintf (parse_err_msg, parse_err_msg_size, + snprintf (parse_err_msg, parse_err_msg_size, "Bad range in index %d", dim + 1); goto err_ret; } @@ -2560,7 +2585,7 @@ strcmp_extended_type (char *p, char *q) { char *r, *s; - + for (r = p, s = q; *r && *s; r++, s++) { if (*r != *s) @@ -3068,7 +3093,7 @@ goto nml_err_ret; if (c != '?') { - snprintf (nml_err_msg, nml_err_msg_size, + snprintf (nml_err_msg, nml_err_msg_size, "namelist read: misplaced = sign"); goto nml_err_ret; } @@ -3084,7 +3109,7 @@ nml_match_name (dtp, "end", 3); if (dtp->u.p.nml_read_error) { - snprintf (nml_err_msg, nml_err_msg_size, + snprintf (nml_err_msg, nml_err_msg_size, "namelist not terminated with / or &end"); goto nml_err_ret; } @@ -3379,7 +3404,7 @@ dtp->u.p.namelist_mode = 1; dtp->u.p.input_complete = 0; dtp->u.p.expanded_read = 0; - + /* Set the next_char and push_char worker functions. */ set_workers (dtp); @@ -3425,7 +3450,7 @@ if (dtp->u.p.nml_read_error) goto find_nml_name; - /* A trailing space is required, we give a little latitude here, 10.9.1. */ + /* A trailing space is required, we give a little latitude here, 10.9.1. */ c = next_char (dtp); if (!is_separator(c) && c != '!') { --- a/libgfortran/io/write_float.def 2015-02-11 05:29:06.000000000 +0100 +++ b/libgfortran/io/write_float.def 2016-02-16 15:03:07.897992463 +0100 @@ -938,7 +938,7 @@ #if defined(GFC_REAL_16_IS_FLOAT128) #define DTOA2Q(prec,val) \ -__qmath_(quadmath_snprintf) (buffer, size, "%+-#.*Qe", (prec), (val)) +quadmath_snprintf (buffer, size, "%+-#.*Qe", (prec), (val)) #endif #define FDTOA(suff,prec,val) TOKENPASTE(FDTOA2,suff)(prec,val) @@ -953,7 +953,7 @@ #if defined(GFC_REAL_16_IS_FLOAT128) #define FDTOA2Q(prec,val) \ -__qmath_(quadmath_snprintf) (buffer, size, "%+-#.*Qf", \ +quadmath_snprintf (buffer, size, "%+-#.*Qf", \ (prec), (val)) #endif --- a/libgo/mksysinfo.sh 2015-11-11 15:16:46.000000000 +0100 +++ b/libgo/mksysinfo.sh 2016-02-16 15:31:11.849428548 +0100 @@ -183,6 +183,12 @@ #ifdef TIOCSCTTY TIOCSCTTY_val = TIOCSCTTY, #endif +#ifdef TIOCGPGRP + TIOCGPGRP_val = TIOCGPGRP, +#endif +#ifdef TIOCSPGRP + TIOCSPGRP_val = TIOCSPGRP, +#endif #ifdef TIOCGPTN TIOCGPTN_val = TIOCGPTN, #endif @@ -261,6 +267,9 @@ #ifdef TUNGETFILTER TUNGETFILTER_val = TUNGETFILTER, #endif +#ifdef NLA_HDRLEN + NLA_HDRLEN_val = NLA_HDRLEN, +#endif }; EOF @@ -531,7 +540,7 @@ # GNU/Linux specific; it should do no harm if there is no # _user_regs_struct. regs=`grep '^type _user_regs_struct struct' gen-sysinfo.go || true` -if test "$regs" == ""; then +if test "$regs" = ""; then # s390 regs=`grep '^type __user_regs_struct struct' gen-sysinfo.go || true` if test "$regs" != ""; then @@ -875,11 +884,13 @@ -e 's/ ai_/ Ai_/g' \ >> ${OUT} -# The addrinfo flags and errors. +# The addrinfo and nameinfo flags and errors. grep '^const _AI_' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(AI_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} grep '^const _EAI_' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(EAI_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} +grep '^const _NI_' gen-sysinfo.go | \ + sed -e 's/^\(const \)_\(NI_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} # The passwd struct. grep '^type _passwd ' gen-sysinfo.go | \ @@ -915,6 +926,16 @@ echo 'const TIOCSCTTY = _TIOCSCTTY_val' >> ${OUT} fi fi +if ! grep '^const TIOCGPGRP' ${OUT} >/dev/null 2>&1; then + if grep '^const _TIOCGPGRP_val' ${OUT} >/dev/null 2>&1; then + echo 'const TIOCGPGRP = _TIOCGPGRP_val' >> ${OUT} + fi +fi +if ! grep '^const TIOCSPGRP' ${OUT} >/dev/null 2>&1; then + if grep '^const _TIOCSPGRP_val' ${OUT} >/dev/null 2>&1; then + echo 'const TIOCSPGRP = _TIOCSPGRP_val' >> ${OUT} + fi +fi if ! grep '^const TIOCGPTN' ${OUT} >/dev/null 2>&1; then if grep '^const _TIOCGPTN_val' ${OUT} >/dev/null 2>&1; then echo 'const TIOCGPTN = _TIOCGPTN_val' >> ${OUT} @@ -1057,8 +1078,6 @@ fi fi - - # The ioctl flags for terminal control grep '^const _TC[GS]ET' gen-sysinfo.go | grep -v _val | \ sed -e 's/^\(const \)_\(TC[GS]ET[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} @@ -1404,9 +1423,15 @@ # The GNU/Linux netlink flags. grep '^const _NETLINK_' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(NETLINK_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} -grep '^const _NLA_' gen-sysinfo.go | \ +grep '^const _NLA_' gen-sysinfo.go | grep -v '_val =' | \ sed -e 's/^\(const \)_\(NLA_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} +if ! grep '^const NLA_HDRLEN' ${OUT} >/dev/null 2>&1; then + if grep '^const _NLA_HDRLEN_val' ${OUT} >/dev/null 2>&1; then + echo 'const NLA_HDRLEN = _NLA_HDRLEN_val' >> ${OUT} + fi +fi + # The GNU/Linux packet socket flags. grep '^const _PACKET_' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(PACKET_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} @@ -1426,6 +1451,11 @@ # The GNU/Linux CLONE flags. grep '^const _CLONE_' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(CLONE_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} +# We need some CLONE constants that are not defined in older versions +# of glibc. +if ! grep '^const CLONE_NEWUSER ' ${OUT} > /dev/null 2>&1; then + echo "const CLONE_NEWUSER = 0x10000000" >> ${OUT} +fi # Struct sizes. set cmsghdr Cmsghdr ip_mreq IPMreq ip_mreqn IPMreqn ipv6_mreq IPv6Mreq \ --- a/libmpx/mpxrt/mpxrt.c 2015-03-10 10:37:41.000000000 +0100 +++ b/libmpx/mpxrt/mpxrt.c 2016-02-16 15:29:46.587786427 +0100 @@ -296,7 +296,7 @@ __mpxrt_write_uint (VERB_ERROR, trapno, 10); __mpxrt_write (VERB_ERROR, ", ip = 0x"); __mpxrt_write_uint (VERB_ERROR, ip, 16); - __mpxrt_write (VERB_BR, "\n"); + __mpxrt_write (VERB_ERROR, "\n"); exit (255); } else @@ -305,7 +305,7 @@ __mpxrt_write_uint (VERB_ERROR, trapno, 10); __mpxrt_write (VERB_ERROR, "! at 0x"); __mpxrt_write_uint (VERB_ERROR, ip, 16); - __mpxrt_write (VERB_BR, "\n"); + __mpxrt_write (VERB_ERROR, "\n"); exit (255); } } --- a/libsanitizer/asan/asan_mac.cc 2014-11-13 21:41:38.000000000 +0100 +++ b/libsanitizer/asan/asan_mac.cc 2016-02-16 15:24:56.841175125 +0100 @@ -99,6 +99,23 @@ } } +bool DyldNeedsEnvVariable() { +// If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if +// DYLD_INSERT_LIBRARIES is not set. + +#if SANITIZER_IOSSIM + // GetMacosVersion will not work for the simulator, whose kernel version + // is tied to the host. Use a weak linking hack for the simulator. + // This API was introduced in the same version of the OS as the dyld + // optimization. + + // Check for presence of a symbol that is available on OS X 10.11+, iOS 9.0+. + return (dlsym(RTLD_NEXT, "mach_memory_info") == nullptr); +#else + return (GetMacosVersion() <= MACOS_VERSION_YOSEMITE); +#endif +} + void MaybeReexec() { if (!flags()->allow_reexec) return; // Make sure the dynamic ASan runtime library is preloaded so that the @@ -111,8 +128,9 @@ uptr old_env_len = dyld_insert_libraries ? internal_strlen(dyld_insert_libraries) : 0; uptr fname_len = internal_strlen(info.dli_fname); - if (!dyld_insert_libraries || - !REAL(strstr)(dyld_insert_libraries, info.dli_fname)) { + bool lib_is_in_env = + dyld_insert_libraries && REAL(strstr)(dyld_insert_libraries, info.dli_fname); + if (DyldNeedsEnvVariable() && !lib_is_in_env) { // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime // library. char program_name[1024]; @@ -141,6 +159,10 @@ VReport(1, "Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n"); execv(program_name, *_NSGetArgv()); } else { + + if (!lib_is_in_env) + return; + // DYLD_INSERT_LIBRARIES is set and contains the runtime library. if (old_env_len == fname_len) { // It's just the runtime library name - fine to unset the variable. --- a/libsanitizer/sanitizer_common/sanitizer_mac.cc 2014-11-13 21:41:38.000000000 +0100 +++ b/libsanitizer/sanitizer_common/sanitizer_mac.cc 2016-02-16 15:24:56.841175125 +0100 @@ -296,7 +296,11 @@ case '2': return MACOS_VERSION_MOUNTAIN_LION; case '3': return MACOS_VERSION_MAVERICKS; case '4': return MACOS_VERSION_YOSEMITE; - default: return MACOS_VERSION_UNKNOWN; + default: + if (IsDigit(version[1])) + return MACOS_VERSION_UNKNOWN_NEWER; + else + return MACOS_VERSION_UNKNOWN; } } default: return MACOS_VERSION_UNKNOWN; --- a/libsanitizer/sanitizer_common/sanitizer_mac.h 2014-11-13 21:41:38.000000000 +0100 +++ b/libsanitizer/sanitizer_common/sanitizer_mac.h 2016-02-16 15:24:56.841175125 +0100 @@ -25,6 +25,7 @@ MACOS_VERSION_MOUNTAIN_LION, MACOS_VERSION_MAVERICKS, MACOS_VERSION_YOSEMITE, + MACOS_VERSION_UNKNOWN_NEWER }; MacosVersion GetMacosVersion(); --- a/libstdc++-v3/include/backward/strstream 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/backward/strstream 2016-02-16 15:09:05.791852030 +0100 @@ -40,9 +40,8 @@ // MAY BE REMOVED in a future standard revision. One should use the // header instead. -/** @file backward/strstream - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{sstream} +/** @file strstream + * This is a Standard C++ Library header. */ #ifndef _BACKWARD_STRSTREAM --- a/libstdc++-v3/include/bits/alloc_traits.h 2015-05-28 14:33:26.000000000 +0200 +++ b/libstdc++-v3/include/bits/alloc_traits.h 2016-02-16 15:44:11.879453856 +0100 @@ -409,7 +409,7 @@ * Calls @c __a.destroy(__p) if that expression is well-formed, * otherwise calls @c __p->~_Tp() */ - template + template static void destroy(_Alloc& __a, _Tp* __p) { _S_destroy(__a, __p); } @@ -437,6 +437,130 @@ { return _S_select(__rhs, 0); } }; + /// Partial specialization for std::allocator. + template + struct allocator_traits> + { + /// The allocator type + using allocator_type = allocator<_Tp>; + /// The allocated type + using value_type = _Tp; + + /// The allocator's pointer type. + using pointer = _Tp*; + + /// The allocator's const pointer type. + using const_pointer = const _Tp*; + + /// The allocator's void pointer type. + using void_pointer = void*; + + /// The allocator's const void pointer type. + using const_void_pointer = const void*; + + /// The allocator's difference type + using difference_type = std::ptrdiff_t; + + /// The allocator's size type + using size_type = std::size_t; + + /// How the allocator is propagated on copy assignment + using propagate_on_container_copy_assignment = false_type; + + /// How the allocator is propagated on move assignment + using propagate_on_container_move_assignment = true_type; + + /// How the allocator is propagated on swap + using propagate_on_container_swap = false_type; + + template + using rebind_alloc = allocator<_Up>; + + template + using rebind_traits = allocator_traits>; + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * + * Calls @c a.allocate(n) + */ + static pointer + allocate(allocator_type& __a, size_type __n) + { return __a.allocate(__n); } + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * @param __hint Aid to locality. + * @return Memory of suitable size and alignment for @a n objects + * of type @c value_type + * + * Returns a.allocate(n, hint) + */ + static pointer + allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) + { return __a.allocate(__n, __hint); } + + /** + * @brief Deallocate memory. + * @param __a An allocator. + * @param __p Pointer to the memory to deallocate. + * @param __n The number of objects space was allocated for. + * + * Calls a.deallocate(p, n) + */ + static void + deallocate(allocator_type& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + /** + * @brief Construct an object of type @a _Up + * @param __a An allocator. + * @param __p Pointer to memory of suitable size and alignment for Tp + * @param __args Constructor arguments. + * + * Calls __a.construct(__p, std::forward(__args)...) + */ + template + static void + construct(allocator_type& __a, _Up* __p, _Args&&... __args) + { __a.construct(__p, std::forward<_Args>(__args)...); } + + /** + * @brief Destroy an object of type @a _Up + * @param __a An allocator. + * @param __p Pointer to the object to destroy + * + * Calls @c __a.destroy(__p). + */ + template + static void + destroy(allocator_type& __a, _Up* __p) + { __a.destroy(__p); } + + /** + * @brief The maximum supported allocation size + * @param __a An allocator. + * @return @c __a.max_size() + */ + static size_type + max_size(const allocator_type& __a) noexcept + { return __a.max_size(); } + + /** + * @brief Obtain an allocator to use when copying a container. + * @param __rhs An allocator. + * @return @c __rhs + */ + static allocator_type + select_on_container_copy_construction(const allocator_type& __rhs) + { return __rhs; } + }; + + template inline void __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) --- a/libstdc++-v3/include/bits/basic_string.h 2015-11-25 17:11:33.000000000 +0100 +++ b/libstdc++-v3/include/bits/basic_string.h 2016-02-16 15:24:28.231617711 +0100 @@ -322,7 +322,6 @@ template static void _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2) - _GLIBCXX_NOEXCEPT { for (; __k1 != __k2; ++__k1, ++__p) traits_type::assign(*__p, *__k1); // These types are off. @@ -2782,7 +2781,6 @@ template static void _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2) - _GLIBCXX_NOEXCEPT { for (; __k1 != __k2; ++__k1, ++__p) traits_type::assign(*__p, *__k1); // These types are off. --- a/libstdc++-v3/include/bits/c++0x_warning.h 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/bits/c++0x_warning.h 2016-02-16 15:17:37.913515585 +0100 @@ -29,9 +29,9 @@ #define _CXX0X_WARNING_H 1 #if __cplusplus < 201103L -#error This file requires compiler and library support for the \ -ISO C++ 2011 standard. This support is currently experimental, and must be \ -enabled with the -std=c++11 or -std=gnu++11 compiler options. +#error This file requires compiler and library support \ +for the ISO C++ 2011 standard. This support must be enabled \ +with the -std=c++11 or -std=gnu++11 compiler options. #endif #endif --- a/libstdc++-v3/include/bits/c++config 2015-03-20 14:26:55.000000000 +0100 +++ b/libstdc++-v3/include/bits/c++config 2016-02-16 15:00:57.786515265 +0100 @@ -294,7 +294,7 @@ # endif # if _GLIBCXX_USE_CXX11_ABI - inline namespace __cxx11 __attribute__((__abi_tag__)) { } + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } # endif } --- a/libstdc++-v3/include/bits/forward_list.h 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/bits/forward_list.h 2016-02-16 15:09:05.791852030 +0100 @@ -463,7 +463,8 @@ /** * @brief Creates a %forward_list with default constructed elements. - * @param __n The number of elements to initially create. + * @param __n The number of elements to initially create. + * @param __al An allocator object. * * This constructor creates the %forward_list with @a __n default * constructed elements. @@ -1083,6 +1084,7 @@ * after @a __pos in constant time. * * Undefined if @a __pos is in (__before,__last). + * @{ */ void splice_after(const_iterator __pos, forward_list&&, @@ -1093,6 +1095,7 @@ splice_after(const_iterator __pos, forward_list&, const_iterator __before, const_iterator __last) { _M_splice_after(__pos, __before, __last); } + // @} /** * @brief Remove all elements equal to value. --- a/libstdc++-v3/include/bits/locale_facets_nonio.h 2015-01-20 12:50:51.000000000 +0100 +++ b/libstdc++-v3/include/bits/locale_facets_nonio.h 2016-02-16 15:09:05.792852052 +0100 @@ -709,7 +709,7 @@ * * @param __s Start of string to parse. * @param __end End of string to parse. - * @param __io Source of the locale. + * @param __f Source of the locale. * @param __err Error flags to set. * @param __tm Pointer to struct tm to fill in. * @param __format Format specifier. --- a/libstdc++-v3/include/bits/regex_executor.tcc 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/bits/regex_executor.tcc 2016-02-16 15:11:31.213978569 +0100 @@ -147,7 +147,10 @@ bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: _M_lookahead(_State<_TraitsT> __state) { - _ResultsVec __what(_M_cur_results.size()); + // Backreferences may refer to captured content. + // We may want to make this faster by not copying, + // but let's not be clever prematurely. + _ResultsVec __what(_M_cur_results); _Executor __sub(_M_current, _M_end, __what, _M_re, _M_flags); __sub._M_states._M_start = __state._M_alt; if (__sub._M_search_from_first()) --- a/libstdc++-v3/include/bits/shared_ptr_base.h 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/bits/shared_ptr_base.h 2016-02-16 15:02:04.148780336 +0100 @@ -1540,19 +1540,25 @@ _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept { _M_weak_this._M_assign(__p, __n); } - template + template<_Lock_policy _Lp1, typename _Tp1, typename _Tp2> friend void - __enable_shared_from_this_helper(const __shared_count<_Lp>& __pn, - const __enable_shared_from_this* __pe, - const _Tp1* __px) noexcept - { - if (__pe != 0) - __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn); - } + __enable_shared_from_this_helper(const __shared_count<_Lp1>&, + const __enable_shared_from_this<_Tp1, + _Lp1>*, const _Tp2*) noexcept; mutable __weak_ptr<_Tp, _Lp> _M_weak_this; }; + template<_Lock_policy _Lp1, typename _Tp1, typename _Tp2> + inline void + __enable_shared_from_this_helper(const __shared_count<_Lp1>& __pn, + const __enable_shared_from_this<_Tp1, + _Lp1>* __pe, + const _Tp2* __px) noexcept + { + if (__pe != nullptr) + __pe->_M_weak_assign(const_cast<_Tp2*>(__px), __pn); + } template inline __shared_ptr<_Tp, _Lp> --- a/libstdc++-v3/include/bits/shared_ptr.h 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/bits/shared_ptr.h 2016-02-16 15:02:04.148780336 +0100 @@ -582,19 +582,25 @@ _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept { _M_weak_this._M_assign(__p, __n); } - template + template friend void - __enable_shared_from_this_helper(const __shared_count<>& __pn, - const enable_shared_from_this* __pe, - const _Tp1* __px) noexcept - { - if (__pe != 0) - __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn); - } + __enable_shared_from_this_helper(const __shared_count<>&, + const enable_shared_from_this<_Tp1>*, + const _Tp2*) noexcept; mutable weak_ptr<_Tp> _M_weak_this; }; + template + inline void + __enable_shared_from_this_helper(const __shared_count<>& __pn, + const enable_shared_from_this<_Tp1>* + __pe, const _Tp2* __px) noexcept + { + if (__pe != nullptr) + __pe->_M_weak_assign(const_cast<_Tp2*>(__px), __pn); + } + /** * @brief Create an object that is owned by a shared_ptr. * @param __a An allocator. --- a/libstdc++-v3/include/bits/valarray_before.h 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/bits/valarray_before.h 2016-02-16 15:37:14.613642837 +0100 @@ -331,14 +331,24 @@ { return pow(__x, __y); } }; + template + struct __fun_with_valarray + { + typedef _Tp result_type; + }; + + template + struct __fun_with_valarray<_Tp, false> + { + // No result type defined for invalid value types. + }; // We need these bits in order to recover the return type of // some functions/operators now that we're no longer using // function templates. template - struct __fun + struct __fun : __fun_with_valarray<_Tp> { - typedef _Tp result_type; }; // several specializations for relational operators. --- a/libstdc++-v3/include/c_global/cmath 2015-11-24 14:25:07.000000000 +0100 +++ b/libstdc++-v3/include/c_global/cmath 2016-02-16 15:27:06.419691445 +0100 @@ -880,7 +880,11 @@ signbit(_Tp __f) { typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_signbit(__type(__f)); + return sizeof(__type) == sizeof(float) + ? __builtin_signbitf(__type(__f)) + : sizeof(__type) == sizeof(double) + ? __builtin_signbit(__type(__f)) + : __builtin_signbitl(__type(__f)); } template --- a/libstdc++-v3/include/debug/vector 2015-04-28 19:54:13.000000000 +0200 +++ b/libstdc++-v3/include/debug/vector 2016-02-16 15:09:05.792852052 +0100 @@ -37,9 +37,12 @@ namespace __gnu_debug { - /// Special vector safe base class to add a guaranteed capacity information - /// useful to detect code relying on the libstdc++ reallocation management - /// implementation detail. + /** @brief Base class for Debug Mode vector. + * + * Adds information about the guaranteed capacity, which is useful for + * detecting code which relies on non-portable implementation details of + * the libstdc++ reallocation policy. + */ template class _Safe_vector --- a/libstdc++-v3/include/experimental/fs_fwd.h 2015-08-18 19:58:22.000000000 +0200 +++ b/libstdc++-v3/include/experimental/fs_fwd.h 2016-02-16 15:09:05.792852052 +0100 @@ -22,8 +22,9 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . -/** @file experimental/filesystem - * This is a TS C++ Library header. +/** @file experimental/fs_fwd.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{experimental/filesystem} */ #ifndef _GLIBCXX_EXPERIMENTAL_FS_FWD_H @@ -52,7 +53,7 @@ #endif /** - * @defgroup filesystem + * @defgroup filesystem Filesystem * @ingroup experimental * * Utilities for performing operations on file systems and their components, --- a/libstdc++-v3/include/experimental/fs_ops.h 2015-08-18 19:58:22.000000000 +0200 +++ b/libstdc++-v3/include/experimental/fs_ops.h 2016-02-16 15:09:05.792852052 +0100 @@ -22,8 +22,9 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . -/** @file experimental/filesystem - * This is a TS C++ Library header. +/** @file experimental/fs_fwd.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{experimental/filesystem} */ #ifndef _GLIBCXX_EXPERIMENTAL_FS_OPS_H --- a/libstdc++-v3/include/experimental/fs_path.h 2015-10-07 23:00:50.000000000 +0200 +++ b/libstdc++-v3/include/experimental/fs_path.h 2016-02-16 15:01:29.895127798 +0100 @@ -549,16 +549,6 @@ std::string _M_what = _M_gen_what(); }; - struct path::_Cmpt : path - { - _Cmpt(string_type __s, _Type __t, size_t __pos) - : path(std::move(__s), __t), _M_pos(__pos) { } - - _Cmpt() : _M_pos(-1) { } - - size_t _M_pos; - }; - template<> struct path::__is_encoded_char : std::true_type { using value_type = char; }; @@ -575,6 +565,16 @@ struct path::__is_encoded_char : std::true_type { using value_type = char32_t; }; + struct path::_Cmpt : path + { + _Cmpt(string_type __s, _Type __t, size_t __pos) + : path(std::move(__s), __t), _M_pos(__pos) { } + + _Cmpt() : _M_pos(-1) { } + + size_t _M_pos; + }; + // specialize _Cvt for degenerate 'noconv' case template<> struct path::_Cvt --- a/libstdc++-v3/include/experimental/optional 2015-01-20 12:51:03.000000000 +0100 +++ b/libstdc++-v3/include/experimental/optional 2016-02-16 15:09:05.792852052 +0100 @@ -33,6 +33,12 @@ * @defgroup experimental Experimental * * Components specified by various Technical Specifications. + * + * As indicated by the std::experimental namespace and the header paths, + * the contents of these Technical Specifications are experimental and not + * part of the C++ standard. As such the interfaces and implementations may + * change in the future, and there is no guarantee of compatibility + * between different GCC releases for these features. */ #if __cplusplus <= 201103L --- a/libstdc++-v3/include/experimental/string_view 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/experimental/string_view 2016-02-16 15:09:05.792852052 +0100 @@ -23,7 +23,7 @@ // . /** @file experimental/string_view - * This is a Standard C++ Library header. + * This is a TS C++ Library header. */ // --- a/libstdc++-v3/include/experimental/string_view.tcc 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/experimental/string_view.tcc 2016-02-16 15:09:05.792852052 +0100 @@ -24,7 +24,7 @@ /** @file experimental/string_view.tcc * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{string_view} + * Do not attempt to use it directly. @headername{experimental/string_view} */ // --- a/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/traits.hpp 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/traits.hpp 2016-02-16 15:09:05.793852074 +0100 @@ -166,13 +166,8 @@ class Node_Update, class Node, typename _Alloc> - struct bin_search_tree_traits< - Key, - null_type, - Cmp_Fn, - Node_Update, - Node, - _Alloc> + struct + bin_search_tree_traits { private: typedef types_traits type_traits; --- a/libstdc++-v3/include/std/bitset 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/std/bitset 2016-02-16 15:09:05.793852074 +0100 @@ -663,7 +663,7 @@ }; #if __cplusplus >= 201103L - template + template struct _Sanitize_val { static constexpr unsigned long long @@ -681,8 +681,6 @@ #endif /** - * @class bitset - * * @brief The %bitset class represents a @e fixed-size sequence of bits. * @ingroup utilities * --- a/libstdc++-v3/include/std/functional 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/std/functional 2016-02-16 15:24:14.452348979 +0100 @@ -1122,7 +1122,7 @@ // Call unqualified template()( + = decltype( std::declval<_Functor&>()( _Mu<_Bound_args>()( std::declval<_Bound_args&>(), std::declval&>() )... ) )> _Result @@ -1136,7 +1136,7 @@ // Call as const template= 0), - typename add_const<_Functor>::type>::type>()( + typename add_const<_Functor>::type&>::type>()( _Mu<_Bound_args>()( std::declval(), std::declval&>() )... ) )> _Result @@ -1150,7 +1150,7 @@ // Call as volatile template= 0), - typename add_volatile<_Functor>::type>::type>()( + typename add_volatile<_Functor>::type&>::type>()( _Mu<_Bound_args>()( std::declval(), std::declval&>() )... ) )> _Result @@ -1164,7 +1164,7 @@ // Call as const volatile template= 0), - typename add_cv<_Functor>::type>::type>()( + typename add_cv<_Functor>::type&>::type>()( _Mu<_Bound_args>()( std::declval(), std::declval&>() )... ) )> _Result @@ -1883,7 +1883,7 @@ static _Res _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) { - return __callable_functor(**_Base::_M_get_pointer(__functor))( + return std::__callable_functor(**_Base::_M_get_pointer(__functor))( std::forward<_ArgTypes>(__args)...); } }; @@ -1898,7 +1898,7 @@ static void _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) { - __callable_functor(**_Base::_M_get_pointer(__functor))( + std::__callable_functor(**_Base::_M_get_pointer(__functor))( std::forward<_ArgTypes>(__args)...); } }; @@ -1977,19 +1977,14 @@ { typedef _Res _Signature_type(_ArgTypes...); - template - using _Invoke = decltype(__callable_functor(std::declval<_Functor&>()) - (std::declval<_ArgTypes>()...) ); + template::type> + struct _Callable : __check_func_return_type<_Res2, _Res> { }; // Used so the return type convertibility checks aren't done when // performing overload resolution for copy construction/assignment. template - using _NotSelf = __not_>; - - template - using _Callable - = __and_<_NotSelf<_Functor>, - __check_func_return_type<_Invoke<_Functor>, _Res>>; + struct _Callable : false_type { }; template using _Requires = typename enable_if<_Cond::value, _Tp>::type; @@ -2054,6 +2049,7 @@ * reference_wrapper, this function will not throw. */ template>, void>, typename = _Requires<_Callable<_Functor>, void>> function(_Functor); @@ -2246,7 +2242,7 @@ } template - template + template function<_Res(_ArgTypes...)>:: function(_Functor __f) : _Function_base() --- a/libstdc++-v3/include/std/mutex 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/std/mutex 2016-02-16 15:09:05.793852074 +0100 @@ -114,7 +114,7 @@ * @{ */ - /// mutex + /// The standard mutex type. class mutex : private __mutex_base { public: @@ -158,7 +158,7 @@ { return &_M_mutex; } }; - /// recursive_mutex + /// The standard recursive mutex type. class recursive_mutex : private __recursive_mutex_base { public: @@ -243,7 +243,7 @@ } }; - /// timed_mutex + /// The standard timed mutex type. class timed_mutex : private __mutex_base, public __timed_mutex_impl { @@ -295,7 +295,7 @@ { return &_M_mutex; } }; - /// recursive_timed_mutex + /// The standard recursive timed mutex type. class recursive_timed_mutex : private __recursive_mutex_base, public __timed_mutex_impl @@ -360,13 +360,22 @@ /// and manage it. struct adopt_lock_t { }; + /// Tag used to prevent a scoped lock from acquiring ownership of a mutex. constexpr defer_lock_t defer_lock { }; + + /// Tag used to prevent a scoped lock from blocking if a mutex is locked. constexpr try_to_lock_t try_to_lock { }; + + /// Tag used to make a scoped lock take ownership of a locked mutex. constexpr adopt_lock_t adopt_lock { }; - /// @brief Scoped lock idiom. - // Acquire the mutex here with a constructor call, then release with - // the destructor call in accordance with RAII style. + /** @brief A movable scoped lock type. + * + * A unique_lock controls mutex ownership within a scope. Ownership of the + * mutex can be delayed until after construction and can be transferred + * to another unique_lock by move construction or move assignment. If a + * mutex lock is owned when the destructor runs ownership will be released. + */ template class lock_guard { --- a/libstdc++-v3/include/tr2/dynamic_bitset 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/tr2/dynamic_bitset 2016-02-16 15:09:05.793852074 +0100 @@ -593,6 +593,9 @@ * @param __str A string of '0' and '1' characters. * @param __pos Index of the first character in @p __str to use. * @param __n The number of characters to copy. + * @param __zero The character to use for unset bits. + * @param __one The character to use for set bits. + * @param __alloc An allocator. * @throw std::out_of_range If @p __pos is bigger the size of @p __str. * @throw std::invalid_argument If a character appears in the string * which is neither '0' nor '1'. --- a/libstdc++-v3/src/c++11/futex.cc 2015-03-23 17:47:18.000000000 +0100 +++ b/libstdc++-v3/src/c++11/futex.cc 2016-02-16 15:12:51.420663390 +0100 @@ -52,7 +52,7 @@ // we will fall back to spin-waiting. The only thing we could do // here on errors is abort. int ret __attribute__((unused)); - ret = syscall (SYS_futex, __addr, futex_wait_op, __val); + ret = syscall (SYS_futex, __addr, futex_wait_op, __val, nullptr); _GLIBCXX_DEBUG_ASSERT(ret == 0 || errno == EINTR || errno == EAGAIN); return true; } --- a/wgetpatch 1970-01-01 01:00:00.000000000 +0100 +++ b/wgetpatch 2016-02-16 15:10:55.439218657 +0100 @@ -0,0 +1,3 @@ +#!/bin/bash -e + +wget "$1" -O - | patch -Np1 -i -