data: parse partial template specializations
* fixed: implicit template specializations will be found even if the original template definition is located in a different file (that gets included). * implemented correct extraction of template parameters, template arguments and template specialization edges. * added token locations for template parameters of partial template specializations. * graph view displays full names of template parameters and template arguments. * added test code for features
This commit is contained in:
@@ -100,9 +100,12 @@ public:
|
||||
virtual Id onTemplateRecordParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy) = 0;
|
||||
virtual Id onTemplateRecordArgumentTypeParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& templateArgumentTypeNameHierarchy,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy) = 0;
|
||||
virtual Id onTemplateRecordSpecializationParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy) = 0;
|
||||
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy) = 0;
|
||||
virtual Id onTemplateFunctionParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const ParseFunction function) = 0;
|
||||
|
||||
@@ -275,36 +275,44 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
||||
if (hasValidLocation(declaration))
|
||||
{
|
||||
std::vector<std::string> templateRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
|
||||
|
||||
clang::TemplateParameterList* parameterList = declaration->getTemplateParameters();
|
||||
for (size_t i = 0; i < parameterList->size(); i++)
|
||||
{
|
||||
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
||||
|
||||
if (hasValidLocation(namedDecl))
|
||||
{
|
||||
std::string templateParameterTypeName = namedDecl->getNameAsString();
|
||||
|
||||
m_client->onTemplateRecordParameterTypeParsed(
|
||||
getParseLocationForNamedDecl(namedDecl),
|
||||
templateParameterTypeName,
|
||||
namedDecl->getNameAsString(),
|
||||
templateRecordNameHierarchy
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (clang::ClassTemplateDecl::spec_iterator it = declaration->specializations().begin(); // template argument as parameter does not work
|
||||
it != declaration->specializations().end(); it++
|
||||
)
|
||||
{
|
||||
ParserClient::RecordType specializedRecordType = it->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS;
|
||||
std::vector<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(*(it));
|
||||
m_client->onTemplateRecordSpecializationParsed(
|
||||
getParseLocationForNamedDecl(*it), specializedRecordNameHierarchy, specializedRecordType, templateRecordNameHierarchy
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// for implicit template specializations we do not need a valid location of the original template class definition (since that file could be included)
|
||||
// handles explicit specializations and implicit specializations but no explicit partial specializations
|
||||
for (clang::ClassTemplateDecl::spec_iterator it = declaration->specializations().begin();
|
||||
it != declaration->specializations().end(); it++
|
||||
)
|
||||
{
|
||||
clang::ClassTemplateSpecializationDecl* specializationDecl = *it;
|
||||
|
||||
std::vector<std::string> specializationParentNameHierarchy = utility::getTemplateSpecializationParentNameHierarchy(specializationDecl);
|
||||
|
||||
ParserClient::RecordType specializedRecordType = specializationDecl->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS;
|
||||
std::vector<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(specializationDecl);
|
||||
m_client->onTemplateRecordSpecializationParsed(
|
||||
getParseLocationForNamedDecl(*it), specializedRecordNameHierarchy, specializedRecordType, specializationParentNameHierarchy
|
||||
);
|
||||
|
||||
const clang::TemplateArgumentList &argList = specializationDecl->getTemplateArgs();
|
||||
for (int i = 0; i < argList.size(); i++)
|
||||
{
|
||||
std::vector<std::string> argumentNameHierarchy = utility::qualTypeToDataType(argList.get(i).getAsType()).getTypeNameHierarchy();
|
||||
m_client->onTemplateRecordArgumentTypeParsed(ParseLocation(), argumentNameHierarchy, specializedRecordNameHierarchy); // TODO: What about the ParseLocation
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -312,32 +320,40 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
|
||||
{
|
||||
if (hasValidLocation(declaration))
|
||||
{
|
||||
//std::vector<std::string> templateRecordNameHierarchy = utility::splitToVector(
|
||||
// declaration->getQualifiedNameAsString(), "::"
|
||||
//);
|
||||
std::vector<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
|
||||
std::vector<std::string> specializationParentNameHierarchy = utility::getTemplateSpecializationParentNameHierarchy(declaration);
|
||||
|
||||
//clang::ClassTemplateDecl* baseTemplateDecl = declaration->getSpecializedTemplate();
|
||||
ParserClient::RecordType specializedRecordType = declaration->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS;
|
||||
m_client->onTemplateRecordSpecializationParsed(
|
||||
getParseLocationForNamedDecl(declaration), specializedRecordNameHierarchy, specializedRecordType, specializationParentNameHierarchy
|
||||
);
|
||||
|
||||
//std::string specializedParameterNamePart = "<";
|
||||
//const clang::TemplateArgumentList& templateArgumentList = declaration->getTemplateArgs();
|
||||
//for (int i = 0; i < templateArgumentList.size(); i++)
|
||||
//{
|
||||
// DataType datatype = utility::qualTypeToDataType(templateArgumentList.get(i).getAsType());
|
||||
// if (datatype.isTemplateParameterType())
|
||||
// {
|
||||
// specializedParameterNamePart += baseTemplateDecl->getTemplateParameters()->getParam(i)->getNameAsString();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// specializedParameterNamePart += datatype.getFullTypeName();
|
||||
// }
|
||||
// specializedParameterNamePart += (i < templateArgumentList.size() - 1) ? ", " : "";
|
||||
//}
|
||||
//specializedParameterNamePart += ">";
|
||||
clang::TemplateParameterList* parameterList = declaration->getTemplateParameters();
|
||||
for (size_t i = 0; i < parameterList->size(); i++)
|
||||
{
|
||||
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
||||
if (hasValidLocation(namedDecl))
|
||||
{
|
||||
m_client->onTemplateRecordParameterTypeParsed(
|
||||
getParseLocationForNamedDecl(namedDecl),
|
||||
namedDecl->getNameAsString(),
|
||||
specializedRecordNameHierarchy
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//int foo = 0;
|
||||
const clang::ASTTemplateArgumentListInfo* argumentInfoList = declaration->getTemplateArgsAsWritten();
|
||||
for (int i = 0; i < argumentInfoList->NumTemplateArgs; i++)
|
||||
{
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
const clang::QualType argumentType = argumentLoc.getArgument().getAsType();
|
||||
|
||||
m_client->onTemplateRecordArgumentTypeParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
|
||||
specializedRecordNameHierarchy);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,18 +107,22 @@ namespace utility
|
||||
|
||||
std::vector<std::string> getDeclNameHierarchy(clang::Decl* declaration)
|
||||
{
|
||||
std::string declName = "";
|
||||
std::vector<std::string> contextNameHierarchy;
|
||||
if (declaration)
|
||||
{
|
||||
std::string declName = "";
|
||||
|
||||
if (clang::isa<clang::NamedDecl>(declaration))
|
||||
{
|
||||
declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declaration));
|
||||
if (clang::isa<clang::NamedDecl>(declaration))
|
||||
{
|
||||
declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declaration));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("unhandled declaration type");
|
||||
}
|
||||
contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext());
|
||||
contextNameHierarchy.push_back(declName);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("unhandled declaration type");
|
||||
}
|
||||
std::vector<std::string> contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext());
|
||||
contextNameHierarchy.push_back(declName);
|
||||
return contextNameHierarchy;
|
||||
}
|
||||
|
||||
@@ -154,6 +158,19 @@ namespace utility
|
||||
{
|
||||
declName = getDeclName(templateClassDeclaration);
|
||||
}
|
||||
else if (clang::isa<clang::ClassTemplatePartialSpecializationDecl>(declaration))
|
||||
{
|
||||
int templateArgumentCount = clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration)->getTemplateArgs().size();
|
||||
const clang::ASTTemplateArgumentListInfo* templateArgumentListInfo = clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration)->getTemplateArgsAsWritten();
|
||||
std::string specializedParameterNamePart = "<";
|
||||
for (int i = 0; i < templateArgumentCount; i++)
|
||||
{
|
||||
specializedParameterNamePart += templateArgumentListInfo->getTemplateArgs()[i].getArgument().getAsType().getAsString();
|
||||
specializedParameterNamePart += (i < templateArgumentCount - 1) ? ", " : "";
|
||||
}
|
||||
specializedParameterNamePart += ">";
|
||||
declName += specializedParameterNamePart;
|
||||
}
|
||||
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
|
||||
{
|
||||
std::string specializedParameterNamePart = "<";
|
||||
@@ -188,4 +205,21 @@ namespace utility
|
||||
}
|
||||
return declName;
|
||||
}
|
||||
|
||||
std::vector<std::string> getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration)
|
||||
{
|
||||
std::vector<std::string> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
|
||||
class DataType;
|
||||
|
||||
@@ -17,6 +18,7 @@ namespace utility
|
||||
std::vector<std::string> getDeclNameHierarchy(clang::Decl* declaration);
|
||||
std::vector<std::string> getContextNameHierarchy(clang::DeclContext* declaration);
|
||||
std::string getDeclName(clang::NamedDecl* declaration);
|
||||
std::vector<std::string> getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration);
|
||||
}
|
||||
|
||||
#endif // UTILITY_CLANG_H
|
||||
|
||||
Reference in New Issue
Block a user