Backports to 7.3

Message ID 20171215222321.GT2353@tucnak
State New
Headers show
Series
  • Backports to 7.3
Related show

Commit Message

Jakub Jelinek Dec. 15, 2017, 10:23 p.m.
Hi!

I've backported today following 23 patches after bootstrapping/regtesting
them on x86_64-linux and i686-linux.

Some of the backports are just partial backports, in particular for
r255133 I've just backported the removal of case BUILT_IN_STPNCPY_CHK:,
for r255354 the patch didn't apply at all, because we don't have the
C++ __builtin_unreachables with BUILTINS_LOCATION, so rewrote it manually,
and finally r255574 is just the fix, so am not trying to extend it to
reversed loops and of course it didn't apply cleanly either.

	Jakub
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-20  Jakub Jelinek  <jakub@redhat.com>

	PR c++/82781
	* constexpr.c (cxx_eval_vector_conditional_expression): New function.
	(cxx_eval_constant_expression) <case VEC_COND_EXPR>: Use it instead
	of cxx_eval_conditional_expression.

	* g++.dg/ext/constexpr-pr82781.C: New test.
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-21  Jakub Jelinek  <jakub@redhat.com>

	PR c++/83059
	* c-common.c (get_atomic_generic_size): Use TREE_INT_CST_LOW
	instead of tree_to_uhwi, formatting fix.

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

