ASTMatchers: isVirtual and isOverride

Hi and thanks again,

I clearly expressed incorretly the problem. I’ll try to explain it more in detail:

If we have the classes below:

class A{
public: A(){}
};

class B: public A{
public: int b, h;
B():A(){b=0; h=0;}
};

class C: public A{
public C(){}
};

I want my matcher retrieves ONLY the default constructor declaration of B. However this is what happened with the matcher you proposed me:

CXXConstructorDecl 0xa1f6080 </home/pedro/clang-llvm/build/testClases.cpp:14:3, col:25> B ‘void (void)’

-CXXCtorInitializer ‘class A’

-CXXConstructExpr 0xa1f6608 <col:8, col:10> ‘class A’ ‘void (void)’
`-CompoundStmt 0xa1f6710 <col:11, col:25>
-BinaryOperator 0xa1f6698 <col:12, col:16> ‘int’ lvalue ‘=’

-MemberExpr 0xa1f6660 col:12 ‘int’ lvalue ->b 0xa1f6100
-CXXThisExpr 0xa1f6650 <col:12> 'class B *' this -IntegerLiteral 0xa1f6680 col:16 ‘int’ 0
-BinaryOperator 0xa1f66f8 <col:19, col:23> 'int' lvalue '=' -MemberExpr 0xa1f66c0 <col:19> 'int' lvalue ->h 0xa1f6140 -CXXThisExpr 0xa1f66b0 col:19 ‘class B *’ this
`-IntegerLiteral 0xa1f66e0 col:23 ‘int’ 0
Found declaration at 14:3
CXXConstructorDecl 0xa1f68b0 </home/pedro/clang-llvm/build/testClases.cpp:25:3, col:7> C ‘void (void)’
-CXXCtorInitializer ‘class A’

-CXXConstructExpr 0xa1f6c08 col:3 ‘class A’ ‘void (void)’
`-CompoundStmt 0xa1f6c58 <col:6, col:7>
Found declaration at 25:3

The default constructor of C is also matched as there is an implicit call to the default constructor of class A (and effectively, this is an expression and not a declaration as I said in the last message). So, I’ve been thinking about it and, though I don’t have the solution, I’m quite sure we have to change “anything()” inside “hasAnyConstructorInitializer()” to avoid this exception. Any suggestion?

On the other hand, I’ve been trying to use the methods you told me, but I have to use those methods after the matcher execution, haven’t I? This is a bit inefficiently as the mathcer is looking up in some files that are not needed. Is it possible to search for nodes only in some files indicated by the user? Normally, a class is declared in a .h file and defined in the .cpp file and i would like to search in both of them.
I have seen that every file has “id” and, for instance, instead of using “isInSystemHeader” and “isInExternCSystemHeader” could i do the next?:

class DefaultConstructor : public MatchFinder::MatchCallback {
public :
virtual void run(const MatchFinder::MatchResult &Result) {
ASTContext *Context = Result.Context;
FileID mainFileID = Context->getSourceManager.getMainFileID();
if (const CXXConstructorDecl *FS = Result.Nodes.getNodeAsclang::CXXConstructorDecl(“methods”)){
FullSourceLoc FullLocation = Context->getFullLoc(FS->getLocStart());
if (FullLocation.isValid() && FullLocation.getFileID() == mainFileID)
… …
}
}
};

( I got an error with this: reference to non-static member function must be called
FileID mainFileID = (Context->getSourceManager).getMainFileID();
^~~~~~~~~~~~~~~~~~~~~~~~~~~ )

Thank you for your time Gábor. I have put this, but I don’t know why it doesn’t fetch any nodes at all… Could you test this?

I did test it, and worked fine for me. Not sure what could be the issue.

Umm… What a strange thing… I will get over this one more time and see if I did something wrong.
Maybe something is missing or is different in AStMatchersInternal or ASTMatchersMacros.

Thanks,

Pedro.

El dia 19 abr 2013 16:28, Gábor Kozár kozargabor@gmail.com escribió:

Hi,

The default constructor of C is also matched as there is an implicit call to the default constructor of class A (and effectively, this is an expression and not a declaration as I said in the last message). So, I’ve been thinking about it and, though I don’t have the solution, I’m quite sure we have to change “anything()” inside “hasAnyConstructorInitializer()” to avoid this exception. Any suggestion?

This is indeed something I haven’t considered, but should be easy to fix. Looking at the documentation for CXXCtorInitializer, you’ll see that there’s a member called isBaseInitializer(). The other thing you’ll need to check (probably, if that is what you need) for is whether the base ctor call is implicit, which is probably done best by constraining the CXXConstructExpr with argumentCountIs(0). Putting together a custom matcher using these should be simple.

Also keep in mind that if you put together a generic and useful enough matcher, you should totally contribute it as a patch, so that others in need of a similar thing have it available in the future.

On the other hand, I’ve been trying to use the methods you told me, but I have to use those methods after the matcher execution, haven’t I? This is a bit inefficiently as the mathcer is looking up in some files that are not needed.

Yes, you need to use these in the matcher callback. It is indeed inefficient, but we’ve been unable to come up with any better solution. The problem is in the underlying compiler technology, i.e. the nature of header files.

Is it possible to search for nodes only in some files indicated by the user?

Sure, take a look at the clang::ast_matchers::match functions - they allow you to run a matcher on the specified node, not the whole AST. Unfortunately I do not think this will help you in this case, as you cannot distinguish the parts of the TU coming from system header files and the parts coming from user files at the AST level.

> I have seen that every file has “id” and, for instance, instead of using “isInSystemHeader” and “isInExternCSystemHeader” could i do the next?:

I’m not sure I understand what you’re trying to do here… As the error you’re getting, it’s because getSourceManager is missing the paranthesis, i.e. the () that would indicate it’s a method call.

Umm… What a strange thing… I will get over this one more time and see if I did something wrong.
Maybe something is missing or is different in AStMatchersInternal or ASTMatchersMacros.

Yes, that’s quite possible, as I’m using clang 3.2. Nonetheless, you should be able to figure out what the issue is, as I’ve given you a draft (a pattern, if you will).

Good luck!

Gabor