Have I found a bug in Clang and GCC? - c++

main.cpp:
#include <iostream>
struct Cls {
static void some_method() {
std::cout << __FILE__ << ": " << __LINE__ << std::endl;
}
};
extern void call_some_method();
void never_caled() {
Cls::some_method(); // (1)
}
int main() {
call_some_method();
return 0;
}
cls.cpp:
#include <iostream>
struct Cls {
static void some_method() {
std::cout << __FILE__ << ": " << __LINE__ << std::endl;
}
};
void call_some_method() {
Cls::some_method();
}
When (1) is commented, call_some_method() write "/home/maxim/CLionProjects/bug/cls.cpp: 5" to std::cout.
When (1) is uncommented, call_some_method() write "/home/maxim/CLionProjects/bug/main.cpp: 5" to std::cout.
How it can be possible for different outputs?

__FILE__ and __LINE__ are macros that are expanded by the pre-processor. Since those macros are in different files, and depend on the files they are used in, they expand to different token sequences.
That means that your definition of Cls::some_method is different across different translation units. This violates the one-definition-rule (ODR) which requires, among other things, that there be exactly one definition of a particular entity in your entire program. If there are multiple definitions, that's fine, so long as the token sequence of those definitions is identical in every translation unit, and those tokens mean the same thing when they are parsed.
This is obviously not true in your case, so you are violating the ODR, which makes the program ill-formed (No Diagnosis Required). This means the compiler is not obliged to give you an error, but if it does produce a program, executing that program invokes undefined behavior (UB). So your program could do anything at all, including producing the output that you are seeing.

Related

#ifdef is returning different values inside the same header file

I have two C++ files main.cpp and client.cpp, and a header file action.h. I am trying to mimic a simple client-server scenario using preprocessor directives. The code is as follows:
//main.cpp
#include "action.h"
extern void connect();
static Action server;
int main()
{
server.init();
connect();
server.execute();
return 0;
}
//client.cpp
#define CLIENT
#include "action.h"
void connect()
{
Action client;
client.init();
client.execute();
}
And the header file.
#include <iostream>
struct Action
{
#ifdef CLIENT
int data = 10;
#else
int data = 13;
#endif
inline void init()
{
#ifdef CLIENT
std::cout << "Client " << data << std::endl;
data = -1;
#else
std::cout << "Server " << data << std::endl;
data = 0;
#endif
}
inline void execute()
{
#ifdef CLIENT
std::cout << "Server is " << data << std::endl;
#else
std::cout << "Number of clients is " << data << std::endl;
#endif
}
};
When I run this, I get the following result:
Server 13
Server 10
Number of clients is 0
Number of clients is 0
Now my question is why is the #ifdef CLIENT block executing in the declaration section of action.h (int data = 10) while the #else block is executing inside the init() and execute() functions when I call them from client.cpp file? Why are not all three calls going to the #ifdef part?
This program exhibits undefined behavior. It violates the One Definition Rule (ODR). Specifically this part:
[basic.def.odr]/6 There can be more than one definition of a class type, ... inline function with external linkage ... in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then
(6.1) — each definition of D shall consist of the same sequence of tokens...
...
If the definitions of D do not satisfy these requirements, then the behavior is undefined.
In your case, you have two definitions of class Action as well as its inline member functions Action::init and Action::execute, that consist of different sequence of tokens, thanks to macro trickery.

Pre-processor parsing on C++

If we want to use user input to do something in a program, or print a result we need to
#include <iostream>
otherwise, cout and cin will not be acknowledged by the compiler.However the command #include is a pre-processor command. And when I was writing my program the following happened. I wrote the following code :
#define PRINT_DEBUG_INFO(a) {cout << “Info: ” << a << endl;}
#include <iostream>
And no errors popped up.How is it possible to use cout before including iostream? Even if I declare the PRINT_DEBUG_INFO(a) without including iostream, I don't get a compiling error.
Can somebody explain me why this happens?
The preprocessor doesn't require any C++ declared symbols to be evaluated to do its work.
It's pure text processing, so defining a macro like
#define PRINT_DEBUG_INFO(a) {cout << “Info: ” << a << endl;}
and expanding it like
#include <iostream>
void foo {
int a = 5;
PRINT_DEBUG_INFO(a);
}
will become
// All the literal stuff appearing in <iostream>
void foo {
int a = 5;
{cout << “Info: ” << a << endl;};
}
So there's nothing checked regarding proper C++ syntax during definition or expansion of the macro.
These statements will be processed further by the C++ compiler, which will complain about cout isn't declared in the global scope.
To fix this, declare your macro like
#define PRINT_DEBUG_INFO(a) {std::cout << “Info: ” << a << std::endl;}
You define PRINT_DEBUG_INFO but you don't use it so there is nothing for the compiler to compile or complain about.
You are just defining PRINT_DEBUG_INFO(a) and not using it. When you actually use it inside your program you will get the error that cout is not defined.
When you are not actually using it, the compiler finds no place to substitute the defined constant. When you actually use it, the program gets expanded during compilation and shows you the error.
And moreover there is a bracket in your macro which gets expanded with brackets and may lead to error.

One Definition Rule - Multiple definition of inline functions

I was reading ODR and as the rule says "In the entire program, an object or non-inline function cannot have more than one definition" and I tried the following...
file1.cpp
#include <iostream>
using namespace std;
inline int func1(void){ return 5; }
inline int func2(void){ return 6; }
inline int func3(void){ return 7; }
int sum(void);
int main(int argc, char *argv[])
{
cout << func1() << endl;
cout << func2() << endl;
cout << func3() << endl;
cout << sum() << endl;
return 0;
}
file2.cpp
inline int func1(void) { return 5; }
inline int func2(void) { return 6; }
inline int func3(void) { return 7; }
int sum(void) { return func1() + func2() + func3(); }
It worked as the rule says. I can have multiple definition of inline functions.
What is the difference between non-inline function linkage and inline function linkage?
How the linker differentiate between these two?
Making a function inline does two things (the second point is more relevant to your question):
It is a suggestion by the programmer to the compiler, to make calls to this function fast, possibly by doing inline expansion. Roughly, inline expansion is similar to treating the inline function like a macro, expanding each call to it, by the code of its body. This is a suggestion - the compiler may not (and sometimes cannot) perform various optimizations like that.
It specifies the scope of the function to be that of a translation unit. So, if an inline function appears in foo.cpp (either because it was written in it, or because it #includes a header in which it was written, in which case the preprocessor basically makes it so). Now you compile foo.cpp, and possibly also some other bar.cpp which also contains an inline function with the same signature (possibly the exact same one; probably due to both #includeing the same header). When the linker links the two object files, it will not be considered a violation of the ODR, as the inline directive made each copy of the file local to its translation unit (the object file created by compiling it, effectively). This is not a suggestion, it is binding.
It is not coincidental that these two things go together. The most common case is for an inline function to appear in a header #included by several source files, probably because the programmer wanted to request fast inline expansion. This requires the translation-unit locality rule, though, so that linker errors shouldn't arise.

C++ macro to get full function path and declaration

I want to get full function path and declaration in code via macro or some compiler magic. I have this code (click here to run):
#include <iostream>
namespace NS {
struct Foo {
static int sum(int a, int b) {
std::cout << "This is from " << __FILE__ << ":" << __LINE__ << " # " << __func__ << std::endl;
return a+b;
}
static int sum(int a, int b, int c) {
std::cout << "This is from " << __FILE__ << ":" << __LINE__ << " # " << __func__ << std::endl;
return a+b+c;
}
};
}
int main() {
NS::Foo::sum(1,2);
NS::Foo::sum(1,2, 3);
}
And I get the output:
This is from /some/where/main.cpp:7 # sum
This is from /some/where/main.cpp:12 # sum
My questions are:
How do I get the full path of sum function invoked?(NS::Foo::sum)
How can I get the full function declaration with argument types?( sum(int, int) or sum(int, int, int))
I am interested in mainstream compilers: Clang, GCC, Microsoft C++ compiler
Answering for GCC.
Checkout the __PRETTY_FUNCTION__ macro. I've found it in the defintion of assert macro in <assert.h>. Perhaps same could be found for other compilers and libc implementations.
For Microsoft Visual Studio compiler, __FUNCSIG__ can give you a lot about the function.
__FUNCSIG__ will give you full function signature
__FUNCDNAME__ gives magnled name.
__FUNCTION__ is just for function name.
If you don't want to limit yourself to a single compiler, and don't fancy writing a pre-processor ifdef chain yourself, boost has already defined a macro BOOST_CURRENT_FUNCTION which is defined as the full function signature macro that's defined on the used compiler. __PRETTY_FUNCTION__ in gcc and other compilers that support that, __FUNCSIG__ where that is supported (msvc), also supports some lesser used compilers and falls back to __func__ as defined by the C standard (or a static placeholder if even that's not supported).

#define directives not working outside main() function

I just started learning C++ today. With previous knowledge in other languages I am doing fine so far, but I am confused about #define directives.
I have this code in my "review" C++ file:
#include <iostream>
#define TEST //object-like macro
#ifdef TEST //if TEST is defined
std::cout << "This works!" << std::endl;
#endif
#ifndef NOT_TEST //if NOT_TEST is NOT defined
std::wcout << "This also works!" << std::endl;
#endif
int main()
{
//program code
}
The above code produces errors, first one being syntax error : mssing ';' before '<<'. When I move the #define/#if directives into the main loop, it works properly:
#include <iostream>
int main()
{
#define TEST //object-like macro
#ifdef TEST //if TEST is defined
std::cout << "This works!" << std::endl;
#endif
#ifndef NOT_TEST //if NOT_TEST is NOT defined
std::wcout << "This also works!" << std::endl;
#endif
}
What about the first block of code is incorrect? based on the tutorial I am using, I thought that was how it was supposed to be formatted?
EDIT: I've updated my code to be more clear.
This has nothing to do with formatting. In fact, C++ files are formatting-agnostic. The problem is that after the pre-processor parses your file, you end up with 2 cout statements outside the main function. In C++ you cannot have standalone statements outside of a function, except for declarations/definitions.
You should understand that compilation of a C++ program is a two-step process. First the preproccessor is executed that transforms the file according to instructions you gave it (those that start with #). Then the C++ compiler is executed on the resulting file.
The “code relating to the preprocessor” here is just the #ifdef/#ifndef (with the condition that follows it immediately) and #endif keywords and, indeed, you can put those wherever you like, since preprocessor doesn’t care about C++ syntax, it performs straightforward string operations.
When the preprocessor runs it plugs your C++ code between #ifdef and #endif into the file, so the effect is the same as if you just had the cout << … line (outside the main function).
So, since TEST is defined and NOT_TEST is not, after the preprocessor did its job you are left with a file that has just two lines:
std::cout << "This works!" << std::endl;
std::wcout << "This also works!" << std::endl;
If you try to compile it, you’ll see that the compiler is not happy, because that’s, obviously, not a valid C++ program.
The Problem is using of cout << out of main function.
If you wanna have any output line you can use #error directive to abort compilation process.