Strange error message for isprint() using arm-none-eabi-gcc - gcc

I have the following code:
#include <ctype.h>
void myfn(void)
{
uint8_t any0 = 'c';
char any1 = 'c';
if (isprint(any0))
{
return;
}
if (isprint(any1))
{
return;
}
}
When I compile it with gcc for arm, I get the following error:
error: array subscript has type 'char' [-Werror=char-subscripts]
if (isprint(any1))
^
If I pass an unit8_t to isprint, the compiler is happy, but not if I pass it a char.
The prototype for isprint is:
int isprint(int c);
It expects an int as parameter, I give it a char.
I would expect it to complain about the type of the parameter, but not something unrelated as 'array subscript'.
The error goes away if I change the call to:
if (isprint((uint8_t)any1))
Is there something I have overlooked?
The compiler I use is:
GNU C (15:4.9.3+svn231177-1) version 4.9.3 20150529 (prerelease) (arm-none-eabi)
compiled by GNU C version 5.2.1 20151129, GMP version 6.1.0, MPFR version 3.1.3, MPC version 1.0.3
warning: MPFR header version 3.1.3 differs from library version 3.1.4.
Commandline options:
'-v' '-fshort-enums' '-specs=nosys.specs' '-specs=nano.specs'
'-mfloat-abi=soft' '-save-temps' '-Werror' '-Wpedantic' '-pedantic-errors' '-mthumb' '-fno-builtin' '-mcpu=cortex-m0' '-Wall' '-std=gnu99' '-ffunction-sections'
'-fdata-sections' '-fomit-frame-pointer' '-mabi=aapcs' '-fno-unroll-loops' '-ffast-math' '-ftree-vectorize' '-Og' '-g'
If I compile the same code with the gcc compiler for AVR /usr/bin/avr-gcc (using similar commandline options and I intentionally added option -Werror=char-subscripts), it doesn't complain about isprint. So it seems to be something related to the ARM compiler.

It turned out that the implementation of isprint for ARM is a macro and, more importantly, header file ctype.h contains the following comment:
These macros are intentionally written in a manner that will trigger
a gcc -Wall warning if the user mistakenly passes a 'char' instead of
an int containing an 'unsigned char'.
For AVR, header file ctype.h contains:
extern int isprint(int __c) __ATTR_CONST__;
This explains the difference in behaviour when compiling for AVR or for ARM.

Related

gcc 11.3.0 on macOS/Apple Silicon and SHA-3 instructions

I have gcc 11.3.0 installed using Homebrew on a MacBook Air with Apple Silicon M1 CPU. The binary is the aarch64 native version, not Rosetta emulated. The installed OS is macOS Monterey 12.3.
I'm having an issue compiling a program which uses the ARMv8.2-A SHA-3 extension instructions, which are supported by the M1 CPU. This is a minimal reproducible example:
#include <arm_neon.h>
int main() {
uint64x2_t a = {0}, b = {0}, c = {0};
veor3q_u64(a, b, c);
return 0;
}
This code compiles just fine with the Apple supplied clang compiler.
I compiled it using the following command line for gcc 11:
gcc-11 -o test test.c -march=armv8-a+sha3
This results in the following error:
In file included from test.c:1:
test.c: In function 'main':
/opt/homebrew/Cellar/gcc/11.3.0/lib/gcc/11/gcc/aarch64-apple-darwin21/11/include/arm_neon.h:32320:1: error: inlining failed in call to 'always_inline' 'veor3q_u64': target specific option mismatch
32320 | veor3q_u64 (uint64x2_t __a, uint64x2_t __b, uint64x2_t __c)
| ^~~~~~~~~~
test.c:5:5: note: called from here
5 | veor3q_u64(a, b, c);
| ^~~~~~~~~~~~~~~~~~~
Is this a bug in this particular hardware/software combination, or is there some command-line option I can pass to gcc to make this particular program compile?
Solved the problem. It turns out that gcc requires -march=armv8.2-a+sha3 rather than just -march=armv8-a+sha3 to compile this intrinsic. Indeed, in gcc's version of arm_neon.h, one can find this right before the block of intrinsics which includes veor3q_u64:
#pragma GCC target ("arch=armv8.2-a+sha3")

Undocumented ABI changes of std::function between GCC-4 and GCC-5/6/7/8/9, how to make a .so working with devtoolset-4/6/7/8/9?

