* Strange warning message @ 2017-11-27 8:40 reinert 2017-11-27 9:00 ` Jacob Sparre Andersen ` (3 more replies) 0 siblings, 4 replies; 18+ messages in thread From: reinert @ 2017-11-27 8:40 UTC (permalink / raw) Hei there, when I compile the enclosed program with option "-gnatwa" (i.e. "gnatmake -gnatwa test1k.adb", I get the following annoying warning: "warning: useless assignment to "test1", value never referenced" I use debian, updated (gnat-6 6.3.0-18). Do others out there get the same warning when compiling the test program below? Is there a bug to blame in my version of the compiler? Just to relax - or it seems I do something bad? :-) Here is the program: ----------------------------------------------------------------- with Text_IO; procedure test1k is task type test1_t; task body test1_t is begin Text_IO.Put_Line("Hello there!"); end test1_t; test1 : array(1..1) of access test1_t; begin for e of test1 loop e := new test1_t; end loop; -- Commenting out this statement makes the warning disapipear: test1(1) := new test1_t; end test1k; ------------------------------------------------------------------- I here make the array "test1" only to illustrate (it can serve as an ugly trick to get rid of the warning message). reinert https://korsnesbiocomputing.no/ ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 8:40 Strange warning message reinert @ 2017-11-27 9:00 ` Jacob Sparre Andersen 2017-11-27 9:13 ` reinert 2017-11-27 9:01 ` gautier_niouzes ` (2 subsequent siblings) 3 siblings, 1 reply; 18+ messages in thread From: Jacob Sparre Andersen @ 2017-11-27 9:00 UTC (permalink / raw) Reinert <reinkor@gmail.com> writes: > "warning: useless assignment to "test1", value never referenced" Yes. > procedure test1k is [...] > test1 : array(1..1) of access test1_t; > begin > for e of test1 loop > e := new test1_t; > end loop; > > -- Commenting out this statement makes the warning disapipear: > test1 (1) := new test1_t; > end test1k; As the warning says, you don't reference the variable "test1". If that is on purpose and you use GNAT, you can attach the aspect "Unreferenced" to "test1". Greetings, Jacob -- "Being an absolute ruler today was not as simple as people thought. At least, it was not simple if your ambitions included being an absolute ruler tomorrow." ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 9:00 ` Jacob Sparre Andersen @ 2017-11-27 9:13 ` reinert 2017-11-27 9:45 ` Jacob Sparre Andersen 0 siblings, 1 reply; 18+ messages in thread From: reinert @ 2017-11-27 9:13 UTC (permalink / raw) On Monday, November 27, 2017 at 10:00:41 AM UTC+1, Jacob Sparre Andersen wrote: ...snip... > > As the warning says, you don't reference the variable "test1". OK, but still I am confused. The loop (in the program): for e of test1 loop e := new test1_t; end loop; does the same as "test1(1) := new test1_t;" ? I would expect the loop should cause a warning as well? My intention is a start a task when/if I want (using "new test1_t;"). reinert > > If that is on purpose and you use GNAT, you can attach the aspect > "Unreferenced" to "test1". > > Greetings, > > Jacob > -- > "Being an absolute ruler today was not as simple as people > thought. At least, it was not simple if your ambitions > included being an absolute ruler tomorrow." ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 9:13 ` reinert @ 2017-11-27 9:45 ` Jacob Sparre Andersen 2017-11-27 10:43 ` reinert 0 siblings, 1 reply; 18+ messages in thread From: Jacob Sparre Andersen @ 2017-11-27 9:45 UTC (permalink / raw) Reinert <reinkor@gmail.com> writes: > OK, but still I am confused. The loop (in the program): > > for e of test1 loop > e := new test1_t; > end loop; > > does the same as "test1(1) := new test1_t;"? Yes. Both of them only write to "test1". GNAT usually means "reads values from", when it writes "references". Greetings, Jacob -- xsnow | xshovel > /dev/null ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 9:45 ` Jacob Sparre Andersen @ 2017-11-27 10:43 ` reinert 0 siblings, 0 replies; 18+ messages in thread From: reinert @ 2017-11-27 10:43 UTC (permalink / raw) On Monday, November 27, 2017 at 10:45:12 AM UTC+1, Jacob Sparre Andersen wrote: > Reinert <reinkor@gmail.com> writes: > > > OK, but still I am confused. The loop (in the program): > > > > for e of test1 loop > > e := new test1_t; > > end loop; > > > > does the same as "test1(1) := new test1_t;"? > > Yes. Both of them only write to "test1". GNAT usually means "reads > values from", when it writes "references". But then I would expect the same warning (for the loop and "test1(1) := new test1_t;" ? reinert > > Greetings, > > Jacob > -- > xsnow | xshovel > /dev/null ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 8:40 Strange warning message reinert 2017-11-27 9:00 ` Jacob Sparre Andersen @ 2017-11-27 9:01 ` gautier_niouzes 2017-11-27 9:09 ` gautier_niouzes 2017-11-27 10:42 ` Jeffrey R. Carter 2017-11-29 0:43 ` Robert Eachus 3 siblings, 1 reply; 18+ messages in thread From: gautier_niouzes @ 2017-11-27 9:01 UTC (permalink / raw) > when I compile the enclosed program with option "-gnatwa" (i.e. "gnatmake -gnatwa test1k.adb", I get the following annoying warning: > > "warning: useless assignment to "test1", value never referenced" With GNAT GPL 2017 the formulation is a bit "rounder": test1k.adb:20:03: warning: possibly useless assignment to "test1", value might not be referenced Now, *in your example* the warning is justified, since you make a useless assignement :-) . ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 9:01 ` gautier_niouzes @ 2017-11-27 9:09 ` gautier_niouzes 2017-11-27 9:27 ` reinert 0 siblings, 1 reply; 18+ messages in thread From: gautier_niouzes @ 2017-11-27 9:09 UTC (permalink / raw) > Now, *in your example* the warning is justified, since you make a useless assignement :-) . Ooops - didn't see you were starting a task in that case. But you could avoid using a pointer at all with declare local : test1_t; begin null; end; The only case I need an useless assignement is when I call a C function (for its side effects) and don't use the result. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 9:09 ` gautier_niouzes @ 2017-11-27 9:27 ` reinert 0 siblings, 0 replies; 18+ messages in thread From: reinert @ 2017-11-27 9:27 UTC (permalink / raw) On Monday, November 27, 2017 at 10:09:15 AM UTC+1, gautier...@hotmail.com wrote: > > Now, *in your example* the warning is justified, since you make a useless assignement :-) . > > Ooops - didn't see you were starting a task in that case. > But you could avoid using a pointer at all with > > declare > local : test1_t; > begin > null; > end; > > The only case I need an useless assignement is when I call a C function (for its side effects) and don't use the result. As you see for this program (below), the task does not behave like "fire and forget". This was the intention for my use of "test1(1) := new test1_t;". reinert with Text_IO; procedure test1l is task type test1_t; task body test1_t is begin Text_IO.Put_Line("Hello there!"); delay 5.0; end test1_t; begin declare test1 : test1_t; begin null; end; Text_IO.Put_Line(" Here we go "); end test1l; ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 8:40 Strange warning message reinert 2017-11-27 9:00 ` Jacob Sparre Andersen 2017-11-27 9:01 ` gautier_niouzes @ 2017-11-27 10:42 ` Jeffrey R. Carter 2017-11-27 10:47 ` reinert 2017-11-29 0:43 ` Robert Eachus 3 siblings, 1 reply; 18+ messages in thread From: Jeffrey R. Carter @ 2017-11-27 10:42 UTC (permalink / raw) On 11/27/2017 09:40 AM, reinert wrote: > > when I compile the enclosed program with option "-gnatwa" (i.e. "gnatmake -gnatwa test1k.adb", I get the following annoying warning: > > "warning: useless assignment to "test1", value never referenced" In order to produce warnings like this, the compiler has to do some data-flow analysis. The amount of data-flow analysis required by the ARM is zero. So GNAT is making an extra effort to be helpful. That the warning is annoying in this case is the price you pay for it being correct in most others. Clearly GNAT's data-flow analysis is incomplete, or it would also flag the assignment in the loop. Complete data-flow analysis is possible (SPARK does it). but apparently it's hard, and possibly not really compatible with a compiler's main purpose, but even if GNAT did have complete data-flow analysis, you'd still get the warning. I found that even if I change the loop to for I in Test1'range loop Test1 (I) := new Test1_T; end loop; GNAT (7.2) still doesn't flag the assignment in the loop, so it's not just that GNAT's analysis hasn't caught up with the new "for E of" construct. -- Jeff Carter "We burst our pimples at you." Monty Python & the Holy Grail 16 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 10:42 ` Jeffrey R. Carter @ 2017-11-27 10:47 ` reinert 2017-11-27 11:52 ` reinert 0 siblings, 1 reply; 18+ messages in thread From: reinert @ 2017-11-27 10:47 UTC (permalink / raw) On Monday, November 27, 2017 at 11:42:11 AM UTC+1, Jeffrey R. Carter wrote: > On 11/27/2017 09:40 AM, reinert wrote: > > > > when I compile the enclosed program with option "-gnatwa" (i.e. "gnatmake -gnatwa test1k.adb", I get the following annoying warning: > > > > "warning: useless assignment to "test1", value never referenced" > > In order to produce warnings like this, the compiler has to do some data-flow > analysis. The amount of data-flow analysis required by the ARM is zero. So GNAT > is making an extra effort to be helpful. That the warning is annoying in this > case is the price you pay for it being correct in most others. > > Clearly GNAT's data-flow analysis is incomplete, or it would also flag the > assignment in the loop. Complete data-flow analysis is possible (SPARK does it). > but apparently it's hard, and possibly not really compatible with a compiler's > main purpose, but even if GNAT did have complete data-flow analysis, you'd still > get the warning. > > I found that even if I change the loop to > > for I in Test1'range loop > Test1 (I) := new Test1_T; > end loop; > > GNAT (7.2) still doesn't flag the assignment in the loop, so it's not just that > GNAT's analysis hasn't caught up with the new "for E of" construct. > > -- > Jeff Carter > "We burst our pimples at you." > Monty Python & the Holy Grail > 16 This clarifies, reinert ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 10:47 ` reinert @ 2017-11-27 11:52 ` reinert 0 siblings, 0 replies; 18+ messages in thread From: reinert @ 2017-11-27 11:52 UTC (permalink / raw) For the sake of order, I here post an update of the original test program (above). Making an "empty" entry and a reference to it, makes warnings to disappear: with Text_IO; procedure test1m is task type test1_t is entry run1; end test1_t; task body test1_t is begin select accept run1 do null; end run1; Text_IO.Put_Line("Hello there!"); delay 5.0; or terminate; end select; end test1_t; test1 : array(1..1) of access test1_t; begin for e of test1 loop e := new test1_t; e.run1; end loop; test1(1) := new test1_t; test1(1).run1; Text_IO.Put_Line(" Here we go "); end test1m; ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-27 8:40 Strange warning message reinert ` (2 preceding siblings ...) 2017-11-27 10:42 ` Jeffrey R. Carter @ 2017-11-29 0:43 ` Robert Eachus 2017-11-29 10:39 ` reinert 3 siblings, 1 reply; 18+ messages in thread From: Robert Eachus @ 2017-11-29 0:43 UTC (permalink / raw) On Monday, November 27, 2017 at 3:40:41 AM UTC-5, reinert wrote: > Hei there, > > when I compile the enclosed program with option "-gnatwa" (i.e. "gnatmake -gnatwa test1k.adb", I get the following annoying warning: This is not about the warning, but overthinking the problem. ALL tasks that declared at the library level are "fire and forget" from the point of view of the main program, and it is the only sane way to get this behavior. 10.2(25) requires that all such tasks complete (or are waiting at a terminate alternative) for the program (partition) as a whole to complete. Note that it is the parent of the task that matters here, not whether or not it is of a task type. If you need to fire off tasks, but don't know the number of tasks needed until the main program is running, you will need a task type, and an access type both declared in a library package: package Workers is task type Worker; type WA: access Worker; end Workers; You can track the existence of Worker tasks or not. I have a number of programs where the main program figures out how many Workers are needed, spawns them, and sits around waiting so it can print out a timestamp. It is much easier to put all the Workers inside the main program to do this. If you need tasks whose master is the environment task and some global close behavior, that can get messy. But I've never had the problem. Um. I have to explain that. If you need library level tasks, go right ahead. Create a task with two entries, basically a counting semaphore. All the worker tasks call Add in their elaboration code, and Remove just before completing. Now it the body of that task, you have a place for your last wishes. Why is this sometimes needed? If you have a distributed program across hundreds of nodes, you end up with a two or three level tree to create all the per node worker tasks. The main program may complete hours before the worker tasks, and in fact, before all the worker tasks are created... ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-29 0:43 ` Robert Eachus @ 2017-11-29 10:39 ` reinert 2017-11-29 20:47 ` Randy Brukardt 2017-12-01 22:53 ` Robert Eachus 0 siblings, 2 replies; 18+ messages in thread From: reinert @ 2017-11-29 10:39 UTC (permalink / raw) Sorry for showing a bit confusion here, but could you indicate in few words what is a "task declared at the library level" ? A task declared i package "above" the main program? I refer i John Barnes: "Programming in Ada 2012" at the top of page 531 (about tasks created through access types): "Furthermore, such tasks are not dependent upon the unit where they are created but are dependent upon the block, subprogram body or task body containing the declaration of the access type itself". Then it is "fire and forget" ? I may approach better understanding now. Hopefully :-) reinert On Wednesday, November 29, 2017 at 1:44:14 AM UTC+1, Robert Eachus wrote: > On Monday, November 27, 2017 at 3:40:41 AM UTC-5, reinert wrote: > > Hei there, > > > > when I compile the enclosed program with option "-gnatwa" (i.e. "gnatmake -gnatwa test1k.adb", I get the following annoying warning: > > This is not about the warning, but overthinking the problem. ALL tasks that declared at the library level are "fire and forget" from the point of view of the main program, and it is the only sane way to get this behavior. 10.2(25) requires that all such tasks complete (or are waiting at a terminate alternative) for the program (partition) as a whole to complete. > > Note that it is the parent of the task that matters here, not whether or not it is of a task type. If you need to fire off tasks, but don't know the number of tasks needed until the main program is running, you will need a task type, and an access type both declared in a library package: > > package Workers is > task type Worker; > type WA: access Worker; > end Workers; > > You can track the existence of Worker tasks or not. I have a number of programs where the main program figures out how many Workers are needed, spawns them, and sits around waiting so it can print out a timestamp. It is much easier to put all the Workers inside the main program to do this. If you need tasks whose master is the environment task and some global close behavior, that can get messy. But I've never had the problem. > > Um. I have to explain that. If you need library level tasks, go right ahead. Create a task with two entries, basically a counting semaphore. All the worker tasks call Add in their elaboration code, and Remove just before completing. Now it the body of that task, you have a place for your last wishes. Why is this sometimes needed? If you have a distributed program across hundreds of nodes, you end up with a two or three level tree to create all the per node worker tasks. The main program may complete hours before the worker tasks, and in fact, before all the worker tasks are created... ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-29 10:39 ` reinert @ 2017-11-29 20:47 ` Randy Brukardt 2017-11-30 14:11 ` reinert 2017-12-01 22:53 ` Robert Eachus 1 sibling, 1 reply; 18+ messages in thread From: Randy Brukardt @ 2017-11-29 20:47 UTC (permalink / raw) "reinert" <reinkor@gmail.com> wrote in message news:51a6bff7-ca9f-44d8-a00b-9068727fb104@googlegroups.com... >Sorry for showing a bit confusion here, but could you indicate in few words >what is a "task declared at the library level" ? A task declared i package >"above" the main program? Library-level is the place where top-level compilation units exist. For instance, Ada.Text_IO is at library-level. Your own separately compiled packages also exist there. "Library-level" is sometimes called "global", as it belongs to the progam as a whole, and isn't scoped like things declared in subprograms or tasks are. Hope this helps. Randy. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-29 20:47 ` Randy Brukardt @ 2017-11-30 14:11 ` reinert 0 siblings, 0 replies; 18+ messages in thread From: reinert @ 2017-11-30 14:11 UTC (permalink / raw) It helped, reinert ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-11-29 10:39 ` reinert 2017-11-29 20:47 ` Randy Brukardt @ 2017-12-01 22:53 ` Robert Eachus 2017-12-02 8:47 ` Simon Wright 1 sibling, 1 reply; 18+ messages in thread From: Robert Eachus @ 2017-12-01 22:53 UTC (permalink / raw) On Wednesday, November 29, 2017 at 5:39:39 AM UTC-5, reinert wrote: > Sorry for showing a bit confusion here, but could you indicate in few words what is a "task declared at the library level" ? A task declared i package "above" the main program? Hmm. Library level is shorthand for a unit declared as a library unit, or directly within a package that is a library unit. Of course, you can have library units, like Ada.Text_IO.Open is a library level unit, even though it is nested in two packages. In general you want as much of your program declarations to be either within the current unit, within the main program or at the library level. This way the linker or loader has a static address for the variable, subroutine, or whatever, rather than run-time code needing to go through a display or a stack walk to find the right instance. Of course, if you use recursion, you want to have many versions of a named object on the stack. ;-) Note that generic instantiations can be at the library level. Generic units even if declared at the library level do not make their contents library level declarations. Instantiating a generic at the library level can do that. For tasks, we have this additional constraint. You can't leave the scope in which a task is declared because the task can still access those objects. So functions, procedures, tasks and even packages can need to wait for all the tasks declared locally to be completed (or waiting at a terminate alternative). Again declaring library level tasks, if you don't need this complex behavior, eliminates run-time code to make it work. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-12-01 22:53 ` Robert Eachus @ 2017-12-02 8:47 ` Simon Wright 2017-12-02 9:47 ` Niklas Holsti 0 siblings, 1 reply; 18+ messages in thread From: Simon Wright @ 2017-12-02 8:47 UTC (permalink / raw) Robert Eachus <rieachus@comcast.net> writes: > For tasks, we have this additional constraint. You can't leave the > scope in which a task is declared because the task can still access > those objects. So functions, procedures, tasks and even packages can > need to wait for all the tasks declared locally to be completed (or > waiting at a terminate alternative). Again declaring library level > tasks, if you don't need this complex behavior, eliminates run-time > code to make it work. In my experience, when GNAT (with the default static elaboration) has been unable to find a valid elaboration order, it's almost always been because of library-level tasks; the binder can't tell whether the task (which starts executing on completion of its package's elaboration) actually makes any calls to with'd packages at that point, so assumes the worst. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Strange warning message 2017-12-02 8:47 ` Simon Wright @ 2017-12-02 9:47 ` Niklas Holsti 0 siblings, 0 replies; 18+ messages in thread From: Niklas Holsti @ 2017-12-02 9:47 UTC (permalink / raw) On 17-12-02 10:47 , Simon Wright wrote: > Robert Eachus <rieachus@comcast.net> writes: > >> For tasks, we have this additional constraint. You can't leave the >> scope in which a task is declared because the task can still access >> those objects. So functions, procedures, tasks and even packages can >> need to wait for all the tasks declared locally to be completed (or >> waiting at a terminate alternative). Again declaring library level >> tasks, if you don't need this complex behavior, eliminates run-time >> code to make it work. > > In my experience, when GNAT (with the default static elaboration) has > been unable to find a valid elaboration order, it's almost always been > because of library-level tasks; the binder can't tell whether the task > (which starts executing on completion of its package's elaboration) > actually makes any calls to with'd packages at that point, so assumes > the worst. That is also my experience, and I therefore isolate library-level tasks in their own packages which do _not_ provide any public operations. For example, if a subsystem is implemented by the data and operations in package Foo, but also needs a library-level task, I put the task in a child package, Foo.Tasks, which provides nothing else (so a pragma Elaborate_Body is usually needed in the declaration of Foo.Tasks). Only the main subprogram has context clauses "with Xxx.Tasks". No other package refers to the Xxx.Tasks packages. GNAT can then put all the Xxx.Tasks packages at the end of the elaboration order (before the main subprogram) and they cause no elaboration circularities. Another benefit of this separation is that it becomes easy to select the (sub)set of tasks that are included in the program. For example, unit testing of package Foo can be performed in a sequential way by not including Foo.Tasks in the unit-testing program. Another approach to the elaboration problem is to use pragma Partition_Elaboration_Policy (Sequential) to delay the activation of library-level tasks until the end of the library elaboration. I haven't tried that yet. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2017-12-02 9:47 UTC | newest] Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-11-27 8:40 Strange warning message reinert 2017-11-27 9:00 ` Jacob Sparre Andersen 2017-11-27 9:13 ` reinert 2017-11-27 9:45 ` Jacob Sparre Andersen 2017-11-27 10:43 ` reinert 2017-11-27 9:01 ` gautier_niouzes 2017-11-27 9:09 ` gautier_niouzes 2017-11-27 9:27 ` reinert 2017-11-27 10:42 ` Jeffrey R. Carter 2017-11-27 10:47 ` reinert 2017-11-27 11:52 ` reinert 2017-11-29 0:43 ` Robert Eachus 2017-11-29 10:39 ` reinert 2017-11-29 20:47 ` Randy Brukardt 2017-11-30 14:11 ` reinert 2017-12-01 22:53 ` Robert Eachus 2017-12-02 8:47 ` Simon Wright 2017-12-02 9:47 ` Niklas Holsti
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox