生成注释
假设有下面的源码:
struct Vec3 { float x, y, z; }; struct Vec4 { float x, y, z, w; };
生成这样的代码:
//[[CLASS INFO]] class:Vec3, is pod:true, is aggregate:true struct Vec3 { float x, y, z; }; //[[CLASS INFO]] use struct-binding method : //const auto &[_m0,_m1,_m2] = Vec3; //[[CLASS INFO]] class:Vec4, is pod:true, is aggregate:true struct Vec4 { float x, y, z, w; }; //[[CLASS INFO]] use struct-binding method : //const auto &[_m0,_m1,_m2,_m3] = Vec4;
#include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/Frontend/ASTUnit.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/PreprocessorOutputOptions.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Tooling/Tooling.h" #include "llvm/Support/raw_ostream.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Rewrite/Core/Rewriter.h" #include <format> #include <iostream> using namespace clang; class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor> { public: MyASTVisitor(Rewriter &w ) : writer{w}{} bool VisitCXXRecordDecl(CXXRecordDecl *declaration) { auto sourceBeginLoc = declaration->getSourceRange().getBegin(); auto sourceEndLoc = declaration->getSourceRange().getEnd(); declaration->dump();
auto name = declaration->getNameAsString(); bool isPod = declaration->isPOD(); auto isAggregate = declaration->isAggregate(); auto fieldCount = std::distance(declaration->field_begin(), declaration->field_end()); std::string fieldBinding{"const auto &["}; for(auto i=0;i<fieldCount;i++){ fieldBinding += "_m" + std::to_string(i); if(i!=fieldCount-1) fieldBinding += ","; } fieldBinding += "] = "; fieldBinding += name; auto classInfo = std::format("//[[CLASS INFO]] class:{}, is pod:{}, is aggregate:{}\n", name, isPod, isAggregate); auto howToBind = std::format("\n//[[CLASS INFO]] use struct-binding method : \n//{};\n\n", fieldBinding); writer.InsertText(sourceBeginLoc, classInfo, true, true); writer.InsertText(declaration->getEndLoc().getLocWithOffset(2), howToBind,true, true); // location使用sourceEndLoc变量也可以 return true; } private: Rewriter &writer; }; class MyASTConsumer : public ASTConsumer { public: MyASTConsumer(Rewriter &w) : writer{w}{} void HandleTranslationUnit(ASTContext &context) override { MyASTVisitor visitor{writer}; visitor.TraverseDecl(context.getTranslationUnitDecl()); } Rewriter &writer; }; class MyFrontendAction : public ASTFrontendAction { public: void EndSourceFileAction() override{ auto &sm = writer.getSourceMgr(); writer.getEditBuffer(sm.getMainFileID()).write(llvm::outs()); } std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &compiler, StringRef file) override { llvm::outs() << "create ast consumer for: " << file << "\n"; compiler.getLangOpts().CPlusPlus = true; compiler.getPreprocessorOpts().addMacroDef("__cplusplus"); compiler.getPreprocessorOpts().addMacroDef("Vec3=struct Vec3"); compiler.getLangOpts().CPlusPlus2b = true; writer.setSourceMgr(compiler.getSourceManager(), compiler.getLangOpts()); return std::make_unique<MyASTConsumer>(writer); } private: Rewriter writer; }; int main(int argc, const char **argv) { auto code= R"( struct Vec3 { float x, y, z; }; struct Vec4 { float x, y, z, w; }; )"; clang::tooling::runToolOnCode(std::make_unique<MyFrontendAction>(), code); return 0; }
输出:
D:\Plugin_Dev\CPP\LLVM\modify_ast\cmake-build-debug\xxx.exe create ast consumer for: input.cc CXXRecordDecl 0x23cdd3e7c48 <input.cc:3:1, line:5:1> line:3:8 struct Vec3 definition |-DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal | |-DefaultConstructor exists trivial needs_implicit | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param | |-MoveConstructor exists simple trivial needs_implicit | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param | |-MoveAssignment exists simple trivial needs_implicit | `-Destructor simple irrelevant trivial needs_implicit |-CXXRecordDecl 0x23cdd3e7d68 <col:1, col:8> col:8 implicit struct Vec3 |-FieldDecl 0x23cdd3e7e10 <line:4:3, col:9> col:9 x 'float' |-FieldDecl 0x23cdd3e7e80 <col:3, col:12> col:12 y 'float' `-FieldDecl 0x23cdd3e7ef0 <col:3, col:15> col:15 z 'float' CXXRecordDecl 0x23cdd3e7f80 <input.cc:7:1, line:9:1> line:7:8 struct Vec4 definition |-DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal | |-DefaultConstructor exists trivial needs_implicit | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param | |-MoveConstructor exists simple trivial needs_implicit | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param | |-MoveAssignment exists simple trivial needs_implicit | `-Destructor simple irrelevant trivial needs_implicit |-CXXRecordDecl 0x23cdd3e8098 <col:1, col:8> col:8 implicit struct Vec4 |-FieldDecl 0x23cdd3e8140 <line:8:3, col:9> col:9 x 'float' |-FieldDecl 0x23cdd3e81b0 <col:3, col:12> col:12 y 'float' |-FieldDecl 0x23cdd3e8220 <col:3, col:15> col:15 z 'float' `-FieldDecl 0x23cdd3e8290 <col:3, col:18> col:18 w 'float' //[[CLASS INFO]] class:Vec3, is pod:true, is aggregate:true struct Vec3 { float x, y, z; }; //[[CLASS INFO]] use struct-binding method : //const auto &[_m0,_m1,_m2] = Vec3; //[[CLASS INFO]] class:Vec4, is pod:true, is aggregate:true struct Vec4 { float x, y, z, w; }; //[[CLASS INFO]] use struct-binding method : //const auto &[_m0,_m1,_m2,_m3] = Vec4; Process finished with exit code 0
参考:
标签:struct,float,clang,源码,操作,include,trivial,implicit From: https://www.cnblogs.com/gearslogy/p/17279979.html