diff options
Diffstat (limited to 'gcc/cp/method.c')
-rw-r--r-- | gcc/cp/method.c | 77 |
1 files changed, 62 insertions, 15 deletions
diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 3fe3bd8..353046d 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1029,6 +1029,8 @@ is_cat (tree type, comp_cat_tag tag) static comp_cat_tag cat_tag_for (tree type) { + if (!CLASS_TYPE_P (type) || !decl_in_std_namespace_p (TYPE_MAIN_DECL (type))) + return cc_last; for (int i = 0; i < cc_last; ++i) { comp_cat_tag tag = (comp_cat_tag)i; @@ -1087,7 +1089,8 @@ genericize_spaceship (location_t loc, tree type, tree op0, tree op1) gcc_checking_assert (tag < cc_last); tree r; - if (SCALAR_TYPE_P (TREE_TYPE (op0))) + bool scalar = SCALAR_TYPE_P (TREE_TYPE (op0)); + if (scalar) { op0 = save_expr (op0); op1 = save_expr (op1); @@ -1097,26 +1100,53 @@ genericize_spaceship (location_t loc, tree type, tree op0, tree op1) int flags = LOOKUP_NORMAL; tsubst_flags_t complain = tf_none; + tree comp; if (tag == cc_partial_ordering) { /* op0 == op1 ? equivalent : op0 < op1 ? less : op1 < op0 ? greater : unordered */ tree uo = lookup_comparison_result (tag, type, 3); - tree comp = build_new_op (loc, LT_EXPR, flags, op1, op0, complain); - r = build_conditional_expr (loc, comp, gt, uo, complain); + if (scalar) + { + /* For scalars use the low level operations; using build_new_op causes + trouble with constexpr eval in the middle of genericize (100367). */ + comp = fold_build2 (LT_EXPR, boolean_type_node, op1, op0); + r = fold_build3 (COND_EXPR, type, comp, gt, uo); + } + else + { + comp = build_new_op (loc, LT_EXPR, flags, op1, op0, complain); + r = build_conditional_expr (loc, comp, gt, uo, complain); + } } else /* op0 == op1 ? equal : op0 < op1 ? less : greater */ r = gt; tree lt = lookup_comparison_result (tag, type, 2); - tree comp = build_new_op (loc, LT_EXPR, flags, op0, op1, complain); - r = build_conditional_expr (loc, comp, lt, r, complain); + if (scalar) + { + comp = fold_build2 (LT_EXPR, boolean_type_node, op0, op1); + r = fold_build3 (COND_EXPR, type, comp, lt, r); + } + else + { + comp = build_new_op (loc, LT_EXPR, flags, op0, op1, complain); + r = build_conditional_expr (loc, comp, lt, r, complain); + } tree eq = lookup_comparison_result (tag, type, 0); - comp = build_new_op (loc, EQ_EXPR, flags, op0, op1, complain); - r = build_conditional_expr (loc, comp, eq, r, complain); + if (scalar) + { + comp = fold_build2 (EQ_EXPR, boolean_type_node, op0, op1); + r = fold_build3 (COND_EXPR, type, comp, eq, r); + } + else + { + comp = build_new_op (loc, EQ_EXPR, flags, op0, op1, complain); + r = build_conditional_expr (loc, comp, eq, r, complain); + } return r; } @@ -1793,7 +1823,7 @@ build_stub_type (tree type, int quals, bool rvalue) /* Build a dummy glvalue from dereferencing a dummy reference of type REFTYPE. */ -static tree +tree build_stub_object (tree reftype) { if (!TYPE_REF_P (reftype)) @@ -2789,9 +2819,9 @@ explain_implicit_non_constexpr (tree decl) /* DECL is an instantiation of an inheriting constructor template. Deduce the correct exception-specification and deletedness for this particular - specialization. */ + specialization. Return true if the deduction succeeds; false otherwise. */ -void +bool deduce_inheriting_ctor (tree decl) { decl = DECL_ORIGIN (decl); @@ -2804,6 +2834,8 @@ deduce_inheriting_ctor (tree decl) /*diag*/false, &inh, FUNCTION_FIRST_USER_PARMTYPE (decl)); + if (spec == error_mark_node) + return false; if (TREE_CODE (inherited_ctor_binfo (decl)) != TREE_BINFO) /* Inherited the same constructor from different base subobjects. */ deleted = true; @@ -2818,6 +2850,8 @@ deduce_inheriting_ctor (tree decl) TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec); SET_DECL_INHERITED_CTOR (clone, inh); } + + return true; } /* Implicitly declare the special function indicated by KIND, as a @@ -2993,9 +3027,17 @@ implicitly_declare_fn (special_function_kind kind, tree type, if (raises != error_mark_node) fn_type = build_exception_variant (fn_type, raises); else - /* Can happen, eg, in C++98 mode for an ill-formed non-static data - member initializer (c++/89914). */ - gcc_assert (seen_error ()); + { + /* Can happen, e.g., in C++98 mode for an ill-formed non-static data + member initializer (c++/89914). Also, in C++98, we might have + failed to deduce RAISES, so try again but complain this time. */ + if (cxx_dialect < cxx11) + synthesized_method_walk (type, kind, const_p, &raises, nullptr, + nullptr, nullptr, /*diag=*/true, + &inherited_ctor, inherited_parms); + /* We should have seen an error at this point. */ + gcc_assert (seen_error ()); + } } fn = build_lang_decl (FUNCTION_DECL, name, fn_type); if (kind != sfk_inheriting_constructor) @@ -3119,7 +3161,12 @@ defaulted_late_check (tree fn) /* If the function was declared constexpr, check that the definition qualifies. Otherwise we can define the function lazily. */ if (DECL_DECLARED_CONSTEXPR_P (fn) && !DECL_INITIAL (fn)) - synthesize_method (fn); + { + /* Prevent GC. */ + function_depth++; + synthesize_method (fn); + function_depth--; + } return; } @@ -3239,7 +3286,7 @@ defaultable_fn_check (tree fn) /* Avoid do_warn_unused_parameter warnings. */ for (tree p = FUNCTION_FIRST_USER_PARM (fn); p; p = DECL_CHAIN (p)) if (DECL_NAME (p)) - TREE_NO_WARNING (p) = 1; + suppress_warning (p, OPT_Wunused_parameter); if (current_class_type && TYPE_BEING_DEFINED (current_class_type)) /* Defer checking. */; |