Creating New Types

Hi all,

I'd like to create new types based on previous types. E.g., if I have two types like this:

  int const * volatile * const * const
  float * volatile * const * volatile * const * const * restrict

I'd like to be able to create these two types from them:

  char const * volatile * const *
  char volatile * const * const *

(This is related to the description of "casting away constness" in the C++ standard [5.2.11p8].)

What's the best way to code this? I'm currently thinking of using the context to get the builtin type "char", and then creating a QualType around that. Then continuing to create QualTypes around that, etc.

When I do this, will the QualType be uniqued? Is there something not good about doing this? Or is there a simpler way of doing this?

Thanks!
-bw

Hi all,
I'd like to create new types based on previous types. E.g., if I have
two types like this:

  int const * volatile * const * const
  float * volatile * const * volatile * const * const * restrict

I'd like to be able to create these two types from them:

  char const * volatile * const *
  char volatile * const * const *

What's the best way to code this? I'm currently thinking of using the
context to get the builtin type "char", and then creating a QualType
around that. Then continuing to create QualTypes around that, etc.

The answer is that you have to recursively build the type from the inside out. To get the first, do something like this:

QualType T = ASTContext.CharTy; // char
T.addConst(); // const char

T = ASTContext.getPointerType(T); // const char *
T.addVolatile(); // const char * volatile
...

When I do this, will the QualType be uniqued? Is there something not
good about doing this? Or is there a simpler way of doing this?

Types are always autouniqued.

(This is related to the description of "casting away constness" in
the C++ standard [5.2.11p8].)

How so? const_cast should never change the underlying type (e.g. from float to char). In fact, my understanding of const cast is that it isn't a "recursive" process, it just looks at the top-level qualifiers and pointer/reference.

-Chris

(This is related to the description of "casting away constness" in
the C++ standard [5.2.11p8].)

How so? const_cast should never change the underlying type (e.g.
from float to char). In fact, my understanding of const cast is that
it isn't a "recursive" process, it just looks at the top-level
qualifiers and pointer/reference.

Actually, const_cast has to *compare* the src and dest type recursively, but I still don't think it has to *reconstruct* a mix of the two.

-Chris

It seemed to say that if one pointer type with N pointers could be
implicitly cast to a "subtype" of another pointer type with M
pointers, where N < M for some type T, then we aren't casting away
constness. That's what I was doing with my example. I was going to use
the implicit cast checking stuff to make sure that this is valid. I
suppose it's possible to compare it recursively, if I can make sure
that the checking is valid for each step.

-bw

I'm not certain I know what you mean, but I don't think that is valid. Can you give me an example C++ function that does this for concreteness?

-Chris

I think that there's a misunderstanding of why I'm doing this. I'm not doing this for the const_cast operator. But it's a check that needs to be performed for all of the other casting operators. For instance, take the reinterpret_cast which can change the underlying type; it's not allowed to cast away constness. So this is allowed:

int * ip;
float ** fpp = reinterpret_cast<float**>(ip);

But this isn't:

int const * ip;
float ** fpp = reinterpret_cast<float**>(ip);
float const ** cfpp = reinterpret_cast<float const **>(ip);

(T const * cannot be implicitly converted to T *.) But this is:

int const * ip;
float * const * fpp = reinterpret_cast<float* const *>(ip);

My understanding is that this is because there's an implicit cast between T const * to T const * (identity), which would be the check that needs to be performed due to [5.2.11p8].

-bw