g++ integer to to string assignment without an error/warning - gcc

The following code compiles without any warning or error on G++ (GCC) 4.1.2.
Is there a reason for not issuing an error/warning?
Is there a flag that can cause it to issue a warning or error?
#include <iostream>
using namespace std;
void func(string &s)
{
unsigned long u = 123;
s = u;
}
int main()
{
string s;
func (s);
return 0;
}

The reason there's no warning or error is because this is valid C++. std::string overloads the assignment operator (operator=) to take a char. long can be implicitly converted to a char, hence the code makes sense.

Related

compiler error assigning a new pair<T> object to an existing pair<T> object

The following code produces an error in C++Builder XE7, using the 32-bit compiler:
#include <utility>
#include <boost/any.hpp>
std::pair< int, boost::any > y;
void test()
{
y = std::pair< int, boost::any >( 1, 2 ); // error!
}
The error is:
"Could not find a match for 'operator std::pair<int,boost::any>::=(std::pair<int,boost::any>)'"
I don't get it. There is nothing inherently wrong with this code, and it compiles just fine in (much) older compilers. Now here are the interesting bits:
1) The 64-bit compiler compiles the code without error
2) If I change the pair's second type from 'boost::any' to a built-in type, such as 'int', the code compiles without error
As a work-around, I was able to do this:
#include <utility>
#include <boost/any.hpp>
std::pair< int, boost::any > y;
void test()
{
std::pair< int, boost::any > temp = std::pair< int, boost::any >( 1, 2 );
y = temp;
}
It's less efficient, but it gets me around the compiler error.
Until recently, I had been using antiquated C++ compilers (C++Builder 5/6), so I have not kept up-to-date with the C++ standards and the changes for C++11. Therefore, I might be unaware of a language change that makes this code invalid. So, can someone please tell me if this compiler error is a result of a language change, or is it a compiler bug?
Thanks,
Dennis

How to enable the _Generic keyword

