Need Help in resolving exception while calling FunctionDecl Method

Hi there,

Just now started with Clang. so, this might silly question.

I am getting exception while calling FunctionDecl->getNameAsString() or FunctionDecl->****getName().str();

Exception Details:-

Type:- “Exception thrown: read access violation.”

Points to:-

File:- include\clang\AST\DeclarationNames.h

StoredNameKind getStoredNameKind() const {
return static_cast(Ptr & PtrMask);
}

Actual Code

Main.cpp

static llvm::cl::OptionCategory ToolingSampleCategory(“Tooling Sample”);

int main(int argc, const char **argv)
{

CommonOptionsParser OptionsParser(argc, argv, ToolingSampleCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());

DeclarationMatcher funcMatcher = functionDecl( ).bind(“functionMatcher”);

FunctionHelper funcHelper;
funcHelper.setNodeBindName(“functionMatcher”);
funcHelper.MatchFinder.addMatcher(funcMatcher, &funcHelper);

Tool.run(newFrontendActionFactory(&(funcHelper.MatchFinder)).get());

llvm::SmallVector<const clang::FunctionDecl*, 5U> allFuncDecl = funcHelper.getAllFunctionDecl();
const FunctionDecl* fnDecl = allFuncDecl[0];
cout << fnDecl->getName().str(); /* Exception Generated while calling method. If same method called from run method then it works. */

return 0;
}

FunctionalHelper.h

typedef struct _FunctionInfo
{
std::string funcName;
std::string sourceFileName;
unsigned int paramCount;
}FunctionInfo;

class FunctionHelper : public clang::ast_matchers::MatchFinder::MatchCallback {

std::vector m_vec_FunctionInfo;
std::string m_str_NodeBindName;
llvm::SmallVector<const clang::FunctionDecl*,5> m_vec_FunctionDecl;

private:
void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override
{
const clang::FunctionDecl* tempFuncDecl = Result.Nodes.getNodeAsclang::FunctionDecl(m_str_NodeBindName.c_str());

// tempFuncDecl ->getName().str(); //from here, it’s works.

if (tempFuncDecl)
{
FunctionInfo tempFuncInfo;
fillFunctionInfo(tempFuncDecl, tempFuncInfo);

m_vec_FunctionInfo.push_back(tempFuncInfo);
m_vec_FunctionDecl.push_back(tempFuncDecl);
}
}

public:
clang::ast_matchers::MatchFinder MatchFinder;
void setNodeBindName(std::string nodeBindName) { m_str_NodeBindName = nodeBindName; };

std::vector getFuncInfoForAllMatchedNodes()
{
return m_vec_FunctionInfo;
}

llvm::SmallVector<const clang::FunctionDecl*,5> getAllFunctionDecl()
{
return m_vec_FunctionDecl;
}

static std::string getFunctionName(const clang::FunctionDecl* funcDecl)
{
if (!funcDecl) { return “”; }
return funcDecl->getNameAsString();
}

static std::string getSourceFileName(const clang::FunctionDecl* funcDecl)
{
if (!funcDecl) { return “”; }
return funcDecl->getASTContext().getSourceManager().getFilename(funcDecl->getLocation()).str();
}

static unsigned int getParamsCount(const clang::FunctionDecl* funcDecl)
{
if (!funcDecl) { return 0; }
return funcDecl->getNumParams();
}

static void fillFunctionInfo(const clang::FunctionDecl* funcDecl, FunctionInfo &funcInfo)
{
if (!funcDecl) { return; }
funcInfo.funcName = FunctionHelper::getFunctionName(funcDecl);
funcInfo.sourceFileName = FunctionHelper::getSourceFileName(funcDecl);
funcInfo.paramCount = FunctionHelper::getParamsCount(funcDecl);
}
};

Config:- 32bit, Debug
OS:- Windows
Compiled through VS2015.
Clang Version:- latest available. [ I guess 4.0]

So, Need help in resolving issue.
Thanks In Advance.!!

Regards,
Apoorva

Tool.run(newFrontendActionFactory(&(funcHelper.MatchFinder)).get());

As I can guess, newFrontendActionFactory() returns std::unique_ptr which is destructed immediately after this statement is executed. So, it seems like you have a memory use-after-free. Try this instead:

std::unique_ptr<FrontendActionFactory> Factory =
       newFrontendActionFactory(&funcHelper.MatchFinder);
Tool.run(Factory.get());

Does it help?

It is also a good idea to check that your vector is non-empty before getting an element.

27.12.2016 17:57, Apoorva Paneliya via cfe-dev пишет:

Hi Aleksei,

I tried your below suggestion.

std::unique_ptr Factory =
newFrontendActionFactory(&funcHelper.MatchFinder);
Tool.run(Factory.get());

unfortunately, result is same (still, exception is generated).

It is also a good idea to check that your vector is non-empty before getting an element. → Implemented.

Let me know if you have any other suggestion.

thank you very much.!!

Another suggestion is that ASTContext that is used for running your tool dies before Tool.run() is executed.

In FrontendActionFactory::runInvocation a CompilerInstance is created. It has a smart pointer to the created ASTContext. But the CompilerInstance is a local variable and it is destroyed within all its data after invocation ends.
You can try to set a breakpoint on the ASTContext destructor and see the moment where it is destructed and the stack trace.

27.12.2016 22:49, Apoorva Paneliya пишет:

Hi Aleksei,

I had put break point on ASTContext Destructor but somehow, it was not hitting.

After that, I looked at the clang-query code and got a clue. [Just Build AST]

CommonOptionsParser OptionsParser(argc, argv, ToolingSampleCategory);
ClangTool tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());

std::vector<std::unique_ptr> ASTs;
if (tool.buildASTs(ASTs) == 0)
{
cout << "successfully generated AST " << std::endl;
}
else
{
cout << "Failed to Generate AST " << std::endl;
return -1;
}

Thank you very much for giving suggestion.