From patchwork Fri Aug 30 14:06:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 1155942 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508034-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="SG/ajj0U"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46KhBR1V7Hz9s7T for ; Sat, 31 Aug 2019 00:07:27 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:reply-to:mime-version:content-type; q=dns; s=default; b=aKrVIrCWUYt5Dix5AHv3nVQC9zXR/hnF53D+qJV4doW Vfi7EVDWnHE3J1Dp+hyForgJ7E8QoJxzQOXoDzGWer7cGppD/3gqJIWZA8DflTWU +RmyfJToq0zHIJANvSuipXnxE088JNOu5Xf6tKt2AtYqBJp4CXkxN28/pHmoX/5o = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:reply-to:mime-version:content-type; s=default; bh=G+oVRG+MQG8a31AQkvQks3jQc+s=; b=SG/ajj0U+/OMGB42E zkEDG+Xw+PdJHrui/gaSeO97ZJwpXiW7Kn4K2Kkdx71JzKQ0kQb/yuWhmysfZRBG 5AOmvGbO/thECu4VdVAnrYXy4/4BFHYdYOaP98ieXeEhLpZOYc7qIfxfJHhrooT1 4ammsN7B3X7Mf5ZxZZR73DTLy0= Received: (qmail 13208 invoked by alias); 30 Aug 2019 14:07:12 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 13192 invoked by uid 89); 30 Aug 2019 14:07:12 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-10.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 30 Aug 2019 14:06:57 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7D85030821EC for ; Fri, 30 Aug 2019 14:06:56 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-116-139.ams2.redhat.com [10.36.116.139]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7B23E1D3 for ; Fri, 30 Aug 2019 14:06:54 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id x7UE6qau007088 for ; Fri, 30 Aug 2019 16:06:52 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id x7UE6qUL007087 for gcc-patches@gcc.gnu.org; Fri, 30 Aug 2019 16:06:52 +0200 Date: Fri, 30 Aug 2019 16:06:51 +0200 From: Jakub Jelinek To: gcc-patches@gcc.gnu.org Subject: Backports to 7.5 (part 2) Message-ID: <20190830140651.GD2120@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.11.3 (2019-02-01) X-IsSubscribed: yes Hi! I've backported 97 commits from trunk to 7.5, bootstrapped/regtested them on x86_64-linux and i686-linux and committed. Here is the second half of them. Jakub 2019-08-30 Jakub Jelinek Backported from mainline 2019-02-20 Jakub Jelinek PR middle-end/88074 PR middle-end/89415 * toplev.c (do_compile): Double the emin/emax exponents to workaround buggy mpc_norm. 2019-02-19 Richard Biener PR middle-end/88074 * toplev.c (do_compile): Initialize mpfr's exponent range based on available float modes. 2019-02-20 Jakub Jelinek PR middle-end/88074 PR middle-end/89415 * gcc.dg/pr88074-2.c: New test. 2019-02-19 Richard Biener PR middle-end/88074 * gcc.dg/pr88074.c: New testcase. 2019-08-30 Jakub Jelinek Backported from mainline 2019-02-20 Jakub Jelinek David Malcolm PR middle-end/89091 * fold-const.c (decode_field_reference): Return NULL_TREE if lang_hooks.types.type_for_size returns NULL. Check it before overwriting *exp_. Use return NULL_TREE instead of return 0. * gcc.dg/torture/pr89091.c: New test. --- gcc/fold-const.c (revision 270712) +++ gcc/fold-const.c (revision 270713) @@ -4239,7 +4239,7 @@ decode_field_reference (location_t loc, There are problems with FP fields since the type_for_size call below can fail for, e.g., XFmode. */ if (! INTEGRAL_TYPE_P (TREE_TYPE (exp))) - return 0; + return NULL_TREE; /* We are interested in the bare arrangement of bits, so strip everything that doesn't affect the machine mode. However, record the type of the @@ -4255,7 +4255,7 @@ decode_field_reference (location_t loc, exp = TREE_OPERAND (exp, 0); STRIP_NOPS (exp); STRIP_NOPS (and_mask); if (TREE_CODE (and_mask) != INTEGER_CST) - return 0; + return NULL_TREE; } poly_int64 poly_bitsize, poly_bitpos; @@ -4271,7 +4271,11 @@ decode_field_reference (location_t loc, || (! AGGREGATE_TYPE_P (TREE_TYPE (inner)) && compare_tree_int (TYPE_SIZE (TREE_TYPE (inner)), *pbitpos + *pbitsize) < 0)) - return 0; + return NULL_TREE; + + unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1); + if (unsigned_type == NULL_TREE) + return NULL_TREE; *exp_ = exp; @@ -4282,7 +4286,6 @@ decode_field_reference (location_t loc, *punsignedp = TYPE_UNSIGNED (outer_type); /* Compute the mask to access the bitfield. */ - unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1); precision = TYPE_PRECISION (unsigned_type); mask = build_int_cst_type (unsigned_type, -1); --- gcc/testsuite/gcc.dg/torture/pr89091.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/pr89091.c (revision 270713) @@ -0,0 +1,10 @@ +/* PR middle-end/89091 */ +/* { dg-do compile { target int128 } } */ + +struct S { unsigned __int128 s : 65; }; + +int +foo (struct S *x, int y) +{ + return y && x->s; +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-02-20 Jakub Jelinek PR middle-end/89412 * expr.c (expand_assignment): If result is a MEM, use change_address instead of simplify_gen_subreg. * gcc.c-torture/compile/pr89412.c: New test. --- gcc/expr.c (revision 270713) +++ gcc/expr.c (revision 270714) @@ -5147,9 +5147,14 @@ expand_assignment (tree to, tree from, b } else { - rtx from_rtx - = simplify_gen_subreg (GET_MODE (to_rtx), result, - TYPE_MODE (TREE_TYPE (from)), 0); + rtx from_rtx; + if (MEM_P (result)) + from_rtx = change_address (result, GET_MODE (to_rtx), + NULL_RTX); + else + from_rtx + = simplify_gen_subreg (GET_MODE (to_rtx), result, + TYPE_MODE (TREE_TYPE (from)), 0); if (from_rtx) { emit_move_insn (XEXP (to_rtx, 0), --- gcc/testsuite/gcc.c-torture/compile/pr89412.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr89412.c (revision 270714) @@ -0,0 +1,16 @@ +/* PR middle-end/89412 */ + +struct S { double a, b; } d; +int e; +double f; + +void +foo () +{ + _Complex double h; + while (e) + { + f = h; + *(struct S *) &h = d; + } +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-02-20 Jakub Jelinek PR c++/89403 * decl2.c (c_parse_final_cleanups): Move TREE_ASM_WRITTEN setting for flag_syntax_only from here... * semantics.c (expand_or_defer_fn_1): ... here. * g++.dg/cpp0x/pr89403.C: New test. --- gcc/cp/semantics.c (revision 270715) +++ gcc/cp/semantics.c (revision 270716) @@ -4268,7 +4268,12 @@ expand_or_defer_fn_1 (tree fn) /* There's no reason to do any of the work here if we're only doing semantic analysis; this code just generates RTL. */ if (flag_syntax_only) - return false; + { + /* Pretend that this function has been written out so that we don't try + to expand it again. */ + TREE_ASM_WRITTEN (fn) = 1; + return false; + } return true; } --- gcc/cp/decl2.c (revision 270715) +++ gcc/cp/decl2.c (revision 270716) @@ -4888,11 +4888,6 @@ c_parse_final_cleanups (void) /* Generate RTL for this function now that we know we need it. */ expand_or_defer_fn (decl); - /* If we're compiling -fsyntax-only pretend that this - function has been written out so that we don't try to - expand it again. */ - if (flag_syntax_only) - TREE_ASM_WRITTEN (decl) = 1; reconsider = true; } } --- gcc/testsuite/g++.dg/cpp0x/pr89403.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/pr89403.C (revision 270716) @@ -0,0 +1,18 @@ +// PR c++/89403 +// { dg-do compile { target c++11 } } +// { dg-options "-Os -fsyntax-only" } + +template +struct A : T { + constexpr A() : T() { } +}; + +template +struct B { + A b; + constexpr B() { } +}; + +struct C { struct {} s; }; +constexpr B b{}; +constexpr C c = b.b; 2019-08-30 Jakub Jelinek Backported from mainline 2019-02-28 Jakub Jelinek PR c/89520 * convert.c (convert_to_real_1, convert_to_integer_1): Punt for builtins if they don't have a single scalar floating point argument. Formatting fixes. * gcc.dg/pr89520-1.c: New test. * gcc.dg/pr89520-2.c: New test. --- gcc/convert.c (revision 270716) +++ gcc/convert.c (revision 270717) @@ -190,12 +190,15 @@ convert_to_real_1 (tree type, tree expr, CASE_MATHFN (FABS) CASE_MATHFN (LOGB) #undef CASE_MATHFN + if (call_expr_nargs (expr) != 1 + || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (expr, 0)))) + break; { tree arg0 = strip_float_extensions (CALL_EXPR_ARG (expr, 0)); tree newtype = type; - /* We have (outertype)sqrt((innertype)x). Choose the wider mode from - the both as the safe type for operation. */ + /* We have (outertype)sqrt((innertype)x). Choose the wider mode + from the both as the safe type for operation. */ if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type)) newtype = TREE_TYPE (arg0); @@ -579,7 +582,8 @@ convert_to_integer_1 (tree type, tree ex CASE_FLT_FN (BUILT_IN_ROUND): /* Only convert in ISO C99 mode and with -fno-math-errno. */ - if (!targetm.libc_has_function (function_c99_misc) || flag_errno_math) + if (!targetm.libc_has_function (function_c99_misc) + || flag_errno_math) break; if (outprec < TYPE_PRECISION (integer_type_node) || (outprec == TYPE_PRECISION (integer_type_node) @@ -600,7 +604,8 @@ convert_to_integer_1 (tree type, tree ex gcc_fallthrough (); CASE_FLT_FN (BUILT_IN_RINT): /* Only convert in ISO C99 mode and with -fno-math-errno. */ - if (!targetm.libc_has_function (function_c99_misc) || flag_errno_math) + if (!targetm.libc_has_function (function_c99_misc) + || flag_errno_math) break; if (outprec < TYPE_PRECISION (integer_type_node) || (outprec == TYPE_PRECISION (integer_type_node) @@ -615,13 +620,19 @@ convert_to_integer_1 (tree type, tree ex break; CASE_FLT_FN (BUILT_IN_TRUNC): - return convert_to_integer_1 (type, CALL_EXPR_ARG (s_expr, 0), dofold); + if (call_expr_nargs (s_expr) != 1 + || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (s_expr, 0)))) + break; + return convert_to_integer_1 (type, CALL_EXPR_ARG (s_expr, 0), + dofold); default: break; } - if (fn) + if (fn + && call_expr_nargs (s_expr) == 1 + && SCALAR_FLOAT_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (s_expr, 0)))) { tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0)); return convert_to_integer_1 (type, newexpr, dofold); @@ -652,7 +663,9 @@ convert_to_integer_1 (tree type, tree ex break; } - if (fn) + if (fn + && call_expr_nargs (s_expr) == 1 + && SCALAR_FLOAT_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (s_expr, 0)))) { tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0)); return convert_to_integer_1 (type, newexpr, dofold); --- gcc/testsuite/gcc.dg/pr89520-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr89520-1.c (revision 270717) @@ -0,0 +1,13 @@ +/* PR c/89520 */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -w" } */ + +#define A(name) __typeof (__builtin_##name (0)) name (); long name##1 () { return name (); } +#define B(name) A(name) A(name##f) A(name##l) +B (ceil) +B (floor) +B (round) +B (trunc) +B (nearbyint) +B (rint) +B (logb) --- gcc/testsuite/gcc.dg/pr89520-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr89520-2.c (revision 270717) @@ -0,0 +1,42 @@ +/* PR c/89520 */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -w" } */ + +#define A(name) __typeof (__builtin_##name (0)) name (); \ + float name##1 () { return name (); } \ + double name##2 () { return name (); } +#define B(name) A(name) A(name##l) +B (cosh) +B (exp) +B (exp10) +B (exp2) +B (expm1) +B (gamma) +B (j0) +B (j1) +B (lgamma) +B (pow10) +B (sinh) +B (tgamma) +B (y0) +B (y1) +B (acos) +B (acosh) +B (asin) +B (asinh) +B (atan) +B (atanh) +B (cbrt) +B (cos) +B (erf) +B (erfc) +B (log) +B (log10) +B (log2) +B (log1p) +B (sin) +B (tan) +B (tanh) +B (sqrt) +B (fabs) +B (logb) 2019-08-30 Jakub Jelinek Backported from mainline 2019-02-28 Jakub Jelinek PR c/89521 * gcc.dg/pr89521-1.c: New test. * gcc.dg/pr89521-2.c: New test. --- gcc/testsuite/gcc.dg/pr89521-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr89521-1.c (revision 270718) @@ -0,0 +1,13 @@ +/* PR c/89521 */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -w" } */ + +#define A(name) __typeof (__builtin_##name (0)) name (); long name##1 () { return name (1); } +#define B(name) A(name) A(name##f) A(name##l) +B (ceil) +B (floor) +B (round) +B (trunc) +B (nearbyint) +B (rint) +B (logb) --- gcc/testsuite/gcc.dg/pr89521-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr89521-2.c (revision 270718) @@ -0,0 +1,42 @@ +/* PR c/89521 */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -w" } */ + +#define A(name) __typeof (__builtin_##name (0)) name (); \ + float name##1 () { return name (1); } \ + double name##2 () { return name (1); } +#define B(name) A(name) A(name##l) +B (cosh) +B (exp) +B (exp10) +B (exp2) +B (expm1) +B (gamma) +B (j0) +B (j1) +B (lgamma) +B (pow10) +B (sinh) +B (tgamma) +B (y0) +B (y1) +B (acos) +B (acosh) +B (asin) +B (asinh) +B (atan) +B (atanh) +B (cbrt) +B (cos) +B (erf) +B (erfc) +B (log) +B (log10) +B (log2) +B (log1p) +B (sin) +B (tan) +B (tanh) +B (sqrt) +B (fabs) +B (logb) 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-05 Jakub Jelinek PR middle-end/89590 * builtins.c (maybe_emit_free_warning): Punt if free doesn't have exactly one argument. * gcc.dg/pr89590.c: New test. --- gcc/builtins.c (revision 270718) +++ gcc/builtins.c (revision 270719) @@ -10088,6 +10088,9 @@ maybe_emit_sprintf_chk_warning (tree exp static void maybe_emit_free_warning (tree exp) { + if (call_expr_nargs (exp) != 1) + return; + tree arg = CALL_EXPR_ARG (exp, 0); STRIP_NOPS (arg); --- gcc/testsuite/gcc.dg/pr89590.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr89590.c (revision 270719) @@ -0,0 +1,11 @@ +/* PR middle-end/89590 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wall -w" } */ + +void free (void *); + +void +foo (void) +{ + ((void (*)()) free) (); +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-05 Jakub Jelinek PR target/89587 * config/rs6000/t-linux (MULTIARCH_DIRNAME): Set to non-empty only if_multiarch. --- gcc/config/rs6000/t-linux (revision 270719) +++ gcc/config/rs6000/t-linux (revision 270720) @@ -5,9 +5,9 @@ ifneq (,$(findstring powerpc64,$(target) MULTILIB_OSDIRNAMES := .=../lib64$(call if_multiarch,:powerpc64-linux-gnu) else ifneq (,$(findstring spe,$(target))) -MULTIARCH_DIRNAME := powerpc-linux-gnuspe$(if $(findstring 8548,$(with_cpu)),,v1) +MULTIARCH_DIRNAME := $(call if_multiarch,powerpc-linux-gnuspe$(if $(findstring 8548,$(with_cpu)),,v1)) else -MULTIARCH_DIRNAME := powerpc-linux-gnu +MULTIARCH_DIRNAME := $(call if_multiarch,powerpc-linux-gnu) endif endif ifneq (,$(findstring powerpcle,$(target))) 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-06 Jakub Jelinek PR c++/87148 * init.c (build_value_init_noctor): Ignore flexible array members. * g++.dg/ext/flexary34.C: New test. --- gcc/cp/init.c (revision 270720) +++ gcc/cp/init.c (revision 270721) @@ -419,6 +419,15 @@ build_value_init_noctor (tree type, tsub if (ftype == error_mark_node) continue; + /* Ignore flexible array members for value initialization. */ + if (TREE_CODE (ftype) == ARRAY_TYPE + && !COMPLETE_TYPE_P (ftype) + && !TYPE_DOMAIN (ftype) + && COMPLETE_TYPE_P (TREE_TYPE (ftype)) + && (next_initializable_field (DECL_CHAIN (field)) + == NULL_TREE)) + continue; + /* We could skip vfields and fields of types with user-defined constructors, but I think that won't improve performance at all; it should be simpler in general just --- gcc/testsuite/g++.dg/ext/flexary34.C (nonexistent) +++ gcc/testsuite/g++.dg/ext/flexary34.C (revision 270721) @@ -0,0 +1,10 @@ +// PR c++/87148 +// { dg-do compile } +// { dg-options "-pedantic" } + +struct Tst { int i; char t[]; }; // { dg-warning "forbids flexible array member" } + +Tst t {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } } +Tst u = Tst(); +void foo () { Tst u = {}; } +Tst *bar () { return new Tst (); } 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-08 Jakub Jelinek PR c++/82075 * g++.dg/cpp1z/decomp49.C: New test. --- gcc/testsuite/g++.dg/cpp1z/decomp49.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp1z/decomp49.C (revision 270722) @@ -0,0 +1,14 @@ +// PR c++/82075 +// { dg-do run { target c++11 } } +// { dg-options "" } + +struct B { }; +struct D : B { int i; }; + +int +main () +{ + auto [i] = D{}; // { dg-warning "only available with" "" { target c++14_down } } + if (i != 0) + __builtin_abort (); +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-09 Jakub Jelinek PR c/88568 * tree.c (handle_dll_attribute): Don't clear TREE_STATIC for dllimport on VAR_DECLs with RECORD_TYPE or UNION_TYPE DECL_CONTEXT. * g++.dg/other/pr88568.C: New test. --- gcc/tree.c (revision 270722) +++ gcc/tree.c (revision 270723) @@ -6456,8 +6456,11 @@ handle_dll_attribute (tree * pnode, tree a function global scope, unless declared static. */ if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) TREE_PUBLIC (node) = 1; - /* Clear TREE_STATIC because DECL_EXTERNAL is set. */ - TREE_STATIC (node) = 0; + /* Clear TREE_STATIC because DECL_EXTERNAL is set, unless + it is a C++ static data member. */ + if (DECL_CONTEXT (node) == NULL_TREE + || !RECORD_OR_UNION_TYPE_P (DECL_CONTEXT (node))) + TREE_STATIC (node) = 0; } if (*no_add_attrs == false) --- gcc/testsuite/g++.dg/other/pr88568.C (nonexistent) +++ gcc/testsuite/g++.dg/other/pr88568.C (revision 270723) @@ -0,0 +1,13 @@ +// PR c/88568 +// { dg-do compile } +// { dg-require-dll "" } + +struct S { + __attribute__((dllimport)) static const char foo[]; +}; + +int +foo (int x) +{ + return S::foo[x]; +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-11 Jakub Jelinek PR fortran/89651 * trans-openmp.c (gfc_omp_clause_default_ctor): Set TREE_NO_WARNING on decl if adding COND_EXPR for allocatable. (gfc_omp_clause_copy_ctor): Set TREE_NO_WARNING on dest. * gfortran.dg/gomp/pr89651.f90: New test. --- gcc/fortran/trans-openmp.c (revision 270723) +++ gcc/fortran/trans-openmp.c (revision 270724) @@ -548,6 +548,9 @@ gfc_omp_clause_default_ctor (tree clause build3_loc (input_location, COND_EXPR, void_type_node, cond, then_b, else_b)); + /* Avoid -W*uninitialized warnings. */ + if (DECL_P (decl)) + TREE_NO_WARNING (decl) = 1; } else gfc_add_expr_to_block (&block, then_b); @@ -654,6 +657,9 @@ gfc_omp_clause_copy_ctor (tree clause, t gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR, void_type_node, cond, then_b, else_b)); + /* Avoid -W*uninitialized warnings. */ + if (DECL_P (dest)) + TREE_NO_WARNING (dest) = 1; return gfc_finish_block (&block); } --- gcc/testsuite/gfortran.dg/gomp/pr89651.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/gomp/pr89651.f90 (revision 270724) @@ -0,0 +1,21 @@ +! PR fortran/89651 +! { dg-do compile } +! { dg-additional-options "-Wuninitialized" } + +program pr89651 + integer :: n + real, allocatable :: t(:) + n = 10 + allocate (t(n), source = 0.0) +!$omp parallel firstprivate(t) + print *, sum (t) ! { dg-bogus "lbound' may be used uninitialized in this function" } + ! { dg-bogus "ubound' may be used uninitialized in this function" "" { target *-*-* } .-1 } + ! { dg-bogus "offset' may be used uninitialized in this function" "" { target *-*-* } .-2 } +!$omp end parallel +!$omp parallel private(t) + t = 0.0 + print *, sum (t) ! { dg-bogus "lbound' may be used uninitialized in this function" } + ! { dg-bogus "ubound' may be used uninitialized in this function" "" { target *-*-* } .-1 } + ! { dg-bogus "offset' may be used uninitialized in this function" "" { target *-*-* } .-2 } +!$omp end parallel +end program pr89651 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-12 Jakub Jelinek PR middle-end/89663 * builtins.c (expand_builtin_int_roundingfn, expand_builtin_int_roundingfn_2): Return NULL_RTX instead of gcc_unreachable if validate_arglist fails. * gcc.c-torture/compile/pr89663-1.c: New test. * gcc.c-torture/compile/pr89663-2.c: New test. --- gcc/builtins.c (revision 270724) +++ gcc/builtins.c (revision 270725) @@ -2560,7 +2560,7 @@ expand_builtin_int_roundingfn (tree exp, tree arg; if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) - gcc_unreachable (); + return NULL_RTX; arg = CALL_EXPR_ARG (exp, 0); @@ -2696,7 +2696,7 @@ expand_builtin_int_roundingfn_2 (tree ex enum built_in_function fallback_fn = BUILT_IN_NONE; if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) - gcc_unreachable (); + return NULL_RTX; arg = CALL_EXPR_ARG (exp, 0); --- gcc/testsuite/gcc.c-torture/compile/pr89663-1.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr89663-1.c (revision 270725) @@ -0,0 +1,81 @@ +/* PR middle-end/89663 */ + +int irint (); +long lrint (); +long long llrint (); +int iround (); +long lround (); +long long llround (); +int iceil (); +long lceil (); +long long llceil (); +int ifloor (); +long lfloor (); +long long llfloor (); +int irintf (); +long lrintf (); +long long llrintf (); +int iroundf (); +long lroundf (); +long long llroundf (); +int iceilf (); +long lceilf (); +long long llceilf (); +int ifloorf (); +long lfloorf (); +long long llfloorf (); +int irintl (); +long lrintl (); +long long llrintl (); +int iroundl (); +long lroundl (); +long long llroundl (); +int iceill (); +long lceill (); +long long llceill (); +int ifloorl (); +long lfloorl (); +long long llfloorl (); + +void +foo (long long *p) +{ + int n = 0; +#define T(f) p[n++] = f (1); + T (irint) + T (lrint) + T (llrint) + T (iround) + T (lround) + T (llround) + T (iceil) + T (lceil) + T (llceil) + T (ifloor) + T (lfloor) + T (llfloor) + T (irintf) + T (lrintf) + T (llrintf) + T (iroundf) + T (lroundf) + T (llroundf) + T (iceilf) + T (lceilf) + T (llceilf) + T (ifloorf) + T (lfloorf) + T (llfloorf) + T (irintl) + T (lrintl) + T (llrintl) + T (iroundl) + T (lroundl) + T (llroundl) + T (iceill) + T (lceill) + T (llceill) + T (ifloorl) + T (lfloorl) + T (llfloorl) +} --- gcc/testsuite/gcc.c-torture/compile/pr89663-2.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr89663-2.c (revision 270725) @@ -0,0 +1,82 @@ +/* PR middle-end/89663 */ + +int irint (double); +long lrint (double); +long long llrint (double); +int iround (double); +long lround (double); +long long llround (double); +int iceil (double); +long lceil (double); +long long llceil (double); +int ifloor (double); +long lfloor (double); +long long llfloor (double); +int irintf (float); +long lrintf (float); +long long llrintf (float); +int iroundf (float); +long lroundf (float); +long long llroundf (float); +int iceilf (float); +long lceilf (float); +long long llceilf (float); +int ifloorf (float); +long lfloorf (float); +long long llfloorf (float); +int irintl (long double); +long lrintl (long double); +long long llrintl (long double); +int iroundl (long double); +long lroundl (long double); +long long llroundl (long double); +int iceill (long double); +long lceill (long double); +long long llceill (long double); +int ifloorl (long double); +long lfloorl (long double); +long long llfloorl (long double); + +void +foo (long long *p) +{ + int (*fn) (int); + int n = 0; +#define T(f) fn = (int (*) (int)) f; p[n++] = fn (1); + T (irint) + T (lrint) + T (llrint) + T (iround) + T (lround) + T (llround) + T (iceil) + T (lceil) + T (llceil) + T (ifloor) + T (lfloor) + T (llfloor) + T (irintf) + T (lrintf) + T (llrintf) + T (iroundf) + T (lroundf) + T (llroundf) + T (iceilf) + T (lceilf) + T (llceilf) + T (ifloorf) + T (lfloorf) + T (llfloorf) + T (irintl) + T (lrintl) + T (llrintl) + T (iroundl) + T (lroundl) + T (llroundl) + T (iceill) + T (lceill) + T (llceill) + T (ifloorl) + T (lfloorl) + T (llfloorl) +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-13 Jakub Jelinek PR middle-end/88588 * omp-simd-clone.c (ipa_simd_modify_stmt_ops): Handle PHI args. (ipa_simd_modify_function_body): Handle PHIs. * c-c++-common/gomp/pr88588.c: New test. --- gcc/omp-simd-clone.c (revision 270725) +++ gcc/omp-simd-clone.c (revision 270726) @@ -868,6 +868,18 @@ ipa_simd_modify_stmt_ops (tree *tp, int if (tp != orig_tp) { + if (gimple_code (info->stmt) == GIMPLE_PHI + && cand + && TREE_CODE (*orig_tp) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (*orig_tp, 0)) == PARM_DECL + && cand->alias_ptr_type) + { + gcc_assert (TREE_CODE (cand->alias_ptr_type) == SSA_NAME); + *orig_tp = cand->alias_ptr_type; + info->modified = true; + return NULL_TREE; + } + repl = build_fold_addr_expr (repl); gimple *stmt; if (is_gimple_debug (info->stmt)) @@ -884,7 +896,18 @@ ipa_simd_modify_stmt_ops (tree *tp, int stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl); repl = gimple_assign_lhs (stmt); } - gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt); + gimple_stmt_iterator gsi; + if (gimple_code (info->stmt) == GIMPLE_PHI) + { + gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun))); + /* Cache SSA_NAME for next time. */ + if (cand + && TREE_CODE (*orig_tp) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (*orig_tp, 0)) == PARM_DECL) + cand->alias_ptr_type = repl; + } + else + gsi = gsi_for_stmt (info->stmt); gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); *orig_tp = repl; } @@ -985,6 +1008,31 @@ ipa_simd_modify_function_body (struct cg { gimple_stmt_iterator gsi; + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gphi *phi = as_a (gsi_stmt (gsi)); + int i, n = gimple_phi_num_args (phi); + info.stmt = phi; + struct walk_stmt_info wi; + memset (&wi, 0, sizeof (wi)); + info.modified = false; + wi.info = &info; + for (i = 0; i < n; ++i) + { + int walk_subtrees = 1; + tree arg = gimple_phi_arg_def (phi, i); + tree op = arg; + ipa_simd_modify_stmt_ops (&op, &walk_subtrees, &wi); + if (op != arg) + { + SET_PHI_ARG_DEF (phi, i, op); + gcc_assert (TREE_CODE (op) == SSA_NAME); + if (gimple_phi_arg_edge (phi, i)->flags & EDGE_ABNORMAL) + SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op) = 1; + } + } + } + gsi = gsi_start_bb (bb); while (!gsi_end_p (gsi)) { --- gcc/testsuite/c-c++-common/gomp/pr88588.c (nonexistent) +++ gcc/testsuite/c-c++-common/gomp/pr88588.c (revision 270726) @@ -0,0 +1,18 @@ +/* PR middle-end/88588 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -O1" } */ + +int *v; + +#pragma omp declare simd +void +foo (int x) +{ + int *a = &x; + + for (;;) + { + *v = *a; + a = v; + } +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-14 Jakub Jelinek PR c++/89512 * semantics.c (finish_qualified_id_expr): Reject variable templates. * g++.dg/cpp1y/var-templ61.C: New test. --- gcc/cp/semantics.c (revision 270727) +++ gcc/cp/semantics.c (revision 270728) @@ -2067,6 +2067,14 @@ finish_qualified_id_expr (tree qualifyin } else if (BASELINK_P (expr)) ; + else if (!template_p + && TREE_CODE (expr) == TEMPLATE_DECL + && !DECL_FUNCTION_TEMPLATE_P (expr)) + { + if (complain & tf_error) + error ("%qE missing template arguments", expr); + return error_mark_node; + } else { /* In a template, return a SCOPE_REF for most qualified-ids --- gcc/testsuite/g++.dg/cpp1y/var-templ61.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp1y/var-templ61.C (revision 270728) @@ -0,0 +1,20 @@ +// PR c++/89512 +// { dg-do compile { target c++14 } } + +struct A { + template + static const int a = 0; +}; + +struct B { + template + static int foo () + { + return T::a; // { dg-error "missing template arguments" } + } +}; + +int bar () +{ + return B::foo (); // { dg-message "required from here" } +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-14 Jakub Jelinek PR tree-optimization/89703 * tree-ssa-strlen.c (valid_builtin_call): Punt if stmt call types aren't compatible also with builtin_decl_explicit. Check pure or non-pure status of BUILT_IN_STR{{,N}CMP,N{LEN,{CAT,CPY}{,_CHK}}} and BUILT_IN_STPNCPY{,_CHK}. * gcc.c-torture/compile/pr89703-1.c: New test. * gcc.c-torture/compile/pr89703-2.c: New test. --- gcc/tree-ssa-strlen.c (revision 270728) +++ gcc/tree-ssa-strlen.c (revision 270729) @@ -996,10 +996,18 @@ valid_builtin_call (gimple *stmt) return false; tree callee = gimple_call_fndecl (stmt); + tree decl = builtin_decl_explicit (DECL_FUNCTION_CODE (callee)); + if (decl + && decl != callee + && !gimple_builtin_call_types_compatible_p (stmt, decl)) + return false; + switch (DECL_FUNCTION_CODE (callee)) { case BUILT_IN_MEMCMP: case BUILT_IN_MEMCMP_EQ: + case BUILT_IN_STRCMP: + case BUILT_IN_STRNCMP: case BUILT_IN_STRCHR: case BUILT_IN_STRCHR_CHKP: case BUILT_IN_STRLEN: @@ -1024,6 +1032,8 @@ valid_builtin_call (gimple *stmt) case BUILT_IN_STPCPY_CHK: case BUILT_IN_STPCPY_CHKP: case BUILT_IN_STPCPY_CHK_CHKP: + case BUILT_IN_STPNCPY: + case BUILT_IN_STPNCPY_CHK: case BUILT_IN_STRCAT: case BUILT_IN_STRCAT_CHK: case BUILT_IN_STRCAT_CHKP: @@ -1032,6 +1042,10 @@ valid_builtin_call (gimple *stmt) case BUILT_IN_STRCPY_CHK: case BUILT_IN_STRCPY_CHKP: case BUILT_IN_STRCPY_CHK_CHKP: + case BUILT_IN_STRNCAT: + case BUILT_IN_STRNCAT_CHK: + case BUILT_IN_STRNCPY: + case BUILT_IN_STRNCPY_CHK: /* The above functions should be neither const nor pure. Punt if they aren't. */ if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE) --- gcc/testsuite/gcc.c-torture/compile/pr89703-1.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr89703-1.c (revision 270729) @@ -0,0 +1,13 @@ +/* PR tree-optimization/89703 */ + +typedef __SIZE_TYPE__ size_t; +extern char *strlen (const char *); +extern char *strnlen (const char *, size_t); +extern char c[2]; + +void +foo (char **q) +{ + q[0] = strlen (c); + q[1] = strnlen (c, 2); +} --- gcc/testsuite/gcc.c-torture/compile/pr89703-2.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr89703-2.c (revision 270729) @@ -0,0 +1,13 @@ +/* PR tree-optimization/89703 */ + +typedef __SIZE_TYPE__ size_t; +extern void *memcpy (void *, const void *, size_t); +extern char *strlen (const char *); +extern char c[2]; + +void +foo (char **q) +{ + memcpy (c, "a", 2); + q[0] = strlen (c); +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-14 Jakub Jelinek PR rtl-optimization/89679 * expmed.c (expand_mult_const): Don't add a REG_EQUAL note if it would contain a paradoxical SUBREG. * gcc.dg/pr89679.c: New test. --- gcc/expmed.c (revision 270729) +++ gcc/expmed.c (revision 270730) @@ -3179,11 +3179,19 @@ expand_mult_const (machine_mode mode, rt tem = gen_lowpart (nmode, op0); } - insn = get_last_insn (); - set_dst_reg_note (insn, REG_EQUAL, - gen_rtx_MULT (nmode, tem, - gen_int_mode (val_so_far, nmode)), - accum_inner); + /* Don't add a REG_EQUAL note if tem is a paradoxical SUBREG. + In that case, only the low bits of accum would be guaranteed to + be equal to the content of the REG_EQUAL note, the upper bits + can be anything. */ + if (!paradoxical_subreg_p (tem)) + { + insn = get_last_insn (); + set_dst_reg_note (insn, REG_EQUAL, + gen_rtx_MULT (nmode, tem, + gen_int_mode (val_so_far, + nmode)), + accum_inner); + } } } --- gcc/testsuite/gcc.dg/pr89679.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr89679.c (revision 270730) @@ -0,0 +1,26 @@ +/* PR rtl-optimization/89679 */ +/* { dg-do run } */ +/* { dg-options "-Og -frerun-cse-after-loop -fno-tree-fre" } */ + +unsigned short g; + +void +foo (unsigned long long x) +{ + if (x != 0xffff) + __builtin_abort (); +} + +int +main () +{ +#if __SIZEOF_SHORT__ == 2 && __SIZEOF_INT__ == 4 && __CHAR_BIT__ == 8 + unsigned short d = 0; + unsigned long long x, c = ~0; + c = c >> d; + __builtin_memset (&d, c, 2); + x = d + g; + foo (x); +#endif + return 0; +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-15 Jakub Jelinek PR debug/89704 * dwarf2out.c (add_const_value_attribute): Return false for MINUS, SIGN_EXTEND and ZERO_EXTEND. * gcc.dg/debug/pr89704.c: New test. --- gcc/dwarf2out.c (revision 270731) +++ gcc/dwarf2out.c (revision 270732) @@ -19675,6 +19675,9 @@ add_const_value_attribute (dw_die_ref di case HIGH: case CONST_FIXED: + case MINUS: + case SIGN_EXTEND: + case ZERO_EXTEND: return false; case MEM: --- gcc/testsuite/gcc.dg/debug/pr89704.c (nonexistent) +++ gcc/testsuite/gcc.dg/debug/pr89704.c (revision 270732) @@ -0,0 +1,14 @@ +/* PR debug/89704 */ +/* { dg-do compile } */ + +typedef __INTPTR_TYPE__ intptr_t; + +int +foo (void) +{ + lab1:; + lab2:; + static int i = (intptr_t) &&lab1 - (intptr_t) &&lab2; + static int j = (intptr_t) &&lab1 - (intptr_t) &&lab2; + return i; +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-19 Jakub Jelinek PR c/89734 * c-decl.c (grokdeclarator): Call c_build_qualified_type on function return type even if quals_used is 0. Formatting fixes. * gcc.dg/pr89734.c: New test. --- gcc/c/c-decl.c (revision 270732) +++ gcc/c/c-decl.c (revision 270733) @@ -6436,10 +6436,12 @@ grokdeclarator (const struct c_declarato quals_used &= TYPE_QUAL_ATOMIC; if (quals_used && VOID_TYPE_P (type) && really_funcdef) pedwarn (specs_loc, 0, - "function definition has qualified void return type"); + "function definition has qualified void " + "return type"); else warning_at (specs_loc, OPT_Wignored_qualifiers, - "type qualifiers ignored on function return type"); + "type qualifiers ignored on function " + "return type"); /* Ensure an error for restrict on invalid types; the DR#423 resolution is not entirely clear about @@ -6449,8 +6451,7 @@ grokdeclarator (const struct c_declarato && (!POINTER_TYPE_P (type) || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))) error_at (loc, "invalid use of %"); - if (quals_used) - type = c_build_qualified_type (type, quals_used); + type = c_build_qualified_type (type, quals_used); } type_quals = TYPE_UNQUALIFIED; --- gcc/testsuite/gcc.dg/pr89734.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr89734.c (revision 270733) @@ -0,0 +1,12 @@ +/* PR c/89734 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +typedef const int CI; +typedef _Atomic int AI; + +CI foo (void); +const int foo (void); + +AI baz (void); +_Atomic int baz (void); 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-19 Jakub Jelinek PR target/89726 * config/i386/i386.c (ix86_expand_floorceildf_32): In ceil compensation use x2 += 1 instead of x2 -= -1 and when honoring signed zeros, do another copysign after the compensation. * gcc.target/i386/fpprec-1.c (x): Add 6 new constants. (expect_round, expect_rint, expect_floor, expect_ceil, expect_trunc): Add expected results for them. --- gcc/config/i386/i386.c (revision 270733) +++ gcc/config/i386/i386.c (revision 270734) @@ -45624,8 +45624,10 @@ ix86_expand_floorceildf_32 (rtx operand0 x2 -= 1; Compensate. Ceil: if (x2 < x) - x2 -= -1; - return x2; + x2 += 1; + if (HONOR_SIGNED_ZEROS (mode)) + x2 = copysign (x2, x); + return x2; */ machine_mode mode = GET_MODE (operand0); rtx xa, TWO52, tmp, one, res, mask; @@ -45651,17 +45653,16 @@ ix86_expand_floorceildf_32 (rtx operand0 /* xa = copysign (xa, operand1) */ ix86_sse_copysign_to_positive (xa, xa, res, mask); - /* generate 1.0 or -1.0 */ - one = force_reg (mode, - const_double_from_real_value (do_floor - ? dconst1 : dconstm1, mode)); + /* generate 1.0 */ + one = force_reg (mode, const_double_from_real_value (dconst1, mode)); /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */ tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor); emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp))); - /* We always need to subtract here to preserve signed zero. */ - tmp = expand_simple_binop (mode, MINUS, + tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS, xa, tmp, NULL_RTX, 0, OPTAB_DIRECT); + if (!do_floor && HONOR_SIGNED_ZEROS (mode)) + ix86_sse_copysign_to_positive (tmp, tmp, res, mask); emit_move_insn (res, tmp); emit_label (label); --- gcc/testsuite/gcc.target/i386/fpprec-1.c (revision 270733) +++ gcc/testsuite/gcc.target/i386/fpprec-1.c (revision 270734) @@ -11,6 +11,9 @@ double x[] = { __builtin_nan(""), __buil 0x1.0000000000001p-1, 0x1.fffffffffffffp-2, 0x1.0000000000001p+0, 0x1.fffffffffffffp-1, 0x1.8000000000001p+0, 0x1.7ffffffffffffp+0, + -0x1.0000000000001p-1, -0x1.fffffffffffffp-2, + -0x1.0000000000001p+0, -0x1.fffffffffffffp-1, + -0x1.8000000000001p+0, -0x1.7ffffffffffffp+0, -0.0, 0.0, -0.5, 0.5, -1.0, 1.0, -1.5, 1.5, -2.0, 2.0, -2.5, 2.5 }; #define NUM (sizeof(x)/sizeof(double)) @@ -19,6 +22,7 @@ double expect_round[] = { __builtin_nan( -0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023, -0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 2.0, 1.0, + -1.0, -0.0, -1.0, -1.0, -2.0, -1.0, -0.0, 0.0, -1.0, 1.0, -1.0, 1.0, -2.0, 2.0, -2.0, 2.0, -3.0, 3.0 }; @@ -26,6 +30,7 @@ double expect_rint[] = { __builtin_nan(" -0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023, -0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 2.0, 1.0, + -1.0, -0.0, -1.0, -1.0, -2.0, -1.0, -0.0, 0.0, -0.0, 0.0, -1.0, 1.0, -2.0, 2.0, -2.0, 2.0, -2.0, 2.0 }; @@ -33,6 +38,7 @@ double expect_floor[] = { __builtin_nan( -0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, + -1.0, -1.0, -2.0, -1.0, -2.0, -2.0, -0.0, 0.0, -1.0, 0.0, -1.0, 1.0, -2.0, 1.0, -2.0, 2.0, -3.0, 2.0 }; @@ -40,6 +46,7 @@ double expect_ceil[] = { __builtin_nan(" -0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023, -0.0, 1.0, 1.0, 1.0, 2.0, 1.0, 2.0, 2.0, + -0.0, -0.0, -1.0, -0.0, -1.0, -1.0, -0.0, 0.0, -0.0, 1.0, -1.0, 1.0, -1.0, 2.0, -2.0, 2.0, -2.0, 3.0 }; @@ -47,6 +54,7 @@ double expect_trunc[] = { __builtin_nan( -0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+1023, -0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, + -0.0, -0.0, -1.0, -0.0, -1.0, -1.0, -0.0, 0.0, -0.0, 0.0, -1.0, 1.0, -1.0, 1.0, -2.0, 2.0, -2.0, 2.0 }; 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-19 Jakub Jelinek PR target/89752 * gimplify.c (gimplify_asm_expr): For output argument with TREE_ADDRESSABLE type, clear allows_reg if it allows memory, otherwise diagnose error. * g++.dg/ext/asm15.C: Check for particular diagnostic wording. * g++.dg/ext/asm16.C: Likewise. * g++.dg/ext/asm17.C: New test. --- gcc/gimplify.c (revision 270734) +++ gcc/gimplify.c (revision 270735) @@ -6144,6 +6144,19 @@ gimplify_asm_expr (tree *expr_p, gimple_ is_inout = false; } + /* If we can't make copies, we can only accept memory. */ + if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (link)))) + { + if (allows_mem) + allows_reg = 0; + else + { + error ("impossible constraint in %"); + error ("non-memory output %d must stay in memory", i); + return GS_ERROR; + } + } + if (!allows_reg && allows_mem) mark_addressable (TREE_VALUE (link)); --- gcc/testsuite/g++.dg/ext/asm15.C (revision 270734) +++ gcc/testsuite/g++.dg/ext/asm15.C (revision 270735) @@ -6,5 +6,6 @@ struct S { S (); ~S (); int s; }; void foo (S &s) { - __asm volatile ("" : "+r" (s) : : "memory"); // { dg-error "" } + __asm volatile ("" : "+r" (s) : : "memory"); // { dg-error "impossible constraint" } + // { dg-error "must stay in memory" "" { target *-*-* } .-1 } } --- gcc/testsuite/g++.dg/ext/asm16.C (revision 270734) +++ gcc/testsuite/g++.dg/ext/asm16.C (revision 270735) @@ -6,5 +6,6 @@ struct S { S (); ~S (); int s[64]; } s; void foo () { - __asm volatile ("" : "=r" (s) : : "memory"); // { dg-error "" } + __asm volatile ("" : "=r" (s) : : "memory"); // { dg-error "impossible constraint" } + // { dg-error "must stay in memory" "" { target *-*-* } .-1 } } --- gcc/testsuite/g++.dg/ext/asm17.C (nonexistent) +++ gcc/testsuite/g++.dg/ext/asm17.C (revision 270735) @@ -0,0 +1,11 @@ +// PR target/89752 +// { dg-do compile } + +struct A { A (); ~A (); short c; }; + +void +foo () +{ + A a0, a1; + __asm volatile ("" : "+rm" (a0), "+rm" (a1)); +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-19 Jakub Jelinek PR rtl-optimization/89768 * loop-unroll.c (unroll_loop_constant_iterations): Use gen_int_mode instead of GEN_INT. (unroll_loop_runtime_iterations): Likewise. --- gcc/loop-unroll.c (revision 270735) +++ gcc/loop-unroll.c (revision 270736) @@ -630,7 +630,7 @@ unroll_loop_constant_iterations (struct if (loop->any_likely_upper_bound) loop->nb_iterations_likely_upper_bound = wi::udiv_trunc (loop->nb_iterations_likely_upper_bound, max_unroll + 1); - desc->niter_expr = GEN_INT (desc->niter); + desc->niter_expr = gen_int_mode (desc->niter, desc->mode); /* Remove the edges. */ FOR_EACH_VEC_ELT (remove_edges, i, e) @@ -996,7 +996,8 @@ unroll_loop_runtime_iterations (struct l preheader->frequency += iter_freq; preheader->count += iter_count; single_succ_edge (preheader)->count = preheader->count; - branch_code = compare_and_jump_seq (copy_rtx (niter), GEN_INT (j), EQ, + branch_code = compare_and_jump_seq (copy_rtx (niter), + gen_int_mode (j, desc->mode), EQ, block_label (preheader), p, NULL); 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-20 Jakub Jelinek PR target/89752 * lra-constraints.c (process_alt_operands) : For BLKmode, don't update this_alternative nor this_alternative_set. --- gcc/lra-constraints.c (revision 270736) +++ gcc/lra-constraints.c (revision 270737) @@ -2315,6 +2315,8 @@ process_alt_operands (int only_alternati break; reg: + if (mode == BLKmode) + break; this_alternative = reg_class_subunion[this_alternative][cl]; IOR_HARD_REG_SET (this_alternative_set, reg_class_contents[cl]); @@ -2325,8 +2327,6 @@ process_alt_operands (int only_alternati IOR_HARD_REG_SET (this_costly_alternative_set, reg_class_contents[cl]); } - if (mode == BLKmode) - break; winreg = true; if (REG_P (op)) { 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-21 Jakub Jelinek PR c++/89767 * parser.c (cp_parser_lambda_introducer): Add ids and first_capture_id variables, check for duplicates in this function. * lambda.c (add_capture): Don't check for duplicates nor use IDENTIFIER_MARKED. (register_capture_members): Don't clear IDENTIFIER_MARKED here. * g++.dg/cpp1y/lambda-init18.C: New test. * g++.dg/cpp1y/lambda-init19.C: New test. * g++.dg/cpp1y/pr89767.C: New test. --- gcc/cp/parser.c (revision 270737) +++ gcc/cp/parser.c (revision 270738) @@ -10010,6 +10010,11 @@ cp_parser_lambda_introducer (cp_parser* first = false; } + hash_set *ids = NULL; +#if GCC_VERSION >= 7000 + char ids_buf[sizeof (hash_set) + __alignof__ (hash_set) - 1]; +#endif + tree first_capture_id = NULL_TREE; while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE)) { cp_token* capture_token; @@ -10044,11 +10049,14 @@ cp_parser_lambda_introducer (cp_parser* pedwarn (loc, 0, "explicit by-copy capture of % redundant " "with by-copy capture default"); cp_lexer_consume_token (parser->lexer); - add_capture (lambda_expr, - /*id=*/this_identifier, - /*initializer=*/finish_this_expr (), - /*by_reference_p=*/true, - explicit_init_p); + if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr)) + pedwarn (input_location, 0, + "already captured %qD in lambda expression", + this_identifier); + else + add_capture (lambda_expr, /*id=*/this_identifier, + /*initializer=*/finish_this_expr (), + /*by_reference_p=*/true, explicit_init_p); continue; } @@ -10062,11 +10070,14 @@ cp_parser_lambda_introducer (cp_parser* "-std=c++1z or -std=gnu++1z"); cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer); - add_capture (lambda_expr, - /*id=*/this_identifier, - /*initializer=*/finish_this_expr (), - /*by_reference_p=*/false, - explicit_init_p); + if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr)) + pedwarn (input_location, 0, + "already captured %qD in lambda expression", + this_identifier); + else + add_capture (lambda_expr, /*id=*/this_identifier, + /*initializer=*/finish_this_expr (), + /*by_reference_p=*/false, explicit_init_p); continue; } @@ -10190,13 +10201,44 @@ cp_parser_lambda_introducer (cp_parser* "default", capture_id); } - add_capture (lambda_expr, - capture_id, - capture_init_expr, - /*by_reference_p=*/capture_kind == BY_REFERENCE, - explicit_init_p); + /* Check for duplicates. + Optimize for the zero or one explicit captures cases and only create + the hash_set after adding second capture. */ + bool found = false; + if (ids && ids->elements ()) + found = ids->add (capture_id); + else if (first_capture_id == NULL_TREE) + first_capture_id = capture_id; + else if (capture_id == first_capture_id) + found = true; + else + { +#if GCC_VERSION >= 7000 + ids = new (ids_buf + + (-(uintptr_t) ids_buf + & (__alignof__ (hash_set ) - 1))) hash_set ; +#else + ids = new hash_set ; +#endif + ids->add (first_capture_id); + ids->add (capture_id); + } + if (found) + pedwarn (input_location, 0, + "already captured %qD in lambda expression", capture_id); + else + add_capture (lambda_expr, capture_id, capture_init_expr, + /*by_reference_p=*/capture_kind == BY_REFERENCE, + explicit_init_p); } + if (ids) +#if GCC_VERSION >= 7000 + ids->~hash_set (); +#else + delete ids; +#endif + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); } --- gcc/cp/lambda.c (revision 270737) +++ gcc/cp/lambda.c (revision 270738) @@ -612,19 +612,6 @@ add_capture (tree lambda, tree id, tree IDENTIFIER_LENGTH (id) + 1); name = get_identifier (buf); - /* If TREE_TYPE isn't set, we're still in the introducer, so check - for duplicates. */ - if (!LAMBDA_EXPR_CLOSURE (lambda)) - { - if (IDENTIFIER_MARKED (name)) - { - pedwarn (input_location, 0, - "already captured %qD in lambda expression", id); - return NULL_TREE; - } - IDENTIFIER_MARKED (name) = true; - } - if (variadic) type = make_pack_expansion (type); @@ -685,8 +672,6 @@ register_capture_members (tree captures) if (PACK_EXPANSION_P (field)) field = PACK_EXPANSION_PATTERN (field); - /* We set this in add_capture to avoid duplicates. */ - IDENTIFIER_MARKED (DECL_NAME (field)) = false; finish_member_declaration (field); } --- gcc/testsuite/g++.dg/cpp1y/pr89767.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp1y/pr89767.C (revision 270738) @@ -0,0 +1,32 @@ +// PR c++/89767 +// { dg-do compile { target c++14 } } +// { dg-options "-O2 -Wall" } + +template struct e { using g = d; }; +template class> using h = e; +template class i> +using j = typename h::g; +template int k(c); +template class au; +struct l { template using m = typename c::f; }; +struct s : l { using af = j *, m>; }; +template struct o; +template using q = typename o::g; +template struct r; +template struct r { typedef c aj; }; +template struct al { typename r::aj operator*(); void operator++(); }; +template +bool operator!=(al, al); +template struct ap; +template +struct ap : ap<1, as...> {}; +template struct ap {}; +template class au : public ap<0, at...> {}; +template +struct o> : o

> {}; +template struct o<0, au> { typedef ar g; }; +template constexpr ar av(ap __t) { return ar (); } +template constexpr q> aw(au __t) { av

(__t); return q> (); } +struct bg { typedef s::af af; }; +struct F { typedef al bk; bk begin(); bk end(); }; +void bo() { int t = 0; F cv; for (auto bp : cv) [t, n = k(aw<1>(bp))] {}; } --- gcc/testsuite/g++.dg/cpp1y/lambda-init18.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp1y/lambda-init18.C (revision 270738) @@ -0,0 +1,12 @@ +// PR c++/89767 +// { dg-do compile { target c++14 } } + +void bar (int); + +void +foo () +{ + int x = 0; + auto z = [x, y = [x] { bar (x); }] { y (); bar (x); }; + z (); +} --- gcc/testsuite/g++.dg/cpp1y/lambda-init19.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp1y/lambda-init19.C (revision 270738) @@ -0,0 +1,15 @@ +// PR c++/89767 +// { dg-do compile { target c++14 } } + +void bar (int); + +void +foo () +{ + int x = 0; + int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0; + auto z = [x, y = [x] { bar (x); }, x] { y (); bar (x); }; // { dg-error "already captured 'x' in lambda expression" } + auto w = [x, a, b, c, d, y = [x] { bar (x); }, e, f, g, h, x] { y (); bar (x + a + b + c + d + e + f + g + h); }; // { dg-error "already captured 'x' in lambda expression" } + z (); + w (); +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-22 Jakub Jelinek PR c++/60702 * cp-tree.h (get_tls_wrapper_fn): Remove declaration. (maybe_get_tls_wrapper_call): Declare. * decl2.c (get_tls_wrapper_fn): Make static. (maybe_get_tls_wrapper_call): New function. * typeck.c (build_class_member_access_expr): Handle accesses to TLS variables. * semantics.c (finish_qualified_id_expr): Likewise. (finish_id_expression_1): Use maybe_get_tls_wrapper_call. * pt.c (tsubst_copy_and_build): Likewise. * g++.dg/tls/thread_local11.C: New test. * g++.dg/tls/thread_local11.h: New test. * g++.dg/tls/thread_local12a.C: New test. * g++.dg/tls/thread_local12b.C: New test. * g++.dg/tls/thread_local12c.C: New test. * g++.dg/tls/thread_local12d.C: New test. * g++.dg/tls/thread_local12e.C: New test. * g++.dg/tls/thread_local12f.C: New test. * g++.dg/tls/thread_local12g.C: New test. * g++.dg/tls/thread_local12h.C: New test. * g++.dg/tls/thread_local12i.C: New test. * g++.dg/tls/thread_local12j.C: New test. * g++.dg/tls/thread_local12k.C: New test. * g++.dg/tls/thread_local12l.C: New test. --- gcc/cp/typeck.c (revision 270738) +++ gcc/cp/typeck.c (revision 270739) @@ -2437,6 +2437,12 @@ build_class_member_access_expr (cp_expr /* A static data member. */ result = member; mark_exp_read (object); + + if (tree wrap = maybe_get_tls_wrapper_call (result)) + /* Replace an evaluated use of the thread_local variable with + a call to its wrapper. */ + result = wrap; + /* If OBJECT has side-effects, they are supposed to occur. */ if (TREE_SIDE_EFFECTS (object)) result = build2 (COMPOUND_EXPR, TREE_TYPE (result), object, result); --- gcc/cp/pt.c (revision 270738) +++ gcc/cp/pt.c (revision 270739) @@ -18894,17 +18894,10 @@ tsubst_copy_and_build (tree t, { tree r = tsubst_copy (t, args, complain, in_decl); /* ??? We're doing a subset of finish_id_expression here. */ - if (VAR_P (r) - && !processing_template_decl - && !cp_unevaluated_operand - && (TREE_STATIC (r) || DECL_EXTERNAL (r)) - && CP_DECL_THREAD_LOCAL_P (r)) - { - if (tree wrap = get_tls_wrapper_fn (r)) - /* Replace an evaluated use of the thread_local variable with - a call to its wrapper. */ - r = build_cxx_call (wrap, 0, NULL, tf_warning_or_error); - } + if (tree wrap = maybe_get_tls_wrapper_call (r)) + /* Replace an evaluated use of the thread_local variable with + a call to its wrapper. */ + r = wrap; else if (outer_automatic_var_p (r)) r = process_outer_var_ref (r, complain); --- gcc/cp/semantics.c (revision 270738) +++ gcc/cp/semantics.c (revision 270739) @@ -2125,6 +2125,8 @@ finish_qualified_id_expr (tree qualifyin expr = build_qualified_name (TREE_TYPE (expr), qualifying_class, expr, template_p); + else if (tree wrap = maybe_get_tls_wrapper_call (expr)) + expr = wrap; expr = convert_from_reference (expr); } @@ -3720,18 +3722,10 @@ finish_id_expression (tree id_expression *non_integral_constant_expression_p = true; } - tree wrap; - if (VAR_P (decl) - && !cp_unevaluated_operand - && !processing_template_decl - && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)) - && CP_DECL_THREAD_LOCAL_P (decl) - && (wrap = get_tls_wrapper_fn (decl))) - { - /* Replace an evaluated use of the thread_local variable with - a call to its wrapper. */ - decl = build_cxx_call (wrap, 0, NULL, tf_warning_or_error); - } + if (tree wrap = maybe_get_tls_wrapper_call (decl)) + /* Replace an evaluated use of the thread_local variable with + a call to its wrapper. */ + decl = wrap; else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR && !dependent_p && variable_template_p (TREE_OPERAND (decl, 0))) --- gcc/cp/decl2.c (revision 270738) +++ gcc/cp/decl2.c (revision 270739) @@ -3357,7 +3357,7 @@ get_tls_init_fn (tree var) VAR and then returns a reference to VAR. The wrapper function is used in place of VAR everywhere VAR is mentioned. */ -tree +static tree get_tls_wrapper_fn (tree var) { /* Only C++11 TLS vars need this wrapper fn. */ @@ -3409,6 +3409,22 @@ get_tls_wrapper_fn (tree var) return fn; } +/* If EXPR is a thread_local variable that should be wrapped by init + wrapper function, return a call to that function, otherwise return + NULL. */ + +tree +maybe_get_tls_wrapper_call (tree expr) +{ + if (VAR_P (expr) + && !processing_template_decl + && !cp_unevaluated_operand + && CP_DECL_THREAD_LOCAL_P (expr)) + if (tree wrap = get_tls_wrapper_fn (expr)) + return build_cxx_call (wrap, 0, NULL, tf_warning_or_error); + return NULL; +} + /* At EOF, generate the definition for the TLS wrapper function FN: T& var_wrapper() { --- gcc/cp/cp-tree.h (revision 270738) +++ gcc/cp/cp-tree.h (revision 270739) @@ -6390,7 +6390,7 @@ extern tree cp_build_parm_decl (tree, extern tree get_guard (tree); extern tree get_guard_cond (tree, bool); extern tree set_guard (tree); -extern tree get_tls_wrapper_fn (tree); +extern tree maybe_get_tls_wrapper_call (tree); extern void mark_needed (tree); extern bool decl_needed_p (tree); extern void note_vague_linkage_fn (tree); --- gcc/testsuite/g++.dg/tls/thread_local11.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local11.C (revision 270739) @@ -0,0 +1,48 @@ +// PR c++/60702 +// { dg-do compile { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } +// { dg-additional-options "-fdump-tree-gimple" } +// { dg-final { scan-tree-dump-times "_ZTW2s1" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTW2s2" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTW2s3" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTW2s4" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u1E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u2E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u3E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u4E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u5E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u6E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u7E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u8E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s1" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s2" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s3" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s4" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u1E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u2E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u3E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u4E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u5E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u6E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u7E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u8E" 1 "gimple" } } + +#include "thread_local11.h" + +void +foo () +{ + f1 (); + f2 (); + f3 (); + f4 (); + f5 (); + f6 (); + f7<0> (); + f8<0> (); + f9<0> (); + f10<0> (); + f11<0> (); + f12<0> (); +} --- gcc/testsuite/g++.dg/tls/thread_local12a.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12a.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f1 ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12b.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12b.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f2 () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12c.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12c.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f3 ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12d.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12d.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f4 () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12e.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12e.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f5 ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12f.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12f.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f6 () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12g.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12g.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f7<0> ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12h.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12h.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f8<0> () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12i.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12i.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f9<0> ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12j.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12j.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f10<0> () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12k.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12k.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f11<0> ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12l.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local12l.C (revision 270739) @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f12<0> () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local11.h (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local11.h (revision 270739) @@ -0,0 +1,26 @@ +// PR c++/60702 + +extern "C" void abort (); +struct S { S () { i = 42; }; int i; }; +thread_local S s1, s2, s3, s4; +struct T { static thread_local S u1, u2, u3, u4, u5, u6, u7, u8; int i; } t; +thread_local S T::u1, T::u2, T::u3, T::u4, T::u5, T::u6, T::u7, T::u8; + +S *f1 () { return &s1; } +int *f2 () { return &s2.i; } +S *f3 () { return &t.u1; } +int *f4 () { return &t.u2.i; } +S *f5 () { return &T::u3; } +int *f6 () { return &T::u4.i; } +template +S *f7 () { return &s3; } +template +int *f8 () { return &s4.i; } +template +S *f9 () { return &t.u5; } +template +int *f10 () { return &t.u6.i; } +template +S *f11 () { return &T::u7; } +template +int *f12 () { return &T::u8.i; } 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-25 Jakub Jelinek PR c++/60702 * g++.dg/tls/thread_local11.C: Remove scan-tree-dump-times directives for _ZTH* calls. * g++.dg/tls/thread_local11a.C: New test. --- gcc/testsuite/g++.dg/tls/thread_local11.C (revision 270739) +++ gcc/testsuite/g++.dg/tls/thread_local11.C (revision 270740) @@ -15,18 +15,6 @@ // { dg-final { scan-tree-dump-times "_ZTWN1T2u6E" 2 "gimple" } } // { dg-final { scan-tree-dump-times "_ZTWN1T2u7E" 2 "gimple" } } // { dg-final { scan-tree-dump-times "_ZTWN1T2u8E" 2 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTH2s1" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTH2s2" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTH2s3" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTH2s4" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTHN1T2u1E" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTHN1T2u2E" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTHN1T2u3E" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTHN1T2u4E" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTHN1T2u5E" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTHN1T2u6E" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTHN1T2u7E" 1 "gimple" } } -// { dg-final { scan-tree-dump-times "_ZTHN1T2u8E" 1 "gimple" } } #include "thread_local11.h" --- gcc/testsuite/g++.dg/tls/thread_local11a.C (nonexistent) +++ gcc/testsuite/g++.dg/tls/thread_local11a.C (revision 270740) @@ -0,0 +1,20 @@ +// PR c++/60702 +// { dg-do compile { target c++11 } } +// { dg-add-options tls } +// { dg-require-alias "" } +// { dg-require-effective-target tls_runtime } +// { dg-additional-options "-fdump-tree-gimple" } +// { dg-final { scan-tree-dump-times "_ZTH2s1" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s2" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s3" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s4" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u1E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u2E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u3E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u4E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u5E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u6E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u7E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u8E" 1 "gimple" } } + +#include "thread_local11.C" 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-26 Jakub Jelinek PR c++/89796 * semantics.c (finish_omp_atomic): Add warning_sentinel for -Wunused-value around finish_expr_stmt call. * g++.dg/gomp/pr89796.C: New test. * gcc.dg/gomp/pr89796.c: New test. --- gcc/cp/semantics.c (revision 270740) +++ gcc/cp/semantics.c (revision 270741) @@ -8462,6 +8462,11 @@ finish_omp_atomic (enum tree_code code, stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt); OMP_ATOMIC_SEQ_CST (stmt) = seq_cst; } + + /* Avoid -Wunused-value warnings here, the whole construct has side-effects + and even if it might be wrapped from fold-const.c or c-omp.c wrapped + in some tree that appears to be unused, the value is not unused. */ + warning_sentinel w (warn_unused_value); finish_expr_stmt (stmt); } --- gcc/testsuite/gcc.dg/gomp/pr89796.c (nonexistent) +++ gcc/testsuite/gcc.dg/gomp/pr89796.c (revision 270741) @@ -0,0 +1,23 @@ +/* PR c++/89796 */ +/* { dg-do compile } */ +/* { dg-additional-options "-Wunused-value" } */ + +int +f1 (int *p) +{ + int r; + #pragma omp atomic capture /* { dg-bogus "value computed is not used" } */ + { r = *p; (*p)++; } + return r; +} + +int +f2 (int *p) +{ + int s + = ({ int r; + #pragma omp atomic capture /* { dg-bogus "value computed is not used" } */ + { r = *p; (*p)++; } + r; }); + return s; +} --- gcc/testsuite/g++.dg/gomp/pr89796.C (nonexistent) +++ gcc/testsuite/g++.dg/gomp/pr89796.C (revision 270741) @@ -0,0 +1,53 @@ +// PR c++/89796 +// { dg-do compile } +// { dg-additional-options "-Wunused-value" } + +int +f1 (int &c) +{ + int r; + #pragma omp atomic capture // { dg-bogus "value computed is not used" } + { r = c; c++; } + return r; +} + +template +int +f2 (int &c) +{ + int r; + #pragma omp atomic capture // { dg-bogus "value computed is not used" } + { r = c; c++; } + return r; +} + +int +f3 (int &c) +{ + return f2 <0> (c); +} + +int +f4 (int *p) +{ + int r; + #pragma omp atomic capture // { dg-bogus "value computed is not used" } + { r = *p; (*p)++; } + return r; +} + +template +int +f5 (int *p) +{ + int r; + #pragma omp atomic capture // { dg-bogus "value computed is not used" } + { r = *p; (*p)++; } + return r; +} + +int +f6 (int *p) +{ + return f5 <0> (p); +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-28 Jakub Jelinek PR middle-end/89621 * tree-inline.h (struct copy_body_data): Add dont_remap_vla_if_no_change flag. * tree-inline.c (remap_type_3, remap_type_2): New functions. (remap_type): Don't remap vla types if id->dont_remap_vla_if_no_change and remap_type_2 returns false. * omp-low.c (new_omp_context): Set ctx->cb.dont_remap_vla_if_no_change. * gfortran.dg/gomp/pr89621.f90: New test. --- gcc/tree-inline.h (revision 270741) +++ gcc/tree-inline.h (revision 270742) @@ -119,6 +119,13 @@ struct copy_body_data /* > 0 if we are remapping a type currently. */ int remapping_type_depth; + /* Usually copy_decl callback always creates new decls, in that case + we want to remap all variably_modified_type_p types. If this flag + is set, remap_type will do further checks to see if remap_decl + of any decls mentioned in the type will remap to anything but itself + and only in that case will actually remap the type. */ + bool dont_remap_vla_if_no_change; + /* A function to be called when duplicating BLOCK nodes. */ void (*transform_lang_insert_block) (tree); --- gcc/tree-inline.c (revision 270741) +++ gcc/tree-inline.c (revision 270742) @@ -578,6 +578,92 @@ remap_type_1 (tree type, copy_body_data return new_tree; } +/* Helper function for remap_type_2, called through walk_tree. */ + +static tree +remap_type_3 (tree *tp, int *walk_subtrees, void *data) +{ + copy_body_data *id = (copy_body_data *) data; + + if (TYPE_P (*tp)) + *walk_subtrees = 0; + + else if (DECL_P (*tp) && remap_decl (*tp, id) != *tp) + return *tp; + + return NULL_TREE; +} + +/* Return true if TYPE needs to be remapped because remap_decl on any + needed embedded decl returns something other than that decl. */ + +static bool +remap_type_2 (tree type, copy_body_data *id) +{ + tree t; + +#define RETURN_TRUE_IF_VAR(T) \ + do \ + { \ + tree _t = (T); \ + if (_t) \ + { \ + if (DECL_P (_t) && remap_decl (_t, id) != _t) \ + return true; \ + if (!TYPE_SIZES_GIMPLIFIED (type) \ + && walk_tree (&_t, remap_type_3, id, NULL)) \ + return true; \ + } \ + } \ + while (0) + + switch (TREE_CODE (type)) + { + case POINTER_TYPE: + case REFERENCE_TYPE: + case FUNCTION_TYPE: + case METHOD_TYPE: + return remap_type_2 (TREE_TYPE (type), id); + + case INTEGER_TYPE: + case REAL_TYPE: + case FIXED_POINT_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + RETURN_TRUE_IF_VAR (TYPE_MIN_VALUE (type)); + RETURN_TRUE_IF_VAR (TYPE_MAX_VALUE (type)); + return false; + + case ARRAY_TYPE: + if (remap_type_2 (TREE_TYPE (type), id) + || (TYPE_DOMAIN (type) && remap_type_2 (TYPE_DOMAIN (type), id))) + return true; + break; + + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + for (t = TYPE_FIELDS (type); t; t = DECL_CHAIN (t)) + if (TREE_CODE (t) == FIELD_DECL) + { + RETURN_TRUE_IF_VAR (DECL_FIELD_OFFSET (t)); + RETURN_TRUE_IF_VAR (DECL_SIZE (t)); + RETURN_TRUE_IF_VAR (DECL_SIZE_UNIT (t)); + if (TREE_CODE (type) == QUAL_UNION_TYPE) + RETURN_TRUE_IF_VAR (DECL_QUALIFIER (t)); + } + break; + + default: + return false; + } + + RETURN_TRUE_IF_VAR (TYPE_SIZE (type)); + RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (type)); + return false; +#undef RETURN_TRUE_IF_VAR +} + tree remap_type (tree type, copy_body_data *id) { @@ -593,7 +679,10 @@ remap_type (tree type, copy_body_data *i return *node; /* The type only needs remapping if it's variably modified. */ - if (! variably_modified_type_p (type, id->src_fn)) + if (! variably_modified_type_p (type, id->src_fn) + /* Don't remap if copy_decl method doesn't always return a new + decl and for all embedded decls returns the passed in decl. */ + || (id->dont_remap_vla_if_no_change && !remap_type_2 (type, id))) { insert_decl_map (id, type, type); return type; --- gcc/omp-low.c (revision 270741) +++ gcc/omp-low.c (revision 270742) @@ -851,6 +851,7 @@ new_omp_context (gimple *stmt, omp_conte ctx->cb.copy_decl = omp_copy_decl; ctx->cb.eh_lp_nr = 0; ctx->cb.transform_call_graph_edges = CB_CGE_MOVE; + ctx->cb.dont_remap_vla_if_no_change = true; ctx->depth = 1; } --- gcc/testsuite/gfortran.dg/gomp/pr89621.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/gomp/pr89621.f90 (revision 270742) @@ -0,0 +1,18 @@ +! PR middle-end/89621 +! { dg-do compile } + +subroutine sub(str) + character(*), intent(in) :: str +end subroutine sub + +program pr89621 + implicit none + integer i + character(len=:), allocatable :: str + str = "test" + !$omp parallel do + do i = 1, 10 + call sub(str) + enddo + !$omp end parallel do +end program pr89621 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-29 Jakub Jelinek PR c/89872 * gimplify.c (gimplify_compound_literal_expr): Don't optimize a non-addressable complit into its initializer if it is volatile. * gcc.dg/tree-ssa/pr89872.c: New test. --- gcc/gimplify.c (revision 270742) +++ gcc/gimplify.c (revision 270743) @@ -4650,6 +4650,7 @@ gimplify_compound_literal_expr (tree *ex otherwise we'd generate a new temporary, and we can as well just use the decl we already have. */ else if (!TREE_ADDRESSABLE (decl) + && !TREE_THIS_VOLATILE (decl) && init && (fallback & fb_lvalue) == 0 && gimple_test_f (init)) --- gcc/testsuite/gcc.dg/tree-ssa/pr89872.c (nonexistent) +++ gcc/testsuite/gcc.dg/tree-ssa/pr89872.c (revision 270743) @@ -0,0 +1,27 @@ +/* PR c/89872 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times " ={v} 1;" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " ={v} 2;" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " ={v} 3;" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " ={v} 4;" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " ={v} 0;" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " ={v} " 10 "optimized" } } */ + +void +foo (void) +{ + (volatile int){1} + (volatile int){2}; +} + +void +bar (void) +{ + (volatile int){3}; +} + +void +baz (void) +{ + (volatile int){4} / (volatile int){0}; +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-03-29 Jakub Jelinek PR sanitizer/89869 * typeck.c: Include gimplify.h. (cp_build_modify_expr) : Unshare rhs before using it for second time. Formatting fixes. * g++.dg/ubsan/vptr-14.C: New test. --- gcc/cp/typeck.c (revision 270743) +++ gcc/cp/typeck.c (revision 270744) @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. #include "c-family/c-ubsan.h" #include "params.h" #include "gcc-rich-location.h" +#include "gimplify.h" static tree cp_build_addr_expr_strict (tree, tsubst_flags_t); static tree cp_build_function_call (tree, tree, tsubst_flags_t); @@ -7676,8 +7677,6 @@ cp_build_modify_expr (location_t loc, tr /* Produce (a ? (b = rhs) : (c = rhs)) except that the RHS goes through a save-expr so the code to compute it is only emitted once. */ - tree cond; - if (VOID_TYPE_P (TREE_TYPE (rhs))) { if (complain & tf_error) @@ -7692,13 +7691,20 @@ cp_build_modify_expr (location_t loc, tr if (!lvalue_or_else (lhs, lv_assign, complain)) return error_mark_node; - cond = build_conditional_expr - (input_location, TREE_OPERAND (lhs, 0), - cp_build_modify_expr (loc, TREE_OPERAND (lhs, 1), - modifycode, rhs, complain), - cp_build_modify_expr (loc, TREE_OPERAND (lhs, 2), - modifycode, rhs, complain), - complain); + tree op1 = cp_build_modify_expr (loc, TREE_OPERAND (lhs, 1), + modifycode, rhs, complain); + /* When sanitizing undefined behavior, even when rhs doesn't need + stabilization at this point, the sanitization might add extra + SAVE_EXPRs in there and so make sure there is no tree sharing + in the rhs, otherwise those SAVE_EXPRs will have initialization + only in one of the two branches. */ + if (flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)) + rhs = unshare_expr (rhs); + tree op2 = cp_build_modify_expr (loc, TREE_OPERAND (lhs, 2), + modifycode, rhs, complain); + tree cond = build_conditional_expr (input_location, + TREE_OPERAND (lhs, 0), op1, op2, + complain); if (cond == error_mark_node) return cond; --- gcc/testsuite/g++.dg/ubsan/vptr-14.C (nonexistent) +++ gcc/testsuite/g++.dg/ubsan/vptr-14.C (revision 270744) @@ -0,0 +1,18 @@ +// PR sanitizer/89869 +// { dg-do run } +// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" } + +struct S { S *s = 0; virtual ~S () {} }; + +void +foo (S *x, S *y) +{ + (x->s ? y : x) = x->s; +} + +int +main () +{ + S a; + foo (&a, 0); +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-04-09 Jakub Jelinek PR tree-optimization/89998 * gimple-ssa-sprintf.c (try_substitute_return_value): Use lhs type instead of integer_type_node if possible, don't add ranges if return type is not compatible with int. * gimple-fold.c (gimple_fold_builtin_sprintf, gimple_fold_builtin_snprintf): Use lhs type instead of hardcoded integer_type_node. * gcc.c-torture/compile/pr89998-1.c: New test. * gcc.c-torture/compile/pr89998-2.c: New test. --- gcc/gimple-ssa-sprintf.c (revision 270744) +++ gcc/gimple-ssa-sprintf.c (revision 270745) @@ -3353,10 +3353,10 @@ try_substitute_return_value (gimple_stmt are badly declared. */ && !stmt_ends_bb_p (info.callstmt)) { - tree cst = build_int_cst (integer_type_node, minretval); + tree cst = build_int_cst (lhs ? TREE_TYPE (lhs) : integer_type_node, + minretval); - if (lhs == NULL_TREE - && info.nowrite) + if (lhs == NULL_TREE && info.nowrite) { /* Remove the call to the bounded function with a zero size (e.g., snprintf(0, 0, "%i", 123)) if there is no lhs. */ @@ -3397,7 +3397,7 @@ try_substitute_return_value (gimple_stmt } } } - else if (lhs) + else if (lhs && types_compatible_p (TREE_TYPE (lhs), integer_type_node)) { bool setrange = false; --- gcc/gimple-fold.c (revision 270744) +++ gcc/gimple-fold.c (revision 270745) @@ -3031,11 +3031,10 @@ gimple_fold_builtin_sprintf (gimple_stmt gimple_seq stmts = NULL; gimple *repl = gimple_build_call (fn, 2, dest, fmt); gimple_seq_add_stmt_without_update (&stmts, repl); - if (gimple_call_lhs (stmt)) + if (tree lhs = gimple_call_lhs (stmt)) { - repl = gimple_build_assign (gimple_call_lhs (stmt), - build_int_cst (integer_type_node, - strlen (fmt_str))); + repl = gimple_build_assign (lhs, build_int_cst (TREE_TYPE (lhs), + strlen (fmt_str))); gimple_seq_add_stmt_without_update (&stmts, repl); gsi_replace_with_seq_vops (gsi, stmts); /* gsi now points at the assignment to the lhs, get a @@ -3079,12 +3078,12 @@ gimple_fold_builtin_sprintf (gimple_stmt gimple_seq stmts = NULL; gimple *repl = gimple_build_call (fn, 2, dest, orig); gimple_seq_add_stmt_without_update (&stmts, repl); - if (gimple_call_lhs (stmt)) + if (tree lhs = gimple_call_lhs (stmt)) { - if (!useless_type_conversion_p (integer_type_node, + if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (orig_len))) - orig_len = fold_convert (integer_type_node, orig_len); - repl = gimple_build_assign (gimple_call_lhs (stmt), orig_len); + orig_len = fold_convert (TREE_TYPE (lhs), orig_len); + repl = gimple_build_assign (lhs, orig_len); gimple_seq_add_stmt_without_update (&stmts, repl); gsi_replace_with_seq_vops (gsi, stmts); /* gsi now points at the assignment to the lhs, get a @@ -3164,10 +3163,10 @@ gimple_fold_builtin_snprintf (gimple_stm gimple_seq stmts = NULL; gimple *repl = gimple_build_call (fn, 2, dest, fmt); gimple_seq_add_stmt_without_update (&stmts, repl); - if (gimple_call_lhs (stmt)) + if (tree lhs = gimple_call_lhs (stmt)) { - repl = gimple_build_assign (gimple_call_lhs (stmt), - build_int_cst (integer_type_node, len)); + repl = gimple_build_assign (lhs, + build_int_cst (TREE_TYPE (lhs), len)); gimple_seq_add_stmt_without_update (&stmts, repl); gsi_replace_with_seq_vops (gsi, stmts); /* gsi now points at the assignment to the lhs, get a @@ -3216,12 +3215,12 @@ gimple_fold_builtin_snprintf (gimple_stm gimple_seq stmts = NULL; gimple *repl = gimple_build_call (fn, 2, dest, orig); gimple_seq_add_stmt_without_update (&stmts, repl); - if (gimple_call_lhs (stmt)) + if (tree lhs = gimple_call_lhs (stmt)) { - if (!useless_type_conversion_p (integer_type_node, + if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (orig_len))) - orig_len = fold_convert (integer_type_node, orig_len); - repl = gimple_build_assign (gimple_call_lhs (stmt), orig_len); + orig_len = fold_convert (TREE_TYPE (lhs), orig_len); + repl = gimple_build_assign (lhs, orig_len); gimple_seq_add_stmt_without_update (&stmts, repl); gsi_replace_with_seq_vops (gsi, stmts); /* gsi now points at the assignment to the lhs, get a --- gcc/testsuite/gcc.c-torture/compile/pr89998-1.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr89998-1.c (revision 270745) @@ -0,0 +1,42 @@ +/* PR tree-optimization/89998 */ + +unsigned int sprintf (char *str, const char *fmt, ...); +unsigned int snprintf (char *str, __SIZE_TYPE__ len, const char *fmt, ...); + +int +f1 (char *s) +{ + return sprintf (s, "foo"); +} + +int +f2 (char *s) +{ + return sprintf (s, "%d", 123); +} + +int +f3 (int *p, char *s) +{ + const char *t = "bar"; + return sprintf (s, "%s", t); +} + +int +f4 (char *s) +{ + return snprintf (s, 8, "foo"); +} + +int +f5 (char *s) +{ + return snprintf (s, 8, "%d", 123); +} + +int +f6 (int *p, char *s) +{ + const char *t = "bar"; + return snprintf (s, 8, "%s", t); +} --- gcc/testsuite/gcc.c-torture/compile/pr89998-2.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr89998-2.c (revision 270745) @@ -0,0 +1,4 @@ +/* PR tree-optimization/89998 */ +/* { dg-additional-options "-fno-printf-return-value" } */ + +#include "pr89998-1.c" 2019-08-30 Jakub Jelinek Backported from mainline 2019-04-12 Jakub Jelinek PR c/89933 * c-decl.c (merge_decls): When newdecl's type is its main variant, don't try to remove it from the variant list, but instead assert it has no variants. * decl.c (duplicate_decls): When newdecl's type is its main variant, don't try to remove it from the variant list, but instead assert it has no variants. * c-c++-common/pr89933.c: New test. --- gcc/c/c-decl.c (revision 270750) +++ gcc/c/c-decl.c (revision 270751) @@ -2352,13 +2352,16 @@ merge_decls (tree newdecl, tree olddecl, if (TYPE_NAME (TREE_TYPE (newdecl)) == newdecl) { tree remove = TREE_TYPE (newdecl); - for (tree t = TYPE_MAIN_VARIANT (remove); ; - t = TYPE_NEXT_VARIANT (t)) - if (TYPE_NEXT_VARIANT (t) == remove) - { - TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove); - break; - } + if (TYPE_MAIN_VARIANT (remove) == remove) + gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE); + else + for (tree t = TYPE_MAIN_VARIANT (remove); ; + t = TYPE_NEXT_VARIANT (t)) + if (TYPE_NEXT_VARIANT (t) == remove) + { + TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove); + break; + } } } --- gcc/cp/decl.c (revision 270750) +++ gcc/cp/decl.c (revision 270751) @@ -2163,13 +2163,16 @@ next_arg:; if (TYPE_NAME (TREE_TYPE (newdecl)) == newdecl) { tree remove = TREE_TYPE (newdecl); - for (tree t = TYPE_MAIN_VARIANT (remove); ; - t = TYPE_NEXT_VARIANT (t)) - if (TYPE_NEXT_VARIANT (t) == remove) - { - TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove); - break; - } + if (TYPE_MAIN_VARIANT (remove) == remove) + gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE); + else + for (tree t = TYPE_MAIN_VARIANT (remove); ; + t = TYPE_NEXT_VARIANT (t)) + if (TYPE_NEXT_VARIANT (t) == remove) + { + TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove); + break; + } } } else if (merge_attr) --- gcc/testsuite/c-c++-common/pr89933.c (nonexistent) +++ gcc/testsuite/c-c++-common/pr89933.c (revision 270751) @@ -0,0 +1,5 @@ +/* PR c/89933 */ +/* { dg-do compile } */ + +typedef unsigned int a __attribute__ ((__aligned__(8), __may_alias__)); +typedef unsigned int a __attribute__ ((__aligned__(8), __may_alias__)); 2019-08-30 Jakub Jelinek Backported from mainline 2019-04-16 Jakub Jelinek PR tree-optimization/90090 * tree-ssa-math-opts.c (is_division_by): Ignore divisions that can throw internally. * g++.dg/opt/pr90090.C: New test. --- gcc/tree-ssa-math-opts.c (revision 270751) +++ gcc/tree-ssa-math-opts.c (revision 270752) @@ -334,7 +334,8 @@ is_division_by (gimple *use_stmt, tree d /* Do not recognize x / x as valid division, as we are getting confused later by replacing all immediate uses x in such a stmt. */ - && gimple_assign_rhs1 (use_stmt) != def; + && gimple_assign_rhs1 (use_stmt) != def + && !stmt_can_throw_internal (use_stmt); } /* Return whether USE_STMT is DEF * DEF. */ --- gcc/testsuite/g++.dg/opt/pr90090.C (nonexistent) +++ gcc/testsuite/g++.dg/opt/pr90090.C (revision 270752) @@ -0,0 +1,19 @@ +// PR tree-optimization/90090 +// { dg-do compile } +// { dg-options "-Ofast -fno-associative-math -fsignaling-nans -fno-tree-dce -fnon-call-exceptions" } + +double bar (double, double, double, double, double); +double baz (); + +double +foo (double a) +{ + try + { + return bar (1.0/a, 2.0/a, 4.0/a, 8.0/a, 16.0/a); + } + catch (...) + { + return baz (); + } +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-04-16 Jakub Jelinek PR rtl-optimization/90082 * dce.c (can_delete_call): New function. (deletable_insn_p, mark_insn): Use it. * gcc.dg/pr90082.c: New test. --- gcc/dce.c (revision 270752) +++ gcc/dce.c (revision 270753) @@ -87,6 +87,32 @@ deletable_insn_p_1 (rtx body) } } +/* Don't delete calls that may throw if we cannot do so. */ + +static bool +can_delete_call (rtx_insn *insn) +{ + if (cfun->can_delete_dead_exceptions && can_alter_cfg) + return true; + if (!insn_nothrow_p (insn)) + return false; + if (can_alter_cfg) + return true; + /* If we can't alter cfg, even when the call can't throw exceptions, it + might have EDGE_ABNORMAL_CALL edges and so we shouldn't delete such + calls. */ + gcc_assert (CALL_P (insn)); + if (BLOCK_FOR_INSN (insn) && BB_END (BLOCK_FOR_INSN (insn)) == insn) + { + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, BLOCK_FOR_INSN (insn)->succs) + if ((e->flags & EDGE_ABNORMAL_CALL) != 0) + return false; + } + return true; +} /* Return true if INSN is a normal instruction that can be deleted by the DCE pass. */ @@ -111,8 +137,7 @@ deletable_insn_p (rtx_insn *insn, bool f && (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)) /* Don't delete calls that may throw if we cannot do so. */ - && ((cfun->can_delete_dead_exceptions && can_alter_cfg) - || insn_nothrow_p (insn))) + && can_delete_call (insn)) return find_call_stack_args (as_a (insn), false, fast, arg_stores); @@ -205,8 +230,7 @@ mark_insn (rtx_insn *insn, bool fast) && !SIBLING_CALL_P (insn) && (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)) - && ((cfun->can_delete_dead_exceptions && can_alter_cfg) - || insn_nothrow_p (insn))) + && can_delete_call (insn)) find_call_stack_args (as_a (insn), true, fast, NULL); } } --- gcc/testsuite/gcc.dg/pr90082.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr90082.c (revision 270753) @@ -0,0 +1,13 @@ +/* PR rtl-optimization/90082 */ +/* { dg-do compile } */ +/* { dg-options "-O1 -fnon-call-exceptions -ftrapv" } */ + +void *buf[5]; + +void +foo (int a) +{ + if (__builtin_setjmp (buf) == 0) + __asm__ ("" : : "n" (a * 2)); /* { dg-error "impossible constraint in 'asm'" } */ + /* { dg-warning "asm operand 0 probably doesn't match constraints" "" { target *-*-* } .-1 } */ +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-04-19 Jakub Jelinek PR c++/90108 * c-decl.c (merge_decls): If remove is main variant and DECL_ORIGINAL_TYPE is some other type, remove a DECL_ORIGINAL_TYPE variant that has newdecl as TYPE_NAME if any. * decl.c (duplicate_decls): If remove is main variant and DECL_ORIGINAL_TYPE is some other type, remove a DECL_ORIGINAL_TYPE variant that has newdecl as TYPE_NAME if any. * c-c++-common/pr90108.c: New test. --- gcc/c/c-decl.c (revision 270753) +++ gcc/c/c-decl.c (revision 270754) @@ -2353,7 +2353,24 @@ merge_decls (tree newdecl, tree olddecl, { tree remove = TREE_TYPE (newdecl); if (TYPE_MAIN_VARIANT (remove) == remove) - gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE); + { + gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE); + /* If remove is the main variant, no need to remove that + from the list. One of the DECL_ORIGINAL_TYPE + variants, e.g. created for aligned attribute, might still + refer to the newdecl TYPE_DECL though, so remove that one + in that case. */ + if (DECL_ORIGINAL_TYPE (newdecl) + && DECL_ORIGINAL_TYPE (newdecl) != remove) + for (tree t = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (newdecl)); + t; t = TYPE_MAIN_VARIANT (t)) + if (TYPE_NAME (TYPE_NEXT_VARIANT (t)) == newdecl) + { + TYPE_NEXT_VARIANT (t) + = TYPE_NEXT_VARIANT (TYPE_NEXT_VARIANT (t)); + break; + } + } else for (tree t = TYPE_MAIN_VARIANT (remove); ; t = TYPE_NEXT_VARIANT (t)) --- gcc/cp/decl.c (revision 270753) +++ gcc/cp/decl.c (revision 270754) @@ -2164,7 +2164,24 @@ next_arg:; { tree remove = TREE_TYPE (newdecl); if (TYPE_MAIN_VARIANT (remove) == remove) - gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE); + { + gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE); + /* If remove is the main variant, no need to remove that + from the list. One of the DECL_ORIGINAL_TYPE + variants, e.g. created for aligned attribute, might still + refer to the newdecl TYPE_DECL though, so remove that one + in that case. */ + if (tree orig = DECL_ORIGINAL_TYPE (newdecl)) + if (orig != remove) + for (tree t = TYPE_MAIN_VARIANT (orig); t; + t = TYPE_MAIN_VARIANT (t)) + if (TYPE_NAME (TYPE_NEXT_VARIANT (t)) == newdecl) + { + TYPE_NEXT_VARIANT (t) + = TYPE_NEXT_VARIANT (TYPE_NEXT_VARIANT (t)); + break; + } + } else for (tree t = TYPE_MAIN_VARIANT (remove); ; t = TYPE_NEXT_VARIANT (t)) --- gcc/testsuite/c-c++-common/pr90108.c (nonexistent) +++ gcc/testsuite/c-c++-common/pr90108.c (revision 270754) @@ -0,0 +1,6 @@ +/* PR c++/90108 */ +/* { dg-do compile } */ +/* { dg-options "--param ggc-min-heapsize=0" } */ + +typedef unsigned int a __attribute__ ((__aligned__(8), __may_alias__)); +typedef unsigned int a __attribute__ ((__aligned__(8), __may_alias__)); 2019-08-30 Jakub Jelinek Backported from mainline 2019-04-24 Jakub Jelinek PR tree-optimization/90208 * tree-cfg.c (remove_bb): Move forced labels from removed bbs after labels of new_bb, not before them. * gcc.dg/tsan/pr90208-2.c: New test. --- gcc/tree-cfg.c (revision 270754) +++ gcc/tree-cfg.c (revision 270755) @@ -2170,7 +2170,7 @@ remove_bb (basic_block bb) } new_bb = bb->prev_bb; - new_gsi = gsi_start_bb (new_bb); + new_gsi = gsi_after_labels (new_bb); gsi_remove (&i, false); gsi_insert_before (&new_gsi, stmt, GSI_NEW_STMT); } --- gcc/testsuite/gcc.dg/tsan/pr90208-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/tsan/pr90208-2.c (revision 270755) @@ -0,0 +1,20 @@ +/* PR tree-optimization/90208 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fexceptions -fsanitize=thread" } */ + +void *b[5]; +void foo (void); + +void +bar (int d) +{ + while (d) + foo (); +} + +void +baz (void) +{ + bar (2); + __builtin_setjmp (b); +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-04-24 Jakub Jelinek PR target/90187 * config/i386/i386.c (ix86_expand_sse_fp_minmax): Force if_true into a register if both if_true and if_false are MEMs. * g++.dg/opt/pr90187.C: New test. --- gcc/config/i386/i386.c (revision 270755) +++ gcc/config/i386/i386.c (revision 270756) @@ -23981,6 +23981,8 @@ ix86_expand_sse_fp_minmax (rtx dest, enu else { code = is_min ? SMIN : SMAX; + if (MEM_P (if_true) && MEM_P (if_false)) + if_true = force_reg (mode, if_true); tmp = gen_rtx_fmt_ee (code, mode, if_true, if_false); } --- gcc/testsuite/g++.dg/opt/pr90187.C (nonexistent) +++ gcc/testsuite/g++.dg/opt/pr90187.C (revision 270756) @@ -0,0 +1,15 @@ +// PR target/90187 +// { dg-do compile } +// { dg-options "-Ofast -ffloat-store" } + +double a[64]; +double *foo (void); + +void +bar (int x, const double *y) +{ + int i; + for (i = 0; i < x; i++) + if (y[i] < a[i]) + a[i] = y[i]; +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-05-29 Jakub Jelinek PR fortran/90329 * lto-streamer.h (LTO_minor_version): Bump to 1. Backported from mainline 2019-05-16 Jakub Jelinek PR fortran/90329 * tree-core.h (struct tree_decl_common): Document decl_nonshareable_flag for PARM_DECLs. * tree.h (DECL_HIDDEN_STRING_LENGTH): Define. * calls.c (expand_call): Don't try tail call if caller has any DECL_HIDDEN_STRING_LENGTH PARM_DECLs that are or might be passed on the stack and callee needs to pass any arguments on the stack. * tree-streamer-in.c (unpack_ts_decl_common_value_fields): Use else if instead of series of mutually exclusive ifs. Handle DECL_HIDDEN_STRING_LENGTH for PARM_DECLs. * tree-streamer-out.c (pack_ts_decl_common_value_fields): Likewise. * lang.opt (fbroken-callers): Remove. (ftail-call-workaround, ftail-call-workaround=): New options. * gfortran.h (struct gfc_namespace): Add implicit_interface_calls. * interface.c (gfc_procedure_use): Set implicit_interface_calls for calls to implicit interface procedures. * trans-decl.c (create_function_arglist): Use flag_tail_call_workaround instead of flag_broken_callers. If it is not 2, also require sym->ns->implicit_interface_calls. * invoke.texi (fbroken-callers): Remove documentation. (ftail-call-workaround, ftail-call-workaround=): Document. 2019-05-19 Thomas Koenig PR fortran/90329 * invoke.texi: Document -fbroken-callers. * lang.opt: Add -fbroken-callers. * trans-decl.c (create_function_arglist): Only set DECL_HIDDEN_STRING_LENGTH if flag_broken_callers is set. 2019-05-16 Jakub Jelinek PR fortran/90329 * trans-decl.c (create_function_arglist): Set DECL_HIDDEN_STRING_LENGTH on hidden string length PARM_DECLs if len is constant. --- gcc/tree.h (revision 271743) +++ gcc/tree.h (revision 271744) @@ -909,6 +909,11 @@ extern void omp_clause_range_check_faile (TREE_CHECK2 (NODE, VAR_DECL, \ RESULT_DECL)->decl_common.decl_nonshareable_flag) +/* In a PARM_DECL, set for Fortran hidden string length arguments that some + buggy callers don't pass to the callee. */ +#define DECL_HIDDEN_STRING_LENGTH(NODE) \ + (TREE_CHECK (NODE, PARM_DECL)->decl_common.decl_nonshareable_flag) + /* In a CALL_EXPR, means that the call is the jump from a thunk to the thunked-to function. */ #define CALL_FROM_THUNK_P(NODE) (CALL_EXPR_CHECK (NODE)->base.protected_flag) --- gcc/calls.c (revision 271743) +++ gcc/calls.c (revision 271744) @@ -3333,6 +3333,28 @@ expand_call (tree exp, rtx target, int i || dbg_cnt (tail_call) == false) try_tail_call = 0; + /* Workaround buggy C/C++ wrappers around Fortran routines with + character(len=constant) arguments if the hidden string length arguments + are passed on the stack; if the callers forget to pass those arguments, + attempting to tail call in such routines leads to stack corruption. + Avoid tail calls in functions where at least one such hidden string + length argument is passed (partially or fully) on the stack in the + caller and the callee needs to pass any arguments on the stack. + See PR90329. */ + if (try_tail_call && args_size.constant != 0) + for (tree arg = DECL_ARGUMENTS (current_function_decl); + arg; arg = DECL_CHAIN (arg)) + if (DECL_HIDDEN_STRING_LENGTH (arg) && DECL_INCOMING_RTL (arg)) + { + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, DECL_INCOMING_RTL (arg), NONCONST) + if (MEM_P (*iter)) + { + try_tail_call = 0; + break; + } + } + /* If the user has marked the function as requiring tail-call optimization, attempt it. */ if (must_tail_call) --- gcc/tree-streamer-out.c (revision 271743) +++ gcc/tree-streamer-out.c (revision 271744) @@ -212,7 +212,7 @@ pack_ts_decl_common_value_fields (struct bp_pack_var_len_unsigned (bp, EH_LANDING_PAD_NR (expr)); } - if (TREE_CODE (expr) == FIELD_DECL) + else if (TREE_CODE (expr) == FIELD_DECL) { bp_pack_value (bp, DECL_PACKED (expr), 1); bp_pack_value (bp, DECL_NONADDRESSABLE_P (expr), 1); @@ -220,12 +220,15 @@ pack_ts_decl_common_value_fields (struct bp_pack_value (bp, expr->decl_common.off_align, 8); } - if (VAR_P (expr)) + else if (VAR_P (expr)) { bp_pack_value (bp, DECL_HAS_DEBUG_EXPR_P (expr), 1); bp_pack_value (bp, DECL_NONLOCAL_FRAME (expr), 1); } + else if (TREE_CODE (expr) == PARM_DECL) + bp_pack_value (bp, DECL_HIDDEN_STRING_LENGTH (expr), 1); + if (TREE_CODE (expr) == RESULT_DECL || TREE_CODE (expr) == PARM_DECL || VAR_P (expr)) --- gcc/tree-streamer-in.c (revision 271743) +++ gcc/tree-streamer-in.c (revision 271744) @@ -252,7 +252,7 @@ unpack_ts_decl_common_value_fields (stru LABEL_DECL_UID (expr) = -1; } - if (TREE_CODE (expr) == FIELD_DECL) + else if (TREE_CODE (expr) == FIELD_DECL) { DECL_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_NONADDRESSABLE_P (expr) = (unsigned) bp_unpack_value (bp, 1); @@ -260,12 +260,15 @@ unpack_ts_decl_common_value_fields (stru expr->decl_common.off_align = bp_unpack_value (bp, 8); } - if (VAR_P (expr)) + else if (VAR_P (expr)) { DECL_HAS_DEBUG_EXPR_P (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_NONLOCAL_FRAME (expr) = (unsigned) bp_unpack_value (bp, 1); } + else if (TREE_CODE (expr) == PARM_DECL) + DECL_HIDDEN_STRING_LENGTH (expr) = (unsigned) bp_unpack_value (bp, 1); + if (TREE_CODE (expr) == RESULT_DECL || TREE_CODE (expr) == PARM_DECL || VAR_P (expr)) --- gcc/tree-core.h (revision 271743) +++ gcc/tree-core.h (revision 271744) @@ -1644,6 +1644,7 @@ struct GTY(()) tree_decl_common { /* In a VAR_DECL and PARM_DECL, this is DECL_READ_P. */ unsigned decl_read_flag : 1; /* In a VAR_DECL or RESULT_DECL, this is DECL_NONSHAREABLE. */ + /* In a PARM_DECL, this is DECL_HIDDEN_STRING_LENGTH. */ unsigned decl_nonshareable_flag : 1; /* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */ --- gcc/lto-streamer.h (revision 271743) +++ gcc/lto-streamer.h (revision 271744) @@ -129,7 +129,7 @@ along with GCC; see the file COPYING3. form followed by the data for the string. */ #define LTO_major_version 6 -#define LTO_minor_version 0 +#define LTO_minor_version 1 typedef unsigned char lto_decl_flags_t; --- gcc/fortran/interface.c (revision 271743) +++ gcc/fortran/interface.c (revision 271744) @@ -3657,6 +3657,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_ gfc_warning (OPT_Wimplicit_procedure, "Procedure %qs called at %L is not explicitly declared", sym->name, where); + gfc_find_proc_namespace (sym->ns)->implicit_interface_calls = 1; } if (sym->attr.if_source == IFSRC_UNKNOWN) --- gcc/fortran/gfortran.h (revision 271743) +++ gcc/fortran/gfortran.h (revision 271744) @@ -1857,6 +1857,9 @@ typedef struct gfc_namespace /* Set to 1 for !$ACC ROUTINE namespaces. */ unsigned oacc_routine:1; + + /* Set to 1 if there are any calls to procedures with implicit interface. */ + unsigned implicit_interface_calls:1; } gfc_namespace; --- gcc/fortran/lang.opt (revision 271743) +++ gcc/fortran/lang.opt (revision 271744) @@ -742,6 +742,13 @@ fsign-zero Fortran Var(flag_sign_zero) Init(1) Apply negative sign to zero values. +ftail-call-workaround +Frotran Alias(ftail-call-workaround=,1,0) + +ftail-call-workaround= +Fortran RejectNegative Joined UInteger IntegerRange(0, 2) Var(flag_tail_call_workaround) Init(1) +Disallow tail call optimization when a calling routine may have omitted character lenghts. + funderscoring Fortran Var(flag_underscoring) Init(1) Append underscores to externally visible names. --- gcc/fortran/invoke.texi (revision 271743) +++ gcc/fortran/invoke.texi (revision 271744) @@ -181,7 +181,8 @@ and warnings}. @item Code Generation Options @xref{Code Gen Options,,Options for code generation conventions}. @gccoptlist{-faggressive-function-elimination -fblas-matmul-limit=@var{n} @gol --fbounds-check -fcheck-array-temporaries @gol +-fbounds-check -ftail-call-workaround -ftail-call-workaround=@var{n} @gol +-fcheck-array-temporaries @gol -fcheck=@var{} @gol -fcoarray=@var{} -fexternal-blas -ff2c -ffrontend-loop-interchange @gol @@ -1580,6 +1581,39 @@ warnings for generated array temporaries @c Note: This option is also referred in gcc's manpage Deprecated alias for @option{-fcheck=bounds}. +@item -ftail-call-workaround +@itemx -ftail-call-workaround=@var{n} +@opindex @code{tail-call-workaround} +Some C interfaces to Fortran codes violate the gfortran ABI by +omitting the hidden character length arguments as described in +@xref{Argument passing conventions}. This can lead to crashes +because pushing arguments for tail calls can overflow the stack. + +To provide a workaround for existing binary packages, this option +disables tail call optimization for gfortran procedures with character +arguments. With @option{-ftail-call-workaround=2} tail call optimization +is disabled in all gfortran procedures with character arguments, +with @option{-ftail-call-workaround=1} or equivalent +@option{-ftail-call-workaround} only in gfortran procedures with character +arguments that call implicitly prototyped procedures. + +Using this option can lead to problems including crashes due to +insufficient stack space. + +It is @emph{very strongly} recommended to fix the code in question. +The @option{-fc-prototypes-external} option can be used to generate +prototypes which conform to gfortran's ABI, for inclusion in the +source code. + +Support for this option will likely be withdrawn in a future release +of gfortran. + +The negative form, @option{-fno-tail-call-workaround} or equivalent +@option{-ftail-call-workaround=0}, can be used to disable this option. + +Default is currently @option{-ftail-call-workaround}, this will change +in future releases. + @item -fcheck-array-temporaries @opindex @code{fcheck-array-temporaries} Deprecated alias for @option{-fcheck=array-temps}. --- gcc/fortran/trans-decl.c (revision 271743) +++ gcc/fortran/trans-decl.c (revision 271744) @@ -2513,6 +2513,17 @@ create_function_arglist (gfc_symbol * sy TREE_READONLY (length) = 1; gfc_finish_decl (length); + /* Marking the length DECL_HIDDEN_STRING_LENGTH will lead + to tail calls being disabled. Only do that if we + potentially have broken callers. */ + if (flag_tail_call_workaround + && f->sym->ts.u.cl + && f->sym->ts.u.cl->length + && f->sym->ts.u.cl->length->expr_type == EXPR_CONSTANT + && (flag_tail_call_workaround == 2 + || f->sym->ns->implicit_interface_calls)) + DECL_HIDDEN_STRING_LENGTH (length) = 1; + /* Remember the passed value. */ if (!f->sym->ts.u.cl || f->sym->ts.u.cl->passed_length) { 2019-08-30 Jakub Jelinek Backported from mainline 2019-05-30 Jakub Jelinek * lang.opt (ftail-call-workaround=): Fix a typo - lenghts to lengths. --- gcc/fortran/lang.opt (revision 271771) +++ gcc/fortran/lang.opt (revision 271772) @@ -747,7 +747,7 @@ Frotran Alias(ftail-call-workaround=,1,0 ftail-call-workaround= Fortran RejectNegative Joined UInteger IntegerRange(0, 2) Var(flag_tail_call_workaround) Init(1) -Disallow tail call optimization when a calling routine may have omitted character lenghts. +Disallow tail call optimization when a calling routine may have omitted character lengths. funderscoring Fortran Var(flag_underscoring) Init(1) 2019-08-30 Jakub Jelinek Backported from mainline 2019-06-11 Jakub Jelinek PR target/90811 * config/nvptx/nvptx.c (nvptx_output_softstack_switch): Use and.b%d instead of and.u%d. * testsuite/libgomp.c/pr90811.c: New test. --- gcc/config/nvptx/nvptx.c (revision 272162) +++ gcc/config/nvptx/nvptx.c (revision 272163) @@ -1377,7 +1377,7 @@ nvptx_output_softstack_switch (FILE *fil fputs (";\n", file); if (!CONST_INT_P (size) || UINTVAL (align) > GET_MODE_SIZE (DImode)) fprintf (file, - "\t\tand.u%d %%r%d, %%r%d, -" HOST_WIDE_INT_PRINT_DEC ";\n", + "\t\tand.b%d %%r%d, %%r%d, -" HOST_WIDE_INT_PRINT_DEC ";\n", bits, regno, regno, UINTVAL (align)); } if (cfun->machine->has_softstack) --- libgomp/testsuite/libgomp.c/pr90811.c (nonexistent) +++ libgomp/testsuite/libgomp.c/pr90811.c (revision 272163) @@ -0,0 +1,29 @@ +/* PR target/90811 */ + +int +main () +{ + long long a[100], b[100]; + int i; + for (i = 0; i < 100; i++) + { + a[i] = i; + b[i] = i % 10; + } + #pragma omp target teams distribute parallel for simd map(tofrom: a[:100], b[:100]) + for (i = 0; i < 100; i++) + { + long long c = 0; + const long long d[] = { 1, 3, 5, 7, 9 }; + for (int j = 4; j >= 0; j--) + c = d[j] + b[i] * c; + a[i] += c; + } + for (i = 0; i < 100; i++) + { + const long long r[] = { 1, 26, 229, 976, 2849, 6646, 13381, 24284, 40801, 64594 }; + if (a[i] != r[i % 10] + (i / 10 * 10)) + __builtin_abort (); + } + return 0; +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-04-19 Jakub Jelinek PR middle-end/90139 * tree-outof-ssa.c (get_temp_reg): If reg_mode is BLKmode, return assign_temp instead of gen_reg_rtx. * gcc.c-torture/compile/pr90139.c: New test. --- gcc/tree-outof-ssa.c (revision 270456) +++ gcc/tree-outof-ssa.c (revision 270457) @@ -653,6 +653,8 @@ get_temp_reg (tree name) tree type = TREE_TYPE (name); int unsignedp; machine_mode reg_mode = promote_ssa_mode (name, &unsignedp); + if (reg_mode == BLKmode) + return assign_temp (type, 0, 0); rtx x = gen_reg_rtx (reg_mode); if (POINTER_TYPE_P (type)) mark_reg_pointer (x, TYPE_ALIGN (TREE_TYPE (type))); --- gcc/testsuite/gcc.c-torture/compile/pr90139.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr90139.c (revision 270457) @@ -0,0 +1,20 @@ +/* PR middle-end/90139 */ + +typedef float __attribute__((vector_size (sizeof (float)))) V; +void bar (int, V *); +int l; + +void +foo (void) +{ + V n, b, o; + while (1) + switch (l) + { + case 0: + o = n; + n = b; + b = o; + bar (1, &o); + } +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-05-10 Jakub Jelinek PR pch/90326 cp/ * config-lang.in (gtfiles): Remove c-family/c-lex.c, add c-family/c-cppbuiltin.c. objcp/ * config-lang.in (gtfiles): Remove c-family/c-lex.c, add c-family/c-cppbuiltin.c. testsuite/ * g++.dg/pch/pr90326.C: New test. * g++.dg/pch/pr90326.Hs: New file. --- gcc/cp/config-lang.in (revision 271349) +++ gcc/cp/config-lang.in (revision 271350) @@ -29,4 +29,4 @@ compilers="cc1plus\$(exeext)" target_libs="target-libstdc++-v3" -gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.c" +gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.c" --- gcc/objcp/config-lang.in (revision 271349) +++ gcc/objcp/config-lang.in (revision 271350) @@ -45,6 +45,6 @@ subdir_requires="objc cp" # This list is separated in two parts: the first one is identical to # the C++ one, the second one contains our ObjC++ additions. -gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.c \ +gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.c \ \$(srcdir)/objc/objc-map.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c" --- gcc/testsuite/g++.dg/pch/pr90326.C (nonexistent) +++ gcc/testsuite/g++.dg/pch/pr90326.C (revision 271350) @@ -0,0 +1,9 @@ +#include "pr90326.H" + +int main() +{ + float f = __FLT_MAX__; + if (f == 0.0) + __builtin_abort (); + return 0; +} --- gcc/testsuite/g++.dg/pch/pr90326.Hs (nonexistent) +++ gcc/testsuite/g++.dg/pch/pr90326.Hs (revision 271350) @@ -0,0 +1 @@ +// empty 2019-08-30 Jakub Jelinek Backported from mainline 2019-05-24 Jakub Jelinek PR libgomp/90585 * plugin/plugin-hsa.c (print_kernel_dispatch, run_kernel): Use PRIu64 macro instead of "lu". (release_kernel_dispatch): Likewise. Cast shadow->debug to uintptr_t before casting to void *. --- libgomp/plugin/plugin-hsa.c (revision 271956) +++ libgomp/plugin/plugin-hsa.c (revision 271957) @@ -1154,8 +1154,9 @@ create_single_kernel_dispatch (struct ke static void release_kernel_dispatch (struct GOMP_hsa_kernel_dispatch *shadow) { - HSA_DEBUG ("Released kernel dispatch: %p has value: %lu (%p)\n", shadow, - shadow->debug, (void *) shadow->debug); + HSA_DEBUG ("Released kernel dispatch: %p has value: %" PRIu64 " (%p)\n", + shadow, shadow->debug, + (void *) (uintptr_t) shadow->debug); hsa_fns.hsa_memory_free_fn (shadow->kernarg_address); @@ -1276,9 +1277,9 @@ print_kernel_dispatch (struct GOMP_hsa_k indent_stream (stderr, indent); fprintf (stderr, "kernarg_address: %p\n", dispatch->kernarg_address); indent_stream (stderr, indent); - fprintf (stderr, "object: %lu\n", dispatch->object); + fprintf (stderr, "object: %" PRIu64 "\n", dispatch->object); indent_stream (stderr, indent); - fprintf (stderr, "signal: %lu\n", dispatch->signal); + fprintf (stderr, "signal: %" PRIu64 "\n", dispatch->signal); indent_stream (stderr, indent); fprintf (stderr, "private_segment_size: %u\n", dispatch->private_segment_size); @@ -1286,7 +1287,7 @@ print_kernel_dispatch (struct GOMP_hsa_k fprintf (stderr, "group_segment_size: %u\n", dispatch->group_segment_size); indent_stream (stderr, indent); - fprintf (stderr, "children dispatches: %lu\n", + fprintf (stderr, "children dispatches: %" PRIu64 "\n", dispatch->kernel_dispatch_count); indent_stream (stderr, indent); fprintf (stderr, "omp_num_threads: %u\n", @@ -1594,7 +1595,7 @@ run_kernel (struct kernel_info *kernel, hsa_signal_t child_s; child_s.handle = shadow->children_dispatches[i]->signal; - HSA_DEBUG ("Waiting for children completion signal: %lu\n", + HSA_DEBUG ("Waiting for children completion signal: %" PRIu64 "\n", shadow->children_dispatches[i]->signal); hsa_fns.hsa_signal_load_acquire_fn (child_s); } 2019-08-30 Jakub Jelinek Backported from mainline 2019-06-12 Jakub Jelinek PR c/90760 * symtab.c (symtab_node::set_section): Allow being called on aliases as long as they aren't analyzed yet. * gcc.dg/pr90760.c: New test. --- gcc/symtab.c (revision 272799) +++ gcc/symtab.c (revision 272800) @@ -1553,7 +1553,7 @@ symtab_node::set_section (symtab_node *n void symtab_node::set_section (const char *section) { - gcc_assert (!this->alias); + gcc_assert (!this->alias || !this->analyzed); call_for_symbol_and_aliases (symtab_node::set_section, const_cast(section), true); } --- gcc/testsuite/gcc.dg/pr90760.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr90760.c (revision 272800) @@ -0,0 +1,8 @@ +/* PR c/90760 */ +/* { dg-do compile } */ +/* { dg-require-named-sections "" } */ + +void bar (void) {} +void foo (void) __attribute__ ((alias ("bar"))); /* { dg-error "section of alias 'foo' must match section of its target" } */ +void foo (void) __attribute__ ((section ("baz"))); +void qux (void) __attribute__ ((alias ("bar"), section ("baz"))); /* { dg-error "section of alias 'qux' must match section of its target" } */ 2019-08-30 Jakub Jelinek Backported from mainline 2019-06-21 Jakub Jelinek PR c++/90950 * semantics.c (finish_omp_clauses): Don't reject references to incomplete types if processing_template_decl. * g++.dg/gomp/lastprivate-1.C: New test. --- gcc/cp/semantics.c (revision 272800) +++ gcc/cp/semantics.c (revision 272801) @@ -7315,7 +7315,8 @@ finish_omp_clauses (tree clauses, enum c t = require_complete_type (t); if (t == error_mark_node) remove = true; - else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE + else if (!processing_template_decl + && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE && !complete_type_or_else (TREE_TYPE (TREE_TYPE (t)), t)) remove = true; } --- gcc/testsuite/g++.dg/gomp/lastprivate-1.C (nonexistent) +++ gcc/testsuite/g++.dg/gomp/lastprivate-1.C (revision 272801) @@ -0,0 +1,16 @@ +// PR c++/90950 +// { dg-do compile } + +template +T +foo (void) +{ + T y = 0; + T &x = y; + #pragma omp parallel for lastprivate (x) + for (int i = 0; i < 8; ++i) + x = i; + return x; +} + +int a = foo (); 2019-08-30 Jakub Jelinek Backported from mainline 2019-06-25 Jakub Jelinek PR sanitizer/90954 * c-omp.c (c_finish_omp_atomic): Allow tree_invariant_p in addition to SAVE_EXPR in first operand of a COMPOUND_EXPR. * c-c++-common/gomp/pr90954.c: New test. --- gcc/c-family/c-omp.c (revision 272801) +++ gcc/c-family/c-omp.c (revision 272802) @@ -305,7 +305,7 @@ c_finish_omp_atomic (location_t loc, enu if (TREE_CODE (x) == COMPOUND_EXPR) { pre = TREE_OPERAND (x, 0); - gcc_assert (TREE_CODE (pre) == SAVE_EXPR); + gcc_assert (TREE_CODE (pre) == SAVE_EXPR || tree_invariant_p (pre)); x = TREE_OPERAND (x, 1); } gcc_assert (TREE_CODE (x) == MODIFY_EXPR); --- gcc/testsuite/c-c++-common/gomp/pr90954.c (nonexistent) +++ gcc/testsuite/c-c++-common/gomp/pr90954.c (revision 272802) @@ -0,0 +1,27 @@ +/* PR sanitizer/90954 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fsanitize=undefined" } */ + +float v; +int i; + +void +foo (float x, float y) +{ + #pragma omp atomic + v += x / y; +} + +void +bar (int x, int y) +{ + #pragma omp atomic + i += x / y; +} + +void +baz (int x, int y) +{ + #pragma omp atomic + i *= (x << y); +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-07-04 Jakub Jelinek PR rtl-optimization/90756 * explow.c (promote_ssa_mode): Always use TYPE_MODE, don't bypass it for VECTOR_TYPE_P. * gcc.dg/pr90756.c: New test. --- gcc/explow.c (revision 273475) +++ gcc/explow.c (revision 273476) @@ -892,16 +892,7 @@ promote_ssa_mode (const_tree name, int * tree type = TREE_TYPE (name); int unsignedp = TYPE_UNSIGNED (type); - machine_mode mode = TYPE_MODE (type); - - /* Bypass TYPE_MODE when it maps vector modes to BLKmode. */ - if (mode == BLKmode) - { - gcc_assert (VECTOR_TYPE_P (type)); - mode = type->type_common.mode; - } - - machine_mode pmode = promote_mode (type, mode, &unsignedp); + machine_mode pmode = promote_mode (type, TYPE_MODE (type), &unsignedp); if (punsignedp) *punsignedp = unsignedp; --- gcc/testsuite/gcc.dg/pr90756.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr90756.c (revision 273476) @@ -0,0 +1,26 @@ +/* PR rtl-optimization/90756 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wno-psabi" } */ +/* { dg-additional-options "-mno-sse" { target ia32 } } */ + +typedef float B __attribute__((vector_size(4 * sizeof (float)))); +typedef unsigned long long C __attribute__((vector_size(4 * sizeof (long long)))); +typedef short D __attribute__((vector_size(4 * sizeof (short)))); +B z; +void foo (C); +C bar (D); +B baz (); +D qux (B); + +void +quux (int x) +{ + B n = z, b = z; + while (1) + switch (x) + { + case 0: n = baz (); /* FALLTHRU */ + case 1: { B o = n; n = b; b = o; } /* FALLTHRU */ + case 2: { D u = qux (b); C v = bar (u); foo (v); } + } +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-07-04 Jakub Jelinek PR middle-end/78884 * gimplify.c (struct gimplify_omp_ctx): Add add_safelen1 member. (gimplify_bind_expr): If seeing TREE_ADDRESSABLE VLA inside of simd loop body, set ctx->add_safelen1 instead of making it GOVD_PRIVATE. (gimplify_adjust_omp_clauses): Add safelen (1) clause if ctx->add_safelen1 is set. * gcc.dg/gomp/pr78884.c: New test. --- gcc/gimplify.c (revision 273476) +++ gcc/gimplify.c (revision 273477) @@ -191,6 +191,7 @@ struct gimplify_omp_ctx bool target_map_scalars_firstprivate; bool target_map_pointers_as_0len_arrays; bool target_firstprivatize_array_bases; + bool add_safelen1; }; static struct gimplify_ctx *gimplify_ctxp; @@ -1294,12 +1295,17 @@ gimplify_bind_expr (tree *expr_p, gimple || splay_tree_lookup (ctx->variables, (splay_tree_key) t) == NULL)) { + int flag = GOVD_LOCAL; if (ctx->region_type == ORT_SIMD && TREE_ADDRESSABLE (t) && !TREE_STATIC (t)) - omp_add_variable (ctx, t, GOVD_PRIVATE | GOVD_SEEN); - else - omp_add_variable (ctx, t, GOVD_LOCAL | GOVD_SEEN); + { + if (TREE_CODE (DECL_SIZE_UNIT (t)) != INTEGER_CST) + ctx->add_safelen1 = true; + else + flag = GOVD_PRIVATE; + } + omp_add_variable (ctx, t, flag | GOVD_SEEN); } DECL_SEEN_IN_BIND_EXPR_P (t) = 1; @@ -9026,6 +9032,19 @@ gimplify_adjust_omp_clauses (gimple_seq omp_find_stores_op, &wi); } } + + if (ctx->add_safelen1) + { + /* If there are VLAs in the body of simd loop, prevent + vectorization. */ + gcc_assert (ctx->region_type == ORT_SIMD); + c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN); + OMP_CLAUSE_SAFELEN_EXPR (c) = integer_one_node; + OMP_CLAUSE_CHAIN (c) = *list_p; + *list_p = c; + list_p = &OMP_CLAUSE_CHAIN (c); + } + while ((c = *list_p) != NULL) { splay_tree_node n; --- gcc/testsuite/gcc.dg/gomp/pr78884.c (nonexistent) +++ gcc/testsuite/gcc.dg/gomp/pr78884.c (revision 273477) @@ -0,0 +1,16 @@ +/* PR middle-end/78884 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fopenmp" } */ + +void bar (int *); + +void +foo (int n) +{ +#pragma omp simd + for (int i = 0; i < 1024; i++) + { + int vla[n]; + bar (vla); + } +} 2019-08-30 Jakub Jelinek Backported from mainline 2019-07-30 Jakub Jelinek PR target/91150 * config/i386/i386.c (expand_vec_perm_blend): Change mask type from unsigned to unsigned HOST_WIDE_INT. For E_V64QImode cast comparison to unsigned HOST_WIDE_INT before shifting it left. * gcc.target/i386/avx512bw-pr91150.c: New test. --- gcc/config/i386/i386.c (revision 273963) +++ gcc/config/i386/i386.c (revision 273964) @@ -46199,7 +46199,8 @@ static bool expand_vec_perm_blend (struct expand_vec_perm_d *d) { machine_mode mmode, vmode = d->vmode; - unsigned i, mask, nelt = d->nelt; + unsigned i, nelt = d->nelt; + unsigned HOST_WIDE_INT mask; rtx target, op0, op1, maskop, x; rtx rperm[32], vperm; @@ -46253,7 +46254,7 @@ expand_vec_perm_blend (struct expand_vec case E_V16SImode: case E_V8DImode: for (i = 0; i < nelt; ++i) - mask |= (d->perm[i] >= nelt) << i; + mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i; break; case E_V2DImode: --- gcc/testsuite/gcc.target/i386/avx512bw-pr91150.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/avx512bw-pr91150.c (revision 273964) @@ -0,0 +1,37 @@ +/* PR target/91150 */ +/* { dg-do run } */ +/* { dg-options "-O2 -mavx512bw" } */ +/* { dg-require-effective-target avx512bw } */ + +#include "avx512bw-check.h" + +typedef unsigned char V __attribute__((vector_size (64))); + +__attribute__((noinline, noclone)) void +foo (V *x, V *y, V *z) +{ + *x = __builtin_shuffle (*y, *z, (V) { 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127 }); +} + +static void +avx512bw_test (void) +{ + union U { unsigned char a[64]; V v; } a, b, c; + int i; + for (i = 0; i < 64; i++) + { + b.a[i] = i + 1; + c.a[i] = i + 65; + } + foo (&a.v, &b.v, &c.v); + for (i = 0; i < 64; i++) + if (a.a[i] != (i < 16 ? i + 1 : i + 65)) + __builtin_abort (); +} --- gcc/toplev.c (revision 270711) +++ gcc/toplev.c (revision 270712) @@ -1981,6 +1981,36 @@ do_compile () else int_n_enabled_p[i] = false; + /* Initialize mpfrs exponent range. This is important to get + underflow/overflow in a reasonable timeframe. */ + machine_mode mode; + int min_exp = -1; + int max_exp = 1; + for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + if (SCALAR_FLOAT_MODE_P (mode)) + { + const real_format *fmt = REAL_MODE_FORMAT (mode); + if (fmt) + { + /* fmt->emin - fmt->p + 1 should be enough but the + back-and-forth dance in real_to_decimal_for_mode we + do for checking fails due to rounding effects then. */ + if ((fmt->emin - fmt->p) < min_exp) + min_exp = fmt->emin - fmt->p; + if (fmt->emax > max_exp) + max_exp = fmt->emax; + } + } + /* E.g. mpc_norm assumes it can square a number without bothering with + with range scaling, so until that is fixed, double the minimum + and maximum exponents, plus add some buffer for arithmetics + on the squared numbers. */ + if (mpfr_set_emin (2 * (min_exp - 1)) + || mpfr_set_emax (2 * (max_exp + 1))) + sorry ("mpfr not configured to handle all float modes"); + /* Set up the back-end if requested. */ if (!no_backend) backend_init (); --- gcc/testsuite/gcc.dg/pr88074.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr88074.c (revision 270712) @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +#include + +int main() +{ + _Complex double x; + __real x = 3.091e+8; + __imag x = -4.045e+8; + /* This used to spend huge amounts of compile-time inside mpc. */ + volatile _Complex double y = ctan (x); + return 0; +} --- gcc/testsuite/gcc.dg/pr88074-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr88074-2.c (revision 270712) @@ -0,0 +1,17 @@ +/* PR middle-end/88074 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-add-options float128 } */ +/* { dg-require-effective-target float128 } */ +/* { dg-final { scan-tree-dump-not "link_error " "optimized" } } */ + +extern void link_error (void); +int +main () +{ + if (((__FLT128_MAX__ * 0.5 + __FLT128_MAX__ * 0.5i) + / (__FLT128_MAX__ * 0.25 + __FLT128_MAX__ * 0.25i)) + != (_Complex _Float128) 2) + link_error (); + return 0; +}