Browse Source

Reworked template parsing with support for specializations and partial specializations.

Fixes #121.
pull/123/head
triton 12 years ago
parent
commit
f1755f6d46
  1. 11
      src/AST/Namespace.cs
  2. 102
      src/AST/Template.cs
  3. 211
      src/Parser/Parser.cpp
  4. 6
      src/Parser/Parser.h

11
src/AST/Namespace.cs

@ -226,9 +226,16 @@ namespace CppSharp.AST @@ -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)

102
src/AST/Template.cs

@ -1,4 +1,6 @@ @@ -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 @@ -7,8 +9,17 @@ namespace CppSharp.AST
public string Name;
}
/// <summary>
/// The base class of all kinds of template declarations
/// (e.g., class, function, etc.).
/// </summary>
public abstract class Template : Declaration
{
protected Template()
{
Parameters = new List<TemplateParameter>();
}
protected Template(Declaration decl)
{
TemplatedDecl = decl;
@ -25,16 +36,27 @@ namespace CppSharp.AST @@ -25,16 +36,27 @@ namespace CppSharp.AST
}
}
/// <summary>
/// Declaration of a class template.
/// </summary>
public class ClassTemplate : Template
{
public ClassTemplate(Declaration decl)
: base(decl)
public List<ClassTemplateSpecialization> Specializations;
public Class TemplatedClass
{
get { return TemplatedDecl as Class; }
}
public Class TemplatedClass
public ClassTemplate()
{
get { return TemplatedDecl as Class; }
Specializations = new List<ClassTemplateSpecialization>();
}
public ClassTemplate(Declaration decl)
: base(decl)
{
Specializations = new List<ClassTemplateSpecialization>();
}
public override T Visit<T>(IDeclVisitor<T> visitor)
@ -75,17 +97,87 @@ namespace CppSharp.AST @@ -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;
}
}
/// <summary>
/// Describes the kind of template specialization that a particular
/// template specialization declaration represents.
/// </summary>
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
}
/// <summary>
/// Represents a class template specialization, which refers to a class
/// template with a given set of template arguments.
/// </summary>
public class ClassTemplateSpecialization : Class
{
public ClassTemplate TemplatedDecl;
public List<TemplateArgument> Arguments;
public TemplateSpecializationKind SpecializationKind;
public ClassTemplateSpecialization()
{
Arguments = new List<TemplateArgument>();
}
}
/// <summary>
/// Represents a class template partial specialization, which refers to
/// a class template with a given partial set of template arguments.
/// </summary>
public class ClassTemplatePartialSpecialization : ClassTemplateSpecialization
{
}
/// <summary>
/// Declaration of a template function.
/// </summary>
public class FunctionTemplate : Template
{
public FunctionTemplate(Declaration decl)

211
src/Parser/Parser.cpp

@ -527,45 +527,12 @@ void Parser::WalkVTable(clang::CXXRecordDecl* RD, CppSharp::AST::Class^ C) @@ -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<E_UTF8>(GetTagDeclName(Record));
auto HasEmptyName = Record->getDeclName().isEmpty();
if (HasEmptyName)
{
if (auto AR = NS->FindAnonymous((uint64_t)Record))
RC = safe_cast<CppSharp::AST::Class^>(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) @@ -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<E_UTF8>(GetTagDeclName(Record));
auto HasEmptyName = Record->getDeclName().isEmpty();
if (HasEmptyName)
{
if (auto AR = NS->FindAnonymous((uint64_t)Record))
RC = safe_cast<CppSharp::AST::Class^>(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 @@ -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, @@ -951,10 +1052,15 @@ CppSharp::AST::DeclarationContext^ Parser::GetNamespace(clang::Decl* D,
continue;
}
case Decl::ClassTemplateSpecialization:
{
auto CTSpec = cast<ClassTemplateSpecializationDecl>(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<ClassTemplatePartialSpecializationDecl>(Ctx);
DC = WalkClassTemplatePartialSpecialization(CTPSpec);
continue;
}
default:
@ -1072,6 +1178,13 @@ static CppSharp::AST::CallingConvention ConvertCallConv(clang::CallingConv CC) @@ -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, @@ -1982,17 +2095,13 @@ CppSharp::AST::Declaration^ Parser::WalkDeclaration(clang::Decl* D,
ClassTemplateDecl* TD = cast<ClassTemplateDecl>(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<ClassTemplateSpecializationDecl>(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, @@ -2000,21 +2109,17 @@ CppSharp::AST::Declaration^ Parser::WalkDeclaration(clang::Decl* D,
case Decl::ClassTemplatePartialSpecialization:
{
auto TS = cast<ClassTemplatePartialSpecializationDecl>(D);
auto CT = gcnew CppSharp::AST::ClassTemplatePartialSpecialization();
auto CT = WalkClassTemplatePartialSpecialization(TS);
Decl = CT;
break;
}
case Decl::FunctionTemplate:
{
FunctionTemplateDecl* TD = cast<FunctionTemplateDecl>(D);
auto Template = WalkFunctionTemplate(TD);
auto TD = cast<FunctionTemplateDecl>(D);
auto FT = WalkFunctionTemplate(TD);
auto NS = GetNamespace(TD);
Template->Namespace = NS;
NS->Templates->Add(Template);
Decl = Template;
Decl = FT;
break;
}
case Decl::Enum:

6
src/Parser/Parser.h

@ -65,6 +65,11 @@ protected: @@ -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: @@ -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&);

Loading…
Cancel
Save