Compare commits
5 Commits
45829ecc7e
...
55aa93eee2
Author | SHA1 | Date |
---|---|---|
|
55aa93eee2 | |
|
5b8a014013 | |
|
aa93dba62f | |
|
6e748b6c94 | |
|
494038ebde |
|
@ -21,3 +21,8 @@ ACP_Ray2/
|
||||||
build/
|
build/
|
||||||
# game_re/
|
# game_re/
|
||||||
windows_libs/
|
windows_libs/
|
||||||
|
tooling/build/
|
||||||
|
|
||||||
|
*.code-workspace
|
||||||
|
*.log
|
||||||
|
.edits_backup/
|
|
@ -0,0 +1,61 @@
|
||||||
|
cmake_minimum_required(VERSION 3.26.4)
|
||||||
|
project(reman3_tooling)
|
||||||
|
|
||||||
|
set(LLVM_PATH "" CACHE STRING "Path to the LLVM source tree")
|
||||||
|
|
||||||
|
set(LLVM_ADD_PATH ${LLVM_PATH}/llvm)
|
||||||
|
if(NOT EXISTS ${LLVM_ADD_PATH}/CMakeLists.txt)
|
||||||
|
message(FATAL_ERROR "LLVM_PATH is invalid (${LLVM_PATH})")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
set(LLVM_INCLUDE_UTILS OFF CACHE BOOL "" FORCE)
|
||||||
|
set(LLVM_INCLUDE_RUNTIMES OFF CACHE BOOL "" FORCE)
|
||||||
|
set(LLVM_BUILD_RUNTIME OFF CACHE BOOL "" FORCE)
|
||||||
|
set(LLVM_INCLUDE_TESTS OFF CACHE BOOL "" FORCE)
|
||||||
|
set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||||
|
set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "" FORCE)
|
||||||
|
set(LLVM_ENABLE_OCAMLDOC OFF CACHE BOOL "" FORCE)
|
||||||
|
set(LLVM_ENABLE_BINDINGS OFF CACHE BOOL "" FORCE)
|
||||||
|
set(LLVM_ENABLE_TELEMETRY OFF CACHE BOOL "" FORCE)
|
||||||
|
set(LLVM_INCLUDE_BENCHMARKS OFF CACHE BOOL "" FORCE)
|
||||||
|
set(LLVM_TARGETS_TO_BUILD "X86" CACHE STRING "" FORCE)
|
||||||
|
set(LLVM_ENABLE_PROJECTS "clang" CACHE STRING "" FORCE)
|
||||||
|
|
||||||
|
set(LLVM_BINARY_DIR ${CMAKE_BINARY_DIR}/external/llvm)
|
||||||
|
add_subdirectory(${LLVM_ADD_PATH} ${LLVM_BINARY_DIR})
|
||||||
|
add_subdirectory(../game_re/third_party/spdlog spdlog)
|
||||||
|
|
||||||
|
# Add the clang tooling executable
|
||||||
|
add_executable(clang_tool main.cpp)
|
||||||
|
|
||||||
|
target_include_directories(clang_tool PRIVATE
|
||||||
|
${LLVM_PATH}/llvm/include
|
||||||
|
${LLVM_PATH}/clang/include
|
||||||
|
${LLVM_BINARY_DIR}/include
|
||||||
|
${LLVM_BINARY_DIR}/tools/clang/include
|
||||||
|
)
|
||||||
|
|
||||||
|
# Link against clang tooling libraries
|
||||||
|
target_link_libraries(clang_tool
|
||||||
|
clangTooling
|
||||||
|
clangFrontend
|
||||||
|
clangASTMatchers
|
||||||
|
clangAST
|
||||||
|
clangBasic
|
||||||
|
clangSerialization
|
||||||
|
clangDriver
|
||||||
|
clangParse
|
||||||
|
clangSema
|
||||||
|
clangAnalysis
|
||||||
|
clangEdit
|
||||||
|
clangRewrite
|
||||||
|
clangLex
|
||||||
|
spdlog::spdlog
|
||||||
|
)
|
||||||
|
|
||||||
|
# Include LLVM/Clang headers
|
||||||
|
target_include_directories(clang_tool PRIVATE
|
||||||
|
${LLVM_INCLUDE_DIRS}
|
||||||
|
${CLANG_INCLUDE_DIRS}
|
||||||
|
)
|
|
@ -0,0 +1,122 @@
|
||||||
|
#include "clang/AST/ASTConsumer.h"
|
||||||
|
#include "clang/AST/RecursiveASTVisitor.h"
|
||||||
|
#include "clang/Frontend/CompilerInstance.h"
|
||||||
|
#include "clang/Frontend/FrontendAction.h"
|
||||||
|
#include "clang/Tooling/CommonOptionsParser.h"
|
||||||
|
#include "clang/Tooling/Tooling.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include "clang/AST/ASTConcept.h"
|
||||||
|
|
||||||
|
using namespace clang;
|
||||||
|
using namespace clang::tooling;
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
// Apply a custom category to all command-line options so that they are the
|
||||||
|
// only ones displayed.
|
||||||
|
static cl::OptionCategory MyToolCategory("my-tool options");
|
||||||
|
|
||||||
|
// CommonOptionsParser declares HelpMessage with a description of the common
|
||||||
|
// command-line options related to the compilation database and input files.
|
||||||
|
// It's nice to have this help message in all tools.
|
||||||
|
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
|
||||||
|
|
||||||
|
// A help message for this specific tool can be added afterwards.
|
||||||
|
static cl::extrahelp MoreHelp("\nMore help text...\n");
|
||||||
|
|
||||||
|
class FunctionVisitor : public RecursiveASTVisitor<FunctionVisitor> {
|
||||||
|
private:
|
||||||
|
ASTContext *Context;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FunctionVisitor(ASTContext *Context) : Context(Context) {}
|
||||||
|
|
||||||
|
bool VisitFunctionDecl(FunctionDecl *Declaration) {
|
||||||
|
if (Declaration->hasBody()) {
|
||||||
|
SourceManager &SM = Context->getSourceManager();
|
||||||
|
SourceLocation Loc = Declaration->getLocation();
|
||||||
|
|
||||||
|
if (SM.isInMainFile(Loc)) {
|
||||||
|
std::string FuncName = Declaration->getNameInfo().getName().getAsString();
|
||||||
|
unsigned Line = SM.getExpansionLineNumber(Loc);
|
||||||
|
|
||||||
|
spdlog::info("Found function '{}' at line {}", FuncName, Line);
|
||||||
|
|
||||||
|
// Count parameters
|
||||||
|
unsigned ParamCount = Declaration->getNumParams();
|
||||||
|
spdlog::debug(" - Function '{}' has {} parameters", FuncName, ParamCount);
|
||||||
|
|
||||||
|
// Check if it's a main function
|
||||||
|
if (FuncName == "main") {
|
||||||
|
spdlog::warn("Found main function at line {}", Line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VisitVarDecl(VarDecl *Declaration) {
|
||||||
|
SourceManager &SM = Context->getSourceManager();
|
||||||
|
SourceLocation Loc = Declaration->getLocation();
|
||||||
|
|
||||||
|
if (SM.isInMainFile(Loc)) {
|
||||||
|
std::string VarName = Declaration->getNameAsString();
|
||||||
|
unsigned Line = SM.getExpansionLineNumber(Loc);
|
||||||
|
|
||||||
|
spdlog::debug("Found variable '{}' at line {}", VarName, Line);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FunctionConsumer : public ASTConsumer {
|
||||||
|
private:
|
||||||
|
FunctionVisitor Visitor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FunctionConsumer(ASTContext *Context) : Visitor(Context) {}
|
||||||
|
|
||||||
|
void HandleTranslationUnit(ASTContext &Context) override {
|
||||||
|
spdlog::info("Starting AST traversal...");
|
||||||
|
Visitor.TraverseDecl(Context.getTranslationUnitDecl());
|
||||||
|
spdlog::info("AST traversal completed");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FunctionAction : public ASTFrontendAction {
|
||||||
|
public:
|
||||||
|
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
|
||||||
|
StringRef InFile) override {
|
||||||
|
spdlog::info("Processing file: {}", InFile.str());
|
||||||
|
return std::make_unique<FunctionConsumer>(&Compiler.getASTContext());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, const char **argv) {
|
||||||
|
// Set up logging
|
||||||
|
spdlog::set_level(spdlog::level::debug);
|
||||||
|
spdlog::info("Starting clang tooling example");
|
||||||
|
|
||||||
|
auto ExpectedParser = CommonOptionsParser::create(argc, argv, MyToolCategory);
|
||||||
|
if (!ExpectedParser) {
|
||||||
|
// Fail gracefully for unsupported options.
|
||||||
|
llvm::errs() << ExpectedParser.takeError();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
CommonOptionsParser &OptionsParser = ExpectedParser.get();
|
||||||
|
ClangTool Tool(OptionsParser.getCompilations(),
|
||||||
|
OptionsParser.getSourcePathList());
|
||||||
|
|
||||||
|
spdlog::info("Running tool on {} source files",
|
||||||
|
OptionsParser.getSourcePathList().size());
|
||||||
|
|
||||||
|
int Result = Tool.run(newFrontendActionFactory<FunctionAction>().get());
|
||||||
|
|
||||||
|
if (Result == 0) {
|
||||||
|
spdlog::info("Tool completed successfully");
|
||||||
|
} else {
|
||||||
|
spdlog::error("Tool failed with exit code {}", Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int add(int a, int b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void greet(const std::string& name) {
|
||||||
|
std::cout << "Hello, " << name << "!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int x = 5;
|
||||||
|
int y = 10;
|
||||||
|
int result = add(x, y);
|
||||||
|
|
||||||
|
greet("World");
|
||||||
|
|
||||||
|
std::cout << "Result: " << result << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue