comp.lang.ada
 help / color / mirror / Atom feed
* 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  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: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: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  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  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  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 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