data: non-type- and template-template parameters
* name of template class now also contains type information on the template parameters (e.g. typename, class, bool, const std::string&, etc.) * implemented handling of non-type template parameters and template template parameters. * implemented lots of tests for these features.
This commit is contained in:
@@ -1,14 +1,8 @@
|
||||
template <typename T, typename U>
|
||||
class TemplateTestClass
|
||||
template <bool B, typename, class F>
|
||||
class Foo
|
||||
{
|
||||
public:
|
||||
template <typename P>
|
||||
void run(P param);
|
||||
void bar()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
template <typename P>
|
||||
void TemplateTestClass<T, U>::run(P param)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
TemplateTestClass<float, float> t1;
|
||||
t1.run<float>(6.9f);
|
||||
TemplateTestClass<int, int> t2;
|
||||
t2.run<int>(6);
|
||||
Foo<true, int, float> ft;
|
||||
ft.bar();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
[MainWindow]
|
||||
maximized=false
|
||||
size=@Size(600 400)
|
||||
position=@Point(200 200)
|
||||
|
||||
[General]
|
||||
DOCK_LOCATIONS=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x2\0\0\x2X\0\0\x1g\xfc\x1\0\0\0\x3\xfb\0\0\0\x1a\0\x44\0o\0\x63\0k\0G\0r\0\x61\0p\0h\0V\0i\0\x65\0w\x1\0\0\0\0\0\0\0\x86\0\0\0P\0\xff\xff\xff\xfb\0\0\0\x18\0\x44\0o\0\x63\0k\0\x43\0o\0\x64\0\x65\0V\0i\0\x65\0w\x1\0\0\0\x8a\0\0\0\xb3\0\0\0P\0\xff\xff\xff\xfb\0\0\0\"\0\x44\0o\0\x63\0k\0\x43\0o\0m\0p\0o\0s\0i\0t\0\x65\0V\0i\0\x65\0w\x1\0\0\x1\x41\0\0\x1\x17\0\0\x1\x10\0\xff\xff\xff\0\0\x2X\0\0\0\0\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\0)
|
||||
@@ -1,27 +1,4 @@
|
||||
ConfigManager.cpp ERROR: value path/to/nowhere is not present in config.
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
Edge.cpp ERROR: Nodes are not plain copies.
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Storage.cpp INFO: file: input.cc < 0:0 0:0>
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
Storage.cpp INFO: method: A::getCount <input.cc 8:13 8:20>
|
||||
Storage.cpp INFO: global usage: A::getCount -> A::count <input.cc 10:10 10:14>
|
||||
Storage.cpp INFO: method: A::process <input.cc 14:15 14:21>
|
||||
Storage.cpp INFO: field: A::count <input.cc 17:13 17:17>
|
||||
Storage.cpp INFO: class: B <input.cc 20:7 20:7>
|
||||
Storage.cpp INFO: inheritance: B : A <input.cc 21:4 21:11>
|
||||
Storage.cpp INFO: method: B::process <input.cc 24:15 24:21>
|
||||
Storage.cpp INFO: override: A::process -> B::process < 0:0 0:0>
|
||||
Storage.cpp INFO: type usage: B::process -> int <input.cc 26:3 26:5>
|
||||
Storage.cpp INFO: function: main <input.cc 30:5 30:8>
|
||||
Storage.cpp INFO: type usage: main -> B <input.cc 32:2 32:2>
|
||||
Storage.cpp INFO: call: main -> B::B <input.cc 32:4 32:4>
|
||||
Storage.cpp INFO: call: main -> A::getCount <input.cc 34:9 34:21>
|
||||
Storage.cpp INFO: file: input.cc < 0:0 0:0>
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
@@ -56,6 +33,29 @@ SearchMatch.cpp INFO:
|
||||
190 A::A
|
||||
^^^^
|
||||
|
||||
Storage.cpp INFO: file: input.cc < 0:0 0:0>
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
Storage.cpp INFO: method: A::getCount <input.cc 8:13 8:20>
|
||||
Storage.cpp INFO: global usage: A::getCount -> A::count <input.cc 10:10 10:14>
|
||||
Storage.cpp INFO: method: A::process <input.cc 14:15 14:21>
|
||||
Storage.cpp INFO: field: A::count <input.cc 17:13 17:17>
|
||||
Storage.cpp INFO: class: B <input.cc 20:7 20:7>
|
||||
Storage.cpp INFO: inheritance: B : A <input.cc 21:4 21:11>
|
||||
Storage.cpp INFO: method: B::process <input.cc 24:15 24:21>
|
||||
Storage.cpp INFO: override: A::process -> B::process < 0:0 0:0>
|
||||
Storage.cpp INFO: type usage: B::process -> int <input.cc 26:3 26:5>
|
||||
Storage.cpp INFO: function: main <input.cc 30:5 30:8>
|
||||
Storage.cpp INFO: type usage: main -> B <input.cc 32:2 32:2>
|
||||
Storage.cpp INFO: call: main -> B::B <input.cc 32:4 32:4>
|
||||
Storage.cpp INFO: call: main -> A::getCount <input.cc 34:9 34:21>
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
Edge.cpp ERROR: Nodes are not plain copies.
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Settings.cpp WARNING: File for Settings not found.
|
||||
ConfigManager.cpp ERROR: value Bool is not present in config.
|
||||
ConfigManager.cpp ERROR: value Int is not present in config.
|
||||
@@ -71,6 +71,7 @@ ConfigManager.cpp ERROR: value Int is not present in config.
|
||||
ConfigManager.cpp ERROR: value Float is not present in config.
|
||||
ConfigManager.cpp ERROR: value String is not present in config.
|
||||
ConfigManager.cpp ERROR: value NewBool is not present in config.
|
||||
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
|
||||
Storage.cpp INFO: typedef: type -> int <file.cpp 1:1 1:1>
|
||||
Storage.cpp INFO: class: Class <file.cpp 1:1 1:1>
|
||||
Storage.cpp INFO: struct: Struct <file.cpp 1:1 1:1>
|
||||
@@ -135,7 +136,6 @@ Storage.cpp INFO: file: file.h < 0:0 0:0>
|
||||
Storage.cpp INFO: file: file.cpp < 0:0 0:0>
|
||||
Storage.cpp INFO: include: f.h <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: include: file.h <file.cpp 1:0 1:0>
|
||||
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
|
||||
TextAccess.cpp WARNING: Index 'firstLine' has to be lower or equal index 'lastLine', is 3 > 2
|
||||
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
|
||||
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
|
||||
|
||||
@@ -532,12 +532,12 @@ Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& v
|
||||
return edge->getId();
|
||||
}
|
||||
|
||||
Id Storage::onTemplateArgumentParsed(
|
||||
Id Storage::onTemplateArgumentTypeParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& argumentNameHierarchy,
|
||||
const std::vector<std::string>& templateNameHierarchy)
|
||||
{
|
||||
log(
|
||||
"template argument",
|
||||
"template argument type",
|
||||
utility::join(argumentNameHierarchy, "::") + " -> " + utility::join(templateNameHierarchy, "::"),
|
||||
location
|
||||
);
|
||||
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function);
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable);
|
||||
|
||||
virtual Id onTemplateArgumentParsed(
|
||||
virtual Id onTemplateArgumentTypeParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& argumentNameHierarchy,
|
||||
const std::vector<std::string>& templateNameHierarchy);
|
||||
virtual Id onTemplateDefaultArgumentTypeParsed(
|
||||
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) = 0;
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable) = 0;
|
||||
|
||||
virtual Id onTemplateArgumentParsed(
|
||||
virtual Id onTemplateArgumentTypeParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& argumentNameHierarchy,
|
||||
const std::vector<std::string>& templateNameHierarchy) = 0;
|
||||
virtual Id onTemplateDefaultArgumentTypeParsed(
|
||||
|
||||
@@ -303,11 +303,14 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
||||
for (size_t i = 0; i < parameterList->size(); i++)
|
||||
{
|
||||
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
||||
m_client->onTemplateRecordParameterTypeParsed(
|
||||
getParseLocationForNamedDecl(namedDecl),
|
||||
utility::getDeclNameHierarchy(namedDecl),
|
||||
templateRecordNameHierarchy
|
||||
);
|
||||
if (!namedDecl->getName().empty()) // do not create node for template param if the param has no name
|
||||
{
|
||||
m_client->onTemplateRecordParameterTypeParsed(
|
||||
getParseLocationForNamedDecl(namedDecl),
|
||||
utility::getDeclNameHierarchy(namedDecl),
|
||||
templateRecordNameHierarchy
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +342,7 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
||||
|
||||
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
|
||||
{
|
||||
m_client->onTemplateArgumentParsed(
|
||||
m_client->onTemplateArgumentTypeParsed(
|
||||
ParseLocation(specializationFilePath, 0, 0), // TODO: Find a valid ParseLocation here!
|
||||
argumentNameHierarchy,
|
||||
specializedRecordNameHierarchy
|
||||
@@ -367,11 +370,14 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
|
||||
for (size_t i = 0; i < parameterList->size(); i++)
|
||||
{
|
||||
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
||||
m_client->onTemplateRecordParameterTypeParsed(
|
||||
getParseLocationForNamedDecl(namedDecl),
|
||||
utility::getDeclNameHierarchy(namedDecl),
|
||||
specializedRecordNameHierarchy
|
||||
);
|
||||
if (!namedDecl->getName().empty()) // do not create node for template param if the param has no name
|
||||
{
|
||||
m_client->onTemplateRecordParameterTypeParsed(
|
||||
getParseLocationForNamedDecl(namedDecl),
|
||||
utility::getDeclNameHierarchy(namedDecl),
|
||||
specializedRecordNameHierarchy
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const clang::ASTTemplateArgumentListInfo* argumentInfoList = declaration->getTemplateArgsAsWritten();
|
||||
@@ -379,15 +385,11 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
|
||||
{
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
const clang::TemplateArgument& argument = argumentLoc.getArgument();
|
||||
if (argument.getKind() == clang::TemplateArgument::Type)
|
||||
{
|
||||
const clang::QualType argumentType = argument.getAsType();
|
||||
|
||||
m_client->onTemplateArgumentParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
|
||||
specializedRecordNameHierarchy);
|
||||
}
|
||||
m_client->onTemplateArgumentTypeParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
utility::templateArgumentToDataType(argument).getTypeNameHierarchy(),
|
||||
specializedRecordNameHierarchy);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -439,7 +441,7 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
const clang::QualType argumentType = argumentLoc.getArgument().getAsType();
|
||||
|
||||
m_client->onTemplateArgumentParsed(
|
||||
m_client->onTemplateArgumentTypeParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
|
||||
specializedFunction.nameHierarchy);
|
||||
@@ -459,7 +461,7 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
|
||||
const clang::TemplateArgument& argument = argumentList->get(i);
|
||||
const clang::QualType argumentType = argument.getAsType();
|
||||
|
||||
m_client->onTemplateArgumentParsed(
|
||||
m_client->onTemplateArgumentTypeParsed(
|
||||
ParseLocation(specializedFunctionLocation.filePath, 0, 0), // TODO: Find a valid ParseLocation here!
|
||||
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
|
||||
specializedFunction.nameHierarchy);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "data/type/DataTypeQualifierList.h"
|
||||
#include "utility/utilityString.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace utility
|
||||
{
|
||||
@@ -26,7 +27,6 @@ namespace utility
|
||||
while (needsRefinement)
|
||||
{
|
||||
const clang::Type* type = qualType.getTypePtr();
|
||||
clang::Type::TypeClass tk = type->getTypeClass();
|
||||
switch (type->getTypeClass())
|
||||
{
|
||||
case clang::Type::Paren:
|
||||
@@ -92,7 +92,6 @@ namespace utility
|
||||
break;
|
||||
}
|
||||
case clang::Type::Builtin:
|
||||
case clang::Type::TemplateSpecialization:
|
||||
{
|
||||
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
|
||||
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
|
||||
@@ -100,6 +99,12 @@ namespace utility
|
||||
std::string typeName = qualType.getUnqualifiedType().getAsString(pp);
|
||||
typeNameHerarchy.push_back(typeName);
|
||||
|
||||
needsRefinement = false;
|
||||
break;
|
||||
}
|
||||
case clang::Type::TemplateSpecialization:
|
||||
{
|
||||
typeNameHerarchy = getDeclNameHierarchy(type->getAs<clang::TagType>()->getDecl());
|
||||
needsRefinement = false;
|
||||
break;
|
||||
}
|
||||
@@ -175,7 +180,8 @@ namespace utility
|
||||
LOG_ERROR("unhandled declaration type: " + std::string(declaration->getDeclKindName()));
|
||||
}
|
||||
contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext());
|
||||
if (clang::isa<clang::TemplateTypeParmDecl>(declaration))
|
||||
if (clang::isa<clang::NonTypeTemplateParmDecl>(declaration) ||
|
||||
clang::isa<clang::TemplateTypeParmDecl>(declaration)) // TODO: Handle templatetemplate stuff
|
||||
{
|
||||
contextNameHierarchy.back() += "::" + declName;
|
||||
}
|
||||
@@ -211,7 +217,6 @@ namespace utility
|
||||
std::string getDeclName(const clang::NamedDecl* declaration)
|
||||
{
|
||||
std::string declName = declaration->getNameAsString();
|
||||
|
||||
if (clang::isa<clang::CXXRecordDecl>(declaration))
|
||||
{
|
||||
clang::ClassTemplateDecl* templateClassDeclaration = clang::dyn_cast<clang::CXXRecordDecl>(declaration)->getDescribedClassTemplate();
|
||||
@@ -224,24 +229,23 @@ namespace utility
|
||||
const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl =
|
||||
clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration);
|
||||
|
||||
clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters();
|
||||
int currentParameterIndex = 0;
|
||||
|
||||
std::string specializedParameterNamePart = "<";
|
||||
int templateArgumentCount = partialSpecializationDecl->getTemplateArgs().size();
|
||||
const clang::ASTTemplateArgumentListInfo* templateArgumentListInfo = partialSpecializationDecl->getTemplateArgsAsWritten();
|
||||
std::string specializedParameterNamePart = "<";
|
||||
for (int i = 0; i < templateArgumentCount; i++)
|
||||
{
|
||||
const clang::TemplateArgument& templateArgument = templateArgumentListInfo->getTemplateArgs()[i].getArgument();
|
||||
const clang::TemplateArgument::ArgKind kind = templateArgument.getKind();
|
||||
switch (kind)
|
||||
if (templateArgument.isDependent()) // TODO: fix case when arg depends on template parameter of outer template class.
|
||||
{
|
||||
case clang::TemplateArgument::Type:
|
||||
specializedParameterNamePart += templateArgument.getAsType().getAsString();
|
||||
break;
|
||||
case clang::TemplateArgument::Integral:
|
||||
specializedParameterNamePart += templateArgument.getIntegralType().getAsString();
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Type of template argument not handled.");
|
||||
break;
|
||||
specializedParameterNamePart += getTemplateParameterString(parameterList->getParam(currentParameterIndex));
|
||||
currentParameterIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
specializedParameterNamePart += getTemplateArgumentName(templateArgument);
|
||||
}
|
||||
specializedParameterNamePart += (i < templateArgumentCount - 1) ? ", " : "";
|
||||
}
|
||||
@@ -254,8 +258,7 @@ namespace utility
|
||||
const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(declaration)->getTemplateArgs();
|
||||
for (size_t i = 0; i < templateArgumentList.size(); i++)
|
||||
{
|
||||
const clang::TemplateArgument& templateArgument = templateArgumentList.get(i);
|
||||
specializedParameterNamePart += templateArgumentToDataType(templateArgument).getFullTypeName();
|
||||
specializedParameterNamePart += getTemplateArgumentName(templateArgumentList.get(i));
|
||||
specializedParameterNamePart += (i < templateArgumentList.size() - 1) ? ", " : "";
|
||||
}
|
||||
specializedParameterNamePart += ">";
|
||||
@@ -283,15 +286,17 @@ namespace utility
|
||||
declName += specializedParameterNamePart;
|
||||
}
|
||||
}
|
||||
else if (clang::isa<clang::TemplateTemplateParmDecl>(declaration))
|
||||
{
|
||||
// nothing to do here
|
||||
}
|
||||
else if (clang::isa<clang::TemplateDecl>(declaration))
|
||||
{
|
||||
std::string templateParameterNamePart = "<";
|
||||
clang::TemplateParameterList* parameterList = clang::dyn_cast<clang::TemplateDecl>(declaration)->getTemplateParameters();
|
||||
for (size_t i = 0; i < parameterList->size(); i++)
|
||||
{
|
||||
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
||||
|
||||
templateParameterNamePart += namedDecl->getNameAsString();
|
||||
templateParameterNamePart += getTemplateParameterString(parameterList->getParam(i));
|
||||
templateParameterNamePart += (i < parameterList->size() - 1) ? ", " : "";
|
||||
}
|
||||
templateParameterNamePart += ">";
|
||||
@@ -323,7 +328,7 @@ namespace utility
|
||||
return specializationParentNameHierarchy;
|
||||
}
|
||||
|
||||
DataType templateArgumentToDataType(const clang::TemplateArgument& argument)
|
||||
DataType templateArgumentToDataType(const clang::TemplateArgument& argument) // remove this! this is stupid! agurment is not always a datatype.
|
||||
{
|
||||
const clang::TemplateArgument::ArgKind kind = argument.getKind();
|
||||
switch (kind)
|
||||
@@ -332,10 +337,115 @@ namespace utility
|
||||
return utility::qualTypeToDataType(argument.getAsType());
|
||||
case clang::TemplateArgument::Integral:
|
||||
return utility::qualTypeToDataType(argument.getIntegralType());
|
||||
case clang::TemplateArgument::Null:
|
||||
LOG_ERROR("Type of template argument not handled: Null");
|
||||
break;
|
||||
case clang::TemplateArgument::Declaration:
|
||||
return utility::qualTypeToDataType(argument.getAsDecl()->getType());
|
||||
case clang::TemplateArgument::NullPtr:
|
||||
return utility::qualTypeToDataType(argument.getNullPtrType());
|
||||
break;
|
||||
case clang::TemplateArgument::Template:
|
||||
{
|
||||
clang::TemplateName templateName = argument.getAsTemplate();
|
||||
switch (templateName.getKind())
|
||||
{
|
||||
case clang::TemplateName::Template:
|
||||
return DataType(getDeclNameHierarchy(templateName.getAsTemplateDecl()));
|
||||
}
|
||||
LOG_ERROR("Type of template argument not handled: Template");
|
||||
}
|
||||
break;
|
||||
case clang::TemplateArgument::TemplateExpansion:
|
||||
LOG_ERROR("Type of template argument not handled: TemplateExpansion");
|
||||
break;
|
||||
case clang::TemplateArgument::Expression:
|
||||
return utility::qualTypeToDataType(argument.getAsExpr()->getType());
|
||||
case clang::TemplateArgument::Pack:
|
||||
LOG_ERROR("Type of template argument not handled: Pack");
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Type of template argument not handled.");
|
||||
LOG_ERROR("Type of template argument not handled." + argument.getKind());
|
||||
break;
|
||||
}
|
||||
return DataType(std::vector<std::string>());
|
||||
}
|
||||
|
||||
std::string getTemplateParameterString(const clang::NamedDecl* parameter)
|
||||
{
|
||||
std::string templateParameterString = "";
|
||||
clang::Decl::Kind templateParameterKind = parameter->getKind();
|
||||
switch (templateParameterKind)
|
||||
{
|
||||
case clang::Decl::NonTypeTemplateParm:
|
||||
{
|
||||
const clang::NonTypeTemplateParmDecl* nonTypeTemplateParmDecl = clang::dyn_cast<clang::NonTypeTemplateParmDecl>(parameter);
|
||||
templateParameterString = qualTypeToDataType(nonTypeTemplateParmDecl->getType()).getFullTypeName();
|
||||
}
|
||||
break;
|
||||
case clang::Decl::TemplateTypeParm:
|
||||
{
|
||||
const clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast<clang::TemplateTypeParmDecl>(parameter);
|
||||
templateParameterString = templateTypeParmDecl->wasDeclaredWithTypename() ? "typename" : "class";
|
||||
}
|
||||
break;
|
||||
case clang::Decl::TemplateTemplateParm:
|
||||
{
|
||||
const clang::TemplateTemplateParmDecl* templateTemplateParmDecl = clang::dyn_cast<clang::TemplateTemplateParmDecl>(parameter);
|
||||
templateParameterString = "template<";
|
||||
clang::TemplateParameterList* parameterList = templateTemplateParmDecl->getTemplateParameters();
|
||||
for (size_t i = 0; i < parameterList->size(); i++)
|
||||
{
|
||||
templateParameterString += getTemplateParameterString(parameterList->getParam(i));
|
||||
templateParameterString += (i < parameterList->size() - 1) ? ", " : "";
|
||||
}
|
||||
templateParameterString += ">";
|
||||
templateParameterString += " typename"; // TODO: what if template template parameter is defined with class keyword?
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unhandled kind of template parameter.");
|
||||
}
|
||||
|
||||
std::string parameterName = parameter->getName();
|
||||
if (!parameterName.empty())
|
||||
{
|
||||
templateParameterString += " " + parameterName;
|
||||
}
|
||||
return templateParameterString;
|
||||
}
|
||||
|
||||
std::string getTemplateArgumentName(const clang::TemplateArgument& argument)
|
||||
{
|
||||
const clang::TemplateArgument::ArgKind kind = argument.getKind();
|
||||
switch (kind)
|
||||
{
|
||||
case clang::TemplateArgument::Type:
|
||||
return utility::qualTypeToDataType(argument.getAsType()).getFullTypeName();
|
||||
case clang::TemplateArgument::Integral:
|
||||
case clang::TemplateArgument::Null:
|
||||
case clang::TemplateArgument::Declaration:
|
||||
case clang::TemplateArgument::NullPtr:
|
||||
case clang::TemplateArgument::Template:
|
||||
case clang::TemplateArgument::TemplateExpansion:
|
||||
case clang::TemplateArgument::Expression:
|
||||
{
|
||||
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
|
||||
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
|
||||
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
|
||||
|
||||
std::string buf;
|
||||
llvm::raw_string_ostream os(buf);
|
||||
argument.print(pp, os);
|
||||
return os.str();
|
||||
}
|
||||
case clang::TemplateArgument::Pack:
|
||||
LOG_ERROR("Type of template argument not handled: Pack");
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Type of template argument not handled." + argument.getKind());
|
||||
break;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace utility
|
||||
std::string getDeclName(const clang::NamedDecl* declaration);
|
||||
std::vector<std::string> getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration);
|
||||
DataType templateArgumentToDataType(const clang::TemplateArgument& argument);
|
||||
std::string getTemplateParameterString(const clang::NamedDecl* parameter);
|
||||
std::string getTemplateArgumentName(const clang::TemplateArgument& argument);
|
||||
}
|
||||
|
||||
#endif // UTILITY_CLANG_H
|
||||
|
||||
+334
-34
@@ -1198,7 +1198,7 @@ public:
|
||||
}
|
||||
|
||||
|
||||
void test_cxx_parser_finds_template_parameter_type_of_template_class()
|
||||
void test_cxx_parser_finds_type_template_parameter_type_of_template_class()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
@@ -1208,10 +1208,69 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<T>::T <1:20 1:20>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<typename T>::T <1:20 1:20>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_parameter_types_of_template_class_with_multiple_parameters()
|
||||
void test_cxx_parser_finds_type_template_parameter_defined_with_class_keyword()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <class T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<class T>::T <1:17 1:17>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_int_template_parameter_of_template_class()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <int T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<int T>::T <1:15 1:15>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_bool_template_parameter_of_template_class()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <bool T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<bool T>::T <1:16 1:16>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_template_parameter_of_template_class()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{};\n"
|
||||
"template <template<typename> typename T>\n"
|
||||
"class B\n"
|
||||
"{};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" B<A> ba;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<typename T>::T <1:20 1:20>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "B<template<typename> typename T>::T <4:39 4:39>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_type_template_parameters_of_template_class_with_multiple_parameters()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T, typename U>\n"
|
||||
@@ -1221,8 +1280,21 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<T, U>::T <1:20 1:20>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A<T, U>::U <1:32 1:32>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<typename T, typename U>::T <1:20 1:20>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A<typename T, typename U>::U <1:32 1:32>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_skips_creating_node_for_template_parameter_without_a_name()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->classes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->classes[0], "A<typename> <2:1 <2:7 2:7> 4:1>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_parameter_of_template_method_definition_outside_template_class()
|
||||
@@ -1240,12 +1312,12 @@ public:
|
||||
"{}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 3);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<T>::T <1:20 1:20>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A<T>::foo<U>::U <4:21 4:21>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[2], "A<T>::foo<U>::U <8:20 8:20>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<typename T>::T <1:20 1:20>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A<typename T>::foo<typename U>::U <4:21 4:21>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[2], "A<typename T>::foo<typename U>::U <8:20 8:20>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_argument_of_implicit_template_specialization()
|
||||
void test_cxx_parser_finds_type_template_argument_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
@@ -1262,6 +1334,112 @@ public:
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_int_template_argument_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <int T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<1> a;\n"
|
||||
" return 0;\n"
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<1>->int <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_bool_template_argument_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <bool T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<true> a;\n"
|
||||
" return 0;\n"
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<true>->bool <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_custom_pointer_template_argument_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"class P\n"
|
||||
"{};\n"
|
||||
"template <P* p>\n"
|
||||
"class A\n"
|
||||
"{};\n"
|
||||
"P p;\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<&p> a;\n"
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_custom_reference_template_argument_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"class P\n"
|
||||
"{};\n"
|
||||
"template <P& p>\n"
|
||||
"class A\n"
|
||||
"{};\n"
|
||||
"P p;\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<p> a;\n"
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_nullptr_template_argument_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"#include <cstddef>\n"
|
||||
"template <std::nullptr_t T>\n"
|
||||
"class A\n"
|
||||
"{};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<nullptr> a;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<nullptr>->nullptr_t <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_template_argument_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{};\n"
|
||||
"template <template<typename> typename T>\n"
|
||||
"class B\n"
|
||||
"{};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" B<A> ba;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<A>->A<typename T> <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_explicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
@@ -1275,7 +1453,74 @@ public:
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<int> -> A<T> <6:7 6:7>");
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<int> -> A<typename T> <6:7 6:7>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_type_template_argument_of_explicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"template <>\n"
|
||||
"class A<int>\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_int_template_argument_of_explicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <int T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"template <>\n"
|
||||
"class A<1>\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<1>->int <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_bool_template_argument_of_explicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <bool T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"template <>\n"
|
||||
"class A<true>\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<true>->bool <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_template_argument_of_explicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{};\n"
|
||||
"template <template<typename> typename T>\n"
|
||||
"class B\n"
|
||||
"{};\n"
|
||||
"template <>\n"
|
||||
"class B<A>\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<A>->A<typename T> <0:0 0:0>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_explicit_partial_template_specialization()
|
||||
@@ -1291,10 +1536,10 @@ public:
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<T, int> -> A<T, U> <6:7 6:7>");
|
||||
// TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<typename T, int> -> A<typename T, typename U> <6:7 6:7>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_argument_of_explicit_partial_template_specialization()
|
||||
void test_cxx_parser_finds_type_template_argument_of_explicit_partial_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T, typename U>\n"
|
||||
@@ -1307,8 +1552,44 @@ public:
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<T, int>->A<T, int>::T <6:9 6:9>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<T, int>->int <6:12 6:12>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<typename T, int>->A<typename T, int>::T <6:9 6:9>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<typename T, int>->int <6:12 6:12>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_specialized_non_type_bool_template_argument_of_explicit_partial_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <bool T, typename U>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"template <typename U>\n"
|
||||
"class A<true, U>\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<true, typename U>->bool <6:9 6:9>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<true, typename U>->A<true, typename U>::U <6:15 6:15>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_unspecialized_non_type_bool_template_argument_of_explicit_partial_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <bool T, typename U>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"template <bool T>\n"
|
||||
"class A<T, int>\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<bool T, int>->bool <6:9 6:9>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<bool T, int>->int <6:12 6:12>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_correct_name_of_explicit_template_specialization()
|
||||
@@ -1324,8 +1605,8 @@ public:
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->classes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->classes[0], "A<T, U> <2:1 <2:7 2:7> 4:1>");
|
||||
TS_ASSERT_EQUALS(client->classes[1], "A<T, int> <5:1 <6:7 6:7> 8:1>");
|
||||
TS_ASSERT_EQUALS(client->classes[0], "A<typename T, typename U> <2:1 <2:7 2:7> 4:1>");
|
||||
TS_ASSERT_EQUALS(client->classes[1], "A<typename T, int> <5:1 <6:7 6:7> 8:1>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_argument_of_explicit_template_specialization()
|
||||
@@ -1355,7 +1636,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->fields.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private int A<T>::foo <4:6 4:8>");
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private int A<typename T>::foo <4:6 4:8>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_correct_type_of_field_member_of_template_class_in_declaration()
|
||||
@@ -1369,7 +1650,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->fields.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private A<T>::T A<T>::foo <4:4 4:6>");
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private A<typename T>::T A<typename T>::foo <4:4 4:6>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_implicit_template_class_specialization()
|
||||
@@ -1385,7 +1666,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<int> -> A<T> <2:7 2:7>");
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<int> -> A<typename T> <2:7 2:7>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_class_inheritance_from_implicit_template_class_specialization()
|
||||
@@ -1438,7 +1719,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->usages.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->usages[0], "void A<T>::A<T>() -> A<T>::foo <4:7 4:9>");
|
||||
TS_ASSERT_EQUALS(client->usages[0], "void A<typename T>::A<T>() -> A<typename T>::foo <4:7 4:9>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_enum_definition_in_template_class()
|
||||
@@ -1456,7 +1737,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->enums.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->enums[0], "private A<T>::TestType <4:2 <4:7 4:14> 8:2>");
|
||||
TS_ASSERT_EQUALS(client->enums[0], "private A<typename T>::TestType <4:2 <4:7 4:14> 8:2>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_enum_usage_in_template_class()
|
||||
@@ -1475,7 +1756,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->fields.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private A<T>::TestType A<T>::foo <9:11 9:13>");
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private A<typename T>::TestType A<typename T>::foo <9:11 9:13>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_enum_constants_in_template_class()
|
||||
@@ -1493,8 +1774,8 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->enumConstants.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->enumConstants[0], "A<T>::TestType::TEST_ONE <6:3 6:3>");
|
||||
TS_ASSERT_EQUALS(client->enumConstants[1], "A<T>::TestType::TEST_TWO <7:3 7:3>");
|
||||
TS_ASSERT_EQUALS(client->enumConstants[0], "A<typename T>::TestType::TEST_ONE <6:3 6:3>");
|
||||
TS_ASSERT_EQUALS(client->enumConstants[1], "A<typename T>::TestType::TEST_TWO <7:3 7:3>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_correct_field_member_type_of_nested_template_class_in_declaration_____typedef()
|
||||
@@ -1508,7 +1789,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->typedefs.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->typedefs[0], "private A<T>::T -> A<T>::TempType <4:12 4:19>");
|
||||
TS_ASSERT_EQUALS(client->typedefs[0], "private A<typename T>::T -> A<typename T>::TempType <4:12 4:19>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_correct_field_member_type_of_nested_template_class_in_declaration()
|
||||
@@ -1525,7 +1806,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->fields.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private A<T>::T A<T>::B::foo <6:5 6:7>");
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private A<typename T>::T A<typename T>::B::foo <6:5 6:7>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_correct_method_member_name_of_template_class_in_declaration()
|
||||
@@ -1539,7 +1820,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->methods.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->methods[0], "private int A<T>::foo() <4:6 4:8>");
|
||||
TS_ASSERT_EQUALS(client->methods[0], "private int A<typename T>::foo() <4:6 4:8>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_correct_method_return_type_of_template_class_in_declaration()
|
||||
@@ -1553,7 +1834,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->methods.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->methods[0], "private A<T>::T A<T>::foo() <4:4 4:6>");
|
||||
TS_ASSERT_EQUALS(client->methods[0], "private A<typename T>::T A<typename T>::foo() <4:4 4:6>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_default_argument_type_of_template_class()
|
||||
@@ -1566,11 +1847,30 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> A<T>::T <1:24 1:26>");
|
||||
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> A<typename T>::T <1:24 1:26>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//void ___test_cxx_parser_skips_creating_node_for_explicit_template_specialization_with_template_parameter_without_a_name() // i think this would not be valid code...
|
||||
//{
|
||||
// std::shared_ptr<TestParserClient> client = parseCode(
|
||||
// "template <typename T>\n"
|
||||
// "class A\n"
|
||||
// "{\n"
|
||||
// "};\n"
|
||||
// "template <typename>\n"
|
||||
// "class A<int>\n"
|
||||
// "{\n"
|
||||
// "};\n"
|
||||
// );
|
||||
|
||||
// TS_ASSERT_EQUALS(client->classes.size(), 1);
|
||||
// TS_ASSERT_EQUALS(client->classes[0], "A<typename> <2:1 <2:7 2:7> 4:1>");
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void test_cxx_parser_finds_template_parameter_type_of_template_function()
|
||||
@@ -1584,7 +1884,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "test<T>::T <1:20 1:20>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "test<typename T>::T <1:20 1:20>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_implicit_specialization_of_template_function()
|
||||
@@ -1603,7 +1903,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "test<int> -> test<T> <2:3 2:6>");
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "test<int> -> test<typename T> <2:3 2:6>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_explicit_specialization_of_template_function()
|
||||
@@ -1623,7 +1923,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "test<int> -> test<T> <8:5 8:8>");
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "test<int> -> test<typename T> <8:5 8:8>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_argument_of_explicit_specialization_of_template_function()
|
||||
@@ -1676,7 +1976,7 @@ public:
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> test<T>::T <1:24 1:26>");
|
||||
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> test<typename T>::T <1:24 1:26>");
|
||||
}
|
||||
|
||||
|
||||
@@ -1898,7 +2198,7 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateArgumentParsed(
|
||||
virtual Id onTemplateArgumentTypeParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& templateArgumentTypeNameHierarchy,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user