diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs
index 9d5105837a9bb..8967e6b3e69b3 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs
@@ -310,6 +310,20 @@ private static IncrementalMethodStubGenerationContext CalculateStubInformation(M
})
};
}
+ var direction = GetDirectionFromOptions(generatedComInterfaceAttributeData.Options);
+
+ // Ensure the size of collections are known at marshal / unmarshal in time.
+ // A collection that is marshalled in cannot have a size that is an 'out' parameter.
+ foreach (TypePositionInfo parameter in signatureContext.ManagedParameters)
+ {
+ MarshallerHelpers.ValidateCountInfoAvailableAtCall(
+ direction,
+ parameter,
+ generatorDiagnostics,
+ symbol,
+ GeneratorDiagnostics.SizeOfInCollectionMustBeDefinedAtCallOutParam,
+ GeneratorDiagnostics.SizeOfInCollectionMustBeDefinedAtCallReturnValue);
+ }
var containingSyntaxContext = new ContainingSyntaxContext(syntax);
@@ -322,7 +336,7 @@ private static IncrementalMethodStubGenerationContext CalculateStubInformation(M
var declaringType = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol.ContainingType);
- var virtualMethodIndexData = new VirtualMethodIndexData(index, ImplicitThisParameter: true, GetDirectionFromOptions(generatedComInterfaceAttributeData.Options), true, ExceptionMarshalling.Com);
+ var virtualMethodIndexData = new VirtualMethodIndexData(index, ImplicitThisParameter: true, direction, true, ExceptionMarshalling.Com);
return new IncrementalMethodStubGenerationContext(
signatureContext,
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs
index 0f3ec3d047d00..621e4c9b17001 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs
@@ -444,6 +444,26 @@ public class Ids
WellKnownDiagnosticTags.Unnecessary
});
+ ///
+ public static readonly DiagnosticDescriptor SizeOfInCollectionMustBeDefinedAtCallOutParam =
+ new DiagnosticDescriptor(
+ Ids.InvalidGeneratedComInterfaceAttributeUsage,
+ GetResourceString(nameof(SR.SizeOfCollectionMustBeKnownAtMarshalTimeTitle)),
+ GetResourceString(nameof(SR.SizeOfCollectionMustBeKnownAtMarshalTimeMessageOutParam)),
+ Category,
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
+ ///
+ public static readonly DiagnosticDescriptor SizeOfInCollectionMustBeDefinedAtCallReturnValue =
+ new DiagnosticDescriptor(
+ Ids.InvalidGeneratedComInterfaceAttributeUsage,
+ GetResourceString(nameof(SR.SizeOfCollectionMustBeKnownAtMarshalTimeTitle)),
+ GetResourceString(nameof(SR.SizeOfCollectionMustBeKnownAtMarshalTimeMessageReturnValue)),
+ Category,
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
///
public static readonly DiagnosticDescriptor ComMethodManagedReturnWillBeOutVariable =
new DiagnosticDescriptor(
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx
index 5dd131c0afa37..a096158343d16 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx
@@ -700,6 +700,15 @@
COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf
index 5dab1b24b59f6..e2c18dab20458 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf
@@ -997,6 +997,21 @@
Abstraktní typ odvozený ze SafeHandle nelze zařadit pomocí odkazu. Poskytnutý typ musí být konkrétní.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ Stavový zařazovač musí mít instanční metodu s názvem Free, která nemá žádné parametry a vrací void.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf
index 49a475c5dcaaf..d085560facf7f 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf
@@ -997,6 +997,21 @@
Ein abstrakter Typ, der von \"SafeHandle\" abgeleitet wird, kann nicht als Verweis gemarshallt werden. Der angegebene Typ muss ein konkretes Element sein.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ Ein statusbehafteter Marshaller muss eine Instanzmethode mit dem Namen „Free“ mit null Parametern haben, die „nichtig“ zurückgibt.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf
index 21b41f24a8385..0307795f45eb2 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf
@@ -997,6 +997,21 @@
Un tipo abstracto derivado de “SafeHandle” no se puede serializar por referencia. El tipo proporcionado debe ser concreto.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ Un serializador con estado debe tener un método de instancia de devolución void de parámetro cero denominado 'Free'.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf
index f3aa7dac375ec..fdbcb443261ef 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf
@@ -997,6 +997,21 @@
Un type abstrait dérivé de « SafeHandle » ne peut pas être marshalé par référence. Le type fourni doit être concret.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ Un marshaleur avec état doit avoir une méthode d’instance de retour void de paramètre zéro nommée 'Free'.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf
index ac87db54081a4..a0aa417a60164 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf
@@ -997,6 +997,21 @@
Non è possibile effettuare il marshalling per riferimento di un tipo astratto derivato da 'SafeHandle'. Il tipo specificato deve essere concreto.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ Un gestore di marshalling con stato deve avere un metodo di istanza con restituzione void con parametro zero denominato 'Free'.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf
index 867f5472f698a..85834a4023adc 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf
@@ -997,6 +997,21 @@
'SafeHandle' から派生した抽象型は、参照でマーシャリングできません。指定される型は具象型である必要があります。
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ ステートフル マーシャラーには、'Free' という名前で、パラメーターがなく、‘void’ を返すインスタンス メソッドが必要です。
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf
index c04b1253058eb..546cdfa094717 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf
@@ -997,6 +997,21 @@
'SafeHandle'에서 파생된 추상 형식은 참조로 마샬링할 수 없습니다. 제공된 형식은 구체적이어야 합니다.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ 상태 저장 마샬러에는 'Free'라는 0 매개 변수 반환 인스턴스 메서드가 있어야 합니다.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf
index 6a4a6f7ba9840..e1adb5d335b29 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf
@@ -997,6 +997,21 @@
Typ abstrakcyjny pochodzący od elementu „SafeHandle” nie może być skierowany przez odwołanie. Podany typ musi być konkretny.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ Stanowy marshaller musi mieć metodę wystąpienia zwracającą wartość nieważną o parametrze 0 o nazwie „Free”.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf
index 6ae9c3061d4b5..7bd7f73064878 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf
@@ -997,6 +997,21 @@
Um tipo abstrato derivado de 'SafeHandle' não pode ser marshalled por referência. O tipo fornecido deve ser concreto.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ Um marshaller com estado deve ter um método de instância de retorno nulo de parâmetro zero chamado 'Gratuito'.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf
index 2f16b177e2231..5bcb3d31ebae0 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf
@@ -997,6 +997,21 @@
Абстрактный тип, производный от \"SafeHandle\", нельзя маршализировать по ссылке. Указанный тип должен быть конкретным.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ Маршалер с отслеживанием состояния должен иметь метод экземпляра с нулевым параметром, возвращающий void, с именем "Free".
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf
index 521f0b8cb7356..b9e3a106e9537 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf
@@ -997,6 +997,21 @@
'SafeHandle' özelliğinden türetilen soyut türler, başvuruya göre sıralanamaz. Sağlanan tür somut olmalıdır.
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ Durum bilgisi olan bir hazırlayıcının 'Free' adlı sıfır parametreli hükümsüz dönen bir örnek yöntemi olmalıdır.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf
index a303503da5f30..5c452bbf91561 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf
@@ -997,6 +997,21 @@
无法通过引用封送派生自 “SafeHandle” 的抽象类型。提供的类型必须是具体的。
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ 监控状态的封送程序必须具有名为 “Free” 的零参数 void 返回实例方法。
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf
index adf2ea22b5353..8a8dd483eaab6 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf
+++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf
@@ -997,6 +997,21 @@
衍生自 'SafeHandle' 的抽象類型無法依參考排列。提供的類型必須是實體。
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but count parameter '{1}' is an 'out' parameter.
+
+
+
+
+ The size of parameter '{0}' that is marshalled to the callee must be defined when the method is called, but the return value is used as the size of the collection.
+
+
+
+
+ The size of a collection that is marshalled to the callee must be defined when the method is called.
+
+ 具狀態的封送處理常式必須有名稱為 'Free' 的零參數無效傳回執行個體方法。
diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs
index 140775be274cc..5e59f2d5bf8e3 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs
@@ -233,6 +233,26 @@ public class Ids
WellKnownDiagnosticTags.Unnecessary
});
+ ///
+ public static readonly DiagnosticDescriptor SizeOfInCollectionMustBeDefinedAtCallOutParam =
+ new DiagnosticDescriptor(
+ Ids.InvalidLibraryImportAttributeUsage,
+ GetResourceString(nameof(SR.SizeOfCollectionMustBeKnownAtMarshalTimeTitle)),
+ GetResourceString(nameof(SR.SizeOfCollectionMustBeKnownAtMarshalTimeMessageOutParam)),
+ Category,
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
+ ///
+ public static readonly DiagnosticDescriptor SizeOfInCollectionMustBeDefinedAtCallReturnValue =
+ new DiagnosticDescriptor(
+ Ids.InvalidLibraryImportAttributeUsage,
+ GetResourceString(nameof(SR.SizeOfCollectionMustBeKnownAtMarshalTimeTitle)),
+ GetResourceString(nameof(SR.SizeOfCollectionMustBeKnownAtMarshalTimeMessageReturnValue)),
+ Category,
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
///
/// Report diagnostic for invalid configuration for string marshalling.
///
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs
index 77cd004720dea..ebb1f01bf8d3f 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs
@@ -404,5 +404,46 @@ public static MarshalDirection GetMarshalDirection(TypePositionInfo info, StubCo
}
throw new UnreachableException("An element is either a return value or passed by value or by ref.");
}
+
+ ///
+ /// Ensure that the count of a collection is available at call time if the parameter is not an out parameter.
+ /// It only looks at an indirection level of 0 (the size of the outer array), so there are some holes in
+ /// analysis if the parameter is a multidimensional array, but that case seems very unlikely to be hit.
+ ///
+ public static void ValidateCountInfoAvailableAtCall(MarshalDirection stubDirection, TypePositionInfo info, GeneratorDiagnosticsBag generatorDiagnostics, IMethodSymbol symbol, DiagnosticDescriptor outParamDescriptor, DiagnosticDescriptor returnValueDescriptor)
+ {
+ // In managed to unmanaged stubs, we can always just get the length of managed object
+ // We only really need to be concerned about unmanaged to managed stubs
+ if (stubDirection is MarshalDirection.ManagedToUnmanaged)
+ return;
+
+ if (info.MarshallingAttributeInfo is NativeLinearCollectionMarshallingInfo collectionMarshallingInfo
+ && collectionMarshallingInfo.ElementCountInfo is CountElementCountInfo countInfo
+ && !(info.RefKind is RefKind.Out
+ || info.ManagedIndex is TypePositionInfo.ReturnIndex))
+ {
+ if (countInfo.ElementInfo.IsByRef && countInfo.ElementInfo.RefKind is RefKind.Out)
+ {
+ Location location = TypePositionInfo.GetLocation(info, symbol);
+ generatorDiagnostics.ReportDiagnostic(
+ DiagnosticInfo.Create(
+ outParamDescriptor,
+ location,
+ info.InstanceIdentifier,
+ countInfo.ElementInfo.InstanceIdentifier));
+ }
+ else if (countInfo.ElementInfo.ManagedIndex is TypePositionInfo.ReturnIndex)
+ {
+ Location location = TypePositionInfo.GetLocation(info, symbol);
+ generatorDiagnostics.ReportDiagnostic(
+ DiagnosticInfo.Create(
+ returnValueDescriptor,
+ location,
+ info.InstanceIdentifier));
+ }
+ // If the parameter is multidimensional and a higher indirection level parameter is ByValue [Out], then we should warn.
+ }
+ }
+
}
}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs
index bb40116731362..76697b0e6dd6a 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs
@@ -96,6 +96,17 @@ public static TypePositionInfo CreateForParameter(IParameterSymbol paramSymbol,
return typeInfo;
}
+ public static Location GetLocation(TypePositionInfo info, IMethodSymbol methodSymbol)
+ {
+ if (info.ManagedIndex is UnsetIndex)
+ return Location.None;
+
+ if (info.ManagedIndex is ReturnIndex or ExceptionIndex)
+ return methodSymbol.Locations[0];
+
+ return methodSymbol.Parameters[info.ManagedIndex].Locations[0];
+ }
+
private static (ByValueContentsMarshalKind, Location? inAttribute, Location? outAttribute) GetByValueContentsMarshalKind(IEnumerable attributes, Compilation compilation)
{
INamedTypeSymbol outAttributeType = compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_OutAttribute)!;
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs
index 04ba3b30e83d0..b013d8c26c459 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs
@@ -89,7 +89,7 @@ internal struct IntStruct
[CustomMarshaller(typeof(IntStruct), MarshalMode.Default, typeof(IntStructMarshaller))]
internal static class IntStructMarshaller
{
- public static nint ConvertToUnmanaged(int managed) => (nint)0;
+ public static nint ConvertToUnmanaged(IntStruct managed) => (nint)0;
public static IntStruct ConvertToManaged(nint unmanaged) => default;
}
""";
@@ -268,6 +268,53 @@ partial interface INativeAPI
{{_attributeProvider.AdditionalUserRequiredInterfaces("INativeAPI")}}
""";
+ public string CollectionMarshallingWithCountRefKinds(
+ (string parameterType, string parameterModifiers, string[] countNames) returnType,
+ params (string parameterType, string parameterModifiers, string parameterName, string[] countNames)[] parameters)
+ {
+ List parameterSources = new();
+ int i = 1;
+ foreach (var (parameterType, parameterModifiers, parameterName, countNames) in parameters)
+ {
+ List marshalUsings = new();
+ int j = 0;
+ foreach (var countName in countNames)
+ {
+ marshalUsings.Add($"[MarshalUsing(CountElementName = {countName}, ElementIndirectionDepth = {j})]");
+ j++;
+ }
+ parameterSources.Add($$"""
+ {{string.Join(' ', marshalUsings)}} {{parameterModifiers}} {{parameterType}} {|#{{i}}:{{parameterName}}|}
+ """);
+ i++;
+ }
+ string returnTypeSource;
+ {
+ List marshalUsings = new();
+ var (parameterType, parameterModifiers, countNames) = returnType;
+ foreach (var countName in countNames)
+ {
+ marshalUsings.Add($"[return: MarshalUsing(CountElementName = nameof({countName}))]");
+ }
+ returnTypeSource = $"{string.Join(' ', marshalUsings)} {parameterModifiers} {parameterType}";
+ }
+ var parametersSource = string.Join(',', parameterSources);
+ return $$"""
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.InteropServices.Marshalling;
+ [assembly:DisableRuntimeMarshalling]
+
+ {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
+ {{GeneratedComInterface()}}
+ partial interface INativeAPI
+ {
+ {{VirtualMethodIndex(0)}}
+ {{returnTypeSource}} {|#0:Method|}({{parametersSource}});
+ }
+ """;
+ }
+
public string BasicReturnTypeComExceptionHandling(string typeName, string preDeclaration = "") => $$"""
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -423,17 +470,17 @@ partial interface INativeAPI
public static event EventHandler StaticEvent;
}
-
+
{{_attributeProvider.AdditionalUserRequiredInterfaces("INativeAPI")}}
interface IOtherInterface
{
int Property { get; set; }
-
+
public static int StaticProperty { get; set; }
-
+
event EventHandler Event;
-
+
public static event EventHandler StaticEvent;
}
""";
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs
index a0f117690734d..ef9d76ff4c920 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs
@@ -975,6 +975,102 @@ partial interface {|#0:J|}
await test.RunAsync();
}
+ public static IEnumerable