
Per the GCC info page: If the function is declared 'extern', then this definition of the function is used only for inlining. In no case is the function compiled as a standalone function, not even if you take its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it. Respect that behavior for inline builtins: keep the original definition, and generate a copy of the declaration suffixed by '.inline' that's only referenced in direct call. This fixes holes in c3717b6858d32d64514a187ede1a77be8ba4e542. Differential Revision: https://reviews.llvm.org/D111009
30 lines
1.1 KiB
C
30 lines
1.1 KiB
C
// RUN: %clang_cc1 -triple x86_64 -S -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
|
|
//
|
|
// Verifies that clang-generated *.inline are flagged as internal.
|
|
|
|
typedef unsigned long size_t;
|
|
|
|
#define AVAILABLE_EXTERNALLY extern inline __attribute__((always_inline)) __attribute__((gnu_inline))
|
|
// Clang recognizes an inline builtin and renames it to memcmp.inline to prevent conflict with builtins.
|
|
AVAILABLE_EXTERNALLY int memcmp(const void *a, const void *b, size_t c) {
|
|
return __builtin_memcmp(a, b, c);
|
|
}
|
|
|
|
// CHECK: internal{{.*}}memcmp.inline
|
|
int bar(const void *a, const void *b, size_t c) {
|
|
return memcmp(a, b, c);
|
|
}
|
|
|
|
// Note that extern has been omitted here.
|
|
#define TRIPLE_INLINE inline __attribute__((always_inline)) __attribute__((gnu_inline))
|
|
|
|
// Clang recognizes an inline builtin and renames it to memcpy.inline to prevent conflict with builtins.
|
|
TRIPLE_INLINE void *memcpy(void *a, const void *b, size_t c) {
|
|
return __builtin_memcpy(a, b, c);
|
|
}
|
|
|
|
// CHECK: internal{{.*}}memcpy.inline
|
|
void *foo(void *a, const void *b, size_t c) {
|
|
return memcpy(a, b, c);
|
|
}
|