Bug 587128 - Apparent gcc 4.4.3 miscompilation
Summary: Apparent gcc 4.4.3 miscompilation
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Fedora
Classification: Fedora
Component: gcc
Version: 12
Hardware: All
OS: Linux
low
medium
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2010-04-29 01:34 UTC by Sam Varshavchik
Modified: 2010-04-29 09:02 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2010-04-29 09:02:34 UTC
Type: ---


Attachments (Terms of Use)

Description Sam Varshavchik 2010-04-29 01:34:19 UTC
Description of problem:

Looks like gcc might be miscompiling code that uses the XOR hack of swapping two integer values.

Version-Release number of selected component (if applicable):

gcc-4.4.3-4.fc12.i686

How reproducible:

#include <iostream>

struct A {

	size_t x1, y1, x2, y2;

	void foo(size_t &row1, size_t &row2,
		 size_t &pos1, size_t &pos2);
};

void A::foo(size_t &row1, size_t &row2,
	    size_t &pos1, size_t &pos2)
{
	row1=y1;
	row2=y2;
	pos1=x1;
	pos2=x2;

	if (row2 < row1 || (row2 == row1 && pos2 < pos1))
	{
                // Swap the coordinate pairs

		row1 ^= row2 ^= row1 ^= row2;
		pos1 ^= pos2 ^= pos1 ^= pos2;
	}
}

int main()
{
	A aa;

	aa.y1=5;
	aa.x1=1;
	aa.y2=0;
	aa.x2=2;

	size_t row1, row2, col1, col2;

	aa.foo(row1, row2, col1, col2);

	std::cout << "row1=" << row1 << ", col1=" << col1
		  << ", row2=" << row2 << ", col2=" << col2 << std::endl;

	return (0);
}

Steps to Reproduce:
1. Compile the above code: g++ -o /tmp/t /tmp/t.C
2.
3.
  
Actual results:

$ /tmp/t
row1=0, col1=0, row2=5, col2=1

Expected results:

$ /tmp/t
row1=0, col1=2, row2=5, col2=1

Additional info:

The sequence "a ^= b ^= a ^= b" is a hack which essentially swaps the values of a and b. Example:

Starting values: a=1, b=2

After a ^= b:  a=3, b=2

After b ^= a ^= b: a=3, b=1

After a ^= b ^= a ^= b: a=2, b=1

The above example is a snippet of code that takes a pair of two-dimensional (x, y) coordinates, and returns the "lowest" (x, y) pair and the highest pair.

Looks like a struct/class, and a function call passing return values by reference are a necessary ingredient to trigger the miscompilation.

Comment 1 Jakub Jelinek 2010-04-29 09:02:34 UTC
row1 ^= row2 ^= row1 ^= row2;
has undefined behavior in both C and C++, and even -Wsequence-point (part of -Wall) warns about it.


Note You need to log in before you can comment on or make changes to this bug.