Bug 103067 - Tautological compare warning not appearing if the self-comparison is on object members
Summary: Tautological compare warning not appearing if the self-comparison is on objec...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 11.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wtautological-compare
  Show dependency treegraph
 
Reported: 2021-11-03 17:56 UTC by crillion
Modified: 2022-05-16 01:27 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-11-03 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description crillion 2021-11-03 17:56:49 UTC
Hi,

   I've found that on gcc 11.2 (tested on windows 10, with msys2), and compiling with :

g++ -std=c++20 -pedantic -Wall -Wextra -Werror=return-type -Wshadow=local -Wempty-body -fdiagnostics-color -s -Os program.cpp -o program_gpp.exe  -LC:/programs/msys64/mingw64/lib

(I have also tried adding -Wtautological-compare but with the same effect described below).

 if I have a code with a struct person that in operator== erroneously compares one of its members, of an object type, with itself as in the following example :

// this is a struct for field members, here comparison is implemented correctly
struct object_member
{
	int a = 20;
	bool operator==(const m& rhs) const
	{
		return a == rhs.a;
	}
};

// this struct has the error in the operator==
struct person
{	
	bool operator==(const person& rhs) const
	{
            // comparing this instance member with itself!
	    return age == age; // instead of age == rhs.age
	}
	
	object_member age;
};

int main()
{
	person p1, p2;
	if(p1 == p2) std::cout << "equal!\n";
}

I don't get the tautological compare warning. The behavior seems to occur only with struct/class types (also with string and optional), but not with primitive numeric types (i.e. : if age is an int, I get normally the tautological-compare warning. It occurs also if the expression is in AND with other correct comparisons. The causing part seems to be an operator== involving an object member (struct, class) compared with itself.

In case of a single member I get instead the warning "rhs parameter not used", but if I add to the struct and comparison another field (ex.: int a), comparing it correctly, no warning shows at all:

(...)
operator==(const person& rhs)
{
    return a == rhs.a && age == age;
}

(...)
int a = 0;
object_member age;
(...)

Is this correct ? or should I get this important warning also if the member is an object ?

Note : I see clang 11.0 does not issue the warning either.

Thanks,

    Marco
Comment 1 crillion 2021-11-03 18:04:34 UTC
in object_member the comparison operator signature is

bool operator==(const object_member& rhs) const
Comment 2 Jonathan Wakely 2021-11-03 18:06:27 UTC
This is "correct" in that each function is compiled in isolation, and within the body of the function you are comparing two different objects, this->a and rhs.a

The fact that rhs and *this actually alias each other **in your specific example** is not visible when compiling that function (and is not always going to be true for other alls to the function).

You'll get just the same for something like:

bool f(int& i, int& j) { return i == j; }
int i = 0;
bool b = f(i, i);
Comment 3 Jonathan Wakely 2021-11-03 20:11:06 UTC
The warning could be smarter and assume that operator== has the usual semantics, and therefore 'age == age' would warn, even though *in theory* the operator== could do something meaningful when called like that. But in practice, warning would be helpful a lot more often than anybody writes weird operator== definitions where 'age == age' is actually what the developer meant to write. 99.999% of operator== functions do what you expect, and so 'age == age' is probably a mistake and should warn.

Related to that, it would be nice if calls to operator== functions also gave -Wunused-value warnings, like the built-in == for scalars. Again, 99.999% of operator== functions have no side effects and are only called for the result, so if it's unused, the compiler should warn.