Visual C++ Compiler Error C2338

Message Text

text

Circumstances (External)

This error serves mainly as a placeholder for errors generated externally to the compiler. The message text is entirely in the hands of the external component, which is why it is shown simply as text above. For this mechanism to be useful, the text would describe the error in some detail, perhaps even with its own scheme of error numbers.

The external component will be an attribute provider DLL, such as ATLPROV. Indeed, since Microsoft does not document how to write attribute providers, ATLPROV is in practice the only cause of externally generated C2338 errors.

ATL Errors

All ATL errors generated by ATLPROV feed back to the compiler as C2338. The complete error message is:

position : error C2338: attribute
        Atl Attribute Provider : error ATLnumber: message

where position (the file name and line number) is generated by the compiler, as usual, but everything from attribute onwards is from ATLPROV, including most notably the ATL error number and message text.

Circumstances (Internal)

Three cases exist in which the compiler may itself raise error C2338, with the compiler’s own message text.

Boxing by Dynamic Cast

The history is not known, but it seems that the cloning of a value type into a managed object may once upon a time have been done by casting, perhaps before (and prompting) invention of the __box keyword. In this case of an internally generated C2338, the message text is

deprecated use of dynamic_cast: use __box instead to box a value type

To see this admittedly obscure (and certainly undocumented) error, compile the following with the /clr option:

#using  <mscorlib.dll>
using namespace System;

Object *box (int x)
{
    return dynamic_cast <Object *> (x);         // C2338
}

Bad Input to the Attribute Provider Provider

The other cases of internally generated C2338 both arise from misuse of the attribute provider provider (ProvProv). This special attribute provider is implemented within the compiler to help other attribute providers define their own attributes, most notably to standardise the grammar.

Bad Group Attribute

Error C2338 occurs with the message text

'group': incorrect format for attribute 'group'

when the group given as the value of the group attribute is not one of:

eComGroup, eCompilerGroup, eComPlusMetaDataGroup, eControlGroup, eCPlusPlusGroup, eDBConsumerGroup, eDBProviderGroup, eDebugGroup, eDHTMLGroup, eHPS, eIDLGroup, eInterfaceGroup, eModuleGroup, eRegistryGroup, eStockPMEGroup, eUserDefinedGroup or eWindowGroup

Because this validation is performed as part of ProvProv’s parsing of the group attribute, this case of error C2338 does not require real-world use of the ProvProv attributes, just that they be activated and that the group attribute be given with an invalid value. Even the following suffices:

[
    provider ("ProvProv", "6462678A-83F5-11D2-B8DA-00C04F799BBB")
];

[
    group = rubbish
];                              // C2338 and (most likely) C1903

Bad Usage Attribute

Error C2338 occurs with the message text

'usage': incorrect format for attribute 'usage'

when the usage given as the value of the usage attribute is not one of the following or a bit-wise OR of more than one:

eAnonymousUsage, eAnyIDLUsage, eAnyUsage, eAsynchronousUsage, eClassUsage, eCoClassMemberUsage, eCoClassMethodUsage, eCoClassUsage, eCOMInterfaceUsage, eDefineTagUsage, eEnumUsage, eEventUsage, eGlobalDataUsage, eGlobalMethodUsage, eIDLModuleUsage, eIllegalUsage, eInterfaceUsage, eInterfaceMethodUsage, eInterfaceParameterUsage, eLocalUsage, eMemberUsage, eMethodParameterUsage, eMethodUsage, eModuleUsage, ePropertyUsage, eStructUsage, eTemplateUsage, eTypedefUsage, or eUnionUsage

However, this validation is not performed unless ProvProv injects code for the GetAttributeList method of the IAttributeGrammar interface. Such injection is attempted only in response to the implement_grammar attribute and requires source code that is at least suggestive of real-world use. For a roughly minimal example, create empty header files named

and compile

[
    provider ("ProvProv", "6462678A-83F5-11D2-B8DA-00C04F799BBB"),
];

[
    provider_name = {"test", "00000000-0000-0000-0000-000000000000"},
    implement_grammar
]
class Test
{
    [
        define_attribute = "rubbish",
        usage = rubbish
    ];
}                               // C2338 and (most likely) C1903

Coding Error

Note that in both the group and usage cases, error C2338 is most likely followed by fatal error C1903. This is no orderly exit. It is instead the most likely outcome of a coding error in the compiler. The code that asks for error C2338 assumes there will be no return, as if C2338 were fatal. Since there is a return, the compiler soon executes whatever code happens to follow in memory. The best and most likely outcome is a CPU fault, such as would ordinarily be presented as an internal compiler error (C1001), but is presented instead as C1903 because of the previous error. To let the CPU exception escape the compiler for easy viewing, add the /Bd option when compiling the examples.