[cfe-dev] Embedded conditionals not being evaluated correctly?
Michael Jackson
mike.jackson at bluequartz.net
Thu Jul 29 10:30:44 PDT 2010
On Jul 29, 2010, at 1:03 PM, Douglas Gregor wrote:
>
> On Jul 29, 2010, at 9:03 AM, Michael Jackson wrote:
>
>> I have code that looks something like this:
>>
>>
>> bool evaluate(int i, int j) { return (i < j) ? true : false; }
>>
>> void function()
>> {
>> int i = 0;
>> int j = 1;
>> if ( evaluate(i, j) == true ) { }
>> else { std::cout << "This is BAD" << std::endl; }
>>
>> }
>>
>> when I compile this code with clang (latest SVN head) and then run
>> it I will get
>> the "This is BAD" printed out which is obviously NOT correct. If I
>> change the code
>> to introduce an intermediate variable:
>>
>> bool b = evaluate(i,j);
>> if ( b == true ) { }
>> else { std::cout << "This is BAD" << std::endl; }
>>
>> this this compiles and runs just fine.
>>
>> The fun part in all of this is that I am unable to create a small
>> reproducible test case
>> for a bug report. I have used the OS X 10.6 gdb to debug through
>> the code and verify what
>> should really be going on and that the executable is NOT matching
>> what should be happening.
>>
>> If I compile my code with GCC then I get the expected results.
>
> Unfortunately, that's not much for us to go on, since we don't know
> the code in question. It may not even be a Clang bug, if there's
> undefined behavior or order-of-evaluation issues involved.
>
>> My question is simple: Are there known or questionable issues with
>> clang++ and nested conditionals
>> that evaluate to C++ bool? I did some searches through the clang
>> bugzilla but did not identify my problems.
>
>
> Does the actual condition involve temporary objects? The most likely
> culprit would be our handling of temporaries, e.g., that we destroy
> a temporary too soon, forget to destroy a temporary that matters, or
> perform some kind of unsanctioned copy.
>
> - Doug
Just some more info on this. I have the following code:
MXA_REQUIRE(metaData->isValid(errorMessage) == false);
where MXA_REQUIRE is a macro:
#define MXA_REQUIRE( P ) \
if ( (P) == false) \
{MXA_TEST_THROW_EXCEPTION( #P)}
when the above is fully expanded it gives:
if ( (metaData->isValid(errorMessage) == false) == false)
{throw TestException( "metaData->isValid(errorMessage) == false",
"/Users/mjackson/Workspace/MXADataModel/Tests/DataModelTest.cpp", 81);
}
So I placed the following code in my program (Not the line numbers)
1: bool b = metaData->isValid(errorMessage);
2: std::cout << "b: " << (int)b << std::endl;
3: if ( (metaData->isValid(errorMessage) == false) == false)
4: {
5: throw TestException( "metaData->isValid(errorMessage) ==
false",
6: "/Users/mjackson/Workspace/MXADataModel/Tests/
DataModelTest.cpp", 81);
7: }
and I get the following output:
b: 0
TestRequiredMetaData() FAILED
Reason: metaData->isValid(errorMessage) == false
File: /Users/mjackson/Workspace/MXADataModel/Tests/
DataModelTest.cpp
Line: 81
Which means that variable "b" evaluated correctly to "false" in line
1. In line 3 something goes wrong and we get the following:
if (( true == false) == false) which then triggers the exception to
be thrown which is INCORRECT.
If I change line 3 to be:
3: f ( (b == false) == false)
then I get the "correct" result. So Doug's ideas are probably
correct. The issue I am still having is getting this down to a
reproducible test case.
Thanks
Mike Jackson
More information about the cfe-dev
mailing list