Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add find labels #1

Merged
merged 3 commits into from
Jun 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions find_labels/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.10)
project(find_labels)

find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_definitions(${LLVM_DEFINITIONS})
link_directories(${LLVM_LIBRARY_DIRS})
llvm_map_components_to_libnames(llvm_libs x86asmparser bitreader support mc option profiledata)

add_executable(find_labels main.cpp)
target_include_directories(find_labels PRIVATE ${LLVM_INCLUDE_DIRS})
target_link_libraries(find_labels PRIVATE
clangFrontend
clangSerialization
clangDriver
clangTooling
clangParse
clangSema
clangAnalysis
clangRewriteFrontend
clangRewrite
clangEdit
clangAST
clangLex
clangBasic
clangASTMatchers
${llvm_libs})
set_target_properties(find_labels PROPERTIES COMPILE_FLAGS -fno-rtti)
target_compile_options(find_labels PRIVATE -g)
32 changes: 32 additions & 0 deletions find_labels/ex.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <memory>

class Labels{};

class Machine{
public:
std::shared_ptr<Labels> m_labels;
};

class test: public Machine{

public:
void run(){
auto t = std::make_shared<Labels>();
m_labels = t; // can match

m_labels = t; // can't match?
}
//can't match run3?
void run3(){
auto t = std::make_shared<Labels>();
m_labels = t;

m_labels = t;
}

void run2(){
auto t = m_labels; // can match

auto t2 = m_labels; // can't match?
}
};
110 changes: 110 additions & 0 deletions find_labels/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "clang/AST/Stmt.h"
#include "llvm/Support/CommandLine.h"
#include <set>
using namespace clang::tooling;
using namespace llvm;
using namespace clang;
using namespace clang::ast_matchers;

// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static llvm::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");

auto LabelMatcher = memberExpr(member(hasName("m_labels"))).bind("func");

std::set<std::string> func_names;
class labels_matcher : public MatchFinder::MatchCallback
{
public:
void run(const MatchFinder::MatchResult &Result)
{

ASTContext *Context = Result.Context;
const MemberExpr *FS = Result.Nodes.getNodeAs<MemberExpr>("func");
// We do not want to convert header files!
if (!FS || !Context->getSourceManager().isWrittenInMainFile(FS->getLocStart()))
return;
const auto &SM = Result.SourceManager;
const auto &Loc = FS->getLocStart();
auto ast_list = Context->getParents(*FS);
std::stack<clang::ast_type_traits::DynTypedNode> nodes;
for (auto &&ast : ast_list)
{
nodes.push(ast);
}
while (!nodes.empty())
{
auto &&node = nodes.top();
nodes.pop();
if (auto method = node.get<CXXMethodDecl>())
{
std::string func_name = method->getNameAsString();
std::string record_name = method->getParent()->getNameAsString();

auto record = method->getParent();
bool is_derived_from_machine = false;

llvm::SmallPtrSet<const CXXRecordDecl *, 4> Bases;
auto Collect = [&Bases](const CXXRecordDecl *Base) {
Bases.insert(Base);
return true;
};
record->forallBases(Collect);
for (auto &&base : Bases)
{
if (base->getNameAsString() == "Machine")
{
is_derived_from_machine = true;
break;
}
}
if (is_derived_from_machine)
{
func_name = record_name + "::" + func_name;
if (func_names.find(func_name) == func_names.end())
{
func_names.insert(func_name);
llvm::outs() << func_name << "\n";
}
}
break;
}
else
{
auto node_parents = Context->getParents(node);
for (const auto &sub_node : node_parents)
{
nodes.push(sub_node);
}
}
}
}
};

int main(int argc, const char **argv)
{
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());

labels_matcher Printer;
MatchFinder Finder;
Finder.addMatcher(LabelMatcher, &Printer);

return Tool.run(newFrontendActionFactory(&Finder).get());
}