Given a class hierarchy:
class A {};
class B {};
class C : public A {};
class D : public C {};
I'm trying to refactor class C to inherit from class B rather than class A. I can easily get the definition statement using a recordDecl
:
recordDecl(hasName("C"), isDefinition()).bind("MyClass")
With an associated MatchCallback, I can dump()
the class to verify it matched the right node. However I have not found a way to bind instead to the public A
or, even better, just the A
.
What would be an appropriate AST Matcher to capture either public A
or A
for class C?
EDIT:
The output of clang -ast-dump
filtered for class C in this situation would show something similar to the following:
CXXRecordDecl [address] <line numbers> <loc> class C definition
|- public 'class A'
|- CXXRecordDecl [address 2] <columns> <loc> implicit referenced class C
It's as if there is no AST Node type to represent parent class declarations in the ast-dump.
I found this link providing some context for how to drill down. Notably, one tutorial suggested using RecordDecl
in the match handler for the returned node vs. this reference using CXXRecordDecl
. So if we output each base in the match handler:
if (const CXXRecord *entityBase = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("entityBase")) {
for (auto &p : entityBase->bases()) {
p.dump();
}
}
We find that the reference to class A is RecordType
which is referred to by a CXXRecord
. However using clang-query
, I did not find a way to chain match recordType(...)
with anything conducive to pulling just public A
or A
. Instead, the solution became something similar to this:
std::string qual = "public ";
std::string parentName = "A";
std::string parentType = "class " + parentName;
if (0 == parentType.compare(p.getType().getAsString())) {
Replacement Rep(*(Result.SourceManager),
p.getLocStart().getLocWithOffset(qual.length()),
parentName.length(),
"B");
Replace->insert(Rep);
}
I'm not marking this as the answer yet just in case someone has a way to use recordType to snag the base class reference directly rather than iterating and checking base class type names, as shown above.