Esempio n. 1
0
        public override bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals)
        {
            if (!VisitType(typedef, quals))
            {
                return(false);
            }

            var decl = typedef.Declaration;

            var functionType = decl.Type as FunctionType;

            if (functionType != null || decl.Type.IsPointerTo(out functionType))
            {
                var ptrName = $"{Generator.GeneratedIdentifier("ptr")}{Context.ParameterIndex}";

                Context.Before.WriteLine($"var {ptrName} = {Context.ReturnVarName};");

                var  specialization = decl.Namespace as ClassTemplateSpecialization;
                Type returnType     = Context.ReturnType.Type.Desugar();
                var  finalType      = (returnType.GetFinalPointee() ?? returnType).Desugar();
                var  res            = string.Format(
                    "{0} == IntPtr.Zero? null : {1}({2}) Marshal.GetDelegateForFunctionPointer({0}, typeof({2}))",
                    ptrName,
                    finalType.IsDependent ? $@"({specialization.TemplatedDecl.TemplatedClass.Typedefs.First(
                        t => t.Name == decl.Name).Visit(this.typePrinter)}) (object) " : string.Empty,
                    typedef);
                Context.Return.Write(res);
                return(true);
            }

            return(decl.Type.Visit(this));
        }
Esempio n. 2
0
        public override bool VisitClassDecl(Class @class)
        {
            var  originalClass = @class.OriginalClass ?? @class;
            Type returnType    = Context.ReturnType.Type.Desugar();

            // if the class is an abstract impl, use the original for the object map
            var qualifiedClass = originalClass.Visit(typePrinter);

            if (returnType.IsAddress())
            {
                Context.Return.Write(HandleReturnedPointer(@class, qualifiedClass.Type));
            }
            else
            {
                Context.Return.Write($"{qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName})");
            }

            var   finalType = (returnType.GetFinalPointee() ?? returnType).Desugar();
            Class returnedClass;

            if (finalType.TryGetClass(out returnedClass) && returnedClass.IsDependent)
            {
                Context.Return.Write($" as {returnType.Visit(typePrinter)}");
            }
            return(true);
        }
Esempio n. 3
0
        public bool FindTypeMap(Type type, out TypeMap typeMap)
        {
            if (typeMaps.ContainsKey(type))
            {
                typeMap = typeMaps[type];
                return(typeMap.IsEnabled);
            }

            var template = type as TemplateSpecializationType;

            if (template != null)
            {
                var specialization = template.GetClassTemplateSpecialization();
                if (specialization != null && FindTypeMap(specialization, type, out typeMap))
                {
                    return(true);
                }
                if (template.Template.TemplatedDecl != null)
                {
                    return(FindTypeMap(template.Template.TemplatedDecl, type,
                                       out typeMap));
                }
            }

            Type desugared  = type.Desugar();
            bool printExtra = desugared.GetPointee() != null &&
                              desugared.GetFinalPointee().Desugar().IsPrimitiveType();
            var typePrinter = new CppTypePrinter
            {
                PrintTypeQualifiers = printExtra,
                PrintTypeModifiers  = printExtra,
                PrintLogicalNames   = true
            };

            foreach (var resolveTypeDefs in new[] { true, false })
            {
                foreach (var typePrintScopeKind in
                         new[] { TypePrintScopeKind.Local, TypePrintScopeKind.Qualified })
                {
                    typePrinter.ResolveTypedefs = resolveTypeDefs;
                    typePrinter.PrintScopeKind  = typePrintScopeKind;
                    if (FindTypeMap(type.Visit(typePrinter), out typeMap))
                    {
                        typeMap.Type   = type;
                        typeMaps[type] = typeMap;
                        return(true);
                    }
                }
            }

            typeMap = null;
            var typedef = type as TypedefType;

            return(typedef != null && FindTypeMap(typedef.Declaration, type, out typeMap));
        }
Esempio n. 4
0
        public static void CheckTypeForSpecialization(Type type, Declaration container,
                                                      Action <ClassTemplateSpecialization> addSpecialization,
                                                      ITypeMapDatabase typeMaps, bool internalOnly = false)
        {
            type = type.Desugar();
            type = (type.GetFinalPointee() ?? type).Desugar();
            ClassTemplateSpecialization specialization;

            type.TryGetDeclaration(out specialization);
            if (specialization == null)
            {
                return;
            }

            TypeMap typeMap;

            typeMaps.FindTypeMap(specialization, out typeMap);

            if ((!internalOnly && (((specialization.Ignore ||
                                     specialization.TemplatedDecl.TemplatedClass.Ignore) && typeMap == null) ||
                                   specialization.Arguments.Any(a => UnsupportedTemplateArgument(
                                                                    specialization, a, typeMaps)))) ||
                specialization.IsIncomplete ||
                (!internalOnly && specialization.TemplatedDecl.TemplatedClass.IsIncomplete) ||
                specialization is ClassTemplatePartialSpecialization ||
                container.Namespace == specialization)
            {
                return;
            }

            while (container.Namespace != null)
            {
                if (container.Namespace == specialization)
                {
                    return;
                }
                container = container.Namespace;
            }

            if (!internalOnly && typeMaps.FindTypeMap(specialization, out typeMap))
            {
                var typePrinterContext = new TypePrinterContext {
                    Type = type
                };
                var mappedTo = typeMap.CSharpSignatureType(typePrinterContext);
                mappedTo = mappedTo.Desugar();
                mappedTo = (mappedTo.GetFinalPointee() ?? mappedTo);
                if (mappedTo.IsPrimitiveType() || mappedTo.IsPointerToPrimitiveType() || mappedTo.IsEnum())
                {
                    return;
                }
            }

            addSpecialization(specialization);
        }
Esempio n. 5
0
        public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals)
        {
            Type returnType = Context.ReturnType.Type.Desugar();
            Type finalType  = (returnType.GetFinalPointee() ?? returnType).Desugar();

            if (finalType.IsDependent)
            {
                Context.Return.Write($"({param.ReplacedParameter.Parameter.Name}) (object) ");
            }
            if (param.Replacement.Type.Desugar().IsPointerToPrimitiveType())
            {
                Context.Return.Write($"({CSharpTypePrinter.IntPtrType}) ");
            }
            return(base.VisitTemplateParameterSubstitutionType(param, quals));
        }
Esempio n. 6
0
        public static bool IsTypeExternal(Module module, Type type)
        {
            Declaration declaration;

            if (!(type.GetFinalPointee() ?? type).TryGetDeclaration(out declaration))
            {
                return(false);
            }

            declaration = declaration.CompleteDeclaration ?? declaration;
            if (declaration.Namespace == null || declaration.TranslationUnit.Module == null)
            {
                return(false);
            }

            return(declaration.TranslationUnit.Module.Dependencies.Contains(module));
        }
Esempio n. 7
0
        public static bool CheckTypeForSpecialization(Type type, Declaration container,
                                                      Action <ClassTemplateSpecialization> addSpecialization,
                                                      ITypeMapDatabase typeMaps, bool internalOnly = false)
        {
            type = type.Desugar();
            type = (type.GetFinalPointee() ?? type).Desugar();
            ClassTemplateSpecialization specialization = GetParentSpecialization(type);

            if (specialization == null)
            {
                return(true);
            }

            if (IsSpecializationNeeded(container, typeMaps, internalOnly,
                                       type, specialization))
            {
                return(false);
            }

            if (!internalOnly)
            {
                if (IsSpecializationSelfContained(specialization, container))
                {
                    return(true);
                }

                if (IsMappedToPrimitive(typeMaps, type))
                {
                    return(true);
                }
            }

            if (specialization.Arguments.Select(
                    a => a.Type.Type).Any(t => t != null &&
                                          !CheckTypeForSpecialization(t, specialization, addSpecialization,
                                                                      typeMaps, internalOnly)))
            {
                return(false);
            }

            addSpecialization(specialization);
            return(true);
        }
