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:
malte_langkabel
2015-02-03 13:10:56 +01:00
parent 944554d034
commit e17341fc43
18 changed files with 363 additions and 126 deletions
+20 -7
View File
@@ -388,25 +388,38 @@ Id Storage::onTemplateRecordParameterTypeParsed(
const std::vector<std::string>& templateRecordNameHierarchy
)
{
log("class template type parameter", templateParameterTypeName, location);
log("template record type parameter", templateParameterTypeName, location);
std::vector<std::string> templateParameterTypeNameHierarchy = templateRecordNameHierarchy;
templateParameterTypeNameHierarchy.back() += "::" + templateParameterTypeName;
Node* templateParameterNode = addNodeHierarchy(Node::NODE_TEMPLATE_PARAMETER_TYPE, templateParameterTypeNameHierarchy);
addTokenLocation(templateParameterNode, location);
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateRecordNameHierarchy);
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_PARAMETER_OF, templateParameterNode, templateRecordNode);
//addTokenLocation(edge, location);
return 0;
}
Id Storage::onTemplateRecordArgumentTypeParsed(
const ParseLocation& location, const std::vector<std::string>& templateArgumentTypeNameHierarchy,
const std::vector<std::string>& templateRecordNameHierarchy)
{
log("template record argument", utility::join(templateArgumentTypeNameHierarchy, "::") + " -> " + utility::join(templateRecordNameHierarchy, "::"), location);
Node* templateArgumentNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateArgumentTypeNameHierarchy);
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateRecordNameHierarchy);
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_ARGUMENT_OF, templateArgumentNode, templateRecordNode);
if (location.isValid())
{
addTokenLocation(templateArgumentNode, location);
}
return 0;
}
Id Storage::onTemplateRecordSpecializationParsed(
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy)
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy)
{
log("class template specialization", utility::join(specializedRecordNameHierarchy, "::") + " -> " + utility::join(templateRecordNameHierarchy, "::"), location);
log("template record specialization", utility::join(specializedRecordNameHierarchy, "::") + " -> " + utility::join(specializedFromNameHierarchy, "::"), location);
Node::NodeType specializedRecordNodeType = Node::NODE_CLASS;
if (specializedRecordType == ParserClient::RECORD_STRUCT)
@@ -415,7 +428,7 @@ Id Storage::onTemplateRecordSpecializationParsed(
}
Node* specializedRecordNode = addNodeHierarchy(specializedRecordNodeType, specializedRecordNameHierarchy);
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateRecordNameHierarchy);
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, specializedFromNameHierarchy);
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_SPECIALIZATION_OF, specializedRecordNode, templateRecordNode);
//addTokenLocation(edge, location);
@@ -555,7 +568,7 @@ std::shared_ptr<Graph> Storage::getGraphForActiveTokenIds(const std::vector<Id>&
else if (tokenIds.size() == 1)
{
Token* token = m_graph.getTokenById(tokenIds[0]);
if (!token)
{
LOG_ERROR_STREAM(<< "Token with id " << tokenIds[0] << " was not found");
+6 -1
View File
@@ -83,9 +83,14 @@ public:
virtual Id onTemplateRecordParameterTypeParsed(
const ParseLocation& location, const std::string& templateParameterTypeName,
const std::vector<std::string>& templateRecordNameHierarchy);
virtual Id onTemplateRecordArgumentTypeParsed(
const ParseLocation& location, const std::vector<std::string>& templateArgumentTypeNameHierarchy,
const std::vector<std::string>& templateRecordNameHierarchy);
virtual Id onTemplateRecordSpecializationParsed(
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy);
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy);
virtual Id onTemplateFunctionParameterTypeParsed(
const ParseLocation& location, const std::string& templateParameterTypeName, const ParseFunction function);
virtual Id onTemplateFunctionSpecializationParsed(
+2
View File
@@ -133,6 +133,8 @@ std::string Edge::getTypeString(EdgeType type) const
return "typedef";
case EDGE_TEMPLATE_PARAMETER_OF:
return "template parameter";
case EDGE_TEMPLATE_ARGUMENT_OF:
return "template argument";
case EDGE_TEMPLATE_SPECIALIZATION_OF:
return "template specialization";
case EDGE_AGGREGATION:
+3 -2
View File
@@ -27,9 +27,10 @@ public:
EDGE_INHERITANCE = 0x80,
EDGE_TYPEDEF_OF = 0x100,
EDGE_TEMPLATE_PARAMETER_OF = 0x200,
EDGE_TEMPLATE_SPECIALIZATION_OF = 0x400,
EDGE_TEMPLATE_ARGUMENT_OF = 0x400,
EDGE_TEMPLATE_SPECIALIZATION_OF = 0x800,
EDGE_AGGREGATION = 0x800
EDGE_AGGREGATION = 0x1000
};
Edge(EdgeType type, Node* from, Node* to);
-6
View File
@@ -9,12 +9,6 @@
#include "data/graph/token_component/TokenComponentSignature.h"
#include "utility/logging/logging.h"
Node::Node(NodeType type, const std::string& name)
: m_type(type)
, m_nameComponent(std::make_shared<TokenComponentNameCached>(name))
{
}
Node::Node(NodeType type, std::shared_ptr<TokenComponentName> nameComponent)
: m_type(type)
, m_nameComponent(nameComponent)
-1
View File
@@ -38,7 +38,6 @@ public:
NODE_TEMPLATE_PARAMETER_TYPE = 0x2000
};
Node(NodeType type, const std::string& name);
Node(NodeType type, std::shared_ptr<TokenComponentName> nameComponent);
Node(const Node& other);
virtual ~Node();
@@ -29,7 +29,7 @@ TokenComponentNameReferenced::~TokenComponentNameReferenced()
std::shared_ptr<TokenComponent> TokenComponentNameReferenced::copy() const
{
return std::make_shared<TokenComponentNameCached>(getFullName());
return std::make_shared<TokenComponentNameCached>(m_searchNode->getNameHierarchy());
}
std::string TokenComponentNameReferenced::getName() const
@@ -47,8 +47,8 @@ const SearchNode* TokenComponentNameReferenced::getSearchNode() const
return m_searchNode;
}
TokenComponentNameCached::TokenComponentNameCached(const std::string& fullName)
: m_fullName(fullName)
TokenComponentNameCached::TokenComponentNameCached(const std::vector<std::string>& nameHierarchy)
: m_nameHierarchy(nameHierarchy)
{
}
@@ -58,17 +58,17 @@ TokenComponentNameCached::~TokenComponentNameCached()
std::shared_ptr<TokenComponent> TokenComponentNameCached::copy() const
{
return std::make_shared<TokenComponentNameCached>(m_fullName);
return std::make_shared<TokenComponentNameCached>(m_nameHierarchy);
}
std::string TokenComponentNameCached::getName() const
{
return utility::split(m_fullName, SearchIndex::DELIMITER).back();
return m_nameHierarchy.back();
}
std::string TokenComponentNameCached::getFullName() const
{
return m_fullName;
return utility::join(m_nameHierarchy, "::");
}
const SearchNode* TokenComponentNameCached::getSearchNode() const
@@ -45,7 +45,7 @@ class TokenComponentNameCached
: public TokenComponentName
{
public:
TokenComponentNameCached(const std::string& fullName);
TokenComponentNameCached(const std::vector<std::string>& nameHierarchy);
virtual ~TokenComponentNameCached();
virtual std::shared_ptr<TokenComponent> copy() const;
@@ -56,7 +56,7 @@ public:
virtual const SearchNode* getSearchNode() const;
private:
const std::string m_fullName;
const std::vector<std::string> m_nameHierarchy;
};
#endif // TOKEN_COMPONENT_NAME_H
+4 -1
View File
@@ -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;
+54 -38
View File
@@ -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;
}
+44 -10
View File
@@ -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;
}
}
+2
View File
@@ -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
+12
View File
@@ -24,6 +24,18 @@ const std::string& SearchNode::getName() const
return m_name;
}
std::vector<std::string> SearchNode::getNameHierarchy() const
{
std::vector<std::string> nameHierarchy;
const SearchNode* parent = getParent();
if (parent)
{
nameHierarchy = parent->getNameHierarchy();
}
nameHierarchy.push_back(getName());
return nameHierarchy;
}
std::string SearchNode::getFullName() const
{
if (m_parent && m_parent->m_nameId)
+1
View File
@@ -23,6 +23,7 @@ public:
~SearchNode();
const std::string& getName() const;
std::vector<std::string> getNameHierarchy() const;
std::string getFullName() const;
Id getNameId() const;