From patchwork Thu Feb 8 16:29:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 870941 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-472867-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="jsn1f0TA"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zckDf288zz9s72 for ; Fri, 9 Feb 2018 03:29:37 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=bx7Tdaah7klTCKG8GAp66q5Ch5Mc8ZDR8upx28z3xBfKciTXJE xSrI62GX4quqzJDyZEj6HBg+FMIq5TDeNv3VSAyUs8UEL+N4IMwRdO6BfgT0VpVc 34+F+5MosPDnQ1ZAft31lm2hQfgBFyIwJ1VUVc4D+oiFEnw690uFfKnTw= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=nFLg3x0zl1PEcLTmHklvmmrC2dM=; b=jsn1f0TAI+MNZM4jvpa3 G0Lc1WBeIFgZ1SyoVYdVjagDzw+Ghe3DEeBf9RROsNjSU8hcP0dP9vXTO4Ggdd5l hU+hru1nX3nMBVQKfDv+qsNRP9jP9dXOBmuFut2bj6rBQAn8IOWLr7gTtWZUq2Ew UdzWOCGS5bMo6DrriQRxhfo= Received: (qmail 110812 invoked by alias); 8 Feb 2018 16:29:30 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 110803 invoked by uid 89); 8 Feb 2018 16:29:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.1 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=proceeds, remained, spin, Within X-HELO: mail-yw0-f177.google.com Received: from mail-yw0-f177.google.com (HELO mail-yw0-f177.google.com) (209.85.161.177) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 08 Feb 2018 16:29:27 +0000 Received: by mail-yw0-f177.google.com with SMTP id b16so2996895ywh.12 for ; Thu, 08 Feb 2018 08:29:27 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=IFo7Rtmfw7MUrTUbd6AXYiV+M2jHuC99uX+VfM9U9Yw=; b=pD8KlnwvOmBKBp4KdgdLDUGb/CE9qaP1TIF18lwargudA6qk6n6fZknPy5Hw0mk+fe GJm5BQLj2J+UHlZwxn6aJo6RtEvUKwY2cOKxeW4fwezTKquQRkOdDReouzDwtlyMHyWO vpPtwMUTGji4Js2dWkJBvO8hVySCqeAntxTJASg4xQNEiJJpPiyS+9YMXCb6mFMUSHxV 4pzXkZ59z0EQsYpiljYqseFxRq4j/LrzyQ0TkO1QKLKGLeXG8feaKCWj//Ow5cPashto XoZ/zQXB+jIUWybj45F6UE/F8YrIFZTrUmhk7Z34Td/2zRNL2sVGuBTWIhvyIdtSFSDx gN6A== X-Gm-Message-State: APf1xPDFV9zMhJle8PX14Jiqq9MAO6UAy9FuVZ4F5k/cB8Mp6sks4SaV INRI1KZJNv4nSpwub3GxOyc= X-Google-Smtp-Source: AH8x225KSbt6QK1tUcN7yg/A+j6gSDRN3qdttU2PrNPuZG2hGF7Z4ZLyEOgOeJbss0AMjAMVXJuT6g== X-Received: by 10.37.189.204 with SMTP id g12mr907793ybk.287.1518107365675; Thu, 08 Feb 2018 08:29:25 -0800 (PST) Received: from ?IPv6:2620:10d:c0a3:20fb:7500:e7fb:4a6f:2254? ([2620:10d:c091:200::1:9e4e]) by smtp.googlemail.com with ESMTPSA id g126sm116024ywg.8.2018.02.08.08.29.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 08 Feb 2018 08:29:25 -0800 (PST) To: GCC Patches , =?utf-8?q?Martin_Li=C5=A1ka?= From: Nathan Sidwell Subject: [PR c++/84263] GC ICE with decltype Message-ID: Date: Thu, 8 Feb 2018 11:29:23 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 MIME-Version: 1.0 This patch fixes 84263, a GC breakage entirely unconnected with the patch of mine that exposed it. I guess I perturbed the memory layout sufficiently to tickle it -- on a 32bit host. The underlying problem is that decltype parsing has to squirrel away some data in the same manner to template-ids. But it was failing to push and pop the deferring access stack. That meant it stashed its own deferred accesses, but they also remained on the stack. A subsequent deferred access could reallocate the vector of accesses there, if a subsequent access needed deferring. That reallocation proceeds by gc_alloc/gc_free. The gc_free frees the original set, which is what we had stashed away. All is well until we try and GC things, with that token still live. Boom! Fixed by pushing and popping the access stack. I also reorganized the code to use the modern construct of 'if ... else', rather the assembler-level use of a goto! Martin, I've bootstrapped this on an x86_64 native setup, but i686 native is tricky. Are you able to give this a spin? I modified the testcase slightly -- replacing an 'int' with '__SIZE_TYPE__'. nathan 2018-02-08 Nathan Sidwell PR c++/84263 * parser.c (cp_parser_decltype): Push and pop deferring_access_checks. Reorganize to avoid goto. * g++.dg/parse/pr84263.C: New. Index: cp/parser.c =================================================================== --- cp/parser.c (revision 257496) +++ cp/parser.c (working copy) @@ -14049,12 +14049,7 @@ cp_parser_decltype_expr (cp_parser *pars static tree cp_parser_decltype (cp_parser *parser) { - tree expr; bool id_expression_or_member_access_p = false; - const char *saved_message; - bool saved_integral_constant_expression_p; - bool saved_non_integral_constant_expression_p; - bool saved_greater_than_is_operator_p; cp_token *start_token = cp_lexer_peek_token (parser->lexer); if (start_token->type == CPP_DECLTYPE) @@ -14073,77 +14068,83 @@ cp_parser_decltype (cp_parser *parser) if (!parens.require_open (parser)) return error_mark_node; - /* decltype (auto) */ + push_deferring_access_checks (dk_deferred); + + tree expr = NULL_TREE; + if (cxx_dialect >= cxx14 && cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO)) + /* decltype (auto) */ + cp_lexer_consume_token (parser->lexer); + else { - cp_lexer_consume_token (parser->lexer); - if (!parens.require_close (parser)) - return error_mark_node; - expr = make_decltype_auto (); - AUTO_IS_DECLTYPE (expr) = true; - goto rewrite; - } + /* decltype (expression) */ - /* Types cannot be defined in a `decltype' expression. Save away the - old message. */ - saved_message = parser->type_definition_forbidden_message; - - /* And create the new one. */ - parser->type_definition_forbidden_message - = G_("types may not be defined in % expressions"); - - /* The restrictions on constant-expressions do not apply inside - decltype expressions. */ - saved_integral_constant_expression_p - = parser->integral_constant_expression_p; - saved_non_integral_constant_expression_p - = parser->non_integral_constant_expression_p; - parser->integral_constant_expression_p = false; - - /* Within a parenthesized expression, a `>' token is always - the greater-than operator. */ - saved_greater_than_is_operator_p - = parser->greater_than_is_operator_p; - parser->greater_than_is_operator_p = true; - - /* Do not actually evaluate the expression. */ - ++cp_unevaluated_operand; - - /* Do not warn about problems with the expression. */ - ++c_inhibit_evaluation_warnings; - - expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p); - - /* Go back to evaluating expressions. */ - --cp_unevaluated_operand; - --c_inhibit_evaluation_warnings; - - /* The `>' token might be the end of a template-id or - template-parameter-list now. */ - parser->greater_than_is_operator_p - = saved_greater_than_is_operator_p; - - /* Restore the old message and the integral constant expression - flags. */ - parser->type_definition_forbidden_message = saved_message; - parser->integral_constant_expression_p - = saved_integral_constant_expression_p; - parser->non_integral_constant_expression_p - = saved_non_integral_constant_expression_p; + /* Types cannot be defined in a `decltype' expression. Save away the + old message and set the new one. */ + const char *saved_message = parser->type_definition_forbidden_message; + parser->type_definition_forbidden_message + = G_("types may not be defined in % expressions"); + + /* The restrictions on constant-expressions do not apply inside + decltype expressions. */ + bool saved_integral_constant_expression_p + = parser->integral_constant_expression_p; + bool saved_non_integral_constant_expression_p + = parser->non_integral_constant_expression_p; + parser->integral_constant_expression_p = false; + + /* Within a parenthesized expression, a `>' token is always + the greater-than operator. */ + bool saved_greater_than_is_operator_p + = parser->greater_than_is_operator_p; + parser->greater_than_is_operator_p = true; + + /* Do not actually evaluate the expression. */ + ++cp_unevaluated_operand; + + /* Do not warn about problems with the expression. */ + ++c_inhibit_evaluation_warnings; + + expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p); + + /* Go back to evaluating expressions. */ + --cp_unevaluated_operand; + --c_inhibit_evaluation_warnings; + + /* The `>' token might be the end of a template-id or + template-parameter-list now. */ + parser->greater_than_is_operator_p + = saved_greater_than_is_operator_p; + + /* Restore the old message and the integral constant expression + flags. */ + parser->type_definition_forbidden_message = saved_message; + parser->integral_constant_expression_p + = saved_integral_constant_expression_p; + parser->non_integral_constant_expression_p + = saved_non_integral_constant_expression_p; + } /* Parse to the closing `)'. */ if (!parens.require_close (parser)) { cp_parser_skip_to_closing_parenthesis (parser, true, false, /*consume_paren=*/true); + pop_deferring_access_checks (); return error_mark_node; } - expr = finish_decltype_type (expr, id_expression_or_member_access_p, - tf_warning_or_error); + if (!expr) + { + /* Build auto. */ + expr = make_decltype_auto (); + AUTO_IS_DECLTYPE (expr) = true; + } + else + expr = finish_decltype_type (expr, id_expression_or_member_access_p, + tf_warning_or_error); - rewrite: /* Replace the decltype with a CPP_DECLTYPE so we don't need to parse it again. */ start_token->type = CPP_DECLTYPE; @@ -14153,6 +14154,8 @@ cp_parser_decltype (cp_parser *parser) start_token->keyword = RID_MAX; cp_lexer_purge_tokens_after (parser->lexer, start_token); + pop_to_parent_deferring_access_checks (); + return expr; } Index: testsuite/g++.dg/parse/pr84263.C =================================================================== --- testsuite/g++.dg/parse/pr84263.C (revision 0) +++ testsuite/g++.dg/parse/pr84263.C (working copy) @@ -0,0 +1,36 @@ +// { dg-do compile { target c++11 } } +// { dg-additional-options "--param ggc-min-expand=0 --param ggc-min-heapsize=0" } +// PR 84263, a GC bug exposed on i686 native compiler (and possibly +// other 32-bit hosts). decltype parsing could create a +// pointer that would be gc-freed by later actions. + +namespace std { +template struct b { + int c; + a d; +}; +template class g; +template class initializer_list { + void *e; + __SIZE_TYPE__ f; +}; +class h; +class j { + typedef b i; + +public: + j(); + j(initializer_list); +}; +template struct m; +template struct m {}; +class h { +public: + template h(l &); +}; +class G { + G(); + j n; +}; +G::G() { n = decltype(n){{0, ""}, {1, ".unoLineArrowEnd"}}; } +}