aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-12-07 10:45:52 -0800
committerIan Lance Taylor <iant@golang.org>2020-12-07 10:45:52 -0800
commit45c32be1f96ace25b66c34a84818dc5e07e9d516 (patch)
tree2a6658e3df17c11dd8d74d9c7403c9bc69678010 /gcc/cp
parent945ae3ab27757d3261d99446f96105c5ebe70247 (diff)
parentb737b70fad398728f6006e8397d1bb31ccea4ce7 (diff)
downloadgcc-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/ChangeLog95
-rw-r--r--gcc/cp/constexpr.c64
-rw-r--r--gcc/cp/constraint.cc192
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c17
-rw-r--r--gcc/cp/tree.c40
-rw-r--r--gcc/cp/typeck.c61
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. */