From 1b2317d1444b3ba43302223a7ba40f899ff2bdc0 Mon Sep 17 00:00:00 2001
From: qing zhao <qing.zhao@oracle.com>
Date: Mon, 3 May 2021 22:40:03 +0000
Subject: [PATCH] change of 2nd version

---
 gcc/c-family/c-attribs.c                  |  6 +-
 gcc/doc/invoke.texi                       |  6 +-
 gcc/gimplify.c                            | 24 ++++---
 gcc/internal-fn.c                         |  2 +-
 gcc/testsuite/c-c++-common/auto-init-15.c | 13 ++++
 gcc/testsuite/c-c++-common/auto-init-16.c | 13 ++++
 gcc/tree-cfg.c                            | 57 ++++++++++++-----
 gcc/tree-core.h                           |  3 +-
 gcc/tree-sra.c                            | 76 ++++++++++++++---------
 gcc/tree-ssa-structalias.c                | 28 +--------
 gcc/tree-ssa-uninit.c                     | 33 ++++++++--
 gcc/tree-ssa.c                            | 27 +++++++-
 gcc/tree.c                                | 75 +++++++++++++---------
 gcc/tree.h                                |  6 +-
 14 files changed, 239 insertions(+), 130 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-15.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-16.c

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 7684b83ed67f..de53c3a2da88 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -1526,16 +1526,14 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   return NULL_TREE;
 }
 
-/* Handle a "uninitialized" attribute; arguments as in
+/* Handle an "uninitialized" attribute; arguments as in
    struct attribute_spec.handler.  */
 
 static tree
 handle_uninitialized_attribute (tree *node, tree name, tree ARG_UNUSED (args),
 				int ARG_UNUSED (flags), bool *no_add_attrs)
 {
-  if (VAR_P (*node))
-    DECL_UNINITIALIZED (*node) = 1;
-  else
+  if (!VAR_P (*node))
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 508f27fd7a91..e68cbb13d9e8 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -11553,7 +11553,11 @@ and @option{-fauto-profile}.
 @item -ftrivial-auto-var-init=@var{choice}
 @opindex ftrivial-auto-var-init
 Initialize automatic variables with either a pattern or with zeroes to increase
-program security by preventing uninitialized memory disclosure and use.
+the security and predictability of a program by preventing uninitialized memory
+disclosure and use.
+GCC still considers an automatic variable that doesn't have an explicit
+initializer as uninitialized, -Wuninitialized will still report warning messages
+on such automatic variables.
 
 The three values of @var{choice} are:
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 3be830199f67..b14e79a84fd4 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1718,7 +1718,7 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
       && VAR_P (decl)
       && !DECL_EXTERNAL (decl)
       && !TREE_STATIC (decl)
-      && !DECL_UNINITIALIZED (decl))
+      && !lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl)))
     switch (flag_trivial_auto_var_init)
       {
       case AUTO_INIT_UNINITIALIZED:
@@ -1743,7 +1743,7 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
 	      {
 		element_type = TREE_TYPE (TREE_TYPE (decl));
 		size_of_element = DECL_SIZE_UNIT (element_type);
-		init_node = build_pattern_cst (element_type);
+		init_node = build_pattern_cst_for_auto_init (element_type);
 		cur = addr;
 		offset = DECL_SIZE_UNIT (decl) - size_of_element;
 		end = addr + offset;
@@ -1769,6 +1769,10 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
 	  tree label_loop = create_artificial_label (UNKNOWN_LOCATION);
 
 	  element_type = TREE_TYPE (TREE_TYPE (decl));
+	  /* If this is a nested array, we should go down to the element that
+	     is not an array.  */
+	  while (TREE_CODE (element_type) == ARRAY_TYPE)
+	    element_type = TREE_TYPE (element_type);
 
 	  gcond *cond_stmt = gimple_build_cond (GT_EXPR, DECL_SIZE_UNIT (decl),
 						build_zero_cst (sizetype),
@@ -1787,7 +1791,9 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
 
 	  gimplify_assign (size_of_element, TYPE_SIZE_UNIT (element_type),
 			   seq_p);
-	  gimplify_assign (init_node, build_pattern_cst (element_type), seq_p);
+	  gimplify_assign (init_node,
+			   build_pattern_cst_for_auto_init (element_type),
+			   seq_p);
 
 	  cur = create_tmp_var (ptr_type, ".cur_addr");
 	  end = create_tmp_var (ptr_type, ".end_addr");
@@ -1849,10 +1855,7 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
    1st argument: DECL;
    2nd argument: INIT_TYPE;
 
-   as DEFERRED_INIT (DECL, INIT_TYPE)
-
-   DEFERRED_INIT is defined as:
-   DEF_INTERNAL_FN(DEFERRED_INIT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL).  */
+   as DEFERRED_INIT (DECL, INIT_TYPE).  */
 
 static gimple *
 build_deferred_init (tree decl,
@@ -1882,7 +1885,7 @@ gimple_add_init_for_auto_var (tree decl,
     if (init_approach == AUTO_INIT_A)
     {
       tree init = (init_type == AUTO_INIT_PATTERN)
-		   ? build_pattern_cst (TREE_TYPE (decl)) :
+		   ? build_pattern_cst_for_auto_init (TREE_TYPE (decl)) :
 		   build_zero_cst (TREE_TYPE (decl));
       init = build2 (INIT_EXPR, void_type_node, decl, init);
       gimplify_and_add (init, seq_p);
@@ -1992,9 +1995,10 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
 	}
       /* When there is no explicit initializer, if the user requested,
 	 We should insert an artifical initializer for this automatic
-	 variable for non vla variables.  */
+	 variable for non VLA variables.  VLA variables are handled
+	 in gimplify_vla_decl differently.  */
       else if (flag_trivial_auto_var_init > AUTO_INIT_UNINITIALIZED
-	       && !DECL_UNINITIALIZED (decl)
+	       && !lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl))
 	       && !TREE_STATIC (decl)
 	       && !is_vla)
 	gimple_add_init_for_auto_var (decl,
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 35de829dcf83..28d23e923b3c 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2985,7 +2985,7 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
     default:
       gcc_unreachable ();
     case AUTO_INIT_PATTERN:
-      init = build_pattern_cst (TREE_TYPE (var));
+      init = build_pattern_cst_for_auto_init (TREE_TYPE (var));
       expand_assignment (var, init, false);
       break;
     case AUTO_INIT_ZERO:
diff --git a/gcc/testsuite/c-c++-common/auto-init-15.c b/gcc/testsuite/c-c++-common/auto-init-15.c
new file mode 100644
index 000000000000..6f12f96ac1e2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-15.c
@@ -0,0 +1,13 @@
+/* Verify the auto initialization of nested VLA.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+void g(void *);
+
+void foo(int a)
+{
+  int x[a][a];
+  g(x);
+}
+
+/* { dg-final { scan-tree-dump "__builtin_memset" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-16.c b/gcc/testsuite/c-c++-common/auto-init-16.c
new file mode 100644
index 000000000000..c6a3627da542
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-16.c
@@ -0,0 +1,13 @@
+/* Verify the auto initialization of nested VLA.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+void g(void *);
+
+void foo(int a)
+{
+  int x[a][a];
+  g(x);
+}
+
+/* { dg-final { scan-tree-dump "__builtin_memcpy" "gimple" } } */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 3717c6d26a54..8ffcc6675893 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3433,27 +3433,56 @@ verify_gimple_call (gcall *stmt)
 	}
     }
 
+  /* For a call to .DEFERRED_INIT, we should guarantee that the lhs is
+     the same as the first argument of the call.  */
   if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
-    return false;
+    {
+      tree arg0 = gimple_call_arg (stmt, 0);
+      if (TREE_CODE (lhs) == SSA_NAME)
+	lhs = SSA_NAME_VAR (lhs);
+      if (TREE_CODE (arg0) == SSA_NAME)
+	arg0 = SSA_NAME_VAR (arg0);
+      if (lhs != arg0)
+	{
+	  error ("%<DEFFERED_INIT%> calls should have the same LHS as the "
+		 "first argument");
+	  return true;
+	}
+    }
 
+  /* We will not verify the arguments for the calls to .DEFERRED_INIT.
+     Such call is not a real call, just a placeholder for a later
+     initialization during expand phase.
+     This is mainly to avoid assertion failure for the following
+     case:
+
+     uni_var = .DEFERRED_INIT (uni_var, INIT_TYPE);
+     foo (&uni_var);
+
+     in the above, the uninitialized auto variable "uni_var" is
+     addressable, therefore should not be in registers, resulting
+     the assertion failure in the following argument verification.  */
+  if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+    return false;
   /* ???  The C frontend passes unpromoted arguments in case it
      didn't see a function declaration before the call.  So for now
      leave the call arguments mostly unverified.  Once we gimplify
      unit-at-a-time we have a chance to fix this.  */
 
-  for (i = 0; i < gimple_call_num_args (stmt); ++i)
-    {
-      tree arg = gimple_call_arg (stmt, i);
-      if ((is_gimple_reg_type (TREE_TYPE (arg))
-	   && !is_gimple_val (arg))
-	  || (!is_gimple_reg_type (TREE_TYPE (arg))
-	      && !is_gimple_lvalue (arg)))
-	{
-	  error ("invalid argument to gimple call");
-	  debug_generic_expr (arg);
-	  return true;
-	}
-    }
+  else
+    for (i = 0; i < gimple_call_num_args (stmt); ++i)
+      {
+	tree arg = gimple_call_arg (stmt, i);
+	if ((is_gimple_reg_type (TREE_TYPE (arg))
+	     && !is_gimple_val (arg))
+	    || (!is_gimple_reg_type (TREE_TYPE (arg))
+		&& !is_gimple_lvalue (arg)))
+	  {
+	    error ("invalid argument to gimple call");
+	    debug_generic_expr (arg);
+	    return true;
+	  }
+      }
 
   return false;
 }
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 02f580e5f04c..2e0e76ea8838 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1808,7 +1808,6 @@ struct GTY(()) tree_decl_with_vis {
  unsigned in_text_section : 1;
  unsigned in_constant_pool : 1;
  unsigned dllimport_flag : 1;
- unsigned uninitialized : 1;
  /* Don't belong to VAR_DECL exclusively.  */
  unsigned weak_flag : 1;
 
@@ -1830,7 +1829,7 @@ struct GTY(()) tree_decl_with_vis {
  unsigned final : 1;
  /* Belong to FUNCTION_DECL exclusively.  */
  unsigned regdecl_flag : 1;
- /* 13 unused bits.  */
+ /* 14 unused bits.  */
  /* 32 more unused on 64 bit HW. */
 };
 
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 302a123bf549..4c74df272141 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -4079,15 +4079,12 @@ get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
 
 
 /* Generate statements to call .DEFERRED_INIT to initialize scalar replacements
-   of accesses within a subtree ACCESS, all its children, siblings and their
-   children are to be processed.  TOP_OFFSET is the offset  of the processed
-   subtree which has to be subtracted from offsets of individual accesses to
-   get corresponding offsets for AGG.  GSI is a statement iterator used to place
-   the new statements.  */
+   of accesses within a subtree ACCESS; all its children, siblings and their
+   children are to be processed.
+   GSI is a statement iterator used to place the new statements.  */
 static void
-generate_subtree_deferred_init (struct access *access, tree agg,
+generate_subtree_deferred_init (struct access *access,
 				enum auto_init_type init_type,
-				HOST_WIDE_INT top_offset,
 				gimple_stmt_iterator *gsi,
 				location_t loc)
 {
@@ -4109,17 +4106,19 @@ generate_subtree_deferred_init (struct access *access, tree agg,
 	}
       else if (access->grp_to_be_debug_replaced)
 	{
-	  /* FIXME, this part might have some issue.  */
-	  tree drhs = build_debug_ref_for_model (loc, agg,
-						 access->offset - top_offset,
-						 access);
-	  gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
-						drhs, gsi_stmt (*gsi));
+	  tree drepl = get_access_replacement (access);
+	  tree init_type_node
+	    = build_int_cst (integer_type_node, (int) init_type);
+	  tree call = build_call_expr_internal_loc
+		     (UNKNOWN_LOCATION, IFN_DEFERRED_INIT,
+		      TREE_TYPE (drepl), 2, drepl, init_type_node);
+	  gdebug *ds = gimple_build_debug_bind (drepl, call,
+						gsi_stmt (*gsi));
 	  gsi_insert_before (gsi, ds, GSI_SAME_STMT);
 	}
       if (access->first_child)
-	generate_subtree_deferred_init (access->first_child, agg, init_type,
-					top_offset, gsi, loc);
+	generate_subtree_deferred_init (access->first_child, init_type,
+					gsi, loc);
 
       access = access ->next_sibling;
     }
@@ -4132,40 +4131,55 @@ generate_subtree_deferred_init (struct access *access, tree agg,
    there is one, also replace the RHS call to a call to .DEFERRED_INIT of
    the corresponding scalar relacement variable.  Examine the subtree and
    do the scalar replacements in the subtree too.  STMT is the call, GSI is
-   the statment iterator to place newly created statements.  */
+   the statment iterator to place newly created statement.  */
 
 static enum assignment_mod_result
 sra_modify_deferred_init (gimple *stmt, gimple_stmt_iterator *gsi)
 {
   tree lhs = gimple_call_lhs (stmt);
+  tree arg0 = gimple_call_arg (stmt, 0);
   enum auto_init_type init_type
     = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
-  struct access *access = get_access_for_expr (lhs);
-  if (!access)
+  struct access *lhs_access = get_access_for_expr (lhs);
+  struct access *arg0_access = get_access_for_expr (arg0);
+  if (!lhs_access && !arg0_access)
     return SRA_AM_NONE;
+  gcc_assert (lhs_access && arg0_access);
+
   location_t loc = gimple_location (stmt);
 
-  if (access->grp_to_be_replaced)
+  if (lhs_access->grp_to_be_replaced)
     {
-      tree repl = get_access_replacement (access);
-      gimple_call_set_lhs (stmt, repl);
-      gimple_call_set_arg (stmt, 0, repl);
+      tree lhs_repl = get_access_replacement (lhs_access);
+      tree arg0_repl = get_access_replacement (arg0_access);
+      if (TREE_CODE (lhs_repl) == SSA_NAME)
+	{
+	  gcc_assert (TREE_CODE (arg0_repl) == SSA_NAME);
+	  gcc_assert (SSA_NAME_VAR (lhs_repl) == SSA_NAME_VAR (arg0_repl));
+	}
+      else
+	gcc_assert (lhs_repl == arg0_repl);
+      gimple_call_set_lhs (stmt, lhs_repl);
+      gimple_call_set_arg (stmt, 0, arg0_repl);
       sra_stats.deferred_init++;
     }
-  else if (access->grp_to_be_debug_replaced)
+  else if (lhs_access->grp_to_be_debug_replaced)
     {
-      /* FIXME, this part might have some issues.  */
-      tree drepl = get_access_replacement (access);
-      gdebug *ds = gimple_build_debug_bind (drepl, NULL_TREE,
+      tree lhs_drepl = get_access_replacement (lhs_access);
+      tree init_type_node
+	   = build_int_cst (integer_type_node, (int) init_type);
+      tree call = build_call_expr_internal_loc
+		  (UNKNOWN_LOCATION, IFN_DEFERRED_INIT,
+		  TREE_TYPE (lhs_drepl), 2, lhs_drepl, init_type_node);
+      gdebug *ds = gimple_build_debug_bind (lhs_drepl, call,
 					    gsi_stmt (*gsi));
       gsi_insert_before (gsi, ds, GSI_SAME_STMT);
     }
 
-  if (access->first_child)
-    generate_subtree_deferred_init (access->first_child, lhs,
-				    init_type, access->offset,
-				    gsi, loc);
-  if (access->grp_covered)
+  if (lhs_access->first_child)
+    generate_subtree_deferred_init (lhs_access->first_child,
+				    init_type, gsi, loc);
+  if (lhs_access->grp_covered)
     {
       unlink_stmt_vdef (stmt);
       gsi_remove (gsi, true);
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index e4ee3ff93f09..547df1c7b41d 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -4851,29 +4851,6 @@ find_func_aliases_for_builtin_call (struct function *fn, gcall *t)
   return false;
 }
 
-static void
-find_func_aliases_for_deferred_init (gcall *t)
-{
-  tree lhsop = gimple_call_lhs (t);
-  enum auto_init_type init_type
-    = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (t, 1));
-  auto_vec<ce_s, 2> lhsc;
-  auto_vec<ce_s, 4> rhsc;
-  struct constraint_expr temp;
-
-  get_constraint_for (lhsop, &lhsc);
-  if (init_type == AUTO_INIT_ZERO && flag_delete_null_pointer_checks)
-    temp.var = nothing_id;
-  else
-    temp.var = nonlocal_id;
-  temp.type = ADDRESSOF;
-  temp.offset = 0;
-  rhsc.safe_push (temp);
-
-  process_all_all_constraints (lhsc, rhsc);
-  return;
-}
-
 /* Create constraints for the call T.  */
 
 static void
@@ -4888,10 +4865,7 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
     return;
 
   if (gimple_call_internal_p (t, IFN_DEFERRED_INIT))
-    {
-      find_func_aliases_for_deferred_init (t);
-      return;
-    }
+    return;
 
   fi = get_fi_for_callee (t);
   if (!in_ipa_mode
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index e8ca1469a083..c86c59cbabd4 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -136,8 +136,30 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
       && gimple_assign_rhs_code (context) == COMPLEX_EXPR)
     return;
 
-  /* Ignore REALPART_EXPR or IMAGPART_EXPR if its operand is
-     a call to .DEFERRED_INIT.  */
+  /* Ignore REALPART_EXPR or IMAGPART_EXPR if its operand is a call to
+     .DEFERRED_INIT.  This is for handling the following case correctly:
+
+  1 typedef _Complex float C;
+  2 C foo(int cond)
+  3 {
+  4   C f;
+  5   __imag__ f = 0;
+  6   if (cond)
+  7     {
+  8       __real__ f = 1;
+  9       return f;
+ 10     }
+ 11   return f;
+ 12 }
+
+    with -ftrivial-auto-var-init, compiler will insert the following
+    artificial initialization at line 4:
+  f = .DEFERRED_INIT (f, 2);
+  _1 = REALPART_EXPR <f>;
+
+    without the following special handling, _1 = REALPART_EXPR <f> will
+    be treated as the uninitialized use point, which is incorrect. (the
+    real uninitialized use point is at line 11).  */
   if (is_gimple_assign (context)
       && (gimple_assign_rhs_code (context) == REALPART_EXPR
 	  || gimple_assign_rhs_code (context) == IMAGPART_EXPR))
@@ -224,12 +246,12 @@ check_defs (ao_ref *ref, tree vdef, void *data_)
   check_defs_data *data = (check_defs_data *)data_;
   gimple *def_stmt = SSA_NAME_DEF_STMT (vdef);
 
-  /* Ignore the vdef iff the definition statement is a call
+  /* Ignore the vdef if the definition statement is a call
      to .DEFERRED_INIT function.  */
   if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT))
     return false;
 
-  /* Ignore the vdef iff the definition statement is a call
+  /* Ignore the vdef if the definition statement is a call
      to builtin_memset function that is added for uninitialized
      auto variable initialization.  */
   if (gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET)
@@ -638,6 +660,9 @@ warn_uninitialized_vars (bool wmaybe_uninit)
 	  ssa_op_iter op_iter;
 	  tree use;
 
+	  /* The call is an artificial use, will not provide meaningful
+	     error message.  If the result of the call is used somewhere
+	     else, we warn there instead.  */
 	  if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
 	    continue;
 
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 2058849a3a4c..0c285f7b4f0f 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1325,11 +1325,35 @@ ssa_undefined_value_p (tree t, bool partial)
   if (gimple_nop_p (def_stmt))
     return true;
 
-  /* The value is undefined iff the definition statement is a call
+  /* The value is undefined if the definition statement is a call
      to .DEFERRED_INIT function.  */
   if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT))
     return true;
 
