Browse Source

Merge pull request #248 from azeno/improved-template-support

Improved template support
pull/250/head
João Matos 11 years ago
parent
commit
73c4212c43
  1. 1
      build/LLVM.lua
  2. 20
      src/AST/Class.cs
  3. 8
      src/AST/Declaration.cs
  4. 7
      src/AST/Function.cs
  5. 43
      src/AST/Namespace.cs
  6. 72
      src/AST/Template.cs
  7. 8
      src/AST/Type.cs
  8. 16
      src/AST/TypeExtensions.cs
  9. 27
      src/Core/Parser/ASTConverter.cs
  10. 137
      src/CppParser/AST.cpp
  11. 33
      src/CppParser/AST.h
  12. 176
      src/CppParser/Bindings/CLI/AST.cpp
  13. 109
      src/CppParser/Bindings/CLI/AST.h
  14. 652
      src/CppParser/Bindings/CSharp/AST.cs
  15. 376
      src/CppParser/Parser.cpp
  16. 6
      src/CppParser/Parser.h
  17. 59
      src/Generator.Tests/AST/TestAST.cs
  18. 4
      src/Generator.Tests/ASTTestFixture.cs
  19. 2
      src/Generator/Generator.cs
  20. 9
      src/Generator/Passes/CleanUnitPass.cs
  21. 386
      src/Parser/Parser.cpp
  22. 6
      src/Parser/Parser.h
  23. 36
      tests/Native/AST.h
  24. 9
      tests/Native/ASTExtensions.h

1
build/LLVM.lua

@ -79,6 +79,7 @@ function SetupLLVMLibs()
"clangParse", "clangParse",
"clangSema", "clangSema",
"clangSerialization", "clangSerialization",
"clangIndex",
} }
StaticLinksOpt { "LLVMProfileData" } StaticLinksOpt { "LLVMProfileData" }

20
src/AST/Class.cs

@ -220,9 +220,27 @@ namespace CppSharp.AST
return base.GetOverloads(function); return base.GetOverloads(function);
} }
public Method FindMethod(string name)
{
return Methods
.Concat(Templates.OfType<FunctionTemplate>()
.Select(t => t.TemplatedFunction)
.OfType<Method>())
.FirstOrDefault(m => m.Name == name);
}
public Method FindMethodByUSR(string usr)
{
return Methods
.Concat(Templates.OfType<FunctionTemplate>()
.Select(t => t.TemplatedFunction)
.OfType<Method>())
.FirstOrDefault(m => m.USR == usr);
}
public override T Visit<T>(IDeclVisitor<T> visitor) public override T Visit<T>(IDeclVisitor<T> visitor)
{ {
return visitor.VisitClassDecl(this); return visitor.VisitClassDecl(this);
} }
} }
} }

8
src/AST/Declaration.cs

@ -285,6 +285,14 @@ namespace CppSharp.AST
// Pointer to the original declaration from Clang. // Pointer to the original declaration from Clang.
public IntPtr OriginalPtr; public IntPtr OriginalPtr;
// The Unified Symbol Resolution (USR) for the declaration.
// A Unified Symbol Resolution (USR) is a string that identifies a
// particular entity (function, class, variable, etc.) within a program.
// USRs can be compared across translation units to determine, e.g.,
// when references in one translation refer to an entity defined in
// another translation unit.
public string USR;
public List<Attribute> Attributes { get; private set; } public List<Attribute> Attributes { get; private set; }
protected Declaration() protected Declaration()

7
src/AST/Function.cs

@ -119,6 +119,11 @@ namespace CppSharp.AST
OriginalFunction = function.OriginalFunction; OriginalFunction = function.OriginalFunction;
Mangled = function.Mangled; Mangled = function.Mangled;
Index = function.Index; Index = function.Index;
if (function.SpecializationInfo != null)
{
SpecializationInfo = new FunctionTemplateSpecialization(function.SpecializationInfo);
SpecializationInfo.SpecializedFunction = function;
}
} }
public QualifiedType ReturnType { get; set; } public QualifiedType ReturnType { get; set; }
@ -136,6 +141,8 @@ namespace CppSharp.AST
public CallingConvention CallingConvention { get; set; } public CallingConvention CallingConvention { get; set; }
public FunctionTemplateSpecialization SpecializationInfo { get; set; }
public bool IsThisCall public bool IsThisCall
{ {
get { return CallingConvention == CallingConvention.ThisCall; } get { return CallingConvention == CallingConvention.ThisCall; }

43
src/AST/Namespace.cs

@ -216,6 +216,22 @@ namespace CppSharp.AST
return @namespace.FindFunction(funcName, createDecl); return @namespace.FindFunction(funcName, createDecl);
} }
public Function FindFunction(string name)
{
return Functions
.Concat(Templates.OfType<FunctionTemplate>()
.Select(t => t.TemplatedFunction))
.FirstOrDefault(f => f.Name == name);
}
public Function FindFunctionByUSR(string usr)
{
return Functions
.Concat(Templates.OfType<FunctionTemplate>()
.Select(t => t.TemplatedFunction))
.FirstOrDefault(f => f.USR == usr);
}
Class CreateClass(string name, bool isComplete) Class CreateClass(string name, bool isComplete)
{ {
var @class = new Class var @class = new Class
@ -294,23 +310,28 @@ namespace CppSharp.AST
return newClass; return newClass;
} }
public FunctionTemplate FindFunctionTemplate(string name, public FunctionTemplate FindFunctionTemplate(string name)
List<TemplateParameter> @params) {
return Templates.OfType<FunctionTemplate>()
.FirstOrDefault(t => t.Name == name);
}
public FunctionTemplate FindFunctionTemplateByUSR(string usr)
{ {
return Templates.FirstOrDefault(template => template.Name == name return Templates.OfType<FunctionTemplate>()
&& template.Parameters.SequenceEqual(@params)) as FunctionTemplate; .FirstOrDefault(t => t.USR == usr);
} }
public FunctionTemplate FindFunctionTemplate(IntPtr ptr) public ClassTemplate FindClassTemplate(string name)
{ {
return Templates.FirstOrDefault(template => return Templates.OfType<ClassTemplate>()
template.OriginalPtr == ptr) as FunctionTemplate; .FirstOrDefault(t => t.Name == name);
} }
public ClassTemplate FindClassTemplate(IntPtr ptr) public ClassTemplate FindClassTemplateByUSR(string usr)
{ {
return Templates.FirstOrDefault(template => return Templates.OfType<ClassTemplate>()
template.OriginalPtr == ptr) as ClassTemplate; .FirstOrDefault(t => t.USR == usr);
} }
public TypedefDecl FindTypedef(string name, bool createDecl = false) public TypedefDecl FindTypedef(string name, bool createDecl = false)
@ -417,4 +438,4 @@ namespace CppSharp.AST
return visitor.VisitNamespace(this); return visitor.VisitNamespace(this);
} }
} }
} }

72
src/AST/Template.cs

@ -13,6 +13,10 @@ namespace CppSharp.AST
// Generic type constraint // Generic type constraint
public string Constraint; public string Constraint;
// Whether the template parameter represents a type parameter,
// like "T" in template<typename T>.
public bool IsTypeParameter;
} }
/// <summary> /// <summary>
@ -24,8 +28,18 @@ namespace CppSharp.AST
// Name of the declaration. // Name of the declaration.
public override string Name public override string Name
{ {
get { return TemplatedDecl.Name; } get
set { base.Name = value; } {
if (TemplatedDecl != null)
return TemplatedDecl.Name;
return base.Name;
}
set
{
base.Name = value;
if (TemplatedDecl != null)
TemplatedDecl.Name = value;
}
} }
protected Template() protected Template()
@ -111,27 +125,14 @@ namespace CppSharp.AST
} }
} }
public ClassTemplateSpecialization FindSpecialization( public ClassTemplateSpecialization FindSpecializationByUSR(string usr)
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; return Specializations.FirstOrDefault(spec => spec.USR == usr);
} }
public ClassTemplatePartialSpecialization FindPartialSpecialization(IntPtr ptr) public ClassTemplatePartialSpecialization FindPartialSpecializationByUSR(string usr)
{ {
return FindSpecialization(ptr) as ClassTemplatePartialSpecialization; return FindSpecializationByUSR(usr) as ClassTemplatePartialSpecialization;
} }
} }
@ -193,13 +194,17 @@ namespace CppSharp.AST
/// </summary> /// </summary>
public class FunctionTemplate : Template public class FunctionTemplate : Template
{ {
public List<FunctionTemplateSpecialization> Specializations;
public FunctionTemplate() public FunctionTemplate()
{ {
Specializations = new List<FunctionTemplateSpecialization>();
} }
public FunctionTemplate(Declaration decl) public FunctionTemplate(Declaration decl)
: base(decl) : base(decl)
{ {
Specializations = new List<FunctionTemplateSpecialization>();
} }
public Function TemplatedFunction public Function TemplatedFunction
@ -212,4 +217,33 @@ namespace CppSharp.AST
return visitor.VisitFunctionTemplateDecl(this); return visitor.VisitFunctionTemplateDecl(this);
} }
} }
/// <summary>
/// Represents a function template specialization, which refers to a function
/// template with a given set of template arguments.
/// </summary>
public class FunctionTemplateSpecialization
{
public FunctionTemplate Template;
public List<TemplateArgument> Arguments;
public Function SpecializedFunction;
public TemplateSpecializationKind SpecializationKind;
public FunctionTemplateSpecialization()
{
Arguments = new List<TemplateArgument>();
}
public FunctionTemplateSpecialization(FunctionTemplateSpecialization fts)
{
Template = fts.Template;
Arguments = new List<TemplateArgument>();
Arguments.AddRange(fts.Arguments);
SpecializedFunction = fts.SpecializedFunction;
SpecializationKind = fts.SpecializationKind;
}
}
} }

8
src/AST/Type.cs

@ -508,6 +508,9 @@ namespace CppSharp.AST
public class TemplateParameterType : Type public class TemplateParameterType : Type
{ {
public TemplateParameter Parameter; public TemplateParameter Parameter;
public uint Depth;
public uint Index;
public bool IsParameterPack;
public override T Visit<T>(ITypeVisitor<T> visitor, public override T Visit<T>(ITypeVisitor<T> visitor,
TypeQualifiers quals = new TypeQualifiers()) TypeQualifiers quals = new TypeQualifiers())
@ -520,7 +523,10 @@ namespace CppSharp.AST
var type = obj as TemplateParameterType; var type = obj as TemplateParameterType;
if (type == null) return false; if (type == null) return false;
return Parameter.Equals(type.Parameter); return Parameter.Equals(type.Parameter)
&& Depth.Equals(type.Depth)
&& Index.Equals(type.Index)
&& IsParameterPack.Equals(type.IsParameterPack);
} }
public override int GetHashCode() public override int GetHashCode()

16
src/AST/TypeExtensions.cs

@ -158,16 +158,22 @@
public static Type Desugar(this Type t) public static Type Desugar(this Type t)
{ {
var type = t as TypedefType; var typeDef = t as TypedefType;
if (typeDef != null)
if (type != null)
{ {
var decl = type.Declaration.Type; var decl = typeDef.Declaration.Type;
if (decl != null) if (decl != null)
return decl.Desugar(); return decl.Desugar();
} }
var substType = t as TemplateParameterSubstitutionType;
if (substType != null)
{
var replacement = substType.Replacement.Type;
if (replacement != null)
return replacement.Desugar();
}
return t; return t;
} }

27
src/Core/Parser/ASTConverter.cs

@ -496,6 +496,9 @@ namespace CppSharp
{ {
var _type = new AST.TemplateParameterType(); var _type = new AST.TemplateParameterType();
_type.Parameter = DeclConverter.VisitTemplateParameter(type.Parameter); _type.Parameter = DeclConverter.VisitTemplateParameter(type.Parameter);
_type.Depth = type.Depth;
_type.Index = type.Index;
_type.IsParameterPack = type.IsParameterPack;
VisitType(type, _type); VisitType(type, _type);
return _type; return _type;
} }
@ -1255,6 +1258,7 @@ namespace CppSharp
{ {
var _param = new AST.TemplateParameter(); var _param = new AST.TemplateParameter();
_param.Name = param.Name; _param.Name = param.Name;
_param.IsTypeParameter = param.IsTypeParameter;
return _param; return _param;
} }
@ -1356,11 +1360,30 @@ namespace CppSharp
public override AST.Declaration VisitFunctionTemplate(FunctionTemplate decl) public override AST.Declaration VisitFunctionTemplate(FunctionTemplate decl)
{ {
var _decl = new AST.FunctionTemplate(); var _decl = new AST.FunctionTemplate(Visit(decl.TemplatedDecl));
VisitTemplate(decl, _decl); VisitTemplate(decl, _decl);
for (uint i = 0; i < decl.SpecializationsCount; ++i)
{
var _spec = VisitFunctionTemplateSpecialization(decl.getSpecializations(i));
_decl.Specializations.Add(_spec);
}
return _decl; return _decl;
} }
private AST.FunctionTemplateSpecialization VisitFunctionTemplateSpecialization(FunctionTemplateSpecialization spec)
{
var _spec = new AST.FunctionTemplateSpecialization();
_spec.Template = (AST.FunctionTemplate)Visit(spec.Template);
_spec.SpecializedFunction = (AST.Function)Visit(spec.SpecializedFunction);
_spec.SpecializationKind = VisitSpecializationKind(spec.SpecializationKind);
for (uint i = 0; i < spec.ArgumentsCount; ++i)
{
var _arg = VisitTemplateArgument(spec.getArguments(i));
_spec.Arguments.Add(_arg);
}
return _spec;
}
void VisitPreprocessedEntity(PreprocessedEntity entity, AST.PreprocessedEntity _entity) void VisitPreprocessedEntity(PreprocessedEntity entity, AST.PreprocessedEntity _entity)
{ {
VisitDeclaration(entity, _entity); VisitDeclaration(entity, _entity);
@ -1416,4 +1439,4 @@ namespace CppSharp
#endregion #endregion
} }
#endif #endif

137
src/CppParser/AST.cpp

@ -69,8 +69,16 @@ TemplateSpecializationType::TemplateSpecializationType(
DEF_VECTOR(TemplateSpecializationType, TemplateArgument, Arguments) DEF_VECTOR(TemplateSpecializationType, TemplateArgument, Arguments)
// TemplateParameter // TemplateParameter
TemplateParameter::TemplateParameter() {} TemplateParameter::TemplateParameter()
TemplateParameter::TemplateParameter(const TemplateParameter& rhs) : Name(rhs.Name) {} : IsTypeParameter(false)
{
}
TemplateParameter::TemplateParameter(const TemplateParameter& rhs)
: Name(rhs.Name)
, IsTypeParameter(rhs.IsTypeParameter)
{
}
DEF_STRING(TemplateParameter, Name) DEF_STRING(TemplateParameter, Name)
@ -341,60 +349,44 @@ Enumeration* DeclarationContext::FindEnumWithItem(const std::string& Name)
return nullptr; return nullptr;
} }
Function* DeclarationContext::FindFunction(const std::string& Name, bool Create) Function* DeclarationContext::FindFunction(const std::string& USR)
{ {
auto foundFunction = std::find_if(Functions.begin(), Functions.end(), auto foundFunction = std::find_if(Functions.begin(), Functions.end(),
[&](Function* func) { return func->Name == Name; }); [&](Function* func) { return func->USR == USR; });
if (foundFunction != Functions.end()) if (foundFunction != Functions.end())
return *foundFunction; return *foundFunction;
if (!Create)
return nullptr;
auto function = new Function();
function->Name = Name;
function->_Namespace = this;
Functions.push_back(function);
return function;
}
ClassTemplate*
DeclarationContext::FindClassTemplate(void* OriginalPtr)
{
auto foundTemplate = std::find_if(Templates.begin(), Templates.end(), auto foundTemplate = std::find_if(Templates.begin(), Templates.end(),
[&](Template* t) { return t->OriginalPtr == OriginalPtr; }); [&](Template* t) { return t->TemplatedDecl->USR == USR; });
if (foundTemplate != Templates.end()) if (foundTemplate != Templates.end())
return static_cast<ClassTemplate*>(*foundTemplate); return static_cast<Function*>((*foundTemplate)->TemplatedDecl);
return nullptr; return nullptr;
} }
FunctionTemplate* ClassTemplate*
DeclarationContext::FindFunctionTemplate(void* OriginalPtr) DeclarationContext::FindClassTemplate(const std::string& USR)
{ {
auto foundFunction = std::find_if(Templates.begin(), Templates.end(), auto foundTemplate = std::find_if(Templates.begin(), Templates.end(),
[&](Template* func) { return func->OriginalPtr == OriginalPtr; }); [&](Template* t) { return t->USR == USR; });
if (foundFunction != Templates.end()) if (foundTemplate != Templates.end())
return static_cast<FunctionTemplate*>(*foundFunction); return static_cast<ClassTemplate*>(*foundTemplate);
return nullptr; return nullptr;
} }
FunctionTemplate* FunctionTemplate*
DeclarationContext::FindFunctionTemplate(const std::string& Name, DeclarationContext::FindFunctionTemplate(const std::string& USR)
const std::vector<TemplateParameter>& Params)
{ {
FunctionTemplate* func = 0; auto foundTemplate = std::find_if(Templates.begin(), Templates.end(),
auto foundFunction = std::find_if(Templates.begin(), Templates.end(), [&](Template* t) { return t->USR == USR; }
[&](Template* func) { return func->Name == Name && func->Parameters == Params; }
); );
if (foundFunction != Templates.end()) if (foundTemplate != Templates.end())
return static_cast<FunctionTemplate*>(*foundFunction); return static_cast<FunctionTemplate*>(*foundTemplate);
return nullptr; return nullptr;
} }
@ -423,15 +415,32 @@ TypedefDecl::TypedefDecl() : Declaration(DeclarationKind::Typedef) {}
Parameter::Parameter() : Declaration(DeclarationKind::Parameter), Parameter::Parameter() : Declaration(DeclarationKind::Parameter),
IsIndirect(false), HasDefaultValue(false) {} IsIndirect(false), HasDefaultValue(false) {}
Function::Function() : Declaration(DeclarationKind::Function), Function::Function()
IsReturnIndirect(false) {} : Declaration(DeclarationKind::Function)
, IsReturnIndirect(false)
, SpecializationInfo(0)
{
}
DEF_STRING(Function, Mangled) DEF_STRING(Function, Mangled)
DEF_STRING(Function, Signature) DEF_STRING(Function, Signature)
DEF_VECTOR(Function, Parameter*, Parameters) DEF_VECTOR(Function, Parameter*, Parameters)
Method::Method() : IsDefaultConstructor(false), IsCopyConstructor(false), Method::Method()
IsMoveConstructor(false) { Kind = DeclarationKind::Method; } : Function()
, AccessDecl(0)
, IsVirtual(false)
, IsStatic(false)
, IsConst(false)
, IsImplicit(false)
, IsExplicit(false)
, IsOverride(false)
, IsDefaultConstructor(false)
, IsCopyConstructor(false)
, IsMoveConstructor(false)
{
Kind = DeclarationKind::Method;
}
// Enumeration // Enumeration
@ -496,16 +505,44 @@ ClassTemplate::ClassTemplate() : Template(DeclarationKind::ClassTemplate) {}
DEF_VECTOR(ClassTemplate, ClassTemplateSpecialization*, Specializations) DEF_VECTOR(ClassTemplate, ClassTemplateSpecialization*, Specializations)
ClassTemplateSpecialization::ClassTemplateSpecialization() : TemplatedDecl(0) ClassTemplateSpecialization::ClassTemplateSpecialization()
{ Kind = DeclarationKind::ClassTemplateSpecialization; } : Class()
, TemplatedDecl(0)
{
Kind = DeclarationKind::ClassTemplateSpecialization;
}
DEF_VECTOR(ClassTemplateSpecialization, TemplateArgument, Arguments) DEF_VECTOR(ClassTemplateSpecialization, TemplateArgument, Arguments)
ClassTemplatePartialSpecialization::ClassTemplatePartialSpecialization() ClassTemplatePartialSpecialization::ClassTemplatePartialSpecialization()
{ Kind = DeclarationKind::ClassTemplatePartialSpecialization; } : ClassTemplateSpecialization()
{
Kind = DeclarationKind::ClassTemplatePartialSpecialization;
}
FunctionTemplate::FunctionTemplate() : Template(DeclarationKind::FunctionTemplate) {} FunctionTemplate::FunctionTemplate() : Template(DeclarationKind::FunctionTemplate) {}
DEF_VECTOR(FunctionTemplate, FunctionTemplateSpecialization*, Specializations)
FunctionTemplateSpecialization* FunctionTemplate::FindSpecialization(const std::string& usr)
{
auto foundSpec = std::find_if(Specializations.begin(), Specializations.end(),
[&](FunctionTemplateSpecialization* cts) { return cts->SpecializedFunction->USR == usr; });
if (foundSpec != Specializations.end())
return static_cast<FunctionTemplateSpecialization*>(*foundSpec);
return nullptr;
}
FunctionTemplateSpecialization::FunctionTemplateSpecialization()
: Template(0)
, SpecializedFunction(0)
{
}
DEF_VECTOR(FunctionTemplateSpecialization, TemplateArgument, Arguments)
Namespace::Namespace() Namespace::Namespace()
: DeclarationContext(DeclarationKind::Namespace) : DeclarationContext(DeclarationKind::Namespace)
, IsInline(false) , IsInline(false)
@ -536,10 +573,10 @@ DEF_VECTOR_STRING(NativeLibrary, Symbols)
// ASTContext // ASTContext
DEF_VECTOR(ASTContext, TranslationUnit*, TranslationUnits) DEF_VECTOR(ASTContext, TranslationUnit*, TranslationUnits)
ClassTemplateSpecialization* ClassTemplate::FindSpecialization(void* ptr) ClassTemplateSpecialization* ClassTemplate::FindSpecialization(const std::string& usr)
{ {
auto foundSpec = std::find_if(Specializations.begin(), Specializations.end(), auto foundSpec = std::find_if(Specializations.begin(), Specializations.end(),
[&](ClassTemplateSpecialization* cts) { return cts->OriginalPtr == ptr; }); [&](ClassTemplateSpecialization* cts) { return cts->USR == usr; });
if (foundSpec != Specializations.end()) if (foundSpec != Specializations.end())
return static_cast<ClassTemplateSpecialization*>(*foundSpec); return static_cast<ClassTemplateSpecialization*>(*foundSpec);
@ -547,26 +584,14 @@ ClassTemplateSpecialization* ClassTemplate::FindSpecialization(void* ptr)
return nullptr; return nullptr;
} }
ClassTemplateSpecialization* ClassTemplatePartialSpecialization* ClassTemplate::FindPartialSpecialization(const std::string& usr)
ClassTemplate::FindSpecialization(TemplateSpecializationType type)
{ {
return 0; auto foundSpec = FindSpecialization(usr);
}
ClassTemplatePartialSpecialization* ClassTemplate::FindPartialSpecialization(void* ptr)
{
auto foundSpec = FindSpecialization(ptr);
if (foundSpec != nullptr) if (foundSpec != nullptr)
return static_cast<ClassTemplatePartialSpecialization*>(foundSpec); return static_cast<ClassTemplatePartialSpecialization*>(foundSpec);
return nullptr; return nullptr;
} }
ClassTemplatePartialSpecialization*
ClassTemplate::FindPartialSpecialization(TemplateSpecializationType type)
{
return 0;
}
ASTContext::ASTContext() {} ASTContext::ASTContext() {}
TranslationUnit* ASTContext::FindOrCreateModule(std::string File) TranslationUnit* ASTContext::FindOrCreateModule(std::string File)

33
src/CppParser/AST.h

@ -191,12 +191,16 @@ struct CS_API TemplateParameter
} }
STRING(Name) STRING(Name)
bool IsTypeParameter;
}; };
struct CS_API TemplateParameterType : public Type struct CS_API TemplateParameterType : public Type
{ {
DECLARE_TYPE_KIND(TemplateParameter) DECLARE_TYPE_KIND(TemplateParameter)
TemplateParameter Parameter; TemplateParameter Parameter;
unsigned int Depth;
unsigned int Index;
bool IsParameterPack;
}; };
struct CS_API TemplateParameterSubstitutionType : public Type struct CS_API TemplateParameterSubstitutionType : public Type
@ -372,6 +376,7 @@ struct CS_API Declaration
unsigned DefinitionOrder; unsigned DefinitionOrder;
VECTOR(PreprocessedEntity*, PreprocessedEntities) VECTOR(PreprocessedEntity*, PreprocessedEntities)
void* OriginalPtr; void* OriginalPtr;
std::string USR;
}; };
struct Class; struct Class;
@ -399,16 +404,14 @@ struct CS_API DeclarationContext : public Declaration
CS_IGNORE Class* FindClass(const std::string& Name, bool IsComplete, CS_IGNORE Class* FindClass(const std::string& Name, bool IsComplete,
bool Create = false); bool Create = false);
CS_IGNORE ClassTemplate* FindClassTemplate(void* OriginalPtr); CS_IGNORE ClassTemplate* FindClassTemplate(const std::string& USR);
CS_IGNORE FunctionTemplate* FindFunctionTemplate(void* OriginalPtr); CS_IGNORE FunctionTemplate* FindFunctionTemplate(const std::string& USR);
CS_IGNORE FunctionTemplate* FindFunctionTemplate(const std::string& Name,
const std::vector<TemplateParameter>& Params);
CS_IGNORE Enumeration* FindEnum(void* OriginalPtr); CS_IGNORE Enumeration* FindEnum(void* OriginalPtr);
CS_IGNORE Enumeration* FindEnum(const std::string& Name, bool Create = false); CS_IGNORE Enumeration* FindEnum(const std::string& Name, bool Create = false);
CS_IGNORE Enumeration* FindEnumWithItem(const std::string& Name); CS_IGNORE Enumeration* FindEnumWithItem(const std::string& Name);
CS_IGNORE Function* FindFunction(const std::string& Name, bool Create = false); CS_IGNORE Function* FindFunction(const std::string& USR);
CS_IGNORE TypedefDecl* FindTypedef(const std::string& Name, bool Create = false); CS_IGNORE TypedefDecl* FindTypedef(const std::string& Name, bool Create = false);
@ -498,6 +501,8 @@ enum struct CXXOperatorKind
Conditional Conditional
}; };
struct FunctionTemplateSpecialization;
struct CS_API Function : public Declaration struct CS_API Function : public Declaration
{ {
Function(); Function();
@ -514,6 +519,7 @@ struct CS_API Function : public Declaration
STRING(Signature) STRING(Signature)
CppSharp::CppParser::AST::CallingConvention CallingConvention; CppSharp::CppParser::AST::CallingConvention CallingConvention;
VECTOR(Parameter*, Parameters) VECTOR(Parameter*, Parameters)
FunctionTemplateSpecialization* SpecializationInfo;
}; };
struct AccessSpecifierDecl; struct AccessSpecifierDecl;
@ -638,10 +644,8 @@ struct CS_API ClassTemplate : public Template
{ {
ClassTemplate(); ClassTemplate();
VECTOR(ClassTemplateSpecialization*, Specializations) VECTOR(ClassTemplateSpecialization*, Specializations)
ClassTemplateSpecialization* FindSpecialization(void* ptr); ClassTemplateSpecialization* FindSpecialization(const std::string& usr);
ClassTemplateSpecialization* FindSpecialization(TemplateSpecializationType type); ClassTemplatePartialSpecialization* FindPartialSpecialization(const std::string& usr);
ClassTemplatePartialSpecialization* FindPartialSpecialization(void* ptr);
ClassTemplatePartialSpecialization* FindPartialSpecialization(TemplateSpecializationType type);
}; };
enum struct TemplateSpecializationKind enum struct TemplateSpecializationKind
@ -669,6 +673,17 @@ struct CS_API ClassTemplatePartialSpecialization : public ClassTemplateSpecializ
struct CS_API FunctionTemplate : public Template struct CS_API FunctionTemplate : public Template
{ {
FunctionTemplate(); FunctionTemplate();
VECTOR(FunctionTemplateSpecialization*, Specializations)
FunctionTemplateSpecialization* FindSpecialization(const std::string& usr);
};
struct CS_API FunctionTemplateSpecialization
{
FunctionTemplateSpecialization();
FunctionTemplate* Template;
VECTOR(TemplateArgument, Arguments)
Function* SpecializedFunction;
TemplateSpecializationKind SpecializationKind;
}; };
struct CS_API Namespace : public DeclarationContext struct CS_API Namespace : public DeclarationContext

176
src/CppParser/Bindings/CLI/AST.cpp

@ -627,6 +627,16 @@ void CppSharp::Parser::AST::TemplateParameter::Name::set(System::String^ s)
((::CppSharp::CppParser::AST::TemplateParameter*)NativePtr)->setName(arg0); ((::CppSharp::CppParser::AST::TemplateParameter*)NativePtr)->setName(arg0);
} }
bool CppSharp::Parser::AST::TemplateParameter::IsTypeParameter::get()
{
return ((::CppSharp::CppParser::AST::TemplateParameter*)NativePtr)->IsTypeParameter;
}
void CppSharp::Parser::AST::TemplateParameter::IsTypeParameter::set(bool value)
{
((::CppSharp::CppParser::AST::TemplateParameter*)NativePtr)->IsTypeParameter = value;
}
CppSharp::Parser::AST::TemplateParameterType::TemplateParameterType(::CppSharp::CppParser::AST::TemplateParameterType* native) CppSharp::Parser::AST::TemplateParameterType::TemplateParameterType(::CppSharp::CppParser::AST::TemplateParameterType* native)
: CppSharp::Parser::AST::Type((::CppSharp::CppParser::AST::Type*)native) : CppSharp::Parser::AST::Type((::CppSharp::CppParser::AST::Type*)native)
{ {
@ -654,6 +664,36 @@ void CppSharp::Parser::AST::TemplateParameterType::Parameter::set(CppSharp::Pars
((::CppSharp::CppParser::AST::TemplateParameterType*)NativePtr)->Parameter = *(::CppSharp::CppParser::AST::TemplateParameter*)value->NativePtr; ((::CppSharp::CppParser::AST::TemplateParameterType*)NativePtr)->Parameter = *(::CppSharp::CppParser::AST::TemplateParameter*)value->NativePtr;
} }
unsigned int CppSharp::Parser::AST::TemplateParameterType::Depth::get()
{
return ((::CppSharp::CppParser::AST::TemplateParameterType*)NativePtr)->Depth;
}
void CppSharp::Parser::AST::TemplateParameterType::Depth::set(unsigned int value)
{
((::CppSharp::CppParser::AST::TemplateParameterType*)NativePtr)->Depth = value;
}
unsigned int CppSharp::Parser::AST::TemplateParameterType::Index::get()
{
return ((::CppSharp::CppParser::AST::TemplateParameterType*)NativePtr)->Index;
}
void CppSharp::Parser::AST::TemplateParameterType::Index::set(unsigned int value)
{
((::CppSharp::CppParser::AST::TemplateParameterType*)NativePtr)->Index = value;
}
bool CppSharp::Parser::AST::TemplateParameterType::IsParameterPack::get()
{
return ((::CppSharp::CppParser::AST::TemplateParameterType*)NativePtr)->IsParameterPack;
}
void CppSharp::Parser::AST::TemplateParameterType::IsParameterPack::set(bool value)
{
((::CppSharp::CppParser::AST::TemplateParameterType*)NativePtr)->IsParameterPack = value;
}
CppSharp::Parser::AST::TemplateParameterSubstitutionType::TemplateParameterSubstitutionType(::CppSharp::CppParser::AST::TemplateParameterSubstitutionType* native) CppSharp::Parser::AST::TemplateParameterSubstitutionType::TemplateParameterSubstitutionType(::CppSharp::CppParser::AST::TemplateParameterSubstitutionType* native)
: CppSharp::Parser::AST::Type((::CppSharp::CppParser::AST::Type*)native) : CppSharp::Parser::AST::Type((::CppSharp::CppParser::AST::Type*)native)
{ {
@ -1614,6 +1654,16 @@ void CppSharp::Parser::AST::Function::CallingConvention::set(CppSharp::Parser::A
((::CppSharp::CppParser::AST::Function*)NativePtr)->CallingConvention = (::CppSharp::CppParser::AST::CallingConvention)value; ((::CppSharp::CppParser::AST::Function*)NativePtr)->CallingConvention = (::CppSharp::CppParser::AST::CallingConvention)value;
} }
CppSharp::Parser::AST::FunctionTemplateSpecialization^ CppSharp::Parser::AST::Function::SpecializationInfo::get()
{
return (((::CppSharp::CppParser::AST::Function*)NativePtr)->SpecializationInfo == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::FunctionTemplateSpecialization((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)((::CppSharp::CppParser::AST::Function*)NativePtr)->SpecializationInfo);
}
void CppSharp::Parser::AST::Function::SpecializationInfo::set(CppSharp::Parser::AST::FunctionTemplateSpecialization^ value)
{
((::CppSharp::CppParser::AST::Function*)NativePtr)->SpecializationInfo = (::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)value->NativePtr;
}
CppSharp::Parser::AST::Method::Method(::CppSharp::CppParser::AST::Method* native) CppSharp::Parser::AST::Method::Method(::CppSharp::CppParser::AST::Method* native)
: CppSharp::Parser::AST::Function((::CppSharp::CppParser::AST::Function*)native) : CppSharp::Parser::AST::Function((::CppSharp::CppParser::AST::Function*)native)
{ {
@ -2295,38 +2345,6 @@ void CppSharp::Parser::AST::ClassTemplate::addSpecializations(CppSharp::Parser::
((::CppSharp::CppParser::AST::ClassTemplate*)NativePtr)->addSpecializations(arg0); ((::CppSharp::CppParser::AST::ClassTemplate*)NativePtr)->addSpecializations(arg0);
} }
CppSharp::Parser::AST::ClassTemplateSpecialization^ CppSharp::Parser::AST::ClassTemplate::FindSpecialization(void* ptr)
{
auto arg0 = (void*)ptr;
auto __ret = ((::CppSharp::CppParser::AST::ClassTemplate*)NativePtr)->FindSpecialization(arg0);
if (__ret == nullptr) return nullptr;
return (__ret == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::ClassTemplateSpecialization((::CppSharp::CppParser::AST::ClassTemplateSpecialization*)__ret);
}
CppSharp::Parser::AST::ClassTemplateSpecialization^ CppSharp::Parser::AST::ClassTemplate::FindSpecialization(CppSharp::Parser::AST::TemplateSpecializationType^ type)
{
auto arg0 = *(::CppSharp::CppParser::AST::TemplateSpecializationType*)type->NativePtr;
auto __ret = ((::CppSharp::CppParser::AST::ClassTemplate*)NativePtr)->FindSpecialization(arg0);
if (__ret == nullptr) return nullptr;
return (__ret == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::ClassTemplateSpecialization((::CppSharp::CppParser::AST::ClassTemplateSpecialization*)__ret);
}
CppSharp::Parser::AST::ClassTemplatePartialSpecialization^ CppSharp::Parser::AST::ClassTemplate::FindPartialSpecialization(void* ptr)
{
auto arg0 = (void*)ptr;
auto __ret = ((::CppSharp::CppParser::AST::ClassTemplate*)NativePtr)->FindPartialSpecialization(arg0);
if (__ret == nullptr) return nullptr;
return (__ret == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::ClassTemplatePartialSpecialization((::CppSharp::CppParser::AST::ClassTemplatePartialSpecialization*)__ret);
}
CppSharp::Parser::AST::ClassTemplatePartialSpecialization^ CppSharp::Parser::AST::ClassTemplate::FindPartialSpecialization(CppSharp::Parser::AST::TemplateSpecializationType^ type)
{
auto arg0 = *(::CppSharp::CppParser::AST::TemplateSpecializationType*)type->NativePtr;
auto __ret = ((::CppSharp::CppParser::AST::ClassTemplate*)NativePtr)->FindPartialSpecialization(arg0);
if (__ret == nullptr) return nullptr;
return (__ret == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::ClassTemplatePartialSpecialization((::CppSharp::CppParser::AST::ClassTemplatePartialSpecialization*)__ret);
}
unsigned int CppSharp::Parser::AST::ClassTemplate::SpecializationsCount::get() unsigned int CppSharp::Parser::AST::ClassTemplate::SpecializationsCount::get()
{ {
auto __ret = ((::CppSharp::CppParser::AST::ClassTemplate*)NativePtr)->getSpecializationsCount(); auto __ret = ((::CppSharp::CppParser::AST::ClassTemplate*)NativePtr)->getSpecializationsCount();
@ -2423,6 +2441,100 @@ CppSharp::Parser::AST::FunctionTemplate::FunctionTemplate()
NativePtr = new ::CppSharp::CppParser::AST::FunctionTemplate(); NativePtr = new ::CppSharp::CppParser::AST::FunctionTemplate();
} }
CppSharp::Parser::AST::FunctionTemplateSpecialization^ CppSharp::Parser::AST::FunctionTemplate::getSpecializations(unsigned int i)
{
auto __ret = ((::CppSharp::CppParser::AST::FunctionTemplate*)NativePtr)->getSpecializations(i);
if (__ret == nullptr) return nullptr;
return (__ret == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::FunctionTemplateSpecialization((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)__ret);
}
void CppSharp::Parser::AST::FunctionTemplate::addSpecializations(CppSharp::Parser::AST::FunctionTemplateSpecialization^ s)
{
auto arg0 = (::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)s->NativePtr;
((::CppSharp::CppParser::AST::FunctionTemplate*)NativePtr)->addSpecializations(arg0);
}
unsigned int CppSharp::Parser::AST::FunctionTemplate::SpecializationsCount::get()
{
auto __ret = ((::CppSharp::CppParser::AST::FunctionTemplate*)NativePtr)->getSpecializationsCount();
return __ret;
}
CppSharp::Parser::AST::FunctionTemplateSpecialization::FunctionTemplateSpecialization(::CppSharp::CppParser::AST::FunctionTemplateSpecialization* native)
{
NativePtr = native;
}
CppSharp::Parser::AST::FunctionTemplateSpecialization::FunctionTemplateSpecialization(System::IntPtr native)
{
auto __native = (::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)native.ToPointer();
NativePtr = __native;
}
CppSharp::Parser::AST::FunctionTemplateSpecialization::FunctionTemplateSpecialization()
{
NativePtr = new ::CppSharp::CppParser::AST::FunctionTemplateSpecialization();
}
CppSharp::Parser::AST::TemplateArgument^ CppSharp::Parser::AST::FunctionTemplateSpecialization::getArguments(unsigned int i)
{
auto __ret = ((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->getArguments(i);
auto ____ret = new ::CppSharp::CppParser::AST::TemplateArgument(__ret);
return (____ret == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::TemplateArgument((::CppSharp::CppParser::AST::TemplateArgument*)____ret);
}
void CppSharp::Parser::AST::FunctionTemplateSpecialization::addArguments(CppSharp::Parser::AST::TemplateArgument^ s)
{
auto &arg0 = *(::CppSharp::CppParser::AST::TemplateArgument*)s->NativePtr;
((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->addArguments(arg0);
}
System::IntPtr CppSharp::Parser::AST::FunctionTemplateSpecialization::__Instance::get()
{
return System::IntPtr(NativePtr);
}
void CppSharp::Parser::AST::FunctionTemplateSpecialization::__Instance::set(System::IntPtr object)
{
NativePtr = (::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)object.ToPointer();
}
unsigned int CppSharp::Parser::AST::FunctionTemplateSpecialization::ArgumentsCount::get()
{
auto __ret = ((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->getArgumentsCount();
return __ret;
}
CppSharp::Parser::AST::FunctionTemplate^ CppSharp::Parser::AST::FunctionTemplateSpecialization::Template::get()
{
return (((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->Template == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::FunctionTemplate((::CppSharp::CppParser::AST::FunctionTemplate*)((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->Template);
}
void CppSharp::Parser::AST::FunctionTemplateSpecialization::Template::set(CppSharp::Parser::AST::FunctionTemplate^ value)
{
((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->Template = (::CppSharp::CppParser::AST::FunctionTemplate*)value->NativePtr;
}
CppSharp::Parser::AST::Function^ CppSharp::Parser::AST::FunctionTemplateSpecialization::SpecializedFunction::get()
{
return (((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->SpecializedFunction == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::Function((::CppSharp::CppParser::AST::Function*)((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->SpecializedFunction);
}
void CppSharp::Parser::AST::FunctionTemplateSpecialization::SpecializedFunction::set(CppSharp::Parser::AST::Function^ value)
{
((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->SpecializedFunction = (::CppSharp::CppParser::AST::Function*)value->NativePtr;
}
CppSharp::Parser::AST::TemplateSpecializationKind CppSharp::Parser::AST::FunctionTemplateSpecialization::SpecializationKind::get()
{
return (CppSharp::Parser::AST::TemplateSpecializationKind)((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->SpecializationKind;
}
void CppSharp::Parser::AST::FunctionTemplateSpecialization::SpecializationKind::set(CppSharp::Parser::AST::TemplateSpecializationKind value)
{
((::CppSharp::CppParser::AST::FunctionTemplateSpecialization*)NativePtr)->SpecializationKind = (::CppSharp::CppParser::AST::TemplateSpecializationKind)value;
}
CppSharp::Parser::AST::Namespace::Namespace(::CppSharp::CppParser::AST::Namespace* native) CppSharp::Parser::AST::Namespace::Namespace(::CppSharp::CppParser::AST::Namespace* native)
: CppSharp::Parser::AST::DeclarationContext((::CppSharp::CppParser::AST::DeclarationContext*)native) : CppSharp::Parser::AST::DeclarationContext((::CppSharp::CppParser::AST::DeclarationContext*)native)
{ {

109
src/CppParser/Bindings/CLI/AST.h

@ -43,6 +43,7 @@ namespace CppSharp
ref class FullComment; ref class FullComment;
ref class Function; ref class Function;
ref class FunctionTemplate; ref class FunctionTemplate;
ref class FunctionTemplateSpecialization;
ref class FunctionType; ref class FunctionType;
ref class InjectedClassNameType; ref class InjectedClassNameType;
ref class MacroDefinition; ref class MacroDefinition;
@ -202,6 +203,15 @@ namespace CppSharp
Unknown = 5 Unknown = 5
}; };
public enum struct TemplateSpecializationKind
{
Undeclared = 0,
ImplicitInstantiation = 1,
ExplicitSpecialization = 2,
ExplicitInstantiationDeclaration = 3,
ExplicitInstantiationDefinition = 4
};
public enum struct CppAbi public enum struct CppAbi
{ {
Itanium = 0, Itanium = 0,
@ -221,15 +231,6 @@ namespace CppSharp
UnusedFunctionPointer = 7 UnusedFunctionPointer = 7
}; };
public enum struct TemplateSpecializationKind
{
Undeclared = 0,
ImplicitInstantiation = 1,
ExplicitSpecialization = 2,
ExplicitInstantiationDeclaration = 3,
ExplicitInstantiationDefinition = 4
};
public enum struct PrimitiveType public enum struct PrimitiveType
{ {
Null = 0, Null = 0,
@ -658,6 +659,12 @@ namespace CppSharp
void set(System::String^); void set(System::String^);
} }
property bool IsTypeParameter
{
bool get();
void set(bool);
}
static bool operator==(CppSharp::Parser::AST::TemplateParameter^ __op, CppSharp::Parser::AST::TemplateParameter^ param); static bool operator==(CppSharp::Parser::AST::TemplateParameter^ __op, CppSharp::Parser::AST::TemplateParameter^ param);
}; };
@ -674,6 +681,24 @@ namespace CppSharp
CppSharp::Parser::AST::TemplateParameter^ get(); CppSharp::Parser::AST::TemplateParameter^ get();
void set(CppSharp::Parser::AST::TemplateParameter^); void set(CppSharp::Parser::AST::TemplateParameter^);
} }
property unsigned int Depth
{
unsigned int get();
void set(unsigned int);
}
property unsigned int Index
{
unsigned int get();
void set(unsigned int);
}
property bool IsParameterPack
{
bool get();
void set(bool);
}
}; };
public ref class TemplateParameterSubstitutionType : CppSharp::Parser::AST::Type public ref class TemplateParameterSubstitutionType : CppSharp::Parser::AST::Type
@ -1201,6 +1226,12 @@ namespace CppSharp
void set(CppSharp::Parser::AST::CallingConvention); void set(CppSharp::Parser::AST::CallingConvention);
} }
property CppSharp::Parser::AST::FunctionTemplateSpecialization^ SpecializationInfo
{
CppSharp::Parser::AST::FunctionTemplateSpecialization^ get();
void set(CppSharp::Parser::AST::FunctionTemplateSpecialization^);
}
CppSharp::Parser::AST::Parameter^ getParameters(unsigned int i); CppSharp::Parser::AST::Parameter^ getParameters(unsigned int i);
void addParameters(CppSharp::Parser::AST::Parameter^ s); void addParameters(CppSharp::Parser::AST::Parameter^ s);
@ -1590,14 +1621,6 @@ namespace CppSharp
CppSharp::Parser::AST::ClassTemplateSpecialization^ getSpecializations(unsigned int i); CppSharp::Parser::AST::ClassTemplateSpecialization^ getSpecializations(unsigned int i);
void addSpecializations(CppSharp::Parser::AST::ClassTemplateSpecialization^ s); void addSpecializations(CppSharp::Parser::AST::ClassTemplateSpecialization^ s);
CppSharp::Parser::AST::ClassTemplateSpecialization^ FindSpecialization(void* ptr);
CppSharp::Parser::AST::ClassTemplateSpecialization^ FindSpecialization(CppSharp::Parser::AST::TemplateSpecializationType^ type);
CppSharp::Parser::AST::ClassTemplatePartialSpecialization^ FindPartialSpecialization(void* ptr);
CppSharp::Parser::AST::ClassTemplatePartialSpecialization^ FindPartialSpecialization(CppSharp::Parser::AST::TemplateSpecializationType^ type);
}; };
public ref class ClassTemplateSpecialization : CppSharp::Parser::AST::Class public ref class ClassTemplateSpecialization : CppSharp::Parser::AST::Class
@ -1646,6 +1669,58 @@ namespace CppSharp
FunctionTemplate(::CppSharp::CppParser::AST::FunctionTemplate* native); FunctionTemplate(::CppSharp::CppParser::AST::FunctionTemplate* native);
FunctionTemplate(System::IntPtr native); FunctionTemplate(System::IntPtr native);
FunctionTemplate(); FunctionTemplate();
property unsigned int SpecializationsCount
{
unsigned int get();
}
CppSharp::Parser::AST::FunctionTemplateSpecialization^ getSpecializations(unsigned int i);
void addSpecializations(CppSharp::Parser::AST::FunctionTemplateSpecialization^ s);
};
public ref class FunctionTemplateSpecialization : ICppInstance
{
public:
property ::CppSharp::CppParser::AST::FunctionTemplateSpecialization* NativePtr;
property System::IntPtr __Instance
{
virtual System::IntPtr get();
virtual void set(System::IntPtr instance);
}
FunctionTemplateSpecialization(::CppSharp::CppParser::AST::FunctionTemplateSpecialization* native);
FunctionTemplateSpecialization(System::IntPtr native);
FunctionTemplateSpecialization();
property unsigned int ArgumentsCount
{
unsigned int get();
}
property CppSharp::Parser::AST::FunctionTemplate^ Template
{
CppSharp::Parser::AST::FunctionTemplate^ get();
void set(CppSharp::Parser::AST::FunctionTemplate^);
}
property CppSharp::Parser::AST::Function^ SpecializedFunction
{
CppSharp::Parser::AST::Function^ get();
void set(CppSharp::Parser::AST::Function^);
}
property CppSharp::Parser::AST::TemplateSpecializationKind SpecializationKind
{
CppSharp::Parser::AST::TemplateSpecializationKind get();
void set(CppSharp::Parser::AST::TemplateSpecializationKind);
}
CppSharp::Parser::AST::TemplateArgument^ getArguments(unsigned int i);
void addArguments(CppSharp::Parser::AST::TemplateArgument^ s);
}; };
public ref class Namespace : CppSharp::Parser::AST::DeclarationContext public ref class Namespace : CppSharp::Parser::AST::DeclarationContext

652
src/CppParser/Bindings/CSharp/AST.cs

File diff suppressed because it is too large Load Diff

376
src/CppParser/Parser.cpp

@ -26,6 +26,7 @@
#include <clang/Sema/SemaConsumer.h> #include <clang/Sema/SemaConsumer.h>
#include <clang/Frontend/Utils.h> #include <clang/Frontend/Utils.h>
#include <clang/Driver/Util.h> #include <clang/Driver/Util.h>
#include <clang/Index/USRGeneration.h>
#include <CodeGen/CodeGenModule.h> #include <CodeGen/CodeGenModule.h>
#include <CodeGen/CodeGenTypes.h> #include <CodeGen/CodeGenTypes.h>
#include <CodeGen/TargetInfo.h> #include <CodeGen/TargetInfo.h>
@ -296,6 +297,15 @@ static std::string GetTagDeclName(const clang::TagDecl* D)
return GetDeclName(D); return GetDeclName(D);
} }
static std::string GetDeclUSR(const clang::Decl* D)
{
using namespace clang;
SmallString<128> usr;
if (!index::generateUSRForDecl(D, usr))
return usr.str();
return "<invalid>";
}
static clang::Decl* GetPreviousDeclInContext(const clang::Decl* D) static clang::Decl* GetPreviousDeclInContext(const clang::Decl* D)
{ {
assert(!D->getLexicalDeclContext()->decls_empty()); assert(!D->getLexicalDeclContext()->decls_empty());
@ -727,26 +737,32 @@ WalkTemplateSpecializationKind(clang::TemplateSpecializationKind Kind)
ClassTemplateSpecialization* ClassTemplateSpecialization*
Parser::WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl* CTS) Parser::WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl* CTS)
{ {
using namespace clang;
auto CT = WalkClassTemplate(CTS->getSpecializedTemplate()); auto CT = WalkClassTemplate(CTS->getSpecializedTemplate());
auto Spec = CT->FindSpecialization(CTS); auto USR = GetDeclUSR(CTS);
if (Spec != nullptr) auto TS = CT->FindSpecialization(USR);
return Spec; if (TS != nullptr)
return TS;
auto TS = new ClassTemplateSpecialization(); TS = new ClassTemplateSpecialization();
HandleDeclaration(CTS, TS); HandleDeclaration(CTS, TS);
TS->Name = CTS->getName();
auto NS = GetNamespace(CTS); auto NS = GetNamespace(CTS);
assert(NS && "Expected a valid namespace"); assert(NS && "Expected a valid namespace");
TS->_Namespace = NS; TS->_Namespace = NS;
TS->Name = CTS->getName();
TS->TemplatedDecl = CT; TS->TemplatedDecl = CT;
TS->SpecializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind()); TS->SpecializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind());
auto &TAL = CTS->getTemplateArgs();
if (auto TSI = CTS->getTypeAsWritten())
{
auto TL = TSI->getTypeLoc();
auto TSL = TL.getAs<TemplateSpecializationTypeLoc>();
TS->Arguments = WalkTemplateArgumentList(&TAL, &TSL);
}
CT->Specializations.push_back(TS); CT->Specializations.push_back(TS);
// TODO: Parse the template argument list
if (CTS->isCompleteDefinition()) if (CTS->isCompleteDefinition())
WalkRecordCXX(CTS, TS); WalkRecordCXX(CTS, TS);
@ -758,12 +774,15 @@ Parser::WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl*
ClassTemplatePartialSpecialization* ClassTemplatePartialSpecialization*
Parser::WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl* CTS) Parser::WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl* CTS)
{ {
using namespace clang;
auto CT = WalkClassTemplate(CTS->getSpecializedTemplate()); auto CT = WalkClassTemplate(CTS->getSpecializedTemplate());
auto Spec = CT->FindPartialSpecialization((void*) CTS); auto USR = GetDeclUSR(CTS);
if (Spec != nullptr) auto TS = CT->FindPartialSpecialization(USR);
return Spec; if (TS != nullptr)
return TS;
auto TS = new ClassTemplatePartialSpecialization(); TS = new ClassTemplatePartialSpecialization();
HandleDeclaration(CTS, TS); HandleDeclaration(CTS, TS);
TS->Name = CTS->getName(); TS->Name = CTS->getName();
@ -774,10 +793,15 @@ Parser::WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecia
TS->TemplatedDecl = CT; TS->TemplatedDecl = CT;
TS->SpecializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind()); TS->SpecializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind());
auto &TAL = CTS->getTemplateArgs();
if (auto TSI = CTS->getTypeAsWritten())
{
auto TL = TSI->getTypeLoc();
auto TSL = TL.getAs<TemplateSpecializationTypeLoc>();
TS->Arguments = WalkTemplateArgumentList(&TAL, &TSL);
}
CT->Specializations.push_back(TS); CT->Specializations.push_back(TS);
// TODO: Parse the template argument list
if (CTS->isCompleteDefinition()) if (CTS->isCompleteDefinition())
WalkRecordCXX(CTS, TS); WalkRecordCXX(CTS, TS);
@ -786,57 +810,173 @@ Parser::WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecia
//-----------------------------------// //-----------------------------------//
CppSharp::CppParser::TemplateParameter
WalkTemplateParameter(const clang::NamedDecl* D)
{
using namespace clang;
auto TP = CppSharp::CppParser::TemplateParameter();
if (D == nullptr)
return TP;
TP.Name = GetDeclName(D);
switch (D->getKind())
{
case Decl::TemplateTypeParm:
{
auto TTPD = cast<TemplateTypeParmDecl>(D);
TP.IsTypeParameter = true;
break;
}
default:
break;
}
return TP;
}
//-----------------------------------//
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 = WalkTemplateParameter(ND);
params.push_back(TP);
}
return params;
}
//-----------------------------------//
ClassTemplate* Parser::WalkClassTemplate(clang::ClassTemplateDecl* TD) ClassTemplate* Parser::WalkClassTemplate(clang::ClassTemplateDecl* TD)
{ {
auto NS = GetNamespace(TD); auto NS = GetNamespace(TD);
assert(NS && "Expected a valid namespace"); assert(NS && "Expected a valid namespace");
auto CT = NS->FindClassTemplate((void*) TD); auto USR = GetDeclUSR(TD);
auto CT = NS->FindClassTemplate(USR);
if (CT != nullptr) if (CT != nullptr)
return CT; return CT;
CT = new ClassTemplate(); CT = new ClassTemplate();
HandleDeclaration(TD, CT); HandleDeclaration(TD, CT);
CT->Name = GetDeclName(TD);
CT->_Namespace = NS; CT->_Namespace = NS;
NS->Templates.push_back(CT); NS->Templates.push_back(CT);
CT->TemplatedDecl = WalkRecordCXX(TD->getTemplatedDecl()); CT->TemplatedDecl = WalkRecordCXX(TD->getTemplatedDecl());
CT->Parameters = WalkTemplateParameterList(TD->getTemplateParameters());
auto TPL = TD->getTemplateParameters(); return CT;
for(auto it = TPL->begin(); it != TPL->end(); ++it) }
{
auto ND = *it; //-----------------------------------//
std::vector<CppSharp::CppParser::TemplateArgument>
Parser::WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL,
clang::TemplateSpecializationTypeLoc* TSTL)
{
using namespace clang;
auto TP = TemplateParameter(); auto params = std::vector<CppSharp::CppParser::TemplateArgument>();
TP.Name = ND->getNameAsString();
CT->Parameters.push_back(TP); for (size_t i = 0, e = TAL->size(); i < e; i++)
{
auto TA = TAL->get(i);
TemplateArgumentLoc *ArgLoc = 0;
if (TSTL && i < TSTL->getNumArgs())
{
auto TAL = TSTL->getArgLoc(i);
ArgLoc = &TAL;
}
auto Arg = WalkTemplateArgument(TA, ArgLoc);
params.push_back(Arg);
} }
return CT; return params;
} }
//-----------------------------------// //-----------------------------------//
static std::vector<CppSharp::CppParser::TemplateParameter> std::vector<CppSharp::CppParser::TemplateArgument>
WalkTemplateParameterList(const clang::TemplateParameterList* TPL) Parser::WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL,
const clang::ASTTemplateArgumentListInfo* TALI)
{ {
auto params = std::vector<CppSharp::CppParser::TemplateParameter>(); using namespace clang;
for(auto it = TPL->begin(); it != TPL->end(); ++it)
{
auto ND = *it;
auto TP = CppSharp::CppParser::TemplateParameter(); auto params = std::vector<CppSharp::CppParser::TemplateArgument>();
TP.Name = ND->getNameAsString();
for (size_t i = 0, e = TAL->size(); i < e; i++)
{
auto TA = TAL->get(i);
auto ArgLoc = TALI->operator[](i);
auto TP = WalkTemplateArgument(TA, &ArgLoc);
params.push_back(TP); params.push_back(TP);
} }
return params; return params;
} }
//-----------------------------------//
CppSharp::CppParser::TemplateArgument
Parser::WalkTemplateArgument(const clang::TemplateArgument& TA, clang::TemplateArgumentLoc* ArgLoc)
{
auto Arg = CppSharp::CppParser::TemplateArgument();
switch (TA.getKind())
{
case clang::TemplateArgument::Type:
{
Arg.Kind = CppSharp::CppParser::TemplateArgument::ArgumentKind::Type;
if (ArgLoc)
{
auto ArgTL = ArgLoc->getTypeSourceInfo()->getTypeLoc();
Arg.Type = GetQualifiedType(TA.getAsType(), WalkType(TA.getAsType(), &ArgTL));
}
else
{
Arg.Type = GetQualifiedType(TA.getAsType(), WalkType(TA.getAsType()));
}
break;
}
case clang::TemplateArgument::Declaration:
Arg.Kind = CppSharp::CppParser::TemplateArgument::ArgumentKind::Declaration;
Arg.Declaration = WalkDeclaration(TA.getAsDecl(), 0);
break;
case clang::TemplateArgument::NullPtr:
Arg.Kind = CppSharp::CppParser::TemplateArgument::ArgumentKind::NullPtr;
break;
case clang::TemplateArgument::Integral:
Arg.Kind = CppSharp::CppParser::TemplateArgument::ArgumentKind::Integral;
//Arg.Type = WalkType(TA.getIntegralType(), 0);
Arg.Integral = TA.getAsIntegral().getLimitedValue();
break;
case clang::TemplateArgument::Template:
Arg.Kind = CppSharp::CppParser::TemplateArgument::ArgumentKind::Template;
break;
case clang::TemplateArgument::TemplateExpansion:
Arg.Kind = CppSharp::CppParser::TemplateArgument::ArgumentKind::TemplateExpansion;
break;
case clang::TemplateArgument::Expression:
Arg.Kind = CppSharp::CppParser::TemplateArgument::ArgumentKind::Expression;
break;
case clang::TemplateArgument::Pack:
Arg.Kind = CppSharp::CppParser::TemplateArgument::ArgumentKind::Pack;
break;
}
return Arg;
}
//-----------------------------------//
FunctionTemplate* Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD) FunctionTemplate* Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD)
{ {
using namespace clang; using namespace clang;
@ -844,32 +984,27 @@ FunctionTemplate* Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD)
auto NS = GetNamespace(TD); auto NS = GetNamespace(TD);
assert(NS && "Expected a valid namespace"); assert(NS && "Expected a valid namespace");
auto FT = NS->FindFunctionTemplate((void*)TD); auto USR = GetDeclUSR(TD);
auto FT = NS->FindFunctionTemplate(USR);
if (FT != nullptr) if (FT != nullptr)
return FT; return FT;
auto Params = WalkTemplateParameterList(TD->getTemplateParameters());
CppSharp::CppParser::AST::Function* Function = nullptr; CppSharp::CppParser::AST::Function* Function = nullptr;
auto TemplatedDecl = TD->getTemplatedDecl(); auto TemplatedDecl = TD->getTemplatedDecl();
if (auto MD = dyn_cast<CXXMethodDecl>(TemplatedDecl)) if (auto MD = dyn_cast<CXXMethodDecl>(TemplatedDecl))
Function = WalkMethodCXX(MD); Function = WalkMethodCXX(MD, /*AddToClass=*/false);
else else
Function = WalkFunction(TemplatedDecl, /*IsDependent=*/true, Function = WalkFunction(TemplatedDecl, /*IsDependent=*/true,
/*AddToNamespace=*/false); /*AddToNamespace=*/false);
auto Name = TD->getNameAsString();
FT = NS->FindFunctionTemplate(Name, Params);
if (FT != nullptr && FT->TemplatedDecl == Function)
return FT;
FT = new FunctionTemplate(); FT = new FunctionTemplate();
HandleDeclaration(TD, FT); HandleDeclaration(TD, FT);
FT->Name = GetDeclName(TD);
FT->_Namespace = NS; FT->_Namespace = NS;
FT->TemplatedDecl = Function; FT->TemplatedDecl = Function;
FT->Parameters = Params; FT->Parameters = WalkTemplateParameterList(TD->getTemplateParameters());
NS->Templates.push_back(FT); NS->Templates.push_back(FT);
@ -878,6 +1013,23 @@ FunctionTemplate* Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD)
//-----------------------------------// //-----------------------------------//
CppSharp::CppParser::FunctionTemplateSpecialization*
Parser::WalkFunctionTemplateSpec(clang::FunctionTemplateSpecializationInfo* FTSI, CppSharp::CppParser::Function* Function)
{
using namespace clang;
auto FTS = new CppSharp::CppParser::FunctionTemplateSpecialization();
FTS->SpecializationKind = WalkTemplateSpecializationKind(FTSI->getTemplateSpecializationKind());
FTS->SpecializedFunction = Function;
if (auto TALI = FTSI->TemplateArgumentsAsWritten)
FTS->Arguments = WalkTemplateArgumentList(FTSI->TemplateArguments, TALI);
FTS->Template = WalkFunctionTemplate(FTSI->getTemplate());
FTS->Template->Specializations.push_back(FTS);
return FTS;
}
//-----------------------------------//
static CXXMethodKind GetMethodKindFromDecl(clang::DeclarationName Name) static CXXMethodKind GetMethodKindFromDecl(clang::DeclarationName Name)
{ {
using namespace clang; using namespace clang;
@ -921,13 +1073,13 @@ static CXXOperatorKind GetOperatorKindFromDecl(clang::DeclarationName Name)
return CXXOperatorKind::None; return CXXOperatorKind::None;
} }
Method* Parser::WalkMethodCXX(clang::CXXMethodDecl* MD) Method* Parser::WalkMethodCXX(clang::CXXMethodDecl* MD, bool AddToClass)
{ {
using namespace clang; using namespace clang;
// We could be in a redeclaration, so process the primary context. // We could be in a redeclaration, so process the primary context.
if (MD->getPrimaryContext() != MD) if (MD->getPrimaryContext() != MD)
return WalkMethodCXX(cast<CXXMethodDecl>(MD->getPrimaryContext())); return WalkMethodCXX(cast<CXXMethodDecl>(MD->getPrimaryContext()), AddToClass);
auto RD = MD->getParent(); auto RD = MD->getParent();
auto Decl = WalkDeclaration(RD, /*IgnoreSystemDecls=*/false); auto Decl = WalkDeclaration(RD, /*IgnoreSystemDecls=*/false);
@ -935,20 +1087,25 @@ Method* Parser::WalkMethodCXX(clang::CXXMethodDecl* MD)
auto Class = static_cast<CppSharp::CppParser::AST::Class*>(Decl); auto Class = static_cast<CppSharp::CppParser::AST::Class*>(Decl);
// Check for an already existing method that came from the same declaration. // Check for an already existing method that came from the same declaration.
auto USR = GetDeclUSR(MD);
for (unsigned I = 0, E = Class->Methods.size(); I != E; ++I) for (unsigned I = 0, E = Class->Methods.size(); I != E; ++I)
{ {
Method* Method = Class->Methods[I]; Method* Method = Class->Methods[I];
if (Method->OriginalPtr == MD) if (Method->USR == USR)
return Method; return Method;
}
for (unsigned I = 0, E = Class->Templates.size(); I != E; ++I)
{
Template* Template = Class->Templates[I];
if (Template->TemplatedDecl->USR == USR)
return static_cast<Method*>(Template->TemplatedDecl);
} }
DeclarationName Name = MD->getDeclName(); auto Method = new CppSharp::CppParser::Method();
Method* Method = new CppSharp::CppParser::Method();
HandleDeclaration(MD, Method); HandleDeclaration(MD, Method);
Method->Access = ConvertToAccess(MD->getAccess()); Method->Access = ConvertToAccess(MD->getAccess());
Method->MethodKind = GetMethodKindFromDecl(Name); Method->MethodKind = GetMethodKindFromDecl(MD->getDeclName());
Method->IsStatic = MD->isStatic(); Method->IsStatic = MD->isStatic();
Method->IsVirtual = MD->isVirtual(); Method->IsVirtual = MD->isVirtual();
Method->IsConst = MD->isConst(); Method->IsConst = MD->isConst();
@ -974,7 +1131,8 @@ Method* Parser::WalkMethodCXX(clang::CXXMethodDecl* MD)
Method->ConversionType = GetQualifiedType(CD->getConversionType(), ConvTy); Method->ConversionType = GetQualifiedType(CD->getConversionType(), ConvTy);
} }
Class->Methods.push_back(Method); if (AddToClass)
Class->Methods.push_back(Method);
return Method; return Method;
} }
@ -1539,71 +1697,35 @@ Type* Parser::WalkType(clang::QualType QualType, clang::TypeLoc* TL,
if (TS->isSugared()) if (TS->isSugared())
TST->Desugared = WalkType(TS->desugar()); TST->Desugared = WalkType(TS->desugar());
auto TypeLocClass = TL->getTypeLocClass(); if (TL && !TL->isNull())
if (TypeLocClass == TypeLoc::Qualified)
{
auto UTL = TL->getUnqualifiedLoc();
TL = &UTL;
}
else if (TypeLocClass == TypeLoc::Elaborated)
{
auto ETL = TL->getAs<ElaboratedTypeLoc>();
auto ITL = ETL.getNextTypeLoc();
TL = &ITL;
}
assert(TL->getTypeLocClass() == TypeLoc::TemplateSpecialization);
auto TSTL = TL->getAs<TemplateSpecializationTypeLoc>();
for (unsigned I = 0, E = TS->getNumArgs(); I != E; ++I)
{ {
const clang::TemplateArgument& TA = TS->getArg(I); auto TypeLocClass = TL->getTypeLocClass();
auto Arg = TemplateArgument(); if (TypeLocClass == TypeLoc::Qualified)
TemplateArgumentLoc ArgLoc;
ArgLoc = TSTL.getArgLoc(I);
switch(TA.getKind())
{
case clang::TemplateArgument::Type:
{ {
Arg.Kind = TemplateArgument::ArgumentKind::Type; auto UTL = TL->getUnqualifiedLoc();
TypeLoc ArgTL; TL = &UTL;
ArgTL = ArgLoc.getTypeSourceInfo()->getTypeLoc();
Arg.Type = GetQualifiedType(TA.getAsType(),
WalkType(TA.getAsType(), &ArgTL));
break;
} }
case clang::TemplateArgument::Declaration: else if (TypeLocClass == TypeLoc::Elaborated)
Arg.Kind = TemplateArgument::ArgumentKind::Declaration; {
Arg.Declaration = WalkDeclaration(TA.getAsDecl(), 0); auto ETL = TL->getAs<ElaboratedTypeLoc>();
break; auto ITL = ETL.getNextTypeLoc();
case clang::TemplateArgument::NullPtr: TL = &ITL;
Arg.Kind = TemplateArgument::ArgumentKind::NullPtr;
break;
case clang::TemplateArgument::Integral:
Arg.Kind = TemplateArgument::ArgumentKind::Integral;
//Arg.Type = WalkType(TA.getIntegralType(), 0);
Arg.Integral = TA.getAsIntegral().getLimitedValue();
break;
case clang::TemplateArgument::Template:
Arg.Kind = TemplateArgument::ArgumentKind::Template;
break;
case clang::TemplateArgument::TemplateExpansion:
Arg.Kind = TemplateArgument::ArgumentKind::TemplateExpansion;
break;
case clang::TemplateArgument::Expression:
Arg.Kind = TemplateArgument::ArgumentKind::Expression;
break;
case clang::TemplateArgument::Pack:
Arg.Kind = TemplateArgument::ArgumentKind::Pack;
break;
} }
TST->Arguments.push_back(Arg); assert(TL->getTypeLocClass() == TypeLoc::TemplateSpecialization);
} }
TemplateSpecializationTypeLoc *TSTL = 0;
if (TL && !TL->isNull())
{
auto TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>();
TSTL = &TSpecTL;
}
TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->getArgs(),
TS->getNumArgs());
TST->Arguments = WalkTemplateArgumentList(&TArgs, TSTL);
Ty = TST; Ty = TST;
break; break;
} }
@ -1611,10 +1733,33 @@ Type* Parser::WalkType(clang::QualType QualType, clang::TypeLoc* TL,
{ {
auto TP = Type->getAs<TemplateTypeParmType>(); auto TP = Type->getAs<TemplateTypeParmType>();
auto TPT = new TemplateParameterType(); auto TPT = new CppSharp::CppParser::TemplateParameterType();
if (auto Ident = TP->getIdentifier()) if (auto Ident = TP->getIdentifier())
TPT->Parameter.Name = Ident->getName(); TPT->Parameter.Name = Ident->getName();
if (TL && !TL->isNull())
{
auto TypeLocClass = TL->getTypeLocClass();
if (TypeLocClass == TypeLoc::Qualified)
{
auto UTL = TL->getUnqualifiedLoc();
TL = &UTL;
}
else if (TypeLocClass == TypeLoc::Elaborated)
{
auto ETL = TL->getAs<ElaboratedTypeLoc>();
auto ITL = ETL.getNextTypeLoc();
TL = &ITL;
}
assert(TL->getTypeLocClass() == TypeLoc::TemplateTypeParm);
auto TTTL = TL->getAs<TemplateTypeParmTypeLoc>();
TPT->Parameter = WalkTemplateParameter(TTTL.getDecl());
}
TPT->Depth = TP->getDepth();
TPT->Index = TP->getIndex();
TPT->IsParameterPack = TP->isParameterPack();
Ty = TPT; Ty = TPT;
break; break;
@ -1965,6 +2110,9 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, Function* F,
F->Parameters[Index++]->IsIndirect = I->info.isIndirect(); F->Parameters[Index++]->IsIndirect = I->info.isIndirect();
} }
} }
if (auto FTSI = FD->getTemplateSpecializationInfo())
F->SpecializationInfo = WalkFunctionTemplateSpec(FTSI, F);
} }
Function* Parser::WalkFunction(clang::FunctionDecl* FD, bool IsDependent, Function* Parser::WalkFunction(clang::FunctionDecl* FD, bool IsDependent,
@ -1977,9 +2125,8 @@ Function* Parser::WalkFunction(clang::FunctionDecl* FD, bool IsDependent,
auto NS = GetNamespace(FD); auto NS = GetNamespace(FD);
assert(NS && "Expected a valid namespace"); assert(NS && "Expected a valid namespace");
auto Name = FD->getNameAsString(); auto USR = GetDeclUSR(FD);
Function* F = NS->FindFunction(Name, /*Create=*/ false); auto F = NS->FindFunction(USR);
if (F != nullptr) if (F != nullptr)
return F; return F;
@ -2233,6 +2380,7 @@ void Parser::HandleDeclaration(clang::Decl* D, Declaration* Decl)
return; return;
Decl->OriginalPtr = (void*) D; Decl->OriginalPtr = (void*) D;
Decl->USR = GetDeclUSR(D);
if (Decl->PreprocessedEntities.empty() && !D->isImplicit()) if (Decl->PreprocessedEntities.empty() && !D->isImplicit())
{ {

6
src/CppParser/Parser.h

@ -75,14 +75,18 @@ protected:
WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl* CTS); WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl* CTS);
ClassTemplatePartialSpecialization* ClassTemplatePartialSpecialization*
WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl* CTS); WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl* CTS);
Method* WalkMethodCXX(clang::CXXMethodDecl* MD); Method* WalkMethodCXX(clang::CXXMethodDecl* MD, bool AddToClass = true);
Field* WalkFieldCXX(clang::FieldDecl* FD, Class* Class); Field* WalkFieldCXX(clang::FieldDecl* FD, Class* Class);
ClassTemplate* WalkClassTemplate(clang::ClassTemplateDecl* TD); ClassTemplate* WalkClassTemplate(clang::ClassTemplateDecl* TD);
FunctionTemplate* WalkFunctionTemplate(clang::FunctionTemplateDecl* TD); FunctionTemplate* WalkFunctionTemplate(clang::FunctionTemplateDecl* TD);
FunctionTemplateSpecialization* WalkFunctionTemplateSpec(clang::FunctionTemplateSpecializationInfo* FTS, Function* Function);
Variable* WalkVariable(clang::VarDecl* VD); Variable* WalkVariable(clang::VarDecl* VD);
RawComment* WalkRawComment(const clang::RawComment* RC); RawComment* WalkRawComment(const clang::RawComment* RC);
Type* WalkType(clang::QualType QualType, clang::TypeLoc* TL = 0, Type* WalkType(clang::QualType QualType, clang::TypeLoc* TL = 0,
bool DesugarType = false); bool DesugarType = false);
TemplateArgument WalkTemplateArgument(const clang::TemplateArgument& TA, clang::TemplateArgumentLoc* ArgLoc);
std::vector<TemplateArgument> WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, clang::TemplateSpecializationTypeLoc* TSTL);
std::vector<TemplateArgument> WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, const clang::ASTTemplateArgumentListInfo* TSTL);
void WalkVTable(clang::CXXRecordDecl* RD, Class* C); void WalkVTable(clang::CXXRecordDecl* RD, Class* C);
VTableLayout WalkVTableLayout(const clang::VTableLayout& VTLayout); VTableLayout WalkVTableLayout(const clang::VTableLayout& VTLayout);
VTableComponent WalkVTableComponent(const clang::VTableComponent& Component); VTableComponent WalkVTableComponent(const clang::VTableComponent& Component);

59
src/Generator.Tests/AST/TestAST.cs

@ -19,7 +19,7 @@ namespace CppSharp.Generator.Tests.AST
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
ParseLibrary("AST.h"); ParseLibrary("AST.h", "ASTExtensions.h");
passBuilder = new PassBuilder<TranslationUnitPass>(Driver); passBuilder = new PassBuilder<TranslationUnitPass>(Driver);
} }
@ -168,5 +168,62 @@ namespace CppSharp.Generator.Tests.AST
Assert.NotNull(@enum); Assert.NotNull(@enum);
Assert.IsTrue(@enum.ItemsByName.ContainsKey("TestItemByName")); Assert.IsTrue(@enum.ItemsByName.ContainsKey("TestItemByName"));
} }
[Test]
public void TestASTFunctionTemplates()
{
var @class = AstContext.FindClass("TestTemplateFunctions").FirstOrDefault();
Assert.IsNotNull(@class, "Couldn't find TestTemplateFunctions class.");
Assert.AreEqual(6, @class.Templates.Count);
var twoParamMethodTemplate = @class.Templates.OfType<FunctionTemplate>()
.FirstOrDefault(t => t.Name == "MethodTemplateWithTwoTypeParameter");
Assert.IsNotNull(twoParamMethodTemplate);
Assert.AreEqual(2, twoParamMethodTemplate.Parameters.Count);
Assert.AreEqual("T", twoParamMethodTemplate.Parameters[0].Name);
Assert.AreEqual("S", twoParamMethodTemplate.Parameters[1].Name);
Assert.IsTrue(twoParamMethodTemplate.Parameters[0].IsTypeParameter);
Assert.IsTrue(twoParamMethodTemplate.Parameters[1].IsTypeParameter);
var twoParamMethod = twoParamMethodTemplate.TemplatedFunction as Method;
Assert.IsNotNull(twoParamMethod);
Assert.IsInstanceOf<TemplateParameterType>(twoParamMethod.Parameters[0].Type);
Assert.IsInstanceOf<TemplateParameterType>(twoParamMethod.Parameters[1].Type);
Assert.AreEqual(twoParamMethodTemplate.Parameters[0],
((TemplateParameterType)twoParamMethod.Parameters[0].Type).Parameter);
Assert.AreEqual(twoParamMethodTemplate.Parameters[1],
((TemplateParameterType)twoParamMethod.Parameters[1].Type).Parameter);
Assert.AreEqual(0, ((TemplateParameterType)twoParamMethod.Parameters[0].Type).Index);
Assert.AreEqual(1, ((TemplateParameterType)twoParamMethod.Parameters[1].Type).Index);
}
[Test]
public void TestASTClassTemplates()
{
var template = AstContext.TranslationUnits
.SelectMany(u => u.Templates.OfType<ClassTemplate>())
.FirstOrDefault(t => t.Name == "TestTemplateClass");
Assert.IsNotNull(template, "Couldn't find TestTemplateClass class.");
Assert.AreEqual(1, template.Parameters.Count);
var templateTypeParameter = template.Parameters[0];
Assert.AreEqual("T", templateTypeParameter.Name);
var ctor = template.TemplatedClass.Constructors
.FirstOrDefault(c => c.Parameters.Count == 1 && c.Parameters[0].Name == "v");
Assert.IsNotNull(ctor);
var paramType = ctor.Parameters[0].Type as TemplateParameterType;
Assert.IsNotNull(paramType);
Assert.AreEqual(templateTypeParameter, paramType.Parameter);
Assert.AreEqual(3, template.Specializations.Count);
Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[0].SpecializationKind);
Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[1].SpecializationKind);
Assert.AreEqual(TemplateSpecializationKind.Undeclared, template.Specializations[2].SpecializationKind);
var typeDef = AstContext.FindTypedef("TestTemplateClassInt").FirstOrDefault();
Assert.IsNotNull(typeDef, "Couldn't find TestTemplateClassInt typedef.");
var integerInst = typeDef.Type as TemplateSpecializationType;
Assert.AreEqual(1, integerInst.Arguments.Count);
var intArgument = integerInst.Arguments[0];
Assert.AreEqual(new BuiltinType(PrimitiveType.Int32), intArgument.Type.Type);
Class classTemplate;
Assert.IsTrue(typeDef.Type.TryGetClass(out classTemplate));
Assert.AreEqual(classTemplate, template.TemplatedClass);
}
} }
} }

4
src/Generator.Tests/ASTTestFixture.cs

@ -10,7 +10,7 @@ namespace CppSharp.Generator.Tests
protected DriverOptions Options; protected DriverOptions Options;
protected ASTContext AstContext; protected ASTContext AstContext;
protected void ParseLibrary(string file) protected void ParseLibrary(params string[] files)
{ {
Options = new DriverOptions(); Options = new DriverOptions();
@ -22,7 +22,7 @@ namespace CppSharp.Generator.Tests
Options.addIncludeDirs(testsPath); Options.addIncludeDirs(testsPath);
#endif #endif
Options.Headers.Add(file); Options.Headers.AddRange(files);
Driver = new Driver(Options, new TextDiagnosticPrinter()); Driver = new Driver(Options, new TextDiagnosticPrinter());
if (!Driver.ParseCode()) if (!Driver.ParseCode())

2
src/Generator/Generator.cs

@ -71,7 +71,7 @@ namespace CppSharp.Generators
if (!unit.IsGenerated || !unit.HasDeclarations) if (!unit.IsGenerated || !unit.HasDeclarations)
continue; continue;
if (unit.IsSystemHeader) if (unit.IsSystemHeader || !unit.IsValid)
continue; continue;
var templates = Generate(unit); var templates = Generate(unit);

9
src/Generator/Passes/CleanUnitPass.cs

@ -18,9 +18,12 @@ namespace CppSharp.Passes
// Try to get an include path that works from the original include // Try to get an include path that works from the original include
// directories paths. // directories paths.
if (unit.IsValid)
unit.IncludePath = GetIncludePath(unit.FilePath); {
return true; unit.IncludePath = GetIncludePath(unit.FilePath);
return true;
}
return false;
} }
string GetIncludePath(string filePath) string GetIncludePath(string filePath)

