(no subject)

I’d like to record all typedef references, but weed out the old style C tag typedefs like these:

typedef struct foo
{
unsigned char m;
unsigned char n;
} foo;

I’d done that with the following ugly code using string compares:

// Find typedefs:
bool VisitTypedefDecl( TypedefDecl * t )
{
const QualType & q = t->getUnderlyingType() ;

const Type * tt = q.getTypePtr() ;
string theUnderlyingType = q.getAsString( ) ;
string typeDefinitionName = t->getName().str() ;
string * pName = NULL ;

if ( tt->isStructureType() && (("struct " + typeDefinitionName) == theUnderlyingType ) )
{
pName = &typeDefinitionName ;
}
else if ( tt->isClassType() && (("class " + typeDefinitionName) == theUnderlyingType ) )
{
pName = &typeDefinitionName ;
}
else if ( tt->isUnionType() && (("union " + typeDefinitionName) == theUnderlyingType ) )
{
pName = &typeDefinitionName ;
}
else
{
insertIntoMap( typeDefinitionName, q, pName ) ;
}

return true ;
}

This does two things:

  1. effectively strips off the ‘struct’, ‘union’, ‘class’ from theUnderlyingType.
  2. uses ugly string comparisions to see if we have ‘typedef {struct|class|union} NNN NNN’.

Are there cleaner ways to do each of the above tasks?

For the first, you can use something like
T->castAs<RecordType>()->getDecl()->getName() to grab the name of a
struct/class/union, as opposed to pretty-printing the type and doing
string manipulation on the result. Might want to be careful that you
don't unintentionally strip qualifiers or anything like that.

For the second, you're fundamentally stuck with a string comparison:
there isn't any other way to distinguish "typedef struct X {} X;" or
"typedef struct Y {} X;". I mean, you could compare IdentifierInfo*s
instead, but that's basically the same thing.

-Eli

With the following input:

typedef struct foo
{
   unsigned char m;
   unsigned char n;
} foo;

typedef struct Foo
{
   unsigned char m;
   unsigned char n;
} bar;

typedef Foo moo ;

and this AST visitor fragment:

   bool VisitTypedefDecl( TypedefDecl * dtDecl )
   {
      const QualType & qtUnderLying = dtDecl->getUnderlyingType() ;
      const Type * tUnderlying = qtUnderLying.getTypePtr() ;
      string theUnderlyingType = qtUnderLying.getAsString( ) ;
      string typeDefinitionName = dtDecl->getName().str() ;
      string * pName = NULL ;
      bool ignore = false ;

      if ( const RecordType * r = dyn_cast<RecordType>( tUnderlying ) )
      {
cout << "RecordType: " << typeDefinitionName << ","<< theUnderlyingType <<
":" << r->getDecl()->getName().str() << endl ;

That RecordType cast is only successful for the moo typedef, giving:

RecordType: moo,struct Foo:Foo

What sort of type would tUnderLying be for the bar and foo typedefs?

In C++, ‘struct foo’ is an ElaboratedType, and RecordType is only used
directly for types like ‘foo’.

If you really want to look at the type as spelled, you should also look through
ParenTypes, which I believes you’ll get in cases like this:
typedef struct Foo (foo);

John.