[cfe-dev] slurping include files

suppamax max.giacometti at gmail.com
Sun Mar 17 15:22:34 PDT 2013


 0 down vote favorite
	

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[2],
                                                                    
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

where infile.cpp begins with #include

and I obtain the following error

/usr/include/c++/4.6/iostream:39:10: fatal error: 'bits/c++config.h' file
not found
#include <bits/c++config.h>

And I don't understand why, since /usr/include/c++/4.6/i686-linux-gnu
includes bits/c++config.h

Could you please help clarifying?




--
View this message in context: http://clang-developers.42468.n3.nabble.com/slurping-include-files-tp4031016.html
Sent from the Clang Developers mailing list archive at Nabble.com.



More information about the cfe-dev mailing list