Iterate over struct's fields

Hi,

I have following C code

typedef struct
{
unsigned int speed;
int len;
snake_segment_t body[100];
} snake_t;

void f(snake_t snake) {}

And I want to iterate over function f's arguments and in case if they are of struct type (like here), over fields of the struct too.

In Clang AST the structure looks like this:

-RecordDecl 0x5611f85ce6c0 <line:45:9, line:52:1> line:45:9 struct definition

-FieldDecl 0x5611f85ce788 <line:47:4, col:20> col:20 referenced speed ‘unsigned int’
-FieldDecl 0x5611f85ce860 <line:50:4, col:20> col:20 referenced len ‘int’
`-FieldDecl 0x5611f85ce9d8 <line:51:4, col:28> col:20 referenced body ‘snake_segment_t [100]’

-TypedefDecl 0x5611f85cea70 <line:45:1, line:52:3> col:3 referenced snake_t ‘struct snake_t’:‘snake_t’
-ElaboratedType 0x5611f85cea20 'struct snake_t' sugar -RecordType 0x5611f85ce750 ‘snake_t’
`-Record 0x5611f85ce6c0 ‘’

First I find FunctionDecl for f, then iterate over its’ ParamDecls to find all arguments. But when I retrieve Decl from ParamDecl->getType() to iterate over struct fields, I get the TypedefDecl (in AST). How can I get the real RecordDecl, the one that also has FieldDecls for struct?

Best,
Anahit.

Hi,

Hi Miklos,

Yes, I tried getUnderlyingType(). Here is the code I have:

void iterateTypeFields(const clang::Type* type)
{
clang::RecordDecl* recordDecl;
if (auto* typedefType = llvm::dyn_castclang::TypedefType(type)) {
typedefType->getDecl()->getUnderlyingType()->dump();
iterateTypeFields(&typedefType->getDecl()->getUnderlyingType());
} else if (auto
elaboratedType = llvm::dyn_castclang::ElaboratedType(type)) {
elaboratedType->getNamedType()->dump();
iterateTypeFields(&*elaboratedType->getNamedType());

} else if (auto* recordType = llvm::dyn_castclang::RecordType(type)) {
recordType->dump();
recordDecl = recordType->getDecl()->getDefinition();
} else if (type->isStructureType()) {
recordDecl = type->getAsStructureType()->getDecl();
} else {
return;
}
int i = 0;
for (auto it = recordDecl->field_begin(); it != recordDecl->field_end(); ++it) {
// Do stuff

}
}

When this code is ran on the example I posted, first I get TypedefType, then its’ underlying type is ElaboratedType which getNamedType is the RecordType. So this function is called with TypedefType, then ElaboratedType then RecordType. However when I try to call field_begin function on RecordDecl obtained from RecordType it crashes in clang sources. That’s why I’m assuming that I’m doing something wrong here.

Thanks!

Hi,