[Bug c++/97222] GCC discards attributes aligned and may_alias for typedefs passed as template arguments
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97222 Mateusz Zych changed: What|Removed |Added See Also||https://bugs.llvm.org/show_ ||bug.cgi?id=47674 --- Comment #4 from Mateusz Zych --- I just wanted to mention, that I raised issue in the Clang Bugzilla, since Clang is matching GCC behavior (also discards attributes): - https://bugs.llvm.org/show_bug.cgi?id=47674 Thanks, Mateusz
[Bug c++/97222] New: GCC discards attributes aligned and may_alias for typedefs passed as template arguments
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97222 Bug ID: 97222 Summary: GCC discards attributes aligned and may_alias for typedefs passed as template arguments Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: mte.zych at gmail dot com Target Milestone: --- Hello! GCC discards aligned attribute, applied on a typdef, when it's passed as a template argument. Compiler Expolorer: GCC -> https://godbolt.org/z/bj8v1T C++ Source Code: #include typedef float vec __attribute__((vector_size(8))); typedef float fp __attribute__((aligned(16))); template struct identity { typedef t type; }; int main () { std::cout << sizeof(typename identity::type) << std::endl; std::cout << sizeof(vec ) << std::endl; std::cout << alignof(typename identity::type) << std::endl; std::cout << alignof(fp ) << std::endl; } Program Output: 8 8 4 16 Compilation Log: warning: ignoring attributes on template argument 'fp' {aka 'float'} [-Wignored-attributes] 13 | std::cout << alignof(typename identity::type) << std::endl; | ^ The above program shows that alignment of the fp typedef changes, after it's been passed through the identity meta-function - it's 4-bytes instead of expected 16-bytes. What's interesting is not all type attributes are discarded - the type attribute vector_size is preserved after being passed through the identity meta-function. This behavior is required, since removal of the vector_size attribute would be a semantic change of the vec type, affecting even its size, because the vec type would represent a single float, instead of a vector of 2 floats. The same could be said about the aligned attribute - discarding it is also a semantic change, since alignment is a fundamental property of a type, affecting among others code generation, that is, two types are not equivalent if they have different alignment. This is the reason why I argue that, passing a typedef as a template argument should preserve its aligned attribute, instead of discarding it. Moreover, the Intel C++ compiler implements this behavior correctly. Compiler Expolorer: ICC -> https://godbolt.org/z/9vr9se Program Output: 8 8 16 16 The issue described above doesn't apply only to the aligned type attribute, but also to the may_alias type attribute. Compiler Expolorer: GCC -> https://godbolt.org/z/6EqsnP C++ Source Code: typedef int integer __attribute__((may_alias)); template struct identity { typedef t type; }; int main () { typename identity::type i; } Compilation Log: warning: ignoring attributes on template argument 'integer' {aka 'int'} [-Wignored-attributes] 7 | typename identity::type i; | ^ Again, discarding attribute may_alias is a semantic change, because aliasing rules can affect code generation. Why this issue is important? Well, because it prevents generic programming, via C++ templates, using x86 SIMD types. If we would look at definitions of x86 SIMD types, we will notice that they are essentially typedefs with attributes vector_size and may_alias applied on them: - immintrin.h typedef float __m256 __attribute__((__vector_size__(32), __may_alias__)); - emmintrin.h typedef long long __m128i __attribute__((__vector_size__(16), __may_alias__)); typedef double__m128d __attribute__((__vector_size__(16), __may_alias__)); - xmmintrin.h typedef float __m128 __attribute__((__vector_size__(16), __may_alias__)); Note that, the may_alias attributes is required and cannot be removed: - /usr/lib/gcc/x86_64-linux-gnu/10/include/immintrin.h /* The Intel API is flexible enough that we must allow aliasing with other vector types, and their scalar components. */ Compiler Expolorer: GCC -> https://godbolt.org/z/vz4fWK C++ Source Code: #include template struct identity { typedef t type; }; int main () { typename identity<__m128>::type fvec4; } Compilation Log: warning: ignoring attributes on template argument '__m128' [-Wignored-attributes] 8 | typename identity<__m128>::type fvec4; | ^ What's the root cause of this problem? Well, the problem is in C++ a typedef is just an alias (a new name) for the old type, that is, it does *not* introduce a new type. Implementing support for attributes vector_size, aligned and may_alias in C++ typedefs requires an opaque/strong typedef, introducing a brand new type and storing information about applied attrib
[Bug driver/87769] GCC build from source uses headers and libraries from directories host machine.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87769 --- Comment #11 from Mateusz Zych --- Oh, I forgot to mention that I've also tested this configuration: HOST=x86_64-abc-linux-gnu TARGET=x86_64-xyz-linux-gnu and it worked without any issues. I don't understand why would these configurations fail: HOST = x86_64-linux-gnu TARGET = x86_64-pc-linux-gnu HOST = x86_64-pc-linux-gnu TARGET = x86_64-pc-linux-gnu yet such a fabricated configuration works. This is really confusing. @.@ Best regards, Mateusz
[Bug driver/87769] GCC build from source uses headers and libraries from directories host machine.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87769 --- Comment #10 from Mateusz Zych --- Created attachment 46005 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46005&action=edit Build log of first GCC, ending on compilation failure of libstdc++-v3.
[Bug driver/87769] GCC build from source uses headers and libraries from directories host machine.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87769 --- Comment #9 from Mateusz Zych --- Hi ;) I've analysed this issue further and tested all combinations of different vendors in host and target triplets. Here are the results: +---+ | host| |---| | | glibc |unknown | pc | ++---+ | | | FAIL | PASS | PASS | FAIL | | t |||||| | a | glibc | PASS | FAIL | PASS | PASS | | r |||||| | g |unknown | PASS | PASS | FAIL | PASS | | e |||||| | t | pc | FAIL | PASS | PASS | FAIL | ++---+ Looks like building isolated compiler (target == host) doesn't work at all and for some reason cross-compiling by combining no vendor with pc vendor fails as well. Note that, all failing configurations are encountering the same issue with compilation of libstdc++-v3 during first GCC build: checking whether the /home/mzych/Downloads/build-many-glibcs/gcc-first-build/./gcc/xgcc -B/home/mzych/Downloads/build-many-glibcs/gcc-first-build/./gcc/ -B/home/mzych/Downloads/build-many-glibcs/gcc/x86_64-pc-linux-gnu/bin/ -B/home/mzych/Downloads/build-many-glibcs/gcc/x86_64-pc-linux-gnu/lib/ -isystem /home/mzych/Downloads/build-many-glibcs/gcc/x86_64-pc-linux-gnu/include -isystem /home/mzych/Downloads/build-many-glibcs/gcc/x86_64-pc-linux-gnu/sys-include linker (/home/mzych/Downloads/build-many-glibcs/gcc-first-build/./gcc/collect-ld -m elf_x86_64) supports shared libraries... yes checking dynamic linker characteristics... configure: error: Link tests are not allowed after GCC_NO_EXECUTABLES. Makefile:18985: recipe for target 'configure-stage1-target-libstdc++-v3' failed Initially I was thinking that there might be something wrong with the script, which I've used to build GCC (CreateToolchain.sh), but it seems unlikely, since other configurations work without any issues. To me this looks very surprising that changing vendor in a triplet causes GCC to fail to compile. Can somebody help with figuring out what's going on here? I think that the script CreateToolchain.sh could benefit the whole GCC community, because developers could use it to compile GCC by simply choosing desired configuration. Thank you, Mateusz
[Bug driver/87769] GCC build from source uses headers and libraries from directories host machine.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87769 --- Comment #8 from Mateusz Zych --- Created attachment 45901 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45901&action=edit Script creating standalone GNU toolchain for C++.
[Bug driver/87769] GCC build from source uses headers and libraries from directories host machine.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87769 --- Comment #7 from Mateusz Zych --- Hi Joseph, ;) Thank you very much for your advice - it was really helpful! I've managed to implement a script creating standalone GNU toolchain for C++: - https://github.com/mtezych/cpp/blob/master/CreateToolchain.sh However, I still have an issue with some configurations of triples. For example, the following cross-compiling configurations are building successfully: HOST = x86_64-pc-linux-gnu TARGET = x86_64-glibc-linux-gnu HOST = x86_64-linux-gnu TARGET = x86_64-glibc-linux-gnu HOST = x86_64-pc-linux-gnu TARGET = x86_64-unknown-linux-gnu HOST = x86_64-unknown-linux-gnu TARGET = x86_64-pc-linux-gnu Even cross-compiling for x86 works: HOST = x86_64-unknown-linux-gnu TARGET = i686-pc-linux-gnu However, for some reason these configurations do not work: HOST = x86_64-linux-gnu TARGET = x86_64-pc-linux-gnu HOST = x86_64-pc-linux-gnu TARGET = x86_64-linux-gnu Also, I cannot build an isolated compiler: HOST = x86_64-linux-gnu TARGET = x86_64-linux-gnu HOST = x86_64-pc-linux-gnu TARGET = x86_64-pc-linux-gnu HOST = x86_64-unknown-linux-gnu TARGET = x86_64-unknown-linux-gnu HOST = x86_64-glibc-linux-gnu TARGET = x86_64-glibc-linux-gnu Can you explain to me what's the significance of a vendor in a triplet? That is, what's the difference between these triplets? - x86_64-linux-gnu - x86_64-pc-linux-gnu - x86_64-none-linux-gnu - x86_64-glibc-linux-gnu - x86_64-unknown-linux-gnu Maybe there is a piece of documentation, blog post or an article, that you can point me to, which explains this? Which triplet configuration I should use for a host and a target, when I am using regular GNU/Linux distro (Ubuntu MATE 18.04 LTS) and want to target wide range or GNU/Linux distros? Are triples returned by these commands good values for triples? $ gcc -dumpmachine -> x86_64-linux-gnu $ make -v -> x86_64-pc-linux-gnu Thank you, Mateusz
[Bug driver/87769] GCC build from source uses headers and libraries from directories host machine.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87769 Mateusz Zych changed: What|Removed |Added Status|RESOLVED|UNCONFIRMED Resolution|INVALID |--- --- Comment #5 from Mateusz Zych --- I read numerous articles describing how to build standalone GCC for source: - https://solarianprogrammer.com/2018/05/06/building-gcc-cross-compiler-raspberry-pi/ - https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ - https://wiki.osdev.org/GCC_Cross-Compiler - https://wiki.osdev.org/Building_GCC - https://gist.github.com/maoueh/14ef25a03d5722bc1e03 None of above approaches worked for me. ;( I'm always ending up with some obscure compilation / linking issue. Can someone just explain to me, how to build GCC using configuration option "--with-sysroot="? I would really appreciate it. PS. I am treating this as a bug, because I couldn't find any official documentation explaining how to build GCC using configuration option "--with-sysroot=". I just think that the whole process of doing so shouldn't be that hard. Thanks, Mateusz
[Bug driver/87769] GCC build from source uses headers and libraries from directories host machine.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87769 --- Comment #4 from Mateusz Zych --- Right, the "--with-sysroot=" configuration parameter is the key. The sysroot directory defines minimal filesystem of a target machine, in particular it should contain standard C library and Linux kernel headers, so it makes sense that I have to provide the sysroot directory to build standalone GCC, which would be a cross compiler. However, I don't understand why would configuration parameters "--host=" and "--target=", define whether I am building a cross compiler or not. To me, what differentiates cross compiler form native compiler, is the location of libraries and headers. - Native compilers use libraries and headers from host machine. - Cross compilers never touch host machine and always use sysroot. Of course, all compilers targeting different architecture compared to architecture of the host machine have be cross compilers. But the opposite is not true - not all cross compilers have to target architecture different from architecture of the host machine. They can match, no problem! And this is exactly what I'm trying to do - I want build GCC cross compiler targeting the exact same architecture that my host machine is using. OK, with that out of the way, I've updated my script: # Linux wget https://kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.gz tar -xvf linux-4.19.tar.gz mv linux-4.19 linux-source cd linux-source make ARCH=x86_64 INSTALL_HDR_PATH=$PWD/../gcc/sysroot/usr headers_install cd .. # GNU C Library (glibc) wget https://ftp.gnu.org/gnu/glibc/glibc-2.28.tar.gz tar -xvf glibc-2.28.tar.gz mv glibc-2.28 glibc-source mkdir glibc-build cd glibc-build ../glibc-source/configure --build=x86_64-linux-gnu \ --host=x86_64-linux-gnu \ --target=x86_64-linux-gnu \ --prefix=$PWD/../gcc/sysroot/usr \ --with-headers=$PWD/../gcc/sysroot/usr/include \ --disable-multilib \ --disable-nls \ --disable-timezone-tools make all -j 4 make install cd .. # GNU Binutils wget https://ftp.gnu.org/gnu/binutils/binutils-2.31.tar.gz tar -xvf binutils-2.31.tar.gz mv binutils-2.31 binutils-source mkdir binutils-build cd binutils-build ../binutils-source/configure --build=x86_64-linux-gnu \ --host=x86_64-linux-gnu \ --target=x86_64-linux-gnu \ --prefix=$PWD/../gcc \ --with-sysroot=$PWD/../gcc/sysroot \ --disable-multilib \ --disable-nls make all -j 4 make install cd .. # GCC wget https://ftp.gnu.org/gnu/gcc/gcc-8.2.0/gcc-8.2.0.tar.gz tar -xvf gcc-8.2.0.tar.gz mv gcc-8.2.0 gcc-source cd gcc-source ./contrib/download_prerequisites cd .. mkdir gcc-build cd gcc-build ../gcc-source/configure --build=x86_64-linux-gnu \ --host=x86_64-linux-gnu \ --target=x86_64-linux-gnu \ --prefix=$PWD/../gcc \ --with-sysroot=$PWD/../gcc/sysroot \ --enable-languages=c,c++ \ --disable-multilib \ --disable-nls make all -j 4 make install cd .. Essentially I am puting: - GCC and Binutils into $ROOT/gcc and - glibc with Linux headers into ROOT/gcc/sysroot. Unfortunately with updated script, GCC is not compiling anymore. :( I've never managed to compile GCC configured with parameter "--with-sysroot=". What is actually failing? Well, the libgcc_s.so fails to link with libc.so.6: attempt to open /home/mzych/standalone-gcc/gcc-build/../gcc/sysroot/home/mzych/standalone-gcc/glibc-build/../gcc/sysroot/usr/lib/libc.so.6 failed attempt to open /home/mzych/standalone-gcc/gcc-build/../gcc/sysroot/home/mzych/standalone-gcc/glibc-build/../gcc/sysroot/usr/lib/libc_nonshared.a failed attempt to open /home/mzych/standalone-gcc/gcc-build/../gcc/sysroot/home/mzych/standalone-gcc/glibc-build/../gcc/sysroot/usr/lib/ld-linux-x86-64.so.2 failed /usr/bin/ld: cannot find /home/mzych/standalone-gcc/glibc-build/../gcc/sysroot/usr/lib/libc.so.6 inside /home/mzych/standalone-gcc/gcc-build/../gcc/sysroot /usr/bin/ld: cannot find /home/mzych/standalone-gcc/glibc-build/../gcc/sysroot/usr/lib/libc_nonshared.a inside /home/mzych/standalone-gcc/gcc-build/../gcc/sysroot /usr/bin/ld: cannot find /home/mzych/standalone-gcc/glibc-build/../gcc/sysroot/usr/lib/ld-linux-x86-64.so.2 inside /home/mzych/standalone-gcc/gcc-build/../gcc/sysroot To me this failure looks like an issue with sysroot path, bec
[Bug driver/87769] GCC build from source uses headers and libraries from directories host machine.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87769 --- Comment #2 from Mateusz Zych --- Hi Andrew ;) Thanks for your reply. You are right that, in order to create standalone GCC, I need to provide C standard library, because GCC can work with various C standard library implementations. The GNU C Library (glibc) is just one implementation, which is not always used (for example Android is using bionic). To correct my script, I changed it to download and compile binutils, glibc and gcc respectively: # GNU Binutils wget https://ftp.gnu.org/gnu/binutils/binutils-2.31.tar.gz tar -xvf binutils-2.31.tar.gz mv binutils-2.31 binutils-source mkdir binutils-build cd binutils-build ../binutils-source/configure --build=x86_64-linux-gnu \ --host=x86_64-linux-gnu \ --target=x86_64-linux-gnu \ --prefix=$PWD/gcc \ --disable-multilib \ --disable-nls make -j 4 make install cd .. # GNU C Library (glibc) wget https://ftp.gnu.org/gnu/glibc/glibc-2.28.tar.gz tar -xvf glibc-2.28.tar.gz mv glibc-2.28 glibc-source mkdir glibc-build cd glibc-build ../glibc-source/configure --build=x86_64-linux-gnu \ --host=x86_64-linux-gnu \ --target=x86_64-linux-gnu \ --prefix=$PWD/gcc \ --disable-multilib \ --disable-nls \ --disable-timezone-tools make -j 4 make install cd .. # GCC wget https://ftp.gnu.org/gnu/gcc/gcc-8.2.0/gcc-8.2.0.tar.gz tar -xvf gcc-8.2.0.tar.gz mv gcc-8.2.0 gcc-source cd gcc-source ./contrib/download_prerequisites cd .. mkdir gcc-build cd gcc-build ../gcc-source/configure --build=x86_64-linux-gnu \ --host=x86_64-linux-gnu \ --target=x86_64-linux-gnu \ --prefix=$PWD/gcc \ --enable-languages=c,c++ \ --disable-multilib \ --disable-nls make -j 4 make install cd .. This improved things, in a sense that, in my simple C++ application compiled using GCC build from source it includes only these headers from host machine: - /usr/include/asm-generic/errno-base.h - /usr/include/asm-generic/errno.h - /usr/include/linux/errno.h - /usr/include/x86_64-linux-gnu/asm/errno.h However, header files from host machine are still being included! This can be seen when listing include directories used by GCC build from source: /home/mzych/gcc/bin/../lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0 /home/mzych/gcc/bin/../lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/x86_64-linux-gnu /home/mzych/gcc/bin/../lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/backward /home/mzych/gcc/bin/../lib/gcc/x86_64-linux-gnu/8.2.0/include /home/mzych/gcc/bin/../lib/gcc/x86_64-linux-gnu/8.2.0/include-fixed ---> /usr/local/include /home/mzych/gcc/bin/../lib/gcc/../../include ---> /usr/include/x86_64-linux-gnu ---> /usr/include OK, maybe I'm completely wrong here, but I think that it would be great to introduce to GCC a configuration option, which would prevent GCC from using any headers and libraries from host machine. In this configuration, GCC would simply return compilation error in case where required header or library would not found in its own directory tree. BTW, I was searching for such an option, but I couldn't find it. - https://gcc.gnu.org/install/configure.html Thanks, Mateusz
[Bug driver/87769] New: GCC build from source uses headers and libraries from directories host machine.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87769 Bug ID: 87769 Summary: GCC build from source uses headers and libraries from directories host machine. Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: driver Assignee: unassigned at gcc dot gnu.org Reporter: mte.zych at gmail dot com Target Milestone: --- Hi ;) I'm building GCC from source using the following commands: $ cd /home/mzych $ git clone https://github.com/gcc-mirror/gcc.git gcc-source $ cd gcc-source $ ./contrib/download_prerequisites $ cd .. $ mkdir gcc-build $ cd gcc-build $ ../gcc-source/configure -v \ --build=x86_64-linux-gnu \ --host=x86_64-linux-gnu \ --target=x86_64-linux-gnu \ --prefix=/home/mzych/gcc \ --enable-languages=c,c++ \ --disable-multilib $ make -j 4 $ make install However, I've noticed that GCC build from source includes system headers and links system libraries: $ /home/mzych/gcc/bin/g++ -x c++ -E -v - ... ---> ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/home/mzych/gcc/lib/gcc/x86_64-linux-gnu/9.0.0/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /home/mzych/gcc/lib/gcc/x86_64-linux-gnu/9.0.0/../../../../include/c++/9.0.0 /home/mzych/gcc/lib/gcc/x86_64-linux-gnu/9.0.0/../../../../include/c++/9.0.0/x86_64-linux-gnu /home/mzych/gcc/lib/gcc/x86_64-linux-gnu/9.0.0/../../../../include/c++/9.0.0/backward /home/mzych/gcc/lib/gcc/x86_64-linux-gnu/9.0.0/include ---> /usr/local/include /home/mzych/gcc/include /home/mzych/gcc/lib/gcc/x86_64-linux-gnu/9.0.0/include-fixed ---> /usr/include/x86_64-linux-gnu ---> /usr/include $ /home/mzych/gcc/bin/g++-std=c++14 -E foo.cpp # 1 "foo.cpp" ... # 1 "/home/mzych/gcc/include/c++/9.0.0/cstdint" 1 3 # 32 "/home/mzych/gcc/include/c++/9.0.0/cstdint" 3 ... ---> # 1 "/usr/include/features.h" 1 3 4 ---> # 424 "/usr/include/features.h" 3 4 ---> # 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4 ---> # 427 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4 ... I would expect GCC build from source to be standalone and independent from host machine. Mixing C++ standard library headers from GCC installed on host machine and GCC build from source can cause conflicts, because they could be in competently different versions. BTW, I observed the same behavior with link directories, which results in GCC using link directories from host machine. Am I doing something incorrectly (like not configuring GCC properly) or this is actual issue with GCC? Thanks, Mateusz