Browse Source

Reworked function template parsing.

The previous version did not handle methods properly and lead to duplicate definitions since it did not check for existing templates with the same signature.
pull/144/merge
triton 12 years ago
parent
commit
a754b46438
  1. 7
      src/AST/Namespace.cs
  2. 27
      src/CppParser/AST.cpp
  3. 10
      src/CppParser/AST.h
  4. 54
      src/CppParser/Parser.cpp
  5. 50
      src/Parser/Parser.cpp

7
src/AST/Namespace.cs

@ -219,6 +219,13 @@ namespace CppSharp.AST
return newClass; return newClass;
} }
public FunctionTemplate FindFunctionTemplate(string name,
List<TemplateParameter> @params)
{
return Templates.FirstOrDefault(template => template.Name == name
&& template.Parameters.SequenceEqual(@params)) as FunctionTemplate;
}
public FunctionTemplate FindFunctionTemplate(IntPtr ptr) public FunctionTemplate FindFunctionTemplate(IntPtr ptr)
{ {
return Templates.FirstOrDefault(template => return Templates.FirstOrDefault(template =>

27
src/CppParser/AST.cpp

@ -219,6 +219,33 @@ Function* DeclarationContext::FindFunction(const std::string& Name, bool Create)
return function; return function;
} }
FunctionTemplate*
DeclarationContext::FindFunctionTemplate(void* OriginalPtr)
{
auto foundFunction = std::find_if(Templates.begin(), Templates.end(),
[&](Template* func) { return func->OriginalPtr == OriginalPtr; });
if (foundFunction != Templates.end())
return static_cast<FunctionTemplate*>(*foundFunction);
return nullptr;
}
FunctionTemplate*
DeclarationContext::FindFunctionTemplate(const std::string& Name,
const std::vector<TemplateParameter>& Params)
{
FunctionTemplate* func = 0;
auto foundFunction = std::find_if(Templates.begin(), Templates.end(),
[&](Template* func) { return func->Name == Name && func->Parameters == Params; }
);
if (foundFunction != Templates.end())
return static_cast<FunctionTemplate*>(*foundFunction);
return nullptr;
}
TypedefDecl* DeclarationContext::FindTypedef(const std::string& Name, bool Create) TypedefDecl* DeclarationContext::FindTypedef(const std::string& Name, bool Create)
{ {
auto foundTypedef = std::find_if(Typedefs.begin(), Typedefs.end(), auto foundTypedef = std::find_if(Typedefs.begin(), Typedefs.end(),

10
src/CppParser/AST.h

@ -158,6 +158,11 @@ struct CS_API TemplateSpecializationType : public Type
struct CS_API TemplateParameter struct CS_API TemplateParameter
{ {
bool operator==(const TemplateParameter& param) const
{
return Name == param.Name;
}
std::string Name; std::string Name;
}; };
@ -332,6 +337,7 @@ struct Function;
struct TypedefDecl; struct TypedefDecl;
struct Namespace; struct Namespace;
struct Template; struct Template;
struct FunctionTemplate;
struct Variable; struct Variable;
struct CS_API DeclarationContext : public Declaration struct CS_API DeclarationContext : public Declaration
@ -347,6 +353,10 @@ struct CS_API DeclarationContext : public Declaration
Class* FindClass(const std::string& Name, bool IsComplete, Class* FindClass(const std::string& Name, bool IsComplete,
bool Create = false); bool Create = false);
FunctionTemplate* FindFunctionTemplate(void* OriginalPtr);
FunctionTemplate* FindFunctionTemplate(const std::string& Name,
const std::vector<TemplateParameter>& Params);
Enumeration* FindEnum(const std::string& Name, bool Create = false); Enumeration* FindEnum(const std::string& Name, bool Create = false);
Function* FindFunction(const std::string& Name, bool Create = false); Function* FindFunction(const std::string& Name, bool Create = false);

54
src/CppParser/Parser.cpp

@ -702,29 +702,57 @@ ClassTemplate* Parser::WalkClassTemplate(clang::ClassTemplateDecl* TD)
//-----------------------------------// //-----------------------------------//
static std::vector<CppSharp::CppParser::TemplateParameter>
WalkTemplateParameterList(const clang::TemplateParameterList* TPL)
{
auto params = std::vector<CppSharp::CppParser::TemplateParameter>();
for(auto it = TPL->begin(); it != TPL->end(); ++it)
{
auto ND = *it;
auto TP = CppSharp::CppParser::TemplateParameter();
TP.Name = ND->getNameAsString();
params.push_back(TP);
}
return params;
}
FunctionTemplate* Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD) FunctionTemplate* Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD)
{ {
using namespace clang;
auto NS = GetNamespace(TD); auto NS = GetNamespace(TD);
assert(NS && "Expected a valid namespace"); assert(NS && "Expected a valid namespace");
auto Function = WalkFunction(TD->getTemplatedDecl(), /*IsDependent=*/true, auto FT = NS->FindFunctionTemplate((void*)TD);
/*AddToNamespace=*/false); if (FT != nullptr)
return FT;
FunctionTemplate* FT = new FunctionTemplate; auto Params = WalkTemplateParameterList(TD->getTemplateParameters());
HandleDeclaration(TD, FT);
FT->TemplatedDecl = Function; CppSharp::CppParser::AST::Function* Function = nullptr;
auto TemplatedDecl = TD->getTemplatedDecl();
auto TPL = TD->getTemplateParameters(); if (auto MD = dyn_cast<CXXMethodDecl>(TemplatedDecl))
for(auto it = TPL->begin(); it != TPL->end(); ++it) Function = WalkMethodCXX(MD);
{ else
auto ND = *it; Function = WalkFunction(TemplatedDecl, /*IsDependent=*/true,
/*AddToNamespace=*/false);
auto TP = TemplateParameter(); auto Name = TD->getNameAsString();
TP.Name = ND->getNameAsString(); FT = NS->FindFunctionTemplate(Name, Params);
if (FT != nullptr && FT->TemplatedDecl == Function)
return FT;
FT->Parameters.push_back(TP); FT = new FunctionTemplate();
} HandleDeclaration(TD, FT);
FT->_Namespace = NS;
FT->TemplatedDecl = Function;
FT->Parameters = Params;
NS->Templates.push_back(FT); NS->Templates.push_back(FT);

50
src/Parser/Parser.cpp

@ -800,7 +800,26 @@ CppSharp::AST::ClassTemplate^ Parser::WalkClassTemplate(clang::ClassTemplateDecl
//-----------------------------------// //-----------------------------------//
CppSharp::AST::FunctionTemplate^ Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD) static List<CppSharp::AST::TemplateParameter>^
WalkTemplateParameterList(const clang::TemplateParameterList* TPL)
{
auto params = gcnew List<CppSharp::AST::TemplateParameter>();
for(auto it = TPL->begin(); it != TPL->end(); ++it)
{
auto ND = *it;
auto TP = CppSharp::AST::TemplateParameter();
TP.Name = clix::marshalString<clix::E_UTF8>(ND->getNameAsString());
params->Add(TP);
}
return params;
}
CppSharp::AST::FunctionTemplate^
Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD)
{ {
using namespace clang; using namespace clang;
using namespace clix; using namespace clix;
@ -812,25 +831,28 @@ CppSharp::AST::FunctionTemplate^ Parser::WalkFunctionTemplate(clang::FunctionTem
if (FT != nullptr) if (FT != nullptr)
return FT; return FT;
auto Function = WalkFunction(TD->getTemplatedDecl(), /*IsDependent=*/true, auto Params = WalkTemplateParameterList(TD->getTemplateParameters());
/*AddToNamespace=*/false);
CppSharp::AST::Function^ Function = nullptr;
auto TemplatedDecl = TD->getTemplatedDecl();
if (auto MD = dyn_cast<CXXMethodDecl>(TemplatedDecl))
Function = WalkMethodCXX(MD);
else
Function = WalkFunction(TemplatedDecl, /*IsDependent=*/true,
/*AddToNamespace=*/false);
auto Name = clix::marshalString<clix::E_UTF8>(TD->getNameAsString());
FT = NS->FindFunctionTemplate(Name, Params);
if (FT != nullptr && FT->TemplatedDecl == Function)
return FT;
FT = gcnew CppSharp::AST::FunctionTemplate(Function); FT = gcnew CppSharp::AST::FunctionTemplate(Function);
HandleDeclaration(TD, FT); HandleDeclaration(TD, FT);
FT->Namespace = NS; FT->Namespace = NS;
FT->TemplatedDecl = Function; FT->TemplatedDecl = Function;
FT->Parameters = Params;
auto TPL = TD->getTemplateParameters();
for(auto it = TPL->begin(); it != TPL->end(); ++it)
{
auto ND = *it;
auto TP = CppSharp::AST::TemplateParameter();
TP.Name = clix::marshalString<clix::E_UTF8>(ND->getNameAsString());
FT->Parameters->Add(TP);
}
NS->Templates->Add(FT); NS->Templates->Add(FT);

Loading…
Cancel
Save