From patchwork Thu Sep 21 15:51:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 816988 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-462720-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="Dzj3P3Mm"; 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 3xyh143F4Wz9t42 for ; Fri, 22 Sep 2017 01:51:20 +1000 (AEST) 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=kSXMNOkZnaqFKuEsCfmhMfAFWB6o9GntabMxKttSAAGgtl7+21 4um8Hrky94TcirTtWboFqcvLQWwfBOuFRUQnOK8sVFlVG78ukpGle4M9gQnLR58T 1891vK/6+cvRak3jEEKAaUNRua/d5+RbMINTDPv2AiLmz450So5wi78EA= 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=60HAVIYhMdK1V17ynDnJpaBFIv4=; b=Dzj3P3MmcxWWFaKEVL9r KzYRD2Q4dSstYiOlY0Dqr2Z2sm47AksCN5d5uZEImBc+XOSYY25wpZfPFPbNYA59 TQtIo/iHASo+qq+kcx/brgtou+557Hlz0qVc4qoeeHIQQ4B7p5XQzw3/vVL30DIC koUrYDPMI7T/L6y+1Xproig= Received: (qmail 67924 invoked by alias); 21 Sep 2017 15:51:07 -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 67750 invoked by uid 89); 21 Sep 2017 15:51:07 -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=HX-Gm-Message-State:AHPjjUi, 4847, TEMPLATE X-HELO: mail-pg0-f51.google.com Received: from mail-pg0-f51.google.com (HELO mail-pg0-f51.google.com) (74.125.83.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 21 Sep 2017 15:51:04 +0000 Received: by mail-pg0-f51.google.com with SMTP id j16so3737123pga.1 for ; Thu, 21 Sep 2017 08:51:04 -0700 (PDT) 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=cKVotqSpYztqMuhTSVXHPCDXmHdL5B2YEB0M/LkJFq4=; b=RWvWrFmV3YSaFAt6qAceT6W1YbMHyNFUVluawiuui+zB1uQHFI1J30oOfRoEGDTvEG E24BnAPIY08mtYZteSHg35zhHx3qyMb59E5cEPEjxKKQ/gbYS5TFIsVQDyeV2jve4SB6 SYumFZ9PFHbzuJcw+vbxI1/VMVfw1FVFM5v0Pd8pcz/avmF1EPPY8GZaB5kaJ27A3mZI 4ePYqqyLROFpvbZStwe+8xKZ1LsURXqQpx11U4z+skmsCkS6C7jga6j9H438hvDnWii6 gftSbrUCmizUAz77vrrSRNBa/eJVte3tzW0f2sV/65ielvw8o+IreKdn5snMP1RBfBBp VjUQ== X-Gm-Message-State: AHPjjUi+JpB2zsJ9PVeH74r/eH9kBrfH2RSuFMZ0IH3+K3Y3emt9wXo4 Yb7bi/19v6xYHJgEDq0j7lc= X-Google-Smtp-Source: AOwi7QCsersYAJArFoHKO6VG6leZHxPbFoO1qVpLo6woZidzi+4KkyQHlU/Nos6UKvwn2kt7PdMF0Q== X-Received: by 10.84.234.2 with SMTP id m2mr6040883plk.391.1506009062655; Thu, 21 Sep 2017 08:51:02 -0700 (PDT) Received: from ?IPv6:2620:10d:c082:1055:31e1:4d57:79ff:da5a? ([2620:10d:c090:200::4:1dc4]) by smtp.googlemail.com with ESMTPSA id y4sm2896688pgs.19.2017.09.21.08.51.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 21 Sep 2017 08:51:01 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: [demangler PATCH]: Revert and update generic lambda demangling Message-ID: <85e8e7fc-1676-dd47-e8b3-2da467d9a825@acm.org> Date: Thu, 21 Sep 2017 08:51:00 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.3.0 MIME-Version: 1.0 My recent change to generic lambda demangling was incorrect. It wrapped the function type inside the local name, which allowed the printer to see the correct set of template parameters (and not recurse). Except there was a hack to not do that at the outer most level. but that still ends up failing in some cases. This patch takes a different approach. I revert the previous change to teach d_local_name to parse a function type. Instead I teach d_print_comp_inner that it needs to pull template-parms from inside a LOCAL_NAME. This further exposes an existing display problem, namely that the return type of a template function instantiation containing a local name is shown at the start of the demangle -- which is terribly confusing: 'float Foo()::X::fn()' That 'float' looks like it is the return type of X::fn, but it is not. However, this is an existing problem, and changing the behaviour will change other demangles. I shall post a separate patch for that. nathan 2017-09-21 Nathan Sidwell PR demangler/82195 * cp-demangle.c (d_name): Revert addition of 'toplevel' parm. (has_return_type): Recurse for DEMANGLE_COMPONENT_LOCAL_NAME. (d_encoding): Revert d_name change. Use is_fnqual_component_type to strip modifiers that do not belong. (d_special_name, d_class_enum_type): Revert d_name call change. (d_expresion_1): Commonize DEMANGLE_COMPONENT_UNARY building. (d_local_name): Revert parsing of a function type. (d_print_comp_inner): An inner LOCAL_NAME might contain a TEMPLATE. * testsuite/demangle-expected: Add & adjust tests Index: cp-demangle.c =================================================================== --- cp-demangle.c (revision 253070) +++ cp-demangle.c (working copy) @@ -425,7 +425,7 @@ is_ctor_dtor_or_conversion (struct deman static struct demangle_component *d_encoding (struct d_info *, int); -static struct demangle_component *d_name (struct d_info *, int); +static struct demangle_component *d_name (struct d_info *); static struct demangle_component *d_nested_name (struct d_info *); @@ -484,7 +484,7 @@ static struct demangle_component *d_expr static struct demangle_component *d_expr_primary (struct d_info *); -static struct demangle_component *d_local_name (struct d_info *, int); +static struct demangle_component *d_local_name (struct d_info *); static int d_discriminator (struct d_info *); @@ -1259,6 +1259,8 @@ has_return_type (struct demangle_compone { default: return 0; + case DEMANGLE_COMPONENT_LOCAL_NAME: + return has_return_type (d_right (dc)); case DEMANGLE_COMPONENT_TEMPLATE: return ! is_ctor_dtor_or_conversion (d_left (dc)); FNQUAL_COMPONENT_CASE: @@ -1301,25 +1303,22 @@ static struct demangle_component * d_encoding (struct d_info *di, int top_level) { char peek = d_peek_char (di); + struct demangle_component *dc; if (peek == 'G' || peek == 'T') - return d_special_name (di); + dc = d_special_name (di); else { - struct demangle_component *dc, *dcr; - - dc = d_name (di, top_level); + dc = d_name (di); - if (dc != NULL && top_level && (di->options & DMGL_PARAMS) == 0) + if (!dc) + /* Failed already. */; + else if (top_level && (di->options & DMGL_PARAMS) == 0) { /* Strip off any initial CV-qualifiers, as they really apply to the `this' parameter, and they were not output by the v2 demangler without DMGL_PARAMS. */ - while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS - || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS - || dc->type == DEMANGLE_COMPONENT_CONST_THIS - || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS - || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) + while (is_fnqual_component_type (dc->type)) dc = d_left (dc); /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then @@ -1327,22 +1326,27 @@ d_encoding (struct d_info *di, int top_l really apply here; this happens when parsing a class which is local to a function. */ if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME) + while (is_fnqual_component_type (d_right (dc)->type)) + d_right (dc) = d_left (d_right (dc)); + } + else + { + peek = d_peek_char (di); + if (peek != '\0' && peek != 'E') { - dcr = d_right (dc); - while (is_fnqual_component_type (dcr->type)) - dcr = d_left (dcr); - dc->u.s_binary.right = dcr; - } + struct demangle_component *ftype; - return dc; + ftype = d_bare_function_type (di, has_return_type (dc)); + if (ftype) + dc = d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, + dc, ftype); + else + dc = NULL; + } } - - peek = d_peek_char (di); - if (dc == NULL || peek == '\0' || peek == 'E') - return dc; - dcr = d_bare_function_type (di, has_return_type (dc)); - return d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, dc, dcr); } + + return dc; } /* ::= B */ @@ -1383,7 +1387,7 @@ d_abi_tags (struct d_info *di, struct de */ static struct demangle_component * -d_name (struct d_info *di, int top_level) +d_name (struct d_info *di) { char peek = d_peek_char (di); struct demangle_component *dc; @@ -1394,7 +1398,7 @@ d_name (struct d_info *di, int top_level return d_nested_name (di); case 'Z': - return d_local_name (di, top_level); + return d_local_name (di); case 'U': return d_unqualified_name (di); @@ -2079,11 +2083,11 @@ d_special_name (struct d_info *di) case 'H': return d_make_comp (di, DEMANGLE_COMPONENT_TLS_INIT, - d_name (di, 0), NULL); + d_name (di), NULL); case 'W': return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER, - d_name (di, 0), NULL); + d_name (di), NULL); default: return NULL; @@ -2095,11 +2099,11 @@ d_special_name (struct d_info *di) { case 'V': return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, - d_name (di, 0), NULL); + d_name (di), NULL); case 'R': { - struct demangle_component *name = d_name (di, 0); + struct demangle_component *name = d_name (di); return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, name, d_number_component (di)); } @@ -2935,7 +2939,7 @@ d_bare_function_type (struct d_info *di, static struct demangle_component * d_class_enum_type (struct d_info *di) { - return d_name (di, 0); + return d_name (di); } /* ::= A <(positive dimension) number> _ <(element) type> @@ -3380,13 +3384,10 @@ d_expression_1 (struct d_info *di) if (suffix) /* Indicate the suffix variant for d_print_comp. */ - return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, - d_make_comp (di, - DEMANGLE_COMPONENT_BINARY_ARGS, - operand, operand)); - else - return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, - operand); + operand = d_make_comp (di, DEMANGLE_COMPONENT_BINARY_ARGS, + operand, operand); + + return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, operand); } case 2: { @@ -3568,7 +3569,7 @@ d_expr_primary (struct d_info *di) */ static struct demangle_component * -d_local_name (struct d_info *di, int top_level) +d_local_name (struct d_info *di) { struct demangle_component *function; struct demangle_component *name; @@ -3577,6 +3578,8 @@ d_local_name (struct d_info *di, int top return NULL; function = d_encoding (di, 0); + if (!function) + return NULL; if (! d_check_char (di, 'E')) return NULL; @@ -3601,7 +3604,7 @@ d_local_name (struct d_info *di, int top return NULL; } - name = d_name (di, 0); + name = d_name (di); if (name /* Lambdas and unnamed types have internal discriminators @@ -3609,18 +3612,6 @@ d_local_name (struct d_info *di, int top && name->type != DEMANGLE_COMPONENT_LAMBDA && name->type != DEMANGLE_COMPONENT_UNNAMED_TYPE) { - if (!top_level - && d_peek_char (di) != 0 /* Not end of string. */ - && d_peek_char (di) != 'E' /* Not end of nested encoding. */ - && d_peek_char (di) != '_') /* Not discriminator. */ - { - struct demangle_component *args; - - args = d_bare_function_type (di, has_return_type (name)); - name = d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, - name, args); - } - /* Read and ignore an optional discriminator. */ if (! d_discriminator (di)) return NULL; @@ -4710,32 +4701,21 @@ d_print_comp_inner (struct d_print_info return; } - /* If typed_name is a template, then it applies to the - function type as well. */ - if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) - { - dpt.next = dpi->templates; - dpi->templates = &dpt; - dpt.template_decl = typed_name; - } - /* If typed_name is a DEMANGLE_COMPONENT_LOCAL_NAME, then there may be CV-qualifiers on its right argument which - really apply here; this happens when parsing a class which + really apply here; this happens when parsing a class that is local to a function. */ if (typed_name->type == DEMANGLE_COMPONENT_LOCAL_NAME) { - struct demangle_component *local_name; - - local_name = d_right (typed_name); - if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG) - local_name = local_name->u.s_unary_num.sub; - if (local_name == NULL) + typed_name = d_right (typed_name); + if (typed_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG) + typed_name = typed_name->u.s_unary_num.sub; + if (typed_name == NULL) { d_print_error (dpi); return; } - while (is_fnqual_component_type (local_name->type)) + while (is_fnqual_component_type (typed_name->type)) { if (i >= sizeof adpm / sizeof adpm[0]) { @@ -4747,15 +4727,24 @@ d_print_comp_inner (struct d_print_info adpm[i].next = &adpm[i - 1]; dpi->modifiers = &adpm[i]; - adpm[i - 1].mod = local_name; + adpm[i - 1].mod = typed_name; adpm[i - 1].printed = 0; adpm[i - 1].templates = dpi->templates; ++i; - local_name = d_left (local_name); + typed_name = d_left (typed_name); } } + /* If typed_name is a template, then it applies to the + function type as well. */ + if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) + { + dpt.next = dpi->templates; + dpi->templates = &dpt; + dpt.template_decl = typed_name; + } + d_print_comp (dpi, options, d_right (dc)); if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) Index: testsuite/demangle-expected =================================================================== --- testsuite/demangle-expected (revision 253070) +++ testsuite/demangle-expected (working copy) @@ -4739,14 +4739,19 @@ __thunk_4294967297__$_1x # demangler/82195 members of lambdas --no-params _ZZZ3FoovENKUlT_E_clIiEEfS_EN5Local2fnEv -Foo()::float {lambda(auto:1)#1}::operator()(int) const::Local::fn() -Foo()::float {lambda(auto:1)#1}::operator()(int) const::Local::fn +float Foo()::{lambda(auto:1)#1}::operator()(int) const::Local::fn() +float Foo()::{lambda(auto:1)#1}::operator()(int) const::Local::fn --no-params _Z7CaptureIZZ3FoovENKUlT_E_clIiEEvS0_EUlvE_EvOS0_ -void Capture(int) const::{lambda()#1}>(Foo()::void {lambda(auto:1)#1}::operator()(int) const::{lambda()#1}&&) -Capture(int) const::{lambda()#1}> +void Capture(int) const::{lambda()#1}>(void Foo()::{lambda(auto:1)#1}::operator()(int) const::{lambda()#1}&&) +Capture(int) const::{lambda()#1}> --no-params _Z4FrobIZZ3FoovENKUlT_E_clIiEEvS0_EUlvE_Evv -void Frob(int) const::{lambda()#1}>() -Frob(int) const::{lambda()#1}> +void Frob(int) const::{lambda()#1}>() +Frob(int) const::{lambda()#1}> # +# A lambda {local-class::member-fn} +--no-params +_ZZ3FoovENKUlT_E_clIiEEfS_ +float Foo()::{lambda(auto:1)#1}::operator()(int) const +Foo()::{lambda(auto:1)#1}::operator()