From 7d48a873f7e2c44bb7cf48c1b84b7c20535c1f3d Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Tue, 5 May 2015 23:21:43 +0200 Subject: [PATCH] data: parse type usages of types used as template arguments This change ist just an interim solution and does not cover all cases. The TokenLocation saved for the template argument is the location of the whole expression. --- bin/app/data/src/test/usage.cpp | 23 ++++++++ src/lib/data/parser/cxx/ASTVisitor.cpp | 77 ++++++++++++++++++++++++++ src/lib/data/parser/cxx/ASTVisitor.h | 7 +++ 3 files changed, 107 insertions(+) create mode 100644 bin/app/data/src/test/usage.cpp diff --git a/bin/app/data/src/test/usage.cpp b/bin/app/data/src/test/usage.cpp new file mode 100644 index 00000000..c0646740 --- /dev/null +++ b/bin/app/data/src/test/usage.cpp @@ -0,0 +1,23 @@ +#include + +class A +{ +}; + +template +class B +{ +}; + +int main() +{ + A a; + + A* aPtr = nullptr; + + std::shared_ptr aSharedPtr = std::make_shared(); + + B b; + + return 0; +} diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp index 6e5a9914..5be556b5 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -9,6 +9,8 @@ #include "utility/utilityString.h" #include "data/parser/cxx/ASTBodyVisitor.h" +#include "data/parser/cxx/name_resolver/CxxDeclNameResolver.h" +#include "data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h" #include "data/parser/cxx/utilityCxx.h" #include "data/parser/ParseFunction.h" #include "data/parser/ParseLocation.h" @@ -233,6 +235,8 @@ bool ASTVisitor::VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration) getParseTypeUsage(init->getTypeSourceInfo()->getTypeLoc(), init->getTypeSourceInfo()->getType()), getParseFunction(declaration) ); + + saveClassTemplateArgumentTypeUsages(init->getTypeSourceInfo(), getParseFunction(declaration)); } ASTBodyVisitor bodyVisitor(this, declaration); @@ -517,6 +521,9 @@ void ASTVisitor::VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallE getParseFunction(decl), getParseFunction(expr->getDirectCallee()) ); + + saveFunctionTemplateArgumentTypeUsages( + expr->getDirectCallee(), expr->getSourceRange(), getParseFunction(decl)); } void ASTVisitor::VisitCallExprInDeclBody(clang::VarDecl* decl, clang::CallExpr* expr) @@ -532,6 +539,9 @@ void ASTVisitor::VisitCallExprInDeclBody(clang::VarDecl* decl, clang::CallExpr* getParseVariable(decl), getParseFunction(expr->getDirectCallee()) ); + + saveFunctionTemplateArgumentTypeUsages( + expr->getDirectCallee(), expr->getSourceRange(), getParseVariable(decl)); } void ASTVisitor::VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clang::CXXConstructExpr* expr) @@ -587,6 +597,9 @@ void ASTVisitor::VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clan getParseFunction(decl), getParseFunction(expr->getConstructor()) ); + + saveFunctionTemplateArgumentTypeUsages( + expr->getConstructor(), expr->getSourceRange(), getParseFunction(decl)); } void ASTVisitor::VisitCXXConstructExprInDeclBody(clang::VarDecl* decl, clang::CXXConstructExpr* expr) @@ -596,6 +609,9 @@ void ASTVisitor::VisitCXXConstructExprInDeclBody(clang::VarDecl* decl, clang::CX getParseVariable(decl), getParseFunction(expr->getConstructor()) ); + + saveFunctionTemplateArgumentTypeUsages( + expr->getConstructor(), expr->getSourceRange(), getParseVariable(decl)); } void ASTVisitor::VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr) @@ -604,6 +620,8 @@ void ASTVisitor::VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXX getParseTypeUsage(expr->getAllocatedTypeSourceInfo()->getTypeLoc(), expr->getAllocatedType()), getParseFunction(decl) ); + + saveClassTemplateArgumentTypeUsages(expr->getAllocatedTypeSourceInfo(), getParseFunction(decl)); } void ASTVisitor::VisitCXXNewExprInDeclBody(clang::VarDecl* decl, clang::CXXNewExpr* expr) @@ -612,6 +630,8 @@ void ASTVisitor::VisitCXXNewExprInDeclBody(clang::VarDecl* decl, clang::CXXNewEx getParseTypeUsage(expr->getAllocatedTypeSourceInfo()->getTypeLoc(), expr->getAllocatedType()), getParseVariable(decl) ); + + saveClassTemplateArgumentTypeUsages(expr->getAllocatedTypeSourceInfo(), getParseVariable(decl)); } void ASTVisitor::VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr) @@ -690,6 +710,8 @@ void ASTVisitor::VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDec getParseTypeUsage(varDecl->getTypeSourceInfo()->getTypeLoc(), varDecl->getType()), getParseFunction(decl) ); + + saveClassTemplateArgumentTypeUsages(varDecl->getTypeSourceInfo(), getParseFunction(decl)); } bool ASTVisitor::isLocatedInUnparsedProjectFile(const clang::Decl* declaration) const @@ -920,3 +942,58 @@ ParseFunction ASTVisitor::getParseFunction(const clang::FunctionTemplateDecl* de { return getParseFunction(declaration->getTemplatedDecl()); } + +template +void ASTVisitor::saveClassTemplateArgumentTypeUsages(const clang::TypeSourceInfo* typeInfo, const T& t) +{ + const clang::Type* type = typeInfo->getType().getTypePtr(); + + if (type->getTypeClass() == clang::Type::Elaborated) + { + type = clang::dyn_cast(type)->getNamedType().getTypePtr(); + } + + if (type->getTypeClass() == clang::Type::TemplateSpecialization) + { + const clang::TemplateSpecializationType* templateSpecializationType = type->getAs(); + CxxDeclNameResolver declNameResolver(templateSpecializationType->getTemplateName().getAsTemplateDecl()); + + CxxTemplateArgumentNameResolver resolver; + for (size_t i = 0; i < templateSpecializationType->getNumArgs(); i++) + { + std::string argumentName = resolver.getTemplateArgumentName(templateSpecializationType->getArg(i)); + NameHierarchy argumentNameHierarchy; + argumentNameHierarchy.push(std::make_shared(argumentName)); + + std::shared_ptr argumentType = std::make_shared(argumentNameHierarchy); + + m_client->onTypeUsageParsed(getParseTypeUsage(typeInfo->getTypeLoc(), argumentType), t); + } + } +} + +template +void ASTVisitor::saveFunctionTemplateArgumentTypeUsages( + const clang::FunctionDecl* decl, const clang::SourceRange& sourceRange, const T& t +){ + const clang::TemplateArgumentList* argumentList = decl->getTemplateSpecializationArgs(); + if (!argumentList) + { + return; + } + + CxxTemplateArgumentNameResolver resolver; + for (size_t i = 0; i < argumentList->size(); i++) + { + std::string argumentName = resolver.getTemplateArgumentName(argumentList->get(i)); + if (argumentName.size()) + { + NameHierarchy argumentNameHierarchy; + argumentNameHierarchy.push(std::make_shared(argumentName)); + + std::shared_ptr argumentType = std::make_shared(argumentNameHierarchy); + + m_client->onTypeUsageParsed(getParseTypeUsage(sourceRange, argumentType), t); + } + } +} diff --git a/src/lib/data/parser/cxx/ASTVisitor.h b/src/lib/data/parser/cxx/ASTVisitor.h index 445bdd45..641073ef 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.h +++ b/src/lib/data/parser/cxx/ASTVisitor.h @@ -80,6 +80,13 @@ private: ParseFunction getParseFunction(const clang::FunctionDecl* declaration) const; ParseFunction getParseFunction(const clang::FunctionTemplateDecl* declaration) const; + template + void saveClassTemplateArgumentTypeUsages(const clang::TypeSourceInfo* typeInfo, const T& t); + + template + void saveFunctionTemplateArgumentTypeUsages( + const clang::FunctionDecl* decl, const clang::SourceRange& sourceRange, const T& t); + clang::ASTContext* m_context; ParserClient* m_client; FileRegister* m_fileRegister;