[RFH] "cannot apply asm label to function after its first use" on sparc64

Hello!

The stage2 builds are failing on the Linux sparc64 CI with an error message that
I don't really understand [1]:

FAILED: projects/compiler-rt/lib/sanitizer_common/CMakeFiles/RTSanitizerCommonSymbolizerNoHooks.sparc.dir/sanitizer_stackdepot.cpp.o
/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux-multistage/stage1.install/bin/clang++ -DHAVE_RPC_XDR_H=1 -D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Iprojects/compiler-rt/lib/sanitizer_common -I/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux-multistage/llvm/compiler-rt/lib/sanitizer_common -Iinclude -I/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux-multistage/llvm/llvm/include -I/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux-multistage/llvm/compiler-rt/lib/sanitizer_common/.. -fPIC -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -fdiagnostics-color -ffunction-sections -fdata-sections -Wall -std=c++14 -Wno-unused-parameter -O3 -m32 -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fno-stack-protector -fno-sanitize=safe-stack -fvisibility=hidden -fno-lto -O3 -gline-tables-only -Wno-gnu -Wno-variadic-macros -Wno-c99-extensions -nostdinc++ -fno-rtti -Wframe-larger-than=570 -Wglobal-constructors -DSANITIZER_SUPPORTS_WEAK_HOOKS=0 -UNDEBUG -std=c++14 -MD -MT projects/compiler-rt/lib/sanitizer_common/CMakeFiles/RTSanitizerCommonSymbolizerNoHooks.sparc.dir/sanitizer_stackdepot.cpp.o -MF projects/compiler-rt/lib/sanitizer_common/CMakeFiles/RTSanitizerCommonSymbolizerNoHooks.sparc.dir/sanitizer_stackdepot.cpp.o.d -o projects/compiler-rt/lib/sanitizer_common/CMakeFiles/RTSanitizerCommonSymbolizerNoHooks.sparc.dir/sanitizer_stackdepot.cpp.o -c /var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux-multistage/llvm/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
In file included from /var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux-multistage/llvm/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp:17:
In file included from /var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux-multistage/llvm/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h:16:
In file included from /usr/include/stdio.h:870:
/usr/include/bits/stdio-ldbl.h:26:20: error: cannot apply asm label to function after its first use
__LDBL_REDIR_DECL (vfprintf)
~~~~~~~~~~~~~~~~~~~^~~~~~~~~
/usr/include/sys/cdefs.h:467:26: note: expanded from macro '__LDBL_REDIR_DECL'
  extern __typeof (name) name __asm (__ASMNAME ("__nldbl_" #name));
                         ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

Does anyone have any idea what this error message actually means?

Thanks,
Adrian

My guess is that the stdio.h declaration conflicts with an earlier one in the sanitizer internal headers, in particular sanitizer_common_interceptors.inc, which has:

...

#ifdef SANITIZER_NLDBL_VERSION
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn) \
    COMMON_INTERCEPT_FUNCTION_VER(fn, SANITIZER_NLDBL_VERSION)
#else
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn) \
    COMMON_INTERCEPT_FUNCTION(fn)
#endif

...

#if SANITIZER_INTERCEPT_PRINTF
#define INIT_PRINTF \
  COMMON_INTERCEPT_FUNCTION_LDBL(printf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(sprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(snprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(asprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(fprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
#else
#define INIT_PRINTF
#endif

It would become easier to figure out where the "first use" came from, if you managed to grab the preprocessed version of sanitizer_stackdepot.cpp, for example by adding -save-temps.

-Dimitry

Hi Dimitry!

Does anyone have any idea what this error message actually means?

(...)

It would become easier to figure out where the "first use" came from, if you managed to grab
the preprocessed version of sanitizer_stackdepot.cpp, for example by adding -save-temps.

Thanks for the suggestion. I have attached the preprocessed source to the bug report now [1].

Adrian

Hi,

/usr/include/bits/stdio-ldbl.h:26:20: error: cannot apply asm label to function after its first use
__LDBL_REDIR_DECL (vfprintf)
~~~~~~~~~~~~~~~~~~~^~~~~~~~~
/usr/include/sys/cdefs.h:467:26: note: expanded from macro '__LDBL_REDIR_DECL'
   extern __typeof (name) name __asm (__ASMNAME ("__nldbl_" #name));
                          ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

Does anyone have any idea what this error message actually means?

This error message means you cannot use the asm keyword to change how the function is named in the generated assembly after you have already done something that relies on that name. For instance:

   void f();
   void g() { f(); }
   void f() asm("h"); // Bad!

Here, as soon as the compiler has seen that g calls f, the external name for f is locked in, it can no longer be changed. However:

   void f();
   void f() asm("h"); // Ok!
   void g() { f(); }

Here, although there was a previous declaration of f without the asm keyword, f has not yet been used, nothing has been done that relies on its external name, and as such its external name may still be modified.

The line marked "Bad!" is accepted by GCC, but clang is intentionally incompatible with GCC here based on the assumption that glibc does not use this pattern and no one else should either, see bug 22830. It looks like that assumption is wrong, glibc does use this pattern (still? again?) for some targets, so if it is the intention that glibc does not, this will probably need to be fixed there.

FWIW, with test.c nothing more than #include <stdio.h>:

clang -c test.c -O -D__LONG_DOUBLE_MATH_OPTIONAL -D__NO_LONG_DOUBLE_MATH

produces the same error on Ubuntu x86-64 with libc6-dev 2.32-0ubuntu3. This is not actually a valid configuration, but may be good enough to make the problem easier to track down.

Cheers,
Harald van Dijk

Hello Harald!

Yes, I do, Roland McGrath's comment on the bug that this is was unintentional on the glibc side was when he was the glibc maintainer so I think it should be safe to take that as fact. :slight_smile:

Cheers,
Harald van Dijk