DOCUMENT:Q264985 02-OCT-2001 [visualc] TITLE :BUG: C4305 & C4800, When VARIANT* Used as a Parameter to Event PRODUCT :Microsoft C Compiler PROD/VER::3.0,6.0 OPER/SYS: KEYWORDS:kbATL kbCOMt kbConnPts kbVC600bug kbATL300bug kbDSupport kbGrpDSMFCATL ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - Microsoft Visual C++, 32-bit Enterprise Edition, version 6.0 - Microsoft Visual C++, 32-bit Professional Edition, version 6.0 - Microsoft Visual C++, 32-bit Learning Edition, version 6.0 - The Microsoft Active Template Library (ATL) 3.0 ------------------------------------------------------------------------------- SYMPTOMS ======== The ATL Connection Point wizard generates a proxy class that implements a connection point for an outgoing interface. If an outgoing interface has an event that takes an argument of type [out]VARIANT* or [out]long*, the wizard generates incorrect code in the outgoing call (Fire_ method) for that event. The Visual C++ compiler gives the following two warnings when you call this Fire_ method in your code: warning C4305: 'argument' : truncation from 'struct tagVARIANT *' to 'bool' warning C4800: 'struct tagVARIANT *' : forcing value to bool 'true' or 'false' (performance warning) warning C4305: 'argument' : truncation from 'long *' to 'bool' warning C4800: 'long *' : forcing value to bool 'true' or 'false' (performance warning) CAUSE ===== When you use the Connection Point Wizard, incorrect code is generated in the Fire_ method for the event that takes [out]VARIANT* or [out]long* as a parameter. For Event1, with VARIANT* and long* parameters pVar and pLongVal, it generates the following code in the Fire_Event1 method of the proxy class: pvars[0] = pVar; pvars[1] = pLongVal; You receive this error because ATL-generated code directly assigns a VARIANT* and a long* to a CComVariant type. Therefore, the compiler assumes that a CComVariant overloaded operator for these data types is defined; when the compiler does not find one, it considers these values as Boolean and the warning is generated. RESOLUTION ========== The following are two workarounds for this problem: - Change the wizard-generated code from the following pvars[0] = pVar; pvars[1] = pLongVal; to the following: pvars[0].vt = VT_BYREF|VT_VARIANT; pvars[0].pvarVal = pVar; pvars[1].vt = VT_BYREF|VT_I4; pvars[1].plVal = pLongVal; The drawback of this approach is that every time that you add a method to your connection point interface and ask the wizard to implement the connection points, the earlier changes that you made will be overwritten and you will lose your changes. Make sure you back up your changes before allowing the wizard to implement the interface. - Modify the CComVariant class in the AtlBase.h file, and provide overloaded "=" operators for VARIANT* and long*. A sample implementation might resemble the following: CComVariant& operator=(long* nSrc) { if (vt != VT_I4) { InternalClear(); vt = VT_BYREF|VT_I4; } plVal = nSrc; return *this; } CComVariant& operator=(const VARIANT* nSrc) { InternalCopy(nSrc); return *this; } Make these modifications to a copy of the AtlBase.h file (for instance, FixAtlBase.h). Then, in Stdafx.h, comment out AtlBase.h and use FixAtlBase.h instead, as follows: // #include #include "FixAtlBase.h" This technique works only in Debug or ReleaseMinDependency builds. This technique does not work in ReleaseMinSize builds because the ATL.dll file is used, not the code in FixAtlBase.h. STATUS ====== Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. MORE INFORMATION ================ Steps to Reproduce Behavior --------------------------- 1. Create a new ATL DLL/EXE project. 2. Insert a simple object with connection point support. 3. Add a method named Event1 to the source(event) interface that takes a VARIANT* and long* as [out] parameters. 4. Compile the project. 5. Right-click the ATL class and click Implement Connection Point to start the Connection Point Wizard. 6. Select the event interface, and then click OK. 7. Create a test method on the ATL object's incoming interface with VARIANT as a parameter, and call it "Fire_Event1". STDMETHODIMP CTestQ::Test(VARIANT* pVar, long* pLong) { Fire_Event1(pVar,pLong); return S_OK; } 8. Compile your application to see the warnings C4305 and C4800. REFERENCES ========== For more information, see the "Adding Connection Points to an ATL Object" topic on the Microsoft Developer Network (MSDN) Web site: http://msdn.microsoft.com/library/devprods/vs6/visualc/vcmfc/_atl_adding_connection_points_to_an_object.htm For additional information, click the article number below to view the article in the Microsoft Knowledge Base: Q250847 ATL Connection Point Wizard Generated Code for Event with VARIANT Argument Gives C4305 Warning Additional query words: event VARIANT C4305 C4800 ====================================================================== Keywords : kbATL kbCOMt kbConnPts kbVC600bug kbATL300bug kbDSupport kbGrpDSMFCATL Technology : kbVCsearch kbAudDeveloper kbATLsearch kbATL300 kbVC600 kbVC32bitSearch Version : :3.0,6.0 Issue type : kbbug Solution Type : kbpending ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 2001.