Visiting anonymous unions

Hi,

I am writing a source-to-source transformation tool and I need a way
to check if function contains at least one anonymous union inside. My
current way is the following:

class AnonymousUnionChecker : public
clang::RecursiveASTVisitor<AnonymousUnionChecker>
{
     bool foundAnonUnion;

public:
    AnonymousUnionChecker() {}

    bool VisitRecordType(RecordType *T)
    {
        RecordDecl *D = T->getDecl();
        if (D->isUnion() && !D->getIdentifier())
        {
            foundAnonUnion = true;
            return false;
        }
        return true;
    }

    bool CanFindInside(clang::Stmt* stmt) // for functions' bodies
    {
        foundAnonUnion = false;
        TraverseStmt(stmt);
        return foundAnonUnion;
    }
};

It works for code like:

void foo()
{
  union { int a; } a;
  a.a = 5;
}

but it doesn't work (VisitRecordType isn't get called) for code like:

void foo()
{
  union { int a; };
  a = 5;
}

My current idea for a workaround is to scan preprocessed function body
token by token and to check if there is a "union" token followed by
whitespaces and "{" token. Does anybody know a better approach,
possibly using clang's visitor functionality?

Thanks,
Sergejs

Is that valid code? clang gives errors with the default options.

Yes, it is valid C++ code. Clang gives errors if you try to process it
with .c extension, with .cpp all is OK on my machine.

You should see a DeclStmt that declares a single VarDecl whose type
is a RecordType whose RecordDecl has the isAnonymousStructOrUnion()
bit set.

John.

I am writing a source-to-source transformation tool and I need a way
to check if function contains at least one anonymous union inside.

You should see a DeclStmt that declares a single VarDecl whose type
is a RecordType whose RecordDecl has the isAnonymousStructOrUnion()
bit set.

I have played around with that a bit - I have not found a RecordDecl
within the FunctionDecl (but I have found a VarDecl) - if you say that
should be there, that might be a problem with RAV...

Cheers,
/Manuel

The VarDecl is flagged as implicit, so to see it in the visitor you
need to override shouldVisitImplicitCode() to return true.

I think John meant that the RecordDecl is only referenced via the
RecordType of the VarDecl. RAV currently doesn't traverse into the
RecordType though (same as in PR13618).

Overriding shouldVisitImplicitCode() does the trick, thanks! However,
it seems that this RAV method appears in trunk and not in clang 3.1,
so I'll wait for 3.2 to come out and meanwhile use my token-by-token
solution.

Thanks,
Sergejs