+  /* The value is partially undefined if the definition statement is
+     a REALPART_EXPR or IMAGPART_EXPR and its operand is defined by
+     the call to .DEFERRED_INIT function.  This is for handling the
+     following case:
+
+  1 typedef _Complex float C;
+  2 C foo(int cond)
+  3 {
+  4   C f;
+  5   __imag__ f = 0;
+  6   if (cond)
+  7     {
+  8       __real__ f = 1;
+  9       return f;
+ 10     }
+ 11   return f;
+ 12 }
+
+    with -ftrivial-auto-var-init, compiler will insert the following
+    artificial initialization:
+  f = .DEFERRED_INIT (f, 2);
+  _1 = REALPART_EXPR <f>;
+
+    we should treat the definition _1 = REALPART_EXPR <f> as undefined.  */
   if (partial && is_gimple_assign (def_stmt)
       && (gimple_assign_rhs_code (def_stmt) == REALPART_EXPR
 	  || gimple_assign_rhs_code (def_stmt) == IMAGPART_EXPR))
@@ -1341,7 +1365,6 @@ ssa_undefined_value_p (tree t, bool partial)
 	return true;
     }
 
-
   /* Check if the complex was not only partially defined.  */
   if (partial && is_gimple_assign (def_stmt)
       && gimple_assign_rhs_code (def_stmt) == COMPLEX_EXPR)
