Skip to content

Commit

Permalink
Generate valid C# for independent external specializations
Browse files Browse the repository at this point in the history
Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
  • Loading branch information
ddobrev committed Dec 26, 2021
1 parent 3b0eb18 commit c84a6c6
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 26 deletions.
15 changes: 13 additions & 2 deletions src/AST/ClassExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Property> GetConstCharFieldProperties(this Class @class) =>
Expand Down
6 changes: 1 addition & 5 deletions src/Generator/Generators/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 2 additions & 5 deletions src/Generator/Passes/TrimSpecializationsPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/// <summary>
Expand Down Expand Up @@ -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();
Expand Down
11 changes: 8 additions & 3 deletions tests/NamespacesBase/NamespacesBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,12 @@ void TemplateClass<T>::setField(const T& value)
}

template <typename T>
class TemplateWithIndependentFields
class IndependentFields
{
};

template <typename T>
class DependentFields
{
public:
class Nested
Expand All @@ -85,13 +90,13 @@ class TemplateWithIndependentFields
};

template <typename T>
const T& TemplateWithIndependentFields<T>::constField() const
const T& DependentFields<T>::constField() const
{
return *t;
}

template <typename T>
typename TemplateWithIndependentFields<T>::Nested TemplateWithIndependentFields<T>::useDependentPointer(const T* t)
typename DependentFields<T>::Nested DependentFields<T>::useDependentPointer(const T* t)
{
return Nested();
}
Expand Down
4 changes: 2 additions & 2 deletions tests/NamespacesDerived/Independent.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
class Derived;
template<typename T> class TemplateWithIndependentFields;
typedef TemplateWithIndependentFields<Derived*> ForwardedInIndependentHeader;
template<typename T> class DependentFields;
typedef DependentFields<Derived*> ForwardedInIndependentHeader;
11 changes: 8 additions & 3 deletions tests/NamespacesDerived/NamespacesDerived.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ TemplateClass<int> Derived2::getTemplate()
return t;
}

IndependentFields<int> Derived2::getIndependentSpecialization()
{
return independentSpecialization;
}

Derived2::LocalTypedefSpecialization Derived2::getLocalTypedefSpecialization()
{
return LocalTypedefSpecialization();
Expand All @@ -73,13 +78,13 @@ Abstract* Derived2::getAbstract()
}

DerivedFromExternalSpecialization::DerivedFromExternalSpecialization(int i,
TemplateWithIndependentFields<HasVirtualInDependency> defaultExternalSpecialization)
DependentFields<HasVirtualInDependency> defaultExternalSpecialization)
{
}

TemplateWithIndependentFields<Base3> DerivedFromExternalSpecialization::returnExternalSpecialization()
DependentFields<Base3> DerivedFromExternalSpecialization::returnExternalSpecialization()
{
return TemplateWithIndependentFields<Base3>();
return DependentFields<Base3>();
}

int HasVirtualInDependency::callManagedOverride()
Expand Down
15 changes: 9 additions & 6 deletions tests/NamespacesDerived/NamespacesDerived.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,16 @@ class DLL_API Derived2 : public Base3
void defaultEnumValueFromDependency(OverlappingNamespace::ColorsEnum c = OverlappingNamespace::ColorsEnum::black);

TemplateClass<int> getTemplate();
typedef TemplateWithIndependentFields<int> LocalTypedefSpecialization;
IndependentFields<int> getIndependentSpecialization();
typedef DependentFields<int> LocalTypedefSpecialization;
LocalTypedefSpecialization getLocalTypedefSpecialization();
Abstract* getAbstract();
private:
TemplateClass<int> t;
TemplateClass<Derived> d;
TemplateClass<TemplateWithIndependentFields<Derived>> nestedSpecialization;
TemplateClass<DependentFields<Derived>> nestedSpecialization;
IndependentFields<int> independentSpecialization;
IndependentFields<Derived> independentExternalSpecialization;
};

class DLL_API HasVirtualInDependency : public HasVirtualInCore
Expand All @@ -76,13 +79,13 @@ class DLL_API HasVirtualInDependency : public HasVirtualInCore
int callManagedOverride();
};

class DLL_API DerivedFromExternalSpecialization : public TemplateWithIndependentFields<Derived>
class DLL_API DerivedFromExternalSpecialization : public DependentFields<Derived>
{
public:
DerivedFromExternalSpecialization(int i,
TemplateWithIndependentFields<HasVirtualInDependency> defaultExternalSpecialization =
TemplateWithIndependentFields<HasVirtualInDependency>());
TemplateWithIndependentFields<Base3> returnExternalSpecialization();
DependentFields<HasVirtualInDependency> defaultExternalSpecialization =
DependentFields<HasVirtualInDependency>());
DependentFields<Base3> returnExternalSpecialization();
};

class DLL_API DerivedFromSecondaryBaseInDependency : public Derived, public SecondaryBase
Expand Down

0 comments on commit c84a6c6

Please sign in to comment.