So I mistakenly passed an int into a function parameter expecting a pointer to a const object and I got this warning from GCC:
jni/../../../Source/Controller/UserExperienceManager.cpp: In member function 'void CUserExperienceManager::SendUXPToPOS(Types::CString)':
jni/../../../Source/Controller/UserExperienceManager.cpp:243:78: warning: invalid conversion from 'int' to 'const WebService_POSAgent::CDataCheck*' [-fpermissive]
jni/../../../../../Core/WebServices/Services/POSAgent/POSAgent.h:80:18: warning: initializing argument 2 of 'CEvent& WebService_POSAgent::CPOSAgent::AddUserExperienceID(Types::CString, const WebService_POSAgent::CDataCheck*, Types::CString)' [-fpermissive]
I tried to create a reproducible sample of this but I wasn't able to and I can't share too much of the code here. I compiled the same thing on MSVC9 and it properly gave me an error. I'm just in shock that I'm not getting an error from GCC on this! Anyone know why? Here are some simple snippets:
Function Declaration (class member function):
CEvent& AddUserExperienceID(CString userExperienceId, CDataCheck const* check, CString requestId = REQUEST_ID);
Function Call Site:
int nCheckNum = /*some value*/;
CPOSAgent::Instance().AddUserExperienceID(m_UserExperienceId, nCheckNum);
You're compiling that code with -fpermissive set which is downgrading the error to a warning.
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings.
Thus, using -fpermissive will allow some nonconforming code to compile.
What does the fpermissive flag do?
Related
In the following snippet no warnings are produced. g++4.4.3 -Wall -pedantic
//f is
void f(int );
f(3.14);
double d = 3.14;
int i = d+2;
I have a strong recollection of this being a warning, something along the lines of "Possible loss of precision". Was it removed or is my memory playing tricks on me?
How can i turn this into a warning in g++? I find this a useful warning, or is it a bad idea?
I can't even find anything appropriate at http://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Warning-Options.html
$ gcc -Wconversion test.c
test.c: In function ‘main’:
test.c:3: warning: conversion to ‘int’ from ‘double’ may alter its value
Use -Wconversion option. -Wall doesn't include it.
With -Wconversion option, GCC gives these warning messages:
warning: conversion to 'int' alters 'double' constant value
warning: conversion to 'int' from 'double' may alter its value
Apart from what other answers mention it is also worth mentioning that in C++0x {} initialization doesn't narrow. So instead of getting a warning you'll get an error for example
void f(int x)
{
// code
}
int main()
{
f({3.14}); // narrowing conversion of '3.14000000000000012434497875801753252744674682617e+0' from 'double' to 'int' inside { }
}
g++ 4.4 and above support initializer list (with -std=c++0x option)
In the following snippet no warnings are produced. g++4.4.3 -Wall -pedantic
//f is
void f(int );
f(3.14);
double d = 3.14;
int i = d+2;
I have a strong recollection of this being a warning, something along the lines of "Possible loss of precision". Was it removed or is my memory playing tricks on me?
How can i turn this into a warning in g++? I find this a useful warning, or is it a bad idea?
I can't even find anything appropriate at http://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Warning-Options.html
$ gcc -Wconversion test.c
test.c: In function ‘main’:
test.c:3: warning: conversion to ‘int’ from ‘double’ may alter its value
Use -Wconversion option. -Wall doesn't include it.
With -Wconversion option, GCC gives these warning messages:
warning: conversion to 'int' alters 'double' constant value
warning: conversion to 'int' from 'double' may alter its value
Apart from what other answers mention it is also worth mentioning that in C++0x {} initialization doesn't narrow. So instead of getting a warning you'll get an error for example
void f(int x)
{
// code
}
int main()
{
f({3.14}); // narrowing conversion of '3.14000000000000012434497875801753252744674682617e+0' from 'double' to 'int' inside { }
}
g++ 4.4 and above support initializer list (with -std=c++0x option)
trying to compile the TinyXml++ tutorial with CodeBlocks (16.01) and with VS2013 I get the same error at following line:
ticpp::Element* pElem = doc.FirstChildElement()->NextSibling();
CodeBlocks error:
invalid conversion from 'ticpp::Node*' to 'ticpp::Element*'
[-fpermissive]
VS2013 error:
cannot convert from 'ticpp::Node *' to 'ticpp::Element *'
Any idea?
In case you still want to compile it, regardless of whether there is an error in the tutorial, you can use the auto keyword for variable declaration.
For example:
auto pElem = doc.FirstChildElement()->NextSibling();
This way, the compiler will deduce the variable type at compile time.
The return type of NextSibling() is Node*. If you want Element* as return type, you can use NextSiblingElement() instead.
I noticed that g++ complain a bit too strictly about crossed initialization and I wonder why these false-positive errors could not be removed just by looking at the SSA form of the program while compiling.
Let me give a very simple example:
#include <cstdlib>
int main ()
{
goto end;
int i = 0; // unused variable declaration
end:
return EXIT_SUCCESS;
}
When compiled with g++ -Wall -Wextra -o example1 example1.cc (g++ 4.8.1), the compiler gives the following error message:
example1.cc: In function ‘int main()’:
example1.cc:10:2: error: jump to label ‘end’ [-fpermissive]
end:
^
example1.cc:6:8: error: from here [-fpermissive]
goto end;
^
example1.cc:8:7: error: crosses initialization of ‘int i’
int i = 0;
^
example1.cc:8:7: warning: unused variable ‘i’ [-Wunused-variable]
So, it will raise an error where there is actually no risk because the variable is unused (the compiler obviously has both information and cannot combine it to deduce that the error is a false-positive).
More strange, I hoped that LLVM was more efficient at analyzing a program. So, I tried clang++ (LLVM) on this simple example with clang++ -Wall -Wextra -o example1 example1.cc (clang++ 3.4). And, I got about the same error message:
example1.cc:8:7: warning: unused variable 'i' [-Wunused-variable]
int i = 0;
^
example1.cc:6:3: error: goto into protected scope
goto end;
^
example1.cc:8:7: note: jump bypasses variable initialization
int i = 0;
^
1 warning and 1 error generated.
So, I am pretty sure that I am missing something important here, a problem that make the detection of this false-positive harder than I though. But, I do not know what is it. Or maybe, the C++ specification specifically says that it must be like this.
If somebody has an idea, feel free to share !
Edit: I also compiled the exact same code in C (gcc or clang), and it went fine just with the warning about i being an unused variable. So, it reinforce the fact that this is more likely linked to the specification of C++ and not a problem detecting this issue at compile time.
There is nothing wrong with the compilers. Your code is ill-formed according to the standard.
In your particular case, the requirement of the standard may not be necessary and the jump could be allowed and the compiler could create valid code. However, this is only because the initialisation of the variable int i has no side effects.
You can make your code valid by simply enclosing the jumped section in its own scope:
#include <cstdlib>
int main ()
{
goto end;
{
int i = 0; // unused variable declaration
}
end:
// cannot use i here, as it's not defined.
return EXIT_SUCCESS;
}
This is disallowed because potentially you'd call destructors for objects that aren't properly constructed. Admittedly, int doesn't have constructor or destructor, but it's making it "fair" for all types of objects. And technically, something at label end: could be using i, and by making the rule strict, it prevents the machine having to check every single code-path (which becomes a "halting problem").
In c++ primer(5th), it mentioned:
When used with variables of built-in type, this form of initialization
has one
important property: The compiler will not let us list initialize variables of built-in type if the initializer might lead to the loss
of information:
longdouble ld = 3.1415926536;
int a{ld}, b = {ld}; // error: narrowing conversion required
int c(ld), d = ld; // ok: but value will be truncate
I compile the code using gcc4.8.1 , it only give a warning rather than an error.
g++ -W -Wall -Wextra -pedantic -std=c++0x -o m main.cpp
main.cpp: In function ‘int main()’:
main.cpp:64:13: warning: narrowing conversion of ‘ld’ from ‘long double’ to ‘int’ inside { } [-Wnarrowing]
int a{ld}, b= {ld};
^
main.cpp:64:22: warning: narrowing conversion of ‘ld’ from ‘long double’ to ‘int’ inside { } [-Wnarrowing]
int a{ld}, b= {ld};
Is there any flags that will turn on the feature of the important property ?
A quick search for "gcc diagnostic flag" turns up documentation resources.
Inside your program, you could do this:
#ifdef __GNUC__
# pragma GCC diagnostic error "-Wnarrowing"
#endif
There is a command-line option too: -Werror=narrowing, but since you want to alter the semantic meaning of the program itself according to GCC, putting it in the source code is probably more appropriate.
Note, when it makes a difference other than simple well-formedness, such as in overload selection, GCC does diagnose the condition correctly.
The standard never calls for errors or for warnings: the standard only requires an implementation to issue a diagnostic. Whether such a diagnostic takes the form of a compiler error, or a warning, or something entirely different from them both, is outside the scope of the standard.