diff mbox series

Backports to 9.x

Message ID 20191220174925.GA10088@tucnak
State New
Headers show
Series Backports to 9.x | expand

Commit Message

Jakub Jelinek Dec. 20, 2019, 5:49 p.m. UTC
Hi!

I've backported following 25 patches from trunk to 9.x,
bootstrapped/regtested on x86_64-linux and i686-linux, committed
to gcc-9-branch.

	Jakub
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2019-11-21  Jakub Jelinek  <jakub@redhat.com>
		    Jason Merrill  <jason@redhat.com>

	PR c++/90842
	* parser.c (cp_parser_decl_specifier_seq): For concept or typedef
	break early if CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR.
	For type specifiers, set CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS
	if CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR is set.

	* g++.dg/cpp1y/lambda-generic-90842.C: New test.
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR c/90677
	* c-common.h (identifier_global_tag): Declare.
	* c-format.c (get_pointer_to_named_type): Renamed to ...
	(get_named_type): ... this.  Use identifier_global_tag instead of
	identifier_global_value, handle the return value being a TYPE_P.
	(init_dynamic_diag_info): Adjust get_pointer_to_named_type callers
	to call get_named_type instead.  Formatting fixes.

	* c-decl.c (identifier_global_tag): Define.

	* cp-objcp-common.c (identifier_global_tag): Define.

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

--- gcc/c-family/c-common.h	(revision 278633)
+++ gcc/c-family/c-common.h	(revision 278634)
@@ -800,6 +800,7 @@ extern void c_register_addr_space (const
 extern bool in_late_binary_op;
 extern const char *c_addr_space_name (addr_space_t as);
 extern tree identifier_global_value (tree);
+extern tree identifier_global_tag (tree);
 extern tree c_linkage_bindings (tree);
 extern void record_builtin_type (enum rid, const char *, tree);
 extern tree build_void_list_node (void);
--- gcc/c-family/c-format.c	(revision 278633)
+++ gcc/c-family/c-format.c	(revision 278634)
@@ -4899,31 +4899,32 @@ init_dynamic_gfc_info (void)
     }
 }
 
-/* Lookup the type named NAME and return a pointer-to-NAME type if found.
-   Otherwise, return void_type_node if NAME has not been used yet, or NULL_TREE if
-   NAME is not a type (issuing an error).  */
+/* Lookup the type named NAME and return a NAME type if found.
+   Otherwise, return void_type_node if NAME has not been used yet,
+   or NULL_TREE if NAME is not a type (issuing an error).  */
 
 static tree
-get_pointer_to_named_type (const char *name)
+get_named_type (const char *name)
 {
-  tree result;
-  if ((result = maybe_get_identifier (name)))
+  if (tree result = maybe_get_identifier (name))
     {
-      result = identifier_global_value (result);
+      result = identifier_global_tag (result);
       if (result)
 	{
-	  if (TREE_CODE (result) != TYPE_DECL)
+	  if (TYPE_P (result))
+	    ;
+	  else if (TREE_CODE (result) == TYPE_DECL)
+	    result = TREE_TYPE (result);
+	  else
 	    {
 	      error ("%qs is not defined as a type", name);
 	      result = NULL_TREE;
 	    }
-	  else
-	    result = TREE_TYPE (result);
 	}
+      return result;
     }
   else
-    result = void_type_node;
-  return result;
+    return void_type_node;
 }
 
 /* Determine the types of "tree" and "location_t" in the code being
@@ -4953,23 +4954,24 @@ init_dynamic_diag_info (void)
 	 an extra type level.  */
       if ((local_tree_type_node = maybe_get_identifier ("tree")))
 	{
-	  local_tree_type_node = identifier_global_value (local_tree_type_node);
+	  local_tree_type_node
+	    = identifier_global_value (local_tree_type_node);
 	  if (local_tree_type_node)
 	    {
 	      if (TREE_CODE (local_tree_type_node) != TYPE_DECL)
 		{
 		  error ("%<tree%> is not defined as a type");
-		  local_tree_type_node = 0;
+		  local_tree_type_node = NULL_TREE;
 		}
 	      else if (TREE_CODE (TREE_TYPE (local_tree_type_node))
 		       != POINTER_TYPE)
 		{
 		  error ("%<tree%> is not defined as a pointer type");
-		  local_tree_type_node = 0;
+		  local_tree_type_node = NULL_TREE;
 		}
 	      else
-		local_tree_type_node =
-		  TREE_TYPE (TREE_TYPE (local_tree_type_node));
+		local_tree_type_node
+		  = TREE_TYPE (TREE_TYPE (local_tree_type_node));
 	    }
 	}
       else
@@ -4979,12 +4981,12 @@ init_dynamic_diag_info (void)
   /* Similar to the above but for gimple*.  */
   if (!local_gimple_ptr_node
       || local_gimple_ptr_node == void_type_node)
-    local_gimple_ptr_node = get_pointer_to_named_type ("gimple");
+    local_gimple_ptr_node = get_named_type ("gimple");
 
   /* Similar to the above but for cgraph_node*.  */
   if (!local_cgraph_node_ptr_node
       || local_cgraph_node_ptr_node == void_type_node)
-    local_cgraph_node_ptr_node = get_pointer_to_named_type ("cgraph_node");
+    local_cgraph_node_ptr_node = get_named_type ("cgraph_node");
 
   static tree hwi;
 
--- gcc/c/c-decl.c	(revision 278633)
+++ gcc/c/c-decl.c	(revision 278634)
@@ -9941,6 +9941,20 @@ identifier_global_value	(tree t)
   return NULL_TREE;
 }
 
+/* Return the global value of tag T as a symbol.  */
+
+tree
+identifier_global_tag (tree t)
+{
+  struct c_binding *b;
+
+  for (b = I_TAG_BINDING (t); b; b = b->shadowed)
+    if (B_IN_FILE_SCOPE (b) || B_IN_EXTERNAL_SCOPE (b))
+      return b->decl;
+
+  return NULL_TREE;
+}
+
 /* In C, the only C-linkage public declaration is at file scope.  */
 
 tree
--- gcc/cp/cp-objcp-common.c	(revision 278633)
+++ gcc/cp/cp-objcp-common.c	(revision 278634)
@@ -352,6 +352,15 @@ identifier_global_value (tree name)
   return get_global_binding (name);
 }
 
+/* Similarly, but return struct/class/union NAME instead.  */
+
+tree
+identifier_global_tag (tree name)
+{
+  return lookup_qualified_name (global_namespace, name, /*prefer_type*/2,
+				/*complain*/false);
+}
+
 /* Register c++-specific dumps.  */
 
 void
--- gcc/testsuite/c-c++-common/pr90677.c	(nonexistent)
+++ gcc/testsuite/c-c++-common/pr90677.c	(revision 278634)
@@ -0,0 +1,11 @@
+/* PR c/90677 */
+/* { dg-do compile } */
+/* { dg-options "-W -Wall" } */
+
+struct cgraph_node;
+union tree_node;
+typedef union tree_node *tree;
+union gimple_statement_d;
+typedef union gimple_statement_d *gimple;
+struct cgraph_node *cgraph_node (tree);
+void foo (int, const char *, ...) __attribute__((__format__(__gcc_diag__, 2, 3)));
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR target/92615
	* config/i386/i386.c (ix86_md_asm_adjust): If dest_mode is
	GET_MODE (dest), is not QImode, using ZERO_EXTEND and dest is not
	register_operand, force x into register before storing it into dest.
	Formatting fix.

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

--- gcc/config/i386/i386.c	(revision 278641)
+++ gcc/config/i386/i386.c	(revision 278642)
@@ -20819,11 +20819,15 @@ ix86_md_asm_adjust (vec<rtx> &outputs, v
 	    {
 	      x = force_reg (dest_mode, const0_rtx);
 
-	      emit_insn (gen_movstrictqi
-			 (gen_lowpart (QImode, x), destqi));
+	      emit_insn (gen_movstrictqi (gen_lowpart (QImode, x), destqi));
 	    }
 	  else
-	    x = gen_rtx_ZERO_EXTEND (dest_mode, destqi);
+	    {
+	      x = gen_rtx_ZERO_EXTEND (dest_mode, destqi);
+	      if (dest_mode == GET_MODE (dest)
+		  && !register_operand (dest, GET_MODE (dest)))
+		x = force_reg (dest_mode, x);
+	    }
 	}
 
       if (dest_mode != GET_MODE (dest))
