summaryrefslogtreecommitdiff
path: root/src/vm/typestring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/typestring.cpp')
-rw-r--r--src/vm/typestring.cpp1678
1 files changed, 1678 insertions, 0 deletions
diff --git a/src/vm/typestring.cpp b/src/vm/typestring.cpp
new file mode 100644
index 0000000000..ba103c42fa
--- /dev/null
+++ b/src/vm/typestring.cpp
@@ -0,0 +1,1678 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ---------------------------------------------------------------------------
+// typestring.cpp
+// ---------------------------------------------------------------------------
+//
+
+//
+// This module contains a helper function used to produce string
+// representations of types, with options to control the appearance of
+// namespace and assembly information. Its primary use is in
+// reflection (Type.Name, Type.FullName, Type.ToString, etc) but over
+// time it could replace the use of TypeHandle.GetName etc for
+// diagnostic messages.
+//
+// See the header file for more details
+// ---------------------------------------------------------------------------
+
+
+#include "common.h"
+#include "class.h"
+#include "typehandle.h"
+#include "sstring.h"
+#include "sigformat.h"
+#include "typeparse.h"
+#include "typestring.h"
+#include "ex.h"
+#include "typedesc.h"
+
+#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
+TypeNameBuilder * QCALLTYPE TypeNameBuilder::_CreateTypeNameBuilder()
+{
+ QCALL_CONTRACT;
+
+ TypeNameBuilder * retVal = NULL;
+ BEGIN_QCALL;
+ retVal = new TypeNameBuilder();
+ END_QCALL;
+
+ return retVal;
+}
+
+void QCALLTYPE TypeNameBuilder::_ReleaseTypeNameBuilder(TypeNameBuilder * pTnb)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ delete pTnb;
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_ToString(TypeNameBuilder * pTnb, QCall::StringHandleOnStack retString)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ retString.Set(*pTnb->GetString());
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_AddName(TypeNameBuilder * pTnb, LPCWSTR wszName)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->AddName(wszName);
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_AddAssemblySpec(TypeNameBuilder * pTnb, LPCWSTR wszAssemblySpec)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->AddAssemblySpec(wszAssemblySpec);
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_OpenGenericArguments(TypeNameBuilder * pTnb)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->OpenGenericArguments();
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_CloseGenericArguments(TypeNameBuilder * pTnb)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->CloseGenericArguments();
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_OpenGenericArgument(TypeNameBuilder * pTnb)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->OpenGenericArgument();
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_CloseGenericArgument(TypeNameBuilder * pTnb)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->CloseGenericArgument();
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_AddPointer(TypeNameBuilder * pTnb)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->AddPointer();
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_AddByRef(TypeNameBuilder * pTnb)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->AddByRef();
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_AddSzArray(TypeNameBuilder * pTnb)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->AddSzArray();
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_AddArray(TypeNameBuilder * pTnb, DWORD dwRank)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->AddArray(dwRank);
+ END_QCALL;
+}
+
+void QCALLTYPE TypeNameBuilder::_Clear(TypeNameBuilder * pTnb)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pTnb->Clear();
+ END_QCALL;
+}
+
+#endif
+
+//
+// TypeNameBuilder
+//
+TypeNameBuilder::TypeNameBuilder(SString* pStr, ParseState parseState /*= ParseStateSTART*/) :
+ m_pStr(NULL)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+ Clear();
+ m_pStr = pStr;
+ m_parseState = parseState;
+}
+
+void TypeNameBuilder::PushOpenGenericArgument()
+{
+ WRAPPER_NO_CONTRACT;
+
+ m_stack.Push(m_pStr->GetCount());
+}
+
+void TypeNameBuilder::PopOpenGenericArgument()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ COUNT_T index = m_stack.Pop();
+
+ if (!m_bHasAssemblySpec)
+ m_pStr->Delete(m_pStr->Begin() + index - 1, 1);
+
+ m_bHasAssemblySpec = FALSE;
+}
+
+/* This method escapes szName and appends it to this TypeNameBuilder */
+void TypeNameBuilder::EscapeName(LPCWSTR szName)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ if (TypeString::ContainsReservedChar(szName))
+ {
+ while (* szName)
+ {
+ WCHAR c = * szName ++;
+
+ if (IsTypeNameReservedChar(c))
+ Append(W('\\'));
+
+ Append(c);
+ }
+ }
+ else
+ {
+ Append(szName);
+ }
+}
+
+void TypeNameBuilder::EscapeAssemblyName(LPCWSTR szName)
+{
+ WRAPPER_NO_CONTRACT;
+
+ Append(szName);
+}
+
+void TypeNameBuilder::EscapeEmbeddedAssemblyName(LPCWSTR szName)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ LPCWSTR itr = szName;
+ bool bContainsReservedChar = false;
+
+ while (*itr)
+ {
+ if (W(']') == *itr++)
+ {
+ bContainsReservedChar = true;
+ break;
+ }
+ }
+
+ if (bContainsReservedChar)
+ {
+ itr = szName;
+ while (*itr)
+ {
+ WCHAR c = *itr++;
+ if (c == ']')
+ Append(W('\\'));
+
+ Append(c);
+ }
+ }
+ else
+ {
+ Append(szName);
+ }
+}
+
+HRESULT TypeNameBuilder::OpenGenericArgument()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ if (!CheckParseState(ParseStateSTART))
+ return Fail();
+
+ if (m_instNesting == 0)
+ return Fail();
+
+ HRESULT hr = S_OK;
+
+ m_parseState = ParseStateSTART;
+ m_bNestedName = FALSE;
+
+ if (!m_bFirstInstArg)
+ Append(W(','));
+
+ m_bFirstInstArg = FALSE;
+
+ if (m_bUseAngleBracketsForGenerics)
+ Append(W('<'));
+ else
+ Append(W('['));
+ PushOpenGenericArgument();
+
+ return hr;
+}
+
+HRESULT TypeNameBuilder::AddName(LPCWSTR szName)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ if (!szName)
+ return Fail();
+
+ if (!CheckParseState(ParseStateSTART | ParseStateNAME))
+ return Fail();
+
+ HRESULT hr = S_OK;
+
+ m_parseState = ParseStateNAME;
+
+ if (m_bNestedName)
+ Append(W('+'));
+
+ m_bNestedName = TRUE;
+
+ EscapeName(szName);
+
+ return hr;
+}
+
+HRESULT TypeNameBuilder::AddName(LPCWSTR szName, LPCWSTR szNamespace)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ if (!szName)
+ return Fail();
+
+ if (!CheckParseState(ParseStateSTART | ParseStateNAME))
+ return Fail();
+
+ HRESULT hr = S_OK;
+
+ m_parseState = ParseStateNAME;
+
+ if (m_bNestedName)
+ Append(W('+'));
+
+ m_bNestedName = TRUE;
+
+ if (szNamespace && *szNamespace)
+ {
+ EscapeName(szNamespace);
+ Append(W('.'));
+ }
+
+ EscapeName(szName);
+
+ return hr;
+}
+
+HRESULT TypeNameBuilder::OpenGenericArguments()
+{
+ WRAPPER_NO_CONTRACT;
+
+ if (!CheckParseState(ParseStateNAME))
+ return Fail();
+
+ HRESULT hr = S_OK;
+
+ m_parseState = ParseStateSTART;
+ m_instNesting ++;
+ m_bFirstInstArg = TRUE;
+
+ if (m_bUseAngleBracketsForGenerics)
+ Append(W('<'));
+ else
+ Append(W('['));
+
+ return hr;
+}
+
+HRESULT TypeNameBuilder::CloseGenericArguments()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ if (!m_instNesting)
+ return Fail();
+ if (!CheckParseState(ParseStateSTART))
+ return Fail();
+
+ HRESULT hr = S_OK;
+
+ m_parseState = ParseStateGENARGS;
+
+ m_instNesting --;
+
+ if (m_bFirstInstArg)
+ {
+ m_pStr->Truncate(m_pStr->End() - 1);
+ }
+ else
+ {
+ if (m_bUseAngleBracketsForGenerics)
+ Append(W('>'));
+ else
+ Append(W(']'));
+ }
+
+ return hr;
+}
+
+HRESULT TypeNameBuilder::AddPointer()
+{
+ WRAPPER_NO_CONTRACT;
+
+ if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
+ return Fail();
+
+ m_parseState = ParseStatePTRARR;
+
+ Append(W('*'));
+
+ return S_OK;
+}
+
+HRESULT TypeNameBuilder::AddByRef()
+{
+ WRAPPER_NO_CONTRACT;
+
+ if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
+ return Fail();
+
+ m_parseState = ParseStateBYREF;
+
+ Append(W('&'));
+
+ return S_OK;
+}
+
+HRESULT TypeNameBuilder::AddSzArray()
+{
+ WRAPPER_NO_CONTRACT;
+
+ if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
+ return Fail();
+
+ m_parseState = ParseStatePTRARR;
+
+ Append(W("[]"));
+
+ return S_OK;
+}
+
+HRESULT TypeNameBuilder::AddArray(DWORD rank)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
+ return Fail();
+
+ m_parseState = ParseStatePTRARR;
+
+ if (rank <= 0)
+ return E_INVALIDARG;
+
+ if (rank == 1)
+ Append(W("[*]"));
+ else if (rank > 64)
+ {
+ // Only taken in an error path, runtime will not load arrays of more than 32 dimentions
+ WCHAR wzDim[128];
+ _snwprintf_s(wzDim, 128, _TRUNCATE, W("[%d]"), rank);
+ Append(wzDim);
+ }
+ else
+ {
+ WCHAR* wzDim = new (nothrow) WCHAR[rank+3];
+
+ if(wzDim == NULL) // allocation failed, do it the long way (each Append -> memory realloc)
+ {
+ Append(W('['));
+ for(COUNT_T i = 1; i < rank; i ++)
+ Append(W(','));
+ Append(W(']'));
+ }
+ else // allocation OK, do it the fast way
+ {
+ WCHAR* pwz = wzDim+1;
+ *wzDim = '[';
+ for(COUNT_T i = 1; i < rank; i++, pwz++) *pwz=',';
+ *pwz = ']';
+ *(++pwz) = 0;
+ Append(wzDim);
+ delete [] wzDim;
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT TypeNameBuilder::CloseGenericArgument()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF | ParseStateASSEMSPEC))
+ return Fail();
+
+ if (m_instNesting == 0)
+ return Fail();
+
+ m_parseState = ParseStateSTART;
+
+ if (m_bHasAssemblySpec)
+ {
+ if (m_bUseAngleBracketsForGenerics)
+ Append(W('>'));
+ else
+ Append(W(']'));
+ }
+
+ PopOpenGenericArgument();
+
+ return S_OK;
+}
+
+HRESULT TypeNameBuilder::AddAssemblySpec(LPCWSTR szAssemblySpec)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF))
+ return Fail();
+
+ HRESULT hr = S_OK;
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+
+ m_parseState = ParseStateASSEMSPEC;
+
+ if (szAssemblySpec && *szAssemblySpec)
+ {
+ Append(W(", "));
+
+ if (m_instNesting > 0)
+ {
+ EscapeEmbeddedAssemblyName(szAssemblySpec);
+ }
+ else
+ {
+ EscapeAssemblyName(szAssemblySpec);
+ }
+
+ m_bHasAssemblySpec = TRUE;
+ hr = S_OK;
+ }
+
+ END_SO_INTOLERANT_CODE;
+
+ return hr;
+}
+
+HRESULT TypeNameBuilder::ToString(BSTR* pszStringRepresentation)
+{
+ WRAPPER_NO_CONTRACT;
+
+ if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF | ParseStateASSEMSPEC))
+ return Fail();
+
+ if (m_instNesting)
+ return Fail();
+
+ *pszStringRepresentation = SysAllocString(m_pStr->GetUnicode());
+
+ return S_OK;
+}
+
+HRESULT TypeNameBuilder::Clear()
+{
+ CONTRACTL
+ {
+ THROWS; // TypeNameBuilder::Stack::Clear might throw.
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ CONTRACT_VIOLATION(SOToleranceViolation);
+
+ if (m_pStr)
+ {
+ m_pStr->Clear();
+ }
+ m_bNestedName = FALSE;
+ m_instNesting = 0;
+ m_bFirstInstArg = FALSE;
+ m_parseState = ParseStateSTART;
+ m_bHasAssemblySpec = FALSE;
+ m_bUseAngleBracketsForGenerics = FALSE;
+ m_stack.Clear();
+
+ return S_OK;
+}
+
+
+
+// Append the name of the type td to the string
+// The following flags in the FormatFlags argument are significant: FormatNamespace
+void TypeString::AppendTypeDef(SString& ss, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
+{
+ CONTRACT_VOID
+ {
+ MODE_ANY;
+ GC_NOTRIGGER;
+ THROWS;
+ }
+ CONTRACT_END
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
+ {
+ TypeNameBuilder tnb(&ss, TypeNameBuilder::ParseStateNAME);
+ AppendTypeDef(tnb, pImport, td, format);
+ }
+ END_SO_INTOLERANT_CODE;
+
+ RETURN;
+}
+
+
+void TypeString::AppendTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
+{
+ CONTRACT_VOID
+ {
+ MODE_ANY;
+ GC_NOTRIGGER;
+ THROWS;
+ PRECONDITION(CheckPointer(pImport));
+ PRECONDITION(TypeFromToken(td) == mdtTypeDef);
+ }
+ CONTRACT_END
+
+ LPCUTF8 szName;
+ LPCUTF8 szNameSpace;
+ IfFailThrow(pImport->GetNameOfTypeDef(td, &szName, &szNameSpace));
+
+ const WCHAR *wszNameSpace = NULL;
+
+ InlineSString<128> ssName(SString::Utf8, szName);
+ InlineSString<128> ssNameSpace;
+
+ if (format & FormatNamespace)
+ {
+ ssNameSpace.SetUTF8(szNameSpace);
+ wszNameSpace = ssNameSpace.GetUnicode();
+ }
+
+ tnb.AddName(ssName.GetUnicode(), wszNameSpace);
+
+ RETURN;
+}
+
+void TypeString::AppendNestedTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
+{
+ CONTRACT_VOID
+ {
+ MODE_ANY;
+ GC_NOTRIGGER;
+ THROWS;
+ PRECONDITION(CheckPointer(pImport));
+ PRECONDITION(TypeFromToken(td) == mdtTypeDef);
+ }
+ CONTRACT_END
+
+ DWORD dwAttr;
+ IfFailThrow(pImport->GetTypeDefProps(td, &dwAttr, NULL));
+
+ StackSArray<mdTypeDef> arNames;
+ arNames.Append(td);
+ if (format & FormatNamespace && IsTdNested(dwAttr))
+ {
+ while (SUCCEEDED(pImport->GetNestedClassProps(td, &td)))
+ arNames.Append(td);
+ }
+
+ for(SCOUNT_T i = arNames.GetCount() - 1; i >= 0; i --)
+ AppendTypeDef(tnb, pImport, arNames[i], format);
+
+ RETURN;
+}
+
+// Append a square-bracket-enclosed, comma-separated list of n type parameters in inst to the string s
+// and enclose each parameter in square brackets to disambiguate the commas
+// The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
+void TypeString::AppendInst(SString& ss, Instantiation inst, DWORD format)
+{
+ CONTRACT_VOID
+ {
+ MODE_ANY;
+ if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
+ THROWS;
+ }
+ CONTRACT_END
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
+ {
+ TypeNameBuilder tnb(&ss, TypeNameBuilder::ParseStateNAME);
+ if ((format & FormatAngleBrackets) != 0)
+ tnb.SetUseAngleBracketsForGenerics(TRUE);
+ AppendInst(tnb, inst, format);
+ }
+ END_SO_INTOLERANT_CODE;
+
+ RETURN;
+}
+
+void TypeString::AppendInst(TypeNameBuilder& tnb, Instantiation inst, DWORD format)
+{
+ CONTRACT_VOID
+ {
+ MODE_ANY;
+ THROWS;
+ if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
+ PRECONDITION(!inst.IsEmpty());
+ }
+ CONTRACT_END
+
+ tnb.OpenGenericArguments();
+
+ for (DWORD i = 0; i < inst.GetNumArgs(); i++)
+ {
+ tnb.OpenGenericArgument();
+
+ TypeHandle thArg = inst[i];
+
+ if ((format & FormatFullInst) != 0 && !thArg.IsGenericVariable())
+ {
+ AppendType(tnb, thArg, Instantiation(), format | FormatNamespace | FormatAssembly);
+ }
+ else
+ {
+ AppendType(tnb, thArg, Instantiation(), format & (FormatNamespace | FormatAngleBrackets
+#ifdef _DEBUG
+ | FormatDebug
+#endif
+ ));
+ }
+
+ tnb.CloseGenericArgument();
+ }
+
+ tnb.CloseGenericArguments();
+
+ RETURN;
+}
+
+void TypeString::AppendParamTypeQualifier(TypeNameBuilder& tnb, CorElementType kind, DWORD rank)
+{
+ CONTRACTL
+ {
+ MODE_ANY;
+ THROWS;
+ GC_NOTRIGGER;
+ PRECONDITION(CorTypeInfo::IsModifier(kind));
+ }
+ CONTRACTL_END
+
+ switch (kind)
+ {
+ case ELEMENT_TYPE_BYREF :
+ tnb.AddByRef();
+ break;
+ case ELEMENT_TYPE_PTR :
+ tnb.AddPointer();
+ break;
+ case ELEMENT_TYPE_SZARRAY :
+ tnb.AddSzArray();
+ break;
+ case ELEMENT_TYPE_ARRAY :
+ tnb.AddArray(rank);
+ break;
+ default :
+ break;
+ }
+}
+
+// Append a representation of the type t to the string s
+// The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
+
+void TypeString::AppendType(SString& ss, TypeHandle ty, DWORD format)
+{
+ CONTRACT_VOID
+ {
+ MODE_ANY;
+ if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
+ THROWS;
+ }
+ CONTRACT_END
+
+ AppendType(ss, ty, Instantiation(), format);
+
+ RETURN;
+}
+
+void TypeString::AppendType(SString& ss, TypeHandle ty, Instantiation typeInstantiation, DWORD format)
+{
+ CONTRACT_VOID
+ {
+ MODE_ANY;
+ if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
+ THROWS;
+ }
+ CONTRACT_END
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
+ {
+ TypeNameBuilder tnb(&ss);
+ if ((format & FormatAngleBrackets) != 0)
+ tnb.SetUseAngleBracketsForGenerics(TRUE);
+ AppendType(tnb, ty, typeInstantiation, format);
+ }
+ END_SO_INTOLERANT_CODE;
+
+ RETURN;
+}
+
+void TypeString::AppendType(TypeNameBuilder& tnb, TypeHandle ty, Instantiation typeInstantiation, DWORD format)
+{
+ CONTRACT_VOID
+ {
+ MODE_ANY;
+
+ /* This method calls Assembly::GetDisplayName. Since that function
+ uses Fusion which takes some Crsts in some places, it is GC_TRIGGERS.
+ It could be made GC_NOTRIGGER by factoring out Assembly::GetDisplayName.
+ However, its better to leave stuff as GC_TRIGGERS unless really needed,
+ as GC_NOTRIGGER ties your hands up. */
+ if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
+ THROWS;
+ }
+ CONTRACT_END
+
+ INTERIOR_STACK_PROBE_FOR_CHECK_THREAD(10);
+
+ BOOL bToString = (format & (FormatNamespace|FormatFullInst|FormatAssembly)) == FormatNamespace;
+
+ // It's null!
+ if (ty.IsNull())
+ {
+ tnb.AddName(W("(null)"));
+ }
+ else
+ // It's not restored yet!
+ if (ty.IsEncodedFixup())
+ {
+ tnb.AddName(W("(fixup)"));
+ }
+ else
+
+ // It's an array, with format
+ // element_ty[] (1-d, SZARRAY)
+ // element_ty[*] (1-d, ARRAY)
+ // element_ty[,] (2-d, ARRAY) etc
+ // or a pointer (*) or byref (&)
+ if (ty.HasTypeParam() || (!ty.IsTypeDesc() && ty.AsMethodTable()->IsArray()))
+ {
+ if (ty.GetSignatureCorElementType() != ELEMENT_TYPE_VALUETYPE)
+ {
+ DWORD rank;
+ TypeHandle elemType;
+ if (ty.HasTypeParam())
+ {
+ rank = ty.IsArray() ? ty.AsArray()->GetRank() : 0;
+ elemType = ty.GetTypeParam();
+ }
+ else
+ {
+ MethodTable *pMT = ty.GetMethodTable();
+ PREFIX_ASSUME(pMT != NULL);
+ rank = pMT->GetRank();
+ elemType = pMT->GetApproxArrayElementTypeHandle();
+ }
+
+ _ASSERTE(!elemType.IsNull());
+ AppendType(tnb, elemType, Instantiation(), format & ~FormatAssembly);
+ AppendParamTypeQualifier(tnb, ty.GetSignatureCorElementType(), rank);
+ }
+ else
+ {
+ tnb.Append(W("VALUETYPE"));
+ TypeHandle elemType = ty.GetTypeParam();
+ AppendType(tnb, elemType, Instantiation(), format & ~FormatAssembly);
+ }
+ }
+
+ // ...or type parameter
+ else if (ty.IsGenericVariable())
+ {
+ PTR_TypeVarTypeDesc tyvar = dac_cast<PTR_TypeVarTypeDesc>(ty.AsTypeDesc());
+
+ mdGenericParam token = tyvar->GetToken();
+
+ LPCSTR szName = NULL;
+ mdToken mdOwner;
+
+ IfFailThrow(ty.GetModule()->GetMDImport()->GetGenericParamProps(token, NULL, NULL, &mdOwner, NULL, &szName));
+
+ _ASSERTE(TypeFromToken(mdOwner) == mdtTypeDef || TypeFromToken(mdOwner) == mdtMethodDef);
+
+ LPCSTR szPrefix;
+ if (!(format & FormatGenericParam))
+ szPrefix = "";
+ else if (TypeFromToken(mdOwner) == mdtTypeDef)
+ szPrefix = "!";
+ else
+ szPrefix = "!!";
+
+ SmallStackSString pName(SString::Utf8, szPrefix);
+ pName.AppendUTF8(szName);
+ tnb.AddName(pName.GetUnicode());
+
+ format &= ~FormatAssembly;
+ }
+
+ // ...or function pointer
+ else if (ty.IsFnPtrType())
+ {
+ // Don't attempt to format this currently, it may trigger GC due to fixups.
+ tnb.AddName(W("(fnptr)"));
+ }
+
+ // ...otherwise it's just a plain type def or an instantiated type
+ else
+ {
+ // Get the TypeDef token and attributes
+ IMDInternalImport *pImport = ty.GetMethodTable()->GetMDImport();
+ mdTypeDef td = ty.GetCl();
+ if (IsNilToken(td)) {
+ // This type does not exist in metadata. Simply append "dynamicClass".
+ tnb.AddName(W("(dynamicClass)"));
+ }
+ else
+ {
+#ifdef _DEBUG
+ if (format & FormatDebug)
+ {
+ WCHAR wzAddress[128];
+ _snwprintf_s(wzAddress, 128, _TRUNCATE, W("(%p)"), dac_cast<TADDR>(ty.AsPtr()));
+ tnb.AddName(wzAddress);
+ }
+#endif
+ AppendNestedTypeDef(tnb, pImport, td, format);
+ }
+
+ // Append the instantiation
+ if ((format & (FormatNamespace|FormatAssembly)) && ty.HasInstantiation() && (!ty.IsGenericTypeDefinition() || bToString))
+ {
+ if (typeInstantiation.IsEmpty())
+ AppendInst(tnb, ty.GetInstantiation(), format);
+ else
+ AppendInst(tnb, typeInstantiation, format);
+ }
+ }
+
+ // Now append the assembly
+ if (format & FormatAssembly)
+ {
+ Assembly* pAssembly = ty.GetAssembly();
+ _ASSERTE(pAssembly != NULL);
+
+ StackSString pAssemblyName;
+#ifdef DACCESS_COMPILE
+ pAssemblyName.SetUTF8(pAssembly->GetSimpleName());
+#else
+ pAssembly->GetDisplayName(pAssemblyName,
+ ASM_DISPLAYF_PUBLIC_KEY_TOKEN | ASM_DISPLAYF_CONTENT_TYPE |
+ (format & FormatNoVersion ? 0 : ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE));
+#endif
+
+ tnb.AddAssemblySpec(pAssemblyName.GetUnicode());
+
+ }
+
+ END_INTERIOR_STACK_PROBE;
+
+
+ RETURN;
+}
+
+void TypeString::AppendMethod(SString& s, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format)
+{
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_TRIGGERS;
+ THROWS;
+ PRECONDITION(CheckPointer(pMD));
+ PRECONDITION(pMD->IsRestored_NoLogging());
+ PRECONDITION(s.Check());
+ }
+ CONTRACTL_END
+
+ AppendMethodImpl(s, pMD, typeInstantiation, format);
+}
+
+void TypeString::AppendMethodInternal(SString& s, MethodDesc *pMD, const DWORD format)
+{
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_TRIGGERS;
+ SUPPORTS_DAC;
+ THROWS;
+ PRECONDITION(CheckPointer(pMD));
+ PRECONDITION(pMD->IsRestored_NoLogging());
+ PRECONDITION(s.Check());
+ }
+ CONTRACTL_END
+
+ AppendMethodImpl(s, pMD, Instantiation(), format);
+}
+
+void TypeString::AppendMethodImpl(SString& ss, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format)
+{
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_TRIGGERS;
+ SUPPORTS_DAC;
+ THROWS;
+ PRECONDITION(CheckPointer(pMD));
+ PRECONDITION(pMD->IsRestored_NoLogging());
+ PRECONDITION(ss.Check());
+ }
+ CONTRACTL_END
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
+ {
+ TypeHandle th;
+
+ if (pMD->IsDynamicMethod())
+ {
+ if (pMD->IsLCGMethod())
+ {
+ SString sss(SString::Literal, "DynamicClass");
+ ss += sss;
+ }
+ else if (pMD->IsILStub())
+ {
+ SString sss(SString::Literal, ILStubResolver::GetStubClassName(pMD));
+ ss += sss;
+ }
+ }
+ else
+ {
+ th = TypeHandle(pMD->GetMethodTable());
+ AppendType(ss, th, typeInstantiation, format);
+ }
+
+ SString sss1(SString::Literal, NAMESPACE_SEPARATOR_STR);
+ ss += sss1;
+ SString sss2(SString::Utf8, pMD->GetName());
+ ss += sss2;
+
+ if (pMD->HasMethodInstantiation() && !pMD->IsGenericMethodDefinition())
+ {
+ AppendInst(ss, pMD->GetMethodInstantiation(), format);
+ }
+
+ if (format & FormatSignature)
+ {
+ // @TODO: The argument list should be formatted nicely using AppendType()
+
+ SigFormat sigFormatter(pMD, th);
+ const char* sigStr = sigFormatter.GetCStringParmsOnly();
+ SString sss(SString::Utf8, sigStr);
+ ss += sss;
+ }
+
+ if (format & FormatStubInfo) {
+ if (pMD->IsInstantiatingStub())
+ {
+ SString sss(SString::Literal, "{inst-stub}");
+ ss += sss;
+ }
+ if (pMD->IsUnboxingStub())
+ {
+ SString sss(SString::Literal, "{unbox-stub}");
+ ss += sss;
+ }
+ if (pMD->IsSharedByGenericMethodInstantiations())
+ {
+ SString sss(SString::Literal, "{method-shared}");
+ ss += sss;
+ }
+ else if (pMD->IsSharedByGenericInstantiations())
+ {
+ SString sss(SString::Literal, "{shared}");
+ ss += sss;
+ }
+ if (pMD->RequiresInstMethodTableArg())
+ {
+ SString sss(SString::Literal, "{requires-mt-arg}");
+ ss += sss;
+ }
+ if (pMD->RequiresInstMethodDescArg())
+ {
+ SString sss(SString::Literal, "{requires-mdesc-arg}");
+ ss += sss;
+ }
+ }
+ }
+ END_SO_INTOLERANT_CODE;
+}
+
+void TypeString::AppendField(SString& s, FieldDesc *pFD, Instantiation typeInstantiation, const DWORD format /* = FormatNamespace */)
+{
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_TRIGGERS;
+ THROWS;
+ PRECONDITION(CheckPointer(pFD));
+ PRECONDITION(s.Check());
+ }
+ CONTRACTL_END;
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
+ {
+ TypeHandle th(pFD->GetApproxEnclosingMethodTable());
+ AppendType(s, th, typeInstantiation, format);
+
+ s.AppendUTF8(NAMESPACE_SEPARATOR_STR);
+ s.AppendUTF8(pFD->GetName());
+ }
+ END_SO_INTOLERANT_CODE;
+}
+
+#ifdef _DEBUG
+void TypeString::AppendMethodDebug(SString& ss, MethodDesc *pMD)
+{
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_TRIGGERS;
+ NOTHROW;
+ PRECONDITION(CheckPointer(pMD));
+ PRECONDITION(pMD->IsRestored_NoLogging());
+ PRECONDITION(ss.Check());
+ }
+ CONTRACTL_END
+
+#ifndef DACCESS_COMPILE
+ EX_TRY
+ {
+ AppendMethodInternal(ss, pMD, FormatSignature | FormatNamespace);
+ }
+ EX_CATCH
+ {
+ // This function is only used as diagnostic aid in debug builds.
+ // If we run out of memory or hit some other problem,
+ // tough luck for the debugger.
+
+ // Should we set ss to Empty
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+#endif
+}
+
+void TypeString::AppendTypeDebug(SString& ss, TypeHandle t)
+{
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_NOTRIGGER;
+ NOTHROW;
+ PRECONDITION(CheckPointer(t));
+ PRECONDITION(ss.Check());
+ SO_NOT_MAINLINE;
+ }
+ CONTRACTL_END
+
+#ifndef DACCESS_COMPILE
+ {
+ EX_TRY
+ {
+ AppendType(ss, t, FormatNamespace | FormatDebug);
+ }
+ EX_CATCH
+ {
+ // This function is only used as diagnostic aid in debug builds.
+ // If we run out of memory or hit some other problem,
+ // tough luck for the debugger.
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+ }
+#endif
+}
+
+void TypeString::AppendTypeKeyDebug(SString& ss, TypeKey *pTypeKey)
+{
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_NOTRIGGER;
+ NOTHROW;
+ PRECONDITION(CheckPointer(pTypeKey));
+ PRECONDITION(ss.Check());
+ SO_NOT_MAINLINE;
+ }
+ CONTRACTL_END
+
+#ifndef DACCESS_COMPILE
+ {
+ EX_TRY
+ {
+ AppendTypeKey(ss, pTypeKey, FormatNamespace | FormatDebug);
+ }
+ EX_CATCH
+ {
+ // This function is only used as diagnostic aid in debug builds.
+ // If we run out of memory or hit some other problem,
+ // tough luck for the debugger.
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+ }
+#endif
+}
+
+#endif // _DEBUG
+
+
+void TypeString::AppendTypeKey(TypeNameBuilder& tnb, TypeKey *pTypeKey, DWORD format)
+{
+ CONTRACT_VOID
+ {
+ MODE_ANY;
+ THROWS;
+ if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
+ PRECONDITION(CheckPointer(pTypeKey));
+ SO_INTOLERANT;
+ }
+ CONTRACT_END
+
+ Module *pModule = NULL;
+
+ // It's an array, with format
+ // element_ty[] (1-d, SZARRAY)
+ // element_ty[*] (1-d, ARRAY)
+ // element_ty[,] (2-d, ARRAY) etc
+ // or a pointer (*) or byref (&)
+ CorElementType kind = pTypeKey->GetKind();
+ if (CorTypeInfo::IsModifier(kind))
+ {
+ DWORD rank = 0;
+ TypeHandle elemType = pTypeKey->GetElementType();
+ if (CorTypeInfo::IsArray(kind))
+ {
+ rank = pTypeKey->GetRank();
+ }
+
+ AppendType(tnb, elemType, Instantiation(), format);
+ AppendParamTypeQualifier(tnb, kind, rank);
+ pModule = elemType.GetModule();
+ }
+ else if (kind == ELEMENT_TYPE_VALUETYPE)
+ {
+ tnb.Append(W("VALUETYPE"));
+ TypeHandle elemType = pTypeKey->GetElementType();
+ AppendType(tnb, elemType, Instantiation(), format);
+ pModule = elemType.GetModule();
+ }
+ else if (kind == ELEMENT_TYPE_FNPTR)
+ {
+ RETURN;
+ }
+
+ // ...otherwise it's just a plain type def or an instantiated type
+ else
+ {
+ // Get the TypeDef token and attributes
+ pModule = pTypeKey->GetModule();
+ if (pModule != NULL)
+ {
+ IMDInternalImport *pImport = pModule->GetMDImport();
+ mdTypeDef td = pTypeKey->GetTypeToken();
+ _ASSERTE(!IsNilToken(td));
+
+ AppendNestedTypeDef(tnb, pImport, td, format);
+
+ // Append the instantiation
+ if ((format & (FormatNamespace|FormatAssembly)) && pTypeKey->HasInstantiation())
+ AppendInst(tnb, pTypeKey->GetInstantiation(), format);
+ }
+
+ }
+
+ // Now append the assembly
+ if (pModule != NULL && (format & FormatAssembly))
+ {
+ Assembly* pAssembly = pModule->GetAssembly();
+ _ASSERTE(pAssembly != NULL);
+
+ StackSString pAssemblyName;
+#ifdef DACCESS_COMPILE
+ pAssemblyName.SetUTF8(pAssembly->GetSimpleName());
+#else
+ pAssembly->GetDisplayName(pAssemblyName,
+ ASM_DISPLAYF_PUBLIC_KEY_TOKEN | ASM_DISPLAYF_CONTENT_TYPE |
+ (format & FormatNoVersion ? 0 : ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE));
+#endif
+ tnb.AddAssemblySpec(pAssemblyName.GetUnicode());
+ }
+
+ RETURN;
+}
+
+void TypeString::AppendTypeKey(SString& ss, TypeKey *pTypeKey, DWORD format)
+{
+ CONTRACT_VOID
+ {
+ MODE_ANY;
+ if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
+ THROWS;
+ PRECONDITION(CheckPointer(pTypeKey));
+ }
+ CONTRACT_END
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
+ {
+ TypeNameBuilder tnb(&ss);
+ AppendTypeKey(tnb, pTypeKey, format);
+ }
+ END_SO_INTOLERANT_CODE;
+
+ RETURN;
+}
+
+/*static*/
+void TypeString::EscapeSimpleTypeName(SString* ssTypeName, SString* ssEscapedTypeName)
+{
+ SString::Iterator itr = ssTypeName->Begin();
+ WCHAR c;
+ while ((c = *itr++) != W('\0'))
+ {
+ if (IsTypeNameReservedChar(c))
+ ssEscapedTypeName->Append(W("\\"));
+
+ ssEscapedTypeName->Append(c);
+ }
+}
+
+/*static*/
+bool TypeString::ContainsReservedChar(LPCWSTR pTypeName)
+{
+ CONTRACTL
+ {
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ WCHAR c;
+ while ((c = * pTypeName++) != W('\0'))
+ {
+ if (IsTypeNameReservedChar(c))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::QueryInterface(REFIID riid, void **ppUnk)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+
+ *ppUnk = 0;
+
+ if (riid == IID_IUnknown)
+ *ppUnk = (IUnknown *)this;
+ else if (riid == IID_ITypeNameBuilder)
+ *ppUnk = (ITypeNameBuilder*)this;
+ else
+ return (E_NOINTERFACE);
+
+ AddRef();
+ return S_OK;
+}
+
+ULONG __stdcall TypeNameBuilderWrapper::AddRef()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+
+ return InterlockedIncrement(&m_ref);
+}
+
+ULONG __stdcall TypeNameBuilderWrapper::Release()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ SO_TOLERANT;
+ SUPPORTS_DAC_HOST_ONLY;
+ }
+ CONTRACTL_END;
+
+ LONG ref = 0;
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+
+ ref = InterlockedDecrement(&m_ref);
+ if (ref == 0)
+ delete this;
+
+ END_SO_INTOLERANT_CODE;
+
+ return ref;
+}
+
+
+HRESULT __stdcall TypeNameBuilderWrapper::OpenGenericArguments()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.OpenGenericArguments();
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::CloseGenericArguments()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.CloseGenericArguments();
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::OpenGenericArgument()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.OpenGenericArgument();
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::CloseGenericArgument()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.CloseGenericArgument();
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::AddName(LPCWSTR szName)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.AddName(szName);
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::AddPointer()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.AddPointer();
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::AddByRef()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.AddByRef();
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::AddSzArray()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.AddSzArray();
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::AddArray(DWORD rank)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.AddArray(rank);
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::AddAssemblySpec(LPCWSTR szAssemblySpec)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.AddAssemblySpec(szAssemblySpec);
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::ToString(BSTR* pszStringRepresentation)
+{
+ WRAPPER_NO_CONTRACT;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.ToString(pszStringRepresentation);
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}
+
+HRESULT __stdcall TypeNameBuilderWrapper::Clear()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr;
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ hr = m_tnb.Clear();
+ END_SO_INTOLERANT_CODE;
+ return hr;
+}