build: lib for the parser

lib_parser is new, its use by app and test

<description>
This commit is contained in:
Andreas Stallinger
2015-12-09 14:34:14 +01:00
parent a6648cafeb
commit 59d6143fbf
35 changed files with 169 additions and 216 deletions
@@ -0,0 +1,36 @@
#include "data/parser/cxx/ASTAction.h"
#include "clang/Lex/Preprocessor.h"
#include "data/parser/cxx/CommentHandler.h"
#include "data/parser/cxx/PreprocessorCallbacks.h"
ASTAction::ASTAction(ParserClient* client, FileRegister* fileRegister)
: m_client(client)
, m_fileRegister(fileRegister)
, m_commentHandler(client, fileRegister)
{
}
ASTAction::~ASTAction()
{
}
std::unique_ptr<clang::ASTConsumer> ASTAction::CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile)
{
return std::unique_ptr<clang::ASTConsumer>(new ASTConsumer(&compiler.getASTContext(), m_client, m_fileRegister));
}
bool ASTAction::BeginSourceFileAction(clang::CompilerInstance& compiler, llvm::StringRef filePath)
{
clang::Preprocessor& preprocessor = compiler.getPreprocessor();
preprocessor.addPPCallbacks(
llvm::make_unique<PreprocessorCallbacks>(compiler.getSourceManager(), m_client, m_fileRegister));
preprocessor.addCommentHandler(&m_commentHandler);
return true;
}
void ASTAction::EndSourceFileAction()
{
m_fileRegister->markParsingIncludeFilesParsed();
}
@@ -0,0 +1,30 @@
#ifndef AST_ACTION_H
#define AST_ACTION_H
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "data/parser/cxx/ASTConsumer.h"
#include "data/parser/cxx/CommentHandler.h"
#include "utility/file/FileRegister.h"
class ASTAction : public clang::ASTFrontendAction
{
public:
explicit ASTAction(ParserClient* client, FileRegister* fileRegister);
virtual ~ASTAction();
protected:
virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile);
virtual bool BeginSourceFileAction(clang::CompilerInstance& compiler, llvm::StringRef filePath);
virtual void EndSourceFileAction();
private:
ParserClient* m_client;
FileRegister* m_fileRegister;
CommentHandler m_commentHandler;
};
#endif // AST_ACTION_H
@@ -0,0 +1,16 @@
#include "data/parser/cxx/ASTActionFactory.h"
ASTActionFactory::ASTActionFactory(ParserClient* client, FileRegister* fileRegister)
: m_client(client)
, m_fileRegister(fileRegister)
{
}
ASTActionFactory::~ASTActionFactory()
{
}
clang::FrontendAction* ASTActionFactory::create()
{
return new ASTAction(m_client, m_fileRegister);
}
@@ -0,0 +1,22 @@
#ifndef AST_ACTION_FACTORY
#define AST_ACTION_FACTORY
#include "clang/Tooling/Tooling.h"
#include "data/parser/cxx/ASTAction.h"
#include "utility/file/FileRegister.h"
class ASTActionFactory : public clang::tooling::FrontendActionFactory
{
public:
explicit ASTActionFactory(ParserClient* client, FileRegister* fileRegister);
virtual ~ASTActionFactory();
virtual clang::FrontendAction* create();
private:
ParserClient* m_client;
FileRegister* m_fileRegister;
};
#endif // AST_ACTION_FACTORY
@@ -0,0 +1,189 @@
#include "data/parser/cxx/ASTBodyVisitor.h"
#include "clang/AST/DeclCXX.h"
ASTBodyVisitor::ASTBodyVisitor(ASTBodyVisitorClient* client, clang::FunctionDecl* functionDecl)
: m_client(client)
, m_functionDecl(functionDecl)
, m_varDecl(nullptr)
{
}
ASTBodyVisitor::ASTBodyVisitor(ASTBodyVisitorClient* client, clang::DeclaratorDecl* varDecl)
: m_client(client)
, m_functionDecl(nullptr)
, m_varDecl(varDecl)
{
}
ASTBodyVisitor::~ASTBodyVisitor()
{
}
void ASTBodyVisitor::VisitStmt(clang::Stmt* stmt)
{
VisitChildren(stmt);
}
void ASTBodyVisitor::VisitChildren(clang::Stmt* stmt)
{
for (clang::Stmt::child_iterator it = stmt->child_begin(); it != stmt->child_end(); it++)
{
if (*it)
{
static_cast<ASTBodyVisitor*>(this)->Visit(*it);
}
}
}
void ASTBodyVisitor::VisitCallExpr(clang::CallExpr* expr)
{
bool ignore = false;
// check if lambda call
if (clang::isa<clang::CXXOperatorCallExpr>(expr))
{
clang::Decl* calleeDecl = expr->getCalleeDecl();
if (calleeDecl && clang::isa<clang::CXXMethodDecl>(calleeDecl))
{
clang::CXXRecordDecl* recordDecl = clang::dyn_cast<clang::CXXMethodDecl>(calleeDecl)->getParent();
ignore = recordDecl->isLambda();
}
}
if (!ignore)
{
if (m_functionDecl)
{
m_client->VisitCallExprInDeclBody(m_functionDecl, expr);
}
else
{
m_client->VisitCallExprInDeclBody(m_varDecl, expr);
}
}
VisitStmt(expr);
}
void ASTBodyVisitor::VisitCXXConstructExpr(clang::CXXConstructExpr* expr)
{
if (m_functionDecl)
{
m_client->VisitCXXConstructExprInDeclBody(m_functionDecl, expr);
}
else
{
m_client->VisitCXXConstructExprInDeclBody(m_varDecl, expr);
}
VisitStmt(expr);
}
void ASTBodyVisitor::VisitExplicitCastExpr(clang::ExplicitCastExpr* expr)
{
if (m_functionDecl)
{
m_client->VisitExplicitCastExprInDeclBody(m_functionDecl, expr);
}
else
{
m_client->VisitExplicitCastExprInDeclBody(m_varDecl, expr);
}
VisitStmt(expr);
}
void ASTBodyVisitor::VisitCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* expr)
{
if (m_functionDecl)
{
m_client->VisitCXXTemporaryObjectExprInDeclBody(m_functionDecl, expr);
}
else
{
m_client->VisitCXXTemporaryObjectExprInDeclBody(m_varDecl, expr);
}
VisitStmt(expr);
}
void ASTBodyVisitor::VisitCXXNewExpr(clang::CXXNewExpr* expr)
{
if (m_functionDecl)
{
m_client->VisitCXXNewExprInDeclBody(m_functionDecl, expr);
}
else
{
m_client->VisitCXXNewExprInDeclBody(m_varDecl, expr);
}
VisitStmt(expr);
}
void ASTBodyVisitor::VisitMemberExpr(clang::make_ptr<clang::MemberExpr>::type expr)
{
if (expr->getMemberDecl()->getKind() == clang::Decl::Kind::Field)
{
if(m_functionDecl)
{
m_client->VisitMemberExprInDeclBody(m_functionDecl, expr);
}
else
{
m_client->VisitMemberExprInDeclBody(m_varDecl, expr);
}
}
VisitStmt(expr);
}
void ASTBodyVisitor::VisitDeclRefExpr(clang::DeclRefExpr* expr)
{
if (m_functionDecl)
{
m_client->VisitDeclRefExprInDeclBody(m_functionDecl, expr);
}
else
{
m_client->VisitDeclRefExprInDeclBody(m_varDecl, expr);
}
if (expr->getDecl()->getKind() == clang::Decl::Var && expr->getDecl()->isDefinedOutsideFunctionOrMethod())
{
if (m_functionDecl)
{
m_client->VisitGlobalVariableExprInDeclBody(m_functionDecl, expr);
}
else
{
m_client->VisitGlobalVariableExprInDeclBody(m_varDecl, expr);
}
}
else if (expr->getDecl()->getKind() == clang::Decl::EnumConstant)
{
if (m_functionDecl)
{
m_client->VisitEnumExprInDeclBody(m_functionDecl, expr);
}
else
{
m_client->VisitEnumExprInDeclBody(m_varDecl, expr);
}
}
VisitStmt(expr);
}
void ASTBodyVisitor::VisitDeclStmt(clang::DeclStmt* stmt)
{
for (clang::Decl* decl : stmt->decls())
{
if (clang::isa<clang::VarDecl>(decl))
{
m_client->VisitVarDeclInDeclBody(m_functionDecl, clang::dyn_cast<clang::VarDecl>(decl));
}
}
VisitStmt(stmt);
}
@@ -0,0 +1,31 @@
#ifndef AST_BODY_VISITOR
#define AST_BODY_VISITOR
#include "clang/AST/StmtVisitor.h"
#include "data/parser/cxx/ASTBodyVisitorClient.h"
class ASTBodyVisitor: public clang::StmtVisitor<ASTBodyVisitor>
{
public:
ASTBodyVisitor(ASTBodyVisitorClient* client, clang::FunctionDecl* functionDecl);
ASTBodyVisitor(ASTBodyVisitorClient* client, clang::DeclaratorDecl* varDecl);
virtual ~ASTBodyVisitor();
void VisitStmt(clang::Stmt* stmt);
void VisitChildren(clang::Stmt* stmt);
void VisitCallExpr(clang::CallExpr* expr);
void VisitCXXConstructExpr(clang::CXXConstructExpr* expr);
void VisitExplicitCastExpr(clang::ExplicitCastExpr* expr);
void VisitCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* expr);
void VisitCXXNewExpr(clang::CXXNewExpr* expr);
void VisitMemberExpr(clang::make_ptr<clang::MemberExpr>::type expr);
void VisitDeclRefExpr(clang::make_ptr<clang::DeclRefExpr>::type expr);
void VisitDeclStmt(clang::DeclStmt* stmt);
private:
ASTBodyVisitorClient* m_client;
clang::FunctionDecl* m_functionDecl;
clang::DeclaratorDecl* m_varDecl;
};
#endif // AST_BODY_VISITOR
@@ -0,0 +1,9 @@
#include "data/parser/cxx/ASTBodyVisitorClient.h"
ASTBodyVisitorClient::ASTBodyVisitorClient()
{
}
ASTBodyVisitorClient::~ASTBodyVisitorClient()
{
}
@@ -0,0 +1,35 @@
#ifndef AST_BODY_VISITOR_CLIENT_H
#define AST_BODY_VISITOR_CLIENT_H
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
class ASTBodyVisitorClient
{
public:
ASTBodyVisitorClient();
virtual ~ASTBodyVisitorClient();
virtual void VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallExpr* expr) = 0;
virtual void VisitCallExprInDeclBody(clang::DeclaratorDecl* decl, clang::CallExpr* expr) = 0;
virtual void VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) = 0;
virtual void VisitDeclRefExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr) = 0;
virtual void VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clang::CXXConstructExpr* expr) = 0;
virtual void VisitCXXConstructExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXConstructExpr* expr) = 0;
virtual void VisitExplicitCastExprInDeclBody(clang::FunctionDecl* decl, clang::ExplicitCastExpr* expr) = 0;
virtual void VisitExplicitCastExprInDeclBody(clang::DeclaratorDecl* decl, clang::ExplicitCastExpr* expr) = 0;
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::FunctionDecl* decl, clang::CXXTemporaryObjectExpr* expr) = 0;
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXTemporaryObjectExpr* expr) = 0;
virtual void VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr) = 0;
virtual void VisitCXXNewExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXNewExpr* expr) = 0;
virtual void VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr) = 0;
virtual void VisitMemberExprInDeclBody(clang::DeclaratorDecl* decl, clang::MemberExpr* expr) = 0;
virtual void VisitGlobalVariableExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) = 0;
virtual void VisitGlobalVariableExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr) = 0;
virtual void VisitEnumExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) = 0;
virtual void VisitEnumExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr) = 0;
virtual void VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDecl* varDecl) = 0;
};
#endif // AST_BODY_VISITOR_CLIENT_H
@@ -0,0 +1,17 @@
#include "data/parser/cxx/ASTConsumer.h"
#include "data/parser/ParserClient.h"
ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister)
: m_visitor(context, client, fileRegister)
{
}
ASTConsumer::~ASTConsumer()
{
}
void ASTConsumer::HandleTranslationUnit(clang::ASTContext& context)
{
m_visitor.TraverseDecl(context.getTranslationUnitDecl());
}
@@ -0,0 +1,24 @@
#ifndef AST_CONSUMER_H
#define AST_CONSUMER_H
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "utility/file/FileRegister.h"
#include "data/parser/cxx/ASTVisitor.h"
class ASTConsumer
: public clang::ASTConsumer
{
public:
explicit ASTConsumer(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister);
virtual ~ASTConsumer();
virtual void HandleTranslationUnit(clang::ASTContext& context);
private:
ASTVisitor m_visitor;
};
#endif // AST_CONSUMER_H
File diff suppressed because it is too large Load Diff
+107
View File
@@ -0,0 +1,107 @@
#ifndef AST_VISITOR_H
#define AST_VISITOR_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "utility/file/FileRegister.h"
#include "data/parser/cxx/ASTBodyVisitorClient.h"
#include "data/parser/ParserClient.h"
class ASTVisitor
: public clang::RecursiveASTVisitor<ASTVisitor>
, public ASTBodyVisitorClient
{
public:
ASTVisitor(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister);
virtual ~ASTVisitor();
// Left for debugging purposes. Uncomment to see a colored ast-dump of the parsed file.
// virtual bool VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl)
// {
// decl->dump();
// return true;
// }
// RecursiveASTVisitor implementation
virtual bool VisitStmt(const clang::Stmt* statement); // avoid visiting
virtual bool VisitTypedefDecl(clang::TypedefDecl* declaration); // typedefs
virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl* declaration); // structs, classes and inheritance
virtual bool VisitVarDecl(clang::VarDecl* declaration); // global variables and static fields
virtual bool VisitFieldDecl(clang::FieldDecl* declaration); // fields
virtual bool VisitFunctionDecl(clang::FunctionDecl* declaration); // functions
virtual bool VisitParmVarDecl(clang::ParmVarDecl* declaration);
virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl* declaration); // methods
virtual bool VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration); // initialization list
virtual bool VisitNamespaceDecl(clang::NamespaceDecl* declaration); // namespaces
virtual bool VisitEnumDecl(clang::EnumDecl* declaration); // enums
virtual bool VisitEnumConstantDecl(clang::EnumConstantDecl* declaration); // enum fields
virtual bool VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl *declaration);
virtual bool VisitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl *declaration);
virtual bool VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration);
virtual bool VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* declaration);
virtual bool VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declaration);
// ASTBodyVisitorClient implementation
virtual void VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallExpr* expr); // calls
virtual void VisitCallExprInDeclBody(clang::DeclaratorDecl* decl, clang::CallExpr* expr); // calls in initialization of global variables
virtual void VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr);
virtual void VisitDeclRefExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr);
virtual void VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clang::CXXConstructExpr* expr); // constructor calls
virtual void VisitCXXConstructExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXConstructExpr* expr); // constructor calls of global variables
virtual void VisitExplicitCastExprInDeclBody(clang::FunctionDecl* decl, clang::ExplicitCastExpr* expr);
virtual void VisitExplicitCastExprInDeclBody(clang::DeclaratorDecl* decl, clang::ExplicitCastExpr* expr);
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::FunctionDecl* decl, clang::CXXTemporaryObjectExpr* expr);
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXTemporaryObjectExpr* expr);
virtual void VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr); // type use of new operator
virtual void VisitCXXNewExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXNewExpr* expr); // type use of new operator in global space
virtual void VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr); // field usages
virtual void VisitMemberExprInDeclBody(clang::DeclaratorDecl* decl, clang::MemberExpr* expr); // field usages
virtual void VisitGlobalVariableExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr); // global variable usage
virtual void VisitGlobalVariableExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr); // global variable usage
virtual void VisitEnumExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr); // enum field usage
virtual void VisitEnumExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr); // enum field usage in global variable
virtual void VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDecl* varDecl); // type usages
private:
void processFunctionDecl(clang::FunctionDecl* declaration);
void processTemplateArgumentsOfExplicitSpecialization(clang::FunctionDecl* declaration);
void processTemplateArgumentsOfExplicitSpecialization(clang::ClassTemplateSpecializationDecl* specializationDecl);
void processTemplateArguments(clang::DeclRefExpr* expr);
void processTemplateArguments(clang::TemplateSpecializationTypeLoc loc);
bool isLocatedInUnparsedProjectFile(const clang::Decl* declaration) const;
bool isLocatedInProjectFile(const ParseLocation& location) const;
bool isLocatedInProjectFile(const clang::Decl* declaration) const;
ParserClient::AccessType convertAccessType(clang::AccessSpecifier) const;
ParserClient::AbstractionType getAbstractionType(const clang::CXXMethodDecl* methodDecl) const;
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
ParseLocation getParseLocationForTokenAtLocation(const clang::SourceLocation& loc) const;
ParseLocation getParseLocationForTokensInRange(const clang::SourceRange& range) const;
ParseLocation getParseLocationForNamedDecl(const clang::NamedDecl* decl) const;
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
ParseLocation getParseLocationOfRecordBody(clang::CXXRecordDecl* decl) const;
ParseTypeUsage getParseTypeUsage(const clang::TypeLoc& typeLoc, const clang::QualType& type) const;
ParseTypeUsage getParseTypeUsage(const clang::TypeLoc& typeLoc, const std::shared_ptr<DataType> type) const;
ParseTypeUsage getParseTypeUsage(const clang::SourceRange& sourceRange, const std::shared_ptr<DataType> type) const;
ParseTypeUsage getParseTypeUsageOfReturnType(const clang::FunctionDecl* declaration) const;
std::vector<ParseTypeUsage> getParameters(const clang::FunctionDecl* declaration) const;
ParseVariable getParseVariable(const clang::DeclaratorDecl* declaration) const;
ParseFunction getParseFunction(const clang::FunctionDecl* declaration) const;
ParseFunction getParseFunction(const clang::FunctionTemplateDecl* declaration) const;
clang::ASTContext* m_context;
ParserClient* m_client;
FileRegister* m_fileRegister;
};
#endif // AST_VISITOR_H
@@ -0,0 +1,36 @@
#include "data/parser/cxx/CommentHandler.h"
#include "data/parser/ParserClient.h"
#include "utility/file/FileManager.h"
#include "utility/file/FileRegister.h"
CommentHandler::CommentHandler(ParserClient* client, FileRegister* fileRegister)
: m_client(client)
, m_fileRegister(fileRegister)
{
}
CommentHandler::~CommentHandler()
{
}
bool CommentHandler::HandleComment(clang::Preprocessor& preprocessor, clang::SourceRange sourceRange)
{
clang::SourceManager& sourceManager = preprocessor.getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(sourceRange.getBegin(), false);
const clang::PresumedLoc& presumedEnd = sourceManager.getPresumedLoc(sourceRange.getEnd(), false);
FilePath filePath = FilePath(presumedBegin.getFilename());
if (m_fileRegister->getFileManager()->hasFilePath(filePath) && !m_fileRegister->fileIsParsed(filePath))
{
m_client->onCommentParsed(ParseLocation(
presumedBegin.getFilename(),
presumedBegin.getLine(),
presumedBegin.getColumn(),
presumedEnd.getLine(),
presumedEnd.getColumn()
));
}
return false;
}
@@ -0,0 +1,23 @@
#ifndef COMMENT_HANDLER_H
#define COMMENT_HANDLER_H
#include "clang/Lex/Preprocessor.h"
class FileRegister;
class ParserClient;
class CommentHandler
: public clang::CommentHandler
{
public:
CommentHandler(ParserClient* client, FileRegister* fileRegister);
virtual ~CommentHandler();
virtual bool HandleComment(clang::Preprocessor& preprocessor, clang::SourceRange sourceRange);
private:
ParserClient* m_client;
FileRegister* m_fileRegister;
};
#endif // COMMENT_HANDLER_H
@@ -0,0 +1,83 @@
#include "data/parser/cxx/CxxDiagnosticConsumer.h"
#include "clang/Basic/SourceManager.h"
#include "utility/file/FileManager.h"
#include "data/parser/ParseLocation.h"
#include "data/parser/ParserClient.h"
CxxDiagnosticConsumer::CxxDiagnosticConsumer(
clang::raw_ostream &os,
clang::DiagnosticOptions *diags,
ParserClient* client,
const FileManager* fileManager,
bool useLogging
)
: clang::TextDiagnosticPrinter(os, diags)
, m_client(client)
, m_fileManager(fileManager)
, m_isParsingFile(false)
, m_useLogging(useLogging)
{
}
void CxxDiagnosticConsumer::BeginSourceFile(const clang::LangOptions& langOptions, const clang::Preprocessor* preProcessor)
{
if (m_useLogging)
{
clang::TextDiagnosticPrinter::BeginSourceFile(langOptions, preProcessor);
}
m_isParsingFile = true;
}
void CxxDiagnosticConsumer::EndSourceFile()
{
if (m_useLogging)
{
clang::TextDiagnosticPrinter::EndSourceFile();
}
m_isParsingFile = false;
}
void CxxDiagnosticConsumer::HandleDiagnostic(clang::DiagnosticsEngine::Level level, const clang::Diagnostic& info)
{
if (m_useLogging)
{
clang::TextDiagnosticPrinter::HandleDiagnostic(level, info);
}
if (!m_isParsingFile)
{
return;
}
if (level == clang::DiagnosticsEngine::Error || level == clang::DiagnosticsEngine::Fatal)
{
llvm::SmallString<100> messageStr;
info.FormatDiagnostic(messageStr);
std::string message = messageStr.str();
std::string filePath;
uint line = 0;
uint column = 0;
if (info.getLocation().isValid() && info.hasSourceManager())
{
const clang::SourceManager& sourceManager = info.getSourceManager();
clang::PresumedLoc presumedLocation = sourceManager.getPresumedLoc(info.getLocation());
filePath = presumedLocation.getFilename();
line = presumedLocation.getLine();
column = presumedLocation.getColumn();
}
// if (m_fileManager->hasFilePath(filePath))
if (m_fileManager)
{
m_client->onError(ParseLocation(filePath, line, column), message);
}
}
}
@@ -0,0 +1,33 @@
#ifndef CXX_DIAGNOSTIC_CONSUMER
#define CXX_DIAGNOSTIC_CONSUMER
#include "clang/Frontend/TextDiagnosticPrinter.h"
class FileManager;
class ParserClient;
class CxxDiagnosticConsumer
: public clang::TextDiagnosticPrinter
{
public:
CxxDiagnosticConsumer(
clang::raw_ostream &os,
clang::DiagnosticOptions *diags,
ParserClient* client,
const FileManager* fileManager,
bool useLogging = true
);
void BeginSourceFile(const clang::LangOptions& langOptions, const clang::Preprocessor* preProcessor);
void EndSourceFile();
void HandleDiagnostic(clang::DiagnosticsEngine::Level level, const clang::Diagnostic& info);
private:
ParserClient* m_client;
const FileManager* m_fileManager;
bool m_isParsingFile;
bool m_useLogging;
};
#endif // CXX_DIAGNOSTIC_CONSUMER
@@ -0,0 +1,198 @@
#include "data/parser/cxx/CxxParser.h"
#include "clang/Tooling/Tooling.h"
#include "utility/file/FileManager.h"
#include "utility/file/FileRegister.h"
#include "utility/logging/logging.h"
#include "utility/text/TextAccess.h"
#include "data/parser/cxx/ASTActionFactory.h"
#include "data/parser/cxx/CxxDiagnosticConsumer.h"
namespace
{
static std::vector<std::string> getSyntaxOnlyToolArgs(const std::vector<std::string> &ExtraArgs, llvm::StringRef FileName)
{
std::vector<std::string> Args;
Args.push_back("clang-tool");
Args.push_back("-fsyntax-only");
Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
Args.push_back(FileName.str());
return Args;
}
// custom implementation of clang::runToolOnCodeWithArgs which also sets our custon DiagnosticConsumer
static bool runToolOnCodeWithArgs(
clang::DiagnosticConsumer* DiagConsumer,
clang::FrontendAction *ToolAction,
const llvm::Twine &Code,
const std::vector<std::string> &Args,
const llvm::Twine &FileName = "input.cc",
const clang::tooling::FileContentMappings &VirtualMappedFiles = clang::tooling::FileContentMappings()
)
{
llvm::SmallString<16> FileNameStorage;
llvm::StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
llvm::IntrusiveRefCntPtr<clang::FileManager> Files(new clang::FileManager(clang::FileSystemOptions()));
clang::tooling::ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction, Files.get());
llvm::SmallString<1024> CodeStorage;
Invocation.mapVirtualFile(FileNameRef, Code.toNullTerminatedStringRef(CodeStorage));
for (auto &FilenameWithContent : VirtualMappedFiles)
{
Invocation.mapVirtualFile(FilenameWithContent.first, FilenameWithContent.second);
}
Invocation.setDiagnosticConsumer(DiagConsumer);
return Invocation.run();
}
}
CxxParser::CxxParser(ParserClient* client, const FileManager* fileManager)
: Parser(client)
, m_fileRegister(std::make_shared<FileRegister>(fileManager))
{
}
CxxParser::~CxxParser()
{
}
void CxxParser::parseFiles(const std::vector<FilePath>& filePaths, const Arguments& arguments)
{
setupParsing(filePaths, arguments);
std::vector<std::string> sourcePaths;
for (const FilePath& path : m_fileRegister->getUnparsedSourceFilePaths())
{
sourcePaths.push_back(path.absolute().str());
}
runTool(sourcePaths);
std::vector<FilePath> unparsedHeaders = m_fileRegister->getUnparsedIncludeFilePaths();
for (const FilePath& path : unparsedHeaders)
{
if (!m_fileRegister->includeFileIsParsed(path))
{
runTool(std::vector<std::string>(1, path.str()));
}
}
}
void CxxParser::parseFile(const FilePath& filePath, std::shared_ptr<TextAccess> textAccess, const Arguments& arguments)
{
setupParsing(std::vector<FilePath>(1, filePath), arguments);
std::vector<std::string> args = getCommandlineArguments(arguments);
std::shared_ptr<CxxDiagnosticConsumer> diagnostics = getDiagnostics(arguments);
ASTActionFactory actionFactory(m_client, m_fileRegister.get());
runToolOnCodeWithArgs(diagnostics.get(), actionFactory.create(), textAccess->getText(), args);
}
std::vector<std::string> CxxParser::getCommandlineArguments(const Arguments& arguments) const
{
std::vector<std::string> args;
// verbose
// args.push_back("-v");
// The option -fno-delayed-template-parsing signals that templates that there should
// be AST elements for unused template functions as well.
args.push_back("-fno-delayed-template-parsing");
// The option -c signals that no executable is built.
args.push_back("-c");
// The option '-x c++' treats subsequent input files as C++.
args.push_back("-x");
args.push_back("c++");
args.push_back("-std=c++11");
args.insert(args.begin(), arguments.compilerFlags.begin(), arguments.compilerFlags.end());
for (const FilePath& path : arguments.headerSearchPaths)
{
args.push_back("-I" + path.str());
}
for (const FilePath& path : arguments.systemHeaderSearchPaths)
{
args.push_back("-isystem" + path.str());
}
for (const FilePath& path : arguments.frameworkSearchPaths)
{
args.push_back("-iframework" + path.str());
}
return args;
}
std::shared_ptr<clang::tooling::FixedCompilationDatabase> CxxParser::getCompilationDatabase(
const Arguments& arguments
) const {
// Commandline flags passed to the programm. Everything after '--' will be interpreted by the ClangTool.
std::vector<std::string> args = getCommandlineArguments(arguments);
args.insert(args.begin(), "app");
args.insert(args.begin() + 1, "--");
int argc = args.size();
const char** argv = new const char*[argc];
for (size_t i = 0; i < args.size(); i++)
{
argv[i] = args[i].c_str();
}
std::shared_ptr<clang::tooling::FixedCompilationDatabase> compilationDatabase(
clang::tooling::FixedCompilationDatabase::loadFromCommandLine(argc, argv)
);
delete[] argv;
if (!compilationDatabase)
{
LOG_ERROR("Failed to load compilation database");
return nullptr;
}
return compilationDatabase;
}
std::shared_ptr<CxxDiagnosticConsumer> CxxParser::getDiagnostics(const Arguments& arguments) const
{
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> options = new clang::DiagnosticOptions();
return std::make_shared<CxxDiagnosticConsumer>(
llvm::errs(), &*options, m_client, m_fileRegister->getFileManager(), arguments.logErrors);
}
void CxxParser::setupParsing(const std::vector<FilePath>& filePaths, const Arguments& arguments)
{
m_fileRegister->setFilePaths(filePaths);
m_compilationDatabase = getCompilationDatabase(arguments);
m_diagnostics = getDiagnostics(arguments);
}
void CxxParser::runTool(const std::vector<std::string>& files)
{
clang::tooling::ClangTool tool(*m_compilationDatabase, files);
tool.setDiagnosticConsumer(m_diagnostics.get());
ASTActionFactory actionFactory(m_client, m_fileRegister.get());
tool.run(&actionFactory);
}
FileRegister* CxxParser::getFileRegister()
{
return m_fileRegister.get();
}
ParserClient* CxxParser::getParserClient()
{
return m_client;
}
@@ -0,0 +1,50 @@
#ifndef CXX_PARSER_H
#define CXX_PARSER_H
#include "data/parser/Parser.h"
namespace clang
{
namespace tooling
{
class FixedCompilationDatabase;
}
}
class CxxDiagnosticConsumer;
class FileManager;
class FileRegister;
class TaskParseCxx;
class CxxParser: public Parser
{
public:
CxxParser(ParserClient* client, const FileManager* fileManager);
~CxxParser();
// ParserClient implementation
virtual void parseFiles(const std::vector<FilePath>& filePaths, const Arguments& arguments);
virtual void parseFile(const FilePath& filePath, std::shared_ptr<TextAccess> textAccess, const Arguments& arguments);
private:
std::vector<std::string> getCommandlineArguments(const Arguments& arguments) const;
std::shared_ptr<clang::tooling::FixedCompilationDatabase> getCompilationDatabase(const Arguments& arguments) const;
std::shared_ptr<CxxDiagnosticConsumer> getDiagnostics(const Arguments& arguments) const;
// Accessed by TaskParseCxx
void setupParsing(const std::vector<FilePath>& filePaths, const Arguments& arguments);
void runTool(const std::vector<std::string>& files);
FileRegister* getFileRegister();
ParserClient* getParserClient();
friend class TaskParseCxx;
std::shared_ptr<FileRegister> m_fileRegister;
std::shared_ptr<clang::tooling::FixedCompilationDatabase> m_compilationDatabase;
std::shared_ptr<CxxDiagnosticConsumer> m_diagnostics;
};
#endif // CXX_PARSER_H
@@ -0,0 +1,159 @@
#include "data/parser/cxx/PreprocessorCallbacks.h"
#include "clang/Driver/Util.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Lex/MacroArgs.h"
#include "utility/file/FileManager.h"
#include "utility/file/FileRegister.h"
#include "data/parser/ParserClient.h"
#include "data/parser/ParseLocation.h"
PreprocessorCallbacks::PreprocessorCallbacks(
clang::SourceManager& sourceManager, ParserClient* client, FileRegister* fileRegister
)
: m_sourceManager(sourceManager)
, m_client(client)
, m_fileRegister(fileRegister)
{
}
void PreprocessorCallbacks::FileChanged(
clang::SourceLocation location, FileChangeReason reason, clang::SrcMgr::CharacteristicKind, clang::FileID)
{
if (reason != EnterFile)
{
return;
}
const clang::FileEntry *fileEntry = m_sourceManager.getFileEntryForID(m_sourceManager.getFileID(location));
if (!fileEntry)
{
return;
}
FilePath filePath(fileEntry->getName());
if (m_fileRegister->getFileManager()->hasFilePath(filePath.str()))
{
m_client->onFileParsed(m_fileRegister->getFileManager()->getFileInfo(filePath));
m_fileRegister->markIncludeFileParsing(filePath.str());
}
}
void PreprocessorCallbacks::InclusionDirective(
clang::SourceLocation hashLocation, const clang::Token& includeToken, llvm::StringRef fileName, bool isAngled,
clang::CharSourceRange fileNameRange, const clang::FileEntry* fileEntry, llvm::StringRef searchPath,
llvm::StringRef relativePath, const clang::Module* imported
){
const clang::FileEntry* baseFileEntry = m_sourceManager.getFileEntryForID(m_sourceManager.getFileID(hashLocation));
if (fileEntry && baseFileEntry)
{
std::string baseFilePath = baseFileEntry->getName();
std::string includedFilePath = fileEntry->getName();
const FileManager* fileManager = m_fileRegister->getFileManager();
if (fileManager->hasFilePath(baseFilePath) && fileManager->hasFilePath(includedFilePath) &&
!m_fileRegister->fileIsParsed(baseFilePath))
{
m_client->onFileIncludeParsed(
getParseLocation(fileNameRange.getAsRange()),
fileManager->getFileInfo(baseFilePath),
fileManager->getFileInfo(includedFilePath)
);
}
}
}
void PreprocessorCallbacks::MacroDefined(const clang::Token& macroNameToken, const clang::MacroDirective* macroDirective)
{
const std::string& fileStr = m_sourceManager.getFilename(macroNameToken.getLocation());
if (!fileStr.size())
{
return;
}
FilePath filePath = FilePath(fileStr);
if (m_fileRegister->getFileManager()->hasFilePath(filePath) && !m_fileRegister->fileIsParsed(filePath))
{
// ignore builtin macros
if (m_sourceManager.getSpellingLoc(macroNameToken.getLocation()).printToString(m_sourceManager)[0] == '<')
{
return;
}
NameHierarchy nameHierarchy;
nameHierarchy.push(std::make_shared<NameElement>(macroNameToken.getIdentifierInfo()->getName().str()));
m_client->onMacroDefineParsed(
getParseLocation(macroNameToken), nameHierarchy, getParseLocation(macroDirective->getMacroInfo()));
}
}
void PreprocessorCallbacks::MacroExpands(
const clang::Token& macroNameToken, const clang::MacroDefinition& macroDirective,
clang::SourceRange range, const clang::MacroArgs* args
){
const std::string& fileStr = m_sourceManager.getFilename(macroNameToken.getLocation());
if (!fileStr.size())
{
return;
}
FilePath filePath = FilePath(fileStr);
if (m_fileRegister->getFileManager()->hasFilePath(filePath) && !m_fileRegister->fileIsParsed(filePath))
{
NameHierarchy nameHierarchy;
nameHierarchy.push(std::make_shared<NameElement>(macroNameToken.getIdentifierInfo()->getName().str()));
m_client->onMacroExpandParsed(getParseLocation(macroNameToken), nameHierarchy);
}
}
ParseLocation PreprocessorCallbacks::getParseLocation(const clang::Token& macroNameTok) const
{
clang::SourceLocation location = macroNameTok.getLocation();
return ParseLocation(
m_sourceManager.getFilename(location),
m_sourceManager.getSpellingLineNumber(location),
m_sourceManager.getSpellingColumnNumber(location),
m_sourceManager.getSpellingLineNumber(macroNameTok.getEndLoc()),
m_sourceManager.getSpellingColumnNumber(macroNameTok.getEndLoc()) - 1
);
}
ParseLocation PreprocessorCallbacks::getParseLocation(const clang::MacroInfo* macroInfo) const
{
clang::SourceLocation location = macroInfo->getDefinitionLoc();
clang::SourceLocation endLocation = macroInfo->getDefinitionEndLoc();
return ParseLocation(
m_sourceManager.getFilename(location),
m_sourceManager.getSpellingLineNumber(location),
m_sourceManager.getSpellingColumnNumber(location),
m_sourceManager.getSpellingLineNumber(endLocation),
m_sourceManager.getSpellingColumnNumber(endLocation) - 1
);
}
ParseLocation PreprocessorCallbacks::getParseLocation(const clang::SourceRange& sourceRange) const
{
if (sourceRange.isInvalid())
{
return ParseLocation();
}
const clang::PresumedLoc& presumedBegin = m_sourceManager.getPresumedLoc(sourceRange.getBegin(), false);
const clang::PresumedLoc& presumedEnd = m_sourceManager.getPresumedLoc(sourceRange.getEnd(), false);
return ParseLocation(
presumedBegin.getFilename(),
presumedBegin.getLine(),
presumedBegin.getColumn(),
presumedEnd.getLine(),
presumedEnd.getColumn() - 1
);
}
@@ -0,0 +1,44 @@
#ifndef PREPROCESSOR_CALLBACKS_H
#define PREPROCESSOR_CALLBACKS_H
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Token.h"
class FileRegister;
class ParserClient;
struct ParseLocation;
class PreprocessorCallbacks
: public clang::PPCallbacks
{
public:
explicit PreprocessorCallbacks(clang::SourceManager& sourceManager, ParserClient* client, FileRegister* fileRegister);
virtual void FileChanged(clang::SourceLocation location, FileChangeReason reason, clang::SrcMgr::CharacteristicKind, clang::FileID);
virtual void InclusionDirective(
clang::SourceLocation hashLocation, const clang::Token& includeToken, llvm::StringRef fileName, bool isAngled,
clang::CharSourceRange fileNameRange, const clang::FileEntry* fileEntry, llvm::StringRef searchPath,
llvm::StringRef relativePath, const clang::Module* imported);
virtual void MacroDefined(const clang::Token& macroNameToken, const clang::MacroDirective* macroDirective);
virtual void MacroExpands(
const clang::Token& macroNameToken, const clang::MacroDefinition& macroDirective,
clang::SourceRange range, const clang::MacroArgs* args
);
private:
ParseLocation getParseLocation(const clang::Token& macroNameToc) const;
ParseLocation getParseLocation(const clang::MacroInfo* macroNameToc) const;
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
const clang::SourceManager& m_sourceManager;
ParserClient* m_client;
FileRegister* m_fileRegister;
};
#endif // PREPROCESSOR_CALLBACKS_H
@@ -0,0 +1,287 @@
#include "data/parser/cxx/name_resolver/CxxDeclNameResolver.h"
#include <clang/AST/DeclTemplate.h>
#include <clang/AST/ASTContext.h>
#include "data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h"
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
#include "utility/file/FilePath.h"
#include "utility/logging/logging.h"
CxxDeclNameResolver::CxxDeclNameResolver(const clang::Decl* declaration)
: CxxNameResolver(std::vector<const clang::Decl*>())
, m_declaration(declaration)
{
}
CxxDeclNameResolver::CxxDeclNameResolver(const clang::Decl* declaration, std::vector<const clang::Decl*> ignoredContextDecls)
: CxxNameResolver(ignoredContextDecls)
, m_declaration(declaration)
{
}
CxxDeclNameResolver::~CxxDeclNameResolver()
{
}
NameHierarchy CxxDeclNameResolver::getDeclNameHierarchy()
{
NameHierarchy contextNameHierarchy;
if (m_declaration)
{
std::string declName = "";
if (clang::isa<clang::NamedDecl>(m_declaration))
{
declName = getDeclName(clang::dyn_cast<const clang::NamedDecl>(m_declaration));
}
else
{
LOG_INFO("unhandled declaration type: " + std::string(m_declaration->getDeclKindName()));
}
contextNameHierarchy = getContextNameHierarchy(m_declaration->getDeclContext());
if ((clang::isa<clang::NonTypeTemplateParmDecl>(m_declaration) ||
clang::isa<clang::TemplateTypeParmDecl>(m_declaration) ||
clang::isa<clang::TemplateTemplateParmDecl>(m_declaration)) &&
contextNameHierarchy.size() > 0)
{
std::string lastContextElementName = contextNameHierarchy.back()->getFullName();
contextNameHierarchy.pop();
contextNameHierarchy.push(std::make_shared<NameElement>(lastContextElementName + "::" + declName));
}
else
{
contextNameHierarchy.push(std::make_shared<NameElement>(declName));
}
}
return contextNameHierarchy;
}
NameHierarchy CxxDeclNameResolver::getContextNameHierarchy(const clang::DeclContext* declContext)
{
NameHierarchy contextNameHierarchy;
if (!ignoresContext(declContext))
{
const clang::DeclContext* parentContext = declContext->getParent();
if (parentContext)
{
contextNameHierarchy = getContextNameHierarchy(parentContext);
}
if (clang::isa<clang::NamedDecl>(declContext))
{
std::string declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declContext));
if (declName != "")
{
contextNameHierarchy.push(std::make_shared<NameElement>(declName));
}
}
}
return contextNameHierarchy;
}
std::string CxxDeclNameResolver::getDeclName()
{
const clang::NamedDecl* declaration = clang::dyn_cast<clang::NamedDecl>(m_declaration);
std::string declName = declaration->getNameAsString();
if (clang::isa<clang::CXXRecordDecl>(declaration))
{
clang::ClassTemplateDecl* templateClassDeclaration = clang::dyn_cast<clang::CXXRecordDecl>(declaration)->getDescribedClassTemplate();
if (templateClassDeclaration)
{
declName = getDeclName(templateClassDeclaration);
}
else if (clang::isa<clang::ClassTemplatePartialSpecializationDecl>(declaration))
{
const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl =
clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration);
clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters();
unsigned int currentParameterIndex = 0;
std::string specializedParameterNamePart = "<";
int templateArgumentCount = partialSpecializationDecl->getTemplateArgs().size();
const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs();
for (int i = 0; i < templateArgumentCount; i++)
{
const clang::TemplateArgument& templateArgument = templateArgumentList.get(i);
if (templateArgument.isDependent()) // IMPORTANT_TODO: fix case when arg depends on template parameter of outer template class, or depends on first template parameter.
{
if(currentParameterIndex < parameterList->size())
{
specializedParameterNamePart += getTemplateParameterString(parameterList->getParam(currentParameterIndex));
}
else
{
//this if fixes the crash, but not the problem TODO
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
LOG_INFO("Template getParam out of Range "+declaration->getLocation().printToString(sourceManager));
}
currentParameterIndex++;
}
else
{
specializedParameterNamePart += getTemplateArgumentName(templateArgument);
}
specializedParameterNamePart += (i < templateArgumentCount - 1) ? ", " : "";
}
specializedParameterNamePart += ">";
declName += specializedParameterNamePart;
}
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
{
std::string templateArgumentNamePart = "<";
const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(declaration)->getTemplateArgs();
for (size_t i = 0; i < templateArgumentList.size(); i++)
{
templateArgumentNamePart += getTemplateArgumentName(templateArgumentList.get(i));
templateArgumentNamePart += (i < templateArgumentList.size() - 1) ? ", " : "";
}
templateArgumentNamePart += ">";
declName += templateArgumentNamePart;
}
}
else if (clang::isa<clang::FunctionDecl>(declaration))
{
clang::FunctionTemplateDecl* templateFunctionDeclaration = clang::dyn_cast<clang::FunctionDecl>(declaration)->getDescribedFunctionTemplate();
if (templateFunctionDeclaration)
{
declName = getDeclName(templateFunctionDeclaration);
}
else if (clang::dyn_cast<clang::FunctionDecl>(declaration)->isFunctionTemplateSpecialization())
{
std::string templateArgumentNamePart = "<";
const clang::TemplateArgumentList* templateArgumentList = clang::dyn_cast<clang::FunctionDecl>(declaration)->getTemplateSpecializationArgs();
for (size_t i = 0; i < templateArgumentList->size(); i++)
{
const clang::TemplateArgument& templateArgument = templateArgumentList->get(i);
templateArgumentNamePart += getTemplateArgumentName(templateArgument);
templateArgumentNamePart += (i < templateArgumentList->size() - 1) ? ", " : "";
}
templateArgumentNamePart += ">";
declName += templateArgumentNamePart;
}
}
else if (clang::isa<clang::TemplateDecl>(declaration)) // also triggers on TemplateTemplateParmDecl
{
std::string templateParameterNamePart = "<";
clang::TemplateParameterList* parameterList = clang::dyn_cast<clang::TemplateDecl>(declaration)->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
templateParameterNamePart += getTemplateParameterString(parameterList->getParam(i));
templateParameterNamePart += (i < parameterList->size() - 1) ? ", " : "";
}
templateParameterNamePart += ">";
declName += templateParameterNamePart;
}
else if (clang::isa<clang::NamespaceDecl>(declaration) && clang::dyn_cast<clang::NamespaceDecl>(declaration)->isAnonymousNamespace())
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
declName = "anonymous namespace (" + FilePath(presumedBegin.getFilename()).fileName() + ")";
}
else if (clang::isa<clang::EnumDecl>(declaration) && declName.size() == 0)
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
declName = "anonymous enum (" + FilePath(presumedBegin.getFilename()).fileName() + ")";
}
return declName;
}
std::string CxxDeclNameResolver::getDeclName(const clang::NamedDecl* declaration)
{
CxxDeclNameResolver resolver(declaration);
return resolver.getDeclName();
}
std::string CxxDeclNameResolver::getTemplateParameterString(const clang::NamedDecl* parameter)
{
std::string templateParameterTypeString = "";
clang::Decl::Kind templateParameterKind = parameter->getKind();
switch (templateParameterKind)
{
case clang::Decl::NonTypeTemplateParm:
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::NonTypeTemplateParmDecl>(parameter));
break;
case clang::Decl::TemplateTypeParm:
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTypeParmDecl>(parameter));
break;
case clang::Decl::TemplateTemplateParm:
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTemplateParmDecl>(parameter));
break;
default:
LOG_INFO("Unhandled kind of template parameter.");
}
std::string parameterName = parameter->getName();
if (!parameterName.empty())
{
templateParameterTypeString += " " + parameterName;
}
return templateParameterTypeString;
}
std::string CxxDeclNameResolver::getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter)
{
CxxTypeNameResolver typeNameResolver(getIgnoredContextDecls());
if (clang::isa<clang::TemplateDecl>(m_declaration))
{
typeNameResolver.ignoreContextDecl(clang::dyn_cast<clang::TemplateDecl>(m_declaration)->getTemplatedDecl());
}
else // works for partial template specializations
{
typeNameResolver.ignoreContextDecl(m_declaration);
}
std::string typeString = typeNameResolver.qualTypeToDataType(parameter->getType())->getFullTypeName();
if (parameter->isTemplateParameterPack())
{
typeString += "...";
}
return typeString;
}
std::string CxxDeclNameResolver::getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter)
{
std::string typeString = (parameter->wasDeclaredWithTypename() ? "typename" : "class");
if (parameter->isTemplateParameterPack())
{
typeString += "...";
}
return typeString;
}
std::string CxxDeclNameResolver::getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter)
{
std::string templateParameterTypeString = "template<";
clang::TemplateParameterList* parameterList = parameter->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
templateParameterTypeString += getTemplateParameterString(parameterList->getParam(i));
templateParameterTypeString += (i < parameterList->size() - 1) ? ", " : "";
}
templateParameterTypeString += ">";
templateParameterTypeString += " typename"; // TODO: what if template template parameter is defined with class keyword?
if (parameter->isTemplateParameterPack())
{
templateParameterTypeString += "...";
}
return templateParameterTypeString;
}
std::string CxxDeclNameResolver::getTemplateArgumentName(const clang::TemplateArgument& argument)
{
CxxTemplateArgumentNameResolver resolver(getIgnoredContextDecls());
return resolver.getTemplateArgumentName(argument);
}
@@ -0,0 +1,29 @@
#ifndef CXX_DECL_NAME_RESOLVER_H
#define CXX_DECL_NAME_RESOLVER_H
#include "data/name/NameHierarchy.h"
#include "data/parser/cxx/name_resolver/CxxNameResolver.h"
class CxxDeclNameResolver: public CxxNameResolver
{
public:
CxxDeclNameResolver(const clang::Decl* declaration);
CxxDeclNameResolver(const clang::Decl* declaration, std::vector<const clang::Decl*> ignoredContextDecls);
~CxxDeclNameResolver();
NameHierarchy getDeclNameHierarchy();
std::string getDeclName();
private:
NameHierarchy getContextNameHierarchy(const clang::DeclContext* declaration);
std::string getDeclName(const clang::NamedDecl* declaration);
std::string getTemplateParameterString(const clang::NamedDecl* parameter);
std::string getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter);
std::string getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter);
std::string getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter);
std::string getTemplateArgumentName(const clang::TemplateArgument& argument);
const clang::Decl* m_declaration;
};
#endif // CXX_DECL_NAME_RESOLVER_H
@@ -0,0 +1,33 @@
#include "data/parser/cxx/name_resolver/CxxNameResolver.h"
CxxNameResolver::CxxNameResolver(std::vector<const clang::Decl*> ignoredContextDecls)
: m_ignoredContextDecls(ignoredContextDecls)
{
}
CxxNameResolver::~CxxNameResolver()
{
}
void CxxNameResolver::ignoreContextDecl(const clang::Decl* decl)
{
m_ignoredContextDecls.push_back(decl);
}
bool CxxNameResolver::ignoresContext(const clang::DeclContext* declContext)
{
const clang::Decl* decl = clang::dyn_cast<clang::Decl>(declContext);
for (size_t i = 0; i < m_ignoredContextDecls.size(); i++)
{
if (decl == m_ignoredContextDecls[i])
{
return true;
}
}
return false;
}
std::vector<const clang::Decl*> CxxNameResolver::getIgnoredContextDecls() const
{
return m_ignoredContextDecls;
}
@@ -0,0 +1,24 @@
#ifndef CXX_NAME_RESOLVER_H
#define CXX_NAME_RESOLVER_H
#include <vector>
#include "clang/AST/Decl.h"
class CxxNameResolver
{
public:
CxxNameResolver(std::vector<const clang::Decl*> ignoredContextDecls);
~CxxNameResolver();
void ignoreContextDecl(const clang::Decl* decl);
bool ignoresContext(const clang::DeclContext* declContext);
protected:
std::vector<const clang::Decl*> getIgnoredContextDecls() const;
private:
std::vector<const clang::Decl*> m_ignoredContextDecls;
};
#endif // CXX_NAME_RESOLVER_H
@@ -0,0 +1,73 @@
#include "data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h"
#include <clang/AST/PrettyPrinter.h>
#include <clang/AST/DeclTemplate.h>
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
#include "data/type/NamedDataType.h"
#include "utility/logging/logging.h"
CxxTemplateArgumentNameResolver::CxxTemplateArgumentNameResolver()
: CxxNameResolver(std::vector<const clang::Decl*>())
{
}
CxxTemplateArgumentNameResolver::CxxTemplateArgumentNameResolver(std::vector<const clang::Decl*> ignoredContextDecls)
: CxxNameResolver(ignoredContextDecls)
{
}
CxxTemplateArgumentNameResolver::~CxxTemplateArgumentNameResolver()
{
}
std::string CxxTemplateArgumentNameResolver::getTemplateArgumentName(const clang::TemplateArgument& argument)
{
const clang::TemplateArgument::ArgKind kind = argument.getKind();
switch (kind)
{
case clang::TemplateArgument::Type:
{
CxxTypeNameResolver typeNameResolver(getIgnoredContextDecls());
return typeNameResolver.qualTypeToDataType(argument.getAsType())->getFullTypeName();
}
case clang::TemplateArgument::Integral:
case clang::TemplateArgument::Null:
case clang::TemplateArgument::Declaration:
case clang::TemplateArgument::NullPtr:
case clang::TemplateArgument::Template:
case clang::TemplateArgument::TemplateExpansion: // handled correctly? template template parameter...
case clang::TemplateArgument::Expression:
{
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
std::string buf;
llvm::raw_string_ostream os(buf);
argument.print(pp, os);
const std::string typeName = os.str();
return typeName;
}
case clang::TemplateArgument::Pack:
{
std::string typeName = "<";
argument.getPackAsArray();
llvm::ArrayRef<clang::TemplateArgument> pack = argument.getPackAsArray();
for (size_t i = 0; i < pack.size(); i++)
{
typeName += getTemplateArgumentName(pack[i]);
if (i < pack.size() - 1)
{
typeName += ", ";
}
}
typeName += ">";
return typeName;
}
}
return "";
}
@@ -0,0 +1,20 @@
#ifndef CXX_TEMPLATE_ARGUMENT_NAME_RESOLVER_H
#define CXX_TEMPLATE_ARGUMENT_NAME_RESOLVER_H
#include <memory>
#include "data/parser/cxx/name_resolver/CxxNameResolver.h"
class DataType;
class CxxTemplateArgumentNameResolver: public CxxNameResolver
{
public:
CxxTemplateArgumentNameResolver();
CxxTemplateArgumentNameResolver(std::vector<const clang::Decl*> ignoredContextDecls);
~CxxTemplateArgumentNameResolver();
std::string getTemplateArgumentName(const clang::TemplateArgument& argument);
};
#endif // CXX_TEMPLATE_ARGUMENT_NAME_RESOLVER_H
@@ -0,0 +1,246 @@
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
#include <clang/AST/PrettyPrinter.h>
#include <clang/AST/DeclTemplate.h>
#include <clang/AST/ASTContext.h>
#include "data/parser/cxx/name_resolver/CxxDeclNameResolver.h"
#include "data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h"
#include "data/type/DataType.h"
#include "data/type/NamedDataType.h"
#include "data/type/ArrayModifiedDataType.h"
#include "data/type/PointerModifiedDataType.h"
#include "data/type/ReferenceModifiedDataType.h"
#include "utility/logging/logging.h"
CxxTypeNameResolver::CxxTypeNameResolver()
: CxxNameResolver(std::vector<const clang::Decl*>())
{
}
CxxTypeNameResolver::CxxTypeNameResolver(std::vector<const clang::Decl*> ignoredContextDecls)
: CxxNameResolver(ignoredContextDecls)
{
}
CxxTypeNameResolver::~CxxTypeNameResolver()
{
}
std::shared_ptr<DataType> CxxTypeNameResolver::qualTypeToDataType(clang::QualType qualType)
{
std::shared_ptr<DataType> dataType = typeToDataType(qualType.getTypePtr());
if (qualType.isConstQualified())
{
dataType->addQualifier(DataType::QUALIFIER_CONST);
}
return dataType;
}
std::shared_ptr<DataType> CxxTypeNameResolver::typeToDataType(const clang::Type* type)
{
std::shared_ptr<DataType> dataType;
switch (type->getTypeClass())
{
case clang::Type::Paren:
{
dataType = qualTypeToDataType(type->getAs<clang::ParenType>()->getInnerType());
break;
}
case clang::Type::Typedef:
{
CxxDeclNameResolver declNameResolver(type->getAs<clang::TypedefType>()->getDecl(), getIgnoredContextDecls());
dataType = std::make_shared<NamedDataType>(declNameResolver.getDeclNameHierarchy());
break;
}
case clang::Type::MemberPointer:
{
// test this case!
}
case clang::Type::Pointer:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(type->getPointeeType());
dataType = std::make_shared<PointerModifiedDataType>(innerType);
break;
}
case clang::Type::ConstantArray:
case clang::Type::VariableArray:
case clang::Type::DependentSizedArray:
case clang::Type::IncompleteArray:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(clang::dyn_cast<clang::ArrayType>(type)->getElementType());
dataType = std::make_shared<ArrayModifiedDataType>(innerType);
break;
}
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(type->getPointeeType());
dataType = std::make_shared<ReferenceModifiedDataType>(innerType);
break;
}
case clang::Type::Elaborated:
{
dataType = qualTypeToDataType(clang::dyn_cast<clang::ElaboratedType>(type)->getNamedType());
break;
}
case clang::Type::Enum:
case clang::Type::Record:
{
CxxDeclNameResolver declNameResolver(type->getAs<clang::TagType>()->getDecl(), getIgnoredContextDecls());
dataType = std::make_shared<NamedDataType>(declNameResolver.getDeclNameHierarchy());
break;
}
case clang::Type::Builtin:
{
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
clang::SmallString<64> Buf;
llvm::raw_svector_ostream StrOS(Buf);
clang::QualType::print(type, clang::Qualifiers(), StrOS, pp, clang::Twine());
std::string typeName = StrOS.str();
NameHierarchy typeNameHerarchy;
typeNameHerarchy.push(std::make_shared<NameElement>(typeName));
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::TemplateSpecialization:
{
NameHierarchy typeNameHerarchy;
const clang::TagType* tagType = type->getAs<clang::TagType>(); // remove this case when NameHierarchy is split into namepart and parameter part
if (tagType)
{
CxxDeclNameResolver declNameResolver(tagType->getDecl(), getIgnoredContextDecls());
typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
}
else // specialization of a template template parameter (no concrete class)
{
const clang::TemplateSpecializationType* templateSpecializationType = type->getAs<clang::TemplateSpecializationType>();
CxxDeclNameResolver declNameResolver(templateSpecializationType->getTemplateName().getAsTemplateDecl(), getIgnoredContextDecls());
typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
if (typeNameHerarchy.size() > 0)
{
std::string templateArgumentNamePart = "<";
CxxTemplateArgumentNameResolver resolver(getIgnoredContextDecls());
for (size_t i = 0; i < templateSpecializationType->getNumArgs(); i++)
{
templateArgumentNamePart += resolver.getTemplateArgumentName(templateSpecializationType->getArg(i));
if (i + 1 < templateSpecializationType->getNumArgs())
templateArgumentNamePart += ", ";
}
templateArgumentNamePart += ">";
std::string declName = typeNameHerarchy.back()->getFullName();
declName = declName.substr(0, declName.rfind("<")); // remove template parameters - TODO: FIX: does not work for A<ajaj<ajsj>>
declName += templateArgumentNamePart; // add template arguments
typeNameHerarchy.pop();
typeNameHerarchy.push(std::make_shared<NameElement>(declName));
}
}
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::TemplateTypeParm:
{
clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast<clang::TemplateTypeParmType>(type)->getDecl();
CxxDeclNameResolver declNameResolver(templateTypeParmDecl, getIgnoredContextDecls());
NameHierarchy typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::SubstTemplateTypeParm:
{
dataType = qualTypeToDataType(type->getAs<clang::SubstTemplateTypeParmType>()->getReplacementType());
break;
}
case clang::Type::DependentName:
{
const clang::DependentNameType* dependentNameType = clang::dyn_cast<clang::DependentNameType>(type);
NameHierarchy typeNameHerarchy = getNameHierarchy(dependentNameType->getQualifier());
typeNameHerarchy.push(std::make_shared<NameElement>(dependentNameType->getIdentifier()->getName().str()));
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::PackExpansion:
{
const clang::PackExpansionType* packExpansionType = clang::dyn_cast<clang::PackExpansionType>(type);
dataType = qualTypeToDataType(packExpansionType->getPattern());
break;
}
default:
{
LOG_INFO(std::string("Unhandled kind of type encountered: ") + type->getTypeClassName());
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
clang::SmallString<64> Buf;
llvm::raw_svector_ostream StrOS(Buf);
clang::QualType::print(type, clang::Qualifiers(), StrOS, pp, clang::Twine());
std::string typeName = StrOS.str();
NameHierarchy typeNameHerarchy;
typeNameHerarchy.push(std::make_shared<NameElement>(typeName));
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
}
return dataType;
}
NameHierarchy CxxTypeNameResolver::getNameHierarchy(const clang::NestedNameSpecifier* nestedNameSpecifier)
{
clang::NestedNameSpecifier::SpecifierKind nnsKind = nestedNameSpecifier->getKind();
NameHierarchy typeNameHerarchy;
switch (nnsKind)
{
case clang::NestedNameSpecifier::Identifier:
{
const clang::NestedNameSpecifier* prefix = nestedNameSpecifier->getPrefix();
if (prefix)
{
typeNameHerarchy = getNameHierarchy(prefix);
}
typeNameHerarchy.push(std::make_shared<NameElement>(nestedNameSpecifier->getAsIdentifier()->getName()));
}
break;
case clang::NestedNameSpecifier::Namespace:
{
CxxDeclNameResolver declNameResolver(nestedNameSpecifier->getAsNamespace(), getIgnoredContextDecls());
typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
}
break;
case clang::NestedNameSpecifier::NamespaceAlias:
{
CxxDeclNameResolver declNameResolver(nestedNameSpecifier->getAsNamespaceAlias(), getIgnoredContextDecls());
typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
}
break;
case clang::NestedNameSpecifier::TypeSpec:
case clang::NestedNameSpecifier::TypeSpecWithTemplate:
typeNameHerarchy = typeToDataType(nestedNameSpecifier->getAsType())->getTypeNameHierarchy();
break;
case clang::NestedNameSpecifier::Global:
// no context name hierarchy needed.
break;
case clang::NestedNameSpecifier::Super:
{
CxxDeclNameResolver declNameResolver(nestedNameSpecifier->getAsRecordDecl(), getIgnoredContextDecls());
typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
}
break;
}
return typeNameHerarchy;
}
@@ -0,0 +1,21 @@
#ifndef CXX_TYPE_NAME_RESOLVER_H
#define CXX_TYPE_NAME_RESOLVER_H
#include "data/parser/cxx/name_resolver/CxxNameResolver.h"
#include "data/type/DataType.h"
class CxxTypeNameResolver: public CxxNameResolver
{
public:
CxxTypeNameResolver();
CxxTypeNameResolver(std::vector<const clang::Decl*> ignoredContextDecls);
~CxxTypeNameResolver();
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType);
private:
std::shared_ptr<DataType> typeToDataType(const clang::Type* type);
NameHierarchy getNameHierarchy(const clang::NestedNameSpecifier* nestedNameSpecifier);
};
#endif // CXX_TYPE_NAME_RESOLVER_H
@@ -0,0 +1,97 @@
#include "data/parser/cxx/utilityCxx.h"
#include "data/parser/cxx/name_resolver/CxxDeclNameResolver.h"
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
#include "data/type/NamedDataType.h"
#include "utility/logging/logging.h"
namespace utility
{
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType)
{
CxxTypeNameResolver resolver;
return resolver.qualTypeToDataType(qualType);
}
NameHierarchy getDeclNameHierarchy(const clang::Decl* declaration)
{
CxxDeclNameResolver resolver(declaration);
return resolver.getDeclNameHierarchy();
}
NameHierarchy getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration)
{
NameHierarchy specializationParentNameHierarchy;
llvm::PointerUnion<clang::ClassTemplateDecl*, clang::ClassTemplatePartialSpecializationDecl*> pu = declaration->getSpecializedTemplateOrPartial();
if (pu.is<clang::ClassTemplateDecl*>())
{
clang::ClassTemplateDecl* specializedFromDecl = pu.get<clang::ClassTemplateDecl*>();
specializationParentNameHierarchy = utility::getDeclNameHierarchy(specializedFromDecl);
}
else if (pu.is<clang::ClassTemplatePartialSpecializationDecl*>())
{
clang::ClassTemplatePartialSpecializationDecl* specializedFromDecl = pu.get<clang::ClassTemplatePartialSpecializationDecl*>();
specializationParentNameHierarchy = utility::getDeclNameHierarchy(specializedFromDecl);
}
return specializationParentNameHierarchy;
}
std::shared_ptr<DataType> templateArgumentToDataType(const clang::TemplateArgument& argument) // remove this! this is stupid! agurment is not always a datatype.
{
const clang::TemplateArgument::ArgKind kind = argument.getKind();
switch (kind)
{
case clang::TemplateArgument::Type:
return utility::qualTypeToDataType(argument.getAsType());
case clang::TemplateArgument::Integral:
return utility::qualTypeToDataType(argument.getIntegralType());
case clang::TemplateArgument::Null:
LOG_ERROR("Type of template argument not handled: Null");
break;
case clang::TemplateArgument::Declaration:
return utility::qualTypeToDataType(argument.getAsDecl()->getType());
case clang::TemplateArgument::NullPtr:
return utility::qualTypeToDataType(argument.getNullPtrType());
break;
case clang::TemplateArgument::Template:
{
clang::TemplateName templateName = argument.getAsTemplate();
switch (templateName.getKind())
{
case clang::TemplateName::Template:
return std::make_shared<NamedDataType>(getDeclNameHierarchy(templateName.getAsTemplateDecl()));
break;
default:
LOG_ERROR("Type of template argument not handled: Template");
}
}
break;
case clang::TemplateArgument::TemplateExpansion:
LOG_ERROR("Type of template argument not handled: TemplateExpansion");
break;
case clang::TemplateArgument::Expression:
return utility::qualTypeToDataType(argument.getAsExpr()->getType());
case clang::TemplateArgument::Pack:
{
std::string typeName = "<";
argument.getPackAsArray();
llvm::ArrayRef<clang::TemplateArgument> pack = argument.getPackAsArray();
for (size_t i = 0; i < pack.size(); i++)
{
typeName += templateArgumentToDataType(pack[i])->getFullTypeName();
if (i < pack.size() - 1)
{
typeName += ", ";
}
}
typeName += ">";
NameHierarchy typeNameHerarchy;
typeNameHerarchy.push(std::make_shared<NameElement>(typeName));
return std::make_shared<NamedDataType>(typeNameHerarchy);
}
break;
}
return std::make_shared<NamedDataType>(NameHierarchy());
}
}
@@ -0,0 +1,24 @@
#ifndef UTILITY_CLANG_H
#define UTILITY_CLANG_H
#include <memory>
#include <string>
#include <vector>
#include "clang/AST/Type.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
class DataType;
class NameHierarchy;
namespace utility
{
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType);
NameHierarchy getDeclNameHierarchy(const clang::Decl* declaration);
std::shared_ptr<DataType> templateArgumentToDataType(const clang::TemplateArgument& argument);
NameHierarchy getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration);
}
#endif // UTILITY_CLANG_H