Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 344656c

Browse files
IIFEBuild Agent
and
Build Agent
authoredApr 3, 2020
Move the GenerateInclude logic to GetTypeReference (mono#1319)
Improve generation of forward references and includes in C++/CLI. Move the GenerateInclude logic to GetTypeReference so that an include is also generated for visited types of an ASTRecord that are forward declared, and come from typedef of ignored class template. Co-authored-by: Build Agent <[email protected]>
1 parent d2f5c26 commit 344656c

File tree

13 files changed

+177
-36
lines changed

13 files changed

+177
-36
lines changed
 

‎build/Tests.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ function SetupTestCSharp(name)
3131
SetupTestProjectsCSharp(name)
3232
end
3333

34-
function SetupTestCLI(name)
34+
function SetupTestCLI(name, extraFiles, suffix)
3535
SetupTestGeneratorProject(name)
3636
SetupTestNativeProject(name)
37-
SetupTestProjectsCLI(name)
37+
SetupTestProjectsCLI(name, extraFiles, suffix)
3838
end
3939

4040
function SetupManagedTestProject()

‎src/Generator/Generators/CLI/CLITypeReferences.cs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,25 @@ public CLITypeReference GetTypeReference(Declaration decl)
4848
if (typeReferences.ContainsKey(decl))
4949
return typeReferences[decl];
5050

51-
var @ref = new CLITypeReference { Declaration = decl };
52-
typeReferences.Add(decl, @ref);
51+
var translationUnit = decl.Namespace.TranslationUnit;
52+
53+
if (ShouldIncludeTranslationUnit(translationUnit) && decl.IsGenerated && !IsBuiltinTypedef(decl))
54+
{
55+
var @ref = new CLITypeReference { Declaration = decl };
56+
57+
@ref.Include = new CInclude
58+
{
59+
File = GetIncludePath(translationUnit),
60+
TranslationUnit = translationUnit,
61+
Kind = translationUnit.IsGenerated ? CInclude.IncludeKind.Quoted : CInclude.IncludeKind.Angled
62+
};
5363

54-
return @ref;
64+
typeReferences.Add(decl, @ref);
65+
66+
return @ref;
67+
}
68+
69+
return null;
5570
}
5671

5772
static Namespace GetEffectiveNamespace(Declaration decl)
@@ -104,39 +119,27 @@ private void GenerateInclude(ASTRecord<Declaration> record)
104119
if (decl.Namespace == null)
105120
return;
106121

122+
var typedefType = record.Value as TypedefNameDecl;
123+
107124
// Find a type map for the declaration and use it if it exists.
108125
TypeMap typeMap;
109-
if (TypeMapDatabase.FindTypeMap(record.Value, out typeMap))
126+
if (TypeMapDatabase.FindTypeMap(record.Value, out typeMap)
127+
|| (typedefType != null && TypeMapDatabase.FindTypeMap(typedefType.Type.Desugar(), out typeMap)))
110128
{
111129
typeMap.CLITypeReference(this, record);
112130
return;
113131
}
114132

115-
var translationUnit = decl.Namespace.TranslationUnit;
116-
117-
if (translationUnit.IsSystemHeader || !translationUnit.IsValid)
118-
return;
119-
120-
if (!decl.IsGenerated)
121-
return;
122-
123-
if (IsBuiltinTypedef(decl))
124-
return;
125-
126133
var typeRef = GetTypeReference(decl);
127-
if (typeRef.Include.TranslationUnit == null)
134+
if(typeRef != null)
128135
{
129-
typeRef.Include = new CInclude
130-
{
131-
File = GetIncludePath(translationUnit),
132-
TranslationUnit = translationUnit,
133-
Kind = translationUnit.IsGenerated
134-
? CInclude.IncludeKind.Quoted
135-
: CInclude.IncludeKind.Angled,
136-
};
136+
typeRef.Include.InHeader |= IsIncludeInHeader(record);
137137
}
138+
}
138139

139-
typeRef.Include.InHeader |= IsIncludeInHeader(record);
140+
private bool ShouldIncludeTranslationUnit(TranslationUnit unit)
141+
{
142+
return !unit.IsSystemHeader && unit.IsValid && !unit.Ignore;
140143
}
141144

142145
private string GetIncludePath(TranslationUnit translationUnit)
@@ -168,7 +171,7 @@ private bool IsBuiltinTypedef(Declaration decl)
168171
return typedefType.Declaration.Type is BuiltinType;
169172
}
170173

171-
private bool IsIncludeInHeader(ASTRecord<Declaration> record)
174+
public bool IsIncludeInHeader(ASTRecord<Declaration> record)
172175
{
173176
if (TranslationUnit == record.Value.Namespace.TranslationUnit)
174177
return false;
@@ -198,7 +201,12 @@ public override bool VisitClassDecl(Class @class)
198201

199202
var @ref = $"{keywords} {@class.Name};";
200203

201-
GetTypeReference(@class).FowardReference = @ref;
204+
var typeRef = GetTypeReference(@class);
205+
206+
if (typeRef != null)
207+
{
208+
typeRef.FowardReference = @ref;
209+
}
202210

203211
return false;
204212
}
@@ -217,7 +225,12 @@ public override bool VisitEnumDecl(Enumeration @enum)
217225

218226
var @ref = $"{enumKind} {@enum.Name}{@base};";
219227

220-
GetTypeReference(@enum).FowardReference = @ref;
228+
var typeRef = GetTypeReference(@enum);
229+
230+
if (typeRef != null)
231+
{
232+
typeRef.FowardReference = @ref;
233+
}
221234

222235
return false;
223236
}

