[cfe-dev] Parsing C++ Header file
Raghavendra K
raghavendrak at huawei.com
Thu May 30 00:14:55 PDT 2013
Hi,
Related to parsing header files, code is as below,
logic is in this function ==> Decl* VisitRecordDecl(RecordDecl *D),
In this function, pCXXRecord->getDescribedClassTemplate(); //is always NULL
Pls hlep how to proceed further
regards
ragha
#include <cstdio>
#include <string>
#include <sstream>
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/Rewriters.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/CommandLine.h"
using namespace clang;
using namespace std;
FILE* flogs;
clang::LangOptions* planguageOptions = NULL;
// By implementing RecursiveASTVisitor, we can specify which AST nodes
// we're interested in by overriding relevant methods.
class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>
{
public:
MyASTVisitor(Rewriter &R)
: TheRewriter(R)
{}
Decl* VisitRecordDecl(RecordDecl *D)
{
if(D->isClass() == true)
{
if(strstr(D->getQualifiedNameAsString().c_str(),"std::")
||
strstr(D->getQualifiedNameAsString().c_str(),"__gnu_cxx::"))
{
return D;
}
fprintf(flogs,"ClassName=%s\n",D->getQualifiedNameAsString().c_str());
RecordDecl::field_iterator classfieldItr = D->field_begin();
RecordDecl::field_iterator classfieldItrEnd = D->field_end();
for(;classfieldItr != classfieldItrEnd; classfieldItr++)
{
//Array Handling Todo
if((*classfieldItr)->getType().getTypePtrOrNull()->isArrayType() == true)
{
//TODO:how to get the base type and chk if it is simple or complex type
fprintf(flogs,"FieldName=%s is Array Type\n",classfieldItr->getQualifiedNameAsString().c_str());
}
//Array Handling Todo
if((*classfieldItr)->getType().getTypePtrOrNull()->isStructureOrClassType() == false)
{
fprintf(flogs,"FieldName=%s is not Complex Type,Its Name=%s,\n",classfieldItr->getQualifiedNameAsString().c_str(),(*classfieldItr)->getType().getTypePtrOrNull()->getTypeClassName());
//generate code by calling encode_(i);
if((*classfieldItr)->getType().getTypePtrOrNull()->isPointerType() == true)
{
continue;
}
fprintf(flogs,"****encodeBasic(%s)\n",classfieldItr->getQualifiedNameAsString().c_str());
}
else
{
fprintf(flogs,"FieldName=%s is Complex Type,Its Name=%s,\n",classfieldItr->getQualifiedNameAsString().c_str(),(*classfieldItr)->getType().getTypePtrOrNull()->getTypeClassName());
fprintf(flogs,"Desugar=%s",(*classfieldItr)->getType().getTypePtrOrNull()->getUnqualifiedDesugaredType()->getTypeClassName());
CXXRecordDecl* fieldClass = (*classfieldItr)->getType().getTypePtrOrNull()->getUnqualifiedDesugaredType()->getAsCXXRecordDecl();
if(fieldClass != NULL)
{
if(fieldClass->getQualifiedNameAsString()== "std::string"
||
fieldClass->getQualifiedNameAsString()== "std::basic_string")
{
fprintf(flogs,"****encodeString\n");
continue;
}
if( fieldClass->getQualifiedNameAsString()== "std::map")
{
fprintf(flogs,"****encodeMAP\n");
RecordDecl* oriClass = ((*classfieldItr)->getParent());
if(oriClass)
{
CXXRecordDecl* pCXXRecord = (CXXRecordDecl*)oriClass->getDefinition();
if(pCXXRecord)
{
fprintf(flogs,"****1\n");
ClassTemplateDecl* classTemp = pCXXRecord->getDescribedClassTemplate(); //is always NULL
if(classTemp)
{
fprintf(flogs,"****2\n");
TemplateParameterList* tempList = classTemp->getTemplateParameters();
if(tempList)
fprintf(flogs,"****SOFAR SO GOOD\n");
}
}
}
continue;
}
if(fieldClass->getQualifiedNameAsString()== "std::list")
{
fprintf(flogs,"****encodeList\n");
continue;
}
//anything else i.e full object
fprintf(flogs,"**** %s.encode\n",fieldClass->getQualifiedNameAsString().c_str());
}
}
}
}
return D;
}
private:
Rewriter &TheRewriter;
};
// Implementation of the ASTConsumer interface for reading an AST produced
// by the Clang parser.
class MyASTConsumer : public ASTConsumer
{
public:
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;
};
static llvm::cl::list<string> directorySearchPathList("I", llvm::cl::value_desc("Directory_"),llvm::cl::Prefix,llvm::cl::desc("<Specify Include Directory Search Path>"));
static llvm::cl::opt<string> InputFilename(llvm::cl::Positional,llvm::cl::value_desc("FileName_"),llvm::cl::Required,llvm::cl::desc("<input file>"));
int main(int argc, char *argv[])
{
flogs = fopen("logs","w");
llvm::cl::ParseCommandLineOptions(argc, argv);
printf("****INPUTFileName=%s\n",InputFilename.c_str());
// CompilerInstance will hold the instance of the Clang compiler for us,
// managing the various objects needed to run the compiler.
CompilerInstance TheCompInst;
clang::LangOptions& languageOptions = TheCompInst.getLangOpts();
planguageOptions = &languageOptions;
CompilerInvocation::setLangDefaults(languageOptions,IK_CXX);
HeaderSearchOptions& headOptions = TheCompInst.getHeaderSearchOpts();
for (int i = 0; i < directorySearchPathList.size(); ++i)
{
// fprintf(flogs,"****HEAD=%s",directorySearchPathList[i].c_str());
headOptions.AddPath(directorySearchPathList[i],clang::frontend::Angled,true,false,false);
}
//headOptions.AddSystemHeaderPrefix("/usr/include/c++/4.1.2",true);
headOptions.Verbose = 1;
TheCompInst.createDiagnostics(0, 0);
// Initialize target info with the default triple for our platform.
TargetOptions* TO = new TargetOptions;
TO->Triple = llvm::sys::getDefaultTargetTriple();
TargetInfo *TI = TargetInfo::CreateTargetInfo( TheCompInst.getDiagnostics(), *TO);
TheCompInst.setTarget(TI);
TheCompInst.createFileManager();
FileManager &FileMgr = TheCompInst.getFileManager();
TheCompInst.createSourceManager(FileMgr);
SourceManager &SourceMgr = TheCompInst.getSourceManager();
TheCompInst.createPreprocessor();
TheCompInst.createASTContext();
// A Rewriter helps us manage the code rewriting task.
Rewriter TheRewriter;
TheRewriter.setSourceMgr(SourceMgr, TheCompInst.getLangOpts());
// Set the main file handled by the source manager to the input file.
const FileEntry *FileIn = FileMgr.getFile(InputFilename.c_str());
SourceMgr.createMainFileID(FileIn);
TheCompInst.getDiagnosticClient().BeginSourceFile( TheCompInst.getLangOpts(), &TheCompInst.getPreprocessor());
// Create an AST consumer instance which is going to get called by
// ParseAST.
MyASTConsumer TheConsumer(TheRewriter);
// Parse the file to AST, registering our consumer as the AST consumer.
ParseAST(TheCompInst.getPreprocessor(), &TheConsumer, TheCompInst.getASTContext());
printf("everything ok");
// At this point the rewriter's buffer should be full with the rewritten
// file contents.
const RewriteBuffer *RewriteBuf =
TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID());
llvm::outs() << string(RewriteBuf->begin(), RewriteBuf->end());
//TheCompInst->setTarget(NULL);
return 0;
}
More information about the cfe-dev
mailing list