?
Xmacros kannte ich noch nicht, thx Ich hab mich jetzt für eine... etwas umständlichere lösung entschieden. Zumindest wenn man auf windows ist. Ich hab über libtooling clang benutzt um den src zu parsen und daraus den benötigten initialisierungs code zu bauen. Clang unter windows zu kompilieren geht super einfach aber die stl ist ein absoluter krampf und ich musste viel mit mingw rumspielen um die zum laufen zu bekommen (die VS stl klappt nur mit wenigen headern). Der eigentliche code ist aber super kurz und fast 1zu1 aus nem beispiel. Die src beispiele sind verständlich, auch wenn die doku doch zu wünschen übrig lässt. Vieles findet man nur durch ausgiebiges googeln. Wenn wer mal auf die gleiche idee kommt, hier der src.
// https://github.com/eliben/llvm-clang-samples
// http://eli.thegreenplace.net/tag/llvm-clang
// http://eli.thegreenplace.net/tag/compilation
// -> http://eli.thegreenplace.net/2014/samples-for-using-llvm-and-clang-as-a-library/
// -> http://eli.thegreenplace.net/2015/on-parsing-c-type-declarations-and-fake-headers/
// -> http://eli.thegreenplace.net/2014/05/21/compilation-databases-for-clang-based-tools
// -> http://eli.thegreenplace.net/2014/05/01/modern-source-to-source-transformation-with-clang-and-libtooling/
// -> http://eli.thegreenplace.net/2014/07/29/ast-matchers-and-clang-refactoring-tools
// https://genericlanguage.wordpress.com/2013/08/12/newbie-guide-understanding-clang-ast-construction/
// http://xinhuang.github.io/clang/2014/10/19/clang-tutorial-finding-declarations/
// http://stackoverflow.com/questions/6525245/getting-clang-to-work-on-windows
// https://llvm.org/bugs/show_bug.cgi?id=23275
// http://here-be-braces.com/blog/building-clang-natively-on-windows-mingw
// http://stackoverflow.com/questions/14902683/compiling-clang-on-windows
// https://woboq.com/blog/moc-with-clang.html
// - https://code.woboq.org/mocng/src/mocng.cpp.html
// http://www.myopictopics.com/?p=368
// https://github.com/sk-havok/clang-extract
// http://www.gdcvault.com/play/1015586/
// https://bitbucket.org/dwilliamson/clreflect/overview
// https://github.com/AustinBrunkhorst/CPP-Reflection
// maybe http://szelei.me/code-generator/
// https://www.youtube.com/watch?v=yuIOGfcOH0k
#include <sstream>
#include <string>
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
static llvm::cl::OptionCategory ToolingSampleCategory("Tooling Sample");
// By implementing RecursiveASTVisitor, we can specify which AST nodes
// we're interested in by overriding relevant methods.
// http://clang.llvm.org/doxygen/classclang_1_1ASTDeclReader.html
class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>
{
public:
MyASTVisitor(Rewriter& r)
: TheRewriter(r)
{}
// find classes
bool VisitCXXRecordDecl(CXXRecordDecl *decl)
{
// only parse structs in the "main" file, not in included files
SourceLocation sloc = decl->getSourceRange().getBegin();
// http://stackoverflow.com/questions/20658987/clang-3-5-libtooling-getting-file-name-of-a-variable-in-clangvardecl
if (!decl->getASTContext().getSourceManager().isInMainFile(sloc)) {
return true;
}
std::stringstream ss;
// https://github.com/d3faultdotxbe/libclang-recursiveastvisitor-tutorial-building-linking-on-debian-wheezy/blob/master/FindClassDecls.cpp
// theres also getQualifiedNameAsString() if needed e.g.: a::b::blaa
auto className = decl->getNameAsString();
ss << "\n\tstatic struct init {\n"
"\t\tinit() {\n";
// http://stackoverflow.com/questions/6602967/handle-c-functions-with-clang-api-to-insert-code
for (auto it = decl->field_begin(); it != decl->field_end(); it++)
{
auto varName = it->getNameAsString();
auto varType = it->getType().getCanonicalType().getAsString();
ss << "\t\t\treflect::RegisterOffset<" << varType << ">(\"" << className << "\", \"" << varName << "\", offsetof(" << className << ", " << varName << "));\n";
}
ss << "\t\t}\n"
"\t} _initializer;\n";
SourceLocation blockEndSloc = decl->getLocEnd();
TheRewriter.InsertText(blockEndSloc, ss.str(), true, true);
SourceLocation fieldEndSloc = decl->getLocEnd().getLocWithOffset(2);
TheRewriter.InsertText(fieldEndSloc, "\n" + className + "::init " + className + "::initializer;\n", true, true);
return true;
}
private:
Rewriter &TheRewriter;
};
// Implementation of the ASTConsumer interface for reading an AST produced
// by the Clang parser.
class MyASTConsumer : public ASTConsumer
{
public:
MyASTConsumer(Rewriter& r)
: Visitor(r)
{}
// Override the method that gets called for each parsed top-level
// declaration.
bool HandleTopLevelDecl(DeclGroupRef dr) override
{
for (DeclGroupRef::iterator b = dr.begin(), e = dr.end(); b != e; ++b)
{
// Traverse the declaration using our AST visitor.
Visitor.TraverseDecl(*b);
//(*b)->dump();
}
return true;
}
private:
MyASTVisitor Visitor;
};
// For each source file provided to the tool, a new FrontendAction is created.
class MyFrontendAction : public ASTFrontendAction
{
public:
MyFrontendAction() {}
void EndSourceFileAction() override
{
SourceManager &sm = TheRewriter.getSourceMgr();
llvm::errs() << "** EndSourceFileAction for: " << sm.getFileEntryForID(sm.getMainFileID())->getName() << "\n";
// Now emit the rewritten buffer.
TheRewriter.getEditBuffer(sm.getMainFileID()).write(llvm::outs());
}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance& ci, StringRef file) override
{
llvm::errs() << "** Creating AST consumer for: " << file << "\n";
TheRewriter.setSourceMgr(ci.getSourceManager(), ci.getLangOpts());
return llvm::make_unique<MyASTConsumer>(TheRewriter);
}
private:
Rewriter TheRewriter;
};
int main(int argc, const char **argv)
{
CommonOptionsParser op(argc, argv, ToolingSampleCategory);
ClangTool Tool(op.getCompilations(), op.getSourcePathList());
// ClangTool::run accepts a FrontendActionFactory, which is then used to
// create new objects implementing the FrontendAction interface. Here we use
// the helper newFrontendActionFactory to create a default factory that will
// return a new MyFrontendAction object every time.
// To further customize this, we could create our own factory class.
return Tool.run(newFrontendActionFactory<MyFrontendAction>().get());
}