I have this test source:
#include <stdio.h>
int main()
{
int x;
printf("x=%d\n", _Generic('x', int: 1, default: 0));
return 0;
}
Compiling with c++ (from GCC 4.9.2) fails:
t.cpp: In function ‘int main()’:
t.cpp:7:33: error: expected primary-expression before ‘int’
printf("x=%d\n", _Generic('x', int: 1, default: 0));
^
t.cpp:7:41: error: expected primary-expression before ‘default’
printf("x=%d\n", _Generic('x', int: 1, default: 0));
^
t.cpp:7:51: error: ‘_Generic’ was not declared in this scope
printf("x=%d\n", _Generic('x', int: 1, default: 0));
The compiler arguments are:
c++ --std=c++11 t.cpp -o t
What am I doing wrong?
_Generic is a C11 feature. It is not present in C++ (any version at least up to C++14 - I don't really expect it to be added either).
If you want to use it, you'll need to write C code, and use a compiler that supports that standard (reasonably recent versions of gcc and clang do for example, using -std=c11).
If you want to write C++, use overloading or templates instead, for example:
#include <iostream>
int foo(int) { return 1; }
int foo(char) { return 0; }
int main()
{
std::cout << "x=" << foo('x') << std::endl;
}
This prints x=0 in C++, the foo(char) overload is the best match.
Note that there's difference between C and C++ that might trick you here too: 'x' is a char in C++. It's an int in C. So if _Generic had been implemented (maybe as an extension) by your compiler, chances are you'd get different output when compiling your example as C versus compiling as C++.
Here's the C++ form (forgive me for using the using directive, I know its bad form):
#include <iostream>
using namespace std;
template< typename T> T do_something(T argument) {
// Put here what you need
}
int main()
{
int x;
cout << "x" << (x = do_something(x));
return 0;
}
_Generic is C11, you're probably using a C++ compiler when you meant to use a C compiler.

gcc "not inlined" warning

Does gcc's inline __attribute__((__always_inline__)) generate warning, when compiler can't inline function?
Because VS does http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx:
If the compiler cannot inline a function declared with __forceinline,
it generates a level 1 warning.
You need -Winline to get warnings about non-inlined functions.
If you want to verify this you can try taking the address of an inline function (which prevents it from being inlined) and then you should see a warning.
#include <stdio.h>
static inline __attribute__ ((always_inline)) int add(int a, int b)
{
return a + b;
}
int main(void)
{
printf("%d\n", add(21, 21));
printf("%p\n", add);
return 0;
}
EDIT
I've been trying to produce a warning with the above code and other examples without success - it seems that the behaviour of current versions of gcc and clang may have changed in this area. I'll delete this answer if I can't code up with a better example that generates a warning.

Dereferencing void* warnings on Xcode

I'm aware of this SO question and this SO question. The element
of novelty in this one is in its focus on Xcode, and in its use of
square brackets to dereference a pointer to void.
The following program compiles with no warning in Xcode 4.5.2, compiles
with a warning on GCC 4.2 and, even though I don't have Visual Studio
right now, I remember that it would consider this a compiler
error, and MSDN and Internet agree.
#include <stdio.h>
int main(int argc, const char * argv[])
{
int x = 24;
void *xPtr = &x;
int *xPtr2 = (int *)&xPtr[1];
printf("%p %p\n", xPtr, xPtr2);
}
If I change the third line of the body of main to:
int *xPtr2 = (int *)(xPtr + 1);
It compiles with no warnings on both GCC and Xcode.
I would like to know how can I turn this silence into warnings or errors, on
GDB and especially Xcode/LLVM, including the fact that function main is int but
does not explicitly return any value (By the way I think -Wall does
the trick on GDB).
that isnt wrong at all...
the compiler doesnt know how big the pointer is ... a void[] ~~ void*
thats why char* used as strings need to be \0-terminated
you cannot turn on a warning for that as it isnt possible to determine a 'size of memory pointer to by a pointer' at compile time
void *v = nil;
*v[1] = 0 //invalid
void *v = malloc(sizeof(int)*2);
*v[1] = 0 //valid
*note typed inline on SO -- sorry for any non-working code

Visual Studio 2010 (C++): suppress C4706 warning temporarily

When you compile the following C++ source file in Visual Studio 2010 with warning level /W4 enabled
#include <cstdio> // for printf
#include <cstring> // for strcmp
char str0[] = "Hello";
char str1[] = "World";
int main()
{
int result;
if (result = strcmp(str0, str1)) // line 11
{
printf("Strings are different\n");
}
}
you get the following warning
warning C4706: assignment within conditional expression
for line 11.
I want to suppress this warning exactly at this place. So I tried Google and found this page: http://msdn.microsoft.com/en-us/library/2c8f766e(v=VS.100).aspx
So I changed the code to the following - hoping this would solve the problem:
#include <cstdio> // for printf
#include <cstring> // for strcmp
char str0[] = "Hello";
char str1[] = "World";
int main()
{
int result;
#pragma warning(push)
#pragma warning(disable : 4706)
if (result = strcmp(str0, str1))
#pragma warning(pop)
{
printf("Strings are different\n");
}
}
It didn't help.
This variant didn't help either:
#include <cstdio> // for printf
#include <cstring> // for strcmp
char str0[] = "Hello";
char str1[] = "World";
int main()
{
int result;
#pragma warning(push)
#pragma warning(disable : 4706)
if (result = strcmp(str0, str1))
{
#pragma warning(pop)
printf("Strings are different\n");
}
}
To avoid one further inquiry: I cleaned the solution before each compilation. So this is probably not the fault.
So in conclusion: how do I suppress the C4706 exactly at this place?
Edit Yes, rewriting is possible - but I really want to know why the way I try to suppress the warning (that is documented officially on MSDN) doesn't work - where is the mistake?
Instead of trying to hide your warning, fix the issue it's complaining about; your assignment has a value (the value on the left side of the assignment) that can be legally used in another expression.
You can fix this by explicitly testing the result of the assignment:
if ((result = strcmp(str0, str1)) != 0)
{
printf("Strings are different\n");
}
In MSDN Libray: http://msdn.microsoft.com/en-us/library/2c8f766e(v=VS.100).aspx, There is the section as follows.
For warning numbers in the range 4700-4999, which are the ones
associated with code generation, the state of the warning in effect
when the compiler encounters the open curly brace of a function will
be in effect for the rest of the function. Using the warning pragma in
the function to change the state of a warning that has a number larger
than 4699 will only take effect after the end of the function. The
following example shows the correct placement of warning pragmas to
disable a code-generation warning message, and then to restore it.
So '#pragma warning' only works for an each function/method.
Please see the following code for more detail.
#include <cstdio> // for printf
#include <cstring> // for strcmp
char str0[] = "Hello";
char str1[] = "World";
#pragma warning(push)
#pragma warning( disable : 4706 )
void func()
{
int result;
if (result = strcmp(str0, str1)) // No warning
{
printf("Strings are different\n");
}
#pragma warning(pop)
}
int main()
{
int result;
if (result = strcmp(str0, str1)) // 4706 Warning.
{
printf("Strings are different\n");
}
}
The sane solution is to rewrite the condition to
if( (result = strcmp(str0, str1)) != 0 )
which will inform any C compiler that you really want to assign, and is almost certain to generate the same object code.
There is another solution which avoids the warning: the comma operator.
The main advantage here will be that you don't need parentheses so it's a bit shorter than the !=0 solution when your variable name is short.
For example:
if (result = strcmp(str0, str1), result)
{
printf("Strings are different\n");
}
There is a simple construction !! to cast a type to bool. Like this:
if (!!(result = strcmp(str0, str1)))
However, in some cases direct comparison != 0 might be more clear to a reader.

Resources