Skip to content

Instantly share code, notes, and snippets.

@inlinechan
Last active October 25, 2016 02:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save inlinechan/5159dd3b4f8ca311354f4a205f3da6af to your computer and use it in GitHub Desktop.
Save inlinechan/5159dd3b4f8ca311354f4a205f3da6af to your computer and use it in GitHub Desktop.
clangtool
cmake_minimum_required(VERSION 2.8)
set(PROJECT_NAME finder)
project(${PROJECT_NAME})
option(test "Build all tests." OFF)
execute_process(COMMAND llvm-config-3.8 --cxxflags
OUTPUT_VARIABLE LLVM_CXXFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CMAKE_CXX_FLAGS "${LLVM_CXXFLAGS} -Wno-strict-aliasing")
execute_process(COMMAND llvm-config-3.8 --ldflags
OUTPUT_VARIABLE LLVM_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND llvm-config-3.8 --libs
OUTPUT_VARIABLE LLVM_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND llvm-config-3.8 --system-libs
OUTPUT_VARIABLE LLVM_SYSTEM_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CLANG_LIBS " -Wl,--start-group -lclangAST -lclangASTMatchers -lclangAnalysis -lclangBasic -lclangDriver -lclangEdit -lclangFrontend -lclangFrontendTool -lclangLex -lclangParse -lclangSema -lclangEdit -lclangRewrite -lclangRewriteFrontend -lclangStaticAnalyzerFrontend -lclangStaticAnalyzerCheckers -lclangStaticAnalyzerCore -lclangSerialization -lclangToolingCore -lclangTooling -lclangFormat -Wl,--end-group ")
add_executable(test_tool test_tool.cpp)
set(CLANG_LINK_FLAGS
"${CLANG_LIBS} ${LLVM_LDFLAGS} ${LLVM_LIBS} ${LLVM_SYSTEM_LIBS}")
set(CMAKE_CXX_LINK_EXECUTABLE
"<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${CLANG_LINK_FLAGS}")
if (test)
enable_testing()
add_subdirectory(tests)
endif()
.PHONY: all
all: test_tool
test_tool: test_tool.o
$(CXX) -o $@ $< $(CLANG_LIBS) $(LDFLAGS) $(LLVM_LDFLAGS)
# CXXFLAGS := -g
CXXFLAGS_OVERRIDE := -Wno-strict-aliasing
LLVM_CXXFLAGS := $(CXXFLAGS) `llvm-config-3.8 --cxxflags` $(CXXFLAGS_OVERRIDE)
LLVM_LDFLAGS := `llvm-config-3.8 --ldflags --libs --system-libs`
CLANG_LIBS := \
-Wl,--start-group \
-lclangAST \
-lclangASTMatchers \
-lclangAnalysis \
-lclangBasic \
-lclangDriver \
-lclangEdit \
-lclangFrontend \
-lclangFrontendTool \
-lclangLex \
-lclangParse \
-lclangSema \
-lclangEdit \
-lclangRewrite \
-lclangRewriteFrontend \
-lclangStaticAnalyzerFrontend \
-lclangStaticAnalyzerCheckers \
-lclangStaticAnalyzerCore \
-lclangSerialization \
-lclangToolingCore \
-lclangTooling \
-lclangFormat \
-Wl,--end-group
test_tool.o: test_tool.cpp
$(CXX) $(LLVM_CXXFLAGS) -o $@ -c $<
.PHONY: clean
clean:
rm -f *.o test_tool
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
#include <string>
#include <vector>
using namespace clang::driver;
using namespace clang::tooling;
using namespace llvm;
class IndexerASTConsumer : public clang::ASTConsumer {
public:
IndexerASTConsumer(clang::SourceManager &sourceManager)
: SourceManager(sourceManager) {}
~IndexerASTConsumer() override {}
private:
void HandleTranslationUnit(clang::ASTContext &ctx);
clang::SourceManager &SourceManager;
};
class ASTIndexer : clang::RecursiveASTVisitor<ASTIndexer> {
public:
ASTIndexer(clang::SourceManager &sourceManager)
: SourceManager(sourceManager) {}
void indexDecl(clang::Decl *d) { TraverseDecl(d); }
private:
typedef clang::RecursiveASTVisitor<ASTIndexer> base;
friend class clang::RecursiveASTVisitor<ASTIndexer>;
bool TraverseDecl(clang::Decl *d);
bool VisitDeclRefExpr(clang::DeclRefExpr *e);
void RecordDeclRefExpr(clang::NamedDecl *d, clang::SourceLocation loc,
clang::Expr *e);
bool VisitDecl(clang::Decl *d);
void RecordDeclRef(clang::NamedDecl *d, clang::SourceLocation beginLoc);
clang::SourceManager &SourceManager;
};
bool ASTIndexer::TraverseDecl(clang::Decl *d) { return base::TraverseDecl(d); }
bool ASTIndexer::VisitDeclRefExpr(clang::DeclRefExpr *e) {
RecordDeclRefExpr(e->getDecl(), e->getLocation(), e);
return true;
}
#include <iostream>
void ASTIndexer::RecordDeclRefExpr(clang::NamedDecl *d,
clang::SourceLocation loc, clang::Expr *e) {
assert(d != nullptr);
if (llvm::isa<clang::FunctionDecl>(*d)) {
std::string fileName(SourceManager.getFilename(loc).str());
std::cout << fileName << ":" << (loc.getRawEncoding() - 1) << ":"
<< d->getQualifiedNameAsString() << std::endl;
}
}
bool ASTIndexer::VisitDecl(clang::Decl *d) {
if (clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(d)) {
clang::SourceLocation loc = nd->getLocation();
if (clang::FunctionDecl *fd = llvm::dyn_cast<clang::FunctionDecl>(d)) {
if (fd->getTemplateInstantiationPattern() != NULL) {
} else {
// bool isDefinition = fd->isThisDeclarationADefinition();
if (llvm::isa<clang::CXXMethodDecl>(fd)) {
RecordDeclRef(nd, loc);
} else {
RecordDeclRef(nd, loc);
}
}
}
}
return true;
}
void ASTIndexer::RecordDeclRef(clang::NamedDecl *d,
clang::SourceLocation beginLoc) {
assert(d != NULL);
std::string fileName(SourceManager.getFilename(beginLoc).str());
std::cout << fileName << ":" << (beginLoc.getRawEncoding() - 1) << ":"
<< d->getQualifiedNameAsString() << std::endl;
}
void IndexerASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
ASTIndexer iv(SourceManager);
iv.indexDecl(ctx.getTranslationUnitDecl());
}
class IndexerAction : public clang::ASTFrontendAction {
protected:
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &CI, StringRef InFile) override;
};
std::unique_ptr<clang::ASTConsumer>
IndexerAction::CreateASTConsumer(clang::CompilerInstance &CI,
StringRef InFile) {
return std::unique_ptr<clang::ASTConsumer>(
new IndexerASTConsumer(CI.getSourceManager()));
}
static cl::OptionCategory MyToolCategory("My tool options");
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
static cl::extrahelp MoreHelp("\nMore help text...");
// class ClangCheckActionFactory {
// public:
// std::unique_ptr<clang::ASTConsumer> newASTConsumer() {
// // return clang::CreateASTDumper("", true, false);
// return std::unique_ptr<clang::ASTConsumer>(new IndexerASTConsumer);
// }
// };
int main(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
// Initialize targets for clang module support.
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllAsmParsers();
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
// ClangCheckActionFactory CheckFactory;
std::unique_ptr<FrontendActionFactory> FrontendFactory;
// FrontendFactory = newFrontendActionFactory(&CheckFactory);
// FrontendFactory = newFrontendActionFactory<clang::HTMLPrintAction>();
FrontendFactory = newFrontendActionFactory<IndexerAction>();
return Tool.run(FrontendFactory.get());
}
add_subdirectory(googletest-release-1.8.0)
include_directories(${gtest_SOURCE_DIR}/inlcude ${gtest_SOURCE_DIR})
add_executable(runUnitTests test.cpp)
target_link_libraries(runUnitTests gtest gtest_main)
add_test(NAME helloTest COMMAND ${CMAKE_CURRENT_BINARY_DIR}/runUnitTests)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment