From patchwork Thu Apr 23 11:34:16 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andre Vehreschild X-Patchwork-Id: 463932 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 661D814011D for ; Thu, 23 Apr 2015 21:34:43 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass reason="1024-bit key; unprotected key" header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=hPvCezyY; dkim-adsp=none (unprotected policy); dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:in-reply-to:references :mime-version:content-type; q=dns; s=default; b=VTSdjg89Pitu1iwK kJ0pKEKM8EiY/jE/dl6Ld/UI6nlRiRy0FMXybG7d0M7VvlhFcKU2U0L8KG+zxzjQ +bS4EwhPLhl9ocBPTVaPWdLUBdqwJh6bO40vNohes3sbTqOMZ/LQA1D5DAhpxCa9 BECTziLT9An+OEdNQt7+291nqzQ= 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:date :from:to:cc:subject:message-id:in-reply-to:references :mime-version:content-type; s=default; bh=LWDyLb3cUgKfuZCTdCuFIL xQifY=; b=hPvCezyYXnnWkK2X5wH9JcVL6y7/7+0Ca0AhEto8ghGhdJWsNCDcMk PW0Bie/+GhfRmmBrLJUNSEVZtexRKzo/0FlKkI3G4KKTJ69FituBduLsNbjAexkF bsgPBIK2Q5qRvBUGKi4d0xJVpv7m52fW/t3jHqHtZhYuSJdHLz5XE= Received: (qmail 29304 invoked by alias); 23 Apr 2015 11:34:32 -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 29280 invoked by uid 89); 23 Apr 2015 11:34:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.0 required=5.0 tests=AWL, BAYES_50, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=no version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mout.gmx.net Received: from mout.gmx.net (HELO mout.gmx.net) (212.227.17.20) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 23 Apr 2015 11:34:24 +0000 Received: from localhost ([88.75.104.20]) by mail.gmx.com (mrgmx102) with ESMTPSA (Nemesis) id 0MRjd7-1Ys51n0MfZ-00Ssm7; Thu, 23 Apr 2015 13:34:19 +0200 Date: Thu, 23 Apr 2015 13:34:16 +0200 From: Andre Vehreschild To: Paul Richard Thomas Cc: Mikael Morin , GCC-Fortran-ML , GCC-Patches-ML , Antony Lewis , Dominique Dhumieres Subject: Re: [commited, Patch, Fortran, pr60322, addendum] was: [Patch 1/2, Fortran, pr60322] [OOP] Incorrect bounds on polymorphic dummy array Message-ID: <20150423133416.12210ec4@gmx.de> In-Reply-To: References: <20150226181717.480e282c@vepi2> <551006FF.1080704@sfr.fr> <20150323134357.6af740d1@vepi2> <20150324180620.3c72960e@vepi2> <20150409143709.6d33aa8c@vepi2> <20150414190054.473a9bbb@gmx.de> MIME-Version: 1.0 X-UI-Out-Filterresults: notjunk:1; Hi Paul, hi all, Paul, thanks for the review. I have commited this as r222361. Regards, Andre On Thu, 16 Apr 2015 21:13:31 +0200 Paul Richard Thomas wrote: > Hi Andre, > > The delta patch is OK for trunk and eventual backport to 5.2. > > Thanks for all the hard work > > Paul > > On 14 April 2015 at 19:00, Andre Vehreschild wrote: > > Hi all, > > > > during further testing of a big Fortran software I encounter two bugs with > > class arrays, that are somehow connected to pr60322. I therefore propose an > > extended patch for pr60322. Because Paul has already reviewed most the > > extended patch, I give you two patches: > > > > 1. a full patch, fixing all the issues connected to pr60322, and > > 2. a delta patch to get from the reviewed patch to the latest version. > > > > With the second patch I hope to get a faster review, because it is > > significantly shorter. > > > > Now what was the issue? To be precise there were two issues: > > > > i. a pointer to a class array (CLASS_DATA(sym).attr.class_pointer == 1) was > > dereferenced, which lead to an ICE (the patch for this in the delta is > > chunk 5 in gfc_conv_expr_descriptor, and > > > > ii. (and this was a severe brain cracker) in chains of references > > consisting of more then one class-(array)-ref always the _vptr of the first > > symbol was taken and not the _vptr of the currently dereferenced class > > object. This occurred when fortran code similiar to this was executed: > > > > type innerT > > integer, allocatable :: arr(:) > > end type > > > > type T > > class(innerT) :: mat(:,:) > > end type > > > > class(T) :: o > > > > allocate(o%mat(2,2)) > > allocate(o%mat(:,:)%arr(10)) ! This is obviously pseudo code, > > ! but I think you get what is meant. > > > > o%mat(1,1)%arr(1) = 1 > > > > In the last line the address to get to arr(1) was computed using the > > _vptr->size of o and not of o%mat(1,1). To fix this gfc_component_ref () now > > computes the class' _vptr-ref whenever it does a _data-ref (chunk 1 of > > trans-expr.c in the delta patch). The _vptr-ref is stored in gfc_se, where I > > added the new member class_vptr. The gfc_se->class_vptr is then used in > > array-refs (chunk 2 of trans.c) to get the size of the array elements of the > > correct level. > > > > The other chunks of the delta patch are: > > - parameter passing fixes, and > > - documentation fixes as requested for the version 5 of the pr60322 patch. > > > > I hope this helps in getting the patch reviewed quickly. > > > > Bootstraps and regtests ok on x86_64-linux-gnu/F21. > > > > Ok for trunk -> 6.0? > > Ok, for backport to 5.2, once available? > > > > Note, the patches may apply with shifts, as I forgot to update before taking > > the diffs. > > > > Regards, > > Andre > > > > On Thu, 9 Apr 2015 14:37:09 +0200 > > Andre Vehreschild wrote: > > > >> Hi Paul, hi all, > >> > >> Paul, thanks for the review. Answers to your questions are inline below: > >> > >> On Sun, 5 Apr 2015 11:13:05 +0200 > >> Paul Richard Thomas wrote: > >> > >> > + /* The dummy is returned for pointer, allocatable or assumed rank > >> > arrays. > >> > + The check for pointerness needs to be repeated here (it is done in > >> > + IS_CLASS_ARRAY (), too), because for class arrays that are > >> > pointers, as > >> > + is the one of the sym, which is incorrect here. */ > >> > > >> > What does this mean, please? > >> > >> The first sentence is about regular arrays and should be unchanged from the > >> original source. Then I have to check for class (arrays) that are pointers, > >> i.e., independent of whether the sym is a class array or a regular pointer > >> to a class object. (The latter shouldn't make it into the routine anyway.) > >> IS_CLASS_ARRAY () returns false for too many reasons to be of use here. I > >> have to apologize and confess that the comment was a mere note to myself > >> to not return to use is_classarray in the if below. Let me rephrase the > >> comment to be: > >> > >> /* The dummy is returned for pointer, allocatable or assumed rank arrays. > >> For class arrays the information if sym is an allocatable or pointer > >> object needs to be checked explicitly (IS_CLASS_ARRAY can be false for > >> too many reasons to be of use here). */ > >> > >> > + /* Returning the descriptor for dummy class arrays is hazardous, > >> > because > >> > + some caller is expecting an expression to apply the component refs > >> > to. > >> > + Therefore the descriptor is only created and stored in > >> > + sym->backend_decl's GFC_DECL_SAVED_DESCRIPTOR. The caller is then > >> > + responsible to extract it from there, when the descriptor is > >> > + desired. */ > >> > + if (IS_CLASS_ARRAY (sym) > >> > + && (!DECL_LANG_SPECIFIC (sym->backend_decl) > >> > + || !GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl))) > >> > + { > >> > + decl = gfc_build_dummy_array_decl (sym, sym->backend_decl); > >> > + /* Prevent the dummy from being detected as unused if it is > >> > copied. */ > >> > + if (sym->backend_decl != NULL && decl != sym->backend_decl) > >> > + DECL_ARTIFICIAL (sym->backend_decl) = 1; > >> > + sym->backend_decl = decl; > >> > + } > >> > > >> > The comments, such as the above are often going well beyond column 72, > >> > into the 80's. I know that much of the existing code violates this > >> > style requirement but there is no need to do so if clarity is not > >> > reduced thereby. > >> > >> Er, the document at > >> > >> https://gcc.gnu.org/codingconventions.html#C_Formatting > >> > >> says that line length is 80, or is there another convention, that I am not > >> aware of? > >> > >> > In trans-stmt.c s/standart/standard/ > >> > >> Fixed. > >> > >> > Don't forget to put the PR numbers in the ChangeLogs. > >> > >> I won't anymore, already got told off :-) > >> > >> > For this submission, I would have appreciated some a description of > >> > what each chunk in the patch is doing, just because there is so much > >> > of it. I suppose that it was good for my imortal soul to sort it out > >> > for myself but it took a little while :-) > >> > >> I initially tried to split the submission in two parts to make it more > >> manageable. One part with the brain-dead substitutions of as and array_attr > >> and one with the new code. Albeit I failed to get the brain-dead part right > >> and made some mistakes there already, which Mikael pointed out. I therefore > >> went for the big submission. > >> > >> Now doing a description of what each "chunk" does is quite tedious. I > >> really would like to spend my time more productive. Would you be > >> satisfied, when I write a story about the patch, referring to some parts > >> more explicitly, like > >> > >> "Chunk 4 of file trans-stmt.c is the heart of the patch and does this and > >> that. The remaining chunks are more or less putting the data together." > >> > >> (This is not correct for this patch of course. Just an example.) More > >> elaborate of course, but just to give an idea. > >> > >> Thanks again. I will commit as soon as 5.2/6.0 commit window is open. > >> > >> Regards, > >> Andre > >> > >> > > >> > Cheers and many thanks for the patch. > >> > > >> > Paul > >> > > >> > On 27 March 2015 at 13:48, Paul Richard Thomas > >> > wrote: > >> > > Dear Andre, > >> > > > >> > > I am in the UK as of last night. Before leaving, I bootstrapped and > >> > > regtested your patch and all was well. I must drive to Cambridge this > >> > > afternoon to see my mother and will try to get to it either this > >> > > evening or tomorrow morning. There is so much of it and it touches > >> > > many places; so I must give it a very careful looking over before > >> > > giving the green light. Bear with me please. > >> > > > >> > > Great work though! > >> > > > >> > > Paul > >> > > > >> > > On 24 March 2015 at 18:06, Andre Vehreschild wrote: > >> > >> Hi all, > >> > >> > >> > >> I have worked on the comments Mikael gave me. I am now checking for > >> > >> class_pointer in the way he pointed out. > >> > >> > >> > >> Furthermore did I *join the two parts* of the patch into this one, > >> > >> because keeping both in sync was no benefit but only tedious and did > >> > >> not prove to be reviewed faster. > >> > >> > >> > >> Paul, Dominique: I have addressed the LOC issue that came up lately. > >> > >> Or rather the patch addressed it already. I feel like this is not > >> > >> tested very well, not the loc() call nor the sizeof() call as given > >> > >> in the 57305 second's download. Unfortunately, is that download not > >> > >> runable. I would love to see a test similar to that download, but > >> > >> couldn't come up with one, that satisfied me. Given that the patch's > >> > >> review will last some days, I still have enough time to come up with > >> > >> something beautiful which I will add then. > >> > >> > >> > >> Bootstraps and regtests ok on x86_64-linux-gnu/F20. > >> > >> > >> > >> Regards, > >> > >> Andre > >> > >> > >> > >> > >> > >> On Tue, 24 Mar 2015 11:13:27 +0100 > >> > >> Paul Richard Thomas wrote: > >> > >> > >> > >>> Dear Andre, > >> > >>> > >> > >>> Dominique pointed out to me that the 'loc' patch causes a ICE in the > >> > >>> testsuite. It seems that 'loc' should provide the address of the > >> > >>> class container in some places and the address of the data in > >> > >>> others. I will put my thinking cap on tonight :-) > >> > >>> > >> > >>> Cheers > >> > >>> > >> > >>> Paul > >> > >>> > >> > >>> On 23 March 2015 at 13:43, Andre Vehreschild wrote: > >> > >>> > Hi Mikael, > >> > >>> > > >> > >>> > thanks for looking at the patch. Please note, that Paul has sent an > >> > >>> > addendum to the patches for 60322, which I deliberately have > >> > >>> > attached. > >> > >>> > > >> > >>> >> 26/02/2015 18:17, Andre Vehreschild a écrit : > >> > >>> >> > This first patch is only preparatory and does not change any of > >> > >>> >> > the semantics of gfortran at all. > >> > >>> >> Sure? > >> > >>> > > >> > >>> > With the counterexample you found below, this of course is a wrong > >> > >>> > statement. > >> > >>> > > >> > >>> >> > diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c > >> > >>> >> > index ab6f7a5..d28cf77 100644 > >> > >>> >> > --- a/gcc/fortran/expr.c > >> > >>> >> > +++ b/gcc/fortran/expr.c > >> > >>> >> > @@ -4059,10 +4060,10 @@ gfc_lval_expr_from_sym (gfc_symbol *sym) > >> > >>> >> > lval->symtree = gfc_find_symtree (sym->ns->sym_root, > >> > >>> >> > sym->name); > >> > >>> >> > > >> > >>> >> > /* It will always be a full array. */ > >> > >>> >> > - lval->rank = sym->as ? sym->as->rank : 0; > >> > >>> >> > + as = sym->as; > >> > >>> >> > + lval->rank = as ? as->rank : 0; > >> > >>> >> > if (lval->rank) > >> > >>> >> > - gfc_add_full_array_ref (lval, sym->ts.type == BT_CLASS ? > >> > >>> >> > - CLASS_DATA (sym)->as : sym->as); > >> > >>> >> > + gfc_add_full_array_ref (lval, as); > >> > >>> >> > >> > >>> >> This is a change of semantics. Or do you know that > >> > >>> >> sym->ts.type != BT_CLASS? > >> > >>> > > >> > >>> > You are completely right. I have made a mistake here. I have to > >> > >>> > tell the truth, I never ran a regtest with only part 1 of the > >> > >>> > patches applied. The second part of the patch will correct this, > >> > >>> > by setting the variable as depending on whether type == BT_CLASS > >> > >>> > or not. Sorry for the mistake. > >> > >>> > > >> > >>> >> > diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c > >> > >>> >> > index 3664824..e571a17 100644 > >> > >>> >> > --- a/gcc/fortran/trans-decl.c > >> > >>> >> > +++ b/gcc/fortran/trans-decl.c > >> > >>> >> > @@ -1013,16 +1017,24 @@ gfc_build_dummy_array_decl (gfc_symbol * > >> > >>> >> > sym, tree dummy) tree decl; > >> > >>> >> > tree type; > >> > >>> >> > gfc_array_spec *as; > >> > >>> >> > + symbol_attribute *array_attr; > >> > >>> >> > char *name; > >> > >>> >> > gfc_packed packed; > >> > >>> >> > int n; > >> > >>> >> > bool known_size; > >> > >>> >> > > >> > >>> >> > - if (sym->attr.pointer || sym->attr.allocatable > >> > >>> >> > - || (sym->as && sym->as->type == AS_ASSUMED_RANK)) > >> > >>> >> > + /* Use the array as and attr. */ > >> > >>> >> > + as = sym->as; > >> > >>> >> > + array_attr = &sym->attr; > >> > >>> >> > + > >> > >>> >> > + /* The pointer attribute is always set on a _data component, > >> > >>> >> > therefore check > >> > >>> >> > + the sym's attribute only. */ > >> > >>> >> > + if (sym->attr.pointer || array_attr->allocatable > >> > >>> >> > + || (as && as->type == AS_ASSUMED_RANK)) > >> > >>> >> > return dummy; > >> > >>> >> > > >> > >>> >> Any reason to sometimes use array_attr, sometimes not, like here? > >> > >>> >> By the way, the comment is misleading: for classes, there is the > >> > >>> >> class_pointer attribute (and it is a pain, I know). > >> > >>> > > >> > >>> > Yes, and a good one. Array_attr is sometimes sym->attr and > >> > >>> > sometimes CLASS_DATA(sym)->attr aka > >> > >>> > sym->ts.u.derived->components->attr. In the later case .pointer is > >> > >>> > always set to 1 in the _data component's attr. I.e., the above if, > >> > >>> > would always yield true for a class_array, which is not intended, > >> > >>> > but rather destructive. I know about the class_pointer attribute, > >> > >>> > but I figured, that it is not relevant here. Any idea how to > >> > >>> > formulate the comment better, to reflect what I just explained? > >> > >>> > > >> > >>> > Regards, > >> > >>> > Andre > >> > >>> > -- > >> > >>> > Andre Vehreschild * Email: vehre ad gmx dot de > >> > >>> > > >> > >>> > > >> > >>> > ---------- Forwarded message ---------- > >> > >>> > From: Paul Richard Thomas > >> > >>> > To: Andre Vehreschild , Dominique Dhumieres > >> > >>> > Cc: > >> > >>> > Date: Sun, 22 Mar 2015 21:20:20 +0100 > >> > >>> > Subject: Bug in intrinsic LOC for scalar class objects > >> > >>> > Dear Andre and Dominique, > >> > >>> > > >> > >>> > I have found that LOC is returning the address of the class > >> > >>> > container rather than the _data component for class scalars. See > >> > >>> > the source below, which you will recognise! A fix is attached. > >> > >>> > > >> > >>> > Note that the scalar allocate fails with MOLD= and so I substituted > >> > >>> > SOURCE=. > >> > >>> > > >> > >>> > Cheers > >> > >>> > > >> > >>> > Paul > >> > >>> > > >> > >>> > class(*), allocatable :: a(:), e ! Change 'e' to an array and > >> > >>> > second memcpy works correctly > >> > >>> > ! Problem is with loc(e), > >> > >>> > which returns the address of the > >> > >>> > ! class container. > >> > >>> > allocate (e, source = 99.0) > >> > >>> > allocate (a(2), source = [1.0, 2.0]) > >> > >>> > call add_element_poly (a,e) > >> > >>> > select type (a) > >> > >>> > type is (real) > >> > >>> > print *, a > >> > >>> > end select > >> > >>> > > >> > >>> > contains > >> > >>> > > >> > >>> > subroutine add_element_poly(a,e) > >> > >>> > use iso_c_binding > >> > >>> > class(*),allocatable,intent(inout),target :: a(:) > >> > >>> > class(*),intent(in),target :: e > >> > >>> > class(*),allocatable,target :: tmp(:) > >> > >>> > type(c_ptr) :: dummy > >> > >>> > > >> > >>> > interface > >> > >>> > function memcpy(dest,src,n) bind(C,name="memcpy") > >> > >>> > result(res) import > >> > >>> > type(c_ptr) :: res > >> > >>> > integer(c_intptr_t),value :: dest > >> > >>> > integer(c_intptr_t),value :: src > >> > >>> > integer(c_size_t),value :: n > >> > >>> > end function > >> > >>> > end interface > >> > >>> > > >> > >>> > if (.not.allocated(a)) then > >> > >>> > allocate(a(1), source=e) > >> > >>> > else > >> > >>> > allocate(tmp(size(a)),source=a) > >> > >>> > deallocate(a) > >> > >>> > allocate(a(size(tmp)+1),source=e) ! mold gives a segfault > >> > >>> > dummy = memcpy(loc(a(1)),loc(tmp),sizeof(tmp)) > >> > >>> > dummy = memcpy(loc(a(size(tmp)+1)),loc(e),sizeof(e)) > >> > >>> > end if > >> > >>> > end subroutine > >> > >>> > end > >> > >>> > > >> > >>> > >> > >>> > >> > >>> > >> > >> > >> > >> > >> > >> -- > >> > >> Andre Vehreschild * Email: vehre ad gmx dot de > >> > > > >> > > > >> > > > >> > > -- > >> > > Outside of a dog, a book is a man's best friend. Inside of a dog it's > >> > > too dark to read. > >> > > > >> > > Groucho Marx > >> > > >> > > >> > > >> > >> > > > > > > -- > > Andre Vehreschild * Email: vehre ad gmx dot de > > > Index: gcc/fortran/trans-expr.c =================================================================== --- gcc/fortran/trans-expr.c (Revision 222360) +++ gcc/fortran/trans-expr.c (Arbeitskopie) @@ -149,6 +149,11 @@ gfc_class_vptr_get (tree decl) { tree vptr; + /* For class arrays decl may be a temporary descriptor handle, the vptr is + then available through the saved descriptor. */ + if (TREE_CODE (decl) == VAR_DECL && DECL_LANG_SPECIFIC (decl) + && GFC_DECL_SAVED_DESCRIPTOR (decl)) + decl = GFC_DECL_SAVED_DESCRIPTOR (decl); if (POINTER_TYPE_P (TREE_TYPE (decl))) decl = build_fold_indirect_ref_loc (input_location, decl); vptr = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)), @@ -163,6 +168,11 @@ gfc_class_len_get (tree decl) { tree len; + /* For class arrays decl may be a temporary descriptor handle, the len is + then available through the saved descriptor. */ + if (TREE_CODE (decl) == VAR_DECL && DECL_LANG_SPECIFIC (decl) + && GFC_DECL_SAVED_DESCRIPTOR (decl)) + decl = GFC_DECL_SAVED_DESCRIPTOR (decl); if (POINTER_TYPE_P (TREE_TYPE (decl))) decl = build_fold_indirect_ref_loc (input_location, decl); len = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)), @@ -804,6 +814,16 @@ gfc_add_modify (&parmse->pre, ctree, tmp); } + else if (class_ts.type == BT_CLASS + && class_ts.u.derived->components + && class_ts.u.derived->components->ts.u + .derived->attr.unlimited_polymorphic) + { + ctree = gfc_class_len_get (var); + gfc_add_modify (&parmse->pre, ctree, + fold_convert (TREE_TYPE (ctree), + integer_zero_node)); + } /* Pass the address of the class object. */ parmse->expr = gfc_build_addr_expr (NULL_TREE, var); } @@ -830,6 +850,7 @@ tree tmp; tree vptr; tree cond = NULL_TREE; + tree slen = NULL_TREE; gfc_ref *ref; gfc_ref *class_ref; stmtblock_t block; @@ -921,7 +942,12 @@ tmp = NULL_TREE; if (class_ref == NULL && e->symtree && e->symtree->n.sym->ts.type == BT_CLASS) - tmp = e->symtree->n.sym->backend_decl; + { + tmp = e->symtree->n.sym->backend_decl; + if (DECL_LANG_SPECIFIC (tmp) && GFC_DECL_SAVED_DESCRIPTOR (tmp)) + tmp = GFC_DECL_SAVED_DESCRIPTOR (tmp); + slen = integer_zero_node; + } else { /* Remove everything after the last class reference, convert the @@ -933,6 +959,7 @@ gfc_conv_expr (&tmpse, e); class_ref->next = ref; tmp = tmpse.expr; + slen = tmpse.string_length; } gcc_assert (tmp != NULL_TREE); @@ -951,11 +978,38 @@ gfc_add_modify (&parmse->post, vptr, fold_convert (TREE_TYPE (vptr), ctree)); + /* For unlimited polymorphic objects also set the _len component. */ + if (class_ts.type == BT_CLASS + && class_ts.u.derived->components + && class_ts.u.derived->components->ts.u + .derived->attr.unlimited_polymorphic) + { + ctree = gfc_class_len_get (var); + if (UNLIMITED_POLY (e)) + tmp = gfc_class_len_get (tmp); + else if (e->ts.type == BT_CHARACTER) + { + gcc_assert (slen != NULL_TREE); + tmp = slen; + } + else + tmp = integer_zero_node; + gfc_add_modify (&parmse->pre, ctree, + fold_convert (TREE_TYPE (ctree), tmp)); + } + if (optional) { tree tmp2; cond = gfc_conv_expr_present (e->symtree->n.sym); + /* parmse->pre may contain some preparatory instructions for the + temporary array descriptor. Those may only be executed when the + optional argument is set, therefore add parmse->pre's instructions + to block, which is later guarded by an if (optional_arg_given). */ + gfc_add_block_to_block (&parmse->pre, &block); + block.head = parmse->pre.head; + parmse->pre.head = NULL_TREE; tmp = gfc_finish_block (&block); if (optional_alloc_ptr) @@ -1042,7 +1096,7 @@ fcn_type = TREE_TYPE (TREE_TYPE (fcn)); if (from != NULL_TREE) - from_data = gfc_class_data_get (from); + from_data = gfc_class_data_get (from); else from_data = gfc_class_vtab_def_init_get (to); @@ -1099,7 +1153,8 @@ gfc_init_block (&ifbody); gfc_add_block_to_block (&ifbody, &loop.pre); stdcopy = gfc_finish_block (&ifbody); - if (unlimited) + /* In initialization mode from_len is a constant zero. */ + if (unlimited && !integer_zerop (from_len)) { vec_safe_push (args, from_len); vec_safe_push (args, to_len); @@ -1141,7 +1196,8 @@ vec_safe_push (args, to_data); stdcopy = build_call_vec (fcn_type, fcn, args); - if (unlimited) + /* In initialization mode from_len is a constant zero. */ + if (unlimited && !integer_zerop (from_len)) { vec_safe_push (args, from_len); vec_safe_push (args, to_len); @@ -1156,6 +1212,18 @@ tmp = stdcopy; } + /* Only copy _def_init to to_data, when it is not a NULL-pointer. */ + if (from == NULL_TREE) + { + tree cond; + cond = fold_build2_loc (input_location, NE_EXPR, + boolean_type_node, + from_data, null_pointer_node); + tmp = fold_build3_loc (input_location, COND_EXPR, + void_type_node, cond, + tmp, build_empty_stmt (input_location)); + } + return tmp; } @@ -1229,6 +1297,8 @@ been referenced. */ gfc_get_derived_type (rhs->ts.u.derived); gfc_add_def_init_component (rhs); + /* The _def_init is always scalar. */ + rhs->rank = 0; if (code->expr1->ts.type == BT_CLASS && CLASS_DATA (code->expr1)->attr.dimension) @@ -2203,6 +2273,16 @@ field = f2; } + if (ref->u.c.sym && ref->u.c.sym->ts.type == BT_CLASS + && strcmp ("_data", c->name) == 0) + { + /* Found a ref to the _data component. Store the associated ref to + the vptr in se->class_vptr. */ + se->class_vptr = gfc_class_vptr_get (decl); + } + else + se->class_vptr = NULL_TREE; + tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), decl, field, NULL_TREE); @@ -2284,8 +2364,11 @@ bool return_value; bool alternate_entry; bool entry_master; + bool is_classarray; + bool first_time = true; sym = expr->symtree->n.sym; + is_classarray = IS_CLASS_ARRAY (sym); ss = se->ss; if (ss != NULL) { @@ -2389,9 +2472,24 @@ } else if (!sym->attr.value) { + /* Dereference temporaries for class array dummy arguments. */ + if (sym->attr.dummy && is_classarray + && GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))) + { + if (!se->descriptor_only) + se->expr = GFC_DECL_SAVED_DESCRIPTOR (se->expr); + + se->expr = build_fold_indirect_ref_loc (input_location, + se->expr); + } + /* Dereference non-character scalar dummy arguments. */ if (sym->attr.dummy && !sym->attr.dimension - && !(sym->attr.codimension && sym->attr.allocatable)) + && !(sym->attr.codimension && sym->attr.allocatable) + && (sym->ts.type != BT_CLASS + || (!CLASS_DATA (sym)->attr.dimension + && !(CLASS_DATA (sym)->attr.codimension + && CLASS_DATA (sym)->attr.allocatable)))) se->expr = build_fold_indirect_ref_loc (input_location, se->expr); @@ -2403,11 +2501,12 @@ se->expr = build_fold_indirect_ref_loc (input_location, se->expr); - /* Dereference non-character pointer variables. + /* Dereference non-character, non-class pointer variables. These must be dummies, results, or scalars. */ - if ((sym->attr.pointer || sym->attr.allocatable - || gfc_is_associate_pointer (sym) - || (sym->as && sym->as->type == AS_ASSUMED_RANK)) + if (!is_classarray + && (sym->attr.pointer || sym->attr.allocatable + || gfc_is_associate_pointer (sym) + || (sym->as && sym->as->type == AS_ASSUMED_RANK)) && (sym->attr.dummy || sym->attr.function || sym->attr.result @@ -2415,6 +2514,32 @@ && (!sym->attr.codimension || !sym->attr.allocatable)))) se->expr = build_fold_indirect_ref_loc (input_location, se->expr); + /* Now treat the class array pointer variables accordingly. */ + else if (sym->ts.type == BT_CLASS + && sym->attr.dummy + && (CLASS_DATA (sym)->attr.dimension + || CLASS_DATA (sym)->attr.codimension) + && ((CLASS_DATA (sym)->as + && CLASS_DATA (sym)->as->type == AS_ASSUMED_RANK) + || CLASS_DATA (sym)->attr.allocatable + || CLASS_DATA (sym)->attr.class_pointer)) + se->expr = build_fold_indirect_ref_loc (input_location, + se->expr); + /* And the case where a non-dummy, non-result, non-function, + non-allotable and non-pointer classarray is present. This case was + previously covered by the first if, but with introducing the + condition !is_classarray there, that case has to be covered + explicitly. */ + else if (sym->ts.type == BT_CLASS + && !sym->attr.dummy + && !sym->attr.function + && !sym->attr.result + && (CLASS_DATA (sym)->attr.dimension + || CLASS_DATA (sym)->attr.codimension) + && !CLASS_DATA (sym)->attr.allocatable + && !CLASS_DATA (sym)->attr.class_pointer) + se->expr = build_fold_indirect_ref_loc (input_location, + se->expr); } ref = expr->ref; @@ -2452,6 +2577,18 @@ break; case REF_COMPONENT: + if (first_time && is_classarray && sym->attr.dummy + && se->descriptor_only + && !CLASS_DATA (sym)->attr.allocatable + && !CLASS_DATA (sym)->attr.class_pointer + && CLASS_DATA (sym)->as + && CLASS_DATA (sym)->as->type != AS_ASSUMED_RANK + && strcmp ("_data", ref->u.c.component->name) == 0) + /* Skip the first ref of a _data component, because for class + arrays that one is already done by introducing a temporary + array descriptor. */ + break; + if (ref->u.c.sym->attr.extension) conv_parent_component_references (se, ref); @@ -2471,6 +2608,7 @@ gcc_unreachable (); break; } + first_time = false; ref = ref->next; } /* Pointer assignment, allocation or pass by reference. Arrays are handled @@ -4597,7 +4735,19 @@ gfc_init_se (&parmse, se); parm_kind = ELEMENTAL; - if (fsym && fsym->attr.value) + /* For all value functions or polymorphic scalar non-pointer + non-allocatable variables use the expression in e directly. This + ensures, that initializers of polymorphic entities are correctly + copied. */ + if (fsym && (fsym->attr.value + || (e->expr_type == EXPR_VARIABLE + && fsym->ts.type == BT_DERIVED + && e->ts.type == BT_DERIVED + && !e->ts.u.derived->attr.dimension + && !e->rank + && (!e->symtree + || (!e->symtree->n.sym->attr.allocatable + && !e->symtree->n.sym->attr.pointer))))) gfc_conv_expr (&parmse, e); else gfc_conv_expr_reference (&parmse, e); Index: gcc/fortran/ChangeLog =================================================================== --- gcc/fortran/ChangeLog (Revision 222360) +++ gcc/fortran/ChangeLog (Arbeitskopie) @@ -1,3 +1,61 @@ +2015-04-23 Andre Vehreschild + + PR fortran/60322 + * expr.c (gfc_lval_expr_from_sym): Code to select the regular + or class array added. + * gfortran.h: Add IS_CLASS_ARRAY macro. + * trans-array.c (gfc_add_loop_ss_code): Treat class objects + to be referenced always. + (build_class_array_ref): Adapt retrieval of array descriptor. + (build_array_ref): Likewise. + (gfc_conv_array_ref): Hand the vptr or the descriptor to + build_array_ref depending whether the sym is class or not. + (gfc_trans_array_cobounds): Select correct gfc_array_spec for + regular and class arrays. + (gfc_trans_array_bounds): Likewise. + (gfc_trans_dummy_array_bias): Likewise. + (gfc_get_dataptr_offset): Correcting call of build_array_ref. + (gfc_conv_expr_descriptor): Set the array's offset to -1 when + lbound in inner most dim is 1 and symbol non-pointer/assoc. + * trans-decl.c (gfc_build_qualified_array): Select correct + gfc_array_spec for regular and class arrays. + (gfc_build_dummy_array_decl): Likewise. + (gfc_get_symbol_decl): Get a dummy array for class arrays. + (gfc_trans_deferred_vars): Tell conv_expr that the descriptor + is desired. + * trans-expr.c (gfc_class_vptr_get): Get the class descriptor + from the correct location for class arrays. + (gfc_class_len_get): Likewise. + (gfc_conv_intrinsic_to_class): Add handling of _len component. + (gfc_conv_class_to_class): Prevent access to unset array data + when the array is an optional argument. Add handling of _len + component. + (gfc_copy_class_to_class): Check that _def_init is non-NULL + when used in _vptr->copy() + (gfc_trans_class_init_assign): Ensure that the rank of + _def_init is zero. + (gfc_conv_component_ref): Get the _vptr along with _data refs. + (gfc_conv_variable): Make sure the temp array descriptor is + returned for class arrays, too, and that class arrays are + dereferenced correctly. + (gfc_conv_procedure_call): For polymorphic type initialization + the initializer has to be a pointer to _def_init stored in a + dummy variable, which then needs to be used by value. + * trans-intrinsic.c (gfc_conv_intrinsic_sizeof): Use the + temporary array descriptor for class arrays, too. + (gfc_conv_intrinsic_storage_size): Likewise. + (gfc_conv_intrinsic_loc): Add ref to _data for BT_CLASS + expressions. + * trans-stmt.c (trans_associate_var): Use a temporary array for + the associate variable of class arrays, too, making the array + one-based (lbound == 1). + * trans-types.c (gfc_is_nodesc_array): Use the correct + array data. + * trans.c (gfc_build_array_ref): Use the dummy array descriptor + when present. + * trans.h: Add class_vptr to gfc_se for storing a class ref's + vptr. + 2015-04-22 Steven G. Kargl PR fortran/65429 Index: gcc/fortran/trans-types.c =================================================================== --- gcc/fortran/trans-types.c (Revision 222360) +++ gcc/fortran/trans-types.c (Arbeitskopie) @@ -1288,25 +1288,35 @@ int gfc_is_nodesc_array (gfc_symbol * sym) { - gcc_assert (sym->attr.dimension || sym->attr.codimension); + symbol_attribute *array_attr; + gfc_array_spec *as; + bool is_classarray = IS_CLASS_ARRAY (sym); + array_attr = is_classarray ? &CLASS_DATA (sym)->attr : &sym->attr; + as = is_classarray ? CLASS_DATA (sym)->as : sym->as; + + gcc_assert (array_attr->dimension || array_attr->codimension); + /* We only want local arrays. */ - if (sym->attr.pointer || sym->attr.allocatable) + if ((sym->ts.type != BT_CLASS && sym->attr.pointer) + || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer) + || array_attr->allocatable) return 0; /* We want a descriptor for associate-name arrays that do not have an - explicitly known shape already. */ - if (sym->assoc && sym->as->type != AS_EXPLICIT) + explicitly known shape already. */ + if (sym->assoc && as->type != AS_EXPLICIT) return 0; + /* The dummy is stored in sym and not in the component. */ if (sym->attr.dummy) - return sym->as->type != AS_ASSUMED_SHAPE - && sym->as->type != AS_ASSUMED_RANK; + return as->type != AS_ASSUMED_SHAPE + && as->type != AS_ASSUMED_RANK; if (sym->attr.result || sym->attr.function) return 0; - gcc_assert (sym->as->type == AS_EXPLICIT || sym->as->cp_was_assumed); + gcc_assert (as->type == AS_EXPLICIT || as->cp_was_assumed); return 1; } Index: gcc/fortran/trans-stmt.c =================================================================== --- gcc/fortran/trans-stmt.c (Revision 222360) +++ gcc/fortran/trans-stmt.c (Arbeitskopie) @@ -1390,13 +1390,30 @@ gfc_init_se (&se, NULL); se.descriptor_only = 1; - gfc_conv_expr (&se, e); + /* In a select type the (temporary) associate variable shall point to + a standard fortran array (lower bound == 1), but conv_expr () + just maps to the input array in the class object, whose lbound may + be arbitrary. conv_expr_descriptor solves this by inserting a + temporary array descriptor. */ + gfc_conv_expr_descriptor (&se, e); - gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))); + gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) + || GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr))); gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl))); - gfc_add_modify (&se.pre, sym->backend_decl, se.expr); + if (GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr))) + { + if (INDIRECT_REF_P (se.expr)) + tmp = TREE_OPERAND (se.expr, 0); + else + tmp = se.expr; + gfc_add_modify (&se.pre, sym->backend_decl, + gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (tmp))); + } + else + gfc_add_modify (&se.pre, sym->backend_decl, se.expr); + if (unlimited) { /* Recover the dtype, which has been overwritten by the @@ -1406,7 +1423,7 @@ gfc_get_dtype (TREE_TYPE (sym->backend_decl))); } - gfc_add_init_cleanup (block, gfc_finish_block( &se.pre), + gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), gfc_finish_block (&se.post)); } @@ -1449,9 +1466,18 @@ } if (need_len_assign) { - /* Get the _len comp from the target expr by stripping _data - from it and adding component-ref to _len. */ - tmp = gfc_class_len_get (TREE_OPERAND (target_expr, 0)); + if (e->symtree + && DECL_LANG_SPECIFIC (e->symtree->n.sym->backend_decl) + && GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl)) + /* Use the original class descriptor stored in the saved + descriptor to get the target_expr. */ + target_expr = + GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl); + else + /* Strip the _data component from the target_expr. */ + target_expr = TREE_OPERAND (target_expr, 0); + /* Add a reference to the _len comp to the target expr. */ + tmp = gfc_class_len_get (target_expr); /* Get the component-ref for the temp structure's _len comp. */ charlen = gfc_class_len_get (se.expr); /* Add the assign to the beginning of the the block... */ Index: gcc/fortran/gfortran.h =================================================================== --- gcc/fortran/gfortran.h (Revision 222360) +++ gcc/fortran/gfortran.h (Arbeitskopie) @@ -3210,6 +3210,11 @@ && CLASS_DATA (sym) \ && CLASS_DATA (sym)->ts.u.derived \ && CLASS_DATA (sym)->ts.u.derived->attr.unlimited_polymorphic) +#define IS_CLASS_ARRAY(sym) \ + (sym->ts.type == BT_CLASS \ + && CLASS_DATA (sym) \ + && CLASS_DATA (sym)->attr.dimension \ + && !CLASS_DATA (sym)->attr.class_pointer) /* frontend-passes.c */ Index: gcc/fortran/trans-intrinsic.c =================================================================== --- gcc/fortran/trans-intrinsic.c (Revision 222360) +++ gcc/fortran/trans-intrinsic.c (Arbeitskopie) @@ -5921,8 +5921,17 @@ } else if (arg->ts.type == BT_CLASS) { - if (arg->rank) + /* For deferred length arrays, conv_expr_descriptor returns an + indirect_ref to the component. */ + if (arg->rank < 0 + || (arg->rank > 0 && !VAR_P (argse.expr) + && GFC_DECL_CLASS (TREE_OPERAND (argse.expr, 0)))) byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0)); + else if (arg->rank > 0) + /* The scalarizer added an additional temp. To get the class' vptr + one has to look at the original backend_decl. */ + byte_size = gfc_class_vtab_size_get ( + GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl)); else byte_size = gfc_class_vtab_size_get (argse.expr); } @@ -6053,7 +6062,11 @@ gfc_conv_expr_descriptor (&argse, arg); if (arg->ts.type == BT_CLASS) { - tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0)); + if (arg->rank > 0) + tmp = gfc_class_vtab_size_get ( + GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl)); + else + tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0)); tmp = fold_convert (result_type, tmp); goto done; } @@ -7080,7 +7093,11 @@ arg_expr = expr->value.function.actual->expr; if (arg_expr->rank == 0) - gfc_conv_expr_reference (se, arg_expr); + { + if (arg_expr->ts.type == BT_CLASS) + gfc_add_component_ref (arg_expr, "_data"); + gfc_conv_expr_reference (se, arg_expr); + } else gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL); se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr); Index: gcc/fortran/trans.c =================================================================== --- gcc/fortran/trans.c (Revision 222360) +++ gcc/fortran/trans.c (Arbeitskopie) @@ -321,7 +321,7 @@ /* Build an ARRAY_REF with its natural type. */ tree -gfc_build_array_ref (tree base, tree offset, tree decl) +gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr) { tree type = TREE_TYPE (base); tree tmp; @@ -353,30 +353,47 @@ /* If the array reference is to a pointer, whose target contains a subreference, use the span that is stored with the backend decl and reference the element with pointer arithmetic. */ - if (decl && (TREE_CODE (decl) == FIELD_DECL - || TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == PARM_DECL) - && ((GFC_DECL_SUBREF_ARRAY_P (decl) - && !integer_zerop (GFC_DECL_SPAN(decl))) + if ((decl && (TREE_CODE (decl) == FIELD_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL) + && ((GFC_DECL_SUBREF_ARRAY_P (decl) + && !integer_zerop (GFC_DECL_SPAN (decl))) || GFC_DECL_CLASS (decl))) + || vptr) { - if (GFC_DECL_CLASS (decl)) + if (decl) { - /* Allow for dummy arguments and other good things. */ - if (POINTER_TYPE_P (TREE_TYPE (decl))) - decl = build_fold_indirect_ref_loc (input_location, decl); + if (GFC_DECL_CLASS (decl)) + { + /* When a temporary is in place for the class array, then the + original class' declaration is stored in the saved + descriptor. */ + if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl)) + decl = GFC_DECL_SAVED_DESCRIPTOR (decl); + else + { + /* Allow for dummy arguments and other good things. */ + if (POINTER_TYPE_P (TREE_TYPE (decl))) + decl = build_fold_indirect_ref_loc (input_location, decl); - /* Check if '_data' is an array descriptor. If it is not, - the array must be one of the components of the class object, - so return a normal array reference. */ - if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_class_data_get (decl)))) - return build4_loc (input_location, ARRAY_REF, type, base, - offset, NULL_TREE, NULL_TREE); + /* Check if '_data' is an array descriptor. If it is not, + the array must be one of the components of the class + object, so return a normal array reference. */ + if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE ( + gfc_class_data_get (decl)))) + return build4_loc (input_location, ARRAY_REF, type, base, + offset, NULL_TREE, NULL_TREE); + } - span = gfc_class_vtab_size_get (decl); + span = gfc_class_vtab_size_get (decl); + } + else if (GFC_DECL_SUBREF_ARRAY_P (decl)) + span = GFC_DECL_SPAN (decl); + else + gcc_unreachable (); } - else if (GFC_DECL_SUBREF_ARRAY_P (decl)) - span = GFC_DECL_SPAN(decl); + else if (vptr) + span = gfc_vptr_size_get (vptr); else gcc_unreachable (); Index: gcc/fortran/trans-decl.c =================================================================== --- gcc/fortran/trans-decl.c (Revision 222360) +++ gcc/fortran/trans-decl.c (Arbeitskopie) @@ -812,8 +812,13 @@ int dim; int nest; gfc_namespace* procns; + symbol_attribute *array_attr; + gfc_array_spec *as; + bool is_classarray = IS_CLASS_ARRAY (sym); type = TREE_TYPE (decl); + array_attr = is_classarray ? &CLASS_DATA (sym)->attr : &sym->attr; + as = is_classarray ? CLASS_DATA (sym)->as : sym->as; /* We just use the descriptor, if there is one. */ if (GFC_DESCRIPTOR_TYPE_P (type)) @@ -824,8 +829,8 @@ nest = (procns->proc_name->backend_decl != current_function_decl) && !sym->attr.contained; - if (sym->attr.codimension && flag_coarray == GFC_FCOARRAY_LIB - && sym->as->type != AS_ASSUMED_SHAPE + if (array_attr->codimension && flag_coarray == GFC_FCOARRAY_LIB + && as->type != AS_ASSUMED_SHAPE && GFC_TYPE_ARRAY_CAF_TOKEN (type) == NULL_TREE) { tree token; @@ -878,8 +883,8 @@ } /* Don't try to use the unknown bound for assumed shape arrays. */ if (GFC_TYPE_ARRAY_UBOUND (type, dim) == NULL_TREE - && (sym->as->type != AS_ASSUMED_SIZE - || dim < GFC_TYPE_ARRAY_RANK (type) - 1)) + && (as->type != AS_ASSUMED_SIZE + || dim < GFC_TYPE_ARRAY_RANK (type) - 1)) { GFC_TYPE_ARRAY_UBOUND (type, dim) = create_index_var ("ubound", nest); TREE_NO_WARNING (GFC_TYPE_ARRAY_UBOUND (type, dim)) = 1; @@ -920,7 +925,7 @@ } if (GFC_TYPE_ARRAY_SIZE (type) == NULL_TREE - && sym->as->type != AS_ASSUMED_SIZE) + && as->type != AS_ASSUMED_SIZE) { GFC_TYPE_ARRAY_SIZE (type) = create_index_var ("size", nest); TREE_NO_WARNING (GFC_TYPE_ARRAY_SIZE (type)) = 1; @@ -947,12 +952,12 @@ } if (TYPE_NAME (type) != NULL_TREE - && GFC_TYPE_ARRAY_UBOUND (type, sym->as->rank - 1) != NULL_TREE - && TREE_CODE (GFC_TYPE_ARRAY_UBOUND (type, sym->as->rank - 1)) == VAR_DECL) + && GFC_TYPE_ARRAY_UBOUND (type, as->rank - 1) != NULL_TREE + && TREE_CODE (GFC_TYPE_ARRAY_UBOUND (type, as->rank - 1)) == VAR_DECL) { tree gtype = DECL_ORIGINAL_TYPE (TYPE_NAME (type)); - for (dim = 0; dim < sym->as->rank - 1; dim++) + for (dim = 0; dim < as->rank - 1; dim++) { gcc_assert (TREE_CODE (gtype) == ARRAY_TYPE); gtype = TREE_TYPE (gtype); @@ -966,7 +971,7 @@ { tree gtype = TREE_TYPE (type), rtype, type_decl; - for (dim = sym->as->rank - 1; dim >= 0; dim--) + for (dim = as->rank - 1; dim >= 0; dim--) { tree lbound, ubound; lbound = GFC_TYPE_ARRAY_LBOUND (type, dim); @@ -1014,41 +1019,56 @@ tree decl; tree type; gfc_array_spec *as; + symbol_attribute *array_attr; char *name; gfc_packed packed; int n; bool known_size; + bool is_classarray = IS_CLASS_ARRAY (sym); - if (sym->attr.pointer || sym->attr.allocatable - || (sym->as && sym->as->type == AS_ASSUMED_RANK)) + /* Use the array as and attr. */ + as = is_classarray ? CLASS_DATA (sym)->as : sym->as; + array_attr = is_classarray ? &CLASS_DATA (sym)->attr : &sym->attr; + + /* The dummy is returned for pointer, allocatable or assumed rank arrays. + For class arrays the information if sym is an allocatable or pointer + object needs to be checked explicitly (IS_CLASS_ARRAY can be false for + too many reasons to be of use here). */ + if ((sym->ts.type != BT_CLASS && sym->attr.pointer) + || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer) + || array_attr->allocatable + || (as && as->type == AS_ASSUMED_RANK)) return dummy; - /* Add to list of variables if not a fake result variable. */ + /* Add to list of variables if not a fake result variable. + These symbols are set on the symbol only, not on the class component. */ if (sym->attr.result || sym->attr.dummy) gfc_defer_symbol_init (sym); - type = TREE_TYPE (dummy); + /* For a class array the array descriptor is in the _data component, while + for a regular array the TREE_TYPE of the dummy is a pointer to the + descriptor. */ + type = TREE_TYPE (is_classarray ? gfc_class_data_get (dummy) + : TREE_TYPE (dummy)); + /* type now is the array descriptor w/o any indirection. */ gcc_assert (TREE_CODE (dummy) == PARM_DECL - && POINTER_TYPE_P (type)); + && POINTER_TYPE_P (TREE_TYPE (dummy))); /* Do we know the element size? */ known_size = sym->ts.type != BT_CHARACTER || INTEGER_CST_P (sym->ts.u.cl->backend_decl); - if (known_size && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))) + if (known_size && !GFC_DESCRIPTOR_TYPE_P (type)) { /* For descriptorless arrays with known element size the actual argument is sufficient. */ - gcc_assert (GFC_ARRAY_TYPE_P (type)); gfc_build_qualified_array (dummy, sym); return dummy; } - type = TREE_TYPE (type); if (GFC_DESCRIPTOR_TYPE_P (type)) { /* Create a descriptorless array pointer. */ - as = sym->as; packed = PACKED_NO; /* Even when -frepack-arrays is used, symbols with TARGET attribute @@ -1079,8 +1099,11 @@ packed = PACKED_PARTIAL; } - type = gfc_typenode_for_spec (&sym->ts); - type = gfc_get_nodesc_array_type (type, sym->as, packed, + /* For classarrays the element type is required, but + gfc_typenode_for_spec () returns the array descriptor. */ + type = is_classarray ? gfc_get_element_type (type) + : gfc_typenode_for_spec (&sym->ts); + type = gfc_get_nodesc_array_type (type, as, packed, !sym->attr.target); } else @@ -1110,7 +1133,7 @@ /* We should never get deferred shape arrays here. We used to because of frontend bugs. */ - gcc_assert (sym->as->type != AS_DEFERRED); + gcc_assert (as->type != AS_DEFERRED); if (packed == PACKED_PARTIAL) GFC_DECL_PARTIAL_PACKED_ARRAY (decl) = 1; @@ -1429,6 +1452,23 @@ sym->backend_decl = decl; } + /* Returning the descriptor for dummy class arrays is hazardous, because + some caller is expecting an expression to apply the component refs to. + Therefore the descriptor is only created and stored in + sym->backend_decl's GFC_DECL_SAVED_DESCRIPTOR. The caller is then + responsible to extract it from there, when the descriptor is + desired. */ + if (IS_CLASS_ARRAY (sym) + && (!DECL_LANG_SPECIFIC (sym->backend_decl) + || !GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl))) + { + decl = gfc_build_dummy_array_decl (sym, sym->backend_decl); + /* Prevent the dummy from being detected as unused if it is copied. */ + if (sym->backend_decl != NULL && decl != sym->backend_decl) + DECL_ARTIFICIAL (sym->backend_decl) = 1; + sym->backend_decl = decl; + } + TREE_USED (sym->backend_decl) = 1; if (sym->attr.assign && GFC_DECL_ASSIGN (sym->backend_decl) == 0) { @@ -1435,7 +1475,7 @@ gfc_add_assign_aux_vars (sym); } - if (sym->attr.dimension + if ((sym->attr.dimension || IS_CLASS_ARRAY (sym)) && DECL_LANG_SPECIFIC (sym->backend_decl) && GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl) && DECL_CONTEXT (sym->backend_decl) != current_function_decl) @@ -3976,18 +4016,31 @@ = gfc_class_set_static_fields (sym->backend_decl, vptr, tmp); TREE_CONSTANT (DECL_INITIAL (sym->backend_decl)) = 1; } - else if (sym->attr.dimension || sym->attr.codimension) + else if (sym->attr.dimension || sym->attr.codimension + || (IS_CLASS_ARRAY (sym) && !CLASS_DATA (sym)->attr.allocatable)) { - /* Assumed-size Cray pointees need to be treated as AS_EXPLICIT. */ - array_type tmp = sym->as->type; - if (tmp == AS_ASSUMED_SIZE && sym->as->cp_was_assumed) - tmp = AS_EXPLICIT; - switch (tmp) + bool is_classarray = IS_CLASS_ARRAY (sym); + symbol_attribute *array_attr; + gfc_array_spec *as; + array_type tmp; + + array_attr = is_classarray ? &CLASS_DATA (sym)->attr : &sym->attr; + as = is_classarray ? CLASS_DATA (sym)->as : sym->as; + /* Assumed-size Cray pointees need to be treated as AS_EXPLICIT. */ + tmp = as->type; + if (tmp == AS_ASSUMED_SIZE && as->cp_was_assumed) + tmp = AS_EXPLICIT; + switch (tmp) { case AS_EXPLICIT: if (sym->attr.dummy || sym->attr.result) gfc_trans_dummy_array_bias (sym, sym->backend_decl, block); - else if (sym->attr.pointer || sym->attr.allocatable) + /* Allocatable and pointer arrays need to processed + explicitly. */ + else if ((sym->ts.type != BT_CLASS && sym->attr.pointer) + || (sym->ts.type == BT_CLASS + && CLASS_DATA (sym)->attr.class_pointer) + || array_attr->allocatable) { if (TREE_STATIC (sym->backend_decl)) { @@ -4002,7 +4055,8 @@ gfc_trans_deferred_array (sym, block); } } - else if (sym->attr.codimension && TREE_STATIC (sym->backend_decl)) + else if (sym->attr.codimension + && TREE_STATIC (sym->backend_decl)) { gfc_init_block (&tmpblock); gfc_trans_array_cobounds (TREE_TYPE (sym->backend_decl), @@ -4041,7 +4095,7 @@ case AS_ASSUMED_SIZE: /* Must be a dummy parameter. */ - gcc_assert (sym->attr.dummy || sym->as->cp_was_assumed); + gcc_assert (sym->attr.dummy || as->cp_was_assumed); /* We should always pass assumed size arrays the g77 way. */ if (sym->attr.dummy) @@ -4103,6 +4157,7 @@ } else { + se.descriptor_only = 1; gfc_conv_expr (&se, e); descriptor = se.expr; se.expr = gfc_conv_descriptor_data_addr (se.expr); Index: gcc/fortran/trans.h =================================================================== --- gcc/fortran/trans.h (Revision 222360) +++ gcc/fortran/trans.h (Arbeitskopie) @@ -49,6 +49,10 @@ /* The length of a character string value. */ tree string_length; + /* When expr is a reference to a class object, store its vptr access + here. */ + tree class_vptr; + /* If set gfc_conv_variable will return an expression for the array descriptor. When set, want_pointer should also be set. If not set scalarizing variables will be substituted. */ @@ -528,7 +532,7 @@ tree gfc_build_addr_expr (tree, tree); /* Build an ARRAY_REF. */ -tree gfc_build_array_ref (tree, tree, tree); +tree gfc_build_array_ref (tree, tree, tree, tree vptr = NULL_TREE); /* Creates a label. Decl is artificial if label_id == NULL_TREE. */ tree gfc_build_label_decl (tree); Index: gcc/fortran/trans-array.c =================================================================== --- gcc/fortran/trans-array.c (Revision 222360) +++ gcc/fortran/trans-array.c (Arbeitskopie) @@ -2495,11 +2495,14 @@ case GFC_SS_REFERENCE: /* Scalar argument to elemental procedure. */ gfc_init_se (&se, NULL); - if (ss_info->can_be_null_ref) + if (ss_info->can_be_null_ref || (expr->symtree + && (expr->symtree->n.sym->ts.type == BT_DERIVED + || expr->symtree->n.sym->ts.type == BT_CLASS))) { /* If the actual argument can be absent (in other words, it can be a NULL reference), don't try to evaluate it; pass instead - the reference directly. */ + the reference directly. The reference is also needed when + expr is of type class or derived. */ gfc_conv_expr_reference (&se, expr); } else @@ -3046,7 +3049,14 @@ return false; } else if (class_ref == NULL) - decl = expr->symtree->n.sym->backend_decl; + { + decl = expr->symtree->n.sym->backend_decl; + /* For class arrays the tree containing the class is stored in + GFC_DECL_SAVED_DESCRIPTOR of the sym's backend_decl. + For all others it's sym's backend_decl directly. */ + if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl)) + decl = GFC_DECL_SAVED_DESCRIPTOR (decl); + } else { /* Remove everything after the last class reference, convert the @@ -3155,20 +3165,35 @@ static tree -build_array_ref (tree desc, tree offset, tree decl) +build_array_ref (tree desc, tree offset, tree decl, tree vptr) { tree tmp; tree type; + tree cdecl; + bool classarray = false; + /* For class arrays the class declaration is stored in the saved + descriptor. */ + if (INDIRECT_REF_P (desc) + && DECL_LANG_SPECIFIC (TREE_OPERAND (desc, 0)) + && GFC_DECL_SAVED_DESCRIPTOR (TREE_OPERAND (desc, 0))) + cdecl = gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR ( + TREE_OPERAND (desc, 0))); + else + cdecl = desc; + /* Class container types do not always have the GFC_CLASS_TYPE_P but the canonical type does. */ - if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)) - && TREE_CODE (desc) == COMPONENT_REF) + if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (cdecl)) + && TREE_CODE (cdecl) == COMPONENT_REF) { - type = TREE_TYPE (TREE_OPERAND (desc, 0)); + type = TREE_TYPE (TREE_OPERAND (cdecl, 0)); if (TYPE_CANONICAL (type) && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type))) - type = TYPE_CANONICAL (type); + { + type = TREE_TYPE (desc); + classarray = true; + } } else type = NULL; @@ -3175,10 +3200,10 @@ /* Class array references need special treatment because the assigned type size needs to be used to point to the element. */ - if (type && GFC_CLASS_TYPE_P (type)) + if (classarray) { - type = gfc_get_element_type (TREE_TYPE (desc)); - tmp = TREE_OPERAND (desc, 0); + type = gfc_get_element_type (type); + tmp = TREE_OPERAND (cdecl, 0); tmp = gfc_get_class_array_ref (offset, tmp); tmp = fold_convert (build_pointer_type (type), tmp); tmp = build_fold_indirect_ref_loc (input_location, tmp); @@ -3187,7 +3212,7 @@ tmp = gfc_conv_array_data (desc); tmp = build_fold_indirect_ref_loc (input_location, tmp); - tmp = gfc_build_array_ref (tmp, offset, decl); + tmp = gfc_build_array_ref (tmp, offset, decl, vptr); return tmp; } @@ -3350,7 +3375,8 @@ offset = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, offset, cst_offset); - se->expr = build_array_ref (se->expr, offset, sym->backend_decl); + se->expr = build_array_ref (se->expr, offset, sym->ts.type == BT_CLASS ? + NULL_TREE : sym->backend_decl, se->class_vptr); } @@ -5570,7 +5596,7 @@ gfc_se se; gfc_array_spec *as; - as = sym->as; + as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as; for (dim = as->rank; dim < as->rank + as->corank; dim++) { @@ -5613,7 +5639,7 @@ int dim; - as = sym->as; + as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as; size = gfc_index_one_node; offset = gfc_index_zero_node; @@ -5900,12 +5926,17 @@ int checkparm; int no_repack; bool optional_arg; + gfc_array_spec *as; + bool is_classarray = IS_CLASS_ARRAY (sym); /* Do nothing for pointer and allocatable arrays. */ - if (sym->attr.pointer || sym->attr.allocatable) + if ((sym->ts.type != BT_CLASS && sym->attr.pointer) + || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer) + || sym->attr.allocatable + || (is_classarray && CLASS_DATA (sym)->attr.allocatable)) return; - if (sym->attr.dummy && gfc_is_nodesc_array (sym)) + if (!is_classarray && sym->attr.dummy && gfc_is_nodesc_array (sym)) { gfc_trans_g77_array (sym, block); return; @@ -5918,7 +5949,13 @@ type = TREE_TYPE (tmpdesc); gcc_assert (GFC_ARRAY_TYPE_P (type)); dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc); - dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc); + if (is_classarray) + /* For a class array the dummy array descriptor is in the _class + component. */ + dumdesc = gfc_class_data_get (dumdesc); + else + dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc); + as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as; gfc_start_block (&init); if (sym->ts.type == BT_CHARACTER @@ -5925,7 +5962,7 @@ && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL) gfc_conv_string_length (sym->ts.u.cl, NULL, &init); - checkparm = (sym->as->type == AS_EXPLICIT + checkparm = (as->type == AS_EXPLICIT && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)); no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc) @@ -6001,9 +6038,9 @@ size = gfc_index_one_node; /* Evaluate the bounds of the array. */ - for (n = 0; n < sym->as->rank; n++) + for (n = 0; n < as->rank; n++) { - if (checkparm || !sym->as->upper[n]) + if (checkparm || !as->upper[n]) { /* Get the bounds of the actual parameter. */ dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]); @@ -6019,7 +6056,7 @@ if (!INTEGER_CST_P (lbound)) { gfc_init_se (&se, NULL); - gfc_conv_expr_type (&se, sym->as->lower[n], + gfc_conv_expr_type (&se, as->lower[n], gfc_array_index_type); gfc_add_block_to_block (&init, &se.pre); gfc_add_modify (&init, lbound, se.expr); @@ -6027,13 +6064,13 @@ ubound = GFC_TYPE_ARRAY_UBOUND (type, n); /* Set the desired upper bound. */ - if (sym->as->upper[n]) + if (as->upper[n]) { /* We know what we want the upper bound to be. */ if (!INTEGER_CST_P (ubound)) { gfc_init_se (&se, NULL); - gfc_conv_expr_type (&se, sym->as->upper[n], + gfc_conv_expr_type (&se, as->upper[n], gfc_array_index_type); gfc_add_block_to_block (&init, &se.pre); gfc_add_modify (&init, ubound, se.expr); @@ -6086,7 +6123,7 @@ gfc_array_index_type, offset, tmp); /* The size of this dimension, and the stride of the next. */ - if (n + 1 < sym->as->rank) + if (n + 1 < as->rank) { stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1); @@ -6234,7 +6271,7 @@ return; } - tmp = build_array_ref (desc, offset, NULL); + tmp = build_array_ref (desc, offset, NULL, NULL); /* Offset the data pointer for pointer assignments from arrays with subreferences; e.g. my_integer => my_type(:)%integer_component. */ @@ -6789,6 +6826,7 @@ tree from; tree to; tree base; + bool onebased = false; ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen; @@ -6930,6 +6968,7 @@ gfc_array_index_type, to, tmp); from = gfc_index_one_node; } + onebased = integer_onep (from); gfc_conv_descriptor_lbound_set (&loop.pre, parm, gfc_rank_cst[dim], from); @@ -6986,13 +7025,29 @@ gfc_get_dataptr_offset (&loop.pre, parm, desc, offset, subref_array_target, expr); - if (((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc))) - && !se->data_not_needed) - || (se->use_offset && base != NULL_TREE)) + /* Force the offset to be -1, when the lower bound of the highest + dimension is one and the symbol is present and is not a + pointer/allocatable or associated. */ + if (onebased && se->use_offset + && expr->symtree + && !(expr->symtree->n.sym && expr->symtree->n.sym->ts.type == BT_CLASS + && !CLASS_DATA (expr->symtree->n.sym)->attr.class_pointer) + && !expr->symtree->n.sym->attr.allocatable + && !expr->symtree->n.sym->attr.pointer + && !expr->symtree->n.sym->attr.host_assoc + && !expr->symtree->n.sym->attr.use_assoc) { - /* Set the offset. */ - gfc_conv_descriptor_offset_set (&loop.pre, parm, base); + /* Set the offset to -1. */ + mpz_t minus_one; + mpz_init_set_si (minus_one, -1); + tmp = gfc_conv_mpz_to_tree (minus_one, gfc_index_integer_kind); + gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp); } + else if (((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc))) + && !se->data_not_needed) + || (se->use_offset && base != NULL_TREE)) + /* Set the offset depending on base. */ + gfc_conv_descriptor_offset_set (&loop.pre, parm, base); else { /* Only the callee knows what the correct offset it, so just set Index: gcc/fortran/expr.c =================================================================== --- gcc/fortran/expr.c (Revision 222360) +++ gcc/fortran/expr.c (Arbeitskopie) @@ -4052,6 +4052,7 @@ gfc_lval_expr_from_sym (gfc_symbol *sym) { gfc_expr *lval; + gfc_array_spec *as; lval = gfc_get_expr (); lval->expr_type = EXPR_VARIABLE; lval->where = sym->declared_at; @@ -4059,10 +4060,10 @@ lval->symtree = gfc_find_symtree (sym->ns->sym_root, sym->name); /* It will always be a full array. */ - lval->rank = sym->as ? sym->as->rank : 0; + as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as; + lval->rank = as ? as->rank : 0; if (lval->rank) - gfc_add_full_array_ref (lval, sym->ts.type == BT_CLASS ? - CLASS_DATA (sym)->as : sym->as); + gfc_add_full_array_ref (lval, as); return lval; } Index: gcc/testsuite/gfortran.dg/finalize_10.f90 =================================================================== --- gcc/testsuite/gfortran.dg/finalize_10.f90 (Revision 222360) +++ gcc/testsuite/gfortran.dg/finalize_10.f90 (Arbeitskopie) @@ -27,8 +27,8 @@ ! Finalize CLASS + set default init ! { dg-final { scan-tree-dump-times "y->_vptr->_final \\(&desc.\[0-9\]+, y->_vptr->_size, 0\\);" 1 "original" } } ! { dg-final { scan-tree-dump "__builtin_memcpy \\(\\(void .\\) y->_data, \\(void .\\) y->_vptr->_def_init, \\((unsigned long|unsigned int|character\\(kind=4\\))\\) y->_vptr->_size\\);" "original" } } -! { dg-final { scan-tree-dump-times "x->_vptr->_final \\(&x->_data, x->_vptr->_size, 0\\);" 1 "original" } } -! { dg-final { scan-tree-dump-times "x->_vptr->_copy \\(x->_vptr->_def_init, &x->_data\\);" 1 "original" } } +! { dg-final { scan-tree-dump-times "x->_vptr->_final \\(&parm.\[0-9\]+, x->_vptr->_size, 0\\);" 1 "original" } } +! { dg-final { scan-tree-dump-times "x->_vptr->_copy \\(" 1 "original" } } ! FINALIZE TYPE: ! { dg-final { scan-tree-dump-times "parm.\[0-9\]+.data = \\(void \\*\\) &\\(\\*aa.\[0-9\]+\\)\\\[0\\\];" 1 "original" } } Index: gcc/testsuite/gfortran.dg/finalize_15.f90 =================================================================== --- gcc/testsuite/gfortran.dg/finalize_15.f90 (Revision 222360) +++ gcc/testsuite/gfortran.dg/finalize_15.f90 (Arbeitskopie) @@ -9,37 +9,37 @@ implicit none type t1 - integer :: i + integer :: i = 1 contains final :: fini_elem end type t1 type, extends(t1) :: t1e - integer :: j + integer :: j = 11 contains final :: fini_elem2 end type t1e type t2 - integer :: i + integer :: i = 2 contains final :: fini_shape end type t2 type, extends(t2) :: t2e - integer :: j + integer :: j = 22 contains final :: fini_shape2 end type t2e type t3 - integer :: i + integer :: i = 3 contains final :: fini_explicit end type t3 type, extends(t3) :: t3e - integer :: j + integer :: j = 33 contains final :: fini_explicit2 end type t3e @@ -204,31 +204,31 @@ select type(x) type is (t1e) - call check_val(x%i, 1) - call check_val(x%j, 100) + call check_val(x%i, 1, 1) + call check_val(x%j, 100, 11) end select select type(y) type is (t2e) - call check_val(y%i, 1) - call check_val(y%j, 100) + call check_val(y%i, 1, 2) + call check_val(y%j, 100, 22) end select select type(z) type is (t3e) - call check_val(z%i, 1) - call check_val(z%j, 100) + call check_val(z%i, 1, 3) + call check_val(z%j, 100, 33) end select contains - subroutine check_val(x, factor) + subroutine check_val(x, factor, val) integer :: x(:,:) - integer, value :: factor + integer, value :: factor, val integer :: i, j do i = 1, 10 do j = 1, 10 if (mod (j-1, 2) == 0 .and. mod (i-1, 3) == 0) then - if (x(j,i) /= (j + 100*i)*factor*(-13)) call abort () + if (x(j,i) /= val) call abort () else if (x(j,i) /= (j + 100*i)*factor) call abort () end if Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (Revision 222360) +++ gcc/testsuite/ChangeLog (Arbeitskopie) @@ -1,3 +1,14 @@ +2015-04-23 Andre Vehreschild + + PR fortran/60322 + * gfortran.dg/class_allocate_19.f03: New test. + * gfortran.dg/class_array_20.f03: New test. + * gfortran.dg/class_array_21.f03: New test. + * gfortran.dg/finalize_10.f90: Corrected scan-trees. + * gfortran.dg/finalize_15.f90: Fixing comparision to model + initialization correctly. + * gfortran.dg/finalize_29.f08: New test. + 2015-04-22 Bill Schmidt * gcc.target/powerpc/swaps-p8-18.c: New test.