[PATCH] Fortran: fix assignment to allocatable scalar polymorphic component [PR121616]

Harald Anlauf anlauf@gmx.de
Sun Sep 14 19:17:03 GMT 2025


Am 13.09.25 um 22:54 schrieb Mikael Morin:
> Le 12/09/2025 à 22:51, Harald Anlauf a écrit :
>> Am 12.09.25 um 11:12 schrieb Mikael Morin:
>>> Le 11/09/2025 à 22:46, Harald Anlauf a écrit :
>>>> Am 11.09.25 um 22:27 schrieb Mikael Morin:
>>>>> Le 11/09/2025 à 20:28, Harald Anlauf a écrit :
>>>>>> Dear all,
>>>>>>
>>>>>> here's a - once found - seemingly simple and obvious fix for a memory
>>>>>> corruption happening when intrinsic assignment is used to set a 
>>>>>> scalar
>>>>>> allocatable polymorphic component of a derived type when the latter
>>>>>> is instanciated as an array of rank > 0.  Just get the dimension
>>>>>> attribute right when using gfc_variable_attr ...
>>>>>>
>>>>>> The testcase is an extended version of the reporter's with unlimited
>>>>>> polymorphism, including another simpler one contributed by a friend.
>>>>>> Without the fix, both tests crash with memory corruption of various
>>>>>> kinds.
>>>>>>
>>>>>> Regtested on x86_64-pc-linux-gnu.  OK for mainline?
>>>>>>
>>>>> Hello Harald,
>>>>>
>>>>>> diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
>>>>>> index 6df95558bb1..2cb930d83b8 100644
>>>>>> --- a/gcc/fortran/primary.cc
>>>>>> +++ b/gcc/fortran/primary.cc
>>>>>> @@ -3057,12 +3057,14 @@ gfc_variable_attr (gfc_expr *expr, 
>>>>>> gfc_typespec *ts)
>>>>>>
>>>>>>      if (comp->ts.type == BT_CLASS)
>>>>>>        {
>>>>>> +        dimension = CLASS_DATA (comp)->attr.dimension;
>>>>>>          codimension = CLASS_DATA (comp)->attr.codimension;
>>>>>>          pointer = CLASS_DATA (comp)->attr.class_pointer;
>>>>>>          allocatable = CLASS_DATA (comp)->attr.allocatable;
>>>>>>        }
>>>>>>      else
>>>>>>        {
>>>>>> +        dimension = comp->attr.dimension;
>>>>>>          codimension = comp->attr.codimension;
>>>>>>          if (expr->ts.type == BT_CLASS && strcmp (comp->name, 
>>>>>> "_data") == 0)
>>>>>>            pointer = comp->attr.class_pointer;
>>>>>
>>>>> I think the dimension flag should additionally be cleared if there 
>>>>> is an array element reference after the component.  Otherwise one 
>>>>> could get the dimension attribute for a scalar expression (say 
>>>>> derived%array_comp(123)).
>>>>> I don't really have a testcase that would exhibit a failure, I'm 
>>>>> just being overly cautious.
>>>>> Thanks for the patch in any case.
>>>>
>>>> You mean further up?
>>>>
>>>>      switch (ref->type)
>>>>        {
>>>>        case REF_ARRAY:
>>>>
>>>>      switch (ref->u.ar.type)
>>>>        {
>>>> ...
>>>>        case AR_ELEMENT:
>>>>          /* Handle coarrays.  */
>>>>          if (ref->u.ar.dimen > 0)
>>>>            allocatable = pointer = optional = false;
>>>>          break;
>>>>
>>> Yes, that's the place.
>>>
>>> The more I look at your patch, the less I understand it.
>>> So, given an array expression such as array(:)%scalar_comp, 
>>> gfc_variable_attr on it would return a result without the dimension 
>>> attribute?
>>
>> Well, the comment before gfc_variable_attr says:
>>
>> /* Given an expression that is a variable, figure out what the
>>     ultimate variable's type and attribute is, traversing the reference
>>     structures if necessary.
>>
>>     This subroutine is trickier than it looks.  We start at the base
>>     symbol and store the attribute.  Component references load a
>>     completely new attribute.
>>
> The latter sentence applies to allocatable, pointer/target, etc, but I 
> don't think it should apply to dimension.
> Dimension is different because it's the parent reference that determines 
> whether the subreference is a scalar or an array, thus whether it has 
> the dimension attribute or not.
> 
>> ...
>>
>> Assuming that scalar_comp is the ultimate component, its dimension is 0.
>>
> Err, well, no. I mean, it depends on what's before it.
> derived(123)%scalar_comp is a scalar, so it doesn't have the dimension 
> attribute.
> But derived(:)%scalar_comp is an array, so it has the dimension attribute.
> 
>>
>> The standard appears somewhat ambiguous on the expression you give:
>>
>> 9.4 Scalars
>>
>> Note 2
>> ARRAY_PARENT(1:N)%SCALAR_FIELD  component of array section parent
>>
> That one is definitely an array, I hope we can agree on that.
> See the second sentence of 9.4.2 saying:
>      A structure component may be a scalar or an array.
> 
> So the presence in the section about scalars is not an indication that 
> it really is scalar.
> 
>> 9.5 Arrays
>>
>> Note 3
>>
>> SCALAR_PARENT%ARRAY_FIELD(1:N)               array section
>> SCALAR_PARENT%ARRAY_FIELD(1:N)%SCALAR_FIELD  array section
>>
> 
> Coming back to your patch, rephrasing my previous concerns.
> If I understand correctly, your patch changes the dimension attribute 
> for the following cases:
>                             old value   new value
> 1. array(i)%scalar_comp       1           0
> 2. array(:)%scalar_comp       1           0
> 3. scalar%array_comp(i)       0           1
> 
> 1. is the desired change, but I think 2. and 3. are undesired.

Well, the patch changes gfc_variable_attr, but see also the comment
I cited.  This is needed that the scalarized assignment sees the
ultimate component, which is an allocatable scalar for the testcase.

I did not claim that gfc_expr_attr always returns the right attributes.



More information about the Fortran mailing list