Esempio n. 8
0
        public override TypePrinterResult VisitParameter(Parameter arg, bool hasName = true)
        {
            var type      = arg.Type.Visit(this, arg.QualifiedType.Qualifiers).Type;
            var name      = arg.Name;
            var printName = hasName && !string.IsNullOrEmpty(name);

            if (PrintFlavorKind == CppTypePrintFlavorKind.ObjC)
            {
                return(printName ? string.Format(":({0}){1}", type, name)
                    : string.Format(":({0})", type));
            }

            CppSharp.AST.Type desugared = arg.Type.Desugar();
            desugared = (desugared.GetFinalPointee() ?? desugared).Desugar();
            return(printName ?
                   ((!(arg.Type is TypedefType) || ResolveTypedefs) &&
                    desugared is FunctionType ?
                    type.Replace("(*)", $"(*{name})") : $"{type} {name}") : type);
        }
Esempio n. 9
0
        private void MarshalRefClass(Class @class)
        {
            var method = Context.Function as Method;

            if (method != null &&
                method.Conversion == MethodConversionKind.FunctionToInstanceMethod &&
                Context.ParameterIndex == 0)
            {
                Context.Return.Write("{0}", Helpers.InstanceIdentifier);
                return;
            }

            string param = Context.Parameter.Name;
            Type   type  = Context.Parameter.Type.Desugar(resolveTemplateSubstitution: false);
            string paramInstance;
            Class  @interface;
            var    finalType    = type.GetFinalPointee() ?? type;
            var    templateType = finalType as TemplateParameterSubstitutionType;

            type = Context.Parameter.Type.Desugar();
            if (finalType.TryGetClass(out @interface) &&
                @interface.IsInterface)
            {
                paramInstance = $"{param}.__PointerTo{@interface.OriginalClass.Name}";
            }
            else
            {
                paramInstance = $@"{
                    (templateType != null ? $"(({@class.Visit(typePrinter)}) (object) " : string.Empty)}{
                    param}{(templateType != null ? ")" : string.Empty)
                    }.{Helpers.InstanceIdentifier}";
            }
            if (type.IsAddress())
            {
                Class decl;
                if (type.TryGetClass(out decl) && decl.IsValueType)
                {
                    Context.Return.Write(paramInstance);
                }
                else
                {
                    if (type.IsPointer())
                    {
                        Context.Return.Write("{0}{1}",
                                             method != null && method.OperatorKind == CXXOperatorKind.EqualEqual
                                ? string.Empty
                                : $"ReferenceEquals({param}, null) ? global::System.IntPtr.Zero : ",
                                             paramInstance);
                    }
                    else
                    {
                        if (method == null ||
                            // redundant for comparison operators, they are handled in a special way
                            (method.OperatorKind != CXXOperatorKind.EqualEqual &&
                             method.OperatorKind != CXXOperatorKind.ExclaimEqual))
                        {
                            Context.Before.WriteLine("if (ReferenceEquals({0}, null))", param);
                            Context.Before.WriteLineIndent(
                                "throw new global::System.ArgumentNullException(\"{0}\", " +
                                "\"Cannot be null because it is a C++ reference (&).\");",
                                param);
                        }
                        Context.Return.Write(paramInstance);
                    }
                }
                return;
            }

            var realClass           = @class.OriginalClass ?? @class;
            var qualifiedIdentifier = typePrinter.PrintNative(realClass);

            Context.Return.Write(
                "ReferenceEquals({0}, null) ? new {1}() : *({1}*) {2}",
                param, qualifiedIdentifier, paramInstance);
        }
Esempio n. 10
0
        public override bool VisitClassDecl(Class @class)
        {
            var  originalClass = @class.OriginalClass ?? @class;
            Type returnType    = Context.ReturnType.Type.Desugar();

            // if the class is an abstract impl, use the original for the object map
            var qualifiedClass = originalClass.Visit(typePrinter);

            var   finalType = (returnType.GetFinalPointee() ?? returnType).Desugar();
            Class returnedClass;

            if (finalType.TryGetClass(out returnedClass) && returnedClass.IsDependent)
            {
                Context.Return.Write($"({returnType.Visit(typePrinter)}) (object) ");
            }

            // these two aren't the same for members of templates
            if (Context.Function?.OriginalReturnType.Type.Desugar().IsAddress() == true ||
                returnType.IsAddress())
            {
                Context.Return.Write(HandleReturnedPointer(@class, qualifiedClass));
            }
            else
            {
                if (Context.MarshalKind == MarshalKind.NativeField ||
                    Context.MarshalKind == MarshalKind.Variable ||
                    Context.MarshalKind == MarshalKind.ReturnVariableArray ||
                    !originalClass.HasNonTrivialDestructor)
                {
                    Context.Return.Write($"{qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName})");
                }
                else
                {
                    Context.Before.WriteLine($@"var __{Context.ReturnVarName} = {
                        qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName});");
                    Method dtor = originalClass.Destructors.First();
                    if (dtor.IsVirtual)
                    {
                        var i           = VTables.GetVTableIndex(dtor);
                        int vtableIndex = 0;
                        if (Context.Context.ParserOptions.IsMicrosoftAbi)
                        {
                            vtableIndex = @class.Layout.VFTables.IndexOf(@class.Layout.VFTables.First(
                                                                             v => v.Layout.Components.Any(c => c.Method == dtor)));
                        }
                        string instance = $"new {typePrinter.IntPtrType}(&{Context.ReturnVarName})";
                        Context.Before.WriteLine($@"var __vtables = new IntPtr[] {{ {
                            string.Join(", ", originalClass.Layout.VTablePointers.Select(
                                x => $"*({typePrinter.IntPtrType}*) ({instance} + {x.Offset})"))} }};");
                        Context.Before.WriteLine($@"var __slot = *({typePrinter.IntPtrType}*) (__vtables[{
                            vtableIndex}] + {i} * sizeof({typePrinter.IntPtrType}));");
                        Context.Before.Write($"Marshal.GetDelegateForFunctionPointer<{dtor.FunctionType}>(__slot)({instance}");
                        if (dtor.GatherInternalParams(Context.Context.ParserOptions.IsItaniumLikeAbi).Count > 1)
                        {
                            Context.Before.Write(", 0");
                        }
                        Context.Before.WriteLine(");");
                    }
                    else
                    {
                        string suffix         = string.Empty;
                        var    specialization = @class as ClassTemplateSpecialization;
                        if (specialization != null)
                        {
                            suffix = Helpers.GetSuffixFor(specialization);
                        }
                        Context.Before.WriteLine($@"{typePrinter.PrintNative(originalClass)}.dtor{
                            suffix}(new {typePrinter.IntPtrType}(&{Context.ReturnVarName}));");
                    }
                    Context.Return.Write($"__{Context.ReturnVarName}");
                }
            }

            return(true);
        }