diff --git a/gcc/tree.c b/gcc/tree.c
index a199fa773fb7..c320781befec 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2533,7 +2533,7 @@ build_zero_cst (tree type)
    auto variables.  */
 
 tree
-build_pattern_cst (tree type)
+build_pattern_cst_for_auto_init (tree type)
 {
   /* The following value is a guaranteed unmappable pointer value and has a
      repeated byte-pattern which makes it easier to synthesize.  We use it for
@@ -2548,13 +2548,20 @@ build_pattern_cst (tree type)
 
   switch (TREE_CODE (type))
     {
-    case INTEGER_TYPE:
-    case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
-      /* This will initialize a boolean type variable to 0 instead of 1.
- 	 We think that initializint a boolean variable to 0 other than 1
+      /* We think that initializing the boolean variable to 0 other than 1
 	 is better even for pattern initialization.  */
-      return build_int_cstu (type, largevalue);
+      return build_zero_cst (type);
+    case INTEGER_TYPE:
+    case ENUMERAL_TYPE:
+      {
+	unsigned char ptr[16]
+	  = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+	     0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
+	int total_bytes = GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (type));
+	wide_int result = wi::from_buffer (ptr, total_bytes);
+	return wide_int_to_tree (type, result);
+      }
     case POINTER_TYPE:
     case OFFSET_TYPE:
     case REFERENCE_TYPE:
@@ -2564,25 +2571,28 @@ build_pattern_cst (tree type)
 
 	if (POINTER_SIZE == 64)
 	  intvalue = largevalue;
-	else if (POINTER_SIZE == 32)
-	  intvalue = smallvalue;
 	else
-	  gcc_assert (0);
+	  intvalue = smallvalue;
 	return build_int_cstu (type, intvalue);
       }
     case REAL_TYPE:
       {
 	REAL_VALUE_TYPE rnan;
+	machine_mode mode = TYPE_MODE (type);
 
-	/* create an quiet NAN for REAL TYPE.  */
-	if (real_nan (&rnan, "", 1, TYPE_MODE (type)))
-	  return build_real (type, rnan);
-	return NULL_TREE;
+	/* create an quiet NAN for REAL TYPE.
+	   if failed, fallback to MAX_FLOAT instead.  */
+	if (!real_nan (&rnan, "", 1, mode))
+	  {
+	    char buf[128];
+ 
+	    get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
+	    real_from_string (&rnan, buf);
+	  }
+	return build_real (type, rnan);
       }
-
     case FIXED_POINT_TYPE:
       {
-	/* FIXME.  What should we put into a fixed point?  */
 	FIXED_VALUE_TYPE fixed;
 	fixed_from_string (&fixed, "0xFFFFFFFFFFFFFFFF",
 			   SCALAR_TYPE_MODE (type));
@@ -2590,12 +2600,12 @@ build_pattern_cst (tree type)
       }
     case VECTOR_TYPE:
       {
-	tree scalar = build_pattern_cst (TREE_TYPE (type));
+	tree scalar = build_pattern_cst_for_auto_init (TREE_TYPE (type));
 	return build_vector_from_val (type, scalar);
       }
     case COMPLEX_TYPE:
       {
-	tree element = build_pattern_cst (TREE_TYPE (type));
+	tree element = build_pattern_cst_for_auto_init (TREE_TYPE (type));
 	return build_complex (type, element, element);
       }
     case RECORD_TYPE:
@@ -2607,8 +2617,8 @@ build_pattern_cst (tree type)
 	  {
 	    if (TREE_CODE (field) != FIELD_DECL)
 	      continue;
-	    /* if the field is a variable length array, it should be the last
-	       field of the record, and no need to initialize.  */
+	    /* If the field is a flexible array member, it should be the last
+	       field of the record, and no need to initialize it.  */
 	    if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
 		&& TYPE_SIZE (TREE_TYPE (field)) == NULL_TREE
 		&& ((TYPE_DOMAIN (TREE_TYPE (field)) != NULL_TREE
@@ -2616,7 +2626,7 @@ build_pattern_cst (tree type)
 				       == NULL_TREE)
 		   || TYPE_DOMAIN (TREE_TYPE (field)) == NULL_TREE))
 	      continue;
-	    field_value = build_pattern_cst (TREE_TYPE (field));
+	    field_value = build_pattern_cst_for_auto_init (TREE_TYPE (field));
 	    CONSTRUCTOR_APPEND_ELT (v, field, field_value);
 	  }
 	return build_constructor (type, v);
@@ -2628,25 +2638,30 @@ build_pattern_cst (tree type)
 	unsigned max_size = 0;
 	tree field_value;
 	vec<constructor_elt, va_gc> *v = NULL;
