Fixing MemberPointerTypeLoc.

Hello.

We would like to get rid of the FIXME in MemberPointerTypeLoc so as to
provide appropriate NNSLoc info. As an example of the current problem,
code such as the following:

int S<int[2+3]>::* ptr = 0;

gets printed as follows (note that the array size is computed):

int S<int [5]>::*ptr = 0;

The situation seems to be much like that of ElaboratedTypeLoc, except
for the fact that in ElaboratedType we do have an NestedNameSpecifier,
while in MemberPointerType we have instead

  /// The class of which the pointee is a member. Must ultimately be a
  /// RecordType, but could be a typedef or a template parameter too.
  const Type *Class;

So, what would be the best way to proceed?

Can we _add_ a NNS* to MemberPointerType?

Should we _replace_ the Type* with the NNS* and have the method
getClass() recompute the class type on the fly?

Should we add a TypeSourceInfo* (rather than an NNSLoc) for the class
type to the MemberPointerTypeLoc ?

Enea.

I think this is the best option, since it allows us to represent the source accurately without making MemberPointerType larger. Thanks for working on this!

  - Doug

In theory it was the best options, but to recompute the class type
inside getClass() we definitely need to have the ASTContext, right?

There are 48 callers of getClass() and some call it from contexts where
ASTContext is unreachable.

I'd suggest to choose another solution among:

1) add a NNS* to MemberPointerType
2) add a TypeSourceInfo* for the class type to the MemberPointerTypeLoc
3) other ideas?

Do we?

The nested-name-specifier will have to have, as its last component, a Type*. Isn't that what we want from getClass()?

  - Doug

Basically, we would need to move this code chunk from SemaType.cpp into
the getClass() method of MemberPointerType:

  QualType ClsType = QualType(NNS->getAsType(), 0);

  // Note: if NNS is dependent, then its prefix (if any) is already
  // included in ClsType; this does not hold if ClsNNS is
  // nondependent: in this case (if there is indeed a prefix)
  // ClsType needs to be wrapped into an elaborated type.
  NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
  if (NNSPrefix && !NNS->isDependent())
    ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);

However, this assumes a Context object is available to build the
ElaboratedType.

Enea.

So, it seems like this code is trying to make sure that the nested-name-specifier is already encoded within the class type of the MemberPointerType. If that's the case, why can't we just have TypeLoc information for the class type within MemberPointerTypeLoc?

  - Doug

Hello.

We would like to get rid of the FIXME in MemberPointerTypeLoc so as to
provide appropriate NNSLoc info. As an example of the current problem,
code such as the following:

int S<int[2+3]>::* ptr = 0;

gets printed as follows (note that the array size is computed):

int S<int [5]>::*ptr = 0;

The situation seems to be much like that of ElaboratedTypeLoc, except
for the fact that in ElaboratedType we do have an NestedNameSpecifier,
while in MemberPointerType we have instead

/// The class of which the pointee is a member. Must ultimately be a
/// RecordType, but could be a typedef or a template parameter too.
const Type *Class;

So, what would be the best way to proceed?

Can we _add_ a NNS* to MemberPointerType?

Should we _replace_ the Type* with the NNS* and have the method
getClass() recompute the class type on the fly?

I think this is the best option, since it allows us to represent the source accurately without making MemberPointerType larger. Thanks for working on this!

In theory it was the best options, but to recompute the class type
inside getClass() we definitely need to have the ASTContext, right?

Do we?

The nested-name-specifier will have to have, as its last component, a Type*. Isn't that what we want from getClass()?

  - Doug

Basically, we would need to move this code chunk from SemaType.cpp into
the getClass() method of MemberPointerType:

QualType ClsType = QualType(NNS->getAsType(), 0);

// Note: if NNS is dependent, then its prefix (if any) is already
// included in ClsType; this does not hold if ClsNNS is
// nondependent: in this case (if there is indeed a prefix)
// ClsType needs to be wrapped into an elaborated type.
NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
if (NNSPrefix && !NNS->isDependent())
   ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);

So, it seems like this code is trying to make sure that the
nested-name-specifier is already encoded within the class type of the
MemberPointerType. If that's the case, why can't we just have TypeLoc
information for the class type within MemberPointerTypeLoc?

Sorry, I'm not sure to understand: in what is different this solution from

2) add a TypeSourceInfo* for the class type to the MemberPointerTypeLoc

?

This is what currently is done for TypeOfTypeLoc.

It's.... not different at all. Sorry, I'm distracted by the deluge of bugs :slight_smile:

  - Doug