GabrielDosReis / ipr

Compiler-neutral Internal Program Representation for C++
BSD 3-Clause "New" or "Revised" License
222 stars 23 forks source link

How to represent array new? #154

Closed Xazax-hun closed 3 years ago

Xazax-hun commented 3 years ago

How should the IPR representation look for the code below:

int f();

void g() {
    int *a = new int[f()]{1, 2, 3, 4};
}

New node will have a Construction as its child, and Construction will have an expression list of 1, 2, 3, 4 as its argument. The type created is int[]. But where can I put the f() which determines the size of the allocated array?

Putting it in the type like int[f()] does not feel right to me. What would a type like that represent? How can I check if two types are the same? And the meaning of the type would depend on the context (since f() might not be a pure function). Moreover, the size expression might refer to local variables that cannot be resolved elsewhere. So the type would only have a meaning in a really local scope, the scope of the expression.

GabrielDosReis commented 3 years ago

Putting it in the type like int[f()] does not feel right to me.

Actually, that is exactly where you're expected to put it.

What is not right about it?

How can I check if two types are the same?

you don't at compile time, and the reason for that has nothing to do with IPR. It is a runtime value.

So the type would only have a meaning in a really local scope, the scope of the expression.

Yes.

Xazax-hun commented 3 years ago

What is not right about it?

I cannot think of any other type in C++ that has its meaning tied to an expression (with potential side effects). int[f()] is not a C++ type, the standard says nothing about its behavior, conversions (while I know IPR is not C++, IPR semantics is not documented anywhere). Moreover, it feels error prone as any user referring to this type in a different context will shoot themselves in the foot. If the only purpose of this type is to hold the size expression what is the advantage of having it in the type instead of having it as a subexpression (of new)?

For subexpressions, it is natural to have no meaning in other contexts and we don't need to introduce/assume semantics that is not documented anywhere.

I will close this for now as this is not a blocking anything and one could argue that this topic comes down to preference/taste.

GabrielDosReis commented 3 years ago

cannot think of any other type in C++ that has its meaning tied to an expression (with potential side effects).

  1. While precedents are good, lack of precedents is not a good reason to reject an idea though
  2. IPR types aren't restricted to be exactly standard C++ types
  3. In the dynamic semantics, the type of the object is still an array type. The side effect is computed as part of the overall new expression, but it is OK to represent the static semantics that way. It just means care needs to be exercised during unification.

If the only purpose of this type is to hold the size expression what is the advantage of having it in the type instead of having it as a subexpression (of new)?

The type of the object is an array type, the bound given by that expression. That expression is part of the type, which is represented.

In general, we have develop comfort with dealing with types that are beyond what the ISO C++ standards spec can express in its impoverished specification language.