‎src/Generator/Types/Std/Stdlib.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -690,13 +690,16 @@ public override void CLITypeReference(CLITypeReferenceCollector collector,
690690
{
691691
var typeRef = collector.GetTypeReference(loc.Value);
692692

693-
var include = new CInclude
693+
if (typeRef != null)
694694
{
695-
File = "cstddef",
696-
Kind = CInclude.IncludeKind.Angled,
697-
};
695+
var include = new CInclude
696+
{
697+
File = "cstddef",
698+
Kind = CInclude.IncludeKind.Angled,
699+
};
698700

699-
typeRef.Include = include;
701+
typeRef.Include = include;
702+
}
700703
}
701704
}
702705

‎tests/CLI/CLI.Tests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,13 @@ public void TestByRefEnumParam()
2626
Assert.AreEqual(EnumParam.E1, byRefEnumParam.GetPassedEnumParam(EnumParam.E1));
2727
}
2828
}
29+
30+
[Test]
31+
public void GetEmployeeNameFromOrgTest()
32+
{
33+
using (EmployeeOrg org = new EmployeeOrg())
34+
{
35+
Assert.AreEqual("Employee", org.Employee.Name);
36+
}
37+
}
2938
}

‎tests/CLI/CLI.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,58 @@
11
using CppSharp.AST;
2+
using CppSharp.AST.Extensions;
23
using CppSharp.Generators;
4+
using CppSharp.Passes;
5+
using CppSharp.Types;
36
using CppSharp.Utils;
47

58
namespace CppSharp.Tests
69
{
10+
[TypeMap("IgnoredClassTemplateForEmployee")]
11+
public class IgnoredClassTemplateForEmployeeMap : TypeMap
12+
{
13+
public override Type CLISignatureType(TypePrinterContext ctx)
14+
{
15+
return new CustomType("CLI::Employee^");
16+
}
17+
18+
public override void CLIMarshalToManaged(MarshalContext ctx)
19+
{
20+
ctx.Return.Write($"gcnew CLI::Employee({ctx.ReturnVarName}.m_employee)");
21+
}
22+
}
23+
24+
public class CompleteIgnoredClassTemplateForEmployeeTypedefPass : TranslationUnitPass
25+
{
26+
public override bool VisitTypedefDecl(TypedefDecl typedef)
27+
{
28+
var templateType = GetDesugaredFinalPointeeElseType(typedef?.Type?.Desugar()) as TemplateSpecializationType;
29+
bool isTemplateTypedef = IsTemplateTypedef(templateType?.Template?.OriginalName);
30+
if (isTemplateTypedef)
31+
{
32+
Class @class;
33+
if (templateType.TryGetClass(out @class))
34+
{
35+
@class.IsIncomplete = false;
36+
return true;
37+
}
38+
}
39+
40+
return base.VisitTypedefDecl(typedef);
41+
}
42+
43+
private bool IsTemplateTypedef(string templateName)
44+
{
45+
return !string.IsNullOrEmpty(templateName) && "IgnoredClassTemplateForEmployee" == templateName;
46+
}
47+
48+
public Type GetDesugaredFinalPointeeElseType(Type t)
49+
{
50+
Type finalPointee = t.GetFinalPointee();
51+
52+
return finalPointee != null ? finalPointee.Desugar() : t;
53+
}
54+
}
55+
756
public class CLITestsGenerator : GeneratorTest
857
{
958
public CLITestsGenerator(GeneratorKind kind)
@@ -22,6 +71,11 @@ public override void Preprocess(Driver driver, ASTContext ctx)
2271
{
2372
}
2473

74+
public override void SetupPasses(Driver driver)
75+
{
76+
driver.AddTranslationUnitPass(new CompleteIgnoredClassTemplateForEmployeeTypedefPass());
77+
}
78+
2579
public static void Main(string[] args)
2680
{
2781
ConsoleDriver.Run(new CLITestsGenerator(GeneratorKind.CLI));

‎tests/CLI/CLI.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include "../Tests.h"
22

3+
#include "UseTemplateTypeFromIgnoredClassTemplate/Employee.h"
4+
#include "UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.h"
5+
36
#include <ostream>
47

58
// Tests for C++ types
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "Employee.h"
2+
3+
std::string Employee::GetName()
4+
{
5+
return "Employee";
6+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
#include "../../Tests.h"
4+
#include <string>
5+
6+
class DLL_API Employee
7+
{
8+
public:
9+
virtual std::string GetName();
10+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#include "IgnoredClassTemplateForEmployee.h"
2+
3+
class Employee;
4+
typedef IgnoredClassTemplateForEmployee<Employee> EmployeeTypedef;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include "EmployeeOrg.h"
2+
3+
#include "Employee.h"
4+
5+
EmployeeTypedef EmployeeOrg::GetEmployee()
6+
{
7+
return IgnoredClassTemplateForEmployee<Employee>(new Employee());
8+
}
9+
10+
void EmployeeOrg::DoSomething()
11+
{
12+
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#include "../../Tests.h"
4+
5+
#include "EmployeeForwardDecl.h"
6+
7+
class DLL_API EmployeeOrg
8+
{
9+
public:
10+
void DoSomething();
11+
12+
EmployeeTypedef GetEmployee();
13+
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
template<typename EmployeeT>
4+
class IgnoredClassTemplateForEmployee
5+
{
6+
public:
7+
IgnoredClassTemplateForEmployee<EmployeeT>(EmployeeT* employee)
8+
: m_employee(employee)
9+
{
10+
}
11+
12+
EmployeeT* m_employee;
13+
};

‎tests/CLI/premake4.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
group "Tests/CLI"
2-
SetupTestCLI("CLI")
2+
SetupTestCLI("CLI", { "Employee", "EmployeeOrg" })

0 commit comments

Comments
 (0)
Please sign in to comment.