Warning in list initialization in C++11 - c++11

This is my code :
int x=65;
char ch{x};
And this is the warning when compiled with `-std=C++11 flag:
Narrowed conversion from "int to char"
But I think there should be an error as x is not a constant and we are initializing ch with a non-constant value. What actually happens?

You're right that the standard treats this as an error, and allows implementations to flat out reject this code.
However, implementations are almost never required to reject code that does not conform to the standard. They have to diagnose the problem, but if they attach the label "warning" to it and continue to accept the code, there is no problem.
In this case, C++11 made perfectly well-formed C++03 code into an error (not entirely your code, but char ch[] = {x}; used to be valid), so compilers have a good reason to treat it as only a warning: they want to accept as much formerly valid code as reasonable, or users might have a good reason to switch to another compiler.

clang will give you an error:
main.cpp:23:9: error: non-constant-expression cannot be narrowed from type 'int' to 'char' in initializer list [-Wc++11-narrowing]
gcc as far as I remember decided to issue warning as there is too many source code that would be broken by such decision.
when you initialize variable using uniform initialization then narrowing conversions are forbidden.

Related

Why does gcc misinterpret this macro?

I have found the large-precision code of MPFR C++ to be very useful, and have used it successfully in the past. Recently, while developing a new app, I encountered an enormous number of compiler errors in their header code (mpreal.h). I have identified the cause of all these errors: the the use of a name both in a typedef and as the name of a function, coupled with an unintuitive result of a macro. The relevant macro was in the mpfr package, and occurred between mpfr 4.0.2-5 and 4.1.0-6. I am using the latest version of mpreal.h (version 3.6.8), but other earlier versions behave the same.
The compiler errors vary somewhat, but the following is typical:
In file included from mpreal.h:125:
mpreal.h:624:32: error: no matching function for call to ‘mpfr::mpreal::mpfr_srcptr(const __mpfr_struct*&)’
624 | mpfr_init2(mpfr_ptr(), mpfr_get_prec(u));
| ^~~~~~~~~~~~~
mpreal.h:324:19: note: candidate: ‘const __mpfr_struct* mpfr::mpreal::mpfr_srcptr() const’
324 | ::mpfr_srcptr mpfr_srcptr() const;
| ^~~~~~~~~~~
mpreal.h:324:19: note: candidate expects 0 arguments, 1 provided
The relevant lines of code (int addition to the above) are:
mpreal.h:125 #include <mpfr>
mpfr.h:866 #define mpfr_get_prec(_x) MPFR_VALUE_OF(MPFR_SRCPTR(_x)->_mpfr_prec)
mpfr.h:845 #define MPFR_VALUE_OF(x) (0 ? (x) : (x))
mpfr.h:847 #define MPFR_SRCPTR(x) ((mpfr_srcptr) (0 ? (x) : (mpfr_srcptr) (x)))
The problem seems to be in the macro of line 847. The (mpfr_srcptr) (x) appearing in MPFR_SRCPTR(x) is meant to be a type-cast of x to the type mpfr_srcptr, but is being interpreted to mean a call to mpfr_srcptr() with argument x. Outside of a macro, gcc can tell the difference between (mpfr_srcptr)(x) and mpfr_srcptr(x), but the macro is apparently ignoring the parentheses. Can anyone explain this macro behavior? I know that gcc has a huge number of switches to control almost everything, but is there an option somewhere that would affect the interpretation of parentheses in macros?
I suppose that this behavior could be unique to my system, but I find that hard to believe. But I also find it hard to believe that such a bug has gone unnoticed by the rest of the community; I found no suggestion of any problem either on the website or on github, to which the project has recently been transferred.
The macro SRCPTR is not ignoring parentheses as I originally thought; the behavior is explained by the difference in scopes. The SRCPTR macro, while occurring within the mpfr coding at global scope, is actually being called from mpreal's scope. Since mpreal has redefined srcptr as a function, that definition is the only one used when SRCPTR is executed from mpreal. (SRCPTR, being a macro, has no scope.) When mpfr's functions are called from mpreal, the functions operate with the global scope, and the SRCPTR macro invoked there would therefore use the global definition.

What's the under-the-hood mechanism g++ uses to identify modification of 'const' variables?

when we declare a variable to be const
const int cv = 3;
I guess g++ reserve 4 bytes somewhere (say, address 0xFF77 ) in the data area. In the future, when people access cv, the compiler goes to 0xFF77 to get the value 3.
However, how does the compiler store the information 'const'? g++ must somehow store this information, so when another line tries to modify cv, the compiler knows 'oh, this is not correct, because I know 0xFF77 is const'.
Anybody here familiar with gcc compiler? could you give me some insight?
Thanks
Once the program is executing, the compiler is no longer present. It's work is done; the program has been compiled into an executable, and it can then be executed without the compiler even being installed. (Consequently, it is possible to distribute executables to machines which have no compiler.)
But even if your question were rewritten to fix that issue, there is an unwarranted and incorrect assumption:
g++ must somehow store this information, so when another line tries to modify cv, the run-time knows 'oh, this is not correct, because I know 0xFF77 is const'.
In fact, the run-time is under no obligation to stop the variable from being modified. That is the programmer's responsibility. When you declare a variable to be const, you are informing the compiler that you will not modify its value, which may allow the compiler to do a better job of optimising. Such optimisations may fail if it turns out that you do, in fact, modify the variable; that is covered by the fact that modifying a value declared const is "undefined behaviour". (Undefined behaviour is really undefined. Throwing an error would be defined behaviour.)
Under certain circumstances, the compiler can in fact detect during compilation that a variable declared const is being modified.
const int cv = 3;
cv = 42;
Most compilers will produce a warning if they see a blatant violation of the contract. But it is a warning, not an error, and there are times when the compiler has been misled. For example, the following code cannot produce an error, assuming that the function always_false lives up to its name:
const int cv = 3;
if (always_false(cv)) cv = 42;
In short, C++ does not undertake to save you from your errors; if you choose to write programs in C++, you must be prepared to ensure that you play by the rules.
However, how does the compiler store the information 'const'?
It doesn't. The const keyword is a type qualifier. Such knowledge about constness matters during type checking, a task performed by a compiler's frontend.
If no (invalid) attempt to modify a const value - beware of the difference between copy and reference/pointer semantics - is found, the compiler's backend will emit code. Then, the data in question is placed in an object file (not necessarily at a read-only section) like ELF.
Eventually, your operating system will load such binary file. What exactly happens upon modification of that once "const object", either from a violating expression not caught by the compiler's type-checker or any intrusive mechanism, can vary.

LD Link Failed - Bad Value

I am trying to compile my code using the DS-5 compiler. In the linking state, I am getting the linker fail error. I see warnings but not concrete errors like undefined references or the like. Can someone help me out on the same
The log is as below
/usr/local/DS-5/sw/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: warning: /opt/arm-2010.09/lib/gcc/arm-none-eabi/4.5.1/libgcc.a(bpabi.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/local/DS-5/sw/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: warning: /opt/arm-2010.09/lib/gcc/arm-none-eabi/4.5.1/libgcc.a(unwind-arm.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/local/DS-5/sw/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: warning: /opt/arm-2010.09/lib/gcc/arm-none-eabi/4.5.1/libgcc.a(pr-support.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/local/DS-5/sw/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: warning: /opt/arm-2010.09/lib/gcc/arm-none-eabi/4.5.1/libgcc.a(_divdi3.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/local/DS-5/sw/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: warning: /opt/arm-2010.09/lib/gcc/arm-none-eabi/4.5.1/libgcc.a(_udivdi3.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/local/DS-5/sw/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: .ddr_text has both ordered [`.ARM.exidx.atcm_text' in .//hw/obj/target/hw.a] and unordered [`.ARM.extab' in /opt/arm-2010.09/lib/gcc/arm-none-eabi/4.5.1/libgcc.a(_udivdi3.o)] sections
/usr/local/DS-5/sw/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
make: *** [all] Error 1
This problem can happen when you use the gcc compiler switch -fno-short-enums to force all enums to be 32bits. The actual warning message comes from the linker when the linker's target is set for variable sized enums.
If you specify the compiler switch -fshort-enums the warnings will go away because all enums are now consistent. That's the good news. The bad news is... If you truly require the enums to be 32bits, I don't know what option the linker requires to so. This is my problem. I believe it is implied by some other build setting and still looking...

