[cfe-dev] Implement AST visitor, avoid visiting included header files

mats petersson via cfe-dev cfe-dev at lists.llvm.org
Thu Jun 23 10:31:53 PDT 2016


No, I could see your code, but you don't have anything from the SO post in
your code.

So if you describe what the exact PROBLEM is that you are seeing when you
try to implement that, then perhaps someone can help (I have a basic
understanding of AST's and their visitors, but by no means an expert, so if
it's complicated, I may not know how to fix it)

Also, use reply-all when replying, so that here is a copy going to the
mailing list, otherwise someone else may well ask/answer/comment the same
thing again, which is a waste of time.

--
Mats

On 23 June 2016 at 17:56, Andreas Georgiou <antreas_geo at hotmail.com> wrote:

> Sorry I inserted my code as an attachment. I thought you could see that.
> Anyway am pasting in again below.
>
> #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>
> #include <fstream>
>
> using namespace std;
> using namespace clang;
> using namespace clang::driver;
> using namespace clang::tooling;
> using namespace llvm;
>
> Rewriter rewriter;
> int numFunctions = 0;
> int numVariables = 0;
> int numFuncCalls = 0;
>
> ofstream APIs;
> LangOptions LangOpts;
> PrintingPolicy Policy(LangOpts);
>
>
> class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
> private:
>     ASTContext *astContext; // used for getting additional AST info
> //SourceManager *SM;
> public:
>     explicit ExampleVisitor(CompilerInstance *CI)
>       : astContext(&(CI->getASTContext())) //SM(&(CI->getASTContext()))//
> directly initialize private members
>     {
> }
>     virtual bool VisitVarDecl(VarDecl *var)
>     {
>         numVariables++;
>         string varName = var->getQualifiedNameAsString();
> string varType = var->getType().getAsString();
> cout << "Found variable declaration: " << varName << " of type " <<
> varType << "\n";
> APIs << varType << ", ";
>         return true;
>     }
>
>     virtual bool VisitFunctionDecl(FunctionDecl *func)
>     {
>         numFunctions++;
>         string funcName = func->getNameInfo().getName().getAsString();
> string funcType = func->getResultType().getAsString();
> cout << "Found function declaration: " << funcName << " of type " <<
> funcType << "\n";
> APIs << "\n\n" << funcName <<": ";
> APIs << funcType << ", ";
>         return true;
>     }
>
>     virtual bool VisitStmt(Stmt *st)
>     {
> if (CallExpr *call = dyn_cast<CallExpr>(st))
> {
>   numFuncCalls++;
>           FunctionDecl *func_decl = call->getDirectCallee();
>             string funcCall =
> func_decl->getNameInfo().getName().getAsString();
> cout << "Found function call: " << funcCall << " with arguments ";
> APIs << funcCall << ", ";
>   for(int i=0, j = call->getNumArgs(); i<j; i++)
>       {
>         string TypeS;
>         raw_string_ostream s(TypeS);
>         call->getArg(i)->printPretty(s, 0, Policy);
>         APIs<< s.str() << ", ";
> cout<< s.str() << ", ";
>       }
> cout << "\n";
>         }
>         return true;
>     }
> };
>
>
> class ExampleASTConsumer : public ASTConsumer
> {
> private:
>     ExampleVisitor *visitor; // doesn't have to be private
>
> public:
>     // override the constructor in order to pass CI
>     explicit ExampleASTConsumer(CompilerInstance *CI)
>         : visitor(new ExampleVisitor(CI)) // initialize the visitor
>     { }
>
>     // override this to call our ExampleVisitor on the entire source file
>     virtual void HandleTranslationUnit(ASTContext &Context) {
>         /* we can use ASTContext to get the TranslationUnitDecl, which is
>              a single Decl that collectively represents the entire source
> file */
>         visitor->TraverseDecl(Context.getTranslationUnitDecl());
>     }
> };
>
>
>
> class ExampleFrontendAction : public ASTFrontendAction {
> public:
>     virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef
> file) {
>         return new ExampleASTConsumer(&CI); // pass CI pointer to
> ASTConsumer
>     }
> };
>
>
>
> int main(int argc, const char **argv)
> {
>     if (argc < 3)
>     {
>     cerr << "usage: " << argv[0] << " <filename> --" << endl;
>     return EXIT_FAILURE;
>     }
>
>     APIs.open ("API.txt");
>     // parse the command-line args passed to your code
>     CommonOptionsParser op(argc, argv);
>     // create a new Clang Tool instance (a LibTooling environment)
>     ClangTool Tool(op.getCompilations(), op.getSourcePathList());
>
>     // run the Clang Tool, creating a new FrontendAction (explained below)
>     int result =
> Tool.run(newFrontendActionFactory<ExampleFrontendAction>());
>
>     cout << "\nFound " << numFunctions << " functions.\n" << "Found " <<
> numVariables << " variable declarations.\n" << "Found " << numFuncCalls <<
> " function calls.\n" ;
>     APIs.close();
>     return result;
> }
>
>
> I have found this solution in stackoverflow but I cannot make it work.
>
> http://stackoverflow.com/questions/10454075/avoid-traversing-included-system-libaries
> My code is based on this tutorial:
>
> https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-i-introduction/
>
> The thing is. I want my AST visitor to parse the files but not to print
> any information not originated from the main file.
> For example if there is a struct definition i "something.h" header file I
> dont want it to be printed in the console.
>
>
> Thank you,
> Andreas Georgiou
>
> ------------------------------
> From: mats at planetcatfish.com
> Date: Thu, 23 Jun 2016 16:08:05 +0100
> Subject: Re: [cfe-dev] Implement AST visitor, avoid visiting included
> header files
> To: antreas_geo at hotmail.com
> CC: cfe-dev at lists.llvm.org
>
>
> What in the solution from SO is it that you can't make work? I can't see
> the implementation in your code, so I can't explain what, if anything is
> wrong with your code.
>
> Clearly, the compiler will have to parse header files to be able to
> compile any [non-trivial] source file, since there are declarations and
> definitions there that are required to compile the whole source. So the
> only way to determine if the AST is part of your main file is to use a
> filter to say "is this from the main file or from a header" on each (top
> level) AST entry, which is what the SO code does.
>
> --
> Mats
>
> On 23 June 2016 at 13:28, Andreas Georgiou via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
>
> Hello,
>
> As you can see I want to implement an AST visitor to extract some specific
> nodes from the AST.
> Unfortunately my code traverses also the included header files which is
> something that I dont want because it prints me everything about them which
> is not what I want.
> For example I want to extract every function declaration or variable
> declaration and their correspondig types.
>
> I have found this solution in stackoverflow but I cannot make it work.
>
> http://stackoverflow.com/questions/10454075/avoid-traversing-included-system-libaries
> My code is based on this tutorial:
>
> https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-i-introduction/
>
> Please also find attached my code.
>
> Thank you for your help.
> Andreas Georgiou
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160623/4c55a25e/attachment.html>


More information about the cfe-dev mailing list