386
src/Parser/Parser.cpp

@ -27,6 +27,7 @@
#include <clang/Sema/SemaConsumer.h> #include <clang/Sema/SemaConsumer.h>
#include <clang/Frontend/Utils.h> #include <clang/Frontend/Utils.h>
#include <clang/Driver/Util.h> #include <clang/Driver/Util.h>
#include <clang/Index/USRGeneration.h>
#include <CodeGen/CodeGenModule.h> #include <CodeGen/CodeGenModule.h>
#include <CodeGen/CodeGenTypes.h> #include <CodeGen/CodeGenTypes.h>
#include <CodeGen/TargetInfo.h> #include <CodeGen/TargetInfo.h>
@ -292,6 +293,15 @@ static std::string GetTagDeclName(const clang::TagDecl* D)
return GetDeclName(D); return GetDeclName(D);
} }
static std::string GetDeclUSR(const clang::Decl* D)
{
using namespace clang;
SmallString<128> usr;
if (!index::generateUSRForDecl(D, usr))
return usr.str();
return "<invalid>";
}
static clang::Decl* GetPreviousDeclInContext(const clang::Decl* D) static clang::Decl* GetPreviousDeclInContext(const clang::Decl* D)
{ {
assert(!D->getLexicalDeclContext()->decls_empty()); assert(!D->getLexicalDeclContext()->decls_empty());
@ -725,26 +735,33 @@ WalkTemplateSpecializationKind(clang::TemplateSpecializationKind Kind)
CppSharp::AST::ClassTemplateSpecialization^ CppSharp::AST::ClassTemplateSpecialization^
Parser::WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl* CTS) Parser::WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl* CTS)
{ {
using namespace clang;
using namespace clix;
auto CT = WalkClassTemplate(CTS->getSpecializedTemplate()); auto CT = WalkClassTemplate(CTS->getSpecializedTemplate());
auto Spec = CT->FindSpecialization(System::IntPtr(CTS)); auto USR = marshalString<Encoding::E_UTF8>(GetDeclUSR(CTS));
if (Spec != nullptr) auto TS = CT->FindSpecializationByUSR(USR);
return Spec; if (TS != nullptr)
return TS;
auto TS = gcnew CppSharp::AST::ClassTemplateSpecialization(); TS = gcnew CppSharp::AST::ClassTemplateSpecialization();
HandleDeclaration(CTS, TS); HandleDeclaration(CTS, TS);
TS->Name = clix::marshalString<clix::E_UTF8>(CTS->getName());
auto NS = GetNamespace(CTS); auto NS = GetNamespace(CTS);
assert(NS && "Expected a valid namespace"); assert(NS && "Expected a valid namespace");
TS->Namespace = NS; TS->Namespace = NS;
TS->Name = clix::marshalString<clix::E_UTF8>(GetDeclName(CTS));
TS->TemplatedDecl = CT; TS->TemplatedDecl = CT;
TS->SpecializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind()); TS->SpecializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind());
auto &TAL = CTS->getTemplateArgs();
if (auto TSI = CTS->getTypeAsWritten())
{
auto TL = TSI->getTypeLoc();
auto TSL = TL.getAs<TemplateSpecializationTypeLoc>();
TS->Arguments = WalkTemplateArgumentList(&TAL, &TSL);
}
CT->Specializations->Add(TS); CT->Specializations->Add(TS);
// TODO: Parse the template argument list
if (CTS->isCompleteDefinition()) if (CTS->isCompleteDefinition())
WalkRecordCXX(CTS, TS); WalkRecordCXX(CTS, TS);
@ -756,15 +773,19 @@ Parser::WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl*
CppSharp::AST::ClassTemplatePartialSpecialization^ CppSharp::AST::ClassTemplatePartialSpecialization^
Parser::WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl* CTS) Parser::WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl* CTS)
{ {
using namespace clang;
using namespace clix;
auto CT = WalkClassTemplate(CTS->getSpecializedTemplate()); auto CT = WalkClassTemplate(CTS->getSpecializedTemplate());
auto Spec = CT->FindPartialSpecialization(System::IntPtr(CTS)); auto USR = marshalString<Encoding::E_UTF8>(GetDeclUSR(CTS));
if (Spec != nullptr) auto TS = CT->FindPartialSpecializationByUSR(USR);
return Spec; if (TS != nullptr)
return TS;
auto TS = gcnew CppSharp::AST::ClassTemplatePartialSpecialization(); TS = gcnew CppSharp::AST::ClassTemplatePartialSpecialization();
HandleDeclaration(CTS, TS); HandleDeclaration(CTS, TS);
TS->Name = clix::marshalString<clix::E_UTF8>(CTS->getName()); TS->Name = clix::marshalString<clix::E_UTF8>(GetDeclName(CTS));
auto NS = GetNamespace(CTS); auto NS = GetNamespace(CTS);
assert(NS && "Expected a valid namespace"); assert(NS && "Expected a valid namespace");
@ -772,10 +793,15 @@ Parser::WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecia
TS->TemplatedDecl = CT; TS->TemplatedDecl = CT;
TS->SpecializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind()); TS->SpecializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind());
auto &TAL = CTS->getTemplateArgs();
if (auto TSI = CTS->getTypeAsWritten())
{
auto TL = TSI->getTypeLoc();
auto TSL = TL.getAs<TemplateSpecializationTypeLoc>();
TS->Arguments = WalkTemplateArgumentList(&TAL, &TSL);
}
CT->Specializations->Add(TS); CT->Specializations->Add(TS);
// TODO: Parse the template argument list
if (CTS->isCompleteDefinition()) if (CTS->isCompleteDefinition())
WalkRecordCXX(CTS, TS); WalkRecordCXX(CTS, TS);
@ -784,6 +810,52 @@ Parser::WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecia
//-----------------------------------// //-----------------------------------//
CppSharp::AST::TemplateParameter
WalkTemplateParameter(const clang::NamedDecl* D)
{
using namespace clang;
using namespace clix;
auto TP = CppSharp::AST::TemplateParameter();
if (D == nullptr)
return TP;
TP.Name = marshalString<E_UTF8>(GetDeclName(D));
switch (D->getKind())
{
case Decl::TemplateTypeParm:
{
auto TTPD = cast<TemplateTypeParmDecl>(D);
TP.IsTypeParameter = true;
break;
}
default:
break;
}
return TP;
}
//-----------------------------------//
static List<CppSharp::AST::TemplateParameter>^
WalkTemplateParameterList(const clang::TemplateParameterList* TPL)
{
using namespace clang;
auto params = gcnew List<CppSharp::AST::TemplateParameter>();
for (auto it = TPL->begin(); it != TPL->end(); ++it)
{
auto ND = *it;
auto TP = WalkTemplateParameter(ND);
params->Add(TP);
}
return params;
}
//-----------------------------------//
CppSharp::AST::ClassTemplate^ Parser::WalkClassTemplate(clang::ClassTemplateDecl* TD) CppSharp::AST::ClassTemplate^ Parser::WalkClassTemplate(clang::ClassTemplateDecl* TD)
{ {
using namespace clang; using namespace clang;
@ -792,52 +864,128 @@ CppSharp::AST::ClassTemplate^ Parser::WalkClassTemplate(clang::ClassTemplateDecl
auto NS = GetNamespace(TD); auto NS = GetNamespace(TD);
assert(NS && "Expected a valid namespace"); assert(NS && "Expected a valid namespace");
auto CT = NS->FindClassTemplate(System::IntPtr(TD)); auto USR = marshalString<Encoding::E_UTF8>(GetDeclUSR(TD));
auto CT = NS->FindClassTemplateByUSR(USR);
if (CT != nullptr) if (CT != nullptr)
return CT; return CT;
CT = gcnew CppSharp::AST::ClassTemplate(); CT = gcnew CppSharp::AST::ClassTemplate();
HandleDeclaration(TD, CT); HandleDeclaration(TD, CT);
CT->Name = marshalString<E_UTF8>(GetDeclName(TD));
CT->Namespace = NS; CT->Namespace = NS;
NS->Templates->Add(CT); NS->Templates->Add(CT);
CT->TemplatedDecl = WalkRecordCXX(TD->getTemplatedDecl()); CT->TemplatedDecl = WalkRecordCXX(TD->getTemplatedDecl());
CT->Parameters = WalkTemplateParameterList(TD->getTemplateParameters());
auto TPL = TD->getTemplateParameters(); return CT;
for(auto it = TPL->begin(); it != TPL->end(); ++it) }
{
auto ND = *it; //-----------------------------------//
List<CppSharp::AST::TemplateArgument>^
Parser::WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL,
clang::TemplateSpecializationTypeLoc* TSTL)
{
using namespace clang;
auto TP = CppSharp::AST::TemplateParameter(); auto params = gcnew List<CppSharp::AST::TemplateArgument>();
TP.Name = clix::marshalString<clix::E_UTF8>(ND->getNameAsString());
CT->Parameters->Add(TP); for (size_t i = 0, e = TAL->size(); i < e; i++)
{
auto TA = TAL->get(i);
TemplateArgumentLoc *ArgLoc = 0;
if (TSTL && i < TSTL->getNumArgs())
{
auto TAL = TSTL->getArgLoc(i);
ArgLoc = &TAL;
}
auto Arg = WalkTemplateArgument(TA, ArgLoc);
params->Add(Arg);
} }
return CT; return params;
} }
//-----------------------------------// //-----------------------------------//
static List<CppSharp::AST::TemplateParameter>^ List<CppSharp::AST::TemplateArgument>^
WalkTemplateParameterList(const clang::TemplateParameterList* TPL) Parser::WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL,
const clang::ASTTemplateArgumentListInfo* TALI)
{ {
auto params = gcnew List<CppSharp::AST::TemplateParameter>(); using namespace clang;
for(auto it = TPL->begin(); it != TPL->end(); ++it)
{
auto ND = *it;
auto TP = CppSharp::AST::TemplateParameter(); auto params = gcnew List<CppSharp::AST::TemplateArgument>();
TP.Name = clix::marshalString<clix::E_UTF8>(ND->getNameAsString());
for (size_t i = 0, e = TAL->size(); i < e; i++)
{
auto TA = TAL->get(i);
auto ArgLoc = TALI->operator[](i);
auto TP = WalkTemplateArgument(TA, &ArgLoc);
params->Add(TP); params->Add(TP);
} }
return params; return params;
} }
//-----------------------------------//
CppSharp::AST::TemplateArgument
Parser::WalkTemplateArgument(const clang::TemplateArgument& TA, clang::TemplateArgumentLoc* ArgLoc)
{
using namespace clang;
using namespace clix;
auto Arg = CppSharp::AST::TemplateArgument();
switch (TA.getKind())
{
case TemplateArgument::Type:
{
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Type;
if (ArgLoc)
{
auto ArgTL = ArgLoc->getTypeSourceInfo()->getTypeLoc();
Arg.Type = GetQualifiedType(TA.getAsType(), WalkType(TA.getAsType(), &ArgTL));
}
else
{
Arg.Type = GetQualifiedType(TA.getAsType(), WalkType(TA.getAsType()));
}
break;
}
case TemplateArgument::Declaration:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Declaration;
Arg.Declaration = WalkDeclaration(TA.getAsDecl(), 0);
break;
case TemplateArgument::NullPtr:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::NullPtr;
break;
case TemplateArgument::Integral:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Integral;
//Arg.Type = WalkType(TA.getIntegralType(), 0);
Arg.Integral = TA.getAsIntegral().getLimitedValue();
break;
case TemplateArgument::Template:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Template;
break;
case TemplateArgument::TemplateExpansion:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::TemplateExpansion;
break;
case TemplateArgument::Expression:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Expression;
break;
case TemplateArgument::Pack:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Pack;
break;
}
return Arg;
}
//-----------------------------------//
CppSharp::AST::FunctionTemplate^ CppSharp::AST::FunctionTemplate^
Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD) Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD)
{ {
@ -847,32 +995,27 @@ Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD)
auto NS = GetNamespace(TD); auto NS = GetNamespace(TD);
assert(NS && "Expected a valid namespace"); assert(NS && "Expected a valid namespace");
auto FT = NS->FindFunctionTemplate(System::IntPtr(TD)); auto USR = marshalString<Encoding::E_UTF8>(GetDeclUSR(TD));
auto FT = NS->FindFunctionTemplateByUSR(USR);
if (FT != nullptr) if (FT != nullptr)
return FT; return FT;
auto Params = WalkTemplateParameterList(TD->getTemplateParameters());
CppSharp::AST::Function^ Function = nullptr; CppSharp::AST::Function^ Function = nullptr;
auto TemplatedDecl = TD->getTemplatedDecl(); auto TemplatedDecl = TD->getTemplatedDecl();
if (auto MD = dyn_cast<CXXMethodDecl>(TemplatedDecl)) if (auto MD = dyn_cast<CXXMethodDecl>(TemplatedDecl))
Function = WalkMethodCXX(MD); Function = WalkMethodCXX(MD, /*AddToClass=*/false);
else else
Function = WalkFunction(TemplatedDecl, /*IsDependent=*/true, Function = WalkFunction(TemplatedDecl, /*IsDependent=*/true,
/*AddToNamespace=*/false); /*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->Name = marshalString<E_UTF8>(GetDeclName(TD));
FT->Namespace = NS; FT->Namespace = NS;
FT->TemplatedDecl = Function; FT->TemplatedDecl = Function;
FT->Parameters = Params; FT->Parameters = WalkTemplateParameterList(TD->getTemplateParameters());
NS->Templates->Add(FT); NS->Templates->Add(FT);
@ -881,6 +1024,24 @@ Parser::WalkFunctionTemplate(clang::FunctionTemplateDecl* TD)
//-----------------------------------// //-----------------------------------//
CppSharp::AST::FunctionTemplateSpecialization^
Parser::WalkFunctionTemplateSpec(clang::FunctionTemplateSpecializationInfo* FTSI, CppSharp::AST::Function^ Function)
{
using namespace clang;
auto FTS = gcnew CppSharp::AST::FunctionTemplateSpecialization();
FTS->SpecializationKind = WalkTemplateSpecializationKind(FTSI->getTemplateSpecializationKind());
FTS->SpecializedFunction = Function;
if (auto TALI = FTSI->TemplateArgumentsAsWritten)
FTS->Arguments = WalkTemplateArgumentList(FTSI->TemplateArguments, TALI);
FTS->Template = WalkFunctionTemplate(FTSI->getTemplate());
FTS->Template->Specializations->Add(FTS);
return FTS;
}
//-----------------------------------//
static CppSharp::AST::CXXMethodKind GetMethodKindFromDecl(clang::DeclarationName Name) static CppSharp::AST::CXXMethodKind GetMethodKindFromDecl(clang::DeclarationName Name)
{ {
using namespace clang; using namespace clang;
@ -924,13 +1085,14 @@ static CppSharp::AST::CXXOperatorKind GetOperatorKindFromDecl(clang::Declaration
return CppSharp::AST::CXXOperatorKind::None; return CppSharp::AST::CXXOperatorKind::None;
} }
CppSharp::AST::Method^ Parser::WalkMethodCXX(clang::CXXMethodDecl* MD) CppSharp::AST::Method^ Parser::WalkMethodCXX(clang::CXXMethodDecl* MD, bool AddToClass)
{ {
using namespace clang; using namespace clang;
using namespace clix;
// We could be in a redeclaration, so process the primary context. // We could be in a redeclaration, so process the primary context.
if (MD->getPrimaryContext() != MD) if (MD->getPrimaryContext() != MD)
return WalkMethodCXX(cast<CXXMethodDecl>(MD->getPrimaryContext())); return WalkMethodCXX(cast<CXXMethodDecl>(MD->getPrimaryContext()), AddToClass);
auto RD = MD->getParent(); auto RD = MD->getParent();
auto Decl = WalkDeclaration(RD, /*IgnoreSystemDecls=*/false); auto Decl = WalkDeclaration(RD, /*IgnoreSystemDecls=*/false);
@ -938,15 +1100,12 @@ CppSharp::AST::Method^ Parser::WalkMethodCXX(clang::CXXMethodDecl* MD)
auto Class = safe_cast<CppSharp::AST::Class^>(Decl); auto Class = safe_cast<CppSharp::AST::Class^>(Decl);
// Check for an already existing method that came from the same declaration. // Check for an already existing method that came from the same declaration.
for each (CppSharp::AST::Method^ Method in Class->Methods) auto USR = marshalString<Encoding::E_UTF8>(GetDeclUSR(MD));
{ auto Method = Class->FindMethodByUSR(USR);
if (Method->OriginalPtr.ToPointer() == MD) if (Method != nullptr)
return Method; return Method;
}
DeclarationName Name = MD->getDeclName();
CppSharp::AST::Method^ Method = gcnew CppSharp::AST::Method(); Method = gcnew CppSharp::AST::Method();
HandleDeclaration(MD, Method); HandleDeclaration(MD, Method);
Method->Access = ConvertToAccess(MD->getAccess()); Method->Access = ConvertToAccess(MD->getAccess());
@ -957,7 +1116,7 @@ CppSharp::AST::Method^ Parser::WalkMethodCXX(clang::CXXMethodDecl* MD)
WalkFunction(MD, Method); WalkFunction(MD, Method);
Method->Kind = GetMethodKindFromDecl(Name); Method->Kind = GetMethodKindFromDecl(MD->getDeclName());
if (const CXXConstructorDecl* CD = dyn_cast<CXXConstructorDecl>(MD)) if (const CXXConstructorDecl* CD = dyn_cast<CXXConstructorDecl>(MD))
{ {
@ -977,7 +1136,8 @@ CppSharp::AST::Method^ Parser::WalkMethodCXX(clang::CXXMethodDecl* MD)
Method->ConversionType = GetQualifiedType(CD->getConversionType(), ConvTy); Method->ConversionType = GetQualifiedType(CD->getConversionType(), ConvTy);
} }
Class->Methods->Add(Method); if (AddToClass)
Class->Methods->Add(Method);
return Method; return Method;
} }
@ -1555,71 +1715,35 @@ CppSharp::AST::Type^ Parser::WalkType(clang::QualType QualType, clang::TypeLoc*
if (TS->isSugared()) if (TS->isSugared())
TST->Desugared = WalkType(TS->desugar()); TST->Desugared = WalkType(TS->desugar());
auto TypeLocClass = TL->getTypeLocClass(); if (TL && !TL->isNull())
if (TypeLocClass == TypeLoc::Qualified)
{
auto UTL = TL->getUnqualifiedLoc();
TL = &UTL;
}
else if (TypeLocClass == TypeLoc::Elaborated)
{
auto ETL = TL->getAs<ElaboratedTypeLoc>();
auto ITL = ETL.getNextTypeLoc();
TL = &ITL;
}
assert(TL->getTypeLocClass() == TypeLoc::TemplateSpecialization);
auto TSTL = TL->getAs<TemplateSpecializationTypeLoc>();
for (unsigned I = 0, E = TS->getNumArgs(); I != E; ++I)
{ {
const TemplateArgument& TA = TS->getArg(I); auto TypeLocClass = TL->getTypeLocClass();
auto Arg = CppSharp::AST::TemplateArgument(); if (TypeLocClass == TypeLoc::Qualified)
TemplateArgumentLoc ArgLoc;
ArgLoc = TSTL.getArgLoc(I);
switch(TA.getKind())
{
case TemplateArgument::Type:
{ {
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Type; auto UTL = TL->getUnqualifiedLoc();
TypeLoc ArgTL; TL = &UTL;
ArgTL = ArgLoc.getTypeSourceInfo()->getTypeLoc();
Arg.Type = GetQualifiedType(TA.getAsType(),
WalkType(TA.getAsType(), &ArgTL));
break;
} }
case TemplateArgument::Declaration: else if (TypeLocClass == TypeLoc::Elaborated)
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Declaration; {
Arg.Declaration = WalkDeclaration(TA.getAsDecl(), 0); auto ETL = TL->getAs<ElaboratedTypeLoc>();
break; auto ITL = ETL.getNextTypeLoc();
case TemplateArgument::NullPtr: TL = &ITL;
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::NullPtr;
break;
case TemplateArgument::Integral:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Integral;
//Arg.Type = WalkType(TA.getIntegralType(), 0);
Arg.Integral = TA.getAsIntegral().getLimitedValue();
break;
case TemplateArgument::Template:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Template;
break;
case TemplateArgument::TemplateExpansion:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::TemplateExpansion;
break;
case TemplateArgument::Expression:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Expression;
break;
case TemplateArgument::Pack:
Arg.Kind = CppSharp::AST::TemplateArgument::ArgumentKind::Pack;
break;
} }
TST->Arguments->Add(Arg); assert(TL->getTypeLocClass() == TypeLoc::TemplateSpecialization);
}
TemplateSpecializationTypeLoc *TSTL = 0;
if (TL && !TL->isNull())
{
auto TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>();
TSTL = &TSpecTL;
} }
TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->getArgs(),
TS->getNumArgs());
TST->Arguments = WalkTemplateArgumentList(&TArgs, TSTL);
Ty = TST; Ty = TST;
break; break;
} }
@ -1631,6 +1755,29 @@ CppSharp::AST::Type^ Parser::WalkType(clang::QualType QualType, clang::TypeLoc*
if (auto Ident = TP->getIdentifier()) if (auto Ident = TP->getIdentifier())
TPT->Parameter.Name = marshalString<E_UTF8>(Ident->getName()); TPT->Parameter.Name = marshalString<E_UTF8>(Ident->getName());
if (TL && !TL->isNull())
{
auto TypeLocClass = TL->getTypeLocClass();
if (TypeLocClass == TypeLoc::Qualified)
{
auto UTL = TL->getUnqualifiedLoc();
TL = &UTL;
}
else if (TypeLocClass == TypeLoc::Elaborated)
{
auto ETL = TL->getAs<ElaboratedTypeLoc>();
auto ITL = ETL.getNextTypeLoc();
TL = &ITL;
}
assert(TL->getTypeLocClass() == TypeLoc::TemplateTypeParm);
auto TTTL = TL->getAs<TemplateTypeParmTypeLoc>();
TPT->Parameter = WalkTemplateParameter(TTTL.getDecl());
}
TPT->Depth = TP->getDepth();
TPT->Index = TP->getIndex();
TPT->IsParameterPack = TP->isParameterPack();
Ty = TPT; Ty = TPT;
break; break;
@ -1983,6 +2130,9 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, CppSharp::AST::Function^ F,
F->Parameters[Index++]->IsIndirect = I->info.isIndirect(); F->Parameters[Index++]->IsIndirect = I->info.isIndirect();
} }
} }
if (auto FTSI = FD->getTemplateSpecializationInfo())
F->SpecializationInfo = WalkFunctionTemplateSpec(FTSI, F);
} }
CppSharp::AST::Function^ Parser::WalkFunction(clang::FunctionDecl* FD, bool IsDependent, CppSharp::AST::Function^ Parser::WalkFunction(clang::FunctionDecl* FD, bool IsDependent,
@ -1996,9 +2146,8 @@ CppSharp::AST::Function^ Parser::WalkFunction(clang::FunctionDecl* FD, bool IsDe
auto NS = GetNamespace(FD); auto NS = GetNamespace(FD);
assert(NS && "Expected a valid namespace"); assert(NS && "Expected a valid namespace");
auto Name = marshalString<E_UTF8>(FD->getNameAsString()); auto USR = marshalString<Encoding::E_UTF8>(GetDeclUSR(FD));
CppSharp::AST::Function^ F = NS->FindFunction(Name, /*Create=*/ false); auto F = NS->FindFunctionByUSR(USR);
if (F != nullptr) if (F != nullptr)
return F; return F;
@ -2254,6 +2403,7 @@ void Parser::HandleDeclaration(clang::Decl* D, CppSharp::AST::Declaration^ Decl)
return; return;
Decl->OriginalPtr = System::IntPtr(D); Decl->OriginalPtr = System::IntPtr(D);
Decl->USR = clix::marshalString<clix::Encoding::E_UTF8>(GetDeclUSR(D));
if (Decl->PreprocessedEntities->Count == 0 && !D->isImplicit()) if (Decl->PreprocessedEntities->Count == 0 && !D->isImplicit())
{ {

6
src/Parser/Parser.h

@ -73,15 +73,19 @@ protected:
WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl* CTS); WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl* CTS);
CppSharp::AST::ClassTemplatePartialSpecialization^ CppSharp::AST::ClassTemplatePartialSpecialization^
WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl* CTS); WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl* CTS);
CppSharp::AST::Method^ WalkMethodCXX(clang::CXXMethodDecl* MD); CppSharp::AST::Method^ WalkMethodCXX(clang::CXXMethodDecl* MD, bool AddToClass = true);
CppSharp::AST::Field^ WalkFieldCXX(clang::FieldDecl* FD, CppSharp::AST::Class^ Class); CppSharp::AST::Field^ WalkFieldCXX(clang::FieldDecl* FD, CppSharp::AST::Class^ Class);
CppSharp::AST::ClassTemplate^ Parser::WalkClassTemplate(clang::ClassTemplateDecl* TD); CppSharp::AST::ClassTemplate^ Parser::WalkClassTemplate(clang::ClassTemplateDecl* TD);
CppSharp::AST::FunctionTemplate^ Parser::WalkFunctionTemplate( CppSharp::AST::FunctionTemplate^ Parser::WalkFunctionTemplate(
clang::FunctionTemplateDecl* TD); clang::FunctionTemplateDecl* TD);
CppSharp::AST::FunctionTemplateSpecialization^ WalkFunctionTemplateSpec(clang::FunctionTemplateSpecializationInfo* FTS, CppSharp::AST::Function^ Function);
CppSharp::AST::Variable^ WalkVariable(clang::VarDecl* VD); CppSharp::AST::Variable^ WalkVariable(clang::VarDecl* VD);
CppSharp::AST::RawComment^ WalkRawComment(const clang::RawComment* RC); CppSharp::AST::RawComment^ WalkRawComment(const clang::RawComment* RC);
CppSharp::AST::Type^ WalkType(clang::QualType QualType, clang::TypeLoc* TL = 0, CppSharp::AST::Type^ WalkType(clang::QualType QualType, clang::TypeLoc* TL = 0,
bool DesugarType = false); bool DesugarType = false);
CppSharp::AST::TemplateArgument WalkTemplateArgument(const clang::TemplateArgument& TA, clang::TemplateArgumentLoc* ArgLoc);
List<CppSharp::AST::TemplateArgument>^ WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, clang::TemplateSpecializationTypeLoc* TSTL);
List<CppSharp::AST::TemplateArgument>^ WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, const clang::ASTTemplateArgumentListInfo* TSTL);
CppSharp::AST::QualifiedType^ WalkQualifiedType(clang::TypeSourceInfo* TSI); CppSharp::AST::QualifiedType^ WalkQualifiedType(clang::TypeSourceInfo* TSI);
void WalkVTable(clang::CXXRecordDecl* RD, CppSharp::AST::Class^ C); void WalkVTable(clang::CXXRecordDecl* RD, CppSharp::AST::Class^ C);
CppSharp::AST::VTableLayout^ WalkVTableLayout(const clang::VTableLayout& VTLayout); CppSharp::AST::VTableLayout^ WalkVTableLayout(const clang::VTableLayout& VTLayout);

36
tests/Native/AST.h

@ -22,4 +22,38 @@ namespace Math
} }
// Tests Enum.ItemByName // Tests Enum.ItemByName
enum TestASTEnumItemByName { TestItemByName }; enum TestASTEnumItemByName { TestItemByName };
// Tests class templates
template<typename T>
class TestTemplateClass
{
public:
TestTemplateClass(T v);
T Identity(T x);
T value;
};
// Tests function templates
class TestTemplateFunctions
{
public:
template<typename T> T Identity(T x) { return x; }
template<int N> void Ignore() { };
template<typename T, typename S> void MethodTemplateWithTwoTypeParameter(T t, S s) { };
template<typename T> void Ignore(TestTemplateClass<T> v) { };
template<typename T> T Valid(TestTemplateClass<int> v, T x) { return x; };
template<typename T> T& Valid(TestTemplateClass<int> v, T x) const { return x; }
};
// Explicit instantiation
template class TestTemplateClass<int>;
// Implicit instantiation
typedef TestTemplateClass<int> TestTemplateClassInt;
// Now use the typedef
class TestTemplateClass2
{
public:
TestTemplateClassInt* CreateIntTemplate();
};

9
tests/Native/ASTExtensions.h

@ -0,0 +1,9 @@
#include "AST.h"
#include <vector>
// Tests class templates accross translation units
// Explicit instantiation
template class TestTemplateClass<Math::Complex>;
// Implicit instantiations
typedef TestTemplateClass<Math::Complex> TestTemplateClassComplex;
typedef TestTemplateClass<std::vector<Math::Complex>> TestTemplateClassMoreComplex;
Loading…
Cancel
Save