with _GLIBCXX_USE_CXX11_ABI=0
std::function of GCC-4 is different of GCC-5 and follwing versions.
The following code show you the fact:
==> lib.cc <==
#include <functional>
std::function<int(const void*p)> holder;
int run_holder(const void *p)
{
return holder(p);
}
==> main.cc <==
#include <stdio.h>
#include <functional>
extern int run_holder(const void*p);
extern std::function<int(const void*p)> holder;
int foo(const void* p)
{
printf("p=%p\n", p);
return 0;
}
int main()
{
holder = foo;
foo((void*)0x12345678);
holder((void*)0x12345678);
run_holder((void*)0x12345678);
}
==> make.sh <==
#!/bin/bash
GCC4=/usr/bin/g++
GCCN="scl enable devtoolset-5 -- g++"
$GCC4 -std=c++11 -c -g lib.cc -shared -o libfoo.so &&
$GCCN -std=c++11 -L. -lfoo -g main.cc -o a.out &&
LD_LIBRARY_PATH=. ./a.out
expected result, something like:
p=0x12345678
p=0x12345678
p=0x12345678
actual result:
p=0x12345678
./make.sh: line 6: 973 Segmentation fault LD_LIBRARY_PATH=. ./a.out
The reason is the implementation of std::function changes without document.
gcc4: /usr/include/c++/4.8.2/functional:2430
typedef _Res (*_Invoker_type)(const _Any_data&, _ArgTypes...);
gcc5: /opt/rh/devtoolset-4/root/usr/include/c++/5.3.1/functional:2226
gcc8: /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/std_function.h:609
using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
So I can not write a .so using std::function compiled by gcc4 and used by gcc5/6/7/8. There is no macro like _GLIBCXX_USE_CXX11_ABI can control the behavior.
So I can not write a .so using std::function compiled by gcc4 and used by gcc5/6/7/8.
Correct. Neither Red Hat nor the GCC project has ever claimed that's possible, quite the opposite. C++11 support in GCC 4.x was incomplete and unstable, and subject to ABI changes and API changes. What you're trying to do was never supported.
I've explained this in more detail at https://stackoverflow.com/a/49119902/981959
The Developer Toolset documentation covers it too (emphasis mine):
"A compiler in C++11 or C++14 mode is only guaranteed to be compatible with another compiler in C++11 or C++14 mode if they are from the same release series (for example from Red Hat Developer Toolset 6.x).
...
"Using the C++14 language version is supported in Red Hat Developer Toolset when all C++ objects compiled with the respective flag have been built using Red Hat Developer Toolset 6 or later. Objects compiled by the system GCC in its default mode of C++98 are also compatible, but objects compiled with the system GCC in C++11 or C++14 mode are not compatible."
There is no macro like _GLIBCXX_USE_CXX11_ABI can control the behavior.
We do not provide macros to control things that are unsupported and cannot work.
If you want to use C++11 with a mix of GCC versions you need to use a release that has stable, non-experimental support for C++11. So not GCC 4.x.

How to suppress warning that gcc option is deprecated

I'm using the official release of ARM GCC 2018 Q4 Major. For this C code:
int main(void) { return 0; }
the compiler produces a warning:
$ arm-none-eabi-gcc -mstructure-size-boundary=32 main.c
cc1.exe: warning: option '-mstructure-size-boundary' is deprecated
Is it possible to suppress this warning? The flag -Wno-deprecated has no effect.
I need to use the -mstructure-size-boundary option because I need to link against someone else's closed source compiled libraries that used the same setting. (Well, I guess I could edit their headers and manually set trailing struct padding but that would not be Plan A).

Coudn't run code used std::async on GCC 5.3.0

I was practicing std::asyn function that introduced in c++11, I wrote a simple example
#include<future>
#include<iostream>
using namespace std;
void check()
{
cout<<"some"<<endl;
}
int main()
{
auto p=std::async(std::launch::async,check);
p.get();
}
Yes very simple to start off with and i am compiling it using GCC 5.3.0
g++ -std=c++11 practise.cpp -lpthread
and the error
practise.cpp: In function 'int main()':
practise.cpp:13:47: error: invalid use of incomplete type 'class std::future<int>'
auto p=std::async(std::launch::async,chech);
^
In file included from practise.cpp:1:0:
C:/Program Files/mingw32/i686-w64-mingw32/include/c++/future:115:11: note: declaration of 'class std::future<int>'
class future;
^
Am i missing anything? is the way i linked lpthread is ok? i am on windows 7.
Your problem looks very similar to the one from this SO:
c++11 std::async doesn't work in mingw
You should check what gcc -v returns for 'Thread model:'. In above SO it returns win32 - and quite possibly mingw still does not support async/future in this mode.
In my mingw installation - also 5.3.0, I have Thread model: posix. I checked the exact same compile flags as yours and your example always compiles fine.
So my suggestion is for you to first check thread model with gcc -v, if its non posix, then reinstall mingw with posix threads. You choose threads model when running mingw-w64-install.exe installer/

Clang OS X Lion, cannot find cstdint

I'm trying to compile an application that utilizes cstdint. Since Apple deprecated the gcc, I wanted to try compiling it with clang, but i get the error:
fatal error: 'cstdint' file not found
I know that the gcc 4.6.2 version has the option for -std=c++0x, to include the library, but since the os x version is 4.2 that's not much of an option here. Any suggestions on how I can move forward? I have tried to install 4.6.2, but ran into a variety of issues when compiling some of the needed libraries before building gcc.
Presumably, you have the source code to this application, so you can modify the headers to include the correct cstdint header, as Clang 3.0 (which Lion's tools come with) does have the header.
Quick Solution
The header is under the tr1 directory, so you will want to do either of these includes:
#include <tr1/cstdint>
Or
#include <stdint.h> // which will use the C99 header
Longer, boring explanation
After doing some additional reading since I remember you can do this without the tr1 directory:
By default, you are going to be including C++ headers from /usr/include/c++/4.2.1, which are the GNU GCC headers. /usr/include/c++/4.2.1/tr1 includes the TR1 header files, like cstdint.
The alternative method is to compile using the Clang++ frontend and passing the -stdlib=libc++ flag, which will use the headers from /usr/include/c++/v1, which are Clang's C++ header implementations. It has cstdint.
Example:
// file called example.cxx
#include <tr1/cstdint>
int main() {
// whatever...
}
Compile this with:
g++ example.cxx
or
clang++ example.cxx
And it will do what you want.
If you don't want to use the tr1 version (which is roughly the same, if not exactly):
// file called example.cxx
#include <cstdint>
int main() {
// stuff
}
This is compiled like this:
clang++ -stdlib=libc++ example.cxx
Though if you use -stdlib=libc++, it means you're linking to Clang's C++ library libc++, rather than GCC's libstdc++.

Resources