src: Template Argument Handling
* improved handling of template arguments
This commit is contained in:
@@ -516,7 +516,7 @@ Id Storage::onTypeUsageParsed(const ParseTypeUsage& typeUsage, const ParseVariab
|
||||
return edgeId;
|
||||
}
|
||||
|
||||
Id Storage::onTemplateArgumentTypeParsed(
|
||||
Id Storage::onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const NameHierarchy& templateNameHierarchy)
|
||||
{
|
||||
@@ -536,20 +536,40 @@ Id Storage::onTemplateArgumentTypeParsed(
|
||||
return argumentNodeId;
|
||||
}
|
||||
|
||||
Id Storage::onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseFunction& templateFunction)
|
||||
{
|
||||
log(
|
||||
"template argument type",
|
||||
argumentNameHierarchy.getFullName() + " -> " + templateFunction.getFullName(),
|
||||
location
|
||||
);
|
||||
|
||||
Id argumentNodeId = addNodeHierarchy(Node::NODE_TYPE, argumentNameHierarchy, false);
|
||||
// does not need a source location because this type that is already defined (and therefore has a location).
|
||||
|
||||
Id templateNodeId = addNodeHierarchyWithDistinctSignature(Node::NODE_FUNCTION, templateFunction, false);
|
||||
|
||||
addEdge(templateNodeId, argumentNodeId, Edge::EDGE_TEMPLATE_ARGUMENT, location);
|
||||
|
||||
return argumentNodeId;
|
||||
}
|
||||
|
||||
Id Storage::onTemplateDefaultArgumentTypeParsed(
|
||||
const ParseTypeUsage& defaultArgumentTypeUsage,
|
||||
const NameHierarchy& templateArgumentTypeNameHierarchy // actually this is the template parameter???
|
||||
const NameHierarchy& templateParameterNameHierarchy // actually this is the template parameter???
|
||||
){
|
||||
log(
|
||||
"template default argument",
|
||||
defaultArgumentTypeUsage.dataType->getTypeNameHierarchy().getFullName() + " -> " + templateArgumentTypeNameHierarchy.getFullName(),
|
||||
defaultArgumentTypeUsage.dataType->getTypeNameHierarchy().getFullName() + " -> " + templateParameterNameHierarchy.getFullName(),
|
||||
defaultArgumentTypeUsage.location
|
||||
);
|
||||
|
||||
Id defaultArgumentNodeId = addNodeHierarchy(Node::NODE_TYPE, defaultArgumentTypeUsage.dataType->getTypeNameHierarchy(), false);
|
||||
// does not need a source location because this type that is already defined (and therefore has a location).
|
||||
|
||||
Id argumentNodeId = addNodeHierarchy(Node::NODE_TYPE, templateArgumentTypeNameHierarchy, false);
|
||||
Id argumentNodeId = addNodeHierarchy(Node::NODE_TYPE, templateParameterNameHierarchy, false);
|
||||
|
||||
addEdge(argumentNodeId, defaultArgumentNodeId, Edge::EDGE_TEMPLATE_DEFAULT_ARGUMENT, defaultArgumentTypeUsage.location);
|
||||
|
||||
|
||||
@@ -100,11 +100,14 @@ public:
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& typeUsage, const ParseFunction& function);
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& typeUsage, const ParseVariable& variable);
|
||||
|
||||
virtual Id onTemplateArgumentTypeParsed(
|
||||
virtual Id onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const NameHierarchy& templateNameHierarchy);
|
||||
virtual Id onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseFunction& templateFunction);
|
||||
virtual Id onTemplateDefaultArgumentTypeParsed(
|
||||
const ParseTypeUsage& defaultArgumentTypeUsage, const NameHierarchy& templateArgumentTypeNameHierarchy);
|
||||
const ParseTypeUsage& defaultArgumentTypeUsage, const NameHierarchy& templateParameterNameHierarchy);
|
||||
virtual Id onTemplateRecordParameterTypeParsed(
|
||||
const ParseLocation& location, const NameHierarchy& templateParameterTypeNameHierarchy,
|
||||
const NameHierarchy& templateRecordNameHierarchy);
|
||||
|
||||
@@ -116,9 +116,12 @@ public:
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) = 0;
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable) = 0;
|
||||
|
||||
virtual Id onTemplateArgumentTypeParsed(
|
||||
virtual Id onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const NameHierarchy& templateNameHierarchy) = 0;
|
||||
virtual Id onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseFunction& templateFunction) = 0;
|
||||
virtual Id onTemplateDefaultArgumentTypeParsed(
|
||||
const ParseTypeUsage& type, const NameHierarchy& templateArgumentTypeNameHierarchy) = 0;
|
||||
virtual Id onTemplateRecordParameterTypeParsed(
|
||||
|
||||
@@ -309,8 +309,6 @@ bool ASTVisitor::VisitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl *
|
||||
|
||||
bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
||||
{
|
||||
NameHierarchy rarchy = utility::getDeclNameHierarchy(declaration);
|
||||
|
||||
if (isLocatedInUnparsedProjectFile(declaration))
|
||||
{
|
||||
NameHierarchy templateRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
|
||||
@@ -335,43 +333,34 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
||||
)
|
||||
{
|
||||
clang::ClassTemplateSpecializationDecl* specializationDecl = *it;
|
||||
NameHierarchy specializedRecordNameHierarchy = utility::getDeclNameHierarchy(specializationDecl);
|
||||
NameHierarchy specializationNameHierarchy = utility::getDeclNameHierarchy(specializationDecl); // TODO: rename this! to specialization..
|
||||
|
||||
ParseLocation specializationLocation = getParseLocationForNamedDecl(*it);
|
||||
ParseLocation specializationLocation = getParseLocationForNamedDecl(specializationDecl);
|
||||
if (specializationDecl->getSpecializationKind() == clang::TSK_ImplicitInstantiation)
|
||||
{
|
||||
specializationLocation = getParseLocation(specializationDecl->getPointOfInstantiation());
|
||||
}
|
||||
|
||||
// template arguments
|
||||
// handling template arguments
|
||||
std::string specializationFilePath = specializationLocation.filePath.str();
|
||||
const clang::TemplateArgumentList &argList = specializationDecl->getTemplateArgs();
|
||||
for (size_t i = 0; i < argList.size(); i++) // TODO: handle arguments of partial template spec and template functions the same!
|
||||
if (!isLocatedInProjectFile(specializationLocation))
|
||||
{
|
||||
specializationFilePath = "";
|
||||
}
|
||||
|
||||
const clang::TemplateArgumentList& argList = specializationDecl->getTemplateArgs();
|
||||
for (size_t i = 0; i < argList.size(); i++)
|
||||
{
|
||||
const clang::TemplateArgument& argument = argList.get(i);
|
||||
|
||||
bool addArgument = isLocatedInProjectFile(declaration); // TODO: Store this value somewhere!
|
||||
if (!addArgument)
|
||||
{
|
||||
if (argument.getKind() == clang::TemplateArgument::Type)
|
||||
{
|
||||
clang::TagDecl *argumentDecl = argument.getAsType()->getAsTagDecl();
|
||||
if (argumentDecl && isLocatedInProjectFile(getParseLocation(argumentDecl->getSourceRange())))
|
||||
{
|
||||
addArgument = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addArgument)
|
||||
if (needsToAddTemplateArgument(argument, declaration))
|
||||
{
|
||||
NameHierarchy argumentNameHierarchy = utility::templateArgumentToDataType(argument)->getTypeNameHierarchy();
|
||||
|
||||
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
|
||||
{
|
||||
m_client->onTemplateArgumentTypeParsed(
|
||||
ParseLocation(specializationFilePath, 0, 0), // TODO: Find a valid ParseLocation here!
|
||||
m_client->onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
ParseLocation(specializationFilePath, 0, 0), // TODO: get a better location here!
|
||||
argumentNameHierarchy,
|
||||
specializedRecordNameHierarchy
|
||||
specializationNameHierarchy
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -379,15 +368,11 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
||||
|
||||
if (isLocatedInProjectFile(declaration))
|
||||
{
|
||||
ParserClient::RecordType specializedRecordType = specializationDecl->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS;
|
||||
// The specializationParent can be an indirect specialization of the ClassTemplate (by specializing a partial specialization).
|
||||
NameHierarchy specializationParentNameHierarchy = utility::getTemplateSpecializationParentNameHierarchy(specializationDecl);
|
||||
|
||||
m_client->onTemplateRecordSpecializationParsed(
|
||||
specializationLocation,
|
||||
specializedRecordNameHierarchy,
|
||||
specializedRecordType,
|
||||
specializationParentNameHierarchy
|
||||
specializationNameHierarchy,
|
||||
specializationDecl->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS,
|
||||
utility::getTemplateSpecializationParentNameHierarchy(specializationDecl)
|
||||
);
|
||||
|
||||
// template member specializations
|
||||
@@ -455,7 +440,7 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
const clang::TemplateArgument& argument = argumentLoc.getArgument();
|
||||
|
||||
m_client->onTemplateArgumentTypeParsed(
|
||||
m_client->onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
utility::templateArgumentToDataType(argument)->getTypeNameHierarchy(),
|
||||
specializedRecordNameHierarchy);
|
||||
@@ -486,72 +471,100 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isLocatedInProjectFile(declaration))
|
||||
|
||||
for (clang::FunctionTemplateDecl::spec_iterator it = declaration->specializations().begin(); it != declaration->specializations().end(); it++)
|
||||
{
|
||||
for (clang::FunctionTemplateDecl::spec_iterator it = declaration->specializations().begin(); it != declaration->specializations().end(); it++)
|
||||
const clang::FunctionDecl* specializationDecl = *it;
|
||||
ParseLocation specializationLocation = getParseLocationForNamedDecl(specializationDecl);
|
||||
ParseFunction specializationFunction = getParseFunction(specializationDecl);
|
||||
|
||||
if (specializationDecl->getTemplateSpecializationKind() == clang::TSK_ExplicitSpecialization)
|
||||
{
|
||||
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 (isLocatedInUnparsedProjectFile(declaration))
|
||||
{
|
||||
if (isLocatedInUnparsedProjectFile(declaration))
|
||||
m_client->onTemplateFunctionSpecializationParsed(
|
||||
specializationLocation,
|
||||
specializationFunction,
|
||||
templateFunction
|
||||
);
|
||||
}
|
||||
if (specializationDecl->getTemplateSpecializationArgsAsWritten())
|
||||
{
|
||||
const clang::ASTTemplateArgumentListInfo* argumentInfoList = specializationDecl->getTemplateSpecializationArgsAsWritten();
|
||||
for (size_t i = 0; i < argumentInfoList->NumTemplateArgs; i++)
|
||||
{
|
||||
m_client->onTemplateFunctionSpecializationParsed(
|
||||
specializedFunctionLocation,
|
||||
specializedFunction,
|
||||
templateFunction);
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
|
||||
if(specializedFunctionDecl->getTemplateSpecializationArgsAsWritten())
|
||||
const clang::TemplateArgument& argument = argumentLoc.getArgument();
|
||||
if (needsToAddTemplateArgument(argument, declaration))
|
||||
{
|
||||
const clang::ASTTemplateArgumentListInfo* argumentInfoList = specializedFunctionDecl->getTemplateSpecializationArgsAsWritten();
|
||||
for (size_t i = 0; i < argumentInfoList->NumTemplateArgs; i++)
|
||||
NameHierarchy argumentNameHierarchy = utility::templateArgumentToDataType(argument)->getTypeNameHierarchy();
|
||||
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
|
||||
{
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
const clang::QualType argumentType = argumentLoc.getArgument().getAsType();
|
||||
|
||||
m_client->onTemplateArgumentTypeParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
utility::qualTypeToDataType(argumentType)->getTypeNameHierarchy(),
|
||||
specializedFunction.nameHierarchy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const clang::TemplateArgumentList* argumentList = specializedFunctionDecl->getTemplateSpecializationArgs();
|
||||
for(size_t i = 0; i < argumentList->size(); ++i)
|
||||
{
|
||||
const clang::TemplateArgumentLoc& argumentLoc = clang::TemplateArgumentLoc(argumentList->get(i), specializedFunctionDecl->getTypeSourceInfo());
|
||||
const clang::QualType argumentType = argumentLoc.getArgument().getAsType();
|
||||
|
||||
m_client->onTemplateArgumentTypeParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
utility::qualTypeToDataType(argumentType)->getTypeNameHierarchy(),
|
||||
specializedFunction.nameHierarchy);
|
||||
m_client->onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
argumentNameHierarchy,
|
||||
specializationFunction
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // info->getTemplateSpecializationKind() == clang::TSK_ImplicitInstantiation
|
||||
else
|
||||
{
|
||||
m_client->onTemplateFunctionSpecializationParsed(
|
||||
specializedFunctionLocation,
|
||||
specializedFunction,
|
||||
templateFunction);
|
||||
|
||||
const clang::TemplateArgumentList* argumentList = specializedFunctionDecl->getTemplateSpecializationArgs();
|
||||
for (size_t i = 0; i < argumentList->size(); i++)
|
||||
const clang::TemplateArgumentList* argumentList = specializationDecl->getTemplateSpecializationArgs();
|
||||
for(size_t i = 0; i < argumentList->size(); ++i)
|
||||
{
|
||||
const clang::TemplateArgument& argument = argumentList->get(i);
|
||||
if (argument.getKind() == clang::TemplateArgument::Type)
|
||||
const clang::TemplateArgumentLoc& argumentLoc = clang::TemplateArgumentLoc(argument, specializationDecl->getTypeSourceInfo());
|
||||
|
||||
if (needsToAddTemplateArgument(argument, declaration))
|
||||
{
|
||||
const clang::QualType argumentType = argument.getAsType();
|
||||
m_client->onTemplateArgumentTypeParsed(
|
||||
ParseLocation(specializedFunctionLocation.filePath.str(), 0, 0), // TODO: Find a valid ParseLocation here!
|
||||
utility::qualTypeToDataType(argumentType)->getTypeNameHierarchy(),
|
||||
specializedFunction.nameHierarchy);
|
||||
NameHierarchy argumentNameHierarchy = utility::templateArgumentToDataType(argument)->getTypeNameHierarchy();
|
||||
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
|
||||
{
|
||||
m_client->onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
argumentNameHierarchy,
|
||||
specializationFunction
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // if (info->getTemplateSpecializationKind() == clang::TSK_ImplicitInstantiation)
|
||||
{
|
||||
if (isLocatedInProjectFile(declaration))
|
||||
{
|
||||
m_client->onTemplateFunctionSpecializationParsed(
|
||||
specializationLocation,
|
||||
specializationFunction,
|
||||
templateFunction
|
||||
);
|
||||
}
|
||||
|
||||
// handling template arguments
|
||||
std::string specializationFilePath = specializationLocation.filePath.str();
|
||||
if (!isLocatedInProjectFile(specializationLocation))
|
||||
{
|
||||
specializationFilePath = "";
|
||||
}
|
||||
|
||||
const clang::TemplateArgumentList* argumentList = specializationDecl->getTemplateSpecializationArgs();
|
||||
for (size_t i = 0; i < argumentList->size(); i++)
|
||||
{
|
||||
const clang::TemplateArgument& argument = argumentList->get(i);
|
||||
if (needsToAddTemplateArgument(argument, declaration))
|
||||
{
|
||||
NameHierarchy argumentNameHierarchy = utility::templateArgumentToDataType(argument)->getTypeNameHierarchy();
|
||||
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
|
||||
{
|
||||
m_client->onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
ParseLocation(specializationFilePath, 0, 0), // TODO: get a better location here!
|
||||
argumentNameHierarchy,
|
||||
specializationFunction
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -818,6 +831,23 @@ bool ASTVisitor::isLocatedInProjectFile(const clang::Decl* declaration) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTVisitor::needsToAddTemplateArgument(const clang::TemplateArgument& argument, const clang::Decl* specializedDecl)
|
||||
{
|
||||
bool addArgument = isLocatedInProjectFile(specializedDecl);
|
||||
if (!addArgument)
|
||||
{
|
||||
if (argument.getKind() == clang::TemplateArgument::Type)
|
||||
{
|
||||
clang::TagDecl *argumentDecl = argument.getAsType()->getAsTagDecl();
|
||||
if (argumentDecl && isLocatedInProjectFile(getParseLocation(argumentDecl->getSourceRange())))
|
||||
{
|
||||
addArgument = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return addArgument;
|
||||
}
|
||||
|
||||
ParserClient::AccessType ASTVisitor::convertAccessType(clang::AccessSpecifier access) const
|
||||
{
|
||||
switch (access)
|
||||
|
||||
@@ -64,6 +64,8 @@ private:
|
||||
bool isLocatedInProjectFile(const ParseLocation& location) const;
|
||||
bool isLocatedInProjectFile(const clang::Decl* declaration) const;
|
||||
|
||||
bool needsToAddTemplateArgument(const clang::TemplateArgument& argument, const clang::Decl* specializedDecl);
|
||||
|
||||
ParserClient::AccessType convertAccessType(clang::AccessSpecifier) const;
|
||||
ParserClient::AbstractionType getAbstractionType(const clang::CXXMethodDecl* methodDecl) const;
|
||||
|
||||
|
||||
@@ -2766,12 +2766,22 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateArgumentTypeParsed(
|
||||
const ParseLocation& location, const NameHierarchy& templateArgumentTypeNameHierarchy,
|
||||
const NameHierarchy& templateRecordNameHierarchy)
|
||||
virtual Id onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const NameHierarchy& templateNameHierarchy)
|
||||
{
|
||||
templateArgumentTypes.push_back(
|
||||
addLocationSuffix(templateRecordNameHierarchy.getFullName() + "->" + templateArgumentTypeNameHierarchy.getFullName(), location)
|
||||
addLocationSuffix(templateNameHierarchy.getFullName() + "->" + argumentNameHierarchy.getFullName(), location)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseFunction& templateFunction)
|
||||
{
|
||||
templateArgumentTypes.push_back(
|
||||
addLocationSuffix(templateFunction.getFullName() + "->" + argumentNameHierarchy.getFullName(), location)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user