Commit 1906392b by Andrew Sutton Committed by Andrew Sutton

Diagnose certain constraint errors as hard errors, but otherwise treat them the…

Diagnose certain constraint errors as hard errors, but otherwise treat them the same as normal SFINAE-type errors.

2019-11-27  Andrew Sutton  <asutton@lock3software.com>

	Diagnose certain constraint errors as hard errors, but otherwise treat
	them the same as normal SFINAE-type errors. Also, generally clean up
	the satisfaction functions.

gcc/cp/
	* constexpr.c (cxx_eval_constant_expression): Use
	evaluate_concept_check.
	* constraint.cc (normalize_concept_definition): Accept a diagnostic
	flag and only cache when not diagnosing errors.
	(decl_satisfied_cache): Map to trees instead of bools.
	(satisfy_atom): Guarantee a location for the errors, propagate complain
	flags to force_rvalue, and emit errors for non-boolean constraints.
	(get_normalized_constraints_and_args): New overloads. Factored out of
	satisfy_constraint_expression and satisfy_declaration_constraints.
	(satisfy_constraint_expression): Propagate diagnostic info to
	normalization.
	(satisfy_declaration_constraints): New. Factored out of
	constraints_satisfied_p.
	(constraint_satisfaction_value): New. Calls
	satisfy_constraint_expression or satisfy_declaration_constraints.
	(constraints_satisfied_p): Call constraint_satisfaction_value.
	(evaluate_concept_check): Don't take tsubst_falgs_t. Replay
	satisfaction if an error is encountered.
	(current_failed_constraint): Moved from pt.c.
	(diagnose_constraints): Call constraint_satisfaction_value.
	* cp-tree.h: Update declarations.
	* pt.c (current_failed_constraint): Moved to constraint.cc.
	* semantics.c (finish_id_expression_1): Remove a duplicate case.

gcc/testsuite/
	* g++.dg/concepts/pr84330.C: Update diagnostics.
	* g++.dg/cpp2a/concepts-requires2.C: Likewise.

From-SVN: r278768
parent 45a45488
2019-11-27 Andrew Sutton <asutton@lock3software.com>
Diagnose certain constraint errors as hard errors, but otherwise treat
them the same as normal SFINAE-type errors. Also, generally clean up
the satisfaction functions.
* constexpr.c (cxx_eval_constant_expression): Use
evaluate_concept_check.
* constraint.cc (normalize_concept_definition): Accept a diagnostic
flag and only cache when not diagnosing errors.
(decl_satisfied_cache): Map to trees instead of bools.
(satisfy_atom): Guarantee a location for the errors, propagate complain
flags to force_rvalue, and emit errors for non-boolean constraints.
(get_normalized_constraints_and_args): New overloads. Factored out of
satisfy_constraint_expression and satisfy_declaration_constraints.
(satisfy_constraint_expression): Propagate diagnostic info to
normalization.
(satisfy_declaration_constraints): New. Factored out of
constraints_satisfied_p.
(constraint_satisfaction_value): New. Calls
satisfy_constraint_expression or satisfy_declaration_constraints.
(constraints_satisfied_p): Call constraint_satisfaction_value.
(evaluate_concept_check): Don't take tsubst_falgs_t. Replay
satisfaction if an error is encountered.
(current_failed_constraint): Moved from pt.c.
(diagnose_constraints): Call constraint_satisfaction_value.
* cp-tree.h: Update declarations.
* pt.c (current_failed_constraint): Moved to constraint.cc.
* semantics.c (finish_id_expression_1): Remove a duplicate case.
2019-11-27 Jakub Jelinek <jakub@redhat.com>
PR c++/92524
......
......@@ -5649,7 +5649,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
internal_error ("unexpected template-id %qE", t);
if (!processing_template_decl)
return satisfy_constraint_expression (t);
return evaluate_concept_check (t, tf_warning_or_error);
else
*non_constant_p = true;
return t;
......
......@@ -7821,8 +7821,8 @@ extern bool processing_constraint_expression_p ();
extern tree unpack_concept_check (tree);
extern tree evaluate_concept_check (tree, tsubst_flags_t);
extern tree satisfy_constraint_expression (tree);
extern bool constraints_satisfied_p (tree);
extern bool constraints_satisfied_p (tree, tree);
extern bool constraints_satisfied_p (tree);
extern bool constraints_satisfied_p (tree, tree);
extern void clear_satisfaction_cache ();
extern bool* lookup_subsumption_result (tree, tree);
extern bool save_subsumption_result (tree, tree, bool);
......
......@@ -3358,6 +3358,9 @@ cp_print_error_function (diagnostic_context *context,
to be wrong, so just rely on print_instantiation_full_context. */
if (current_instantiation ())
return;
/* The above is true for constraint satisfaction also. */
if (current_failed_constraint)
return;
if (diagnostic_last_function_changed (context, diagnostic))
{
char *old_prefix = pp_take_prefix (context->printer);
......
......@@ -28736,8 +28736,6 @@ convert_generic_types_to_packs (tree parm, int start_idx, int end_idx)
return tsubst (parm, replacement, tf_none, NULL_TREE);
}
GTY(()) tree current_failed_constraint;
/* __integer_pack(N) in a pack expansion expands to a sequence of numbers from
0..N-1. */
......
......@@ -3970,16 +3970,6 @@ finish_id_expression_1 (tree id_expression,
decl = baselink_for_fns (decl);
}
else if (concept_check_p (decl))
{
/* If this is a standard or variable concept check, potentially
evaluate it. Function concepts need to be called as functions,
so don't try evaluating them here. */
tree tmpl = TREE_OPERAND (decl, 0);
tree args = TREE_OPERAND (decl, 1);
if (!function_concept_p (tmpl) && !uses_template_parms (args))
decl = evaluate_concept_check (decl, tf_warning_or_error);
}
else
{
if (DECL_P (decl) && DECL_NONLOCAL (decl)
......
2019-11-27 Andrew Sutton <asutton@lock3software.com>
Emit hard errors for certain satisfaction errors.
* g++.dg/concepts/pr84330.C: Update diagnostics.
* g++.dg/cpp2a/concepts-requires2.C: Likewise.
2019-11-27 Richard Biener <rguenther@suse.de>
PR tree-optimization/92690
......
......@@ -5,7 +5,7 @@
struct A
{
template<typename T>
requires (sizeof(T) >> 0)
requires (sizeof(T) >> 0) // { dg-error "constraint does not have type 'bool'" }
void foo(T);
void bar()
......
......@@ -12,7 +12,7 @@ template<typename T> constexpr fool p1() { return {}; }
template<typename T> constexpr fool p2() { return {}; }
template<typename T>
concept Bad = p1<T>() && p2<T>();
concept Bad = p1<T>() && p2<T>(); // { dg-error "does not have type 'bool'" }
template<typename T> requires Bad<T> void bad(T x) { }
......@@ -26,14 +26,14 @@ struct X { };
int operator==(X, X) { return 0; }
template<typename T>
concept C1 = (X());
concept C1 = (X()); // { dg-error "does not have type 'bool'" }
template<typename T>
concept C2 = (X() == X());
concept C2 = (X() == X()); // { dg-error "does not have type 'bool'" }
template<typename T>
requires C1<T>
void h1(T) { }
void h1(T) { }
template<typename T>
requires C2<T>
......@@ -42,12 +42,12 @@ void h2(T);
void driver_3()
{
h1(0); // { dg-error "" }
h2(0); // { dg-error "" }
h2(0); // { dg-error "" }
}
// req7.C
template<bool B>
struct boolean_constant
struct boolean_constant
{
constexpr operator bool() const { return B; }
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment