From c84a6c606e8c40a09e4cee57fa8c36023a2bc3c9 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Sun, 26 Dec 2021 22:41:19 +0200 Subject: [PATCH] Generate valid C# for independent external specializations Signed-off-by: Dimitar Dobrev --- src/AST/ClassExtensions.cs | 15 +++++++++++++-- src/Generator/Generators/CodeGenerator.cs | 6 +----- src/Generator/Passes/TrimSpecializationsPass.cs | 7 ++----- tests/NamespacesBase/NamespacesBase.h | 11 ++++++++--- tests/NamespacesDerived/Independent.h | 4 ++-- tests/NamespacesDerived/NamespacesDerived.cpp | 11 ++++++++--- tests/NamespacesDerived/NamespacesDerived.h | 15 +++++++++------ 7 files changed, 43 insertions(+), 26 deletions(-) diff --git a/src/AST/ClassExtensions.cs b/src/AST/ClassExtensions.cs index 514b52490b..1e98671a54 100644 --- a/src/AST/ClassExtensions.cs +++ b/src/AST/ClassExtensions.cs @@ -252,8 +252,19 @@ public static bool HasDependentValueFieldInLayout(this Class @class) if (@class.Fields.Any(f => IsValueDependent(f.Type))) return true; - return @class.Bases.Where(b => b.IsClass).Select( - b => b.Class).Any(HasDependentValueFieldInLayout); + if (@class.Bases.Where(b => b.IsClass).Select( + b => b.Class).Any(HasDependentValueFieldInLayout)) + return true; + + // HACK: Clang can't always resolve complex templates such as the base of std::atomic in msvc + if (@class.IsTemplate && @class.Specializations.Any( + s => s.Layout.Fields.Any( + f => f.QualifiedType.Type.TryGetDeclaration( + out ClassTemplateSpecialization specialization) && + specialization.TemplatedDecl.TemplatedClass.HasDependentValueFieldInLayout()))) + return true; + + return false; } public static IEnumerable GetConstCharFieldProperties(this Class @class) => diff --git a/src/Generator/Generators/CodeGenerator.cs b/src/Generator/Generators/CodeGenerator.cs index b96b428b1b..fb7b629c54 100644 --- a/src/Generator/Generators/CodeGenerator.cs +++ b/src/Generator/Generators/CodeGenerator.cs @@ -1322,11 +1322,7 @@ public static string GetSuffixForInternal(Class @class) return "_Ptr"; return GetSuffixFor(specialization); } - // HACK: Clang can't always resolve complex templates such as the base of std::atomic in msvc - return (from @base in @class.Bases - let suffix = GetSuffixForInternal(@base.Class) - where suffix.Length > 0 - select suffix).DefaultIfEmpty(string.Empty).First(); + return string.Empty; } public static string GetSuffixFor(Declaration decl) diff --git a/src/Generator/Passes/TrimSpecializationsPass.cs b/src/Generator/Passes/TrimSpecializationsPass.cs index 80614c1548..6bee663d99 100644 --- a/src/Generator/Passes/TrimSpecializationsPass.cs +++ b/src/Generator/Passes/TrimSpecializationsPass.cs @@ -138,7 +138,8 @@ private void CleanSpecializations(Class template) template.Specializations.All(s => s.Ignore)) template.ExplicitlyIgnore(); - TryMoveExternalSpecializations(template); + if (template.Specializations.Any() && template.HasDependentValueFieldInLayout()) + TryMoveExternalSpecializations(template); } /// @@ -174,17 +175,13 @@ private static Module GetExternalModule(ClassTemplateSpecialization specializati { Module module = arg.Type.Type.GetModule(); if (module != null) - { modules.Add(module); - } } if (arg.Type.Type.TryGetDeclaration(out ClassTemplateSpecialization nestedSpecialization)) { Module module = GetExternalModule(nestedSpecialization); if (module != null) - { modules.Add(module); - } } } return modules.TopologicalSort(m => m.Dependencies).LastOrDefault(); diff --git a/tests/NamespacesBase/NamespacesBase.h b/tests/NamespacesBase/NamespacesBase.h index 99838835e4..e54e71aace 100644 --- a/tests/NamespacesBase/NamespacesBase.h +++ b/tests/NamespacesBase/NamespacesBase.h @@ -71,7 +71,12 @@ void TemplateClass::setField(const T& value) } template -class TemplateWithIndependentFields +class IndependentFields +{ +}; + +template +class DependentFields { public: class Nested @@ -85,13 +90,13 @@ class TemplateWithIndependentFields }; template -const T& TemplateWithIndependentFields::constField() const +const T& DependentFields::constField() const { return *t; } template -typename TemplateWithIndependentFields::Nested TemplateWithIndependentFields::useDependentPointer(const T* t) +typename DependentFields::Nested DependentFields::useDependentPointer(const T* t) { return Nested(); } diff --git a/tests/NamespacesDerived/Independent.h b/tests/NamespacesDerived/Independent.h index 2afe45bfbe..90ca3d8b8c 100644 --- a/tests/NamespacesDerived/Independent.h +++ b/tests/NamespacesDerived/Independent.h @@ -1,3 +1,3 @@ class Derived; -template class TemplateWithIndependentFields; -typedef TemplateWithIndependentFields ForwardedInIndependentHeader; \ No newline at end of file +template class DependentFields; +typedef DependentFields ForwardedInIndependentHeader; \ No newline at end of file diff --git a/tests/NamespacesDerived/NamespacesDerived.cpp b/tests/NamespacesDerived/NamespacesDerived.cpp index 29c549e73f..d6aed0a9d9 100644 --- a/tests/NamespacesDerived/NamespacesDerived.cpp +++ b/tests/NamespacesDerived/NamespacesDerived.cpp @@ -62,6 +62,11 @@ TemplateClass Derived2::getTemplate() return t; } +IndependentFields Derived2::getIndependentSpecialization() +{ + return independentSpecialization; +} + Derived2::LocalTypedefSpecialization Derived2::getLocalTypedefSpecialization() { return LocalTypedefSpecialization(); @@ -73,13 +78,13 @@ Abstract* Derived2::getAbstract() } DerivedFromExternalSpecialization::DerivedFromExternalSpecialization(int i, - TemplateWithIndependentFields defaultExternalSpecialization) + DependentFields defaultExternalSpecialization) { } -TemplateWithIndependentFields DerivedFromExternalSpecialization::returnExternalSpecialization() +DependentFields DerivedFromExternalSpecialization::returnExternalSpecialization() { - return TemplateWithIndependentFields(); + return DependentFields(); } int HasVirtualInDependency::callManagedOverride() diff --git a/tests/NamespacesDerived/NamespacesDerived.h b/tests/NamespacesDerived/NamespacesDerived.h index 613fcf23d7..812ffb480a 100644 --- a/tests/NamespacesDerived/NamespacesDerived.h +++ b/tests/NamespacesDerived/NamespacesDerived.h @@ -60,13 +60,16 @@ class DLL_API Derived2 : public Base3 void defaultEnumValueFromDependency(OverlappingNamespace::ColorsEnum c = OverlappingNamespace::ColorsEnum::black); TemplateClass getTemplate(); - typedef TemplateWithIndependentFields LocalTypedefSpecialization; + IndependentFields getIndependentSpecialization(); + typedef DependentFields LocalTypedefSpecialization; LocalTypedefSpecialization getLocalTypedefSpecialization(); Abstract* getAbstract(); private: TemplateClass t; TemplateClass d; - TemplateClass> nestedSpecialization; + TemplateClass> nestedSpecialization; + IndependentFields independentSpecialization; + IndependentFields independentExternalSpecialization; }; class DLL_API HasVirtualInDependency : public HasVirtualInCore @@ -76,13 +79,13 @@ class DLL_API HasVirtualInDependency : public HasVirtualInCore int callManagedOverride(); }; -class DLL_API DerivedFromExternalSpecialization : public TemplateWithIndependentFields +class DLL_API DerivedFromExternalSpecialization : public DependentFields { public: DerivedFromExternalSpecialization(int i, - TemplateWithIndependentFields defaultExternalSpecialization = - TemplateWithIndependentFields()); - TemplateWithIndependentFields returnExternalSpecialization(); + DependentFields defaultExternalSpecialization = + DependentFields()); + DependentFields returnExternalSpecialization(); }; class DLL_API DerivedFromSecondaryBaseInDependency : public Derived, public SecondaryBase