Browse Source

Added support for default values of parameters.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/285/head
Dimitar Dobrev 11 years ago
parent
commit
0499556bfe
  1. 4
      src/AST/Expression.cs
  2. 3
      src/AST/Function.cs
  3. 16
      src/AST/Statement.cs
  4. 21
      src/Core/Parser/ASTConverter.cs
  5. 8
      src/CppParser/AST.cpp
  6. 23
      src/CppParser/AST.h
  7. 76
      src/CppParser/Bindings/CLI/AST.cpp
  8. 56
      src/CppParser/Bindings/CLI/AST.h
  9. 191
      src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/AST.cs
  10. 191
      src/CppParser/Bindings/CSharp/i686-pc-win32/AST.cs
  11. 50
      src/CppParser/Parser.cpp
  12. 2
      src/CppParser/Parser.h
  13. 2
      src/Generator/Driver.cs
  14. 21
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  15. 5
      src/Generator/Options.cs
  16. 173
      src/Generator/Passes/HandleDefaultParamValuesPass.cs
  17. 14
      tests/CSharpTemp/CSharpTemp.Tests.cs
  18. 28
      tests/CSharpTemp/CSharpTemp.cpp
  19. 2
      tests/CSharpTemp/CSharpTemp.cs
  20. 21
      tests/CSharpTemp/CSharpTemp.h

4
src/AST/Expression.cs

@ -1,8 +1,6 @@ @@ -1,8 +1,6 @@
using System;
namespace CppSharp.AST
{
public abstract class Expression
public abstract class Expression : Statement
{
public string DebugText;

3
src/AST/Function.cs

@ -46,6 +46,7 @@ namespace CppSharp.AST @@ -46,6 +46,7 @@ namespace CppSharp.AST
Kind = p.Kind;
QualifiedType = p.QualifiedType;
Usage = p.Usage;
DefaultArgument = p.DefaultArgument;
}
public Type Type { get { return QualifiedType.Type; } }
@ -57,6 +58,8 @@ namespace CppSharp.AST @@ -57,6 +58,8 @@ namespace CppSharp.AST
public ParameterUsage Usage { get; set; }
public bool HasDefaultValue { get; set; }
public Expression DefaultArgument { get; set; }
public bool IsIn { get { return Usage == ParameterUsage.In; } }
public bool IsOut { get { return Usage == ParameterUsage.Out; } }
public bool IsInOut { get { return Usage == ParameterUsage.InOut; } }

16
src/AST/Statement.cs

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
namespace CppSharp.AST
{
public enum StatementClass
{
Any,
DeclarationReference,
ConstructorReference
}
public abstract class Statement
{
public StatementClass Class { get; set; }
public Declaration Declaration { get; set; }
public string String { get; set; }
}
}

21
src/Core/Parser/ASTConverter.cs

@ -833,10 +833,31 @@ namespace CppSharp @@ -833,10 +833,31 @@ namespace CppSharp
_param.IsIndirect = decl.IsIndirect;
_param.HasDefaultValue = decl.HasDefaultValue;
_param.Index = decl.Index;
_param.DefaultArgument = VisitStatement(decl.DefaultArgument);
return _param;
}
private AST.Expression VisitStatement(Statement statement)
{
if (statement == null)
return null;
var expression = new AST.BuiltinTypeExpression();
expression.Declaration = this.typeConverter.declConverter.Visit(statement.Decl);
expression.String = statement.String;
switch (statement.Class)
{
case StatementClass.DeclRefExprClass:
expression.Class = AST.StatementClass.DeclarationReference;
break;
case StatementClass.CXXConstructExprClass:
expression.Class = AST.StatementClass.ConstructorReference;
break;
}
return expression;
}
public void VisitFunction(Function function, AST.Function _function)
{
VisitDeclaration(function, _function);

8
src/CppParser/AST.cpp

@ -418,8 +418,14 @@ TypedefDecl* DeclarationContext::FindTypedef(const std::string& Name, bool Creat @@ -418,8 +418,14 @@ TypedefDecl* DeclarationContext::FindTypedef(const std::string& Name, bool Creat
TypedefDecl::TypedefDecl() : Declaration(DeclarationKind::Typedef) {}
DEF_STRING(Statement, String)
Statement::Statement(const std::string& str, StatementClass stmtClass, Declaration* decl) : String(str), Class(stmtClass), Decl(decl) {}
Expression::Expression(const std::string& str, StatementClass stmtClass, Declaration* decl) : Statement(str, stmtClass, decl) {}
Parameter::Parameter() : Declaration(DeclarationKind::Parameter),
IsIndirect(false), HasDefaultValue(false) {}
IsIndirect(false), HasDefaultValue(false), DefaultArgument(0) {}
Function::Function()
: Declaration(DeclarationKind::Function)

23
src/CppParser/AST.h

@ -455,6 +455,28 @@ public: @@ -455,6 +455,28 @@ public:
CppSharp::CppParser::AST::QualifiedType QualifiedType;
};
enum class StatementClass
{
Any,
DeclRefExprClass,
CXXConstructExprClass
};
class CS_API Statement
{
public:
Statement(const std::string& str, StatementClass Class = StatementClass::Any, Declaration* decl = 0);
StatementClass Class;
Declaration* Decl;
STRING(String)
};
class CS_API Expression : public Statement
{
public:
Expression(const std::string& str, StatementClass Class = StatementClass::Any, Declaration* decl = 0);
};
class CS_API Parameter : public Declaration
{
public:
@ -464,6 +486,7 @@ public: @@ -464,6 +486,7 @@ public:
bool IsIndirect;
bool HasDefaultValue;
unsigned int Index;
Expression* DefaultArgument;
};
enum class CXXMethodKind

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

@ -1465,6 +1465,72 @@ void CppSharp::Parser::AST::TypedefDecl::QualifiedType::set(CppSharp::Parser::AS @@ -1465,6 +1465,72 @@ void CppSharp::Parser::AST::TypedefDecl::QualifiedType::set(CppSharp::Parser::AS
((::CppSharp::CppParser::AST::TypedefDecl*)NativePtr)->QualifiedType = *(::CppSharp::CppParser::AST::QualifiedType*)value->NativePtr;
}
CppSharp::Parser::AST::Statement::Statement(::CppSharp::CppParser::AST::Statement* native)
{
NativePtr = native;
}
CppSharp::Parser::AST::Statement::Statement(System::IntPtr native)
{
auto __native = (::CppSharp::CppParser::AST::Statement*)native.ToPointer();
NativePtr = __native;
}
System::IntPtr CppSharp::Parser::AST::Statement::__Instance::get()
{
return System::IntPtr(NativePtr);
}
void CppSharp::Parser::AST::Statement::__Instance::set(System::IntPtr object)
{
NativePtr = (::CppSharp::CppParser::AST::Statement*)object.ToPointer();
}
System::String^ CppSharp::Parser::AST::Statement::String::get()
{
auto __ret = ((::CppSharp::CppParser::AST::Statement*)NativePtr)->getString();
if (__ret == nullptr) return nullptr;
return clix::marshalString<clix::E_UTF8>(__ret);
}
void CppSharp::Parser::AST::Statement::String::set(System::String^ s)
{
auto _arg0 = clix::marshalString<clix::E_UTF8>(s);
auto arg0 = _arg0.c_str();
((::CppSharp::CppParser::AST::Statement*)NativePtr)->setString(arg0);
}
CppSharp::Parser::AST::StatementClass CppSharp::Parser::AST::Statement::Class::get()
{
return (CppSharp::Parser::AST::StatementClass)((::CppSharp::CppParser::AST::Statement*)NativePtr)->Class;
}
void CppSharp::Parser::AST::Statement::Class::set(CppSharp::Parser::AST::StatementClass value)
{
((::CppSharp::CppParser::AST::Statement*)NativePtr)->Class = (::CppSharp::CppParser::AST::StatementClass)value;
}
CppSharp::Parser::AST::Declaration^ CppSharp::Parser::AST::Statement::Decl::get()
{
return (((::CppSharp::CppParser::AST::Statement*)NativePtr)->Decl == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::Declaration((::CppSharp::CppParser::AST::Declaration*)((::CppSharp::CppParser::AST::Statement*)NativePtr)->Decl);
}
void CppSharp::Parser::AST::Statement::Decl::set(CppSharp::Parser::AST::Declaration^ value)
{
((::CppSharp::CppParser::AST::Statement*)NativePtr)->Decl = (::CppSharp::CppParser::AST::Declaration*)value->NativePtr;
}
CppSharp::Parser::AST::Expression::Expression(::CppSharp::CppParser::AST::Expression* native)
: CppSharp::Parser::AST::Statement((::CppSharp::CppParser::AST::Statement*)native)
{
}
CppSharp::Parser::AST::Expression::Expression(System::IntPtr native)
: CppSharp::Parser::AST::Statement(native)
{
auto __native = (::CppSharp::CppParser::AST::Expression*)native.ToPointer();
}
CppSharp::Parser::AST::Parameter::Parameter(::CppSharp::CppParser::AST::Parameter* native)
: CppSharp::Parser::AST::Declaration((::CppSharp::CppParser::AST::Declaration*)native)
{
@ -1522,6 +1588,16 @@ void CppSharp::Parser::AST::Parameter::Index::set(unsigned int value) @@ -1522,6 +1588,16 @@ void CppSharp::Parser::AST::Parameter::Index::set(unsigned int value)
((::CppSharp::CppParser::AST::Parameter*)NativePtr)->Index = value;
}
CppSharp::Parser::AST::Expression^ CppSharp::Parser::AST::Parameter::DefaultArgument::get()
{
return (((::CppSharp::CppParser::AST::Parameter*)NativePtr)->DefaultArgument == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::Expression((::CppSharp::CppParser::AST::Expression*)((::CppSharp::CppParser::AST::Parameter*)NativePtr)->DefaultArgument);
}
void CppSharp::Parser::AST::Parameter::DefaultArgument::set(CppSharp::Parser::AST::Expression^ value)
{
((::CppSharp::CppParser::AST::Parameter*)NativePtr)->DefaultArgument = (::CppSharp::CppParser::AST::Expression*)value->NativePtr;
}
CppSharp::Parser::AST::Function::Function(::CppSharp::CppParser::AST::Function* native)
: CppSharp::Parser::AST::Declaration((::CppSharp::CppParser::AST::Declaration*)native)
{

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

@ -20,6 +20,7 @@ namespace CppSharp @@ -20,6 +20,7 @@ namespace CppSharp
enum struct MacroLocation;
enum struct PrimitiveType;
enum struct RawCommentKind;
enum struct StatementClass;
enum struct TemplateSpecializationKind;
enum struct TypeKind;
enum struct VTableComponentKind;
@ -40,6 +41,7 @@ namespace CppSharp @@ -40,6 +41,7 @@ namespace CppSharp
ref class DeclarationContext;
ref class DependentNameType;
ref class Enumeration;
ref class Expression;
ref class Field;
ref class FullComment;
ref class Function;
@ -59,6 +61,7 @@ namespace CppSharp @@ -59,6 +61,7 @@ namespace CppSharp
ref class PreprocessedEntity;
ref class QualifiedType;
ref class RawComment;
ref class Statement;
ref class TagType;
ref class Template;
ref class TemplateArgument;
@ -204,6 +207,13 @@ namespace CppSharp @@ -204,6 +207,13 @@ namespace CppSharp
Unknown = 5
};
public enum struct StatementClass
{
Any = 0,
DeclRefExprClass = 1,
CXXConstructExprClass = 2
};
public enum struct TemplateSpecializationKind
{
Undeclared = 0,
@ -1127,6 +1137,46 @@ namespace CppSharp @@ -1127,6 +1137,46 @@ namespace CppSharp
}
};
public ref class Statement : ICppInstance
{
public:
property ::CppSharp::CppParser::AST::Statement* NativePtr;
property System::IntPtr __Instance
{
virtual System::IntPtr get();
virtual void set(System::IntPtr instance);
}
Statement(::CppSharp::CppParser::AST::Statement* native);
Statement(System::IntPtr native);
property System::String^ String
{
System::String^ get();
void set(System::String^);
}
property CppSharp::Parser::AST::StatementClass Class
{
CppSharp::Parser::AST::StatementClass get();
void set(CppSharp::Parser::AST::StatementClass);
}
property CppSharp::Parser::AST::Declaration^ Decl
{
CppSharp::Parser::AST::Declaration^ get();
void set(CppSharp::Parser::AST::Declaration^);
}
};
public ref class Expression : CppSharp::Parser::AST::Statement
{
public:
Expression(::CppSharp::CppParser::AST::Expression* native);
Expression(System::IntPtr native);
};
public ref class Parameter : CppSharp::Parser::AST::Declaration
{
public:
@ -1158,6 +1208,12 @@ namespace CppSharp @@ -1158,6 +1208,12 @@ namespace CppSharp
unsigned int get();
void set(unsigned int);
}
property CppSharp::Parser::AST::Expression^ DefaultArgument
{
CppSharp::Parser::AST::Expression^ get();
void set(CppSharp::Parser::AST::Expression^);
}
};
public ref class Function : CppSharp::Parser::AST::Declaration

191
src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/AST.cs

@ -131,6 +131,13 @@ namespace CppSharp @@ -131,6 +131,13 @@ namespace CppSharp
Unknown = 5
}
public enum StatementClass
{
Any = 0,
DeclRefExprClass = 1,
CXXConstructExprClass = 2
}
public enum TemplateSpecializationKind
{
Undeclared = 0,
@ -3411,9 +3418,171 @@ namespace CppSharp @@ -3411,9 +3418,171 @@ namespace CppSharp
}
}
public unsafe partial class Statement : IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 20)]
public struct Internal
{
[FieldOffset(0)]
public CppSharp.Parser.AST.StatementClass Class;
[FieldOffset(4)]
public global::System.IntPtr Decl;
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser3AST9StatementC2ERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEENS1_14StatementClassEPNS1_11DeclarationE")]
internal static extern void ctor_0(global::System.IntPtr instance, global::System.IntPtr str, CppSharp.Parser.AST.StatementClass Class, global::System.IntPtr decl);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser3AST9StatementC2ERKS2_")]
internal static extern void cctor_2(global::System.IntPtr instance, global::System.IntPtr _0);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser3AST9StatementD2Ev")]
internal static extern void dtor_0(global::System.IntPtr instance);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser3AST9Statement9getStringEv")]
internal static extern global::System.IntPtr getString_0(global::System.IntPtr instance);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser3AST9Statement9setStringEPKc")]
internal static extern void setString_0(global::System.IntPtr instance, global::System.IntPtr s);
}
public global::System.IntPtr __Instance { get; protected set; }
internal Statement(Statement.Internal* native)
: this(new global::System.IntPtr(native))
{
}
internal Statement(Statement.Internal native)
: this(&native)
{
}
public Statement(global::System.IntPtr native, bool isInternalImpl = false)
{
__Instance = native;
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
Internal.dtor_0(__Instance);
Marshal.FreeHGlobal(__Instance);
}
public string String
{
get
{
var __ret = Internal.getString_0(__Instance);
if (__ret == global::System.IntPtr.Zero) return null;
return Marshal.PtrToStringAnsi(__ret);
}
set
{
var arg0 = Marshal.StringToHGlobalAnsi(value);
Internal.setString_0(__Instance, arg0);
Marshal.FreeHGlobal(arg0);
}
}
public CppSharp.Parser.AST.StatementClass Class
{
get
{
var __ptr = (Internal*)__Instance.ToPointer();
return __ptr->Class;
}
set
{
var __ptr = (Internal*)__Instance.ToPointer();
__ptr->Class = value;
}
}
public CppSharp.Parser.AST.Declaration Decl
{
get
{
var __ptr = (Internal*)__Instance.ToPointer();
return (__ptr->Decl == IntPtr.Zero) ? null : new CppSharp.Parser.AST.Declaration(__ptr->Decl);
}
set
{
var __ptr = (Internal*)__Instance.ToPointer();
__ptr->Decl = value == (CppSharp.Parser.AST.Declaration) null ? global::System.IntPtr.Zero : value.__Instance;
}
}
}
public unsafe partial class Expression : CppSharp.Parser.AST.Statement, IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 20)]
public new struct Internal
{
[FieldOffset(0)]
public CppSharp.Parser.AST.StatementClass Class;
[FieldOffset(4)]
public global::System.IntPtr Decl;
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser3AST10ExpressionC2ERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEENS1_14StatementClassEPNS1_11DeclarationE")]
internal static extern void ctor_0(global::System.IntPtr instance, global::System.IntPtr str, CppSharp.Parser.AST.StatementClass Class, global::System.IntPtr decl);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser3AST10ExpressionC2ERKS2_")]
internal static extern void cctor_1(global::System.IntPtr instance, global::System.IntPtr _0);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser3AST10ExpressionD2Ev")]
internal static extern void dtor_0(global::System.IntPtr instance);
}
internal Expression(Expression.Internal* native)
: this(new global::System.IntPtr(native))
{
}
internal Expression(Expression.Internal native)
: this(&native)
{
}
public Expression(global::System.IntPtr native, bool isInternalImpl = false)
: base(native)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
public unsafe partial class Parameter : CppSharp.Parser.AST.Declaration, IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 100)]
[StructLayout(LayoutKind.Explicit, Size = 104)]
public new struct Internal
{
[FieldOffset(0)]
@ -3458,6 +3627,9 @@ namespace CppSharp @@ -3458,6 +3627,9 @@ namespace CppSharp
[FieldOffset(96)]
public uint Index;
[FieldOffset(100)]
public global::System.IntPtr DefaultArgument;
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser3AST9ParameterC2Ev")]
@ -3492,7 +3664,7 @@ namespace CppSharp @@ -3492,7 +3664,7 @@ namespace CppSharp
public Parameter()
: this(IntPtr.Zero)
{
__Instance = Marshal.AllocHGlobal(100);
__Instance = Marshal.AllocHGlobal(104);
Internal.ctor_0(__Instance);
}
@ -3562,6 +3734,21 @@ namespace CppSharp @@ -3562,6 +3734,21 @@ namespace CppSharp
__ptr->Index = value;
}
}
public CppSharp.Parser.AST.Expression DefaultArgument
{
get
{
var __ptr = (Internal*)__Instance.ToPointer();
return (__ptr->DefaultArgument == IntPtr.Zero) ? null : new CppSharp.Parser.AST.Expression(__ptr->DefaultArgument);
}
set
{
var __ptr = (Internal*)__Instance.ToPointer();
__ptr->DefaultArgument = value == (CppSharp.Parser.AST.Expression) null ? global::System.IntPtr.Zero : value.__Instance;
}
}
}
public unsafe partial class Function : CppSharp.Parser.AST.Declaration, IDisposable

191
src/CppParser/Bindings/CSharp/i686-pc-win32/AST.cs

@ -131,6 +131,13 @@ namespace CppSharp @@ -131,6 +131,13 @@ namespace CppSharp
Unknown = 5
}
public enum StatementClass
{
Any = 0,
DeclRefExprClass = 1,
CXXConstructExprClass = 2
}
public enum TemplateSpecializationKind
{
Undeclared = 0,
@ -3411,9 +3418,171 @@ namespace CppSharp @@ -3411,9 +3418,171 @@ namespace CppSharp
}
}
public unsafe partial class Statement : IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 32)]
public struct Internal
{
[FieldOffset(0)]
public CppSharp.Parser.AST.StatementClass Class;
[FieldOffset(4)]
public global::System.IntPtr Decl;
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??0Statement@AST@CppParser@CppSharp@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@W4StatementClass@123@PAVDeclaration@123@@Z")]
internal static extern global::System.IntPtr ctor_0(global::System.IntPtr instance, global::System.IntPtr str, CppSharp.Parser.AST.StatementClass Class, global::System.IntPtr decl);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??0Statement@AST@CppParser@CppSharp@@QAE@ABV0123@@Z")]
internal static extern global::System.IntPtr cctor_2(global::System.IntPtr instance, global::System.IntPtr _0);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??1Statement@AST@CppParser@CppSharp@@QAE@XZ")]
internal static extern void dtor_0(global::System.IntPtr instance);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="?getString@Statement@AST@CppParser@CppSharp@@QAEPBDXZ")]
internal static extern global::System.IntPtr getString_0(global::System.IntPtr instance);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="?setString@Statement@AST@CppParser@CppSharp@@QAEXPBD@Z")]
internal static extern void setString_0(global::System.IntPtr instance, global::System.IntPtr s);
}
public global::System.IntPtr __Instance { get; protected set; }
internal Statement(Statement.Internal* native)
: this(new global::System.IntPtr(native))
{
}
internal Statement(Statement.Internal native)
: this(&native)
{
}
public Statement(global::System.IntPtr native, bool isInternalImpl = false)
{
__Instance = native;
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
Internal.dtor_0(__Instance);
Marshal.FreeHGlobal(__Instance);
}
public string String
{
get
{
var __ret = Internal.getString_0(__Instance);
if (__ret == global::System.IntPtr.Zero) return null;
return Marshal.PtrToStringAnsi(__ret);
}
set
{
var arg0 = Marshal.StringToHGlobalAnsi(value);
Internal.setString_0(__Instance, arg0);
Marshal.FreeHGlobal(arg0);
}
}
public CppSharp.Parser.AST.StatementClass Class
{
get
{
var __ptr = (Internal*)__Instance.ToPointer();
return __ptr->Class;
}
set
{
var __ptr = (Internal*)__Instance.ToPointer();
__ptr->Class = value;
}
}
public CppSharp.Parser.AST.Declaration Decl
{
get
{
var __ptr = (Internal*)__Instance.ToPointer();
return (__ptr->Decl == IntPtr.Zero) ? null : new CppSharp.Parser.AST.Declaration(__ptr->Decl);
}
set
{
var __ptr = (Internal*)__Instance.ToPointer();
__ptr->Decl = value == (CppSharp.Parser.AST.Declaration) null ? global::System.IntPtr.Zero : value.__Instance;
}
}
}
public unsafe partial class Expression : CppSharp.Parser.AST.Statement, IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 32)]
public new struct Internal
{
[FieldOffset(0)]
public CppSharp.Parser.AST.StatementClass Class;
[FieldOffset(4)]
public global::System.IntPtr Decl;
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??0Expression@AST@CppParser@CppSharp@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@W4StatementClass@123@PAVDeclaration@123@@Z")]
internal static extern global::System.IntPtr ctor_0(global::System.IntPtr instance, global::System.IntPtr str, CppSharp.Parser.AST.StatementClass Class, global::System.IntPtr decl);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??0Expression@AST@CppParser@CppSharp@@QAE@ABV0123@@Z")]
internal static extern global::System.IntPtr cctor_1(global::System.IntPtr instance, global::System.IntPtr _0);
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??1Expression@AST@CppParser@CppSharp@@QAE@XZ")]
internal static extern void dtor_0(global::System.IntPtr instance);
}
internal Expression(Expression.Internal* native)
: this(new global::System.IntPtr(native))
{
}
internal Expression(Expression.Internal native)
: this(&native)
{
}
public Expression(global::System.IntPtr native, bool isInternalImpl = false)
: base(native)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
public unsafe partial class Parameter : CppSharp.Parser.AST.Declaration, IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 136)]
[StructLayout(LayoutKind.Explicit, Size = 140)]
public new struct Internal
{
[FieldOffset(0)]
@ -3458,6 +3627,9 @@ namespace CppSharp @@ -3458,6 +3627,9 @@ namespace CppSharp
[FieldOffset(132)]
public uint Index;
[FieldOffset(136)]
public global::System.IntPtr DefaultArgument;
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??0Parameter@AST@CppParser@CppSharp@@QAE@XZ")]
@ -3492,7 +3664,7 @@ namespace CppSharp @@ -3492,7 +3664,7 @@ namespace CppSharp
public Parameter()
: this(IntPtr.Zero)
{
__Instance = Marshal.AllocHGlobal(136);
__Instance = Marshal.AllocHGlobal(140);
Internal.ctor_0(__Instance);
}
@ -3562,6 +3734,21 @@ namespace CppSharp @@ -3562,6 +3734,21 @@ namespace CppSharp
__ptr->Index = value;
}
}
public CppSharp.Parser.AST.Expression DefaultArgument
{
get
{
var __ptr = (Internal*)__Instance.ToPointer();
return (__ptr->DefaultArgument == IntPtr.Zero) ? null : new CppSharp.Parser.AST.Expression(__ptr->DefaultArgument);
}
set
{
var __ptr = (Internal*)__Instance.ToPointer();
__ptr->DefaultArgument = value == (CppSharp.Parser.AST.Expression) null ? global::System.IntPtr.Zero : value.__Instance;
}
}
}
public unsafe partial class Function : CppSharp.Parser.AST.Declaration, IDisposable

