Backports to 5.5

Jakub Jelinek jakub@redhat.com
Thu Jul 7 13:03:00 GMT 2016


Hi!

I've bootstrapped/regtested on x86_64-linux and i686-linux following 18
trunk/6.x commits and committed them to gcc-5-branch.

	Jakub
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-02-02  Segher Boessenkool  <segher@kernel.crashing.org>

	* c-c++-common/vector-compare-4.c: Prune "non-standard ABI extension"
	warning.

--- gcc/testsuite/c-c++-common/vector-compare-4.c	(revision 233092)
+++ gcc/testsuite/c-c++-common/vector-compare-4.c	(revision 233093)
@@ -1,6 +1,8 @@
 /* PR c/68062 */
 /* { dg-do compile } */
 /* { dg-options "-Wsign-compare" } */
+/* Ignore warning on some powerpc configurations. */
+/* { dg-prune-output "non-standard ABI extension" } */
 
 typedef signed char __attribute__ ((vector_size (4))) v4qi;
 typedef unsigned char __attribute__ ((vector_size (4))) uv4qi;
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-03-02  Jakub Jelinek  <jakub@redhat.com>

	PR c/68062
	* c-c++-common/vector-compare-4.c: Add -Wno-psabi to dg-options.

--- gcc/testsuite/c-c++-common/vector-compare-4.c	(revision 233904)
+++ gcc/testsuite/c-c++-common/vector-compare-4.c	(revision 233905)
@@ -1,6 +1,6 @@
 /* PR c/68062 */
 /* { dg-do compile } */
-/* { dg-options "-Wsign-compare" } */
+/* { dg-options "-Wsign-compare -Wno-psabi" } */
 /* Ignore warning on some powerpc configurations. */
 /* { dg-prune-output "non-standard ABI extension" } */
 
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-04-05  Jakub Jelinek  <jakub@redhat.com>

	PR c++/70336
	* match.pd (nested int casts): Limit to GIMPLE.

	* c-c++-common/pr70336.c: New test.
	* gcc.dg/torture/builtin-isinf_sign-1.c (foo): Guard tests
	no longer optimized away at -O0 with #ifndef __OPTIMIZE__.

--- gcc/match.pd	(revision 234763)
+++ gcc/match.pd	(revision 234764)
@@ -750,7 +750,8 @@ along with GCC; see the file COPYING3.
 
    /* A truncation to an unsigned type (a zero-extension) should be
       canonicalized as bitwise and of a mask.  */
-   (if (final_int && inter_int && inside_int
+   (if (GIMPLE /* PR70366: doing this in GENERIC breaks -Wconversion.  */
+	&& final_int && inter_int && inside_int
 	&& final_prec == inside_prec
 	&& final_prec > inter_prec
 	&& inter_unsignedp)
--- gcc/testsuite/gcc.dg/torture/builtin-isinf_sign-1.c	(revision 234763)
+++ gcc/testsuite/gcc.dg/torture/builtin-isinf_sign-1.c	(revision 234764)
@@ -24,6 +24,7 @@ foo (float f, double d, long double ld)
       != (__builtin_isinf(ld) ? (__builtin_signbitl(ld) ? -1 : 1) : 0))
     link_error (__LINE__);
 
+#ifdef __OPTIMIZE__
   /* In boolean contexts, GCC will fold the inner conditional
      expression to 1.  So isinf_sign folds to plain isinf.  */
 
@@ -33,6 +34,7 @@ foo (float f, double d, long double ld)
     link_error (__LINE__);
   if ((_Bool)__builtin_isinf_sign(ld) != (__builtin_isinf(ld) != 0))
     link_error (__LINE__);
+#endif
 
   if ((__builtin_isinf_sign(f) != 0) != (__builtin_isinf(f) != 0))
     link_error (__LINE__);
--- gcc/testsuite/c-c++-common/pr70336.c	(revision 0)
+++ gcc/testsuite/c-c++-common/pr70336.c	(revision 234764)
@@ -0,0 +1,37 @@
+/* PR c++/70336 */
+/* { dg-do compile } */
+/* { dg-options "-Wconversion" } */
+
+void
+f1 (unsigned char * x, int y, int z)
+{
+  x[z / 8] |= (unsigned char) (0x80 >> y);	/* { dg-bogus "may alter its value" } */
+}
+
+unsigned char
+f2 (unsigned char x, int y)
+{
+  x = x | (unsigned char) (0x80 >> y);		/* { dg-bogus "may alter its value" } */
+  return x;
+}
+
+unsigned char
+f3 (unsigned char x, int y)
+{
+  x = x | (unsigned char) (y & 255);		/* { dg-bogus "may alter its value" } */
+  return x;
+}
+
+unsigned char
+f4 (unsigned char x, unsigned char y)
+{
+  x = x | (unsigned char) (y & 255);		/* { dg-bogus "may alter its value" } */
+  return x;
+}
+
+unsigned char
+f5 (unsigned char x, int y)
+{
+  x = (unsigned char) (y & 255);		/* { dg-bogus "may alter its value" } */
+  return x;
+}
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-04-08  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/70574
	* fwprop.c (forward_propagate_and_simplify): Don't add
	REG_EQUAL note if DF_REF_REG (use) is a paradoxical subreg.
	(try_fwprop_subst): Don't add REG_EQUAL note if there are any
	paradoxical subregs within *loc.

	* gcc.target/i386/avx2-pr70574.c: New test.

--- gcc/fwprop.c	(revision 234832)
+++ gcc/fwprop.c	(revision 234833)
@@ -999,10 +999,27 @@ try_fwprop_subst (df_ref use, rtx *loc,
 	 making a new one if one does not already exist.  */
       if (set_reg_equal)
 	{
-	  if (dump_file)
-	    fprintf (dump_file, " Setting REG_EQUAL note\n");
+	  /* If there are any paradoxical SUBREGs, don't add REG_EQUAL note,
+	     because the bits in there can be anything and so might not
+	     match the REG_EQUAL note content.  See PR70574.  */
+	  subrtx_var_iterator::array_type array;
+	  FOR_EACH_SUBRTX_VAR (iter, array, *loc, NONCONST)
+	    {
+	      rtx x = *iter;
+	      if (SUBREG_P (x) && paradoxical_subreg_p (x))
+		{
+		  set_reg_equal = false;
+		  break;
+		}
+	    }
+
+	  if (set_reg_equal)
+	    {
+	      if (dump_file)
+		fprintf (dump_file, " Setting REG_EQUAL note\n");
 
-	  note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (new_rtx));
+	      note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (new_rtx));
+	    }
 	}
     }
 
@@ -1300,14 +1317,19 @@ forward_propagate_and_simplify (df_ref u
 	 that isn't mentioned in USE_SET, as the note would be invalid
 	 otherwise.  We also don't want to install a note if we are merely
 	 propagating a pseudo since verifying that this pseudo isn't dead
-	 is a pain; moreover such a note won't help anything.  */
+	 is a pain; moreover such a note won't help anything.
+	 If the use is a paradoxical subreg, make sure we don't add a
+	 REG_EQUAL note for it, because it is not equivalent, it is one
+	 possible value for it, but we can't rely on it holding that value.
+	 See PR70574.  */
       set_reg_equal = (note == NULL_RTX
 		       && REG_P (SET_DEST (use_set))
 		       && !REG_P (src)
 		       && !(GET_CODE (src) == SUBREG
 			    && REG_P (SUBREG_REG (src)))
 		       && !reg_mentioned_p (SET_DEST (use_set),
-					    SET_SRC (use_set)));
+					    SET_SRC (use_set))
+		       && !paradoxical_subreg_p (DF_REF_REG (use)));
     }
 
   if (GET_MODE (*loc) == VOIDmode)
--- gcc/testsuite/gcc.target/i386/avx2-pr70574.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/avx2-pr70574.c	(revision 234833)
@@ -0,0 +1,26 @@
+/* PR rtl-optimization/70574 */
+/* { dg-do run { target lp64 } } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-options "-O -frerun-cse-after-loop -fno-tree-ccp -mcmodel=medium -mavx2" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+#include "avx2-check.h"
+
+typedef char A __attribute__((vector_size (32)));
+typedef short B __attribute__((vector_size (32)));
+
+int
+foo (int x, __int128 y, __int128 z, A w)
+{
+  y <<= 64;
+  w *= (A) { 0, -1, z, 0, ~y };
+  return w[0] + ((B) { x, 0, y, 0, -1 } | 1)[4];
+}
+
+static void
+avx2_test ()
+{
+  int x = foo (0, 0, 0, (A) {});
+  if (x != -1)
+    __builtin_abort ();
+}
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-04-13  Jakub Jelinek  <jakub@redhat.com>

	PR debug/70628
	* explow.c (convert_memory_address_addr_space_1): Formatting fix.

	PR debug/70628
	* rtl.h (convert_memory_address_addr_space_1): New prototype.
	* explow.c (convert_memory_address_addr_space_1): No longer static,
	add NO_EMIT argument and don't call convert_modes if true, pass
	it down recursively, remove break after return.
	(convert_memory_address_addr_space): Adjust caller.
	* simplify-rtx.c (simplify_unary_operation_1): Call
	convert_memory_address_addr_space_1 instead of convert_memory_address,
	if it returns NULL, don't simplify.

	* gcc.dg/torture/pr70628.c: New test.

--- gcc/simplify-rtx.c	(revision 234932)
+++ gcc/simplify-rtx.c	(revision 234933)
@@ -1438,7 +1438,14 @@ simplify_unary_operation_1 (enum rtx_cod
 		  && REG_P (SUBREG_REG (op))
 		  && REG_POINTER (SUBREG_REG (op))
 		  && GET_MODE (SUBREG_REG (op)) == Pmode)))
-	return convert_memory_address (Pmode, op);
+	{
+	  temp
+	    = convert_memory_address_addr_space_1 (Pmode, op,
+						   ADDR_SPACE_GENERIC, false,
+						   true);
+	  if (temp)
+	    return temp;
+	}
 #endif
       break;
 
@@ -1559,7 +1566,14 @@ simplify_unary_operation_1 (enum rtx_cod
 		  && REG_P (SUBREG_REG (op))
 		  && REG_POINTER (SUBREG_REG (op))
 		  && GET_MODE (SUBREG_REG (op)) == Pmode)))
-	return convert_memory_address (Pmode, op);
+	{
+	  temp
+	    = convert_memory_address_addr_space_1 (Pmode, op,
+						   ADDR_SPACE_GENERIC, false,
+						   true);
+	  if (temp)
+	    return temp;
+	}
 #endif
       break;
 
--- gcc/explow.c	(revision 234932)
+++ gcc/explow.c	(revision 234937)
@@ -259,12 +259,14 @@ break_out_memory_refs (rtx x)
    which way).  We take advantage of the fact that pointers are not allowed to
    overflow by commuting arithmetic operations over conversions so that address
    arithmetic insns can be used. IN_CONST is true if this conversion is inside
-   a CONST.  */
+   a CONST. NO_EMIT is true if no insns should be emitted, and instead
+   it should return NULL if it can't be simplified without emitting insns.  */
 
-static rtx
+rtx
 convert_memory_address_addr_space_1 (machine_mode to_mode ATTRIBUTE_UNUSED,
 				     rtx x, addr_space_t as ATTRIBUTE_UNUSED,
-				     bool in_const ATTRIBUTE_UNUSED)
+				     bool in_const ATTRIBUTE_UNUSED,
+				     bool no_emit ATTRIBUTE_UNUSED)
 {
 #ifndef POINTERS_EXTEND_UNSIGNED
   gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
@@ -310,19 +312,16 @@ convert_memory_address_addr_space_1 (mac
       temp = gen_rtx_LABEL_REF (to_mode, LABEL_REF_LABEL (x));
       LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
       return temp;
-      break;
 
     case SYMBOL_REF:
       temp = shallow_copy_rtx (x);
       PUT_MODE (temp, to_mode);
       return temp;
-      break;
 
     case CONST:
-      return gen_rtx_CONST (to_mode,
-			    convert_memory_address_addr_space_1
-			      (to_mode, XEXP (x, 0), as, true));
-      break;
+      temp = convert_memory_address_addr_space_1 (to_mode, XEXP (x, 0), as,
+						  true, no_emit);
+      return temp ? gen_rtx_CONST (to_mode, temp) : temp;
 
     case PLUS:
     case MULT:
@@ -338,18 +337,25 @@ convert_memory_address_addr_space_1 (mac
 	      && CONST_INT_P (XEXP (x, 1))
 	      && ((in_const && POINTERS_EXTEND_UNSIGNED != 0)
 		  || XEXP (x, 1) == convert_memory_address_addr_space_1
-				     (to_mode, XEXP (x, 1), as, in_const)
+				     (to_mode, XEXP (x, 1), as, in_const,
+				      no_emit)
                   || POINTERS_EXTEND_UNSIGNED < 0)))
-	return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
-			       convert_memory_address_addr_space_1
-				 (to_mode, XEXP (x, 0), as, in_const),
-			       XEXP (x, 1));
+	{
+	  temp = convert_memory_address_addr_space_1 (to_mode, XEXP (x, 0),
+						      as, in_const, no_emit);
+	  return (temp ? gen_rtx_fmt_ee (GET_CODE (x), to_mode,
+					 temp, XEXP (x, 1))
+		       : temp);
+	}
       break;
 
     default:
       break;
     }
 
+  if (no_emit)
+    return NULL_RTX;
+
   return convert_modes (to_mode, from_mode,
 			x, POINTERS_EXTEND_UNSIGNED);
 #endif /* defined(POINTERS_EXTEND_UNSIGNED) */
@@ -364,7 +370,7 @@ convert_memory_address_addr_space_1 (mac
 rtx
 convert_memory_address_addr_space (machine_mode to_mode, rtx x, addr_space_t as)
 {
-  return convert_memory_address_addr_space_1 (to_mode, x, as, false);
+  return convert_memory_address_addr_space_1 (to_mode, x, as, false, false);
 }
 
 
--- gcc/rtl.h	(revision 234932)
+++ gcc/rtl.h	(revision 234933)
@@ -2747,6 +2747,8 @@ extern unsigned int subreg_highpart_offs
 					    machine_mode);
 extern int byte_lowpart_offset (machine_mode, machine_mode);
 extern rtx make_safe_from (rtx, rtx);
+extern rtx convert_memory_address_addr_space_1 (machine_mode, rtx,
+						addr_space_t, bool, bool);
 extern rtx convert_memory_address_addr_space (machine_mode, rtx,
 					      addr_space_t);
 #define convert_memory_address(to_mode,x) \
--- gcc/testsuite/gcc.dg/torture/pr70628.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr70628.c	(revision 234933)
@@ -0,0 +1,46 @@
+/* PR debug/70628 */
+/* { dg-do compile } */
+/* { dg-options "-g -w" } */
+
+struct S { char s[64]; int *t; } *a;
+char b[64];
+int *foo (void);
+struct S *bar (int *);
+int baz (void);
+
+void
+test (const char *p, long q)
+{
+  int *c;
+  c = foo ();
+  while (a = bar (c))
+    {
+      if (__builtin_strstr (p, "ABCD")
+	  || __builtin_strstr (p, "EFGHI")
+	  || __builtin_strstr (p, "JKL")
+	  || __builtin_strstr (p, "MNOPQR")
+	  || __builtin_strstr (p, "STUV")
+	  || __builtin_strstr (p, "WXYZabcd")
+	  || __builtin_strstr (p, "efghij")
+	  || __builtin_strstr (p, "klmno")
+	  || __builtin_strstr (p, "pqrstuvw")
+	  || __builtin_strstr (b, "MNOPQR") != "EFGHI"
+	  || __builtin_strstr (b, "JKL"))
+	if (__builtin_strstr (a->s, "xyz12"))
+	  continue;
+      __builtin_printf ("%p\n", a->t);
+    }
+  bar (c);
+  while (a)
+    if (__builtin_strstr (p, "ABCD")
+	|| __builtin_strstr (p, "EFGHI")
+	|| __builtin_strstr (p, "JKL")
+	|| __builtin_strstr (p, "MNOPQR")
+	|| __builtin_strstr (p, "STUV")
+	|| __builtin_strstr (p, "WXYZabcd")
+	|| __builtin_strstr (p, "efghij")
+	|| __builtin_strstr (p, "klmno")
+	|| __builtin_strstr (p, "pqrstuvw")
+	|| __builtin_strstr ((const char *) q, "MNOPQR"))
+      baz ();
+}
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-04-13  Jakub Jelinek  <jakub@redhat.com>
 
	PR middle-end/70633
	* gimplify.c (gimplify_init_constructor): Clear TREE_STATIC if
	gimplification turns some element into non-constant.

	* gcc.c-torture/compile/pr70633.c: New test.

--- gcc/gimplify.c	(revision 234933)
+++ gcc/gimplify.c	(revision 234934)
@@ -4164,7 +4164,7 @@ gimplify_init_constructor (tree *expr_p,
 	  }
 
 	/* Vector types use CONSTRUCTOR all the way through gimple
-	  compilation as a general initializer.  */
+	   compilation as a general initializer.  */
 	FOR_EACH_VEC_SAFE_ELT (elts, ix, ce)
 	  {
 	    enum gimplify_status tret;
@@ -4172,6 +4172,10 @@ gimplify_init_constructor (tree *expr_p,
 				  fb_rvalue);
 	    if (tret == GS_ERROR)
 	      ret = GS_ERROR;
+	    else if (TREE_STATIC (ctor)
+		     && !initializer_constant_valid_p (ce->value,
+						       TREE_TYPE (ce->value)))
+	      TREE_STATIC (ctor) = 0;
 	  }
 	if (!is_gimple_reg (TREE_OPERAND (*expr_p, 0)))
 	  TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (ctor, pre_p);
--- gcc/testsuite/gcc.c-torture/compile/pr70633.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/compile/pr70633.c	(revision 234934)
@@ -0,0 +1,12 @@
+/* PR middle-end/70633 */
+
+typedef long V __attribute__((vector_size (4 * sizeof (long))));
+
+void foo (V *);
+
+void
+bar (void)
+{ 
+  V b = { (long) bar, 0, 0, 0 };
+  foo (&b);
+}
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-04-13  Jakub Jelinek  <jakub@redhat.com>
 
	PR c++/70641
	* ipa-pure-const.c (pass_nothrow::execute): Call maybe_clean_eh_stmt
	on all recursive call stmts.  Return TODO_cleanup_cfg if any dead
	eh edges have been purged.

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

--- gcc/ipa-pure-const.c	(revision 234961)
+++ gcc/ipa-pure-const.c	(revision 234962)
@@ -1961,10 +1961,25 @@ pass_nothrow::execute (function *)
     }
 
   node->set_nothrow_flag (true);
+
+  bool cfg_changed = false;
+  if (self_recursive_p (node))
+    FOR_EACH_BB_FN (this_block, cfun)
+      if (gimple g = last_stmt (this_block))
+	if (is_gimple_call (g))
+	  {
+	    tree callee_t = gimple_call_fndecl (g);
+	    if (callee_t
+		&& recursive_call_p (current_function_decl, callee_t)
+		&& maybe_clean_eh_stmt (g)
+		&& gimple_purge_dead_eh_edges (this_block))
+	      cfg_changed = true;
+	  }
+
   if (dump_file)
     fprintf (dump_file, "Function found to be nothrow: %s\n",
 	     current_function_name ());
-  return 0;
+  return cfg_changed ? TODO_cleanup_cfg : 0;
 }
 
 } // anon namespace
--- gcc/testsuite/g++.dg/opt/pr70641.C	(revision 0)
+++ gcc/testsuite/g++.dg/opt/pr70641.C	(revision 234962)
@@ -0,0 +1,10 @@
+// PR c++/70641
+// { dg-do compile }
+// { dg-options "-O2" }
+
+void
+foo ()
+{
+  try { foo (); }
+  catch (...) { __builtin_abort (); }
+}
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-13  Jakub Jelinek  <jakub@redhat.com>

	PR sanitizer/71498
	* c-gimplify.c (ubsan_walk_array_refs_r): Set *walk_subtrees = 0 on
	all BIND_EXPRs, and on all BIND_EXPRs recurse also on BIND_EXPR_BODY.

	* c-c++-common/ubsan/bounds-13.c: New test.

--- gcc/c-family/c-gimplify.c	(revision 237411)
+++ gcc/c-family/c-gimplify.c	(revision 237412)
@@ -67,23 +67,23 @@ ubsan_walk_array_refs_r (tree *tp, int *
 {
   hash_set<tree> *pset = (hash_set<tree> *) data;
 
-  /* Since walk_tree doesn't call the callback function on the decls
-     in BIND_EXPR_VARS, we have to walk them manually.  */
   if (TREE_CODE (*tp) == BIND_EXPR)
     {
+      /* Since walk_tree doesn't call the callback function on the decls
+	 in BIND_EXPR_VARS, we have to walk them manually, so we can avoid
+	 instrumenting DECL_INITIAL of TREE_STATIC vars.  */
+      *walk_subtrees = 0;
       for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
 	{
 	  if (TREE_STATIC (decl))
-	    {
-	      *walk_subtrees = 0;
-	      continue;
-	    }
+	    continue;
 	  walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset,
 		     pset);
 	  walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset);
 	  walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset,
 		     pset);
 	}
+      walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset);
     }
   else if (TREE_CODE (*tp) == ADDR_EXPR
 	   && TREE_CODE (TREE_OPERAND (*tp, 0)) == ARRAY_REF)
--- gcc/testsuite/c-c++-common/ubsan/bounds-13.c	(revision 0)
+++ gcc/testsuite/c-c++-common/ubsan/bounds-13.c	(revision 237412)
@@ -0,0 +1,31 @@
+/* PR sanitizer/71498 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds -Wno-array-bounds" } */
+
+struct S { int a[100]; int b, c; } s;
+
+__attribute__((noinline, noclone)) int
+foo (int x)
+{
+  return s.a[x];
+}
+
+__attribute__((noinline, noclone)) int
+bar (int x)
+{
+  static int *d = &s.a[99];
+  asm volatile ("" : : "r" (&d));
+  return s.a[x];
+}
+
+int
+main ()
+{
+  volatile int a = 0;
+  a += foo (100);
+  a += bar (100);
+  return 0;
+}
+
+/* { dg-output "index 100 out of bounds for type 'int \\\[100\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*index 100 out of bounds for type 'int \\\[100\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-10  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/71494
	* tree-nested.c (convert_nonlocal_reference_stmt): For GIMPLE_GOTO
	without LABEL_DECL, set *handled_ops_p to false instead of true.

	* gcc.c-torture/execute/pr71494.c: New test.

--- gcc/tree-nested.c	(revision 237448)
+++ gcc/tree-nested.c	(revision 237449)
@@ -1348,7 +1348,7 @@ convert_nonlocal_reference_stmt (gimple_
 	{
 	  wi->val_only = true;
 	  wi->is_lhs = false;
-	  *handled_ops_p = true;
+	  *handled_ops_p = false;
 	  return NULL_TREE;
 	}
       break;
--- gcc/testsuite/gcc.c-torture/execute/pr71494.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr71494.c	(revision 237449)
@@ -0,0 +1,22 @@
+/* PR middle-end/71494 */
+
+int
+main ()
+{
+  void *label = &&out;
+  int i = 0;
+  void test (void)
+  {
+    label = &&out2;
+    goto *label;
+   out2:;
+    i++;
+  }
+  goto *label;
+ out:
+  i += 2;
+  test ();
+  if (i != 3)
+    __builtin_abort ();
+  return 0;
+}
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-14  Jakub Jelinek  <jakub@redhat.com>

	PR c++/71516
	* decl.c (complete_vars): Handle gracefully type == error_mark_node.

	* g++.dg/init/pr71516.C: New test.

--- gcc/cp/decl.c	(revision 237449)
+++ gcc/cp/decl.c	(revision 237450)
@@ -15008,8 +15008,9 @@ complete_vars (tree type)
 	  tree var = iv->decl;
 	  tree type = TREE_TYPE (var);
 
-	  if (TYPE_MAIN_VARIANT (strip_array_types (type))
-	      == iv->incomplete_type)
+	  if (type != error_mark_node
+	      && (TYPE_MAIN_VARIANT (strip_array_types (type))
+		  == iv->incomplete_type))
 	    {
 	      /* Complete the type of the variable.  The VAR_DECL itself
 		 will be laid out in expand_expr.  */

--- gcc/testsuite/g++.dg/init/pr71516.C	(revision 0)
+++ gcc/testsuite/g++.dg/init/pr71516.C	(revision 237450)
@@ -0,0 +1,10 @@
+// PR c++/71516
+// { dg-do compile }
+
+struct A;	// { dg-message "forward declaration of" }
+struct B
+{ 
+  static A a;
+};
+A B::a = A();	// { dg-error "has initializer but incomplete type|invalid use of incomplete type" }
+struct A {};
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-14  Jakub Jelinek  <jakub@redhat.com>

	PR c++/71528
	* decl.c (duplicate_decls): For DECL_INITIALIZED_P non-external
	olddecl vars, preserve their TREE_READONLY bit.

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

--- gcc/cp/decl.c	(revision 237628)
+++ gcc/cp/decl.c	(revision 237629)
@@ -2090,6 +2090,14 @@ duplicate_decls (tree newdecl, tree oldd
       if (VAR_P (newdecl))
 	{
 	  DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
+	  /* For already initialized vars, TREE_READONLY could have been
+	     cleared in cp_finish_decl, because the var needs runtime
+	     initialization or destruction.  Make sure not to set
+	     TREE_READONLY on it again.  */
+	  if (DECL_INITIALIZED_P (olddecl)
+	      && !DECL_EXTERNAL (olddecl)
+	      && !TREE_READONLY (olddecl))
+	    TREE_READONLY (newdecl) = 0;
 	  DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
 	  DECL_NONTRIVIALLY_INITIALIZED_P (newdecl)
 	    |= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl);
--- gcc/testsuite/g++.dg/opt/pr71528.C	(revision 0)
+++ gcc/testsuite/g++.dg/opt/pr71528.C	(revision 237629)
@@ -0,0 +1,23 @@
+// PR c++/71528
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern int &x;
+int y;
+
+int &
+foo ()
+{
+  return y;
+}
+
+int &x = foo ();
+
+int
+main ()
+{
+  if (&x != &y)
+    __builtin_abort ();
+}
+
+extern int &x;
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-20  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/71581
	* tree-ssa-uninit.c (warn_uninit): If EXPR and VAR are NULL,
	see if T isn't anonymous SSA_NAME with COMPLEX_EXPR created
	for conversion of scalar user var to complex type and use the
	underlying SSA_NAME_VAR in that case.  If EXPR is still NULL,
	punt.

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

--- gcc/tree-ssa-uninit.c	(revision 237631)
+++ gcc/tree-ssa-uninit.c	(revision 237632)
@@ -159,6 +159,31 @@ warn_uninit (enum opt_code wc, tree t, t
   if (!has_undefined_value_p (t))
     return;
 
+  /* Anonymous SSA_NAMEs shouldn't be uninitialized, but ssa_undefined_value_p
+     can return true if the def stmt of anonymous SSA_NAME is COMPLEX_EXPR
+     created for conversion from scalar to complex.  Use the underlying var of
+     the COMPLEX_EXPRs real part in that case.  See PR71581.  */
+  if (expr == NULL_TREE
+      && var == NULL_TREE
+      && SSA_NAME_VAR (t) == NULL_TREE
+      && is_gimple_assign (SSA_NAME_DEF_STMT (t))
+      && gimple_assign_rhs_code (SSA_NAME_DEF_STMT (t)) == COMPLEX_EXPR)
+    {
+      tree v = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (t));
+      if (TREE_CODE (v) == SSA_NAME
+	  && has_undefined_value_p (v)
+	  && (integer_zerop (gimple_assign_rhs2 (SSA_NAME_DEF_STMT (t)))
+	      || real_zerop (gimple_assign_rhs2 (SSA_NAME_DEF_STMT (t)))
+	      || fixed_zerop (gimple_assign_rhs2 (SSA_NAME_DEF_STMT (t)))))
+	{
+	  expr = SSA_NAME_VAR (v);
+	  var = expr;
+	}
+    }
+
+  if (expr == NULL_TREE)
+    return;
+
   /* TREE_NO_WARNING either means we already warned, or the front end
      wishes to suppress the warning.  */
   if ((context
--- gcc/testsuite/gcc.dg/pr71581.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr71581.c	(revision 237632)
@@ -0,0 +1,24 @@
+/* PR middle-end/71581 */
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized" } */
+
+_Complex float
+f1 (void)
+{
+  float x;
+  return x;	/* { dg-warning "is used uninitialized in this function" } */
+}
+
+_Complex double
+f2 (void)
+{
+  double x;
+  return x;	/* { dg-warning "is used uninitialized in this function" } */
+}
+
+_Complex int
+f3 (void)
+{
+  int x;
+  return x;	/* { dg-warning "is used uninitialized in this function" } */
+}
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-21  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/71588
	* tree-ssa-strlen.c (valid_builtin_call): New function.
	(adjust_last_stmt, handle_builtin_memset, strlen_optimize_stmt): Use
	it.

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

--- gcc/tree-ssa-strlen.c	(revision 237632)
+++ gcc/tree-ssa-strlen.c	(revision 237633)
@@ -916,6 +916,65 @@ find_equal_ptrs (tree ptr, int idx)
     }
 }
 
+/* Return true if STMT is a call to a builtin function with the right
+   arguments and attributes that should be considered for optimization
+   by this pass.  */
+
+static bool
+valid_builtin_call (gimple stmt)
+{
+  if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+    return false;
+
+  tree callee = gimple_call_fndecl (stmt);
+  switch (DECL_FUNCTION_CODE (callee))
+    {
+    case BUILT_IN_MEMCMP:
+    case BUILT_IN_STRCHR:
+    case BUILT_IN_STRCHR_CHKP:
+    case BUILT_IN_STRLEN:
+    case BUILT_IN_STRLEN_CHKP:
+      /* The above functions should be pure.  Punt if they aren't.  */
+      if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
+	return false;
+      break;
+
+    case BUILT_IN_CALLOC:
+    case BUILT_IN_MALLOC:
+    case BUILT_IN_MEMCPY:
+    case BUILT_IN_MEMCPY_CHK:
+    case BUILT_IN_MEMCPY_CHKP:
+    case BUILT_IN_MEMCPY_CHK_CHKP:
+    case BUILT_IN_MEMPCPY:
+    case BUILT_IN_MEMPCPY_CHK:
+    case BUILT_IN_MEMPCPY_CHKP:
+    case BUILT_IN_MEMPCPY_CHK_CHKP:
+    case BUILT_IN_MEMSET:
+    case BUILT_IN_STPCPY:
+    case BUILT_IN_STPCPY_CHK:
+    case BUILT_IN_STPCPY_CHKP:
+    case BUILT_IN_STPCPY_CHK_CHKP:
+    case BUILT_IN_STRCAT:
+    case BUILT_IN_STRCAT_CHK:
+    case BUILT_IN_STRCAT_CHKP:
+    case BUILT_IN_STRCAT_CHK_CHKP:
+    case BUILT_IN_STRCPY:
+    case BUILT_IN_STRCPY_CHK:
+    case BUILT_IN_STRCPY_CHKP:
+    case BUILT_IN_STRCPY_CHK_CHKP:
+      /* 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)
+	return false;
+      break;
+
+    default:
+      break;
+    }
+
+  return true;
+}
+
 /* If the last .MEM setter statement before STMT is
    memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
    and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
@@ -991,7 +1050,7 @@ adjust_last_stmt (strinfo si, gimple stm
       return;
     }
 
-  if (!gimple_call_builtin_p (last.stmt, BUILT_IN_NORMAL))
+  if (!valid_builtin_call (last.stmt))
     return;
 
   callee = gimple_call_fndecl (last.stmt);
@@ -1867,7 +1926,7 @@ handle_builtin_memset (gimple_stmt_itera
   if (!stmt1 || !is_gimple_call (stmt1))
     return true;
   tree callee1 = gimple_call_fndecl (stmt1);
-  if (!gimple_call_builtin_p (stmt1, BUILT_IN_NORMAL))
+  if (!valid_builtin_call (stmt1))
     return true;
   enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
   tree size = gimple_call_arg (stmt2, 2);
@@ -2112,7 +2171,7 @@ strlen_optimize_stmt (gimple_stmt_iterat
   if (is_gimple_call (stmt))
     {
       tree callee = gimple_call_fndecl (stmt);
-      if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+      if (valid_builtin_call (stmt))
 	switch (DECL_FUNCTION_CODE (callee))
 	  {
 	  case BUILT_IN_STRLEN:
--- gcc/testsuite/gcc.dg/pr71558.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr71558.c	(revision 237633)
@@ -0,0 +1,17 @@
+/* PR tree-optimization/71588 */
+
+/* strcpy must not be pure, but make sure we don't ICE even when
+   it is declared incorrectly.  */
+char *strcpy (char *, const char *) __attribute__ ((__pure__));
+__SIZE_TYPE__ strlen (const char *);
+void *malloc (__SIZE_TYPE__);
+
+char a[20];
+
+char *
+foo (void)
+{
+  __SIZE_TYPE__ b = strlen (a);
+  char *c = malloc (b);
+  return strcpy (c, a);
+}
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-28  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/71626
	* config/i386/i386.c (ix86_expand_vector_move): For SUBREG of
	a constant, force its SUBREG_REG into memory or register instead
	of whole op1.

	* gcc.c-torture/execute/pr71626-1.c: New test.
	* gcc.c-torture/execute/pr71626-2.c: New test.

--- gcc/config/i386/i386.c	(revision 237938)
+++ gcc/config/i386/i386.c	(revision 237939)
@@ -17599,12 +17599,29 @@ ix86_expand_vector_move (machine_mode mo
      of the register, once we have that information we may be able
      to handle some of them more efficiently.  */
   if (can_create_pseudo_p ()
-      && register_operand (op0, mode)
       && (CONSTANT_P (op1)
 	  || (GET_CODE (op1) == SUBREG
 	      && CONSTANT_P (SUBREG_REG (op1))))
-      && !standard_sse_constant_p (op1))
-    op1 = validize_mem (force_const_mem (mode, op1));
+      && ((register_operand (op0, mode)
+	   && !standard_sse_constant_p (op1))
+	  /* ix86_expand_vector_move_misalign() does not like constants.  */
+	  || (SSE_REG_MODE_P (mode)
+	      && MEM_P (op0)
+	      && MEM_ALIGN (op0) < align)))
+    {
+      if (SUBREG_P (op1))
+	{
+	  machine_mode imode = GET_MODE (SUBREG_REG (op1));
+	  rtx r = force_const_mem (imode, SUBREG_REG (op1));
+	  if (r)
+	    r = validize_mem (r);
+	  else
+	    r = force_reg (imode, SUBREG_REG (op1));
+	  op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1));
+	}
+      else
+	op1 = validize_mem (force_const_mem (mode, op1));
+    }
 
   /* We need to check memory alignment for SSE mode since attribute
      can make operands unaligned.  */
@@ -17615,13 +17632,8 @@ ix86_expand_vector_move (machine_mode mo
     {
       rtx tmp[2];
 
-      /* ix86_expand_vector_move_misalign() does not like constants ... */
-      if (CONSTANT_P (op1)
-	  || (GET_CODE (op1) == SUBREG
-	      && CONSTANT_P (SUBREG_REG (op1))))
-	op1 = validize_mem (force_const_mem (mode, op1));
-
-      /* ... nor both arguments in memory.  */
+      /* ix86_expand_vector_move_misalign() does not like both
+	 arguments in memory.  */
       if (!register_operand (op0, mode)
 	  && !register_operand (op1, mode))
 	op1 = force_reg (mode, op1);
--- gcc/testsuite/gcc.c-torture/execute/pr71626-1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr71626-1.c	(revision 237939)
@@ -0,0 +1,19 @@
+/* PR middle-end/71626 */
+
+typedef __INTPTR_TYPE__ V __attribute__((__vector_size__(sizeof (__INTPTR_TYPE__))));
+
+__attribute__((noinline, noclone)) V
+foo ()
+{
+  V v = { (__INTPTR_TYPE__) foo };
+  return v;
+}
+
+int
+main ()
+{
+  V v = foo ();
+  if (v[0] != (__INTPTR_TYPE__) foo)
+    __builtin_abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.c-torture/execute/pr71626-2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr71626-2.c	(revision 237939)
@@ -0,0 +1,4 @@
+/* PR middle-end/71626 */
+/* { dg-additional-options "-fpic" { target fpic } } */
+
+#include "pr71626-1.c"
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-30  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/71705
	* trans-openmp.c (gfc_trans_omp_clauses): Set TREE_ADDRESSABLE on
	decls in to/from clauses.

	* gfortran.dg/gomp/pr71705.f90: New test.

--- gcc/fortran/trans-openmp.c	(revision 237940)
+++ gcc/fortran/trans-openmp.c	(revision 237941)
@@ -2180,6 +2180,8 @@ gfc_trans_omp_clauses (stmtblock_t *bloc
 		  tree decl = gfc_get_symbol_decl (n->sym);
 		  if (gfc_omp_privatize_by_reference (decl))
 		    decl = build_fold_indirect_ref (decl);
+		  else if (DECL_P (decl))
+		    TREE_ADDRESSABLE (decl) = 1;
 		  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
 		    {
 		      tree type = TREE_TYPE (decl);
--- gcc/testsuite/gfortran.dg/gomp/pr71705.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr71705.f90	(revision 237941)
@@ -0,0 +1,7 @@
+! PR fortran/71705
+! { dg-do compile }
+
+  real :: x
+  x = 0.0
+  !$omp target update to(x)
+end
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-30  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/71704
	* parse.c (matchs, matcho): Move right before decode_omp_directive.
	If spec_only, only gfc_match the keyword and if successful, goto
	do_spec_only.
	(matchds, matchdo): Define.
	(decode_omp_directive): Add spec_only local var and set it.
	Use matchds or matchdo macros instead of matchs or matcho
	for declare target, declare simd, declare reduction and threadprivate
	directives.  Return ST_GET_FCN_CHARACTERISTICS if a non-declarative
	directive could be matched.
	(next_statement): For ST_GET_FCN_CHARACTERISTICS restore
	gfc_current_locus from old_locus even if there is no label.

	* gfortran.dg/gomp/pr71704.f90: New test.

--- gcc/fortran/parse.c	(revision 237941)
+++ gcc/fortran/parse.c	(revision 237942)
@@ -589,28 +589,6 @@ decode_statement (void)
   return ST_NONE;
 }
 
-/* Like match, but set a flag simd_matched if keyword matched.  */
-#define matchs(keyword, subr, st)				\
-    do {							\
-      if (match_word_omp_simd (keyword, subr, &old_locus,	\
-			       &simd_matched) == MATCH_YES)	\
-	return st;						\
-      else							\
-	undo_new_statement ();				  	\
-    } while (0);
-
-/* Like match, but don't match anything if not -fopenmp.  */
-#define matcho(keyword, subr, st)				\
-    do {							\
-      if (!flag_openmp)						\
-	;							\
-      else if (match_word (keyword, subr, &old_locus)		\
-	       == MATCH_YES)					\
-	return st;						\
-      else							\
-	undo_new_statement ();				  	\
-    } while (0);
-
 static gfc_statement
 decode_oacc_directive (void)
 {
@@ -702,12 +680,63 @@ decode_oacc_directive (void)
   return ST_NONE;
 }
 
+/* Like match, but set a flag simd_matched if keyword matched
+   and if spec_only, goto do_spec_only without actually matching.  */
+#define matchs(keyword, subr, st)				\
+    do {							\
+      if (spec_only && gfc_match (keyword) == MATCH_YES)	\
+	goto do_spec_only;					\
+      if (match_word_omp_simd (keyword, subr, &old_locus,	\
+			       &simd_matched) == MATCH_YES)	\
+	return st;						\
+      else							\
+	undo_new_statement ();				  	\
+    } while (0);
+
+/* Like match, but don't match anything if not -fopenmp
+   and if spec_only, goto do_spec_only without actually matching.  */
+#define matcho(keyword, subr, st)				\
+    do {							\
+      if (!flag_openmp)						\
+	;							\
+      else if (spec_only && gfc_match (keyword) == MATCH_YES)	\
+	goto do_spec_only;					\
+      else if (match_word (keyword, subr, &old_locus)		\
+	       == MATCH_YES)					\
+	return st;						\
+      else							\
+	undo_new_statement ();				  	\
+    } while (0);
+
+/* Like match, but set a flag simd_matched if keyword matched.  */
+#define matchds(keyword, subr, st)				\
+    do {							\
+      if (match_word_omp_simd (keyword, subr, &old_locus,	\
+			       &simd_matched) == MATCH_YES)	\
+	return st;						\
+      else							\
+	undo_new_statement ();				  	\
+    } while (0);
+
+/* Like match, but don't match anything if not -fopenmp.  */
+#define matchdo(keyword, subr, st)				\
+    do {							\
+      if (!flag_openmp)						\
+	;							\
+      else if (match_word (keyword, subr, &old_locus)		\
+	       == MATCH_YES)					\
+	return st;						\
+      else							\
+	undo_new_statement ();				  	\
+    } while (0);
+
 static gfc_statement
 decode_omp_directive (void)
 {
   locus old_locus;
   char c;
   bool simd_matched = false;
+  bool spec_only = false;
 
   gfc_enforce_clean_symbol_state ();
 
@@ -722,6 +751,10 @@ decode_omp_directive (void)
       return ST_NONE;
     }
 
+  if (gfc_current_state () == COMP_FUNCTION
+      && gfc_current_block ()->result->ts.kind == -1)
+    spec_only = true;
+
   gfc_unset_implicit_pure (NULL);
 
   old_locus = gfc_current_locus;
@@ -750,12 +783,12 @@ decode_omp_directive (void)
       matcho ("critical", gfc_match_omp_critical, ST_OMP_CRITICAL);
       break;
     case 'd':
-      matchs ("declare reduction", gfc_match_omp_declare_reduction,
-	      ST_OMP_DECLARE_REDUCTION);
-      matchs ("declare simd", gfc_match_omp_declare_simd,
-	      ST_OMP_DECLARE_SIMD);
-      matcho ("declare target", gfc_match_omp_declare_target,
-	      ST_OMP_DECLARE_TARGET);
+      matchds ("declare reduction", gfc_match_omp_declare_reduction,
+	       ST_OMP_DECLARE_REDUCTION);
+      matchds ("declare simd", gfc_match_omp_declare_simd,
+	       ST_OMP_DECLARE_SIMD);
+      matchdo ("declare target", gfc_match_omp_declare_target,
+	       ST_OMP_DECLARE_TARGET);
       matchs ("distribute parallel do simd",
 	      gfc_match_omp_distribute_parallel_do_simd,
 	      ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD);
@@ -875,8 +908,8 @@ decode_omp_directive (void)
       matcho ("teams distribute", gfc_match_omp_teams_distribute,
 	      ST_OMP_TEAMS_DISTRIBUTE);
       matcho ("teams", gfc_match_omp_teams, ST_OMP_TEAMS);
-      matcho ("threadprivate", gfc_match_omp_threadprivate,
-	      ST_OMP_THREADPRIVATE);
+      matchdo ("threadprivate", gfc_match_omp_threadprivate,
+	       ST_OMP_THREADPRIVATE);
       break;
     case 'w':
       matcho ("workshare", gfc_match_omp_workshare, ST_OMP_WORKSHARE);
@@ -899,6 +932,13 @@ decode_omp_directive (void)
   gfc_error_recovery ();
 
   return ST_NONE;
+
+ do_spec_only:
+  reject_statement ();
+  gfc_clear_error ();
+  gfc_buffer_error (false);
+  gfc_current_locus = old_locus;
+  return ST_GET_FCN_CHARACTERISTICS;
 }
 
 static gfc_statement
@@ -1319,10 +1359,13 @@ next_statement (void)
 
   gfc_buffer_error (false);
 
-  if (st == ST_GET_FCN_CHARACTERISTICS && gfc_statement_label != NULL)
+  if (st == ST_GET_FCN_CHARACTERISTICS)
     {
-      gfc_free_st_label (gfc_statement_label);
-      gfc_statement_label = NULL;
+      if (gfc_statement_label != NULL)
+	{
+	  gfc_free_st_label (gfc_statement_label);
+	  gfc_statement_label = NULL;
+	}
       gfc_current_locus = old_locus;
     }
 
--- gcc/testsuite/gfortran.dg/gomp/pr71704.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr71704.f90	(revision 237942)
@@ -0,0 +1,58 @@
+! PR fortran/71704
+! { dg-do compile }
+
+real function f0 ()
+!$omp declare simd (f0)
+  f0 = 1
+end
+
+real function f1 ()
+!$omp declare target (f1)
+  f1 = 1
+end
+
+real function f2 ()
+!$omp declare reduction (foo : integer : omp_out = omp_out + omp_in) &
+!$omp & initializer (omp_priv = 0)
+  f2 = 1
+end
+
+real function f3 ()
+  real, save :: t
+!$omp threadprivate (t)
+  f3 = 1
+end
+
+real function f4 ()
+!$omp taskwait
+  f4 = 1
+end
+
+real function f5 ()
+!$omp barrier
+  f5 = 1
+end
+
+real function f6 ()
+!$omp parallel
+!$omp end parallel
+  f6 = 1
+end
+
+real function f7 ()
+!$omp single
+!$omp end single
+  f7 = 1
+end
+
+real function f8 ()
+!$omp critical
+!$omp end critical
+  f8 = 1
+end
+
+real function f9 ()
+!$omp critical
+!$omp end critical
+  f9 = 1
+end
-------------- next part --------------
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-07-01  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/71717
	* trans-openmp.c (gfc_omp_privatize_by_reference): Return false
	for GFC_DECL_ASSOCIATE_VAR_P with POINTER_TYPE.

	* testsuite/libgomp.fortran/associate3.f90: New test.

--- gcc/fortran/trans-openmp.c	(revision 237942)
+++ gcc/fortran/trans-openmp.c	(revision 237943)
@@ -61,6 +61,7 @@ gfc_omp_privatize_by_reference (const_tr
       if (GFC_DECL_GET_SCALAR_POINTER (decl)
 	  || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
 	  || GFC_DECL_CRAY_POINTEE (decl)
+	  || GFC_DECL_ASSOCIATE_VAR_P (decl)
 	  || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
 	return false;
 
--- libgomp/testsuite/libgomp.fortran/associate3.f90	(revision 0)
+++ libgomp/testsuite/libgomp.fortran/associate3.f90	(revision 237943)
@@ -0,0 +1,20 @@
+! PR fortran/71717
+! { dg-do run }
+
+  type t
+    real, allocatable :: f(:)
+  end type
+  type (t) :: v
+  integer :: i, j
+  allocate (v%f(4))
+  v%f = 19.
+  i = 5
+  associate (u => v, k => i)
+  !$omp parallel do
+  do j = 1, 4
+    u%f(j) = 21.
+    if (j.eq.1) k = 7
+  end do
+  end associate
+  if (any (v%f(:).ne.21.) .or. i.ne.7) call abort
+end


More information about the Gcc-patches mailing list