Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7944 Discussions

Conditional compilation bug or feature ?

emmanuel_attia
Beginner
431 Views

Hi,

I have a software that has 2 versions of an implemented algorithm, so it used different versions of the same class (in my case its SSE vs AVX, but really, it's not relevant) in 2 different compiler units, and suprisingly the linker take the initiative of taking an arbitrary one.

Is it a bug (that I reproduced as well in Microsoft and GCC compiler) or a feature (if that so can someone help me finding where this behavior is specified) ?

Here is how to reproduce the problem:

toto.h

#include <stdio.h>

#ifdef FLAG
class foo
{
public:
    void bar()
    {
        printf("FLAG\n");
    }
};
#else
class foo
{
public:
    void bar()
    {
        printf("NO FLAG\n");
    }
};
#endif

#ifdef FLAG
void call_foobar_FLAG()
#else
void call_foobar_NOFLAG()
#endif
{
    foo().bar();
}

toto_flag.cpp

#define FLAG
#include "toto.h"

toto_noflag.cpp

#include "toto.h"


main.cpp

void call_foobar_FLAG();
void call_foobar_NOFLAG();

int main(int argc, char ** argv)
{
    call_foobar_FLAG();
    call_foobar_NOFLAG();
}

We should expect as output

FLAG
NO FLAG

But we get

FLAG
FLAG

or

NO FLAG
NO FLAG


depending in which order object are linked...

0 Kudos
5 Replies
jimdempseyatthecove
Honored Contributor III
431 Views

FLAG may be #defined in (by) stdio.h

Also, you may have enabled pre-compiled headers.

Jim Dempsey

0 Kudos
emmanuel_attia
Beginner
431 Views

Ok rename FLAG with RANDOM34834626723, <stdio.h> is here just for the printf to work in this reproductible example.

You would have the same result.

And no i did not enabled precompiled headers (nor optimizations, nor /Qip or /Qipo or global optimization or anything that could do some "magic" across objs)

Actually

gcc main.cpp toto_noflag.cpp toto_flag.cpp && a.exe

silently outputs NO FLAG twice

gcc main.cpp toto_flag.cpp toto_noflag.cpp && a.exe

silently outputs FLAG twice

So it's even not specific to Intel if this is a bug.

0 Kudos
Judith_W_Intel
Employee
431 Views

 

You are violating the ODR (One Definition Rule) so the implementation is allowed to do anything it wants.

See:

http://en.wikipedia.org/wiki/One_Definition_Rule

and section 3.2 of the C++ standard.

 

Judy

 

 

0 Kudos
emmanuel_attia
Beginner
431 Views

Thank you Judith, I understand now why what I did was completely non-standard.

I solved my issues by enclosing it in anonymous namespaces, which seems the proper way to do.

0 Kudos
emmanuel_attia
Beginner
431 Views

Hi Judith,

This ODR raises another problem.

If I have a project mixing a file compiled with /QxAVX and another one with any other architecture selection (for instance /QxSSE), if both for instance use a STL class like std::basic_string. Then in both translation unit will share the same std::basic_string and have AVX code into it.

And unfortunately in Intel Compiler there is no flag to activate AVX (in the way that the instrinsic are translated into VEX instructions) without having these injection of AVX code where its not needed (and which prevents the use of classes, that I cannot put in an anonymous namespace, between compilands targeted for different architectures).

Best Regards,

Emmanuel

0 Kudos
Reply