Skip to content

Commit

Permalink
Merge pull request #309 from tannergooding/main
Browse files Browse the repository at this point in the history
Ensure that non-virtual C++ instance methods without a body have an inserted parameter for pThis
  • Loading branch information
tannergooding authored Dec 3, 2021
2 parents 875efb3 + 467f4b7 commit 93db16d
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 13 deletions.
40 changes: 31 additions & 9 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -482,14 +482,16 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)

var cxxMethodDecl = functionDecl as CXXMethodDecl;
var body = functionDecl.Body;
var hasBody = body is not null;

var isVirtual = (cxxMethodDecl != null) && cxxMethodDecl.IsVirtual;
var isCxxMethodDecl = cxxMethodDecl is not null;
var isVirtual = isCxxMethodDecl && cxxMethodDecl.IsVirtual;
var escapedName = isVirtual ? PrefixAndStripName(name, GetOverloadIndex(cxxMethodDecl)) : EscapeAndStripName(name);

var returnType = functionDecl.ReturnType;
var returnTypeName = GetRemappedTypeName(functionDecl, cxxRecordDecl, returnType, out var nativeTypeName);

if ((isVirtual || (body is null)) && (returnTypeName == "bool"))
if ((isVirtual || !hasBody) && (returnTypeName == "bool"))
{
// bool is not blittable, so we shouldn't use it for P/Invoke signatures
returnTypeName = "byte";
Expand All @@ -499,15 +501,15 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)
var type = functionDecl.Type;
var callingConventionName = GetCallingConvention(functionDecl, cxxRecordDecl, type);

var isDllImport = body is null && !isVirtual;
var isDllImport = !hasBody && !isVirtual;
var entryPoint = "";

if (isDllImport)
{
entryPoint = functionDecl.IsExternC ? GetCursorName(functionDecl) : functionDecl.Handle.Mangling.CString;
}

var needsReturnFixup = isVirtual && NeedsReturnFixup(cxxMethodDecl);
var needsReturnFixup = isCxxMethodDecl && NeedsReturnFixup(cxxMethodDecl);

var desc = new FunctionOrDelegateDesc {
AccessSpecifier = accessSppecifier,
Expand All @@ -521,8 +523,8 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)
IsDllImport = isDllImport,
HasFnPtrCodeGen = !_config.ExcludeFnptrCodegen,
SetLastError = GetSetLastError(functionDecl),
IsCxx = cxxMethodDecl is not null,
IsStatic = isDllImport || (cxxMethodDecl?.IsStatic ?? true),
IsCxx = isCxxMethodDecl,
IsStatic = isDllImport || !isCxxMethodDecl || cxxMethodDecl.IsStatic,
NeedsNewKeyword = NeedsNewKeyword(escapedName, functionDecl.Parameters),
IsUnsafe = IsUnsafe(functionDecl),
IsCtxCxxRecord = cxxRecordDecl is not null,
Expand All @@ -531,7 +533,7 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)
ReturnType = needsReturnFixup ? $"{returnTypeName}*" : returnTypeName,
IsCxxConstructor = functionDecl is CXXConstructorDecl,
Location = functionDecl.Location,
HasBody = body is not null,
HasBody = hasBody,
WriteCustomAttrs = static context => {
(var functionDecl, var outputBuilder, var generator) = ((FunctionDecl, IOutputBuilder, PInvokeGenerator))context;
Expand All @@ -552,7 +554,7 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)

_outputBuilder.BeginFunctionInnerPrototype(escapedName);

if (isVirtual)
if (isVirtual || (isCxxMethodDecl && !hasBody && cxxMethodDecl.IsInstance))
{
Debug.Assert(cxxRecordDecl != null);

Expand Down Expand Up @@ -593,7 +595,7 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)

_outputBuilder.EndFunctionInnerPrototype();

if ((body is not null) && !isVirtual)
if (hasBody && !isVirtual)
{
var firstCtorInitializer = functionDecl.Parameters.Any() ? (functionDecl.CursorChildren.IndexOf(functionDecl.Parameters.Last()) + 1) : 0;
var lastCtorInitializer = (functionDecl.Body != null) ? functionDecl.CursorChildren.IndexOf(functionDecl.Body) : functionDecl.CursorChildren.Count;
Expand Down Expand Up @@ -3406,6 +3408,26 @@ private bool IsConstant(string targetTypeName, Expr initExpr)

case CX_StmtClass.CX_StmtClass_CallExpr:
{
var callExpr = (CallExpr)initExpr;

if (callExpr.DirectCallee.IsInlined)
{
var evaluateResult = callExpr.Handle.Evaluate;

switch (evaluateResult.Kind)
{
case CXEvalResultKind.CXEval_Int:
{
return true;
}

case CXEvalResultKind.CXEval_Float:
{
return true;
}
}
}

return false;
}

Expand Down
46 changes: 46 additions & 0 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
Expand Down Expand Up @@ -68,6 +69,51 @@ private void VisitCallExpr(CallExpr callExpr)
var outputBuilder = StartCSharpCode();
var calleeDecl = callExpr.CalleeDecl;

if (callExpr.DirectCallee.IsInlined)
{
var evalResult = callExpr.Handle.Evaluate;
var canonicalType = callExpr.Type.CanonicalType;

switch (evalResult.Kind)
{
case CXEvalResultKind.CXEval_Int:
{
if (canonicalType.Handle.IsUnsigned)
{
outputBuilder.Write(evalResult.AsUnsigned);
}
else
{
outputBuilder.Write(evalResult.AsLongLong);
}

StopCSharpCode();
return;
}

case CXEvalResultKind.CXEval_Float:
{
if (canonicalType.Kind == CXTypeKind.CXType_Float)
{
outputBuilder.Write((float)evalResult.AsDouble);
}
else
{
outputBuilder.Write(evalResult.AsDouble);
}

StopCSharpCode();
return;
}

case CXEvalResultKind.CXEval_StrLiteral:
{
AddDiagnostic(DiagnosticLevel.Info, "Possible string constant");
break;
}
}
}

if (calleeDecl is null)
{
Visit(callExpr.Callee);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ namespace ClangSharp.Test
public partial struct MyStruct
{{
[DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.ThisCall, EntryPoint = ""{entryPoint}"", ExactSpelling = true)]
public static extern void MyVoidMethod();
public static extern void MyVoidMethod(MyStruct* pThis);
public int MyInt32Method()
{{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ namespace ClangSharp.Test
public partial struct MyStruct
{{
[DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.ThisCall, EntryPoint = ""{entryPoint}"", ExactSpelling = true)]
public static extern void MyVoidMethod();
public static extern void MyVoidMethod(MyStruct* pThis);
public int MyInt32Method()
{{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ namespace ClangSharp.Test
public partial struct MyStruct
{{
[DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.ThisCall, EntryPoint = ""{entryPoint}"", ExactSpelling = true)]
public static extern void MyVoidMethod();
public static extern void MyVoidMethod(MyStruct* pThis);
public int MyInt32Method()
{{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ namespace ClangSharp.Test
public partial struct MyStruct
{{
[DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.ThisCall, EntryPoint = ""{entryPoint}"", ExactSpelling = true)]
public static extern void MyVoidMethod();
public static extern void MyVoidMethod(MyStruct* pThis);
public int MyInt32Method()
{{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ int MyInt32Method()
<struct name=""MyStruct"" access=""public"">
<function name=""MyVoidMethod"" access=""public"" lib=""ClangSharpPInvokeGenerator"" convention=""ThisCall"" entrypoint=""{entryPoint}"" static=""true"">
<type>void</type>
<param name=""pThis"">
<type>MyStruct*</type>
</param>
</function>
<function name=""MyInt32Method"" access=""public"">
<type>int</type>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ int MyInt32Method()
<struct name=""MyStruct"" access=""public"">
<function name=""MyVoidMethod"" access=""public"" lib=""ClangSharpPInvokeGenerator"" convention=""ThisCall"" entrypoint=""{entryPoint}"" static=""true"">
<type>void</type>
<param name=""pThis"">
<type>MyStruct*</type>
</param>
</function>
<function name=""MyInt32Method"" access=""public"">
<type>int</type>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ int MyInt32Method()
<struct name=""MyStruct"" access=""public"">
<function name=""MyVoidMethod"" access=""public"" lib=""ClangSharpPInvokeGenerator"" convention=""ThisCall"" entrypoint=""{entryPoint}"" static=""true"">
<type>void</type>
<param name=""pThis"">
<type>MyStruct*</type>
</param>
</function>
<function name=""MyInt32Method"" access=""public"">
<type>int</type>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ int MyInt32Method()
<struct name=""MyStruct"" access=""public"">
<function name=""MyVoidMethod"" access=""public"" lib=""ClangSharpPInvokeGenerator"" convention=""ThisCall"" entrypoint=""{entryPoint}"" static=""true"">
<type>void</type>
<param name=""pThis"">
<type>MyStruct*</type>
</param>
</function>
<function name=""MyInt32Method"" access=""public"">
<type>int</type>
Expand Down

0 comments on commit 93db16d

Please sign in to comment.