diff --git a/src/Generator/AST/Utils.cs b/src/Generator/AST/Utils.cs index 7ead35cd6b..d697ce40fe 100644 --- a/src/Generator/AST/Utils.cs +++ b/src/Generator/AST/Utils.cs @@ -147,8 +147,8 @@ private static bool UsesAdditionalTypeParam(Method method) }); } - private static bool UnsupportedTemplateArgument( - ClassTemplateSpecialization specialization, TemplateArgument a, ITypeMapDatabase typeMaps) + public static bool UnsupportedTemplateArgument(this ClassTemplateSpecialization specialization, + TemplateArgument a, ITypeMapDatabase typeMaps) { if (a.Type.Type == null || IsTypeExternal( @@ -168,8 +168,7 @@ private static bool IsSpecializationNeeded(Declaration container, return (!internalOnly && (((specialization.Ignore || specialization.TemplatedDecl.TemplatedClass.Ignore) && typeMap == null) || - specialization.Arguments.Any(a => UnsupportedTemplateArgument( - specialization, a, typeMaps)) || + specialization.Arguments.Any(a => specialization.UnsupportedTemplateArgument(a, typeMaps)) || container.Namespace == specialization)) || (!internalOnly && specialization.TemplatedDecl.TemplatedClass.IsIncomplete) || specialization is ClassTemplatePartialSpecialization; diff --git a/src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs b/src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs index fb01dbde06..b122c0ea80 100644 --- a/src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs +++ b/src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs @@ -41,6 +41,7 @@ public static IEnumerable KeepSingleAllPointersSpecialization( static bool allPointers(TemplateArgument a) => a.Type.Type?.Desugar().IsAddress() == true; var groups = (from @class in specializations let spec = @class.GetParentSpecialization() + orderby spec.IsGenerated descending group @class by spec.Arguments.All(allPointers) into @group select @group).ToList(); diff --git a/src/Generator/Passes/CheckIgnoredDecls.cs b/src/Generator/Passes/CheckIgnoredDecls.cs index 6ab94bbc4f..9d5d3c6d4c 100644 --- a/src/Generator/Passes/CheckIgnoredDecls.cs +++ b/src/Generator/Passes/CheckIgnoredDecls.cs @@ -52,7 +52,9 @@ public override bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializ return false; TypeMap typeMap; - if (!Options.GenerateClassTemplates && !specialization.IsExplicitlyGenerated && + if (!Options.GenerateClassTemplates && + !specialization.IsExplicitlyGenerated && + specialization.GenerationKind != GenerationKind.Internal && !Context.TypeMaps.FindTypeMap(specialization, out typeMap)) { specialization.ExplicitlyIgnore(); @@ -578,7 +580,7 @@ private bool IsDeclIgnored(Declaration decl) private void IgnoreUnsupportedTemplates(Class @class) { if (@class.TemplateParameters.Any(param => param is NonTypeTemplateParameter)) - foreach (var specialization in @class.Specializations) + foreach (var specialization in @class.Specializations.Where(s => s.IsGenerated)) specialization.ExplicitlyIgnore(); if (!Options.IsCLIGenerator && !@class.TranslationUnit.IsSystemHeader && @@ -589,7 +591,7 @@ private void IgnoreUnsupportedTemplates(Class @class) foreach (var specialization in @class.Specializations) if (specialization.IsExplicitlyGenerated) hasExplicitlyGeneratedSpecializations = true; - else + else if (specialization.GenerationKind != GenerationKind.Internal) specialization.ExplicitlyIgnore(); if (!hasExplicitlyGeneratedSpecializations) diff --git a/src/Generator/Passes/GenerateSymbolsPass.cs b/src/Generator/Passes/GenerateSymbolsPass.cs index 5829e13b89..8610a69b58 100644 --- a/src/Generator/Passes/GenerateSymbolsPass.cs +++ b/src/Generator/Passes/GenerateSymbolsPass.cs @@ -83,6 +83,16 @@ private void GenerateSymbols() } } + public override bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization) + { + if (!specialization.IsGenerated || + specialization.Arguments.Any( + a => specialization.UnsupportedTemplateArgument(a, Context.TypeMaps))) + return false; + + return base.VisitClassTemplateSpecializationDecl(specialization); + } + public override bool VisitClassDecl(Class @class) { if (!base.VisitClassDecl(@class)) diff --git a/src/Generator/Passes/IgnoreSystemDeclarationsPass.cs b/src/Generator/Passes/IgnoreSystemDeclarationsPass.cs index 80f34b1cc2..e88dd78804 100644 --- a/src/Generator/Passes/IgnoreSystemDeclarationsPass.cs +++ b/src/Generator/Passes/IgnoreSystemDeclarationsPass.cs @@ -35,7 +35,7 @@ public override bool VisitClassDecl(Class @class) if (!@class.IsDependent || @class.Specializations.Count == 0) return false; - foreach (var specialization in @class.Specializations) + foreach (var specialization in @class.Specializations.Where(s => s.IsGenerated)) specialization.ExplicitlyIgnore(); // we only need a few members for marshalling so strip the rest @@ -51,6 +51,7 @@ where arg.IsPrimitiveType(PrimitiveType.Char) select s) { specialization.GenerationKind = GenerationKind.Generate; + InternalizeSpecializationsInFields(specialization); } break; } @@ -100,5 +101,22 @@ public override bool VisitVariableDecl(Variable variable) return true; } + + private void InternalizeSpecializationsInFields(ClassTemplateSpecialization specialization) + { + foreach (Field field in specialization.Fields) + { + ASTUtils.CheckTypeForSpecialization(field.Type, specialization, + specialization => + { + if (!specialization.IsExplicitlyGenerated && + specialization.GenerationKind != GenerationKind.Internal) + { + specialization.GenerationKind = GenerationKind.Internal; + InternalizeSpecializationsInFields(specialization); + } + }, Context.TypeMaps, true); + } + } } } diff --git a/src/Generator/Passes/TrimSpecializationsPass.cs b/src/Generator/Passes/TrimSpecializationsPass.cs index d6d4400f87..b79fe63d5e 100644 --- a/src/Generator/Passes/TrimSpecializationsPass.cs +++ b/src/Generator/Passes/TrimSpecializationsPass.cs @@ -22,7 +22,7 @@ public override bool VisitASTContext(ASTContext context) public override bool VisitClassDecl(Class @class) { - if (!base.VisitClassDecl(@class)) + if (!@class.Ignore && !base.VisitClassDecl(@class)) return false; if (@class.IsTemplate) @@ -124,7 +124,7 @@ private void CleanSpecializations(Class template) specialization.ExplicitlyIgnore(); foreach (var specialization in template.Specializations.Where( - s => !s.IsExplicitlyGenerated && internalSpecializations.Contains(s))) + s => !s.IsExplicitlyGenerated && !s.Ignore && internalSpecializations.Contains(s))) specialization.GenerationKind = GenerationKind.Internal; for (int i = template.Specializations.Count - 1; i >= 0; i--) diff --git a/tests/NamespacesDerived/NamespacesDerived.Gen.cs b/tests/NamespacesDerived/NamespacesDerived.Gen.cs index 27adc4a47b..91267cebcf 100644 --- a/tests/NamespacesDerived/NamespacesDerived.Gen.cs +++ b/tests/NamespacesDerived/NamespacesDerived.Gen.cs @@ -27,6 +27,11 @@ public override void Setup(Driver driver) module.Libraries.Add($"{@base}.Native"); driver.Options.Modules[1].Dependencies.Add(module); } + + public override void Preprocess(Driver driver, AST.ASTContext ctx) + { + ctx.IgnoreClassWithName("Ignored"); + } } public static class NamespacesDerived diff --git a/tests/NamespacesDerived/NamespacesDerived.h b/tests/NamespacesDerived/NamespacesDerived.h index 223ad8ffed..b1e8e7bfa4 100644 --- a/tests/NamespacesDerived/NamespacesDerived.h +++ b/tests/NamespacesDerived/NamespacesDerived.h @@ -1,6 +1,7 @@ #include "../Tests.h" #include "../NamespacesBase/NamespacesBase.h" #include "Independent.h" +#include // Namespace clashes with NamespacesBase.OverlappingNamespace // Test whether qualified names turn out right. @@ -86,6 +87,27 @@ class DLL_API DerivedFromSecondaryBaseInDependency : public Derived, public Seco { }; +template +class CustomAllocator +{ +public: + typedef T value_type; + + T* allocate(size_t cnt, const void* = 0) + { + return 0; + } + void deallocate(T* p, size_t cnt) + { + } +}; + +class DLL_API Ignored +{ +private: + std::basic_string, CustomAllocator> f; +}; + DLL_API bool operator<<(const Base& b, const char* str); namespace NamespacesBase