Browse Source

Fixed the generated C# for members of types nested in templates.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/1026/head
Dimitar Dobrev 9 years ago
parent
commit
fceb204a98
  1. 29
      src/AST/ClassExtensions.cs
  2. 2
      src/CLI/Generator.cs
  3. 18
      src/CppParser/AST.cpp
  4. 6
      src/CppParser/AST.h
  5. 10
      src/CppParser/Bindings/CLI/CppParser.cpp
  6. 6
      src/CppParser/Bindings/CLI/CppParser.h
  7. 18
      src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/CppSharp.CppParser.cs
  8. 18
      src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/CppSharp.CppParser.cs
  9. 18
      src/CppParser/Bindings/CSharp/x86_64-apple-darwin12.4.0/CppSharp.CppParser.cs
  10. 18
      src/CppParser/Bindings/CSharp/x86_64-linux-gnu-cxx11abi/CppSharp.CppParser.cs
  11. 18
      src/CppParser/Bindings/CSharp/x86_64-linux-gnu/CppSharp.CppParser.cs
  12. 18
      src/CppParser/Bindings/CSharp/x86_64-pc-win32-msvc/CppSharp.CppParser.cs
  13. 1
      src/CppParser/CppParser.cpp
  14. 1
      src/CppParser/CppParser.h
  15. 6
      src/CppParser/Parser.cpp
  16. 2
      src/CppParser/ParserGen/ParserGen.cs
  17. 2
      src/Generator/Driver.cs
  18. 15
      src/Generator/Generators/CSharp/CSharpSources.cs
  19. 5
      src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs
  20. 11
      src/Generator/Options.cs
  21. 36
      src/Generator/Passes/ResolveIncompleteDeclsPass.cs
  22. 3
      src/Generator/Passes/TrimSpecializationsPass.cs
  23. 3
      src/Parser/ParserOptions.cs
  24. 2
      tests/CSharp/AnotherUnit.h
  25. 7
      tests/CSharp/CSharp.cs
  26. 2
      tests/Common/Common.cs

29
src/AST/ClassExtensions.cs

@ -148,21 +148,36 @@ namespace CppSharp.AST
return units.Where(u => u.IsGenerated && (u.HasDeclarations || u.IsSystemHeader) && u.IsValid); return units.Where(u => u.IsGenerated && (u.HasDeclarations || u.IsSystemHeader) && u.IsValid);
} }
public static List<ClassTemplateSpecialization> GetSpecializationsToGenerate( public static IEnumerable<Class> GetSpecializedClassesToGenerate(
this Class classTemplate) this Class dependentClass)
{ {
if (classTemplate.HasDependentValueFieldInLayout()) IEnumerable<Class> specializedClasses = GetSpecializedClassesOf(dependentClass);
return classTemplate.Specializations; if (!specializedClasses.Any() || dependentClass.HasDependentValueFieldInLayout())
return specializedClasses;
var specializations = new List<ClassTemplateSpecialization>(); var specializations = new List<Class>();
var specialization = classTemplate.Specializations.FirstOrDefault(s => !s.Ignore); var specialization = specializedClasses.FirstOrDefault(s => s.IsGenerated);
if (specialization == null) if (specialization == null)
specializations.Add(classTemplate.Specializations[0]); specializations.Add(specializedClasses.First());
else else
specializations.Add(specialization); specializations.Add(specialization);
return specializations; return specializations;
} }
private static IEnumerable<Class> GetSpecializedClassesOf(this Class dependentClass)
{
if (dependentClass.IsTemplate)
return dependentClass.Specializations;
Class template = dependentClass.Namespace as Class;
if (template == null || !template.IsTemplate)
// just one level of nesting supported for the time being
return Enumerable.Empty<Class>();
return template.Specializations.SelectMany(s => s.Classes.Where(
c => c.Name == dependentClass.Name)).ToList();
}
public static bool HasDependentValueFieldInLayout(this Class @class) public static bool HasDependentValueFieldInLayout(this Class @class)
{ {
if (@class.Fields.Any(f => IsValueDependent(f.Type))) if (@class.Fields.Any(f => IsValueDependent(f.Type)))

2
src/CLI/Generator.cs

@ -189,7 +189,7 @@ namespace CppSharp
driverOptions.CompileCode = options.Compile; driverOptions.CompileCode = options.Compile;
driverOptions.OutputDir = options.OutputDir; driverOptions.OutputDir = options.OutputDir;
driverOptions.CheckSymbols = options.CheckSymbols; driverOptions.CheckSymbols = options.CheckSymbols;
driverOptions.UnityBuild = options.UnityBuild; parserOptions.UnityBuild = options.UnityBuild;
driverOptions.Verbose = options.Verbose; driverOptions.Verbose = options.Verbose;
} }

18
src/CppParser/AST.cpp

@ -350,7 +350,8 @@ Namespace* DeclarationContext::FindCreateNamespace(const std::string& Name)
return _namespace; return _namespace;
} }
Class* DeclarationContext::FindClass(const std::string& Name, bool IsComplete) Class* DeclarationContext::FindClass(const void* OriginalPtr,
const std::string& Name, bool IsComplete)
{ {
if (Name.empty()) return nullptr; if (Name.empty()) return nullptr;
@ -359,8 +360,9 @@ Class* DeclarationContext::FindClass(const std::string& Name, bool IsComplete)
if (entries.size() == 1) if (entries.size() == 1)
{ {
auto _class = std::find_if(Classes.begin(), Classes.end(), auto _class = std::find_if(Classes.begin(), Classes.end(),
[&](Class* klass) { return klass->name == Name && [OriginalPtr, Name, IsComplete](Class* klass) {
(klass->isIncomplete == !IsComplete); }); return (OriginalPtr && klass->originalPtr == OriginalPtr) ||
(klass->name == Name && klass->isIncomplete == !IsComplete); });
return _class != Classes.end() ? *_class : nullptr; return _class != Classes.end() ? *_class : nullptr;
} }
@ -374,10 +376,10 @@ Class* DeclarationContext::FindClass(const std::string& Name, bool IsComplete)
if (!_namespace) if (!_namespace)
return nullptr; return nullptr;
return _namespace->FindClass(className, IsComplete); return _namespace->FindClass(OriginalPtr, className, IsComplete);
} }
Class* DeclarationContext::CreateClass(std::string Name, bool IsComplete) Class* DeclarationContext::CreateClass(const std::string& Name, bool IsComplete)
{ {
auto _class = new Class(); auto _class = new Class();
_class->name = Name; _class->name = Name;
@ -387,10 +389,10 @@ Class* DeclarationContext::CreateClass(std::string Name, bool IsComplete)
return _class; return _class;
} }
Class* DeclarationContext::FindClass(const std::string& Name, bool IsComplete, Class* DeclarationContext::FindClass(const void* OriginalPtr,
bool Create) const std::string& Name, bool IsComplete, bool Create)
{ {
auto _class = FindClass(Name, IsComplete); auto _class = FindClass(OriginalPtr, Name, IsComplete);
if (!_class) if (!_class)
{ {

6
src/CppParser/AST.h

@ -516,9 +516,9 @@ public:
CS_IGNORE Namespace* FindNamespace(const std::vector<std::string>&); CS_IGNORE Namespace* FindNamespace(const std::vector<std::string>&);
CS_IGNORE Namespace* FindCreateNamespace(const std::string& Name); CS_IGNORE Namespace* FindCreateNamespace(const std::string& Name);
CS_IGNORE Class* CreateClass(std::string Name, bool IsComplete); CS_IGNORE Class* CreateClass(const std::string& Name, bool IsComplete);
CS_IGNORE Class* FindClass(const std::string& Name, bool IsComplete); CS_IGNORE Class* FindClass(const void* OriginalPtr, const std::string& Name, bool IsComplete);
CS_IGNORE Class* FindClass(const std::string& Name, bool IsComplete, CS_IGNORE Class* FindClass(const void* OriginalPtr, const std::string& Name, bool IsComplete,
bool Create); bool Create);
CS_IGNORE template<typename T> T* FindTemplate(const std::string& USR); CS_IGNORE template<typename T> T* FindTemplate(const std::string& USR);

10
src/CppParser/Bindings/CLI/CppParser.cpp

@ -480,6 +480,16 @@ void CppSharp::Parser::CppParserOptions::Verbose::set(bool value)
((::CppSharp::CppParser::CppParserOptions*)NativePtr)->verbose = value; ((::CppSharp::CppParser::CppParserOptions*)NativePtr)->verbose = value;
} }
bool CppSharp::Parser::CppParserOptions::UnityBuild::get()
{
return ((::CppSharp::CppParser::CppParserOptions*)NativePtr)->unityBuild;
}
void CppSharp::Parser::CppParserOptions::UnityBuild::set(bool value)
{
((::CppSharp::CppParser::CppParserOptions*)NativePtr)->unityBuild = value;
}
unsigned int CppSharp::Parser::CppParserOptions::ArgumentsCount::get() unsigned int CppSharp::Parser::CppParserOptions::ArgumentsCount::get()
{ {
auto __ret = ((::CppSharp::CppParser::CppParserOptions*)NativePtr)->getArgumentsCount(); auto __ret = ((::CppSharp::CppParser::CppParserOptions*)NativePtr)->getArgumentsCount();

6
src/CppParser/Bindings/CLI/CppParser.h

@ -187,6 +187,12 @@ namespace CppSharp
void set(bool); void set(bool);
} }
property bool UnityBuild
{
bool get();
void set(bool);
}
property unsigned int ArgumentsCount property unsigned int ArgumentsCount
{ {
unsigned int get(); unsigned int get();

18
src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/CppSharp.CppParser.cs

@ -18051,7 +18051,7 @@ namespace CppSharp
public unsafe partial class CppParserOptions : IDisposable public unsafe partial class CppParserOptions : IDisposable
{ {
[StructLayout(LayoutKind.Explicit, Size = 148)] [StructLayout(LayoutKind.Explicit, Size = 152)]
public partial struct __Internal public partial struct __Internal
{ {
[FieldOffset(0)] [FieldOffset(0)]
@ -18108,6 +18108,9 @@ namespace CppSharp
[FieldOffset(147)] [FieldOffset(147)]
internal byte verbose; internal byte verbose;
[FieldOffset(148)]
internal byte unityBuild;
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, [DllImport("CppSharp.CppParser", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser16CppParserOptionsC2Ev")] EntryPoint="_ZN8CppSharp9CppParser16CppParserOptionsC2Ev")]
@ -18638,6 +18641,19 @@ namespace CppSharp
} }
} }
public bool UnityBuild
{
get
{
return ((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild != 0;
}
set
{
((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild = (byte) (value ? 1 : 0);
}
}
public uint ArgumentsCount public uint ArgumentsCount
{ {
get get

18
src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/CppSharp.CppParser.cs

@ -18051,7 +18051,7 @@ namespace CppSharp
public unsafe partial class CppParserOptions : IDisposable public unsafe partial class CppParserOptions : IDisposable
{ {
[StructLayout(LayoutKind.Explicit, Size = 184)] [StructLayout(LayoutKind.Explicit, Size = 188)]
public partial struct __Internal public partial struct __Internal
{ {
[FieldOffset(0)] [FieldOffset(0)]
@ -18108,6 +18108,9 @@ namespace CppSharp
[FieldOffset(183)] [FieldOffset(183)]
internal byte verbose; internal byte verbose;
[FieldOffset(184)]
internal byte unityBuild;
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall, [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??0CppParserOptions@CppParser@CppSharp@@QAE@XZ")] EntryPoint="??0CppParserOptions@CppParser@CppSharp@@QAE@XZ")]
@ -18638,6 +18641,19 @@ namespace CppSharp
} }
} }
public bool UnityBuild
{
get
{
return ((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild != 0;
}
set
{
((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild = (byte) (value ? 1 : 0);
}
}
public uint ArgumentsCount public uint ArgumentsCount
{ {
get get

18
src/CppParser/Bindings/CSharp/x86_64-apple-darwin12.4.0/CppSharp.CppParser.cs

@ -18050,7 +18050,7 @@ namespace CppSharp
public unsafe partial class CppParserOptions : IDisposable public unsafe partial class CppParserOptions : IDisposable
{ {
[StructLayout(LayoutKind.Explicit, Size = 288)] [StructLayout(LayoutKind.Explicit, Size = 296)]
public partial struct __Internal public partial struct __Internal
{ {
[FieldOffset(0)] [FieldOffset(0)]
@ -18107,6 +18107,9 @@ namespace CppSharp
[FieldOffset(287)] [FieldOffset(287)]
internal byte verbose; internal byte verbose;
[FieldOffset(288)]
internal byte unityBuild;
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, [DllImport("CppSharp.CppParser", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser16CppParserOptionsC2Ev")] EntryPoint="_ZN8CppSharp9CppParser16CppParserOptionsC2Ev")]
@ -18637,6 +18640,19 @@ namespace CppSharp
} }
} }
public bool UnityBuild
{
get
{
return ((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild != 0;
}
set
{
((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild = (byte) (value ? 1 : 0);
}
}
public uint ArgumentsCount public uint ArgumentsCount
{ {
get get

18
src/CppParser/Bindings/CSharp/x86_64-linux-gnu-cxx11abi/CppSharp.CppParser.cs

@ -18050,7 +18050,7 @@ namespace CppSharp
public unsafe partial class CppParserOptions : IDisposable public unsafe partial class CppParserOptions : IDisposable
{ {
[StructLayout(LayoutKind.Explicit, Size = 312)] [StructLayout(LayoutKind.Explicit, Size = 320)]
public partial struct __Internal public partial struct __Internal
{ {
[FieldOffset(0)] [FieldOffset(0)]
@ -18107,6 +18107,9 @@ namespace CppSharp
[FieldOffset(311)] [FieldOffset(311)]
internal byte verbose; internal byte verbose;
[FieldOffset(312)]
internal byte unityBuild;
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, [DllImport("CppSharp.CppParser", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser16CppParserOptionsC2Ev")] EntryPoint="_ZN8CppSharp9CppParser16CppParserOptionsC2Ev")]
@ -18637,6 +18640,19 @@ namespace CppSharp
} }
} }
public bool UnityBuild
{
get
{
return ((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild != 0;
}
set
{
((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild = (byte) (value ? 1 : 0);
}
}
public uint ArgumentsCount public uint ArgumentsCount
{ {
get get

18
src/CppParser/Bindings/CSharp/x86_64-linux-gnu/CppSharp.CppParser.cs

@ -18050,7 +18050,7 @@ namespace CppSharp
public unsafe partial class CppParserOptions : IDisposable public unsafe partial class CppParserOptions : IDisposable
{ {
[StructLayout(LayoutKind.Explicit, Size = 240)] [StructLayout(LayoutKind.Explicit, Size = 248)]
public partial struct __Internal public partial struct __Internal
{ {
[FieldOffset(0)] [FieldOffset(0)]
@ -18107,6 +18107,9 @@ namespace CppSharp
[FieldOffset(239)] [FieldOffset(239)]
internal byte verbose; internal byte verbose;
[FieldOffset(240)]
internal byte unityBuild;
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, [DllImport("CppSharp.CppParser", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="_ZN8CppSharp9CppParser16CppParserOptionsC2Ev")] EntryPoint="_ZN8CppSharp9CppParser16CppParserOptionsC2Ev")]
@ -18637,6 +18640,19 @@ namespace CppSharp
} }
} }
public bool UnityBuild
{
get
{
return ((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild != 0;
}
set
{
((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild = (byte) (value ? 1 : 0);
}
}
public uint ArgumentsCount public uint ArgumentsCount
{ {
get get

18
src/CppParser/Bindings/CSharp/x86_64-pc-win32-msvc/CppSharp.CppParser.cs

@ -18051,7 +18051,7 @@ namespace CppSharp
public unsafe partial class CppParserOptions : IDisposable public unsafe partial class CppParserOptions : IDisposable
{ {
[StructLayout(LayoutKind.Explicit, Size = 312)] [StructLayout(LayoutKind.Explicit, Size = 320)]
public partial struct __Internal public partial struct __Internal
{ {
[FieldOffset(0)] [FieldOffset(0)]
@ -18108,6 +18108,9 @@ namespace CppSharp
[FieldOffset(311)] [FieldOffset(311)]
internal byte verbose; internal byte verbose;
[FieldOffset(312)]
internal byte unityBuild;
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, [DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint="??0CppParserOptions@CppParser@CppSharp@@QEAA@XZ")] EntryPoint="??0CppParserOptions@CppParser@CppSharp@@QEAA@XZ")]
@ -18638,6 +18641,19 @@ namespace CppSharp
} }
} }
public bool UnityBuild
{
get
{
return ((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild != 0;
}
set
{
((global::CppSharp.Parser.CppParserOptions.__Internal*) __Instance)->unityBuild = (byte) (value ? 1 : 0);
}
}
public uint ArgumentsCount public uint ArgumentsCount
{ {
get get

1
src/CppParser/CppParser.cpp

@ -18,6 +18,7 @@ CppParserOptions::CppParserOptions()
, noBuiltinIncludes(false) , noBuiltinIncludes(false)
, microsoftMode(false) , microsoftMode(false)
, verbose(false) , verbose(false)
, unityBuild(false)
{ {
} }

1
src/CppParser/CppParser.h

@ -44,6 +44,7 @@ struct CS_API CppParserOptions
bool noBuiltinIncludes; bool noBuiltinIncludes;
bool microsoftMode; bool microsoftMode;
bool verbose; bool verbose;
bool unityBuild;
}; };
enum class ParserDiagnosticLevel enum class ParserDiagnosticLevel

6
src/CppParser/Parser.cpp

@ -766,13 +766,15 @@ Class* Parser::GetRecord(const clang::RecordDecl* Record, bool& Process)
} }
else else
{ {
RC = NS->FindClass(Name, isCompleteDefinition, /*Create=*/false); RC = NS->FindClass(opts->unityBuild ? Record : 0, Name,
isCompleteDefinition, /*Create=*/false);
} }
if (RC) if (RC)
return RC; return RC;
RC = NS->FindClass(Name, isCompleteDefinition, /*Create=*/true); RC = NS->FindClass(opts->unityBuild ? Record : 0, Name,
isCompleteDefinition, /*Create=*/true);
RC->isInjected = Record->isInjectedClassName(); RC->isInjected = Record->isInjectedClassName();
HandleDeclaration(Record, RC); HandleDeclaration(Record, RC);
EnsureCompleteRecord(Record, NS, RC); EnsureCompleteRecord(Record, NS, RC);

2
src/CppParser/ParserGen/ParserGen.cs

@ -88,7 +88,7 @@ namespace CppSharp
options.CheckSymbols = false; options.CheckSymbols = false;
//options.Verbose = true; //options.Verbose = true;
options.UnityBuild = true; parserOptions.UnityBuild = true;
} }
private void SetupLinuxOptions(ParserOptions options) private void SetupLinuxOptions(ParserOptions options)

2
src/Generator/Driver.cs

@ -124,7 +124,7 @@ namespace CppSharp
var sourceFiles = Options.Modules.SelectMany(m => m.Headers); var sourceFiles = Options.Modules.SelectMany(m => m.Headers);
if (Options.UnityBuild) if (ParserOptions.UnityBuild)
{ {
using (var parserOptions = ParserOptions.BuildForSourceFile( using (var parserOptions = ParserOptions.BuildForSourceFile(
Options.Modules)) Options.Modules))

15
src/Generator/Generators/CSharp/CSharpSources.cs

@ -303,16 +303,7 @@ namespace CppSharp.Generators.CSharp
GenerateClassInternals(specialization); GenerateClassInternals(specialization);
foreach (var group in generated.SelectMany(s => s.Classes).Where( foreach (var group in generated.SelectMany(s => s.Classes).Where(
// HACK: the distinction is needed to eliminate duplicate nested types c => !c.IsIncomplete).GroupBy(c => c.Name))
// Since all template specialisations are incomplete by default,
// so are classes nested in them.
// When such classes are also forwarded, there are two incomplete declarations
// with the same name and in the same scope. Our parser searches by name and
// completion and it can therefore not make a difference between the two.
// Consequently, it always returns the first type it finds even if it isn't the right one.
// When clang::Sema later completes the specialisations, it completes the nested
// types too which leads to two identical complete types in the same scope.
c => !c.IsIncomplete).Distinct().GroupBy(c => c.Name))
GenerateNestedInternals(group.Key, group); GenerateNestedInternals(group.Key, group);
WriteCloseBraceIndent(); WriteCloseBraceIndent();
@ -546,8 +537,8 @@ namespace CppSharp.Generators.CSharp
Class template; Class template;
if (currentSpecialization != null && if (currentSpecialization != null &&
(template = currentSpecialization.TemplatedDecl.TemplatedClass) (template = currentSpecialization.TemplatedDecl.TemplatedClass)
.GetSpecializationsToGenerate().Count == 1) .GetSpecializedClassesToGenerate().Count() == 1)
foreach (var specialization in template.Specializations.Where(s => !s.Ignore)) foreach (var specialization in template.Specializations.Where(s => s.IsGenerated))
GatherClassInternalFunctions(specialization, includeCtors, functions); GatherClassInternalFunctions(specialization, includeCtors, functions);
else else
GatherClassInternalFunctions(@class, includeCtors, functions); GatherClassInternalFunctions(@class, includeCtors, functions);

5
src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs

@ -23,7 +23,8 @@ namespace CppSharp.Generators.CSharp
{ {
var printedClass = @class.Visit(gen.TypePrinter); var printedClass = @class.Visit(gen.TypePrinter);
if (@class.IsDependent) if (@class.IsDependent)
foreach (var specialization in @class.GetSpecializationsToGenerate().Where(s => !s.Ignore)) foreach (var specialization in @class.GetSpecializedClassesToGenerate(
).Where(s => s.IsGenerated))
gen.GenerateNativeConstructorByValue(specialization, printedClass.Type); gen.GenerateNativeConstructorByValue(specialization, printedClass.Type);
else else
gen.GenerateNativeConstructorByValue(@class, printedClass.Type); gen.GenerateNativeConstructorByValue(@class, printedClass.Type);
@ -127,7 +128,7 @@ namespace CppSharp.Generators.CSharp
var typePrinter = new CSharpTypePrinter(gen.Context); var typePrinter = new CSharpTypePrinter(gen.Context);
var supportedTypes = string.Join(", ", var supportedTypes = string.Join(", ",
@class.Specializations.Where(s => !s.Ignore).Select(s => $@"<{string.Join(", ", @class.Specializations.Where(s => !s.Ignore).Select(s => $@"<{string.Join(", ",
s.Arguments.Select(a => typePrinter.VisitTemplateArgument(a)))}>")); s.Arguments.Select(typePrinter.VisitTemplateArgument))}>"));
var typeArguments = string.Join(", ", @class.TemplateParameters.Select(p => p.Name)); var typeArguments = string.Join(", ", @class.TemplateParameters.Select(p => p.Name));
var managedTypes = string.Join(", ", @class.TemplateParameters.Select(p => $"typeof({p.Name}).FullName")); var managedTypes = string.Join(", ", @class.TemplateParameters.Select(p => $"typeof({p.Name}).FullName"));
gen.WriteLine($"throw new ArgumentOutOfRangeException(\"{typeArguments}\", " gen.WriteLine($"throw new ArgumentOutOfRangeException(\"{typeArguments}\", "

11
src/Generator/Options.cs

@ -52,17 +52,6 @@ namespace CppSharp
#endregion #endregion
#region Parser options
/// <summary>
/// If this option is off (the default), each header is parsed separately
/// which is much slower but safer because of a clean state of the preprocessor
/// for each header.
/// </summary>
public bool UnityBuild { get; set; }
#endregion
#region Module options #region Module options
public Module SystemModule { get; } public Module SystemModule { get; }

36
src/Generator/Passes/ResolveIncompleteDeclsPass.cs

@ -19,6 +19,11 @@ namespace CppSharp.Passes
EnsureCompleteDeclaration(@class); EnsureCompleteDeclaration(@class);
if (@class.Namespace is ClassTemplateSpecialization &&
@class.IsIncomplete && @class.CompleteDeclaration == null &&
@class.IsGenerated)
@class.GenerationKind = GenerationKind.Internal;
return true; return true;
} }
@ -50,6 +55,18 @@ namespace CppSharp.Passes
return true; return true;
} }
public override bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization)
{
if (!base.VisitClassTemplateSpecializationDecl(specialization))
return false;
if (specialization.IsIncomplete &&
specialization.CompleteDeclaration == null && specialization.IsGenerated)
specialization.GenerationKind = GenerationKind.Internal;
return true;
}
public override bool VisitEnumDecl(Enumeration @enum) public override bool VisitEnumDecl(Enumeration @enum)
{ {
if (!VisitDeclaration(@enum)) if (!VisitDeclaration(@enum))
@ -86,16 +103,25 @@ namespace CppSharp.Passes
declaration.CompleteDeclaration = declaration.CompleteDeclaration =
ASTContext.FindCompleteClass(declaration.QualifiedName); ASTContext.FindCompleteClass(declaration.QualifiedName);
if (declaration.CompleteDeclaration != null)
return;
if (Context.ParserOptions.UnityBuild)
{
if (declaration.IsGenerated)
foreach (var redecl in declaration.Redeclarations)
redecl.GenerationKind = GenerationKind.None;
return;
}
var @class = declaration as Class; var @class = declaration as Class;
if (CheckForDuplicateForwardClass(@class)) if (CheckForDuplicateForwardClass(@class))
return; return;
if (declaration.CompleteDeclaration == null) if (declaration.IsGenerated)
{
declaration.GenerationKind = GenerationKind.Internal; declaration.GenerationKind = GenerationKind.Internal;
Diagnostics.Debug("Unresolved declaration: {0}", Diagnostics.Debug("Unresolved declaration: {0}",
declaration.Name); declaration.Name);
}
} }
bool CheckForDuplicateForwardClass(Class @class) bool CheckForDuplicateForwardClass(Class @class)

3
src/Generator/Passes/TrimSpecializationsPass.cs

@ -133,9 +133,6 @@ namespace CppSharp.Passes
if (template.Fields.Any(f => f.Type.Desugar() is TemplateParameterType)) if (template.Fields.Any(f => f.Type.Desugar() is TemplateParameterType))
MoveExternalSpecializations(template); MoveExternalSpecializations(template);
foreach (var @class in template.Specializations.SelectMany(s => s.Classes))
@class.ExplicitlyIgnore();
} }
/// <summary> /// <summary>

3
src/Parser/ParserOptions.cs

@ -82,7 +82,8 @@ namespace CppSharp.Parser
NoBuiltinIncludes = this.NoBuiltinIncludes, NoBuiltinIncludes = this.NoBuiltinIncludes,
MicrosoftMode = this.MicrosoftMode, MicrosoftMode = this.MicrosoftMode,
Verbose = this.Verbose, Verbose = this.Verbose,
LanguageVersion = this.LanguageVersion LanguageVersion = this.LanguageVersion,
UnityBuild = this.UnityBuild
}; };
// This eventually gets passed to Clang's MSCompatibilityVersion, which // This eventually gets passed to Clang's MSCompatibilityVersion, which

2
tests/CSharp/AnotherUnit.h

@ -1,6 +1,8 @@
#include "../Tests.h" #include "../Tests.h"
#include <string> #include <string>
#pragma once
void DLL_API functionInAnotherUnit(); void DLL_API functionInAnotherUnit();
struct DLL_API ForwardDeclaredStruct; struct DLL_API ForwardDeclaredStruct;

7
tests/CSharp/CSharp.cs

@ -20,6 +20,13 @@ namespace CppSharp.Tests
{ {
} }
public override void Setup(Driver driver)
{
base.Setup(driver);
driver.ParserOptions.UnityBuild = true;
}
public override void SetupPasses(Driver driver) public override void SetupPasses(Driver driver)
{ {
driver.Context.TranslationUnitPasses.AddPass(new TestAttributesPass()); driver.Context.TranslationUnitPasses.AddPass(new TestAttributesPass());

2
tests/Common/Common.cs

@ -58,7 +58,7 @@ namespace CppSharp.Tests
file.FileNameWithoutExtension + "_GenerateName"; file.FileNameWithoutExtension + "_GenerateName";
driver.Options.Modules[1].OutputNamespace = "CommonTest"; driver.Options.Modules[1].OutputNamespace = "CommonTest";
driver.Options.UnityBuild = true; driver.ParserOptions.UnityBuild = true;
} }
public override void SetupPasses(Driver driver) public override void SetupPasses(Driver driver)

Loading…
Cancel
Save