From patchwork Thu Oct 11 23:16:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tobias Burnus X-Patchwork-Id: 982769 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-487402-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=net-b.de Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="CMj90+5M"; 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 42WRh03jMLz9s9h for ; Fri, 12 Oct 2018 10:17:17 +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=IldV/qBwib/wHG42fe0UN68H7qams1Gxek30WOBKn1Vaj7noro WJ4ayfiexFmZLi3pjeLDARc+DprqGRYoxsHybBOCRuA9vHeCbgCbxeuD7taquELP fe9OoG7yv37xAA051nMplJG2/amKTXQwWadYQ8MCeYNRyEPF2PVwg8YqE= 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=qb/zZ55Y2Jo4xs5wrxO1uxYhhs0=; b=CMj90+5MK9JrqbRs3JwV pZU7R6lQZf135zcqZ90++ZbUk58uZE2fjk3JwWDh9BdiZ342TVYSD65ZX+UTP51o GbKG7Wgn01+HzNGYoim/f7RBdQFqrW6xDqJBZZarCRT60LWOn7uguPxW+fn1q+9c GSsfUwOoVtuwfPQ8s9onN1c= Received: (qmail 59144 invoked by alias); 11 Oct 2018 23:17:10 -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 59066 invoked by uid 89); 11 Oct 2018 23:17:03 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=54, PROGRAM, sk:module_, declc X-HELO: mx-relay68-hz2.antispameurope.com Received: from mx-relay68-hz2.antispameurope.com (HELO mx-relay68-hz2.antispameurope.com) (94.100.136.168) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 11 Oct 2018 23:17:01 +0000 Received: from s041.bre.qsc.de ([195.90.7.81]) by mx-relay68-hz2.antispameurope.com; Fri, 12 Oct 2018 01:16:58 +0200 Received: from tux.net-b.de (port-92-194-24-29.dynamic.qsc.de [92.194.24.29]) by s041.bre.qsc.de (Postfix) with ESMTPSA id 3CA282C00C7; Fri, 12 Oct 2018 01:16:56 +0200 (CEST) To: gcc-patches , fortran@gcc.gnu.org From: Tobias Burnus Subject: [Patch, Fortran] PR58787 ICE (error recovery) in check_proc_interface Message-ID: <6f21174f-436f-d9d5-9230-0b9bd85db703@net-b.de> Date: Fri, 12 Oct 2018 01:16:54 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0 MIME-Version: 1.0 X-cloud-security-sender: burnus@net-b.de X-cloud-security-recipient: gcc-patches@gcc.gnu.org X-cloud-security-Virusscan: CLEAN X-cloud-security-disclaimer: This E-Mail was scanned by E-Mailservice on mx-relay68-hz2.antispameurope.com with D50E0F85940 X-cloud-security-connect: s041.bre.qsc.de[195.90.7.81], TLS=1, IP=195.90.7.81 X-cloud-security: scantime:.2638 Next patch, next try … The problem is the following: We have a use-associated symbol (a function) – which is once referenced (by use association). We now declare a same-name function in the 'contains' section. gfortran now parses the function name, fetches the symbol and reports that one duplicates the function (gfc_error_now). However, it continues afterwards and creates a sym_tree in the gfc_current_ns – and duly increases the sym->refs to 2. A bit later, the function gets rejected. (Parsing of the formal arguments fails when setting a attribute of a use-associated symbol, but I think this doesn't matter. reject_statement() is called, which rolls back the symbol, but again, I think that doesn't matter – it just makes some other solutions a tad more difficult.) Now, the contains namespace is cleaned up: As the function name is in the namespace's sym_tree, gfc_release_symbol() is invoked. The symbol itself is not freed (as --refs > 0), but sym->formal_ns is. (There are some safety nets, like sym->rev == 2 and sym->ns != sym->formal_ns, but they don't help.) Later, the symbol of the parent's namespace is resolved – and this includes resolving the formal arguments. – And accessing freed memory might crash gfortran. As solution, I return early and with an error from get_proc_name(). I think that's cleaner than waiting longer – and the early return avoids creating the symbol at the first place. (Otherwise, modifications have to go beyond rolling back of the symbols; doing refs++ probably helps, but is rather intransparent.) Pro of the early return: Avoids accessing already freed memory, might generate shorter error output as some later fails (like for not being able to modify attributes of a use-associated symbol) are gone. Contra: As one returns before entering a procedure, all following lines are in the outer scope (usually 'contains') and there probably unexpected. Hence, one might get a bunch of follow-up errors which do not help. Build on x86-64 and even more carefully regtested. OK? Tobias 2018-10-12 Tobias Burnus PR fortran/58787 * decl.c (get_proc_name): Return with error before creating sym_tree. PR fortran/58787 * gfortran.dg/goacc/pr77765.f90: Modify dg-error. * gfortran.dg/interface_42.f90: Ditto. * gfortran.dg/internal_references_1.f90: Ditto. * gfortran.dg/invalid_procedure_name.f90: Ditto. * gfortran.dg/pr65453.f90: Ditto. * gfortran.dg/pr77414.f90: Ditto. * gfortran.dg/pr78741.f90: Ditto. * gfortran.dg/same_name_2.f90: Ditto. diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 7f79811d152..87c736fb2db 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -1231,28 +1231,39 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry) && sym->attr.proc != 0 && (sym->attr.subroutine || sym->attr.function || sym->attr.entry) && sym->attr.if_source != IFSRC_UNKNOWN) - gfc_error_now ("Procedure %qs at %C is already defined at %L", - name, &sym->declared_at); - + { + gfc_error_now ("Procedure %qs at %C is already defined at %L", + name, &sym->declared_at); + return true; + } if (sym->attr.flavor != 0 && sym->attr.entry && sym->attr.if_source != IFSRC_UNKNOWN) - gfc_error_now ("Procedure %qs at %C is already defined at %L", - name, &sym->declared_at); + { + gfc_error_now ("Procedure %qs at %C is already defined at %L", + name, &sym->declared_at); + return true; + } if (sym->attr.external && sym->attr.procedure && gfc_current_state () == COMP_CONTAINS) - gfc_error_now ("Contained procedure %qs at %C clashes with " - "procedure defined at %L", - name, &sym->declared_at); + { + gfc_error_now ("Contained procedure %qs at %C clashes with " + "procedure defined at %L", + name, &sym->declared_at); + return true; + } /* Trap a procedure with a name the same as interface in the encompassing scope. */ if (sym->attr.generic != 0 && (sym->attr.subroutine || sym->attr.function) && !sym->attr.mod_proc) - gfc_error_now ("Name %qs at %C is already defined" - " as a generic interface at %L", - name, &sym->declared_at); + { + gfc_error_now ("Name %qs at %C is already defined" + " as a generic interface at %L", + name, &sym->declared_at); + return true; + } /* Trap declarations of attributes in encompassing scope. The signature for this is that ts.kind is set. Legitimate @@ -1263,8 +1274,11 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry) && gfc_current_ns->parent != NULL && sym->attr.access == 0 && !module_fcn_entry) - gfc_error_now ("Procedure %qs at %C has an explicit interface " + { + gfc_error_now ("Procedure %qs at %C has an explicit interface " "from a previous declaration", name); + return true; + } } /* C1246 (R1225) MODULE shall appear only in the function-stmt or @@ -1276,17 +1290,23 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry) && !current_attr.module_procedure && sym->attr.proc == PROC_MODULE && gfc_state_stack->state == COMP_CONTAINS) - gfc_error_now ("Procedure %qs defined in interface body at %L " - "clashes with internal procedure defined at %C", - name, &sym->declared_at); + { + gfc_error_now ("Procedure %qs defined in interface body at %L " + "clashes with internal procedure defined at %C", + name, &sym->declared_at); + return true; + } if (sym && !sym->gfc_new && sym->attr.flavor != FL_UNKNOWN && sym->attr.referenced == 0 && sym->attr.subroutine == 1 && gfc_state_stack->state == COMP_CONTAINS && gfc_state_stack->previous->state == COMP_SUBROUTINE) - gfc_error_now ("Procedure %qs at %C is already defined at %L", - name, &sym->declared_at); + { + gfc_error_now ("Procedure %qs at %C is already defined at %L", + name, &sym->declared_at); + return true; + } if (gfc_current_ns->parent == NULL || *result == NULL) return rc; diff --git a/gcc/testsuite/gfortran.dg/goacc/pr77765.f90 b/gcc/testsuite/gfortran.dg/goacc/pr77765.f90 index 3819cf70c04..afa0a56a632 100644 --- a/gcc/testsuite/gfortran.dg/goacc/pr77765.f90 +++ b/gcc/testsuite/gfortran.dg/goacc/pr77765.f90 @@ -13,7 +13,6 @@ contains end module m ! { dg-error "Procedure 'f' at .1. is already defined" "" { target *-*-* } 8 } -! { dg-error "Duplicate RECURSIVE attribute specified" "" { target *-*-* } 8 } ! { dg-error ".1." "" { target *-*-* } 10 } -! { dg-error "Unexpected ..ACC ROUTINE" "" { target *-*-* } 11 } +! { dg-error "Syntax error in ..ACC ROUTINE . NAME . at .1., invalid function name f" "" { target *-*-* } 11 } ! { dg-error "Expecting END MODULE statement" "" { target *-*-* } 12 } diff --git a/gcc/testsuite/gfortran.dg/interface_42.f90 b/gcc/testsuite/gfortran.dg/interface_42.f90 index 1fd47b920df..d260755eb6a 100644 --- a/gcc/testsuite/gfortran.dg/interface_42.f90 +++ b/gcc/testsuite/gfortran.dg/interface_42.f90 @@ -13,7 +13,7 @@ module copy contains - subroutine foo_da(da, copy) ! { dg-error "defined in interface body" } + subroutine foo_da(da, copy) ! { dg-error "defined in interface body|PROCEDURE attribute conflicts with PROCEDURE attribute" } integer, intent(in) :: da(:) integer, allocatable, intent(out) :: copy(:) allocate( copy( size(da) ) ) @@ -21,4 +21,4 @@ module copy end subroutine foo_da end module copy -{ dg-prune-output "compilation terminated" } +! { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/gfortran.dg/internal_references_1.f90 b/gcc/testsuite/gfortran.dg/internal_references_1.f90 index 2434e28d5e3..b53ab325ade 100644 --- a/gcc/testsuite/gfortran.dg/internal_references_1.f90 +++ b/gcc/testsuite/gfortran.dg/internal_references_1.f90 @@ -16,8 +16,8 @@ contains end subroutine subroutine p (i) ! { dg-error "is already defined" } - integer :: i - end subroutine + integer :: i ! { dg-error "Unexpected data declaration statement in CONTAINS section" } + end subroutine ! { dg-error "Expecting END MODULE statement" } end module ! ! PR25124 - would happily ignore the declaration of foo in the main program. @@ -27,8 +27,8 @@ x = bar () ! This is OK because it is a regular reference. x = foo () contains function foo () ! { dg-error "explicit interface from a previous" } - foo = 1.0 - end function foo + foo = 1.0 ! { dg-error "Unexpected assignment statement in CONTAINS section" } + end function foo ! { dg-error "Expecting END PROGRAM statement" } function bar () bar = 1.0 end function bar diff --git a/gcc/testsuite/gfortran.dg/invalid_procedure_name.f90 b/gcc/testsuite/gfortran.dg/invalid_procedure_name.f90 index dd319382b4d..74eaa636ae0 100644 --- a/gcc/testsuite/gfortran.dg/invalid_procedure_name.f90 +++ b/gcc/testsuite/gfortran.dg/invalid_procedure_name.f90 @@ -9,6 +9,6 @@ INTERFACE I1 ! { dg-error "" } END INTERFACE I1 CONTAINS SUBROUTINE I1(I) ! { dg-error "already defined as a generic" } - END SUBROUTINE I1 + END SUBROUTINE I1 ! { dg-error "Expecting END PROGRAM statement" } END diff --git a/gcc/testsuite/gfortran.dg/pr65453.f90 b/gcc/testsuite/gfortran.dg/pr65453.f90 index 8d30116b79d..9f40121b443 100644 --- a/gcc/testsuite/gfortran.dg/pr65453.f90 +++ b/gcc/testsuite/gfortran.dg/pr65453.f90 @@ -5,4 +5,4 @@ procedure() :: foo ! { dg-error "(1)" } contains subroutine foo() ! { dg-error "clashes with procedure" } end -end +end ! { dg-error "Two main PROGRAMs" } diff --git a/gcc/testsuite/gfortran.dg/pr77414.f90 b/gcc/testsuite/gfortran.dg/pr77414.f90 index 222c1a31542..00f14e35a8d 100644 --- a/gcc/testsuite/gfortran.dg/pr77414.f90 +++ b/gcc/testsuite/gfortran.dg/pr77414.f90 @@ -4,6 +4,6 @@ subroutine a(x) ! { dg-error "(1)" } character(*) :: x contains subroutine a(x) ! { dg-error " is already defined at" } - character(*) :: x + character(*) :: x ! { dg-error "Unexpected data declaration statement in CONTAINS section" } end subroutine a -end subroutine a +end subroutine a ! { dg-error "Expecting END PROGRAM statement" } diff --git a/gcc/testsuite/gfortran.dg/pr78741.f90 b/gcc/testsuite/gfortran.dg/pr78741.f90 index 6eb85789f94..707b2996307 100644 --- a/gcc/testsuite/gfortran.dg/pr78741.f90 +++ b/gcc/testsuite/gfortran.dg/pr78741.f90 @@ -11,6 +11,6 @@ entry g(n, x) ! { dg-error "is already defined" } x = 'b' contains subroutine g ! { dg-error "(1)" } - z(1) = x(1:1) + z(1) = x(1:1) ! { dg-error "Unclassifiable statement" } end end diff --git a/gcc/testsuite/gfortran.dg/same_name_2.f90 b/gcc/testsuite/gfortran.dg/same_name_2.f90 index 463ac8533f8..f37de55e651 100644 --- a/gcc/testsuite/gfortran.dg/same_name_2.f90 +++ b/gcc/testsuite/gfortran.dg/same_name_2.f90 @@ -10,6 +10,6 @@ subroutine aa ! { dg-error "Procedure" } write(*,*) 'AA' end subroutine aa subroutine aa ! { dg-error "is already defined" } - write(*,*) 'BB' -end subroutine aa + write(*,*) 'BB' ! { dg-error "Unexpected WRITE statement in CONTAINS section" } +end subroutine aa ! { dg-error "Expecting END MODULE statement" } end module