From patchwork Wed Mar 18 19:21:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Li, Pan2 via Gcc-patches" X-Patchwork-Id: 1257719 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=XOQ1FJPQ; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48jKf62vg3z9sPR for ; Thu, 19 Mar 2020 06:21:34 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2F0473945060; Wed, 18 Mar 2020 19:21:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2F0473945060 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1584559291; bh=rr3zpLM2snJ/M7ZT6APv7uRualo5AYXeZG6DW1HOG0Q=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=XOQ1FJPQGf/A96gomuW0zsewnX4tvudtPHbq1fPNebG9SNIc9eskGQwy5S5wOH7iw pz5zFPNECNbf0d7WoQBMK1agxWLjb63Y/KDVTh9m1yIRL/Yexppxsf+RrdWzXSuG49 M1GUR/Iq1gqRHw8zLPzd8rBF2FAheKYLvFrW2NRY= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-74.mimecast.com (us-smtp-delivery-74.mimecast.com [63.128.21.74]) by sourceware.org (Postfix) with ESMTP id 9DA1C3944406 for ; Wed, 18 Mar 2020 19:21:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 9DA1C3944406 Received: from mail-qt1-f198.google.com (mail-qt1-f198.google.com [209.85.160.198]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-212-LOKNlQQfN96dqvWJvbZDbg-1; Wed, 18 Mar 2020 15:21:20 -0400 X-MC-Unique: LOKNlQQfN96dqvWJvbZDbg-1 Received: by mail-qt1-f198.google.com with SMTP id o10so26547369qtk.22 for ; Wed, 18 Mar 2020 12:21:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=A3nqd3WVt4fWARVFjVTmJrwOqS6cF29asYE5jFQlm8U=; b=KHinixSNXiC+6ST4jbdH6Ux4Xps5mVZvL1TBuxpQ0HPrrikyk1kPmXg1AfB5t2/kGe sRak613gvb81bliixPveggvsioDIoUeG7CfSDjuB9KGxEtBCJ53Lv11v2fGKjNMbbMjr VE+py2tAC1PTsN+1/OMQiRzzDooAuskKnBZTf8W+mKTCJroiQ/H7ALKEmj79wX2TfA69 /LCM2YAVuk81jzHfl3lOiTfQpr3/TGRMpR63ir6Mxzr9eOCeXs8yj5ePwGhVAn8RU8XP C0uv2agfwUnRXhT+WMvhGrDC8Re4CJ/0KtAA9/xZU2AMv1V5G8g2dx6VaEKV9fT5cWOn BgFQ== X-Gm-Message-State: ANhLgQ3DXSMiOwZAMWSEOPiW3PbRPoXJ3SZwF3YYm9i4uqNxdWVRiXJT fs5Ge4a2qGy3WnwxMkKBg5Hm5sM5jkfWYNZJDarVtsYISH/ob88QkHyOSWhZHNPwpg/zmk3cLBE iouvsHNzf3dqj0jK4qA== X-Received: by 2002:ac8:4c89:: with SMTP id j9mr6276047qtv.68.1584559279968; Wed, 18 Mar 2020 12:21:19 -0700 (PDT) X-Google-Smtp-Source: ADFU+vvSsJq5rz2cleITZINKgvHeDfzhNnIQIl9v1hbBIf/x4siqr9pS3N//mP7OvDISaBlX0zHWLw== X-Received: by 2002:ac8:4c89:: with SMTP id j9mr6276018qtv.68.1584559279540; Wed, 18 Mar 2020 12:21:19 -0700 (PDT) Received: from localhost.localdomain (ool-457d493a.dyn.optonline.net. [69.125.73.58]) by smtp.gmail.com with ESMTPSA id h20sm4692029qka.78.2020.03.18.12.21.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Mar 2020 12:21:18 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH] c++: Include the constraint parameter mapping in diagnostic constraint contexts Date: Wed, 18 Mar 2020 15:21:15 -0400 Message-Id: <20200318192115.1615832-1-ppalka@redhat.com> X-Mailer: git-send-email 2.26.0.rc1.11.g30e9940356 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-25.2 required=5.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Patrick Palka via Gcc-patches From: "Li, Pan2 via Gcc-patches" Reply-To: Patrick Palka Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" When diagnosing a constraint error, we currently try to print the constraint inside a diagnostic constraint context with its template arguments substituted in. If substitution fails, then we instead just print the dependent form, as in the the test case below: gcc/testsuite/g++.dg/concepts/diagnostic6.C:14:15: error: static assertion failed 14 | static_assert(E); // { dg-error "static assertion failed|not a class" } | ^~~~~~ gcc/testsuite/g++.dg/concepts/diagnostic6.C:14:15: note: constraints not satisfied gcc/testsuite/g++.dg/concepts/diagnostic6.C:4:11: required for the satisfaction of ‘C’ gcc/testsuite/g++.dg/concepts/diagnostic6.C:8:11: required for the satisfaction of ‘D’ gcc/testsuite/g++.dg/concepts/diagnostic6.C:14:15: error: ‘int’ is not a class, struct, or union type But printing just the dependent form sometimes makes it difficult to decipher the diagnostic. In the above example, for instance, there's no indication of how the template argument 'int' relates to either of the 'T's. This patch improves the situation by changing these diagnostics to always print the dependent form of the constraint, and alongside it the (preferably substituted) constraint parameter mapping. So with the same test case below we now get: gcc/testsuite/g++.dg/concepts/diagnostic6.C:14:15: error: static assertion failed 14 | static_assert(E); // { dg-error "static assertion failed|not a class" } | ^~~~~~ gcc/testsuite/g++.dg/concepts/diagnostic6.C:14:15: note: constraints not satisfied gcc/testsuite/g++.dg/concepts/diagnostic6.C:4:11: required for the satisfaction of ‘C’ [with T = typename T::type] gcc/testsuite/g++.dg/concepts/diagnostic6.C:8:11: required for the satisfaction of ‘D’ [with T = int] gcc/testsuite/g++.dg/concepts/diagnostic6.C:14:15: error: ‘int’ is not a class, struct, or union type This change arguably makes it easier to figure out what's going on whenever a constraint fails due to substitution resulting in an invalid type rather than failing due to the constraint evaluating to false. Tested on x86_64-pc-linux-gnu, does this look reasonable? I'm not sure if printing an unsubstituted parameter mapping (like in the line 4 message above) is always useful, but perhaps it's better than nothing? gcc/cp/ChangeLog: * cxx-pretty-print.c (pp_cxx_parameter_mapping): Make extern. * cxx-pretty-print.h (pp_cxx_parameter_mapping): Declare. * error.c (rebuild_concept_check): Delete. (print_concept_check_info): Print the constraint uninstantiated and the parameter mapping alongside it. gcc/testsuite/ChangeLog: * g++.dg/concepts/diagnostic6.C: New test. --- gcc/cp/cxx-pretty-print.c | 2 +- gcc/cp/cxx-pretty-print.h | 1 + gcc/cp/error.c | 39 ++++++++------------- gcc/testsuite/g++.dg/concepts/diagnostic6.C | 14 ++++++++ 4 files changed, 30 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/g++.dg/concepts/diagnostic6.C diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 100154e400f..1e89c3f9033 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -2878,7 +2878,7 @@ pp_cxx_check_constraint (cxx_pretty_printer *pp, tree t) /* Output the "[with ...]" clause for a parameter mapping of an atomic constraint. */ -static void +void pp_cxx_parameter_mapping (cxx_pretty_printer *pp, tree map) { for (tree p = map; p; p = TREE_CHAIN (p)) diff --git a/gcc/cp/cxx-pretty-print.h b/gcc/cp/cxx-pretty-print.h index 7c7347f57ba..494f3fdde59 100644 --- a/gcc/cp/cxx-pretty-print.h +++ b/gcc/cp/cxx-pretty-print.h @@ -112,5 +112,6 @@ void pp_cxx_conjunction (cxx_pretty_printer *, tree); void pp_cxx_disjunction (cxx_pretty_printer *, tree); void pp_cxx_constraint (cxx_pretty_printer *, tree); void pp_cxx_constrained_type_spec (cxx_pretty_printer *, tree); +void pp_cxx_parameter_mapping (cxx_pretty_printer *, tree); #endif /* GCC_CXX_PRETTY_PRINT_H */ diff --git a/gcc/cp/error.c b/gcc/cp/error.c index cc51b6ffe13..4bf835e84a1 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -3680,27 +3680,6 @@ print_location (diagnostic_context *context, location_t loc) "locus", xloc.file, xloc.line); } -/* Instantiate the concept check for the purpose of diagnosing an error. */ - -static tree -rebuild_concept_check (tree expr, tree map, tree args) -{ - /* Instantiate the parameter mapping for the template-id. */ - map = tsubst_parameter_mapping (map, args, tf_none, NULL_TREE); - if (map == error_mark_node) - return error_mark_node; - args = get_mapped_args (map); - - /* Rebuild the template id using substituted arguments. Substituting - directly through the expression will trigger recursive satisfaction, - so don't do that. */ - tree id = unpack_concept_check (expr); - args = tsubst_template_args (TREE_OPERAND (id, 1), args, tf_none, NULL_TREE); - if (args == error_mark_node) - return error_mark_node; - return build_nt (TEMPLATE_ID_EXPR, TREE_OPERAND (id, 0), args); -} - static void print_constrained_decl_info (diagnostic_context *context, tree decl) { @@ -3717,12 +3696,22 @@ print_concept_check_info (diagnostic_context *context, tree expr, tree map, tree tree tmpl = TREE_OPERAND (id, 0); if (OVL_P (tmpl)) tmpl = OVL_FIRST (tmpl); - tree check = rebuild_concept_check (expr, map, args); - if (check == error_mark_node) - check = expr; print_location (context, DECL_SOURCE_LOCATION (tmpl)); - pp_verbatim (context->printer, "required for the satisfaction of %qE\n", check); + + cxx_pretty_printer *pp = (cxx_pretty_printer *)context->printer; + pp_verbatim (pp, "required for the satisfaction of %qE", expr); + map = tsubst_parameter_mapping (map, args, tf_none, NULL_TREE); + if (map && map != error_mark_node) + { + pp_cxx_whitespace (pp); + pp_cxx_left_bracket (pp); + pp->translate_string ("with"); + pp_cxx_whitespace (pp); + pp_cxx_parameter_mapping (pp, map); + pp_cxx_right_bracket (pp); + } + pp_newline (pp); } /* Diagnose the entry point into the satisfaction error. Returns the next diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic6.C b/gcc/testsuite/g++.dg/concepts/diagnostic6.C new file mode 100644 index 00000000000..06b17caccbe --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/diagnostic6.C @@ -0,0 +1,14 @@ +// { dg-do compile { target c++2a } } + +template + concept C = requires (T t) { t + 0; }; +// { dg-message "satisfaction of .C. .with T = typename T::type." "" { target *-*-* } .-1 } + +template + concept D = C; +// { dg-message "satisfaction of .D. .with T = int." "" { target *-*-* } .-1 } + +template + concept E = D; + +static_assert(E); // { dg-error "static assertion failed|not a class" }