From 8a2e81344517bfd9338f67ea4b7711919a45c210 Mon Sep 17 00:00:00 2001 From: Mohit Mohta Date: Tue, 15 Aug 2017 02:51:37 +0530 Subject: [PATCH] Merged Delegate Pass and pass for Anonymous Delegates and added the following improvements alongwith. 1. Got rid of Anonymous Names. 2. Merged the common code for Delegate Generation. 3. The delegate pass also works for C++/CLI now. 4. Fixed the calling conventions of delegates for both, C++/CLI and C#. 5. Ensures that if a delegate is used for a virtual as well as something else, it finally ends up as public. 6. Fixed the code generation when the return type of a method is a function pointer that has been used somewhere else as well. 7. Added Access and Calling convention to the delegate definition. The only thing left is to get rid of the hack used, i.e move the code in VisitFunctionDecl to VisitParametersDecl. Somehow, it's not working right now. Signed-off-by: Dimitar Dobrev --- src/AST/Function.cs | 4 +- src/AST/Type.cs | 1 + src/Generator/BindingContext.cs | 5 - src/Generator/Driver.cs | 3 +- src/Generator/Generators/CLI/CLIHeaders.cs | 28 +- .../Generators/CSharp/CSharpMarshal.cs | 4 +- .../Generators/CSharp/CSharpSources.cs | 4 +- .../Generators/CSharp/CSharpTypePrinter.cs | 3 - src/Generator/Passes/DelegatesPass.cs | 290 +++++++++--------- .../Passes/GenerateAnonymousDelegatesPass.cs | 129 -------- tests/CSharp/CSharp.cpp | 6 + tests/CSharp/CSharp.h | 6 + tests/Common/Common.Tests.cs | 2 +- 13 files changed, 180 insertions(+), 305 deletions(-) delete mode 100644 src/Generator/Passes/GenerateAnonymousDelegatesPass.cs diff --git a/src/AST/Function.cs b/src/AST/Function.cs index 97917a5d..0ae0a203 100644 --- a/src/AST/Function.cs +++ b/src/AST/Function.cs @@ -258,7 +258,7 @@ namespace CppSharp.AST return visitor.VisitFunctionDecl(this); } - public Type Type => OriginalReturnType.Type; - public QualifiedType QualifiedType => OriginalReturnType; + public Type Type => ReturnType.Type; + public QualifiedType QualifiedType => ReturnType; } } \ No newline at end of file diff --git a/src/AST/Type.cs b/src/AST/Type.cs index 5b160f3f..cca7c148 100644 --- a/src/AST/Type.cs +++ b/src/AST/Type.cs @@ -260,6 +260,7 @@ namespace CppSharp.AST ReturnType = new QualifiedType((Type) type.ReturnType.Type.Clone(), type.ReturnType.Qualifiers); Parameters.AddRange(type.Parameters.Select(p => new Parameter(p)).ToList()); CallingConvention = type.CallingConvention; + IsDependent = type.IsDependent; } public override T Visit(ITypeVisitor visitor, TypeQualifiers quals = new TypeQualifiers()) diff --git a/src/Generator/BindingContext.cs b/src/Generator/BindingContext.cs index 8b99aa72..4251c9f3 100644 --- a/src/Generator/BindingContext.cs +++ b/src/Generator/BindingContext.cs @@ -2,7 +2,6 @@ using CppSharp.AST; using CppSharp.Passes; using CppSharp.Types; using CppSharp.Parser; -using System.Collections.Generic; namespace CppSharp.Generators { @@ -20,16 +19,12 @@ namespace CppSharp.Generators public PassBuilder TranslationUnitPasses { get; private set; } public PassBuilder GeneratorOutputPasses { get; private set; } - public Dictionary Delegates { get; private set; } - public BindingContext(DriverOptions options, ParserOptions parserOptions = null) { Options = options; ParserOptions = parserOptions; Symbols = new SymbolContext(); - Delegates = new Dictionary(); - TypeMaps = new TypeMapDatabase(); TranslationUnitPasses = new PassBuilder(this); diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index 5c7e04a0..c538e939 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -295,7 +295,6 @@ namespace CppSharp TranslationUnitPasses.AddPass(new CheckStaticClass()); TranslationUnitPasses.AddPass(new MoveOperatorToClassPass()); TranslationUnitPasses.AddPass(new MoveFunctionToClassPass()); - TranslationUnitPasses.AddPass(new GenerateAnonymousDelegatesPass()); TranslationUnitPasses.AddPass(new ConstructorToConversionOperatorPass()); TranslationUnitPasses.AddPass(new MarshalPrimitivePointersAsRefTypePass()); TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions()); @@ -321,8 +320,8 @@ namespace CppSharp } TranslationUnitPasses.AddPass(new MultipleInheritancePass()); TranslationUnitPasses.AddPass(new ParamTypeToInterfacePass()); - TranslationUnitPasses.AddPass(new DelegatesPass()); } + TranslationUnitPasses.AddPass(new DelegatesPass()); TranslationUnitPasses.AddPass(new GetterSetterToPropertyPass()); TranslationUnitPasses.AddPass(new StripUnusedSystemTypesPass()); diff --git a/src/Generator/Generators/CLI/CLIHeaders.cs b/src/Generator/Generators/CLI/CLIHeaders.cs index ebf63934..64298bda 100644 --- a/src/Generator/Generators/CLI/CLIHeaders.cs +++ b/src/Generator/Generators/CLI/CLIHeaders.cs @@ -745,31 +745,27 @@ namespace CppSharp.Generators.CLI if (!typedef.IsGenerated) return false; - FunctionType function; - if (typedef.Type.IsPointerTo(out function)) + var functionType = typedef.Type as FunctionType; + if (functionType != null || typedef.Type.IsPointerTo(out functionType)) { PushBlock(BlockKind.Typedef, typedef); GenerateDeclarationCommon(typedef); var insideClass = typedef.Namespace is Class; - var attributedType = typedef.Type.GetPointee() as AttributedType; - if (attributedType != null) - { - var equivalentFunctionType = attributedType.Equivalent.Type as FunctionType; - var callingConvention = equivalentFunctionType.CallingConvention.ToInteropCallConv(); - if (callingConvention != System.Runtime.InteropServices.CallingConvention.Winapi) - { - WriteLine("[{0}({1}::{2})] ", - "System::Runtime::InteropServices::UnmanagedFunctionPointer", - "System::Runtime::InteropServices::CallingConvention", - callingConvention); - } - } + var attributedType = typedef.Type.GetPointee().Desugar(); + var callingConvention = attributedType == null && functionType != null + ? functionType.CallingConvention + : ((FunctionType)attributedType).CallingConvention; + var interopCallConv = callingConvention.ToInteropCallConv(); + if (interopCallConv != System.Runtime.InteropServices.CallingConvention.Winapi) + WriteLine("[System::Runtime::InteropServices::UnmanagedFunctionPointer" + + "(System::Runtime::InteropServices::CallingConvention::{0})] ", + interopCallConv); WriteLine("{0}{1};", !insideClass ? "public " : "", - string.Format(TypePrinter.VisitDelegate(function).ToString(), + string.Format(TypePrinter.VisitDelegate(functionType).ToString(), typedef.Name)); PopBlock(NewLineKind.BeforeNextBlock); diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index f78ec12f..fe0e50a1 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -256,8 +256,8 @@ namespace CppSharp.Generators.CSharp var decl = typedef.Declaration; - FunctionType function; - if (decl.Type.IsPointerTo(out function)) + var functionType = decl.Type as FunctionType; + if (functionType != null || decl.Type.IsPointerTo(out functionType)) { var ptrName = Generator.GeneratedIdentifier("ptr") + Context.ParameterIndex; diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index 46281cf8..5ae0040a 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -1688,7 +1688,7 @@ namespace CppSharp.Generators.CSharp TypePrinter.PopMarshalKind(); WriteLine("private static {0} {1}Instance;", - Context.Delegates[method].Signature, + method.FunctionType.ToString(), vTableMethodDelegateName); NewLine(); @@ -2490,7 +2490,7 @@ namespace CppSharp.Generators.CSharp var delegateId = Generator.GeneratedIdentifier(@delegate); WriteLine("var {0} = ({1}) Marshal.GetDelegateForFunctionPointer(new IntPtr({2}), typeof({1}));", - delegateId, Context.Delegates[method].Signature, + delegateId, method.FunctionType.ToString(), Helpers.SlotIdentifier); return delegateId; diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index 13a3683e..9298fa23 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -657,9 +657,6 @@ namespace CppSharp.Generators.CSharp typeBuilder.Append(printedType); var type = typeBuilder.ToString(); - if (Context.Delegates.ContainsKey(param)) - return $"{Context.Delegates[param].Signature} {param.Name}"; - if (ContextKind == TypePrinterContextKind.Native) return $"{type} {param.Name}"; diff --git a/src/Generator/Passes/DelegatesPass.cs b/src/Generator/Passes/DelegatesPass.cs index 0a7dd949..77683148 100644 --- a/src/Generator/Passes/DelegatesPass.cs +++ b/src/Generator/Passes/DelegatesPass.cs @@ -3,32 +3,15 @@ using System.Linq; using System.Text; using CppSharp.AST; using CppSharp.AST.Extensions; -using CppSharp.Generators; using CppSharp.Generators.CSharp; namespace CppSharp.Passes { public class DelegatesPass : TranslationUnitPass { - public const string DelegatesNamespace = "Delegates"; - - public class DelegateDefinition - { - public DelegateDefinition(string @namespace, string signature) - { - Namespace = @namespace; - Signature = signature; - } - - public string Namespace { get; } - - public string Signature { get; } - } - public DelegatesPass() { VisitOptions.VisitClassBases = false; - VisitOptions.VisitFunctionParameters = false; VisitOptions.VisitFunctionReturnType = false; VisitOptions.VisitNamespaceEnums = false; VisitOptions.VisitNamespaceTemplates = false; @@ -37,177 +20,194 @@ namespace CppSharp.Passes public override bool VisitASTContext(ASTContext context) { - foreach (var module in Options.Modules) - libsDelegates[module] = new Dictionary(); + bool result = base.VisitASTContext(context); + + foreach (var @delegate in delegates) + @delegate.Namespace.Declarations.Add(@delegate); + delegates.Clear(); - var unit = context.TranslationUnits.GetGenerated().LastOrDefault(); + if (!Options.IsCSharpGenerator) + return result; + + var generatedUnits = context.TranslationUnits.GetGenerated(); + var unit = generatedUnits.LastOrDefault(); if (unit == null) return false; - var result = base.VisitASTContext(context); - - foreach (var module in Options.Modules.Where(m => namespacesDelegates.ContainsKey(m))) - namespacesDelegates[module].Namespace.Declarations.Add(namespacesDelegates[module]); + foreach (var module in Options.Modules.Where(namespacesDelegates.ContainsKey)) + { + var @namespace = namespacesDelegates[module]; + @namespace.Namespace.Declarations.Add(@namespace); + } return result; } - private void AddDelegatesToDictionary(Declaration decl, Module module) + public override bool VisitMethodDecl(Method method) { - CallingConvention callingConvention; - bool isDependent = false; - QualifiedType returnType; - List @params; - if (decl is Method) - { - var method = (Method) decl; - @params = method.GatherInternalParams(Context.ParserOptions.IsItaniumLikeAbi, true).ToList(); - callingConvention = method.CallingConvention; - isDependent = method.IsDependent; - returnType = method.ReturnType; - } - else - { - var param = (Parameter) decl; - var funcTypeParam = param.Type.Desugar().GetFinalPointee().Desugar() as FunctionType; - @params = funcTypeParam.Parameters; - callingConvention = funcTypeParam.CallingConvention; - isDependent = funcTypeParam.IsDependent; - returnType = funcTypeParam.ReturnType; - } + if (!base.VisitMethodDecl(method) || !method.IsVirtual || method.Ignore) + return false; - var delegateName = GenerateDelegateSignature(@params, returnType); - Namespace namespaceDelegates; + method.FunctionType = CheckForDelegate(method.FunctionType, method); - if (namespacesDelegates.ContainsKey(module)) - { - namespaceDelegates = namespacesDelegates[module]; - } - else - { - Namespace parent = null; - if (string.IsNullOrEmpty(module.OutputNamespace)) - { - var group = module.Units.SelectMany(u => u.Declarations).OfType( - ).GroupBy(d => d.Name).Where(g => g.Any(d => d.HasDeclarations)).ToList(); - if (group.Count == 1) - parent = group.Last().Last(); - } - if (parent == null) - parent = module.Units.Last(); - namespaceDelegates = new Namespace - { - Name = DelegatesNamespace, - Namespace = parent - }; - namespacesDelegates.Add(module, namespaceDelegates); - } + return true; + } - var functionType = new FunctionType - { - CallingConvention = callingConvention, - IsDependent = isDependent, - ReturnType = returnType - }; - functionType.Parameters.AddRange(@params); - var @delegate = new TypedefDecl - { - Name = delegateName, - QualifiedType = new QualifiedType( - new PointerType(new QualifiedType(functionType))), - Namespace = namespaceDelegates, - IsSynthetized = true, - Access = decl is Method ? AccessSpecifier.Private : AccessSpecifier.Public - }; + public override bool VisitFunctionDecl(Function function) + { + if (!base.VisitFunctionDecl(function) || function.Ignore) + return false; - var delegateString = @delegate.Visit(TypePrinter).Type; - var existingDelegate = GetExistingDelegate( - module, delegateString); + function.ReturnType = CheckForDelegate(function.ReturnType, function); + return true; + } - if (existingDelegate != null) - { - Context.Delegates.Add(decl, existingDelegate); - return; - } + public override bool VisitParameterDecl(Parameter parameter) + { + if (!base.VisitParameterDecl(parameter) || parameter.Namespace == null || + parameter.Namespace.Ignore) + return false; + + parameter.QualifiedType = CheckForDelegate(parameter.QualifiedType, parameter); + + return true; + } + + private QualifiedType CheckForDelegate(QualifiedType type, ITypedDecl decl) + { + if (type.Type is TypedefType) + return type; + + var desugared = type.Type.Desugar(); + if (desugared.IsDependent) + return type; - existingDelegate = new DelegateDefinition(module.OutputNamespace, delegateString); - Context.Delegates.Add(decl, existingDelegate); + Type pointee = desugared.GetPointee() ?? desugared; + if (pointee is TypedefType) + return type; - libsDelegates[module].Add(delegateString, existingDelegate); + var functionType = pointee.Desugar() as FunctionType; + if (functionType == null) + return type; - namespaceDelegates.Declarations.Add(@delegate); + TypedefDecl @delegate = GetDelegate(type, decl); + return new QualifiedType(new TypedefType { Declaration = @delegate }); } - private void VisitFunctionTypeParameters(Function function) + private TypedefDecl GetDelegate(QualifiedType type, ITypedDecl decl) { - foreach (var param in from param in function.Parameters - where !(param.Type is TypedefType) - let paramType = param.Type.Desugar() - where paramType.IsAddress() && - paramType.GetPointee() is FunctionType - select param) + FunctionType newFunctionType = GetNewFunctionType(decl, type); + + var delegateName = GetDelegateName(newFunctionType); + var access = decl is Method ? AccessSpecifier.Private : AccessSpecifier.Public; + var existingDelegate = delegates.SingleOrDefault(t => t.Name == delegateName); + if (existingDelegate != null) { - var module = function.TranslationUnit.Module; - AddDelegatesToDictionary(param, module); + // Ensure a delegate used for a virtual method and a type is public + if (existingDelegate.Access == AccessSpecifier.Private && + access == AccessSpecifier.Public) + existingDelegate.Access = access; + + // Check if there is an existing delegate with a different calling convention + if (((FunctionType) existingDelegate.Type.GetPointee()).CallingConvention == + newFunctionType.CallingConvention) + return existingDelegate; + + // Add a new delegate with the calling convention appended to its name + delegateName += newFunctionType.CallingConvention; } + + var namespaceDelegates = GetDeclContextForDelegates(((Declaration) decl).Namespace); + var delegateType = new QualifiedType(new PointerType(new QualifiedType(newFunctionType))); + existingDelegate = new TypedefDecl + { + Access = access, + Name = delegateName, + Namespace = namespaceDelegates, + QualifiedType = delegateType, + IsSynthetized = true + }; + delegates.Add(existingDelegate); + + return existingDelegate; } - public override bool VisitFunctionDecl(Function function) + private FunctionType GetNewFunctionType(ITypedDecl decl, QualifiedType type) { - if (!base.VisitFunctionDecl(function) || function.Ignore) - return false; + var functionType = new FunctionType(); + var method = decl as Method; + if (method != null && method.FunctionType == type) + { + functionType.Parameters.AddRange( + method.GatherInternalParams(Context.ParserOptions.IsItaniumLikeAbi, true)); + functionType.CallingConvention = method.CallingConvention; + functionType.IsDependent = method.IsDependent; + functionType.ReturnType = method.ReturnType; + } + else + { + var funcTypeParam = (FunctionType) decl.Type.Desugar().GetFinalPointee().Desugar(); + functionType = new FunctionType(funcTypeParam); + } - // HACK : We should shift this call to VisitFunctionTypeParameters in VisitParameter. We can't do it now - // because we need to use the module and a since a parameter's namespace is null, we can't reach the - // translation unit and thus the module - VisitFunctionTypeParameters(function); + for (int i = 0; i < functionType.Parameters.Count; i++) + functionType.Parameters[i].Name = $"_{i}"; - return true; + return functionType; } - public override bool VisitMethodDecl(Method method) + private DeclarationContext GetDeclContextForDelegates(DeclarationContext @namespace) { - if (!base.VisitMethodDecl(method) || !method.IsVirtual || method.Ignore) - return false; - - var module = method.TranslationUnit.Module; - AddDelegatesToDictionary(method, module); + if (Options.IsCLIGenerator) + return @namespace is Function ? @namespace.Namespace : @namespace; - return true; - } - - private DelegateDefinition GetExistingDelegate(Module module, string delegateString) - { - if (module.Libraries.Count == 0) - return Context.Delegates.Values.FirstOrDefault(t => t.Signature == delegateString); + var module = @namespace.TranslationUnit.Module; + if (namespacesDelegates.ContainsKey(module)) + return namespacesDelegates[module]; - DelegateDefinition @delegate = null; - if (new[] { module }.Union(module.Dependencies).Any( - m => libsDelegates.ContainsKey(m) && libsDelegates[m].TryGetValue( - delegateString, out @delegate))) - return @delegate; + Namespace parent = null; + if (string.IsNullOrEmpty(module.OutputNamespace)) + { + var groups = module.Units.SelectMany(u => u.Declarations).OfType( + ).GroupBy(d => d.Name).Where(g => g.Any(d => d.HasDeclarations)).ToList(); + if (groups.Count == 1) + parent = groups.Last().Last(); + } + + if (parent == null) + parent = module.Units.Last(); - return null; + var namespaceDelegates = new Namespace + { + Name = "Delegates", + Namespace = parent + }; + namespacesDelegates.Add(module, namespaceDelegates); + + return namespaceDelegates; } - private string GenerateDelegateSignature(IEnumerable @params, QualifiedType returnType) + private string GetDelegateName(FunctionType functionType) { var typesBuilder = new StringBuilder(); - if (!returnType.Type.IsPrimitiveType(PrimitiveType.Void)) + if (!functionType.ReturnType.Type.IsPrimitiveType(PrimitiveType.Void)) { - typesBuilder.Insert(0, returnType.Visit(TypePrinter)); + typesBuilder.Insert(0, functionType.ReturnType.Visit(TypePrinter)); typesBuilder.Append('_'); } - foreach (var parameter in @params) + + foreach (var parameter in functionType.Parameters) { typesBuilder.Append(parameter.Visit(TypePrinter)); typesBuilder.Append('_'); } + if (typesBuilder.Length > 0) typesBuilder.Remove(typesBuilder.Length - 1, 1); + var delegateName = FormatTypesStringForIdentifier(typesBuilder); - if (returnType.Type.IsPrimitiveType(PrimitiveType.Void)) + if (functionType.ReturnType.Type.IsPrimitiveType(PrimitiveType.Void)) delegateName.Insert(0, "Action_"); else delegateName.Insert(0, "Func_"); @@ -239,9 +239,13 @@ namespace CppSharp.Passes } } - private Dictionary namespacesDelegates = new Dictionary(); + private Dictionary namespacesDelegates = new Dictionary(); private CSharpTypePrinter typePrinter; - private static readonly Dictionary> libsDelegates = - new Dictionary>(); + + /// + /// The generated typedefs. The tree can't be modified while + /// iterating over it, so we collect all the typedefs and add them at the end. + /// + private readonly List delegates = new List(); } } diff --git a/src/Generator/Passes/GenerateAnonymousDelegatesPass.cs b/src/Generator/Passes/GenerateAnonymousDelegatesPass.cs deleted file mode 100644 index cff31d2a..00000000 --- a/src/Generator/Passes/GenerateAnonymousDelegatesPass.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using CppSharp.AST; -using CppSharp.AST.Extensions; - -namespace CppSharp.Passes -{ - /// - /// C++ function pointers are converted to delegates. If the function pointer is typedef'd then a delegate is - /// generated with that name, otherwise the generic Action or Func delegates are used. The delegates are marhsalled - /// using the GetDelegateForFunctionPointer and GetFunctionPointerForDelegate methods; unfortunately, these methods - /// don't support generic types, so marshalling fails when function pointers are used without typedefs. This pass - /// generates explicit delegates for these function pointers when used as function arguments or return types. - /// - public class GenerateAnonymousDelegatesPass : TranslationUnitPass - { - private struct Typedef - { - public DeclarationContext Context; - public TypedefDecl Declaration; - } - - /// - /// The generated typedefs keyed by the qualified declaration context name. The tree can't be modified while - /// iterating over it, so we collect all the typedefs and add them at the end. - /// - private readonly Dictionary> allTypedefs = new Dictionary>(); - - public override bool VisitASTContext(ASTContext context) - { - bool result = base.VisitASTContext(context); - - foreach (var typedef in allTypedefs) - { - foreach (var foo in typedef.Value) - { - foo.Context.Declarations.Add(foo.Declaration); - } - } - allTypedefs.Clear(); - - return result; - } - - public override bool VisitFunctionDecl(Function function) - { - if (!base.VisitFunctionDecl(function) || function.Ignore) - return false; - - function.ReturnType = CheckType(function.Namespace, function.ReturnType); - foreach (var parameter in function.Parameters) - { - parameter.QualifiedType = CheckType(function.Namespace, parameter.QualifiedType); - } - return true; - } - - /// - /// Generates a new typedef for the given type if necessary and returns the new type. - /// - /// The namespace the typedef will be added to. - /// The type to check. - /// The new type. - private QualifiedType CheckType(DeclarationContext @namespace, QualifiedType type) - { - if (type.Type.IsDependent) - return type; - - var pointerType = type.Type as PointerType; - if (pointerType == null) - return type; - - var functionType = pointerType.Pointee as FunctionType; - if (functionType == null) - return type; - - List typedefs; - if (!allTypedefs.TryGetValue(@namespace.QualifiedName, out typedefs)) - { - typedefs = new List(); - allTypedefs.Add(@namespace.QualifiedName, typedefs); - } - - var typedef = FindMatchingTypedef(typedefs, functionType); - if (typedef == null) - { - for (int i = 0; i < functionType.Parameters.Count; i++) - { - functionType.Parameters[i].Name = string.Format("_{0}", i); - } - - typedef = new TypedefDecl - { - Access = AccessSpecifier.Public, - Name = string.Format("__AnonymousDelegate{0}", typedefs.Count), - Namespace = @namespace, - QualifiedType = type, - IsSynthetized = true - }; - typedefs.Add(new Typedef - { - Context = @namespace, - Declaration = typedef - }); - } - - var typedefType = new TypedefType - { - Declaration = typedef - }; - return new QualifiedType(typedefType); - } - - /// - /// Finds a typedef with the same return type and parameter types. - /// - /// The typedef list to search. - /// The function to match. - /// The matching typedef, or null if not found. - private static TypedefDecl FindMatchingTypedef(IEnumerable typedefs, FunctionType functionType) - { - return (from typedef in typedefs - let type = (FunctionType)typedef.Declaration.Type.GetPointee() - where type.ReturnType == functionType.ReturnType && - type.Parameters.SequenceEqual(functionType.Parameters, ParameterTypeComparer.Instance) - select typedef.Declaration).SingleOrDefault(); - } - } -} diff --git a/tests/CSharp/CSharp.cpp b/tests/CSharp/CSharp.cpp index 416c9088..89e3df73 100644 --- a/tests/CSharp/CSharp.cpp +++ b/tests/CSharp/CSharp.cpp @@ -1382,6 +1382,12 @@ int funcWithTypedefedFuncPtrAsParam(typedefedFuncPtr* func) return func(a, b); } +typedefedFuncPtr* TestDuplicateDelegate::testDuplicateDelegate(int a) +{ + typedefedFuncPtr* func; + return func; +} + void InlineNamespace::FunctionInsideInlineNamespace() { } diff --git a/tests/CSharp/CSharp.h b/tests/CSharp/CSharp.h index d3e89c0b..b7230864 100644 --- a/tests/CSharp/CSharp.h +++ b/tests/CSharp/CSharp.h @@ -1225,6 +1225,12 @@ void useStdStringJustAsParameter(std::string s); typedef int (typedefedFuncPtr)(Foo* a, Bar b); int DLL_API funcWithTypedefedFuncPtrAsParam(typedefedFuncPtr* func); +class DLL_API TestDuplicateDelegate +{ +public: + virtual typedefedFuncPtr* testDuplicateDelegate(int a); +}; + inline namespace InlineNamespace { diff --git a/tests/Common/Common.Tests.cs b/tests/Common/Common.Tests.cs index 9a8ee54f..33acdc5f 100644 --- a/tests/Common/Common.Tests.cs +++ b/tests/Common/Common.Tests.cs @@ -556,7 +556,7 @@ public class CommonTests : GeneratorTestFixture new TestDelegates().MarshalUnattributedDelegate(i => i); } - [Test, Platform(Exclude = "Win", Reason = "This test crashes our Windows build, possibly a problem with the NUnit runner there.")] + [Test] public void TestPassAnonymousDelegate() { var testDelegates = new TestDelegates();