logic: template argument handling
* now Coati will also parse the body of an instantiated template function and follow calls to other template functions there. * Coati will parse template arguments at the point of implicit or explicit template instantiation and explicit template specialization. * refactored template handling in storage.
This commit is contained in:
@@ -163,6 +163,14 @@ ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path i
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
ConfigManager.cpp WARNING: value source/header_search_paths/header_search_path is not present in config.
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Edge.cpp ERROR: Edge type_of can't go from Node undefined to Node undefined
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
|
||||
@@ -531,16 +531,16 @@ Id Storage::onTypeUsageParsed(const ParseTypeUsage& typeUsage, const ParseVariab
|
||||
}
|
||||
|
||||
Id Storage::onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const NameHierarchy& templateNameHierarchy)
|
||||
const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy,
|
||||
const NameHierarchy& templateNameHierarchy)
|
||||
{
|
||||
log(
|
||||
"template argument type",
|
||||
argumentNameHierarchy.getFullName() + " -> " + templateNameHierarchy.getFullName(),
|
||||
argumentTypeNameHierarchy.getFullName() + " -> " + templateNameHierarchy.getFullName(),
|
||||
location
|
||||
);
|
||||
|
||||
Id argumentNodeId = addNodeHierarchy(Node::NODE_TYPE, argumentNameHierarchy, false);
|
||||
Id argumentNodeId = addNodeHierarchy(Node::NODE_TYPE, argumentTypeNameHierarchy, false);
|
||||
// does not need a source location because this type that is already defined (and therefore has a location).
|
||||
|
||||
Id templateNodeId = addNodeHierarchy(Node::NODE_TYPE, templateNameHierarchy, false);
|
||||
@@ -551,16 +551,16 @@ Id Storage::onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
}
|
||||
|
||||
Id Storage::onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy,
|
||||
const ParseFunction& templateFunction)
|
||||
{
|
||||
log(
|
||||
"template argument type",
|
||||
argumentNameHierarchy.getFullName() + " -> " + templateFunction.getFullName(),
|
||||
argumentTypeNameHierarchy.getFullName() + " -> " + templateFunction.getFullName(),
|
||||
location
|
||||
);
|
||||
|
||||
Id argumentNodeId = addNodeHierarchy(Node::NODE_TYPE, argumentNameHierarchy, false);
|
||||
Id argumentNodeId = addNodeHierarchy(Node::NODE_TYPE, argumentTypeNameHierarchy, 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);
|
||||
|
||||
@@ -101,10 +101,10 @@ public:
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& typeUsage, const ParseVariable& variable);
|
||||
|
||||
virtual Id onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy,
|
||||
const NameHierarchy& templateNameHierarchy);
|
||||
virtual Id onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy,
|
||||
const ParseFunction& templateFunction);
|
||||
virtual Id onTemplateDefaultArgumentTypeParsed(
|
||||
const ParseTypeUsage& defaultArgumentTypeUsage, const NameHierarchy& templateParameterNameHierarchy);
|
||||
|
||||
@@ -117,10 +117,10 @@ public:
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable) = 0;
|
||||
|
||||
virtual Id onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy,
|
||||
const NameHierarchy& templateNameHierarchy) = 0;
|
||||
virtual Id onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy,
|
||||
const ParseFunction& templateFunction) = 0;
|
||||
virtual Id onTemplateDefaultArgumentTypeParsed(
|
||||
const ParseTypeUsage& type, const NameHierarchy& templateArgumentTypeNameHierarchy) = 0;
|
||||
|
||||
@@ -81,6 +81,34 @@ void ASTBodyVisitor::VisitCXXConstructExpr(clang::CXXConstructExpr* expr)
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitExplicitCastExpr(clang::ExplicitCastExpr* expr)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitExplicitCastExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitExplicitCastExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* expr)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitCXXTemporaryObjectExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitCXXTemporaryObjectExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitCXXNewExpr(clang::CXXNewExpr* expr)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
@@ -111,8 +139,17 @@ void ASTBodyVisitor::VisitMemberExpr(clang::make_ptr<clang::MemberExpr>::type ex
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitDeclRefExpr(clang::make_ptr<clang::DeclRefExpr>::type expr)
|
||||
void ASTBodyVisitor::VisitDeclRefExpr(clang::DeclRefExpr* expr)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitDeclRefExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitDeclRefExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
|
||||
if (expr->getDecl()->getKind() == clang::Decl::Var && expr->getDecl()->isDefinedOutsideFunctionOrMethod())
|
||||
{
|
||||
if (m_functionDecl)
|
||||
@@ -135,6 +172,7 @@ void ASTBodyVisitor::VisitDeclRefExpr(clang::make_ptr<clang::DeclRefExpr>::type
|
||||
m_client->VisitEnumExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
}
|
||||
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ public:
|
||||
void VisitChildren(clang::Stmt* stmt);
|
||||
void VisitCallExpr(clang::CallExpr* expr);
|
||||
void VisitCXXConstructExpr(clang::CXXConstructExpr* expr);
|
||||
void VisitExplicitCastExpr(clang::ExplicitCastExpr* expr);
|
||||
void VisitCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* expr);
|
||||
void VisitCXXNewExpr(clang::CXXNewExpr* expr);
|
||||
void VisitMemberExpr(clang::make_ptr<clang::MemberExpr>::type expr);
|
||||
void VisitDeclRefExpr(clang::make_ptr<clang::DeclRefExpr>::type expr);
|
||||
|
||||
@@ -13,8 +13,14 @@ public:
|
||||
|
||||
virtual void VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallExpr* expr) = 0;
|
||||
virtual void VisitCallExprInDeclBody(clang::DeclaratorDecl* decl, clang::CallExpr* expr) = 0;
|
||||
virtual void VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) = 0;
|
||||
virtual void VisitDeclRefExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr) = 0;
|
||||
virtual void VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clang::CXXConstructExpr* expr) = 0;
|
||||
virtual void VisitCXXConstructExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXConstructExpr* expr) = 0;
|
||||
virtual void VisitExplicitCastExprInDeclBody(clang::FunctionDecl* decl, clang::ExplicitCastExpr* expr) = 0;
|
||||
virtual void VisitExplicitCastExprInDeclBody(clang::DeclaratorDecl* decl, clang::ExplicitCastExpr* expr) = 0;
|
||||
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::FunctionDecl* decl, clang::CXXTemporaryObjectExpr* expr) = 0;
|
||||
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXTemporaryObjectExpr* expr) = 0;
|
||||
virtual void VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr) = 0;
|
||||
virtual void VisitCXXNewExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXNewExpr* expr) = 0;
|
||||
virtual void VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr) = 0;
|
||||
|
||||
@@ -84,6 +84,8 @@ bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration)
|
||||
utility::qualTypeToDataType(it.getType())->getTypeNameHierarchy(),
|
||||
convertAccessType(it.getAccessSpecifier())
|
||||
);
|
||||
|
||||
// TODO: check for template class and add arguments!
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,17 +160,21 @@ bool ASTVisitor::VisitFunctionDecl(clang::FunctionDecl* declaration)
|
||||
|
||||
if (isLocatedInUnparsedProjectFile(declaration))
|
||||
{
|
||||
m_client->onFunctionParsed(
|
||||
getParseLocationForNamedDecl(declaration),
|
||||
getParseFunction(declaration),
|
||||
getParseLocationOfFunctionBody(declaration)
|
||||
);
|
||||
processFunctionDecl(declaration);
|
||||
}
|
||||
|
||||
if (declaration->hasBody() && declaration->isThisDeclarationADefinition())
|
||||
{
|
||||
ASTBodyVisitor bodyVisitor(this, declaration);
|
||||
bodyVisitor.Visit(declaration->getBody());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTVisitor::VisitParmVarDecl(clang::ParmVarDecl* declaration)
|
||||
{
|
||||
// todo: handle parameters here!
|
||||
// maybe handle template args in visitvardecl to account for local variables and stuff...
|
||||
clang::TypeLoc loc = declaration->getTypeSourceInfo()->getTypeLoc();
|
||||
clang::TypeLoc::TypeLocClass ssd = loc.getTypeLocClass();
|
||||
if (loc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::TemplateSpecialization)
|
||||
{
|
||||
processTemplateArguments(loc.getAs<clang::TemplateSpecializationTypeLoc>());
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -195,7 +201,8 @@ bool ASTVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* declaration)
|
||||
m_client->onMethodOverrideParsed(location, getParseFunction(*it), parseFunction);
|
||||
}
|
||||
|
||||
if (declaration->hasBody() && declaration->getBody() != NULL && declaration->isThisDeclarationADefinition())
|
||||
if (declaration->hasBody() && declaration->getBody() != NULL && declaration->isThisDeclarationADefinition() &&
|
||||
!declaration->isDependentContext())
|
||||
{
|
||||
ASTBodyVisitor bodyVisitor(this, declaration);
|
||||
bodyVisitor.Visit(declaration->getBody());
|
||||
@@ -226,11 +233,9 @@ bool ASTVisitor::VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration)
|
||||
else if (init->isBaseInitializer())
|
||||
{
|
||||
m_client->onTypeUsageParsed(
|
||||
getParseTypeUsage(init->getTypeSourceInfo()->getTypeLoc(), init->getTypeSourceInfo()->getType()),
|
||||
getParseTypeUsage(init->getTypeSourceInfo()->getTypeLoc(), init->getTypeSourceInfo()->getType()), // TODO: rewrite this to old!
|
||||
getParseFunction(declaration)
|
||||
);
|
||||
|
||||
saveClassTemplateArgumentTypeUsages<ParseFunction>(init->getTypeSourceInfo(), getParseFunction(declaration));
|
||||
}
|
||||
|
||||
ASTBodyVisitor bodyVisitor(this, declaration);
|
||||
@@ -246,7 +251,7 @@ bool ASTVisitor::VisitNamespaceDecl(clang::NamespaceDecl* declaration)
|
||||
if (isLocatedInUnparsedProjectFile(declaration))
|
||||
{
|
||||
m_client->onNamespaceParsed(
|
||||
declaration->isAnonymousNamespace() ? ParseLocation() : getParseLocationForNamedDecl(declaration),
|
||||
declaration->isAnonymousNamespace() ? ParseLocation() : getParseLocationForNamedDecl(declaration), // TODO: why no real parse loc for anonymous namespace?
|
||||
utility::getDeclNameHierarchy(declaration),
|
||||
getParseLocation(declaration->getSourceRange())
|
||||
);
|
||||
@@ -298,7 +303,9 @@ bool ASTVisitor::VisitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl *
|
||||
{
|
||||
const clang::TemplateArgumentLoc& defaultArgumentLoc = declaration->getDefaultArgument();
|
||||
clang::SourceRange sr = defaultArgumentLoc.getSourceRange();
|
||||
std::shared_ptr<DataType> defaultArgumentDataType = std::make_shared<NamedDataType>(utility::getDeclNameHierarchy(defaultArgumentLoc.getArgument().getAsTemplate().getAsTemplateDecl()));
|
||||
std::shared_ptr<DataType> defaultArgumentDataType = std::make_shared<NamedDataType>(
|
||||
utility::getDeclNameHierarchy(defaultArgumentLoc.getArgument().getAsTemplate().getAsTemplateDecl())
|
||||
);
|
||||
m_client->onTemplateDefaultArgumentTypeParsed(
|
||||
getParseTypeUsage(sr, defaultArgumentDataType),
|
||||
utility::getDeclNameHierarchy(declaration)
|
||||
@@ -342,28 +349,9 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
||||
}
|
||||
|
||||
// handling template arguments
|
||||
std::string specializationFilePath = specializationLocation.filePath.str();
|
||||
if (!isLocatedInProjectFile(specializationLocation))
|
||||
if (isLocatedInUnparsedProjectFile(specializationDecl) && specializationDecl->isExplicitSpecialization())
|
||||
{
|
||||
specializationFilePath = "";
|
||||
}
|
||||
|
||||
const clang::TemplateArgumentList& argList = specializationDecl->getTemplateArgs();
|
||||
for (size_t i = 0; i < argList.size(); i++)
|
||||
{
|
||||
const clang::TemplateArgument& argument = argList.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->onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
ParseLocation(specializationFilePath, 0, 0), // TODO: get a better location here!
|
||||
argumentNameHierarchy,
|
||||
specializationNameHierarchy
|
||||
);
|
||||
}
|
||||
}
|
||||
processTemplateArgumentsOfExplicitSpecialization(specializationDecl);
|
||||
}
|
||||
|
||||
if (isLocatedInProjectFile(declaration))
|
||||
@@ -434,17 +422,7 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
|
||||
}
|
||||
}
|
||||
|
||||
const clang::ASTTemplateArgumentListInfo* argumentInfoList = declaration->getTemplateArgsAsWritten();
|
||||
for (size_t i = 0; i < argumentInfoList->NumTemplateArgs; i++)
|
||||
{
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
const clang::TemplateArgument& argument = argumentLoc.getArgument();
|
||||
|
||||
m_client->onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
getParseLocation(argumentLoc.getSourceRange()),
|
||||
utility::templateArgumentToDataType(argument)->getTypeNameHierarchy(),
|
||||
specializedRecordNameHierarchy);
|
||||
}
|
||||
processTemplateArgumentsOfExplicitSpecialization(declaration);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -471,108 +449,41 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
|
||||
|
||||
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);
|
||||
clang::FunctionDecl* specializationDecl = *it;
|
||||
bool needsToProcessSpecialization = false;
|
||||
|
||||
if (specializationDecl->getTemplateSpecializationKind() == clang::TSK_ExplicitSpecialization)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
|
||||
const clang::TemplateArgument& argument = argumentLoc.getArgument();
|
||||
if (needsToAddTemplateArgument(argument, declaration))
|
||||
{
|
||||
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
|
||||
{
|
||||
const clang::TemplateArgumentList* argumentList = specializationDecl->getTemplateSpecializationArgs();
|
||||
for(size_t i = 0; i < argumentList->size(); ++i)
|
||||
{
|
||||
const clang::TemplateArgument& argument = argumentList->get(i);
|
||||
const clang::TemplateArgumentLoc& argumentLoc = clang::TemplateArgumentLoc(argument, specializationDecl->getTypeSourceInfo());
|
||||
|
||||
if (needsToAddTemplateArgument(argument, declaration))
|
||||
{
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
processTemplateArgumentsOfExplicitSpecialization(specializationDecl);
|
||||
needsToProcessSpecialization = true;
|
||||
}
|
||||
}
|
||||
else // if (info->getTemplateSpecializationKind() == clang::TSK_ImplicitInstantiation)
|
||||
else if (isLocatedInProjectFile(declaration))
|
||||
{
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
needsToProcessSpecialization = true;
|
||||
}
|
||||
|
||||
if (needsToProcessSpecialization)
|
||||
{
|
||||
processFunctionDecl(specializationDecl);
|
||||
|
||||
m_client->onTemplateFunctionSpecializationParsed(
|
||||
getParseLocationForNamedDecl(specializationDecl),
|
||||
getParseFunction(specializationDecl),
|
||||
templateFunction
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallExpr* expr)
|
||||
{
|
||||
if (!expr->getDirectCallee())
|
||||
clang::FunctionDecl* calleeFunctionDecl = expr->getDirectCallee();
|
||||
if (!calleeFunctionDecl)
|
||||
{
|
||||
// TODO: Save error at location.
|
||||
return;
|
||||
@@ -581,11 +492,8 @@ void ASTVisitor::VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallE
|
||||
m_client->onCallParsed(
|
||||
getParseLocation(expr->getSourceRange()),
|
||||
getParseFunction(decl),
|
||||
getParseFunction(expr->getDirectCallee())
|
||||
getParseFunction(calleeFunctionDecl)
|
||||
);
|
||||
|
||||
saveFunctionTemplateArgumentTypeUsages<ParseFunction>(
|
||||
expr->getDirectCallee(), expr->getSourceRange(), getParseFunction(decl));
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitCallExprInDeclBody(clang::DeclaratorDecl* decl, clang::CallExpr* expr)
|
||||
@@ -601,13 +509,22 @@ void ASTVisitor::VisitCallExprInDeclBody(clang::DeclaratorDecl* decl, clang::Cal
|
||||
getParseVariable(decl),
|
||||
getParseFunction(expr->getDirectCallee())
|
||||
);
|
||||
}
|
||||
|
||||
saveFunctionTemplateArgumentTypeUsages<ParseVariable>(
|
||||
expr->getDirectCallee(), expr->getSourceRange(), getParseVariable(decl));
|
||||
|
||||
void ASTVisitor::VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr)
|
||||
{
|
||||
processTemplateArguments(expr);
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitDeclRefExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr)
|
||||
{
|
||||
processTemplateArguments(expr);
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clang::CXXConstructExpr* expr)
|
||||
{
|
||||
// TODO: refactor this code!
|
||||
std::string caller = decl->getNameAsString();
|
||||
std::string callee = expr->getConstructor()->getNameAsString();
|
||||
clang::SourceRange sourceRange = expr->getSourceRange();
|
||||
@@ -659,9 +576,6 @@ void ASTVisitor::VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clan
|
||||
getParseFunction(decl),
|
||||
getParseFunction(expr->getConstructor())
|
||||
);
|
||||
|
||||
saveFunctionTemplateArgumentTypeUsages<ParseFunction>(
|
||||
expr->getConstructor(), expr->getSourceRange(), getParseFunction(decl));
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitCXXConstructExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXConstructExpr* expr)
|
||||
@@ -671,9 +585,42 @@ void ASTVisitor::VisitCXXConstructExprInDeclBody(clang::DeclaratorDecl* decl, cl
|
||||
getParseVariable(decl),
|
||||
getParseFunction(expr->getConstructor())
|
||||
);
|
||||
}
|
||||
|
||||
saveFunctionTemplateArgumentTypeUsages<ParseVariable>(
|
||||
expr->getConstructor(), expr->getSourceRange(), getParseVariable(decl));
|
||||
void ASTVisitor::VisitExplicitCastExprInDeclBody(clang::FunctionDecl* decl, clang::ExplicitCastExpr* expr)
|
||||
{
|
||||
clang::TypeLoc loc = expr->getTypeInfoAsWritten()->getTypeLoc();
|
||||
if (loc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::TemplateSpecialization)
|
||||
{
|
||||
processTemplateArguments(loc.getAs<clang::TemplateSpecializationTypeLoc>());
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitExplicitCastExprInDeclBody(clang::DeclaratorDecl* decl, clang::ExplicitCastExpr* expr)
|
||||
{
|
||||
clang::TypeLoc loc = expr->getTypeInfoAsWritten()->getTypeLoc();
|
||||
if (loc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::TemplateSpecialization)
|
||||
{
|
||||
processTemplateArguments(loc.getAs<clang::TemplateSpecializationTypeLoc>());
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitCXXTemporaryObjectExprInDeclBody(clang::FunctionDecl* decl, clang::CXXTemporaryObjectExpr* expr)
|
||||
{
|
||||
clang::TypeLoc loc = expr->getTypeSourceInfo()->getTypeLoc();
|
||||
if (loc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::TemplateSpecialization)
|
||||
{
|
||||
processTemplateArguments(loc.getAs<clang::TemplateSpecializationTypeLoc>());
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitCXXTemporaryObjectExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXTemporaryObjectExpr* expr)
|
||||
{
|
||||
clang::TypeLoc loc = expr->getTypeSourceInfo()->getTypeLoc();
|
||||
if (loc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::TemplateSpecialization)
|
||||
{
|
||||
processTemplateArguments(loc.getAs<clang::TemplateSpecializationTypeLoc>());
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr)
|
||||
@@ -683,7 +630,11 @@ void ASTVisitor::VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXX
|
||||
getParseFunction(decl)
|
||||
);
|
||||
|
||||
saveClassTemplateArgumentTypeUsages<ParseFunction>(expr->getAllocatedTypeSourceInfo(), getParseFunction(decl));
|
||||
clang::TypeLoc loc = expr->getAllocatedTypeSourceInfo()->getTypeLoc();
|
||||
if (loc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::TemplateSpecialization)
|
||||
{
|
||||
processTemplateArguments(loc.getAs<clang::TemplateSpecializationTypeLoc>());
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitCXXNewExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXNewExpr* expr)
|
||||
@@ -693,7 +644,11 @@ void ASTVisitor::VisitCXXNewExprInDeclBody(clang::DeclaratorDecl* decl, clang::C
|
||||
getParseVariable(decl)
|
||||
);
|
||||
|
||||
saveClassTemplateArgumentTypeUsages<ParseVariable>(expr->getAllocatedTypeSourceInfo(), getParseVariable(decl));
|
||||
clang::TypeLoc loc = expr->getAllocatedTypeSourceInfo()->getTypeLoc();
|
||||
if (loc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::TemplateSpecialization)
|
||||
{
|
||||
processTemplateArguments(loc.getAs<clang::TemplateSpecializationTypeLoc>());
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr)
|
||||
@@ -787,7 +742,182 @@ void ASTVisitor::VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDec
|
||||
getParseFunction(decl)
|
||||
);
|
||||
|
||||
saveClassTemplateArgumentTypeUsages<ParseFunction>(varDecl->getTypeSourceInfo(), getParseFunction(decl));
|
||||
clang::TypeLoc loc = varDecl->getTypeSourceInfo()->getTypeLoc();
|
||||
if (loc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::TemplateSpecialization)
|
||||
{
|
||||
processTemplateArguments(loc.getAs<clang::TemplateSpecializationTypeLoc>());
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::processFunctionDecl(clang::FunctionDecl* declaration)
|
||||
{
|
||||
m_client->onFunctionParsed(
|
||||
getParseLocationForNamedDecl(declaration),
|
||||
getParseFunction(declaration),
|
||||
getParseLocationOfFunctionBody(declaration)
|
||||
);
|
||||
|
||||
// handle template arguments of return type.
|
||||
clang::TypeLoc functionLoc = declaration->getTypeSourceInfo()->getTypeLoc();
|
||||
if (functionLoc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::FunctionProto)
|
||||
{
|
||||
clang::TypeLoc returnLoc = functionLoc.getAs<clang::FunctionProtoTypeLoc>().getReturnLoc();
|
||||
if (returnLoc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::TemplateSpecialization)
|
||||
{
|
||||
processTemplateArguments(returnLoc.getAs<clang::TemplateSpecializationTypeLoc>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (declaration->hasBody() &&
|
||||
declaration->isThisDeclarationADefinition() &&
|
||||
!declaration->isDependentContext()
|
||||
)
|
||||
{
|
||||
ASTBodyVisitor bodyVisitor(this, declaration);
|
||||
bodyVisitor.Visit(declaration->getBody());
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::processTemplateArgumentsOfExplicitSpecialization(clang::FunctionDecl* specializationDecl)
|
||||
{
|
||||
ParseFunction specializationFunction = getParseFunction(specializationDecl);
|
||||
|
||||
if (specializationDecl->getTemplateSpecializationArgsAsWritten())
|
||||
{
|
||||
const clang::ASTTemplateArgumentListInfo* argumentInfoList = specializationDecl->getTemplateSpecializationArgsAsWritten();
|
||||
for (size_t i = 0; i < argumentInfoList->NumTemplateArgs; i++)
|
||||
{
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
|
||||
const clang::TemplateArgument& argument = argumentLoc.getArgument();
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::processTemplateArgumentsOfExplicitSpecialization(clang::ClassTemplateSpecializationDecl* specializationDecl)
|
||||
{
|
||||
NameHierarchy specializedRecordNameHierarchy = utility::getDeclNameHierarchy(specializationDecl);
|
||||
if (clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl =
|
||||
clang::dyn_cast_or_null<clang::ClassTemplatePartialSpecializationDecl>(specializationDecl))
|
||||
{
|
||||
const clang::ASTTemplateArgumentListInfo* argumentInfoList = partialSpecializationDecl->getTemplateArgsAsWritten();
|
||||
for (size_t i = 0; i < argumentInfoList->NumTemplateArgs; i++)
|
||||
{
|
||||
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||
const clang::TemplateArgument& argument = argumentLoc.getArgument();
|
||||
|
||||
NameHierarchy argumentNameHierarchy = utility::templateArgumentToDataType(argument)->getTypeNameHierarchy();
|
||||
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
|
||||
{
|
||||
m_client->onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
getParseLocationForTokensInRange(argumentLoc.getSourceRange()),
|
||||
argumentNameHierarchy,
|
||||
specializedRecordNameHierarchy
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clang::TypeLoc loc = specializationDecl->getTypeAsWritten()->getTypeLoc();
|
||||
if (loc.getTypeLocClass() == clang::TypeLoc::TypeLocClass::TemplateSpecialization)
|
||||
{
|
||||
processTemplateArguments(loc.getAs<clang::TemplateSpecializationTypeLoc>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::processTemplateArguments(clang::DeclRefExpr* expr)
|
||||
{
|
||||
if (!isLocatedInProjectFile(getParseLocation(expr->getSourceRange())))
|
||||
{
|
||||
return;
|
||||
}
|
||||
clang::FunctionDecl* specializationDecl = clang::dyn_cast_or_null<clang::FunctionDecl>(expr->getDecl());
|
||||
if (!specializationDecl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
clang::FunctionTemplateDecl* specializedDecl = specializationDecl->getPrimaryTemplate(); // just to check if it is really a template.. can be done differently
|
||||
if (!specializedDecl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ParseFunction specializationFunction = getParseFunction(specializationDecl);
|
||||
|
||||
if (expr->hasExplicitTemplateArgs()) // handle explicit template args
|
||||
{
|
||||
const clang::TemplateArgumentLoc* arguments = expr->getTemplateArgs();
|
||||
|
||||
for (unsigned int i = 0; i < expr->getNumTemplateArgs(); i++)
|
||||
{
|
||||
clang::TemplateArgument argument = arguments[i].getArgument();
|
||||
NameHierarchy argumentNameHierarchy = utility::templateArgumentToDataType(argument)->getTypeNameHierarchy();
|
||||
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
|
||||
{
|
||||
m_client->onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
getParseLocation(arguments[i].getSourceRange()),
|
||||
argumentNameHierarchy,
|
||||
specializationFunction
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // handle implicit template args
|
||||
{
|
||||
const clang::TemplateArgumentList* argumentList = specializationDecl->getTemplateSpecializationArgs();
|
||||
for (size_t i = 0; i < argumentList->size(); ++i)
|
||||
{
|
||||
const clang::TemplateArgument& argument = argumentList->get(i);
|
||||
NameHierarchy argumentNameHierarchy = utility::templateArgumentToDataType(argument)->getTypeNameHierarchy();
|
||||
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
|
||||
{
|
||||
const clang::SourceLocation argumentSourceLoc = clang::Lexer::getLocForEndOfToken(
|
||||
expr->getLocEnd(), 1, m_context->getSourceManager(), clang::LangOptions()
|
||||
);
|
||||
m_client->onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
getParseLocation(clang::SourceRange(argumentSourceLoc, argumentSourceLoc)),
|
||||
argumentNameHierarchy,
|
||||
specializationFunction
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ASTVisitor::processTemplateArguments(clang::TemplateSpecializationTypeLoc loc)
|
||||
{
|
||||
NameHierarchy specializationNameHierarchy = utility::qualTypeToDataType(loc.getType())->getTypeNameHierarchy();
|
||||
|
||||
if (!isLocatedInProjectFile(getParseLocation(loc.getSourceRange())))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < loc.getNumArgs(); i++)
|
||||
{
|
||||
const clang::TemplateArgument& argument = loc.getArgLoc(i).getArgument();
|
||||
NameHierarchy argumentNameHierarchy = utility::templateArgumentToDataType(argument)->getTypeNameHierarchy();
|
||||
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
|
||||
{
|
||||
m_client->onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
getParseLocationForTokensInRange(loc.getArgLoc(i).getSourceRange()),
|
||||
argumentNameHierarchy,
|
||||
specializationNameHierarchy
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ASTVisitor::isLocatedInUnparsedProjectFile(const clang::Decl* declaration) const
|
||||
@@ -828,23 +958,6 @@ 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)
|
||||
@@ -896,15 +1009,20 @@ ParseLocation ASTVisitor::getParseLocation(const clang::SourceRange& sourceRange
|
||||
|
||||
ParseLocation ASTVisitor::getParseLocationForTokenAtLocation(const clang::SourceLocation& loc) const
|
||||
{
|
||||
if (loc.isInvalid())
|
||||
return getParseLocationForTokensInRange(clang::SourceRange(loc, loc));
|
||||
}
|
||||
|
||||
ParseLocation ASTVisitor::getParseLocationForTokensInRange(const clang::SourceRange& range) const
|
||||
{
|
||||
if (range.isInvalid())
|
||||
{
|
||||
return ParseLocation();
|
||||
}
|
||||
|
||||
const clang::SourceManager& sourceManager = m_context->getSourceManager();
|
||||
|
||||
clang::SourceLocation startLoc = clang::Lexer::GetBeginningOfToken(loc, sourceManager, clang::LangOptions());
|
||||
clang::SourceLocation endLoc = clang::Lexer::getLocForEndOfToken(loc, 1, sourceManager, clang::LangOptions());
|
||||
clang::SourceLocation startLoc = clang::Lexer::GetBeginningOfToken(range.getBegin(), sourceManager, clang::LangOptions());
|
||||
clang::SourceLocation endLoc = clang::Lexer::getLocForEndOfToken(range.getEnd(), 1, sourceManager, clang::LangOptions());
|
||||
|
||||
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(startLoc);
|
||||
const clang::PresumedLoc& presumedEnd = sourceManager.getPresumedLoc(endLoc);
|
||||
@@ -1090,49 +1208,3 @@ ParseFunction ASTVisitor::getParseFunction(const clang::FunctionTemplateDecl* de
|
||||
{
|
||||
return getParseFunction(declaration->getTemplatedDecl());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ASTVisitor::saveClassTemplateArgumentTypeUsages(const clang::TypeSourceInfo* typeInfo, const T& t)
|
||||
{
|
||||
const clang::Type* type = typeInfo->getType().getTypePtr();
|
||||
|
||||
if (type->getTypeClass() == clang::Type::Elaborated)
|
||||
{
|
||||
type = clang::dyn_cast<clang::ElaboratedType>(type)->getNamedType().getTypePtr();
|
||||
}
|
||||
|
||||
if (type->getTypeClass() == clang::Type::TemplateSpecialization)
|
||||
{
|
||||
const clang::TemplateSpecializationType* templateSpecializationType = type->getAs<clang::TemplateSpecializationType>();
|
||||
for (size_t i = 0; i < templateSpecializationType->getNumArgs(); i++)
|
||||
{
|
||||
CxxTemplateArgumentNameResolver resolver;
|
||||
std::shared_ptr<DataType> argumentType = utility::templateArgumentToDataType(templateSpecializationType->getArg(i));
|
||||
if (argumentType->getFullTypeName().size() > 0)
|
||||
{
|
||||
m_client->onTypeUsageParsed(getParseTypeUsage(typeInfo->getTypeLoc(), argumentType), t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ASTVisitor::saveFunctionTemplateArgumentTypeUsages(
|
||||
const clang::FunctionDecl* decl, const clang::SourceRange& sourceRange, const T& t
|
||||
){
|
||||
const clang::TemplateArgumentList* argumentList = decl->getTemplateSpecializationArgs();
|
||||
if (!argumentList)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < argumentList->size(); i++)
|
||||
{
|
||||
CxxTemplateArgumentNameResolver resolver;
|
||||
std::shared_ptr<DataType> argumentType = utility::templateArgumentToDataType(argumentList->get(i));
|
||||
if (argumentType->getFullTypeName().size() > 0)
|
||||
{
|
||||
m_client->onTypeUsageParsed(getParseTypeUsage(sourceRange, argumentType), t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
virtual bool VisitVarDecl(clang::VarDecl* declaration); // global variables and static fields
|
||||
virtual bool VisitFieldDecl(clang::FieldDecl* declaration); // fields
|
||||
virtual bool VisitFunctionDecl(clang::FunctionDecl* declaration); // functions
|
||||
virtual bool VisitParmVarDecl(clang::ParmVarDecl* declaration);
|
||||
virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl* declaration); // methods
|
||||
virtual bool VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration); // initialization list
|
||||
virtual bool VisitNamespaceDecl(clang::NamespaceDecl* declaration); // namespaces
|
||||
@@ -47,8 +48,14 @@ public:
|
||||
// ASTBodyVisitorClient implementation
|
||||
virtual void VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallExpr* expr); // calls
|
||||
virtual void VisitCallExprInDeclBody(clang::DeclaratorDecl* decl, clang::CallExpr* expr); // calls in initialization of global variables
|
||||
virtual void VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr);
|
||||
virtual void VisitDeclRefExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr);
|
||||
virtual void VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clang::CXXConstructExpr* expr); // constructor calls
|
||||
virtual void VisitCXXConstructExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXConstructExpr* expr); // constructor calls of global variables
|
||||
virtual void VisitExplicitCastExprInDeclBody(clang::FunctionDecl* decl, clang::ExplicitCastExpr* expr);
|
||||
virtual void VisitExplicitCastExprInDeclBody(clang::DeclaratorDecl* decl, clang::ExplicitCastExpr* expr);
|
||||
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::FunctionDecl* decl, clang::CXXTemporaryObjectExpr* expr);
|
||||
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXTemporaryObjectExpr* expr);
|
||||
virtual void VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr); // type use of new operator
|
||||
virtual void VisitCXXNewExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXNewExpr* expr); // type use of new operator in global space
|
||||
virtual void VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr); // field usages
|
||||
@@ -60,17 +67,24 @@ public:
|
||||
virtual void VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDecl* varDecl); // type usages
|
||||
|
||||
private:
|
||||
|
||||
void processFunctionDecl(clang::FunctionDecl* declaration);
|
||||
void processTemplateArgumentsOfExplicitSpecialization(clang::FunctionDecl* declaration);
|
||||
void processTemplateArgumentsOfExplicitSpecialization(clang::ClassTemplateSpecializationDecl* specializationDecl);
|
||||
void processTemplateArguments(clang::DeclRefExpr* expr);
|
||||
void processTemplateArguments(clang::TemplateSpecializationTypeLoc loc);
|
||||
|
||||
|
||||
bool isLocatedInUnparsedProjectFile(const clang::Decl* declaration) const;
|
||||
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;
|
||||
|
||||
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
|
||||
ParseLocation getParseLocationForTokenAtLocation(const clang::SourceLocation& loc) const;
|
||||
ParseLocation getParseLocationForTokensInRange(const clang::SourceRange& range) const;
|
||||
ParseLocation getParseLocationForNamedDecl(const clang::NamedDecl* decl) const;
|
||||
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocationOfRecordBody(clang::CXXRecordDecl* decl) const;
|
||||
@@ -85,13 +99,6 @@ private:
|
||||
ParseFunction getParseFunction(const clang::FunctionDecl* declaration) const;
|
||||
ParseFunction getParseFunction(const clang::FunctionTemplateDecl* declaration) const;
|
||||
|
||||
template <typename T>
|
||||
void saveClassTemplateArgumentTypeUsages(const clang::TypeSourceInfo* typeInfo, const T& t);
|
||||
|
||||
template <typename T>
|
||||
void saveFunctionTemplateArgumentTypeUsages(
|
||||
const clang::FunctionDecl* decl, const clang::SourceRange& sourceRange, const T& t);
|
||||
|
||||
clang::ASTContext* m_context;
|
||||
ParserClient* m_client;
|
||||
FileRegister* m_fileRegister;
|
||||
|
||||
+196
-45
@@ -199,7 +199,7 @@ public:
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"int ceil(float a)\n"
|
||||
"{\n"
|
||||
" return static_cast<int>(a) + 1;\n"
|
||||
" return 1;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
@@ -1539,9 +1539,9 @@ public:
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <7:4 7:6>");
|
||||
}
|
||||
void test_cxx_parser_finds_type_template_argument_for_parameter_pack_of_implicit_template_specialization()
|
||||
void test_cxx_parser_finds_type_template_argument_for_parameter_pack_of_implicit_template_specialization() // actually this is an explicit template instantiation
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename... T>\n"
|
||||
@@ -1552,13 +1552,68 @@ public:
|
||||
"{\n"
|
||||
" A<int, float>();\n"
|
||||
"}\n"
|
||||
);
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<<int, float>>-><int, float> <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<<int, float>>->int <7:6 7:8>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<<int, float>>->float <7:11 7:15>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_int_template_argument_of_implicit_template_specialization()
|
||||
void test_cxx_parser_finds_type_template_argument_for_parameter_of_implicit_template_s______tion_of_non_default_constructor()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" A(int data){}\n"
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<int>(5);\n"
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <9:4 9:6>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_type_template_argument_for_parameter_of_implicit_template_s___kk_tion_of_call_to_default_constructor()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" A(){}\n"
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<int>();\n"
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <9:4 9:6>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_type_template_argument_for_parameter_of_implicit_temple_of_new_expression()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" A(){}\n"
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" new A<int>();\n"
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <9:8 9:10>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_int_template_argument_of_implicit_template_instantiation()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <int T>\n"
|
||||
@@ -1570,11 +1625,25 @@ public:
|
||||
" 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>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<1>->int <7:4 7:4>");
|
||||
}
|
||||
|
||||
//void _____test_cxx_parser_finds_type_template_argument_of_static_cast_expression()
|
||||
//{
|
||||
// std::shared_ptr<TestParserClient> client = parseCode(
|
||||
// "int main()\n"
|
||||
// "{\n"
|
||||
// " return static_cast<int>(4.0f);"
|
||||
// "}\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(
|
||||
@@ -1589,7 +1658,7 @@ public:
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<true>->bool <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<true>->bool <7:4 7:7>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_custom_pointer_template_argument_of_implicit_template_specialization()
|
||||
@@ -1607,7 +1676,7 @@ public:
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <9:4 9:5>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_custom_reference_template_argument_of_implicit_template_specialization()
|
||||
@@ -1625,7 +1694,7 @@ public:
|
||||
"}\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <9:4 9:4>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_nullptr_template_argument_of_implicit_template_specialization()
|
||||
@@ -1642,7 +1711,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<nullptr>->nullptr_t <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<nullptr>->nullptr_t <7:4 7:10>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_int_template_argument_for_parameter_pack_of_implicit_template_specialization()
|
||||
@@ -1654,12 +1723,14 @@ public:
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<1, 2, 3>();\n"
|
||||
" A<1, 2, 33>();\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<<1, 2, 3>>-><int, int, int> <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 3);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<<1, 2, 33>>->int <7:6 7:6>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<<1, 2, 33>>->int <7:9 7:9>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[2], "A<<1, 2, 33>>->int <7:12 7:13>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_template_argument_of_implicit_template_specialization()
|
||||
@@ -1678,7 +1749,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<A>->A<typename T> <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<A>->A<typename T> <9:4 9:4>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_template_argument_for_parameter_pack_of_implicit_template_specialization()
|
||||
@@ -1694,12 +1765,12 @@ public:
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" B<A, A>();\n"
|
||||
" B<A, A>();\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<<A, A>>-><A<typename T>, A<typename T>> <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<<A, A>>->A<typename T> <11:4 11:4>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_member_specialization_of_implicit_template_specialization()
|
||||
@@ -1749,7 +1820,7 @@ public:
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <6:9 6:11>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_int_template_argument_of_explicit_template_specialization()
|
||||
@@ -1765,7 +1836,7 @@ public:
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<1>->int <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<1>->int <6:9 6:9>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_bool_template_argument_of_explicit_template_specialization()
|
||||
@@ -1781,7 +1852,7 @@ public:
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<true>->bool <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<true>->bool <6:9 6:12>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_custom_pointer_template_argument_of_explicit_template_specialization()
|
||||
@@ -1799,7 +1870,7 @@ public:
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <8:9 8:10>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_custom_reference_template_argument_of_explicit_template_specialization()
|
||||
@@ -1817,7 +1888,7 @@ public:
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p>->P <8:9 8:9>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_nullptr_template_argument_of_explicit_template_specialization()
|
||||
@@ -1834,7 +1905,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<nullptr>->nullptr_t <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<nullptr>->nullptr_t <6:9 6:15>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_template_argument_of_explicit_template_specialization()
|
||||
@@ -1853,7 +1924,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<A>->A<typename T> <0:0 0:0>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<A>->A<typename T> <8:9 8:9>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_explicit_partial_template_specialization()
|
||||
@@ -1886,7 +1957,7 @@ public:
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
|
||||
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>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<typename T, int>->int <6:12 6:14>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_int_template_argument_of_explicit_partial_template_specialization()
|
||||
@@ -1921,7 +1992,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<true, bool U>->bool <6:9 6:9>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<true, bool U>->bool <6:9 6:12>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<true, bool U>->bool <6:15 6:15>");
|
||||
}
|
||||
|
||||
@@ -1979,7 +2050,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<nullptr, std::nullptr_t U>->nullptr_t <6:9 6:9>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<nullptr, std::nullptr_t U>->nullptr_t <6:9 6:15>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<nullptr, std::nullptr_t U>->std::nullptr_t <6:18 6:18>");
|
||||
}
|
||||
|
||||
@@ -2019,8 +2090,8 @@ public:
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 3);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<3, typename T2, T2 T3>->int <6:9 6:9>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<3, typename T2, T2 T3>->A<3, typename T2, T2 T3>::T2 <6:12 6:12>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[2], "A<3, typename T2, T2 T3>->A<3, typename T2, T2 T3>::T2 <6:16 6:16>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<3, typename T2, T2 T3>->A<3, typename T2, T2 T3>::T2 <6:12 6:13>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[2], "A<3, typename T2, T2 T3>->A<3, typename T2, T2 T3>::T2 <6:16 6:17>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_non_type_template_argument_that_depends_on_template_template_parameter_of_explicit_partial_template_specialization()
|
||||
@@ -2038,8 +2109,8 @@ public:
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 3);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<3, template<typename> typename T2, T2<int> T3>->int <6:9 6:9>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<3, template<typename> typename T2, T2<int> T3>->A<3, template<typename> typename T2, T2<int> T3>::T2<typename> <6:12 6:12>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[2], "A<3, template<typename> typename T2, T2<int> T3>->A<3, template<typename> typename T2, T2<int> T3>::T2<int> <6:16 6:16>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<3, template<typename> typename T2, T2<int> T3>->A<3, template<typename> typename T2, T2<int> T3>::T2<typename> <6:12 6:13>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[2], "A<3, template<typename> typename T2, T2<int> T3>->A<3, template<typename> typename T2, T2<int> T3>::T2<int> <6:16 6:17>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_correct_name_of_explicit_template_specialization()
|
||||
@@ -2459,7 +2530,7 @@ public:
|
||||
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()
|
||||
void test_cxx_parser_finds_explicit_type_template_argument_of_explicit_specialization_of_template_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
@@ -2476,24 +2547,104 @@ public:
|
||||
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()
|
||||
void test_cxx_parser_finds_explicit_type_template_argument_of_function_call_in_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"void test()\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"void test(){}\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>");
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "test<int>->int <6:7 6:7>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_explicit_non_type_template_argument_of_function_call_in_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <int T>\n"
|
||||
"void test(){}\n"
|
||||
"\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" test<33>();\n"
|
||||
" return 1;\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "test<33>->int <6:7 6:7>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_explicit_template_template_argument_of_function_call_in_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A {};\n"
|
||||
"template <template<typename> class T>\n"
|
||||
"void test(){};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" test<A>();\n"
|
||||
" return 1;\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "test<A>->A<typename T> <7:7 7:7>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_implicit_type_template_argument_of_function_call_in_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"void test(T data){}\n"
|
||||
"\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" test(1);\n"
|
||||
" return 1;\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "test<int>->int <6:5 6:5>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_explicit_type_template_argument_of_function_call_in_var_decl()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"T test(){ return 1; }\n"
|
||||
"\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" int foo = test<int>();\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "test<int>->int <6:17 6:17>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_implicit_type_template_argument_of_function_call_in_var_decl()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"T test(T i){ return i; }\n"
|
||||
"\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" int foo = test(1);\n"
|
||||
"};\n"
|
||||
);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "test<int>->int <6:15 6:15>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void test_cxx_parser_finds_type_template_default_argument_type_of_template_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
@@ -2860,21 +3011,21 @@ private:
|
||||
}
|
||||
|
||||
virtual Id onTemplateArgumentTypeOfTemplateRecordParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy,
|
||||
const NameHierarchy& templateNameHierarchy)
|
||||
{
|
||||
templateArgumentTypes.push_back(
|
||||
addLocationSuffix(templateNameHierarchy.getFullName() + "->" + argumentNameHierarchy.getFullName(), location)
|
||||
addLocationSuffix(templateNameHierarchy.getFullName() + "->" + argumentTypeNameHierarchy.getFullName(), location)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateArgumentTypeOfTemplateFunctionParsed(
|
||||
const ParseLocation& location, const NameHierarchy& argumentNameHierarchy,
|
||||
const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy,
|
||||
const ParseFunction& templateFunction)
|
||||
{
|
||||
templateArgumentTypes.push_back(
|
||||
addLocationSuffix(templateFunction.getFullName() + "->" + argumentNameHierarchy.getFullName(), location)
|
||||
addLocationSuffix(templateFunction.getFullName() + "->" + argumentTypeNameHierarchy.getFullName(), location)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user