Tracing Typedef Chain

If I have code like this:

typedef int X;
typedef X Y;
typedef Y Z;

Z i = 0;

I have the QualType for i. getAsString() returns “Z”. getCanonicalType().getAsString() returns “int”.

Is there some way to trace the typedef chain such that I get “Z”, “Y”, “X”, and “int”? Order is not particularly important to me, but it would be nice to get them in that order.

If you call getTypePtr it should give you the “next” type.

I’m struggling to make this work. Could you possibly give me a more complete example?

At what level are you working? Once in llvm IR, you can cast your type to derived type, and then get the element type

Maybe

Type *T = QT.getTypePtr();
TypedefType *TT = cast(T);

TT->getDecl()->dumpColor();

I tried this with:
auto t = type.getTypePtr();
auto tt = dyn_cast(t);
while(tt) {
tt->getDecl()->dumpColor();
auto x = tt->getDecl()->getNameAsString();
tt = dyn_cast(tt->desugar().getTypePtr());
}

It appeared to work fine when the typedef was at global scope, but when I put the typedef in a namespace the first dyn_cast returned nullptr.

I tried this with:
auto t = type.getTypePtr();
auto tt = dyn_cast<TypedefType>(t);
while(tt) {
  tt->getDecl()->dumpColor();
  auto x = tt->getDecl()->getNameAsString();
  tt = dyn_cast<TypedefType>(tt->desugar().getTypePtr());
}

It appeared to work fine when the typedef was at global scope, but when I
put the typedef in a namespace the first dyn_cast returned nullptr.

Right, in that case you will have an ElaboratedType representing the nested
name specifier written in the source, which desugars to the TypedefType.
Clang has a very rich modeling of type sugar, and you should expect to see
things other than TypedefTypes in your walk.

Depending on what you're trying to do, you might want to consider visiting
the type with a RecursiveASTVisitor or repeatedly calling
getSingleStepDesugaredType to walk the desugarings of the type, or changing
your dyn_cast<TypedefType>(x) calls into x.getAs<TypedefType>() (which will
find the minimally-desugared typedef type in the single-step desugaring
sequence for x).

I tried using getSingleStepDesugaredType with this code:
namespace Test
{
   typedef int X;
   typedef X Y;
   typedef Y Z;
}
Test::Z i;

std::vector<std::string> names;
names.push_back(type.getAsString());
while(true)
{
  type = type.getSingleStepDesugaredType(*result.Context);
  names.push_back(type.getAsString());
}

getAsString() on the QualType returned this chain:
Test::Z
Z
Y
X
int

Ideally I would get this:
Test::Z
Test::Y
Test::X
int

How would I use a RecursiveASTVisitor to walk just the type? I can figure
it out for an entire AST.

I tried this with:
auto t = type.getTypePtr();
auto tt = dyn_cast<TypedefType>(t);
while(tt) {
  tt->getDecl()->dumpColor();
  auto x = tt->getDecl()->getNameAsString();
  tt = dyn_cast<TypedefType>(tt->desugar().getTypePtr());
}

It appeared to work fine when the typedef was at global scope, but when
I put the typedef in a namespace the first dyn_cast returned nullptr.

Right, in that case you will have an ElaboratedType representing the
nested name specifier written in the source, which desugars to the
TypedefType. Clang has a very rich modeling of type sugar, and you should
expect to see things other than TypedefTypes in your walk.

Depending on what you're trying to do, you might want to consider
visiting the type with a RecursiveASTVisitor or repeatedly calling
getSingleStepDesugaredType to walk the desugarings of the type, or changing
your dyn_cast<TypedefType>(x) calls into x.getAs<TypedefType>() (which will
find the minimally-desugared typedef type in the single-step desugaring
sequence for x).

I tried using getSingleStepDesugaredType with this code:
namespace Test
{
   typedef int X;
   typedef X Y;
   typedef Y Z;
}
Test::Z i;

std::vector<std::string> names;
names.push_back(type.getAsString());
while(true)
{
  type = type.getSingleStepDesugaredType(*result.Context);
  names.push_back(type.getAsString());
}

getAsString() on the QualType returned this chain:
Test::Z
Z
Y
X
int

Ideally I would get this:
Test::Z
Test::Y
Test::X
int

You could check if each type is a TypedefType, grab its TypedefNameDecl,
and get the corresponding fully-qualified name. Clang's type sugar nodes
track how the type was written, and that's what you're seeing above.

How would I use a RecursiveASTVisitor to walk just the type? I can figure
it out for an entire AST.

The same way, but start the recursion by calling TraverseType instead of
TraverseDecl. Note that this will recursively visit all of the AST "owned"
by that type, which may be more than you want.