On Sat, 21 Jan 2023, 12:25 language.lawyer--- via Std-Proposals, <std-proposals@lists.isocpp.org> wrote:
On 20/01/2023 12:42, Jens Maurer via Std-Proposals wrote:
> On 20/01/2023 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?
>
> Why is the code iterating over 5 elements of a two-element array to
> start with?
>
> Anyway, the "i++" is undefined behavior per [expr.add] p6:
>
>> For addition or subtraction, if the expressions P or Q have type “pointer to cv T”,
>> where T and the array element type are not similar (7.3.6), the behavior is undefined.

In f(b), first we get array-to-pointer conversion to get a pointer to the first array element, and then conversion to pointer to its I base class subobject, so the pointer type and the object it points to are aligned. Which means there is no UB per [expr.add]/6.

"similar" isn't specified in terms of alignment.