So this is an interesting one...
After commit e7a96b0b7d16 ("pinctrl: aspeed: Add multiple pin group support for functions") in -next, arm all{yes,mod}config builds started failing at link time with a lot of errors like so:
arm-linux-gnueabi-ld: drivers/pinctrl/aspeed/pinctrl-aspeed-g6.o:(.data+0x1088): multiple definition of `sig_exprs_205_GPIOZ5'; drivers/pinctrl/aspeed/pinctrl-aspeed-g4.o:(.data+0x11d4): first defined here
arm-linux-gnueabi-ld: drivers/pinctrl/aspeed/pinctrl-aspeed-g6.o:(.data+0x10a0): multiple definition of `sig_exprs_206_GPIOZ6'; drivers/pinctrl/aspeed/pinctrl-aspeed-g4.o:(.data+0x11f8): first defined here
arm-linux-gnueabi-ld: drivers/pinctrl/aspeed/pinctrl-aspeed-g6.o:(.data+0x10b8): multiple definition of `sig_exprs_207_GPIOZ7'; drivers/pinctrl/aspeed/pinctrl-aspeed-g4.o:(.data+0x121c): first defined here
This can be easily reproduced on next-20190806 and this patch (the KCFLAGS= is needed for an unrelated issue that I will try to deal with shortly):
$ make -s -j$(nproc) ARCH=arm CC=clang CROSS_COMPILE=arm-linux-gnueabi- KCFLAGS="-Wno-error=incompatible-pointer-types" O=out distclean allmodconfig vmlinux
This issue is not present with GCC. Dumping the symbol tables shows that GCC keeps the symbols local whereas Clang makes them global.
$ rg sig_exprs_20 ${TMP}
/tmp/tmp.39vwqYENfC/gcc-pinctrl-aspeed-g6.syms
2362:00001354 d sig_exprs_200_GPIOZ0
2363:0000135c d sig_exprs_200_SPI1CS1
2364:00001334 d sig_exprs_201_GPIOZ1
2365:0000133c d sig_exprs_201_SPI1ABR
2366:00001314 d sig_exprs_202_GPIOZ2
2367:0000131c d sig_exprs_202_SPI1WP
2368:000012f4 d sig_exprs_203_GPIOZ3
2369:000012fc d sig_exprs_203_SPI1CK
2370:000012d8 d sig_exprs_204_GPIOZ4
2371:000012e0 d sig_exprs_204_SPI1MOSI
2372:000012bc d sig_exprs_205_GPIOZ5
2373:000012c4 d sig_exprs_205_SPI1MISO
2374:00001298 d sig_exprs_206_GPIOZ6
2375:000012a8 d sig_exprs_206_SPI1DQ2
2376:000012a0 d sig_exprs_206_TXD13
2377:00001270 d sig_exprs_207_GPIOZ7
2378:00001278 d sig_exprs_207_RXD13
2379:00001280 d sig_exprs_207_SPI1DQ3
2380:00001238 d sig_exprs_208_GPIO18A0
2381:00001248 d sig_exprs_208_RGMII1TXCK
2382:00001240 d sig_exprs_208_RMII1RCLKO
2383:00001210 d sig_exprs_209_GPIO18A1
2384:00001220 d sig_exprs_209_RGMII1TXCTL
2385:00001218 d sig_exprs_209_RMII1TXEN
2386:00002e90 d sig_exprs_20_GPIOC4
2387:00002e98 d sig_exprs_20_RGMII3TXD2
/tmp/tmp.39vwqYENfC/clang-pinctrl-aspeed-g6.syms
2362:00001038 D sig_exprs_200_GPIOZ0
2363:00001030 D sig_exprs_200_SPI1CS1
2364:00001048 D sig_exprs_201_GPIOZ1
2365:00001040 D sig_exprs_201_SPI1ABR
2366:00001058 D sig_exprs_202_GPIOZ2
2367:00001050 D sig_exprs_202_SPI1WP
2368:00001068 D sig_exprs_203_GPIOZ3
2369:00001060 D sig_exprs_203_SPI1CK
2370:00001078 D sig_exprs_204_GPIOZ4
2371:00001070 D sig_exprs_204_SPI1MOSI
2372:00001088 D sig_exprs_205_GPIOZ5
2373:00001080 D sig_exprs_205_SPI1MISO
2374:000010a0 D sig_exprs_206_GPIOZ6
2375:00001090 D sig_exprs_206_SPI1DQ2
2376:00001098 D sig_exprs_206_TXD13
2377:000010b8 D sig_exprs_207_GPIOZ7
2378:000010b0 D sig_exprs_207_RXD13
2379:000010a8 D sig_exprs_207_SPI1DQ3
2380:000010d0 D sig_exprs_208_GPIO18A0
2381:000010c0 D sig_exprs_208_RGMII1TXCK
2382:000010c8 D sig_exprs_208_RMII1RCLKO
2383:000010e8 D sig_exprs_209_GPIO18A1
2384:000010d8 D sig_exprs_209_RGMII1TXCTL
2385:000010e0 D sig_exprs_209_RMII1TXEN
2386:000001e8 D sig_exprs_20_GPIOC4
2387:000001e0 D sig_exprs_20_RGMII3TXD2
That commit is a handful to take in but it looks like this is the problematic section according to creduce:
/**
* Create an expression symbol alias from (signal, group) to (pin, signal).
*
* @pin: The pin number
* @sig: The signal name
* @group: The name of the group of which the pin is a member that is
* associated with the function's signal
*
* Using an alias in this way enables detection of copy/paste errors (defining
* the signal for a group multiple times) whilst enabling multiple pin groups
* to exist for a signal without intrusive side-effects on defining the list of
* signals available on a pin.
*/
#define SIG_EXPR_LIST_ALIAS(pin, sig, group) \
static const struct aspeed_sig_expr *\
SIG_EXPR_LIST_SYM(pin, sig)[ARRAY_SIZE(SIG_EXPR_LIST_SYM(sig, group))] \
__attribute__((alias(istringify(SIG_EXPR_LIST_SYM(sig, group)))))
which spits out:
$ cat test.i
a, b = &a;
static c[0] __attribute__((alias("b")));
d = c;
$ arm-linux-gnueabi-gcc -O2 -c -o test.o test.i
...
$ arm-linux-gnueabi-nm test.o
00000004 C a
00000004 D b
00000004 d c
00000000 D d
$ clang -O2 -no-integrated-as --target=arm-linux-gnueabi --prefix=/home/nathan/cbl/usr/bin/ --gcc-toolchain=/home/nathan/cbl/usr -c -o test.o test.i
...
$ arm-linux-gnueabi-nm test.o
00000004 C a
00000000 D b
00000000 D c
00000004 D d
Interestingness test and full files available here.
So it looks like static and __attribute__((alias("")) is busted in Clang; I swear I've heard this issue before.
I think this happens because in clang all aliases are created with ExternalLinkage. Changing this line to use InternalLinkage instead, I can see that the output symbol is local, as expected.
It's obvious to me some checks need to be added to select the right linkage type.
That patch fixes this issue and (tentatively, haven't done a full run) doesn't introduce any immediately apparent regressions, thanks!
@arndb is asking about this in clang-9 in https://bugs.llvm.org/show_bug.cgi?id=43243
cc @zmodem
I've merged the fix to release_90 and replied on the bug. Thanks!