Embedded conditionals not being evaluated correctly?

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.

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.

The real code is part of a unit testing code base that I have. I have identified an workaround that seems
to let both clang and gcc produce the same test results but something does not sit right with that
solution.

Thanks for any help or comments.

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

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.

Sorry for the light details. I could point you to my actual code base (but it does need a few support libraries built first which I have repos for and is all CMake based). I have spent all morning trying to figure out what is happening and the runtime issues seem to jump around but are all related to this same type of problem.

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

I _thought_ I noticed that if I instead did thins like "if (false == (true == someexpression()) )" would then exhibit the correct behavior but when I changed the code back and recompiled the error jumped to another line. Is there an intermediate form that I could print out that is human readable so someone could verify what _should_ be happening? My project is known to compile with GCC 4.2 (Apple), VS 2008 (32 and 64 bit) and GCC 4.4 from Ubuntu 10.04 and produces the same test results under all the compilers in question.

Thanks
Mike Jackson

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

Even more information and questions:
   Would library bounds or multiple inheritance have anything to do with it? Those are the only differences between my test code (which does run properly) and my actual project code (which does _not_ run properly).
   I inserted a fake class into the actual projects test code and the code runs properly. This fake class does not inherit from any other class and is defined in the same file as the test (so no library bounds).

Yes, you can use -S -emit-llvm on your command line to get LLVM IR. It's a fairly readable intermediate representation.

  - Doug