[cfe-dev] slurping include files

Manuel Klimek klimek at google.com
Mon Mar 18 07:59:07 PDT 2013


In general, getting clang to parse code with the code you have is hard :)
That's why we have a tooling library to make that a lot easier. You can
either use that directly, or look at the implementation to get hints around
what you're doing wrong. My guess is that you're not using C++ mode
('namespace' error) and don't go through the driver's include directory
detection.

See:
http://clang.llvm.org/docs/LibTooling.html

The implementation is here:
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Tooling.cpp?view=markup

Cheers,
/Manuel



On Sun, Mar 17, 2013 at 4:04 PM, suppamax <max.giacometti at gmail.com> wrote:

> Sorry, after posting I identified a stupid mistake. I have to reformulate
> the
> question:
>
>
>
> I'd like to scan clang's AST. I started using some sample code provided in
> one tutorial.
>
> My current code is
>
> #include <iostream>
>
> #include "llvm/Support/raw_ostream.h"
> #include "llvm/Support/Host.h"
> #include "llvm/Support/Casting.h"
>
> #include "clang/Basic/DiagnosticOptions.h"
> #include "clang/Frontend/TextDiagnosticPrinter.h"
>
> #include "clang/Basic/LangOptions.h"
> #include "clang/Basic/FileSystemOptions.h"
>
> #include "clang/Basic/SourceManager.h"
> #include "clang/Lex/HeaderSearch.h"
> #include "clang/Basic/FileManager.h"
>
> #include "clang/Frontend/Utils.h"
>
> #include "clang/Basic/TargetOptions.h"
> #include "clang/Basic/TargetInfo.h"
> #include "clang/Basic/Version.h"
>
> #include "clang/Lex/Preprocessor.h"
> #include "clang/Frontend/FrontendOptions.h"
>
> #include "clang/Basic/IdentifierTable.h"
> #include "clang/Basic/Builtins.h"
>
> #include "clang/AST/ASTContext.h"
> #include "clang/AST/ASTConsumer.h"
> #include "clang/AST/RecursiveASTVisitor.h"
> #include "clang/Sema/Sema.h"
> #include "clang/AST/DeclBase.h"
> #include "clang/AST/Type.h"
> #include "clang/AST/Decl.h"
> #include "clang/Sema/Lookup.h"
> #include "clang/Sema/Ownership.h"
> #include "clang/AST/DeclGroup.h"
>
> #include "clang/Parse/Parser.h"
>
> #include "clang/Parse/ParseAST.h"
> #include "clang/Frontend/CompilerInstance.h"
>
> #include "clang/Rewrite/Core/Rewriter.h"
> #include "clang/Rewrite/Frontend/Rewriters.h"
>
> using namespace clang;
> using namespace std;
>
> // By implementing RecursiveASTVisitor, we can specify which AST nodes
> // we're interested in by overriding relevant methods.
> class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>
> {
> public:
> //  MyASTVisitor() : {}
> //  MyASTVisitor(Rewriter &R)
> //      : TheRewriter(R)
> //  {}
>
>     bool VisitStmt(clang::Stmt *s) {
> //      llvm::errs() << "Visiting statement\n";
> //      if (clang::isa<clang::BinaryOperator>(s)) {
> //          if (cast<BinaryOperator>(s)->isAssignmentOp() == true) {
> //              // blablabla
> //          }
> //      }
>         return true;
>     }
>
>     bool VisitBinaryOperator(BinaryOperator* bo) {
>         if (bo->isAssignmentOp() == true) {
>             llvm::errs() << "Visiting assignment ";
>             Expr *LHS;
>             LHS = bo->getLHS();
>             DeclRefExpr* dre;
>             if ((dre = dyn_cast<DeclRefExpr>(LHS))) {
>                 string name = (dre->getNameInfo()).getName().getAsString();
>                 llvm::errs() << "to " << name;
>             }
>             if (ArraySubscriptExpr* ase =
> dyn_cast<ArraySubscriptExpr>(LHS))
> {
>                 Expr *arrayBase = ase->getBase()->IgnoreParenCasts();
>                 if ((dre = dyn_cast<DeclRefExpr>(arrayBase))) {
>                     string name =
> (dre->getNameInfo()).getName().getAsString();
>                     llvm::errs() << "to array " << name;
>                 }
>             }
>             llvm::errs() << "\n";
>         }
>         return true;
>     }
>
>     bool shouldVisitTemplateInstantiations() const {
>         llvm::errs() << "PIPPOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO" <<
> "\n";
>         return true; }
>
>     bool VisitCXXOperatorCallExprs(CXXOperatorCallExpr *e) {
>         llvm::errs() << "Visiting cxxoperatorcall" << "\n";
>         return true;
>     }
>
>     bool VisitCXXConstructorDecl(CXXConstructorDecl *c) {
>         llvm::errs() << "Visiting CXXConstructorDecl" << "\n";
>         return true;
>     }
>
>     bool VisitDeclRefExpr(DeclRefExpr* expr) {
>         string name = (expr->getNameInfo()).getName().getAsString();
>         llvm::errs() << name << "\n";
>         return true;
>     }
>
>     bool VisitVarDecl(VarDecl *v) {
>         llvm::errs() << "Visiting declaration of variable " <<
> v->getDeclName().getAsString() << "\n";
>         llvm::errs() << "  type: " <<
> v->getTypeSourceInfo()->getType().getTypePtr()->getTypeClassName();
>         if
> (v->getTypeSourceInfo()->getType().getTypePtr()->isFloatingType()
> == true) {
>             llvm::errs() << " -> float";
>         }
>
> if(v->getTypeSourceInfo()->getType().getTypePtr()->isConstantArrayType() ==
> true) {
>             llvm::errs() << " of ";
>             llvm::errs() <<
> v->getTypeSourceInfo()->getType().getAsString();
>             llvm::errs() << " size ";
>             llvm::APInt arraySize =
>
> cast<ConstantArrayType>(v->getTypeSourceInfo()->getType().getTypePtr())->getSize();
>             llvm::errs() << arraySize;
>         }
>         if(v->getTypeSourceInfo()->getType().getTypePtr()->isPointerType()
> == true) {
>             llvm::errs() << " to " <<
> v->getTypeSourceInfo()->getType().getAsString();
>
>         }
>         llvm::errs() << "\n";
>         return true;
>     }
>
>   bool VisitTypedefDecl(clang::TypedefDecl *d) {
>         llvm::errs() << "Visiting " << d->getDeclKindName() << " " <<
> d->getName() << "\n";
>
>         return true; // returning false aborts the traversal
>     }
>
>     bool VisitFunctionDecl(FunctionDecl *f) {
>         llvm::errs() << "Visiting function " <<
> f->getNameInfo().getName().getAsString() << "\n";
>
>         return true;
>     }
>
>
>
> private:
> //  Rewriter &TheRewriter;
> };
>
>
> // Implementation of the ASTConsumer interface for reading an AST produced
> // by the Clang parser.
> class MyASTConsumer : public ASTConsumer
> {
> public:
>     MyASTConsumer() : Visitor() {}
> //  MyASTConsumer(Rewriter &R)
> //      : Visitor(R)
> //  {}
>
>     // Override the method that gets called for each parsed top-level
>     // declaration.
>     virtual bool HandleTopLevelDecl(DeclGroupRef DR) {
>         for (DeclGroupRef::iterator b = DR.begin(), e = DR.end();
>                  b != e; ++b)
>             // Traverse the declaration using our AST visitor.
>             Visitor.TraverseDecl(*b);
>         return true;
>     }
>
> private:
>     MyASTVisitor Visitor;
> };
>
>
> int main(int argc, char** argv)
> {
>     if (argc < 2) {
>         llvm::errs() << "Usage: rewritersample <filename> libs\n";
>         return 1;
>     }
>
>     clang::DiagnosticOptions diagnosticOptions;
>     clang::TextDiagnosticPrinter *pTextDiagnosticPrinter =
>         new clang::TextDiagnosticPrinter(
>             llvm::outs(),
>             &diagnosticOptions);
>     llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> pDiagIDs;
>     clang::DiagnosticsEngine *pDiagnosticsEngine =
>         new clang::DiagnosticsEngine(pDiagIDs,
>             &diagnosticOptions,
>             pTextDiagnosticPrinter);
>
>     clang::LangOptions languageOptions;
>     clang::FileSystemOptions fileSystemOptions;
>     clang::FileManager fileManager(fileSystemOptions);
>
>     clang::SourceManager sourceManager(
>         *pDiagnosticsEngine,
>         fileManager);
>
>     llvm::IntrusiveRefCntPtr<clang::HeaderSearchOptions>
> headerSearchOptions(new clang::HeaderSearchOptions());
>         headerSearchOptions->ResourceDir = "/opt/llvm_build" "/lib/clang/"
> CLANG_VERSION_STRING;
>     // <Warning!!> -- Platform Specific Code lives here
>     // This depends on A) that you're running linux and
>     // B) that you have the same GCC LIBs installed that
>     // I do.
>     // Search through Clang itself for something like this,
>     // go on, you won't find it. The reason why is Clang
>     // has its own versions of std* which are installed under
>     // /usr/local/lib/clang/<version>/include/
>     // See somewhere around Driver.cpp:77 to see Clang adding
>     // its version of the headers to its include path.
>         for (int i = 2; i < argc; i++) {
>             headerSearchOptions->AddPath(argv[i],
>
> clang::frontend::Angled,
>                                                                      false,
>
>  false);
>         }
>     // </Warning!!> -- End of Platform Specific Code
>
>     clang::TargetOptions targetOptions;
>     targetOptions.Triple = llvm::sys::getDefaultTargetTriple();
>
>     clang::TargetInfo *pTargetInfo =
>         clang::TargetInfo::CreateTargetInfo(
>             *pDiagnosticsEngine,
>             &targetOptions);
>
>     clang::HeaderSearch headerSearch(headerSearchOptions,
>                                      fileManager,
>                                      *pDiagnosticsEngine,
>                                      languageOptions,
>                                      pTargetInfo);
>     clang::CompilerInstance compInst;
>
>     llvm::IntrusiveRefCntPtr<clang::PreprocessorOptions> pOpts( new
> clang::PreprocessorOptions());
>     clang::Preprocessor preprocessor(
>         pOpts,
>         *pDiagnosticsEngine,
>         languageOptions,
>         pTargetInfo,
>         sourceManager,
>         headerSearch,
>         compInst);
>
>     clang::FrontendOptions frontendOptions;
>     clang::InitializePreprocessor(
>         preprocessor,
>         *pOpts,
>         *headerSearchOptions,
>         frontendOptions);
>
>     const clang::FileEntry *pFile = fileManager.getFile(
>         argv[1]);
>     sourceManager.createMainFileID(pFile);
>
>     const clang::TargetInfo &targetInfo = *pTargetInfo;
>
>     clang::IdentifierTable identifierTable(languageOptions);
>     clang::SelectorTable selectorTable;
>
>     clang::Builtin::Context builtinContext;
>     builtinContext.InitializeTarget(targetInfo);
>     clang::ASTContext astContext(
>         languageOptions,
>         sourceManager,
>         pTargetInfo,
>         identifierTable,
>         selectorTable,
>         builtinContext,
>         0 /* size_reserve*/);
>    MyASTConsumer astConsumer;
>
>     clang::Sema sema(
>         preprocessor,
>         astContext,
>         astConsumer);
>
>     pTextDiagnosticPrinter->BeginSourceFile(languageOptions,
> &preprocessor);
>     clang::ParseAST(preprocessor, &astConsumer, astContext);
>     pTextDiagnosticPrinter->EndSourceFile();
>     return 0;
> }
>
> I run the executable in this way
>
> ./ast_analyzer infile.cpp /usr/include/c++/4.6
> /usr/include/c++/4.6/i686-linux-gnu /usr/include/c++/4.6/parallel/
> /usr/include/c++/4.6/tr1 /usr/include/i386-linux-gnu/c++/4.6
> /usr/include/c++/4.6 /usr/include
> /usr/src/linux-headers-3.2.0-35/include/linux
> /usr/src/linux-headers-3.2.0-35/include
>
> where infile.cpp begins with
>
> #include <iostream>
>
> and I obtain the following error
>
> In file included from input04.c:1:
> In file included from /usr/include/c++/4.6/iostream:40:
> In file included from /usr/include/c++/4.6/ostream:40:
> In file included from /usr/include/c++/4.6/ios:39:
> In file included from /usr/include/c++/4.6/iosfwd:41:
> /usr/include/c++/4.6/bits/stringfwd.h:43:1: error: unknown type name
> 'namespace'
> namespace std _GLIBCXX_VISIBILITY(default)
> ^
> /usr/include/c++/4.6/bits/stringfwd.h:43:43: error: expected ';' after top
> level    declarator
> namespace std _GLIBCXX_VISIBILITY(default)
>                                       ^
> In file included from input04.c:1:
> In file included from /usr/include/c++/4.6/iostream:40:
> In file included from /usr/include/c++/4.6/ostream:40:
> In file included from /usr/include/c++/4.6/ios:42:
> In file included from /usr/include/c++/4.6/bits/localefwd.h:42:
> In file included from
> /usr/include/c++/4.6/i686-linux-gnu/bits/c++locale.h:42:
> In file included from /usr/include/c++/4.6/clocale:44:
> /usr/include/locale.h:30:10: fatal error: 'bits/locale.h' file not found
> #include <bits/locale.h>
>          ^
>
> Could you please help clarifying?
>
>
>
>
> --
> View this message in context:
> http://clang-developers.42468.n3.nabble.com/slurping-include-files-tp4031016p4031017.html
> Sent from the Clang Developers mailing list archive at Nabble.com.
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130318/5404aebc/attachment.html>


More information about the cfe-dev mailing list