--- gcc/c-family/c-common.c	(revision 254989)
+++ gcc/c-family/c-common.c	(revision 254990)
@@ -6671,13 +6671,14 @@ get_atomic_generic_size (location_t loc,
       tree p = (*params)[x];
       if (TREE_CODE (p) == INTEGER_CST)
         {
-	  int i = tree_to_uhwi (p);
-	  if (i < 0 || (memmodel_base (i) >= MEMMODEL_LAST))
-	    {
-	      warning_at (loc, OPT_Winvalid_memory_model,
-			  "invalid memory model argument %d of %qE", x + 1,
-			  function);
-	    }
+	  /* memmodel_base masks the low 16 bits, thus ignore any bits above
+	     it by using TREE_INT_CST_LOW instead of tree_to_*hwi.  Those high
+	     bits will be checked later during expansion in target specific
+	     way.  */
+	  if (memmodel_base (TREE_INT_CST_LOW (p)) >= MEMMODEL_LAST)
+	    warning_at (loc, OPT_Winvalid_memory_model,
+			"invalid memory model argument %d of %qE", x + 1,
+			function);
 	}
       else
 	if (!INTEGRAL_TYPE_P (TREE_TYPE (p)))
--- gcc/testsuite/c-c++-common/pr83059.c	(nonexistent)
+++ gcc/testsuite/c-c++-common/pr83059.c	(revision 254990)
@@ -0,0 +1,10 @@
+/* PR c++/83059 */
+/* { dg-do compile } */
+
+void
+foo (int *p, int *q, int *r)
+{
+  __atomic_compare_exchange (p, q, r, 0, 0, -1);	/* { dg-warning "invalid memory model argument 6" } */
+  /* { dg-warning "\[uU]nknown architecture specifi" "" { target *-*-* } .-1 } */
+  /* { dg-warning "failure memory model cannot be stronger than success memory model" "" { target *-*-* } .-2 } */
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-21  James Cowgill  <James.Cowgill@imgtec.com>
		    Jakub Jelinek  <jakub@redhat.com>

	PR target/82880
	* config/mips/frame-header-opt.c (mips_register_frame_header_opt):
	Remove static keyword from f variable.

	* gcc.dg/opts-8.c: New test.

--- gcc/config/mips/frame-header-opt.c	(revision 255003)
+++ gcc/config/mips/frame-header-opt.c	(revision 255004)
@@ -99,8 +99,7 @@ void
 mips_register_frame_header_opt (void)
 {
   opt_pass *p = make_pass_ipa_frame_header_opt (g);
-  static struct register_pass_info f =
-    {p, "comdats", 1, PASS_POS_INSERT_AFTER };
+  struct register_pass_info f = { p, "comdats", 1, PASS_POS_INSERT_AFTER };
   register_pass (&f);
 }
 
--- gcc/testsuite/gcc.dg/opts-8.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/opts-8.c	(revision 255004)
@@ -0,0 +1,6 @@
+/* PR target/82880 */
+/* Test we don't ICE or hang.  */
+/* { dg-do compile } */
+/* { dg-options "--help=target --help=optimizers" } */
+/* { dg-allow-blank-lines-in-output 1 } */
+/* { dg-prune-output ".*" } */
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-22  Jakub Jelinek  <jakub@redhat.com>

	PR debug/83084
	* valtrack.c (propagate_for_debug_subst, propagate_for_debug): Reset
	debug insns if they would contain UNSPEC_VOLATILE or volatile asm.
	(dead_debug_insert_temp): Likewise, but also ignore even non-volatile
	asm.

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

--- gcc/valtrack.c	(revision 255050)
+++ gcc/valtrack.c	(revision 255051)
@@ -171,10 +171,13 @@ propagate_for_debug_subst (rtx from, con
 	if (REG_P (*iter) && ++cnt > 1)
 	  {
 	    rtx dval = make_debug_expr_from_rtl (old_rtx);
+	    rtx to = pair->to;
+	    if (volatile_insn_p (to))
+	      to = gen_rtx_UNKNOWN_VAR_LOC ();
 	    /* Emit a debug bind insn.  */
 	    rtx bind
 	      = gen_rtx_VAR_LOCATION (GET_MODE (old_rtx),
-				      DEBUG_EXPR_TREE_DECL (dval), pair->to,
+				      DEBUG_EXPR_TREE_DECL (dval), to,
 				      VAR_INIT_STATUS_INITIALIZED);
 	    rtx_insn *bind_insn = emit_debug_insn_before (bind, pair->insn);
 	    df_insn_rescan (bind_insn);
@@ -217,6 +220,8 @@ propagate_for_debug (rtx_insn *insn, rtx
 					 dest, propagate_for_debug_subst, &p);
 	  if (loc == INSN_VAR_LOCATION_LOC (insn))
 	    continue;
+	  if (volatile_insn_p (loc))
+	    loc = gen_rtx_UNKNOWN_VAR_LOC ();
 	  INSN_VAR_LOCATION_LOC (insn) = loc;
 	  df_insn_rescan (insn);
 	}
@@ -660,6 +665,12 @@ dead_debug_insert_temp (struct dead_debu
 		}
 	      return 0;
 	    }
+	  /* Asm in DEBUG_INSN is never useful, we can't emit debug info for
+	     that.  And for volatile_insn_p, it is actually harmful
+	     - DEBUG_INSNs shouldn't have any side-effects.  */
+	  else if (GET_CODE (src) == ASM_OPERANDS
+		   || volatile_insn_p (src))
+	    set = NULL_RTX;
 	}
 
       /* ??? Should we try to extract it from a PARALLEL?  */
--- gcc/testsuite/g++.dg/opt/pr83084.C	(nonexistent)
+++ gcc/testsuite/g++.dg/opt/pr83084.C	(revision 255051)
@@ -0,0 +1,16 @@
+// PR debug/83084
+// { dg-do compile }
+// { dg-options "-O2 -fcompare-debug -Wno-return-type" }
+
+enum E { F };
+template <E = F> struct A {
+  bool foo ();
+  int b;
+};
+template <> bool A<>::foo () {
+  int a;
+  do
+    if (a)
+      return false;
+  while (__atomic_compare_exchange_n (&b, &a, 0, 1, 4, 0));
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-23  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/82253
	* expr.c (expand_assignment): For CONCAT to_rtx, complex type from and
	bitpos/bitsize covering the whole destination, use store_expr only if
	the complex mode is the same.  Otherwise, use expand_normal and if
	it returns CONCAT, subreg each part separately instead of trying to
	subreg the whole result.

	* gfortran.dg/pr82253.f90: New test.

--- gcc/expr.c	(revision 255094)
+++ gcc/expr.c	(revision 255095)
@@ -5107,7 +5107,8 @@ expand_assignment (tree to, tree from, b
       else if (GET_CODE (to_rtx) == CONCAT)
 	{
 	  unsigned short mode_bitsize = GET_MODE_BITSIZE (GET_MODE (to_rtx));
-	  if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from)))
+	  if (TYPE_MODE (TREE_TYPE (from)) == GET_MODE (to_rtx)
+	      && COMPLEX_MODE_P (GET_MODE (to_rtx))
 	      && bitpos == 0
 	      && bitsize == mode_bitsize)
 	    result = store_expr (from, to_rtx, false, nontemporal, reversep);
@@ -5128,14 +5129,30 @@ expand_assignment (tree to, tree from, b
 				  nontemporal, reversep);
 	  else if (bitpos == 0 && bitsize == mode_bitsize)
 	    {
-	      rtx from_rtx;
 	      result = expand_normal (from);
-	      from_rtx = simplify_gen_subreg (GET_MODE (to_rtx), result,
-					      TYPE_MODE (TREE_TYPE (from)), 0);
-	      emit_move_insn (XEXP (to_rtx, 0),
-			      read_complex_part (from_rtx, false));
-	      emit_move_insn (XEXP (to_rtx, 1),
-			      read_complex_part (from_rtx, true));
+	      if (GET_CODE (result) == CONCAT)
+		{
+		  machine_mode to_mode = GET_MODE_INNER (GET_MODE (to_rtx));
+		  machine_mode from_mode = GET_MODE_INNER (GET_MODE (result));
+		  rtx from_real
+		    = simplify_gen_subreg (to_mode, XEXP (result, 0),
+					   from_mode, 0);
+		  rtx from_imag
+		    = simplify_gen_subreg (to_mode, XEXP (result, 1),
+					   from_mode, 1);
+		  emit_move_insn (XEXP (to_rtx, 0), from_real);
+		  emit_move_insn (XEXP (to_rtx, 1), from_imag);
+		}
+	      else
+		{
+		  rtx from_rtx
+		    = simplify_gen_subreg (GET_MODE (to_rtx), result,
+					   TYPE_MODE (TREE_TYPE (from)), 0);
+		  emit_move_insn (XEXP (to_rtx, 0),
+				  read_complex_part (from_rtx, false));
+		  emit_move_insn (XEXP (to_rtx, 1),
+				  read_complex_part (from_rtx, true));
+		}
 	    }
 	  else
 	    {
--- gcc/testsuite/gfortran.dg/pr82253.f90	(nonexistent)
+++ gcc/testsuite/gfortran.dg/pr82253.f90	(revision 255095)
@@ -0,0 +1,40 @@
+! PR middle-end/82253
+! { dg-do compile { target fortran_real_16 } }
+! { dg-options "-Og" }
+
+module pr82253
+  implicit none
+  private
+  public :: static_type
+  type, public :: T
+    procedure(), nopass, pointer :: testProc => null()
+  end type
+  type, public :: S
+    complex(kind=16), pointer :: ptr
+  end type
+  type(T), target :: type_complex32
+  interface static_type
+    module procedure foo
+  end interface
+  interface
+    subroutine bar (testProc)
+      procedure(), optional :: testProc
+    end subroutine
+  end interface
+  contains
+    function foo (self) result(res)
+      complex(kind=16) :: self
+      type(T), pointer :: res
+      call bar (testProc = baz)
+    end function
+    subroutine baz (buffer, status)
+      character(len=*) :: buffer
+      integer(kind=4) :: status
+      complex(kind=16), target :: obj
+      type(S) :: self
+      integer(kind=1), parameter :: zero(storage_size(obj)/8) = 0
+      obj = transfer (zero, obj)
+      self%ptr => obj
+      write (buffer, *, iostat=status) self%ptr, '#'
+    end subroutine
+end module pr82253
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-23  Dirk Broemmel  <d.broemmel@fz-juelich.de>
		    Jakub Jelinek  <jakub@redhat.com>

	PR fortran/81841
	* parse.c (parse_spec): Allow ST_OMP_THREADPRIVATE inside of
	BLOCK DATA.

	* libgomp.fortran/pr81841.f90: New test.

--- gcc/fortran/parse.c	(revision 255114)
+++ gcc/fortran/parse.c	(revision 255115)
@@ -3699,6 +3699,7 @@ loop:
 	case ST_EQUIVALENCE:
 	case ST_IMPLICIT:
 	case ST_IMPLICIT_NONE:
+	case ST_OMP_THREADPRIVATE:
 	case ST_PARAMETER:
 	case ST_STRUCTURE_DECL:
 	case ST_TYPE:
--- libgomp/testsuite/libgomp.fortran/pr81841.f90	(nonexistent)
+++ libgomp/testsuite/libgomp.fortran/pr81841.f90	(revision 255115)
@@ -0,0 +1,26 @@
+! PR fortran/81841
+! { dg-do run }
+
+block data
+  integer :: a
+  real :: b(2)
+  common /c/ a, b
+  !$omp threadprivate (/c/)
+  data a / 32 /
+  data b /2*1./
+end
+
+program pr81841
+  use omp_lib
+  integer :: e
+  real :: f(2)
+  common /c/ e, f
+  !$omp threadprivate (/c/)
+  !$omp parallel num_threads(8)
+  if ((e /= 32) .or. any(f /= 1.)) call abort
+  e = omp_get_thread_num ()
+  f = e + 19.
+  !$omp barrier
+  if ((e /= omp_get_thread_num ()) .or. any(f /= e + 19.)) call abort
+  !$omp end parallel
+end
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-23  Jakub Jelinek  <jakub@redhat.com>

	* parser.c (cp_parser_omp_declare): Change return type to bool from
	void, return true for declare simd.
	(cp_parser_pragma): Return cp_parser_omp_declare returned value
	rather than always false.

--- gcc/cp/parser.c	(revision 255116)
+++ gcc/cp/parser.c	(revision 255117)
@@ -37903,7 +37903,7 @@ cp_parser_omp_declare_reduction (cp_pars
       initializer-clause[opt] new-line
    #pragma omp declare target new-line  */
 
-static void
+static bool
 cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
 		       enum pragma_context context)
 {
@@ -37917,7 +37917,7 @@ cp_parser_omp_declare (cp_parser *parser
 	  cp_lexer_consume_token (parser->lexer);
 	  cp_parser_omp_declare_simd (parser, pragma_tok,
 				      context);
-	  return;
+	  return true;
 	}
       cp_ensure_no_omp_declare_simd (parser);
       if (strcmp (p, "reduction") == 0)
@@ -37925,23 +37925,24 @@ cp_parser_omp_declare (cp_parser *parser
 	  cp_lexer_consume_token (parser->lexer);
 	  cp_parser_omp_declare_reduction (parser, pragma_tok,
 					   context);
-	  return;
+	  return false;
 	}
       if (!flag_openmp)  /* flag_openmp_simd  */
 	{
 	  cp_parser_skip_to_pragma_eol (parser, pragma_tok);
-	  return;
+	  return false;
 	}
       if (strcmp (p, "target") == 0)
 	{
 	  cp_lexer_consume_token (parser->lexer);
 	  cp_parser_omp_declare_target (parser, pragma_tok);
-	  return;
+	  return false;
 	}
     }
   cp_parser_error (parser, "expected %<simd%> or %<reduction%> "
 			   "or %<target%>");
   cp_parser_require_pragma_eol (parser, pragma_tok);
+  return false;
 }
 
 /* OpenMP 4.5:
@@ -38860,8 +38861,7 @@ cp_parser_pragma (cp_parser *parser, enu
       return false;
 
     case PRAGMA_OMP_DECLARE:
-      cp_parser_omp_declare (parser, pragma_tok, context);
-      return false;
+      return cp_parser_omp_declare (parser, pragma_tok, context);
 
     case PRAGMA_OACC_DECLARE:
       cp_parser_oacc_declare (parser, pragma_tok);
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-24  Jakub Jelinek  <jakub@redhat.com>

	* tree-object-size.c (pass_through_call): Do not handle
	BUILT_IN_STPNCPY_CHK which is not a pass through call.

	* gcc.dg/builtin-object-size-18.c: New test.

--- gcc/tree-object-size.c	(revision 255132)
+++ gcc/tree-object-size.c	(revision 255133)
@@ -481,7 +481,6 @@ pass_through_call (const gcall *call)
       case BUILT_IN_MEMSET_CHK:
       case BUILT_IN_STRCPY_CHK:
       case BUILT_IN_STRNCPY_CHK:
-      case BUILT_IN_STPNCPY_CHK:
       case BUILT_IN_STRCAT_CHK:
       case BUILT_IN_STRNCAT_CHK:
       case BUILT_IN_ASSUME_ALIGNED:
--- gcc/testsuite/gcc.dg/builtin-object-size-18.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/builtin-object-size-18.c	(revision 255133)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* __stpncpy_chk could return buf up to buf + 64, so
+   the minimum object size might be far smaller than 64.  */
+/* { dg-final { scan-tree-dump-not "return 64;" "optimized" } } */
+
+typedef __SIZE_TYPE__ size_t;
+
+size_t
+foo (const char *p, size_t s, size_t t)
+{
+  char buf[64];
+  char *q = __builtin___stpncpy_chk (buf, p, s, t);
+  return __builtin_object_size (q, 2);
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-24  Jakub Jelinek  <jakub@redhat.com>
 
	PR sanitizer/83014
	* ubsan.c (ubsan_type_descriptor): Use pp_unsigned_wide_integer
	instead of pp_printf with HOST_WIDE_INT_PRINT_DEC.  Avoid calling
	tree_to_uhwi twice.

	* gcc.dg/ubsan/pr83014.c: New test.

--- gcc/ubsan.c	(revision 255133)
+++ gcc/ubsan.c	(revision 255134)
@@ -436,10 +436,10 @@ ubsan_type_descriptor (tree type, enum u
 	      && TYPE_MAX_VALUE (dom) != NULL_TREE
 	      && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
 	    {
+	      unsigned HOST_WIDE_INT m;
 	      if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
-		  && tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1 != 0)
-		pp_printf (&pretty_name, HOST_WIDE_INT_PRINT_DEC,
-			    tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
+		  && (m = tree_to_uhwi (TYPE_MAX_VALUE (dom))) + 1 != 0)
+		pp_unsigned_wide_integer (&pretty_name, m + 1);
 	      else
 		pp_wide_int (&pretty_name,
 			     wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
--- gcc/testsuite/gcc.dg/ubsan/pr83014.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/ubsan/pr83014.c	(revision 255134)
@@ -0,0 +1,12 @@
+/* PR sanitizer/83014 */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=undefined" } */
+
+int
+foo (void)
+{
+  int data[5];
+  data[0] = 0;
+  data[5] = 0;
+  return data[0];
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-24  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/81304
	* trans-openmp.c (gfc_trans_omp_array_reduction_or_udr): Set
	attr.implicit_type in intrinsic_sym to avoid undesirable warning.

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

--- gcc/fortran/trans-openmp.c	(revision 255143)
+++ gcc/fortran/trans-openmp.c	(revision 255144)
@@ -1623,6 +1623,7 @@ gfc_trans_omp_array_reduction_or_udr (tr
       intrinsic_sym.attr.referenced = 1;
       intrinsic_sym.attr.intrinsic = 1;
       intrinsic_sym.attr.function = 1;
+      intrinsic_sym.attr.implicit_type = 1;
       intrinsic_sym.result = &intrinsic_sym;
       intrinsic_sym.declared_at = where;
 
--- libgomp/testsuite/libgomp.fortran/pr81304.f90	(nonexistent)
+++ libgomp/testsuite/libgomp.fortran/pr81304.f90	(revision 255144)
@@ -0,0 +1,17 @@
+! PR fortran/81304
+! { dg-do run }
+! { dg-options "-Wsurprising" }
+
+program pr81304
+   integer :: i
+   real, dimension(1:3) :: a, b, c
+   a = 128
+   b = 0
+!$omp parallel do reduction(min: a) reduction(max: b) private (c)	! { dg-bogus "Type specified for intrinsic function" }
+   do i = 1, 16
+     c = (/ i, i - 5, i + 5 /)
+     a = min (a, c)
+     b = max (b, c)
+   end do
+   if (any (a /= (/ 1, -4, 6 /)) .or. any (b /= (/ 16, 11, 21 /))) call abort
+end
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-25  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/81553
	* combine.c (simplify_if_then_else): In (if_then_else COND (OP Z C1) Z)
	to (OP Z (mult COND (C1 * STORE_FLAG_VALUE))) optimization, if OP
	is a shift where C1 has different mode than the whole shift, use C1's
	mode for MULT rather than the shift's mode.

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

--- gcc/combine.c	(revision 255149)
+++ gcc/combine.c	(revision 255150)
@@ -6639,11 +6639,15 @@ simplify_if_then_else (rtx x)
 
       if (z)
 	{
-	  temp = subst (simplify_gen_relational (true_code, m, VOIDmode,
+	  machine_mode cm = m;
+	  if ((op == ASHIFT || op == LSHIFTRT || op == ASHIFTRT)
+	      && GET_MODE (c1) != VOIDmode)
+	    cm = GET_MODE (c1);
+	  temp = subst (simplify_gen_relational (true_code, cm, VOIDmode,
 						 cond_op0, cond_op1),
 			pc_rtx, pc_rtx, 0, 0, 0);
-	  temp = simplify_gen_binary (MULT, m, temp,
-				      simplify_gen_binary (MULT, m, c1,
+	  temp = simplify_gen_binary (MULT, cm, temp,
+				      simplify_gen_binary (MULT, cm, c1,
 							   const_true_rtx));
 	  temp = subst (temp, pc_rtx, pc_rtx, 0, 0, 0);
 	  temp = simplify_gen_binary (op, m, gen_lowpart (m, z), temp);
--- gcc/testsuite/gcc.c-torture/compile/pr81553.c	(nonexistent)
+++ gcc/testsuite/gcc.c-torture/compile/pr81553.c	(revision 255150)
@@ -0,0 +1,10 @@
+/* PR rtl-optimization/81553 */
+
+int a, b, c, d;
+
+void
+foo (void)
+{
+  d = 1 >> c >> 1;
+  b = ~(209883449764912897ULL & d) << (0 >= a) | ~d;
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-27  Jakub Jelinek  <jakub@redhat.com>

	PR c++/81675
	* cp-gimplify.c (cp_fold) <case COND_EXPR>: Don't return immediately
	for VOID_TYPE_P COND_EXPRs, instead fold the operands and if op0 is
	INTEGER_CST, ensure that both op1 and op2 are non-NULL and fall
	through into normal folding, otherwise just rebuild x if any op
	changed.

	* g++.dg/warn/pr81675.C: New test.

--- gcc/cp/cp-gimplify.c	(revision 255166)
+++ gcc/cp/cp-gimplify.c	(revision 255167)
@@ -2299,13 +2299,6 @@ cp_fold (tree x)
 
     case VEC_COND_EXPR:
     case COND_EXPR:
-
-      /* Don't bother folding a void condition, since it can't produce a
-	 constant value.  Also, some statement-level uses of COND_EXPR leave
-	 one of the branches NULL, so folding would crash.  */
-      if (VOID_TYPE_P (TREE_TYPE (x)))
-	return x;
-
       loc = EXPR_LOCATION (x);
       op0 = cp_fold_rvalue (TREE_OPERAND (x, 0));
       op1 = cp_fold (TREE_OPERAND (x, 1));
@@ -2319,6 +2312,29 @@ cp_fold (tree x)
 	  if (!VOID_TYPE_P (TREE_TYPE (op2)))
 	    op2 = cp_truthvalue_conversion (op2);
 	}
+      else if (VOID_TYPE_P (TREE_TYPE (x)))
+	{
+	  if (TREE_CODE (op0) == INTEGER_CST)
+	    {
+	      /* If the condition is constant, fold can fold away
+		 the COND_EXPR.  If some statement-level uses of COND_EXPR
+		 have one of the branches NULL, avoid folding crash.  */
+	      if (!op1)
+		op1 = build_empty_stmt (loc);
+	      if (!op2)
+		op2 = build_empty_stmt (loc);
+	    }
+	  else
+	    {
+	      /* Otherwise, don't bother folding a void condition, since
+		 it can't produce a constant value.  */
+	      if (op0 != TREE_OPERAND (x, 0)
+		  || op1 != TREE_OPERAND (x, 1)
+		  || op2 != TREE_OPERAND (x, 2))
+		x = build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
+	      break;
+	    }
+	}
 
       if (op0 != TREE_OPERAND (x, 0)
 	  || op1 != TREE_OPERAND (x, 1)
--- gcc/testsuite/g++.dg/warn/pr81675.C	(nonexistent)
+++ gcc/testsuite/g++.dg/warn/pr81675.C	(revision 255167)
@@ -0,0 +1,15 @@
+// PR c++/81675
+// { dg-do compile }
+// { dg-options "-Wall" }
+
+struct S
+{
+  ~S () __attribute__((noreturn));
+  int a;
+};
+
+int
+foo ()
+{
+  false ? 5 : S ().a;
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-27  Jakub Jelinek  <jakub@redhat.com>

	PR c++/81888
	* parser.c (cp_parser_decomposition_declaration): Reject just
	BRACE_ENCLOSED_INITIALIZER_P initializers with nelts != 1 rather
	than all such CONSTRUCTORs, and only if is_direct_init is true.

	* g++.dg/cpp1z/decomp30.C: Add a test for structured binding with
	= {} and = { a, a } initializers.
	* g++.dg/cpp1z/decomp31.C: New test.

--- gcc/cp/parser.c	(revision 255179)
+++ gcc/cp/parser.c	(revision 255180)
@@ -13382,7 +13382,8 @@ cp_parser_decomposition_declaration (cp_
       if (initializer == NULL_TREE
 	  || (TREE_CODE (initializer) == TREE_LIST
 	      && TREE_CHAIN (initializer))
-	  || (TREE_CODE (initializer) == CONSTRUCTOR
+	  || (is_direct_init
+	      && BRACE_ENCLOSED_INITIALIZER_P (initializer)
 	      && CONSTRUCTOR_NELTS (initializer) != 1))
 	{
 	  error_at (loc, "invalid initializer for structured binding "
--- gcc/testsuite/g++.dg/cpp1z/decomp30.C	(revision 255179)
+++ gcc/testsuite/g++.dg/cpp1z/decomp30.C	(revision 255180)
@@ -10,3 +10,5 @@ auto [j, k] { a, a };	// { dg-error "inv
 auto [l, m] = { a };	// { dg-error "deducing from brace-enclosed initializer list requires" }
 auto [n, o] {};		// { dg-error "invalid initializer for structured binding declaration" }
 auto [p, q] ();		// { dg-error "invalid initializer for structured binding declaration" }
+auto [r, s] = {};	// { dg-error "deducing from brace-enclosed initializer list requires" }
+auto [t, u] = { a, a };	// { dg-error "deducing from brace-enclosed initializer list requires" }
--- gcc/testsuite/g++.dg/cpp1z/decomp31.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp31.C	(revision 255180)
@@ -0,0 +1,18 @@
+// PR c++/81888
+// { dg-do compile { target c++1z } }
+
+struct S {
+  bool s = true;
+};
+
+auto [a] = S{};
+
+template <class T>
+bool
+foo () noexcept
+{
+  auto [c] = T{};
+  return c;
+}
+
+const bool b = foo<S> ();
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-11-29  Jakub Jelinek  <jakub@redhat.com>

	PR target/80819
	* config/i386/sse.md (vec_concatv2di): Remove * from (=Yr,0,*rm)
	alternative.

	* gcc.target/i386/pr80819-1.c: New test.
	* gcc.target/i386/pr80819-2.c: New test.

--- gcc/config/i386/sse.md	(revision 255225)
+++ gcc/config/i386/sse.md	(revision 255226)
@@ -13919,7 +13919,7 @@ (define_insn "vec_concatv2di"
 	  (match_operand:DI 1 "nonimmediate_operand"
 	  "  0, 0,x ,Yv,r ,vm,?!*Yn,0,Yv,0,0,v")
 	  (match_operand:DI 2 "vector_move_operand"
-	  "*rm,rm,rm,rm,C ,C ,C ,x,Yv,x,m,m")))]
+	  " rm,rm,rm,rm,C ,C ,C ,x,Yv,x,m,m")))]
   "TARGET_SSE"
   "@
    pinsrq\t{$1, %2, %0|%0, %2, 1}
--- gcc/testsuite/gcc.target/i386/pr80819-1.c	(nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr80819-1.c	(revision 255226)
@@ -0,0 +1,13 @@
+/* PR target/80819 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse4 -mno-avx -mtune=haswell -masm=att" } */
+
+typedef unsigned long long V __attribute__((vector_size (16)));
+
+V
+foo (unsigned long long x, unsigned long long y)
+{
+  return (V) { x, y };
+}
+
+/* { dg-final { scan-assembler-not "movq\[ \t]*%rsi, \[-0-9]*\\(" } } */
--- gcc/testsuite/gcc.target/i386/pr80819-2.c	(nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr80819-2.c	(revision 255226)
@@ -0,0 +1,13 @@
+/* PR target/80819 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse4 -mno-avx -mtune=generic -masm=att" } */
+
+typedef unsigned long long V __attribute__((vector_size (16)));
+
+V
+foo (unsigned long long x, unsigned long long y)
+{
+  return (V) { x, y };
+}
+
+/* { dg-final { scan-assembler-not "movq\[ \t]*%rsi, \[-0-9]*\\(" } } */
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-02  Jakub Jelinek  <jakub@redhat.com>

	PR target/78643
	PR target/80583
	* expr.c (get_inner_reference): If DECL_MODE of a non-bitfield
	is BLKmode for vector field with vector raw mode, use TYPE_MODE
	instead of DECL_MODE.

	* gcc.target/i386/pr80583.c: New test.

--- gcc/expr.c	(revision 255352)
+++ gcc/expr.c	(revision 255353)
@@ -7032,7 +7032,16 @@ get_inner_reference (tree exp, HOST_WIDE
 	     size.  */
 	mode = TYPE_MODE (DECL_BIT_FIELD_TYPE (field));
       else if (!DECL_BIT_FIELD (field))
-	mode = DECL_MODE (field);
+	{
+	  mode = DECL_MODE (field);
+	  /* For vector fields re-check the target flags, as DECL_MODE
+	     could have been set with different target flags than
+	     the current function has.  */
+	  if (mode == BLKmode
+	      && VECTOR_TYPE_P (TREE_TYPE (field))
+	      && VECTOR_MODE_P (TYPE_MODE_RAW (TREE_TYPE (field))))
+	    mode = TYPE_MODE (TREE_TYPE (field));
+	}
       else if (DECL_MODE (field) == BLKmode)
 	blkmode_bitfield = true;
 
--- gcc/testsuite/gcc.target/i386/pr80583.c	(nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr80583.c	(revision 255353)
@@ -0,0 +1,13 @@
+/* PR target/80583 */
+/* { dg-do compile } */
+/* { dg-options "-O0 -mno-avx" } */
+
+typedef int V __attribute__((__vector_size__(32)));
+struct S { V a; };
+
+V __attribute__((target ("avx")))
+foo (struct S *b)
+{
+  V x = b->a;
+  return x;
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-02  Jakub Jelinek  <jakub@redhat.com>

	PR c++/81212
	* tree-cfg.c (pass_warn_function_return::execute): Handle
	__builtin_ubsan_handle_missing_return like __builtin_unreachable
	with BUILTINS_LOCATION.

	* g++.dg/ubsan/pr81212.C: New test.

--- gcc/tree-cfg.c	(revision 255353)
+++ gcc/tree-cfg.c	(revision 255354)
@@ -8917,7 +8917,6 @@ pass_warn_function_return::execute (func
      without returning a value.  */
   else if (warn_return_type
 	   && !TREE_NO_WARNING (fun->decl)
-	   && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun)->preds) > 0
 	   && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fun->decl))))
     {
       FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (fun)->preds)
@@ -8931,11 +8930,40 @@ pass_warn_function_return::execute (func
 	      location = gimple_location (last);
 	      if (location == UNKNOWN_LOCATION)
 		location = fun->function_end_locus;
-	      warning_at (location, OPT_Wreturn_type, "control reaches end of non-void function");
+	      warning_at (location, OPT_Wreturn_type,
+			  "control reaches end of non-void function");
 	      TREE_NO_WARNING (fun->decl) = 1;
 	      break;
 	    }
 	}
+      /* -fsanitize=return turns fallthrough from the end of non-void function
+	 into __builtin___ubsan_handle_missing_return () call.
+	 Recognize those too.  */
+      basic_block bb;
+      if (!TREE_NO_WARNING (fun->decl) && (flag_sanitize & SANITIZE_RETURN))
+	FOR_EACH_BB_FN (bb, fun)
+	  if (EDGE_COUNT (bb->succs) == 0)
+	    {
+	      gimple *last = last_stmt (bb);
+	      const enum built_in_function ubsan_missing_ret
+		= BUILT_IN_UBSAN_HANDLE_MISSING_RETURN;
+	      if (last && gimple_call_builtin_p (last, ubsan_missing_ret))
+		{
+		  gimple_stmt_iterator gsi = gsi_for_stmt (last);
+		  gsi_prev_nondebug (&gsi);
+		  gimple *prev = gsi_stmt (gsi);
+		  if (prev == NULL)
+		    location = UNKNOWN_LOCATION;
+		  else
+		    location = gimple_location (prev);
+		  if (LOCATION_LOCUS (location) == UNKNOWN_LOCATION)
+		    location = fun->function_end_locus;
+		  warning_at (location, OPT_Wreturn_type,
+			      "control reaches end of non-void function");
+		  TREE_NO_WARNING (fun->decl) = 1;
+		  break;
+		}
+	    }
     }
   return 0;
 }
--- gcc/testsuite/g++.dg/ubsan/pr81212.C	(nonexistent)
+++ gcc/testsuite/g++.dg/ubsan/pr81212.C	(revision 255354)
@@ -0,0 +1,16 @@
+// PR c++/81212
+// { dg-do compile }
+// { dg-options "-Wreturn-type -fsanitize=return" }
+
+struct S
+{
+  S (void *);
+  void *s;
+};
+
+S
+foo (bool x, void *y)
+{
+  if (x)
+    return S (y);
+}	// { dg-warning "control reaches end of non-void function" }
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-06  Jakub Jelinek  <jakub@redhat.com>

	PR c++/80259
	* decl2.c (grokfield): Diagnose = delete redefinition of a friend.

	* g++.dg/cpp0x/pr80259.C: New test.

--- gcc/cp/decl2.c	(revision 255455)
+++ gcc/cp/decl2.c	(revision 255456)
@@ -911,9 +911,18 @@ grokfield (const cp_declarator *declarat
 	{
 	  if (init == ridpointers[(int)RID_DELETE])
 	    {
-	      DECL_DELETED_FN (value) = 1;
-	      DECL_DECLARED_INLINE_P (value) = 1;
-	      DECL_INITIAL (value) = error_mark_node;
+	      if (friendp && decl_defined_p (value))
+		{
+		  error ("redefinition of %q#D", value);
+		  inform (DECL_SOURCE_LOCATION (value),
+			  "%q#D previously defined here", value);
+		}
+	      else
+		{
+		  DECL_DELETED_FN (value) = 1;
+		  DECL_DECLARED_INLINE_P (value) = 1;
+		  DECL_INITIAL (value) = error_mark_node;
+		}
 	    }
 	  else if (init == ridpointers[(int)RID_DEFAULT])
 	    {
--- gcc/testsuite/g++.dg/cpp0x/pr80259.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp0x/pr80259.C	(revision 255456)
@@ -0,0 +1,13 @@
+// PR c++/80259
+// { dg-do compile { target c++11 } }
+
+void foo () {}	// { dg-message "previously defined here" }
+void bar ();
+
+struct A
+{
+  friend void foo () = delete;	// { dg-error "redefinition of" }
+  friend void bar () = delete;	// { dg-message "previously defined here" }
+};
+
+void bar () {}	// { dg-error "redefinition of" }
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-08  Joseph Myers  <joseph@codesourcery.com>
		    Alexander Monakov  <amonakov@ispras.ru>
		    Jakub Jelinek  <jakub@redhat.com>

	PR target/81906
	* config/i386/i386.c (ix86_expand_rint): Handle flag_rounding_math.

	* gcc.target/i386/pr81906.c: New test.

--- gcc/config/i386/i386.c	(revision 255485)
+++ gcc/config/i386/i386.c	(revision 255486)
@@ -44255,8 +44255,7 @@ ix86_expand_lfloorceil (rtx op0, rtx op1
   emit_move_insn (op0, ireg);
 }
 
-/* Expand rint (IEEE round to nearest) rounding OPERAND1 and storing the
-   result in OPERAND0.  */
+/* Expand rint rounding OPERAND1 and storing the result in OPERAND0.  */
 void
 ix86_expand_rint (rtx operand0, rtx operand1)
 {
@@ -44264,11 +44263,17 @@ ix86_expand_rint (rtx operand0, rtx oper
 	xa = fabs (operand1);
         if (!isless (xa, 2**52))
 	  return operand1;
-        xa = xa + 2**52 - 2**52;
+        two52 = 2**52;
+        if (flag_rounding_math)
+	  {
+	    two52 = copysign (two52, operand1);
+	    xa = operand1;
+	  }
+        xa = xa + two52 - two52;
         return copysign (xa, operand1);
    */
   machine_mode mode = GET_MODE (operand0);
-  rtx res, xa, TWO52, mask;
+  rtx res, xa, TWO52, two52, mask;
   rtx_code_label *label;
 
   res = gen_reg_rtx (mode);
@@ -44281,8 +44286,16 @@ ix86_expand_rint (rtx operand0, rtx oper
   TWO52 = ix86_gen_TWO52 (mode);
   label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
 
-  xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
-  xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
+  two52 = TWO52;
+  if (flag_rounding_math)
+    {
+      two52 = gen_reg_rtx (mode);
+      ix86_sse_copysign_to_positive (two52, TWO52, res, mask);
+      xa = res;
+    }
+
+  xa = expand_simple_binop (mode, PLUS, xa, two52, NULL_RTX, 0, OPTAB_DIRECT);
+  xa = expand_simple_binop (mode, MINUS, xa, two52, xa, 0, OPTAB_DIRECT);
 
   ix86_sse_copysign_to_positive (res, xa, res, mask);
 
--- gcc/testsuite/gcc.target/i386/pr81906.c	(nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr81906.c	(revision 255486)
@@ -0,0 +1,37 @@
+/* PR target/81906 */
+/* { dg-do run { target *-*-linux* *-*-gnu* } }
+/* { dg-options "-O2 -frounding-math" } */
+
+#include <fenv.h>
+
+int
+main ()
+{
+  #define N 12
+  double a[N] = { 2.0, 2.25, 2.5, 2.75, 3.5, -2.0, -2.25, -2.5, -2.75, -3.5, 0x2.0p53, -0x2.0p53 };
+  double b[N], c[N], d[N], e[N];
+  double be[N] = { 2.0, 2.0, 2.0, 3.0, 4.0, -2.0, -2.0, -2.0, -3.0, -4.0, 0x2.0p53, -0x2.0p53 };
+  double ce[N] = { 2.0, 2.0, 2.0, 2.0, 3.0, -2.0, -3.0, -3.0, -3.0, -4.0, 0x2.0p53, -0x2.0p53 };
+  double de[N] = { 2.0, 3.0, 3.0, 3.0, 4.0, -2.0, -2.0, -2.0, -2.0, -3.0, 0x2.0p53, -0x2.0p53 };
+  double ee[N] = { 2.0, 2.0, 2.0, 2.0, 3.0, -2.0, -2.0, -2.0, -2.0, -3.0, 0x2.0p53, -0x2.0p53 };
+  asm volatile ("" : : "g" (a), "g" (be), "g" (ce), "g" (de), "g" (ee) : "memory");
+
+  int i;
+  fesetround (FE_TONEAREST);
+  for (i = 0; i < N; ++i)
+    b[i] = __builtin_rint (a[i]);
+  fesetround (FE_DOWNWARD);
+  for (i = 0; i < N; ++i)
+    c[i] = __builtin_rint (a[i]);
+  fesetround (FE_UPWARD);
+  for (i = 0; i < N; ++i)
+    d[i] = __builtin_rint (a[i]);
+  fesetround (FE_TOWARDZERO);
+  for (i = 0; i < N; ++i)
+    e[i] = __builtin_rint (a[i]);
+  fesetround (FE_TONEAREST);
+  for (i = 0; i < N; ++i)
+    if (b[i] != be[i] || c[i] != ce[i] || d[i] != de[i] || e[i] != ee[i])
+      __builtin_abort ();
+  return 0;
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

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

	PR tree-optimization/80631
	* tree-vect-loop.c (get_initial_def_for_reduction): Fix comment typo.
	(vect_create_epilog_for_reduction): Add INDUC_VAL argument, for
	INTEGER_INDUC_COND_REDUCTION use INDUC_VAL instead of
	hardcoding zero as the value if COND_EXPR is never true.  For
	INTEGER_INDUC_COND_REDUCTION don't emit the final COND_EXPR if
	INDUC_VAL is equal to INITIAL_DEF.
	(vectorizable_reduction): Compute INDUC_VAL for
	vect_create_epilog_for_reduction, if no value is suitable, don't
	use INTEGER_INDUC_COND_REDUCTION for now.  Formatting fixes.

	* gcc.dg/vect/pr80631-1.c: New test.
	* gcc.dg/vect/pr80631-2.c: New test.

	PR tree-optimization/80631
	* gcc.target/i386/avx2-pr80631.c: New test.

--- gcc/tree-vect-loop.c	(revision 255573)
+++ gcc/tree-vect-loop.c	(revision 255574)
@@ -4262,7 +4262,7 @@ get_initial_def_for_reduction (gimple *s
       case BIT_XOR_EXPR:
       case MULT_EXPR:
       case BIT_AND_EXPR:
-        /* ADJUSMENT_DEF is NULL when called from
+        /* ADJUSTMENT_DEF is NULL when called from
            vect_create_epilog_for_reduction to vectorize double reduction.  */
         if (adjustment_def)
 	  *adjustment_def = init_val;
@@ -4358,6 +4358,9 @@ get_initial_def_for_reduction (gimple *s
      first one in this group is STMT.
    INDUCTION_INDEX is the index of the loop for condition reductions.
      Otherwise it is undefined.
+   INDUC_VAL is for INTEGER_INDUC_COND_REDUCTION the value to use for the case
+     when the COND_EXPR is never true in the loop.  It needs to
+     be smaller than any value of the IV in the loop.
 
    This function:
    1. Creates the reduction def-use cycles: sets the arguments for 
@@ -4403,7 +4406,8 @@ vect_create_epilog_for_reduction (vec<tr
 				  int ncopies, enum tree_code reduc_code,
 				  vec<gimple *> reduction_phis,
                                   int reduc_index, bool double_reduc, 
-				  slp_tree slp_node, tree induction_index)
+				  slp_tree slp_node, tree induction_index,
+				  tree induc_val)
 {
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
   stmt_vec_info prev_phi_info;
@@ -4488,6 +4492,15 @@ vect_create_epilog_for_reduction (vec<tr
       gimple *def_stmt = SSA_NAME_DEF_STMT (reduction_op);
       initial_def = PHI_ARG_DEF_FROM_EDGE (def_stmt,
 					   loop_preheader_edge (loop));
+      /* Optimize: if initial_def is for REDUC_MAX smaller than the base
+	 and we can't use zero for induc_val, use initial_def.  Similarly
+	 for REDUC_MIN and initial_def larger than the base.  */
+      if (TREE_CODE (initial_def) == INTEGER_CST
+	  && (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
+	      == INTEGER_INDUC_COND_REDUCTION)
+	  && !integer_zerop (induc_val)
+	  && tree_int_cst_lt (initial_def, induc_val))
+	induc_val = initial_def;
       vect_is_simple_use (initial_def, loop_vinfo, &def_stmt, &initial_def_dt);
       vec_initial_def = get_initial_def_for_reduction (stmt, initial_def,
 						       &adjustment_def);
@@ -4528,9 +4541,10 @@ vect_create_epilog_for_reduction (vec<tr
 	      gcc_assert (i == 0);
 
 	      tree vec_init_def_type = TREE_TYPE (vec_init_def);
-	      tree zero_vec = build_zero_cst (vec_init_def_type);
+	      tree induc_val_vec
+		= build_vector_from_val (vec_init_def_type, induc_val);
 
-	      add_phi_arg (as_a <gphi *> (phi), zero_vec,
+	      add_phi_arg (as_a <gphi *> (phi), induc_val_vec,
 			   loop_preheader_edge (loop), UNKNOWN_LOCATION);
 	    }
 	  else
@@ -4879,14 +4893,16 @@ vect_create_epilog_for_reduction (vec<tr
       gimple_assign_set_lhs (epilog_stmt, new_temp);
       gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
 
-      if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
-	  == INTEGER_INDUC_COND_REDUCTION)
+      if ((STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
+	   == INTEGER_INDUC_COND_REDUCTION)
+	  && !operand_equal_p (initial_def, induc_val, 0))
 	{
-	  /* Earlier we set the initial value to be zero.  Check the result
-	     and if it is zero then replace with the original initial
-	     value.  */
-	  tree zero = build_zero_cst (scalar_type);
-	  tree zcompare = build2 (EQ_EXPR, boolean_type_node, new_temp, zero);
+	  /* Earlier we set the initial value to be a vector if induc_val
+	     values.  Check the result and if it is induc_val then replace
+	     with the original initial value, unless induc_val is
+	     the same as initial_def already.  */
+	  tree zcompare = build2 (EQ_EXPR, boolean_type_node, new_temp,
+				  induc_val);
 
 	  tmp = make_ssa_name (new_scalar_dest);
 	  epilog_stmt = gimple_build_assign (tmp, COND_EXPR, zcompare,
@@ -5001,7 +5017,7 @@ vect_create_epilog_for_reduction (vec<tr
               else
                 vec_temp = gimple_assign_lhs (new_phi);
               tree rhs = build3 (BIT_FIELD_REF, scalar_type, vec_temp, bitsize,
-                            bitsize_zero_node);
+				 bitsize_zero_node);
               epilog_stmt = gimple_build_assign (new_scalar_dest, rhs);
               new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
               gimple_assign_set_lhs (epilog_stmt, new_temp);
@@ -5485,6 +5501,7 @@ vectorizable_reduction (gimple *stmt, gi
   gimple *def_stmt;
   enum vect_def_type dt, cond_reduc_dt = vect_unknown_def_type;
   gphi *new_phi = NULL;
+  gimple *cond_reduc_def_stmt = NULL;
   tree scalar_type;
   bool is_simple_use;
   gimple *orig_stmt;
@@ -5672,9 +5689,13 @@ vectorizable_reduction (gimple *stmt, gi
 	      cond_reduc_dt = dt;
 	      cond_reduc_val = ops[i];
 	    }
-	  if (dt == vect_induction_def && def_stmt != NULL
+	  if (dt == vect_induction_def
+	      && def_stmt != NULL
 	      && is_nonwrapping_integer_induction (def_stmt, loop))
-	    cond_reduc_dt = dt;
+	    {
+	      cond_reduc_dt = dt;
+	      cond_reduc_def_stmt = def_stmt;
+	    }
 	}
     }
 
@@ -5713,12 +5734,28 @@ vectorizable_reduction (gimple *stmt, gi
     {
       if (cond_reduc_dt == vect_induction_def)
 	{
-	  if (dump_enabled_p ())
-	    dump_printf_loc (MSG_NOTE, vect_location,
-			     "condition expression based on "
-			     "integer induction.\n");
-	  STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
-	    = INTEGER_INDUC_COND_REDUCTION;
+	  stmt_vec_info cond_stmt_vinfo = vinfo_for_stmt (cond_reduc_def_stmt);
+	  tree base
+	    = STMT_VINFO_LOOP_PHI_EVOLUTION_BASE_UNCHANGED (cond_stmt_vinfo);
+
+	  gcc_assert (TREE_CODE (base) == INTEGER_CST);
+	  cond_reduc_val = NULL_TREE;
+	  /* Find a suitable value below base; punt if base is the minimum
+	     value of the type for now.  */
+	  if (tree_int_cst_sgn (base) == 1)
+	    cond_reduc_val = build_int_cst (TREE_TYPE (base), 0);
+	  else if (tree_int_cst_lt (TYPE_MIN_VALUE (TREE_TYPE (base)), base))
+	    cond_reduc_val
+	      = int_const_binop (MINUS_EXPR, base, integer_one_node);
+	  if (cond_reduc_val)
+	    {
+	      if (dump_enabled_p ())
+		dump_printf_loc (MSG_NOTE, vect_location,
+				 "condition expression based on "
+				 "integer induction.\n");
+	      STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
+		= INTEGER_INDUC_COND_REDUCTION;
+	    }
 	}
 
       /* Loop peeling modifies initial value of reduction PHI, which
@@ -5915,7 +5952,7 @@ vectorizable_reduction (gimple *stmt, gi
 	  gcc_assert (orig_code == MAX_EXPR || orig_code == MIN_EXPR);
 	}
       else if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
-		 == INTEGER_INDUC_COND_REDUCTION)
+	       == INTEGER_INDUC_COND_REDUCTION)
 	orig_code = MAX_EXPR;
     }
 
@@ -6382,7 +6419,8 @@ vectorizable_reduction (gimple *stmt, gi
 
   vect_create_epilog_for_reduction (vect_defs, stmt, epilog_copies,
                                     epilog_reduc_code, phis, reduc_index,
-				    double_reduc, slp_node, cond_name);
+				    double_reduc, slp_node, cond_name,
+				    cond_reduc_val);
 
   return true;
 }
--- gcc/testsuite/gcc.dg/vect/pr80631-1.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/vect/pr80631-1.c	(revision 255574)
@@ -0,0 +1,76 @@
+/* PR tree-optimization/80631 */
+/* { dg-do run } */
+
+#include "tree-vect.h"
+
+int v[8] = { 77, 1, 79, 3, 4, 3, 6, 7 };
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+  int k, r = -1;
+  for (k = 0; k < 8; k++)
+    if (v[k] == 77)
+      r = k;
+  if (r != 0)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+  int k, r = 4;
+  for (k = 0; k < 8; k++)
+    if (v[k] == 79)
+      r = k;
+  if (r != 2)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f3 (void)
+{
+  int k, r = -17;
+  for (k = 0; k < 8; k++)
+    if (v[k] == 78)
+      r = k;
+  if (r != -17)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f4 (void)
+{
+  int k, r = 7;
+  for (k = 0; k < 8; k++)
+    if (v[k] == 78)
+      r = k;
+  if (r != 7)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f5 (void)
+{
+  int k, r = -1;
+  for (k = 0; k < 8; k++)
+    if (v[k] == 3)
+      r = k;
+  if (r != 5)
+    abort ();
+}
+
+int
+main ()
+{
+  check_vect ();
+  f1 ();
+  f2 ();
+  f3 ();
+  f4 ();
+  f5 ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 5 "vect" { xfail { ! vect_max_reduc } } } } */
+/* { dg-final { scan-tree-dump-times "condition expression based on integer induction." 10 "vect" { xfail { ! vect_max_reduc } } } } */
--- gcc/testsuite/gcc.dg/vect/pr80631-2.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/vect/pr80631-2.c	(revision 255574)
@@ -0,0 +1,73 @@
+/* PR tree-optimization/80631 */
+/* { dg-do run } */
+
+#include "tree-vect.h"
+
+int v[8] = { 77, 1, 79, 3, 4, 3, 6, 7 };
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+  int k, r = -1;
+  for (k = 7; k >= 0; k--)
+    if (v[k] == 77)
+      r = k;
+  if (r != 0)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+  int k, r = 4;
+  for (k = 7; k >= 0; k--)
+    if (v[k] == 79)
+      r = k;
+  if (r != 2)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f3 (void)
+{
+  int k, r = -17;
+  for (k = 7; k >= 0; k--)
+    if (v[k] == 78)
+      r = k;
+  if (r != -17)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f4 (void)
+{
+  int k, r = 7;
+  for (k = 7; k >= 0; k--)
+    if (v[k] == 78)
+      r = k;
+  if (r != 7)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f5 (void)
+{
+  int k, r = -1;
+  for (k = 7; k >= 0; k--)
+    if (v[k] == 3)
+      r = k;
+  if (r != 3)
+    abort ();
+}
+
+int
+main ()
+{
+  check_vect ();
+  f1 ();
+  f2 ();
+  f3 ();
+  f4 ();
+  f5 ();
+  return 0;
+}
--- gcc/testsuite/gcc.target/i386/avx2-pr80631.c	(nonexistent)
+++ gcc/testsuite/gcc.target/i386/avx2-pr80631.c	(revision 255701)
@@ -0,0 +1,23 @@
+/* PR tree-optimization/80631 */
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -mavx2 -fno-vect-cost-model" } */
+/* { dg-require-effective-target avx2 } */
+
+#include "avx2-check.h"
+
+#define N 8
+
+static void
+avx2_test (void)
+{
+  int v[N], k;
+  for(k = 0; k < N; k++)
+    v[k] = k;
+  v[0] = 77;
+  int found_index = -1;
+  for (k = 0; k < N; k++)
+    if (v[k] == 77)
+      found_index = k;
+  if (found_index != 0)
+    abort ();
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-14  Jakub Jelinek  <jakub@redhat.com>

	PR c++/79650
	* pt.c (convert_nontype_argument): Diagnose
	reduced_constant_expression_p expressions that aren't INTEGER_CST.

	* g++.dg/template/pr79650.C: New test.

--- gcc/cp/pt.c	(revision 255622)
+++ gcc/cp/pt.c	(revision 255623)
@@ -6523,7 +6523,20 @@ convert_nontype_argument (tree type, tre
 		return NULL_TREE;
 	      /* else cxx_constant_value complained but gave us
 		 a real constant, so go ahead.  */
-	      gcc_assert (TREE_CODE (expr) == INTEGER_CST);
+	      if (TREE_CODE (expr) != INTEGER_CST)
+		{
+		  /* Some assemble time constant expressions like
+		     (intptr_t)&&lab1 - (intptr_t)&&lab2 or
+		     4 + (intptr_t)&&var satisfy reduced_constant_expression_p
+		     as we can emit them into .rodata initializers of
+		     variables, yet they can't fold into an INTEGER_CST at
+		     compile time.  Refuse them here.  */
+		  gcc_checking_assert (reduced_constant_expression_p (expr));
+		  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+		  error_at (loc, "template argument %qE for type %qT not "
+				 "a constant integer", expr, type);
+		  return NULL_TREE;
+		}
 	    }
 	  else
 	    return NULL_TREE;
--- gcc/testsuite/g++.dg/template/pr79650.C	(nonexistent)
+++ gcc/testsuite/g++.dg/template/pr79650.C	(revision 255623)
@@ -0,0 +1,20 @@
+// PR c++/79650
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+typedef __INTPTR_TYPE__ intptr_t;
+template<intptr_t> struct A {};
+
+void
+foo ()
+{
+  static int a, b;
+lab1:
+lab2:
+  A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab2> c;	// { dg-error "not a constant integer" }
+  A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab1> d;
+  A<(intptr_t)&a - (intptr_t)&b> e;			// { dg-error "is not a constant expression" }
+  A<(intptr_t)&a - (intptr_t)&a> f;
+  A<(intptr_t)sizeof(a) + (intptr_t)&a> g;		// { dg-error "not a constant integer" }
+  A<(intptr_t)&a> h;					// { dg-error "conversion from pointer type" }
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-14  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/83198
	* gimple-ssa-sprintf.c (format_floating): Set type solely based on
	dir.modifier, regardless of TREE_TYPE (arg).  Assume non-REAL_CST
	value if arg is a REAL_CST with incompatible type.

	* gcc.dg/pr83198.c: New test.
	* gcc.dg/tree-ssa/pr83198.c: New test.

--- gcc/gimple-ssa-sprintf.c	(revision 255625)
+++ gcc/gimple-ssa-sprintf.c	(revision 255626)
@@ -1885,6 +1885,8 @@ static fmtresult
 format_floating (const directive &dir, tree arg)
 {
   HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] };
+  tree type = (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll
+	       ? long_double_type_node : double_type_node);
 
   /* For an indeterminate precision the lower bound must be assumed
      to be zero.  */
@@ -1892,10 +1894,6 @@ format_floating (const directive &dir, t
     {
       /* Get the number of fractional decimal digits needed to represent
 	 the argument without a loss of accuracy.  */
-      tree type = arg ? TREE_TYPE (arg) :
-	(dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll
-	 ? long_double_type_node : double_type_node);
-
       unsigned fmtprec
 	= REAL_MODE_FORMAT (TYPE_MODE (type))->p;
 
@@ -1946,7 +1944,9 @@ format_floating (const directive &dir, t
 	}
     }
 
-  if (!arg || TREE_CODE (arg) != REAL_CST)
+  if (!arg
+      || TREE_CODE (arg) != REAL_CST
+      || !useless_type_conversion_p (type, TREE_TYPE (arg)))
     return format_floating (dir, prec);
 
   /* The minimum and maximum number of bytes produced by the directive.  */
--- gcc/testsuite/gcc.dg/pr83198.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/pr83198.c	(revision 255626)
@@ -0,0 +1,18 @@
+/* PR tree-optimization/83198 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -Wno-format" } */
+
+int
+foo (char *d[6], int x)
+{
+  int r = 0;
+  r += __builtin_sprintf (d[0], "%f", x);
+  r += __builtin_sprintf (d[1], "%a", x);
+  r += __builtin_sprintf (d[2], "%f", "foo");
+  r += __builtin_sprintf (d[3], "%a", "bar");
+#ifdef __SIZEOF_FLOAT128__
+  r += __builtin_sprintf (d[4], "%a", 1.0Q);
+  r += __builtin_sprintf (d[5], "%Lf", 1.0Q);
+#endif
+  return r;
+}
--- gcc/testsuite/gcc.dg/tree-ssa/pr83198.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr83198.c	(revision 255626)
@@ -0,0 +1,23 @@
+/* PR tree-optimization/83198 */
+/* { dg-do compile { target __float128 } } */
+/* { dg-options "-O2 -fprintf-return-value -Wno-format -fdump-tree-optimized" } */
+/* { dg-add-options __float128 } */
+
+void bar (void);
+void link_error (void);
+
+void
+foo (char *x)
+{
+  int a = __builtin_sprintf (x, "%f", 1.0Q);
+  if (a < 8)
+    link_error ();
+  if (a > 13)
+    bar ();
+  if (a > 322)
+    link_error ();
+}
+
+/* Verify we don't optimize return value to [8, 13].  */
+/* { dg-final { scan-tree-dump-not "link_error \\(\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump "bar \\(\\);" "optimized" } } */
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/83269
	* fold-const.c (fold_binary_loc): Perform (-A) - B -> (-B) - A
	subtraction in arg0's type if type is signed and arg0 is unsigned.
	Formatting fix.

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

--- gcc/fold-const.c	(revision 255696)
+++ gcc/fold-const.c	(revision 255697)
@@ -9123,8 +9123,8 @@ expr_not_equal_to (tree t, const wide_in
    return NULL_TREE.  */
 
 tree
-fold_binary_loc (location_t loc,
-	     enum tree_code code, tree type, tree op0, tree op1)
+fold_binary_loc (location_t loc, enum tree_code code, tree type,
+		 tree op0, tree op1)
 {
   enum tree_code_class kind = TREE_CODE_CLASS (code);
   tree arg0, arg1, tem;
@@ -9728,10 +9728,17 @@ fold_binary_loc (location_t loc,
     case MINUS_EXPR:
       /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
-	  && negate_expr_p (op1))
-	return fold_build2_loc (loc, MINUS_EXPR, type,
-				negate_expr (op1),
-				fold_convert_loc (loc, type,
+	  && negate_expr_p (op1)
+	  /* If arg0 is e.g. unsigned int and type is int, then this could
+	     introduce UB, because if A is INT_MIN at runtime, the original
+	     expression can be well defined while the latter is not.
+	     See PR83269.  */
+	  && !(ANY_INTEGRAL_TYPE_P (type)
+	       && TYPE_OVERFLOW_UNDEFINED (type)
+	       && ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+	       && !TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))))
+	return fold_build2_loc (loc, MINUS_EXPR, type, negate_expr (op1),
+			        fold_convert_loc (loc, type,
 						  TREE_OPERAND (arg0, 0)));
 
       /* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to
--- gcc/testsuite/gcc.c-torture/execute/pr83269.c	(nonexistent)
+++ gcc/testsuite/gcc.c-torture/execute/pr83269.c	(revision 255697)
@@ -0,0 +1,14 @@
+/* PR tree-optimization/83269 */
+
+int
+main ()
+{
+#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ > 4 && __CHAR_BIT__ == 8
+  volatile unsigned char a = 1;
+  long long b = 0x80000000L;
+  int c = -((int)(-b) - (-0x7fffffff * a));
+  if (c != 1)
+    __builtin_abort ();
+#endif
+  return 0;
+}
2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	PR c++/83217
	* decl.c (cp_finish_decomp): If decl's type is REFERENCE_TYPE,
	call complete_type (TREE_TYPE (type)).

	* g++.dg/cpp1z/decomp33.C: New test.

--- gcc/cp/decl.c	(revision 255701)
+++ gcc/cp/decl.c	(revision 255702)
@@ -7404,7 +7404,9 @@ cp_finish_decomp (tree decl, tree first,
   if (TREE_CODE (type) == REFERENCE_TYPE)
     {
       dexp = convert_from_reference (dexp);
-      type = TREE_TYPE (type);
+      type = complete_type (TREE_TYPE (type));
+      if (type == error_mark_node)
+	goto error_out;
     }
 
   tree eltype = NULL_TREE;
--- gcc/testsuite/g++.dg/cpp1z/decomp33.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp33.C	(revision 255702)
@@ -0,0 +1,21 @@
+// PR c++/83217
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+template <typename T>
+struct S
+{
+  T a;
+};
+
+void
+foo (S<int> *b)
+{
+  auto & [c] = *b;	// { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+}
+
+void
+bar (S<char> *d)
+{
+  auto [e] = *d;	// { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+}

Comments

Jakub Jelinek Dec. 16, 2017, 12:41 a.m. | #1
On Fri, Dec 15, 2017 at 11:23:21PM +0100, Jakub Jelinek wrote:
> Hi!

> 

> I've backported today following 23 patches after bootstrapping/regtesting

> them on x86_64-linux and i686-linux.


And 2 more:

	Jakub
2017-12-16  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	PR c++/81197
	* cp-tree.h (cp_maybe_mangle_decomp): Declare.
	* decl.c (cp_maybe_mangle_decomp): New function.
	(cp_finish_decomp): Don't SET_DECL_ASSEMBLER_NAME here.
	* parser.c (cp_convert_range_for,
	cp_parser_decomposition_declaration): Call cp_maybe_mangle_decomp.
	* pt.c (tsubst_expr): Likewise.
	* mangle.c (find_decomp_unqualified_name): New function.
	(write_unqualified_name): Handle DECL_DECOMPOSITION_P
	where DECL_ASSEMBLER_NAME is already set.

	* g++.dg/cpp1z/decomp34.C: New test.

--- gcc/cp/decl.c	(revision 255704)
+++ gcc/cp/decl.c	(revision 255705)
@@ -7339,6 +7339,25 @@ lookup_decomp_type (tree v)
   return *decomp_type_table->get (v);
 }
 
+/* Mangle a decomposition declaration if needed.  Arguments like
+   in cp_finish_decomp.  */
+
+void
+cp_maybe_mangle_decomp (tree decl, tree first, unsigned int count)
+{
+  if (!processing_template_decl
+      && !error_operand_p (decl)
+      && DECL_NAMESPACE_SCOPE_P (decl))
+    {
+      auto_vec<tree, 16> v;
+      v.safe_grow (count);
+      tree d = first;
+      for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
+	v[count - i - 1] = d;
+      SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v));
+    }
+}
+
 /* Finish a decomposition declaration.  DECL is the underlying declaration
    "e", FIRST is the head of a chain of decls for the individual identifiers
    chained through DECL_CHAIN in reverse order and COUNT is the number of
@@ -7612,8 +7631,6 @@ cp_finish_decomp (tree decl, tree first,
 	    DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
 	  }
     }
-  else if (DECL_NAMESPACE_SCOPE_P (decl))
-    SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v));
 }
 
 /* Returns a declaration for a VAR_DECL as if:
--- gcc/cp/pt.c	(revision 255704)
+++ gcc/cp/pt.c	(revision 255705)
@@ -16135,19 +16135,23 @@ tsubst_expr (tree t, tree args, tsubst_f
 		    if (VAR_P (decl))
 		      const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
 				    (pattern_decl));
-		    cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
 		    if (VAR_P (decl)
 			&& DECL_DECOMPOSITION_P (decl)
 			&& TREE_TYPE (pattern_decl) != error_mark_node)
 		      {
 			unsigned int cnt;
 			tree first;
-			decl = tsubst_decomp_names (decl, pattern_decl, args,
-						    complain, in_decl, &first,
-						    &cnt);
-			if (decl != error_mark_node)
-			  cp_finish_decomp (decl, first, cnt);
+			tree ndecl
+			  = tsubst_decomp_names (decl, pattern_decl, args,
+						 complain, in_decl, &first, &cnt);
+			if (ndecl != error_mark_node)
+			  cp_maybe_mangle_decomp (ndecl, first, cnt);
+			cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
+			if (ndecl != error_mark_node)
+			  cp_finish_decomp (ndecl, first, cnt);
 		      }
+		    else
+		      cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
 		  }
 	      }
 	  }
--- gcc/cp/parser.c	(revision 255704)
+++ gcc/cp/parser.c	(revision 255705)
@@ -11735,6 +11735,9 @@ cp_convert_range_for (tree statement, tr
 				     tf_warning_or_error);
   finish_for_expr (expression, statement);
 
+  if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl))
+    cp_maybe_mangle_decomp (range_decl, decomp_first_name, decomp_cnt);
+
   /* The declaration is initialized with *__begin inside the loop body.  */
   cp_finish_decl (range_decl,
 		  build_x_indirect_ref (input_location, begin, RO_NULL,
@@ -13059,6 +13062,7 @@ cp_parser_decomposition_declaration (cp_
 
       if (decl != error_mark_node)
 	{
+	  cp_maybe_mangle_decomp (decl, prev, v.length ());
 	  cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE,
 			  is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT);
 	  cp_finish_decomp (decl, prev, v.length ());
--- gcc/cp/mangle.c	(revision 255704)
+++ gcc/cp/mangle.c	(revision 255705)
@@ -1247,6 +1247,51 @@ write_template_prefix (const tree node)
   add_substitution (substitution);
 }
 
+/* As the list of identifiers for the structured binding declaration
+   DECL is likely gone, try to recover the DC <source-name>+ E portion
+   from its mangled name.  Return pointer to the DC and set len to
+   the length up to and including the terminating E.  On failure
+   return NULL.  */
+
+static const char *
+find_decomp_unqualified_name (tree decl, size_t *len)
+{
+  const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
+  bool nested = false;
+  if (strncmp (p, "_Z", 2))
+    return NULL;
+  p += 2;
+  if (!strncmp (p, "St", 2))
+    p += 2;
+  else if (*p == 'N')
+    {
+      nested = true;
+      ++p;
+      while (ISDIGIT (p[0]))
+	{
+	  char *e;
+	  long num = strtol (p, &e, 10);
+	  if (num >= 1 && num < end - e)
+	    p = e + num;
+	  else
+	    break;
+	}
+    }
+  if (strncmp (p, "DC", 2))
+    return NULL;
+  if (nested)
+    {
+      if (end[-1] != 'E')
+	return NULL;
+      --end;
+    }
+  if (end[-1] != 'E')
+    return NULL;
+  *len = end - p;
+  return p;
+}
+
 /* We don't need to handle thunks, vtables, or VTTs here.  Those are
    mangled through special entry points.
 
@@ -1291,7 +1336,17 @@ write_unqualified_name (tree decl)
     {
       found = true;
       gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
-      write_source_name (DECL_ASSEMBLER_NAME (decl));
+      const char *decomp_str = NULL;
+      size_t decomp_len = 0;
+      if (VAR_P (decl)
+	  && DECL_DECOMPOSITION_P (decl)
+	  && DECL_NAME (decl) == NULL_TREE
+	  && DECL_NAMESPACE_SCOPE_P (decl))
+	decomp_str = find_decomp_unqualified_name (decl, &decomp_len);
+      if (decomp_str)
+	write_chars (decomp_str, decomp_len);
+      else
+	write_source_name (DECL_ASSEMBLER_NAME (decl));
     }
   else if (DECL_DECLARES_FUNCTION_P (decl))
     {
--- gcc/cp/cp-tree.h	(revision 255704)
+++ gcc/cp/cp-tree.h	(revision 255705)
@@ -6149,6 +6149,7 @@ extern void start_decl_1			(tree, bool);
 extern bool check_array_initializer		(tree, tree, tree);
 extern void cp_finish_decl			(tree, tree, bool, tree, int);
 extern tree lookup_decomp_type			(tree);
+extern void cp_maybe_mangle_decomp		(tree, tree, unsigned int);
 extern void cp_finish_decomp			(tree, tree, unsigned int);
 extern int cp_complete_array_type		(tree *, tree, bool);
 extern int cp_complete_array_type_or_error	(tree *, tree, bool, tsubst_flags_t);
--- gcc/testsuite/g++.dg/cpp1z/decomp34.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp34.C	(revision 255705)
@@ -0,0 +1,11 @@
+// PR c++/81197
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct X { int a; };
+struct Y { int b, c, d; };
+auto&& [t] = X{};	// { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+namespace A { namespace B { auto&& [u, v, ww] = Y{}; } }	// { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+
+// { dg-final { scan-assembler "_ZGRDC1tE0" } }
+// { dg-final { scan-assembler "_ZGRN1A1BDC1u1v2wwEE1" } }
2017-12-16  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-15  Jakub Jelinek  <jakub@redhat.com>

	PR c++/83205
	* decl.c (cp_finish_decomp): Handle the case when tsize is not
	error_mark_node, but doesn't fit into uhwi.  Split up count != eltscnt
	and !tree_fits_uhwi_p (tsize) error_at calls into error_n and inform_n
	to handle plural forms properly.

	* g++.dg/cpp1z/decomp3.C: Adjust for structured binding count
	mismatch diagnostics split into error and warning with plural
	forms.
	* g++.dg/cpp1z/decomp10.C: Likewise.
	* g++.dg/cpp1z/decomp32.C: New test.

--- gcc/cp/decl.c	(revision 255705)
+++ gcc/cp/decl.c	(revision 255706)
@@ -7446,11 +7446,20 @@ cp_finish_decomp (tree decl, tree first,
 	{
        cnt_mismatch:
 	  if (count > eltscnt)
-	    error_at (loc, "%u names provided while %qT decomposes into "
-			   "%wu elements", count, type, eltscnt);
+	    error_n (loc, count,
+		     "%u name provided for structured binding",
+		     "%u names provided for structured binding", count);
 	  else
-	    error_at (loc, "only %u names provided while %qT decomposes into "
-			   "%wu elements", count, type, eltscnt);
+	    error_n (loc, count,
+		     "only %u name provided for structured binding",
+		     "only %u names provided for structured binding", count);
+	  /* Some languages have special plural rules even for large values,
+	     but it is periodic with period of 10, 100, 1000 etc.  */
+	  inform_n (loc, eltscnt > INT_MAX
+			 ? (eltscnt % 1000000) + 1000000 : eltscnt,
+		    "while %qT decomposes into %wu element",
+		    "while %qT decomposes into %wu elements",
+		    type, eltscnt);
 	  goto error_out;
 	}
       eltype = TREE_TYPE (type);
@@ -7519,6 +7528,15 @@ cp_finish_decomp (tree decl, tree first,
 			 "constant expression", type);
 	  goto error_out;
 	}
+      if (!tree_fits_uhwi_p (tsize))
+	{
+	  error_n (loc, count,
+		   "%u name provided for structured binding",
+		   "%u names provided for structured binding", count);
+	  inform (loc, "while %qT decomposes into %E elements",
+		  type, tsize);
+	  goto error_out;
+	}
       eltscnt = tree_to_uhwi (tsize);
       if (count != eltscnt)
 	goto cnt_mismatch;
--- gcc/testsuite/g++.dg/cpp1z/decomp3.C	(revision 255705)
+++ gcc/testsuite/g++.dg/cpp1z/decomp3.C	(revision 255706)
@@ -51,16 +51,21 @@ int arr[4];
 void
 test3 (A &b, B c)
 {
-  auto [ d, e, f ] = arr;		// { dg-error "only 3 names provided while 'int .4.' decomposes into 4 elements" }
-					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
-  auto & [ g, h, i, j, k ] = arr;	// { dg-error "5 names provided while 'int .4.' decomposes into 4 elements" }
-					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
-  auto [ l, m ] = b;			// { dg-error "only 2 names provided while 'A' decomposes into 3 elements" }
-					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
-  auto & [ n, o, p, q ] = b;		// { dg-error "4 names provided while 'A' decomposes into 3 elements" }
-					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+  auto [ d, e, f ] = arr;		// { dg-error "only 3 names provided" }
+					// { dg-message "while 'int .4.' decomposes into 4 elements" "" { target *-*-* } .-1 }
+					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 }
+  auto & [ g, h, i, j, k ] = arr;	// { dg-error "5 names provided" }
+					// { dg-message "while 'int .4.' decomposes into 4 elements" "" { target *-*-* } .-1 }
+					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 }
+  auto [ l, m ] = b;			// { dg-error "only 2 names provided" }
+					// { dg-message "while 'A' decomposes into 3 elements" "" { target *-*-* } .-1 }
+					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 }
+  auto & [ n, o, p, q ] = b;		// { dg-error "4 names provided" }
+					// { dg-message "while 'A' decomposes into 3 elements" "" { target *-*-* } .-1 }
+					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 }
   auto [] { c };			// { dg-error "empty decomposition declaration" }
 					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
-  auto [ r, s ] = c;			// { dg-error "2 names provided while 'B' decomposes into 1 elements" }
-					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+  auto [ r, s ] = c;			// { dg-error "2 names provided" }
+					// { dg-message "while 'B' decomposes into 1 element" "" { target *-*-* } .-1 }
+					// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 }
 }
--- gcc/testsuite/g++.dg/cpp1z/decomp10.C	(revision 255705)
+++ gcc/testsuite/g++.dg/cpp1z/decomp10.C	(revision 255706)
@@ -11,7 +11,8 @@ void f1() { auto [ x ] = a1; }	// { dg-e
 
 struct A2 { int i,j; } a2;
 template<> struct std::tuple_size<A2> { enum { value = 5 }; };
-void f2() { auto [ x ] = a2; }	// { dg-error "decomposes into 5" }
+void f2() { auto [ x ] = a2; }	// { dg-error "only 1 name provided" }
+			        // { dg-message "decomposes into 5" "" { target *-*-* } .-1 }
 
 struct A3 { int i,j; } a3;
 template<> struct std::tuple_size<A3> { enum { value = 1 }; };
--- gcc/testsuite/g++.dg/cpp1z/decomp32.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp32.C	(revision 255706)
@@ -0,0 +1,32 @@
+// PR c++/83205
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct A { int i; };
+struct B { int i; };
+namespace std {
+  template <typename T> struct tuple_size;
+  template <> struct tuple_size<A> {
+    static constexpr int value = -1;
+  };
+#ifdef __SIZEOF_INT128__
+  template <> struct tuple_size<B> {
+    static constexpr unsigned __int128 value = -1;
+  };
+#endif
+}
+
+auto [a] = A{};	// { dg-error "1 name provided" }
+		// { dg-message "while 'A' decomposes into -1 elements" "" { target *-*-* } .-1 }
+		// { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-2 }
+#ifdef __SIZEOF_INT128__
+auto [b] = B{};	// { dg-error "1 name provided" "" { target int128 } }
+		// { dg-message "while 'B' decomposes into \[0-9xa-fXA-F]* elements" "" { target int128 } .-1 }
+		// { dg-warning "decomposition declaration only available with" "" { target { c++14_down && int128 } } .-2 }
+auto [c, d] = B{};	// { dg-error "2 names provided" "" { target int128 } }
+			// { dg-message "while 'B' decomposes into \[0-9xa-fXA-F]* elements" "" { target int128 } .-1 }
+			// { dg-warning "decomposition declaration only available with" "" { target { c++14_down && int128 } } .-2 }
+#endif
+auto [e, f, g] = A{};	// { dg-error "3 names provided" }
+			// { dg-message "while 'A' decomposes into -1 elements" "" { target *-*-* } .-1 }
+			// { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-2 }

Patch

--- gcc/cp/constexpr.c	(revision 254951)
+++ gcc/cp/constexpr.c	(revision 254952)
@@ -2086,6 +2086,45 @@  cxx_eval_conditional_expression (const c
 				       jump_target);
 }
 
+/* Subroutine of cxx_eval_constant_expression.
+   Attempt to evaluate vector condition expressions.  Unlike
+   cxx_eval_conditional_expression, VEC_COND_EXPR acts like a normal
+   ternary arithmetics operation, where all 3 arguments have to be
+   evaluated as constants and then folding computes the result from
+   them.  */
+
+static tree
+cxx_eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t,
+					bool *non_constant_p, bool *overflow_p)
+{
+  tree arg1 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
+					    /*lval*/false,
+					    non_constant_p, overflow_p);
+  VERIFY_CONSTANT (arg1);
+  tree arg2 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
+					    /*lval*/false,
+					    non_constant_p, overflow_p);
+  VERIFY_CONSTANT (arg2);
+  tree arg3 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2),
+					    /*lval*/false,
+					    non_constant_p, overflow_p);
+  VERIFY_CONSTANT (arg3);
+  location_t loc = EXPR_LOCATION (t);
+  tree type = TREE_TYPE (t);
+  tree r = fold_ternary_loc (loc, VEC_COND_EXPR, type, arg1, arg2, arg3);
+  if (r == NULL_TREE)
+    {
+      if (arg1 == TREE_OPERAND (t, 0)
+	  && arg2 == TREE_OPERAND (t, 1)
+	  && arg3 == TREE_OPERAND (t, 2))
+	r = t;
+      else
+	r = build3_loc (loc, VEC_COND_EXPR, type, arg1, arg2, arg3);
+    }
+  VERIFY_CONSTANT (r);
+  return r;
+}
+
 /* Returns less than, equal to, or greater than zero if KEY is found to be
    less than, to match, or to be greater than the constructor_elt's INDEX.  */
 
@@ -4398,12 +4437,14 @@  cxx_eval_constant_expression (const cons
 					      jump_target);
 	  break;
 	}
-      /* FALLTHRU */
-    case VEC_COND_EXPR:
       r = cxx_eval_conditional_expression (ctx, t, lval,
 					   non_constant_p, overflow_p,
 					   jump_target);
       break;
+    case VEC_COND_EXPR:
+      r = cxx_eval_vector_conditional_expression (ctx, t, non_constant_p,
+						  overflow_p);
+      break;
 
     case CONSTRUCTOR:
       if (TREE_CONSTANT (t))
--- gcc/testsuite/g++.dg/ext/constexpr-pr82781.C	(nonexistent)
+++ gcc/testsuite/g++.dg/ext/constexpr-pr82781.C	(revision 254952)
@@ -0,0 +1,12 @@ 
+// PR c++/82781
+// { dg-do compile { target c++11 } }
+
+typedef int V __attribute__ ((vector_size (16)));
+constexpr V b1 = { 0, 1, 10, 20 };
+constexpr V b2 = { 0, 2, 10, 0 };
+constexpr V b3 = b1 == b2;
+
+static_assert (b3[0] == -1, "");
+static_assert (b3[1] == 0, "");
+static_assert (b3[2] == -1, "");
+static_assert (b3[3] == 0, "");