Изменение анонимных структур и объединений в AST Clang

#clang #llvm #llvm-c -api

#clang #llvm #llvm-c -api

Вопрос:

Я пытаюсь написать внешний модификатор AST Clang, который переводит определения анонимных структур и объединений в другую форму. Например, у меня есть:

 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 первой переменной, но, похоже, я не могу понять, как преобразовать определение структуры.

Комментарии:

1. это помогло бы людям понять и ответить, если вы также покажете свой «внешний модификатор AST Clang».

Ответ №1:

В конечном счете, это довольно интересная особенность AST Clang. При представлении вложенных наборов структур и объединений вложенные объявления и определения разделяются на уникальные 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() amp;amp; !TD->isFreeStanding()){
       // save StructDecl
     }
  }
}