// Probe assembly for MSVC's xml doc ID string generator (the ECMA-372-style
// dialect ILSpy's IdStringProvider must reproduce for C++/CLI assemblies).
// Every documented member below lands in the generated .xml; the members are
// independent, so if one fails to compile, delete it and rebuild.
//
// Build (VS Developer Command Prompt):
// msbuild IdStringProbe.vcxproj -p:Configuration=Debug -p:Platform=x64
// Return: x64\Debug\IdStringProbe.dll and x64\Debug\IdStringProbe.xml
using namespace System;
using namespace System::Collections::Generic;
/// Probe class.
public ref class IdProbe
{
public:
/// const int parameter; known baseline: System.Int32!System.Runtime.CompilerServices.IsConst
static int ConstValue(const int x) { return x; }
/// long parameter; modopt(IsLong) on Int32
static void TakesLong(long x) { (void)x; }
/// unsigned long parameter; modopt(IsLong) on UInt32
static void TakesULong(unsigned long x) { (void)x; }
/// char pointer parameter; modopt(IsSignUnspecifiedByte) under a pointer
static void TakesCharPtr(char* p) { (void)p; }
/// const char pointer parameter; IsConst and IsSignUnspecifiedByte together (modifier ordering)
static void TakesConstCharPtr(const char* p) { (void)p; }
/// volatile int pointer parameter; modreq(IsVolatile): the open question is whether MSVC renders '|', '!', or omits it
static void TakesVolatilePtr(volatile int* p) { (void)p; }
/// const volatile int pointer parameter; modreq and modopt mixed on one type
static void TakesConstVolatilePtr(const volatile int* p) { (void)p; }
/// tracking reference parameter; expected System.Int32@
static void TakesTrackingRef(int% r) { r = 0; }
/// const tracking reference parameter; modifier placement relative to the '@'
static void TakesConstTrackingRef(const int% r) { (void)r; }
/// native reference parameter under /clr; representation evidence
static void TakesNativeRef(int& r) { r = 0; }
/// two-dimensional managed array parameter; expected System.Int32[0:,0:]
static void TakesArray2(array^ a) { (void)a; }
/// nested type of a generic instantiation; how does MSVC distribute the type arguments?
static void TakesEnumerator(List::Enumerator e) { (void)e; }
/// generic method; expected arity marker and grave-accent parameter encoding
generic static void Gen(T t) { (void)t; }
/// conversion operator with a by-value ref-class parameter; the MSVC docs show IdProbe!IsByValue and a '~' return type
static explicit operator int(IdProbe x) { (void)x; return 0; }
/// indexed property with a long parameter; modopt inside the indexer parentheses
property int default[long]
{
int get(long i) { return (int)i; }
void set(long i, int value) { (void)i; (void)value; }
}
};
/// Generic ref class; arity in the type ID.
generic public ref class GBox
{
public:
/// method on a generic type taking T; expected grave-accent zero
void Hold(T item) { (void)item; }
};
/// Consumer of an instantiated generic type.
public ref class GBoxUser
{
public:
/// generic instantiation in a signature; expected GBox{System.Int32}
static void Use(GBox^ b) { (void)b; }
};