-	/* find the field with the largest size.  */
+	/* Find the field with the largest size.  */
 	for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
 	  {
 	    if (TREE_CODE (field) != FIELD_DECL)
 	      continue;
-	    if (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field))) >= max_size)
+	    if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (field))))
+	      if (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field))) >= max_size)
 	      {
 		max_size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
 		max_field = field;
 	      }
 	  }
-	  field_value = build_pattern_cst (TREE_TYPE (max_field));
-	  CONSTRUCTOR_APPEND_ELT (v, max_field, field_value);
+	if (max_field)
+	  {
+	    field_value
+	      = build_pattern_cst_for_auto_init (TREE_TYPE (max_field));
+	    CONSTRUCTOR_APPEND_ELT (v, max_field, field_value);
+	  }
 	return build_constructor (type, v);
       }
     case ARRAY_TYPE:
       {
 	vec<constructor_elt, va_gc> *elts = NULL;
-	tree element = build_pattern_cst (TREE_TYPE (type));
+	tree element = build_pattern_cst_for_auto_init (TREE_TYPE (type));
 	tree nelts = array_type_nelts (type);
 	if (nelts && tree_fits_uhwi_p (nelts))
 	  {
@@ -2655,14 +2670,16 @@ build_pattern_cst (tree type)
 	      CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, element);
 	    return build_constructor (type, elts);
 	  }
-	/* variable length array should not be here.  */
-	gcc_assert (0);
+	/* Variable length array should not be here.  */
+	gcc_unreachable ();
       }
     default:
       if (!AGGREGATE_TYPE_P (type))
-	return fold_convert (type, build_pattern_cst (unsigned_type_node));
+	return
+	  fold_convert (type,
+			build_pattern_cst_for_auto_init (unsigned_type_node));
       else
-	gcc_assert (0);
+	gcc_unreachable ();
 
     }
 }
diff --git a/gcc/tree.h b/gcc/tree.h
index 089494e020a8..7b7d5bf76bd1 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2874,10 +2874,6 @@ extern void decl_value_expr_insert (tree, tree);
 #define DECL_HARD_REGISTER(NODE)  \
   (VAR_DECL_CHECK (NODE)->decl_with_vis.hard_register)
 
-/* In a VAR_DECL, nonzero if the decl is intentionly not initialized.  */
-#define DECL_UNINITIALIZED(NODE)  \
-  (VAR_DECL_CHECK (NODE)->decl_with_vis.uninitialized)
-
   /* Used to indicate that this DECL has weak linkage.  */
 #define DECL_WEAK(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.weak_flag)
 
@@ -4464,7 +4460,7 @@ extern tree build_one_cst (tree);
 extern tree build_minus_one_cst (tree);
 extern tree build_all_ones_cst (tree);
 extern tree build_zero_cst (tree);
-extern tree build_pattern_cst (tree);
+extern tree build_pattern_cst_for_auto_init (tree);
 extern tree build_string (unsigned, const char * = NULL);
 extern tree build_poly_int_cst (tree, const poly_wide_int_ref &);
 extern tree build_tree_list (tree, tree CXX_MEM_STAT_INFO);
-- 
2.27.0

