I'm using the following code get parent struct of a nested struct using clang libtooling.
bool VisitRecordDecl(clang::RecordDecl *RD) {
llvm::outs() <<"\n\tTrying to get parents of "<<RD->getNameAsString()<<"\n\n";
clang::RecordDecl *Parent = dyn_cast<clang::RecordDecl>(RD->getParent());
if(!Parent) {
llvm::outs()<<"NULL RecordDecl with dyn_cast\n";
clang::DeclContext *DParent = RD->getParent(); // trying to find what did getParent return
llvm::outs()<<DParent->getDeclKindName()<<"\n"; // prints TransaltionUnit
DParent->dumpDeclContext(); // prints whole source file
}
else{
Parent->dump();
}
return true;
}
This is the source file in which I run the code
struct outer{
struct inner{
int ia;
int ib;
struct deep{
int da;
}dobj;
}iobj;
int oa;
}oboj;
int main(){
return 0;
}
For each invocation of VisitRecordDecl, getParent returns a TranslationUnit which cannot be casted into RecordDecl to get parent struct of inner or deep struct. getLexicalParent() returns RecordDecl correctly but why is getParent() not working?
The
DeclContextgetParentmethod returns the "semantic" parent. Although the concept of semantic parent has some quirks (see thegetLookupParentmethod implementation), to a first approximation, the semantic parent ofBisAifBcan be found by qualified lookup asA::B.But the code in question is being interpreted as C, not C++ (per a clarification in a comment), and C does not have qualified lookup at all! C does allow structure definitions to appear inside other structure definitions, for example:
but the effect is semantically the same as if they had not been nested:
In particular, to name the inner type in C, one writes just
struct Inner, notstruct Outer::Inner. See C99 6.7.2.1p7 and compare to C++11 9.2p1. See also the question Nested structures in C and C++.Consequently,
getParentreturns theTranslationUnitDeclfor bothRecordDecls.As you've noted, you can instead use the
getLexicalParentmethod to get the syntactic context in which the declaration appeared.If you compile the code as C++, either by changing the file extension to one that
clangrecognizes as being C++ (such as.ccor.cpp), or pass the-xc++command line option to the command line parser, then the semantic parent ofInnerwill be reported asOuter.