Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/2224249/?format=api
{ "id": 2224249, "url": "http://patchwork.ozlabs.org/api/1.2/patches/2224249/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/CAGkQGiK6nmyc7LVmN7-8SafPpDY8gfXy0S_-TR_hRZRnCUi+xw@mail.gmail.com/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/1.2/projects/17/?format=api", "name": "GNU Compiler Collection", "link_name": "gcc", "list_id": "gcc-patches.gcc.gnu.org", "list_email": "gcc-patches@gcc.gnu.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<CAGkQGiK6nmyc7LVmN7-8SafPpDY8gfXy0S_-TR_hRZRnCUi+xw@mail.gmail.com>", "list_archive_url": null, "date": "2026-04-17T07:36:48", "name": "[fortran] PR121384 - Wrongly initialized associate array descriptor when the target is wrapped in parenthesis", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "7fc7b6060d793492a74a1c28a98bc7bde49af58a", "submitter": { "id": 4392, "url": "http://patchwork.ozlabs.org/api/1.2/people/4392/?format=api", "name": "Paul Richard Thomas", "email": "paul.richard.thomas@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/CAGkQGiK6nmyc7LVmN7-8SafPpDY8gfXy0S_-TR_hRZRnCUi+xw@mail.gmail.com/mbox/", "series": [ { "id": 500252, "url": "http://patchwork.ozlabs.org/api/1.2/series/500252/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=500252", "date": "2026-04-17T07:36:48", "name": "[fortran] PR121384 - Wrongly initialized associate array descriptor when the target is wrapped in parenthesis", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/500252/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2224249/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2224249/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=Qtz/+ViM;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)", "sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=Qtz/+ViM", "sourceware.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "sourceware.org; spf=pass smtp.mailfrom=gmail.com", "server2.sourceware.org;\n arc=pass smtp.remote-ip=74.125.82.42" ], "Received": [ "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fxmv12mJCz1yDF\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 17:37:47 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 9316C4BAD142\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 07:37:44 +0000 (GMT)", "from mail-dl1-f42.google.com (mail-dl1-f42.google.com\n [74.125.82.42])\n by sourceware.org (Postfix) with ESMTPS id E64374BA2E0A\n for <gcc-patches@gcc.gnu.org>; Fri, 17 Apr 2026 07:37:03 +0000 (GMT)", "by mail-dl1-f42.google.com with SMTP id\n a92af1059eb24-1274204434bso1092008c88.1\n for <gcc-patches@gcc.gnu.org>; Fri, 17 Apr 2026 00:37:03 -0700 (PDT)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 9316C4BAD142", "OpenDKIM Filter v2.11.0 sourceware.org E64374BA2E0A" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org E64374BA2E0A", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org E64374BA2E0A", "ARC-Seal": [ "i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1776411424; cv=pass;\n b=FtfcmrTTT/uRBeXkQ7Vnwge7zOrmrZI4p+qYijblwBU6I/ocoWmkkRrdRj9rN5MnQcgvxBjyeYQT3Q11GBzhn2r7xDEHEh4+Py36opXjupGD40+rvPrzBEYV1n4K1vI5cOZQiAQ3ysC1hrfahDWzUwLlHgYSXPuAdAvs6TgevL0=", "i=1; a=rsa-sha256; t=1776411423; cv=none;\n d=google.com; s=arc-20240605;\n b=QZjovt463JFXGlwQCykF3RVgeaoe/et3w3L6z4pkzmgzayKOhia1mFJwShDJYcD0aQ\n IkoWTbV4L4LUfexvEFWhn6TmNKrO9kgNXrEkdwT+aRtrn1/7DNo0XTskDFaAmiYSpu+B\n +i/0nqMnvPBXESadjMqWM8RcCIJwy/00pqgt59obJ2MuNU/rAnHh+TAQDlc9/SMPoeRA\n Ek13/Cp9sX8H02ejQgKRQbpezCucQ6fDyyJPgDsCVvWW/3horSv4orkPdG0WtpXWJ0/P\n STTflBYWXNJ6Au7lfsnQ19D+9x3gWDO10sN27yHMLzugJdInJ8hqYGZ4iowgx03BA3lM\n U5zA==" ], "ARC-Message-Signature": [ "i=2; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776411424; c=relaxed/simple;\n bh=I0jHxzN6eeeQOlk4LI/qMDe3L1XNMUv0fCTPQzosmMY=;\n h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To;\n b=Ewdp5rc8ExIE6okdiYlC4xEgTamLSk6Ivfzrvwx4Tq1kifyaA3k4kasCSRrJoylFQJ3NVA3Alj592jcYD02/GhMeRUxbEQP2HbSFp/zKrVUIE3wSOM2pfeaf8ELYC5Gl61Zv5jY30j/Oxf64wCgpDIJnr1/ifkecAd1LcRh2jzU=", "i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com;\n s=arc-20240605;\n h=to:subject:message-id:date:from:mime-version:dkim-signature;\n bh=I0jHxzN6eeeQOlk4LI/qMDe3L1XNMUv0fCTPQzosmMY=;\n fh=uwBox9RMZtdUOt0m8EF5Ek3gnPUtI+jsRyNuj+/VoS8=;\n b=Qjia8IDz8fLhjACG/kQEquhXqKYUC9vtmrreS7symPdUwqtV4qzD2cWyh0acT8zlWz\n X1C78eTgHcmALruHvo0RRTVj/1Y42Mq5xOy3pTftQ+6xgtaIQwEN+ONgF9UhdG2PN5Xt\n gwKgSwZkN5LwJfuwRe+1jMFGcNoFOj5v+K8YIUHqQchoMcx35813bPaSynXlj513/lxG\n 64NC/GIP9yQz+m8xiJwFNbNCD4iuxoD21n0dusgaz/llGlFnR3GT8EphZma2r9uZe/Os\n edCB7KDbSZlhyAQdm2wHdA3XSxymqG2WgMb9sdqpPEkVpFJSJ8fs+7IbneTMgrl8nFk9\n +NIg==; darn=gcc.gnu.org" ], "ARC-Authentication-Results": [ "i=2; server2.sourceware.org", "i=1; mx.google.com; arc=none" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1776411423; x=1777016223; darn=gcc.gnu.org;\n h=to:subject:message-id:date:from:mime-version:from:to:cc:subject\n :date:message-id:reply-to;\n bh=I0jHxzN6eeeQOlk4LI/qMDe3L1XNMUv0fCTPQzosmMY=;\n b=Qtz/+ViM/sHEHtDknUjHduBBY2Gzv0h3dN/D3L5h8ku31mbWwMMsS3jEluvhB1T1PC\n TVpfRs8u4wHv1nPdkLREOhVRCh/VNMVcey5fDIX/zm3wdE/BAE2jDVAA+r/h2n9ccNvH\n nnWndU3f75beIYWbW2LVpmSzvuG4cINwvJVLYHKtP5+WQcnG2LZ/cD2Bs7AFRT5O0+zp\n FgDnlGWYViiraeEKFWa8rV3uCSsWBZN7FYUtTg4QAOUwuBWp+DWY2BJSjR7XQNJypOhc\n K6t56PPXovZVLd0tJ3ZGTPyrQB3tNJbZ6FJQsW9K25bCteY+HDtofqRA/YZ8xzVOZQGx\n X9EQ==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776411423; x=1777016223;\n h=to:subject:message-id:date:from:mime-version:x-gm-gg\n :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;\n bh=I0jHxzN6eeeQOlk4LI/qMDe3L1XNMUv0fCTPQzosmMY=;\n b=fDi1D4b6dd7Us+xhYrggfuloAqnxwWQwPHIHfoDyCMrqdfxULlBGFERfGRCGTOHAYl\n 938RIgDnfDRn5Oy8GahitPMQveP0tIw4CLzRfmxoPTt36h4w0Zk7i8ow4cxXQvncAHdt\n pwzGZN3lkcuHwzzvf+0k2ftKvGKZoYtfCYNn+TWkQpTwkddpBJCUetmLpc1Vn48+PaTM\n 4kkJLCrEV6AORwEIEXYK5wnjISAB3Dlse8qTWukptAcM4e72nlbYvSYK17o2Rq5hINmD\n Q4FsN4lBQoSlHv4d555XZsgNDj/wUMJNFxwSVl51lQjOrKrptv+tydHpE+HmFSMFLQD6\n OcZw==", "X-Forwarded-Encrypted": "i=1;\n AFNElJ9romyqie48niULUuzfD8uEMxYHECwM1tcyQvR2ZynKDqZGT69OdWtrFjh+nvhndOeKaWScml3MhXnkwA==@gcc.gnu.org", "X-Gm-Message-State": "AOJu0YwuOteVC8IGLhar0J76Dn4m99LnwguIQI8xvMYPqqgmZ3o02Yre\n gB9Nx1FvrtvMdqdzIvCbZAj5LrbES5eqchPFgFzGlgJFF97XfHI6t11cX1R1racmGH9jum3QFSe\n lQbqLSdoq+iOVotnME/9lqes+gdhQPf+VMA==", "X-Gm-Gg": "AeBDietNFEKuni32FOGaGh0xG7ASAIErxlhmyqGbm94/1/WRzaqzpalV2pUgUiSB9Ss\n /nPNVXsEme8B3q6GhDlFaOmLu+SVQTSSIPikfc8jOhyN6KEPHx80r7muOx0boNRGBo5QOi4XYgk\n mBRifjAReA97SS7VINm0XWlAuSD5pW46Oqzz9p9v0zvpiNBEmbIKbiO7+jADAjD2MjmO6jUvzrd\n xN0KrvNMk/o8vlcggCavhn7c0IwHtHJyVnvSaqyvi2SX3YtTuEM3DQQiPW6QpcqoGITy7R0PWgE\n CLztANuDeKKnDKvyaxJnZ6Py5QHr67eDuOz37Gkijkoo94J/8YAm", "X-Received": "by 2002:a05:7022:6181:b0:12b:fd86:b443 with SMTP id\n a92af1059eb24-12c73afa6a5mr625347c88.7.1776411422480; Fri, 17 Apr 2026\n 00:37:02 -0700 (PDT)", "MIME-Version": "1.0", "From": "Paul Richard Thomas <paul.richard.thomas@gmail.com>", "Date": "Fri, 17 Apr 2026 08:36:48 +0100", "X-Gm-Features": "AQROBzD-8kTOBfLiqUu5s-FKFNhvxj2r4_FjrkXlM9Ggc14l1c2rZfIxmVbGLKI", "Message-ID": "\n <CAGkQGiK6nmyc7LVmN7-8SafPpDY8gfXy0S_-TR_hRZRnCUi+xw@mail.gmail.com>", "Subject": "[Patch, fortran] PR121384 - Wrongly initialized associate array\n descriptor when the target is wrapped in parenthesis", "To": "\"fortran@gcc.gnu.org\" <fortran@gcc.gnu.org>,\n gcc-patches <gcc-patches@gcc.gnu.org>", "Content-Type": "multipart/mixed; boundary=\"000000000000d059e9064fa30370\"", "X-BeenThere": "gcc-patches@gcc.gnu.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>", "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>", "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>", "List-Post": "<mailto:gcc-patches@gcc.gnu.org>", "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>", "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>", "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org" }, "content": "This one is actually very straightforward. Most of the patch consists\nof moves of helper functions to allow a temporary to be constructed\nfor the selector.\n\nRegtests on FC43/x86_64 - OK for mainline?\n\nOnce 17-branch is open, I will see if an extension to this patch can\nbe used to eliminate a lot of code in trans-stmt.cc.\n\nPaul", "diff": "From 691c7503f509423c3ffedbfa0bda5207281951bd Mon Sep 17 00:00:00 2001\nFrom: Paul Thomas <pault@gcc.gnu.org>\nDate: Fri, 17 Apr 2026 06:00:03 +0100\nSubject: [PATCH] Fortran: Fix wrongly initialized associate-name descriptor\n [PR121384]\n\n2026-04-17 Paul Thomas <pault@gcc.gnu.org>\n\ngcc/fortran\n\tPR fortran/121384\n\t* resolve.cc (add_comp_ref, build_assignment,\n\tadd_code_to_chain, get_temp_from_expr,\n\tadd_temp_assign_before_call) : Move to top of file and delete\n\tprototypes.\n\t(resolve_block_construct): Generate a temporary for subref\n\tarray selectors enclosed in parantheses.\n\ngcc/testsuite\n\tPR fortran/121384\n\t* gfortran.dg/associate_79.f90: New test.\n---\n gcc/fortran/resolve.cc | 556 +++++++++++----------\n gcc/testsuite/gfortran.dg/associate_79.f90 | 43 ++\n 2 files changed, 338 insertions(+), 261 deletions(-)\n create mode 100644 gcc/testsuite/gfortran.dg/associate_79.f90\n\ndiff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc\nindex a5d9add9d2f..bf078a40206 100644\n--- a/gcc/fortran/resolve.cc\n+++ b/gcc/fortran/resolve.cc\n@@ -204,6 +204,264 @@ check_proc_interface (gfc_symbol *ifc, locus *where)\n static void resolve_symbol (gfc_symbol *sym);\n \n \n+/*************Helper functions for modifying code*********************/\n+\n+/* Add a component reference onto an expression. */\n+\n+static void\n+add_comp_ref (gfc_expr *e, gfc_component *c)\n+{\n+ gfc_ref **ref;\n+ ref = &(e->ref);\n+ while (*ref)\n+ ref = &((*ref)->next);\n+ *ref = gfc_get_ref ();\n+ (*ref)->type = REF_COMPONENT;\n+ (*ref)->u.c.sym = e->ts.u.derived;\n+ (*ref)->u.c.component = c;\n+ e->ts = c->ts;\n+\n+ /* Add a full array ref, as necessary. */\n+ if (c->as)\n+ {\n+ gfc_add_full_array_ref (e, c->as);\n+ e->rank = c->as->rank;\n+ e->corank = c->as->corank;\n+ }\n+}\n+\n+\n+/* Build an assignment. Keep the argument 'op' for future use, so that\n+ pointer assignments can be made. */\n+\n+static gfc_code *\n+build_assignment (gfc_exec_op op, gfc_expr *expr1, gfc_expr *expr2,\n+\t\t gfc_component *comp1, gfc_component *comp2, locus loc)\n+{\n+ gfc_code *this_code;\n+\n+ this_code = gfc_get_code (op);\n+ this_code->next = NULL;\n+ this_code->expr1 = gfc_copy_expr (expr1);\n+ this_code->expr2 = gfc_copy_expr (expr2);\n+ this_code->loc = loc;\n+ if (comp1 && comp2)\n+ {\n+ add_comp_ref (this_code->expr1, comp1);\n+ add_comp_ref (this_code->expr2, comp2);\n+ }\n+\n+ return this_code;\n+}\n+\n+\n+/* Makes a temporary variable expression based on the characteristics of\n+ a given variable expression. If allocatable is set, the temporary is\n+ unconditionally allocatable*/\n+\n+static gfc_expr*\n+get_temp_from_expr (gfc_expr *e, gfc_namespace *ns,\n+\t\t bool allocatable = false)\n+{\n+ static int serial = 0;\n+ char name[GFC_MAX_SYMBOL_LEN];\n+ gfc_symtree *tmp;\n+ gfc_array_spec *as;\n+ gfc_array_ref *aref;\n+ gfc_ref *ref;\n+\n+ sprintf (name, GFC_PREFIX(\"DA%d\"), serial++);\n+ gfc_get_sym_tree (name, ns, &tmp, false);\n+ gfc_add_type (tmp->n.sym, &e->ts, NULL);\n+\n+ if (e->expr_type == EXPR_CONSTANT && e->ts.type == BT_CHARACTER)\n+ tmp->n.sym->ts.u.cl->length = gfc_get_int_expr (gfc_charlen_int_kind,\n+\t\t\t\t\t\t NULL,\n+\t\t\t\t\t\t e->value.character.length);\n+\n+ as = NULL;\n+ ref = NULL;\n+ aref = NULL;\n+\n+ /* Obtain the arrayspec for the temporary. */\n+ if (e->rank && e->expr_type != EXPR_ARRAY\n+ && e->expr_type != EXPR_FUNCTION\n+ && e->expr_type != EXPR_OP)\n+ {\n+ aref = gfc_find_array_ref (e);\n+ if (e->expr_type == EXPR_VARIABLE\n+\t && e->symtree->n.sym->as == aref->as)\n+\tas = aref->as;\n+ else\n+\t{\n+\t for (ref = e->ref; ref; ref = ref->next)\n+\t if (ref->type == REF_COMPONENT\n+\t\t&& ref->u.c.component->as == aref->as)\n+\t {\n+\t\tas = aref->as;\n+\t\tbreak;\n+\t }\n+\t}\n+ }\n+\n+ /* Add the attributes and the arrayspec to the temporary. */\n+ tmp->n.sym->attr = gfc_expr_attr (e);\n+ tmp->n.sym->attr.function = 0;\n+ tmp->n.sym->attr.proc_pointer = 0;\n+ tmp->n.sym->attr.result = 0;\n+ tmp->n.sym->attr.flavor = FL_VARIABLE;\n+ tmp->n.sym->attr.dummy = 0;\n+ tmp->n.sym->attr.use_assoc = 0;\n+ tmp->n.sym->attr.intent = INTENT_UNKNOWN;\n+\n+\n+ if (as && !allocatable)\n+ {\n+ tmp->n.sym->as = gfc_copy_array_spec (as);\n+ if (!ref)\n+\tref = e->ref;\n+ if (as->type == AS_DEFERRED)\n+\ttmp->n.sym->attr.allocatable = 1;\n+ }\n+ else if ((e->rank || e->corank)\n+\t && (e->expr_type == EXPR_ARRAY || e->expr_type == EXPR_FUNCTION\n+\t || e->expr_type == EXPR_OP || allocatable))\n+ {\n+ tmp->n.sym->as = gfc_get_array_spec ();\n+ tmp->n.sym->as->type = AS_DEFERRED;\n+ tmp->n.sym->as->rank = e->rank;\n+ tmp->n.sym->as->corank = e->corank;\n+ tmp->n.sym->attr.allocatable = 1;\n+ tmp->n.sym->attr.dimension = e->rank ? 1 : 0;\n+ tmp->n.sym->attr.codimension = e->corank ? 1 : 0;\n+ }\n+ else\n+ tmp->n.sym->attr.dimension = 0;\n+\n+ gfc_set_sym_referenced (tmp->n.sym);\n+ gfc_commit_symbol (tmp->n.sym);\n+ e = gfc_lval_expr_from_sym (tmp->n.sym);\n+\n+ /* Should the lhs be a section, use its array ref for the\n+ temporary expression. */\n+ if (aref && aref->type != AR_FULL && !allocatable)\n+ {\n+ gfc_free_ref_list (e->ref);\n+ e->ref = gfc_copy_ref (ref);\n+ }\n+ return e;\n+}\n+\n+\n+/* Helper function to take an argument in a subroutine call with a dependency\n+ on another argument, copy it to an allocatable temporary and use the\n+ temporary in the call expression. The new code is embedded in a block to\n+ ensure local, automatic deallocation. */\n+\n+static void\n+add_temp_assign_before_call (gfc_code *code, gfc_namespace *ns,\n+\t\t\t gfc_expr **rhsptr)\n+{\n+ gfc_namespace *block_ns;\n+ gfc_expr *tmp_var;\n+\n+ /* Wrap the new code in a block so that the temporary is deallocated. */\n+ block_ns = gfc_build_block_ns (ns);\n+\n+ /* As it stands, the block_ns does not not stand up to resolution because the\n+ the assignment would be converted to a call and, in any case, the modified\n+ call fails in gfc_check_conformance. */\n+ block_ns->resolved = 1;\n+\n+ /* Assign the original expression to the temporary. */\n+ tmp_var = get_temp_from_expr (*rhsptr, block_ns, true);\n+ block_ns->code = build_assignment (EXEC_ASSIGN, tmp_var, *rhsptr,\n+\t\t\t\t NULL, NULL, (*rhsptr)->where);\n+\n+ /* Transfer the call to the block and terminate block code. */\n+ *rhsptr = gfc_copy_expr (tmp_var);\n+ block_ns->code->next = gfc_get_code (EXEC_NOP);\n+ *(block_ns->code->next) = *code;\n+ block_ns->code->next->next = NULL;\n+\n+ /* Convert the original code to execute the block. */\n+ code->op = EXEC_BLOCK;\n+ code->ext.block.ns = block_ns;\n+ code->ext.block.assoc = NULL;\n+ code->expr1 = code->expr2 = NULL;\n+}\n+\n+\n+/* Add one line of code to the code chain, making sure that 'head' and\n+ 'tail' are appropriately updated. */\n+\n+static void\n+add_code_to_chain (gfc_code **this_code, gfc_code **head, gfc_code **tail)\n+{\n+ gcc_assert (this_code);\n+ if (*head == NULL)\n+ *head = *tail = *this_code;\n+ else\n+ *tail = gfc_append_code (*tail, *this_code);\n+ *this_code = NULL;\n+}\n+\n+\n+/* Generate a final call from a variable expression */\n+\n+static void\n+generate_final_call (gfc_expr *tmp_expr, gfc_code **head, gfc_code **tail)\n+{\n+ gfc_code *this_code;\n+ gfc_expr *final_expr = NULL;\n+ gfc_expr *size_expr;\n+ gfc_expr *fini_coarray;\n+\n+ gcc_assert (tmp_expr->expr_type == EXPR_VARIABLE);\n+ if (!gfc_is_finalizable (tmp_expr->ts.u.derived, &final_expr) || !final_expr)\n+ return;\n+\n+ /* Now generate the finalizer call. */\n+ this_code = gfc_get_code (EXEC_CALL);\n+ this_code->symtree = final_expr->symtree;\n+ this_code->resolved_sym = final_expr->symtree->n.sym;\n+\n+ //* Expression to be finalized */\n+ this_code->ext.actual = gfc_get_actual_arglist ();\n+ this_code->ext.actual->expr = gfc_copy_expr (tmp_expr);\n+\n+ /* size_expr = STORAGE_SIZE (...) / NUMERIC_STORAGE_SIZE. */\n+ this_code->ext.actual->next = gfc_get_actual_arglist ();\n+ size_expr = gfc_get_expr ();\n+ size_expr->where = gfc_current_locus;\n+ size_expr->expr_type = EXPR_OP;\n+ size_expr->value.op.op = INTRINSIC_DIVIDE;\n+ size_expr->value.op.op1\n+\t= gfc_build_intrinsic_call (gfc_current_ns, GFC_ISYM_STORAGE_SIZE,\n+\t\t\t\t \"storage_size\", gfc_current_locus, 2,\n+\t\t\t\t gfc_lval_expr_from_sym (tmp_expr->symtree->n.sym),\n+\t\t\t\t gfc_get_int_expr (gfc_index_integer_kind,\n+\t\t\t\t\t\t NULL, 0));\n+ size_expr->value.op.op2 = gfc_get_int_expr (gfc_index_integer_kind, NULL,\n+\t\t\t\t\t gfc_character_storage_size);\n+ size_expr->value.op.op1->ts = size_expr->value.op.op2->ts;\n+ size_expr->ts = size_expr->value.op.op1->ts;\n+ this_code->ext.actual->next->expr = size_expr;\n+\n+ /* fini_coarray */\n+ this_code->ext.actual->next->next = gfc_get_actual_arglist ();\n+ fini_coarray = gfc_get_constant_expr (BT_LOGICAL, gfc_default_logical_kind,\n+\t\t\t\t\t&tmp_expr->where);\n+ fini_coarray->value.logical = (int)gfc_expr_attr (tmp_expr).codimension;\n+ this_code->ext.actual->next->next->expr = fini_coarray;\n+\n+ add_code_to_chain (&this_code, head, tail);\n+\n+}\n+\n+/**********End of helper functions for modifying code*****************/\n+\n+\n /* Resolve the interface for a PROCEDURE declaration or procedure pointer. */\n \n static bool\n@@ -4133,9 +4391,6 @@ check_import_status (gfc_expr *e)\n argument which is not INTENT_IN and requires a temporary, build a temporary\n for the INTENT_IN actual argument as well. */\n \n-static void\n-add_temp_assign_before_call (gfc_code *, gfc_namespace *, gfc_expr **);\n-\n static void\n resolve_elemental_dependencies (gfc_code *c)\n {\n@@ -12876,14 +13131,47 @@ static void\n resolve_block_construct (gfc_code* code)\n {\n gfc_namespace *ns = code->ext.block.ns;\n+ gfc_association_list *assoc;\n+ gfc_expr *tmp_var, *tgt;\n+ gfc_code *tmp_code, *old_code;\n+ gfc_exec_op op;\n+\n+ /* For an ASSOCIATE block, the associations (and their targets) will, for the\n+ main part, be resolved by gfc_resolve_symbol, during resolution of the\n+ BLOCK's namespace. */\n+\n+ assoc = code->ext.block.assoc;\n+\n+ /* Subref arrays that are encloded in parentheses need a temporary. */\n+ for (; assoc; assoc = assoc->next)\n+ {\n+ if (assoc && assoc->st && assoc->st->n.sym->assoc\n+\t && !assoc->st->n.sym->attr.select_type_temporary\n+\t && (tgt = assoc->st->n.sym->assoc->target)\n+\t && gfc_resolve_expr (tgt)\n+\t && tgt->expr_type == EXPR_OP\n+\t && tgt->value.op.op == INTRINSIC_PARENTHESES\n+\t && is_subref_array (tgt->value.op.op1))\n+\t{\n+\t if (gfc_expr_attr (tgt->value.op.op1).pointer)\n+\t op = EXEC_POINTER_ASSIGN;\n+\t else\n+\t op = EXEC_ASSIGN;\n+\t tmp_var = get_temp_from_expr (tgt->value.op.op1, ns->parent, true);\n+\t tmp_code = build_assignment (op, tmp_var, tgt->value.op.op1,\n+\t\t\t\t NULL, NULL, assoc->where);\n+\t assoc->st->n.sym->assoc->target = gfc_copy_expr (tmp_var);\n+\t old_code = gfc_get_code (EXEC_NOP);\n+\t *old_code = *code;\n+\t *code = *tmp_code;\n+\t code->next = old_code;\n+\t free (tmp_code);\n+\t}\n+ }\n \n- /* For an ASSOCIATE block, the associations (and their targets) will be\n- resolved by gfc_resolve_symbol, during resolution of the BLOCK's\n- namespace. */\n gfc_resolve (ns);\n }\n \n-\n /* Resolve lists of blocks found in IF, SELECT CASE, WHERE, FORALL, GOTO and\n DO code nodes. */\n \n@@ -13312,263 +13600,9 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)\n }\n \n \n-/* Add a component reference onto an expression. */\n-\n-static void\n-add_comp_ref (gfc_expr *e, gfc_component *c)\n-{\n- gfc_ref **ref;\n- ref = &(e->ref);\n- while (*ref)\n- ref = &((*ref)->next);\n- *ref = gfc_get_ref ();\n- (*ref)->type = REF_COMPONENT;\n- (*ref)->u.c.sym = e->ts.u.derived;\n- (*ref)->u.c.component = c;\n- e->ts = c->ts;\n-\n- /* Add a full array ref, as necessary. */\n- if (c->as)\n- {\n- gfc_add_full_array_ref (e, c->as);\n- e->rank = c->as->rank;\n- e->corank = c->as->corank;\n- }\n-}\n-\n-\n-/* Build an assignment. Keep the argument 'op' for future use, so that\n- pointer assignments can be made. */\n-\n-static gfc_code *\n-build_assignment (gfc_exec_op op, gfc_expr *expr1, gfc_expr *expr2,\n-\t\t gfc_component *comp1, gfc_component *comp2, locus loc)\n-{\n- gfc_code *this_code;\n-\n- this_code = gfc_get_code (op);\n- this_code->next = NULL;\n- this_code->expr1 = gfc_copy_expr (expr1);\n- this_code->expr2 = gfc_copy_expr (expr2);\n- this_code->loc = loc;\n- if (comp1 && comp2)\n- {\n- add_comp_ref (this_code->expr1, comp1);\n- add_comp_ref (this_code->expr2, comp2);\n- }\n-\n- return this_code;\n-}\n-\n-\n-/* Makes a temporary variable expression based on the characteristics of\n- a given variable expression. If allocatable is set, the temporary is\n- unconditionally allocatable*/\n-\n-static gfc_expr*\n-get_temp_from_expr (gfc_expr *e, gfc_namespace *ns,\n-\t\t bool allocatable = false)\n-{\n- static int serial = 0;\n- char name[GFC_MAX_SYMBOL_LEN];\n- gfc_symtree *tmp;\n- gfc_array_spec *as;\n- gfc_array_ref *aref;\n- gfc_ref *ref;\n-\n- sprintf (name, GFC_PREFIX(\"DA%d\"), serial++);\n- gfc_get_sym_tree (name, ns, &tmp, false);\n- gfc_add_type (tmp->n.sym, &e->ts, NULL);\n-\n- if (e->expr_type == EXPR_CONSTANT && e->ts.type == BT_CHARACTER)\n- tmp->n.sym->ts.u.cl->length = gfc_get_int_expr (gfc_charlen_int_kind,\n-\t\t\t\t\t\t NULL,\n-\t\t\t\t\t\t e->value.character.length);\n-\n- as = NULL;\n- ref = NULL;\n- aref = NULL;\n-\n- /* Obtain the arrayspec for the temporary. */\n- if (e->rank && e->expr_type != EXPR_ARRAY\n- && e->expr_type != EXPR_FUNCTION\n- && e->expr_type != EXPR_OP)\n- {\n- aref = gfc_find_array_ref (e);\n- if (e->expr_type == EXPR_VARIABLE\n-\t && e->symtree->n.sym->as == aref->as)\n-\tas = aref->as;\n- else\n-\t{\n-\t for (ref = e->ref; ref; ref = ref->next)\n-\t if (ref->type == REF_COMPONENT\n-\t\t&& ref->u.c.component->as == aref->as)\n-\t {\n-\t\tas = aref->as;\n-\t\tbreak;\n-\t }\n-\t}\n- }\n-\n- /* Add the attributes and the arrayspec to the temporary. */\n- tmp->n.sym->attr = gfc_expr_attr (e);\n- tmp->n.sym->attr.function = 0;\n- tmp->n.sym->attr.proc_pointer = 0;\n- tmp->n.sym->attr.result = 0;\n- tmp->n.sym->attr.flavor = FL_VARIABLE;\n- tmp->n.sym->attr.dummy = 0;\n- tmp->n.sym->attr.use_assoc = 0;\n- tmp->n.sym->attr.intent = INTENT_UNKNOWN;\n-\n-\n- if (as && !allocatable)\n- {\n- tmp->n.sym->as = gfc_copy_array_spec (as);\n- if (!ref)\n-\tref = e->ref;\n- if (as->type == AS_DEFERRED)\n-\ttmp->n.sym->attr.allocatable = 1;\n- }\n- else if ((e->rank || e->corank)\n-\t && (e->expr_type == EXPR_ARRAY || e->expr_type == EXPR_FUNCTION\n-\t || e->expr_type == EXPR_OP || allocatable))\n- {\n- tmp->n.sym->as = gfc_get_array_spec ();\n- tmp->n.sym->as->type = AS_DEFERRED;\n- tmp->n.sym->as->rank = e->rank;\n- tmp->n.sym->as->corank = e->corank;\n- tmp->n.sym->attr.allocatable = 1;\n- tmp->n.sym->attr.dimension = e->rank ? 1 : 0;\n- tmp->n.sym->attr.codimension = e->corank ? 1 : 0;\n- }\n- else\n- tmp->n.sym->attr.dimension = 0;\n-\n- gfc_set_sym_referenced (tmp->n.sym);\n- gfc_commit_symbol (tmp->n.sym);\n- e = gfc_lval_expr_from_sym (tmp->n.sym);\n-\n- /* Should the lhs be a section, use its array ref for the\n- temporary expression. */\n- if (aref && aref->type != AR_FULL && !allocatable)\n- {\n- gfc_free_ref_list (e->ref);\n- e->ref = gfc_copy_ref (ref);\n- }\n- return e;\n-}\n-\n-\n-/* Helper function to take an argument in a subroutine call with a dependency\n- on another argument, copy it to an allocatable temporary and use the\n- temporary in the call expression. The new code is embedded in a block to\n- ensure local, automatic deallocation. */\n-\n-static void\n-add_temp_assign_before_call (gfc_code *code, gfc_namespace *ns,\n-\t\t\t gfc_expr **rhsptr)\n-{\n- gfc_namespace *block_ns;\n- gfc_expr *tmp_var;\n-\n- /* Wrap the new code in a block so that the temporary is deallocated. */\n- block_ns = gfc_build_block_ns (ns);\n-\n- /* As it stands, the block_ns does not not stand up to resolution because the\n- the assignment would be converted to a call and, in any case, the modified\n- call fails in gfc_check_conformance. */\n- block_ns->resolved = 1;\n-\n- /* Assign the original expression to the temporary. */\n- tmp_var = get_temp_from_expr (*rhsptr, block_ns, true);\n- block_ns->code = build_assignment (EXEC_ASSIGN, tmp_var, *rhsptr,\n-\t\t\t\t NULL, NULL, (*rhsptr)->where);\n-\n- /* Transfer the call to the block and terminate block code. */\n- *rhsptr = gfc_copy_expr (tmp_var);\n- block_ns->code->next = gfc_get_code (EXEC_NOP);\n- *(block_ns->code->next) = *code;\n- block_ns->code->next->next = NULL;\n-\n- /* Convert the original code to execute the block. */\n- code->op = EXEC_BLOCK;\n- code->ext.block.ns = block_ns;\n- code->ext.block.assoc = NULL;\n- code->expr1 = code->expr2 = NULL;\n-}\n-\n-\n-/* Add one line of code to the code chain, making sure that 'head' and\n- 'tail' are appropriately updated. */\n-\n-static void\n-add_code_to_chain (gfc_code **this_code, gfc_code **head, gfc_code **tail)\n-{\n- gcc_assert (this_code);\n- if (*head == NULL)\n- *head = *tail = *this_code;\n- else\n- *tail = gfc_append_code (*tail, *this_code);\n- *this_code = NULL;\n-}\n-\n-\n-/* Generate a final call from a variable expression */\n-\n-static void\n-generate_final_call (gfc_expr *tmp_expr, gfc_code **head, gfc_code **tail)\n-{\n- gfc_code *this_code;\n- gfc_expr *final_expr = NULL;\n- gfc_expr *size_expr;\n- gfc_expr *fini_coarray;\n-\n- gcc_assert (tmp_expr->expr_type == EXPR_VARIABLE);\n- if (!gfc_is_finalizable (tmp_expr->ts.u.derived, &final_expr) || !final_expr)\n- return;\n-\n- /* Now generate the finalizer call. */\n- this_code = gfc_get_code (EXEC_CALL);\n- this_code->symtree = final_expr->symtree;\n- this_code->resolved_sym = final_expr->symtree->n.sym;\n-\n- //* Expression to be finalized */\n- this_code->ext.actual = gfc_get_actual_arglist ();\n- this_code->ext.actual->expr = gfc_copy_expr (tmp_expr);\n-\n- /* size_expr = STORAGE_SIZE (...) / NUMERIC_STORAGE_SIZE. */\n- this_code->ext.actual->next = gfc_get_actual_arglist ();\n- size_expr = gfc_get_expr ();\n- size_expr->where = gfc_current_locus;\n- size_expr->expr_type = EXPR_OP;\n- size_expr->value.op.op = INTRINSIC_DIVIDE;\n- size_expr->value.op.op1\n-\t= gfc_build_intrinsic_call (gfc_current_ns, GFC_ISYM_STORAGE_SIZE,\n-\t\t\t\t \"storage_size\", gfc_current_locus, 2,\n-\t\t\t\t gfc_lval_expr_from_sym (tmp_expr->symtree->n.sym),\n-\t\t\t\t gfc_get_int_expr (gfc_index_integer_kind,\n-\t\t\t\t\t\t NULL, 0));\n- size_expr->value.op.op2 = gfc_get_int_expr (gfc_index_integer_kind, NULL,\n-\t\t\t\t\t gfc_character_storage_size);\n- size_expr->value.op.op1->ts = size_expr->value.op.op2->ts;\n- size_expr->ts = size_expr->value.op.op1->ts;\n- this_code->ext.actual->next->expr = size_expr;\n-\n- /* fini_coarray */\n- this_code->ext.actual->next->next = gfc_get_actual_arglist ();\n- fini_coarray = gfc_get_constant_expr (BT_LOGICAL, gfc_default_logical_kind,\n-\t\t\t\t\t&tmp_expr->where);\n- fini_coarray->value.logical = (int)gfc_expr_attr (tmp_expr).codimension;\n- this_code->ext.actual->next->next->expr = fini_coarray;\n-\n- add_code_to_chain (&this_code, head, tail);\n-\n-}\n-\n /* Counts the potential number of part array references that would\n result from resolution of typebound defined assignments. */\n \n-\n static int\n nonscalar_typebound_assign (gfc_symbol *derived, int depth)\n {\ndiff --git a/gcc/testsuite/gfortran.dg/associate_79.f90 b/gcc/testsuite/gfortran.dg/associate_79.f90\nnew file mode 100644\nindex 00000000000..ff657e6499e\n--- /dev/null\n+++ b/gcc/testsuite/gfortran.dg/associate_79.f90\n@@ -0,0 +1,43 @@\n+! { dg-do run }\n+! Test the fix for PR121384\n+! Contributed by Mikael Morin <mikael@gcc.gnu.org>\n+program test\n+ implicit none\n+ type :: t\n+ integer :: i,j\n+ end type\n+ type(t) :: a(5)\n+ class(t), allocatable :: c(:)\n+ a = [ t(2,3), t(5,7), t(11,13), t(17,19), t(23,29) ]\n+ associate (x => (a%i))\n+ if (rank(x) /= 1) error stop 11\n+ if (any(shape(x) /= [5])) error stop 12\n+ if (any(x /= [2,5,11,17,23])) error stop 13\n+ x(1) = 3\n+ end associate\n+ if (a(1)%i /= 2) stop 14\n+ associate (x => (a%j))\n+ if (rank(x) /= 1) error stop 21\n+ if (any(shape(x) /= [5])) error stop 22\n+ if (any(x /= [3,7,13,19,29])) error stop 23\n+ x(1) = 4\n+ end associate\n+ if (a(1)%j /= 3) stop 24\n+\n+! Check the class variants\n+ c = a\n+ associate (x => (c%i))\n+ if (rank(x) /= 1) error stop 31\n+ if (any(shape(x) /= [5])) error stop 32\n+ if (any(x /= [2,5,11,17,23])) error stop 33\n+ x(1) = 3\n+ end associate\n+ if (c(1)%i /= 2) stop 34\n+ associate (x => (c%j))\n+ if (rank(x) /= 1) error stop 41\n+ if (any(shape(x) /= [5])) error stop 42\n+ if (any(x /= [3,7,13,19,29])) error stop 43\n+ x(1) = 4\n+ end associate\n+ if (c(1)%j /= 3) stop 44\n+end program\n-- \n2.53.0\n\n", "prefixes": [ "fortran" ] }