comp.lang.ada
 help / color / mirror / Atom feed
* Question about circular elaboration order error (GNAT).
@ 2008-04-13 18:12 Peter C. Chapin
  2008-04-13 19:43 ` Samuel Tardieu
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Peter C. Chapin @ 2008-04-13 18:12 UTC (permalink / raw)



I'm using GNAT GPL 2007. Consider the following packages. The 
specifications and bodies are each in their own files, as usual.

----> parent.ads <----

package Parent is
    -- Needed so this package requires/allows a body.
    procedure Dummy;
end Parent;

----> parent-child.ads <----

package Parent.Child is
    procedure Print_Stuff;
end Parent.Child;

----> parent.adb <----

with Parent.Child;
package body Parent is
    procedure Dummy is
    begin
       null;
    end;
begin
    Parent.Child.Print_Stuff;   -- Note: invoking child here.
end Parent;

----> parent-child.adb <----

with Ada.Text_IO;
package body Parent.Child is
    procedure Print_Stuff is
    begin
       Ada.Text_IO.Put_Line("Printing stuff in package Parent.Child");
    end Print_Stuff;
end Parent.Child;

My main procedure just does a "with Parent" but otherwise does nothing 
(it contains only a null statement). Note that the elaboration code in 
package Parent is calling a subprogram in package Parent.Child. With the 
-gnatwl option, GNAT tells me

    warning: implicit pragma Elaborate_All for "Parent.Child" generated

when compiling parent.adb. This does not surprise me and seems fine. 
However, when trying to build the executable I get:

error: elaboration circularity detected
info:    "parent (body)" must be elaborated before "parent (body)"
info:       reason: implicit Elaborate_All in unit "parent (body)"
info:       recompile "parent (body)" with -gnatwl for full details
info:          "parent (body)"
info:             must be elaborated along with its spec:
info:          "parent (spec)"
info:             which is withed by:
info:          "parent.child (spec)"
info:             which is withed by:
info:          "parent (body)"

gnatmake: *** bind failed.

I don't understand where the circularity is coming from. Isn't the 
following elaborate order acceptable:

parent (spec)
parent.child (spec)
parent.child (body)
parent (body)

How is it the case that parent (body) must be elaborated before parent 
(body)? I've tried tinkering around with some explicit elaboration 
related pragmas to control the order of elaboration, but GNAT insists 
there is circularity regardless. I'm left with the impression that all 
my attempts to control the elaboration order are fruitless.

Note my actual program involves a task in the parent that is trying to 
use subprograms in the child. However, the difficulties I'm having 
appear to be unrelated to tasking.

Thanks in advance for any thoughts you might have.

Peter



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-13 18:12 Question about circular elaboration order error (GNAT) Peter C. Chapin
@ 2008-04-13 19:43 ` Samuel Tardieu
  2008-04-13 20:20   ` Robert A Duff
  2008-04-13 19:46 ` Robert A Duff
  2008-04-14 17:33 ` Jeffrey R. Carter
  2 siblings, 1 reply; 12+ messages in thread
From: Samuel Tardieu @ 2008-04-13 19:43 UTC (permalink / raw)


>>>>> "Peter" == Peter C Chapin <pchapin@sover.net> writes:

Peter> I don't understand where the circularity is coming from. Isn't
Peter> the following elaborate order acceptable:

No. pragma Elaborate_All is transitive, and forces the elaboration of
Parent body (since Parent.Child has an implicit dependency on Parent)
before... Parent body elaboration. Hence the circular elaboration
order.

But you can fix the situation by providing GNAT with the necessary
elaboration information:

  - put a "pragma Elaborate (Parent.Child)" in Parent body to indicate
    that Parent elaboration requires Parent.Child to be elaborated; this
    pragma isn't transitive, so you have to ensure that subprograms of
    Parent.Child called during the elaboration of Parent do not
    themselves require that other packages be elaborated first, or add
    the required pragma;

  - put a "pragma Elaborate_Body" in Parent.Child spec if you know
    that this package is likely to be called during the elaboration of
    other packages; this requires that the body be elaborated just
    after the spec.

Using only the "pragma Elaborate_Body" will not be enough for GNAT, so
the "pragma Elaborate" is required. That is because GNAT is
overcautious and adds implicit "pragma Elaborate_All" unless you
provide explicit "pragma Elaborate".

Note that having GNAT be overcautious by default is actually a good
thing: I spent three hours two weeks ago debugging a tricky
elaboration problem in a software written for an embedded system. The
original author incorrectly used "pragma Elaborate". Had he done
nothing, GNAT would have warned him about the dangerous situation.

I hope this clarifies things.

  Sam
-- 
Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-13 18:12 Question about circular elaboration order error (GNAT) Peter C. Chapin
  2008-04-13 19:43 ` Samuel Tardieu
@ 2008-04-13 19:46 ` Robert A Duff
  2008-04-13 22:49   ` Peter C. Chapin
  2008-04-14 17:33 ` Jeffrey R. Carter
  2 siblings, 1 reply; 12+ messages in thread
From: Robert A Duff @ 2008-04-13 19:46 UTC (permalink / raw)


"Peter C. Chapin" <pchapin@sover.net> writes:

> I'm using GNAT GPL 2007. Consider the following packages. The
> specifications and bodies are each in their own files, as usual.
>
> ----> parent.ads <----
>
> package Parent is
>    -- Needed so this package requires/allows a body.
>    procedure Dummy;
> end Parent;
>
> ----> parent-child.ads <----
>
> package Parent.Child is
>    procedure Print_Stuff;
> end Parent.Child;
>
> ----> parent.adb <----
>
> with Parent.Child;
> package body Parent is
>    procedure Dummy is
>    begin
>       null;
>    end;
> begin
>    Parent.Child.Print_Stuff;   -- Note: invoking child here.
> end Parent;
>
> ----> parent-child.adb <----
>
> with Ada.Text_IO;
> package body Parent.Child is
>    procedure Print_Stuff is
>    begin
>       Ada.Text_IO.Put_Line("Printing stuff in package Parent.Child");
>    end Print_Stuff;
> end Parent.Child;
>
> My main procedure just does a "with Parent" but otherwise does nothing
> (it contains only a null statement). Note that the elaboration code in
> package Parent is calling a subprogram in package Parent.Child. With the
> -gnatwl option, GNAT tells me
>
>    warning: implicit pragma Elaborate_All for "Parent.Child" generated

This pragma (on Parent body) means Parent.Child, and it's body, and
everything they depend on, and their bodies, and so on, must all be
elaborated before Parent body.  One of those is Parent body --
hence the cycle.

If you write pragma Elaborate, I think GNAT will not generate the
implicit pragma Elab_All.  Pragma Elaborate(Parent.Child) on Parent body
means elaborate the body of Parent.Child before Parent body, but it's
not transitive.

Note that the default GNAT rules are stricter than standard Ada.
To get the standard Ada rules, use -gnatE.  But it's not a good
idea -- the stricter rules are beneficial.  For your program,
if you use the standard rules, it is implementation dependent
whether or not you get Program_Error.  That's bad language design!

The stricter rules are conservative, and modular -- when compiling
Parent, it sees that you're calling Parent.Child, and assumes the worst
WITHOUT looking at Parent.Child body.  For example, it assumes that
Parent.Child might call Dummy, causing a real cycle.

Pragma Elaborate is somewhat evil, since it breaks this modularity
(it requires one package body to "know" what's in another package
body).

I suggest you read the section in the GNAT docs about elaboration.
It explains all this stuff in great detail.

>... I'm left with the impression that all
> my attempts to control the elaboration order are fruitless.

Well, they're not fruitless, but elab cycles are indeed frustrating.
I find the error messages (from all compilers I've tried, not just
GNAT) to be confusing.  And every time you add or delete one
of those pragmas you have to recompile a whole bunch of stuff.

> Note my actual program involves a task in the parent that is trying to
> use subprograms in the child. However, the difficulties I'm having
> appear to be unrelated to tasking.

Don't be too sure.  Tasks get activated "early", and can easily cause
elab cycles.  Look at the docs for details.

- Bob



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-13 19:43 ` Samuel Tardieu
@ 2008-04-13 20:20   ` Robert A Duff
  2008-04-13 21:20     ` Samuel Tardieu
  0 siblings, 1 reply; 12+ messages in thread
From: Robert A Duff @ 2008-04-13 20:20 UTC (permalink / raw)


Samuel Tardieu <sam@rfc1149.net> writes:

> No. pragma Elaborate_All is transitive, and forces the elaboration of
> Parent body (since Parent.Child has an implicit dependency on Parent)

