Hi!

I've backported a couple of patches from trunk to 6 branch,
bootstrapped/regtested on x86_64-linux and i686-linux, committed
to 6.x.

        Jakub
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-09-16  Jakub Jelinek  <ja...@redhat.com>

        PR c++/77375
        * class.c (check_bases): Set CLASSTYPE_HAS_MUTABLE if any
        TYPE_HAS_MUTABLE_P for any bases.

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

--- gcc/cp/class.c      (revision 240194)
+++ gcc/cp/class.c      (revision 240195)
@@ -1796,6 +1796,8 @@ check_bases (tree t,
       SET_CLASSTYPE_REF_FIELDS_NEED_INIT
        (t, CLASSTYPE_REF_FIELDS_NEED_INIT (t)
         | CLASSTYPE_REF_FIELDS_NEED_INIT (basetype));
+      if (TYPE_HAS_MUTABLE_P (basetype))
+       CLASSTYPE_HAS_MUTABLE (t) = 1;
 
       /*  A standard-layout class is a class that:
          ...
--- gcc/testsuite/g++.dg/cpp0x/mutable1.C       (revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/mutable1.C       (revision 240195)
@@ -0,0 +1,12 @@
+// PR c++/77375
+// { dg-do run { target c++11 } }
+
+struct Base { mutable int i; };
+struct Derived : Base {};
+const Derived foo{};
+
+int
+main ()
+{
+  foo.i = 42;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-09-16  Jakub Jelinek  <ja...@redhat.com>

        PR c++/77482
        * error.c (dump_simple_decl): Only check DECL_DECLARED_CONCEPT_P
        if DECL_LANG_SPECIFIC is non-NULL.  Fix up formatting.

        PR c++/77482
        * g++.dg/cpp0x/constexpr-77482.C: New test.

--- gcc/cp/error.c      (revision 240197)
+++ gcc/cp/error.c      (revision 240198)
@@ -959,14 +959,13 @@ dump_simple_decl (cxx_pretty_printer *pp
 {
   if (flags & TFF_DECL_SPECIFIERS)
     {
-      if (VAR_P (t)
-         && DECL_DECLARED_CONSTEXPR_P (t))
-            {
-              if (DECL_DECLARED_CONCEPT_P (t))
-                pp_cxx_ws_string (pp, "concept");
-              else
-               pp_cxx_ws_string (pp, "constexpr");
-            }
+      if (VAR_P (t) && DECL_DECLARED_CONSTEXPR_P (t))
+        {
+         if (DECL_LANG_SPECIFIC (t) && DECL_DECLARED_CONCEPT_P (t))
+           pp_cxx_ws_string (pp, "concept");
+         else
+           pp_cxx_ws_string (pp, "constexpr");
+       }
       dump_type_prefix (pp, type, flags & ~TFF_UNQUALIFIED_NAME);
       pp_maybe_space (pp);
     }
--- gcc/testsuite/g++.dg/cpp0x/constexpr-77482.C        (revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-77482.C        (revision 240198)
@@ -0,0 +1,6 @@
+// PR c++/77482
+// { dg-do compile { target c++11 } }
+
+constexpr auto x;      // { dg-error "declaration\[^\n\r]*has no initializer" }
+extern struct S s;
+constexpr auto y = s;  // { dg-error "has incomplete type" }
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-09-19  Jakub Jelinek  <ja...@redhat.com>
                    Jan Hubicka  <j...@suse.cz>

        PR target/77587
        * cgraph.c (cgraph_node::rtl_info): Pass &avail to
        ultimate_alias_target call, return NULL if avail < AVAIL_AVAILABLE.
        Call ultimate_alias_target just once, not up to 4 times.

        * gcc.dg/pr77587.c: New test.
        * gcc.dg/pr77587a.c: New file.

--- gcc/cgraph.c        (revision 240231)
+++ gcc/cgraph.c        (revision 240232)
@@ -1955,14 +1955,17 @@ cgraph_node::rtl_info (tree decl)
   cgraph_node *node = get (decl);
   if (!node)
     return NULL;
-  node = node->ultimate_alias_target ();
-  if (node->decl != current_function_decl
-      && !TREE_ASM_WRITTEN (node->decl))
+  enum availability avail;
+  node = node->ultimate_alias_target (&avail);
+  if (decl != current_function_decl
+      && (avail < AVAIL_AVAILABLE
+         || (node->decl != current_function_decl
+             && !TREE_ASM_WRITTEN (node->decl))))
     return NULL;
-  /* Allocate if it doesnt exist.  */
-  if (node->ultimate_alias_target ()->rtl == NULL)
-    node->ultimate_alias_target ()->rtl = ggc_cleared_alloc<cgraph_rtl_info> 
();
-  return node->ultimate_alias_target ()->rtl;
+  /* Allocate if it doesn't exist.  */
+  if (node->rtl == NULL)
+    node->rtl = ggc_cleared_alloc<cgraph_rtl_info> ();
+  return node->rtl;
 }
 
 /* Return a string describing the failure REASON.  */
--- gcc/testsuite/gcc.dg/pr77587.c      (revision 0)
+++ gcc/testsuite/gcc.dg/pr77587.c      (revision 240232)
@@ -0,0 +1,14 @@
+/* PR target/77587 */
+/* { dg-do run } */
+/* { dg-require-weak-override "" } */
+/* { dg-additional-sources "pr77587a.c" } */
+
+void
+bar (long x, long y, long z)
+{
+  struct __attribute__((aligned (16))) S { long a, b, c, d; } s;
+  char *p = (char *) &s;
+  __asm ("" : "+r" (p));
+  if (((__UINTPTR_TYPE__) p) & 15)
+    __builtin_abort ();
+}
--- gcc/testsuite/gcc.dg/pr77587a.c     (revision 0)
+++ gcc/testsuite/gcc.dg/pr77587a.c     (revision 240232)
@@ -0,0 +1,23 @@
+/* PR target/77587 */
+/* { dg-do compile } */
+/* { dg-require-weak-override "" } */
+
+void
+foo (long x, long y, long z)
+{
+}
+
+void bar (long x, long y, long z) __attribute__ ((weak, alias ("foo")));
+
+void
+baz (long x, long y, long z)
+{
+  bar (0, 0, 0);
+}
+
+int
+main ()
+{
+  baz (0, 0, 0);
+  return 0;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-09-20  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/77624
        * builtins.c (fold_builtin_atomic_always_lock_free): Only look through
        cast to void * if the cast is from some other pointer type.

        * c-c++-common/pr77624-1.c: New test.
        * c-c++-common/pr77624-2.c: New test.

--- gcc/builtins.c      (revision 240262)
+++ gcc/builtins.c      (revision 240263)
@@ -5575,8 +5575,10 @@ fold_builtin_atomic_always_lock_free (tr
         end before anything else has a chance to look at it.  The pointer
         parameter at this point is usually cast to a void *, so check for that
         and look past the cast.  */
-      if (CONVERT_EXPR_P (arg1) && POINTER_TYPE_P (ttype)
-         && VOID_TYPE_P (TREE_TYPE (ttype)))
+      if (CONVERT_EXPR_P (arg1)
+         && POINTER_TYPE_P (ttype)
+         && VOID_TYPE_P (TREE_TYPE (ttype))
+         && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
        arg1 = TREE_OPERAND (arg1, 0);
 
       ttype = TREE_TYPE (arg1);
--- gcc/testsuite/c-c++-common/pr77624-1.c      (revision 0)
+++ gcc/testsuite/c-c++-common/pr77624-1.c      (revision 240263)
@@ -0,0 +1,14 @@
+/* PR middle-end/77624 */
+/* { dg-do compile } */
+
+int
+foo (int a)
+{
+  return __atomic_is_lock_free (2, a);         /* { dg-warning "pointer from 
integer" "" { target c } } */
+}                                              /* { dg-error "invalid 
conversion" "" { target c++ } 7 } */
+
+int
+bar (int a)
+{
+  return __atomic_always_lock_free (2, a);     /* { dg-warning "pointer from 
integer" "" { target c } } */
+}                                              /* { dg-error "invalid 
conversion" "" { target c++ } 13 } */
--- gcc/testsuite/c-c++-common/pr77624-2.c      (revision 0)
+++ gcc/testsuite/c-c++-common/pr77624-2.c      (revision 240263)
@@ -0,0 +1,26 @@
+/* PR middle-end/77624 */
+/* { dg-do compile } */
+
+void
+foo (int *a)
+{
+  double b = 0;
+  __atomic_is_lock_free (2, a, 2);     /* { dg-error "too many arguments" } */
+  __atomic_is_lock_free (2);           /* { dg-error "too few arguments" } */
+  __atomic_is_lock_free (2, b);                /* { dg-error "incompatible 
type" "" { target c } } */
+                                       /* { dg-message "expected" "" { target 
c } 10 } */
+                                       /* { dg-error "convert" "" { target c++ 
} 10 } */
+  __atomic_is_lock_free (2, 0);
+}
+
+void
+bar (int *a)
+{
+  double b = 0;
+  __atomic_always_lock_free (2, a, 2); /* { dg-error "too many arguments" } */
+  __atomic_always_lock_free (2);       /* { dg-error "too few arguments" } */
+  __atomic_always_lock_free (2, b);    /* { dg-error "incompatible type" "" { 
target c } } */
+                                       /* { dg-message "expected" "" { target 
c } 22 } */
+                                       /* { dg-error "convert" "" { target c++ 
} 22 } */
+  __atomic_always_lock_free (2, 0);
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-09-20  Jakub Jelinek  <ja...@redhat.com>

        PR c++/77637
        * parser.c (cp_parser_std_attribute_list): Reject ... without
        preceding attribute.

        * g++.dg/cpp0x/gen-attrs-62.C: New test.

--- gcc/cp/parser.c     (revision 240264)
+++ gcc/cp/parser.c     (revision 240265)
@@ -24221,8 +24221,12 @@ cp_parser_std_attribute_list (cp_parser
       if (token->type == CPP_ELLIPSIS)
        {
          cp_lexer_consume_token (parser->lexer);
-         TREE_VALUE (attribute)
-           = make_pack_expansion (TREE_VALUE (attribute));
+         if (attribute == NULL_TREE)
+           error_at (token->location,
+                     "expected attribute before %<...%>");
+         else
+           TREE_VALUE (attribute)
+             = make_pack_expansion (TREE_VALUE (attribute));
          token = cp_lexer_peek_token (parser->lexer);
        }
       if (token->type != CPP_COMMA)
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-62.C   (revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-62.C   (revision 240265)
@@ -0,0 +1,5 @@
+// PR c++/77637
+// { dg-do compile { target c++11 } }
+
+int [[...]] a;         // { dg-error "expected attribute before '...'" }
+int [[,,...]] b;       // { dg-error "expected attribute before '...'" }
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-09-20  Jakub Jelinek  <ja...@redhat.com>

        PR c++/77638
        * parser.c (cp_parser_template_declaration_after_parameter): For 2
        argument operator"" template set ok to false for
        parm == error_mark_node.

        * g++.dg/cpp0x/udlit-tmpl-arg-neg2.C: New test.

--- gcc/cp/parser.c     (revision 240265)
+++ gcc/cp/parser.c     (revision 240266)
@@ -25723,7 +25723,8 @@ cp_parser_template_declaration_after_par
              tree type = INNERMOST_TEMPLATE_PARMS (parm_type);
              tree parm_list = TREE_VEC_ELT (parameter_list, 1);
              tree parm = INNERMOST_TEMPLATE_PARMS (parm_list);
-             if (TREE_TYPE (parm) != TREE_TYPE (type)
+             if (parm == error_mark_node
+                 || TREE_TYPE (parm) != TREE_TYPE (type)
                  || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
                ok = false;
            }
--- gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg2.C    (revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg2.C    (revision 240266)
@@ -0,0 +1,7 @@
+// PR c++/77638
+// { dg-do compile { target c++11 } }
+
+template <T, T... U>           // { dg-error "'T' has not been declared" }
+int operator"" _foo ();                // { dg-error "has invalid parameter 
list" }
+template <T... U>              // { dg-error "'T' has not been declared" }
+int operator"" _bar ();                // { dg-error "has invalid parameter 
list" }
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-09-22  Jakub Jelinek  <ja...@redhat.com>

        PR fortran/77665
        * tree-inline.c (remap_gimple_stmt): Set has_simduid_loops
        for all IFN_GOMP_SIMD_* internal fns, not just for
        IFN_GOMP_SIMD_ORDERED_*.

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

--- gcc/tree-inline.c   (revision 240347)
+++ gcc/tree-inline.c   (revision 240348)
@@ -1644,11 +1644,19 @@ remap_gimple_stmt (gimple *stmt, copy_bo
            gimple_call_set_tail (call_stmt, false);
          if (gimple_call_from_thunk_p (call_stmt))
            gimple_call_set_from_thunk (call_stmt, false);
-         if (gimple_call_internal_p (call_stmt)
-             && IN_RANGE (gimple_call_internal_fn (call_stmt),
-                          IFN_GOMP_SIMD_ORDERED_START,
-                          IFN_GOMP_SIMD_ORDERED_END))
-           DECL_STRUCT_FUNCTION (id->dst_fn)->has_simduid_loops = true;
+         if (gimple_call_internal_p (call_stmt))
+           switch (gimple_call_internal_fn (call_stmt))
+             {
+             case IFN_GOMP_SIMD_LANE:
+             case IFN_GOMP_SIMD_VF:
+             case IFN_GOMP_SIMD_LAST_LANE:
+             case IFN_GOMP_SIMD_ORDERED_START:
+             case IFN_GOMP_SIMD_ORDERED_END:
+               DECL_STRUCT_FUNCTION (id->dst_fn)->has_simduid_loops = true;
+               break;
+             default:
+               break;
+             }
        }
 
       /* Remap the region numbers for __builtin_eh_{pointer,filter},
--- gcc/testsuite/gfortran.dg/gomp/pr77665.f90  (revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr77665.f90  (revision 240348)
@@ -0,0 +1,18 @@
+! PR fortran/77665
+! { dg-do compile }
+! { dg-additional-options "-O2" }
+
+program pr77665
+  type t
+    integer :: a = 0
+  end type
+  type(t) :: x
+  integer :: i
+  !$omp declare reduction (+:t: omp_out%a = omp_out%a + omp_in%a)
+  !$omp simd reduction(+:x)
+  do i = 1, 8
+    if (abs(i) < 5) call abort
+    x%a = x%a + 1
+  end do
+  print *, x%a
+end
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-09-27  Jakub Jelinek  <ja...@redhat.com>

        PR fortran/77666
        * trans-openmp.c (gfc_omp_private_outer_ref): Return true even for
        references to allocatable arrays.

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

--- gcc/fortran/trans-openmp.c  (revision 240521)
+++ gcc/fortran/trans-openmp.c  (revision 240522)
@@ -207,6 +207,9 @@ gfc_omp_private_outer_ref (tree decl)
 {
   tree type = TREE_TYPE (decl);
 
+  if (gfc_omp_privatize_by_reference (decl))
+    type = TREE_TYPE (type);
+
   if (GFC_DESCRIPTOR_TYPE_P (type)
       && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
     return true;
@@ -214,9 +217,6 @@ gfc_omp_private_outer_ref (tree decl)
   if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
     return true;
 
-  if (gfc_omp_privatize_by_reference (decl))
-    type = TREE_TYPE (type);
-
   if (gfc_has_alloc_comps (type, decl))
     return true;
 
--- gcc/testsuite/gfortran.dg/gomp/pr77666.f90  (revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr77666.f90  (revision 240522)
@@ -0,0 +1,26 @@
+! PR fortran/77666
+! { dg-do compile }
+
+subroutine foo(x)
+  interface
+    subroutine baz(x, y)
+      integer, allocatable :: x(:), y
+    end subroutine
+  end interface
+  integer, allocatable :: x(:), y
+!$omp parallel private(x, y)
+  call baz (x, y)
+!$omp end parallel
+end
+subroutine bar
+  interface
+    subroutine baz(x, y)
+      integer, allocatable :: x(:), y
+    end subroutine
+  end interface
+  integer, allocatable :: x(:), y
+  call baz (x, y)
+!$omp parallel private(x, y)
+  call baz (x, y)
+!$omp end parallel
+end
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-09-27  Jakub Jelinek  <ja...@redhat.com>

        PR c++/77722
        * cp-gimplify.c (cp_ubsan_maybe_instrument_return): Instrument also
        functions that have just a STATEMENT_LIST instead of BIND_EXPR, or
        BIND_EXPR with some statement rather than STATEMENT_LIST as body.

        * g++.dg/ubsan/return-4.C: New test.
        * g++.dg/ubsan/return-5.C: New test.
        * g++.dg/ubsan/return-6.C: New test.

--- gcc/cp/cp-gimplify.c        (revision 240554)
+++ gcc/cp/cp-gimplify.c        (revision 240555)
@@ -1570,14 +1570,11 @@ cp_ubsan_maybe_instrument_return (tree f
     }
   if (t == NULL_TREE)
     return;
-  t = DECL_SAVED_TREE (fndecl);
-  if (TREE_CODE (t) == BIND_EXPR
-      && TREE_CODE (BIND_EXPR_BODY (t)) == STATEMENT_LIST)
-    {
-      tree_stmt_iterator i = tsi_last (BIND_EXPR_BODY (t));
-      t = ubsan_instrument_return (DECL_SOURCE_LOCATION (fndecl));
-      tsi_link_after (&i, t, TSI_NEW_STMT);
-    }
+  tree *p = &DECL_SAVED_TREE (fndecl);
+  if (TREE_CODE (*p) == BIND_EXPR)
+    p = &BIND_EXPR_BODY (*p);
+  t = ubsan_instrument_return (DECL_SOURCE_LOCATION (fndecl));
+  append_to_statement_list (t, p);
 }
 
 void
--- gcc/testsuite/g++.dg/ubsan/return-4.C       (revision 0)
+++ gcc/testsuite/g++.dg/ubsan/return-4.C       (revision 240555)
@@ -0,0 +1,18 @@
+// PR c++/77722
+// { dg-do run }
+// { dg-options "-fsanitize=return -w" }
+// { dg-shouldfail "ubsan" }
+
+int
+foo ()
+{
+}
+
+int
+main ()
+{
+  foo ();
+  return 0;
+}
+
+// { dg-output "execution reached the end of a value-returning function 
without returning a value" }
--- gcc/testsuite/g++.dg/ubsan/return-5.C       (revision 0)
+++ gcc/testsuite/g++.dg/ubsan/return-5.C       (revision 240555)
@@ -0,0 +1,19 @@
+// PR c++/77722
+// { dg-do run }
+// { dg-options "-fsanitize=return -w" }
+// { dg-shouldfail "ubsan" }
+
+int
+foo ()
+{
+  int a = 5;
+}
+
+int
+main ()
+{
+  foo ();
+  return 0;
+}
+
+// { dg-output "execution reached the end of a value-returning function 
without returning a value" }
--- gcc/testsuite/g++.dg/ubsan/return-6.C       (revision 0)
+++ gcc/testsuite/g++.dg/ubsan/return-6.C       (revision 240555)
@@ -0,0 +1,20 @@
+// PR c++/77722
+// { dg-do run }
+// { dg-options "-fsanitize=return -w" }
+// { dg-shouldfail "ubsan" }
+
+int
+foo ()
+{
+  int a = 5;
+  int b = 5;
+}
+
+int
+main ()
+{
+  foo ();
+  return 0;
+}
+
+// { dg-output "execution reached the end of a value-returning function 
without returning a value" }
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-09-28  Jakub Jelinek  <ja...@redhat.com>

        PR c++/77467
        * constexpr.c (enum constexpr_switch_state): New.
        (struct constexpr_ctx): Add css_state field.
        (label_matches): Add CTX and STMT arguments, remove I and
        DEFAULT_LABEL.  For CASE_LABEL_EXPR assert ctx->css_state != NULL,
        handle default labels according to css_state.
        (cxx_eval_statement_list): Remove statement skipping, label_matches
        and default_label handling code.
        (cxx_eval_loop_expr): Exit after first iteration even if
        switches (jump_target).
        (cxx_eval_switch_expr): Set up css_state field in ctx, if default
        label has been seen in the body, but no cases matched, evaluate
        the body second time.
        (cxx_eval_constant_expression): Handle stmt skipping and label_matches
        here.  Handle PREDICT_EXPR.  For MODIFY_EXPR or INIT_EXPR, assert
        statement is not skipped.  For COND_EXPR during skipping, don't
        evaluate condition, just the then block and if still skipping at the
        end also the else block.
        (cxx_eval_outermost_constant_expr): Adjust constexpr_ctx initializer.
        (is_sub_constant_expr): Likewise.

        * g++.dg/cpp1y/constexpr-77467.C: New test.

--- gcc/cp/constexpr.c  (revision 240590)
+++ gcc/cp/constexpr.c  (revision 240591)
@@ -900,6 +900,18 @@ struct constexpr_call_hasher : ggc_ptr_h
   static bool equal (constexpr_call *, constexpr_call *);
 };
 
+enum constexpr_switch_state {
+  /* Used when processing a switch for the first time by cxx_eval_switch_expr
+     and default: label for that switch has not been seen yet.  */
+  css_default_not_seen,
+  /* Used when processing a switch for the first time by cxx_eval_switch_expr
+     and default: label for that switch has been seen already.  */
+  css_default_seen,
+  /* Used when processing a switch for the second time by
+     cxx_eval_switch_expr, where default: label should match.  */
+  css_default_processing
+};
+
 /* The constexpr expansion context.  CALL is the current function
    expansion, CTOR is the current aggregate initializer, OBJECT is the
    object being initialized by CTOR, either a VAR_DECL or a _REF.  VALUES
@@ -919,6 +931,8 @@ struct constexpr_ctx {
   tree ctor;
   /* The object we're building the CONSTRUCTOR for.  */
   tree object;
+  /* If inside SWITCH_EXPR.  */
+  constexpr_switch_state *css_state;
   /* Whether we should error on a non-constant expression or fail quietly.  */
   bool quiet;
   /* Whether we are strictly conforming to constant expression rules or
@@ -3484,14 +3498,12 @@ switches (tree *jump_target)
 }
 
 /* Subroutine of cxx_eval_statement_list.  Determine whether the statement
-   at I matches *jump_target.  If we're looking for a case label and we see
-   the default label, copy I into DEFAULT_LABEL.  */
+   STMT matches *jump_target.  If we're looking for a case label and we see
+   the default label, note it in ctx->css_state.  */
 
 static bool
-label_matches (tree *jump_target, tree_stmt_iterator i,
-              tree_stmt_iterator& default_label)
+label_matches (const constexpr_ctx *ctx, tree *jump_target, tree stmt)
 {
-  tree stmt = tsi_stmt (i);
   switch (TREE_CODE (*jump_target))
     {
     case LABEL_DECL:
@@ -3503,8 +3515,18 @@ label_matches (tree *jump_target, tree_s
     case INTEGER_CST:
       if (TREE_CODE (stmt) == CASE_LABEL_EXPR)
        {
+         gcc_assert (ctx->css_state != NULL);
          if (!CASE_LOW (stmt))
-           default_label = i;
+           {
+             /* default: should appear just once in a SWITCH_EXPR
+                body (excluding nested SWITCH_EXPR).  */
+             gcc_assert (*ctx->css_state != css_default_seen);
+             /* When evaluating SWITCH_EXPR body for the second time,
+                return true for the default: label.  */
+             if (*ctx->css_state == css_default_processing)
+               return true;
+             *ctx->css_state = css_default_seen;
+           }
          else if (CASE_HIGH (stmt))
            {
              if (tree_int_cst_le (CASE_LOW (stmt), *jump_target)
@@ -3531,7 +3553,6 @@ cxx_eval_statement_list (const constexpr
                         tree *jump_target)
 {
   tree_stmt_iterator i;
-  tree_stmt_iterator default_label = tree_stmt_iterator();
   tree local_target;
   /* In a statement-expression we want to return the last value.  */
   tree r = NULL_TREE;
@@ -3542,18 +3563,7 @@ cxx_eval_statement_list (const constexpr
     }
   for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
     {
-    reenter:
       tree stmt = tsi_stmt (i);
-      if (*jump_target)
-       {
-         if (TREE_CODE (stmt) == STATEMENT_LIST)
-           /* The label we want might be inside.  */;
-         else if (label_matches (jump_target, i, default_label))
-           /* Found it.  */
-           *jump_target = NULL_TREE;
-         else
-           continue;
-       }
       r = cxx_eval_constant_expression (ctx, stmt, false,
                                        non_constant_p, overflow_p,
                                        jump_target);
@@ -3562,12 +3572,6 @@ cxx_eval_statement_list (const constexpr
       if (returns (jump_target) || breaks (jump_target))
        break;
     }
-  if (switches (jump_target) && !tsi_end_p (default_label))
-    {
-      i = default_label;
-      *jump_target = NULL_TREE;
-      goto reenter;
-    }
   return r;
 }
 
@@ -3606,7 +3610,10 @@ cxx_eval_loop_expr (const constexpr_ctx
          break;
        }
     }
-  while (!returns (jump_target) && !breaks (jump_target) && !*non_constant_p);
+  while (!returns (jump_target)
+        && !breaks (jump_target)
+        && !switches (jump_target)
+        && !*non_constant_p);
 
   if (breaks (jump_target))
     *jump_target = NULL_TREE;
@@ -3629,8 +3636,20 @@ cxx_eval_switch_expr (const constexpr_ct
   *jump_target = cond;
 
   tree body = TREE_OPERAND (t, 1);
-  cxx_eval_statement_list (ctx, body,
-                          non_constant_p, overflow_p, jump_target);
+  constexpr_ctx new_ctx = *ctx;
+  constexpr_switch_state css = css_default_not_seen;
+  new_ctx.css_state = &css;
+  cxx_eval_constant_expression (&new_ctx, body, false,
+                               non_constant_p, overflow_p, jump_target);
+  if (switches (jump_target) && css == css_default_seen)
+    {
+      /* If the SWITCH_EXPR body has default: label, process it once again,
+        this time instructing label_matches to return true for default:
+        label on switches (jump_target).  */
+      css = css_default_processing;
+      cxx_eval_constant_expression (&new_ctx, body, false,
+                                   non_constant_p, overflow_p, jump_target);
+    }
   if (breaks (jump_target) || switches (jump_target))
     *jump_target = NULL_TREE;
   return NULL_TREE;
@@ -3650,6 +3669,27 @@ cxx_eval_constant_expression (const cons
   constexpr_ctx new_ctx;
   tree r = t;
 
+  if (jump_target && *jump_target)
+    {
+      /* If we are jumping, ignore all statements/expressions except those
+        that could have LABEL_EXPR or CASE_LABEL_EXPR in their bodies.  */
+      switch (TREE_CODE (t))
+       {
+       case BIND_EXPR:
+       case STATEMENT_LIST:
+       case LOOP_EXPR:
+       case COND_EXPR:
+         break;
+       case LABEL_EXPR:
+       case CASE_LABEL_EXPR:
+         if (label_matches (ctx, jump_target, t))
+           /* Found it.  */
+           *jump_target = NULL_TREE;
+         return NULL_TREE;
+       default:
+         return NULL_TREE;
+       }
+    }
   if (t == error_mark_node)
     {
       *non_constant_p = true;
@@ -3730,6 +3770,7 @@ cxx_eval_constant_expression (const cons
     case LABEL_DECL:
     case LABEL_EXPR:
     case CASE_LABEL_EXPR:
+    case PREDICT_EXPR:
       return t;
 
     case PARM_DECL:
@@ -3835,6 +3876,7 @@ cxx_eval_constant_expression (const cons
 
     case INIT_EXPR:
     case MODIFY_EXPR:
+      gcc_assert (jump_target == NULL || *jump_target == NULL_TREE);
       r = cxx_eval_store_expression (ctx, t, lval,
                                     non_constant_p, overflow_p);
       break;
@@ -4065,6 +4107,22 @@ cxx_eval_constant_expression (const cons
       break;
 
     case COND_EXPR:
+      if (jump_target && *jump_target)
+       {
+         /* When jumping to a label, the label might be either in the
+            then or else blocks, so process then block first in skipping
+            mode first, and if we are still in the skipping mode at its end,
+            process the else block too.  */
+         r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
+                                           lval, non_constant_p, overflow_p,
+                                           jump_target);
+         if (*jump_target)
+           r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2),
+                                             lval, non_constant_p, overflow_p,
+                                             jump_target);
+         break;
+       }
+      /* FALLTHRU */
     case VEC_COND_EXPR:
       r = cxx_eval_conditional_expression (ctx, t, lval,
                                           non_constant_p, overflow_p,
@@ -4340,7 +4398,7 @@ cxx_eval_outermost_constant_expr (tree t
   bool overflow_p = false;
   hash_map<tree,tree> map;
 
-  constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL,
+  constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, NULL,
                        allow_non_constant, strict };
 
   tree type = initialized_type (t);
@@ -4460,7 +4518,7 @@ is_sub_constant_expr (tree t)
   bool overflow_p = false;
   hash_map <tree, tree> map;
 
-  constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, true, true };
+  constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, NULL, true, true };
 
   cxx_eval_constant_expression (&ctx, t, false, &non_constant_p,
                                &overflow_p);
--- gcc/testsuite/g++.dg/cpp1y/constexpr-77467.C        (revision 0)
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-77467.C        (revision 240591)
@@ -0,0 +1,128 @@
+// PR c++/77467
+// { dg-do compile { target c++14 } }
+
+constexpr int
+foo (const int x, const unsigned n) noexcept
+{
+  switch (n)
+    {
+    case 0:
+      return 1;
+    case 1:
+      return x;
+    default:
+      const auto m = (n >> 1);
+      const auto y = foo (x, m);
+      return ((m << 1) == n) ? y * y : x * y * y;
+    }
+}
+
+static_assert (foo (3, 2) == 9, "");
+static_assert (foo (2, 3) == 8, "");
+
+constexpr int
+bar (int x)
+{
+  int a = x;
+  switch (x)
+    a = x + 1;
+  return a;
+}
+
+static_assert (bar (0) == 0, "");
+static_assert (bar (1) == 1, "");
+
+constexpr int
+baz (const int x, int y) noexcept
+{
+  switch (x)
+    {
+    case 0:
+      return 1;
+    case 1:
+      return x;
+    case 2:
+      if ((y += 2) == 0)
+       {
+       case 3:
+         y += 4;
+         break;
+       }
+      else
+       {
+       case 4:
+         y += 8;
+         break;
+       }
+      break;
+    case 5:
+      for (y = 0; y < 3; y++)
+       {
+       case 7:
+         if (y == -4)
+           y += 3;
+         if (y == -3)
+           continue;
+         if (y == -2)
+           {
+             y += 18;
+             break;
+           }
+         if (y == 2)
+           {
+           case 6:
+             y += 12;
+           default:
+             y++;
+             break;
+           }
+       }
+      break;
+    case -1:
+    case -2:
+      switch (y)
+       {
+       case 19:
+         y += 2;
+         break;
+       case 20:
+         y += 3;
+         if (x == 2)
+           case 21:;
+         y += 2;
+         if (x == 3)
+           default:;
+         y += 4;
+         break;
+       }
+      return x + y + 1;
+    }
+  return x + y;
+}
+
+static_assert (baz (0, 7) == 1, "");
+static_assert (baz (1, 7) == 1, "");
+static_assert (baz (2, -2) == 6, "");
+static_assert (baz (2, 0) == 12, "");
+static_assert (baz (3, 1) == 8, "");
+static_assert (baz (4, 2) == 14, "");
+static_assert (baz (5, -20) == 20, "");
+static_assert (baz (6, 5) == 24, "");
+static_assert (baz (7, -5) == 22, "");
+static_assert (baz (7, -4) == 22, "");
+static_assert (baz (7, -3) == 23, "");
+static_assert (baz (7, -2) == 23, "");
+static_assert (baz (7, -1) == 22, "");
+static_assert (baz (7, 0) == 22, "");
+static_assert (baz (7, 2) == 22, "");
+static_assert (baz (7, 6) == 14, "");
+static_assert (baz (8, 9) == 18, "");
+static_assert (baz (8, -2) == 7, "");
+static_assert (baz (-1, 19) == 21, "");
+static_assert (baz (-1, 20) == 29, "");
+static_assert (baz (-1, 21) == 27, "");
+static_assert (baz (-1, 5) == 9, "");
+static_assert (baz (-2, 19) == 20, "");
+static_assert (baz (-2, 20) == 28, "");
+static_assert (baz (-2, 21) == 26, "");
+static_assert (baz (-2, 5) == 8, "");
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-10-05  Jakub Jelinek  <ja...@redhat.com>

        PR sanitizer/66343
        * ubsan.c (ubsan_ids): New GTY(()) array.
        (ubsan_type_descriptor, ubsan_create_data): Use ubsan_ids
        instead of static local counters.

        * gcc.dg/pch/pr66343-1.c: New test.
        * gcc.dg/pch/pr66343-1.hs: New file.
        * gcc.dg/pch/pr66343-2.c: New test.
        * gcc.dg/pch/pr66343-2.hs: New file.

--- gcc/ubsan.c (revision 240802)
+++ gcc/ubsan.c (revision 240803)
@@ -314,6 +314,10 @@ get_ubsan_type_info_for_type (tree type)
     return 0;
 }
 
+/* Counters for internal labels.  ubsan_ids[0] for Lubsan_type,
+   ubsan_ids[1] for Lubsan_data labels.  */
+static GTY(()) unsigned int ubsan_ids[2];
+
 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
    descriptor.  It first looks into the hash table; if not found,
    create the VAR_DECL, put it into the hash table and return the
@@ -461,10 +465,9 @@ ubsan_type_descriptor (tree type, enum u
   TREE_STATIC (str) = 1;
 
   char tmp_name[32];
-  static unsigned int type_var_id_num;
-  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
+  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", ubsan_ids[0]++);
   decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
-                         dtype);
+                    dtype);
   TREE_STATIC (decl) = 1;
   TREE_PUBLIC (decl) = 0;
   DECL_ARTIFICIAL (decl) = 1;
@@ -564,8 +567,7 @@ ubsan_create_data (const char *name, int
 
   /* Now, fill in the type.  */
   char tmp_name[32];
-  static unsigned int ubsan_var_id_num;
-  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
+  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_ids[1]++);
   tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
                         ret);
   TREE_STATIC (var) = 1;
--- gcc/testsuite/gcc.dg/pch/pr66343-1.c        (revision 0)
+++ gcc/testsuite/gcc.dg/pch/pr66343-1.c        (revision 240803)
@@ -0,0 +1,15 @@
+/* PR sanitizer/66343 */
+/* { dg-do assemble } */
+/* { dg-options "-fsanitize=undefined" } */
+
+#include "pr66343-1.h"
+
+void
+bar (int a, int b)
+{
+  a / b;
+}
+
+/* Hack to turn off PCH assembly comparison, as it is incompatible
+   with dg-do assemble.  The target condition will be always false.  */
+/* { dg-error "" "" { target { lp64 && { ! lp64 } } } } */
--- gcc/testsuite/gcc.dg/pch/pr66343-1.hs       (revision 0)
+++ gcc/testsuite/gcc.dg/pch/pr66343-1.hs       (revision 240803)
@@ -0,0 +1,8 @@
+/* PR sanitizer/66343 */
+/* { dg-options "-fsanitize=undefined" } */
+
+void
+foo (int a, int b)
+{
+  a / b;
+}
--- gcc/testsuite/gcc.dg/pch/pr66343-2.c        (revision 0)
+++ gcc/testsuite/gcc.dg/pch/pr66343-2.c        (revision 240803)
@@ -0,0 +1,10 @@
+/* PR sanitizer/66343 */
+/* { dg-options "-fsanitize=undefined" } */
+
+#include "pr66343-2.h"
+
+void
+bar (int a, int b)
+{
+  a / b;
+}
--- gcc/testsuite/gcc.dg/pch/pr66343-2.hs       (revision 0)
+++ gcc/testsuite/gcc.dg/pch/pr66343-2.hs       (revision 240803)
@@ -0,0 +1,8 @@
+/* PR sanitizer/66343 */
+/* { dg-options "-fsanitize=undefined" } */
+
+void
+foo (int a, int b)
+{
+  a / b;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-10-26  Jakub Jelinek  <ja...@redhat.com>
                    Martin Liska  <mli...@suse.cz>

        PR fortran/77973
        * gimplify.c (gimplify_adjust_omp_clauses_1): For all added map
        clauses with OMP_CLAUSE_SIZE being a decl, call omp_notice_variable
        on outer context if any.

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

--- gcc/gimplify.c      (revision 241580)
+++ gcc/gimplify.c      (revision 241581)
@@ -8421,9 +8421,10 @@ gimplify_adjust_omp_clauses_1 (splay_tre
       && omp_shared_to_firstprivate_optimizable_decl_p (decl))
     omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
 
+  tree chain = *list_p;
   clause = build_omp_clause (input_location, code);
   OMP_CLAUSE_DECL (clause) = decl;
-  OMP_CLAUSE_CHAIN (clause) = *list_p;
+  OMP_CLAUSE_CHAIN (clause) = chain;
   if (private_debug)
     OMP_CLAUSE_PRIVATE_DEBUG (clause) = 1;
   else if (code == OMP_CLAUSE_PRIVATE && (flags & GOVD_PRIVATE_OUTER_REF))
@@ -8450,7 +8451,7 @@ gimplify_adjust_omp_clauses_1 (splay_tre
       OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_ALLOC);
       OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (clause) = 1;
       OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
-      OMP_CLAUSE_CHAIN (nc) = *list_p;
+      OMP_CLAUSE_CHAIN (nc) = chain;
       OMP_CLAUSE_CHAIN (clause) = nc;
       struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
       gimplify_omp_ctxp = ctx->outer_context;
@@ -8520,7 +8521,7 @@ gimplify_adjust_omp_clauses_1 (splay_tre
       tree nc = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
       OMP_CLAUSE_DECL (nc) = decl;
       OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (nc) = 1;
-      OMP_CLAUSE_CHAIN (nc) = *list_p;
+      OMP_CLAUSE_CHAIN (nc) = chain;
       OMP_CLAUSE_CHAIN (clause) = nc;
       struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
       gimplify_omp_ctxp = ctx->outer_context;
@@ -8531,6 +8532,12 @@ gimplify_adjust_omp_clauses_1 (splay_tre
   struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
   gimplify_omp_ctxp = ctx->outer_context;
   lang_hooks.decls.omp_finish_clause (clause, pre_p);
+  if (gimplify_omp_ctxp)
+    for (; clause != chain; clause = OMP_CLAUSE_CHAIN (clause))
+      if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
+         && DECL_P (OMP_CLAUSE_SIZE (clause)))
+       omp_notice_variable (gimplify_omp_ctxp, OMP_CLAUSE_SIZE (clause),
+                            true);
   gimplify_omp_ctxp = ctx;
   return 0;
 }
--- gcc/testsuite/gfortran.dg/gomp/pr77973.f90  (revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr77973.f90  (revision 241581)
@@ -0,0 +1,12 @@
+! PR fortran/77973
+! { dg-do compile }
+
+subroutine s(x)
+  integer :: x(:)
+  integer :: i
+!$omp parallel
+!$omp target
+  x(1) = 1
+!$omp end target
+!$omp end parallel
+end
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-10-27  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/78025
        * omp-simd-clone.c (simd_clone_adjust): Handle noreturn declare simd
        functions.

        * g++.dg/gomp/declare-simd-7.C: New test.

--- gcc/omp-simd-clone.c        (revision 241627)
+++ gcc/omp-simd-clone.c        (revision 241628)
@@ -1107,7 +1107,7 @@ simd_clone_adjust (struct cgraph_node *n
      return values accordingly.  */
   tree iter = create_tmp_var (unsigned_type_node, "iter");
   tree iter1 = make_ssa_name (iter);
-  tree iter2 = make_ssa_name (iter);
+  tree iter2 = NULL_TREE;
   ipa_simd_modify_function_body (node, adjustments, retval, iter1);
   adjustments.release ();
 
@@ -1121,39 +1121,57 @@ simd_clone_adjust (struct cgraph_node *n
 
   pop_gimplify_context (NULL);
 
+  gimple *g;
+  basic_block incr_bb = NULL;
+  struct loop *loop = NULL;
+
   /* Create a new BB right before the original exit BB, to hold the
      iteration increment and the condition/branch.  */
-  basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
-  basic_block incr_bb = create_empty_bb (orig_exit);
-  add_bb_to_loop (incr_bb, body_bb->loop_father);
-  /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
-     flag.  Set it now to be a FALLTHRU_EDGE.  */
-  gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
-  EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
-  for (unsigned i = 0;
-       i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
+  if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds))
+    {
+      basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
+      incr_bb = create_empty_bb (orig_exit);
+      add_bb_to_loop (incr_bb, body_bb->loop_father);
+      /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
+        flag.  Set it now to be a FALLTHRU_EDGE.  */
+      gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
+      EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
+      for (unsigned i = 0;
+          i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
+       {
+         edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
+         redirect_edge_succ (e, incr_bb);
+       }
+    }
+  else if (node->simdclone->inbranch)
+    {
+      incr_bb = create_empty_bb (entry_bb);
+      add_bb_to_loop (incr_bb, body_bb->loop_father);
+    }
+
+  if (incr_bb)
     {
-      edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
-      redirect_edge_succ (e, incr_bb);
+      edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+      e->probability = REG_BR_PROB_BASE;
+      gsi = gsi_last_bb (incr_bb);
+      iter2 = make_ssa_name (iter);
+      g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
+                              build_int_cst (unsigned_type_node, 1));
+      gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+
+      /* Mostly annotate the loop for the vectorizer (the rest is done
+        below).  */
+      loop = alloc_loop ();
+      cfun->has_force_vectorize_loops = true;
+      loop->safelen = node->simdclone->simdlen;
+      loop->force_vectorize = true;
+      loop->header = body_bb;
     }
-  edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
-  e->probability = REG_BR_PROB_BASE;
-  gsi = gsi_last_bb (incr_bb);
-  gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
-                                  build_int_cst (unsigned_type_node, 1));
-  gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
-
-  /* Mostly annotate the loop for the vectorizer (the rest is done below).  */
-  struct loop *loop = alloc_loop ();
-  cfun->has_force_vectorize_loops = true;
-  loop->safelen = node->simdclone->simdlen;
-  loop->force_vectorize = true;
-  loop->header = body_bb;
 
   /* Branch around the body if the mask applies.  */
   if (node->simdclone->inbranch)
     {
-      gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
+      gsi = gsi_last_bb (loop->header);
       tree mask_array
        = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
       tree mask;
@@ -1227,50 +1245,59 @@ simd_clone_adjust (struct cgraph_node *n
       FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
     }
 
+  basic_block latch_bb = NULL;
+  basic_block new_exit_bb = NULL;
+
   /* Generate the condition.  */
-  g = gimple_build_cond (LT_EXPR,
-                        iter2,
-                        build_int_cst (unsigned_type_node,
-                                       node->simdclone->simdlen),
-                        NULL, NULL);
-  gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
-  e = split_block (incr_bb, gsi_stmt (gsi));
-  basic_block latch_bb = e->dest;
-  basic_block new_exit_bb;
-  new_exit_bb = split_block_after_labels (latch_bb)->dest;
-  loop->latch = latch_bb;
-
-  redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
-
-  make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
-  /* The successor of incr_bb is already pointing to latch_bb; just
-     change the flags.
-     make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE);  */
-  FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
+  if (incr_bb)
+    {
+      gsi = gsi_last_bb (incr_bb);
+      g = gimple_build_cond (LT_EXPR, iter2,
+                            build_int_cst (unsigned_type_node,
+                                           node->simdclone->simdlen),
+                            NULL, NULL);
+      gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+      edge e = split_block (incr_bb, gsi_stmt (gsi));
+      latch_bb = e->dest;
+      new_exit_bb = split_block_after_labels (latch_bb)->dest;
+      loop->latch = latch_bb;
+
+      redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
+
+      make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
+      /* The successor of incr_bb is already pointing to latch_bb; just
+        change the flags.
+        make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE);  */
+      FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
+    }
 
   gphi *phi = create_phi_node (iter1, body_bb);
   edge preheader_edge = find_edge (entry_bb, body_bb);
-  edge latch_edge = single_succ_edge (latch_bb);
+  edge latch_edge = NULL;
   add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
               UNKNOWN_LOCATION);
-  add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
-
-  /* Generate the new return.  */
-  gsi = gsi_last_bb (new_exit_bb);
-  if (retval
-      && TREE_CODE (retval) == VIEW_CONVERT_EXPR
-      && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
-    retval = TREE_OPERAND (retval, 0);
-  else if (retval)
+  if (incr_bb)
     {
-      retval = build1 (VIEW_CONVERT_EXPR,
-                      TREE_TYPE (TREE_TYPE (node->decl)),
-                      retval);
-      retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
-                                        false, GSI_CONTINUE_LINKING);
+      latch_edge = single_succ_edge (latch_bb);
+      add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
+
+      /* Generate the new return.  */
+      gsi = gsi_last_bb (new_exit_bb);
+      if (retval
+         && TREE_CODE (retval) == VIEW_CONVERT_EXPR
+         && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
+       retval = TREE_OPERAND (retval, 0);
+      else if (retval)
+       {
+         retval = build1 (VIEW_CONVERT_EXPR,
+                          TREE_TYPE (TREE_TYPE (node->decl)),
+                          retval);
+         retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
+                                            false, GSI_CONTINUE_LINKING);
+       }
+      g = gimple_build_return (retval);
+      gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
     }
-  g = gimple_build_return (retval);
-  gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
 
   /* Handle aligned clauses by replacing default defs of the aligned
      uniform args with __builtin_assume_aligned (arg_N(D), alignment)
@@ -1386,7 +1413,8 @@ simd_clone_adjust (struct cgraph_node *n
          {
            def = make_ssa_name (TREE_TYPE (orig_arg));
            iter1 = make_ssa_name (TREE_TYPE (orig_arg));
-           iter2 = make_ssa_name (TREE_TYPE (orig_arg));
+           if (incr_bb)
+             iter2 = make_ssa_name (TREE_TYPE (orig_arg));
            gsi = gsi_after_labels (entry_bb);
            g = gimple_build_assign (def, orig_arg);
            gsi_insert_before (&gsi, g, GSI_NEW_STMT);
@@ -1399,23 +1427,27 @@ simd_clone_adjust (struct cgraph_node *n
            else
              {
                iter1 = make_ssa_name (orig_arg);
-               iter2 = make_ssa_name (orig_arg);
+               if (incr_bb)
+                 iter2 = make_ssa_name (orig_arg);
              }
          }
        if (def)
          {
            phi = create_phi_node (iter1, body_bb);
            add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
-           add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
-           enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
-                                 ? PLUS_EXPR : POINTER_PLUS_EXPR;
-           tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
-                          ? TREE_TYPE (orig_arg) : sizetype;
-           tree addcst = simd_clone_linear_addend (node, i, addtype,
-                                                   entry_bb);
-           gsi = gsi_last_bb (incr_bb);
-           g = gimple_build_assign (iter2, code, iter1, addcst);
-           gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+           if (incr_bb)
+             {
+               add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
+               enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
+                                     ? PLUS_EXPR : POINTER_PLUS_EXPR;
+               tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
+                              ? TREE_TYPE (orig_arg) : sizetype;
+               tree addcst = simd_clone_linear_addend (node, i, addtype,
+                                                       entry_bb);
+               gsi = gsi_last_bb (incr_bb);
+               g = gimple_build_assign (iter2, code, iter1, addcst);
+               gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+             }
 
            imm_use_iterator iter;
            use_operand_p use_p;
@@ -1448,10 +1480,11 @@ simd_clone_adjust (struct cgraph_node *n
          {
            tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
            iter1 = make_ssa_name (orig_arg);
-           iter2 = make_ssa_name (orig_arg);
+           if (incr_bb)
+             iter2 = make_ssa_name (orig_arg);
            tree iter3 = make_ssa_name (rtype);
            tree iter4 = make_ssa_name (rtype);
-           tree iter5 = make_ssa_name (rtype);
+           tree iter5 = incr_bb ? make_ssa_name (rtype) : NULL_TREE;
            gsi = gsi_after_labels (entry_bb);
            gimple *load
              = gimple_build_assign (iter3, build_simple_mem_ref (def));
@@ -1462,24 +1495,30 @@ simd_clone_adjust (struct cgraph_node *n
            tree ptr = build_fold_addr_expr (array);
            phi = create_phi_node (iter1, body_bb);
            add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
-           add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
-           g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
-                                    TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
-           gsi = gsi_last_bb (incr_bb);
-           gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+           if (incr_bb)
+             {
+               add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
+               g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
+                                        TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
+               gsi = gsi_last_bb (incr_bb);
+               gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+             }
 
            phi = create_phi_node (iter4, body_bb);
            add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
-           add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
-           enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
-                                 ? PLUS_EXPR : POINTER_PLUS_EXPR;
-           tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
-                          ? TREE_TYPE (iter3) : sizetype;
-           tree addcst = simd_clone_linear_addend (node, i, addtype,
-                                                   entry_bb);
-           g = gimple_build_assign (iter5, code, iter4, addcst);
-           gsi = gsi_last_bb (incr_bb);
-           gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+           if (incr_bb)
+             {
+               add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
+               enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
+                                     ? PLUS_EXPR : POINTER_PLUS_EXPR;
+               tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
+                              ? TREE_TYPE (iter3) : sizetype;
+               tree addcst = simd_clone_linear_addend (node, i, addtype,
+                                                       entry_bb);
+               g = gimple_build_assign (iter5, code, iter4, addcst);
+               gsi = gsi_last_bb (incr_bb);
+               gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+             }
 
            g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
            gsi = gsi_after_labels (body_bb);
@@ -1495,7 +1534,7 @@ simd_clone_adjust (struct cgraph_node *n
                FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
                  SET_USE (use_p, iter1);
 
-           if (!TYPE_READONLY (rtype))
+           if (!TYPE_READONLY (rtype) && incr_bb)
              {
                tree v = make_ssa_name (rtype);
                tree aref = build4 (ARRAY_REF, rtype, array,
@@ -1511,7 +1550,8 @@ simd_clone_adjust (struct cgraph_node *n
       }
 
   calculate_dominance_info (CDI_DOMINATORS);
-  add_loop (loop, loop->header->loop_father);
+  if (loop)
+    add_loop (loop, loop->header->loop_father);
   update_ssa (TODO_update_ssa);
 
   pop_cfun ();
--- gcc/testsuite/g++.dg/gomp/declare-simd-7.C  (revision 0)
+++ gcc/testsuite/g++.dg/gomp/declare-simd-7.C  (revision 241628)
@@ -0,0 +1,50 @@
+// PR middle-end/78025
+// { dg-do compile }
+// { dg-additional-options "-O2" }
+
+struct S { S (); ~S (); };
+
+int bar1 (int, int, float &, S &, int *, int, int &, int &, int &, int &, int 
&);
+int bar2 (int, int, float &, S &, int *, int, int &, int &, int &, int &, int 
&);
+int bar3 (int, int, float &, S &, int *, int, int &, int &, int &, int &, int 
&) __attribute__((noreturn));
+int bar4 (int, int, float &, S &, int *, int, int &, int &, int &, int &, int 
&) __attribute__((noreturn));
+
+#pragma omp declare simd notinbranch uniform (b, c, d, e) aligned (e : 16) \
+                   linear (f : 2) linear (ref (g) : 1) \
+                   linear (val (h) : 1) linear (uval (i) : 1) \
+                   linear (k : 4)
+int
+foo1 (int a, int b, float c, S d, int *e, int f, int &g, int &h, int &i, int 
j, int k)
+{
+  return bar1 (a, b, c, d, e, f, g, h, i, j, k);
+}
+
+#pragma omp declare simd inbranch uniform (b, c, d, e) aligned (e : 16) \
+                   linear (f : 2) linear (ref (g) : 1) \
+                   linear (val (h) : 1) linear (uval (i) : 1) \
+                   linear (k : 4)
+int
+foo2 (int a, int b, float c, S d, int *e, int f, int &g, int &h, int &i, int 
j, int k)
+{
+  return bar2 (a, b, c, d, e, f, g, h, i, j, k);
+}
+
+#pragma omp declare simd notinbranch uniform (b, c, d, e) aligned (e : 16) \
+                   linear (f : 2) linear (ref (g) : 1) \
+                   linear (val (h) : 1) linear (uval (i) : 1) \
+                   linear (k : 4)
+int
+foo3 (int a, int b, float c, S d, int *e, int f, int &g, int &h, int &i, int 
j, int k)
+{
+  return bar3 (a, b, c, d, e, f, g, h, i, j, k);
+}
+
+#pragma omp declare simd inbranch uniform (b, c, d, e) aligned (e : 16) \
+                   linear (f : 2) linear (ref (g) : 1) \
+                   linear (val (h) : 1) linear (uval (i) : 1) \
+                   linear (k : 4)
+int
+foo4 (int a, int b, float c, S d, int *e, int f, int &g, int &h, int &i, int 
j, int k)
+{
+  return bar4 (a, b, c, d, e, f, g, h, i, j, k);
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-10-28  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/77919
        * expr.c (expand_expr_real_1) <normal_inner_ref>: Force CONCAT into
        MEM if mode1 is not a complex mode.

        * g++.dg/torture/pr77919.C: New test.

--- gcc/expr.c  (revision 241641)
+++ gcc/expr.c  (revision 241642)
@@ -10421,7 +10421,8 @@ expand_expr_real_1 (tree exp, rtx target
        if (GET_CODE (op0) == CONCAT && !must_force_mem)
          {
            if (bitpos == 0
-               && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
+               && bitsize == GET_MODE_BITSIZE (GET_MODE (op0))
+               && COMPLEX_MODE_P (mode1))
              {
                if (reversep)
                  op0 = flip_storage_order (GET_MODE (op0), op0);
--- gcc/testsuite/g++.dg/torture/pr77919.C      (revision 0)
+++ gcc/testsuite/g++.dg/torture/pr77919.C      (revision 241642)
@@ -0,0 +1,11 @@
+// PR rtl-optimization/77919
+// { dg-do compile }
+// { dg-additional-options "-Wno-psabi" }
+
+struct A { A (double) {} _Complex double i; };
+typedef int __attribute__ ((vector_size (16))) B;
+typedef struct { B b; } C;
+struct D { D (const B &x) : b (x) {} B b; };
+static inline B foo (const double *x) { C *a; a = (C *) x; return a->b; }
+static inline D baz (const A &x) { return foo ((double *) &x); }
+D b = baz (0);
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-10-29  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/77919
        * expr.c (expand_expr_real_1) <normal_inner_ref>: Only avoid forcing
        into memory if both modes are complex and their inner modes have the
        same precision.  If the two modes are different complex modes, convert
        each part separately and generate a new CONCAT.

        * g++.dg/torture/pr77919-2.C: New test.

--- gcc/expr.c  (revision 241680)
+++ gcc/expr.c  (revision 241681)
@@ -10422,10 +10422,35 @@ expand_expr_real_1 (tree exp, rtx target
          {
            if (bitpos == 0
                && bitsize == GET_MODE_BITSIZE (GET_MODE (op0))
-               && COMPLEX_MODE_P (mode1))
+               && COMPLEX_MODE_P (mode1)
+               && COMPLEX_MODE_P (GET_MODE (op0))
+               && (GET_MODE_PRECISION (GET_MODE_INNER (mode1))
+                   == GET_MODE_PRECISION (GET_MODE_INNER (GET_MODE (op0)))))
              {
                if (reversep)
                  op0 = flip_storage_order (GET_MODE (op0), op0);
+               if (mode1 != GET_MODE (op0))
+                 {
+                   rtx parts[2];
+                   for (int i = 0; i < 2; i++)
+                     {
+                       rtx op = read_complex_part (op0, i != 0);
+                       if (GET_CODE (op) == SUBREG)
+                         op = force_reg (GET_MODE (op), op);
+                       rtx temp = gen_lowpart_common (GET_MODE_INNER (mode1),
+                                                      op);
+                       if (temp)
+                         op = temp;
+                       else
+                         {
+                           if (!REG_P (op) && !MEM_P (op))
+                             op = force_reg (GET_MODE (op), op);
+                           op = gen_lowpart (GET_MODE_INNER (mode1), op);
+                         }
+                       parts[i] = op;
+                     }
+                   op0 = gen_rtx_CONCAT (mode1, parts[0], parts[1]);
+                 }
                return op0;
              }
            if (bitpos == 0
--- gcc/testsuite/g++.dg/torture/pr77919-2.C    (revision 0)
+++ gcc/testsuite/g++.dg/torture/pr77919-2.C    (revision 241681)
@@ -0,0 +1,10 @@
+// PR rtl-optimization/77919
+// { dg-do compile }
+
+typedef _Complex long long B;
+struct A { A (double) {} _Complex double i; };
+typedef struct { B b; } C;
+struct D { D (const B &x) : b (x) {} B b; };
+static inline B foo (const double *x) { C *a; a = (C *) x; return a->b; }
+static inline D baz (const A &x) { return foo ((double *) &x); }
+D b = baz (0);
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-10-31  Jakub Jelinek  <ja...@redhat.com>

        PR c++/78089
        * parser.c (cp_parser_postfix_expression): Replace return statement in
        the first switch with setting postfix_expression to the return
        expression and break;.

        * c-c++-common/builtin-shuffle-1.c: New test.

--- gcc/cp/parser.c     (revision 241709)
+++ gcc/cp/parser.c     (revision 241710)
@@ -6404,7 +6404,10 @@ cp_parser_postfix_expression (cp_parser
           can be used in constant-expressions.  */
        if (!cast_valid_in_integral_constant_expression_p (type)
            && cp_parser_non_integral_constant_expression (parser, NIC_CAST))
-         return error_mark_node;
+         {
+           postfix_expression = error_mark_node;
+           break;
+         }
 
        switch (keyword)
          {
@@ -6484,7 +6487,7 @@ cp_parser_postfix_expression (cp_parser
        parser->type_definition_forbidden_message = saved_message;
        /* `typeid' may not appear in an integral constant expression.  */
        if (cp_parser_non_integral_constant_expression (parser, NIC_TYPEID))
-         return error_mark_node;
+         postfix_expression = error_mark_node;
       }
       break;
 
@@ -6576,23 +6579,28 @@ cp_parser_postfix_expression (cp_parser
                    /*cast_p=*/false, /*allow_expansion_p=*/true,
                    /*non_constant_p=*/NULL);
        if (vec == NULL)
-         return error_mark_node;
+         {
+           postfix_expression = error_mark_node;
+           break;
+         }
 
        FOR_EACH_VEC_ELT (*vec, i, p)
          mark_exp_read (p);
 
        if (vec->length () == 2)
-         return build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE, (*vec)[1],
-                                        tf_warning_or_error);
+         postfix_expression
+           = build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE, (*vec)[1],
+                                    tf_warning_or_error);
        else if (vec->length () == 3)
-         return build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1], (*vec)[2],
-                                        tf_warning_or_error);
+         postfix_expression
+           = build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1], (*vec)[2],
+                                    tf_warning_or_error);
        else
-       {
-         error_at (loc, "wrong number of arguments to "
-             "%<__builtin_shuffle%>");
-         return error_mark_node;
-       }
+         {
+           error_at (loc, "wrong number of arguments to "
+                          "%<__builtin_shuffle%>");
+           postfix_expression = error_mark_node;
+         }
        break;
       }
 
--- gcc/testsuite/c-c++-common/builtin-shuffle-1.c      (revision 0)
+++ gcc/testsuite/c-c++-common/builtin-shuffle-1.c      (revision 241710)
@@ -0,0 +1,22 @@
+/* PR c++/78089 */
+/* { dg-do run } */
+
+typedef int V __attribute__((vector_size (16)));
+V a, b, c;
+
+int
+foo ()
+{
+  return __builtin_shuffle (a, b, c)[3];
+}
+
+int
+main ()
+{
+  a = (V) { 1, 2, 3, 4 };
+  b = (V) { 5, 6, 7, 8 };
+  c = (V) { 7, 2, 5, 6 };
+  if (foo () != 7)
+    __builtin_abort ();
+  return 0;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-01  Jakub Jelinek  <ja...@redhat.com>

        * hashtab.h: Use standard GPLv3 with runtime exception
        boilerplate.

--- libgomp/hashtab.h   (revision 241745)
+++ libgomp/hashtab.h   (revision 241746)
@@ -2,19 +2,27 @@
    Copyright (C) 1999-2016 Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmaka...@cygnus.com>.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 
USA.  */
+   This file is part of the GNU Offloading and Multi Processing Library
+   (libgomp).
+
+   Libgomp is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+   more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
 
 /* The hash table code copied from include/hashtab.[hc] and adjusted,
    so that the hash table entries are in the flexible array at the end
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-04  Jakub Jelinek  <ja...@redhat.com>

        PR target/77834
        * alias.c (nonoverlapping_memrefs_p): Return 0 if exprx or expry
        doesn't have rtl set.

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

--- gcc/alias.c (revision 241858)
+++ gcc/alias.c (revision 241859)
@@ -2755,6 +2755,13 @@ nonoverlapping_memrefs_p (const_rtx x, c
       || TREE_CODE (expry) == CONST_DECL)
     return 1;
 
+  /* If either of the decls doesn't have DECL_RTL set (e.g. marked as
+     living in multiple places), we can't tell anything.  Exception
+     are FUNCTION_DECLs for which we can create DECL_RTL on demand.  */
+  if ((!DECL_RTL_SET_P (exprx) && TREE_CODE (exprx) != FUNCTION_DECL)
+      || (!DECL_RTL_SET_P (expry) && TREE_CODE (expry) != FUNCTION_DECL))
+    return 0;
+
   rtlx = DECL_RTL (exprx);
   rtly = DECL_RTL (expry);
 
--- gcc/testsuite/gcc.dg/pr77834.c      (revision 0)
+++ gcc/testsuite/gcc.dg/pr77834.c      (revision 241859)
@@ -0,0 +1,18 @@
+/* PR target/77834 */
+/* { dg-do compile } */
+/* { dg-options "-O -ftree-pre -Wno-psabi" } */
+/* { dg-additional-options "-mstringop-strategy=libcall" { target i?86-*-* 
x86_64-*-* } } */
+
+typedef int V __attribute__ ((vector_size (64)));
+
+V
+foo (V u, V v, int w)
+{
+  do
+    {
+      if (u[0]) v ^= u[w];
+    }
+  while ((V) { 0, u[w] }[1]);
+  u = (V) { v[v[0]], u[u[0]] };
+  return v + u;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-07  Jakub Jelinek  <ja...@redhat.com>

        PR target/78227
        * config/i386/i386.c (ix86_expand_sse_cmp): Force dest into
        cmp_mode argument even for -O0 if cmp_mode != mode and maskcmp.

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

--- gcc/config/i386/i386.c      (revision 241915)
+++ gcc/config/i386/i386.c      (revision 241916)
@@ -23561,6 +23561,7 @@ ix86_expand_sse_cmp (rtx dest, enum rtx_
     cmp_op1 = force_reg (cmp_ops_mode, cmp_op1);
 
   if (optimize
+      || (maskcmp && cmp_mode != mode)
       || (op_true && reg_overlap_mentioned_p (dest, op_true))
       || (op_false && reg_overlap_mentioned_p (dest, op_false)))
     dest = gen_reg_rtx (maskcmp ? cmp_mode : mode);
--- gcc/testsuite/gcc.target/i386/pr78227-1.c   (revision 0)
+++ gcc/testsuite/gcc.target/i386/pr78227-1.c   (revision 241916)
@@ -0,0 +1,30 @@
+/* PR target/78227 */
+/* { dg-do compile } */
+/* { dg-options "-mavx512f -O0 -Wno-psabi" } */
+
+typedef int V __attribute__((vector_size (64)));
+typedef long long int W __attribute__((vector_size (64)));
+
+V
+foo1 (V v)
+{
+  return v > 0;
+}
+
+V
+bar1 (V v)
+{
+  return v != 0;
+}
+
+W
+foo2 (W w)
+{
+  return w > 0;
+}
+
+W
+bar2 (W w)
+{
+  return w != 0;
+}
--- gcc/testsuite/gcc.target/i386/pr78227-2.c   (revision 0)
+++ gcc/testsuite/gcc.target/i386/pr78227-2.c   (revision 241916)
@@ -0,0 +1,30 @@
+/* PR target/78227 */
+/* { dg-do compile } */
+/* { dg-options "-mavx512bw -O0 -Wno-psabi" } */
+
+typedef signed char V __attribute__((vector_size (64)));
+typedef short int W __attribute__((vector_size (64)));
+
+V
+foo1 (V v)
+{
+  return v > 0;
+}
+
+V
+bar1 (V v)
+{
+  return v != 0;
+}
+
+W
+foo2 (W w)
+{
+  return w > 0;
+}
+
+W
+bar2 (W w)
+{
+  return w != 0;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-07  Jakub Jelinek  <ja...@redhat.com>

        PR target/77834
        * dse.c (dse_step5): Call scan_reads even if just
        insn_info->frame_read.  Improve and fix dump file messages.

--- gcc/dse.c   (revision 241916)
+++ gcc/dse.c   (revision 241917)
@@ -3298,12 +3298,19 @@ dse_step5 (void)
                  bitmap_clear (v);
                }
              else if (insn_info->read_rec
-                       || insn_info->non_frame_wild_read)
+                      || insn_info->non_frame_wild_read
+                      || insn_info->frame_read)
                {
-                 if (dump_file && !insn_info->non_frame_wild_read)
-                   fprintf (dump_file, "regular read\n");
-                  else if (dump_file && (dump_flags & TDF_DETAILS))
-                   fprintf (dump_file, "non-frame wild read\n");
+                 if (dump_file && (dump_flags & TDF_DETAILS))
+                   {
+                     if (!insn_info->non_frame_wild_read
+                         && !insn_info->frame_read)
+                       fprintf (dump_file, "regular read\n");
+                     if (insn_info->non_frame_wild_read)
+                       fprintf (dump_file, "non-frame wild read\n");
+                     if (insn_info->frame_read)
+                       fprintf (dump_file, "frame read\n");
+                   }
                  scan_reads (insn_info, v, NULL);
                }
            }
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-16  Jakub Jelinek  <ja...@redhat.com>

        PR fortran/78299
        * omp-low.c (expand_omp_for_static_nochunk): Don't assert
        that loop->header == body_bb if broken_loop.

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

--- gcc/omp-low.c       (revision 242506)
+++ gcc/omp-low.c       (revision 242507)
@@ -9685,7 +9685,7 @@ expand_omp_for_static_nochunk (struct om
   struct loop *loop = body_bb->loop_father;
   if (loop != entry_bb->loop_father)
     {
-      gcc_assert (loop->header == body_bb);
+      gcc_assert (broken_loop || loop->header == body_bb);
       gcc_assert (broken_loop
                  || loop->latch == region->cont
                  || single_pred (loop->latch) == region->cont);
--- gcc/testsuite/gfortran.dg/gomp/pr78299.f90  (revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr78299.f90  (revision 242507)
@@ -0,0 +1,55 @@
+! PR fortran/78299
+! { dg-do compile }
+! { dg-additional-options "-fcheck=bounds" }
+
+program pr78299
+  integer, parameter :: n = 8
+  integer :: i, j
+  real :: x(n), y(n)
+  x = 1.0
+  y = 2.0
+  do j = 1, 9
+    !$omp parallel workshare
+    !$omp parallel default(shared)
+    !$omp do
+    do i = 1, n
+      x(i) = x(i) * y(9)               ! { dg-warning "is out of bounds" }
+    end do
+    !$omp end do
+    !$omp end parallel
+    !$omp end parallel workshare
+  end do
+  do j = 1, 9
+    !$omp parallel workshare
+    !$omp parallel default(shared)
+    !$omp do schedule(static)
+    do i = 1, n
+      x(i) = x(i) * y(9)               ! { dg-warning "is out of bounds" }
+    end do
+    !$omp end do
+    !$omp end parallel
+    !$omp end parallel workshare
+  end do
+  do j = 1, 9
+    !$omp parallel workshare
+    !$omp parallel default(shared)
+    !$omp do schedule(static, 2)
+    do i = 1, n
+      x(i) = x(i) * y(9)               ! { dg-warning "is out of bounds" }
+    end do
+    !$omp end do
+    !$omp end parallel
+    !$omp end parallel workshare
+  end do
+  do j = 1, 9
+    !$omp parallel workshare
+    !$omp parallel default(shared)
+    !$omp do schedule(dynamic, 3)
+    do i = 1, n
+      x(i) = x(i) * y(9)               ! { dg-warning "is out of bounds" }
+    end do
+    !$omp end do
+    !$omp end parallel
+    !$omp end parallel workshare
+  end do
+end
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-16  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/78378
        * combine.c (make_extraction): Use force_to_mode for non-{REG,MEM}
        inner only if pos is 0.  Fix up formatting.

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

--- gcc/combine.c       (revision 242525)
+++ gcc/combine.c       (revision 242526)
@@ -7369,6 +7369,7 @@ make_extraction (machine_mode mode, rtx
   if (tmode != BLKmode
       && ((pos_rtx == 0 && (pos % BITS_PER_WORD) == 0
           && !MEM_P (inner)
+          && (pos == 0 || REG_P (inner))
           && (inner_mode == tmode
               || !REG_P (inner)
               || TRULY_NOOP_TRUNCATION_MODES_P (tmode, inner_mode)
@@ -7445,10 +7446,9 @@ make_extraction (machine_mode mode, rtx
        }
       else
        new_rtx = force_to_mode (inner, tmode,
-                            len >= HOST_BITS_PER_WIDE_INT
-                            ? ~(unsigned HOST_WIDE_INT) 0
-                            : ((unsigned HOST_WIDE_INT) 1 << len) - 1,
-                            0);
+                                len >= HOST_BITS_PER_WIDE_INT
+                                ? ~(unsigned HOST_WIDE_INT) 0
+                                : ((unsigned HOST_WIDE_INT) 1 << len) - 1, 0);
 
       /* If this extraction is going into the destination of a SET,
         make a STRICT_LOW_PART unless we made a MEM.  */
--- gcc/testsuite/gcc.c-torture/execute/pr78378.c       (revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr78378.c       (revision 242526)
@@ -0,0 +1,18 @@
+/* PR rtl-optimization/78378 */
+
+unsigned long long __attribute__ ((noinline, noclone))
+foo (unsigned long long x)
+{
+  x <<= 41;
+  x /= 232;
+  return 1 + (unsigned short) x;
+}
+
+int
+main ()
+{
+  unsigned long long x = foo (1);
+  if (x != 0x2c24)
+    __builtin_abort();
+  return 0;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-18  Jakub Jelinek  <ja...@redhat.com>

        PR c++/77285
        * mangle.c (mangle_tls_init_fn, mangle_tls_wrapper_fn): Call
        check_abi_tags.

        * g++.dg/tls/pr77285-1.C: New test.
        * g++.dg/tls/pr77285-2.C: New test.

--- gcc/cp/mangle.c     (revision 242606)
+++ gcc/cp/mangle.c     (revision 242607)
@@ -4301,6 +4301,7 @@ mangle_guard_variable (const tree variab
 tree
 mangle_tls_init_fn (const tree variable)
 {
+  check_abi_tags (variable);
   start_mangling (variable);
   write_string ("_ZTH");
   write_guarded_var_name (variable);
@@ -4315,6 +4316,7 @@ mangle_tls_init_fn (const tree variable)
 tree
 mangle_tls_wrapper_fn (const tree variable)
 {
+  check_abi_tags (variable);
   start_mangling (variable);
   write_string (TLS_WRAPPER_PREFIX);
   write_guarded_var_name (variable);
--- gcc/testsuite/g++.dg/tls/pr77285-1.C        (revision 0)
+++ gcc/testsuite/g++.dg/tls/pr77285-1.C        (revision 242607)
@@ -0,0 +1,7 @@
+// { dg-do link { target c++11 } }
+// { dg-require-effective-target tls }
+// { dg-additional-sources pr77285-2.C }
+
+struct __attribute__((abi_tag("tag"))) X { ~X () {} int i = 0; };
+thread_local X var1;
+X var2;
--- gcc/testsuite/g++.dg/tls/pr77285-2.C        (revision 0)
+++ gcc/testsuite/g++.dg/tls/pr77285-2.C        (revision 242607)
@@ -0,0 +1,17 @@
+// PR c++/77285
+// { dg-do compile { target c++11 } }
+// { dg-require-effective-target tls }
+// { dg-final { scan-assembler "_Z4var1B3tag" } }
+// { dg-final { scan-assembler "_Z4var2B3tag" } }
+// { dg-final { scan-assembler "_ZTH4var1B3tag" } }
+// { dg-final { scan-assembler "_ZTW4var1B3tag" } }
+
+struct __attribute__((abi_tag("tag"))) X { ~X () {} int i = 0; };
+extern thread_local X var1;
+extern X var2;
+
+int
+main ()
+{
+ return var1.i + var2.i;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-18  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/78419
        * multiple_target.c (get_attr_len): Start with argnum and increment
        argnum on every arg.  Use strchr in a loop instead of counting commas
        manually.
        (get_attr_str): Increment argnum for every comma in the string.
        (separate_attrs): Use for instead of while loop, simplify.
        (expand_target_clones): Rename defenition argument to definition.
        Free attrs and attr_str even when diagnosing errors.  Temporarily
        change input_location around targetm.target_option.valid_attribute_p
        calls.  Don't emit warning or errors if that function fails.

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

--- gcc/multiple_target.c       (revision 242607)
+++ gcc/multiple_target.c       (revision 242608)
@@ -101,22 +101,18 @@ get_attr_len (tree arglist)
 {
   tree arg;
   int str_len_sum = 0;
-  int argnum = 1;
+  int argnum = 0;
 
   for (arg = arglist; arg; arg = TREE_CHAIN (arg))
     {
-      unsigned int i;
       const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
-      int len = strlen (str);
-
+      size_t len = strlen (str);
       str_len_sum += len + 1;
-      if (arg != arglist)
+      for (const char *p = strchr (str, ','); p; p = strchr (p + 1, ','))
        argnum++;
-      for (i = 0; i < strlen (str); i++)
-       if (str[i] == ',')
-         argnum++;
+      argnum++;
     }
-  if (argnum == 1)
+  if (argnum <= 1)
     return -1;
   return str_len_sum;
 }
@@ -134,8 +130,9 @@ get_attr_str (tree arglist, char *attr_s
   for (arg = arglist; arg; arg = TREE_CHAIN (arg))
     {
       const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
-
       size_t len = strlen (str);
+      for (const char *p = strchr (str, ','); p; p = strchr (p + 1, ','))
+       argnum++;
       memcpy (attr_str + str_len_sum, str, len);
       attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
       str_len_sum += len + 1;
@@ -152,19 +149,16 @@ separate_attrs (char *attr_str, char **a
 {
   int i = 0;
   bool has_default = false;
-  char *attr = strtok (attr_str, ",");
 
-  while (attr != NULL)
+  for (char *attr = strtok (attr_str, ",");
+       attr != NULL; attr = strtok (NULL, ","))
     {
       if (strcmp (attr, "default") == 0)
        {
          has_default = true;
-         attr = strtok (NULL, ",");
          continue;
        }
-      attrs[i] = attr;
-      attr = strtok (NULL, ",");
-      i++;
+      attrs[i++] = attr;
     }
   if (!has_default)
     return -1;
@@ -235,7 +229,7 @@ create_target_clone (cgraph_node *node,
    create the appropriate clone for each valid target attribute.  */
 
 static bool
-expand_target_clones (struct cgraph_node *node, bool defenition)
+expand_target_clones (struct cgraph_node *node, bool definition)
 {
   int i;
   /* Parsing target attributes separated by comma.  */
@@ -266,6 +260,8 @@ expand_target_clones (struct cgraph_node
     {
       error_at (DECL_SOURCE_LOCATION (node->decl),
                "default target was not set");
+      XDELETEVEC (attrs);
+      XDELETEVEC (attr_str);
       return false;
     }
 
@@ -286,22 +282,24 @@ expand_target_clones (struct cgraph_node
 
       create_new_asm_name (attr, suffix);
       /* Create new target clone.  */
-      cgraph_node *new_node = create_target_clone (node, defenition, suffix);
+      cgraph_node *new_node = create_target_clone (node, definition, suffix);
       XDELETEVEC (suffix);
 
       /* Set new attribute for the clone.  */
       tree attributes = make_attribute ("target", attr,
                                        DECL_ATTRIBUTES (new_node->decl));
       DECL_ATTRIBUTES (new_node->decl) = attributes;
+      location_t saved_loc = input_location;
+      input_location = DECL_SOURCE_LOCATION (node->decl);
       if (!targetm.target_option.valid_attribute_p (new_node->decl, NULL,
-                                                   TREE_VALUE (attributes), 0))
+                                                   TREE_VALUE (attributes),
+                                                   0))
        {
-         warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
-                     "attribute(target_clones(\"%s\")) is not "
-                     "valid for current target", attr);
+         input_location = saved_loc;
          continue;
        }
 
+      input_location = saved_loc;
       decl2_v = new_node->function_version ();
       if (decl2_v != NULL)
         continue;
@@ -320,22 +318,20 @@ expand_target_clones (struct cgraph_node
       DECL_FUNCTION_VERSIONED (new_node->decl) = 1;
     }
 
-  /* Setting new attribute to initial function.  */
-  tree attributes =  make_attribute ("target", "default",
-                                    DECL_ATTRIBUTES (node->decl));
-  DECL_ATTRIBUTES (node->decl) = attributes;
-  if (!targetm.target_option.valid_attribute_p (node->decl, NULL,
-                                               TREE_VALUE (attributes), 0))
-    {
-      error_at (DECL_SOURCE_LOCATION (node->decl),
-               "attribute(target_clones(\"default\")) is not "
-               "valid for current target");
-      return false;
-    }
-
   XDELETEVEC (attrs);
   XDELETEVEC (attr_str);
-  return true;
+
+  /* Setting new attribute to initial function.  */
+  tree attributes = make_attribute ("target", "default",
+                                   DECL_ATTRIBUTES (node->decl));
+  DECL_ATTRIBUTES (node->decl) = attributes;
+  location_t saved_loc = input_location;
+  input_location = DECL_SOURCE_LOCATION (node->decl);
+  bool ret
+    = targetm.target_option.valid_attribute_p (node->decl, NULL,
+                                              TREE_VALUE (attributes), 0);
+  input_location = saved_loc;
+  return ret;
 }
 
 static bool target_clone_pass;
--- gcc/testsuite/gcc.target/i386/pr78419.c     (revision 0)
+++ gcc/testsuite/gcc.target/i386/pr78419.c     (revision 242608)
@@ -0,0 +1,23 @@
+/* PR middle-end/78419 */
+/* { dg-do compile } */
+
+static double bar (double *__restrict, double *__restrict, int)
+__attribute__ ((target_clones("avx,foo,avx2,avx512f,default")));
+
+double
+foo (double *__restrict a, double *__restrict b, int n)
+{
+  return bar (a,b,n);
+}
+
+double
+bar (double *__restrict a, double *__restrict b, int n)        /* { dg-error 
"attribute\[^\n\r]*foo\[^\n\r]* is unknown" } */
+{
+  double s;
+  int i;
+  s = 0.0;
+  for (i=0; i<n; i++)
+    s += a[i] + b[i];
+
+  return s;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-21  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/67335
        * omp-simd-clone.c (simd_clone_adjust_argument_types): Use NULL prefix
        for tmp simd array if DECL_NAME (parm) is NULL.

        * g++.dg/vect/simd-clone-7.cc: New test.

--- gcc/omp-simd-clone.c        (revision 242677)
+++ gcc/omp-simd-clone.c        (revision 242678)
@@ -630,8 +630,9 @@ simd_clone_adjust_argument_types (struct
 
          if (node->definition)
            sc->args[i].simd_array
-             = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
-                                      parm_type, sc->simdlen);
+             = create_tmp_simd_array (DECL_NAME (parm)
+                                      ? IDENTIFIER_POINTER (DECL_NAME (parm))
+                                      : NULL, parm_type, sc->simdlen);
        }
       adjustments.safe_push (adj);
     }
--- gcc/testsuite/g++.dg/vect/simd-clone-7.cc   (revision 0)
+++ gcc/testsuite/g++.dg/vect/simd-clone-7.cc   (revision 242678)
@@ -0,0 +1,10 @@
+// PR middle-end/67335
+// { dg-do compile }
+// { dg-additional-options "-fopenmp-simd" }
+
+#pragma omp declare simd notinbranch uniform(y)
+float
+bar (float x, float *y, int)
+{
+  return y[0] + y[1] * x;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-22  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/78416
        * expmed.c (expand_divmod): Use wide_int for computation of
        op1_is_pow2.  Don't set it if op1 is 0.  Formatting fixes.
        Use size <= HOST_BITS_PER_WIDE_INT instead of
        HOST_BITS_PER_WIDE_INT >= size.

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

--- gcc/expmed.c        (revision 242689)
+++ gcc/expmed.c        (revision 242690)
@@ -4031,11 +4031,10 @@ expand_divmod (int rem_flag, enum tree_c
   op1_is_constant = CONST_INT_P (op1);
   if (op1_is_constant)
     {
-      unsigned HOST_WIDE_INT ext_op1 = UINTVAL (op1);
-      if (unsignedp)
-       ext_op1 &= GET_MODE_MASK (mode);
-      op1_is_pow2 = ((EXACT_POWER_OF_2_OR_ZERO_P (ext_op1)
-                    || (! unsignedp && EXACT_POWER_OF_2_OR_ZERO_P 
(-ext_op1))));
+      wide_int ext_op1 = rtx_mode_t (op1, mode);
+      op1_is_pow2 = (wi::popcount (ext_op1) == 1
+                    || (! unsignedp
+                        && wi::popcount (wi::neg (ext_op1)) == 1));
     }
 
   /*
@@ -4116,11 +4115,10 @@ expand_divmod (int rem_flag, enum tree_c
      not straightforward to generalize this.  Maybe we should make an array
      of possible modes in init_expmed?  Save this for GCC 2.7.  */
 
-  optab1 = ((op1_is_pow2 && op1 != const0_rtx)
+  optab1 = (op1_is_pow2
            ? (unsignedp ? lshr_optab : ashr_optab)
            : (unsignedp ? udiv_optab : sdiv_optab));
-  optab2 = ((op1_is_pow2 && op1 != const0_rtx)
-           ? optab1
+  optab2 = (op1_is_pow2 ? optab1
            : (unsignedp ? udivmod_optab : sdivmod_optab));
 
   for (compute_mode = mode; compute_mode != VOIDmode;
@@ -4176,10 +4174,15 @@ expand_divmod (int rem_flag, enum tree_c
       /* convert_modes may have placed op1 into a register, so we
         must recompute the following.  */
       op1_is_constant = CONST_INT_P (op1);
-      op1_is_pow2 = (op1_is_constant
-                    && ((EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
-                         || (! unsignedp
-                             && EXACT_POWER_OF_2_OR_ZERO_P (-UINTVAL 
(op1))))));
+      if (op1_is_constant)
+       {
+         wide_int ext_op1 = rtx_mode_t (op1, compute_mode);
+         op1_is_pow2 = (wi::popcount (ext_op1) == 1
+                        || (! unsignedp
+                            && wi::popcount (wi::neg (ext_op1)) == 1));
+       }
+      else
+       op1_is_pow2 = 0;
     }
 
   /* If one of the operands is a volatile MEM, copy it into a register.  */
@@ -4219,10 +4222,10 @@ expand_divmod (int rem_flag, enum tree_c
                unsigned HOST_WIDE_INT mh, ml;
                int pre_shift, post_shift;
                int dummy;
-               unsigned HOST_WIDE_INT d = (INTVAL (op1)
-                                           & GET_MODE_MASK (compute_mode));
+               wide_int wd = rtx_mode_t (op1, compute_mode);
+               unsigned HOST_WIDE_INT d = wd.to_uhwi ();
 
-               if (EXACT_POWER_OF_2_OR_ZERO_P (d))
+               if (wi::popcount (wd) == 1)
                  {
                    pre_shift = floor_log2 (d);
                    if (rem_flag)
@@ -4362,7 +4365,7 @@ expand_divmod (int rem_flag, enum tree_c
                else if (d == -1)
                  quotient = expand_unop (compute_mode, neg_optab, op0,
                                          tquotient, 0);
-               else if (HOST_BITS_PER_WIDE_INT >= size
+               else if (size <= HOST_BITS_PER_WIDE_INT
                         && abs_d == (unsigned HOST_WIDE_INT) 1 << (size - 1))
                  {
                    /* This case is not handled correctly below.  */
@@ -4372,6 +4375,7 @@ expand_divmod (int rem_flag, enum tree_c
                      goto fail1;
                  }
                else if (EXACT_POWER_OF_2_OR_ZERO_P (d)
+                        && (size <= HOST_BITS_PER_WIDE_INT || d >= 0)
                         && (rem_flag
                             ? smod_pow2_cheap (speed, compute_mode)
                             : sdiv_pow2_cheap (speed, compute_mode))
@@ -4385,7 +4389,9 @@ expand_divmod (int rem_flag, enum tree_c
                                                compute_mode)
                                 != CODE_FOR_nothing)))
                  ;
-               else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d))
+               else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d)
+                        && (size <= HOST_BITS_PER_WIDE_INT
+                            || abs_d != (unsigned HOST_WIDE_INT) d))
                  {
                    if (rem_flag)
                      {
@@ -4520,7 +4526,7 @@ expand_divmod (int rem_flag, enum tree_c
       case FLOOR_DIV_EXPR:
       case FLOOR_MOD_EXPR:
       /* We will come here only for signed operations.  */
-       if (op1_is_constant && HOST_BITS_PER_WIDE_INT >= size)
+       if (op1_is_constant && size <= HOST_BITS_PER_WIDE_INT)
          {
            unsigned HOST_WIDE_INT mh, ml;
            int pre_shift, lgup, post_shift;
@@ -4589,9 +4595,8 @@ expand_divmod (int rem_flag, enum tree_c
                                                  op0, constm1_rtx), NULL_RTX);
                t2 = expand_binop (compute_mode, ior_optab, op0, t1, NULL_RTX,
                                   0, OPTAB_WIDEN);
-               nsign = expand_shift
-                 (RSHIFT_EXPR, compute_mode, t2,
-                  size - 1, NULL_RTX, 0);
+               nsign = expand_shift (RSHIFT_EXPR, compute_mode, t2,
+                                     size - 1, NULL_RTX, 0);
                t3 = force_operand (gen_rtx_MINUS (compute_mode, t1, nsign),
                                    NULL_RTX);
                t4 = expand_divmod (0, TRUNC_DIV_EXPR, compute_mode, t3, op1,
@@ -4700,7 +4705,10 @@ expand_divmod (int rem_flag, enum tree_c
       case CEIL_MOD_EXPR:
        if (unsignedp)
          {
-           if (op1_is_constant && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1)))
+           if (op1_is_constant
+               && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
+               && (size <= HOST_BITS_PER_WIDE_INT
+                   || INTVAL (op1) >= 0))
              {
                rtx t1, t2, t3;
                unsigned HOST_WIDE_INT d = INTVAL (op1);
@@ -4913,7 +4921,7 @@ expand_divmod (int rem_flag, enum tree_c
        break;
 
       case EXACT_DIV_EXPR:
-       if (op1_is_constant && HOST_BITS_PER_WIDE_INT >= size)
+       if (op1_is_constant && size <= HOST_BITS_PER_WIDE_INT)
          {
            HOST_WIDE_INT d = INTVAL (op1);
            unsigned HOST_WIDE_INT ml;
--- gcc/testsuite/gcc.dg/torture/pr78416.c      (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr78416.c      (revision 242690)
@@ -0,0 +1,17 @@
+/* PR middle-end/78416 */
+/* { dg-do run { target int128 } } */
+
+int
+main ()
+{
+  unsigned __int128 x;
+  x = 0xFFFFFFFFFFFFFFFFULL;
+  x /= ~0x7FFFFFFFFFFFFFFFLL;
+  if (x != 0)
+    __builtin_abort ();
+  x = ~0x7FFFFFFFFFFFFFFELL;
+  x /= ~0x7FFFFFFFFFFFFFFFLL;
+  if (x != 1)
+    __builtin_abort ();
+  return 0;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-23  Jakub Jelinek  <ja...@redhat.com>

        PR c++/77739
        * cp-gimplify.c (cp_gimplify_tree) <case VEC_INIT_EXPR>: Pass
        false as handle_invisiref_parm_p to cp_genericize_tree.
        (struct cp_genericize_data): Add handle_invisiref_parm_p field.
        (cp_genericize_r): Don't wrap is_invisiref_parm into references
        if !wtd->handle_invisiref_parm_p.
        (cp_genericize_tree): Add handle_invisiref_parm_p argument,
        set wtd.handle_invisiref_parm_p to it.
        (cp_genericize): Pass true as handle_invisiref_parm_p to
        cp_genericize_tree.  Formatting fix.

        * g++.dg/cpp1y/pr77739.C: New test.

--- gcc/cp/cp-gimplify.c        (revision 242765)
+++ gcc/cp/cp-gimplify.c        (revision 242766)
@@ -38,7 +38,7 @@ along with GCC; see the file COPYING3.
 
 static tree cp_genericize_r (tree *, int *, void *);
 static tree cp_fold_r (tree *, int *, void *);
-static void cp_genericize_tree (tree*);
+static void cp_genericize_tree (tree*, bool);
 static tree cp_fold (tree);
 
 /* Local declarations.  */
@@ -623,7 +623,7 @@ cp_gimplify_expr (tree *expr_p, gimple_s
                                  tf_warning_or_error);
        hash_set<tree> pset;
        cp_walk_tree (expr_p, cp_fold_r, &pset, NULL);
-       cp_genericize_tree (expr_p);
+       cp_genericize_tree (expr_p, false);
        ret = GS_OK;
        input_location = loc;
       }
@@ -995,6 +995,7 @@ struct cp_genericize_data
   struct cp_genericize_omp_taskreg *omp_ctx;
   tree try_block;
   bool no_sanitize_p;
+  bool handle_invisiref_parm_p;
 };
 
 /* Perform any pre-gimplification folding of C++ front end trees to
@@ -1111,7 +1112,7 @@ cp_genericize_r (tree *stmt_p, int *walk
     }
 
   /* Otherwise, do dereference invisible reference parms.  */
-  if (is_invisiref_parm (stmt))
+  if (wtd->handle_invisiref_parm_p && is_invisiref_parm (stmt))
     {
       *stmt_p = convert_from_reference (stmt);
       *walk_subtrees = 0;
@@ -1511,7 +1512,7 @@ cp_genericize_r (tree *stmt_p, int *walk
 /* Lower C++ front end trees to GENERIC in T_P.  */
 
 static void
-cp_genericize_tree (tree* t_p)
+cp_genericize_tree (tree* t_p, bool handle_invisiref_parm_p)
 {
   struct cp_genericize_data wtd;
 
@@ -1520,6 +1521,7 @@ cp_genericize_tree (tree* t_p)
   wtd.omp_ctx = NULL;
   wtd.try_block = NULL_TREE;
   wtd.no_sanitize_p = false;
+  wtd.handle_invisiref_parm_p = handle_invisiref_parm_p;
   cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
   delete wtd.p_set;
   wtd.bind_expr_stack.release ();
@@ -1639,12 +1641,12 @@ cp_genericize (tree fndecl)
   /* Expand all the array notations here.  */
   if (flag_cilkplus 
       && contains_array_notation_expr (DECL_SAVED_TREE (fndecl)))
-    DECL_SAVED_TREE (fndecl) = 
-      expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
+    DECL_SAVED_TREE (fndecl)
+      = expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
 
   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
-  cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
+  cp_genericize_tree (&DECL_SAVED_TREE (fndecl), true);
 
   if (flag_sanitize & SANITIZE_RETURN
       && do_ubsan_in_current_function ())
--- gcc/testsuite/g++.dg/cpp1y/pr77739.C        (revision 0)
+++ gcc/testsuite/g++.dg/cpp1y/pr77739.C        (revision 242766)
@@ -0,0 +1,15 @@
+// PR c++/77739
+// { dg-do compile { target c++14 } }
+
+struct A {
+  A();
+  A(const A &);
+};
+struct B {
+  B();
+  template <typename... Args> auto g(Args &&... p1) {
+    return [=] { f(p1...); };
+  }
+  void f(A, const char *);
+};
+B::B() { g(A(), ""); }
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-23  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/69183
        * omp-low.c (build_outer_var_ref): Change lastprivate argument
        to code, pass it recursively, adjust uses.  For OMP_CLAUSE_PRIVATE
        on worksharing constructs, treat it like clauses on simd construct.
        Formatting fix.
        (lower_rec_input_clauses): For OMP_CLAUSE_PRIVATE_OUTER_REF pass
        OMP_CLAUSE_PRIVATE as last argument to build_outer_var_ref.
        (lower_lastprivate_clauses): Pass OMP_CLAUSE_LASTPRIVATE instead
        of true as last argument to build_outer_var_ref.

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

--- gcc/omp-low.c       (revision 242792)
+++ gcc/omp-low.c       (revision 242793)
@@ -1283,7 +1283,8 @@ build_receiver_ref (tree var, bool by_re
    this is some variable.  */
 
 static tree
-build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
+build_outer_var_ref (tree var, omp_context *ctx,
+                    enum omp_clause_code code = OMP_CLAUSE_ERROR)
 {
   tree x;
 
@@ -1292,7 +1293,7 @@ build_outer_var_ref (tree var, omp_conte
   else if (is_variable_sized (var))
     {
       x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
-      x = build_outer_var_ref (x, ctx, lastprivate);
+      x = build_outer_var_ref (x, ctx, code);
       x = build_simple_mem_ref (x);
     }
   else if (is_taskreg_ctx (ctx))
@@ -1300,11 +1301,17 @@ build_outer_var_ref (tree var, omp_conte
       bool by_ref = use_pointer_for_field (var, NULL);
       x = build_receiver_ref (var, by_ref, ctx);
     }
-  else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-          && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
-    {
-      /* #pragma omp simd isn't a worksharing construct, and can reference even
-        private vars in its linear etc. clauses.  */
+  else if ((gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+           && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
+          || (code == OMP_CLAUSE_PRIVATE
+              && (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+                  || gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS
+                  || gimple_code (ctx->stmt) == GIMPLE_OMP_SINGLE)))
+    {
+      /* #pragma omp simd isn't a worksharing construct, and can reference
+        even private vars in its linear etc. clauses.
+        Similarly for OMP_CLAUSE_PRIVATE with outer ref, that can refer
+        to private vars in all worksharing constructs.  */
       x = NULL_TREE;
       if (ctx->outer && is_taskreg_ctx (ctx))
        x = lookup_decl (var, ctx->outer);
@@ -1313,7 +1320,7 @@ build_outer_var_ref (tree var, omp_conte
       if (x == NULL_TREE)
        x = var;
     }
-  else if (lastprivate && is_taskloop_ctx (ctx))
+  else if (code == OMP_CLAUSE_LASTPRIVATE && is_taskloop_ctx (ctx))
     {
       gcc_assert (ctx->outer);
       splay_tree_node n
@@ -1350,7 +1357,7 @@ build_outer_var_ref (tree var, omp_conte
          gcc_assert (outer
                      && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
        }
-       x = lookup_decl (var, outer);
+      x = lookup_decl (var, outer);
     }
   else if (is_reference (var))
     /* This can happen with orphaned constructs.  If var is reference, it is
@@ -5031,7 +5038,7 @@ lower_rec_input_clauses (tree clauses, g
                  if (is_task_ctx (ctx))
                    x = build_receiver_ref (var, false, ctx);
                  else
-                   x = build_outer_var_ref (var, ctx);
+                   x = build_outer_var_ref (var, ctx, OMP_CLAUSE_PRIVATE);
                }
              else
                x = NULL;
@@ -5697,7 +5704,7 @@ lower_lastprivate_clauses (tree clauses,
                x = ovar;
            }
          if (!x)
-           x = build_outer_var_ref (var, ctx, true);
+           x = build_outer_var_ref (var, ctx, OMP_CLAUSE_LASTPRIVATE);
          if (is_reference (var))
            new_var = build_simple_mem_ref_loc (clause_loc, new_var);
          x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
--- gcc/testsuite/gfortran.dg/gomp/pr69183.f90  (revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr69183.f90  (revision 242793)
@@ -0,0 +1,11 @@
+! PR middle-end/69183
+! { dg-do compile }
+
+program pr69183
+  integer, allocatable :: z
+  integer :: i
+  !$omp do private(z)
+  do i = 1, 2
+    z = i
+  end do
+end
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-28  Jakub Jelinek  <ja...@redhat.com>

        PR c++/77591
        * typeck.c (maybe_warn_about_returning_address_of_local): Optimize
        whats_returned through fold_for_warn.

        * g++.dg/cpp1y/pr77591.C: New test.

--- gcc/cp/typeck.c     (revision 242923)
+++ gcc/cp/typeck.c     (revision 242924)
@@ -8552,7 +8552,8 @@ static bool
 maybe_warn_about_returning_address_of_local (tree retval)
 {
   tree valtype = TREE_TYPE (DECL_RESULT (current_function_decl));
-  tree whats_returned = retval;
+  tree whats_returned = c_fully_fold (retval, /*for_init*/false,
+                                     /*maybe_constp*/NULL);
 
   for (;;)
     {
--- gcc/testsuite/g++.dg/cpp1y/pr77591.C        (revision 0)
+++ gcc/testsuite/g++.dg/cpp1y/pr77591.C        (revision 242924)
@@ -0,0 +1,19 @@
+// PR c++/77591
+// { dg-do compile { target c++14 } }
+// { dg-options "-O0 -Wreturn-local-addr" }
+
+class A { };
+
+decltype(auto)
+foo ()
+{
+  A c;                 // { dg-warning "reference to local variable 'c' 
returned" }
+  return (c);
+}
+
+decltype(auto)
+bar ()
+{
+  A c;                 // { dg-warning "reference to local variable 'c' 
returned" }
+  return 1==1 ? c : c;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-28  Jakub Jelinek  <ja...@redhat.com>

        PR fortran/78298
        * tree-nested.c (convert_local_reference_stmt): After adding
        shared (FRAME.NN) clause to omp parallel, task or target,
        add it also to all outer omp parallel, task or target constructs.

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

--- gcc/tree-nested.c   (revision 242925)
+++ gcc/tree-nested.c   (revision 242926)
@@ -2083,6 +2083,8 @@ convert_local_reference_stmt (gimple_stm
   struct nesting_info *info = (struct nesting_info *) wi->info;
   tree save_local_var_chain;
   bitmap save_suppress;
+  char save_static_chain_added;
+  bool frame_decl_added;
   gimple *stmt = gsi_stmt (*gsi);
 
   switch (gimple_code (stmt))
@@ -2090,29 +2092,44 @@ convert_local_reference_stmt (gimple_stm
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
       save_suppress = info->suppress_expansion;
+      frame_decl_added = false;
       if (convert_local_omp_clauses (gimple_omp_taskreg_clauses_ptr (stmt),
                                     wi))
        {
-         tree c;
+         tree c = build_omp_clause (gimple_location (stmt),
+                                    OMP_CLAUSE_SHARED);
          (void) get_frame_type (info);
-         c = build_omp_clause (gimple_location (stmt),
-                               OMP_CLAUSE_SHARED);
          OMP_CLAUSE_DECL (c) = info->frame_decl;
          OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
          gimple_omp_taskreg_set_clauses (stmt, c);
+         info->static_chain_added |= 4;
+         frame_decl_added = true;
        }
 
       save_local_var_chain = info->new_local_var_chain;
+      save_static_chain_added = info->static_chain_added;
       info->new_local_var_chain = NULL;
+      info->static_chain_added = 0;
 
       walk_body (convert_local_reference_stmt, convert_local_reference_op, 
info,
                 gimple_omp_body_ptr (stmt));
 
+      if ((info->static_chain_added & 4) != 0 && !frame_decl_added)
+       {
+         tree c = build_omp_clause (gimple_location (stmt),
+                                    OMP_CLAUSE_SHARED);
+         (void) get_frame_type (info);
+         OMP_CLAUSE_DECL (c) = info->frame_decl;
+         OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
+         info->static_chain_added |= 4;
+         gimple_omp_taskreg_set_clauses (stmt, c);
+       }
       if (info->new_local_var_chain)
        declare_vars (info->new_local_var_chain,
                      gimple_seq_first_stmt (gimple_omp_body (stmt)), false);
       info->new_local_var_chain = save_local_var_chain;
       info->suppress_expansion = save_suppress;
+      info->static_chain_added |= save_static_chain_added;
       break;
 
     case GIMPLE_OMP_FOR:
@@ -2153,29 +2170,46 @@ convert_local_reference_stmt (gimple_stm
          break;
        }
       save_suppress = info->suppress_expansion;
+      frame_decl_added = false;
       if (convert_local_omp_clauses (gimple_omp_target_clauses_ptr (stmt), wi))
        {
-         tree c;
+         tree c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP);
          (void) get_frame_type (info);
-         c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP);
          OMP_CLAUSE_DECL (c) = info->frame_decl;
          OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
          OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (info->frame_decl);
          OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt);
          gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt), c);
+         info->static_chain_added |= 4;
+         frame_decl_added = true;
        }
 
       save_local_var_chain = info->new_local_var_chain;
+      save_static_chain_added = info->static_chain_added;
       info->new_local_var_chain = NULL;
+      info->static_chain_added = 0;
 
       walk_body (convert_local_reference_stmt, convert_local_reference_op, 
info,
                 gimple_omp_body_ptr (stmt));
 
+      if ((info->static_chain_added & 4) != 0 && !frame_decl_added)
+       {
+         tree c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP);
+         (void) get_frame_type (info);
+         OMP_CLAUSE_DECL (c) = info->frame_decl;
+         OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
+         OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (info->frame_decl);
+         OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt);
+         gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt), c);
+         info->static_chain_added |= 4;
+       }
+
       if (info->new_local_var_chain)
        declare_vars (info->new_local_var_chain,
                      gimple_seq_first_stmt (gimple_omp_body (stmt)), false);
       info->new_local_var_chain = save_local_var_chain;
       info->suppress_expansion = save_suppress;
+      info->static_chain_added |= save_static_chain_added;
       break;
 
     case GIMPLE_OMP_TEAMS:
--- gcc/testsuite/gfortran.dg/gomp/pr78298.f90  (revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr78298.f90  (revision 242926)
@@ -0,0 +1,28 @@
+! PR fortran/78298
+! { dg-do compile }
+! { dg-additional-options "-O2" }
+
+program pr78298
+  integer :: i, j, n
+  n = 2
+  !$omp parallel
+  !$omp do
+  do i = 1, n
+    !$omp parallel
+    !$omp do
+    do j = 1, n
+      call sub(i)
+    end do
+    !$omp end parallel
+  end do
+  !$omp end parallel
+  !call unused()
+contains
+  subroutine sub(x)
+    integer :: x
+  end
+  subroutine unused()
+    i = 0
+    j = 0
+  end
+end
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-28  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/78546
        * simplify-rtx.c (neg_const_int): When negating most negative
        number in mode wider than HOST_BITS_PER_WIDE_INT, use
        simplify_const_unary_operation to produce CONST_DOUBLE or
        CONST_WIDE_INT.
        (simplify_plus_minus): Hanlde the case where neg_const_int
        doesn't return a CONST_INT.

        * gcc.dg/torture/pr78546-1.c: New test.
        * gcc.dg/torture/pr78546-2.c: New test.

--- gcc/simplify-rtx.c  (revision 242928)
+++ gcc/simplify-rtx.c  (revision 242929)
@@ -56,12 +56,17 @@ static rtx simplify_unary_operation_1 (e
 static rtx simplify_binary_operation_1 (enum rtx_code, machine_mode,
                                        rtx, rtx, rtx, rtx);
 
-/* Negate a CONST_INT rtx, truncating (because a conversion from a
-   maximally negative number can overflow).  */
+/* Negate a CONST_INT rtx.  */
 static rtx
 neg_const_int (machine_mode mode, const_rtx i)
 {
-  return gen_int_mode (-(unsigned HOST_WIDE_INT) INTVAL (i), mode);
+  unsigned HOST_WIDE_INT val = -UINTVAL (i);
+  
+  if (GET_MODE_PRECISION (mode) > HOST_BITS_PER_WIDE_INT
+      && val == UINTVAL (i))
+    return simplify_const_unary_operation (NEG, mode, CONST_CAST_RTX (i),
+                                          mode);
+  return gen_int_mode (val, mode);
 }
 
 /* Test whether expression, X, is an immediate constant that represents
@@ -4507,9 +4512,12 @@ simplify_plus_minus (enum rtx_code code,
       rtx value = ops[n_ops - 1].op;
       if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg)
        value = neg_const_int (mode, value);
-      ops[n_ops - 2].op = plus_constant (mode, ops[n_ops - 2].op,
-                                        INTVAL (value));
-      n_ops--;
+      if (CONST_INT_P (value))
+       {
+         ops[n_ops - 2].op = plus_constant (mode, ops[n_ops - 2].op,
+                                            INTVAL (value));
+         n_ops--;
+       }
     }
 
   /* Put a non-negated operand first, if possible.  */
--- gcc/testsuite/gcc.dg/torture/pr78546-1.c    (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr78546-1.c    (revision 242929)
@@ -0,0 +1,22 @@
+/* PR rtl-optimization/78546 */
+/* { dg-do run { target int128 } } */
+
+typedef unsigned __int128 u128;
+u128 b;
+
+static inline u128
+foo (u128 p1)
+{
+  p1 += ~b;
+  return -p1;
+}
+
+int
+main ()
+{
+  asm volatile ("" : : : "memory");
+  u128 x = foo (~0x7fffffffffffffffLL);
+  if (x != 0x8000000000000001ULL)
+    __builtin_abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.dg/torture/pr78546-2.c    (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr78546-2.c    (revision 242929)
@@ -0,0 +1,16 @@
+/* PR rtl-optimization/78546 */
+/* { dg-do run { target int128 } } */
+
+typedef unsigned __int128 u128;
+u128 b;
+
+int
+main ()
+{
+  asm volatile ("" : : : "memory");
+  u128 x = ((u128) ~0x7fffffffffffffffLL) - b;
+  u128 y = 1 - x;
+  if (y != 0x8000000000000001ULL)
+    __builtin_abort ();
+  return 0;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-28  Jakub Jelinek  <ja...@redhat.com>
                    Jason Merrill  <ja...@redhat.com>

        PR c++/72808
        * decl.c (finish_enum_value_list): Call fixup_type_variants on
        current_class_type after
        insert_late_enum_def_into_classtype_sorted_fields.

        * g++.dg/debug/pr72808.C: New test.

--- gcc/cp/decl.c       (revision 242929)
+++ gcc/cp/decl.c       (revision 242930)
@@ -14280,8 +14280,11 @@ finish_enum_value_list (tree enumtype)
   if (at_class_scope_p ()
       && COMPLETE_TYPE_P (current_class_type)
       && UNSCOPED_ENUM_P (enumtype))
-    insert_late_enum_def_into_classtype_sorted_fields (enumtype,
-                                                      current_class_type);
+    {
+      insert_late_enum_def_into_classtype_sorted_fields (enumtype,
+                                                        current_class_type);
+      fixup_type_variants (current_class_type);
+    }
 
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (enumtype, namespace_bindings_p ());
--- gcc/testsuite/g++.dg/debug/pr72808.C        (revision 0)
+++ gcc/testsuite/g++.dg/debug/pr72808.C        (revision 242930)
@@ -0,0 +1,24 @@
+// PR c++/72808
+// { dg-do compile }
+// { dg-options "-g -std=c++14" }
+
+struct A
+{
+  virtual void foo ();
+};
+
+struct B : A
+{
+  void foo ();
+  enum C : int;
+};
+
+enum B::C : int
+{
+  D
+};
+
+void
+B::foo ()
+{
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-11-28  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/78540
        * rtl.h (remove_reg_equal_equiv_notes): Return bool instead of void.
        * rtlanal.c (remove_reg_equal_equiv_notes): Return true if any
        note has been removed.
        * postreload.c (reload_combine_recognize_pattern): If
        remove_reg_equal_equiv_notes returns true, call df_notes_rescan.

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

--- gcc/postreload.c    (revision 242936)
+++ gcc/postreload.c    (revision 242937)
@@ -1192,10 +1192,11 @@ reload_combine_recognize_pattern (rtx_in
              /* Delete the reg-reg addition.  */
              delete_insn (insn);
 
-             if (reg_state[regno].offset != const0_rtx)
-               /* Previous REG_EQUIV / REG_EQUAL notes for PREV
-                  are now invalid.  */
-               remove_reg_equal_equiv_notes (prev);
+             if (reg_state[regno].offset != const0_rtx
+                 /* Previous REG_EQUIV / REG_EQUAL notes for PREV
+                    are now invalid.  */
+                 && remove_reg_equal_equiv_notes (prev))
+               df_notes_rescan (prev);
 
              reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
              return true;
--- gcc/rtlanal.c       (revision 242936)
+++ gcc/rtlanal.c       (revision 242937)
@@ -2351,22 +2351,28 @@ remove_note (rtx_insn *insn, const_rtx n
     }
 }
 
-/* Remove REG_EQUAL and/or REG_EQUIV notes if INSN has such notes.  */
+/* Remove REG_EQUAL and/or REG_EQUIV notes if INSN has such notes.
+   Return true if any note has been removed.  */
 
-void
+bool
 remove_reg_equal_equiv_notes (rtx_insn *insn)
 {
   rtx *loc;
+  bool ret = false;
 
   loc = &REG_NOTES (insn);
   while (*loc)
     {
       enum reg_note kind = REG_NOTE_KIND (*loc);
       if (kind == REG_EQUAL || kind == REG_EQUIV)
-       *loc = XEXP (*loc, 1);
+       {
+         *loc = XEXP (*loc, 1);
+         ret = true;
+       }
       else
        loc = &XEXP (*loc, 1);
     }
+  return ret;
 }
 
 /* Remove all REG_EQUAL and REG_EQUIV notes referring to REGNO.  */
--- gcc/rtl.h   (revision 242936)
+++ gcc/rtl.h   (revision 242937)
@@ -2997,7 +2997,7 @@ extern void add_reg_note (rtx, enum reg_
 extern void add_int_reg_note (rtx, enum reg_note, int);
 extern void add_shallow_copy_of_reg_note (rtx_insn *, rtx);
 extern void remove_note (rtx, const_rtx);
-extern void remove_reg_equal_equiv_notes (rtx_insn *);
+extern bool remove_reg_equal_equiv_notes (rtx_insn *);
 extern void remove_reg_equal_equiv_notes_for_regno (unsigned int);
 extern int side_effects_p (const_rtx);
 extern int volatile_refs_p (const_rtx);
--- gcc/testsuite/gcc.dg/pr78540.c      (revision 0)
+++ gcc/testsuite/gcc.dg/pr78540.c      (revision 242937)
@@ -0,0 +1,27 @@
+/* PR middle-end/78540 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -Wno-psabi" } */
+/* { dg-additional-options "-march=core2" { target i?86-*-* x86_64-*-* } } */
+
+typedef unsigned __int128 V __attribute__ ((vector_size (64)));
+V g;
+
+static inline V
+foo (V a)
+{
+  V b, c;
+  c[0] = 0;
+  a += 2281559097;
+  c ^= 0;
+  b[0] = 0;
+  return 1 + c + b + a;
+}
+
+V
+bar ()
+{
+  V a = g, b = g;
+  a[1] ^= 1;
+  b[foo (a)[0] & 3] |= 1;
+  return b;
+}
2016-12-07  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2016-12-02  Jakub Jelinek  <ja...@redhat.com>

        PR c++/78649
        * pt.c (tsubst_init): Don't call build_value_init if decl's type
        is error_mark_node.

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

--- gcc/cp/pt.c (revision 243203)
+++ gcc/cp/pt.c (revision 243204)
@@ -14082,7 +14082,7 @@ tsubst_init (tree init, tree decl, tree
 
   init = tsubst_expr (init, args, complain, in_decl, false);
 
-  if (!init)
+  if (!init && TREE_TYPE (decl) != error_mark_node)
     {
       /* If we had an initializer but it
         instantiated to nothing,
--- gcc/testsuite/g++.dg/cpp0x/pr78649.C        (revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/pr78649.C        (revision 243204)
@@ -0,0 +1,16 @@
+// PR c++/78649
+// { dg-do compile { target c++11 } }
+
+template <class> void foo ();
+template <class T, class... U>
+void
+test ()
+{
+  T t (foo<U>...);     // { dg-error "declared void" }
+}
+
+int
+main ()
+{
+  test<void> ();
+}

Reply via email to