Ensure that multiple-inheritance scenarios generate unique field names

This commit is contained in:
Tanner Gooding 2022-08-13 11:20:37 -07:00
Родитель 99ab606fd7
Коммит 1fbe370851
11 изменённых файлов: 72 добавлений и 46 удалений

Просмотреть файл

@ -597,7 +597,7 @@ namespace ClangSharp
_outputBuilder.BeginFunctionInnerPrototype(in desc);
bool needsThis = isVirtual || (isCxxMethodDecl && !hasBody && cxxMethodDecl.IsInstance);
var needsThis = isVirtual || (isCxxMethodDecl && !hasBody && cxxMethodDecl.IsInstance);
if (needsThis)
{
@ -669,7 +669,12 @@ namespace ClangSharp
outputBuilder.Write("return ");
}
outputBuilder.Write("Base.");
var cxxBaseSpecifier = _cxxRecordDeclContext.Bases.Where((baseSpecifier) => baseSpecifier.Referenced == cxxMethodDecl.Parent).Single();
var baseFieldName = GetAnonymousName(cxxBaseSpecifier, "Base");
baseFieldName = GetRemappedName(baseFieldName, cxxBaseSpecifier, tryRemapOperatorName: true, out var wasRemapped, skipUsing: true);
outputBuilder.Write(baseFieldName);
outputBuilder.Write('.');
outputBuilder.Write(name);
outputBuilder.Write('(');
@ -1564,8 +1569,9 @@ namespace ClangSharp
if (cxxRecordDecl != null)
{
foreach (var cxxBaseSpecifier in cxxRecordDecl.Bases)
for (var index = 0; index < cxxRecordDecl.Bases.Count; index++)
{
var cxxBaseSpecifier = cxxRecordDecl.Bases[index];
var baseCxxRecordDecl = GetRecordDecl(cxxBaseSpecifier);
if (HasField(baseCxxRecordDecl))
@ -1574,11 +1580,6 @@ namespace ClangSharp
var baseFieldName = GetAnonymousName(cxxBaseSpecifier, "Base");
baseFieldName = GetRemappedName(baseFieldName, cxxBaseSpecifier, tryRemapOperatorName: true, out var wasRemapped, skipUsing: true);
if (baseFieldName.StartsWith("__AnonymousBase_"))
{
baseFieldName = "Base";
}
var fieldDesc = new FieldDesc {
AccessSpecifier = GetAccessSpecifier(baseCxxRecordDecl, matchStar: true),
NativeTypeName = null,

Просмотреть файл

@ -1597,27 +1597,37 @@ namespace ClangSharp
private void VisitMemberExpr(MemberExpr memberExpr)
{
var outputBuilder = StartCSharpCode();
var isForDerivedType = false;
var baseFieldName = "";
if ((memberExpr.Base is ImplicitCastExpr implicitCastExpr) && (implicitCastExpr.CastKind is CX_CastKind.CX_CK_DerivedToBase or CX_CastKind.CX_CK_DerivedToBaseMemberPointer or CX_CastKind.CX_CK_UncheckedDerivedToBase))
{
if (memberExpr.MemberDecl is CXXMethodDecl cxxMethodDecl)
{
isForDerivedType = (_cxxRecordDeclContext is not null) && (_cxxRecordDeclContext != cxxMethodDecl.Parent) && HasField(cxxMethodDecl.Parent);
if ((_cxxRecordDeclContext is not null) && (_cxxRecordDeclContext != cxxMethodDecl.Parent) && HasField(cxxMethodDecl.Parent))
{
var cxxBaseSpecifier = _cxxRecordDeclContext.Bases.Where((baseSpecifier) => baseSpecifier.Referenced == cxxMethodDecl.Parent).Single();
baseFieldName = GetAnonymousName(cxxBaseSpecifier, "Base");
baseFieldName = GetRemappedName(baseFieldName, cxxBaseSpecifier, tryRemapOperatorName: true, out var wasRemapped, skipUsing: true);
}
}
else if (memberExpr.MemberDecl is FieldDecl fieldDecl)
{
isForDerivedType = (_cxxRecordDeclContext is not null) && (_cxxRecordDeclContext != fieldDecl.Parent);
if ((_cxxRecordDeclContext is not null) && (_cxxRecordDeclContext != fieldDecl.Parent))
{
var cxxBaseSpecifier = _cxxRecordDeclContext.Bases.Where((baseSpecifier) => baseSpecifier.Referenced == fieldDecl.Parent).Single();
baseFieldName = GetAnonymousName(cxxBaseSpecifier, "Base");
baseFieldName = GetRemappedName(baseFieldName, cxxBaseSpecifier, tryRemapOperatorName: true, out var wasRemapped, skipUsing: true);
}
}
}
if (!memberExpr.IsImplicitAccess || isForDerivedType)
if (!memberExpr.IsImplicitAccess || !string.IsNullOrWhiteSpace(baseFieldName))
{
var memberExprBase = memberExpr.Base.IgnoreImplicit;
if (isForDerivedType)
if (!string.IsNullOrWhiteSpace(baseFieldName))
{
outputBuilder.Write("Base");
outputBuilder.Write(baseFieldName);
}
else
{

Просмотреть файл

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
@ -2503,6 +2504,20 @@ namespace ClangSharp
return AddUsingDirectiveIfNeeded(_outputBuilder, remappedName, skipUsing);
}
if ((cursor is CXXBaseSpecifier cxxBaseSpecifier) && remappedName.StartsWith("__AnonymousBase_"))
{
remappedName = "Base";
if (_cxxRecordDeclContext.Bases.Count > 1)
{
var index = _cxxRecordDeclContext.Bases.IndexOf(cxxBaseSpecifier) + 1;
remappedName += index.ToString();
}
wasRemapped = true;
return AddUsingDirectiveIfNeeded(_outputBuilder, remappedName, skipUsing);
}
wasRemapped = false;
return AddUsingDirectiveIfNeeded(_outputBuilder, remappedName, skipUsingIfNotRemapped);

Просмотреть файл

@ -755,9 +755,9 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
[NativeTypeName(""struct MyStruct2 : MyStruct1A, MyStruct1B"")]
public partial struct MyStruct2
{
public MyStruct1A Base;
public MyStruct1A Base1;
public MyStruct1B Base;
public MyStruct1B Base2;
public int z;
@ -810,9 +810,9 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
[NativeInheritance(""MyStruct1B"")]
public partial struct MyStruct2
{
public MyStruct1A Base;
public MyStruct1A Base1;
public MyStruct1B Base;
public MyStruct1B Base2;
public int z;

Просмотреть файл

@ -759,9 +759,9 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
[NativeTypeName(""struct MyStruct2 : MyStruct1A, MyStruct1B"")]
public partial struct MyStruct2
{
public MyStruct1A Base;
public MyStruct1A Base1;
public MyStruct1B Base;
public MyStruct1B Base2;
public int z;
@ -814,9 +814,9 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
[NativeInheritance(""MyStruct1B"")]
public partial struct MyStruct2
{
public MyStruct1A Base;
public MyStruct1A Base1;
public MyStruct1B Base;
public MyStruct1B Base2;
public int z;

Просмотреть файл

@ -763,9 +763,9 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
[NativeTypeName(""struct MyStruct2 : MyStruct1A, MyStruct1B"")]
public partial struct MyStruct2
{
public MyStruct1A Base;
public MyStruct1A Base1;
public MyStruct1B Base;
public MyStruct1B Base2;
public int z;
@ -818,9 +818,9 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
[NativeInheritance(""MyStruct1B"")]
public partial struct MyStruct2
{
public MyStruct1A Base;
public MyStruct1A Base1;
public MyStruct1B Base;
public MyStruct1B Base2;
public int z;

Просмотреть файл

@ -767,9 +767,9 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
[NativeTypeName(""struct MyStruct2 : MyStruct1A, MyStruct1B"")]
public partial struct MyStruct2
{
public MyStruct1A Base;
public MyStruct1A Base1;
public MyStruct1B Base;
public MyStruct1B Base2;
public int z;
@ -822,9 +822,9 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
[NativeInheritance(""MyStruct1B"")]
public partial struct MyStruct2
{
public MyStruct1A Base;
public MyStruct1A Base1;
public MyStruct1B Base;
public MyStruct1B Base2;
public int z;

Просмотреть файл

@ -798,10 +798,10 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
</field>
</struct>
<struct name=""MyStruct2"" access=""public"" native=""struct MyStruct2 : MyStruct1A, MyStruct1B"">
<field name=""Base"" access=""public"" inherited=""MyStruct1A"">
<field name=""Base1"" access=""public"" inherited=""MyStruct1A"">
<type>MyStruct1A</type>
</field>
<field name=""Base"" access=""public"" inherited=""MyStruct1B"">
<field name=""Base2"" access=""public"" inherited=""MyStruct1B"">
<type>MyStruct1B</type>
</field>
<field name=""z"" access=""public"">
@ -859,10 +859,10 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
</field>
</struct>
<struct name=""MyStruct2"" access=""public"" native=""struct MyStruct2 : MyStruct1A, MyStruct1B"" parent=""MyStruct1B"">
<field name=""Base"" access=""public"" inherited=""MyStruct1A"">
<field name=""Base1"" access=""public"" inherited=""MyStruct1A"">
<type>MyStruct1A</type>
</field>
<field name=""Base"" access=""public"" inherited=""MyStruct1B"">
<field name=""Base2"" access=""public"" inherited=""MyStruct1B"">
<type>MyStruct1B</type>
</field>
<field name=""z"" access=""public"">

Просмотреть файл

@ -804,10 +804,10 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
</field>
</struct>
<struct name=""MyStruct2"" access=""public"" native=""struct MyStruct2 : MyStruct1A, MyStruct1B"">
<field name=""Base"" access=""public"" inherited=""MyStruct1A"">
<field name=""Base1"" access=""public"" inherited=""MyStruct1A"">
<type>MyStruct1A</type>
</field>
<field name=""Base"" access=""public"" inherited=""MyStruct1B"">
<field name=""Base2"" access=""public"" inherited=""MyStruct1B"">
<type>MyStruct1B</type>
</field>
<field name=""z"" access=""public"">
@ -865,10 +865,10 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
</field>
</struct>
<struct name=""MyStruct2"" access=""public"" native=""struct MyStruct2 : MyStruct1A, MyStruct1B"" parent=""MyStruct1B"">
<field name=""Base"" access=""public"" inherited=""MyStruct1A"">
<field name=""Base1"" access=""public"" inherited=""MyStruct1A"">
<type>MyStruct1A</type>
</field>
<field name=""Base"" access=""public"" inherited=""MyStruct1B"">
<field name=""Base2"" access=""public"" inherited=""MyStruct1B"">
<type>MyStruct1B</type>
</field>
<field name=""z"" access=""public"">

Просмотреть файл

@ -802,10 +802,10 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
</field>
</struct>
<struct name=""MyStruct2"" access=""public"" native=""struct MyStruct2 : MyStruct1A, MyStruct1B"">
<field name=""Base"" access=""public"" inherited=""MyStruct1A"">
<field name=""Base1"" access=""public"" inherited=""MyStruct1A"">
<type>MyStruct1A</type>
</field>
<field name=""Base"" access=""public"" inherited=""MyStruct1B"">
<field name=""Base2"" access=""public"" inherited=""MyStruct1B"">
<type>MyStruct1B</type>
</field>
<field name=""z"" access=""public"">
@ -863,10 +863,10 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
</field>
</struct>
<struct name=""MyStruct2"" access=""public"" native=""struct MyStruct2 : MyStruct1A, MyStruct1B"" parent=""MyStruct1B"">
<field name=""Base"" access=""public"" inherited=""MyStruct1A"">
<field name=""Base1"" access=""public"" inherited=""MyStruct1A"">
<type>MyStruct1A</type>
</field>
<field name=""Base"" access=""public"" inherited=""MyStruct1B"">
<field name=""Base2"" access=""public"" inherited=""MyStruct1B"">
<type>MyStruct1B</type>
</field>
<field name=""z"" access=""public"">

Просмотреть файл

@ -808,10 +808,10 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
</field>
</struct>
<struct name=""MyStruct2"" access=""public"" native=""struct MyStruct2 : MyStruct1A, MyStruct1B"">
<field name=""Base"" access=""public"" inherited=""MyStruct1A"">
<field name=""Base1"" access=""public"" inherited=""MyStruct1A"">
<type>MyStruct1A</type>
</field>
<field name=""Base"" access=""public"" inherited=""MyStruct1B"">
<field name=""Base2"" access=""public"" inherited=""MyStruct1B"">
<type>MyStruct1B</type>
</field>
<field name=""z"" access=""public"">
@ -869,10 +869,10 @@ struct MyStruct2 : MyStruct1A, MyStruct1B
</field>
</struct>
<struct name=""MyStruct2"" access=""public"" native=""struct MyStruct2 : MyStruct1A, MyStruct1B"" parent=""MyStruct1B"">
<field name=""Base"" access=""public"" inherited=""MyStruct1A"">
<field name=""Base1"" access=""public"" inherited=""MyStruct1A"">
<type>MyStruct1A</type>
</field>
<field name=""Base"" access=""public"" inherited=""MyStruct1B"">
<field name=""Base2"" access=""public"" inherited=""MyStruct1B"">
<type>MyStruct1B</type>
</field>
<field name=""z"" access=""public"">