[cfe-dev] Linking files while using Clang AST matchers to implement a call graph

FarSight Studios via cfe-dev cfe-dev at lists.llvm.org
Wed Dec 26 22:41:49 PST 2018


Thank you so much for your help. I will check these options.

I was able to make a connection between nodes located in different ASTs
using Name Mangling.
Every function, and parameter has its own unique mangled name. I am getting
these names from MangleContext and pragmatically connect the functions
later in my application. It seems to work fine.


On Tue, Dec 25, 2018 at 10:47 PM Gábor Márton <martongabesz at gmail.com>
wrote:

> > How I can get to the definition to a callee function from a caller
> location which located in a different source file (different AST)?
>
> AFAIK you have two options, under the hoods both of them use the
> ASTImporter class in Clang.
> 1) Use the "-ast-merge" option of cc1, which will merge all top level
> declarations of the given AST(PCH) file into the actual ASTContext and then
> the original compiler action will be executed. You may merge as many files
> as you want this way.
> 2) Use CrossTranslationUnitContext::getCrossTUDefinition() from the CTU
> library to load a function definition from an external AST file and merge
> it into the the original AST. Clang static analyzer is a client of the CTU
> library, so you may find in the static analyzer code how we use it
> (CallEvent.cpp).
>
> Hope this helps,
> Gabor
>
> On Tue, Dec 25, 2018 at 8:57 AM FarSight Studios via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
>
>> Dear all,
>>
>> I am trying to implement an ability to keep track of reads and writes to
>> a variables and objects. The object can be passed by reference or by
>> pointer to other functions.
>> I am using CLang AST matcher for this task.
>> My solution seems to work, but only when all the functions are located in
>> the same source file.
>> When functionA calls functionB, whose definition is located in another
>> cpp file, I am unable to get the location of the definition of functionB, I
>> only able to get the declaration which located in its header file.
>>
>> My questions are:
>> How I can get to the definition to a callee function from a caller
>> location which located in a different source file (different AST)?
>> Do I need to somehow pass the linkage stage to make it work?
>>
>> I have seen in other posts that CLang libTooling does not support Cross
>> Translation Unit feature.
>> I also seen that LibClang allowed to impenitent this by using Unified
>> Symbol Resolution. Does libTooling offer something like that?
>>
>> Is there any other option to getting to function definition when more
>> than one source file is used?
>>
>>
>>
>> I have searched the web for a few days to find any solution with no luck.
>> Any help will be much appreciated.
>>
>> Thank you
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> Here is more details about how and what I am trying to accomplish. It is
>> a bit LONG so please don't read it if you don't have time:
>> -------------------------------------------
>>
>> I wrote two matchers:
>> One for matching all the write operations to a parameter inside a funcion:
>> binaryOperator(
>> isAssignmentOperator(),
>> hasLHS(ignoringParenImpCasts(
>> anyOf(
>>
>> unaryOperator(hasUnaryOperand(ignoringParenImpCasts(declRefExpr(to(parmVarDecl().bind("parmVarDecl")))))),
>> declRefExpr(to(parmVarDecl().bind("parmVarDecl"))),
>>
>> arraySubscriptExpr(hasLHS(ignoringParenImpCasts(declRefExpr(to(parmVarDecl().bind("parmVarDecl"))))))
>> ))
>> )
>> ,unless(isExpansionInSystemHeader())).bind("binaryOpAssignment")
>>
>> Another one is for matching outer function parameters to the arguments of
>> a callee function.
>> auto innerCallExpr = callExpr(
>> forEachArgumentWithParam(
>>
>> anyOf(unaryOperator(hasDescendant(calleeArgVarDecl)),calleeArgVarDecl),parmVarDecl().bind("calleeParam")),
>>
>> callee(functionDecl().bind("calleeFunc")),unless(isExpansionInSystemHeader())).bind("callExpr");
>>
>> auto outerFuncDect =
>> functionDecl(forEachDescendant(innerCallExpr)).bind("outerFunc");
>>
>>
>> Using these two matchers allows me to build a graph in which I create:
>> 1) Node for each function-parameter pairs (named FUNC-NAME_PARAM-NAME)
>> 2) Relation for each function call in which the parameter is passed to
>> another function.
>>
>> For example, given the following functions:
>>
>> void useSwap(int &p_1, int &p_2) {
>>
>>     swap(p_1, p_2, 1);
>> }
>>
>> void swap(int &x, int &y, int junk) {
>>     int temp;
>>     temp = x;
>>     x = y;             // << SOURCE_CODE_WRITE_LOCATION_OF_x
>>     y = temp;
>>
>>     return;
>> }
>>
>> I can follow useSwap's function parameter with the folowing graph nodes
>> and relations:
>>
>> (useSwap_p_1) -[:CALLS]-> (swap_x) -[:WRITES]->
>> (NODE_FOR_SOURCE_CODE_WRITE_LOCATION_OF_x)
>>
>>
>> For building this proof of concept I have used the LibASTMatchers
>> tutorial from https://clang.llvm.org/docs/LibASTMatchersTutorial.html
>> In that tutorial, CommonOptionParser, ClangTool are used, and the Tool
>> runs with a matcher.
>> If I pass few source files as agrument to the application, an AST created
>> for each of these files individualy.
>> I cannot map the funcions from one AST to another so my call chain is
>> broken.
>>
>> I tryed to pass a the following compilation database file as an argumet
>> to the application:
>> [
>> {
>> "directory": "/home/test",
>> "command": "g++ -I/usr/include/c++/5
>> -I/usr/include/x86_64-linux-gnu/c++/5 -I/usr/include/c++/5/backward
>> -I/usr/local/include -I/usr/include/x86_64-linux-gnu -I/usr/include
>> -std=c++11 /home/test/file1.cpp",
>> "file": "/home/test/file1.cpp"
>> }
>> ,
>> {
>> "directory": "/home/test",
>> "command": "g++ -I/usr/include/c++/5
>> -I/usr/include/x86_64-linux-gnu/c++/5 -I/usr/include/c++/5/backward
>> -I/usr/local/include -I/usr/include/x86_64-linux-gnu -I/usr/include
>> -std=c++11 /home/test/file2.cpp",
>> "file": "/home/test/file2.cpp"
>> }
>> ]
>>
>> Got the following error and warnings and linkage stage failed.
>>
>> warning: /home/test/compile_commands.json: 'linker' input unused
>> [-Wunused-command-line-argument]
>> warning: argument unused during compilation: '-I /usr/include/c++/5'
>> [-Wunused-command-line-argument]
>> warning: argument unused during compilation: '-I
>> /usr/include/x86_64-linux-gnu/c++/5' [-Wunused-command-line-argument]
>> warning: argument unused during compilation: '-I
>> /usr/include/c++/5/backward' [-Wunused-command-line-argument]
>> warning: argument unused during compilation: '-I /usr/local/include'
>> [-Wunused-command-line-argument]
>> warning: argument unused during compilation: '-I
>> /usr/include/x86_64-linux-gnu' [-Wunused-command-line-argument]
>> warning: argument unused during compilation: '-I /usr/include'
>> [-Wunused-command-line-argument]
>> error: unable to handle compilation, expected exactly one compiler job in
>> ''
>> Error while processing /home/test/compile_commands.json.
>>
>> Replacing the "command" section with somethin like "clang++ -c
>> /home/test/file1.cpp" also did not work. I got the following error:
>>
>> warning:
>> /home/dev/projects/samlaCode/clang-tool/examples/compile_commands.json:
>> 'linker' input unused [-Wunused-command-line-argument]
>> warning: argument unused during compilation: '-c'
>> [-Wunused-command-line-argument]
>> error: unable to handle compilation, expected exactly one compiler job in
>> ''
>> Error while processing
>> /home/dev/projects/samlaCode/clang-tool/examples/compile_commands.json.
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>

-- 
-------------------------------------
FarSight Studios
http://design.shadas.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20181227/0efca020/attachment-0001.html>


More information about the cfe-dev mailing list