diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-12-07 10:45:52 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-12-07 10:45:52 -0800 |
commit | 45c32be1f96ace25b66c34a84818dc5e07e9d516 (patch) | |
tree | 2a6658e3df17c11dd8d74d9c7403c9bc69678010 /gcc/cp | |
parent | 945ae3ab27757d3261d99446f96105c5ebe70247 (diff) | |
parent | b737b70fad398728f6006e8397d1bb31ccea4ce7 (diff) | |
download | gcc-45c32be1f96ace25b66c34a84818dc5e07e9d516.zip gcc-45c32be1f96ace25b66c34a84818dc5e07e9d516.tar.gz gcc-45c32be1f96ace25b66c34a84818dc5e07e9d516.tar.bz2 |
Merge from trunk revision b737b70fad398728f6006e8397d1bb31ccea4ce7.
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 95 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 64 | ||||
-rw-r--r-- | gcc/cp/constraint.cc | 192 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 17 | ||||
-rw-r--r-- | gcc/cp/tree.c | 40 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 61 |
7 files changed, 347 insertions, 124 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1bf50cd..f0386a1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,98 @@ +2020-12-05 Patrick Palka <ppalka@redhat.com> + + PR c++/97093 + * constraint.cc (parameter_mapping_equivalent_p): Add some + sanity checks. Clarify comment. + (tsubst_nested_requirement): Always perform satisfaction + quietly first. If that yields an erroneous result, emit a + context message and replay satisfaction noisily with the + diagnostic normal form. + (finish_nested_requirement): Normalize the constraint-expression + twice, once with diagnostic information and once without. Store + them in a TREE_LIST within the TREE_TYPE. + (diagnose_nested_requirement): When replaying satisfaction, use + the diagnostic normal form instead of renormalizing on the spot. + +2020-12-05 Patrick Palka <ppalka@redhat.com> + + PR c++/97093 + * constraint.cc (struct sat_info): Define. + (tsubst_nested_requirement): Pass a sat_info object to + satisfy_constraint. + (satisfy_constraint_r): Take a sat_info argument instead of + subst_info. + (satisfy_conjunction): Likewise. + (satisfy_disjunction): Likewise. Instead of first evaluating + each branch quietly, evaluate each branch only with + unsatisfaction diagnostics disabled. Exit early if evaluation + of a branch returns error_mark_node. + (satisfy_atom): Take a sat_info argument instead of subst_info. + Fix a comment. Check diagnose_unsatisfaction_p() instead of + noisy() before replaying a substitution failure. + (satisfy_constraint): Take a sat_info argument instead of + subst_info. + (satisfy_associated_constraints): Likewise. + (satisfy_constraint_expression): Likewise. + (satisfy_declaration_constraints): Likewise. + (constraint_satisfaction_value): Likewise and adjust + accordingly. Fix formatting. + (constraints_satisfied_p): Pass a sat_info object to + constraint_satisfaction_value. + (evaluate_concept_check): Pass a sat_info object to + satisfy_constraint_expression. + (diagnose_nested_requirement): Likewise. + (diagnose_constraints): Pass an appropriate sat_info object to + constraint_satisfaction_value. + +2020-12-05 Jakub Jelinek <jakub@redhat.com> + + PR c++/98122 + * constexpr.c (cxx_union_active_member): New function. + (cxx_fold_indirect_ref_1): Add ctx argument, pass it through to + recursive call. Handle UNION_TYPE. + (cxx_fold_indirect_ref): Add ctx argument, pass it to recursive calls + and cxx_fold_indirect_ref_1. + (cxx_eval_indirect_ref): Adjust cxx_fold_indirect_ref calls. + +2020-12-04 Jason Merrill <jason@redhat.com> + + PR c++/93083 + * pt.c (convert_template_argument): Handle equivalent placeholders. + (do_class_deduction): Look through EXPR_PACK_EXPANSION, too. + +2020-12-04 Jason Merrill <jason@redhat.com> + + * decl2.c (clear_consteval_vfns): Remove *. + * pt.c (do_auto_deduction): Remove *. + * parser.c (cp_parser_late_parsing_default_args): Change loop + to use range 'for'. + +2020-12-04 Nathan Sidwell <nathan@acm.org> + + PR c++/98116 + * cp-tree.h (comparing_typenames): Delete. + (cplus_build_array_type): Remove default parm. + * pt.c (comparing_typenames): Delete. + (spec_hasher::equal): Don't increment it. + * tree.c (set_array_type_canon): Remove dep parm. + (build_cplus_array_type): Remove dep parm changes. + (cp_build_qualified_type_real): Remove dependent array type + changes. + (strip_typedefs): Likewise. + * typeck.c (structural_comptypes): Revert comparing_typename + changes. + +2020-12-04 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h: Add various inline module state predicates, and + declare the API that will be provided by modules.cc + +2020-12-04 Jakub Jelinek <jakub@redhat.com> + + PR c++/80780 + * cp-gimplify.c (fold_builtin_source_location): Use 2 instead of 0 + as last argument to cxx_printable_name. + 2020-12-03 Jason Merrill <jason@redhat.com> * cp-tree.h (releasing_vec::operator[]): Change parameter type to diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index e0d3580..cb477c84 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -4611,11 +4611,32 @@ same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2) return same_type_ignoring_top_level_qualifiers_p (type1, type2); } +/* Try to determine the currently active union member for an expression + with UNION_TYPE. If it can be determined, return the FIELD_DECL, + otherwise return NULL_TREE. */ + +static tree +cxx_union_active_member (const constexpr_ctx *ctx, tree t) +{ + constexpr_ctx new_ctx = *ctx; + new_ctx.quiet = true; + bool non_constant_p = false, overflow_p = false; + tree ctor = cxx_eval_constant_expression (&new_ctx, t, false, + &non_constant_p, + &overflow_p); + if (TREE_CODE (ctor) == CONSTRUCTOR + && CONSTRUCTOR_NELTS (ctor) == 1 + && CONSTRUCTOR_ELT (ctor, 0)->index + && TREE_CODE (CONSTRUCTOR_ELT (ctor, 0)->index) == FIELD_DECL) + return CONSTRUCTOR_ELT (ctor, 0)->index; + return NULL_TREE; +} + /* Helper function for cxx_fold_indirect_ref_1, called recursively. */ static tree -cxx_fold_indirect_ref_1 (location_t loc, tree type, tree op, - unsigned HOST_WIDE_INT off, bool *empty_base) +cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, + tree op, unsigned HOST_WIDE_INT off, bool *empty_base) { tree optype = TREE_TYPE (op); unsigned HOST_WIDE_INT const_nunits; @@ -4674,13 +4695,29 @@ cxx_fold_indirect_ref_1 (location_t loc, tree type, tree op, tree index = size_int (idx + tree_to_uhwi (min_val)); op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index, NULL_TREE, NULL_TREE); - return cxx_fold_indirect_ref_1 (loc, type, op, rem, + return cxx_fold_indirect_ref_1 (ctx, loc, type, op, rem, empty_base); } } /* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */ - else if (TREE_CODE (optype) == RECORD_TYPE) + else if (TREE_CODE (optype) == RECORD_TYPE + || TREE_CODE (optype) == UNION_TYPE) { + if (TREE_CODE (optype) == UNION_TYPE) + /* For unions prefer the currently active member. */ + if (tree field = cxx_union_active_member (ctx, op)) + { + unsigned HOST_WIDE_INT el_sz + = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field))); + if (off < el_sz) + { + tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), + op, field, NULL_TREE); + if (tree ret = cxx_fold_indirect_ref_1 (ctx, loc, type, cop, + off, empty_base)) + return ret; + } + } for (tree field = TYPE_FIELDS (optype); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL @@ -4691,13 +4728,13 @@ cxx_fold_indirect_ref_1 (location_t loc, tree type, tree op, if (!tree_fits_uhwi_p (pos)) continue; unsigned HOST_WIDE_INT upos = tree_to_uhwi (pos); - unsigned el_sz + unsigned HOST_WIDE_INT el_sz = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field))); if (upos <= off && off < upos + el_sz) { tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), op, field, NULL_TREE); - if (tree ret = cxx_fold_indirect_ref_1 (loc, type, cop, + if (tree ret = cxx_fold_indirect_ref_1 (ctx, loc, type, cop, off - upos, empty_base)) return ret; @@ -4718,7 +4755,8 @@ cxx_fold_indirect_ref_1 (location_t loc, tree type, tree op, with TBAA in fold_indirect_ref_1. */ static tree -cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) +cxx_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, + tree op0, bool *empty_base) { tree sub = op0; tree subtype; @@ -4756,7 +4794,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) return op; } else - return cxx_fold_indirect_ref_1 (loc, type, op, 0, empty_base); + return cxx_fold_indirect_ref_1 (ctx, loc, type, op, 0, empty_base); } else if (TREE_CODE (sub) == POINTER_PLUS_EXPR && tree_fits_uhwi_p (TREE_OPERAND (sub, 1))) @@ -4766,7 +4804,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) STRIP_NOPS (op00); if (TREE_CODE (op00) == ADDR_EXPR) - return cxx_fold_indirect_ref_1 (loc, type, TREE_OPERAND (op00, 0), + return cxx_fold_indirect_ref_1 (ctx, loc, type, TREE_OPERAND (op00, 0), tree_to_uhwi (op01), empty_base); } /* *(foo *)fooarrptr => (*fooarrptr)[0] */ @@ -4776,7 +4814,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) tree type_domain; tree min_val = size_zero_node; tree newsub - = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL); + = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub, NULL); if (newsub) sub = newsub; else @@ -4811,8 +4849,8 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, } /* First try to simplify it directly. */ - tree r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), orig_op0, - &empty_base); + tree r = cxx_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), + orig_op0, &empty_base); if (!r) { /* If that didn't work, evaluate the operand first. */ @@ -4831,7 +4869,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, return t; } - r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), op0, + r = cxx_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), op0, &empty_base); if (r == NULL_TREE) { diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 00d2f2e..b4c501b 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -98,7 +98,42 @@ struct subst_info tree in_decl; }; -static tree satisfy_constraint (tree, tree, subst_info); +/* Provides additional context for satisfaction. + + The flag noisy() controls whether to diagnose ill-formed satisfaction, + such as the satisfaction value of an atom being non-bool or non-constant. + + The flag diagnose_unsatisfaction_p() controls whether to explain why + a constraint is not satisfied. + + The entrypoints to satisfaction for which we set noisy+unsat are + diagnose_constraints and diagnose_nested_requirement. The entrypoints for + which we set noisy-unsat are the replays inside constraint_satisfaction_value, + evaluate_concept_check and tsubst_nested_requirement. In other entrypoints, + e.g. constraints_satisfied_p, we enter satisfaction quietly (both flags + cleared). */ + +struct sat_info : subst_info +{ + sat_info (tsubst_flags_t cmp, tree in, bool diag_unsat = false) + : subst_info (cmp, in), diagnose_unsatisfaction (diag_unsat) + { + if (diagnose_unsatisfaction_p ()) + gcc_checking_assert (noisy ()); + } + + /* True if we should diagnose the cause of satisfaction failure. + Implies noisy(). */ + bool + diagnose_unsatisfaction_p () const + { + return diagnose_unsatisfaction; + } + + bool diagnose_unsatisfaction; +}; + +static tree satisfy_constraint (tree, tree, sat_info); /* True if T is known to be some type other than bool. Note that this is false for dependent types and errors. */ @@ -584,7 +619,8 @@ build_parameter_mapping (tree expr, tree args, tree decl) return map; } -/* True if the parameter mappings of two atomic constraints are equivalent. */ +/* True if the parameter mappings of two atomic constraints formed + from the same expression are equivalent. */ static bool parameter_mapping_equivalent_p (tree t1, tree t2) @@ -593,6 +629,7 @@ parameter_mapping_equivalent_p (tree t1, tree t2) tree map2 = ATOMIC_CONSTR_MAP (t2); while (map1 && map2) { + gcc_checking_assert (TREE_VALUE (map1) == TREE_VALUE (map2)); tree arg1 = TREE_PURPOSE (map1); tree arg2 = TREE_PURPOSE (map2); if (!template_args_equal (arg1, arg2)) @@ -600,6 +637,7 @@ parameter_mapping_equivalent_p (tree t1, tree t2) map1 = TREE_CHAIN (map1); map2 = TREE_CHAIN (map2); } + gcc_checking_assert (!map1 && !map2); return true; } @@ -2057,13 +2095,16 @@ tsubst_compound_requirement (tree t, tree args, subst_info info) static tree tsubst_nested_requirement (tree t, tree args, subst_info info) { - /* Ensure that we're in an evaluation context prior to satisfaction. */ - tree norm = TREE_TYPE (t); - tree result = satisfy_constraint (norm, args, info); - if (result == error_mark_node && info.quiet ()) + /* Perform satisfaction quietly with the regular normal form. */ + sat_info quiet (tf_none, info.in_decl); + tree norm = TREE_VALUE (TREE_TYPE (t)); + tree diag_norm = TREE_PURPOSE (TREE_TYPE (t)); + tree result = satisfy_constraint (norm, args, quiet); + if (result == error_mark_node) { - subst_info noisy (tf_warning_or_error, info.in_decl); - satisfy_constraint (norm, args, noisy); + /* Replay the error using the diagnostic normal form. */ + sat_info noisy (tf_warning_or_error, info.in_decl); + satisfy_constraint (diag_norm, args, noisy); } if (result != boolean_true_node) return error_mark_node; @@ -2499,12 +2540,12 @@ tsubst_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl) return expr; } -static tree satisfy_constraint_r (tree, tree, subst_info info); +static tree satisfy_constraint_r (tree, tree, sat_info info); /* Compute the satisfaction of a conjunction. */ static tree -satisfy_conjunction (tree t, tree args, subst_info info) +satisfy_conjunction (tree t, tree args, sat_info info) { tree lhs = satisfy_constraint_r (TREE_OPERAND (t, 0), args, info); if (lhs == error_mark_node || lhs == boolean_false_node) @@ -2558,20 +2599,25 @@ collect_operands_of_disjunction (tree t, auto_vec<tree_pair> *operands) /* Compute the satisfaction of a disjunction. */ static tree -satisfy_disjunction (tree t, tree args, subst_info info) +satisfy_disjunction (tree t, tree args, sat_info info) { - /* Evaluate the operands quietly. */ - subst_info quiet (tf_none, NULL_TREE); + /* Evaluate each operand with unsatisfaction diagnostics disabled. */ + sat_info sub = info; + sub.diagnose_unsatisfaction = false; - /* Register the constraint for diagnostics, if needed. */ - diagnosing_failed_constraint failure (t, args, info.noisy ()); + tree lhs = satisfy_constraint_r (TREE_OPERAND (t, 0), args, sub); + if (lhs == boolean_true_node || lhs == error_mark_node) + return lhs; - tree lhs = satisfy_constraint_r (TREE_OPERAND (t, 0), args, quiet); - if (lhs == boolean_true_node) - return boolean_true_node; - tree rhs = satisfy_constraint_r (TREE_OPERAND (t, 1), args, quiet); - if (rhs != boolean_true_node && info.noisy ()) + tree rhs = satisfy_constraint_r (TREE_OPERAND (t, 1), args, sub); + if (rhs == boolean_true_node || rhs == error_mark_node) + return rhs; + + /* Both branches evaluated to false. Explain the satisfaction failure in + each branch. */ + if (info.diagnose_unsatisfaction_p ()) { + diagnosing_failed_constraint failure (t, args, info.noisy ()); cp_expr disj_expr = CONSTR_EXPR (t); inform (disj_expr.get_location (), "no operand of the disjunction is satisfied"); @@ -2592,7 +2638,8 @@ satisfy_disjunction (tree t, tree args, subst_info info) } } } - return rhs; + + return boolean_false_node; } /* Ensures that T is a truth value and not (accidentally, as sometimes @@ -2673,7 +2720,7 @@ static void diagnose_atomic_constraint (tree, tree, tree, subst_info); /* Compute the satisfaction of an atomic constraint. */ static tree -satisfy_atom (tree t, tree args, subst_info info) +satisfy_atom (tree t, tree args, sat_info info) { satisfaction_cache cache (t, args, info.complain); if (tree r = cache.get ()) @@ -2691,9 +2738,9 @@ satisfy_atom (tree t, tree args, subst_info info) tree map = tsubst_parameter_mapping (ATOMIC_CONSTR_MAP (t), args, quiet); if (map == error_mark_node) { - /* If instantiation of the parameter mapping fails, the program - is ill-formed. */ - if (info.noisy()) + /* If instantiation of the parameter mapping fails, the constraint is + not satisfied. Replay the substitution. */ + if (info.diagnose_unsatisfaction_p ()) tsubst_parameter_mapping (ATOMIC_CONSTR_MAP (t), args, info); return cache.save (boolean_false_node); } @@ -2720,7 +2767,7 @@ satisfy_atom (tree t, tree args, subst_info info) { /* If substitution results in an invalid type or expression, the constraint is not satisfied. Replay the substitution. */ - if (info.noisy ()) + if (info.diagnose_unsatisfaction_p ()) tsubst_expr (expr, args, info.complain, info.in_decl, false); return cache.save (inst_cache.save (boolean_false_node)); } @@ -2748,7 +2795,7 @@ satisfy_atom (tree t, tree args, subst_info info) result = error_mark_node; } result = satisfaction_value (result); - if (result == boolean_false_node && info.noisy ()) + if (result == boolean_false_node && info.diagnose_unsatisfaction_p ()) diagnose_atomic_constraint (t, map, result, info); return cache.save (inst_cache.save (result)); @@ -2766,7 +2813,7 @@ satisfy_atom (tree t, tree args, subst_info info) constraint only matters for subsumption. */ static tree -satisfy_constraint_r (tree t, tree args, subst_info info) +satisfy_constraint_r (tree t, tree args, sat_info info) { if (t == error_mark_node) return error_mark_node; @@ -2787,7 +2834,7 @@ satisfy_constraint_r (tree t, tree args, subst_info info) /* Check that the normalized constraint T is satisfied for ARGS. */ static tree -satisfy_constraint (tree t, tree args, subst_info info) +satisfy_constraint (tree t, tree args, sat_info info) { auto_timevar time (TV_CONSTRAINT_SAT); @@ -2805,7 +2852,7 @@ satisfy_constraint (tree t, tree args, subst_info info) value (either true, false, or error). */ static tree -satisfy_associated_constraints (tree t, tree args, subst_info info) +satisfy_associated_constraints (tree t, tree args, sat_info info) { /* If there are no constraints then this is trivially satisfied. */ if (!t) @@ -2823,7 +2870,7 @@ satisfy_associated_constraints (tree t, tree args, subst_info info) satisfaction value. */ static tree -satisfy_constraint_expression (tree t, tree args, subst_info info) +satisfy_constraint_expression (tree t, tree args, sat_info info) { if (t == error_mark_node) return error_mark_node; @@ -2852,12 +2899,12 @@ satisfy_constraint_expression (tree t, tree args, subst_info info) tree satisfy_constraint_expression (tree expr) { - subst_info info (tf_none, NULL_TREE); + sat_info info (tf_none, NULL_TREE); return satisfy_constraint_expression (expr, NULL_TREE, info); } static tree -satisfy_declaration_constraints (tree t, subst_info info) +satisfy_declaration_constraints (tree t, sat_info info) { gcc_assert (DECL_P (t)); const tree saved_t = t; @@ -2917,7 +2964,7 @@ satisfy_declaration_constraints (tree t, subst_info info) } static tree -satisfy_declaration_constraints (tree t, tree args, subst_info info) +satisfy_declaration_constraints (tree t, tree args, sat_info info) { /* Update the declaration for diagnostics. */ info.in_decl = t; @@ -2942,9 +2989,8 @@ satisfy_declaration_constraints (tree t, tree args, subst_info info) } static tree -constraint_satisfaction_value (tree t, tsubst_flags_t complain) +constraint_satisfaction_value (tree t, sat_info info) { - subst_info info (complain, NULL_TREE); tree r; if (DECL_P (t)) r = satisfy_declaration_constraints (t, info); @@ -2952,26 +2998,31 @@ constraint_satisfaction_value (tree t, tsubst_flags_t complain) r = satisfy_constraint_expression (t, NULL_TREE, info); if (r == error_mark_node && info.quiet () && !(DECL_P (t) && TREE_NO_WARNING (t))) - { - constraint_satisfaction_value (t, tf_warning_or_error); - if (DECL_P (t)) - /* Avoid giving these errors again. */ - TREE_NO_WARNING (t) = true; - } + { + /* Replay the error with re-normalized requirements. */ + sat_info noisy (tf_warning_or_error, info.in_decl); + constraint_satisfaction_value (t, noisy); + if (DECL_P (t)) + /* Avoid giving these errors again. */ + TREE_NO_WARNING (t) = true; + } return r; } static tree -constraint_satisfaction_value (tree t, tree args, tsubst_flags_t complain) +constraint_satisfaction_value (tree t, tree args, sat_info info) { - subst_info info (complain, NULL_TREE); tree r; if (DECL_P (t)) r = satisfy_declaration_constraints (t, args, info); else r = satisfy_constraint_expression (t, args, info); if (r == error_mark_node && info.quiet ()) - constraint_satisfaction_value (t, args, tf_warning_or_error); + { + /* Replay the error with re-normalized requirements. */ + sat_info noisy (tf_warning_or_error, info.in_decl); + constraint_satisfaction_value (t, args, noisy); + } return r; } @@ -2984,7 +3035,8 @@ constraints_satisfied_p (tree t) if (!flag_concepts) return true; - return constraint_satisfaction_value (t, tf_none) == boolean_true_node; + sat_info quiet (tf_none, NULL_TREE); + return constraint_satisfaction_value (t, quiet) == boolean_true_node; } /* True iff the result of satisfying T with ARGS is BOOLEAN_TRUE_NODE @@ -2996,7 +3048,8 @@ constraints_satisfied_p (tree t, tree args) if (!flag_concepts) return true; - return constraint_satisfaction_value (t, args, tf_none) == boolean_true_node; + sat_info quiet (tf_none, NULL_TREE); + return constraint_satisfaction_value (t, args, quiet) == boolean_true_node; } /* Evaluate a concept check of the form C<ARGS>. This is only used for the @@ -3011,14 +3064,14 @@ evaluate_concept_check (tree check, tsubst_flags_t complain) gcc_assert (concept_check_p (check)); /* Check for satisfaction without diagnostics. */ - subst_info quiet (tf_none, NULL_TREE); + sat_info quiet (tf_none, NULL_TREE); tree result = satisfy_constraint_expression (check, NULL_TREE, quiet); if (result == error_mark_node && (complain & tf_error)) - { - /* Replay the error with re-normalized requirements. */ - subst_info noisy (tf_warning_or_error, NULL_TREE); - satisfy_constraint_expression (check, NULL_TREE, noisy); - } + { + /* Replay the error with re-normalized requirements. */ + sat_info noisy (tf_warning_or_error, NULL_TREE); + satisfy_constraint_expression (check, NULL_TREE, noisy); + } return result; } @@ -3089,10 +3142,15 @@ finish_compound_requirement (location_t loc, tree expr, tree type, bool noexcept tree finish_nested_requirement (location_t loc, tree expr) { - tree norm = normalize_constraint_expression (expr, false); + /* We need to normalize the constraints now, at parse time, while + we have the necessary template context. We normalize twice, + once without diagnostic information and once with, which we'll + later use for quiet and noisy satisfaction respectively. */ + tree norm = normalize_constraint_expression (expr, /*diag=*/false); + tree diag_norm = normalize_constraint_expression (expr, /*diag=*/true); - /* Build the constraint, saving its normalization as its type. */ - tree r = build1 (NESTED_REQ, norm, expr); + /* Build the constraint, saving its two normalizations as its type. */ + tree r = build1 (NESTED_REQ, build_tree_list (diag_norm, norm), expr); SET_EXPR_LOCATION (r, loc); return r; } @@ -3493,10 +3551,11 @@ diagnose_type_requirement (tree req, tree args, tree in_decl) static void diagnose_nested_requirement (tree req, tree args) { - /* Quietly check for satisfaction first. We can elaborate details - later if needed. */ - tree norm = TREE_TYPE (req); - subst_info info (tf_none, NULL_TREE); + /* Quietly check for satisfaction first using the regular normal form. + We can elaborate details later if needed. */ + tree norm = TREE_VALUE (TREE_TYPE (req)); + tree diag_norm = TREE_PURPOSE (TREE_TYPE (req)); + sat_info info (tf_none, NULL_TREE); tree result = satisfy_constraint (norm, args, info); if (result == boolean_true_node) return; @@ -3505,10 +3564,10 @@ diagnose_nested_requirement (tree req, tree args) location_t loc = cp_expr_location (expr); if (diagnosing_failed_constraint::replay_errors_p ()) { - /* Replay the substitution error. */ + /* Replay the substitution error using the diagnostic normal form. */ inform (loc, "nested requirement %qE is not satisfied, because", expr); - subst_info noisy (tf_warning_or_error, NULL_TREE); - satisfy_constraint_expression (expr, args, noisy); + sat_info noisy (tf_warning_or_error, NULL_TREE, /*diag_unsat=*/true); + satisfy_constraint (diag_norm, args, noisy); } else inform (loc, "nested requirement %qE is not satisfied", expr); @@ -3651,11 +3710,12 @@ diagnose_constraints (location_t loc, tree t, tree args) if (concepts_diagnostics_max_depth == 0) return; - /* Replay satisfaction, but diagnose errors. */ + /* Replay satisfaction, but diagnose unsatisfaction. */ + sat_info noisy (tf_warning_or_error, NULL_TREE, /*diag_unsat=*/true); if (!args) - constraint_satisfaction_value (t, tf_warning_or_error); + constraint_satisfaction_value (t, noisy); else - constraint_satisfaction_value (t, args, tf_warning_or_error); + constraint_satisfaction_value (t, args, noisy); static bool suggested_p; if (concepts_diagnostics_max_depth_exceeded_p diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 00901fe..b72069e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7559,7 +7559,7 @@ extern bool is_local_temp (tree); extern tree build_aggr_init_expr (tree, tree); extern tree get_target_expr (tree); extern tree get_target_expr_sfinae (tree, tsubst_flags_t); -extern tree build_cplus_array_type (tree, tree); +extern tree build_cplus_array_type (tree, tree, int is_dep = -1); extern tree build_array_of_n_type (tree, int); extern bool array_of_runtime_bound_p (tree); extern bool vla_type_p (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a28e792..7da8c65 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3690,17 +3690,17 @@ void pop_switch (void) { struct cp_switch *cs = switch_stack; - location_t switch_location; /* Emit warnings as needed. */ - switch_location = cp_expr_loc_or_input_loc (cs->switch_stmt); + location_t switch_location = cp_expr_loc_or_input_loc (cs->switch_stmt); + tree cond = SWITCH_STMT_COND (cs->switch_stmt); const bool bool_cond_p = (SWITCH_STMT_TYPE (cs->switch_stmt) && TREE_CODE (SWITCH_STMT_TYPE (cs->switch_stmt)) == BOOLEAN_TYPE); if (!processing_template_decl) c_do_switch_warnings (cs->cases, switch_location, - SWITCH_STMT_TYPE (cs->switch_stmt), - SWITCH_STMT_COND (cs->switch_stmt), bool_cond_p); + SWITCH_STMT_TYPE (cs->switch_stmt), cond, + bool_cond_p); /* For the benefit of block_may_fallthru remember if the switch body case labels cover all possible values and if there are break; stmts. */ @@ -3711,6 +3711,15 @@ pop_switch (void) SWITCH_STMT_ALL_CASES_P (cs->switch_stmt) = 1; if (!cs->break_stmt_seen_p) SWITCH_STMT_NO_BREAK_P (cs->switch_stmt) = 1; + /* Now that we're done with the switch warnings, set the switch type + to the type of the condition if the index type was of scoped enum type. + (Such types don't participate in the integer promotions.) We do this + because of bit-fields whose declared type is a scoped enum type: + gimplification will use the lowered index type, but convert the + case values to SWITCH_STMT_TYPE, which would have been the declared type + and verify_gimple_switch doesn't accept that. */ + if (is_bitfield_expr_with_lowered_type (cond)) + SWITCH_STMT_TYPE (cs->switch_stmt) = TREE_TYPE (cond); gcc_assert (!cs->in_loop_body_p); splay_tree_delete (cs->cases); switch_stack = switch_stack->next; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 4e6bf9a..d9fa505 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -998,7 +998,7 @@ build_min_array_type (tree elt_type, tree index_type) build_cplus_array_type. */ static void -set_array_type_canon (tree t, tree elt_type, tree index_type) +set_array_type_canon (tree t, tree elt_type, tree index_type, bool dep) { /* Set the canonical type for this new node. */ if (TYPE_STRUCTURAL_EQUALITY_P (elt_type) @@ -1009,30 +1009,33 @@ set_array_type_canon (tree t, tree elt_type, tree index_type) TYPE_CANONICAL (t) = build_cplus_array_type (TYPE_CANONICAL (elt_type), index_type - ? TYPE_CANONICAL (index_type) : index_type); + ? TYPE_CANONICAL (index_type) : index_type, + dep); else TYPE_CANONICAL (t) = t; } /* Like build_array_type, but handle special C++ semantics: an array of a variant element type is a variant of the array of the main variant of - the element type. */ + the element type. IS_DEPENDENT is -ve if we should determine the + dependency. Otherwise its bool value indicates dependency. */ tree -build_cplus_array_type (tree elt_type, tree index_type) +build_cplus_array_type (tree elt_type, tree index_type, int dependent) { tree t; if (elt_type == error_mark_node || index_type == error_mark_node) return error_mark_node; - bool dependent = (uses_template_parms (elt_type) - || (index_type && uses_template_parms (index_type))); + if (dependent < 0) + dependent = (uses_template_parms (elt_type) + || (index_type && uses_template_parms (index_type))); if (elt_type != TYPE_MAIN_VARIANT (elt_type)) /* Start with an array of the TYPE_MAIN_VARIANT. */ t = build_cplus_array_type (TYPE_MAIN_VARIANT (elt_type), - index_type); + index_type, dependent); else if (dependent) { /* Since type_hash_canon calls layout_type, we need to use our own @@ -1062,13 +1065,20 @@ build_cplus_array_type (tree elt_type, tree index_type) *e = t; /* Set the canonical type for this new node. */ - set_array_type_canon (t, elt_type, index_type); + set_array_type_canon (t, elt_type, index_type, dependent); + + /* Mark it as dependent now, this saves time later. */ + TYPE_DEPENDENT_P_VALID (t) = true; + TYPE_DEPENDENT_P (t) = true; } } else { bool typeless_storage = is_byte_access_type (elt_type); t = build_array_type (elt_type, index_type, typeless_storage); + + /* Mark as non-dependenty now, this will save time later. */ + TYPE_DEPENDENT_P_VALID (t) = true; } /* Now check whether we already have this array variant. */ @@ -1083,7 +1093,10 @@ build_cplus_array_type (tree elt_type, tree index_type) if (!t) { t = build_min_array_type (elt_type, index_type); - set_array_type_canon (t, elt_type, index_type); + /* Mark dependency now, this saves time later. */ + TYPE_DEPENDENT_P_VALID (t) = true; + TYPE_DEPENDENT_P (t) = dependent; + set_array_type_canon (t, elt_type, index_type, dependent); if (!dependent) { layout_type (t); @@ -1319,7 +1332,10 @@ cp_build_qualified_type_real (tree type, if (!t) { - t = build_cplus_array_type (element_type, TYPE_DOMAIN (type)); + gcc_checking_assert (TYPE_DEPENDENT_P_VALID (type) + || !dependent_type_p (type)); + t = build_cplus_array_type (element_type, TYPE_DOMAIN (type), + TYPE_DEPENDENT_P (type)); /* Keep the typedef name. */ if (TYPE_NAME (t) != TYPE_NAME (type)) @@ -1555,7 +1571,9 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags) case ARRAY_TYPE: type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes, flags); - result = build_cplus_array_type (type, t0); + gcc_checking_assert (TYPE_DEPENDENT_P_VALID (t) + || !dependent_type_p (t)); + result = build_cplus_array_type (type, t0, TYPE_DEPENDENT_P (t)); break; case FUNCTION_TYPE: case METHOD_TYPE: diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 267b284..4d499af 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1247,14 +1247,8 @@ cxx_safe_function_type_cast_p (tree t1, tree t2) static bool structural_comptypes (tree t1, tree t2, int strict) { - if (t1 == t2) - return true; - - /* Suppress errors caused by previously reported errors. */ - if (t1 == error_mark_node || t2 == error_mark_node) - return false; - - gcc_assert (TYPE_P (t1) && TYPE_P (t2)); + /* Both should be types that are not obviously the same. */ + gcc_checking_assert (t1 != t2 && TYPE_P (t1) && TYPE_P (t2)); if (!comparing_specializations) { @@ -1300,13 +1294,13 @@ structural_comptypes (tree t1, tree t2, int strict) /* Allow for two different type nodes which have essentially the same definition. Note that we already checked for equality of the type qualifiers (just above). */ - if (TREE_CODE (t1) != ARRAY_TYPE && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) - return true; - + goto check_alias; - /* Compare the types. Break out if they could be the same. */ + /* Compare the types. Return false on known not-same. Break on not + known. Never return true from this switch -- you'll break + specialization comparison. */ switch (TREE_CODE (t1)) { case VOID_TYPE: @@ -1332,7 +1326,11 @@ structural_comptypes (tree t1, tree t2, int strict) have identical properties, different TYPE_MAIN_VARIANTs, but represent the same type. The canonical type system keeps track of equivalence in this case, so we fall back on it. */ - return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2); + if (TYPE_CANONICAL (t1) != TYPE_CANONICAL (t2)) + return false; + + /* We don't need or want the attribute comparison. */ + goto check_alias; case TEMPLATE_TEMPLATE_PARM: case BOUND_TEMPLATE_TEMPLATE_PARM: @@ -1477,24 +1475,28 @@ structural_comptypes (tree t1, tree t2, int strict) return false; } - /* Don't treat an alias template specialization with dependent - arguments as equivalent to its underlying type when used as a - template argument; we need them to be distinct so that we - substitute into the specialization arguments at instantiation - time. And aliases can't be equivalent without being ==, so - we don't need to look any deeper. */ + /* If we get here, we know that from a target independent POV the + types are the same. Make sure the target attributes are also + the same. */ + if (!comp_type_attributes (t1, t2)) + return false; + + check_alias: if (comparing_specializations) { + /* Don't treat an alias template specialization with dependent + arguments as equivalent to its underlying type when used as a + template argument; we need them to be distinct so that we + substitute into the specialization arguments at instantiation + time. And aliases can't be equivalent without being ==, so + we don't need to look any deeper. */ tree dep1 = dependent_alias_template_spec_p (t1, nt_transparent); tree dep2 = dependent_alias_template_spec_p (t2, nt_transparent); if ((dep1 || dep2) && dep1 != dep2) return false; } - /* If we get here, we know that from a target independent POV the - types are the same. Make sure the target attributes are also - the same. */ - return comp_type_attributes (t1, t2); + return true; } /* Return true if T1 and T2 are related as allowed by STRICT. STRICT @@ -1509,6 +1511,13 @@ comptypes (tree t1, tree t2, int strict) gcc_checking_assert (TREE_CODE (t1) != TYPE_ARGUMENT_PACK && TREE_CODE (t2) != TYPE_ARGUMENT_PACK); + if (t1 == t2) + return true; + + /* Suppress errors caused by previously reported errors. */ + if (t1 == error_mark_node || t2 == error_mark_node) + return false; + if (strict == COMPARE_STRICT && comparing_specializations && (t1 != TYPE_CANONICAL (t1) || t2 != TYPE_CANONICAL (t2))) /* If comparing_specializations, treat dependent aliases as distinct. */ @@ -1516,12 +1525,6 @@ comptypes (tree t1, tree t2, int strict) if (strict == COMPARE_STRICT) { - if (t1 == t2) - return true; - - if (t1 == error_mark_node || t2 == error_mark_node) - return false; - if (TYPE_STRUCTURAL_EQUALITY_P (t1) || TYPE_STRUCTURAL_EQUALITY_P (t2)) /* At least one of the types requires structural equality, so perform a deep check. */ |