[cfe-dev] TypedefDecl AST Visitor Drops Parent Struct Reference

John Leidel via cfe-dev cfe-dev at lists.llvm.org
Fri Oct 9 19:31:33 PDT 2020


All, I've been working on porting some code forward from an older
version of Clang.  We have Clang transformation that walks the AST,
performs some basic functional modifications and drops out the
equivalent representation for further compilation.  We're having
issues with copying TypedefDecl nodes correctly and maintaining their
parent references.  Consider the following:

typedef struct {
    char * buf;
    size_t pos, len, size, flags;
} BufferBase;
typedef BufferBase *Buffer;

Using the standard Clang methods, we see this resolve to the following
AST snippet:

RecordDecl 0x564021ec3828 <foo.c:3:9, line:6:1> line:3:9 struct definition
| |-FieldDecl 0x564021ec38e8 <line:4:5, col:12> col:12 buf 'char *'
| |-FieldDecl 0x564021ec3948 <line:5:5, col:12> col:12 pos
'size_t':'unsigned long'
| |-FieldDecl 0x564021ec39a8 <col:5, col:17> col:17 len 'size_t':'unsigned long'
| |-FieldDecl 0x564021ec3a08 <col:5, col:22> col:22 size
'size_t':'unsigned long'
| `-FieldDecl 0x564021ec3a68 <col:5, col:28> col:28 flags
'size_t':'unsigned long'
|-TypedefDecl 0x564021ec3b18 <line:3:1, line:6:3> col:3 referenced
BufferBase 'struct BufferBase':'BufferBase'
| `-ElaboratedType 0x564021ec3ac0 'struct BufferBase' sugar
|   `-RecordType 0x564021ec38b0 'BufferBase'
|     `-Record 0x564021ec3828 ''
`-TypedefDecl 0x564021ec3c18 <line:7:1, col:21> col:21 Buffer 'BufferBase *'
  `-PointerType 0x564021ec3be0 'BufferBase *'
    `-TypedefType 0x564021ec3b90 'BufferBase' sugar
      |-Typedef 0x564021ec3b18 'BufferBase'
      `-ElaboratedType 0x564021ec3ac0 'struct BufferBase' sugar
        `-RecordType 0x564021ec38b0 'BufferBase'
          `-Record 0x564021ec3828 ''

In our AST modification code, we attempt to utilize the existing
TypedefDecl to create a new copy with the same attributes.

QualType TransformType(TypeLocBuilder& TLB, TypeLoc Ty) {
      if(SemaRef.Context.hasSameType(Ty.getType(), From)) {
        Ty = SemaRef.Context.getTrivialTypeSourceInfo(To)->getTypeLoc();
      }
      return TreeTransformS::TransformType(TLB, Ty);
}

[..snipped..]
} else if(TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
  DeclContext *NewDC = DC;
  IdentifierInfo *Name = TD->getIdentifier();
  TypeSourceInfo *Ty = TransformType(TD->getTypeSourceInfo());
  // create the AST node
  TypedefDecl *Result = TypedefDecl::Create(SemaRef.Context, NewDC,
TD->getBeginLoc(), TD->getLocation(), Name, Ty);
 Result->dump();
}

However, if we dump the AST immediately following the Create, we get
an anonymous struct as follows:
TypedefDecl 0x55a568c31800 <foo.c:16:1, line:19:3> col:3 BufferBase
'struct (anonymous struct at foo.c:16:9)':'struct (anonymous at
foo.c:16:9)'
`-ElaboratedType 0x55a568c317b0 'struct (anonymous struct at foo.c:16:9)' sugar
  `-RecordType 0x55a568c314f0 'struct (anonymous at foo.c:16:9)'
    `-Record 0x55a568c31468 ''

What are we missing to preserve the linkage between the struct
definition and the typedef?


More information about the cfe-dev mailing list