From patchwork Tue Jan 7 19:36:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 104295 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9F00D385800F for ; Tue, 7 Jan 2025 19:37:40 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9F00D385800F Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=NitFZWyg X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id E17673858D26 for ; Tue, 7 Jan 2025 19:36:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E17673858D26 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E17673858D26 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1736278601; cv=none; b=AAXn/KFYrxOt/nFe8st9kvRyfPZuHo1xFRiX4Uv1x3g09RUzmvXkKIP7L3P05G6zCyfjcI4TStM0xFzEzkFVGSV11GbsccG0IHaf4hHlFh8bFIAFJ3uYNmxHZB1KR94gHmaXR/+TeDT3WFcyhmOkIO43pxWiKU5vOuLHjbNV7wk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1736278601; c=relaxed/simple; bh=Is8IUW8kwCdrNeor+SQT0sq6JX+qZ/UCrZ9QfozoDA0=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=wa+H7PYDWUkfnXXNFdWFZTXZc1t65x+UVZl7jMDehJWpe61kr4os2LLUGf66aqVNvUu1aOoL/0fyEnSYbKzwaypzm/3rWQQnTSu7wpYjB8oGayLsAiYkTNVKtK703yr2AMLEsGIahNnTLLZ0vjdQGxIeduy+YFDizjTNP4qPYvs= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E17673858D26 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1736278600; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=PCShDxxA2S/TliGnBQu/Ju8GZSXbG9LdH+G5WgSUN7o=; b=NitFZWygPwr5g/sU2BbO6RJxehoeouzH8HZlCElMRWsA64eNmI88x8OeMxIZlEipXh+MDI fX4eHmxYbC86L88za9EnTKXi4nr2iOQV+7jmZvgSgmSCRNXR/njV4YnO4h+j/ShR8xfJM5 lzz/cC+RM4YjTS6Gvcx0JPGkb6Wv6jI= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-408-elZNEeN_Mn-z0pueeVwMFQ-1; Tue, 07 Jan 2025 14:36:37 -0500 X-MC-Unique: elZNEeN_Mn-z0pueeVwMFQ-1 X-Mimecast-MFC-AGG-ID: elZNEeN_Mn-z0pueeVwMFQ Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7260519560AA; Tue, 7 Jan 2025 19:36:35 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.5]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A7AD13000197; Tue, 7 Jan 2025 19:36:33 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 507JaU5G416355 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Tue, 7 Jan 2025 20:36:30 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 507JaT3T416354; Tue, 7 Jan 2025 20:36:29 +0100 Date: Tue, 7 Jan 2025 20:36:29 +0100 From: Jakub Jelinek To: Jason Merrill , Andi Kleen Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c++: Fix up ICEs on constexpr inline asm strings in templates [PR118277] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: qqkl3JjPkmG3NTtmVbRjbv4IpXGtIEJydAi87B_ocQk_1736278596 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org Hi! The following patch fixes ICEs when the new inline asm syntax to use C++26 static_assert-like constant expressions in place of string literals is used in templates. As finish_asm_stmt doesn't do any checking for processing_template_decl, this patch also just defers handling those strings in templates rather than say trying fold_non_dependent_expr and if the result is non-dependent and usable, try to extract. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? There is one case I didn't handle and I'd like to discuss. The initial commit to enable this new extension also changed cp_parser_asm_specification_opt to use cp_parser_asm_string_expression. That function doesn't have anything to do with asm statements though, it is about asm redirection of declarations. I couldn't find any testcase coverage for that nor documentation. It is basically whether one can use something like void foo () asm ((std::string_view ("bar"))); or not. GCC 14 didn't support that obviously, now it works when not used in templates (both before and after this patch), but will crash when used on templates. Say template void baz () asm ((std::string_view ("qux"))); (or even worse when it is dependent). Do we want to revert the cp_parser_asm_specification_opt changes and only support void foo () asm ("bar");, or was it intentional to add support for constant expressions even for those? The problem with supporting those in templates is that cp_finish_decl/grokfield really assume asmspec_tree is NULL, error_mark_node or STRING_CST, they perform e.g. pragma renaming on those and there is no obvious place to store the not yet finalized constant expression for the asmspec, those are really stored as const char * later transformed into INDENTIFIER_NODEs. Or shall we sorry if it is used in templates for now? Or say temporarily turn into some internal attribute? 2025-01-07 Jakub Jelinek PR c++/118277 * cp-tree.h (finish_asm_string_expression): Declare. * semantics.cc (finish_asm_string_expression): New function. (finish_asm_stmt): Use it. * parser.cc (cp_parser_asm_string_expression): Likewise. * g++.dg/cpp1z/constexpr-asm-4.C: New test. Jakub --- gcc/cp/cp-tree.h.jj 2025-01-03 17:54:12.405906056 +0100 +++ gcc/cp/cp-tree.h 2025-01-07 11:25:58.138829264 +0100 @@ -7946,6 +7946,7 @@ enum { extern tree begin_compound_stmt (unsigned int); extern void finish_compound_stmt (tree); +extern tree finish_asm_string_expression (location_t, tree); extern tree finish_asm_stmt (location_t, int, tree, tree, tree, tree, tree, bool, bool); extern tree finish_label_stmt (tree); --- gcc/cp/semantics.cc.jj 2025-01-03 11:05:47.908986058 +0100 +++ gcc/cp/semantics.cc 2025-01-07 12:02:47.372041244 +0100 @@ -2133,6 +2133,26 @@ finish_compound_stmt (tree stmt) add_stmt (stmt); } +/* Finish an asm string literal, which can be a string literal + or parenthesized constant expression. Extract the string literal + from the latter. */ + +tree +finish_asm_string_expression (location_t loc, tree string) +{ + if (string == error_mark_node + || TREE_CODE (string) == STRING_CST + || processing_template_decl) + return string; + string = cxx_constant_value (string, tf_error); + cexpr_str cstr (string); + if (!cstr.type_check (loc)) + return error_mark_node; + if (!cstr.extract (loc, string)) + string = error_mark_node; + return string; +} + /* Finish an asm-statement, whose components are a STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, some CLOBBERS and some LABELS. Also note whether the asm-statement should be @@ -2159,6 +2179,26 @@ finish_asm_stmt (location_t loc, int vol oconstraints = XALLOCAVEC (const char *, noutputs); + string = finish_asm_string_expression (cp_expr_loc_or_loc (string, loc), + string); + if (string == error_mark_node) + return error_mark_node; + for (int i = 0; i < 2; ++i) + for (t = i ? input_operands : output_operands; t; t = TREE_CHAIN (t)) + { + tree s = TREE_VALUE (TREE_PURPOSE (t)); + s = finish_asm_string_expression (cp_expr_loc_or_loc (s, loc), s); + if (s == error_mark_node) + return error_mark_node; + TREE_VALUE (TREE_PURPOSE (t)) = s; + } + for (t = clobbers; t; t = TREE_CHAIN (t)) + { + tree s = TREE_VALUE (t); + s = finish_asm_string_expression (cp_expr_loc_or_loc (s, loc), s); + TREE_VALUE (t) = s; + } + string = resolve_asm_operand_names (string, output_operands, input_operands, labels); --- gcc/cp/parser.cc.jj 2025-01-03 11:05:47.878986483 +0100 +++ gcc/cp/parser.cc 2025-01-07 11:27:11.384808357 +0100 @@ -23107,15 +23107,8 @@ cp_parser_asm_string_expression (cp_pars matching_parens parens; parens.consume_open (parser); tree string = cp_parser_constant_expression (parser); - if (string != error_mark_node) - string = cxx_constant_value (string, tf_error); - cexpr_str cstr (string); - if (!cstr.type_check (tok->location)) - return error_mark_node; - if (!cstr.extract (tok->location, string)) - string = error_mark_node; parens.require_close (parser); - return string; + return finish_asm_string_expression (tok->location, string); } else if (!cp_parser_is_string_literal (tok)) { --- gcc/testsuite/g++.dg/cpp1z/constexpr-asm-4.C.jj 2025-01-07 12:19:34.472033295 +0100 +++ gcc/testsuite/g++.dg/cpp1z/constexpr-asm-4.C 2025-01-07 12:28:59.178178486 +0100 @@ -0,0 +1,71 @@ +// PR c++/118277 +// { dg-do compile } +// { dg-options "-std=gnu++17" } + +using size_t = decltype (sizeof (0)); +struct string_view { + size_t s; + const char *d; + constexpr string_view () : s (0), d (nullptr) {} + constexpr string_view (const char *p) : s (__builtin_strlen (p)), d (p) {} + constexpr string_view (size_t l, const char *p) : s (l), d (p) {} + constexpr size_t size () const noexcept { return s; } + constexpr const char *data () const noexcept { return d; } +}; + +template +constexpr T +gen (int n) +{ + switch (n) + { + case 0: return "foo %3,%2,%1,%0"; + case 1: return "=r"; + case 2: return "r"; + case 3: return "memory"; + case 4: return "cc"; + case 5: return "goo %3,%2,%1,%0"; + case 6: return "hoo %3,%2,%1,%0"; + } +} + +void +bar () +{ + int a, b; + asm ((gen (0)) + : (gen (1)) (a), (gen (1)) (b) + : (gen (2)) (1), (gen (2)) (2) + : (gen (3)), (gen (4))); +} + +template +void +baz () +{ + U a, b; + asm ((gen (5)) + : (gen (1)) (a), (gen (1)) (b) + : (gen (2)) (U(1)), (gen (2)) (U(2)) + : (gen (3)), (gen (4))); +} + +template +void +qux () +{ + U a, b; + asm ((gen (6)) + : (gen (1)) (a), (gen (1)) (b) + : (gen (2)) (U(1)), (gen (2)) (U(2)) + : (gen (3)), (gen (4))); +} + +void +corge () +{ + qux (); +} + +/* { dg-final { scan-assembler "foo" } } */ +/* { dg-final { scan-assembler "hoo" } } */