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 DeclContext
getParent
method returns the "semantic" parent. Although the concept
of semantic parent has some quirks (see the getLookupParent
method
implementation), to a first approximation, the semantic parent of B
is
A
if B
can be found by qualified lookup as A::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:
struct Outer {
struct Inner {
int i;
};
int o;
};
but the effect is semantically the same as if they had not been nested:
struct Outer {
int o;
};
struct Inner {
int i;
};
In particular, to name the inner type in C, one writes just struct Inner
,
not struct 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, getParent
returns the
TranslationUnitDecl
for both
RecordDecl
s.
As you've noted, you can instead use the getLexicalParent
method 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 clang
recognizes as being C++ (such as .cc
or .cpp
),
or pass the -xc++
command line option to the command line parser,
then the semantic parent of Inner
will be reported as Outer
.