data: lambda handling

* implemented handling lambdas as functions
* functions can have child nodes now
* NameElements in NameHierarchy can have signatures now.
* fixed crash that occurred when message listener was used while being half way through its destruction process.
This commit is contained in:
malte_langkabel
2015-12-10 18:00:54 +01:00
parent 2b03215ea4
commit 01bcf7266b
22 changed files with 238 additions and 568 deletions
@@ -38,30 +38,13 @@ void ASTBodyVisitor::VisitChildren(clang::Stmt* stmt)
void ASTBodyVisitor::VisitCallExpr(clang::CallExpr* expr)
{
bool ignore = false;
// check if lambda call
if (clang::isa<clang::CXXOperatorCallExpr>(expr))
if (m_functionDecl)
{
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();
}
m_client->VisitCallExprInDeclBody(m_functionDecl, expr);
}
if (!ignore)
else
{
if (m_functionDecl)
{
m_client->VisitCallExprInDeclBody(m_functionDecl, expr);
}
else
{
m_client->VisitCallExprInDeclBody(m_varDecl, expr);
}
m_client->VisitCallExprInDeclBody(m_varDecl, expr);
}
VisitStmt(expr);
@@ -176,6 +159,11 @@ void ASTBodyVisitor::VisitDeclRefExpr(clang::DeclRefExpr* expr)
VisitStmt(expr);
}
void ASTBodyVisitor::VisitLambdaExpr(clang::LambdaExpr* expr)
{
// Don't visit the lambda's children. The ASTVisitor creates a new ASTBodyVisitor for these.
}
void ASTBodyVisitor::VisitDeclStmt(clang::DeclStmt* stmt)
{
for (clang::Decl* decl : stmt->decls())
@@ -20,6 +20,7 @@ public:
void VisitCXXNewExpr(clang::CXXNewExpr* expr);
void VisitMemberExpr(clang::make_ptr<clang::MemberExpr>::type expr);
void VisitDeclRefExpr(clang::make_ptr<clang::DeclRefExpr>::type expr);
void VisitLambdaExpr(clang::LambdaExpr* expr);
void VisitDeclStmt(clang::DeclStmt* stmt);
private:
+11 -2
View File
@@ -166,6 +166,15 @@ bool ASTVisitor::VisitFunctionDecl(clang::FunctionDecl* declaration)
return true;
}
bool ASTVisitor::VisitLambdaExpr(clang::LambdaExpr* expr)
{
if (isLocatedInUnparsedProjectFile(expr->getCallOperator()))
{
processFunctionDecl(expr->getCallOperator());
}
return true;
}
bool ASTVisitor::VisitParmVarDecl(clang::ParmVarDecl* declaration)
{
// todo: handle parameters here!
@@ -755,7 +764,7 @@ void ASTVisitor::processFunctionDecl(clang::FunctionDecl* declaration)
getParseLocationForNamedDecl(declaration),
getParseFunction(declaration),
getParseLocationOfFunctionBody(declaration)
);
);
// handle template arguments of return type.
clang::TypeLoc functionLoc = declaration->getTypeSourceInfo()->getTypeLoc();
@@ -772,7 +781,7 @@ void ASTVisitor::processFunctionDecl(clang::FunctionDecl* declaration)
if (declaration->hasBody() &&
declaration->isThisDeclarationADefinition() &&
!declaration->isDependentContext()
)
)
{
ASTBodyVisitor bodyVisitor(this, declaration);
bodyVisitor.Visit(declaration->getBody());
+1 -2
View File
@@ -32,6 +32,7 @@ public:
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 VisitLambdaExpr(clang::LambdaExpr* expr); // lambdas
virtual bool VisitParmVarDecl(clang::ParmVarDecl* declaration);
virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl* declaration); // methods
virtual bool VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration); // initialization list
@@ -67,14 +68,12 @@ public:
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;
@@ -29,7 +29,7 @@ NameHierarchy CxxDeclNameResolver::getDeclNameHierarchy()
NameHierarchy contextNameHierarchy;
if (m_declaration)
{
std::string declName = "";
std::shared_ptr<NameElement> declName;
if (clang::isa<clang::NamedDecl>(m_declaration))
{
@@ -47,13 +47,13 @@ NameHierarchy CxxDeclNameResolver::getDeclNameHierarchy()
clang::isa<clang::TemplateTemplateParmDecl>(m_declaration)) &&
contextNameHierarchy.size() > 0)
{
std::string lastContextElementName = contextNameHierarchy.back()->getFullName();
std::string lastContextElementName = contextNameHierarchy.back()->getFullName(); // TODO: what about the signature in this case?
contextNameHierarchy.pop();
contextNameHierarchy.push(std::make_shared<NameElement>(lastContextElementName + "::" + declName));
contextNameHierarchy.push(std::make_shared<NameElement>(lastContextElementName + "::" + declName->getFullName()));
}
else
{
contextNameHierarchy.push(std::make_shared<NameElement>(declName));
contextNameHierarchy.push(declName);
}
}
return contextNameHierarchy;
@@ -73,26 +73,26 @@ NameHierarchy CxxDeclNameResolver::getContextNameHierarchy(const clang::DeclCont
if (clang::isa<clang::NamedDecl>(declContext))
{
std::string declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declContext));
if (declName != "")
std::shared_ptr<NameElement> declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declContext));
if (declName)
{
contextNameHierarchy.push(std::make_shared<NameElement>(declName));
contextNameHierarchy.push(declName);
}
}
}
return contextNameHierarchy;
}
std::string CxxDeclNameResolver::getDeclName()
std::shared_ptr<NameElement> CxxDeclNameResolver::getDeclName()
{
const clang::NamedDecl* declaration = clang::dyn_cast<clang::NamedDecl>(m_declaration);
std::string declName = declaration->getNameAsString();
std::string declNameString = declaration->getNameAsString();
if (clang::isa<clang::CXXRecordDecl>(declaration))
{
clang::ClassTemplateDecl* templateClassDeclaration = clang::dyn_cast<clang::CXXRecordDecl>(declaration)->getDescribedClassTemplate();
if (templateClassDeclaration)
{
declName = getDeclName(templateClassDeclaration);
return getDeclName(templateClassDeclaration);
}
else if (clang::isa<clang::ClassTemplatePartialSpecializationDecl>(declaration))
{
@@ -129,7 +129,7 @@ std::string CxxDeclNameResolver::getDeclName()
specializedParameterNamePart += (i < templateArgumentCount - 1) ? ", " : "";
}
specializedParameterNamePart += ">";
declName += specializedParameterNamePart;
return std::make_shared<NameElement>(declNameString + specializedParameterNamePart);
}
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
{
@@ -141,29 +141,78 @@ std::string CxxDeclNameResolver::getDeclName()
templateArgumentNamePart += (i < templateArgumentList.size() - 1) ? ", " : "";
}
templateArgumentNamePart += ">";
declName += templateArgumentNamePart;
return std::make_shared<NameElement>(declNameString + templateArgumentNamePart);
}
}
else if (clang::isa<clang::FunctionDecl>(declaration))
{
clang::FunctionTemplateDecl* templateFunctionDeclaration = clang::dyn_cast<clang::FunctionDecl>(declaration)->getDescribedFunctionTemplate();
if (templateFunctionDeclaration)
if (const clang::CXXMethodDecl* methodDecl = clang::dyn_cast_or_null<clang::CXXMethodDecl>(declaration))
{
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++)
if (methodDecl->getParent()->isLambda())
{
const clang::TemplateArgument& templateArgument = templateArgumentList->get(i);
templateArgumentNamePart += getTemplateArgumentName(templateArgument);
templateArgumentNamePart += (i < templateArgumentList->size() - 1) ? ", " : "";
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(methodDecl->getParent()->getLocStart());
std::string lambdaName = "lambda at " + std::to_string(presumedBegin.getLine()) + ":" + std::to_string(presumedBegin.getColumn());
return std::make_shared<NameElement>(lambdaName, lambdaName);
}
templateArgumentNamePart += ">";
declName += templateArgumentNamePart;
}
const clang::FunctionDecl* functionDecl = clang::dyn_cast<clang::FunctionDecl>(declaration);
if (clang::FunctionTemplateDecl* templateFunctionDeclaration = functionDecl->getDescribedFunctionTemplate())
{
return getDeclName(templateFunctionDeclaration);
}
else
{
std::string functionName = declNameString;
if (functionDecl->isFunctionTemplateSpecialization())
{
std::string templateArgumentNamePart = "<";
const clang::TemplateArgumentList* templateArgumentList = functionDecl->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 += ">";
functionName += templateArgumentNamePart;
}
bool isStatic = false;
bool isConst = false;
if (clang::isa<clang::CXXMethodDecl>(declaration))
{
const clang::CXXMethodDecl* methodDecl = clang::dyn_cast<const clang::CXXMethodDecl>(declaration);
isStatic = methodDecl->isStatic();
isConst = methodDecl->isConst();
}
else
{
isStatic = functionDecl->getStorageClass() == clang::SC_Static;
}
CxxTypeNameResolver typenNameResolver(getIgnoredContextDecls());
std::string returnTypeString = typenNameResolver.qualTypeToDataType(functionDecl->getReturnType())->getFullTypeName();
std::string parameterString = "(";
for (unsigned int i = 0; i < functionDecl->param_size(); i++)
{
parameterString += typenNameResolver.qualTypeToDataType(functionDecl->parameters()[i]->getType())->getFullTypeName();
if (i < functionDecl->param_size() - 1)
{
parameterString += ", ";
}
}
parameterString += ")";
return std::make_shared<NameElement>(
functionName + parameterString + (isConst ? "const" : ""),
(isStatic ? "static " : "") + returnTypeString + " " + functionName + parameterString + (isConst ? " const" : ""));
}
}
else if (clang::isa<clang::TemplateDecl>(declaration)) // also triggers on TemplateTemplateParmDecl
{
@@ -175,25 +224,29 @@ std::string CxxDeclNameResolver::getDeclName()
templateParameterNamePart += (i < parameterList->size() - 1) ? ", " : "";
}
templateParameterNamePart += ">";
declName += templateParameterNamePart;
return std::make_shared<NameElement>(declNameString + 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() + ")";
return std::make_shared<NameElement>("anonymous namespace (" + FilePath(presumedBegin.getFilename()).fileName() + ")");
}
else if (clang::isa<clang::EnumDecl>(declaration) && declName.size() == 0)
else if (clang::isa<clang::EnumDecl>(declaration) && declNameString.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 std::make_shared<NameElement>("anonymous enum (" + FilePath(presumedBegin.getFilename()).fileName() + ")");
}
return declName;
if (declNameString.size() > 0)
{
return std::make_shared<NameElement>(declNameString);
}
return std::shared_ptr<NameElement>();
}
std::string CxxDeclNameResolver::getDeclName(const clang::NamedDecl* declaration)
std::shared_ptr<NameElement> CxxDeclNameResolver::getDeclName(const clang::NamedDecl* declaration)
{
CxxDeclNameResolver resolver(declaration);
return resolver.getDeclName();
@@ -9,14 +9,14 @@ class CxxDeclNameResolver: public CxxNameResolver
public:
CxxDeclNameResolver(const clang::Decl* declaration);
CxxDeclNameResolver(const clang::Decl* declaration, std::vector<const clang::Decl*> ignoredContextDecls);
~CxxDeclNameResolver();
virtual ~CxxDeclNameResolver();
NameHierarchy getDeclNameHierarchy();
std::string getDeclName();
std::shared_ptr<NameElement> getDeclName();
private:
NameHierarchy getContextNameHierarchy(const clang::DeclContext* declaration);
std::string getDeclName(const clang::NamedDecl* declaration);
std::shared_ptr<NameElement> 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);
@@ -9,7 +9,7 @@ class CxxNameResolver
{
public:
CxxNameResolver(std::vector<const clang::Decl*> ignoredContextDecls);
~CxxNameResolver();
virtual ~CxxNameResolver();
void ignoreContextDecl(const clang::Decl* decl);
bool ignoresContext(const clang::DeclContext* declContext);
@@ -12,7 +12,7 @@ class CxxTemplateArgumentNameResolver: public CxxNameResolver
public:
CxxTemplateArgumentNameResolver();
CxxTemplateArgumentNameResolver(std::vector<const clang::Decl*> ignoredContextDecls);
~CxxTemplateArgumentNameResolver();
virtual ~CxxTemplateArgumentNameResolver();
std::string getTemplateArgumentName(const clang::TemplateArgument& argument);
};
@@ -9,7 +9,7 @@ class CxxTypeNameResolver: public CxxNameResolver
public:
CxxTypeNameResolver();
CxxTypeNameResolver(std::vector<const clang::Decl*> ignoredContextDecls);
~CxxTypeNameResolver();
virtual ~CxxTypeNameResolver();
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType);