C++ Logo

std-proposals

Advanced search

Re: [std-proposals] about incrementing a pointer of a type with pure virtual function

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Fri, 20 Jan 2023 17:57:58 +0000
I meant this to be sent to the list as well.

On 20 January 2023 17:45:26 GMT, "Lénárd Szolnoki" <cpp_at_[hidden]> wrote:
>Hi,
>
>On 20 January 2023 17:35:30 GMT, Edward Catmur <ecatmur_at_[hidden]> wrote:
>>On Fri, 20 Jan 2023 at 08:21, Lénárd Szolnoki via Std-Proposals <
>>std-proposals_at_[hidden]> wrote:
>>
>>>
>>>
>>> On 20 January 2023 07:32:56 GMT, Bo Persson via Std-Proposals <
>>> std-proposals_at_[hidden]> wrote:
>>> >On 2023-01-20 at 07:55, Julien Allali via Std-Proposals wrote:
>>> >> Hi everyone,
>>> >>
>>> >> I checked the following code from one of my student:
>>> >>
>>> >> class I{
>>> >> public:
>>> >> virtual ~I(){}
>>> >> virtual void print(){
>>> >> printf("hello %p\n",this);
>>> >> }
>>> >> virtual void f()=0;
>>> >> };
>>> >>
>>> >> class B : public virtual I{
>>> >> int i,j;
>>> >> public:
>>> >> ~B(){}
>>> >> virtual void f(){
>>> >> printf("B %p\n",this);
>>> >> }
>>> >> };
>>> >>
>>> >>
>>> >> void f(I *i){
>>> >> for(int j=0;j<5;++j)
>>> >> {
>>> >> i->print();
>>> >> i->f();
>>> >> printf("i=%p ",i);
>>> >> i++; // PROBLEM IS HERE
>>> >> printf(" => %p \n",i);
>>> >> }
>>> >> }
>>> >>
>>> >> int main(){
>>> >> B b[]={B(),B()};
>>> >> printf("B: %p %p\n",b,b+1);
>>> >> f(b);
>>> >> }
>>> >>
>>> >> As you can see, I is a non instantiable type as it has one pure virtual
>>> method. My concern is about the line "i++": I believed it will lead to an
>>> error or at least a warning (g++ 11.3.0)... Indeed, I can not imagine a
>>> valid case where doing arithmetic on a pointer of a type with pure virtual
>>> function can be valid.... Shouldn't the standard forbid such arithmetic?
>>> >>
>>> >
>>> >Incrementing a pointer to a single element creates a one-past-the-end
>>> pointer for the type. That is ok to *have*, but of course you cannot
>>> dereference it.
>>> >
>>> >
>>> >
>>>
>>> Why do even abstract base classes have a well-formed sizeof?
>>>
>>> https://www.eel.is/c++draft/expr.sizeof#1.sentence-1
>>>
>>> "The sizeof operator yields the number of bytes occupied by a
>>> non-potentially-overlapping object of the type of its operand."
>>>
>>> An abstract base class can never be non-overlapping, so the value has no
>>> meaning.
>>>
>>> If an abstract base did not have well-formed sizeof, then not having
>>> well-formed pointer arithmetic would also be consistent with this.
>>>
>>
>>Great point; I think it'd be worth exploring.
>>
>>More directly, it may not be possible to form a type array of abstract
>>class type - well, clang, MSVC and EDG disallow it, whereas gcc allows it -
>>I can't work out where if anywhere this is specified?
>
>AFAIK there were recent changes to this area. In short it was not desirable for S[] to be well-formed for incomplete S, but ill-formed for complete abstract S. Banning pointer arithmetic does not have the same problem,

https://wg21.link/P0929

>>If it is not possible to form the type array of abstract class type, then
>>[expr.add]/4.2 is excluded, and pointer arithmetic on an abstract class
>>type pointer has undefined behavior already (and is readily diagnosable).
>>
>>I wonder whether there are any compiler modes / static analysis tools that
>>check for this already (sizeof or pointer arithmetic on abstract types)?

Received on 2023-01-20 17:58:03