Skip to content

Commit

Permalink
Ensure remapping and anonymous record names are correct (#219)
Browse files Browse the repository at this point in the history
* Catch exceptions and return them as a trailing error diagnostic

* Handle null statements

* Ensure nested anonymous records get the correct name

* Adding tests to cover remapping nested type names

* Ensure remapping works for either A::B or A.B
  • Loading branch information
tannergooding authored Mar 24, 2021
1 parent f5e2b19 commit b550825
Show file tree
Hide file tree
Showing 11 changed files with 617 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)
}

contextNameParts.Push(EscapeName(contextNamePart));
contextTypeParts.Push(GetRemappedTypeName(anonymousRecordDecl, context: null, anonymousRecordDecl.TypeForDecl, out string nativeTypeName));
contextTypeParts.Push(GetRemappedTypeName(rootRecordDecl, context: null, rootRecordDecl.TypeForDecl, out string nativeTypeName));

if (!rootRecordDecl.IsAnonymousStructOrUnion)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,11 @@ private void VisitMemberExpr(MemberExpr memberExpr)
StopCSharpCode();
}

private void VisitNullStmt(NullStmt nullStmt)
{
// null statements are empty by definition, so nothing to do
}

private void VisitParenExpr(ParenExpr parenExpr)
{
var outputBuilder = StartCSharpCode();
Expand Down Expand Up @@ -1106,7 +1111,13 @@ private void VisitStmt(Stmt stmt)

// case CX_StmtClass.CX_StmtClass_IndirectGotoStmt:
// case CX_StmtClass.CX_StmtClass_MSDependentExistsStmt:
// case CX_StmtClass.CX_StmtClass_NullStmt:

case CX_StmtClass.CX_StmtClass_NullStmt:
{
VisitNullStmt((NullStmt)stmt);
break;
}

// case CX_StmtClass.CX_StmtClass_OMPAtomicDirective:
// case CX_StmtClass.CX_StmtClass_OMPBarrierDirective:
// case CX_StmtClass.CX_StmtClass_OMPCancelDirective:
Expand Down
101 changes: 74 additions & 27 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,42 +275,50 @@ public void GenerateBindings(TranslationUnit translationUnit, string filePath, s
}
}

if (_config.GenerateMacroBindings)
try
{
var translationUnitHandle = translationUnit.Handle;
if (_config.GenerateMacroBindings)
{
var translationUnitHandle = translationUnit.Handle;

var file = translationUnitHandle.GetFile(_filePath);
var fileContents = translationUnitHandle.GetFileContents(file, out var size);
var file = translationUnitHandle.GetFile(_filePath);
var fileContents = translationUnitHandle.GetFileContents(file, out var size);

#if NETCOREAPP
_fileContentsBuilder.Append(Encoding.UTF8.GetString(fileContents));
_fileContentsBuilder.Append(Encoding.UTF8.GetString(fileContents));
#else
_fileContentsBuilder.Append(Encoding.UTF8.GetString(fileContents.ToArray()));
_fileContentsBuilder.Append(Encoding.UTF8.GetString(fileContents.ToArray()));
#endif

foreach (var cursor in translationUnit.TranslationUnitDecl.CursorChildren)
{
if (cursor is PreprocessedEntity preprocessedEntity)
foreach (var cursor in translationUnit.TranslationUnitDecl.CursorChildren)
{
VisitPreprocessedEntity(preprocessedEntity);
if (cursor is PreprocessedEntity preprocessedEntity)
{
VisitPreprocessedEntity(preprocessedEntity);
}
}
}

var unsavedFileContents = _fileContentsBuilder.ToString();
_fileContentsBuilder.Clear();
var unsavedFileContents = _fileContentsBuilder.ToString();
_fileContentsBuilder.Clear();

using var unsavedFile = CXUnsavedFile.Create(_filePath, unsavedFileContents);
var unsavedFiles = new CXUnsavedFile[] { unsavedFile };
using var unsavedFile = CXUnsavedFile.Create(_filePath, unsavedFileContents);
var unsavedFiles = new CXUnsavedFile[] { unsavedFile };

translationFlags = _translationFlags & ~CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord;
var handle = CXTranslationUnit.Parse(IndexHandle, _filePath, _clangCommandLineArgs, unsavedFiles, translationFlags);
translationFlags = _translationFlags & ~CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord;
var handle = CXTranslationUnit.Parse(IndexHandle, _filePath, _clangCommandLineArgs, unsavedFiles, translationFlags);

using var nestedTranslationUnit = TranslationUnit.GetOrCreate(handle);
Visit(nestedTranslationUnit.TranslationUnitDecl);
using var nestedTranslationUnit = TranslationUnit.GetOrCreate(handle);
Visit(nestedTranslationUnit.TranslationUnitDecl);
}
else
{
Visit(translationUnit.TranslationUnitDecl);
}
}
else
catch (Exception e)
{
Visit(translationUnit.TranslationUnitDecl);
var diagnostic = new Diagnostic(DiagnosticLevel.Error, e.ToString());
_diagnostics.Add(diagnostic);
}
}

Expand Down Expand Up @@ -885,7 +893,7 @@ private string GetCursorQualifiedName(NamedDecl namedDecl, bool truncateFunction
while (parts.Count != 0)
{
AppendNamedDecl(part, GetCursorName(part), qualifiedName);
qualifiedName.Append('.');
qualifiedName.Append("::");
part = parts.Pop();
}

Expand Down Expand Up @@ -1078,6 +1086,14 @@ private string GetRemappedCursorName(NamedDecl namedDecl)
return remappedName;
}

name = name.Replace("::", ".");
remappedName = GetRemappedName(name, namedDecl, tryRemapOperatorName: true);

if (remappedName != name)
{
return remappedName;
}

name = GetCursorQualifiedName(namedDecl, truncateFunctionParameters: true);
remappedName = GetRemappedName(name, namedDecl, tryRemapOperatorName: true);

Expand All @@ -1086,6 +1102,14 @@ private string GetRemappedCursorName(NamedDecl namedDecl)
return remappedName;
}

name = name.Replace("::", ".");
remappedName = GetRemappedName(name, namedDecl, tryRemapOperatorName: true);

if (remappedName != name)
{
return remappedName;
}

name = GetCursorName(namedDecl);
remappedName = GetRemappedName(name, namedDecl, tryRemapOperatorName: true);

Expand Down Expand Up @@ -1188,11 +1212,34 @@ private string GetRemappedTypeName(Cursor cursor, Cursor context, Type type, out
name = "_";
name += GetRemappedCursorName(matchingField);
}
else if (parentRecordDecl.AnonymousRecords.Count > 1)
else
{
var index = parentRecordDecl.AnonymousRecords.IndexOf(cursor) + 1;
name += index.ToString();
}
var index = 0;

if (parentRecordDecl.AnonymousRecords.Count > 1)
{
index = parentRecordDecl.AnonymousRecords.IndexOf(cursor) + 1;
}

while ((parentRecordDecl.IsAnonymousStructOrUnion) && (parentRecordDecl.IsUnion == recordType.Decl.IsUnion))
{
index += 1;

if (parentRecordDecl.Parent is RecordDecl parentRecordDeclParent)
{
if (parentRecordDeclParent.AnonymousRecords.Count > 0)
{
index += parentRecordDeclParent.AnonymousRecords.Count - 1;
}
parentRecordDecl = parentRecordDeclParent;
}
}

if (index != 0)
{
name += index.ToString();
}
}
}

name += $"_e__{(recordDecl.IsUnion ? "Union" : "Struct")}";
Expand Down Expand Up @@ -2193,7 +2240,7 @@ bool IsExcludedByName(Cursor cursor, out bool isExcludedByConflictingDefinition)
}
}

if (_config.ExcludedNames.Contains(qualifiedName))
if (_config.ExcludedNames.Contains(qualifiedName) || _config.ExcludedNames.Contains(qualifiedName.Replace("::", ".")))
{
if (_config.LogExclusions)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,26 +122,74 @@ public enum MyEnum : {expectedManagedType}

public override Task RemapTest()
{
var inputContents = @"typedef enum _MyEnum : int
var inputContents = @"typedef enum _MyEnum1 : int
{
MyEnum_Value1,
MyEnum_Value2,
MyEnum_Value3,
} MyEnum;
MyEnum1_Value1,
MyEnum1_Value2,
MyEnum1_Value3,
} MyEnum1;
namespace Namespace1
{
namespace Namespace2
{
typedef enum _MyEnum2 : int
{
MyEnum2_Value1,
MyEnum2_Value2,
MyEnum2_Value3,
} MyEnum2;
typedef enum _MyEnum3 : int
{
MyEnum3_Value1,
MyEnum3_Value2,
MyEnum3_Value3,
} MyEnum3;
typedef enum _MyEnum4 : int
{
MyEnum4_Value1,
MyEnum4_Value2,
MyEnum4_Value3,
} MyEnum4;
}
}
";

var expectedOutputContents = $@"namespace ClangSharp.Test
{{
public enum MyEnum
{{
MyEnum_Value1,
MyEnum_Value2,
MyEnum_Value3,
}}
}}
var expectedOutputContents = @"namespace ClangSharp.Test
{
public enum MyEnum1
{
MyEnum1_Value1,
MyEnum1_Value2,
MyEnum1_Value3,
}
public enum MyEnum2
{
MyEnum2_Value1,
MyEnum2_Value2,
MyEnum2_Value3,
}
public enum MyEnum3
{
MyEnum3_Value1,
MyEnum3_Value2,
MyEnum3_Value3,
}
public enum MyEnum4
{
MyEnum4_Value1,
MyEnum4_Value2,
MyEnum4_Value3,
}
}
";

var remappedNames = new Dictionary<string, string> { ["_MyEnum"] = "MyEnum" };
var remappedNames = new Dictionary<string, string> { ["_MyEnum1"] = "MyEnum1", ["Namespace1.Namespace2._MyEnum2"] = "MyEnum2", ["_MyEnum3"] = "MyEnum3", ["Namespace1::Namespace2::_MyEnum4"] = "MyEnum4" };
return ValidateGeneratedCSharpCompatibleUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,21 @@ struct MyStruct
{nativeType} value;
}} w;
struct
{{
{nativeType} value1;
struct
{{
{nativeType} value;
}};
}};
union
{{
{nativeType} value2;
}};
MyUnion u;
{nativeType} buffer1[4];
MyUnion buffer2[4];
Expand Down Expand Up @@ -871,6 +886,39 @@ public ref _Anonymous_e__Struct._w_e__Struct w
}}
}}
public ref {expectedManagedType} value1
{{
get
{{
fixed (_Anonymous_e__Struct._Anonymous1_e__Struct* pField = &Anonymous.Anonymous1)
{{
return ref pField->value1;
}}
}}
}}
public ref {expectedManagedType} value
{{
get
{{
fixed (_Anonymous_e__Struct._Anonymous1_e__Struct._Anonymous_e__Struct* pField = &Anonymous.Anonymous1.Anonymous)
{{
return ref pField->value;
}}
}}
}}
public ref {expectedManagedType} value2
{{
get
{{
fixed (_Anonymous_e__Struct._Anonymous2_e__Union* pField = &Anonymous.Anonymous2)
{{
return ref pField->value2;
}}
}}
}}
public ref MyUnion u
{{
get
Expand Down Expand Up @@ -911,6 +959,12 @@ public unsafe partial struct _Anonymous_e__Struct
[NativeTypeName(""struct (anonymous struct at ClangUnsavedFile.h:14:9)"")]
public _w_e__Struct w;
[NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:19:9)"")]
public _Anonymous1_e__Struct Anonymous1;
[NativeTypeName(""MyStruct::(anonymous union at ClangUnsavedFile.h:29:9)"")]
public _Anonymous2_e__Union Anonymous2;
public MyUnion u;
[NativeTypeName(""{nativeType} [4]"")]
Expand All @@ -924,6 +978,26 @@ public partial struct _w_e__Struct
public {expectedManagedType} value;
}}
public partial struct _Anonymous1_e__Struct
{{
public {expectedManagedType} value1;
[NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:23:13)"")]
public _Anonymous_e__Struct Anonymous;
public partial struct _Anonymous_e__Struct
{{
public {expectedManagedType} value;
}}
}}
[StructLayout(LayoutKind.Explicit)]
public partial struct _Anonymous2_e__Union
{{
[FieldOffset(0)]
public {expectedManagedType} value2;
}}
public partial struct _buffer2_e__FixedBuffer
{{
public MyUnion e0;
Expand Down
Loading

0 comments on commit b550825

Please sign in to comment.