From patchwork Wed Mar 20 23:53:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1059638 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-498215-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdcproject.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="VHvD/p7Z"; 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 44Pmw83jj9z9sR2 for ; Thu, 21 Mar 2019 10:53:39 +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 :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=XD9sHuwqKR9bwIANSzf8PNz47+WcxhvNtgJ6Xyszd75qnZ HboJNe/2TdufvISdDADlgghqtRggS95hSCwMwl8UPPixsOuGgTJja+IKUhiusXJ/ 33DuYNkxk9iWve+q8C9I0XWW6dZu3p4W4Cjsnl8pPOG6WGieyENRFZh2+ROso= 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 :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=wPG/clZABWBUI+3PmUkfQe3Mm44=; b=VHvD/p7ZwwZ0ugRTJVCP ejk0JTZe5ulrO9AYFba+Egea4mnD6DxKiDIJMb46uzlWZLx4oWnL5xpYqT8nzEw1 BQAHR5qin0HsiRVV8EkubmfnW5TFmtxp7rPQjS1yzWQTk2Ur0Psm5vXPWo5sd9W8 F3xXbBATFKzeunV70nG/MQI= Received: (qmail 48188 invoked by alias); 20 Mar 2019 23:53: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 48177 invoked by uid 89); 20 Mar 2019 23:53:30 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-16.4 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=ds, decl_context, DECL_CONTEXT, pointer_type_p X-HELO: mail-qt1-f170.google.com Received: from mail-qt1-f170.google.com (HELO mail-qt1-f170.google.com) (209.85.160.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 20 Mar 2019 23:53:27 +0000 Received: by mail-qt1-f170.google.com with SMTP id k2so4794753qtm.1 for ; Wed, 20 Mar 2019 16:53:27 -0700 (PDT) MIME-Version: 1.0 From: Iain Buclaw Date: Thu, 21 Mar 2019 00:53:14 +0100 Message-ID: Subject: [PATCH, PR d/89017] Committed fix for ICE in force_type_die, at dwarf2out.c To: gcc-patches X-IsSubscribed: yes Hi, This patch adds a new visit method in the decl walker to handle functions whose return type is instantiated from a nested template (a voldemort type), as it needs to be ensured that all members of the instance are emitted before finishing the outer function, otherwise they will be removed during the prune_unused_types pass. Fixing PR d/89017. Bootstrapped and regression tested on x86_64-linux-gnu. Committed to trunk as r269828. diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index e8233b43c67..26929109b48 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -67,7 +67,7 @@ d_decl_context (Dsymbol *dsym) Dsymbol *parent = dsym; Declaration *decl = dsym->isDeclaration (); - while ((parent = parent->toParent ())) + while ((parent = parent->toParent2 ())) { /* We've reached the top-level module namespace. Set DECL_CONTEXT as the NAMESPACE_DECL of the enclosing module, @@ -101,11 +101,6 @@ d_decl_context (Dsymbol *dsym) return context; } - - /* Instantiated types are given the context of their template. */ - TemplateInstance *ti = parent->isTemplateInstance (); - if (ti != NULL && decl == NULL) - parent = ti->tempdecl; } return NULL_TREE; diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index 7edfe523d3e..fffed97727f 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -255,6 +255,40 @@ public: } } + /* Templates are D's approach to generic programming. They have no members + that can be emitted, however if the template is nested and used as a + voldemort type, then it's members must be compiled before the parent + function finishes. */ + + void visit (TemplateDeclaration *d) + { + /* Type cannot be directly named outside of the scope it's declared in, so + the only way it can be escaped is if the function has auto return. */ + FuncDeclaration *fd = d_function_chain ? d_function_chain->function : NULL; + + if (!fd || !fd->isAuto ()) + return; + + /* Check if the function returns an instantiated type that may contain + nested members. Only applies to classes or structs. */ + Type *tb = fd->type->nextOf ()->baseElemOf (); + + while (tb->ty == Tarray || tb->ty == Tpointer) + tb = tb->nextOf ()->baseElemOf (); + + TemplateInstance *ti = NULL; + + if (tb->ty == Tstruct) + ti = ((TypeStruct *) tb)->sym->isInstantiated (); + else if (tb->ty == Tclass) + ti = ((TypeClass *) tb)->sym->isInstantiated (); + + /* Return type is instantiated from this template declaration, walk over + all members of the instance. */ + if (ti && ti->tempdecl == d) + ti->accept (this); + } + /* Walk over all members in the instantiated template. */ void visit (TemplateInstance *d) @@ -2228,8 +2262,13 @@ build_type_decl (tree type, Dsymbol *dsym) gcc_assert (!POINTER_TYPE_P (type)); + /* If a templated type, use the template instance name, as that includes all + template parameters. */ + const char *name = dsym->parent->isTemplateInstance () + ? ((TemplateInstance *) dsym->parent)->toChars () : dsym->ident->toChars (); + tree decl = build_decl (make_location_t (dsym->loc), TYPE_DECL, - get_identifier (dsym->ident->toChars ()), type); + get_identifier (name), type); SET_DECL_ASSEMBLER_NAME (decl, get_identifier (mangle_decl (dsym))); TREE_PUBLIC (decl) = 1; DECL_ARTIFICIAL (decl) = 1; diff --git a/gcc/testsuite/gdc.dg/pr89017.d b/gcc/testsuite/gdc.dg/pr89017.d new file mode 100644 index 00000000000..b796e6246e8 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr89017.d @@ -0,0 +1,49 @@ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89017 +// { dg-do compile } + +enum Type +{ + Struct, + Class, + Pointer, + Array, +} + +auto f89017(Type type)() +{ + static if (type == Type.Class) + { + class C(S) + { + struct S + { + void fn(){} + } + } + } + else + { + struct C(S) + { + struct S + { + void fn(){} + } + } + } + + static if (type == Type.Struct) + return C!Type(); + static if (type == Type.Class || type == Type.Pointer) + return new C!Type(); + static if (type == Type.Array) + return new C!Type[2]; +} + +void test89017() +{ + f89017!(Type.Class); + f89017!(Type.Struct); + f89017!(Type.Pointer); + f89017!(Type.Array); +}