printing name of owning anonymous structure in RecursiveASTVisitor::VisitFieldDecl?

With an AST field visitor of the following form:

bool VisitFieldDecl( FieldDecl * f )
{
RecordDecl * r = f->getParent() ;

TypeSourceInfo * t = f->getTypeSourceInfo() ;

TypeLoc TL = t->getTypeLoc() ;

if ( const ArrayTypeLoc *Arr = dyn_cast(&TL) )

{
TL = Arr->getElementLoc() ;
}

const QualType & q = TL.getType() ;

cout
<< r->getName().str()
<< " : " << q.getAsString() << endl ;

return true ;
}

I get a printout of

: type-dependence. Example:

struct Test
{
int a, b ;
} ;

gives:

Test : int
Test : int

For anonymous structs like:

struct TestA
{
struct {
int a, b ;
} m ;
} ;

I do get a “name” for the dependent type m:

TestA : struct

However, when the AST visitor is called for the a, b fields in this anonymous struct, my r->getName().str() call returns an empty string.

I’m guessing I could get the “name” above, if I could get the QualType from the ‘RecordDecl * r’ variable, but am unsure how to do so, because getTypeSourceInfo() doesn’t appear to be available to a RecordDecl object. How can I get the RecordDecl’s QualType?

You can try this:
const Type *RT = r->getTypeForDecl();
QualType QT = RT->getCanonicalTypeInternal();

- Yang

Thanks Yang,

That works nicely.

However, any idea why this test attempt doesn’t correctly identify the anonymous nature of the type:

string s ;
if ( r->isAnonymousStructOrUnion() )
{

const Type * RT = r->getTypeForDecl() ;
QualType QT = RT->getCanonicalTypeInternal() ;

s = QT.getAsString() ;
}

else
{
s = r->getName().str() ;
}

I can work around this by using the following instead:

string s = r->getName().str() ;

if ( “” == s )

// else removed.

but it seems like an odd thing to do (try to format the object as a string to test an attribute).

Peeter

Peeter Joot wrote:

Thanks Yang,

That works nicely.

However, any idea why this test attempt doesn't correctly identify the anonymous nature of the type:

      string s ;
      if ( r->isAnonymousStructOrUnion() )
      {
         const Type * RT = r->getTypeForDecl() ;
         QualType QT = RT->getCanonicalTypeInternal() ;

         s = QT.getAsString() ;
      }
      else
      {
          s = r->getName().str() ;
      }

I can work around this by using the following instead:

      string s = r->getName().str() ;
      if ( "" == s )
      // else removed.

but it seems like an odd thing to do (try to format the object as a string to test an attribute).

Peeter

I am sorry I don't know the reason. Maybe others have better ideas on it.

- Yang

Your testcase does not contain an "anonymous union" as defined by C++
[class.union].

-Eli

That's not the right way. getTypeForDecl is a cache, and
getCanonicalTypeInternal is internal. Use ASTContext::getRecordType.

Richard Smith wrote: