// 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; } };