Yes, it has a dependence.  But why do you call it "implicit"?

- Bob



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-13 20:20   ` Robert A Duff
@ 2008-04-13 21:20     ` Samuel Tardieu
  2008-04-14 20:21       ` Robert A Duff
  0 siblings, 1 reply; 12+ messages in thread
From: Samuel Tardieu @ 2008-04-13 21:20 UTC (permalink / raw)


>>>>> "Robert" == Robert A Duff <bobduff@shell01.TheWorld.com> writes:

Robert> Samuel Tardieu <sam@rfc1149.net> writes:
>> No. pragma Elaborate_All is transitive, and forces the elaboration
>> of Parent body (since Parent.Child has an implicit dependency on
>> Parent)

Robert> Yes, it has a dependence.  But why do you call it "implicit"?

Because it is not spelt explicitely using a with clause or an
Elaborate/Elaborate_All pragma. And if it's not explicit, it must be
implicit.

One could say that when you write "package Parent.Child", you
explicitely spell "Parent" so this is an explicit dependency
declaration. However, for me it is a declaration of the "Parent.Child"
package, which implicitely creates a semantic dependency on Parent.

Now, I think we are both nitpicking here, as I don't think the RM says
anything about "explicit" vs. "implicit" dependencies, it only
consider "static dependences" and "elaboration dependences".

Btw, I never noticed the use of "dependence" vs. "dependency"
before. Is there a difference in English?

  Sam
-- 
Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-13 19:46 ` Robert A Duff
@ 2008-04-13 22:49   ` Peter C. Chapin
  2008-04-14 13:56     ` Robert A Duff
  0 siblings, 1 reply; 12+ messages in thread
From: Peter C. Chapin @ 2008-04-13 22:49 UTC (permalink / raw)


Robert A Duff wrote:

> The stricter rules are conservative, and modular -- when compiling
> Parent, it sees that you're calling Parent.Child, and assumes the worst
> WITHOUT looking at Parent.Child body.  For example, it assumes that
> Parent.Child might call Dummy, causing a real cycle.

Thanks to you and Samuel Tardieu for your replies. They do help to 
clarify things for me somewhat. It is easy for me to understand how 
Parent.Child's body would have an elaboration dependency on Parent's 
spec, but I did not expect Parent.Child's body to necessarily have an 
elaboration dependency on Parent's body. Are you saying that it doesn't 
(necessarily) have such a dependency in standard Ada, but that I'm 
experiencing an example of GNAT's stricter rules?

In any event I got my example to work with an appropriate application of 
pragma Elaborate. I guess I didn't stumble into the right combination in 
my earlier tinkering. It helps to have a better idea of what is 
happening. :-)

> I suggest you read the section in the GNAT docs about elaboration.
> It explains all this stuff in great detail.

Yes, actually I read that stuff, but I didn't see anything in particular 
about elaboration dependencies between parent and child packages.

>> Note my actual program involves a task in the parent that is trying to
>> use subprograms in the child. However, the difficulties I'm having
>> appear to be unrelated to tasking.
> 
> Don't be too sure.  Tasks get activated "early", and can easily cause
> elab cycles.  Look at the docs for details.

I'm not saying that the errors in the tasking example (my real program) 
are wrong. Indeed, I assumed there was some non-trivial stuff going on 
during elaboration that was stimulating the error. I was just glad when 
I could (apparently) reproduce the problem with a simpler example. That 
makes it easier to study, of course.

Peter



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-13 22:49   ` Peter C. Chapin
@ 2008-04-14 13:56     ` Robert A Duff
  0 siblings, 0 replies; 12+ messages in thread
From: Robert A Duff @ 2008-04-14 13:56 UTC (permalink / raw)


"Peter C. Chapin" <pchapin@sover.net> writes:

> Thanks to you and Samuel Tardieu for your replies.

You're welcome.

>...They do help to
> clarify things for me somewhat. It is easy for me to understand how
> Parent.Child's body would have an elaboration dependency on Parent's
> spec, but I did not expect Parent.Child's body to necessarily have an
> elaboration dependency on Parent's body. Are you saying that it doesn't
> (necessarily) have such a dependency in standard Ada, but that I'm
> experiencing an example of GNAT's stricter rules?

Yes.  Your original example (with no pragmas added) is legal, and a
valid Ada compiler (such as GNAT with -gnatE) will compile and link it
just fine.  However, it might fail at run time.  Worst case: it works
fine, but 2 years later, you port it to a new compiler (new machine, or
even a new version of the same compiler), and you get a mysterious
Program_Error.

If you get an elab cycle when you modify your program (e.g., you add a
with_clause), it's easy to deal with -- your change is small, and you
know it caused the cycle.  But if you get a Program_Error when porting a
giant program to a new compiler, it can easily take several hours to
figure out the problem.

- Bob



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-13 18:12 Question about circular elaboration order error (GNAT) Peter C. Chapin
  2008-04-13 19:43 ` Samuel Tardieu
  2008-04-13 19:46 ` Robert A Duff
@ 2008-04-14 17:33 ` Jeffrey R. Carter
  2008-04-14 17:52   ` Robert A Duff
  2 siblings, 1 reply; 12+ messages in thread
From: Jeffrey R. Carter @ 2008-04-14 17:33 UTC (permalink / raw)


Peter C. Chapin wrote:
> 
> package Parent is
>    -- Needed so this package requires/allows a body.
>    procedure Dummy;
> end Parent;

Not related to your question, but perhaps of interest to you: Dummy is not 
needed so the pkg allows a body. Pragma Elaborate_Body is a better way to 
achieve that:

package Parent is
    pragma Elaborate_Body;
end Parent;

-- 
Jeff Carter
"My name is Jim, but most people call me ... Jim."
Blazing Saddles
39



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-14 17:33 ` Jeffrey R. Carter
@ 2008-04-14 17:52   ` Robert A Duff
  0 siblings, 0 replies; 12+ messages in thread
From: Robert A Duff @ 2008-04-14 17:52 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.acm.org> writes:

> Peter C. Chapin wrote:
>> package Parent is
>>    -- Needed so this package requires/allows a body.
>>    procedure Dummy;
>> end Parent;
>
> Not related to your question, but perhaps of interest to you: Dummy is
> not needed so the pkg allows a body. Pragma Elaborate_Body is a better
> way to achieve that:

It's better in many cases, but in this particular case,
it would make the program illegal.  ;-)

> package Parent is
>    pragma Elaborate_Body;
> end Parent;

- Bob



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-13 21:20     ` Samuel Tardieu
@ 2008-04-14 20:21       ` Robert A Duff
  2008-04-14 23:36         ` Adam Beneschan
  0 siblings, 1 reply; 12+ messages in thread
From: Robert A Duff @ 2008-04-14 20:21 UTC (permalink / raw)


Samuel Tardieu <sam@rfc1149.net> writes:

>>>>>> "Robert" == Robert A Duff <bobduff@shell01.TheWorld.com> writes:
>
> Robert> Samuel Tardieu <sam@rfc1149.net> writes:
>>> No. pragma Elaborate_All is transitive, and forces the elaboration
>>> of Parent body (since Parent.Child has an implicit dependency on
>>> Parent)
>
> Robert> Yes, it has a dependence.  But why do you call it "implicit"?
>
> Because it is not spelt explicitely using a with clause or an
> Elaborate/Elaborate_All pragma. And if it's not explicit, it must be
> implicit.

OK.

To me, the primary purpose of a with clause, and the primary purpose of
a parent name, is their effect on visibility.  Both appear explicitly in
the code.  Secondary issues are semantic dependences, compilation
dependences, and elaboration-order dependences.  So I don't see one as
more "implicit" than the other.

The reason I asked is that "implicit" is often a matter of opinion, and
I'm curious about what it means to people in cases like this.  There was
some argument at AdaCore recently about what

    pragma Restrictions (No_Implicit_Heap_Allocations);

means in a certain obscure case.

> One could say that when you write "package Parent.Child", you
> explicitely spell "Parent" so this is an explicit dependency
> declaration.

Yes, one could, and I do.  ;-)

>...However, for me it is a declaration of the "Parent.Child"
> package, which implicitely creates a semantic dependency on Parent.
>
> Now, I think we are both nitpicking here,...

Nitpicking?  Yes, I plead guilty as charged.  ;-)

>... as I don't think the RM says
> anything about "explicit" vs. "implicit" dependencies, it only
> consider "static dependences" and "elaboration dependences".
>
> Btw, I never noticed the use of "dependence" vs. "dependency"
> before. Is there a difference in English?

I don't know.  Most people say "dependency".  But the Ada 83 RM used
"dependence", and we didn't change it for Ada 95 (or 2005),
and I've gotten used to typing that.

Note that the primary author of Ada 83 was a Frenchman.  ;-)

- Bob



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-14 20:21       ` Robert A Duff
@ 2008-04-14 23:36         ` Adam Beneschan
  2008-04-15  7:13           ` Georg Bauhaus
  0 siblings, 1 reply; 12+ messages in thread
