* GCC 11 bug? lawyer needed @ 2021-05-03 16:08 Simon Wright 2021-05-05 3:54 ` Randy Brukardt 0 siblings, 1 reply; 10+ messages in thread From: Simon Wright @ 2021-05-03 16:08 UTC (permalink / raw) This code results in the error shown: 1. package Aliased_Tagged_Types is 2. 3. type T is tagged null record; 4. 5. function P (Param : aliased T) return Boolean 6. is (False); 7. 8. function F (Param : T) return Boolean 9. is (Param.P); | >>> actual for explicitly aliased formal is too short lived 10. 11. end Aliased_Tagged_Types; The compiler code that results in this error is at sem_ch4.adb:1490, and was introduced for Ada202x accessibiity checking reasons. -- Check whether the formal is aliased and if the accessibility -- level of the actual is deeper than the accessibility level -- of the enclosing subprogam to which the current return -- statement applies. [...] if Is_Explicitly_Aliased (Form) and then Is_Entity_Name (Act) and then Static_Accessibility_Level (Act, Zero_On_Dynamic_Level) > Subprogram_Access_Level (Current_Subprogram) then Error_Msg_N ("actual for explicitly aliased formal is too" & " short lived", Act); end if; ---- For those interested, this issue affects Alire. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: GCC 11 bug? lawyer needed 2021-05-03 16:08 GCC 11 bug? lawyer needed Simon Wright @ 2021-05-05 3:54 ` Randy Brukardt 2021-05-05 10:01 ` AdaMagica 0 siblings, 1 reply; 10+ messages in thread From: Randy Brukardt @ 2021-05-05 3:54 UTC (permalink / raw) We spent a lot of time and effort in the ARG talking about this case (see AI12-0402-1). The Ada 2012 RM does indeed say this case is illegal. The reason is that aliased parameters are designed so that one can return part of of them in the return object of the function. And a normal parameter is assumed to be local (since its accessibility is unknown) - that means it is too local for an aliased parameter of a function that is used in some non-local way (including being returned from a non-local function). However, since one cannot return a part of a parameter for a function that returns an elementary type (other than anonymous access returns, which have special rules anyway), we added an exception to the rules for that case in Ada 202x. (We tried a number of more liberal exceptions, but they were complex and had [unlikely] holes.) So the most current rule is that the call of P is legal. That wasn't decided until the December ARG meeting, so it happened after the GNATPro 21 release (and I expect that the GNAT CE is derived from that version). And I'd guess that in Ada 2012 mode, this check would remain as it is (the change was not made retroactively - not sure why). Randy. "Simon Wright" <simon@pushface.org> wrote in message news:lyh7jjztor.fsf@pushface.org... > This code results in the error shown: > > 1. package Aliased_Tagged_Types is > 2. > 3. type T is tagged null record; > 4. > 5. function P (Param : aliased T) return Boolean > 6. is (False); > 7. > 8. function F (Param : T) return Boolean > 9. is (Param.P); > | > >>> actual for explicitly aliased formal is too short lived > > 10. > 11. end Aliased_Tagged_Types; > > The compiler code that results in this error is at sem_ch4.adb:1490, and > was introduced for Ada202x accessibiity checking reasons. > > -- Check whether the formal is aliased and if the accessibility > -- level of the actual is deeper than the accessibility level > -- of the enclosing subprogam to which the current return > -- statement applies. > > [...] > > if Is_Explicitly_Aliased (Form) > and then Is_Entity_Name (Act) > and then Static_Accessibility_Level > (Act, Zero_On_Dynamic_Level) > > Subprogram_Access_Level (Current_Subprogram) > then > Error_Msg_N ("actual for explicitly aliased formal is too" > & " short lived", Act); > end if; > > ---- > > For those interested, this issue affects Alire. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: GCC 11 bug? lawyer needed 2021-05-05 3:54 ` Randy Brukardt @ 2021-05-05 10:01 ` AdaMagica 2021-05-05 16:10 ` AdaMagica 0 siblings, 1 reply; 10+ messages in thread From: AdaMagica @ 2021-05-05 10:01 UTC (permalink / raw) Randy Brukardt schrieb am Mittwoch, 5. Mai 2021 um 05:54:46 UTC+2: > And a normal parameter is assumed to be local (since its accessibility is unknown) - that means it is > too local for an aliased parameter of a function that is used in some non-local way RM 3.10(9/3): Finally, a formal parameter or generic formal object of a tagged type is defined to be aliased. RM 6.4.1(6/3): If the formal parameter is an explicitly aliased parameter, the type of the actual parameter shall be tagged or the actual parameter shall be an aliased view of an object. Both of these conditions are fulfilled here. There are many more places about explicitly aliased parameters in the RM. I've read them all. It left me wondering. I do not see what aliasing a tagged parameter buys. A parameter of a tagged typed is aliased per se, or do I misread the RM. I'm having big problems trying to understand the RM. I will try to grock the AI. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: GCC 11 bug? lawyer needed 2021-05-05 10:01 ` AdaMagica @ 2021-05-05 16:10 ` AdaMagica 2021-05-06 0:39 ` Randy Brukardt 0 siblings, 1 reply; 10+ messages in thread From: AdaMagica @ 2021-05-05 16:10 UTC (permalink / raw) AdaMagica schrieb am Mittwoch, 5. Mai 2021 um 12:01:07 UTC+2: > I will try to grock the AI. Hm, I'm still confused. Can anyone please come up with some examples that explain what this is all about? ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: GCC 11 bug? lawyer needed 2021-05-05 16:10 ` AdaMagica @ 2021-05-06 0:39 ` Randy Brukardt 2021-05-06 13:07 ` AdaMagica 2021-05-06 20:02 ` Simon Wright 0 siblings, 2 replies; 10+ messages in thread From: Randy Brukardt @ 2021-05-06 0:39 UTC (permalink / raw) "AdaMagica" <christ-usch.grein@t-online.de> wrote in message news:aaa58296-3298-4b70-ac7e-1393f579f217n@googlegroups.com... > AdaMagica schrieb am Mittwoch, 5. Mai 2021 um 12:01:07 UTC+2: >> I will try to grock the AI. > Hm, I'm still confused. Can anyone please come up with some examples that > explain what this is all about? See 6.4.1(6/3): there is an accessibility check on the actual parameter of an aliased parameter. This allows an aliased parameter to have the accessibility of the return object of a function, rather than local accessibility. There's a bunch of rules in 3.10.2 that combine to have the right effect. You see the result in an operation like "Reference" in the containers. If you have: function Foo (A : in out Container; Idx : in Natural) return access Element; then an implementation of: function Foo (A : in out Container) return access Element is begin return A.Data(Idx)'Access; -- (1) end Foo; (1) is illegal, as A has local to Foo accessibility, while the anonymous access has the accessibility of the return object (the point of call), which is necessarily outside of Foo. You can change (1) to: return A.Data(Idx)'Unchecked_Access; -- (1) but now you can create a dangling pointer, for instance if Foo is assigned to a library-level access type and the actual for A is not library-level. But you can change the parameter to "aliased", then the accessibility check is moved to the call site (where it must always suceeed for the vast majority of calls). There's no accessibility check at (1) in that case (which could be at best a dynamic check, which is a correctness hazard, and also has an overhead cost). And you still have the safety of not being able to create a dangling pointer. It is a bit weird that this property is tied to "aliased" parameters. This property came first, and we discussed the syntax to use for a long time. Eventually it was decided to call them "aliased" parameters, but of course that meant it was necessary to generalize the usages. This special rule does have the downside of being able to fail in some safe cases, like the one noted by the OP. That doesn't happen for procedures, since aliased parameters have no special semantics for procedures. We decided to remove the special semantics for functions for which it is impossible to return a part of the parameter (that is, any elementary-returning function), as that special semantics provides no benefit in such a case (but it does have a cost). I agree that the original author of that program should not have used "aliased" in the way that they did (they don't need the special semantics), but we realize that some people would prefer to *explicitly* mark things as aliased when they are going to take 'Access (and not worry about the type of the parameter -- after all, it could change). That is, they don't want to depend on the implicit behavior of tagged types -- or perhaps they don't even know about it. Which leads to the problem that occurs here, as "aliased" has slightly different meanings for functions (now just composite functions) and procedures. Since this is real code that didn't work as expected, it seemed to make sense to reduce the problem with a minor language tweak. Randy. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: GCC 11 bug? lawyer needed 2021-05-06 0:39 ` Randy Brukardt @ 2021-05-06 13:07 ` AdaMagica 2021-05-06 20:02 ` Simon Wright 1 sibling, 0 replies; 10+ messages in thread From: AdaMagica @ 2021-05-06 13:07 UTC (permalink / raw) Thank you, Randy, for the nice explanation. There're still some hazy places, but I begin to see the big picture. Christoph ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: GCC 11 bug? lawyer needed 2021-05-06 0:39 ` Randy Brukardt 2021-05-06 13:07 ` AdaMagica @ 2021-05-06 20:02 ` Simon Wright 2021-05-06 20:51 ` Dmitry A. Kazakov 2021-05-06 23:59 ` Randy Brukardt 1 sibling, 2 replies; 10+ messages in thread From: Simon Wright @ 2021-05-06 20:02 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > I agree that the original author of that program should not have used > "aliased" in the way that they did (they don't need the special semantics), > but we realize that some people would prefer to *explicitly* mark things as > aliased when they are going to take 'Access (and not worry about the type of > the parameter -- after all, it could change). That is, they don't want to > depend on the implicit behavior of tagged types -- or perhaps they don't > even know about it. Which leads to the problem that occurs here, as > "aliased" has slightly different meanings for functions (now just composite > functions) and procedures. The original code, from the Alire project, had (I've edited it slightly) package Holders is new Ada.Containers.Indefinite_Holders (Node'Class); type Tree is new Holders.Holder and ... function Root (This : Tree) return Node'Class is (This.Constant_Reference); where that Constant_Reference is inherited (eventually) from Ada.Containers.Indefinite_Holders.Holder, function Constant_Reference (Container : aliased Holder) return Constant_Reference_Type; pragma Inline (Constant_Reference); Shame it had to be there. I've just tried splattering 'aliased' wherever the compiler told me it was needed; it's now spreading into other packages. Ugh. The solution might just be using composition rather than inheritance. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: GCC 11 bug? lawyer needed 2021-05-06 20:02 ` Simon Wright @ 2021-05-06 20:51 ` Dmitry A. Kazakov 2021-05-06 23:59 ` Randy Brukardt 1 sibling, 0 replies; 10+ messages in thread From: Dmitry A. Kazakov @ 2021-05-06 20:51 UTC (permalink / raw) On 2021-05-06 22:02, Simon Wright wrote: > "Randy Brukardt" <randy@rrsoftware.com> writes: > >> I agree that the original author of that program should not have used >> "aliased" in the way that they did (they don't need the special semantics), >> but we realize that some people would prefer to *explicitly* mark things as >> aliased when they are going to take 'Access (and not worry about the type of >> the parameter -- after all, it could change). That is, they don't want to >> depend on the implicit behavior of tagged types -- or perhaps they don't >> even know about it. Which leads to the problem that occurs here, as >> "aliased" has slightly different meanings for functions (now just composite >> functions) and procedures. > > The original code, from the Alire project, had (I've edited it slightly) > > package Holders > is new Ada.Containers.Indefinite_Holders (Node'Class); > > type Tree is > new Holders.Holder > and ... > > function Root (This : Tree) return Node'Class is > (This.Constant_Reference); > > where that Constant_Reference is inherited (eventually) from > Ada.Containers.Indefinite_Holders.Holder, > > function Constant_Reference > (Container : aliased Holder) return Constant_Reference_Type; > pragma Inline (Constant_Reference); > > Shame it had to be there. > > I've just tried splattering 'aliased' wherever the compiler told me it > was needed; it's now spreading into other packages. Ugh. > > The solution might just be using composition rather than inheritance. In my experience mixing handles with target types does not work anyway regardless accessibility rules mess. I tend to use interfaces instead: type Abstract_Node_Interface is interface ...; Then both the handle and the target type implement Abstract_Node_Interface. The target type goes into hiding, the client need not to see it. This requires manual delegation in all primitive operations of handles: dereference + call. But in the end it pays off. Especially with trees, because in mutator operations I can check the reference count of the node and choose to clone it (and maybe the subtree) if there are multiple external handles to it. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: GCC 11 bug? lawyer needed 2021-05-06 20:02 ` Simon Wright 2021-05-06 20:51 ` Dmitry A. Kazakov @ 2021-05-06 23:59 ` Randy Brukardt 2021-05-08 10:17 ` Simon Wright 1 sibling, 1 reply; 10+ messages in thread From: Randy Brukardt @ 2021-05-06 23:59 UTC (permalink / raw) "Simon Wright" <simon@pushface.org> wrote in message news:lylf8ry6j5.fsf@pushface.org... > "Randy Brukardt" <randy@rrsoftware.com> writes: > >> I agree that the original author of that program should not have used >> "aliased" in the way that they did (they don't need the special >> semantics), >> but we realize that some people would prefer to *explicitly* mark things >> as >> aliased when they are going to take 'Access (and not worry about the type >> of >> the parameter -- after all, it could change). That is, they don't want to >> depend on the implicit behavior of tagged types -- or perhaps they don't >> even know about it. Which leads to the problem that occurs here, as >> "aliased" has slightly different meanings for functions (now just >> composite >> functions) and procedures. > > The original code, from the Alire project, had (I've edited it slightly) > > package Holders > is new Ada.Containers.Indefinite_Holders (Node'Class); > > type Tree is > new Holders.Holder > and ... > > function Root (This : Tree) return Node'Class is > (This.Constant_Reference); > > where that Constant_Reference is inherited (eventually) from > Ada.Containers.Indefinite_Holders.Holder, > > function Constant_Reference > (Container : aliased Holder) return Constant_Reference_Type; > pragma Inline (Constant_Reference); > > Shame it had to be there. Constant_Reference is the case for which these semantics was designed. Hard to avoid it there. ;-) Note that by returning Node'Class rather than an elementary type, you don't get to use the new rule tweak. Since all tagged types are by-reference (not by copy), the "Root" routine has to return the object that it has, which ultimately is part of Tree. So you actually need "aliased" on Root, since you are (ultimately) returning a part of the formal parameter (and which could become dangling if you pass in an object which is too local). > I've just tried splattering 'aliased' wherever the compiler told me it > was needed; it's now spreading into other packages. Ugh. I think you need to make a copy of the return object somewhere; the obvious answer is to replace function Constant_Reference with function Element. Of course, if the return object is large enough, that could be expensive. (That doesn't work if you want to write the node, but the use of Constant_Reference doesn't allow that anyway, so in this case it doesn't matter.) > The solution might just be using composition rather than inheritance. Yeah, or using handles more as Dmitry says. In any case, it seems like some redesign is necessary. Randy. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: GCC 11 bug? lawyer needed 2021-05-06 23:59 ` Randy Brukardt @ 2021-05-08 10:17 ` Simon Wright 0 siblings, 0 replies; 10+ messages in thread From: Simon Wright @ 2021-05-08 10:17 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > I think you need to make a copy of the return object somewhere; the > obvious answer is to replace function Constant_Reference with function > Element. That appears to be a fine workround! Thanks! ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2021-05-08 10:17 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-05-03 16:08 GCC 11 bug? lawyer needed Simon Wright 2021-05-05 3:54 ` Randy Brukardt 2021-05-05 10:01 ` AdaMagica 2021-05-05 16:10 ` AdaMagica 2021-05-06 0:39 ` Randy Brukardt 2021-05-06 13:07 ` AdaMagica 2021-05-06 20:02 ` Simon Wright 2021-05-06 20:51 ` Dmitry A. Kazakov 2021-05-06 23:59 ` Randy Brukardt 2021-05-08 10:17 ` Simon Wright
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox