From c4c2ef21ced191b1ed3dec6e87ba796687b97bee Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 23 Jun 2016 00:28:57 +0300 Subject: [PATCH] Filled in all missing v-table pointers in record layouts. Signed-off-by: Dimitar Dobrev --- src/AST/ClassLayout.cs | 18 ++- src/AST/Field.cs | 3 - src/AST/LayoutField.cs | 28 ++--- src/Core/Parser/ASTConverter.cs | 11 +- src/CppParser/AST.cpp | 13 ++- src/CppParser/AST.h | 8 +- src/CppParser/Bindings/CLI/AST.cpp | 42 ++++++- src/CppParser/Bindings/CLI/AST.h | 24 +++- .../CSharp/i686-apple-darwin12.4.0/AST.cs | 93 ++++++++++++--- .../Bindings/CSharp/i686-pc-win32-msvc/AST.cs | 93 ++++++++++++--- .../CSharp/x86_64-apple-darwin12.4.0/AST.cs | 93 ++++++++++++--- .../Bindings/CSharp/x86_64-linux-gnu/AST.cs | 93 ++++++++++++--- .../CSharp/x86_64-pc-win32-msvc/AST.cs | 93 ++++++++++++--- src/CppParser/Parser.cpp | 56 ++++++++- src/CppParser/Parser.h | 3 +- .../Generators/CLI/CLIHeadersTemplate.cs | 17 +-- .../Generators/CSharp/CSharpTextTemplate.cs | 110 +++++++----------- .../Passes/CheckDuplicatedNamesPass.cs | 4 +- .../Passes/CleanInvalidDeclNamesPass.cs | 4 + 19 files changed, 608 insertions(+), 198 deletions(-) diff --git a/src/AST/ClassLayout.cs b/src/AST/ClassLayout.cs index f11ac20c..ec69277d 100644 --- a/src/AST/ClassLayout.cs +++ b/src/AST/ClassLayout.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; namespace CppSharp.AST { @@ -132,5 +134,19 @@ namespace CppSharp.AST public int Alignment; public int Size; public int DataSize; + + public IList VTablePointers + { + get + { + if (vTablePointers == null) + { + vTablePointers = new List(Fields.Where(f => f.IsVTablePtr)); + } + return vTablePointers; + } + } + + private List vTablePointers; } } diff --git a/src/AST/Field.cs b/src/AST/Field.cs index 71b86c63..acf360ce 100644 --- a/src/AST/Field.cs +++ b/src/AST/Field.cs @@ -10,8 +10,6 @@ namespace CppSharp.AST public Class Class { get; set; } - public Expression Expression { get; set; } - public bool IsBitField { get; set; } public uint BitWidth { get; set; } @@ -31,7 +29,6 @@ namespace CppSharp.AST { QualifiedType = field.QualifiedType; Class = field.Class; - Expression = field.Expression; IsBitField = field.IsBitField; BitWidth = field.BitWidth; } diff --git a/src/AST/LayoutField.cs b/src/AST/LayoutField.cs index 95f2bb67..37b84fd5 100644 --- a/src/AST/LayoutField.cs +++ b/src/AST/LayoutField.cs @@ -1,28 +1,20 @@ -namespace CppSharp.AST +using System; + +namespace CppSharp.AST { public class LayoutField { - public LayoutField(uint offset, Field field) - { - Field = field; - Offset = offset; - } - + public DeclarationContext Namespace { get; set; } public uint Offset { get; set; } - - public string Name - { - get { return name ?? Field.OriginalName; } - set { name = value; } - } - - public Field Field { get; set; } + public QualifiedType QualifiedType { get; set; } + public string Name { get; set; } + public IntPtr FieldPtr { get; set; } + public bool IsVTablePtr { get { return FieldPtr == IntPtr.Zero; } } + public Expression Expression { get; set; } public override string ToString() { - return string.Format("{0} | {1}", Offset, Field.OriginalName); + return string.Format("{0} | {1}", Offset, Name); } - - private string name; } } \ No newline at end of file diff --git a/src/Core/Parser/ASTConverter.cs b/src/Core/Parser/ASTConverter.cs index 4d8544c4..d27e0f14 100644 --- a/src/Core/Parser/ASTConverter.cs +++ b/src/Core/Parser/ASTConverter.cs @@ -687,7 +687,7 @@ namespace CppSharp public HashSet NativeObjects { get; private set; } - public override AST.Declaration Visit(Parser.AST.Declaration decl) + public override AST.Declaration Visit(Declaration decl) { if (decl == null) return null; @@ -1348,8 +1348,13 @@ namespace CppSharp for (uint i = 0; i < layout.FieldsCount; i++) { var field = layout.getFields(i); - _layout.Fields.Add(new AST.LayoutField(field.Offset, - (AST.Field) Visit(field.Field))); + var _field = new AST.LayoutField(); + _field.Namespace = (AST.DeclarationContext) Visit(field._Namespace); + _field.Offset = field.Offset; + _field.Name = field.Name; + _field.QualifiedType = typeConverter.VisitQualified(field.QualifiedType); + _field.FieldPtr = field.FieldPtr; + _layout.Fields.Add(_field); } return _layout; diff --git a/src/CppParser/AST.cpp b/src/CppParser/AST.cpp index 2465e815..988c2806 100644 --- a/src/CppParser/AST.cpp +++ b/src/CppParser/AST.cpp @@ -189,10 +189,21 @@ VFTableInfo::VFTableInfo(const VFTableInfo& rhs) : VBTableIndex(rhs.VBTableIndex VFPtrOffset(rhs.VFPtrOffset), VFPtrFullOffset(rhs.VFPtrFullOffset), Layout(rhs.Layout) {} -LayoutField::LayoutField() {} +LayoutField::LayoutField() : _Namespace(0), Offset(0), FieldPtr(0) {} + +LayoutField::LayoutField(const LayoutField & other) + : _Namespace(other._Namespace) + , Offset(other.Offset) + , Name(other.Name) + , QualifiedType(other.QualifiedType) + , FieldPtr(other.FieldPtr) +{ +} LayoutField::~LayoutField() {} +DEF_STRING(LayoutField, Name) + ClassLayout::ClassLayout() : ABI(CppAbi::Itanium), HasOwnVFPtr(false), VBPtrOffset(0), Alignment(0), Size(0), DataSize(0) {} diff --git a/src/CppParser/AST.h b/src/CppParser/AST.h index ff1141d2..08163788 100644 --- a/src/CppParser/AST.h +++ b/src/CppParser/AST.h @@ -315,15 +315,19 @@ struct CS_API VFTableInfo VTableLayout Layout; }; -class Field; +class DeclarationContext; class CS_API LayoutField { public: LayoutField(); + LayoutField(const LayoutField& other); ~LayoutField(); + DeclarationContext* _Namespace; unsigned Offset; - Field* Field; + STRING(Name) + QualifiedType QualifiedType; + void* FieldPtr; }; struct CS_API ClassLayout diff --git a/src/CppParser/Bindings/CLI/AST.cpp b/src/CppParser/Bindings/CLI/AST.cpp index 049d89a8..6c4469b2 100644 --- a/src/CppParser/Bindings/CLI/AST.cpp +++ b/src/CppParser/Bindings/CLI/AST.cpp @@ -1333,6 +1333,30 @@ void CppSharp::Parser::AST::LayoutField::__Instance::set(System::IntPtr object) NativePtr = (::CppSharp::CppParser::AST::LayoutField*)object.ToPointer(); } +System::String^ CppSharp::Parser::AST::LayoutField::Name::get() +{ + auto __ret = ((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->getName(); + if (__ret == nullptr) return nullptr; + return (__ret == 0 ? nullptr : clix::marshalString(__ret)); +} + +void CppSharp::Parser::AST::LayoutField::Name::set(System::String^ s) +{ + auto ___arg0 = clix::marshalString(s); + auto __arg0 = ___arg0.c_str(); + ((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->setName(__arg0); +} + +CppSharp::Parser::AST::DeclarationContext^ CppSharp::Parser::AST::LayoutField::_Namespace::get() +{ + return (((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->_Namespace == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::DeclarationContext((::CppSharp::CppParser::AST::DeclarationContext*)((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->_Namespace); +} + +void CppSharp::Parser::AST::LayoutField::_Namespace::set(CppSharp::Parser::AST::DeclarationContext^ value) +{ + ((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->_Namespace = (::CppSharp::CppParser::AST::DeclarationContext*)value->NativePtr; +} + unsigned int CppSharp::Parser::AST::LayoutField::Offset::get() { return ((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->Offset; @@ -1343,14 +1367,24 @@ void CppSharp::Parser::AST::LayoutField::Offset::set(unsigned int value) ((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->Offset = value; } -CppSharp::Parser::AST::Field^ CppSharp::Parser::AST::LayoutField::Field::get() +CppSharp::Parser::AST::QualifiedType^ CppSharp::Parser::AST::LayoutField::QualifiedType::get() +{ + return (&((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->QualifiedType == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::QualifiedType((::CppSharp::CppParser::AST::QualifiedType*)&((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->QualifiedType); +} + +void CppSharp::Parser::AST::LayoutField::QualifiedType::set(CppSharp::Parser::AST::QualifiedType^ value) +{ + ((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->QualifiedType = *(::CppSharp::CppParser::AST::QualifiedType*)value->NativePtr; +} + +::System::IntPtr CppSharp::Parser::AST::LayoutField::FieldPtr::get() { - return (((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->Field == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::Field((::CppSharp::CppParser::AST::Field*)((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->Field); + return ::System::IntPtr(((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->FieldPtr); } -void CppSharp::Parser::AST::LayoutField::Field::set(CppSharp::Parser::AST::Field^ value) +void CppSharp::Parser::AST::LayoutField::FieldPtr::set(::System::IntPtr value) { - ((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->Field = (::CppSharp::CppParser::AST::Field*)value->NativePtr; + ((::CppSharp::CppParser::AST::LayoutField*)NativePtr)->FieldPtr = (void*)value; } CppSharp::Parser::AST::ClassLayout::ClassLayout(::CppSharp::CppParser::AST::ClassLayout* native) diff --git a/src/CppParser/Bindings/CLI/AST.h b/src/CppParser/Bindings/CLI/AST.h index 87337aab..d541eb0c 100644 --- a/src/CppParser/Bindings/CLI/AST.h +++ b/src/CppParser/Bindings/CLI/AST.h @@ -1046,16 +1046,34 @@ namespace CppSharp ~LayoutField(); + property System::String^ Name + { + System::String^ get(); + void set(System::String^); + } + + property CppSharp::Parser::AST::DeclarationContext^ _Namespace + { + CppSharp::Parser::AST::DeclarationContext^ get(); + void set(CppSharp::Parser::AST::DeclarationContext^); + } + property unsigned int Offset { unsigned int get(); void set(unsigned int); } - property CppSharp::Parser::AST::Field^ Field + property CppSharp::Parser::AST::QualifiedType^ QualifiedType + { + CppSharp::Parser::AST::QualifiedType^ get(); + void set(CppSharp::Parser::AST::QualifiedType^); + } + + property ::System::IntPtr FieldPtr { - CppSharp::Parser::AST::Field^ get(); - void set(CppSharp::Parser::AST::Field^); + ::System::IntPtr get(); + void set(::System::IntPtr); } protected: diff --git a/src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/AST.cs b/src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/AST.cs index 8242aa51..6ff8a292 100644 --- a/src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/AST.cs +++ b/src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/AST.cs @@ -2987,14 +2987,20 @@ namespace CppSharp public unsafe partial class LayoutField : IDisposable { - [StructLayout(LayoutKind.Explicit, Size = 8)] + [StructLayout(LayoutKind.Explicit, Size = 32)] public partial struct Internal { [FieldOffset(0)] - public uint Offset; + public global::System.IntPtr _Namespace; [FieldOffset(4)] - public global::System.IntPtr Field; + public uint Offset; + + [FieldOffset(20)] + public CppSharp.Parser.AST.QualifiedType.Internal QualifiedType; + + [FieldOffset(28)] + public global::System.IntPtr FieldPtr; [SuppressUnmanagedCodeSecurity] [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, @@ -3010,6 +3016,16 @@ namespace CppSharp [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, EntryPoint="_ZN8CppSharp9CppParser3AST11LayoutFieldD2Ev")] internal static extern void dtor_0(global::System.IntPtr instance); + + [SuppressUnmanagedCodeSecurity] + [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, + EntryPoint="_ZN8CppSharp9CppParser3AST11LayoutField7getNameEv")] + internal static extern global::System.IntPtr getName_0(global::System.IntPtr instance); + + [SuppressUnmanagedCodeSecurity] + [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, + EntryPoint="_ZN8CppSharp9CppParser3AST11LayoutField7setNameEPKc")] + internal static extern void setName_0(global::System.IntPtr instance, global::System.IntPtr s); } public global::System.IntPtr __Instance { get; protected set; } @@ -3032,8 +3048,8 @@ namespace CppSharp private static void* __CopyValue(LayoutField.Internal native) { - var ret = Marshal.AllocHGlobal(8); - *(LayoutField.Internal*) ret = native; + var ret = Marshal.AllocHGlobal(32); + CppSharp.Parser.AST.LayoutField.Internal.cctor_1(ret, new global::System.IntPtr(&native)); return ret.ToPointer(); } @@ -3053,7 +3069,7 @@ namespace CppSharp public LayoutField() { - __Instance = Marshal.AllocHGlobal(8); + __Instance = Marshal.AllocHGlobal(32); __ownsNativeInstance = true; NativeToManagedMap[__Instance] = this; Internal.ctor_0((__Instance + __PointerAdjustment)); @@ -3061,10 +3077,13 @@ namespace CppSharp public LayoutField(CppSharp.Parser.AST.LayoutField _0) { - __Instance = Marshal.AllocHGlobal(8); + __Instance = Marshal.AllocHGlobal(32); __ownsNativeInstance = true; NativeToManagedMap[__Instance] = this; - *((LayoutField.Internal*) __Instance) = *((LayoutField.Internal*) _0.__Instance); + if (ReferenceEquals(_0, null)) + throw new global::System.ArgumentNullException("_0", "Cannot be null because it is a C++ reference (&)."); + var __arg0 = _0.__Instance; + Internal.cctor_1((__Instance + __PointerAdjustment), __arg0); } public void Dispose() @@ -3081,6 +3100,40 @@ namespace CppSharp Marshal.FreeHGlobal(__Instance); } + public string Name + { + get + { + var __ret = Internal.getName_0((__Instance + __PointerAdjustment)); + return Marshal.PtrToStringAnsi(__ret); + } + + set + { + var __arg0 = Marshal.StringToHGlobalAnsi(value); + Internal.setName_0((__Instance + __PointerAdjustment), __arg0); + Marshal.FreeHGlobal(__arg0); + } + } + + public CppSharp.Parser.AST.DeclarationContext _Namespace + { + get + { + CppSharp.Parser.AST.DeclarationContext __result0; + if (((Internal*) __Instance)->_Namespace == IntPtr.Zero) __result0 = null; + else if (CppSharp.Parser.AST.DeclarationContext.NativeToManagedMap.ContainsKey(((Internal*) __Instance)->_Namespace)) + __result0 = (CppSharp.Parser.AST.DeclarationContext) CppSharp.Parser.AST.DeclarationContext.NativeToManagedMap[((Internal*) __Instance)->_Namespace]; + else __result0 = CppSharp.Parser.AST.DeclarationContext.__CreateInstance(((Internal*) __Instance)->_Namespace); + return __result0; + } + + set + { + ((Internal*) __Instance)->_Namespace = ReferenceEquals(value, null) ? global::System.IntPtr.Zero : value.__Instance; + } + } + public uint Offset { get @@ -3094,21 +3147,29 @@ namespace CppSharp } } - public CppSharp.Parser.AST.Field Field + public CppSharp.Parser.AST.QualifiedType QualifiedType { get { - CppSharp.Parser.AST.Field __result0; - if (((Internal*) __Instance)->Field == IntPtr.Zero) __result0 = null; - else if (CppSharp.Parser.AST.Field.NativeToManagedMap.ContainsKey(((Internal*) __Instance)->Field)) - __result0 = (CppSharp.Parser.AST.Field) CppSharp.Parser.AST.Field.NativeToManagedMap[((Internal*) __Instance)->Field]; - else __result0 = CppSharp.Parser.AST.Field.__CreateInstance(((Internal*) __Instance)->Field); - return __result0; + return CppSharp.Parser.AST.QualifiedType.__CreateInstance(((Internal*) __Instance)->QualifiedType); + } + + set + { + ((Internal*) __Instance)->QualifiedType = ReferenceEquals(value, null) ? new CppSharp.Parser.AST.QualifiedType.Internal() : *(CppSharp.Parser.AST.QualifiedType.Internal*) (value.__Instance); + } + } + + public global::System.IntPtr FieldPtr + { + get + { + return ((Internal*) __Instance)->FieldPtr; } set { - ((Internal*) __Instance)->Field = ReferenceEquals(value, null) ? global::System.IntPtr.Zero : value.__Instance; + ((Internal*) __Instance)->FieldPtr = (global::System.IntPtr) value; } } } diff --git a/src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/AST.cs b/src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/AST.cs index 128f3a6b..cfdf45da 100644 --- a/src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/AST.cs +++ b/src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/AST.cs @@ -2987,14 +2987,20 @@ namespace CppSharp public unsafe partial class LayoutField : IDisposable { - [StructLayout(LayoutKind.Explicit, Size = 8)] + [StructLayout(LayoutKind.Explicit, Size = 44)] public partial struct Internal { [FieldOffset(0)] - public uint Offset; + public global::System.IntPtr _Namespace; [FieldOffset(4)] - public global::System.IntPtr Field; + public uint Offset; + + [FieldOffset(32)] + public CppSharp.Parser.AST.QualifiedType.Internal QualifiedType; + + [FieldOffset(40)] + public global::System.IntPtr FieldPtr; [SuppressUnmanagedCodeSecurity] [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall, @@ -3010,6 +3016,16 @@ namespace CppSharp [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall, EntryPoint="??1LayoutField@AST@CppParser@CppSharp@@QAE@XZ")] internal static extern void dtor_0(global::System.IntPtr instance, int delete); + + [SuppressUnmanagedCodeSecurity] + [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall, + EntryPoint="?getName@LayoutField@AST@CppParser@CppSharp@@QAEPBDXZ")] + internal static extern global::System.IntPtr getName_0(global::System.IntPtr instance); + + [SuppressUnmanagedCodeSecurity] + [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall, + EntryPoint="?setName@LayoutField@AST@CppParser@CppSharp@@QAEXPBD@Z")] + internal static extern void setName_0(global::System.IntPtr instance, global::System.IntPtr s); } public global::System.IntPtr __Instance { get; protected set; } @@ -3032,8 +3048,8 @@ namespace CppSharp private static void* __CopyValue(LayoutField.Internal native) { - var ret = Marshal.AllocHGlobal(8); - *(LayoutField.Internal*) ret = native; + var ret = Marshal.AllocHGlobal(44); + CppSharp.Parser.AST.LayoutField.Internal.cctor_1(ret, new global::System.IntPtr(&native)); return ret.ToPointer(); } @@ -3053,7 +3069,7 @@ namespace CppSharp public LayoutField() { - __Instance = Marshal.AllocHGlobal(8); + __Instance = Marshal.AllocHGlobal(44); __ownsNativeInstance = true; NativeToManagedMap[__Instance] = this; Internal.ctor_0((__Instance + __PointerAdjustment)); @@ -3061,10 +3077,13 @@ namespace CppSharp public LayoutField(CppSharp.Parser.AST.LayoutField _0) { - __Instance = Marshal.AllocHGlobal(8); + __Instance = Marshal.AllocHGlobal(44); __ownsNativeInstance = true; NativeToManagedMap[__Instance] = this; - *((LayoutField.Internal*) __Instance) = *((LayoutField.Internal*) _0.__Instance); + if (ReferenceEquals(_0, null)) + throw new global::System.ArgumentNullException("_0", "Cannot be null because it is a C++ reference (&)."); + var __arg0 = _0.__Instance; + Internal.cctor_1((__Instance + __PointerAdjustment), __arg0); } public void Dispose() @@ -3081,6 +3100,40 @@ namespace CppSharp Marshal.FreeHGlobal(__Instance); } + public string Name + { + get + { + var __ret = Internal.getName_0((__Instance + __PointerAdjustment)); + return Marshal.PtrToStringAnsi(__ret); + } + + set + { + var __arg0 = Marshal.StringToHGlobalAnsi(value); + Internal.setName_0((__Instance + __PointerAdjustment), __arg0); + Marshal.FreeHGlobal(__arg0); + } + } + + public CppSharp.Parser.AST.DeclarationContext _Namespace + { + get + { + CppSharp.Parser.AST.DeclarationContext __result0; + if (((Internal*) __Instance)->_Namespace == IntPtr.Zero) __result0 = null; + else if (CppSharp.Parser.AST.DeclarationContext.NativeToManagedMap.ContainsKey(((Internal*) __Instance)->_Namespace)) + __result0 = (CppSharp.Parser.AST.DeclarationContext) CppSharp.Parser.AST.DeclarationContext.NativeToManagedMap[((Internal*) __Instance)->_Namespace]; + else __result0 = CppSharp.Parser.AST.DeclarationContext.__CreateInstance(((Internal*) __Instance)->_Namespace); + return __result0; + } + + set + { + ((Internal*) __Instance)->_Namespace = ReferenceEquals(value, null) ? global::System.IntPtr.Zero : value.__Instance; + } + } + public uint Offset { get @@ -3094,21 +3147,29 @@ namespace CppSharp } } - public CppSharp.Parser.AST.Field Field + public CppSharp.Parser.AST.QualifiedType QualifiedType { get { - CppSharp.Parser.AST.Field __result0; - if (((Internal*) __Instance)->Field == IntPtr.Zero) __result0 = null; - else if (CppSharp.Parser.AST.Field.NativeToManagedMap.ContainsKey(((Internal*) __Instance)->Field)) - __result0 = (CppSharp.Parser.AST.Field) CppSharp.Parser.AST.Field.NativeToManagedMap[((Internal*) __Instance)->Field]; - else __result0 = CppSharp.Parser.AST.Field.__CreateInstance(((Internal*) __Instance)->Field); - return __result0; + return CppSharp.Parser.AST.QualifiedType.__CreateInstance(((Internal*) __Instance)->QualifiedType); + } + + set + { + ((Internal*) __Instance)->QualifiedType = ReferenceEquals(value, null) ? new CppSharp.Parser.AST.QualifiedType.Internal() : *(CppSharp.Parser.AST.QualifiedType.Internal*) (value.__Instance); + } + } + + public global::System.IntPtr FieldPtr + { + get + { + return ((Internal*) __Instance)->FieldPtr; } set { - ((Internal*) __Instance)->Field = ReferenceEquals(value, null) ? global::System.IntPtr.Zero : value.__Instance; + ((Internal*) __Instance)->FieldPtr = (global::System.IntPtr) value; } } } diff --git a/src/CppParser/Bindings/CSharp/x86_64-apple-darwin12.4.0/AST.cs b/src/CppParser/Bindings/CSharp/x86_64-apple-darwin12.4.0/AST.cs index 3c6f020f..fa10e3a0 100644 --- a/src/CppParser/Bindings/CSharp/x86_64-apple-darwin12.4.0/AST.cs +++ b/src/CppParser/Bindings/CSharp/x86_64-apple-darwin12.4.0/AST.cs @@ -2986,14 +2986,20 @@ namespace CppSharp public unsafe partial class LayoutField : IDisposable { - [StructLayout(LayoutKind.Explicit, Size = 16)] + [StructLayout(LayoutKind.Explicit, Size = 64)] public partial struct Internal { [FieldOffset(0)] - public uint Offset; + public global::System.IntPtr _Namespace; [FieldOffset(8)] - public global::System.IntPtr Field; + public uint Offset; + + [FieldOffset(40)] + public CppSharp.Parser.AST.QualifiedType.Internal QualifiedType; + + [FieldOffset(56)] + public global::System.IntPtr FieldPtr; [SuppressUnmanagedCodeSecurity] [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, @@ -3009,6 +3015,16 @@ namespace CppSharp [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, EntryPoint="_ZN8CppSharp9CppParser3AST11LayoutFieldD2Ev")] internal static extern void dtor_0(global::System.IntPtr instance); + + [SuppressUnmanagedCodeSecurity] + [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, + EntryPoint="_ZN8CppSharp9CppParser3AST11LayoutField7getNameEv")] + internal static extern global::System.IntPtr getName_0(global::System.IntPtr instance); + + [SuppressUnmanagedCodeSecurity] + [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, + EntryPoint="_ZN8CppSharp9CppParser3AST11LayoutField7setNameEPKc")] + internal static extern void setName_0(global::System.IntPtr instance, global::System.IntPtr s); } public global::System.IntPtr __Instance { get; protected set; } @@ -3031,8 +3047,8 @@ namespace CppSharp private static void* __CopyValue(LayoutField.Internal native) { - var ret = Marshal.AllocHGlobal(16); - *(LayoutField.Internal*) ret = native; + var ret = Marshal.AllocHGlobal(64); + CppSharp.Parser.AST.LayoutField.Internal.cctor_1(ret, new global::System.IntPtr(&native)); return ret.ToPointer(); } @@ -3052,7 +3068,7 @@ namespace CppSharp public LayoutField() { - __Instance = Marshal.AllocHGlobal(16); + __Instance = Marshal.AllocHGlobal(64); __ownsNativeInstance = true; NativeToManagedMap[__Instance] = this; Internal.ctor_0((__Instance + __PointerAdjustment)); @@ -3060,10 +3076,13 @@ namespace CppSharp public LayoutField(CppSharp.Parser.AST.LayoutField _0) { - __Instance = Marshal.AllocHGlobal(16); + __Instance = Marshal.AllocHGlobal(64); __ownsNativeInstance = true; NativeToManagedMap[__Instance] = this; - *((LayoutField.Internal*) __Instance) = *((LayoutField.Internal*) _0.__Instance); + if (ReferenceEquals(_0, null)) + throw new global::System.ArgumentNullException("_0", "Cannot be null because it is a C++ reference (&)."); + var __arg0 = _0.__Instance; + Internal.cctor_1((__Instance + __PointerAdjustment), __arg0); } public void Dispose() @@ -3080,6 +3099,40 @@ namespace CppSharp Marshal.FreeHGlobal(__Instance); } + public string Name + { + get + { + var __ret = Internal.getName_0((__Instance + __PointerAdjustment)); + return Marshal.PtrToStringAnsi(__ret); + } + + set + { + var __arg0 = Marshal.StringToHGlobalAnsi(value); + Internal.setName_0((__Instance + __PointerAdjustment), __arg0); + Marshal.FreeHGlobal(__arg0); + } + } + + public CppSharp.Parser.AST.DeclarationContext _Namespace + { + get + { + CppSharp.Parser.AST.DeclarationContext __result0; + if (((Internal*) __Instance)->_Namespace == IntPtr.Zero) __result0 = null; + else if (CppSharp.Parser.AST.DeclarationContext.NativeToManagedMap.ContainsKey(((Internal*) __Instance)->_Namespace)) + __result0 = (CppSharp.Parser.AST.DeclarationContext) CppSharp.Parser.AST.DeclarationContext.NativeToManagedMap[((Internal*) __Instance)->_Namespace]; + else __result0 = CppSharp.Parser.AST.DeclarationContext.__CreateInstance(((Internal*) __Instance)->_Namespace); + return __result0; + } + + set + { + ((Internal*) __Instance)->_Namespace = ReferenceEquals(value, null) ? global::System.IntPtr.Zero : value.__Instance; + } + } + public uint Offset { get @@ -3093,21 +3146,29 @@ namespace CppSharp } } - public CppSharp.Parser.AST.Field Field + public CppSharp.Parser.AST.QualifiedType QualifiedType { get { - CppSharp.Parser.AST.Field __result0; - if (((Internal*) __Instance)->Field == IntPtr.Zero) __result0 = null; - else if (CppSharp.Parser.AST.Field.NativeToManagedMap.ContainsKey(((Internal*) __Instance)->Field)) - __result0 = (CppSharp.Parser.AST.Field) CppSharp.Parser.AST.Field.NativeToManagedMap[((Internal*) __Instance)->Field]; - else __result0 = CppSharp.Parser.AST.Field.__CreateInstance(((Internal*) __Instance)->Field); - return __result0; + return CppSharp.Parser.AST.QualifiedType.__CreateInstance(((Internal*) __Instance)->QualifiedType); + } + + set + { + ((Internal*) __Instance)->QualifiedType = ReferenceEquals(value, null) ? new CppSharp.Parser.AST.QualifiedType.Internal() : *(CppSharp.Parser.AST.QualifiedType.Internal*) (value.__Instance); + } + } + + public global::System.IntPtr FieldPtr + { + get + { + return ((Internal*) __Instance)->FieldPtr; } set { - ((Internal*) __Instance)->Field = ReferenceEquals(value, null) ? global::System.IntPtr.Zero : value.__Instance; + ((Internal*) __Instance)->FieldPtr = (global::System.IntPtr) value; } } } diff --git a/src/CppParser/Bindings/CSharp/x86_64-linux-gnu/AST.cs b/src/CppParser/Bindings/CSharp/x86_64-linux-gnu/AST.cs index 67d6da47..c612ec5d 100644 --- a/src/CppParser/Bindings/CSharp/x86_64-linux-gnu/AST.cs +++ b/src/CppParser/Bindings/CSharp/x86_64-linux-gnu/AST.cs @@ -2986,14 +2986,20 @@ namespace CppSharp public unsafe partial class LayoutField : IDisposable { - [StructLayout(LayoutKind.Explicit, Size = 16)] + [StructLayout(LayoutKind.Explicit, Size = 48)] public partial struct Internal { [FieldOffset(0)] - public uint Offset; + public global::System.IntPtr _Namespace; [FieldOffset(8)] - public global::System.IntPtr Field; + public uint Offset; + + [FieldOffset(24)] + public CppSharp.Parser.AST.QualifiedType.Internal QualifiedType; + + [FieldOffset(40)] + public global::System.IntPtr FieldPtr; [SuppressUnmanagedCodeSecurity] [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, @@ -3009,6 +3015,16 @@ namespace CppSharp [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, EntryPoint="_ZN8CppSharp9CppParser3AST11LayoutFieldD2Ev")] internal static extern void dtor_0(global::System.IntPtr instance); + + [SuppressUnmanagedCodeSecurity] + [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, + EntryPoint="_ZN8CppSharp9CppParser3AST11LayoutField7getNameEv")] + internal static extern global::System.IntPtr getName_0(global::System.IntPtr instance); + + [SuppressUnmanagedCodeSecurity] + [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, + EntryPoint="_ZN8CppSharp9CppParser3AST11LayoutField7setNameEPKc")] + internal static extern void setName_0(global::System.IntPtr instance, global::System.IntPtr s); } public global::System.IntPtr __Instance { get; protected set; } @@ -3031,8 +3047,8 @@ namespace CppSharp private static void* __CopyValue(LayoutField.Internal native) { - var ret = Marshal.AllocHGlobal(16); - *(LayoutField.Internal*) ret = native; + var ret = Marshal.AllocHGlobal(48); + CppSharp.Parser.AST.LayoutField.Internal.cctor_1(ret, new global::System.IntPtr(&native)); return ret.ToPointer(); } @@ -3052,7 +3068,7 @@ namespace CppSharp public LayoutField() { - __Instance = Marshal.AllocHGlobal(16); + __Instance = Marshal.AllocHGlobal(48); __ownsNativeInstance = true; NativeToManagedMap[__Instance] = this; Internal.ctor_0((__Instance + __PointerAdjustment)); @@ -3060,10 +3076,13 @@ namespace CppSharp public LayoutField(CppSharp.Parser.AST.LayoutField _0) { - __Instance = Marshal.AllocHGlobal(16); + __Instance = Marshal.AllocHGlobal(48); __ownsNativeInstance = true; NativeToManagedMap[__Instance] = this; - *((LayoutField.Internal*) __Instance) = *((LayoutField.Internal*) _0.__Instance); + if (ReferenceEquals(_0, null)) + throw new global::System.ArgumentNullException("_0", "Cannot be null because it is a C++ reference (&)."); + var __arg0 = _0.__Instance; + Internal.cctor_1((__Instance + __PointerAdjustment), __arg0); } public void Dispose() @@ -3080,6 +3099,40 @@ namespace CppSharp Marshal.FreeHGlobal(__Instance); } + public string Name + { + get + { + var __ret = Internal.getName_0((__Instance + __PointerAdjustment)); + return Marshal.PtrToStringAnsi(__ret); + } + + set + { + var __arg0 = Marshal.StringToHGlobalAnsi(value); + Internal.setName_0((__Instance + __PointerAdjustment), __arg0); + Marshal.FreeHGlobal(__arg0); + } + } + + public CppSharp.Parser.AST.DeclarationContext _Namespace + { + get + { + CppSharp.Parser.AST.DeclarationContext __result0; + if (((Internal*) __Instance)->_Namespace == IntPtr.Zero) __result0 = null; + else if (CppSharp.Parser.AST.DeclarationContext.NativeToManagedMap.ContainsKey(((Internal*) __Instance)->_Namespace)) + __result0 = (CppSharp.Parser.AST.DeclarationContext) CppSharp.Parser.AST.DeclarationContext.NativeToManagedMap[((Internal*) __Instance)->_Namespace]; + else __result0 = CppSharp.Parser.AST.DeclarationContext.__CreateInstance(((Internal*) __Instance)->_Namespace); + return __result0; + } + + set + { + ((Internal*) __Instance)->_Namespace = ReferenceEquals(value, null) ? global::System.IntPtr.Zero : value.__Instance; + } + } + public uint Offset { get @@ -3093,21 +3146,29 @@ namespace CppSharp } } - public CppSharp.Parser.AST.Field Field + public CppSharp.Parser.AST.QualifiedType QualifiedType { get { - CppSharp.Parser.AST.Field __result0; - if (((Internal*) __Instance)->Field == IntPtr.Zero) __result0 = null; - else if (CppSharp.Parser.AST.Field.NativeToManagedMap.ContainsKey(((Internal*) __Instance)->Field)) - __result0 = (CppSharp.Parser.AST.Field) CppSharp.Parser.AST.Field.NativeToManagedMap[((Internal*) __Instance)->Field]; - else __result0 = CppSharp.Parser.AST.Field.__CreateInstance(((Internal*) __Instance)->Field); - return __result0; + return CppSharp.Parser.AST.QualifiedType.__CreateInstance(((Internal*) __Instance)->QualifiedType); + } + + set + { + ((Internal*) __Instance)->QualifiedType = ReferenceEquals(value, null) ? new CppSharp.Parser.AST.QualifiedType.Internal() : *(CppSharp.Parser.AST.QualifiedType.Internal*) (value.__Instance); + } + } + + public global::System.IntPtr FieldPtr + { + get + { + return ((Internal*) __Instance)->FieldPtr; } set { - ((Internal*) __Instance)->Field = ReferenceEquals(value, null) ? global::System.IntPtr.Zero : value.__Instance; + ((Internal*) __Instance)->FieldPtr = (global::System.IntPtr) value; } } } diff --git a/src/CppParser/Bindings/CSharp/x86_64-pc-win32-msvc/AST.cs b/src/CppParser/Bindings/CSharp/x86_64-pc-win32-msvc/AST.cs index e7d27a39..8e29fdd9 100644 --- a/src/CppParser/Bindings/CSharp/x86_64-pc-win32-msvc/AST.cs +++ b/src/CppParser/Bindings/CSharp/x86_64-pc-win32-msvc/AST.cs @@ -2987,14 +2987,20 @@ namespace CppSharp public unsafe partial class LayoutField : IDisposable { - [StructLayout(LayoutKind.Explicit, Size = 16)] + [StructLayout(LayoutKind.Explicit, Size = 72)] public partial struct Internal { [FieldOffset(0)] - public uint Offset; + public global::System.IntPtr _Namespace; [FieldOffset(8)] - public global::System.IntPtr Field; + public uint Offset; + + [FieldOffset(48)] + public CppSharp.Parser.AST.QualifiedType.Internal QualifiedType; + + [FieldOffset(64)] + public global::System.IntPtr FieldPtr; [SuppressUnmanagedCodeSecurity] [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, @@ -3010,6 +3016,16 @@ namespace CppSharp [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, EntryPoint="??1LayoutField@AST@CppParser@CppSharp@@QEAA@XZ")] internal static extern void dtor_0(global::System.IntPtr instance, int delete); + + [SuppressUnmanagedCodeSecurity] + [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, + EntryPoint="?getName@LayoutField@AST@CppParser@CppSharp@@QEAAPEBDXZ")] + internal static extern global::System.IntPtr getName_0(global::System.IntPtr instance); + + [SuppressUnmanagedCodeSecurity] + [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, + EntryPoint="?setName@LayoutField@AST@CppParser@CppSharp@@QEAAXPEBD@Z")] + internal static extern void setName_0(global::System.IntPtr instance, global::System.IntPtr s); } public global::System.IntPtr __Instance { get; protected set; } @@ -3032,8 +3048,8 @@ namespace CppSharp private static void* __CopyValue(LayoutField.Internal native) { - var ret = Marshal.AllocHGlobal(16); - *(LayoutField.Internal*) ret = native; + var ret = Marshal.AllocHGlobal(72); + CppSharp.Parser.AST.LayoutField.Internal.cctor_1(ret, new global::System.IntPtr(&native)); return ret.ToPointer(); } @@ -3053,7 +3069,7 @@ namespace CppSharp public LayoutField() { - __Instance = Marshal.AllocHGlobal(16); + __Instance = Marshal.AllocHGlobal(72); __ownsNativeInstance = true; NativeToManagedMap[__Instance] = this; Internal.ctor_0((__Instance + __PointerAdjustment)); @@ -3061,10 +3077,13 @@ namespace CppSharp public LayoutField(CppSharp.Parser.AST.LayoutField _0) { - __Instance = Marshal.AllocHGlobal(16); + __Instance = Marshal.AllocHGlobal(72); __ownsNativeInstance = true; NativeToManagedMap[__Instance] = this; - *((LayoutField.Internal*) __Instance) = *((LayoutField.Internal*) _0.__Instance); + if (ReferenceEquals(_0, null)) + throw new global::System.ArgumentNullException("_0", "Cannot be null because it is a C++ reference (&)."); + var __arg0 = _0.__Instance; + Internal.cctor_1((__Instance + __PointerAdjustment), __arg0); } public void Dispose() @@ -3081,6 +3100,40 @@ namespace CppSharp Marshal.FreeHGlobal(__Instance); } + public string Name + { + get + { + var __ret = Internal.getName_0((__Instance + __PointerAdjustment)); + return Marshal.PtrToStringAnsi(__ret); + } + + set + { + var __arg0 = Marshal.StringToHGlobalAnsi(value); + Internal.setName_0((__Instance + __PointerAdjustment), __arg0); + Marshal.FreeHGlobal(__arg0); + } + } + + public CppSharp.Parser.AST.DeclarationContext _Namespace + { + get + { + CppSharp.Parser.AST.DeclarationContext __result0; + if (((Internal*) __Instance)->_Namespace == IntPtr.Zero) __result0 = null; + else if (CppSharp.Parser.AST.DeclarationContext.NativeToManagedMap.ContainsKey(((Internal*) __Instance)->_Namespace)) + __result0 = (CppSharp.Parser.AST.DeclarationContext) CppSharp.Parser.AST.DeclarationContext.NativeToManagedMap[((Internal*) __Instance)->_Namespace]; + else __result0 = CppSharp.Parser.AST.DeclarationContext.__CreateInstance(((Internal*) __Instance)->_Namespace); + return __result0; + } + + set + { + ((Internal*) __Instance)->_Namespace = ReferenceEquals(value, null) ? global::System.IntPtr.Zero : value.__Instance; + } + } + public uint Offset { get @@ -3094,21 +3147,29 @@ namespace CppSharp } } - public CppSharp.Parser.AST.Field Field + public CppSharp.Parser.AST.QualifiedType QualifiedType { get { - CppSharp.Parser.AST.Field __result0; - if (((Internal*) __Instance)->Field == IntPtr.Zero) __result0 = null; - else if (CppSharp.Parser.AST.Field.NativeToManagedMap.ContainsKey(((Internal*) __Instance)->Field)) - __result0 = (CppSharp.Parser.AST.Field) CppSharp.Parser.AST.Field.NativeToManagedMap[((Internal*) __Instance)->Field]; - else __result0 = CppSharp.Parser.AST.Field.__CreateInstance(((Internal*) __Instance)->Field); - return __result0; + return CppSharp.Parser.AST.QualifiedType.__CreateInstance(((Internal*) __Instance)->QualifiedType); + } + + set + { + ((Internal*) __Instance)->QualifiedType = ReferenceEquals(value, null) ? new CppSharp.Parser.AST.QualifiedType.Internal() : *(CppSharp.Parser.AST.QualifiedType.Internal*) (value.__Instance); + } + } + + public global::System.IntPtr FieldPtr + { + get + { + return ((Internal*) __Instance)->FieldPtr; } set { - ((Internal*) __Instance)->Field = ReferenceEquals(value, null) ? global::System.IntPtr.Zero : value.__Instance; + ((Internal*) __Instance)->FieldPtr = (global::System.IntPtr) value; } } } diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp index 5a6f3bbf..58796142 100644 --- a/src/CppParser/Parser.cpp +++ b/src/CppParser/Parser.cpp @@ -82,7 +82,18 @@ std::string GetCurrentLibraryDir() #endif } -void Parser::ReadLayoutFields(Class* Class, const clang::RecordDecl *RD, +LayoutField Parser::WalkVTablePointer(Class* Class, + const clang::CharUnits& Offset, const std::string& prefix) +{ + LayoutField LayoutField; + LayoutField.Offset = Offset.getQuantity(); + LayoutField._Namespace = Class; + LayoutField.Name = prefix + "_" + Class->Name; + LayoutField.QualifiedType = GetQualifiedType(C->getASTContext().VoidPtrTy); + return LayoutField; +} + +void Parser::ReadLayoutFields(Class* Class, const clang::RecordDecl* RD, clang::CharUnits Offset, bool IncludeVirtualBases) { using namespace clang; @@ -90,8 +101,26 @@ void Parser::ReadLayoutFields(Class* Class, const clang::RecordDecl *RD, const auto &Layout = C->getASTContext().getASTRecordLayout(RD); auto CXXRD = dyn_cast(RD); + auto Parent = static_cast( + WalkDeclaration(RD, /*IgnoreSystemDecls =*/false)); + // Dump bases. if (CXXRD) { + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + bool HasOwnVFPtr = Layout.hasOwnVFPtr(); + bool HasOwnVBPtr = Layout.hasOwnVBPtr(); + + // Vtable pointer. + if (CXXRD->isDynamicClass() && !PrimaryBase && + !C->getASTContext().getTargetInfo().getCXXABI().isMicrosoft()) { + auto VPtr = WalkVTablePointer(Parent, Offset, "vptr"); + Class->Layout->Fields.push_back(VPtr); + } + else if (HasOwnVFPtr) { + auto VTPtr = WalkVTablePointer(Parent, Offset, "vfptr"); + Class->Layout->Fields.push_back(VTPtr); + } + // Collect nvbases. SmallVector Bases; for (const CXXBaseSpecifier &Base : CXXRD->bases()) { @@ -113,30 +142,39 @@ void Parser::ReadLayoutFields(Class* Class, const clang::RecordDecl *RD, ReadLayoutFields(Class, Base, BaseOffset, /*IncludeVirtualBases=*/false); } + + // vbptr (for Microsoft C++ ABI) + if (HasOwnVBPtr) { + auto VBPtr = WalkVTablePointer(Parent, + Offset + Layout.getVBPtrOffset(), "vbptr"); + Class->Layout->Fields.push_back(VBPtr); + } } // Dump fields. uint64_t FieldNo = 0; for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++FieldNo) { - const FieldDecl &Field = **I; + auto Field = *I; uint64_t LocalFieldOffsetInBits = Layout.getFieldOffset(FieldNo); CharUnits FieldOffset = Offset + C->getASTContext().toCharUnitsFromBits(LocalFieldOffsetInBits); // Recursively dump fields of record type. - if (auto RT = Field.getType()->getAs()) + if (auto RT = Field->getType()->getAs()) { auto TU = GetTranslationUnit(RT->getDecl()); if (TU->IsSystemHeader) continue; } - auto Parent = WalkDeclaration(RD, /*IgnoreSystemDecls =*/false); - auto F = WalkFieldCXX(&Field, static_cast(Parent)); + auto F = WalkFieldCXX(Field, Parent); LayoutField LayoutField; + LayoutField._Namespace = F->_Namespace; LayoutField.Offset = FieldOffset.getQuantity(); - LayoutField.Field = F; + LayoutField.Name = F->Name; + LayoutField.QualifiedType = GetQualifiedType(Field->getType()); + LayoutField.FieldPtr = (void*)Field; Class->Layout->Fields.push_back(LayoutField); } @@ -151,6 +189,12 @@ void Parser::ReadLayoutFields(Class* Class, const clang::RecordDecl *RD, CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase); + if (VtorDisps.find(VBase)->second.hasVtorDisp()) { + auto VtorDisp = WalkVTablePointer(Parent, + VBaseOffset - CharUnits::fromQuantity(4), "vtordisp"); + Class->Layout->Fields.push_back(VtorDisp); + } + ReadLayoutFields(Class, VBase, VBaseOffset, /*IncludeVirtualBases=*/false); } diff --git a/src/CppParser/Parser.h b/src/CppParser/Parser.h index bcc0bba0..b0c1c514 100644 --- a/src/CppParser/Parser.h +++ b/src/CppParser/Parser.h @@ -98,7 +98,8 @@ private: std::vector WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, const clang::ASTTemplateArgumentListInfo* TSTL); void WalkVTable(const clang::CXXRecordDecl* RD, Class* C); QualifiedType GetQualifiedType(clang::QualType qual, clang::TypeLoc* TL = 0); - void ReadLayoutFields(Class * Class, const clang::RecordDecl * RD, clang::CharUnits Offset, bool IncludeVirtualBases); + void ReadLayoutFields(Class* Class, const clang::RecordDecl* RD, clang::CharUnits Offset, bool IncludeVirtualBases); + LayoutField WalkVTablePointer(Class* Class, const clang::CharUnits& Offset, const std::string& prefix); VTableLayout WalkVTableLayout(const clang::VTableLayout& VTLayout); VTableComponent WalkVTableComponent(const clang::VTableComponent& Component); PreprocessedEntity* WalkPreprocessedEntity(Declaration* Decl, diff --git a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs index ad16d084..1bb54e72 100644 --- a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs +++ b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs @@ -439,9 +439,9 @@ namespace CppSharp.Generators.CLI PushIndent(); // check for value types because some of the ignored fields may back properties; // not the case for ref types because the NativePtr pattern is used there - foreach (var field in @class.Layout.Fields.Where(f => !ASTUtils.CheckIgnoreField(f.Field))) + foreach (var field in @class.Fields.Where(f => !ASTUtils.CheckIgnoreField(f))) { - var property = @class.Properties.FirstOrDefault(p => p.Field == field.Field); + var property = @class.Properties.FirstOrDefault(p => p.Field == field); if (property != null && !property.IsInRefTypeAndBackedByValueClassField()) { GenerateField(@class, field); @@ -450,15 +450,16 @@ namespace CppSharp.Generators.CLI PopIndent(); } - private void GenerateField(Class @class, LayoutField layoutField) + private void GenerateField(Class @class, Field field) { - PushBlock(CLIBlockKind.Field, layoutField.Field); + PushBlock(CLIBlockKind.Field, field); - GenerateDeclarationCommon(layoutField.Field); + GenerateDeclarationCommon(field); if (@class.IsUnion) WriteLine("[System::Runtime::InteropServices::FieldOffset({0})]", - layoutField.Offset); - WriteLine("{0} {1};", layoutField.Field.Type, layoutField.Field.Name); + @class.Layout.Fields.Single( + f => f.Namespace == @class && f.FieldPtr == field.OriginalPtr).Offset); + WriteLine("{0} {1};", field.Type, field.Name); PopBlock(); } @@ -630,7 +631,7 @@ namespace CppSharp.Generators.CLI { if (prop.IsInRefTypeAndBackedByValueClassField()) { - GenerateField(@class, @class.Layout.Fields.Single(f => f.Field == prop.Field)); + GenerateField(@class, prop.Field); continue; } diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index f3b1f9b0..03d299ed 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -601,8 +601,6 @@ namespace CppSharp.Generators.CSharp TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); - if (@class.IsDynamic) - GenerateVTablePointers(@class); foreach (var field in @class.Layout.Fields) GenerateClassInternalsField(field); if (@class.IsGenerated && !(@class is ClassTemplateSpecialization)) @@ -791,16 +789,15 @@ namespace CppSharp.Generators.CSharp } } - private void GenerateClassInternalsField(LayoutField layoutField) + private void GenerateClassInternalsField(LayoutField field) { // we do not support dependent fields yet, see https://github.com/mono/CppSharp/issues/197 Declaration decl; - var field = layoutField.Field; - field.Type.TryGetDeclaration(out decl); + field.QualifiedType.Type.TryGetDeclaration(out decl); if (decl != null && decl.TranslationUnit.IsSystemHeader) return; - var safeIdentifier = Helpers.SafeIdentifier(layoutField.Name); + var safeIdentifier = Helpers.SafeIdentifier(field.Name); if(safeIdentifier.All(c => c.Equals('_'))) { @@ -809,13 +806,13 @@ namespace CppSharp.Generators.CSharp PushBlock(CSharpBlockKind.Field); - WriteLine("[FieldOffset({0})]", layoutField.Offset); + WriteLine("[FieldOffset({0})]", field.Offset); TypePrinter.PushMarshalKind(CSharpMarshalKind.NativeField); var fieldTypePrinted = field.QualifiedType.CSharpType(TypePrinter); TypePrinter.PopMarshalKind(); - var fieldType = field.Type.Desugar().IsAddress() ? + var fieldType = field.QualifiedType.Type.Desugar().IsAddress() ? CSharpTypePrinter.IntPtrType : fieldTypePrinted.Type; var fieldName = safeIdentifier; @@ -837,22 +834,23 @@ namespace CppSharp.Generators.CSharp // Workaround a bug in Mono when handling fixed arrays in P/Invoke declarations. // https://bugzilla.xamarin.com/show_bug.cgi?id=33571 - var arrayType = field.Type.Desugar() as ArrayType; + var arrayType = field.QualifiedType.Type.Desugar() as ArrayType; if (arrayType != null && arrayType.SizeType == ArrayType.ArraySize.Constant && arrayType.Size > 0) { for (var i = 1; i < arrayType.Size; ++i) { - var dummy = new Field + var dummy = new LayoutField { + Namespace = field.Namespace, + Offset = (uint) (field.Offset + i * arrayType.ElementSize / 8), + QualifiedType = new QualifiedType(arrayType.Type), Name = string.Format("{0}_{1}_{2}", Helpers.DummyIdentifier, safeIdentifier, i), - QualifiedType = new QualifiedType(arrayType.Type), - Namespace = field.Namespace + FieldPtr = field.FieldPtr }; - GenerateClassInternalsField(new LayoutField( - (uint) (layoutField.Offset + i * arrayType.ElementSize / 8), dummy)); + GenerateClassInternalsField(dummy); } } } @@ -975,7 +973,7 @@ namespace CppSharp.Generators.CSharp } else { - var name = @class.Layout.Fields.First(f => f.Field == field).Name; + var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name; ctx.ReturnVarName = string.Format("{0}{1}{2}", @class.IsValueType ? Helpers.InstanceField @@ -1027,7 +1025,8 @@ namespace CppSharp.Generators.CSharp type = originalType.ToString(); } - var name = ((Class) field.Namespace).Layout.Fields.First(f => f.Field == field).Name; + var name = ((Class) field.Namespace).Layout.Fields.First( + f => f.FieldPtr == field.OriginalPtr).Name; WriteLine(string.Format("fixed ({0} {1} = {2}.{3})", type, arrPtrIden, Helpers.InstanceField, Helpers.SafeIdentifier(name))); WriteStartBraceIndent(); @@ -1118,7 +1117,7 @@ namespace CppSharp.Generators.CSharp NewLine(); WriteStartBraceIndent(); - var name = @class.Layout.Fields.First(f => f.Field == field).Name; + var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name; var ctx = new CSharpMarshalContext(Driver) { Kind = CSharpMarshalKind.NativeField, @@ -1300,7 +1299,7 @@ namespace CppSharp.Generators.CSharp ArrayType arrayType = prop.Type as ArrayType; if (arrayType != null && arrayType.Type.IsPointerToPrimitiveType() && prop.Field != null) { - var name = @class.Layout.Fields.First(f => f.Field == prop.Field).Name; + var name = @class.Layout.Fields.First(f => f.FieldPtr == prop.Field.OriginalPtr).Name; GenerateClassField(prop.Field); WriteLine("private bool {0};", GeneratedIdentifier(string.Format("{0}Initialised", name))); @@ -1443,7 +1442,7 @@ namespace CppSharp.Generators.CSharp WriteLine("var native = (Internal*) {0}.ToPointer();", Helpers.InstanceIdentifier); NewLine(); - SaveOriginalVTablePointers(@class.Layout.VFTables); + SaveOriginalVTablePointers(@class.Layout.VTablePointers); NewLine(); @@ -1510,13 +1509,16 @@ namespace CppSharp.Generators.CSharp AllocateNewVTablesItanium(@class, wrappedEntries, destructorOnly); } - private void SaveOriginalVTablePointers(IEnumerable vfTables) + private void SaveOriginalVTablePointers(IList vTablePtrs) { if (Driver.Options.IsMicrosoftAbi) WriteLine("__OriginalVTables = new void*[] {{ {0} }};", - string.Join(", ", vfTables.Select((v, i) => string.Format("((Internal*) native)->vfptr{0}.ToPointer()", i)))); + string.Join(", ", + vTablePtrs.Select(v => string.Format("((Internal*) native)->{0}.ToPointer()", v.Name)))); else - WriteLine("__OriginalVTables = new void*[] { ((Internal*) native)->vfptr0.ToPointer() };"); + WriteLine( + "__OriginalVTables = new void*[] {{ ((Internal*) native)->{0}.ToPointer() }};", + vTablePtrs[0].Name); } private void AllocateNewVTablesMS(Class @class, IList wrappedEntries, @@ -1525,23 +1527,24 @@ namespace CppSharp.Generators.CSharp var managedVTables = destructorOnly ? "__ManagedVTablesDtorOnly" : "__ManagedVTables"; WriteLine("{0} = new void*[{1}];", managedVTables, @class.Layout.VFTables.Count); - for (int tableIndex = 0; tableIndex < @class.Layout.VFTables.Count; tableIndex++) + for (int i = 0; i < @class.Layout.VFTables.Count; i++) { - var vfptr = @class.Layout.VFTables[tableIndex]; + var vfptr = @class.Layout.VFTables[i]; var size = vfptr.Layout.Components.Count; WriteLine("var vfptr{0} = Marshal.AllocHGlobal({1} * {2});", - tableIndex, size, Driver.TargetInfo.PointerWidth / 8); - WriteLine("{0}[{1}] = vfptr{1}.ToPointer();", managedVTables, tableIndex); + i, size, Driver.TargetInfo.PointerWidth / 8); + WriteLine("{0}[{1}] = vfptr{1}.ToPointer();", managedVTables, i); - AllocateNewVTableEntries(vfptr.Layout.Components, wrappedEntries, tableIndex, - destructorOnly); + AllocateNewVTableEntries(vfptr.Layout.Components, wrappedEntries, + @class.Layout.VTablePointers[i].Name, i, destructorOnly); } WriteCloseBraceIndent(); NewLine(); - for (var i = 0; i < @class.Layout.VFTables.Count; i++) - WriteLine("native->vfptr{0} = new IntPtr({1}[{0}]);", i, managedVTables); + for (int i = 0; i < @class.Layout.VTablePointers.Count; i++) + WriteLine("native->{0} = new IntPtr({1}[{2}]);", + @class.Layout.VTablePointers[i].Name, managedVTables, i); } private void AllocateNewVTablesItanium(Class @class, IList wrappedEntries, @@ -1558,16 +1561,17 @@ namespace CppSharp.Generators.CSharp WriteLine("{0}[0] = vfptr0.ToPointer();", managedVTables); AllocateNewVTableEntries(@class.Layout.Layout.Components, - wrappedEntries, 0, destructorOnly); + wrappedEntries, @class.Layout.VTablePointers[0].Name, 0, destructorOnly); WriteCloseBraceIndent(); NewLine(); - WriteLine("native->vfptr0 = new IntPtr({0}[0]);", managedVTables); + WriteLine("native->{0} = new IntPtr({1}[0]);", + @class.Layout.VTablePointers[0].Name, managedVTables); } private void AllocateNewVTableEntries(IList entries, - IList wrappedEntries, int tableIndex, bool destructorOnly) + IList wrappedEntries, string vptr, int tableIndex, bool destructorOnly) { var pointerSize = Driver.TargetInfo.PointerWidth / 8; for (var i = 0; i < entries.Count; i++) @@ -1576,7 +1580,7 @@ namespace CppSharp.Generators.CSharp var offset = pointerSize * (i - (Options.IsMicrosoftAbi ? 0 : VTables.ItaniumOffsetToTopAndRTTI)); - var nativeVftableEntry = string.Format("*(void**)(native->vfptr{0} + {1})", tableIndex, offset); + var nativeVftableEntry = string.Format("*(void**)(native->{0} + {1})", vptr, offset); var managedVftableEntry = string.Format("*(void**)(vfptr{0} + {1})", tableIndex, offset); if ((entry.Kind == VTableComponentKind.FunctionPointer || @@ -1761,32 +1765,6 @@ namespace CppSharp.Generators.CSharp return string.Format("_{0}Delegate", nativeId); } - public void GenerateVTablePointers(Class @class) - { - if (Options.IsMicrosoftAbi) - { - var index = 0; - foreach (var info in @class.Layout.VFTables) - { - PushBlock(CSharpBlockKind.InternalsClassField); - - WriteLine("[FieldOffset({0})]", info.VFPtrFullOffset); - WriteLine("public global::System.IntPtr vfptr{0};", index++); - - PopBlock(NewLineKind.BeforeNextBlock); - } - } - else - { - PushBlock(CSharpBlockKind.InternalsClassField); - - WriteLine("[FieldOffset(0)]"); - WriteLine("public global::System.IntPtr vfptr0;"); - - PopBlock(NewLineKind.BeforeNextBlock); - } - } - #endregion #region Events @@ -1994,12 +1972,12 @@ namespace CppSharp.Generators.CSharp if (@class.IsDynamic && GetUniqueVTableMethodEntries(@class).Count != 0) { if (Options.IsMicrosoftAbi) - for (var i = 0; i < @class.Layout.VFTables.Count; i++) - WriteLine("((Internal*) {0})->vfptr{1} = new global::System.IntPtr(__OriginalVTables[{1}]);", - Helpers.InstanceIdentifier, i); + for (var i = 0; i < @class.Layout.VTablePointers.Count; i++) + WriteLine("((Internal*) {0})->{1} = new global::System.IntPtr(__OriginalVTables[{2}]);", + Helpers.InstanceIdentifier, @class.Layout.VTablePointers[i].Name, i); else - WriteLine("((Internal*) {0})->vfptr0 = new global::System.IntPtr(__OriginalVTables[0]);", - Helpers.InstanceIdentifier); + WriteLine("((Internal*) {0})->{1} = new global::System.IntPtr(__OriginalVTables[0]);", + Helpers.InstanceIdentifier, @class.Layout.VTablePointers[0].Name); } } @@ -2095,7 +2073,7 @@ namespace CppSharp.Generators.CSharp } if (@class.IsAbstractImpl || hasVTables) - SaveOriginalVTablePointers(@class.Layout.VFTables); + SaveOriginalVTablePointers(@class.Layout.VTablePointers); if (setupVTables) { diff --git a/src/Generator/Passes/CheckDuplicatedNamesPass.cs b/src/Generator/Passes/CheckDuplicatedNamesPass.cs index fc3811dd..7f49ee80 100644 --- a/src/Generator/Passes/CheckDuplicatedNamesPass.cs +++ b/src/Generator/Passes/CheckDuplicatedNamesPass.cs @@ -169,11 +169,11 @@ namespace CppSharp.Passes if (!@class.IsDependent) { foreach (var fields in @class.Layout.Fields.GroupBy( - f => f.Field.OriginalName).Select(g => g.ToList())) + f => f.Name).Select(g => g.ToList())) { for (var i = 1; i < fields.Count; i++) { - var name = fields[i].Field.OriginalName; + var name = fields[i].Name; fields[i].Name = (string.IsNullOrEmpty(name) ? "__" : name) + i; } } diff --git a/src/Generator/Passes/CleanInvalidDeclNamesPass.cs b/src/Generator/Passes/CleanInvalidDeclNamesPass.cs index 01631112..bd86a7f6 100644 --- a/src/Generator/Passes/CleanInvalidDeclNamesPass.cs +++ b/src/Generator/Passes/CleanInvalidDeclNamesPass.cs @@ -63,6 +63,10 @@ namespace CppSharp.Passes base.VisitClassDecl(@class); uniqueName = currentUniqueName; + if (!@class.IsDependent) + foreach (var field in @class.Layout.Fields.Where(f => string.IsNullOrEmpty(f.Name))) + field.Name = @class.Name == "_" ? "__" : "_"; + if (@class is ClassTemplateSpecialization && !(from c in @class.Namespace.Classes where c.Name == @class.Name && !(@class is ClassTemplateSpecialization) &&