How to use Clang LibTooling multiple times - c++

Minimul source that use Clang LibTooling which is a very common way:
#include "pch.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "clang/Driver/Options.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include <iostream>
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace llvm;
class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
public:
explicit ExampleVisitor(CompilerInstance *CI) {}
};
class ExampleASTConsumer : public ASTConsumer {
private:
CompilerInstance *CI;
public:
explicit ExampleASTConsumer(CompilerInstance *CI) : CI(CI) {}
virtual void HandleTranslationUnit(ASTContext &Context) {
ExampleVisitor(CI).TraverseDecl(Context.getTranslationUnitDecl());
}
};
class ExampleFrontendAction : public ASTFrontendAction {
public:
virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) {
return std::unique_ptr<ASTConsumer>(new ExampleASTConsumer(&CI));
}
};
void run(int argc, const char **argv, llvm::cl::OptionCategory& tc) {
CommonOptionsParser op(argc, argv, tc);
ClangTool Tool(op.getCompilations(), op.getSourcePathList());
std::cout <<"getSourcePathList.size="<< op.getSourcePathList().size()<<"\n";
int result = Tool.run(newFrontendActionFactory<ExampleFrontendAction>().get());
}
int main(int argc, const char **argv) {
llvm::cl::OptionCategory tc1("c1");
llvm::cl::OptionCategory tc2("c2");
llvm::cl::OptionCategory tc3("c3");
run(argc, argv,tc1);
run(argc, argv,tc2);
run(argc, argv,tc3);
std::cin.get();
return 0;
}
the parameters to debug the application is:
"the_only_source_file_to_scan.cpp" --
which is fine.
The output is (from the method "run" above main()):
getSourcePathList.size=1
getSourcePathList.size=2
getSourcePathList.size=3
The problem is that main() calls run() 3 times with the same above parameter which contains only 1 source file to scan, but each time the size of the source-to-scan list stored in CommonOptionsParser increase by one (every item in the list is the same file input from argv), it just seems to append the source file to scan to the list each time.
Everything above is saved in newly created temporary variables in each run, then how and why does LibTooling keep states of the last run and how to "reset" these states?

use FixedCompilationDatabase could circumvent this problem, it can run multiple clangTool in one process

The above code use CommonOptionsParser, whose code is in
clang\lib\Tooling\CommonOptionsParser.cpp
in the method CommonOptionsParser::init there is:
static cl::list<std::string> SourcePaths(...);
Each invocation will add its sources to this static variable. So it is this local static variable that cause the memory of the previous invocations. In each invocation this local static variable is modified by cl::ParseCommandLineOptions in some unkown way since it is not passed into cl::ParseCommandLineOptions at all. After SourcePaths is modified (i.e. sources of the current invocation are added to SourcePaths which may already contain sources of previous invocations), it is finally copied into a instance variable.
BTW #AbaoZhang's clue helps me find the location, indeed CommonOptionsParser::init use FixedCompilationDatabase interally but not for the above situation.

static cl::list<std::string> SourcePaths(...);
#jw_ Yes This code makes problem.
You can fix this.
for (auto iter = llvm::cl::AllSubCommands->OptionsMap.begin(); iter != llvm::cl::AllSubCommands->OptionsMap.end(); iter++)
{
iter->getValue()->setDefault();
}
for (auto iter = llvm::cl::AllSubCommands->PositionalOpts.begin(); iter != llvm::cl::AllSubCommands->PositionalOpts.end(); iter++)
{
(*iter)->setDefault();
}
for (auto iter = llvm::cl::AllSubCommands->SinkOpts.begin(); iter != llvm::cl::AllSubCommands->SinkOpts.end(); iter++)
{
(*iter)->setDefault();
}

Related

Deconstruct const pointer?

