error: narrowing conversion of ‘199’ from ‘int’ to ‘char’ inside { } [-Wnarrowing] - c++

I am trying to compile a really old software in linux debian 9.5, i keep getting this error:
janpdf/PDF.cpp: In member function ‘void PDF::OpenFile(const char*)’:
janpdf/PDF.cpp:41:74: error: narrowing conversion of ‘199’ from ‘int’ to
‘char’ inside { } [-Wnarrowing]
char signature[] = {'%', '%', 'G' + 128, 'R' + 128, 'A' + 128, '\n', 0};
^
janpdf/PDF.cpp:41:74: error: narrowing conversion of ‘210’ from ‘int’ to
‘char’ inside { } [-Wnarrowing]
janpdf/PDF.cpp:41:74: error: narrowing conversion of ‘193’ from ‘int’ to
‘char’ inside { } [-Wnarrowing]
Makefile:153: recipe for target 'janpdf/PDF.o' failed
make: *** [janpdf/PDF.o] Error 1
I have already tried teh signed / unsigned 'char'approach. Although I know almos nothing about coding this is the only answer I found. Any other solution is welcome.
thanks

Well, apparently in your implementation values like 210 and 199 do not fit into the range of type char. So, the conversion is narrowing. {} initializers do not allow narrowing conversions.
This suggests that your implementation apparently uses signed char type.
You can forcefully convert the values to char by using explicit casts inside the {}. You can stop using {} initializers. You can force your implementation to use unsigned char. There are many "solutions" for this problem, but there's no way to chose one without more context.
If the code was originally written for the same "family" of implementations you are compiling it on now, then most likely it was simply written for an older version of the language, which performed that narrowing conversion implicitly. In that case to reproduce the old behavior you'll need explicit casts
char signature[] =
{'%', '%', (char) ('G' + 128), (char) ('R' + 128), (char) ('A' + 128), '\n', 0};

The lowest-effort way to get your thing to build is probably to add -Wno-narrowing to your compiler invocation. If you're using make, you can probably start it with something like CFLAGS=-Wno-narrowing make (assuming you're using bash) to get the desired effect.

Current compilers use by default newer versions of C++. Your compiler may be trying to compile the source in C++11 or C++14 mode.
Try adding -std=c++03 to your compiler flags.

Related

error: narrowing conversion of ‘-58’ from ‘int’ to ‘char’ [-Wnarrowing]

I'm trying to compile https://github.com/jbeder/yaml-cpp on a Raspberry Pi, and I'm getting this error:
/home/pi/yaml-cpp/test/binary_test.cpp:11:38: error: narrowing conversion of ‘-58’ from ‘int’ to ‘char’ [-Wnarrowing]
11 | std::string input{-58, -1, -99, 109};
| ^
I gather that I should explicitly declare the numbers inside the bracket as signed chars, as some older compilers might not do so by themselves. But I am wholly unfamiliar with this syntax: What does this line actually do?

C++ / OpenGL: Texture to pixmap example - narrowing conversion error

I am trying to run this texture to pixmap example from OpenGL and get the following error
tex_to_pix.cpp:40:1: error: narrowing conversion of ‘4294967295u’ from ‘unsigned int’ to ‘int’ inside { } [-Wnarrowing]
The error refers to the following code block of the example:
const int pixmap_config[] = {
GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
GLX_DOUBLEBUFFER, False,
GLX_Y_INVERTED_EXT, GLX_DONT_CARE,
None
};
What is the reason for this error?
Is it a compiler or c++11 problem?
Is there a way i can either make my compiler ignore -Wnarrowing or make a safe conversion?
The issue is with GLX_DONT_CARE which is defined as:
#define GLX_DONT_CARE 0xFFFFFFFF
Because this value does not fit into a 32-bit int, its type is unsigned int (see this answer). The rules for narrowing conversion were indeed changed in c++11.
Trying to implicitly convert this unsigned int into an int causes the narrowing conversion warning. As shown in this answer, the narrowing problem can be fixed by using static_cast(GLX_DONT_CARE & 0xFFFFFFFF) instead of GLX_DONT_CARE
const int pixmap_config[] = {
GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
GLX_DOUBLEBUFFER, False,
GLX_Y_INVERTED_EXT, static_cast<int>(GLX_DONT_CARE & 0xFFFFFFFF),
None
};
Alternatively, disable narrowing conversion errors in your compiler (unspecified).

Pointer arithmatic failed to compile, gcc says invalid type conversion

I wish to calculate the distance between a program's bss section and the start of heap section, so I've got a program like this:
$ cat 1.cpp
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
int empty;//bss
int main()
{
char*p=(char*)malloc(0);
printf("%d\n",(int)p-(int)&empty);
return 0;
}
When I compile that code using:
$ g++ 1.cpp
The errors are:
1.cpp: In function ‘int main()’:
1.cpp:8:22: error: cast from ‘char*’ to ‘int’ loses precision [-fpermissive]
printf("%d\n",(int)p-(int)&empty);
^
1.cpp:8:30: error: cast from ‘int*’ to ‘int’ loses precision [-fpermissive]
printf("%d\n",(int)p-(int)&empty);
^
I don't think it's improper to convert an int* to int. I found plenty of examples doing this on the internet.
Why is my code not compiling?
Don't always trust what you read on the Internet.
Presumably, you're on a platform where pointers are 64-bit and int is 32-bit. In this case, a conversion from a pointer to int loses precision, and you're compiling with the right flags to make this an error. Well done!
The type you're looking for to convert a pointer to an integral type is uintptr_t. This is defined by the standard to be of sufficient width to allow for lossless conversion.
You may want p-reinterpret_cast<char*>(&empty)
But I don't see any reason to calculate distance between the two address. (and is undefined behavior as noted by #mch)
The type to cast to from pointers should be uintptr_t, which is guaranteed not to lose precision, see also fixed width integer types.
If you insist on using printf, then you need to find the right formatter, because that is not fixed. Otherwise, use:
std::cout << reinterpret_cast<uintptr_t>(p);

integer constant is so large that it is unsigned when assigning max type value to enum

Here is my enum declaration :
enum connection_primary_identifier_e : uint64_t
{
INVALID_IDENTIFIER = std::numeric_limits<std::underlying_type<connection_primary_identifier_e>::type>::max(),
}
(same happens if I use uint64_t directly as the type, also if I use -1 or -1ULL)
When I try to compile the file I get the following errors / warnings :
error: integer constant is so large that it is unsigned [-Werror]
error: narrowing conversion of ‘18446744073709551615I128’ from ‘__int128’ to ‘unsigned int’ inside { } [-Werror=narrowing]
error: large integer implicitly truncated to unsigned type [-Werror=overflow]
cc1plus: all warnings being treated as errors
The really weird thing is, the errors are actually produced for non-existing lines (line number is 3 after the last line on file) on another file (which uses the enum), I made sure it isn't a missing parentheses or anything like that.
Update:
Using uint32_t doesn't produce the error.
Using g++ (GCC) 4.8.3
Might be because std::underlying_type was initially underspecified and didn't require a complete type. This unintentionally allowed precisely this code, which uses connection_primary_identifier_e while it's still incomplete.
Starting with C++17, your code is definitely illegal.

Compiler does not give error when using list initialization which will cause information loss

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.