50
src/CppParser/Parser.cpp

@ -2176,6 +2176,10 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, Function* F, @@ -2176,6 +2176,10 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, Function* F,
P->HasDefaultValue = VD->hasDefaultArg();
P->_Namespace = NS;
P->Index = VD->getFunctionScopeIndex();
if (VD->hasDefaultArg() && !VD->hasUnparsedDefaultArg() && !VD->hasUninstantiatedDefaultArg())
{
P->DefaultArgument = WalkStatement(VD->getDefaultArg());
}
HandleDeclaration(VD, P);
F->Parameters.push_back(P);
@ -2430,6 +2434,52 @@ void Parser::HandlePreprocessedEntities(Declaration* Decl) @@ -2430,6 +2434,52 @@ void Parser::HandlePreprocessedEntities(Declaration* Decl)
}
}
AST::Expression* Parser::WalkStatement(clang::Stmt* Statement)
{
using namespace clang;
switch (Statement->getStmtClass())
{
case Stmt::DeclRefExprClass:
return new AST::Expression(GetStringFromStatement(Statement), StatementClass::DeclRefExprClass,
WalkDeclaration(cast<DeclRefExpr>(Statement)->getDecl()));
case Stmt::CStyleCastExprClass:
case Stmt::CXXConstCastExprClass:
case Stmt::CXXDynamicCastExprClass:
case Stmt::CXXFunctionalCastExprClass:
case Stmt::CXXReinterpretCastExprClass:
case Stmt::CXXStaticCastExprClass:
case Stmt::ImplicitCastExprClass:
return WalkStatement(cast<CastExpr>(Statement)->getSubExprAsWritten());
case Stmt::CXXConstructExprClass:
{
auto ConstructorExpr = cast<CXXConstructExpr>(Statement);
auto Arg = ConstructorExpr->getArg(0);
auto TemporaryExpr = dyn_cast<MaterializeTemporaryExpr>(Arg);
if (TemporaryExpr && isa<CastExpr>(TemporaryExpr->GetTemporaryExpr()))
return WalkStatement(TemporaryExpr->GetTemporaryExpr());
return new AST::Expression(GetStringFromStatement(Statement), StatementClass::CXXConstructExprClass,
WalkDeclaration(ConstructorExpr->getConstructor()));
}
case Stmt::MaterializeTemporaryExprClass:
return WalkStatement(cast<MaterializeTemporaryExpr>(Statement)->GetTemporaryExpr());
default:
break;
}
return new AST::Expression(GetStringFromStatement(Statement));
}
std::string Parser::GetStringFromStatement(const clang::Stmt* Statement)
{
using namespace clang;
PrintingPolicy Policy(C->getLangOpts());
std::string s;
llvm::raw_string_ostream as(s);
Statement->printPretty(as, 0, Policy);
return as.str();
}
void Parser::HandlePreprocessedEntities(Declaration* Decl,
clang::SourceRange sourceRange,
MacroLocation macroLocation)

2
src/CppParser/Parser.h

@ -93,6 +93,8 @@ protected: @@ -93,6 +93,8 @@ protected:
VTableComponent WalkVTableComponent(const clang::VTableComponent& Component);
PreprocessedEntity* WalkPreprocessedEntity(Declaration* Decl,
clang::PreprocessedEntity* PPEntity);
AST::Expression* WalkStatement(clang::Stmt* Statement);
std::string GetStringFromStatement(const clang::Stmt* Statement);
// Clang helpers
SourceLocationKind GetLocationKind(const clang::SourceLocation& Loc);

2
src/Generator/Driver.cs

@ -236,6 +236,8 @@ namespace CppSharp @@ -236,6 +236,8 @@ namespace CppSharp
TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass());
TranslationUnitPasses.AddPass(new CheckFlagEnumsPass());
TranslationUnitPasses.AddPass(new CheckDuplicatedNamesPass());
if (Options.IsCSharpGenerator && Options.GenerateDefaultValuesForArguments)
TranslationUnitPasses.AddPass(new HandleDefaultParamValuesPass());
if (Options.GenerateAbstractImpls)
TranslationUnitPasses.AddPass(new GenerateAbstractImplementationsPass());

21
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -2051,6 +2051,19 @@ namespace CppSharp.Generators.CSharp @@ -2051,6 +2051,19 @@ namespace CppSharp.Generators.CSharp
if (method.IsProxy)
goto SkipImpl;
if (method.SynthKind == FunctionSynthKind.DefaultValueOverload)
{
Type type = method.OriginalReturnType.Type;
WriteLine("{0}{1}({2});",
type.IsPrimitiveType(PrimitiveType.Void) ? string.Empty : "return ",
method.Name,
string.Join(", ",
method.Parameters.Where(
p => p.Kind == ParameterKind.Regular).Select(
p => p.GenerationKind == GenerationKind.None ? p.DefaultArgument.String : p.Name)));
goto SkipImpl;
}
if (@class.IsRefType)
{
if (method.IsConstructor)
@ -2534,10 +2547,12 @@ namespace CppSharp.Generators.CSharp @@ -2534,10 +2547,12 @@ namespace CppSharp.Generators.CSharp
{
return string.Join(", ",
from param in @params
where param.Kind != ParameterKind.IndirectReturnType
let typeName = param.CSharpType(TypePrinter)
where param.Kind != ParameterKind.IndirectReturnType && !param.Ignore
let typeName = param.CSharpType(this.TypePrinter)
select string.Format("{0}{1} {2}", GetParameterUsage(param.Usage),
typeName, param.Name));
typeName, param.Name +
(param.DefaultArgument == null || !Options.GenerateDefaultValuesForArguments ?
string.Empty : " = " + param.DefaultArgument.String)));
}
#endregion

5
src/Generator/Options.cs

@ -180,6 +180,11 @@ namespace CppSharp @@ -180,6 +180,11 @@ namespace CppSharp
/// Generates a single C# file.
/// </summary>
public bool GenerateSingleCSharpFile { get; set; }
/// <summary>
/// Generates default values of arguments in the C# code.
/// </summary>
public bool GenerateDefaultValuesForArguments { get; set; }
}
public class InvalidOptionException : Exception

173
src/Generator/Passes/HandleDefaultParamValuesPass.cs

@ -0,0 +1,173 @@ @@ -0,0 +1,173 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Generators.CLI;
using CppSharp.Generators.CSharp;
using CppSharp.Types;
using Type = CppSharp.AST.Type;
namespace CppSharp.Passes
{
public class HandleDefaultParamValuesPass : TranslationUnitPass
{
private static readonly Regex regexFunctionParams = new Regex(@"\((.+)\)", RegexOptions.Compiled);
private static readonly Regex regexDoubleColon = new Regex(@"\w+::", RegexOptions.Compiled);
private static readonly Regex regexName = new Regex(@"(\w+)", RegexOptions.Compiled);
public override bool VisitFunctionDecl(Function function)
{
bool result = base.VisitFunctionDecl(function);
var overloadIndices = new List<int>(function.Parameters.Count);
foreach (var parameter in function.Parameters.Where(p => p.DefaultArgument != null))
{
Type desugared = parameter.Type.Desugar();
if (CheckForDefaultPointer(desugared, parameter))
continue;
bool? defaultConstruct = CheckForDefaultConstruct(desugared, parameter);
if (defaultConstruct == null ||
(!Driver.Options.MarshalCharAsManagedChar &&
parameter.Type.Desugar().IsPrimitiveType(PrimitiveType.UChar)))
{
overloadIndices.Add(function.Parameters.IndexOf(parameter));
continue;
}
if (defaultConstruct == true)
continue;
if (CheckForEnumValue(parameter, desugared))
continue;
CheckForULongValue(parameter, desugared);
}
GenerateOverloads(function, overloadIndices);
return result;
}
private static bool CheckForDefaultPointer(Type desugared, Parameter parameter)
{
if (desugared.IsPointer())
{
parameter.DefaultArgument.String = "null";
return true;
}
return false;
}
private bool? CheckForDefaultConstruct(Type desugared, Parameter parameter)
{
Method ctor = parameter.DefaultArgument.Declaration as Method;
if (ctor == null || !ctor.IsConstructor)
return false;
Type type;
desugared.IsPointerTo(out type);
type = type ?? desugared;
Class decl;
if (!type.TryGetClass(out decl))
return false;
TypeMap typeMap;
if (Driver.TypeDatabase.FindTypeMap(decl, type, out typeMap))
{
string mappedTo;
if (Driver.Options.IsCSharpGenerator)
{
var typePrinterContext = new CSharpTypePrinterContext
{
CSharpKind = CSharpTypePrinterContextKind.Managed,
Type = type
};
mappedTo = typeMap.CSharpSignature(typePrinterContext);
}
else
{
var typePrinterContext = new CLITypePrinterContext
{
Type = type
};
mappedTo = typeMap.CLISignature(typePrinterContext);
}
if (mappedTo == "string" && ctor.Parameters.Count == 0)
{
parameter.DefaultArgument.String = "\"\"";
return true;
}
}
parameter.DefaultArgument.String = string.Format("new {0}", parameter.DefaultArgument.String);
if (ctor.Parameters.Count > 0 && ctor.Parameters[0].OriginalName == "_0")
parameter.DefaultArgument.String = parameter.DefaultArgument.String.Replace("(0)", "()");
return decl.IsValueType ? true : (bool?) null;
}
private static bool CheckForEnumValue(Parameter parameter, Type desugared)
{
var enumItem = parameter.DefaultArgument.Declaration as Enumeration.Item;
if (enumItem != null)
{
parameter.DefaultArgument.String = string.Format("{0}{1}.{2}.{3}",
desugared.IsPrimitiveType() ? "(int) " : string.Empty,
enumItem.Namespace.Namespace.Name, enumItem.Namespace.Name, enumItem.Name);
return true;
}
var call = parameter.DefaultArgument.Declaration as Method;
if (call != null && call.IsConstructor)
{
string @params =
regexFunctionParams.Match(parameter.DefaultArgument.String).Groups[1].Value;
if (@params.Contains("::"))
parameter.DefaultArgument.String = regexDoubleColon.Replace(@params, desugared + ".");
else
parameter.DefaultArgument.String = regexName.Replace(@params, desugared + ".$1");
return true;
}
return false;
}
private static void CheckForULongValue(Parameter parameter, Type desugared)
{
ulong value;
string @default = parameter.DefaultArgument.String;
// HACK: .NET's Parse/TryParse have a bug preventing them from parsing UL-suffixed ulongs
if (desugared.IsPrimitiveType() && @default.EndsWith("UL"))
@default = @default.Substring(0, @default.Length - 2);
if (ulong.TryParse(@default, out value))
parameter.DefaultArgument.String = value.ToString(CultureInfo.InvariantCulture);
}
private static void GenerateOverloads(Function function, List<int> overloadIndices)
{
foreach (var overloadIndex in overloadIndices)
{
var method = function as Method;
Function overload = method != null ? new Method(method) : new Function(function);
overload.SynthKind = FunctionSynthKind.DefaultValueOverload;
overload.Parameters[overloadIndex].GenerationKind = GenerationKind.None;
var indices = overloadIndices.Where(i => i != overloadIndex).ToList();
if (indices.Any())
for (int i = 0; i <= indices.Last(); i++)
if (i != overloadIndex)
overload.Parameters[i].DefaultArgument = null;
if (method != null)
((Class) function.Namespace).Methods.Add((Method) overload);
else
function.Namespace.Functions.Add(overload);
for (int i = 0; i <= overloadIndex; i++)
function.Parameters[i].DefaultArgument = null;
}
}
}
}

14
tests/CSharpTemp/CSharpTemp.Tests.cs

@ -118,10 +118,24 @@ public class CSharpTempTests : GeneratorTestFixture @@ -118,10 +118,24 @@ public class CSharpTempTests : GeneratorTestFixture
Assert.That(testCopyConstructorVal.B, Is.EqualTo(copyBar.B));
}
[Test]
public void TestPropertiesConflictingWithMethod()
{
var p = new P((IQux) new Qux()) { Test = true };
Assert.That(p.Test, Is.True);
p.GetTest();
}
[Test]
public void TestDefaultArguments()
{
var methodsWithDefaultValues = new MethodsWithDefaultValues();
methodsWithDefaultValues.DefaultChar();
methodsWithDefaultValues.DefaultPointer();
methodsWithDefaultValues.DefaultRefTypeAfterOthers();
methodsWithDefaultValues.DefaultRefTypeBeforeAndAfterOthers(5, new Foo());
methodsWithDefaultValues.DefaultRefTypeBeforeOthers();
methodsWithDefaultValues.DefaultValueType();
methodsWithDefaultValues.DefaultIntAssignedAnEnum();
}
}

28
tests/CSharpTemp/CSharpTemp.cpp

@ -206,3 +206,31 @@ TestCopyConstructorVal::TestCopyConstructorVal(const TestCopyConstructorVal& oth @@ -206,3 +206,31 @@ TestCopyConstructorVal::TestCopyConstructorVal(const TestCopyConstructorVal& oth
A = other.A;
B = other.B;
}
void MethodsWithDefaultValues::DefaultPointer(Foo *ptr)
{
}
void MethodsWithDefaultValues::DefaultValueType(ValueType bar)
{
}
void MethodsWithDefaultValues::DefaultChar(char c)
{
}
void MethodsWithDefaultValues::DefaultRefTypeBeforeOthers(Foo foo, int i, Bar::Items item)
{
}
void MethodsWithDefaultValues::DefaultRefTypeAfterOthers(int i, Bar::Items item, Foo foo)
{
}
void MethodsWithDefaultValues::DefaultRefTypeBeforeAndAfterOthers(int i, Foo foo, Bar::Items item, Baz baz)
{
}
void MethodsWithDefaultValues::DefaultIntAssignedAnEnum(int i)
{
}

2
tests/CSharpTemp/CSharpTemp.cs

@ -67,6 +67,8 @@ namespace CppSharp.Tests @@ -67,6 +67,8 @@ namespace CppSharp.Tests
// are not ambiguous with multiple inheritance pass enabled.
driver.Options.GenerateConversionOperators = true;
driver.TranslationUnitPasses.AddPass(new TestAttributesPass());
driver.Options.MarshalCharAsManagedChar = true;
driver.Options.GenerateDefaultValuesForArguments = true;
}
public override void Preprocess(Driver driver, ASTContext ctx)

21
tests/CSharpTemp/CSharpTemp.h

@ -27,6 +27,11 @@ public: @@ -27,6 +27,11 @@ public:
class DLL_API Bar : public Qux
{
public:
enum Items
{
Item1,
Item2
};
Bar();
int method();
const Foo& operator[](int i) const;
@ -165,3 +170,19 @@ public: @@ -165,3 +170,19 @@ public:
void name();
void Name();
};
struct DLL_API ValueType
{
};
class DLL_API MethodsWithDefaultValues
{
public:
void DefaultPointer(Foo* ptr = 0);
void DefaultValueType(ValueType bar = ValueType());
void DefaultChar(char c = 'a');
void DefaultRefTypeBeforeOthers(Foo foo = Foo(), int i = 5, Bar::Items item = Bar::Item2);
void DefaultRefTypeAfterOthers(int i = 5, Bar::Items item = Bar::Item2, Foo foo = Foo());
void DefaultRefTypeBeforeAndAfterOthers(int i = 5, Foo foo = Foo(), Bar::Items item = Bar::Item2, Baz baz = Baz());
void DefaultIntAssignedAnEnum(int i = Bar::Item1);
};

Loading…
Cancel
Save