It's probably very basic but I am stuck and simply don't know what the problem is.
The main code is predefined as a task. The goal is to use const as much as possible. The following constructor is just supposed to copy the literal string to the const m_data and that works fine but I am not able to free the memory - it always leaves 1 block. What am I missing?
main.cpp
#include <iostream>
#include "immstring.hpp"
using namespace std;
using namespace Util;
int main()
{
const ImmutableString s1("Hello");
}
immu.hpp
#include <cstring>
namespace Util {
class ImmutableString {
public:
ImmutableString(const char* src);
~ImmutableString();
private:
char* const m_data;
};
}
immu.cpp
#include "immstring.hpp"
#include <iostream>
#include <cstring>
namespace Util
{
ImmutableString::ImmutableString(const char* src)
:m_data{strcpy(new char[strlen(src)+1],src)}{}
ImmutableString::~ImmutableString()
{
delete m_data;
}
}
To leave all array memories blocks you have to use delete like this :
delete[] m_data;
Thanks,
Robin.

How to mangle and then demangle a function during LLVM pass?

I have an LLVM pass used to rename functions. Given some source file file.cc, I generate LLVM bitcode as follows:
clang -c -o foo.bc -emit-llvm foo.cc.
I'd like to run an LLVM pass over foo.bc and rename all globals, functions and aliases so that I can output the transformed bitcode to a new file file_renamed.bc, and then link file.bc and file_renamed.bc into a single file, file_linked.bc.
One of my issues I encountered is that simply doing F.setName(F.getName() + "_renamed"), will add the suffix after the mangled name returned by F.getName().
Another issue: I have a function demangle(const std::string &Name) below that successfully demangles Name, but I'm having trouble re-mangling that name.
If there is a better way to rename identifiers in LLVM bitcode, or otherwise link two instances of the same bitcode but still be able to uniquely identify the functions and global variables in each version, feel free to suggest it in your answer.
Here is my LLVM pass. Note that I'm using LLVM 3.4 (it is a dependency for the project I'm working on.)
Headers
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cxxabi.h>
#include <memory>
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeFinder.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Target/Mangler.h"
Code
using namespace llvm;
namespace {
struct FunctionRename : public ModulePass {
static char ID; // Pass identification
FunctionRename() : ModulePass(ID) {}
bool runOnModule(Module &M) override {
// Rename all globals and references to them
for (auto it = M.global_begin(); it != M.global_end(); ++it)
{...}
// Rename all aliases and references to them
for (auto it = M.alias_begin(); it != M.alias_end(); ++it)
{...}
// Rename all functions and references to them
for (auto &F : M)
{
StringRef Name = F.getName();
if (F.isDeclaration())
continue;
std::string demangled_name = demangle(Name.str());
std::string new_name = rename(demangled_name);
F.setName(mangle(new_name, &F));
F.setLinkage(GlobalValue::WeakAnyLinkage);
}
return true;
}
std::string demangle(const std::string &Name)
{
int status;
char* demangled_name = NULL;
char* cstr_name = new char[Name.length() + 1];
strcpy(cstr_name, Name.c_str());
demangled_name = __cxxabiv1::__cxa_demangle(cstr_name, NULL, NULL, &status);
if (status != 0)
{
errs() << "Demangling operation failed:\n";
switch (status)
{...}
exit(-1);
}
std::string s(demangled_name);
return s;
}
std::string rename(std::string &Name)
{
std::string search_str = std::string("(");
std::string suffix_str = std::string("_renamed");
size_t i = Name.find_first_of(search_str);
if (i == std::string::npos)
Name.append(suffix_str);
else
Name.insert(i, suffix_str);
return Name;
}
/* PROBLEMATIC FUNCTION */
std::string mangle(const std::string &Name, const GlobalValue *GV)
{
SmallString<256> MangledName(StringRef(Name));
Mangler m;
m.getNameWithPrefix((SmallVectorImpl<char>&) MangledName, GV, false, true);
Twine T;
StringRef S = T.toStringRef((SmallVectorImpl<char>&) MangledName);
return S.str();
}
};
}
// Register Pass
char FunctionRename::ID = 0;
static RegisterPass<FunctionRename> X("functionrename", "Function Rename Pass");
You cannot easily mangle the C++ identifiers just from string. You need to have proper C++ AST. In fact, I don't see why you'd need that mangle / demangle thing at all. Since you're working at LLVM IR level you should not bother with language details (like original unmangled name) at all.

How to find move constructors in codebase using Clang AST tools?

Following up a comment from this question: how can I find move constructors in C++ codebase using Clang AST tools? (find definitions / declarations only)
The Clang AST matcher now provides this functionality with the isMoveConstructor matcher. Here's an example program:
#include <iostream>
#include "clang/AST/AST.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
static llvm::cl::OptionCategory ToolingSampleCategory("move constructor finder");
struct MoveCtorHandler : public clang::ast_matchers::MatchFinder::MatchCallback {
public:
virtual void run(clang::ast_matchers::MatchFinder::MatchResult const& result) override {
using namespace clang;
// reject things from include files
ASTContext *ctx = result.Context;
const CXXConstructorDecl *decl = result.Nodes.getStmtAs<CXXConstructorDecl>("moveCtor");
auto loc = decl->getLocation();
if (!ctx->getSourceManager().isInMainFile(loc)) {
return;
}
std::cout << "found a move constructor at "
<< loc.printToString(ctx->getSourceManager())
<< std::endl;
}
};
int main(int argc, char const **argv) {
using namespace clang;
using namespace clang::tooling;
using namespace clang::ast_matchers;
CommonOptionsParser opt(argc, argv, ToolingSampleCategory);
RefactoringTool tool(opt.getCompilations(), opt.getSourcePathList());
MatchFinder finder;
// set up callbacks
MoveCtorHandler move_ctor_handler;
finder.addMatcher(constructorDecl(isMoveConstructor()).bind("moveCtor"),
&move_ctor_handler);
if (int result = tool.run(newFrontendActionFactory(&finder).get())) {
return result;
}
return 0;
}
When applied to the following input:
#include <vector>
struct foo {
foo() {}
foo(foo && other) : v_(std::move(other.v_)) {}
private:
std::vector<int> v_;
};
int main() {
}
It produces the output:
found a move constructor at xxx.cpp:5:5

Boost test setup error: memory access violation

I am getting the above error while running the executable after compiling and running the following file.
#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/bind.hpp>
#include <boost/test/unit_test_log.hpp>
#include <boost/filesystem/fstream.hpp>
#include "index/DatabaseGroup.hpp"
using namespace boost::unit_test;
namespace indexing {
class ForwardDBTest {
/// A pointer to the database group object.
DatabaseGroup& databaseGroup;
std::string databaseName;
public:
~ForwardDBTest() {
}
;
ForwardDBTest(DatabaseGroup& databaseGroup_, std::string dbName) :
databaseGroup(databaseGroup_), databaseName(dbName) {
}
void boostTestCreateDB() {
databaseGroup.createDatabase(databaseName, databaseName);
}
};
class testSuites: public test_suite {
public:
testSuites() :
test_suite("test_suite") {
std::string db_location = "home/girijag/ripe/ripe_db";
std::cout << "hello" << std::endl;
int concurrency = 0;
std::string db_cache_policy = "AllMem";
boost::shared_ptr<DatabaseGroup> db = boost::shared_ptr<DatabaseGroup>(
new DatabaseGroup(db_location, concurrency, db_cache_policy));
std::string dbName = "DB1";
boost::shared_ptr<ForwardDBTest> instance(
new ForwardDBTest(*db, dbName));
test_case* boostTestCreateDB_test_case = BOOST_CLASS_TEST_CASE(
&ForwardDBTest::boostTestCreateDB, instance);
add(boostTestCreateDB_test_case);
}
~testSuites() {
}
;
};
test_suite* init_unit_test_suite(int argc, char** argv) {
test_suite* suite(BOOST_TEST_SUITE("Master Suite"));
suite->add(new testSuites());
return suite;
}
}'
Please let me know how should i resolve this?
i am getting errors as below:-
Test setup error: memory access violation at address: 0x00000021: no mapping at fault address
I have been struggling from past 2 days to figure out whats my issue
There are a number of disturbing things in the code, and some formatting seems have to been lost when posting the question, otherwise there is no chance it compiles. (For example, }’ ?!)
For starters, you shouldn’t place init_unit_test_suite(int, char**) in the indexing namespace, and subsequently there is no point in defining BOOST_TEST_MAIN - you will end up with multiple definition of the said init_unit_test_suite(int, char**) method.
In your case, the suite should be simply registered in the master test suite, there is no need to return a pointer to it from the method.
Here’s a minimal example that you can work with an extend for your purpose. It follows your structure, but omits non-relevant details:
#include <boost/test/included/unit_test.hpp>
#include <iostream>
using namespace boost::unit_test;
namespace indexing {
class ForwardDBTest {
public:
void boostTestCreateDB() { std::cout << __FUNCTION__ << std::endl; }
};
class TestSuite : public test_suite {
public:
TestSuite() : test_suite("test_suite") {
boost::shared_ptr<ForwardDBTest> instance(new ForwardDBTest);
add(BOOST_CLASS_TEST_CASE(&ForwardDBTest::boostTestCreateDB, instance));
}
};
} // namespace indexing
test_suite* init_unit_test_suite(int, char**) {
framework::master_test_suite().add(new indexing::TestSuite);
return 0;
}
/* Output:
Running 1 test case...
boostTestCreateDB
*** No errors detected
*/

How do I call a class by passing it's object and member function to another function in c++?

How do I execute a member's function by passing the object and the member's function to another function in c++. I do understand the answer to my question is out there; however, I do not know what this is called. So far I created 2 files, exeFunc.h and exeFunc.cpp. Their code consist of:
exeFunc.h
/*
File: exeFunc.h
Header file for exeFunc Library.
*/
#ifndef EXEFUNC_H
#define EXEFUNC_H
#include "mbed.h"
#include "msExtensions.h"
#include "cfExtensions.h"
#include <map>
class exeFunc
{
public:
exeFunc(msExtensions &msExt, cfExtensions &cfExt);
private:
void _splitFuncFromCmd();
void _attachCallback();
msExtensions &_msExt;
cfExtensions &_cfExt;
//FunctionPointer _p;
};
#endif
exeFunc.cpp
/*
File: exeFunc.cpp
Execute functions in other Sensor libraries/classes
Constructor
*/
#include "mbed.h"
#include "ConfigFile.h"
#include "msExtensions.h"
#include "cfExtensions.h"
#include "exeFunc.h"
#include <map>
#include <string>
using namespace std;
exeFunc::exeFunc(msExtensions &msExt, cfExtensions &cfExt) : _msExt(msExt), _cfExt(cfExt)
{
//_cfExt.checkConfigForFirstStart();
//_p.attach(&_cfExt, &cfExtensions::checkConfigForFirstStart);
//_p.call();
}
void exeFunc::_splitFuncFromCmd()
{
}
void exeFunc::_attachCallback()
{
}
I wrote a completed example, may helps
class MyClass
{
public:
MyClass(int b)
:_b(b)
{
}
int Foo(int a)
{
return a * _b;
}
int _b;
};
typedef int (MyClass::*MFP)(int);
int get_result(MyClass* obj, MFP mfp)
{
int r = (obj->*mfp)(5); // 30
return r;
}
int _tmain(int argc, _TCHAR* argv[])
{
MFP mfp = &MyClass::Foo;
MyClass m(6);
get_result(&m, mfp);
return 0;
}
You call it by another function.if you have an independent function.
To be honesty your question is not completely clear.However :
int F(int,int,int);
int g();
//main scope
F(g(),a,b)