Решил потыкать Clang API. Допустим, я хочу пробежаться по AST, найти некоторые места, которые удовлетворяют определённым критериям и модифицировать их.
С первыми двумя пунктами проблем особых нет - я создал плагин для Clang, который создаёт ASTConsumer, переопределил метод HandleToplevelDecl, который по условию запускает RecursiveASTVisitor на некоторых элементах. Наконец, я нахожу места, которые хотел бы модифицировать. А вот с модификацией есть проблемы.
Допустим, я знаю, что интересующие меня ноды являются дочерними элементами CompoundStmt. Я могу переопределить TraverseCompoundStmt, вручную бежать по его детям и вызывать TraverseStmt для них. При этом visitXXX устанавливает флаг, который я потом проверяю. При выполнении условия я могу присвоить *it (где it - итератор из диапазона от stmt->child_begin() до stmt->child_end()) новый узел. В принципе это работает. Например, я могу создать пустой CompoundStmt и заменить узел на него. После этого я вижу с помощью objdump (а также по дампу AST), что соответствующие инструкции исчезают. Но что если я хочу более сложных изменений?
Например, я хочу создать метку (LabelStmt). И тут я натыкаюсь на проблему, что LabelStmt хочет LabelDecl, который в свою очередь хочет IdentifierInfo. Каким образом создать новый идентификатор и получить его IdentifierInfo? Если указать вместо нормального IdentifierInfo nullptr, то clang предсказуемо падает. Каких-либо нормальных конструкторов или статических методов для создания IdentifierInfo в самом IdentifierInfo я не заметил. Значит IdentifierInfo должен создавать кто-то другой. Но кто? Как вообще генерировать новые идентификаторы?