[Patch, fortran] PR fortran/100018 - ICE on missing polymorphic argument
Hi all! Proposed patch to PR100018 - ICE on missing polymorphic argument. Patch tested only on x86_64-pc-linux-gnu. Add association check before de-referencing pointer in order to avoid ICE. Thank you very much. Best regards, José Rui 2021-4-10 José Rui Faustino de Sousa gcc/fortran/ChangeLog: PR fortran/100018 * resolve.c: Add association check before de-referencing pointer. gcc/testsuite/ChangeLog: PR fortran/100018 * gfortran.dg/PR10018.f90: New test. diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 1c9b0c5cb62..dd4b26680e0 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -11999,6 +11999,7 @@ start: /* Assigning a class object always is a regular assign. */ if (code->expr2->ts.type == BT_CLASS && code->expr1->ts.type == BT_CLASS + && CLASS_DATA (code->expr2) && !CLASS_DATA (code->expr2)->attr.dimension && !(gfc_expr_attr (code->expr1).proc_pointer && code->expr2->expr_type == EXPR_VARIABLE diff --git a/gcc/testsuite/gfortran.dg/PR10018.f90 b/gcc/testsuite/gfortran.dg/PR10018.f90 new file mode 100644 index 000..f1cf2676f85 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/PR10018.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! +subroutine foo(that) + implicit none + class(*), target, intent(in) :: this + class(*), pointer, intent(out) :: that + + that => this + return +end subroutine foo +! { dg-error "Symbol at \\\(1\\\) is not a DUMMY variable" "" { target "*-*-*" } 5 }
Re: [Patch, fortran] PR fortran/100018 - ICE on missing polymorphic argument
Hi José, On 10.04.21 18:58, José Rui Faustino de Sousa via Fortran wrote: Proposed patch to PR100018 - ICE on missing polymorphic argument. Patch tested only on x86_64-pc-linux-gnu. LGTM – Thanks for the patch. Two nits: If you don't want to rely on the author field of git and specify an extra line, you need a '0' for the moth in the date (-04- instead of -4-). And you need an additional single-line summary for git – which should be part of the patch submission. Tobias Add association check before de-referencing pointer in order to avoid ICE. Thank you very much. Best regards, José Rui 2021-4-10 José Rui Faustino de Sousa gcc/fortran/ChangeLog: PR fortran/100018 * resolve.c: Add association check before de-referencing pointer. gcc/testsuite/ChangeLog: PR fortran/100018 * gfortran.dg/PR10018.f90: New test.
Re: GSoC 2021 - Fortran run-time argument checking
Dear Krishna, On 07.04.21 17:55, Krishna Kariya wrote: 1. Do we need to create the global variables __gfortran_called_proc, __gfortran_called_interface during compilation? If yes, how would these global variables be initialized, the module containing the caller’s source code or the module containing the callee’s source code? I was thinking NULL initialized static variables (pointers to the actual data/called function) – as weak symbol, i.e. in every translation unit which is compiled with the arg-checking flag. The linker will choose one of the identical symbols and place it (on most systems) in the BSS. Do we plan to do the instrumentation for runtime check inline in the IR itself (inline monitoring)? Or can we write a runtime library that does the checking, and we just insert calls to the runtime library routine at compile time? Either works – but I think it might be simpler to write and avoids a lot of string constants if the actual check is done in libgfortran. 3. Do we need to handle multithreaded programs? How will we handle the race condition in which two different threads call an external procedure at the same time? Shouldn't that work if we use a thread local/private variable ('__thread', "set_decl_tls_model (decl, decl_default_tls_model (decl));"). In any case, it would be useful: (a) combining code which does argument checking with code which does not This means we cannot simply add anything which changes the ABI unless it is guaranteed to also work when the called procedure is not instrumented or when an instrumented procedure is called. (b) avoid race conditions 4. How will we identify the procedures which require the run-time check? I mean, do we need to write a static analysis to figure out which functions are called externally? My idea was that -fcheck=argcheck will simply annotate all calls and procedures, except intrinsic procedures, internal procedures, module procedures – we could argue about bind(C) and about procedures in the same translation unit (that's known). Tobias
Re: [Patch, fortran] 99307 - FAIL: gfortran.dg/class_assign_4.f90 execution test
Dear Paul, sorry for the belate reply. I think you forgot to attach the patch. Tobias On 06.04.21 19:08, Paul Richard Thomas via Fortran wrote: Hi Tobias, I believe that the attached fixes the problems that you found with gfc_find_and_cut_at_last_class_ref. I will test: type1%type%array_class2 → NULL is returned (why?) class1%type%array_class2 → ts = class1 but array2_class is used later on (ups!) class1%...%scalar_class2 → ts = class1 but scalar_class2 is used The ChangeLogs remain the same, apart from the date. Regtests OK on FC33/x86_64. Paul On Mon, 29 Mar 2021 at 14:58, Tobias Burnus wrote: Hi all, as preremark I want to note that the testcase class_assign_4.f90 was added for PR83118/PR96012 (fixes problems in handling class objects, Dec 18, 2020) and got revised for PR99124 (class defined operators, Feb 23, 2021). Both patches were then also applied to GCC 9 and 10. On 26.03.21 17:30, Paul Richard Thomas via Gcc-patches wrote: This patch comes in two versions: submit.diff with Change.Logs or submit2.diff with Change2.Logs. The first fixes the problem by changing array temporaries from class expressions into class temporaries. This permits the use of gfc_get_class_from_expr to obtain the vptr for these temporaries and all the good things that come with that when handling dynamic types. The second part of the fix is to use the array element length from the class descriptor, when reallocating on assignment. This is needed because the vptr is being set too early. I will set about trying to track down why this is happening and fix it after release. The second version does the same as the first but puts in place a load of tidying up that is permitted by the fix to class array temporaries. I couldn't readily see how to prepare a testcase - ideas? Both regtest on FC33/x86_64. The first was tested by Dominique (see the PR). OK for master? Typo – underscore-'c' should be a dot-'c' – both changelog files * trans-expr_c (gfc_trans_scalar_assign): Make use of pre and I think the second longer version is nicer in general, but at least for GCC 9/GCC10 the first version is simpler and, hence, less error prone. As you only ask about mainline, I would prefer the second one. However, I am not happy about gfc_find_and_cut_at_last_class_ref: + of refs following. If ts is non-null the cut is at the class entity + or component that is followed by an array reference, which is not + an element. */ ... + + if (ts) + { + if (e->symtree + && e->symtree->n.sym->ts.type == BT_CLASS) + *ts = &e->symtree->n.sym->ts; + else + *ts = NULL; + } + for (ref = e->ref; ref; ref = ref->next) { + if (ts && ref->type == REF_COMPONENT + && ref->u.c.component->ts.type == BT_CLASS + && ref->next && ref->next->type == REF_COMPONENT + && strcmp (ref->next->u.c.component->name, "_data") == 0 + && ref->next->next + && ref->next->next->type == REF_ARRAY + && ref->next->next->u.ar.type != AR_ELEMENT) + { + *ts = &ref->u.c.component->ts; + class_ref = ref; + break; + } + + if (ts && *ts == NULL) + return NULL; + Namely, if there is: type1%array_class2 → array_class2 is used for 'ts' and later (ok) type1%type%array_class2 → NULL is returned (why?) class1%type%array_class2 → ts = class1 but array2_class is used later on (ups!) class1%...%scalar_class2 → ts = class1 but scalar_class2 is used etc. Thus this either needs to be cleaned up (separate 'ref' loop for ts != NULL) – including the wording in the description which tells what happens if 'ts' is passed as arg but the expr has rank == 0 – and what value is assigned to 'ts'. (You can then also fix 'class.c::' to 'class.c: ' in the description above the function.) Alternatively, you can leave the current code ref handling code in place at build_class_array_ref, which might be the simpler alternative. Otherwise, it looks sensible to me. Tobias - Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank Thürauf
Re: [Patch, fortran] PR fortran/100018 - ICE on missing polymorphic argument
On 10/04/21 17:37, Tobias Burnus wrote: And you need an additional single-line summary for git – which should be part of the patch submission. Fortran: Fix ICE due to referencing a NULL pointer [PR100018] gcc/fortran/ChangeLog: PR fortran/100018 * resolve.c: Add association check before de-referencing pointer. gcc/testsuite/ChangeLog: PR fortran/100018 * gfortran.dg/PR10018.f90: New test. Thank you very much. Best regards, José Rui
[Patch, fortran] PR fortran/100024 PR fortran/100025 ICE on subroutine missing explicit interface
Hi all! Proposed patch to PR100024 & PR100025 - ICE on missing polymorphic argument. Patch tested only on x86_64-pc-linux-gnu. Remove assertion checking for possible assumed rank arrays and added an explicit error message. Change if clause to allow the handling of assumed-rank arrays as arrays. Thank you very much. Best regards, José Rui Fortran: Fix ICE on the handling of assumed-rank procedures [PR100024/PR100025] gcc/fortran/ChangeLog: * interface.c (argument_rank_mismatch): Remove assertion and add an explicit error message. (gfc_get_formal_from_actual_arglist): Allow handling of assume-rank arrays. gcc/testsuite/ChangeLog: * gfortran.dg/PR100024.f90: New test. * gfortran.dg/PR100025.f90: New test. diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c index 60736123550..5868bf23f11 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -2237,8 +2237,11 @@ argument_rank_mismatch (const char *name, locus *where, } else { - gcc_assert (rank2 != -1); - if (rank1 == 0) + if (rank2 == -1) + gfc_error_opt (0, "The assumed-rank array actual argument at %L and " + "actual argument at %L are ambiguous, an explicit " + "interface is required.", where, where_formal); + else if (rank1 == 0) gfc_error_opt (0, "Rank mismatch between actual argument at %L " "and actual argument at %L (scalar and rank-%d)", where, where_formal, rank2); @@ -5358,7 +5361,7 @@ gfc_get_formal_from_actual_arglist (gfc_symbol *sym, s->ts.is_iso_c = 0; s->ts.is_c_interop = 0; s->attr.flavor = FL_VARIABLE; - if (a->expr->rank > 0) + if (a->expr->rank) { s->attr.dimension = 1; s->as = gfc_get_array_spec (); diff --git a/gcc/testsuite/gfortran.dg/PR100024.f90 b/gcc/testsuite/gfortran.dg/PR100024.f90 new file mode 100644 index 000..fe82ef6da0a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/PR100024.f90 @@ -0,0 +1,37 @@ +! { dg-do compile } +! +program foobar + + implicit none + + type :: foo_t + end type foo_t + + class(foo_t), pointer :: a + type(foo_t), target :: b + + call bar1(a) + call bar2(b) + stop + +contains + + subroutine bar1(this) +class(foo_t), pointer, intent(in) :: this(..) + +call foo(this) +return + end subroutine bar1 + + subroutine bar2(this) +type(foo_t), pointer, intent(in) :: this(..) + +call foo(this) +return + end subroutine bar2 + +end program foobar +! { dg-error "Explicit interface required for polymorphic argument at \\\(1\\\)" "" { target "*-*-*" } 22 } +! { dg-excess-errors "" } + + diff --git a/gcc/testsuite/gfortran.dg/PR100025.f90 b/gcc/testsuite/gfortran.dg/PR100025.f90 new file mode 100644 index 000..ef8b58ad94a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/PR100025.f90 @@ -0,0 +1,25 @@ +! { dg-do compile } +! +program foo_p + + implicit none + + class(*), pointer :: a + + call foo(a) + call sub_s(a) + stop + +contains + + subroutine bar_s(this) +class(*), intent(in) :: this(..) + +call foo(this) +return + end subroutine bar_s + +end program foo_p +! { dg-error "Explicit interface required for polymorphic argument at \\\(1\\\)" "" { target "*-*-*" } 10 } +! { dg-excess-errors "" } +
[Patch, fortran] PR fortran/84006, PR fortran/100027 - ICE on storage_size with polymorphic argument
Hi All! Proposed patch to: PR84006 - [8/9/10/11 Regression] ICE in storage_size() with CLASS entity PR100027 - ICE on storage_size with polymorphic argument Patch tested only on x86_64-pc-linux-gnu. Add branch to if clause to handle polymorphic objects, not sure if I got all possible variations... Thank you very much. Best regards, José Rui Fortran: Fix ICE using storage_size intrinsic [PR84006, PR100027] gcc/fortran/ChangeLog: PR fortran/84006 PR fortran/100027 * trans-intrinsic.c (gfc_conv_intrinsic_storage_size): add if clause branch to handle polymorphic objects. gcc/testsuite/ChangeLog: PR fortran/84006 * gfortran.dg/PR84006.f90: New test. PR fortran/100027 * gfortran.dg/PR100027.f90: New test. diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 5e53d1162fa..6536c121f2b 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -8353,10 +8353,16 @@ gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr) if (arg->ts.type == BT_CLASS) { if (arg->rank > 0) - tmp = gfc_class_vtab_size_get ( - GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl)); + { + if (TREE_CODE (argse.expr) == COMPONENT_REF) + tmp = TREE_OPERAND (argse.expr, 0); + else + tmp = GFC_DECL_SAVED_DESCRIPTOR ( + arg->symtree->n.sym->backend_decl); + } else - tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0)); + tmp = TREE_OPERAND (argse.expr, 0); + tmp = gfc_class_vtab_size_get (tmp); tmp = fold_convert (result_type, tmp); goto done; } diff --git a/gcc/testsuite/gfortran.dg/PR100027.f90 b/gcc/testsuite/gfortran.dg/PR100027.f90 new file mode 100644 index 000..dc565872cac --- /dev/null +++ b/gcc/testsuite/gfortran.dg/PR100027.f90 @@ -0,0 +1,31 @@ +! { dg-do run } +! + +program foo_p + + implicit none + + integer, parameter :: n = 11 + + type :: foo_t + end type foo_t + + type, extends(foo_t) :: bar_t + end type bar_t + + class(*), pointer :: apu(:) + class(foo_t), pointer :: apf(:) + class(bar_t), pointer :: apb(:) + type(bar_t), target :: atb(n) + + integer :: m + + apu => atb + m = storage_size(apu) + apf => atb + m = storage_size(apf) + apb => atb + m = storage_size(apb) + +end program foo_p + diff --git a/gcc/testsuite/gfortran.dg/PR84006.f90 b/gcc/testsuite/gfortran.dg/PR84006.f90 new file mode 100644 index 000..41e2161b6e5 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/PR84006.f90 @@ -0,0 +1,12 @@ +! { dg-do run } +! + +program p + type t +integer i + end type + integer rslt + class(t), allocatable :: t_alloc(:) + allocate (t_alloc(10), source=t(1)) + rslt = storage_size(t_alloc) +end program p