Do not update SSA in lto-stremaer-in
[gcc.git] / gcc / cp / tree.c
index ca4d3e2a48bad424b4981fbbf6a1a1d0d2df3540..620e2c2699cb3a6de9de2b9dbcedfcc5783c06e4 100644 (file)
@@ -669,6 +669,15 @@ build_aggr_init_expr (tree type, tree init)
 tree
 build_cplus_new (tree type, tree init, tsubst_flags_t complain)
 {
+  /* This function should cope with what build_special_member_call
+     can produce.  When performing parenthesized aggregate initialization,
+     it can produce a { }.  */
+  if (BRACE_ENCLOSED_INITIALIZER_P (init))
+    {
+      gcc_assert (cxx_dialect >= cxx2a);
+      return finish_compound_literal (type, init, complain);
+    }
+
   tree rval = build_aggr_init_expr (type, init);
   tree slot;
 
@@ -1488,7 +1497,8 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags)
   if (t == TYPE_CANONICAL (t))
     return t;
 
-  if (dependent_alias_template_spec_p (t))
+  if (!(flags & STF_STRIP_DEPENDENT)
+      && dependent_alias_template_spec_p (t, nt_opaque))
     /* DR 1558: However, if the template-id is dependent, subsequent
        template argument substitution still applies to the template-id.  */
     return t;
@@ -1672,15 +1682,21 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags)
          if ((flags & STF_USER_VISIBLE)
              && !user_facing_original_type_p (t))
            return t;
+         /* If T is a non-template alias or typedef, we can assume that
+            instantiating its definition will hit any substitution failure,
+            so we don't need to retain it here as well.  */
+         if (!alias_template_specialization_p (t, nt_opaque))
+           flags |= STF_STRIP_DEPENDENT;
          result = strip_typedefs (DECL_ORIGINAL_TYPE (TYPE_NAME (t)),
                                   remove_attributes, flags);
        }
       else
        result = TYPE_MAIN_VARIANT (t);
     }
-  gcc_assert (!typedef_variant_p (result)
+  /*gcc_assert (!typedef_variant_p (result)
+             || dependent_alias_template_spec_p (result, nt_opaque)
              || ((flags & STF_USER_VISIBLE)
-                 && !user_facing_original_type_p (result)));
+                 && !user_facing_original_type_p (result)));*/
 
   if (COMPLETE_TYPE_P (result) && !COMPLETE_TYPE_P (t))
   /* If RESULT is complete and T isn't, it's likely the case that T
@@ -2331,6 +2347,9 @@ lookup_mark (tree ovl, bool val)
 tree
 lookup_add (tree fns, tree lookup)
 {
+  if (fns == error_mark_node || lookup == error_mark_node)
+    return error_mark_node;
+
   if (lookup || TREE_CODE (fns) == TEMPLATE_DECL)
     {
       lookup = ovl_make (fns, lookup);
@@ -3142,6 +3161,11 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_)
            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))
              {
@@ -4378,6 +4402,63 @@ zero_init_p (const_tree t)
   return 1;
 }
 
+/* True IFF T is a C++20 structural type (P1907R1) that can be used as a
+   non-type template parameter.  If EXPLAIN, explain why not.  */
+
+bool
+structural_type_p (tree t, bool explain)
+{
+  t = strip_array_types (t);
+  if (INTEGRAL_OR_ENUMERATION_TYPE_P (t))
+    return true;
+  if (NULLPTR_TYPE_P (t))
+    return true;
+  if (TYPE_PTR_P (t) || TYPE_PTRMEM_P (t))
+    return true;
+  if (TYPE_REF_P (t) && !TYPE_REF_IS_RVALUE (t))
+    return true;
+  if (!CLASS_TYPE_P (t))
+    return false;
+  if (TREE_CODE (t) == UNION_TYPE)
+    {
+      if (explain)
+       inform (location_of (t), "%qT is a union", t);
+      return false;
+    }
+  if (!literal_type_p (t))
+    {
+      if (explain)
+       explain_non_literal_class (t);
+      return false;
+    }
+  if (CLASSTYPE_HAS_MUTABLE (t))
+    {
+      if (explain)
+       inform (location_of (t), "%qT has a mutable member", t);
+      return false;
+    }
+  for (tree m = next_initializable_field (TYPE_FIELDS (t)); m;
+       m = next_initializable_field (DECL_CHAIN (m)))
+    {
+      if (TREE_PRIVATE (m) || TREE_PROTECTED (m))
+       {
+         if (explain)
+           inform (location_of (m), "%qD is not public", m);
+         return false;
+       }
+      if (!structural_type_p (TREE_TYPE (m)))
+       {
+         if (explain)
+           {
+             inform (location_of (m), "%qD has a non-structural type", m);
+             structural_type_p (TREE_TYPE (m), true);
+           }
+         return false;
+       }
+    }
+  return true;
+}
+
 /* Handle the C++17 [[nodiscard]] attribute, which is similar to the GNU
    warn_unused_result attribute.  */
 
@@ -5042,6 +5123,9 @@ special_function_p (const_tree decl)
     return sfk_conversion;
   if (deduction_guide_p (decl))
     return sfk_deduction_guide;
+  if (DECL_OVERLOADED_OPERATOR_CODE_RAW (decl) >= OVL_OP_EQ_EXPR
+      && DECL_OVERLOADED_OPERATOR_CODE_RAW (decl) <= OVL_OP_SPACESHIP_EXPR)
+    return sfk_comparison;
 
   return sfk_none;
 }
@@ -5540,6 +5624,68 @@ maybe_warn_zero_as_null_pointer_constant (tree expr, location_t loc)
   return false;
 }
 \f
+/* Given an initializer INIT for a TYPE, return true if INIT is zero
+   so that it can be replaced by value initialization.  This function
+   distinguishes betwen empty strings as initializers for arrays and
+   for pointers (which make it return false).  */
+
+bool
+type_initializer_zero_p (tree type, tree init)
+{
+  if (type == error_mark_node || init == error_mark_node)
+    return false;
+
+  STRIP_NOPS (init);
+
+  if (POINTER_TYPE_P (type))
+    return TREE_CODE (init) != STRING_CST && initializer_zerop (init);
+
+  if (TREE_CODE (init) != CONSTRUCTOR)
+    return initializer_zerop (init);
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree elt_type = TREE_TYPE (type);
+      elt_type = TYPE_MAIN_VARIANT (elt_type);
+      if (elt_type == char_type_node)
+       return initializer_zerop (init);
+
+      tree elt_init;
+      unsigned HOST_WIDE_INT i;
+      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, elt_init)
+       if (!type_initializer_zero_p (elt_type, elt_init))
+         return false;
+      return true;
+    }
+
+  if (TREE_CODE (type) != RECORD_TYPE)
+    return initializer_zerop (init);
+
+  if (TYPE_NON_AGGREGATE_CLASS (type))
+    return false;
+
+  tree fld = TYPE_FIELDS (type);
+
+  tree fld_init;
+  unsigned HOST_WIDE_INT i;
+  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, fld_init)
+    {
+      fld = next_initializable_field (fld);
+      if (!fld)
+       return true;
+
+      tree fldtype = TREE_TYPE (fld);
+      if (!type_initializer_zero_p (fldtype, fld_init))
+       return false;
+
+      fld = DECL_CHAIN (fld);
+      if (!fld)
+       break;
+    }
+
+  return true;
+}
+\f
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 /* Complain that some language-specific thing hanging off a tree
    node has been accessed improperly.  */