Esempio n. 11
0
        public bool FindTypeMap(Type type, out TypeMap typeMap)
        {
            // Looks up the type in the cache map.
            if (typeMaps.ContainsKey(type))
            {
                typeMap      = typeMaps[type];
                typeMap.Type = type;
                return(typeMap.IsEnabled);
            }

            var template = type as TemplateSpecializationType;

            if (template != null)
            {
                var specialization = template.GetClassTemplateSpecialization();
                if (specialization != null &&
                    FindTypeMap(specialization, out typeMap))
                {
                    return(true);
                }

                if (template.Template.TemplatedDecl != null)
                {
                    if (FindTypeMap(template.Template.TemplatedDecl,
                                    out typeMap))
                    {
                        typeMap.Type = type;
                        return(true);
                    }

                    return(false);
                }
            }

            Type desugared = type.Desugar();

            desugared = (desugared.GetFinalPointee() ?? desugared).Desugar();

            bool printExtra = desugared.IsPrimitiveType() ||
                              (desugared.GetFinalPointee() ?? desugared).Desugar().IsPrimitiveType();

            var typePrinter = new CppTypePrinter(Context)
            {
                ResolveTypeMaps     = false,
                PrintTypeQualifiers = printExtra,
                PrintTypeModifiers  = printExtra,
                PrintLogicalNames   = true
            };

            typePrinter.PushContext(TypePrinterContextKind.Native);

            foreach (var resolveTypeDefs in new[] { false, true })
            {
                foreach (var typePrintScopeKind in
                         new[] { TypePrintScopeKind.Local, TypePrintScopeKind.Qualified })
                {
                    typePrinter.ResolveTypedefs = resolveTypeDefs;
                    typePrinter.ScopeKind       = typePrintScopeKind;
                    var typeName = type.Visit(typePrinter);
                    if (FindTypeMap(typeName, out typeMap))
                    {
                        typeMap.Type   = type;
                        typeMaps[type] = typeMap;
                        return(true);
                    }
                }
            }

            typeMap = null;
            return(false);
        }
Esempio n. 12
0
        private void MarshalRefClass(Class @class)
        {
            var method = Context.Function as Method;

            if (method != null &&
                method.Conversion == MethodConversionKind.FunctionToInstanceMethod &&
                Context.ParameterIndex == 0)
            {
                Context.Return.Write("{0}", Helpers.InstanceIdentifier);
                return;
            }

            string param = Context.Parameter.Name;
            Type   type  = Context.Parameter.Type.Desugar();
            string paramInstance;
            Class  @interface;

            if ((type.GetFinalPointee() ?? type).TryGetClass(out @interface) &&
                @interface.IsInterface)
            {
                paramInstance = string.Format("{0}.__PointerTo{1}",
                                              param, @interface.OriginalClass.Name);
            }
            else
            {
                paramInstance = string.Format("{0}.{1}", param, Helpers.InstanceIdentifier);
            }
            if (type.IsAddress())
            {
                Class decl;
                if (type.TryGetClass(out decl) && decl.IsValueType)
                {
                    Context.Return.Write(paramInstance);
                }
                else
                {
                    if (type.IsPointer())
                    {
                        Context.Return.Write("{0}{1}",
                                             method != null && method.OperatorKind == CXXOperatorKind.EqualEqual
                                ? string.Empty
                                : string.Format("ReferenceEquals({0}, null) ? global::System.IntPtr.Zero : ", param),
                                             paramInstance);
                    }
                    else
                    {
                        if (method == null ||
                            // redundant for comparison operators, they are handled in a special way
                            (method.OperatorKind != CXXOperatorKind.EqualEqual &&
                             method.OperatorKind != CXXOperatorKind.ExclaimEqual))
                        {
                            Context.SupportBefore.WriteLine("if (ReferenceEquals({0}, null))", param);
                            Context.SupportBefore.WriteLineIndent(
                                "throw new global::System.ArgumentNullException(\"{0}\", " +
                                "\"Cannot be null because it is a C++ reference (&).\");",
                                param);
                        }
                        Context.Return.Write(paramInstance);
                    }
                }
                return;
            }

            var realClass           = @class.OriginalClass ?? @class;
            var qualifiedIdentifier = realClass.Visit(this.typePrinter);

            Context.Return.Write(
                "ReferenceEquals({0}, null) ? new {1}.{2}{3}() : *({1}.{2}{3}*) {4}",
                param, qualifiedIdentifier, Helpers.InternalStruct,
                Helpers.GetSuffixForInternal(@class), paramInstance);
        }