llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.59k stars 11.82k forks source link

RecursiveASTVisitor: VisitTypeOfExprType doesn't get called #13990

Open llvmbot opened 12 years ago

llvmbot commented 12 years ago
Bugzilla Link 13618
Version trunk
OS Windows NT
Reporter LLVM Bugzilla Contributor
CC @zygoloid

Extended Description

I wrote this simple recursive AST visitor:

class MyVisitor : public clang::RecursiveASTVisitor { public: MyVisitor() {}

bool VisitTypeOfExprType(clang::TypeOfExprType* t)
{
    printf("Visiting typeof expr type!\n");
    return true;
}

};

And ran it on AST of the following code (found in one open-source project):

zbx.c:

void foo() { int status = 0;

status = ((((extension (((union { typeof(status) in; int i; }) { .in = (status) }).__i))) & 0xff00) >> 8);

status = ({ union { typeof(status) in; int i; } a; a.in = status; (a.__i & 0xff00) >> 8; }); }

I got only one "Visiting typeof expr type!" as a result, for the 2nd anonymous union. I cannot find a way how to catch __typeof of the first anonymous union with RAV.

ec04fc15-fa35-46f2-80e1-5d271f2ef708 commented 12 years ago

The CompoundLiteralExpr change would be straight forward to add to RAV.

I agree, fixed in r162133.

I'm not sure about the RecordType change though.

Right, that change is not correct (for instance, a named type can be defined in a compound literal in C). I think we want two changes here:

llvmbot commented 12 years ago

Thanks, this workaround seems to work, all tests from different projects pass now!

Sergejs

llvmbot commented 12 years ago

Here's a version of your visitor that can traverse the anonymous union:

class MyVisitor : public clang::RecursiveASTVisitor { typedef RecursiveASTVisitor VisitorBase; public: MyVisitor() {}

bool VisitTypeOfExprType(clang::TypeOfExprType* t)
{
    printf("Visiting typeof expr type!\n");
    return true;
}

bool TraverseCompoundLiteralExpr(CompoundLiteralExpr *E) {
    VisitorBase::TraverseCompoundLiteralExpr(E);
    TraverseTypeLoc(E->getTypeSourceInfo()->getTypeLoc());
    return true;
}

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

};

The CompoundLiteralExpr change would be straight forward to add to RAV.

I'm not sure about the RecordType change though. There's two problems.

First, I don't know whether getIdentifier() is the correct test. I expected isAnonymousStructOrUnion() to be a better test but it didn't work.

Second, this changes results in the 2nd anonymous union being traversed twice. This is because the declaration of 'a' is parsed into a DeclStmt containing both a RecordDecl and a VarDecl (and there is a RecordType as part of the VarDecl), whereas I would have expected only the VarDecl.