--- gcc/testsuite/gcc.target/i386/pr92615.c	(nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr92615.c	(revision 278642)
@@ -0,0 +1,45 @@
+/* PR target/92615 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void *a;
+long long b;
+char c;
+
+void
+foo (void)
+{
+  void *p;
+  long long q;
+  char r;
+  __asm__ ("" : : "r" (&p), "r" (&q), "r" (&r));
+  __asm__ ("" : "=@cca" (p));
+  a = p;
+  __asm__ ("" : "=@cca" (q));
+  b = q;
+  __asm__ ("" : "=@cca" (r));
+  c = r;
+  __asm__ ("" : : "r" (&p), "r" (&q), "r" (&r));
+}
+
+void
+bar (void)
+{
+  void *p;
+  long long q;
+  char r;
+  __asm__ ("" : "=@cca" (p));
+  a = p;
+  __asm__ ("" : "=@cca" (q));
+  b = q;
+  __asm__ ("" : "=@cca" (r));
+  c = r;
+  __asm__ ("" : : "r" (p), "A" (q), "q" (r));
+}
+
+void
+baz (void)
+{
+  void *p = (void *) &p;
+  __asm__ __volatile__ ("" : "=@ccng" (p) : "r" (1));
+}
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2019-11-26  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/92644
	* tree-ssa-phiopt.c (minmax_replacement): Add INTEGRAL_TYPE_P check
	next to INTEGER_CST checks.

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

--- gcc/tree-ssa-phiopt.c	(revision 278719)
+++ gcc/tree-ssa-phiopt.c	(revision 278720)
@@ -1381,7 +1381,8 @@ minmax_replacement (basic_block cond_bb,
 
   /* Turn EQ/NE of extreme values to order comparisons.  */
   if ((cmp == NE_EXPR || cmp == EQ_EXPR)
-      && TREE_CODE (rhs) == INTEGER_CST)
+      && TREE_CODE (rhs) == INTEGER_CST
+      && INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
     {
       if (wi::eq_p (wi::to_wide (rhs), wi::min_value (TREE_TYPE (rhs))))
 	{
@@ -1407,7 +1408,8 @@ minmax_replacement (basic_block cond_bb,
       larger = rhs;
       /* If we have smaller < CST it is equivalent to smaller <= CST-1.
 	 Likewise smaller <= CST is equivalent to smaller < CST+1.  */
-      if (TREE_CODE (larger) == INTEGER_CST)
+      if (TREE_CODE (larger) == INTEGER_CST
+	  && INTEGRAL_TYPE_P (TREE_TYPE (larger)))
 	{
 	  if (cmp == LT_EXPR)
 	    {
@@ -1435,7 +1437,8 @@ minmax_replacement (basic_block cond_bb,
       larger = gimple_cond_lhs (cond);
       /* If we have larger > CST it is equivalent to larger >= CST+1.
 	 Likewise larger >= CST is equivalent to larger > CST-1.  */
-      if (TREE_CODE (smaller) == INTEGER_CST)
+      if (TREE_CODE (smaller) == INTEGER_CST
+	  && INTEGRAL_TYPE_P (TREE_TYPE (smaller)))
 	{
 	  wi::overflow_type overflow;
 	  if (cmp == GT_EXPR)
--- gcc/testsuite/g++.dg/opt/pr92644.C	(nonexistent)
+++ gcc/testsuite/g++.dg/opt/pr92644.C	(revision 278720)
@@ -0,0 +1,6 @@
+// PR tree-optimization/92644
+// { dg-do compile { target c++14 } }
+// { dg-options "-O2 -fno-early-inlining" }
+
+inline auto foo () { return nullptr; }
+int bar () { return foo () ? 1 : 0; }
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2019-11-26  Jakub Jelinek  <jakub@redhat.com>

	PR sanitizer/92154
	* sanitizer_common/sanitizer_platform_limits_posix.h: Cherry-pick
	llvm-project revision 947f9692440836dcb8d88b74b69dd379d85974ce.
	* sanitizer_common/sanitizer_platform_limits_posix.cc: Likewise.

--- libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h	(revision 278721)
+++ libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h	(revision 278722)
@@ -211,26 +211,13 @@ namespace __sanitizer {
     u64 __unused1;
     u64 __unused2;
 #elif defined(__sparc__)
-#if defined(__arch64__)
     unsigned mode;
-    unsigned short __pad1;
-#else
-    unsigned short __pad1;
-    unsigned short mode;
     unsigned short __pad2;
-#endif
     unsigned short __seq;
     unsigned long long __unused1;
     unsigned long long __unused2;
-#elif defined(__mips__) || defined(__aarch64__) || defined(__s390x__)
-    unsigned int mode;
-    unsigned short __seq;
-    unsigned short __pad1;
-    unsigned long __unused1;
-    unsigned long __unused2;
 #else
-    unsigned short mode;
-    unsigned short __pad1;
+    unsigned int mode;
     unsigned short __seq;
     unsigned short __pad2;
 #if defined(__x86_64__) && !defined(_LP64)
--- libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc	(revision 278721)
+++ libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc	(revision 278722)
@@ -1156,12 +1156,9 @@ CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
 CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
 CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
 CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
-#if (!defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)) && \
-    !defined(__arm__)
-/* On aarch64 glibc 2.20 and earlier provided incorrect mode field.  */
-/* On Arm glibc 2.31 and later provide a different mode field, this field is
-   never used by libsanitizer so we can simply ignore this assert for all glibc
-   versions.  */
+#if !SANITIZER_LINUX || __GLIBC_PREREQ (2, 31)
+/* glibc 2.30 and earlier provided 16-bit mode field instead of 32-bit
+   on many architectures.  */
 CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
 #endif
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2019-11-26  Jakub Jelinek  <jakub@redhat.com>

	PR c++/61414
	* c-attribs.c (handle_mode_attribute): Add mode attribute to
	ENUMERAL_TYPEs.

	* class.c (enum_to_min_precision): New hash_map.
	(enum_min_precision): New function.
	(check_bitfield_decl): Use it.

	* g++.dg/cpp0x/enum23.C: Remove xfail.
	* g++.dg/cpp0x/enum28.C: New test.

--- gcc/c-family/c-attribs.c	(revision 278735)
+++ gcc/c-family/c-attribs.c	(revision 278736)
@@ -1866,6 +1866,7 @@ handle_mode_attribute (tree *node, tree
 		typefm = make_signed_type (TYPE_PRECISION (typefm));
 	      TREE_TYPE (typefm) = type;
 	    }
+	  *no_add_attrs = false;
 	}
       else if (VECTOR_MODE_P (mode)
 	       ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
--- gcc/cp/class.c	(revision 278735)
+++ gcc/cp/class.c	(revision 278736)
@@ -3265,6 +3265,60 @@ add_implicitly_declared_members (tree t,
     }
 }
 
+/* Cache of enum_min_precision values.  */
+static GTY((deletable)) hash_map<tree, int> *enum_to_min_precision;
+
+/* Return the minimum precision of a bit-field needed to store all
+   enumerators of ENUMERAL_TYPE TYPE.  */
+
+static int
+enum_min_precision (tree type)
+{
+  type = TYPE_MAIN_VARIANT (type);
+  /* For unscoped enums without fixed underlying type and without mode
+     attribute we can just use precision of the underlying type.  */
+  if (UNSCOPED_ENUM_P (type)
+      && !ENUM_FIXED_UNDERLYING_TYPE_P (type)
+      && !lookup_attribute ("mode", TYPE_ATTRIBUTES (type)))
+    return TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type));
+
+  if (enum_to_min_precision == NULL)
+    enum_to_min_precision = hash_map<tree, int>::create_ggc (37);
+
+  bool existed;
+  int prec = enum_to_min_precision->get_or_insert (type, &existed);
+  if (existed)
+    return prec;
+
+  tree minnode, maxnode;
+  if (TYPE_VALUES (type))
+    {
+      minnode = maxnode = NULL_TREE;
+      for (tree values = TYPE_VALUES (type);
+	   values; values = TREE_CHAIN (values))
+	{
+	  tree decl = TREE_VALUE (values);
+	  tree value = DECL_INITIAL (decl);
+	  if (value == error_mark_node)
+	    value = integer_zero_node;
+	  if (!minnode)
+	    minnode = maxnode = value;
+	  else if (tree_int_cst_lt (maxnode, value))
+	    maxnode = value;
+	  else if (tree_int_cst_lt (value, minnode))
+	    minnode = value;
+	}
+    }
+  else
+    minnode = maxnode = integer_zero_node;
+
+  signop sgn = tree_int_cst_sgn (minnode) >= 0 ? UNSIGNED : SIGNED;
+  int lowprec = tree_int_cst_min_precision (minnode, sgn);
+  int highprec = tree_int_cst_min_precision (maxnode, sgn);
+  prec = MAX (lowprec, highprec);
+  return prec;
+}
+
 /* FIELD is a bit-field.  We are finishing the processing for its
    enclosing type.  Issue any appropriate messages and set appropriate
    flags.  Returns false if an error has been diagnosed.  */
@@ -3326,7 +3380,7 @@ check_bitfield_decl (tree field)
 		    "width of %qD exceeds its type", field);
       else if (TREE_CODE (type) == ENUMERAL_TYPE)
 	{
-	  int prec = TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type));
+	  int prec = enum_min_precision (type);
 	  if (compare_tree_int (w, prec) < 0)
 	    warning_at (DECL_SOURCE_LOCATION (field), 0,
 			"%qD is too small to hold all values of %q#T",
--- gcc/testsuite/g++.dg/cpp0x/enum23.C	(revision 278735)
+++ gcc/testsuite/g++.dg/cpp0x/enum23.C	(revision 278736)
@@ -5,5 +5,5 @@ enum class MyEnum { A = 1 };
 
 struct MyClass
 {
-  MyEnum Field1 : 3; // { dg-bogus "warning: 'MyClass::Field1' is too small" "" { xfail *-*-* } }
+  MyEnum Field1 : 3; // { dg-bogus "warning: 'MyClass::Field1' is too small" }
 };
--- gcc/testsuite/g++.dg/cpp0x/enum38.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp0x/enum38.C	(revision 278736)
@@ -0,0 +1,25 @@
+// PR c++/61414
+// { dg-do compile { target c++11 } }
+
+enum C { C0 = -4, C1 = 3 };
+enum D { D0 = 0, D1 = 15 };
+enum class E { E0 = -4, E1 = 3 };
+enum F : unsigned { F0 = 0, F1 = 15 };
+enum __attribute__((__mode__ (__QI__))) G { G0 = -4, G1 = 3 };
+enum __attribute__((__mode__ (__HI__))) H { H0 = 0, H1 = 15 };
+
+struct S
+{
+  C a : 2;	// { dg-warning "'S::a' is too small to hold all values of 'enum C'" }
+  C b : 3;	// { dg-bogus "'S::b' is too small to hold all values of 'enum C'" }
+  D c : 3;	// { dg-warning "'S::c' is too small to hold all values of 'enum D'" }
+  D d : 4;	// { dg-bogus "'S::d' is too small to hold all values of 'enum D'" }
+  E e : 2;	// { dg-warning "'S::e' is too small to hold all values of 'enum class E'" }
+  E f : 3;	// { dg-bogus "'S::f' is too small to hold all values of 'enum class E'" }
+  F g : 3;	// { dg-warning "'S::g' is too small to hold all values of 'enum F'" }
+  F h : 4;	// { dg-bogus "'S::h' is too small to hold all values of 'enum F'" }
+  G i : 2;	// { dg-warning "'S::i' is too small to hold all values of 'enum G'" }
+  G j : 3;	// { dg-bogus "'S::j' is too small to hold all values of 'enum G'" }
+  H k : 3;	// { dg-warning "'S::k' is too small to hold all values of 'enum H'" }
+  H l : 4;	// { dg-bogus "'S::l' is too small to hold all values of 'enum H'" }
+};
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2019-11-26  Jakub Jelinek  <jakub@redhat.com>

	PR c++/92648
	* parser.c (cp_parser_std_attribute): For unknown attributes,
	skip balanced token seq instead of trying to parse
	attribute-argument-clause as expression list.

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

--- gcc/cp/parser.c	(revision 278736)
+++ gcc/cp/parser.c	(revision 278737)
@@ -2650,6 +2650,7 @@ static bool cp_parser_init_statement_p
   (cp_parser *);
 static bool cp_parser_skip_to_closing_square_bracket
   (cp_parser *);
+static size_t cp_parser_skip_balanced_tokens (cp_parser *, size_t);
 
 /* Concept-related syntactic transformations */
 
@@ -26189,6 +26190,17 @@ cp_parser_std_attribute (cp_parser *pars
       /* A GNU attribute that takes an identifier in parameter.  */
       attr_flag = id_attr;
 
+    const attribute_spec *as
+      = lookup_attribute_spec (TREE_PURPOSE (attribute));
+    if (as == NULL)
+      {
+	/* For unknown attributes, just skip balanced tokens instead of
+	   trying to parse the arguments.  */
+	for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n)
+	  cp_lexer_consume_token (parser->lexer);
+	return attribute;
+      }
+
     vec = cp_parser_parenthesized_expression_list
       (parser, attr_flag, /*cast_p=*/false,
        /*allow_expansion_p=*/true,
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-71.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-71.C	(revision 278737)
@@ -0,0 +1,7 @@
+// PR c++/92648
+// { dg-do compile { target c++11 } }
+
+int a [[gnu::no_such_attribute(![!(!)!]!,;;)]];	// { dg-warning "ignored" }
+int b [[no_such_namespace::nonexisting_attribute(linear(c, d : 2), reduction(*:e), linear(uval (f)))]];	// { dg-warning "ignored" }
+int c [[gnu::nonexisting_attribute()]];	// { dg-warning "ignored" }
+int d [[gnu::another_nonexistent_attr(1,"abcd",g+6)]];	// { dg-warning "ignored" }
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR debug/92664
	* dwarf2out.c (lookup_filename): Use "<stdin>" instead of "".

--- gcc/dwarf2out.c	(revision 278751)
+++ gcc/dwarf2out.c	(revision 278752)
@@ -27118,6 +27118,9 @@ lookup_filename (const char *file_name)
   if (!file_name)
     return NULL;
 
+  if (!file_name[0])
+    file_name = "<stdin>";
+
   dwarf_file_data **slot
     = file_table->find_slot_with_hash (file_name, htab_hash_string (file_name),
 				       INSERT);
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR c++/92524
	* tree.c (replace_placeholders_r): Don't walk constructor elts with
	RANGE_EXPR indexes.

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

--- gcc/cp/tree.c	(revision 278758)
+++ gcc/cp/tree.c	(revision 278759)
@@ -3144,6 +3144,11 @@ replace_placeholders_r (tree* t, int* wa
 	    tree type = TREE_TYPE (*valp);
 	    tree subob = obj;
 
+	    /* Elements with RANGE_EXPR index shouldn't have any
+	       placeholders in them.  */
+	    if (ce->index && TREE_CODE (ce->index) == RANGE_EXPR)
+	      continue;
+
 	    if (TREE_CODE (*valp) == CONSTRUCTOR
 		&& AGGREGATE_TYPE_P (type))
 	      {
--- gcc/testsuite/g++.dg/cpp0x/pr92524.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp0x/pr92524.C	(revision 278759)
@@ -0,0 +1,12 @@
+// PR c++/92524
+// { dg-do compile { target c++11 } }
+
+struct A { char a = '*'; };
+struct B { A b[64]; };
+
+void
+foo ()
+{
+  A a;
+  B{a};
+}
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR fortran/91944
	* simplify.c (gfc_simplify_spread): Check gfc_init_expr_flag instead
	of gfc_current_ns->sym_root->n.sym->attr.flavor == FL_PARAMETER.

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

--- gcc/fortran/simplify.c	(revision 278761)
+++ gcc/fortran/simplify.c	(revision 278762)
@@ -7656,7 +7656,7 @@ gfc_simplify_spread (gfc_expr *source, g
   nelem = mpz_get_si (size) * ncopies;
   if (nelem > flag_max_array_constructor)
     {
-      if (gfc_current_ns->sym_root->n.sym->attr.flavor == FL_PARAMETER)
+      if (gfc_init_expr_flag)
 	{
 	  gfc_error ("The number of elements (%d) in the array constructor "
 		     "at %L requires an increase of the allowed %d upper "
--- gcc/testsuite/gfortran.dg/spread_size_limit_2.f90	(nonexistent)
+++ gcc/testsuite/gfortran.dg/spread_size_limit_2.f90	(revision 278762)
@@ -0,0 +1,11 @@
+! PR fortran/91944
+! { dg-do compile }
+! { dg-options "-fmax-array-constructor=65535" }
+
+program pr91944
+  integer, parameter :: n = 10
+  integer, parameter :: m = 65536
+  integer :: i
+  integer :: x(n,m) = spread([(i,i=1,n)], dim=2, ncopies=m)	! { dg-error "requires an increase of the allowed 65535 upper limit" }
+  print *, x(n,m)
+end
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2019-11-28  Jakub Jelinek  <jakub@redhat.com>

	PR c++/92695
	* decl2.c (mark_used): Don't call note_vague_linkage_fn for pure
	virtual functions, even if they are declared inline.

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

--- gcc/cp/decl2.c	(revision 278801)
+++ gcc/cp/decl2.c	(revision 278802)
@@ -5596,8 +5596,11 @@ mark_used (tree decl, tsubst_flags_t com
 	vec_safe_push (no_linkage_decls, decl);
     }
 
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
-      && !DECL_INITIAL (decl) && !DECL_ARTIFICIAL (decl))
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_DECLARED_INLINE_P (decl)
+      && !DECL_INITIAL (decl)
+      && !DECL_ARTIFICIAL (decl)
+      && !DECL_PURE_VIRTUAL_P (decl))
     /* Remember it, so we can check it was defined.  */
     note_vague_linkage_fn (decl);
 
--- gcc/testsuite/g++.dg/warn/inline3.C	(nonexistent)
+++ gcc/testsuite/g++.dg/warn/inline3.C	(revision 278802)
@@ -0,0 +1,20 @@
+struct S {
+  inline virtual void foo () = 0;	// { dg-bogus "used but never defined" }
+#if __cplusplus > 201703L
+  constexpr virtual void bar () = 0;	// { dg-bogus "used but never defined" "" { target c++2a } }
+#else
+  inline virtual void bar () = 0;	// { dg-bogus "used but never defined" "" { target c++17_down }  }
+#endif
+  S () {}
+};
+struct T : public S {
+  inline virtual void foo () {}
+#if __cplusplus > 201703L
+  constexpr virtual void bar () {}
+#else
+  inline virtual void bar () {}
+#endif
+  T () {}
+};
+T t;
+void foo (S *s) { s->foo (); s->bar (); }
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR c++/60228
	* parser.c (cp_parser_omp_declare_reduction_exprs): If
	processing_template_decl, wrap the combiner or initializer
	into EXPR_STMT.
	* decl.c (start_preparsed_function): Don't start a lambda scope
	for DECL_OMP_DECLARE_REDUCTION_P functions.
	(finish_function): Don't finish a lambda scope for
	DECL_OMP_DECLARE_REDUCTION_P functions, nor cp_fold_function
	them nor cp_genericize them.
	* mangle.c (decl_mangling_context): Look through
	DECL_OMP_DECLARE_REDUCTION_P functions.
	* semantics.c (expand_or_defer_fn_1): For DECL_OMP_DECLARE_REDUCTION_P
	functions, use tentative linkage, don't keep their bodies with
	-fkeep-inline-functions and return false at the end.

	* g++.dg/gomp/openmp-simd-2.C: Don't expect bodies for
	DECL_OMP_DECLARE_REDUCTION_P functions.

	* testsuite/libgomp.c++/udr-20.C: New test.
	* testsuite/libgomp.c++/udr-21.C: New test.

--- gcc/cp/decl.c	(revision 278830)
+++ gcc/cp/decl.c	(revision 278831)
@@ -15632,7 +15632,8 @@ start_preparsed_function (tree decl1, tr
       && !implicit_default_ctor_p (decl1))
     cp_ubsan_maybe_initialize_vtbl_ptrs (current_class_ptr);
 
-  start_lambda_scope (decl1);
+  if (!DECL_OMP_DECLARE_REDUCTION_P (decl1))
+    start_lambda_scope (decl1);
 
   return true;
 }
@@ -16040,7 +16041,8 @@ finish_function (bool inline_p)
   if (fndecl == NULL_TREE)
     return error_mark_node;
 
-  finish_lambda_scope ();
+  if (!DECL_OMP_DECLARE_REDUCTION_P (fndecl))
+    finish_lambda_scope ();
 
   if (c_dialect_objc ())
     objc_finish_function ();
@@ -16157,7 +16159,7 @@ finish_function (bool inline_p)
     invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
 
   /* Perform delayed folding before NRV transformation.  */
-  if (!processing_template_decl)
+  if (!processing_template_decl && !DECL_OMP_DECLARE_REDUCTION_P (fndecl))
     cp_fold_function (fndecl);
 
   /* Set up the named return value optimization, if we can.  Candidate
@@ -16280,7 +16282,8 @@ finish_function (bool inline_p)
   if (!processing_template_decl)
     {
       struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
-      cp_genericize (fndecl);
+      if (!DECL_OMP_DECLARE_REDUCTION_P (fndecl))
+	cp_genericize (fndecl);
       /* Clear out the bits we don't need.  */
       f->x_current_class_ptr = NULL;
       f->x_current_class_ref = NULL;
--- gcc/cp/semantics.c	(revision 278830)
+++ gcc/cp/semantics.c	(revision 278831)
@@ -4417,7 +4417,7 @@ expand_or_defer_fn_1 (tree fn)
       if (DECL_INTERFACE_KNOWN (fn))
 	/* We've already made a decision as to how this function will
 	   be handled.  */;
-      else if (!at_eof)
+      else if (!at_eof || DECL_OMP_DECLARE_REDUCTION_P (fn))
 	tentative_decl_linkage (fn);
       else
 	import_export_decl (fn);
@@ -4429,5 +4431,6 @@ expand_or_defer_fn_1 (tree fn)
       if (DECL_DECLARED_INLINE_P (fn)
 	  && !DECL_REALLY_EXTERN (fn)
+	  && !DECL_OMP_DECLARE_REDUCTION_P (fn)
 	  && (flag_keep_inline_functions
 	      || (flag_keep_inline_dllexport
 		  && lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))))
@@ -4461,6 +4464,9 @@ expand_or_defer_fn_1 (tree fn)
       return false;
     }
 
+  if (DECL_OMP_DECLARE_REDUCTION_P (fn))
+    return false;
+
   return true;
 }
 
--- gcc/cp/parser.c	(revision 278830)
+++ gcc/cp/parser.c	(revision 278831)
@@ -41244,6 +41244,8 @@ cp_parser_omp_declare_reduction_exprs (t
   combiner = cp_parser_expression (parser);
   finish_expr_stmt (combiner);
   block = finish_omp_structured_block (block);
+  if (processing_template_decl)
+    block = build_stmt (input_location, EXPR_STMT, block);
   add_stmt (block);
 
   if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
@@ -41348,6 +41350,8 @@ cp_parser_omp_declare_reduction_exprs (t
 
       block = finish_omp_structured_block (block);
       cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL);
+      if (processing_template_decl)
+	block = build_stmt (input_location, EXPR_STMT, block);
       add_stmt (block);
 
       if (ctor)
--- gcc/cp/mangle.c	(revision 278830)
+++ gcc/cp/mangle.c	(revision 278831)
@@ -873,7 +873,16 @@ decl_mangling_context (tree decl)
   else if (template_type_parameter_p (decl))
      /* template type parms have no mangling context.  */
       return NULL_TREE;
-  return CP_DECL_CONTEXT (decl);
+
+  tcontext = CP_DECL_CONTEXT (decl);
+
+  /* Ignore the artificial declare reduction functions.  */
+  if (tcontext
+      && TREE_CODE (tcontext) == FUNCTION_DECL
+      && DECL_OMP_DECLARE_REDUCTION_P (tcontext))
+    return decl_mangling_context (tcontext);
+
+  return tcontext;
 }
 
 /* <name> ::= <unscoped-name>
--- gcc/testsuite/g++.dg/gomp/openmp-simd-2.C	(revision 278830)
+++ gcc/testsuite/g++.dg/gomp/openmp-simd-2.C	(revision 278831)
@@ -36,8 +36,6 @@ void bar(int n, float *a, float *b)
     a[i] = b[i];
 }
 
-/* { dg-final { scan-tree-dump-times "Function void omp declare reduction operator\\+" 1 "original" } } */
-/* { dg-final { scan-tree-dump-times "Function void omp declare reduction foo" 2 "original" } } */
 /* { dg-final { scan-tree-dump-times "pragma omp simd reduction\\(u\\) reduction\\(t\\) reduction\\(\\+:s\\) aligned\\(a:32\\)" 1 "original" } } */
 /* { dg-final { scan-tree-dump-times "pragma omp simd safelen\\(64\\)" 1 "original" } } */
 /* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
--- libgomp/testsuite/libgomp.c++/udr-20.C	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/udr-20.C	(revision 278832)
@@ -0,0 +1,54 @@
+// PR c++/60228
+// { dg-additional-options "-std=c++11" }
+
+extern "C" void abort ();
+
+struct A
+{
+  typedef int T;
+  #pragma omp declare reduction (x : T : omp_out += omp_in + [](){ return 0; }()) initializer (omp_priv = [](){ return 0; }())
+  static void foo ();
+};
+
+template <typename T>
+struct B
+{
+  #pragma omp declare reduction (x : T : omp_out += omp_in + [](){ return T (0); }()) initializer (omp_priv = [](){ return T (0); }())
+  static void foo ();
+};
+
+void
+A::foo ()
+{
+  int r = 0, s = 0;
+  #pragma omp parallel for reduction (x : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+template <typename T>
+void
+B<T>::foo ()
+{
+  T r = 0, s = 0;
+  #pragma omp parallel for reduction (x : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+int
+main ()
+{
+  A::foo ();
+  B<long>::foo ();
+}
--- libgomp/testsuite/libgomp.c++/udr-21.C	(nonexistent)
+++ libgomp/testsuite/libgomp.c++/udr-21.C	(revision 278832)
@@ -0,0 +1,54 @@
+// PR c++/60228
+// { dg-additional-options "-std=c++11" }
+
+extern "C" void abort ();
+
+struct A
+{
+  typedef int T;
+  #pragma omp declare reduction (y : T : [&omp_out, &omp_in]() { omp_out += omp_in; return 0; }()) initializer (omp_priv = [omp_orig]() { return omp_orig; }())
+  static void foo ();
+};
+
+template <typename T>
+struct B
+{
+  #pragma omp declare reduction (y : T : [&omp_out, &omp_in]() { omp_out += omp_in; return 0; }()) initializer (omp_priv = [omp_orig]() { return omp_orig; }())
+  static void foo ();
+};
+
+void
+A::foo ()
+{
+  int r = 0, s = 0;
+  #pragma omp parallel for reduction (y : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+template <typename T>
+void
+B<T>::foo ()
+{
+  T r = 0, s = 0;
+  #pragma omp parallel for reduction (y : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+int
+main ()
+{
+  A::foo ();
+  B<short>::foo ();
+}
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR c++/92695
	* constexpr.c (cxx_eval_constant_expression) <case OBJ_TYPE_REF>: Use
	STRIP_NOPS before checking for ADDR_EXPR.

	* g++.dg/cpp2a/constexpr-virtual15.C: New test.

--- gcc/cp/constexpr.c	(revision 278911)
+++ gcc/cp/constexpr.c	(revision 278912)
@@ -5548,6 +5548,7 @@ cxx_eval_constant_expression (const cons
 	tree obj = OBJ_TYPE_REF_OBJECT (t);
 	obj = cxx_eval_constant_expression (ctx, obj, lval, non_constant_p,
 					    overflow_p);
+	STRIP_NOPS (obj);
 	/* We expect something in the form of &x.D.2103.D.2094; get x. */
 	if (TREE_CODE (obj) != ADDR_EXPR
 	    || !DECL_P (get_base_address (TREE_OPERAND (obj, 0))))
--- gcc/testsuite/g++.dg/cpp2a/constexpr-virtual15.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp2a/constexpr-virtual15.C	(revision 278912)
@@ -0,0 +1,7 @@
+// PR c++/92695
+// { dg-do compile { target c++2a } }
+
+struct A { virtual int get() = 0; };
+struct B : A { constexpr int get() override { return 10; } };
+struct D { B b[2]; A* c{&(b[0])}; };
+static_assert(D{}.c->get() == 10);
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR c++/92695
	* constexpr.c (cxx_bind_parameters_in_call): For virtual calls,
	adjust the first argument to point to the derived object rather
	than its base.

	* g++.dg/cpp2a/constexpr-virtual14.C: New test.

--- gcc/cp/constexpr.c	(revision 278920)
+++ gcc/cp/constexpr.c	(revision 278921)
@@ -1419,6 +1419,28 @@ cxx_bind_parameters_in_call (const const
 	    arg = adjust_temp_type (type, arg);
 	  if (!TREE_CONSTANT (arg))
 	    *non_constant_args = true;
+
+	  /* For virtual calls, adjust the this argument, so that it is
+	     the object on which the method is called, rather than
+	     one of its bases.  */
+	  if (i == 0 && DECL_VIRTUAL_P (fun))
+	    {
+	      tree addr = arg;
+	      STRIP_NOPS (addr);
+	      if (TREE_CODE (addr) == ADDR_EXPR)
+		{
+		  tree obj = TREE_OPERAND (addr, 0);
+		  while (TREE_CODE (obj) == COMPONENT_REF
+			 && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1))
+			 && !same_type_ignoring_top_level_qualifiers_p
+					(TREE_TYPE (obj), DECL_CONTEXT (fun)))
+		    obj = TREE_OPERAND (obj, 0);
+		  if (obj != TREE_OPERAND (addr, 0))
+		    arg = build_fold_addr_expr_with_type (obj,
+							  TREE_TYPE (arg));
+		}
+	    }
+
 	  *p = build_tree_list (parms, arg);
 	  p = &TREE_CHAIN (*p);
 	}
--- gcc/testsuite/g++.dg/cpp2a/constexpr-virtual14.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp2a/constexpr-virtual14.C	(revision 278921)
@@ -0,0 +1,27 @@
+// PR c++/92695
+// { dg-do compile { target c++2a } }
+
+struct A {
+  virtual int get () = 0;
+  virtual int set (A *o) = 0;
+};
+struct B : A {
+  constexpr int get () override { return 10; }
+  constexpr int set (A *o) override { a = o; return 20; }
+  A *a {};
+};
+constexpr auto addressof = [] (A &n) { return &n; };
+struct C {
+  B b;
+  A *c { addressof (b) };
+  constexpr int add () { return c->set (addressof (b)); }
+};
+struct D {
+  B b[2];
+  A *c { addressof (b[0]) };
+  constexpr int add () { return c->set (addressof (b[0])); }
+};
+template <typename T>
+constexpr int get () { T f; return f.add (); }
+static_assert (get<C> () == 20);
+static_assert (get<D> () == 20);
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR c++/92732
	* typeck2.c (digest_nsdmi_init): For bitfields, use
	DECL_BIT_FIELD_TYPE instead of TREE_TYPE.

	* g++.dg/cpp2a/bitfield3.C: Don't expect narrowing conversion
	warnings.
	* g++.dg/cpp2a/bitfield4.C: New test.

--- gcc/cp/typeck2.c	(revision 278922)
+++ gcc/cp/typeck2.c	(revision 278923)
@@ -1335,6 +1335,8 @@ digest_nsdmi_init (tree decl, tree init,
   gcc_assert (TREE_CODE (decl) == FIELD_DECL);
 
   tree type = TREE_TYPE (decl);
+  if (DECL_BIT_FIELD_TYPE (decl))
+    type = DECL_BIT_FIELD_TYPE (decl);
   int flags = LOOKUP_IMPLICIT;
   if (DIRECT_LIST_INIT_P (init))
     {
--- gcc/testsuite/g++.dg/cpp2a/bitfield3.C	(revision 278922)
+++ gcc/testsuite/g++.dg/cpp2a/bitfield3.C	(revision 278923)
@@ -15,11 +15,9 @@ const int b = 0;
 struct S {
   int c : 5 = 2 * a;			// { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
   int d : 6 { c + a };			// { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
-					// { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
   int e : true ? 7 : a = 3;
   int f : (true ? 8 : b) = d + a;	// { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
   int g : (true ? 9 : b) { f + a };	// { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
-					// { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
   int h : 1 || new int { 0 };
   int i = g + a;
 };
@@ -28,11 +26,9 @@ template <bool V, int W>
 struct U {
   int j : W = 3 * a;			// { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
   int k : W { j + a };			// { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
-					// { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
   int l : V ? 7 : a = 3;
   int m : (V ? W : b) = k + a;		// { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
   int n : (V ? W : b) { m + a };	// { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
-					// { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
   int o : 1 || new int { 0 };
   int p = n + a;
 };
--- gcc/testsuite/g++.dg/cpp2a/bitfield4.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp2a/bitfield4.C	(revision 278923)
@@ -0,0 +1,12 @@
+// PR c++/92732
+// { dg-do compile { target c++17 } }
+// { dg-options "" }
+
+enum class byte : unsigned char { };
+using uint8_t = unsigned char;
+
+struct T
+{
+  byte a : 2 = byte{0};	// { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+  uint8_t b : 2 = 0;	// { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+} t;
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/92756
	* omp-low.c (check_omp_nesting_restrictions): If lang_GNU_Fortran,
	diagnose teams not closely nested inside of target.

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

	PR fortran/92756
	* gfortran.dg/gomp/teams1.f90: New test.

--- gcc/omp-low.c.jj	2019-08-01 08:29:30.880772337 +0200
+++ gcc/omp-low.c	2019-12-20 15:29:59.052918458 +0100
@@ -3041,6 +3041,16 @@ check_omp_nesting_restrictions (gimple *
       }
       break;
     case GIMPLE_OMP_TEAMS:
+      if ((ctx == NULL
+           || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
+           || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
+	  && lang_GNU_Fortran ())
+	{
+	  error_at (gimple_location (stmt),
+		    "%<teams%> construct not closely nested inside of "
+		    "%<target%> construct");
+	  return false;
+	}
       if (ctx == NULL)
 	break;
       else if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
--- gcc/testsuite/gfortran.dg/gomp/teams1.f90	(nonexistent)
+++ gcc/testsuite/gfortran.dg/gomp/teams1.f90	(revision 278956)
@@ -0,0 +1,8 @@
+! PR fortran/92756
+
+program pr92756
+  integer :: i
+  !$omp teams distribute parallel do	! { dg-error "'teams' construct not closely nested inside of 'target' construct" }
+  do i = 1, 64
+  end do
+end
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR fortran/92781
	* trans-decl.c (gfc_get_symbol_decl): If sym->backend_decl is
	current_function_decl, add length to current rather than parent
	function and expect DECL_CONTEXT (length) to be current_function_decl.

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

--- gcc/fortran/trans-decl.c	(revision 278987)
+++ gcc/fortran/trans-decl.c	(revision 278988)
@@ -1631,15 +1631,18 @@ gfc_get_symbol_decl (gfc_symbol * sym)
 	      /* Add the string length to the same context as the symbol.  */
 	      if (DECL_CONTEXT (length) == NULL_TREE)
 		{
-		  if (DECL_CONTEXT (sym->backend_decl)
-		      == current_function_decl)
+		  if (sym->backend_decl == current_function_decl
+		      || (DECL_CONTEXT (sym->backend_decl)
+			  == current_function_decl))
 		    gfc_add_decl_to_function (length);
 		  else
 		    gfc_add_decl_to_parent_function (length);
 		}
 
-	      gcc_assert (DECL_CONTEXT (sym->backend_decl)
-			  == DECL_CONTEXT (length));
+	      gcc_assert (sym->backend_decl == current_function_decl
+			  ? DECL_CONTEXT (length) == current_function_decl
+			  : (DECL_CONTEXT (sym->backend_decl)
+			     == DECL_CONTEXT (length)));
 
 	      gfc_defer_symbol_init (sym);
 	    }
--- gcc/testsuite/gfortran.dg/pr92781.f90	(nonexistent)
+++ gcc/testsuite/gfortran.dg/pr92781.f90	(revision 278988)
@@ -0,0 +1,11 @@
+! PR fortran/92781
+! { dg-do compile }
+
+function foo ()
+  character(:), allocatable :: foo
+  call bar ()
+  foo = 'abc'
+contains
+  subroutine bar
+  end
+end
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR fortran/92775
	* trans.h (struct lang_type, struct lang_decl): Remove span member.
	(GFC_DECL_SPAN, GFC_TYPE_ARRAY_SPAN): Remove macros.
	* trans-array.h (gfc_get_descriptor_offsets_for_info): Add another
	argument.
	* trans-array.c (gfc_get_descriptor_offsets_for_info): Add SPAN_OFF
	argument and initialize *SPAN_OFF to the offset of span field.
	* trans-types.c (gfc_get_array_descr_info): Adjust
	gfc_get_descriptor_offsets_for_info caller.  Compute elem_size
	as base->span instead of TYPE_SIZE_UNIT (etype) constant.

--- gcc/fortran/trans-array.h	(revision 279044)
+++ gcc/fortran/trans-array.h	(revision 279045)
@@ -163,7 +163,7 @@ void gfc_trans_array_cobounds (tree, stm
 
 /* Build expressions for accessing components of an array descriptor.  */
 void gfc_get_descriptor_offsets_for_info (const_tree, tree *, tree *, tree *, tree *,
-					  tree *, tree *, tree *);
+					  tree *, tree *, tree *, tree *);
 
 tree gfc_conv_descriptor_data_get (tree);
 tree gfc_conv_descriptor_data_addr (tree);
--- gcc/fortran/trans-array.c	(revision 279044)
+++ gcc/fortran/trans-array.c	(revision 279045)
@@ -540,9 +540,10 @@ gfc_conv_shift_descriptor_lbound (stmtbl
 
 void
 gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
-				     tree *dtype_off, tree *dim_off,
-				     tree *dim_size, tree *stride_suboff,
-				     tree *lower_suboff, tree *upper_suboff)
+				     tree *dtype_off, tree *span_off,
+				     tree *dim_off, tree *dim_size,
+				     tree *stride_suboff, tree *lower_suboff,
+				     tree *upper_suboff)
 {
   tree field;
   tree type;
@@ -552,6 +553,8 @@ gfc_get_descriptor_offsets_for_info (con
   *data_off = byte_position (field);
   field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
   *dtype_off = byte_position (field);
+  field = gfc_advance_chain (TYPE_FIELDS (type), SPAN_FIELD);
+  *span_off = byte_position (field);
   field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
   *dim_off = byte_position (field);
   type = TREE_TYPE (TREE_TYPE (field));
--- gcc/fortran/trans-types.c	(revision 279044)
+++ gcc/fortran/trans-types.c	(revision 279045)
@@ -3266,7 +3266,7 @@ gfc_get_array_descr_info (const_tree typ
   int rank, dim;
   bool indirect = false;
   tree etype, ptype, t, base_decl;
-  tree data_off, dim_off, dtype_off, dim_size, elem_size;
+  tree data_off, span_off, dim_off, dtype_off, dim_size, elem_size;
   tree lower_suboff, upper_suboff, stride_suboff;
   tree dtype, field, rank_off;
 
@@ -3323,12 +3323,13 @@ gfc_get_array_descr_info (const_tree typ
   if (indirect)
     base_decl = build1 (INDIRECT_REF, ptype, base_decl);
 
-  elem_size = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (etype));
-
-  gfc_get_descriptor_offsets_for_info (type, &data_off, &dtype_off, &dim_off,
-				       &dim_size, &stride_suboff,
+  gfc_get_descriptor_offsets_for_info (type, &data_off, &dtype_off, &span_off,
+				       &dim_off, &dim_size, &stride_suboff,
 				       &lower_suboff, &upper_suboff);
 
+  t = fold_build_pointer_plus (base_decl, span_off);
+  elem_size = build1 (INDIRECT_REF, gfc_array_index_type, t);
+
   t = base_decl;
   if (!integer_zerop (data_off))
     t = fold_build_pointer_plus (t, data_off);
--- gcc/fortran/trans.h	(revision 279044)
+++ gcc/fortran/trans.h	(revision 279045)
@@ -981,7 +981,6 @@ struct GTY(())	lang_type	 {
   tree offset;
   tree dtype;
   tree dataptr_type;
-  tree span;
   tree base_decl[2];
   tree nonrestricted_type;
   tree caf_token;
@@ -997,7 +996,6 @@ struct GTY(()) lang_decl {
      address of target label.  */
   tree stringlen;
   tree addr;
-  tree span;
   /* For assumed-shape coarrays.  */
   tree token, caf_offset;
   unsigned int scalar_allocatable : 1;
@@ -1008,7 +1006,6 @@ struct GTY(()) lang_decl {
 
 #define GFC_DECL_ASSIGN_ADDR(node) DECL_LANG_SPECIFIC(node)->addr
 #define GFC_DECL_STRING_LEN(node) DECL_LANG_SPECIFIC(node)->stringlen
-#define GFC_DECL_SPAN(node) DECL_LANG_SPECIFIC(node)->span
 #define GFC_DECL_TOKEN(node) DECL_LANG_SPECIFIC(node)->token
 #define GFC_DECL_CAF_OFFSET(node) DECL_LANG_SPECIFIC(node)->caf_offset
 #define GFC_DECL_SAVED_DESCRIPTOR(node) \
@@ -1059,7 +1056,6 @@ struct GTY(()) lang_decl {
 #define GFC_TYPE_ARRAY_DTYPE(node) (TYPE_LANG_SPECIFIC(node)->dtype)
 #define GFC_TYPE_ARRAY_DATAPTR_TYPE(node) \
   (TYPE_LANG_SPECIFIC(node)->dataptr_type)
-#define GFC_TYPE_ARRAY_SPAN(node) (TYPE_LANG_SPECIFIC(node)->span)
 #define GFC_TYPE_ARRAY_BASE_DECL(node, internal) \
   (TYPE_LANG_SPECIFIC(node)->base_decl[(internal)])
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR c++/92831 - CWG 1299, not extending temporary lifetime for ?:
	* cp-tree.h (extend_ref_init_temps): Add a new argument with NULL
	default arg.
	* call.c (set_up_extended_ref_temp): Add COND_GUARD argument, pass it
	down to extend_ref_init_temps.  Before pushing cleanup, if COND_GUARD
	is non-NULL, create a bool temporary if needed, initialize to false
	and guard the cleanup with the temporary being true.
	(extend_ref_init_temps_1): Add COND_GUARD argument, pass it down
	to recursive calls and set_up_extended_ref_temp.  Handle COND_EXPR.
	(extend_ref_init_temps): Add COND_GUARD argument, pass it down to
	recursive calls and to extend_ref_init_temps_1.

	* g++.dg/cpp0x/temp-extend2.C: New test.

--- gcc/cp/cp-tree.h	(revision 279063)
+++ gcc/cp/cp-tree.h	(revision 279064)
@@ -6321,7 +6321,9 @@ extern tree convert_for_arg_passing		(tr
 extern bool is_properly_derived_from		(tree, tree);
 extern tree initialize_reference		(tree, tree, int,
 						 tsubst_flags_t);
-extern tree extend_ref_init_temps		(tree, tree, vec<tree, va_gc>**);
+extern tree extend_ref_init_temps		(tree, tree,
+						 vec<tree, va_gc>**,
+						 tree * = NULL);
 extern tree make_temporary_var_for_ref_to_temp	(tree, tree);
 extern bool type_has_extended_temps		(tree);
 extern tree strip_top_quals			(tree);
--- gcc/cp/call.c	(revision 279063)
+++ gcc/cp/call.c	(revision 279064)
@@ -11449,7 +11449,7 @@ make_temporary_var_for_ref_to_temp (tree
 
 static tree
 set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
-			  tree *initp)
+			  tree *initp, tree *cond_guard)
 {
   tree init;
   tree type;
@@ -11480,7 +11480,8 @@ set_up_extended_ref_temp (tree decl, tre
 
   /* Recursively extend temps in this initializer.  */
   TARGET_EXPR_INITIAL (expr)
-    = extend_ref_init_temps (decl, TARGET_EXPR_INITIAL (expr), cleanups);
+    = extend_ref_init_temps (decl, TARGET_EXPR_INITIAL (expr), cleanups,
+			     cond_guard);
 
   /* Any reference temp has a non-trivial initializer.  */
   DECL_NONTRIVIALLY_INITIALIZED_P (var) = true;
@@ -11521,7 +11522,29 @@ set_up_extended_ref_temp (tree decl, tre
 	{
 	  tree cleanup = cxx_maybe_build_cleanup (var, tf_warning_or_error);
 	  if (cleanup)
-	    vec_safe_push (*cleanups, cleanup);
+	    {
+	      if (cond_guard && cleanup != error_mark_node)
+		{
+		  if (*cond_guard == NULL_TREE)
+		    {
+		      *cond_guard = build_decl (input_location, VAR_DECL,
+						NULL_TREE, boolean_type_node);
+		      DECL_ARTIFICIAL (*cond_guard) = 1;
+		      DECL_IGNORED_P (*cond_guard) = 1;
+		      DECL_CONTEXT (*cond_guard) = current_function_decl;
+		      layout_decl (*cond_guard, 0);
+		      add_decl_expr (*cond_guard);
+		      tree set = cp_build_modify_expr (UNKNOWN_LOCATION,
+						       *cond_guard, NOP_EXPR,
+						       boolean_false_node,
+						       tf_warning_or_error);
+		      finish_expr_stmt (set);
+		    }
+		  cleanup = build3 (COND_EXPR, void_type_node,
+				    *cond_guard, cleanup, NULL_TREE);
+		}
+	      vec_safe_push (*cleanups, cleanup);
+	    }
 	}
 
       /* We must be careful to destroy the temporary only
@@ -11626,7 +11649,8 @@ initialize_reference (tree type, tree ex
    which is bound either to a reference or a std::initializer_list.  */
 
 static tree
-extend_ref_init_temps_1 (tree decl, tree init, vec<tree, va_gc> **cleanups)
+extend_ref_init_temps_1 (tree decl, tree init, vec<tree, va_gc> **cleanups,
+			 tree *cond_guard)
 {
   tree sub = init;
   tree *p;
@@ -11634,20 +11658,52 @@ extend_ref_init_temps_1 (tree decl, tree
   if (TREE_CODE (sub) == COMPOUND_EXPR)
     {
       TREE_OPERAND (sub, 1)
-        = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 1), cleanups);
+	= extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 1), cleanups,
+				   cond_guard);
+      return init;
+    }
+  if (TREE_CODE (sub) == COND_EXPR)
+    {
+      tree cur_cond_guard = NULL_TREE;
+      if (TREE_OPERAND (sub, 1))
+	TREE_OPERAND (sub, 1)
+	  = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 1), cleanups,
+				     &cur_cond_guard);
+      if (cur_cond_guard)
+	{
+	  tree set = cp_build_modify_expr (UNKNOWN_LOCATION, cur_cond_guard,
+					   NOP_EXPR, boolean_true_node,
+					   tf_warning_or_error);
+	  TREE_OPERAND (sub, 1)
+	    = cp_build_compound_expr (set, TREE_OPERAND (sub, 1),
+				      tf_warning_or_error);
+	}
+      cur_cond_guard = NULL_TREE;
+      if (TREE_OPERAND (sub, 2))
+	TREE_OPERAND (sub, 2)
+	  = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 2), cleanups,
+				     &cur_cond_guard);
+      if (cur_cond_guard)
+	{
+	  tree set = cp_build_modify_expr (UNKNOWN_LOCATION, cur_cond_guard,
+					   NOP_EXPR, boolean_true_node,
+					   tf_warning_or_error);
+	  TREE_OPERAND (sub, 2)
+	    = cp_build_compound_expr (set, TREE_OPERAND (sub, 2),
+				      tf_warning_or_error);
+	}
       return init;
     }
   if (TREE_CODE (sub) != ADDR_EXPR)
     return init;
   /* Deal with binding to a subobject.  */
   for (p = &TREE_OPERAND (sub, 0);
-       (TREE_CODE (*p) == COMPONENT_REF
-	|| TREE_CODE (*p) == ARRAY_REF); )
+       TREE_CODE (*p) == COMPONENT_REF || TREE_CODE (*p) == ARRAY_REF; )
     p = &TREE_OPERAND (*p, 0);
   if (TREE_CODE (*p) == TARGET_EXPR)
     {
       tree subinit = NULL_TREE;
-      *p = set_up_extended_ref_temp (decl, *p, cleanups, &subinit);
+      *p = set_up_extended_ref_temp (decl, *p, cleanups, &subinit, cond_guard);
       recompute_tree_invariant_for_addr_expr (sub);
       if (init != sub)
 	init = fold_convert (TREE_TYPE (init), sub);
@@ -11662,13 +11718,14 @@ extend_ref_init_temps_1 (tree decl, tree
    lifetime to match that of DECL.  */
 
 tree
-extend_ref_init_temps (tree decl, tree init, vec<tree, va_gc> **cleanups)
+extend_ref_init_temps (tree decl, tree init, vec<tree, va_gc> **cleanups,
+		       tree *cond_guard)
 {
   tree type = TREE_TYPE (init);
   if (processing_template_decl)
     return init;
   if (TYPE_REF_P (type))
-    init = extend_ref_init_temps_1 (decl, init, cleanups);
+    init = extend_ref_init_temps_1 (decl, init, cleanups, cond_guard);
   else
     {
       tree ctor = init;
@@ -11681,7 +11738,8 @@ extend_ref_init_temps (tree decl, tree i
 	      /* The temporary array underlying a std::initializer_list
 		 is handled like a reference temporary.  */
 	      tree array = CONSTRUCTOR_ELT (ctor, 0)->value;
-	      array = extend_ref_init_temps_1 (decl, array, cleanups);
+	      array = extend_ref_init_temps_1 (decl, array, cleanups,
+					       cond_guard);
 	      CONSTRUCTOR_ELT (ctor, 0)->value = array;
 	    }
 	  else
@@ -11690,7 +11748,8 @@ extend_ref_init_temps (tree decl, tree i
 	      constructor_elt *p;
 	      vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
 	      FOR_EACH_VEC_SAFE_ELT (elts, i, p)
-		p->value = extend_ref_init_temps (decl, p->value, cleanups);
+		p->value = extend_ref_init_temps (decl, p->value, cleanups,
+						  cond_guard);
 	    }
 	  recompute_constructor_flags (ctor);
 	  if (decl_maybe_constant_var_p (decl) && TREE_CONSTANT (ctor))
--- gcc/testsuite/g++.dg/cpp0x/temp-extend2.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp0x/temp-extend2.C	(revision 279064)
@@ -0,0 +1,36 @@
+// PR c++/92831
+// { dg-do run { target c++11 } }
+
+template<typename T> using id = T;
+struct S { S () { s++; } ~S () { s--; } S (int) { s++; } static int s; };
+int S::s = 0;
+
+void
+bar (bool cond, bool cond2)
+{
+  if (S::s != (cond ? cond2 ? 7 : 5 : cond2 ? 8 : 9))
+    __builtin_abort ();
+}
+
+void
+foo (bool cond, bool cond2)
+{
+  int i = 1;
+  // temporary array has same lifetime as a
+  S&& a = id<S[3]>{1, 2, 3}[i];
+  // temporary S has same lifetime as b
+  const S& b = static_cast<const S&>(0);
+  // exactly one of the four temporaries is lifetime-extended
+  S&& c = cond ? cond2 ? id<S[3]>{1, 2, 3}[i] : static_cast<S&&>(0)
+	       : cond2 ? id<S[4]>{1, 2, 3, 4}[i] : id<S[5]>{1, 2, 3, 4, 5}[i];
+  bar (cond, cond2);
+}
+
+int
+main ()
+{
+  foo (true, true);
+  foo (true, false);
+  foo (false, true);
+  foo (false, false);
+}
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR target/92723
	* tree-vect-patterns.c (vect_recog_rotate_pattern): If dt is not
	vect_internal_def, use oprnd1 as is, without trying to cast it.
	Formatting fix.

	* gcc.dg/vect/pr92723.c: New test.

--- gcc/tree-vect-patterns.c	(revision 279264)
+++ gcc/tree-vect-patterns.c	(revision 279265)
@@ -2070,14 +2070,12 @@ vect_recog_rotate_pattern (stmt_vec_info
 
   *type_out = vectype;
 
-  if (dt == vect_external_def
-      && TREE_CODE (oprnd1) == SSA_NAME)
+  if (dt == vect_external_def && TREE_CODE (oprnd1) == SSA_NAME)
     ext_def = vect_get_external_def_edge (vinfo, oprnd1);
 
   def = NULL_TREE;
   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
-  if (TREE_CODE (oprnd1) == INTEGER_CST
-      || TYPE_MODE (TREE_TYPE (oprnd1)) == mode)
+  if (dt != vect_internal_def || TYPE_MODE (TREE_TYPE (oprnd1)) == mode)
     def = oprnd1;
   else if (def_stmt && gimple_assign_cast_p (def_stmt))
     {
@@ -2092,14 +2090,7 @@ vect_recog_rotate_pattern (stmt_vec_info
     {
       def = vect_recog_temp_ssa_var (type, NULL);
       def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd1);
-      if (ext_def)
-	{
-	  basic_block new_bb
-	    = gsi_insert_on_edge_immediate (ext_def, def_stmt);
-	  gcc_assert (!new_bb);
-	}
-      else
-	append_pattern_def_seq (stmt_vinfo, def_stmt);
+      append_pattern_def_seq (stmt_vinfo, def_stmt);
     }
   stype = TREE_TYPE (def);
   scalar_int_mode smode = SCALAR_INT_TYPE_MODE (stype);
--- gcc/testsuite/gcc.dg/vect/pr92723.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/vect/pr92723.c	(revision 279265)
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+void
+foo (unsigned long long *x, unsigned long long *y, int z)
+{
+  int i;
+  for (i = 0; i < 1024; i++)
+    x[i] = (y[i] >> z) | (y[i] << (-z & (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1)));
+}
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR fortran/92899
	* trans-openmp.c (gfc_trans_omp_atomic): For GFC_OMP_ATOMIC_SWAP,
	do look through conversion on expr2 if any.

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

--- gcc/fortran/trans-openmp.c	(revision 279265)
+++ gcc/fortran/trans-openmp.c	(revision 279266)
@@ -3534,7 +3534,6 @@ gfc_trans_omp_atomic (gfc_code *code)
   expr2 = code->expr2;
   if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
        != GFC_OMP_ATOMIC_WRITE)
-      && (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP) == 0
       && expr2->expr_type == EXPR_FUNCTION
       && expr2->value.function.isym
       && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
--- libgomp/testsuite/libgomp.fortran/atomic1.f90	(nonexistent)
+++ libgomp/testsuite/libgomp.fortran/atomic1.f90	(revision 279266)
@@ -0,0 +1,46 @@
+! PR fortran/92899
+
+program pr92899
+  real :: x = 1.0
+  double precision :: y
+  integer(kind=4) :: z = 4
+  integer(kind=8) :: w
+  !$omp atomic capture
+  y = x
+  x = 2.0
+  !$omp end atomic
+  if (y /= 1.0 .or. x /= 2.0) stop 1
+  !$omp atomic capture
+  x = y
+  y = 3.0
+  !$omp end atomic
+  if (x /= 1.0 .or. y /= 3.0) stop 2
+  !$omp atomic capture
+  w = z
+  z = 5
+  !$omp end atomic
+  if (w /= 4 .or. z /= 5) stop 3
+  !$omp atomic capture
+  z = w
+  w = 6
+  !$omp end atomic
+  if (z /= 4 .or. w /= 6) stop 4
+  !$omp atomic write
+  x = y
+  !$omp end atomic
+  if (x /= 3.0 .or. y /= 3.0) stop 5
+  x = 7.0
+  !$omp atomic write
+  y = x
+  !$omp end atomic
+  if (x /= 7.0 .or. y /= 7.0) stop 6
+  !$omp atomic write
+  z = w
+  !$omp end atomic
+  if (z /= 6 .or. w /= 6) stop 7
+  z = 8
+  !$omp atomic write
+  w = z
+  !$omp end atomic
+  if (z /= 8 .or. w /= 8) stop 8
+end
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR target/92904
	* config/i386/i386.c (ix86_gimplify_va_arg): If need_intregs and
	not need_temp, decrease alignment of the read because the GPR save
	area only guarantees 8-byte alignment.

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

--- gcc/config/i386/i386.c	(revision 279326)
+++ gcc/config/i386/i386.c	(revision 279327)
@@ -4277,6 +4277,7 @@ ix86_gimplify_va_arg (tree valist, tree
   tree ptrtype;
   machine_mode nat_mode;
   unsigned int arg_boundary;
+  unsigned int type_align;
 
   /* Only 64bit target needs something special.  */
   if (is_va_list_char_pointer (TREE_TYPE (valist)))
@@ -4334,6 +4335,7 @@ ix86_gimplify_va_arg (tree valist, tree
   /* Pull the value out of the saved registers.  */
 
   addr = create_tmp_var (ptr_type_node, "addr");
+  type_align = TYPE_ALIGN (type);
 
   if (container)
     {
@@ -4504,6 +4506,9 @@ ix86_gimplify_va_arg (tree valist, tree
 	  t = build2 (PLUS_EXPR, TREE_TYPE (gpr), gpr,
 		      build_int_cst (TREE_TYPE (gpr), needed_intregs * 8));
 	  gimplify_assign (gpr, t, pre_p);
+	  /* The GPR save area guarantees only 8-byte alignment.  */
+	  if (!need_temp)
+	    type_align = MIN (type_align, 64);
 	}
 
       if (needed_sseregs)
@@ -4548,6 +4553,7 @@ ix86_gimplify_va_arg (tree valist, tree
   if (container)
     gimple_seq_add_stmt (pre_p, gimple_build_label (lab_over));
 
+  type = build_aligned_type (type, type_align);
   ptrtype = build_pointer_type_for_mode (type, ptr_mode, true);
   addr = fold_convert (ptrtype, addr);
 
--- gcc/testsuite/gcc.c-torture/execute/pr92904.c	(nonexistent)
+++ gcc/testsuite/gcc.c-torture/execute/pr92904.c	(revision 279327)
@@ -0,0 +1,395 @@
+/* PR target/92904 */
+
+#include <stdarg.h>
+
+struct S { long long a, b; };
+struct __attribute__((aligned (16))) T { long long a, b; };
+struct U { double a, b, c, d; };
+struct __attribute__((aligned (32))) V { double a, b, c, d; };
+struct W { double a; long long b; };
+struct __attribute__((aligned (16))) X { double a; long long b; };
+#if __SIZEOF_INT128__ == 2 * __SIZEOF_LONG_LONG__
+__int128 b;
+#endif
+struct S c;
+struct T d;
+struct U e;
+struct V f;
+struct W g;
+struct X h;
+
+#if __SIZEOF_INT128__ == 2 * __SIZEOF_LONG_LONG__
+__attribute__((noipa)) __int128
+f1 (int x, ...)
+{
+  __int128 r;
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    va_arg (ap, int);
+  r = va_arg (ap, __int128);
+  va_end (ap);
+  return r;
+}
+#endif
+
+__attribute__((noipa)) struct S
+f2 (int x, ...)
+{
+  struct S r;
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    va_arg (ap, int);
+  r = va_arg (ap, struct S);
+  va_end (ap);
+  return r;
+}
+
+__attribute__((noipa)) struct T
+f3 (int x, ...)
+{
+  struct T r;
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    va_arg (ap, int);
+  r = va_arg (ap, struct T);
+  va_end (ap);
+  return r;
+}
+
+#if __SIZEOF_INT128__ == 2 * __SIZEOF_LONG_LONG__
+__attribute__((noipa)) void
+f4 (int x, ...)
+{
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    va_arg (ap, int);
+  b = va_arg (ap, __int128);
+  va_end (ap);
+}
+#endif
+
+__attribute__((noipa)) void
+f5 (int x, ...)
+{
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    va_arg (ap, int);
+  c = va_arg (ap, struct S);
+  va_end (ap);
+}
+
+__attribute__((noipa)) void
+f6 (int x, ...)
+{
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    va_arg (ap, int);
+  d = va_arg (ap, struct T);
+  va_end (ap);
+}
+
+__attribute__((noipa)) struct U
+f7 (int x, ...)
+{
+  struct U r;
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    va_arg (ap, double);
+  r = va_arg (ap, struct U);
+  va_end (ap);
+  return r;
+}
+
+__attribute__((noipa)) struct V
+f8 (int x, ...)
+{
+  struct V r;
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    va_arg (ap, double);
+  r = va_arg (ap, struct V);
+  va_end (ap);
+  return r;
+}
+
+__attribute__((noipa)) void
+f9 (int x, ...)
+{
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    va_arg (ap, double);
+  e = va_arg (ap, struct U);
+  va_end (ap);
+}
+
+__attribute__((noipa)) void
+f10 (int x, ...)
+{
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    va_arg (ap, double);
+  f = va_arg (ap, struct V);
+  va_end (ap);
+}
+
+__attribute__((noipa)) struct W
+f11 (int x, ...)
+{
+  struct W r;
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    {
+      va_arg (ap, int);
+      va_arg (ap, double);
+    }
+  r = va_arg (ap, struct W);
+  va_end (ap);
+  return r;
+}
+
+__attribute__((noipa)) struct X
+f12 (int x, ...)
+{
+  struct X r;
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    {
+      va_arg (ap, int);
+      va_arg (ap, double);
+    }
+  r = va_arg (ap, struct X);
+  va_end (ap);
+  return r;
+}
+
+__attribute__((noipa)) void
+f13 (int x, ...)
+{
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    {
+      va_arg (ap, int);
+      va_arg (ap, double);
+    }
+  g = va_arg (ap, struct W);
+  va_end (ap);
+}
+
+__attribute__((noipa)) void
+f14 (int x, ...)
+{
+  va_list ap;
+  va_start (ap, x);
+  while (x--)
+    {
+      va_arg (ap, int);
+      va_arg (ap, double);
+    }
+  h = va_arg (ap, struct X);
+  va_end (ap);
+}
+
+int
+main ()
+{
+  union Y {
+#if __SIZEOF_INT128__ == 2 * __SIZEOF_LONG_LONG__
+    __int128 b;
+#endif
+    struct S c;
+    struct T d;
+    struct U e;
+    struct V f;
+    struct W g;
+    struct X h;
+  } u, v;
+  u.c.a = 0x5555555555555555ULL;
+  u.c.b = 0xaaaaaaaaaaaaaaaaULL;
+#define C(x) \
+  do {								\
+    if (u.c.a != x.c.a || u.c.b != x.c.b) __builtin_abort ();	\
+    u.c.a++;							\
+    u.c.b--;							\
+  } while (0)
+#if __SIZEOF_INT128__ == 2 * __SIZEOF_LONG_LONG__
+  v.b = f1 (0, u.b); C (v);
+  v.b = f1 (1, 0, u.b); C (v);
+  v.b = f1 (2, 0, 0, u.b); C (v);
+  v.b = f1 (3, 0, 0, 0, u.b); C (v);
+  v.b = f1 (4, 0, 0, 0, 0, u.b); C (v);
+  v.b = f1 (5, 0, 0, 0, 0, 0, u.b); C (v);
+  v.b = f1 (6, 0, 0, 0, 0, 0, 0, u.b); C (v);
+  v.b = f1 (7, 0, 0, 0, 0, 0, 0, 0, u.b); C (v);
+  v.b = f1 (8, 0, 0, 0, 0, 0, 0, 0, 0, u.b); C (v);
+  v.b = f1 (9, 0, 0, 0, 0, 0, 0, 0, 0, 0, u.b); C (v);
+#endif
+  v.c = f2 (0, u.c); C (v);
+  v.c = f2 (1, 0, u.c); C (v);
+  v.c = f2 (2, 0, 0, u.c); C (v);
+  v.c = f2 (3, 0, 0, 0, u.c); C (v);
+  v.c = f2 (4, 0, 0, 0, 0, u.c); C (v);
+  v.c = f2 (5, 0, 0, 0, 0, 0, u.c); C (v);
+  v.c = f2 (6, 0, 0, 0, 0, 0, 0, u.c); C (v);
+  v.c = f2 (7, 0, 0, 0, 0, 0, 0, 0, u.c); C (v);
+  v.c = f2 (8, 0, 0, 0, 0, 0, 0, 0, 0, u.c); C (v);
+  v.c = f2 (9, 0, 0, 0, 0, 0, 0, 0, 0, 0, u.c); C (v);
+  v.d = f3 (0, u.d); C (v);
+  v.d = f3 (1, 0, u.d); C (v);
+  v.d = f3 (2, 0, 0, u.d); C (v);
+  v.d = f3 (3, 0, 0, 0, u.d); C (v);
+  v.d = f3 (4, 0, 0, 0, 0, u.d); C (v);
+  v.d = f3 (5, 0, 0, 0, 0, 0, u.d); C (v);
+  v.d = f3 (6, 0, 0, 0, 0, 0, 0, u.d); C (v);
+  v.d = f3 (7, 0, 0, 0, 0, 0, 0, 0, u.d); C (v);
+  v.d = f3 (8, 0, 0, 0, 0, 0, 0, 0, 0, u.d); C (v);
+  v.d = f3 (9, 0, 0, 0, 0, 0, 0, 0, 0, 0, u.d); C (v);
+#if __SIZEOF_INT128__ == 2 * __SIZEOF_LONG_LONG__
+  f4 (0, u.b); v.b = b; C (v);
+  f4 (1, 0, u.b); v.b = b; C (v);
+  f4 (2, 0, 0, u.b); v.b = b; C (v);
+  f4 (3, 0, 0, 0, u.b); v.b = b; C (v);
+  f4 (4, 0, 0, 0, 0, u.b); v.b = b; C (v);
+  f4 (5, 0, 0, 0, 0, 0, u.b); v.b = b; C (v);
+  f4 (6, 0, 0, 0, 0, 0, 0, u.b); v.b = b; C (v);
+  f4 (7, 0, 0, 0, 0, 0, 0, 0, u.b); v.b = b; C (v);
+  f4 (8, 0, 0, 0, 0, 0, 0, 0, 0, u.b); v.b = b; C (v);
+  f4 (9, 0, 0, 0, 0, 0, 0, 0, 0, 0, u.b); v.b = b; C (v);
+#endif
+  f5 (0, u.c); v.c = c; C (v);
+  f5 (1, 0, u.c); v.c = c; C (v);
+  f5 (2, 0, 0, u.c); v.c = c; C (v);
+  f5 (3, 0, 0, 0, u.c); v.c = c; C (v);
+  f5 (4, 0, 0, 0, 0, u.c); v.c = c; C (v);
+  f5 (5, 0, 0, 0, 0, 0, u.c); v.c = c; C (v);
+  f5 (6, 0, 0, 0, 0, 0, 0, u.c); v.c = c; C (v);
+  f5 (7, 0, 0, 0, 0, 0, 0, 0, u.c); v.c = c; C (v);
+  f5 (8, 0, 0, 0, 0, 0, 0, 0, 0, u.c); v.c = c; C (v);
+  f5 (9, 0, 0, 0, 0, 0, 0, 0, 0, 0, u.c); v.c = c; C (v);
+  f6 (0, u.d); v.d = d; C (v);
+  f6 (1, 0, u.d); v.d = d; C (v);
+  f6 (2, 0, 0, u.d); v.d = d; C (v);
+  f6 (3, 0, 0, 0, u.d); v.d = d; C (v);
+  f6 (4, 0, 0, 0, 0, u.d); v.d = d; C (v);
+  f6 (5, 0, 0, 0, 0, 0, u.d); v.d = d; C (v);
+  f6 (6, 0, 0, 0, 0, 0, 0, u.d); v.d = d; C (v);
+  f6 (7, 0, 0, 0, 0, 0, 0, 0, u.d); v.d = d; C (v);
+  f6 (8, 0, 0, 0, 0, 0, 0, 0, 0, u.d); v.d = d; C (v);
+  f6 (9, 0, 0, 0, 0, 0, 0, 0, 0, 0, u.d); v.d = d; C (v);
+  u.e.a = 1.25;
+  u.e.b = 2.75;
+  u.e.c = -3.5;
+  u.e.d = -2.0;
+#undef C
+#define C(x) \
+  do {								\
+    if (u.e.a != x.e.a || u.e.b != x.e.b			\
+	|| u.e.c != x.e.c || u.e.d != x.e.d) __builtin_abort ();\
+    u.e.a++;							\
+    u.e.b--;							\
+    u.e.c++;							\
+    u.e.d--;							\
+  } while (0)
+  v.e = f7 (0, u.e); C (v);
+  v.e = f7 (1, 0.0, u.e); C (v);
+  v.e = f7 (2, 0.0, 0.0, u.e); C (v);
+  v.e = f7 (3, 0.0, 0.0, 0.0, u.e); C (v);
+  v.e = f7 (4, 0.0, 0.0, 0.0, 0.0, u.e); C (v);
+  v.e = f7 (5, 0.0, 0.0, 0.0, 0.0, 0.0, u.e); C (v);
+  v.e = f7 (6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.e); C (v);
+  v.e = f7 (7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.e); C (v);
+  v.e = f7 (8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.e); C (v);
+  v.e = f7 (9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.e); C (v);
+  v.f = f8 (0, u.f); C (v);
+  v.f = f8 (1, 0.0, u.f); C (v);
+  v.f = f8 (2, 0.0, 0.0, u.f); C (v);
+  v.f = f8 (3, 0.0, 0.0, 0.0, u.f); C (v);
+  v.f = f8 (4, 0.0, 0.0, 0.0, 0.0, u.f); C (v);
+  v.f = f8 (5, 0.0, 0.0, 0.0, 0.0, 0.0, u.f); C (v);
+  v.f = f8 (6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.f); C (v);
+  v.f = f8 (7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.f); C (v);
+  v.f = f8 (8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.f); C (v);
+  v.f = f8 (9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.f); C (v);
+  f9 (0, u.e); v.e = e; C (v);
+  f9 (1, 0.0, u.e); v.e = e; C (v);
+  f9 (2, 0.0, 0.0, u.e); v.e = e; C (v);
+  f9 (3, 0.0, 0.0, 0.0, u.e); v.e = e; C (v);
+  f9 (4, 0.0, 0.0, 0.0, 0.0, u.e); v.e = e; C (v);
+  f9 (5, 0.0, 0.0, 0.0, 0.0, 0.0, u.e); v.e = e; C (v);
+  f9 (6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.e); v.e = e; C (v);
+  f9 (7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.e); v.e = e; C (v);
+  f9 (8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.e); v.e = e; C (v);
+  f9 (9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.e); v.e = e; C (v);
+  f10 (0, u.f); v.f = f; C (v);
+  f10 (1, 0.0, u.f); v.f = f; C (v);
+  f10 (2, 0.0, 0.0, u.f); v.f = f; C (v);
+  f10 (3, 0.0, 0.0, 0.0, u.f); v.f = f; C (v);
+  f10 (4, 0.0, 0.0, 0.0, 0.0, u.f); v.f = f; C (v);
+  f10 (5, 0.0, 0.0, 0.0, 0.0, 0.0, u.f); v.f = f; C (v);
+  f10 (6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.f); v.f = f; C (v);
+  f10 (7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.f); v.f = f; C (v);
+  f10 (8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.f); v.f = f; C (v);
+  f10 (9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, u.f); v.f = f; C (v);
+  u.g.a = 9.5;
+  u.g.b = 0x5555555555555555ULL;
+#undef C
+#define C(x) \
+  do {								\
+    if (u.e.a != x.e.a || u.e.b != x.e.b) __builtin_abort ();	\
+    u.e.a++;							\
+    u.e.b--;							\
+  } while (0)
+  v.g = f11 (0, u.g); C (v);
+  v.g = f11 (1, 0, 0.0, u.g); C (v);
+  v.g = f11 (2, 0, 0.0, 0, 0.0, u.g); C (v);
+  v.g = f11 (3, 0, 0.0, 0, 0.0, 0, 0.0, u.g); C (v);
+  v.g = f11 (4, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); C (v);
+  v.g = f11 (5, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); C (v);
+  v.g = f11 (6, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); C (v);
+  v.g = f11 (7, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); C (v);
+  v.g = f11 (8, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); C (v);
+  v.g = f11 (9, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); C (v);
+  v.h = f12 (0, u.h); C (v);
+  v.h = f12 (1, 0, 0.0, u.h); C (v);
+  v.h = f12 (2, 0, 0.0, 0, 0.0, u.h); C (v);
+  v.h = f12 (3, 0, 0.0, 0, 0.0, 0, 0.0, u.h); C (v);
+  v.h = f12 (4, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); C (v);
+  v.h = f12 (5, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); C (v);
+  v.h = f12 (6, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); C (v);
+  v.h = f12 (7, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); C (v);
+  v.h = f12 (8, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); C (v);
+  v.h = f12 (9, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); C (v);
+  f13 (0, u.g); v.g = g; C (v);
+  f13 (1, 0, 0.0, u.g); v.g = g; C (v);
+  f13 (2, 0, 0.0, 0, 0.0, u.g); v.g = g; C (v);
+  f13 (3, 0, 0.0, 0, 0.0, 0, 0.0, u.g); v.g = g; C (v);
+  f13 (4, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); v.g = g; C (v);
+  f13 (5, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); v.g = g; C (v);
+  f13 (6, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); v.g = g; C (v);
+  f13 (7, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); v.g = g; C (v);
+  f13 (8, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); v.g = g; C (v);
+  f13 (9, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.g); v.g = g; C (v);
+  f14 (0, u.h); v.h = h; C (v);
+  f14 (1, 0, 0.0, u.h); v.h = h; C (v);
+  f14 (2, 0, 0.0, 0, 0.0, u.h); v.h = h; C (v);
+  f14 (3, 0, 0.0, 0, 0.0, 0, 0.0, u.h); v.h = h; C (v);
+  f14 (4, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); v.h = h; C (v);
+  f14 (5, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); v.h = h; C (v);
+  f14 (6, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); v.h = h; C (v);
+  f14 (7, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); v.h = h; C (v);
+  f14 (8, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); v.h = h; C (v);
+  f14 (9, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, u.h); v.h = h; C (v);
+  return 0;
+}
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR tree-optimization/92930
	* ipa-pure-const.c (special_builtin_state): Don't handle
	BUILT_IN_APPLY.

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

--- gcc/ipa-pure-const.c	(revision 279393)
+++ gcc/ipa-pure-const.c	(revision 279394)
@@ -527,7 +527,6 @@ special_builtin_state (enum pure_const_s
 	case BUILT_IN_CXA_END_CLEANUP:
 	case BUILT_IN_EH_COPY_VALUES:
 	case BUILT_IN_FRAME_ADDRESS:
-	case BUILT_IN_APPLY:
 	case BUILT_IN_APPLY_ARGS:
 	case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT:
 	case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT:
--- gcc/testsuite/gcc.dg/tree-ssa/pr92930.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr92930.c	(revision 279394)
@@ -0,0 +1,19 @@
+/* PR tree-optimization/92930 */
+/* { dg-do compile { target untyped_assembly } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump "__builtin_apply " "optimized" } } */
+/* { dg-final { scan-tree-dump "__builtin_apply_args" "optimized" } } */
+
+void foo (int a, int b, int c, int d, int e, int f, int g);
+
+static void bar (int a, ...)
+{
+  __builtin_apply (foo, __builtin_apply_args (), 20);
+}
+
+int
+main ()
+{
+  bar (1024, 1025, 1026, 1027, 1028, 1029, 1030);
+  return 0;
+}
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

	PR ipa/92357
	* ipa-fnsummary.c (ipa_fn_summary_write): Use
	lto_symtab_encoder_iterator with lsei_start_function_in_partition and
	lsei_next_function_in_partition instead of walking all cgraph nodes
	in encoder.

--- gcc/ipa-fnsummary.c	(revision 279394)
+++ gcc/ipa-fnsummary.c	(revision 279395)
@@ -3452,24 +3452,24 @@ static void
 ipa_fn_summary_write (void)
 {
   struct output_block *ob = create_output_block (LTO_section_ipa_fn_summary);
+  lto_symtab_encoder_iterator lsei;
   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
   unsigned int count = 0;
-  int i;
 
-  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
+  for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
+       lsei_next_function_in_partition (&lsei))
     {
-      symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
-      cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
-      if (cnode && cnode->definition && !cnode->alias)
+      cgraph_node *cnode = lsei_cgraph_node (lsei);
+      if (cnode->definition && !cnode->alias)
 	count++;
     }
   streamer_write_uhwi (ob, count);
 
-  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
+  for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
+       lsei_next_function_in_partition (&lsei))
     {
-      symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
-      cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
-      if (cnode && cnode->definition && !cnode->alias)
+      cgraph_node *cnode = lsei_cgraph_node (lsei);
+      if (cnode->definition && !cnode->alias)
 	{
 	  struct ipa_fn_summary *info = ipa_fn_summaries->get (cnode);
 	  struct bitpack_d bp;
2019-12-20  Jakub Jelinek  <jakub@redhat.com>

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

 	PR fortran/92977
	* frontend-passes.c (call_external_blas): Use || instead of |.

	PR fortran/92977
	* frontend-passes.c (in_omp_atomic): New variable.
	(cfe_expr_0, matmul_to_var_expr, matmul_temp_args,
	inline_matmul_assign, call_external_blas): Don't optimize in
	EXEC_OMP_ATOMIC.
	(optimize_namespace): Clear in_omp_atomic.
	(gfc_code_walker): Set in_omp_atomic for EXEC_OMP_ATOMIC, save/restore
	it around.

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

--- gcc/fortran/frontend-passes.c	(revision 279553)
+++ gcc/fortran/frontend-passes.c	(revision 279554)
@@ -92,6 +92,10 @@ static int forall_level;
 
 static bool in_omp_workshare;
 
+/* Keep track of whether we are within an OMP atomic.  */
+
+static bool in_omp_atomic;
+
 /* Keep track of whether we are within a WHERE statement.  */
 
 static bool in_where;
@@ -913,9 +917,9 @@ cfe_expr_0 (gfc_expr **e, int *walk_subt
   gfc_expr *newvar;
   gfc_expr **ei, **ej;
 
-  /* Don't do this optimization within OMP workshare or ASSOC lists.  */
+  /* Don't do this optimization within OMP workshare/atomic or ASSOC lists.  */
 
-  if (in_omp_workshare || in_assoc_list)
+  if (in_omp_workshare || in_omp_atomic || in_assoc_list)
     {
       *walk_subtrees = 0;
       return 0;
@@ -1464,6 +1468,7 @@ optimize_namespace (gfc_namespace *ns)
   iterator_level = 0;
   in_assoc_list = false;
   in_omp_workshare = false;
+  in_omp_atomic = false;
 
   if (flag_frontend_optimize)
     {
@@ -2818,7 +2823,7 @@ matmul_to_var_expr (gfc_expr **ep, int *
     return 0;
 
   if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
-      || in_where || in_assoc_list)
+      || in_omp_atomic || in_where || in_assoc_list)
     return 0;
 
   /* Check if this is already in the form c = matmul(a,b).  */
@@ -2880,7 +2885,7 @@ matmul_temp_args (gfc_code **c, int *wal
     return 0;
 
   if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
-      || in_where)
+      || in_omp_atomic || in_where)
     return 0;
 
   /* This has some duplication with inline_matmul_assign.  This
@@ -3848,7 +3853,7 @@ inline_matmul_assign (gfc_code **c, int
   /* For now don't do anything in OpenMP workshare, it confuses
      its translation, which expects only the allowed statements in there.
      We should figure out how to parallelize this eventually.  */
-  if (in_omp_workshare)
+  if (in_omp_workshare || in_omp_atomic)
     return 0;
 
   expr1 = co->expr1;
@@ -4385,7 +4390,7 @@ call_external_blas (gfc_code **c, int *w
   /* For now don't do anything in OpenMP workshare, it confuses
      its translation, which expects only the allowed statements in there. */
 
-  if (in_omp_workshare)
+  if (in_omp_workshare || in_omp_atomic)
     return 0;
 
   expr1 = co->expr1;
@@ -5047,6 +5052,7 @@ gfc_code_walker (gfc_code **c, walk_code
 	  gfc_code *co;
 	  gfc_association_list *alist;
 	  bool saved_in_omp_workshare;
+	  bool saved_in_omp_atomic;
 	  bool saved_in_where;
 
 	  /* There might be statement insertions before the current code,
@@ -5054,6 +5060,7 @@ gfc_code_walker (gfc_code **c, walk_code
 
 	  co = *c;
 	  saved_in_omp_workshare = in_omp_workshare;
+	  saved_in_omp_atomic = in_omp_atomic;
 	  saved_in_where = in_where;
 
 	  switch (co->op)
@@ -5251,6 +5258,10 @@ gfc_code_walker (gfc_code **c, walk_code
 	      WALK_SUBEXPR (co->ext.dt->extra_comma);
 	      break;
 
+	    case EXEC_OMP_ATOMIC:
+	      in_omp_atomic = true;
+	      break;
+
 	    case EXEC_OMP_PARALLEL:
 	    case EXEC_OMP_PARALLEL_DO:
 	    case EXEC_OMP_PARALLEL_DO_SIMD:
@@ -5368,6 +5379,7 @@ gfc_code_walker (gfc_code **c, walk_code
 	    select_level --;
 
 	  in_omp_workshare = saved_in_omp_workshare;
+	  in_omp_atomic = saved_in_omp_atomic;
 	  in_where = saved_in_where;
 	}
     }
--- gcc/testsuite/gfortran.dg/gomp/pr92977.f90	(nonexistent)
+++ gcc/testsuite/gfortran.dg/gomp/pr92977.f90	(revision 279554)
@@ -0,0 +1,15 @@
+! PR fortran/92977
+! { dg-do compile }
+! { dg-additional-options "-O2" }
+
+program pr92977
+  integer :: n = 1
+  integer :: a
+!$omp atomic write
+  a = f(n) - f(n)
+contains
+  integer function f(x)
+    integer, intent(in) :: x
+    f = x
+  end
+end
diff mbox series

Patch

--- gcc/cp/parser.c	(revision 278537)
+++ gcc/cp/parser.c	(revision 278538)
@@ -13998,6 +13998,10 @@  cp_parser_decl_specifier_seq (cp_parser*
         case RID_CONCEPT:
           ds = ds_concept;
           cp_lexer_consume_token (parser->lexer);
+
+	  if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
+	    break;
+
 	  /* In C++20 a concept definition is just 'concept name = expr;'
 	     Support that syntax by pretending we've seen 'bool'.  */
 	  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
@@ -14025,6 +14029,10 @@  cp_parser_decl_specifier_seq (cp_parser*
 	  ds = ds_typedef;
 	  /* Consume the token.  */
 	  cp_lexer_consume_token (parser->lexer);
+
+	  if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
+	    break;
+
 	  /* A constructor declarator cannot appear in a typedef.  */
 	  constructor_possible_p = false;
 	  /* The "typedef" keyword can only occur in a declaration; we
@@ -14120,6 +14128,9 @@  cp_parser_decl_specifier_seq (cp_parser*
 	  bool is_cv_qualifier;
 	  tree type_spec;
 
+	  if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
+	    flags |= CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS;
+
 	  type_spec
 	    = cp_parser_type_specifier (parser, flags,
 					decl_specs,
--- gcc/testsuite/g++.dg/cpp1y/lambda-generic-90842.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp1y/lambda-generic-90842.C	(revision 278538)
@@ -0,0 +1,7 @@ 
+// PR c++/90842
+// { dg-do compile { target c++14 } }
+
+auto a = [](auto x) struct C { void foo (); } {};	// { dg-error "expected" }
+							// { dg-error "type-specifier invalid in lambda" "" { target *-*-* } .-1 }
+auto b = [](auto x) mutable typedef {};			// { dg-error "'typedef' invalid in lambda" }
+auto d = [](auto x) mutable friend {};			// { dg-error "'friend' invalid in lambda" }