微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Clang 的 AST 中修改匿名结构和联合

如何解决在 Clang 的 AST 中修改匿名结构和联合

我正在尝试编写一个外部 Clang AST 修饰符,将匿名结构和联合定义转换为不同的形式。例如,我有

typedef struct test_case_t {
  struct {
    int value;
  } first[1];
  int second;
  int third[1];
} test_case_t;

我想将其转换为:

struct test_case_t {
    struct first{
        int value;
    };
    struct first first[1];
    int second;
    int third[1];
};
typedef struct test_case_t test_case_t;

但是,转换似乎删除struct first 声明,所以这就是我得到的:

struct test_case_t {
    struct{ // this should be "struct first"
        int value;
    };
    struct first first[1];
    int second;
    int third[1];
};
typedef struct test_case_t test_case_t;

如何修改结构体定义并添加 first 声明名称我有一个变量定义的 RecordDecl,但我似乎无法弄清楚如何转换结构定义。

解决方法

最终,这是 Clang AST 的一个相当有趣的特性。当表示嵌套的结构和联合集时,嵌套的声明和定义被拆分为唯一的 FieldDecls。首先对结构声明进行词法解析,然后解析变量定义。这要求您保存对结构/联合声明的引用,并将其下游匹配到后续变量定义。这个过程可能相当棘手,但模仿以下内容。具体来说,我们正在寻找匹配的结构声明不是 isFreeStanding()

for(RecordDecl::decl_iterator iter = RD->decls_begin(),end =
RD->decls_end(); iter != end; ++iter) {
  Decl *StructDecl = nullptr;
  if(FieldDecl *FD = dyn_cast_or_null<FieldDecl>(*iter)) {
    // create new FD
    if(const ElaboratedType * NET =
       dyn_cast<ElaboratedType>(SemaRef.Context.getBaseElementType(NewFD->getType())))
{
    if( StructDecl ){
      RecordDecl *MyDecl = dyn_cast<RecordDecl>(StructDecl);
      if( MyDecl )
          MyDecl->setDeclName(FD->getDeclName());
      }
     }
   }
  }else if(TagDecl *TD = dyn_cast<TagDecl>(*iter)){
     if(TD->isThisDeclarationADefinition() && !TD->isFreeStanding()){
       // save StructDecl
     }
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。