diff --git a/src/AST/Namespace.cs b/src/AST/Namespace.cs
index 48566673..64c77d1d 100644
--- a/src/AST/Namespace.cs
+++ b/src/AST/Namespace.cs
@@ -226,9 +226,16 @@ namespace CppSharp.AST
return newClass;
}
- public ClassTemplate FindClassTemplate(string name)
+ public FunctionTemplate FindFunctionTemplate(IntPtr ptr)
{
- return null;
+ return Templates.FirstOrDefault(template =>
+ template.OriginalPtr == ptr) as FunctionTemplate;
+ }
+
+ public ClassTemplate FindClassTemplate(IntPtr ptr)
+ {
+ return Templates.FirstOrDefault(template =>
+ template.OriginalPtr == ptr) as ClassTemplate;
}
public TypedefDecl FindTypedef(string name, bool createDecl = false)
diff --git a/src/AST/Template.cs b/src/AST/Template.cs
index 637400a0..588fd049 100644
--- a/src/AST/Template.cs
+++ b/src/AST/Template.cs
@@ -1,4 +1,6 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace CppSharp.AST
{
@@ -7,8 +9,17 @@ namespace CppSharp.AST
public string Name;
}
+ ///
+ /// The base class of all kinds of template declarations
+ /// (e.g., class, function, etc.).
+ ///
public abstract class Template : Declaration
{
+ protected Template()
+ {
+ Parameters = new List();
+ }
+
protected Template(Declaration decl)
{
TemplatedDecl = decl;
@@ -25,16 +36,27 @@ namespace CppSharp.AST
}
}
+ ///
+ /// Declaration of a class template.
+ ///
public class ClassTemplate : Template
{
- public ClassTemplate(Declaration decl)
- : base(decl)
+ public List Specializations;
+
+ public Class TemplatedClass
{
+ get { return TemplatedDecl as Class; }
}
- public Class TemplatedClass
+ public ClassTemplate()
{
- get { return TemplatedDecl as Class; }
+ Specializations = new List();
+ }
+
+ public ClassTemplate(Declaration decl)
+ : base(decl)
+ {
+ Specializations = new List();
}
public override T Visit(IDeclVisitor visitor)
@@ -75,17 +97,87 @@ namespace CppSharp.AST
base.OriginalName = value;
}
}
+
+ public ClassTemplateSpecialization FindSpecialization(
+ TemplateSpecializationType type)
+ {
+ return Specializations.FirstOrDefault(
+ spec => spec.Arguments.SequenceEqual(type.Arguments));
+ }
+
+ public ClassTemplateSpecialization FindSpecialization(IntPtr ptr)
+ {
+ return Specializations.FirstOrDefault(spec => spec.OriginalPtr == ptr);
+ }
+
+ public ClassTemplatePartialSpecialization FindPartialSpecialization(
+ TemplateSpecializationType type)
+ {
+ return FindSpecialization(type) as ClassTemplatePartialSpecialization;
+ }
+
+ public ClassTemplatePartialSpecialization FindPartialSpecialization(IntPtr ptr)
+ {
+ return FindSpecialization(ptr) as ClassTemplatePartialSpecialization;
+ }
}
+ ///
+ /// Describes the kind of template specialization that a particular
+ /// template specialization declaration represents.
+ ///
+ public enum TemplateSpecializationKind
+ {
+ /// This template specialization was formed from a template-id but has
+ /// not yet been declared, defined, or instantiated.
+ Undeclared,
+
+ /// This template specialization was implicitly instantiated from a
+ /// template.
+ ImplicitInstantiation,
+
+ /// This template specialization was declared or defined by an explicit
+ /// specialization or partial specialization.
+ ExplicitSpecialization,
+
+ /// This template specialization was instantiated from a template due
+ /// to an explicit instantiation declaration request.
+ ExplicitInstantiationDeclaration,
+
+ /// This template specialization was instantiated from a template due
+ /// to an explicit instantiation definition request.
+ ExplicitInstantiationDefinition
+ }
+
+ ///
+ /// Represents a class template specialization, which refers to a class
+ /// template with a given set of template arguments.
+ ///
public class ClassTemplateSpecialization : Class
{
public ClassTemplate TemplatedDecl;
+
+ public List Arguments;
+
+ public TemplateSpecializationKind SpecializationKind;
+
+ public ClassTemplateSpecialization()
+ {
+ Arguments = new List();
+ }
}
+ ///
+ /// Represents a class template partial specialization, which refers to
+ /// a class template with a given partial set of template arguments.
+ ///
public class ClassTemplatePartialSpecialization : ClassTemplateSpecialization
{
}
+ ///
+ /// Declaration of a template function.
+ ///
public class FunctionTemplate : Template
{
public FunctionTemplate(Declaration decl)
diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp
index 6180cdd1..439c194d 100644
--- a/src/Parser/Parser.cpp
+++ b/src/Parser/Parser.cpp
@@ -527,45 +527,12 @@ void Parser::WalkVTable(clang::CXXRecordDecl* RD, CppSharp::AST::Class^ C)
}
}
-CppSharp::AST::Class^ Parser::WalkRecordCXX(clang::CXXRecordDecl* Record)
+void Parser::WalkRecordCXX(clang::CXXRecordDecl* Record,
+ CppSharp::AST::Class^ RC)
{
using namespace clang;
using namespace clix;
- if (Record->isInjectedClassName())
- return nullptr;
-
- auto NS = GetNamespace(Record);
- assert(NS && "Expected a valid namespace");
-
- bool isCompleteDefinition = Record->isCompleteDefinition();
-
- CppSharp::AST::Class^ RC = nullptr;
-
- auto Name = marshalString(GetTagDeclName(Record));
- auto HasEmptyName = Record->getDeclName().isEmpty();
-
- if (HasEmptyName)
- {
- if (auto AR = NS->FindAnonymous((uint64_t)Record))
- RC = safe_cast(AR);
- }
- else
- {
- RC = NS->FindClass(Name, isCompleteDefinition, /*Create=*/false);
- }
-
- if (RC)
- return RC;
-
- RC = NS->FindClass(Name, isCompleteDefinition, /*Create=*/true);
-
- if (HasEmptyName)
- NS->Anonymous[(uint64_t)Record] = RC;
-
- if (!isCompleteDefinition)
- return RC;
-
auto headStartLoc = GetDeclStartLocation(C.get(), Record);
auto headEndLoc = Record->getLocation(); // identifier location
auto bodyEndLoc = Record->getLocEnd();
@@ -674,19 +641,141 @@ CppSharp::AST::Class^ Parser::WalkRecordCXX(clang::CXXRecordDecl* Record)
// Process the vtables
if (hasLayout && Record->isDynamicClass())
WalkVTable(Record, RC);
+}
+
+CppSharp::AST::Class^ Parser::WalkRecordCXX(clang::CXXRecordDecl* Record)
+{
+ using namespace clang;
+ using namespace clix;
+
+ if (Record->isInjectedClassName())
+ return nullptr;
+
+ auto NS = GetNamespace(Record);
+ assert(NS && "Expected a valid namespace");
+
+ bool isCompleteDefinition = Record->isCompleteDefinition();
+
+ CppSharp::AST::Class^ RC = nullptr;
+
+ auto Name = marshalString(GetTagDeclName(Record));
+ auto HasEmptyName = Record->getDeclName().isEmpty();
+
+ if (HasEmptyName)
+ {
+ if (auto AR = NS->FindAnonymous((uint64_t)Record))
+ RC = safe_cast(AR);
+ }
+ else
+ {
+ RC = NS->FindClass(Name, isCompleteDefinition, /*Create=*/false);
+ }
+
+ if (RC)
+ return RC;
+
+ RC = NS->FindClass(Name, isCompleteDefinition, /*Create=*/true);
+
+ if (HasEmptyName)
+ NS->Anonymous[(uint64_t)Record] = RC;
+
+ if (!isCompleteDefinition)
+ return RC;
+
+ WalkRecordCXX(Record, RC);
return RC;
}
//-----------------------------------//
+static CppSharp::AST::TemplateSpecializationKind
+WalkTemplateSpecializationKind(clang::TemplateSpecializationKind Kind)
+{
+ using namespace clang;
+ switch(Kind)
+ {
+ case TSK_Undeclared:
+ return CppSharp::AST::TemplateSpecializationKind::Undeclared;
+ case TSK_ImplicitInstantiation:
+ return CppSharp::AST::TemplateSpecializationKind::ImplicitInstantiation;
+ case TSK_ExplicitSpecialization:
+ return CppSharp::AST::TemplateSpecializationKind::ExplicitSpecialization;
+ case TSK_ExplicitInstantiationDeclaration:
+ return CppSharp::AST::TemplateSpecializationKind::ExplicitInstantiationDeclaration;
+ case TSK_ExplicitInstantiationDefinition:
+ return CppSharp::AST::TemplateSpecializationKind::ExplicitInstantiationDefinition;
+ }
+}
+
+CppSharp::AST::ClassTemplateSpecialization^
+Parser::WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl* CTS)
+{
+ auto CT = WalkClassTemplate(CTS->getSpecializedTemplate());
+ auto Spec = CT->FindSpecialization(System::IntPtr(CTS));
+ if (Spec != nullptr)
+ return Spec;
+
+ auto TS = gcnew CppSharp::AST::ClassTemplateSpecialization();
+ TS->OriginalPtr = System::IntPtr(CTS);
+ TS->TemplatedDecl = CT;
+ TS->SpecializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind());
+ CT->Specializations->Add(TS);
+
+ // TODO: Parse the template argument list
+
+ if (CTS->isCompleteDefinition())
+ WalkRecordCXX(CTS, TS);
+
+ return TS;
+}
+
+//-----------------------------------//
+
+CppSharp::AST::ClassTemplatePartialSpecialization^
+Parser::WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl* CTS)
+{
+ auto CT = WalkClassTemplate(CTS->getSpecializedTemplate());
+ auto Spec = CT->FindPartialSpecialization(System::IntPtr(CTS));
+ if (Spec != nullptr)
+ return Spec;
+
+ auto TS = gcnew CppSharp::AST::ClassTemplatePartialSpecialization();
+ TS->OriginalPtr = System::IntPtr(CTS);
+ TS->TemplatedDecl = CT;
+ TS->SpecializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind());
+ CT->Specializations->Add(TS);
+
+ // TODO: Parse the template argument list
+
+ if (CTS->isCompleteDefinition())
+ WalkRecordCXX(CTS, TS);
+
+ return TS;
+}
+
+//-----------------------------------//
+
CppSharp::AST::ClassTemplate^ Parser::WalkClassTemplate(clang::ClassTemplateDecl* TD)
{
using namespace clang;
using namespace clix;
- auto Class = WalkRecordCXX(TD->getTemplatedDecl());
- CppSharp::AST::ClassTemplate^ CT = gcnew CppSharp::AST::ClassTemplate(Class);
+ if (TD->getCanonicalDecl() != TD)
+ return WalkClassTemplate(TD->getCanonicalDecl());
+
+ auto NS = GetNamespace(TD);
+ assert(NS && "Expected a valid namespace");
+
+ auto CT = NS->FindClassTemplate(System::IntPtr(TD));
+ if (CT != nullptr)
+ return CT;
+
+ CT = gcnew CppSharp::AST::ClassTemplate();
+ CT->OriginalPtr = System::IntPtr(TD);
+ NS->Templates->Add(CT);
+
+ CT->TemplatedDecl = WalkRecordCXX(TD->getTemplatedDecl());
auto TPL = TD->getTemplateParameters();
for(auto it = TPL->begin(); it != TPL->end(); ++it)
@@ -709,9 +798,21 @@ CppSharp::AST::FunctionTemplate^ Parser::WalkFunctionTemplate(clang::FunctionTem
using namespace clang;
using namespace clix;
+ if (TD->getCanonicalDecl() != TD)
+ return WalkFunctionTemplate(TD->getCanonicalDecl());
+
+ auto NS = GetNamespace(TD);
+ assert(NS && "Expected a valid namespace");
+
+ auto FT = NS->FindFunctionTemplate(System::IntPtr(TD));
+ if (FT != nullptr)
+ return FT;
+
auto Function = WalkFunction(TD->getTemplatedDecl(), /*IsDependent=*/true,
/*AddToNamespace=*/false);
- CppSharp::AST::FunctionTemplate^ FT = gcnew CppSharp::AST::FunctionTemplate(Function);
+ FT = gcnew CppSharp::AST::FunctionTemplate(Function);
+ FT->OriginalPtr = System::IntPtr(TD);
+ NS->Templates->Add(FT);
auto TPL = TD->getTemplateParameters();
for(auto it = TPL->begin(); it != TPL->end(); ++it)
@@ -951,10 +1052,15 @@ CppSharp::AST::DeclarationContext^ Parser::GetNamespace(clang::Decl* D,
continue;
}
case Decl::ClassTemplateSpecialization:
+ {
+ auto CTSpec = cast(Ctx);
+ DC = WalkClassTemplateSpecialization(CTSpec);
+ continue;
+ }
case Decl::ClassTemplatePartialSpecialization:
{
- // FIXME: Ignore ClassTemplateSpecialization namespaces...
- // We might be able to translate these to C# nested types.
+ auto CTPSpec = cast(Ctx);
+ DC = WalkClassTemplatePartialSpecialization(CTPSpec);
continue;
}
default:
@@ -1072,6 +1178,13 @@ static CppSharp::AST::CallingConvention ConvertCallConv(clang::CallingConv CC)
return CppSharp::AST::CallingConvention::Default;
}
+CppSharp::AST::QualifiedType^ Parser::WalkQualifiedType(clang::TypeSourceInfo* TSI)
+{
+ auto TL = TSI->getTypeLoc();
+ auto Ty = WalkType(TSI->getType(), &TL);
+ return GetQualifiedType(TSI->getType(), Ty);
+}
+
CppSharp::AST::Type^ Parser::WalkType(clang::QualType QualType, clang::TypeLoc* TL,
bool DesugarType)
{
@@ -1982,17 +2095,13 @@ CppSharp::AST::Declaration^ Parser::WalkDeclaration(clang::Decl* D,
ClassTemplateDecl* TD = cast(D);
auto Template = WalkClassTemplate(TD);
- auto NS = GetNamespace(TD);
- Template->Namespace = NS;
- NS->Templates->Add(Template);
-
Decl = Template;
break;
}
case Decl::ClassTemplateSpecialization:
{
auto TS = cast(D);
- auto CT = gcnew CppSharp::AST::ClassTemplateSpecialization();
+ auto CT = WalkClassTemplateSpecialization(TS);
Decl = CT;
break;
@@ -2000,21 +2109,17 @@ CppSharp::AST::Declaration^ Parser::WalkDeclaration(clang::Decl* D,
case Decl::ClassTemplatePartialSpecialization:
{
auto TS = cast(D);
- auto CT = gcnew CppSharp::AST::ClassTemplatePartialSpecialization();
+ auto CT = WalkClassTemplatePartialSpecialization(TS);
Decl = CT;
break;
}
case Decl::FunctionTemplate:
{
- FunctionTemplateDecl* TD = cast(D);
- auto Template = WalkFunctionTemplate(TD);
+ auto TD = cast(D);
+ auto FT = WalkFunctionTemplate(TD);
- auto NS = GetNamespace(TD);
- Template->Namespace = NS;
- NS->Templates->Add(Template);
-
- Decl = Template;
+ Decl = FT;
break;
}
case Decl::Enum:
diff --git a/src/Parser/Parser.h b/src/Parser/Parser.h
index 305cff25..1069b537 100644
--- a/src/Parser/Parser.h
+++ b/src/Parser/Parser.h
@@ -65,6 +65,11 @@ protected:
CppSharp::AST::Function^ WalkFunction(clang::FunctionDecl*, bool IsDependent = false,
bool AddToNamespace = true);
CppSharp::AST::Class^ WalkRecordCXX(clang::CXXRecordDecl*);
+ void WalkRecordCXX(clang::CXXRecordDecl*, CppSharp::AST::Class^);
+ CppSharp::AST::ClassTemplateSpecialization^
+ WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl*);
+ CppSharp::AST::ClassTemplatePartialSpecialization^
+ WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl*);
CppSharp::AST::Method^ WalkMethodCXX(clang::CXXMethodDecl*);
CppSharp::AST::Field^ WalkFieldCXX(clang::FieldDecl*, CppSharp::AST::Class^);
CppSharp::AST::ClassTemplate^ Parser::WalkClassTemplate(clang::ClassTemplateDecl*);
@@ -74,6 +79,7 @@ protected:
CppSharp::AST::RawComment^ WalkRawComment(const clang::RawComment*);
CppSharp::AST::Type^ WalkType(clang::QualType, clang::TypeLoc* = 0,
bool DesugarType = false);
+ CppSharp::AST::QualifiedType^ WalkQualifiedType(clang::TypeSourceInfo* TSI);
void WalkVTable(clang::CXXRecordDecl*, CppSharp::AST::Class^);
CppSharp::AST::VTableLayout^ WalkVTableLayout(const clang::VTableLayout&);
CppSharp::AST::VTableComponent WalkVTableComponent(const clang::VTableComponent&);