data: parsing template functions
* implemented parsing of template functions. * added tests for those cases.
This commit is contained in:
+29
-29
@@ -490,43 +490,26 @@ Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& v
|
||||
return edge->getId();
|
||||
}
|
||||
|
||||
Id Storage::onTemplateRecordParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy
|
||||
){
|
||||
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);
|
||||
m_graph.createEdge(Edge::EDGE_TEMPLATE_PARAMETER_OF, templateParameterNode, templateRecordNode);
|
||||
|
||||
return templateParameterNode->getId();
|
||||
}
|
||||
|
||||
Id Storage::onTemplateRecordArgumentTypeParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& templateArgumentTypeNameHierarchy,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy
|
||||
){
|
||||
Id Storage::onTemplateArgumentParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& argumentNameHierarchy,
|
||||
const std::vector<std::string>& templateNameHierarchy)
|
||||
{
|
||||
log(
|
||||
"template record argument",
|
||||
utility::join(templateArgumentTypeNameHierarchy, "::") + " -> " + utility::join(templateRecordNameHierarchy, "::"),
|
||||
"template argument",
|
||||
utility::join(argumentNameHierarchy, "::") + " -> " + utility::join(templateNameHierarchy, "::"),
|
||||
location
|
||||
);
|
||||
|
||||
Node* templateArgumentNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateArgumentTypeNameHierarchy);
|
||||
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateRecordNameHierarchy);
|
||||
m_graph.createEdge(Edge::EDGE_TEMPLATE_ARGUMENT_OF, templateArgumentNode, templateRecordNode);
|
||||
Node* argumentNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, argumentNameHierarchy);
|
||||
Node* templateNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateNameHierarchy);
|
||||
m_graph.createEdge(Edge::EDGE_TEMPLATE_ARGUMENT_OF, argumentNode, templateNode);
|
||||
|
||||
if (location.isValid())
|
||||
{
|
||||
addTokenLocation(templateArgumentNode, location);
|
||||
addTokenLocation(argumentNode, location);
|
||||
}
|
||||
|
||||
return templateArgumentNode->getId();
|
||||
return argumentNode->getId();
|
||||
}
|
||||
|
||||
Id Storage::onTemplateDefaultArgumentTypeParsed(
|
||||
@@ -550,6 +533,23 @@ Id Storage::onTemplateDefaultArgumentTypeParsed(
|
||||
return templateDefaultArgumentNode->getId();
|
||||
}
|
||||
|
||||
Id Storage::onTemplateRecordParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy
|
||||
){
|
||||
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);
|
||||
m_graph.createEdge(Edge::EDGE_TEMPLATE_PARAMETER_OF, templateParameterNode, templateRecordNode);
|
||||
|
||||
return templateParameterNode->getId();
|
||||
}
|
||||
|
||||
Id Storage::onTemplateRecordSpecializationParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy
|
||||
@@ -578,7 +578,7 @@ Id Storage::onTemplateRecordSpecializationParsed(
|
||||
Id Storage::onTemplateFunctionParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName, const ParseFunction function
|
||||
){
|
||||
log("function template type parameter", templateParameterTypeName, location);
|
||||
log("template function type parameter", templateParameterTypeName, location);
|
||||
|
||||
std::vector<std::string> templateParameterTypeNameHierarchy;
|
||||
templateParameterTypeNameHierarchy.push_back(function.getFullName() + "::"+ templateParameterTypeName);
|
||||
|
||||
@@ -84,19 +84,17 @@ public:
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function);
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable);
|
||||
|
||||
virtual Id onTemplateArgumentParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& argumentNameHierarchy,
|
||||
const std::vector<std::string>& templateNameHierarchy);
|
||||
virtual Id onTemplateDefaultArgumentTypeParsed(
|
||||
const ParseTypeUsage& type, const std::vector<std::string>& templateArgumentTypeNameHierarchy);
|
||||
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 onTemplateDefaultArgumentTypeParsed(
|
||||
const ParseTypeUsage& type, const std::vector<std::string>& templateArgumentTypeNameHierarchy);
|
||||
|
||||
virtual Id onTemplateRecordSpecializationParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||
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(
|
||||
|
||||
@@ -100,14 +100,14 @@ public:
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) = 0;
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable) = 0;
|
||||
|
||||
virtual Id onTemplateArgumentParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& argumentNameHierarchy,
|
||||
const std::vector<std::string>& templateNameHierarchy) = 0;
|
||||
virtual Id onTemplateDefaultArgumentTypeParsed(
|
||||
const ParseTypeUsage& type, const std::vector<std::string>& templateArgumentTypeNameHierarchy) = 0;
|
||||
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 onTemplateDefaultArgumentTypeParsed(
|
||||
const ParseTypeUsage& type, const std::vector<std::string>& templateArgumentTypeNameHierarchy) = 0;
|
||||
virtual Id onTemplateRecordSpecializationParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy) = 0;
|
||||
|
||||
@@ -322,6 +322,7 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
||||
{
|
||||
clang::ClassTemplateSpecializationDecl* specializationDecl = *it;
|
||||
|
||||
// The specializationParent can be an indirect specialization of the ClassTemplate (by specializing a partial specialization).
|
||||
std::vector<std::string> specializationParentNameHierarchy = utility::getTemplateSpecializationParentNameHierarchy(specializationDecl);
|
||||
|
||||
ParserClient::RecordType specializedRecordType = specializationDecl->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS;
|
||||
@@ -336,7 +337,7 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
||||
std::vector<std::string> argumentNameHierarchy = utility::templateArgumentToDataType(argList.get(i)).getTypeNameHierarchy();
|
||||
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
|
||||
{
|
||||
m_client->onTemplateRecordArgumentTypeParsed(
|
||||
m_client->onTemplateArgumentParsed(
|
||||
ParseLocation(), // TODO: Find a valid ParseLocation here!
|
||||
argumentNameHierarchy,
|
||||
specializedRecordNameHierarchy
|
||||
@@ -380,7 +381,7 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
const clang::QualType argumentType = argumentLoc.getArgument().getAsType();
|
||||
|
||||
m_client->onTemplateRecordArgumentTypeParsed(
|
||||
m_client->onTemplateArgumentParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
|
||||
specializedRecordNameHierarchy);
|
||||
@@ -391,21 +392,9 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
|
||||
|
||||
bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declaration)
|
||||
{
|
||||
const ParseFunction templateFunction = getParseFunction(declaration);
|
||||
if (isLocatedInMainFile(declaration))
|
||||
{
|
||||
const ParseFunction templateFunction = getParseFunction(declaration->getTemplatedDecl());
|
||||
for (clang::FunctionTemplateDecl::spec_iterator it = declaration->specializations().begin(); it != declaration->specializations().end(); it++)
|
||||
{
|
||||
ParseLocation specializedFunctionLocation = getParseLocationForNamedDecl(*(it));
|
||||
ParseFunction specializedFunction = getParseFunction(*(it));
|
||||
m_client->onTemplateFunctionSpecializationParsed(
|
||||
specializedFunctionLocation,
|
||||
specializedFunction,
|
||||
templateFunction);
|
||||
|
||||
m_client->onFunctionParsed(specializedFunctionLocation, specializedFunction, getParseLocationOfFunctionBody(*(it)));
|
||||
}
|
||||
|
||||
clang::TemplateParameterList* parameterList = declaration->getTemplateParameters();
|
||||
for (size_t i = 0; i < parameterList->size(); i++)
|
||||
{
|
||||
@@ -423,7 +412,58 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isLocatedInSourceFile(declaration))
|
||||
{
|
||||
for (clang::FunctionTemplateDecl::spec_iterator it = declaration->specializations().begin(); it != declaration->specializations().end(); it++)
|
||||
{
|
||||
const clang::FunctionDecl* specializedFunctionDecl = *it;
|
||||
ParseLocation specializedFunctionLocation = getParseLocationForNamedDecl(specializedFunctionDecl);
|
||||
ParseFunction specializedFunction = getParseFunction(specializedFunctionDecl);
|
||||
|
||||
clang::FunctionTemplateSpecializationInfo* info = specializedFunctionDecl->getTemplateSpecializationInfo();
|
||||
if (info->getTemplateSpecializationKind() == clang::TSK_ExplicitSpecialization)
|
||||
{
|
||||
if (isLocatedInMainFile(declaration))
|
||||
{
|
||||
m_client->onTemplateFunctionSpecializationParsed(
|
||||
specializedFunctionLocation,
|
||||
specializedFunction,
|
||||
templateFunction);
|
||||
|
||||
const clang::ASTTemplateArgumentListInfo* argumentInfoList = specializedFunctionDecl->getTemplateSpecializationArgsAsWritten();
|
||||
for (size_t i = 0; i < argumentInfoList->NumTemplateArgs; i++)
|
||||
{
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
const clang::QualType argumentType = argumentLoc.getArgument().getAsType();
|
||||
|
||||
m_client->onTemplateArgumentParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
|
||||
specializedFunction.nameHierarchy);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // info->getTemplateSpecializationKind() == clang::TSK_ImplicitInstantiation
|
||||
{
|
||||
m_client->onTemplateFunctionSpecializationParsed(
|
||||
specializedFunctionLocation,
|
||||
specializedFunction,
|
||||
templateFunction);
|
||||
|
||||
const clang::TemplateArgumentList* argumentList = specializedFunctionDecl->getTemplateSpecializationArgs();
|
||||
for (size_t i = 0; i < argumentList->size(); i++)
|
||||
{
|
||||
const clang::TemplateArgument& argument = argumentList->get(i);
|
||||
const clang::QualType argumentType = argument.getAsType();
|
||||
|
||||
m_client->onTemplateArgumentParsed(
|
||||
ParseLocation(), // TODO: get ParseLocation
|
||||
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
|
||||
specializedFunction.nameHierarchy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -682,7 +722,7 @@ ParseLocation ASTVisitor::getParseLocation(const clang::SourceRange& sourceRange
|
||||
);
|
||||
}
|
||||
|
||||
ParseLocation ASTVisitor::getParseLocationForNamedDecl(clang::NamedDecl* decl, const clang::SourceLocation& loc) const
|
||||
ParseLocation ASTVisitor::getParseLocationForNamedDecl(const clang::NamedDecl* decl, const clang::SourceLocation& loc) const
|
||||
{
|
||||
const clang::SourceManager& sourceManager = m_context->getSourceManager();
|
||||
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(loc);
|
||||
@@ -696,12 +736,12 @@ ParseLocation ASTVisitor::getParseLocationForNamedDecl(clang::NamedDecl* decl, c
|
||||
);
|
||||
}
|
||||
|
||||
ParseLocation ASTVisitor::getParseLocationForNamedDecl(clang::NamedDecl* decl) const
|
||||
ParseLocation ASTVisitor::getParseLocationForNamedDecl(const clang::NamedDecl* decl) const
|
||||
{
|
||||
return getParseLocationForNamedDecl(decl, decl->getLocation());
|
||||
}
|
||||
|
||||
ParseLocation ASTVisitor::getParseLocationOfFunctionBody(clang::FunctionDecl* decl) const
|
||||
ParseLocation ASTVisitor::getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const
|
||||
{
|
||||
if (decl->hasBody() && decl->isThisDeclarationADefinition())
|
||||
{
|
||||
@@ -818,3 +858,29 @@ ParseFunction ASTVisitor::getParseFunction(const clang::FunctionDecl* declaratio
|
||||
isConst
|
||||
);
|
||||
}
|
||||
|
||||
ParseFunction ASTVisitor::getParseFunction(const clang::FunctionTemplateDecl* declaration) const
|
||||
{
|
||||
bool isStatic = false;
|
||||
bool isConst = false;
|
||||
|
||||
const clang::FunctionDecl* templatedDecl = declaration->getTemplatedDecl();
|
||||
if (clang::isa<clang::CXXMethodDecl>(templatedDecl))
|
||||
{
|
||||
const clang::CXXMethodDecl* methodDecl = clang::dyn_cast<const clang::CXXMethodDecl>(templatedDecl);
|
||||
isStatic = methodDecl->isStatic();
|
||||
isConst = methodDecl->isConst();
|
||||
}
|
||||
else
|
||||
{
|
||||
isStatic = templatedDecl->getStorageClass() == clang::SC_Static;
|
||||
}
|
||||
|
||||
return ParseFunction(
|
||||
getParseTypeUsageOfReturnType(templatedDecl),
|
||||
utility::getDeclNameHierarchy(declaration),
|
||||
getParameters(templatedDecl),
|
||||
isStatic,
|
||||
isConst
|
||||
);
|
||||
}
|
||||
|
||||
@@ -62,9 +62,9 @@ private:
|
||||
ParserClient::AccessType convertAccessType(clang::AccessSpecifier) const;
|
||||
|
||||
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
|
||||
ParseLocation getParseLocationForNamedDecl(clang::NamedDecl* decl, const clang::SourceLocation& loc) const;
|
||||
ParseLocation getParseLocationForNamedDecl(clang::NamedDecl* decl) const;
|
||||
ParseLocation getParseLocationOfFunctionBody(clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocationForNamedDecl(const clang::NamedDecl* decl, const clang::SourceLocation& loc) const;
|
||||
ParseLocation getParseLocationForNamedDecl(const clang::NamedDecl* decl) const;
|
||||
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocationOfRecordBody(clang::CXXRecordDecl* decl) const;
|
||||
|
||||
ParseTypeUsage getParseTypeUsage(clang::TypeLoc typeLoc, const clang::QualType& type) const;
|
||||
@@ -73,6 +73,7 @@ private:
|
||||
|
||||
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;
|
||||
|
||||
@@ -255,6 +255,27 @@ namespace utility
|
||||
declName += specializedParameterNamePart;
|
||||
}
|
||||
}
|
||||
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 specializedParameterNamePart = "<";
|
||||
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);
|
||||
specializedParameterNamePart += templateArgumentToDataType(templateArgument).getFullTypeName();
|
||||
specializedParameterNamePart += (i < templateArgumentList->size() - 1) ? ", " : "";
|
||||
}
|
||||
specializedParameterNamePart += ">";
|
||||
declName += specializedParameterNamePart;
|
||||
}
|
||||
}
|
||||
else if (clang::isa<clang::TemplateDecl>(declaration))
|
||||
{
|
||||
std::string templateParameterNamePart = "<";
|
||||
|
||||
@@ -1564,7 +1564,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "test::T <1:20 1:20>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "test<T>::T <1:20 1:20>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_implicit_specialization_of_template_function()
|
||||
@@ -1583,7 +1583,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "test -> test <2:3 2:6>");
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "test<int> -> test<T> <2:3 2:6>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_explicit_specialization_of_template_function()
|
||||
@@ -1603,9 +1603,61 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "test -> test <8:5 8:8>");
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "test<int> -> test<T> <8:5 8:8>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_argument_of_explicit_specialization_of_template_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"void test()\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template <>\n"
|
||||
"void test<int>()\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "test<int>->int <7:11 7:11>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_argument_of_implicit_specialization_of_template_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"void test()\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" test<int>();\n"
|
||||
" return 1;\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "test<int>->int <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_default_argument_type_of_template_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T = int>\n"
|
||||
"void test()\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" test<int>();\n"
|
||||
" return 1;\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> test<T>::T <1:24 1:26>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1823,17 +1875,7 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateRecordParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy)
|
||||
{
|
||||
templateParameterTypes.push_back(
|
||||
addLocationSuffix(utility::join(templateRecordNameHierarchy, "::") + "::" + templateParameterTypeName, location)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateRecordArgumentTypeParsed(
|
||||
virtual Id onTemplateArgumentParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& templateArgumentTypeNameHierarchy,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy)
|
||||
{
|
||||
@@ -1852,6 +1894,16 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateRecordParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy)
|
||||
{
|
||||
templateParameterTypes.push_back(
|
||||
addLocationSuffix(utility::join(templateRecordNameHierarchy, "::") + "::" + templateParameterTypeName, location)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateRecordSpecializationParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy)
|
||||
|
||||
Reference in New Issue
Block a user