diff options
author | Andrew Sutton <asutton@lock3software.com> | 2019-11-27 15:23:02 +0000 |
---|---|---|
committer | Andrew Sutton <asutton@gcc.gnu.org> | 2019-11-27 15:23:02 +0000 |
commit | 861d4af8d82819a857e360949545651adf33a264 (patch) | |
tree | 231f0fe9b111f132f4b47a343e458ff6be85c9f3 /gcc/cp/semantics.c | |
parent | 50e0c6e429e7cc664f6fcea59db22826f005ca19 (diff) | |
download | gcc-861d4af8d82819a857e360949545651adf33a264.zip gcc-861d4af8d82819a857e360949545651adf33a264.tar.gz gcc-861d4af8d82819a857e360949545651adf33a264.tar.bz2 |
re PR c++/92236 ([concepts] Explain non-satisfaction in static_assert)
2019-11-27 Andrew Sutton <asutton@lock3software.com>
PR c++/92236
Defer evaluation of concept checks so that static assertions can
emit more detailed diagnostics.
gcc/cp/
* constexpr.c (cxx_eval_call_expression): Handle concept checks.
(cxx_eval_constant_expression): Diagnose misuse of function concepts
as template-id expressions. Follow the usual return path for results.
(cxx_eval_outermost_constant_expr): Avoid calling
cp_get_callee_fndecl_nofold for function concepts.
* constraint.cc (build_function_check): Fully type the concept check
so that we don't ICE in conversions.
* cp-gimplify.c (cp_genericize_r) [CALL_EXPR]: Handle concept checks.
[TEMPLATE_ID_EXPR] Likewise.
* cvt.c (convert_to_void): Always evaluate concept checks so we don't
accidentally ignore them. Substitution during satisfaction can make
a program ill-formed (example in g++.dg/cpp2a/concepts6.C).
* pt.c (tsubst_copy_and_build): [CALL_EXPR]: Don't evaluate concepts.
[TEMPLATE_ID_EXPR]: Likewise.
* semantics.c (finish_call_expr): Don't evaluate concepts.
(finish_id_expression_1): Likewise.
(finish_static_assert): Preserve the original condition so we can
diagnose concept errors when a check returns false.
gcc/testsuite/
* g++.dg/cpp2a/concepts-iconv1.C: Update diagnostics.
* g++.dg/cpp2a/concepts-requires5.C: Likewise.
* g++.dg/cpp2a/concepts6.C: New test.
From-SVN: r278775
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r-- | gcc/cp/semantics.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 6c4785c..4a5479c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2605,10 +2605,6 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual, /* Ensure the result is wrapped as a call expression. */ result = build_concept_check (tmpl, args, tf_warning_or_error); - - /* Evaluate the check if it is non-dependent. */ - if (!uses_template_parms (args)) - result = evaluate_concept_check (result, complain); } else if (is_overloaded_fn (fn)) { @@ -3890,13 +3886,8 @@ finish_id_expression_1 (tree id_expression, } 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); + /* Nothing more to do. All of the analysis for concept checks + is done by build_conept_id, called from the parser. */ } else if (scope) { @@ -9564,6 +9555,9 @@ finish_static_assert (tree condition, tree message, location_t location, return; } + /* Save the condition in case it was a concept check. */ + tree orig_condition = condition; + /* Fold the expression and convert it to a boolean value. */ condition = perform_implicit_conversion_flags (boolean_type_node, condition, complain, LOOKUP_NORMAL); @@ -9590,6 +9584,10 @@ finish_static_assert (tree condition, tree message, location_t location, else error ("static assertion failed: %s", TREE_STRING_POINTER (message)); + + /* Actually explain the failure if this is a concept check. */ + if (concept_check_p (orig_condition)) + diagnose_constraints (location, orig_condition, NULL_TREE); } else if (condition && condition != error_mark_node) { |