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 @@ -219,6 +219,13 @@ namespace CppSharp.AST
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)
{
return Templates.FirstOrDefault(template =>

27
src/CppParser/AST.cpp

@ -219,6 +219,33 @@ Function* DeclarationContext::FindFunction(const std::string& Name, bool Create) @@ -219,6 +219,33 @@ Function* DeclarationContext::FindFunction(const std::string& Name, bool Create)
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)
{
auto foundTypedef = std::find_if(Typedefs.begin(), Typedefs.end(),

10
src/CppParser/AST.h

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

54
src/CppParser/Parser.cpp

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

50
src/Parser/Parser.cpp

@ -800,7 +800,26 @@ CppSharp::AST::ClassTemplate^ Parser::WalkClassTemplate(clang::ClassTemplateDecl @@ -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 clix;
@ -812,25 +831,28 @@ CppSharp::AST::FunctionTemplate^ Parser::WalkFunctionTemplate(clang::FunctionTem @@ -812,25 +831,28 @@ CppSharp::AST::FunctionTemplate^ Parser::WalkFunctionTemplate(clang::FunctionTem
if (FT != nullptr)
return FT;
auto Function = WalkFunction(TD->getTemplatedDecl(), /*IsDependent=*/true,
/*AddToNamespace=*/false);
auto Params = WalkTemplateParameterList(TD->getTemplateParameters());
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);
HandleDeclaration(TD, FT);
FT->Namespace = NS;
FT->TemplatedDecl = Function;
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);
}
FT->Parameters = Params;
NS->Templates->Add(FT);

Loading…
Cancel
Save