Incorrect Warning C4267 - by Steve Youngs

Status : 

  Won't Fix<br /><br />
		Due to several factors the product team decided to focus its efforts on other items.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.


0
0
Sign in
to vote
ID 253172 Comments
Status Closed Workarounds
Type Bug Repros 0
Opened 1/22/2007 2:32:39 AM
Access Restriction Public

Description

Compiling the attached code yields 

 warning C4267: '=' : conversion from 'size_t' to 'std::_Vbase', possible loss of data

for the code 	

Nbisloc[li] = b0; 

I do not believe that this is correct. 
This causes issues for us as we have /WX specified. 

Is the code generation correct?
Sign in to post a comment.
Posted by Microsoft on 1/26/2007 at 3:48 PM
I forgot that my E-mail address isn't automatically displayed. If you have further questions, feel free to contact me at stl@microsoft.com .

Stephan T. Lavavej
VC++ Libraries Team
Posted by Microsoft on 1/26/2007 at 3:43 PM
Hi,

This is an example of how /Wp64 interacts badly with templates. The /Wp64 warnings rely on the presence of the __w64 qualifier, which indicates that a type is 32 bits on 32-bit systems but will become 64 bits on 64-bit systems.

To /Wp64, unsigned int and __w64 unsigned int are different types: if you assign an unsigned int to an unsigned int, that's fine, but if you assign a __w64 unsigned int to an unsigned int, a warning is triggered under /Wp64.

To template instantiation, unsigned int and __w64 unsigned int are identical types. X<unsigned int> and X<__w64 unsigned int> refer to the same type (you can see this with explicit specialization easily). This is true whether or not /Wp64 is enabled.

The problem occurs when /Wp64 is enabled in the presence of templates which involve __w64-qualified types. When a template is instantiated with __w64 T, all occurrences of that T in the template are treated as __w64, even if that instantiation is later referred to with X<T> (without __w64-qualification). Conversely, when a template is instantiated with T, all occurrences of that T in the template are treated as __w64-unqualified, even if that instantiation is later referred to with X<__w64 T>. This behavior of the first instantiation of a template "stamping" the __w64 property (or not) on that instantiation is highly unintuitive and causes these sorts of problems.

In your example, instantiating vector<bool> (through TArray1<bool>) causes a vector<unsigned int> to be instantiated; this is the backing store of vector<bool>, and the unsigned int is referred to as std::_Vbase. Now, vector<unsigned int> has been "stamped" with the absence of __w64. Later, using vector<size_t> (through TArray1<size_t>) refers to vector<__w64 unsigned int>, which has been instantiated as vector<unsigned int>. When you assign a size_t to Nbisloc[li], you are assigning a __w64 unsigned int (b0's type) to an unsigned int (because the vector was instantiated that way), and the warning fires. This behavior is undesirable.

The solution is actually simple: avoid /Wp64 when compiling 32-bit code. Instead, compiling your code under the 64-bit compiler will catch all of the issues that /Wp64 attempts to catch, and more, without generating spurious warnings.

Thank you for taking the time to report this issue.

Stephan T. Lavavej
VC++ Libraries Team
Posted by Steve Youngs on 1/22/2007 at 2:34 AM
If the line of code

TArray1<bool> btt;

in the example is commented out the the code compiles without warning.