data: refined template parameter names

* Fixed template parameters to be resolved to their correct names even if they are (re)definied outside of the class (e.g. for template method definitions).
* Added test code.
This commit is contained in:
malte_langkabel
2015-02-27 14:40:38 +01:00
parent 4f7d31eb79
commit d0c92a6553
9 changed files with 101 additions and 71 deletions
+2 -2
View File
@@ -106,13 +106,13 @@ public:
virtual Id onTemplateDefaultArgumentTypeParsed(
const ParseTypeUsage& type, const std::vector<std::string>& templateArgumentTypeNameHierarchy) = 0;
virtual Id onTemplateRecordParameterTypeParsed(
const ParseLocation& location, const std::string& templateParameterTypeName,
const ParseLocation& location, const std::vector<std::string>& templateParameterTypeNameHierarchy,
const std::vector<std::string>& templateRecordNameHierarchy) = 0;
virtual Id onTemplateRecordSpecializationParsed(
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy) = 0;
virtual Id onTemplateFunctionParameterTypeParsed(
const ParseLocation& location, const std::string& templateParameterTypeName,
const ParseLocation& location, const std::vector<std::string>& templateParameterTypeNameHierarchy,
const ParseFunction function) = 0;
virtual Id onTemplateFunctionSpecializationParsed(
const ParseLocation& location, const ParseFunction specializedFunction, const ParseFunction templateFunction) = 0;
+4 -4
View File
@@ -305,7 +305,7 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
{
m_client->onTemplateRecordParameterTypeParsed(
getParseLocationForNamedDecl(namedDecl),
namedDecl->getNameAsString(),
utility::getDeclNameHierarchy(namedDecl),
templateRecordNameHierarchy
);
}
@@ -369,7 +369,7 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
{
m_client->onTemplateRecordParameterTypeParsed(
getParseLocationForNamedDecl(namedDecl),
namedDecl->getNameAsString(),
utility::getDeclNameHierarchy(namedDecl),
specializedRecordNameHierarchy
);
}
@@ -402,11 +402,11 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
if (isLocatedInMainFile(namedDecl))
{
std::string templateParameterTypeName = namedDecl->getNameAsString();
std::vector<std::string> templateParameterTypeNameHierarchy = utility::getDeclNameHierarchy(namedDecl);
m_client->onTemplateFunctionParameterTypeParsed(
getParseLocationForNamedDecl(namedDecl),
templateParameterTypeName,
templateParameterTypeNameHierarchy,
templateFunction
);
}
+35 -35
View File
@@ -6,47 +6,47 @@
#include "data/parser/cxx/ASTActionFactory.h"
#include "data/parser/cxx/CxxDiagnosticConsumer.h"
namespace {
static std::vector<std::string> getSyntaxOnlyToolArgs(const std::vector<std::string> &ExtraArgs, llvm::StringRef FileName)
namespace
{
std::vector<std::string> Args;
Args.push_back("clang-tool");
Args.push_back("-fsyntax-only");
Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
Args.push_back(FileName.str());
return Args;
}
// custom implementation of clang::runToolOnCodeWithArgs which also sets our custon DiagnosticConsumer
static bool runToolOnCodeWithArgs(
clang::DiagnosticConsumer* DiagConsumer,
clang::FrontendAction *ToolAction,
const llvm::Twine &Code,
const std::vector<std::string> &Args,
const llvm::Twine &FileName = "input.cc",
const clang::tooling::FileContentMappings &VirtualMappedFiles = clang::tooling::FileContentMappings()
){
llvm::SmallString<16> FileNameStorage;
llvm::StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
llvm::IntrusiveRefCntPtr<clang::FileManager> Files(new clang::FileManager(clang::FileSystemOptions()));
clang::tooling::ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction, Files.get());
llvm::SmallString<1024> CodeStorage;
Invocation.mapVirtualFile(FileNameRef,
Code.toNullTerminatedStringRef(CodeStorage));
for (auto &FilenameWithContent : VirtualMappedFiles)
static std::vector<std::string> getSyntaxOnlyToolArgs(const std::vector<std::string> &ExtraArgs, llvm::StringRef FileName)
{
Invocation.mapVirtualFile(FilenameWithContent.first,
FilenameWithContent.second);
std::vector<std::string> Args;
Args.push_back("clang-tool");
Args.push_back("-fsyntax-only");
Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
Args.push_back(FileName.str());
return Args;
}
Invocation.setDiagnosticConsumer(DiagConsumer);
// custom implementation of clang::runToolOnCodeWithArgs which also sets our custon DiagnosticConsumer
static bool runToolOnCodeWithArgs(
clang::DiagnosticConsumer* DiagConsumer,
clang::FrontendAction *ToolAction,
const llvm::Twine &Code,
const std::vector<std::string> &Args,
const llvm::Twine &FileName = "input.cc",
const clang::tooling::FileContentMappings &VirtualMappedFiles = clang::tooling::FileContentMappings()
)
{
llvm::SmallString<16> FileNameStorage;
llvm::StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
llvm::IntrusiveRefCntPtr<clang::FileManager> Files(new clang::FileManager(clang::FileSystemOptions()));
clang::tooling::ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction, Files.get());
return Invocation.run();
}
llvm::SmallString<1024> CodeStorage;
Invocation.mapVirtualFile(FileNameRef,
Code.toNullTerminatedStringRef(CodeStorage));
for (auto &FilenameWithContent : VirtualMappedFiles)
{
Invocation.mapVirtualFile(FilenameWithContent.first,
FilenameWithContent.second);
}
Invocation.setDiagnosticConsumer(DiagConsumer);
return Invocation.run();
}
}
CxxParser::CxxParser(ParserClient* client, FileManager* fileManager)
+16 -9
View File
@@ -105,17 +105,24 @@ namespace utility
}
case clang::Type::TemplateTypeParm:
{
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 typeName = qualType.getUnqualifiedType().getAsString(pp);
clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast<clang::TemplateTypeParmType>(qualType)->getDecl();
typeNameHerarchy = getContextNameHierarchy(templateTypeParmDecl->getDeclContext());
std::string typeName = getDeclName(templateTypeParmDecl);
clang::ASTContext& astContext = templateTypeParmDecl->getASTContext();
llvm::ArrayRef<clang::ast_type_traits::DynTypedNode> parents = astContext.getParents<clang::Decl>(*(clang::dyn_cast<clang::Decl>(templateTypeParmDecl)));
if (parents.size() > 0) // usually this list contains just one parent node.
{
const clang::Decl* parentNode = parents[0].get<clang::Decl>(); // use the fist parent node.
if (clang::isa<clang::NamedDecl>(parentNode))
{
const clang::NamedDecl* parentNamedDecl = clang::dyn_cast<clang::NamedDecl>(parentNode);
typeNameHerarchy = getDeclNameHierarchy(parentNamedDecl);
}
}
if (typeNameHerarchy.size() == 0)
{
int gogo = 0;
typeNameHerarchy.push_back(typeName); // HOT: fix this one! definition of template function outside of class scope!
LOG_ERROR("Unable to resolve type name hierarchy for template parameter \"" + typeName + "\"");
typeNameHerarchy.push_back(typeName);
}
else
{
@@ -165,7 +172,7 @@ namespace utility
}
else
{
LOG_ERROR("unhandled declaration type");
LOG_ERROR("unhandled declaration type: " + std::string(declaration->getDeclKindName()));
}
contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext());
if (clang::isa<clang::TemplateTypeParmDecl>(declaration))