Hi!

I've backported following patches to 5.x, bootstrapped/regtested them on
x86_64-linux and i686-linux and committed.

        Jakub
2017-09-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-06-21  Jakub Jelinek  <ja...@redhat.com>

        PR c++/81154
        * semantics.c (handle_omp_array_sections_1, finish_omp_clauses):
        Complain about t not being a variable if t is OVERLOAD even
        when processing_template_decl.

        * g++.dg/gomp/pr81154.C: New test.

--- gcc/cp/semantics.c  (revision 249482)
+++ gcc/cp/semantics.c  (revision 249483)
@@ -4297,7 +4297,7 @@ handle_omp_array_sections_1 (tree c, tre
        return error_mark_node;
       if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
        {
-         if (processing_template_decl)
+         if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
            return NULL_TREE;
          if (DECL_P (t))
            error_at (OMP_CLAUSE_LOCATION (c),
@@ -5392,7 +5392,7 @@ finish_omp_clauses (tree clauses)
          t = OMP_CLAUSE_DECL (c);
          if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
            {
-             if (processing_template_decl)
+             if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
                break;
              if (DECL_P (t))
                error ("%qD is not a variable in clause %qs", t,
@@ -5417,7 +5417,7 @@ finish_omp_clauses (tree clauses)
          t = OMP_CLAUSE_DECL (c);
          if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
            {
-             if (processing_template_decl)
+             if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
                break;
              if (DECL_P (t))
                error ("%qD is not a variable in clause %<firstprivate%>", t);
@@ -5439,7 +5439,7 @@ finish_omp_clauses (tree clauses)
          t = OMP_CLAUSE_DECL (c);
          if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
            {
-             if (processing_template_decl)
+             if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
                break;
              if (DECL_P (t))
                error ("%qD is not a variable in clause %<lastprivate%>", t);
@@ -5683,7 +5683,7 @@ finish_omp_clauses (tree clauses)
          t = OMP_CLAUSE_DECL (c);
          if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
            {
-             if (processing_template_decl)
+             if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
                break;
              if (DECL_P (t))
                error ("%qD is not a variable in %<aligned%> clause", t);
@@ -5753,7 +5753,7 @@ finish_omp_clauses (tree clauses)
            remove = true;
          else if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
            {
-             if (processing_template_decl)
+             if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
                break;
              if (DECL_P (t))
                error ("%qD is not a variable in %<depend%> clause", t);
@@ -5795,7 +5795,7 @@ finish_omp_clauses (tree clauses)
            remove = true;
          else if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
            {
-             if (processing_template_decl)
+             if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
                break;
              if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
                  && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
--- gcc/testsuite/g++.dg/gomp/pr81154.C (nonexistent)
+++ gcc/testsuite/g++.dg/gomp/pr81154.C (revision 249483)
@@ -0,0 +1,51 @@
+// PR c++/81154
+// { dg-do compile }
+
+template <typename T>
+struct C
+{
+  int foo (T n) const
+  {
+#pragma omp parallel shared (foo)      // { dg-error "is not a variable in 
clause" }
+    ;
+#pragma omp parallel private (foo)     // { dg-error "is not a variable in 
clause" }
+    ;
+#pragma omp parallel firstprivate (foo)        // { dg-error "is not a 
variable in clause" }
+    ;
+#pragma omp parallel for lastprivate (foo)     // { dg-error "is not a 
variable in clause" }
+    for (T i = 0; i < n; i++)
+      ;
+#pragma omp parallel reduction (+:foo) // { dg-error "is not a variable in 
clause" }
+    ;
+    return 0;
+  }
+  int foo (int x, int y) { return x; }
+};
+
+struct D
+{
+  typedef int T;
+  int foo (T n) const
+  {
+#pragma omp parallel shared (foo)      // { dg-error "is not a variable in 
clause" }
+    ;
+#pragma omp parallel private (foo)     // { dg-error "is not a variable in 
clause" }
+    ;
+#pragma omp parallel firstprivate (foo)        // { dg-error "is not a 
variable in clause" }
+    ;
+#pragma omp parallel for lastprivate (foo)     // { dg-error "is not a 
variable in clause" }
+    for (T i = 0; i < n; i++)
+      ;
+#pragma omp parallel reduction (+:foo) // { dg-error "is not a variable in 
clause" }
+    ;
+    return 0;
+  }
+  int foo (int x, int y) { return x; }
+};
+
+int
+main ()
+{
+  C<int> ().foo (1);
+  D ().foo (1);
+}
2017-09-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-06-13  Jakub Jelinek  <ja...@redhat.com>

        PR c++/80984
        * cp-gimplify.c (cp_genericize): Only look for VAR_DECLs in
        BLOCK_VARS (outer) chain.
        (cxx_omp_const_qual_no_mutable): Likewise.

        * g++.dg/opt/nrv18.C: New test.

--- gcc/cp/cp-gimplify.c        (revision 249508)
+++ gcc/cp/cp-gimplify.c        (revision 249509)
@@ -1566,7 +1566,8 @@ cp_genericize (tree fndecl)
 
          if (outer)
            for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
-             if (DECL_NAME (t) == DECL_NAME (var)
+             if (VAR_P (var)
+                 && DECL_NAME (t) == DECL_NAME (var)
                  && DECL_HAS_VALUE_EXPR_P (var)
                  && DECL_VALUE_EXPR (var) == t)
                {
@@ -1813,7 +1814,8 @@ cxx_omp_const_qual_no_mutable (tree decl
 
          if (outer)
            for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
-             if (DECL_NAME (decl) == DECL_NAME (var)
+             if (VAR_P (var)
+                 && DECL_NAME (decl) == DECL_NAME (var)
                  && (TYPE_MAIN_VARIANT (type)
                      == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
                {
--- gcc/testsuite/g++.dg/opt/nrv18.C    (nonexistent)
+++ gcc/testsuite/g++.dg/opt/nrv18.C    (revision 249509)
@@ -0,0 +1,12 @@
+// PR c++/80984
+// { dg-do compile }
+
+struct A { ~A (); };
+
+A
+foo ()
+{
+  A a;
+a:
+  return a;
+}
2017-09-16  Jakub Jelinek  <ja...@redhat.com>

        PR libquadmath/65757
        * math/roundq.c: Cherry-pick upstream glibc 2015-04-28 change.

--- libquadmath/math/roundq.c   (revision 250378)
+++ libquadmath/math/roundq.c   (revision 250379)
@@ -1,5 +1,5 @@
 /* Round __float128 to integer away from zero.
-   Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1997-2017 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drep...@cygnus.com>, 1997 and
                  Jakub Jelinek <j...@ultra.linux.cz>, 1999.
@@ -32,7 +32,7 @@ roundq (__float128 x)
 
   GET_FLT128_WORDS64 (i0, i1, x);
   j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
-  if (j0 < 31)
+  if (j0 < 48)
     {
       if (j0 < 0)
        {
2017-09-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-08-08  Richard Biener  <rguent...@suse.de>

        PR middle-end/81766
        * function.c (thread_prologue_and_epilogue_insns): Restore
        behavior of always calling find_many_sub_basic_blocks on
        the inserted prologue.

        * gcc.target/i386/pr81766.c: New testcase.

        2017-08-02  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/79499
        * function.c (thread_prologue_and_epilogue_insns): Determine blocks
        for find_many_sub_basic_blocks bitmap by looking up BLOCK_FOR_INSN
        of first NONDEBUG_INSN_P in each of the split_prologue_seq and
        prologue_seq sequences - if any.

        * gcc.dg/pr79499.c: New test.

--- gcc/function.c      (revision 250814)
+++ gcc/function.c      (revision 250958)
@@ -6068,13 +6068,19 @@ thread_prologue_and_epilogue_insns (void
 
   try_shrink_wrapping (&entry_edge, &bb_flags, prologue_seq);
 
+  rtx_insn *split_prologue_insn = split_prologue_seq;
   if (split_prologue_seq != NULL_RTX)
     {
+      while (split_prologue_insn && !NONDEBUG_INSN_P (split_prologue_insn))
+       split_prologue_insn = NEXT_INSN (split_prologue_insn);
       insert_insn_on_edge (split_prologue_seq, orig_entry_edge);
       inserted = true;
     }
+  rtx_insn *prologue_insn = prologue_seq;
   if (prologue_seq != NULL_RTX)
     {
+      while (prologue_insn && !NONDEBUG_INSN_P (prologue_insn))
+       prologue_insn = NEXT_INSN (prologue_insn);
       insert_insn_on_edge (prologue_seq, entry_edge);
       inserted = true;
     }
@@ -6215,8 +6221,19 @@ epilogue_done:
       commit_edge_insertions ();
 
       /* Look for basic blocks within the prologue insns.  */
+      if (split_prologue_insn
+         && BLOCK_FOR_INSN (split_prologue_insn) == NULL)
+       split_prologue_insn = NULL;
+      if (prologue_insn
+         && BLOCK_FOR_INSN (prologue_insn) == NULL)
+       prologue_insn = NULL;
       blocks = sbitmap_alloc (last_basic_block_for_fn (cfun));
       bitmap_clear (blocks);
+      if (split_prologue_insn)
+       bitmap_set_bit (blocks,
+                       BLOCK_FOR_INSN (split_prologue_insn)->index);
+      if (prologue_insn)
+       bitmap_set_bit (blocks, BLOCK_FOR_INSN (prologue_insn)->index);
       bitmap_set_bit (blocks, entry_edge->dest->index);
       bitmap_set_bit (blocks, orig_entry_edge->dest->index);
       find_many_sub_basic_blocks (blocks);
--- gcc/testsuite/gcc.dg/pr79499.c      (nonexistent)
+++ gcc/testsuite/gcc.dg/pr79499.c      (revision 250815)
@@ -0,0 +1,13 @@
+/* PR middle-end/79499 */
+/* { dg-do compile { target split_stack } } */
+/* { dg-options "-O2 -fsplit-stack -fno-omit-frame-pointer" } */
+
+struct S { struct S *a, *b; };
+
+void
+foo (struct S *x)
+{
+  do
+    x->b = x->a;
+  while (x = x->a);
+}
--- gcc/testsuite/gcc.target/i386/pr81766.c     (nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr81766.c     (revision 250958)
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -fPIE -mcmodel=large" } */
+
+int main() { return 0; }
2017-09-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-07-27  Jakub Jelinek  <ja...@redhat.com>

        PR c/45784
        * c-omp.c (c_finish_omp_for): If the condition is wrapped in
        rhs of COMPOUND_EXPR(s), skip them and readd their lhs into
        new COMPOUND_EXPRs around the rhs of the comparison.

        * testsuite/libgomp.c/pr45784.c: New test.
        * testsuite/libgomp.c++/pr45784.C: New test.

--- gcc/c-family/c-omp.c        (revision 251847)
+++ gcc/c-family/c-omp.c        (revision 251848)
@@ -531,6 +531,12 @@ c_finish_omp_for (location_t locus, enum
        {
          bool cond_ok = false;
 
+         /* E.g. C sizeof (vla) could add COMPOUND_EXPRs with
+            evaluation of the vla VAR_DECL.  We need to readd
+            them to the non-decl operand.  See PR45784.  */
+         while (TREE_CODE (cond) == COMPOUND_EXPR)
+           cond = TREE_OPERAND (cond, 1);
+
          if (EXPR_HAS_LOCATION (cond))
            elocus = EXPR_LOCATION (cond);
 
@@ -605,6 +611,21 @@ c_finish_omp_for (location_t locus, enum
                  else if (code != CILK_SIMD && code != CILK_FOR)
                    cond_ok = false;
                }
+
+             if (cond_ok && TREE_VEC_ELT (condv, i) != cond)
+               {
+                 tree ce = NULL_TREE, *pce = &ce;
+                 tree type = TREE_TYPE (TREE_OPERAND (cond, 1));
+                 for (tree c = TREE_VEC_ELT (condv, i); c != cond;
+                      c = TREE_OPERAND (c, 1))
+                   {
+                     *pce = build2 (COMPOUND_EXPR, type, TREE_OPERAND (c, 0),
+                                    TREE_OPERAND (cond, 1));
+                     pce = &TREE_OPERAND (*pce, 1);
+                   }
+                 TREE_OPERAND (cond, 1) = ce;
+                 TREE_VEC_ELT (condv, i) = cond;
+               }
            }
 
          if (!cond_ok)
--- libgomp/testsuite/libgomp.c/pr45784.c       (nonexistent)
+++ libgomp/testsuite/libgomp.c/pr45784.c       (revision 251848)
@@ -0,0 +1,41 @@
+/* PR c/45784 */
+/* { dg-do run } */
+
+void
+foo (int n)
+{
+  char *p, vla[2 * n];
+  int i;
+  #pragma omp parallel for
+  for (p = vla; p < vla + (sizeof (vla) / sizeof (vla[0])); p++)
+    *p = ' ';
+  #pragma omp parallel for
+  for (i = 0; i < 2 * n; i++)
+    if (vla[i] != ' ')
+      __builtin_abort ();
+}
+
+void
+bar (int n)
+{
+  char *p, vla1[n], vla2[n * 2], vla3[n * 3], vla4[n * 4];
+  int i;
+  __builtin_memset (vla4, ' ', n * 4);
+  #pragma omp parallel for
+  for (p = vla4 + sizeof (vla1); p < vla4 + sizeof (vla3) - sizeof (vla2) + 
sizeof (vla1); p += sizeof (vla4) / sizeof (vla4))
+    p[0] = '!';
+  #pragma omp parallel for
+  for (i = 0; i < n * 4; i++)
+    if (vla4[i] != ((i >= n && i < 2 * n) ? '!' : ' '))
+      __builtin_abort ();
+}
+
+int
+main ()
+{
+  volatile int n;
+  n = 128;
+  foo (n);
+  bar (n);
+  return 0;
+}
--- libgomp/testsuite/libgomp.c++/pr45784.C     (nonexistent)
+++ libgomp/testsuite/libgomp.c++/pr45784.C     (revision 251848)
@@ -0,0 +1,5 @@
+// PR c/45784
+// { dg-do run }
+
+#include "../libgomp.c/pr45784.c"
+
2017-09-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-08-03  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/81052
        * omp-low.c (diagnose_sb_0): Handle flag_openmp_simd like flag_openmp.
        (pass_diagnose_omp_blocks::gate): Enable also for flag_openmp_simd.

        * c-c++-common/pr81052.c: New test.

--- gcc/omp-low.c       (revision 251848)
+++ gcc/omp-low.c       (revision 251849)
@@ -9089,7 +9089,7 @@ diagnose_sb_0 (gimple_stmt_iterator *gsi
     }
   if (kind == NULL)
     {
-      gcc_checking_assert (flag_openmp);
+      gcc_checking_assert (flag_openmp || flag_openmp_simd);
       kind = "OpenMP";
     }
 
@@ -9349,7 +9349,7 @@ public:
   /* opt_pass methods: */
   virtual bool gate (function *)
   {
-    return flag_cilkplus || flag_openacc || flag_openmp;
+    return flag_cilkplus || flag_openacc || flag_openmp || flag_openmp_simd;
   }
   virtual unsigned int execute (function *)
     {
--- gcc/testsuite/c-c++-common/pr81052.c        (nonexistent)
+++ gcc/testsuite/c-c++-common/pr81052.c        (revision 251849)
@@ -0,0 +1,28 @@
+/* PR middle-end/81052 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -O2" } */
+
+int
+foo (int x, int y)
+{
+  int i;
+#pragma omp simd
+  for (i = x; i < y; ++i)
+    return 0;                  /* { dg-error "invalid branch to/from OpenMP 
structured block" } */
+  return 1;
+}
+
+#ifdef __cplusplus
+template <typename T>
+T
+bar (T x, T y)
+{
+  T i;
+#pragma omp simd
+  for (i = x; i < y; ++i)
+    return 0;                  /* { dg-error "invalid branch to/from OpenMP 
structured block" "" { target c++ } } */
+  return 1;
+}
+
+int x = bar (1, 7);
+#endif
2017-09-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-08-03  Jakub Jelinek  <ja...@redhat.com>

        PR target/81621
        * bb-reorder.c (pass_partition_blocks::execute): Return TODO_df_finish
        after setting changeable df flags.

        * gcc.dg/pr81621.c: New test.

--- gcc/bb-reorder.c    (revision 251850)
+++ gcc/bb-reorder.c    (revision 251851)
@@ -2881,7 +2881,8 @@ pass_partition_blocks::execute (function
 
   crossing_edges = find_rarely_executed_basic_blocks_and_crossing_edges ();
   if (!crossing_edges.exists ())
-    return 0;
+    /* Make sure to process deferred rescans and clear changeable df flags.  */
+    return TODO_df_finish;
 
   crtl->has_bb_partition = true;
 
@@ -2947,7 +2948,8 @@ pass_partition_blocks::execute (function
       df_analyze ();
     }
 
-  return 0;
+  /* Make sure to process deferred rescans and clear changeable df flags.  */
+  return TODO_df_finish;
 }
 
 } // anon namespace
--- gcc/testsuite/gcc.dg/pr81621.c      (nonexistent)
+++ gcc/testsuite/gcc.dg/pr81621.c      (revision 251851)
@@ -0,0 +1,5 @@
+/* PR target/81621 */
+/* { dg-do compile { target freorder } } */
+/* { dg-options "-Og -fno-split-wide-types -freorder-blocks-and-partition" } */
+
+#include "graphite/scop-10.c"
2017-09-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-08-09  Jakub Jelinek  <ja...@redhat.com>

        PR c/81687
        * omp-low.c (omp_copy_decl): Don't remap FORCED_LABEL or DECL_NONLOCAL
        LABEL_DECLs.
        * tree-cfg.c (move_stmt_op): Don't adjust DECL_CONTEXT of FORCED_LABEL
        or DECL_NONLOCAL labels.
        (move_stmt_r) <case GIMPLE_LABEL>: Adjust DECL_CONTEXT of FORCED_LABEL
        or DECL_NONLOCAL labels here.

        * testsuite/libgomp.c/pr81687-1.c: New test.
        * testsuite/libgomp.c/pr81687-2.c: New test.

--- gcc/omp-low.c       (revision 251852)
+++ gcc/omp-low.c       (revision 251853)
@@ -800,6 +800,8 @@ omp_copy_decl (tree var, copy_body_data
 
   if (TREE_CODE (var) == LABEL_DECL)
     {
+      if (FORCED_LABEL (var) || DECL_NONLOCAL (var))
+       return var;
       new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
       DECL_CONTEXT (new_var) = current_function_decl;
       insert_decl_map (&ctx->cb, var, new_var);
--- gcc/tree-cfg.c      (revision 251852)
+++ gcc/tree-cfg.c      (revision 251853)
@@ -6667,7 +6667,15 @@ move_stmt_op (tree *tp, int *walk_subtre
                *tp = t = out->to;
            }
 
-         DECL_CONTEXT (t) = p->to_context;
+         /* For FORCED_LABELs we can end up with references from other
+            functions if some SESE regions are outlined.  It is UB to
+            jump in between them, but they could be used just for printing
+            addresses etc.  In that case, DECL_CONTEXT on the label should
+            be the function containing the glabel stmt with that LABEL_DECL,
+            rather than whatever function a reference to the label was seen
+            last time.  */
+         if (!FORCED_LABEL (t) && !DECL_NONLOCAL (t))
+           DECL_CONTEXT (t) = p->to_context;
        }
       else if (p->remap_decls_p)
        {
@@ -6785,6 +6793,21 @@ move_stmt_r (gimple_stmt_iterator *gsi_p
     case GIMPLE_OMP_RETURN:
     case GIMPLE_OMP_CONTINUE:
       break;
+
+    case GIMPLE_LABEL:
+      {
+       /* For FORCED_LABEL, move_stmt_op doesn't adjust DECL_CONTEXT,
+          so that such labels can be referenced from other regions.
+          Make sure to update it when seeing a GIMPLE_LABEL though,
+          that is the owner of the label.  */
+       walk_gimple_op (stmt, move_stmt_op, wi);
+       *handled_ops_p = true;
+       tree label = gimple_label_label (as_a <glabel *> (stmt));
+       if (FORCED_LABEL (label) || DECL_NONLOCAL (label))
+         DECL_CONTEXT (label) = p->to_context;
+      }
+      break;
+
     default:
       if (is_gimple_omp (stmt))
        {
--- libgomp/testsuite/libgomp.c/pr81687-1.c     (nonexistent)
+++ libgomp/testsuite/libgomp.c/pr81687-1.c     (revision 251853)
@@ -0,0 +1,23 @@
+/* PR c/81687 */
+/* { dg-do link } */
+/* { dg-additional-options "-O2" } */
+
+extern int printf (const char *, ...);
+
+int
+main ()
+{
+  #pragma omp parallel
+  {
+   lab1:
+    printf ("lab1=%p\n", (void *)(&&lab1));
+  }
+ lab2:
+  #pragma omp parallel
+  {
+   lab3:
+    printf ("lab2=%p\n", (void *)(&&lab2));
+  }
+  printf ("lab3=%p\n", (void *)(&&lab3));
+  return 0;
+}
--- libgomp/testsuite/libgomp.c/pr81687-2.c     (nonexistent)
+++ libgomp/testsuite/libgomp.c/pr81687-2.c     (revision 251853)
@@ -0,0 +1,27 @@
+/* PR c/81687 */
+/* { dg-do link } */
+/* { dg-additional-options "-O2" } */
+
+int
+main ()
+{
+  __label__ lab4, lab5, lab6;
+  volatile int l = 0;
+  int m = l;
+  void foo (int x) { if (x == 1) goto lab4; }
+  void bar (int x) { if (x == 2) goto lab5; }
+  void baz (int x) { if (x == 3) goto lab6; }
+  #pragma omp parallel
+  {
+    foo (m + 1);
+   lab4:;
+  }
+  #pragma omp task
+  {
+    bar (m + 2);
+   lab5:;
+  }
+  baz (m + 3);
+ lab6:;
+  return 0;
+}
2017-09-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-09-12  Jakub Jelinek  <ja...@redhat.com>

        PR target/82112
        * c-common.c (sync_resolve_size): Instead of c_dialect_cxx ()
        assertion check that in the condition.
        (get_atomic_generic_size): Likewise.  Before testing if parameter
        has pointer type, if it has array type, call for C++
        default_conversion to perform array-to-pointer conversion.

        * c-c++-common/pr82112.c: New test.
        * gcc.dg/pr82112.c: New test.

--- gcc/c-family/c-common.c     (revision 252802)
+++ gcc/c-family/c-common.c     (revision 252803)
@@ -10534,10 +10534,9 @@ sync_resolve_size (tree function, vec<tr
     }
 
   type = TREE_TYPE ((*params)[0]);
-  if (TREE_CODE (type) == ARRAY_TYPE)
+  if (TREE_CODE (type) == ARRAY_TYPE && c_dialect_cxx ())
     {
       /* Force array-to-pointer decay for C++.  */
-      gcc_assert (c_dialect_cxx());
       (*params)[0] = default_conversion ((*params)[0]);
       type = TREE_TYPE ((*params)[0]);
     }
@@ -10692,10 +10691,9 @@ get_atomic_generic_size (location_t loc,
 
   /* Get type of first parameter, and determine its size.  */
   type_0 = TREE_TYPE ((*params)[0]);
-  if (TREE_CODE (type_0) == ARRAY_TYPE)
+  if (TREE_CODE (type_0) == ARRAY_TYPE && c_dialect_cxx ())
     {
       /* Force array-to-pointer decay for C++.  */
-      gcc_assert (c_dialect_cxx());
       (*params)[0] = default_conversion ((*params)[0]);
       type_0 = TREE_TYPE ((*params)[0]);
     }
@@ -10734,6 +10732,12 @@ get_atomic_generic_size (location_t loc,
       /* __atomic_compare_exchange has a bool in the 4th position, skip it.  */
       if (n_param == 6 && x == 3)
         continue;
+      if (TREE_CODE (type) == ARRAY_TYPE && c_dialect_cxx ())
+       {
+         /* Force array-to-pointer decay for C++.  */
+         (*params)[x] = default_conversion ((*params)[x]);
+         type = TREE_TYPE ((*params)[x]);
+       }
       if (!POINTER_TYPE_P (type))
        {
          error_at (loc, "argument %d of %qE must be a pointer type", x + 1,
--- gcc/testsuite/gcc.dg/pr82112.c      (nonexistent)
+++ gcc/testsuite/gcc.dg/pr82112.c      (revision 252803)
@@ -0,0 +1,21 @@
+/* PR target/82112 */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu90" } */
+
+struct S { int a[10]; } bar (void);
+int b, c;
+
+void
+foo (void)
+{
+  __atomic_load (bar ().a, &b, __ATOMIC_ACQUIRE);      /* { dg-error "argument 
1 of .__atomic_load. must be a non-void pointer type" } */
+  __atomic_load (&b, bar ().a, __ATOMIC_ACQUIRE);      /* { dg-error "argument 
2 of .__atomic_load. must be a pointer type" } */
+  __atomic_store (bar ().a, &b, __ATOMIC_SEQ_CST);     /* { dg-error "argument 
1 of .__atomic_store. must be a non-void pointer type" } */
+  __atomic_store (&b, bar ().a, __ATOMIC_SEQ_CST);     /* { dg-error "argument 
2 of .__atomic_store. must be a pointer type" } */
+  __atomic_exchange (bar ().a, &b, &c, __ATOMIC_RELAXED);      /* { dg-error 
"argument 1 of .__atomic_exchange. must be a non-void pointer type" } */
+  __atomic_exchange (&b, bar ().a, &c, __ATOMIC_RELAXED);      /* { dg-error 
"argument 2 of .__atomic_exchange. must be a pointer type" } */
+  __atomic_exchange (&b, &c, bar ().a, __ATOMIC_RELAXED);      /* { dg-error 
"argument 3 of .__atomic_exchange. must be a pointer type" } */
+  __atomic_compare_exchange (bar ().a, &b, &c, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED); /* { dg-error "argument 1 of .__atomic_compare_exchange. 
must be a non-void pointer type" } */
+  __atomic_compare_exchange (&b, bar ().a, &c, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED); /* { dg-error "argument 2 of .__atomic_compare_exchange. 
must be a pointer type" } */
+  __atomic_compare_exchange (&b, &c, bar ().a, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED); /* { dg-error "argument 3 of .__atomic_compare_exchange. 
must be a pointer type" } */
+}
--- gcc/testsuite/c-c++-common/pr82112.c        (nonexistent)
+++ gcc/testsuite/c-c++-common/pr82112.c        (revision 252803)
@@ -0,0 +1,13 @@
+/* PR target/82112 */
+/* { dg-do compile } */
+
+int c[10], d[10], e[10], f[10], g[10], h[10], i[10], j[10], k[10], l[10];
+
+void
+foo (void)
+{
+  __atomic_load (c, d, __ATOMIC_ACQUIRE);
+  __atomic_store (e, f, __ATOMIC_SEQ_CST);
+  __atomic_exchange (g, h, i, __ATOMIC_RELAXED);
+  __atomic_compare_exchange (j, k, l, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
2017-09-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-09-12  Jakub Jelinek  <ja...@redhat.com>

        PR target/82112
        * gcc.target/powerpc/pr82112.c: New test.
        * g++.dg/ext/altivec-18.C: New test.

--- gcc/testsuite/gcc.target/powerpc/pr82112.c  (nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/pr82112.c  (revision 252804)
@@ -0,0 +1,16 @@
+/* PR target/82112 */
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec -std=gnu90" } */
+
+#include <altivec.h>
+
+struct __attribute__((aligned (16))) S { unsigned char c[64]; } bar (void);
+vector unsigned char v;
+
+void
+foo (void)
+{
+  vec_ld (0, bar ().c);        /* { dg-error "invalid parameter combination 
for AltiVec intrinsic" } */
+  vec_st (v, 0, bar ().c);     /* { dg-error "invalid parameter combination 
for AltiVec intrinsic" } */
+}
--- gcc/testsuite/g++.dg/ext/altivec-18.C       (nonexistent)
+++ gcc/testsuite/g++.dg/ext/altivec-18.C       (revision 252804)
@@ -0,0 +1,14 @@
+// PR target/82112
+// { dg-do compile { target powerpc*-*-* } }
+// { dg-require-effective-target powerpc_altivec_ok }
+// { dg-options "-maltivec" }
+
+#include <altivec.h>
+
+__attribute__((aligned (16))) extern const unsigned char c[16];
+
+void
+foo (void)
+{
+  vec_ld (0, c);
+}

Reply via email to