C++ Logo

sg12

Advanced search

Re: [ub] Draft 2 of Enhanced C/C++ memory and object model

From: Jens Maurer <Jens.Maurer_at_[hidden]>
Date: Wed, 27 Mar 2019 15:49:59 +0100
On 27/03/2019 11.07, Niall Douglas wrote:
>> "associated contractual precondition"
>>
>> Contracts are defined for functions, not for built-in operations.
>> If you want to extend the concept, it might be better to
>> avoid the word "contract" and "precondition" and just
>> state the conditions and the effects when violated.
>
> You are right that I shortcutted explanation, but in essence I would see
> that provenance checking would be implemented very similarly to contract
> checking i.e. optional runtime checking.
>
> I will add a clarifying footnote.

Then you should not claim to present normative wording in this section.
A footnote is definitely not sufficient here.

>> 4.6.1
>> "non-void, non-null, non-function pointer object"
>>
>> This mixes value with type and has a lot of "non".
>> Also, is this intended to cover only pointer objects
>> (i.e. pointers that are materialized somewhere in memory)
>> or also pointer values (which might live in a register)?
>> I think this wants to talk about both.
>
> I wasn't aware there is a difference between pointer objects and pointer
> values. I had assumed (I am guessing incorrectly) that pointer objects
> are trivially copyable and thus can be stored in registers.

An object has storage associated with it, a value not so.

Example:

void * f()
{
  int a[5];
  *(a+1+2) = 2;
}

The abstract machine description says we compute the
pointer value "a+1", but there is no object for that,
it's just a value. (And yes, the implementation is
free to create an object for that, or not.)

Claiming in normative text that something applies to an object
(only) ignores those non-object values. So, saying "value"
is better (because objects have values, too).

>> Suggestion: "non-null pointer to object"
>
> I was trying to avoid using that phrase :). I am hoping to leave open
> the door to Modules, and functions, becoming objects in the future.

This is seriously shocking to me. An object lives in a region of
storage, and functions live in a different universe, unrelated to
the storage for objects. Even more so for modules: They are a
compile-time concept (as currently described) and thus don't appear
at runtime at all.

> Equally, if it's a problem to consider that right now, it can be axed.

Is a specific move to make functions be objects part of this paper
or not? If not, please don't confuse the audience.

>> Where did "safely-derived pointer value" go? The section
>> was replaced entirely, it seems.
>
> It was for this draft. This is because I do not fully understand how
> P1434 could work in practice. I have received further notes from its
> authors, and will try to do better in a future draft.

Ok. Maybe not showing core wording changes, but having
more explanatory prose would help here?

>> "The following operations involving two non-void, non-null pointers shall fail to compile with a
>> diagnostic:
>> Comparisons, including equality and inequality, of two pointers without common provenance
>> (user should convert to void* beforehand)."
>>
>> It seems "provenance" of a pointer is a runtime property, so how can
>> that cause a compile-time diagnostic?
>
> Under P1434, provenance is wholly a runtime property.
>
> Under my proposal, I have rather fudged the situation by envisaging a
> mixed runtime and compile-time checked property. If the compiler can
> statically prove that provenance can never be common, it must error out.
> At least, this is what I was trying to state.
>
> Here's an example:
>
> T a[5], b[5];
> if(a == b) ...
>
> Right now the compiler can at compile time infer this condition must
> always be false. Under my proposal, it would fail to compile. Under
> P1434, it would fail during execution.

You need to normatively delineate under which circumstances
an implementation is required to give an error.
"can statically prove" is a wide area: Some implementations might
not be able to prove anything at all (they don't have an optimizer,
for example), some implementations may be able to do more.

If you want to give implementations the liberty to issue a
compile-time diagnostic, yet prescribe certain run-time behavior,
you don't have to do anything normatively: Implementations can
issue as many diagnostics as they want (e.g. warnings).

Jens

Received on 2019-03-27 15:50:02