From: Adam Beneschan @ 2008-04-14 23:36 UTC (permalink / raw)


On Apr 14, 1:21 pm, Robert A Duff <bobd...@shell01.TheWorld.com>
wrote:

> > Btw, I never noticed the use of "dependence" vs. "dependency"
> > before. Is there a difference in English?
>
> I don't know.  Most people say "dependency".  But the Ada 83 RM used
> "dependence", and we didn't change it for Ada 95 (or 2005),
> and I've gotten used to typing that.

I checked Merriam-Webster Online (www.m-w.com).  The first meaning of
"dependency" is simply a reference to the first meaning of
"dependence".  (The other two meanings of "dependency" aren't close to
being relevant.)  The first meaning of "dependence" is "the quality or
state of being dependent; especially: the quality or state of being
influenced or determined by or subject to another".  I think this is
meaning of "dependence" that applies here (I'm pretty sure the "drug
addiction" meaning does not).

So I'd say that for our purpose, the two words are interchangeable, at
least in American English usage, which is what Merriam-Webster is a
dictionary of.

                                  -- Adam





^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Question about circular elaboration order error (GNAT).
  2008-04-14 23:36         ` Adam Beneschan
@ 2008-04-15  7:13           ` Georg Bauhaus
  0 siblings, 0 replies; 12+ messages in thread
From: Georg Bauhaus @ 2008-04-15  7:13 UTC (permalink / raw)


Adam Beneschan wrote:
> On Apr 14, 1:21 pm, Robert A Duff <bobd...@shell01.TheWorld.com>
> wrote:
> 
>>> Btw, I never noticed the use of "dependence" vs. "dependency"
>>> before. Is there a difference in English?
>> I don't know.  Most people say "dependency".  But the Ada 83 RM used
>> "dependence", and we didn't change it for Ada 95 (or 2005),
>> and I've gotten used to typing that.
> 
> I checked Merriam-Webster Online (www.m-w.com). [...]
> 
> So I'd say that for our purpose, the two words are interchangeable, at
> least in American English usage, which is what Merriam-Webster is a
> dictionary of.

Uhm, there is---or was---a distinction which is of some historical
interest, if not helpful in rediscovering the distinguished meaning
of either word.
Not sure whether everyone will like  Independency Day  8-)

My old 1974/82 (but not my new, 2005) Oxford Advanced Learner's
Dictionary has only this to say about "dependency":

 "country governed or controlled by another."

The newer edition additionally explains that "dependency" now
also refers to a state of unneccessary reliance on the part
of the dependents. Dependency is exemplified in "dependency culture".

The definition of "dependence" includes the word "need".
E.g. A needs the help of X in order to survive. Both "dependence"
and "dependency" are used in place of "addiction", according to OALD.
Otherwise the dictionary seems to agree with M-W online.

I found that
  "concurrence"
and
  "occurrency" ...
had a funny taste when I tried them ;)

Can the widespread use of "dependency" for "dependence" be
attributed to learning words in globalized technical contexts
and not through a study of English? -- I hadn't been
aware of this before to be sure. Thanks for the question.



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2008-04-15  7:13 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-13 18:12 Question about circular elaboration order error (GNAT) Peter C. Chapin
2008-04-13 19:43 ` Samuel Tardieu
2008-04-13 20:20   ` Robert A Duff
2008-04-13 21:20     ` Samuel Tardieu
2008-04-14 20:21       ` Robert A Duff
2008-04-14 23:36         ` Adam Beneschan
2008-04-15  7:13           ` Georg Bauhaus
2008-04-13 19:46 ` Robert A Duff
2008-04-13 22:49   ` Peter C. Chapin
2008-04-14 13:56     ` Robert A Duff
2008-04-14 17:33 ` Jeffrey R. Carter
2008-04-14 17:52   ` Robert A Duff

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox