@@ -378,19 +378,54 @@ private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverload(
378378 . WithModifiers ( TokenList ( TokenWithSpace ( SyntaxKind . OutKeyword ) ) ) ;
379379
380380 // HANDLE SomeLocal;
381- leadingStatements . Add ( LocalDeclarationStatement ( VariableDeclaration ( pointedElementInfo . ToTypeSyntax ( parameterTypeSyntaxSettings , GeneratingElement . FriendlyOverload , null ) . Type ) . AddVariables (
382- VariableDeclarator ( typeDefHandleName . Identifier ) ) ) ) ;
381+ leadingStatements . Add (
382+ LocalDeclarationStatement (
383+ VariableDeclaration (
384+ pointedElementInfo . ToTypeSyntax ( parameterTypeSyntaxSettings , GeneratingElement . FriendlyOverload , null ) . Type ,
385+ VariableDeclarator ( typeDefHandleName . Identifier ) ) ) ) ;
386+
387+ ArgumentSyntax ownsHandleArgument = Argument (
388+ NameColon ( IdentifierName ( "ownsHandle" ) ) ,
389+ refKindKeyword : default ,
390+ LiteralExpression ( doNotRelease ? SyntaxKind . FalseLiteralExpression : SyntaxKind . TrueLiteralExpression ) ) ;
391+
392+ if ( this . canUseMarshalInitHandle )
393+ {
394+ // Some = new SafeHandle(default, ownsHandle: true);
395+ leadingStatements . Add (
396+ ExpressionStatement (
397+ AssignmentExpression (
398+ SyntaxKind . SimpleAssignmentExpression ,
399+ origName ,
400+ ObjectCreationExpression ( safeHandleType , [ Argument ( LiteralExpression ( SyntaxKind . DefaultLiteralExpression ) ) , ownsHandleArgument ] ) ) ) ) ;
401+
402+ // Marshal.InitHandle(Some, SomeLocal);
403+ trailingStatements . Add (
404+ ExpressionStatement (
405+ InvocationExpression (
406+ MemberAccessExpression (
407+ SyntaxKind . SimpleMemberAccessExpression ,
408+ IdentifierName ( nameof ( Marshal ) ) ,
409+ IdentifierName ( "InitHandle" ) ) ,
410+ ArgumentList (
411+ [
412+ Argument ( origName ) ,
413+ Argument ( this . GetIntPtrFromTypeDef ( typeDefHandleName , pointedElementInfo ) ) ,
414+ ] ) ) ) ) ;
415+ }
416+ else
417+ {
418+ // Some = new SafeHandle(SomeLocal, ownsHandle: true);
419+ trailingStatements . Add ( ExpressionStatement ( AssignmentExpression (
420+ SyntaxKind . SimpleAssignmentExpression ,
421+ origName ,
422+ ObjectCreationExpression ( safeHandleType ) . AddArgumentListArguments (
423+ Argument ( this . GetIntPtrFromTypeDef ( typeDefHandleName , pointedElementInfo ) ) ,
424+ ownsHandleArgument ) ) ) ) ;
425+ }
383426
384427 // Argument: &SomeLocal
385428 arguments [ paramIndex ] = Argument ( PrefixUnaryExpression ( SyntaxKind . AddressOfExpression , typeDefHandleName ) ) ;
386-
387- // Some = new SafeHandle(SomeLocal, ownsHandle: true);
388- trailingStatements . Add ( ExpressionStatement ( AssignmentExpression (
389- SyntaxKind . SimpleAssignmentExpression ,
390- origName ,
391- ObjectCreationExpression ( safeHandleType ) . AddArgumentListArguments (
392- Argument ( this . GetIntPtrFromTypeDef ( typeDefHandleName , pointedElementInfo ) ) ,
393- Argument ( LiteralExpression ( doNotRelease ? SyntaxKind . FalseLiteralExpression : SyntaxKind . TrueLiteralExpression ) ) . WithNameColon ( NameColon ( IdentifierName ( "ownsHandle" ) ) ) ) ) ) ) ;
394429 }
395430 }
396431 else if ( this . options . UseSafeHandles && isIn && ! isOut && ! isReleaseMethod && parameterTypeInfo is HandleTypeHandleInfo parameterHandleTypeInfo && this . TryGetHandleReleaseMethod ( parameterHandleTypeInfo . Handle , paramAttributes , out string ? releaseMethod ) && ! this . Reader . StringComparer . Equals ( methodDefinition . Name , releaseMethod )
@@ -1108,7 +1143,46 @@ bool TryHandleCountParam(TypeSyntax elementType, bool nullableSource)
11081143 && returnTypeHandleInfo . Generator . TryGetHandleReleaseMethod ( returnTypeHandleInfo . Handle , returnTypeAttributes , out string ? returnReleaseMethod )
11091144 ? this . RequestSafeHandle ( returnReleaseMethod ) : null ;
11101145
1111- if ( ( returnSafeHandleType is object || minorSignatureChange ) && ! signatureChanged )
1146+ IdentifierNameSyntax resultLocal = IdentifierName ( "__result" ) ;
1147+
1148+ if ( this . canUseMarshalInitHandle && returnSafeHandleType is not null )
1149+ {
1150+ IdentifierNameSyntax resultSafeHandleLocal = IdentifierName ( "__resultSafeHandle" ) ;
1151+
1152+ // SafeHandle __resultSafeHandle = new SafeHandle(default, ownsHandle: true);
1153+ leadingStatements . Add (
1154+ LocalDeclarationStatement (
1155+ VariableDeclaration (
1156+ returnSafeHandleType ,
1157+ VariableDeclarator (
1158+ resultSafeHandleLocal . Identifier ,
1159+ EqualsValueClause (
1160+ ObjectCreationExpression (
1161+ returnSafeHandleType ,
1162+ [
1163+ Argument ( LiteralExpression ( SyntaxKind . DefaultLiteralExpression ) ) ,
1164+ Argument (
1165+ NameColon ( IdentifierName ( "ownsHandle" ) ) ,
1166+ refKindKeyword : default ,
1167+ LiteralExpression ( doNotRelease ? SyntaxKind . FalseLiteralExpression : SyntaxKind . TrueLiteralExpression ) )
1168+ ] ) ) ) ) ) ) ;
1169+
1170+ // Marshal.InitHandle(__resultSafeHandle, __result);
1171+ trailingStatements . Add (
1172+ ExpressionStatement (
1173+ InvocationExpression (
1174+ MemberAccessExpression (
1175+ SyntaxKind . SimpleMemberAccessExpression ,
1176+ IdentifierName ( nameof ( Marshal ) ) ,
1177+ IdentifierName ( "InitHandle" ) ) ,
1178+ ArgumentList (
1179+ [
1180+ Argument ( resultSafeHandleLocal ) ,
1181+ Argument ( this . GetIntPtrFromTypeDef ( resultLocal , originalSignature . ReturnType ) ) ,
1182+ ] ) ) ) ) ;
1183+ }
1184+
1185+ if ( ( returnSafeHandleType is not null || minorSignatureChange ) && ! signatureChanged )
11121186 {
11131187 // The parameter types are all the same, but we need a friendly overload with a different return type.
11141188 // Our only choice is to rename the friendly overload.
@@ -1145,20 +1219,33 @@ bool TryHandleCountParam(TypeSyntax elementType, bool nullableSource)
11451219 } )
11461220 . WithArgumentList ( FixTrivia ( ArgumentList ( ) . AddArguments ( arguments . ToArray ( ) ) ) ) ;
11471221 bool hasVoidReturn = externMethodReturnType is PredefinedTypeSyntax { Keyword : { RawKind : ( int ) SyntaxKind . VoidKeyword } } ;
1148- BlockSyntax ? body = Block ( ) . AddStatements ( leadingStatements . ToArray ( ) ) ;
1149- IdentifierNameSyntax resultLocal = IdentifierName ( "__result" ) ;
1150- if ( returnSafeHandleType is object )
1222+ BlockSyntax ? body = Block ( leadingStatements ) ;
1223+ if ( returnSafeHandleType is not null )
11511224 {
1152- //// HANDLE result = invocation();
1225+ // HANDLE result = invocation();
11531226 body = body . AddStatements ( LocalDeclarationStatement ( VariableDeclaration ( externMethodReturnType )
11541227 . AddVariables ( VariableDeclarator ( resultLocal . Identifier ) . WithInitializer ( EqualsValueClause ( externInvocation ) ) ) ) ) ;
11551228
11561229 body = body . AddStatements ( trailingStatements . ToArray ( ) ) ;
11571230
1158- //// return new SafeHandle(result, ownsHandle: true);
1159- body = body . AddStatements ( ReturnStatement ( ObjectCreationExpression ( returnSafeHandleType ) . AddArgumentListArguments (
1160- Argument ( this . GetIntPtrFromTypeDef ( resultLocal , originalSignature . ReturnType ) ) ,
1161- Argument ( LiteralExpression ( doNotRelease ? SyntaxKind . FalseLiteralExpression : SyntaxKind . TrueLiteralExpression ) ) . WithNameColon ( NameColon ( IdentifierName ( "ownsHandle" ) ) ) ) ) ) ;
1231+ ReturnStatementSyntax returnStatement ;
1232+ if ( this . canUseMarshalInitHandle )
1233+ {
1234+ // return __resultSafeHandle;
1235+ returnStatement = ReturnStatement ( IdentifierName ( "__resultSafeHandle" ) ) ;
1236+ }
1237+ else
1238+ {
1239+ // return new SafeHandle(result, ownsHandle: true);
1240+ returnStatement = ReturnStatement ( ObjectCreationExpression ( returnSafeHandleType ) . AddArgumentListArguments (
1241+ Argument ( this . GetIntPtrFromTypeDef ( resultLocal , originalSignature . ReturnType ) ) ,
1242+ Argument (
1243+ NameColon ( IdentifierName ( "ownsHandle" ) ) ,
1244+ refKindKeyword : default ,
1245+ LiteralExpression ( doNotRelease ? SyntaxKind . FalseLiteralExpression : SyntaxKind . TrueLiteralExpression ) ) ) ) ;
1246+ }
1247+
1248+ body = body . AddStatements ( returnStatement ) ;
11621249 }
11631250 else if ( hasVoidReturn )
11641251 {
0 commit comments