Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  <2017 Index 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  <2017
<== Date ==> <== Thread ==>

Subject: Re: const-constraints on struct rset method arguments
From: Benjamin Franksen <benjamin.franksen@helmholtz-berlin.de>
To: "Mooney, Tim M." <mooney@aps.anl.gov>, EPICS Core-Talk <core-talk@aps.anl.gov>
Date: Fri, 3 Mar 2017 18:08:06 +0100
On 02.03.2017 23:16, Mooney, Tim M. wrote:
> Andrew invited us to weigh in on this thread.  I'm all in favor of
> type checking RSET function-pointer arguments. I don't mind warnings
> if I specify arguments of type "DBADDR*" instead of "const DBADDR*",

Unfortunately, with C++ this is an error (and also if you swap const and
non-const).

> but I feel this const business is less beneficial than type checking.

In general I disagree, but in this case: yes, it really gets in the way
(and that is because it is logically inconsistent when it comes to
passing functions with const parameters).

I think the path of least resistance is this:

We make (only) those method parameters const which are called with const
arguments in base. These are:

    long (*get_precision)(const struct dbAddr *paddr, long *precision);
    long (*get_enum_str)(const struct dbAddr *paddr, char *pbuffer);
    long (*get_enum_strs)(const struct dbAddr *paddr, struct
dbr_enumStrs *p);
    long (*put_enum_str)(const struct dbAddr *paddr, const char *pbuffer);

If we go ahead with this, it means you would probably have to weaken
some of the rset methods e.g. for the motor record.

> (Also, I still have a bunch of arguments specified as "struct dbAddr
> *".)

Note that some of the record support methods are /meant/ to (be able to)
modify the DBADDR, e.g. cvt_dbaddr and since 3.15 also get_array_info.

> I guess the bottom line for me is that I don't mind changes that
> require even a fair amount of editing if there is a syntax that at
> least works for several versions of base.>

You can take a look at my fork of the motor support ()to get an idea of
how e.g. motorRecord.cc can be changed to be compatible with old and new
versions of base. I will update it to reflect the latest changes I made
to the typed-recsup branch of base.

Cheers
Ben

> From: Ben Franksen [benjamin.franksen@helmholtz-berlin.de]
> Subject: const-constraints on struct rset method arguments
> 
> Background: Since ancient times, support interfaces like 'struct rset'
> declare the methods (function pointers) in tables as e.g. RECSUPFUN
> which is a synonym for 'long (*) ()', which in C means 'any number and
> type of arguments'. This is true of record, device, and driver support,
> but for practical reasons I want to limit the discussion to record
> support. A recently discovered bug in base would have been found years
> ago if the interface would not disable type checking here.
> 
> I have been working on a way to get us typed record support methods, for
> base 3.16, taking compatibility questions (forward and backward) into
> account.
> 
> This brought up the question of how to handle the const-ness of the
> DBADDR* argument that many record support methods take. The code in base
> that calls record support does call some of the methods with a const
> DBADDR*. This will result in warnings when the type of the method
> doesn't have the const, when compiled with gcc. However, when the code
> is compiled with g++, as is the case for the motorRecord, then this is
> an error (and, AFAIK, this is how the standard defines things, a few
> remarks on that below).
> 
> Michael, who reviews my changes, commented:
> 
>> Well, one non-const situation (I'm to thank/blame) is
>> get_array_info() which in >=3.15 is allowed to replace pfield. The
>> caller is expected to save and replace it (see dbGet()). This enables
>> a driver to use multiple buffers to avoid copying data into the
>> record.
> 
> So we have to make a decision: do we want to specify const-ness of the
> DBADDR parameter or is this too restricting w.r.t. future extensions? If
> yes, for which methods?
> 
>   * * *
> 
> Side remark re C++ type checking of const: I think what the C++ compiler
> does here (whether by following the standard or for other reasons) is
> logically wrong: if I have a function
> 
>    void f(const int *p)
> 
> it is allowed to pass a non-const 'int*' (no warning) and for a good
> reason. But I get a type error when I assign the address of f to a
> pointer pf of type
> 
>    void (*pf)(int *p)
> 
> That doesn't make sense. Code that calls *pf must assume that the
> function /can/ modify the int behind the pointer; if the function
> refrains form doing so and states that in its type, what's wrong about that?
> 
> In short: const-checking does not take variance into account, and thus
> issues an error even if the conversion would be safe. This is one of the
> problems of prescribing const arguments in function tables.

Attachment: signature.asc
Description: OpenPGP digital signature


References:
const-constraints on struct rset method arguments Ben Franksen
RE: const-constraints on struct rset method arguments Mooney, Tim M.

Navigate by Date:
Prev: RE: const-constraints on struct rset method arguments Mooney, Tim M.
Next: Jenkins build became unstable: epics-base-3.14-win32s #180 APS Jenkins
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  <2017
Navigate by Thread:
Prev: RE: const-constraints on struct rset method arguments Mooney, Tim M.
Next: RE: const-constraints on struct rset method arguments Ron Sluiter
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  <2017
ANJ, 06 Mar 2017 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·