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;
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;
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
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);
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))
{
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. */
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;
}
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. */