From 749e5a399e1a8d6e3a4919c74d6780c6f1634a88 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Tue, 6 May 2014 14:03:59 +0200 Subject: [PATCH 1/6] Added new property Parameter.Index. Also added test which checks whether both parsers assign the AST parameter properties properly. --- src/AST/Function.cs | 1 + src/Core/Parser/ASTConverter.cs | 1 + src/CppParser/AST.h | 1 + src/CppParser/Bindings/CLI/AST.cpp | 10 +++++ src/CppParser/Bindings/CLI/AST.h | 6 +++ src/CppParser/Bindings/CSharp/AST.cs | 22 +++++++++- src/CppParser/Parser.cpp | 1 + src/Generator.Tests/AST/TestAST.cs | 61 ++++++++++++++++++++++++++++ src/Parser/Parser.cpp | 1 + tests/Native/AST.h | 2 + 10 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 src/Generator.Tests/AST/TestAST.cs create mode 100644 tests/Native/AST.h diff --git a/src/AST/Function.cs b/src/AST/Function.cs index a3c795f8..6209e0a7 100644 --- a/src/AST/Function.cs +++ b/src/AST/Function.cs @@ -40,6 +40,7 @@ namespace CppSharp.AST public Type Type { get { return QualifiedType.Type; } } public QualifiedType QualifiedType { get; set; } public bool IsIndirect { get; set; } + public uint Index { get; set; } public ParameterKind Kind { get; set; } public ParameterUsage Usage { get; set; } diff --git a/src/Core/Parser/ASTConverter.cs b/src/Core/Parser/ASTConverter.cs index 73b0c136..30259c37 100644 --- a/src/Core/Parser/ASTConverter.cs +++ b/src/Core/Parser/ASTConverter.cs @@ -803,6 +803,7 @@ namespace CppSharp _param.QualifiedType = typeConverter.VisitQualified(decl.QualifiedType); _param.IsIndirect = decl.IsIndirect; _param.HasDefaultValue = decl.HasDefaultValue; + _param.Index = decl.Index; return _param; } diff --git a/src/CppParser/AST.h b/src/CppParser/AST.h index a6963afa..ad124955 100644 --- a/src/CppParser/AST.h +++ b/src/CppParser/AST.h @@ -433,6 +433,7 @@ struct CS_API Parameter : public Declaration CppSharp::CppParser::AST::QualifiedType QualifiedType; bool IsIndirect; bool HasDefaultValue; + unsigned int Index; }; enum struct CXXMethodKind diff --git a/src/CppParser/Bindings/CLI/AST.cpp b/src/CppParser/Bindings/CLI/AST.cpp index 52512be4..635b1d41 100644 --- a/src/CppParser/Bindings/CLI/AST.cpp +++ b/src/CppParser/Bindings/CLI/AST.cpp @@ -1459,6 +1459,16 @@ void CppSharp::Parser::AST::Parameter::HasDefaultValue::set(bool value) ((::CppSharp::CppParser::AST::Parameter*)NativePtr)->HasDefaultValue = value; } +unsigned int CppSharp::Parser::AST::Parameter::Index::get() +{ + return ((::CppSharp::CppParser::AST::Parameter*)NativePtr)->Index; +} + +void CppSharp::Parser::AST::Parameter::Index::set(unsigned int value) +{ + ((::CppSharp::CppParser::AST::Parameter*)NativePtr)->Index = value; +} + CppSharp::Parser::AST::Function::Function(::CppSharp::CppParser::AST::Function* native) : CppSharp::Parser::AST::Declaration((::CppSharp::CppParser::AST::Declaration*)native) { diff --git a/src/CppParser/Bindings/CLI/AST.h b/src/CppParser/Bindings/CLI/AST.h index 12b55362..b5471ce2 100644 --- a/src/CppParser/Bindings/CLI/AST.h +++ b/src/CppParser/Bindings/CLI/AST.h @@ -1120,6 +1120,12 @@ namespace CppSharp bool get(); void set(bool); } + + property unsigned int Index + { + unsigned int get(); + void set(unsigned int); + } }; public ref class Function : CppSharp::Parser::AST::Declaration diff --git a/src/CppParser/Bindings/CSharp/AST.cs b/src/CppParser/Bindings/CSharp/AST.cs index 8da40492..47ec94c4 100644 --- a/src/CppParser/Bindings/CSharp/AST.cs +++ b/src/CppParser/Bindings/CSharp/AST.cs @@ -3389,7 +3389,7 @@ namespace CppSharp public unsafe partial class Parameter : CppSharp.Parser.AST.Declaration, IDisposable { - [StructLayout(LayoutKind.Explicit, Size = 104)] + [StructLayout(LayoutKind.Explicit, Size = 108)] public new struct Internal { [FieldOffset(0)] @@ -3437,6 +3437,9 @@ namespace CppSharp [FieldOffset(101)] internal bool HasDefaultValue; + [FieldOffset(104)] + internal uint Index; + [SuppressUnmanagedCodeSecurity] [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall, EntryPoint="??0Parameter@AST@CppParser@CppSharp@@QAE@XZ")] @@ -3471,7 +3474,7 @@ namespace CppSharp public Parameter() : this(IntPtr.Zero) { - __Instance = Marshal.AllocHGlobal(104); + __Instance = Marshal.AllocHGlobal(108); Internal.ctor_0(__Instance); } @@ -3526,6 +3529,21 @@ namespace CppSharp __ptr->HasDefaultValue = value; } } + + public uint Index + { + get + { + var __ptr = (Internal*)__Instance.ToPointer(); + return __ptr->Index; + } + + set + { + var __ptr = (Internal*)__Instance.ToPointer(); + __ptr->Index = value; + } + } } public unsafe partial class Function : CppSharp.Parser.AST.Declaration, IDisposable diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp index 66fafabf..4bc41dcc 100644 --- a/src/CppParser/Parser.cpp +++ b/src/CppParser/Parser.cpp @@ -1885,6 +1885,7 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, Function* F, P->QualifiedType = GetQualifiedType(VD->getType(), WalkType(VD->getType(), &PTL)); P->HasDefaultValue = VD->hasDefaultArg(); P->_Namespace = NS; + P->Index = VD->getFunctionScopeIndex(); HandleDeclaration(VD, P); F->Parameters.push_back(P); diff --git a/src/Generator.Tests/AST/TestAST.cs b/src/Generator.Tests/AST/TestAST.cs new file mode 100644 index 00000000..872a7081 --- /dev/null +++ b/src/Generator.Tests/AST/TestAST.cs @@ -0,0 +1,61 @@ +using System.Linq; +using CppSharp.Passes; +using CppSharp.AST; +using CppSharp.AST.Extensions; +using NUnit.Framework; + +namespace CppSharp.Generator.Tests.AST +{ + [TestFixture] + public class TestAST : ASTTestFixture + { + private PassBuilder passBuilder; + + [TestFixtureSetUp] + public void Init() + { + } + + [SetUp] + public void Setup() + { + ParseLibrary("AST.h"); + passBuilder = new PassBuilder(Driver); + } + + [Test] + public void TestASTParameter() + { + var func = AstContext.FindFunction("TestParameterProperties").FirstOrDefault(); + Assert.IsNotNull(func); + + var paramNames = new [] { "a", "b", "c" }; + var paramTypes = new [] + { + new QualifiedType(new BuiltinType(PrimitiveType.Bool)), + new QualifiedType( + new PointerType() + { + Modifier = PointerType.TypeModifier.LVReference, + QualifiedPointee = new QualifiedType( + new BuiltinType(PrimitiveType.Int16), + new TypeQualifiers() { IsConst = true }) + }), + new QualifiedType( + new PointerType() + { + Modifier = PointerType.TypeModifier.Pointer, + QualifiedPointee = new QualifiedType(new BuiltinType(PrimitiveType.Int32)) + }) + }; + for (int i = 0; i < func.Parameters.Count; i++) + { + var param = func.Parameters[i]; + Assert.AreEqual(paramNames[i], param.Name, "Parameter.Name"); + Assert.AreEqual(paramTypes[i], param.QualifiedType, "Parameter.QualifiedType"); + Assert.AreEqual(i, param.Index, "Parameter.Index"); + } + Assert.IsTrue(func.Parameters[2].HasDefaultValue, "Parameter.HasDefaultValue"); + } + } +} diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 747be19c..d2ca2fb5 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -1900,6 +1900,7 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, CppSharp::AST::Function^ F, P->QualifiedType = GetQualifiedType(VD->getType(), WalkType(VD->getType(), &PTL)); P->HasDefaultValue = VD->hasDefaultArg(); P->Namespace = NS; + P->Index = VD->getFunctionScopeIndex(); HandleDeclaration(VD, P); F->Parameters->Add(P); diff --git a/tests/Native/AST.h b/tests/Native/AST.h new file mode 100644 index 00000000..3e917755 --- /dev/null +++ b/tests/Native/AST.h @@ -0,0 +1,2 @@ +// Tests assignment of AST.Parameter properties +void TestParameterProperties(bool a, const short& b, int* c = nullptr) {}; From 487189ebada05f6430b052a957cf9ae9d7507406 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Tue, 6 May 2014 14:06:07 +0200 Subject: [PATCH 2/6] Fixed the FindOperator method for classes. Added AST test case and fixed line endings (LF). --- src/AST/Class.cs | 15 ++- src/AST/Namespace.cs | 152 ++++++++++++++--------------- src/Generator.Tests/AST/TestAST.cs | 9 ++ tests/Native/AST.h | 16 +++ 4 files changed, 111 insertions(+), 81 deletions(-) diff --git a/src/AST/Class.cs b/src/AST/Class.cs index f4812594..15061f45 100644 --- a/src/AST/Class.cs +++ b/src/AST/Class.cs @@ -149,8 +149,8 @@ namespace CppSharp.AST { foreach (var @base in Bases) { - if (@base.IsClass && @base.Class.IsDeclared) - return @base.Class; + if (@base.IsClass && @base.Class.IsDeclared) + return @base.Class; } return null; @@ -199,11 +199,16 @@ namespace CppSharp.AST } } + public override IEnumerable FindOperator(CXXOperatorKind kind) + { + return Methods.Where(m => m.OperatorKind == kind); + } + public override IEnumerable GetOverloads(Function function) { - if (function.IsOperator) - return Methods.Where(fn => fn.OperatorKind == function.OperatorKind); - + if (function.IsOperator) + return Methods.Where(fn => fn.OperatorKind == function.OperatorKind); + var methods = Methods.Where(m => m.Name == function.Name); if (methods.ToList().Count != 0) return methods; diff --git a/src/AST/Namespace.cs b/src/AST/Namespace.cs index 6adaab95..e4927284 100644 --- a/src/AST/Namespace.cs +++ b/src/AST/Namespace.cs @@ -25,16 +25,16 @@ namespace CppSharp.AST public Dictionary Anonymous; // True if the context is inside an extern "C" context. - public bool IsExternCContext; - - public override string LogicalName - { - get { return IsAnonymous ? "" : base.Name; } - } - - public override string LogicalOriginalName - { - get { return IsAnonymous ? "" : base.OriginalName; } + public bool IsExternCContext; + + public override string LogicalName + { + get { return IsAnonymous ? "" : base.Name; } + } + + public override string LogicalOriginalName + { + get { return IsAnonymous ? "" : base.OriginalName; } } protected DeclarationContext() @@ -71,25 +71,25 @@ namespace CppSharp.AST public Declaration FindAnonymous(ulong key) { return Anonymous.ContainsKey(key) ? Anonymous[key] : null; - } - - public DeclarationContext FindDeclaration(IEnumerable declarations) - { - DeclarationContext currentDeclaration = this; - - foreach (var declaration in declarations) - { - var subDeclaration = currentDeclaration.Namespaces - .Concat(currentDeclaration.Classes) - .FirstOrDefault(e => e.Name.Equals(declaration)); - - if (subDeclaration == null) - return null; - - currentDeclaration = subDeclaration; - } - - return currentDeclaration as DeclarationContext; + } + + public DeclarationContext FindDeclaration(IEnumerable declarations) + { + DeclarationContext currentDeclaration = this; + + foreach (var declaration in declarations) + { + var subDeclaration = currentDeclaration.Namespaces + .Concat(currentDeclaration.Classes) + .FirstOrDefault(e => e.Name.Equals(declaration)); + + if (subDeclaration == null) + return null; + + currentDeclaration = subDeclaration; + } + + return currentDeclaration as DeclarationContext; } public Namespace FindNamespace(string name) @@ -165,34 +165,34 @@ namespace CppSharp.AST } public Function FindFunction(string name, bool createDecl = false) - { - if (string.IsNullOrEmpty(name)) - return null; - - var entries = name.Split(new string[] { "::" }, - StringSplitOptions.RemoveEmptyEntries).ToList(); - - if (entries.Count <= 1) - { - var function = Functions.Find(e => e.Name.Equals(name)); - - if (function == null && createDecl) - { - function = new Function() { Name = name, Namespace = this }; - Functions.Add(function); - } - - return function; - } - - var funcName = entries[entries.Count - 1]; - var namespaces = entries.Take(entries.Count - 1); - - var @namespace = FindNamespace(namespaces); - if (@namespace == null) - return null; - - return @namespace.FindFunction(funcName, createDecl); + { + if (string.IsNullOrEmpty(name)) + return null; + + var entries = name.Split(new string[] { "::" }, + StringSplitOptions.RemoveEmptyEntries).ToList(); + + if (entries.Count <= 1) + { + var function = Functions.Find(e => e.Name.Equals(name)); + + if (function == null && createDecl) + { + function = new Function() { Name = name, Namespace = this }; + Functions.Add(function); + } + + return function; + } + + var funcName = entries[entries.Count - 1]; + var namespaces = entries.Take(entries.Count - 1); + + var @namespace = FindNamespace(namespaces); + if (@namespace == null) + return null; + + return @namespace.FindFunction(funcName, createDecl); } Class CreateClass(string name, bool isComplete) @@ -229,7 +229,7 @@ namespace CppSharp.AST DeclarationContext declContext = FindDeclaration(namespaces); if (declContext == null) - { + { declContext = FindClass(entries[0]); if (declContext == null) return null; @@ -320,13 +320,13 @@ namespace CppSharp.AST return Enums.Find(e => e.ItemsByName.ContainsKey(name)); } - public IEnumerable FindOperator(CXXOperatorKind kind) + public virtual IEnumerable FindOperator(CXXOperatorKind kind) { return Functions.Where(fn => fn.OperatorKind == kind); } - public virtual IEnumerable GetOverloads(Function function) - { + public virtual IEnumerable GetOverloads(Function function) + { if (function.IsOperator) return FindOperator(function.OperatorKind); return Functions.Where(fn => fn.Name == function.Name); @@ -335,17 +335,17 @@ namespace CppSharp.AST public bool HasDeclarations { get - { + { Predicate pred = (t => t.IsGenerated); return Enums.Exists(pred) || HasFunctions || Typedefs.Exists(pred) - || Classes.Any() || Namespaces.Exists(n => n.HasDeclarations); + || Classes.Any() || Namespaces.Exists(n => n.HasDeclarations); } } public bool HasFunctions { get - { + { Predicate pred = (t => t.IsGenerated); return Functions.Exists(pred) || Namespaces.Exists(n => n.HasFunctions); } @@ -357,18 +357,18 @@ namespace CppSharp.AST /// /// Represents a C++ namespace. /// - public class Namespace : DeclarationContext - { - public override string LogicalName - { - get { return IsInline ? string.Empty : base.Name; } - } - - public override string LogicalOriginalName - { - get { return IsInline ? string.Empty : base.OriginalName; } - } - + public class Namespace : DeclarationContext + { + public override string LogicalName + { + get { return IsInline ? string.Empty : base.Name; } + } + + public override string LogicalOriginalName + { + get { return IsInline ? string.Empty : base.OriginalName; } + } + public bool IsInline; public override T Visit(IDeclVisitor visitor) diff --git a/src/Generator.Tests/AST/TestAST.cs b/src/Generator.Tests/AST/TestAST.cs index 872a7081..ceb50d29 100644 --- a/src/Generator.Tests/AST/TestAST.cs +++ b/src/Generator.Tests/AST/TestAST.cs @@ -57,5 +57,14 @@ namespace CppSharp.Generator.Tests.AST } Assert.IsTrue(func.Parameters[2].HasDefaultValue, "Parameter.HasDefaultValue"); } + + [Test] + public void TestASTHelperMethods() + { + var @class = AstContext.FindClass("Math::Complex").FirstOrDefault(); + Assert.IsNotNull(@class, "Couldn't find Math::Complex class."); + var plusOperator = @class.FindOperator(CXXOperatorKind.Plus).FirstOrDefault(); + Assert.IsNotNull(plusOperator, "Couldn't find operator+ in Math::Complex class."); + } } } diff --git a/tests/Native/AST.h b/tests/Native/AST.h index 3e917755..ac8e6f1d 100644 --- a/tests/Native/AST.h +++ b/tests/Native/AST.h @@ -1,2 +1,18 @@ // Tests assignment of AST.Parameter properties void TestParameterProperties(bool a, const short& b, int* c = nullptr) {}; + +// Tests various AST helper methods (like FindClass, FindOperator etc.) +namespace Math +{ + struct Complex { + Complex(double r, double i) : re(r), im(i) {} + Complex operator+(Complex &other); + private: + double re, im; + }; + + // Operator overloaded using a member function + Complex Complex::operator+(Complex &other) { + return Complex(re + other.re, im + other.im); + } +} \ No newline at end of file From c6701484930cfb444d0dd8acb569acd10c66e078 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Tue, 6 May 2014 14:29:42 +0200 Subject: [PATCH 3/6] The FindTypedef method supports full type names now. --- src/AST/Namespace.cs | 27 +++++++++++++++++++++------ src/Generator.Tests/AST/TestAST.cs | 2 ++ tests/Native/AST.h | 6 +++++- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/AST/Namespace.cs b/src/AST/Namespace.cs index e4927284..2598c953 100644 --- a/src/AST/Namespace.cs +++ b/src/AST/Namespace.cs @@ -294,15 +294,30 @@ namespace CppSharp.AST public TypedefDecl FindTypedef(string name, bool createDecl = false) { - var typedef = Typedefs.Find(e => e.Name.Equals(name)); - - if (typedef == null && createDecl) + var entries = name.Split(new string[] { "::" }, + StringSplitOptions.RemoveEmptyEntries).ToList(); + + if (entries.Count <= 1) { - typedef = new TypedefDecl { Name = name, Namespace = this }; - Typedefs.Add(typedef); + var typeDef = Typedefs.Find(e => e.Name.Equals(name)); + + if (typeDef == null && createDecl) + { + typeDef = new TypedefDecl() { Name = name, Namespace = this }; + Typedefs.Add(typeDef); + } + + return typeDef; } - return typedef; + var typeDefName = entries[entries.Count - 1]; + var namespaces = entries.Take(entries.Count - 1); + + var @namespace = FindNamespace(namespaces); + if (@namespace == null) + return null; + + return @namespace.FindTypedef(typeDefName, createDecl); } public T FindType(string name) where T : Declaration diff --git a/src/Generator.Tests/AST/TestAST.cs b/src/Generator.Tests/AST/TestAST.cs index ceb50d29..e6181a8f 100644 --- a/src/Generator.Tests/AST/TestAST.cs +++ b/src/Generator.Tests/AST/TestAST.cs @@ -65,6 +65,8 @@ namespace CppSharp.Generator.Tests.AST Assert.IsNotNull(@class, "Couldn't find Math::Complex class."); var plusOperator = @class.FindOperator(CXXOperatorKind.Plus).FirstOrDefault(); Assert.IsNotNull(plusOperator, "Couldn't find operator+ in Math::Complex class."); + var typedef = AstContext.FindTypedef("Math::Single").FirstOrDefault(); + Assert.IsNotNull(typedef); } } } diff --git a/tests/Native/AST.h b/tests/Native/AST.h index ac8e6f1d..6db63b44 100644 --- a/tests/Native/AST.h +++ b/tests/Native/AST.h @@ -4,6 +4,7 @@ void TestParameterProperties(bool a, const short& b, int* c = nullptr) {}; // Tests various AST helper methods (like FindClass, FindOperator etc.) namespace Math { + // Tests FindClass("Math::Complex") struct Complex { Complex(double r, double i) : re(r), im(i) {} Complex operator+(Complex &other); @@ -11,7 +12,10 @@ namespace Math double re, im; }; - // Operator overloaded using a member function + // Tests FindTypedef("Math::Single") + typedef float Single; + + // Tests FindOperator method Complex Complex::operator+(Complex &other) { return Complex(re + other.re, im + other.im); } From 61a5ceb5c386df8557ffbad142e0a8d622493172 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Tue, 6 May 2014 14:33:37 +0200 Subject: [PATCH 4/6] Added copy constructors to Class, Parameter and DeclarationContext. --- src/AST/Class.cs | 22 ++++++++++++++++++++++ src/AST/Function.cs | 11 +++++++++++ src/AST/Namespace.cs | 16 ++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/src/AST/Class.cs b/src/AST/Class.cs index 15061f45..ca08569f 100644 --- a/src/AST/Class.cs +++ b/src/AST/Class.cs @@ -133,6 +133,28 @@ namespace CppSharp.AST Layout = new ClassLayout(); } + public Class(Class @class) + : base(@class) + { + Bases = new List(@class.Bases); + Fields = new List(@class.Fields); + Properties = new List(@class.Properties); + Methods = new List(@class.Methods); + Specifiers = new List(@class.Specifiers); + IsPOD = @class.IsPOD; + Type = @class.Type; + Layout = new ClassLayout(@class.Layout); + IsAbstract = @class.IsAbstract; + IsUnion = @class.IsUnion; + IsOpaque = @class.IsOpaque; + IsDynamic = @class.IsDynamic; + IsPolymorphic = @class.IsPolymorphic; + HasNonTrivialDefaultConstructor = @class.HasNonTrivialDefaultConstructor; + HasNonTrivialCopyConstructor = @class.HasNonTrivialCopyConstructor; + HasNonTrivialDestructor = @class.HasNonTrivialDestructor; + IsStatic = @class.IsStatic; + } + public bool HasBase { get { return Bases.Count > 0; } diff --git a/src/AST/Function.cs b/src/AST/Function.cs index 6209e0a7..7215e1c7 100644 --- a/src/AST/Function.cs +++ b/src/AST/Function.cs @@ -37,6 +37,17 @@ namespace CppSharp.AST HasDefaultValue = false; } + public Parameter(Parameter p) + : base(p) + { + HasDefaultValue = p.HasDefaultValue; + Index = p.Index; + IsIndirect = p.IsIndirect; + Kind = p.Kind; + QualifiedType = p.QualifiedType; + Usage = p.Usage; + } + public Type Type { get { return QualifiedType.Type; } } public QualifiedType QualifiedType { get; set; } public bool IsIndirect { get; set; } diff --git a/src/AST/Namespace.cs b/src/AST/Namespace.cs index 2598c953..733be99f 100644 --- a/src/AST/Namespace.cs +++ b/src/AST/Namespace.cs @@ -51,6 +51,22 @@ namespace CppSharp.AST Anonymous = new Dictionary(); } + protected DeclarationContext(DeclarationContext dc) + : base(dc) + { + Namespaces = new List(dc.Namespaces); + Enums = new List(dc.Enums); + Functions = new List(dc.Functions); + Classes = new List(dc.Classes); + Templates = new List