MinGW's gcc reports error where Cygwin's accepts

MingGW's gcc (4.8.1) reports the following error (and more to come) when I try to compile Expstack.c:
parser.h:168:20: error: field '__p__environ' declared as a function
struct term *environ;
where 'environ' is declared inside 'struct term{ ... }'. In unistd.h you find
char **environ
but nowhere a '__p__environ'.
Some other fields are declared likewise, but are accepted. Subsequent errors related to environ are reported as follows
Expstack.c:1170:38: error: expected identifier before '(' token
case Term_src: return e->item.src->environ;
^
Cygwin's gcc (4.8.3) accepts these constructs and has done so over various versions since
2006 at least, and gcc with various versions of Linux before that.
The source text uses CRLF despite my attempts to convert to DOS, and this is my only guess for an explanation.
I'll appreciate clues or ideas to fix the problem, but renaming the field is not especially attractive and ought to be totally irrelevant.
This is very unlikely to have to do with CR/LF.
The name ought to be irrelevant but it isn't: this one relates to the Windows integration that MinGW does and Cygwin does not, as alluded to in http://sourceforge.net/p/mingw/mailman/message/14901207/ (that person is trying to use an extern environ that it expects to be defined by the system. Clearly, the fashion in which MinGW developers have made this variable available breaks the use of the name as a struct member).
You should report this as a MinGW bug. Unpleasant as it may be, in the interim, renaming the member is the simplest workaround. It is possible that a well-placed #undef environ might help, but no guarantees.

GCC 4.7 fails to inline with message "function body not available"

I am trying to compile some legacy code with more modern toolchains. I have tracked down one of my issues to the switch from gcc 4.6 to gcc 4.7:
Some of the functions are annotated with the inline keyword. Gcc fails on these with the error message:
error: inlining failed in call to always_inline 'get_value_global': function body not available
What is the correct way of dealing with this issue? How could the function body not be available? Should the compiler not make sure that it is available in all situations that require it?
Edit
As requested (in a deleted comment), an example of a signature of a function resulting in the error:
inline struct a_value_fmt const *find_a_value_format(struct base_fmt *base)
{
/* the code */
}
That error is typical to inline functions declared in source files, rather than in header files, in which case the compiler is not able to inline them (as the code of the function to be inlined must be visible to the compiler in the same source file being compiled). So, first thing I would check is that all functions declared inline are indeed defined in header files.
It may be that a change in GCC diagnostics in 4.7 caused the error to surface, and that it went silent in GCC 4.6 (but that's just a speculation).
The quoted error indicates that the function is declared with __attribute__((always_inline)). Note that GCC may fail to inline and report a different (and quite obscure) error if function is declared always_inline, but not with the inline keyword - so make sure that any function declared as always_inline is also declared as inline.
Few more tips:
General advice, which may not be applicable: since this is a legacy codebase, you may want to re-evaluate which functions should be inlined, being on the critical path, and which aren't, based on updated profiling results. Sometimes, inline is used generously, even when it is not required, or redundant. In some cases, the fix may be to remove the inline keyword in places where it is not needed.
When functions are declared in header files, the compiler considers them for inlining automatically (given they are small enough, and the compiler thinks that inlining them will improve performance, based on its heuristics) - even when the inline keyword is not used. inline is sort of a "recommendation" to the compiler, and it doesn't have to obey (unless it is given along with the always_inline attribute).
Modern compilers make relatively smart inlining decisions, so it's usually best to let the compiler do it's thing, and declare functions as inline (and moving their implementations to header files) in the appliation hot spots, based on profiling results.

Resources