summaryrefslogtreecommitdiff
path: root/test/InterfaceStubs
diff options
context:
space:
mode:
authorPuyan Lotfi <puyan@puyan.org>2019-06-17 22:46:54 +0000
committerPuyan Lotfi <puyan@puyan.org>2019-06-17 22:46:54 +0000
commitd9cb70af7cf60498423d776efcca80e30a3e233a (patch)
tree47d179841d7311fb2bbf4df8a6bb9088c0aa54f7 /test/InterfaceStubs
parentd8450eac7b8a65d2332a074d4fdafbf4738a0b6b (diff)
downloadclang-d9cb70af7cf60498423d776efcca80e30a3e233a.tar.gz
[clang-ifs] Clang Interface Stubs, first version.
Clang interface stubs (previously referred to as clang-ifsos) is a new frontend action in clang that allows the generation of stub files that contain mangled name info that can be used to produce a stub library. These stub libraries can be useful for breaking up build dependencies and controlling access to a library's internal symbols. Generation of these stubs can be invoked by: clang -fvisibility=<visibility> -emit-interface-stubs \ -interface-stub-version=<interface format> Notice that -fvisibility (along with use of visibility attributes) can be used to control what symbols get generated. Currently the interface format is experimental but there are a wide range of possibilities here. Differential Revision: https://reviews.llvm.org/D60974 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@363626 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/InterfaceStubs')
-rw-r--r--test/InterfaceStubs/bad-format.cpp7
-rw-r--r--test/InterfaceStubs/class-template-specialization.cpp42
-rw-r--r--test/InterfaceStubs/externstatic.c29
-rw-r--r--test/InterfaceStubs/function-template-specialization.cpp41
-rw-r--r--test/InterfaceStubs/hidden-class-inheritance.cpp153
-rw-r--r--test/InterfaceStubs/inline.c67
-rw-r--r--test/InterfaceStubs/inline.h4
-rw-r--r--test/InterfaceStubs/object.cpp13
-rw-r--r--test/InterfaceStubs/template-namespace-function.cpp31
-rw-r--r--test/InterfaceStubs/virtual.cpp41
-rw-r--r--test/InterfaceStubs/visibility.cpp45
-rw-r--r--test/InterfaceStubs/weak.cpp27
12 files changed, 500 insertions, 0 deletions
diff --git a/test/InterfaceStubs/bad-format.cpp b/test/InterfaceStubs/bad-format.cpp
new file mode 100644
index 0000000000..d40b1f965b
--- /dev/null
+++ b/test/InterfaceStubs/bad-format.cpp
@@ -0,0 +1,7 @@
+// RUN: not %clang -target x86_64-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=bar-format %s 2>&1 | FileCheck %s
+
+// CHECK: error: invalid value
+// CHECK: '-interface-stub-version=<experimental-tapi-elf-v1 |
+// CHECK: experimental-yaml-elf-v1>' in 'Must specify a valid interface
+// CHECK: stub format type using
diff --git a/test/InterfaceStubs/class-template-specialization.cpp b/test/InterfaceStubs/class-template-specialization.cpp
new file mode 100644
index 0000000000..d1f1d067cc
--- /dev/null
+++ b/test/InterfaceStubs/class-template-specialization.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | \
+// RUN: FileCheck -check-prefix=CHECK-TAPI %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | \
+// RUN: FileCheck -check-prefix=CHECK-TAPI2 %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c %s | \
+// RUN: llvm-readelf -s - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-SYMBOLS %s
+
+// For the following:
+// g()
+// n::S<int>::S()
+// n::S<int>::~S()
+// n::S<int>::func() const
+// n::S<int>::S(n::S<int> const&)
+
+// We expect these manglings:
+// CHECK-TAPI: Symbols:
+// CHECK-TAPI-NOT: _ZNK1n1SIiEclEv
+// CHECK-TAPI2: Symbols:
+// CHECK-TAPI2: _Z1g
+
+// CHECK-SYMBOLS-DAG: FUNC GLOBAL DEFAULT {{[0-9]}} _Z1g
+// CHECK-SYMBOLS-DAG: FUNC WEAK HIDDEN {{[0-9]}} _ZNK1n1SIiEclEv
+
+namespace n {
+template <typename T>
+struct __attribute__((__visibility__("default"))) S {
+ S() = default;
+ ~S() = default;
+ int __attribute__((__visibility__(("default")))) func() const {
+ return 1844;
+ }
+ int __attribute__((__visibility__(("hidden")))) operator()() const {
+ return 1863;
+ }
+};
+} // namespace n
+
+void g() { n::S<int>()(); }
diff --git a/test/InterfaceStubs/externstatic.c b/test/InterfaceStubs/externstatic.c
new file mode 100644
index 0000000000..9224581ee0
--- /dev/null
+++ b/test/InterfaceStubs/externstatic.c
@@ -0,0 +1,29 @@
+// RUN: %clang -DSTORAGE="extern" -target x86_64-unknown-linux-gnu -o - \
+// RUN: -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 -std=c99 -xc %s | \
+// RUN: FileCheck -check-prefix=CHECK-EXTERN %s
+// RUN: %clang -DSTORAGE="extern" -target x86_64-linux-gnu -O0 -o - -c -std=c99 \
+// RUN: -xc %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-EXTERN %s
+
+// RUN: %clang -DSTORAGE="extern" -target x86_64-unknown-linux-gnu -o - \
+// RUN: -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 -std=c99 -xc %s | \
+// RUN: FileCheck -check-prefix=CHECK-EXTERN2 %s
+// RUN: %clang -DSTORAGE="extern" -target x86_64-linux-gnu -O0 -o - -c -std=c99 \
+// RUN: -xc %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-EXTERN2 %s
+
+// RUN: %clang -DSTORAGE="static" -target x86_64-unknown-linux-gnu -o - \
+// RUN: -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 -std=c99 -xc %s | \
+// RUN: FileCheck -check-prefix=CHECK-STATIC %s
+// RUN: %clang -DSTORAGE="static" -target x86_64-linux-gnu -O0 -o - -c -std=c99 \
+// RUN: -xc %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-STATIC %s
+
+// CHECK-EXTERN-NOT: foo
+// CHECK-STATIC-NOT: foo
+// CHECK-STATIC-NOT: bar
+
+// We want to emit extern function symbols.
+// CHECK-EXTERN2: bar
+STORAGE int foo;
+STORAGE int bar() { return 42; }
diff --git a/test/InterfaceStubs/function-template-specialization.cpp b/test/InterfaceStubs/function-template-specialization.cpp
new file mode 100644
index 0000000000..b6cf64c602
--- /dev/null
+++ b/test/InterfaceStubs/function-template-specialization.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | FileCheck %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 \
+// RUN: -DUSE_TEMPLATE_FUNCTION=1 %s | \
+// RUN: FileCheck -check-prefix=CHECK-USES-TEMPLATE-FUNCTION %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 \
+// RUN: -DSPECIALIZE_TEMPLATE_FUNCTION=1 %s | \
+// RUN: FileCheck -check-prefix=CHECK-SPECIALIZES-TEMPLATE-FUNCTION %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c \
+// RUN: %s | llvm-nm - 2>&1 | FileCheck %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c \
+// RUN: -DUSE_TEMPLATE_FUNCTION=1 %s | llvm-nm - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-USES-TEMPLATE-FUNCTION %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c \
+// RUN: -DSPECIALIZE_TEMPLATE_FUNCTION=1 %s | llvm-nm - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-SPECIALIZES-TEMPLATE-FUNCTION %s
+
+// CHECK-NOT: _Z16templateFunctionIiET_S0_
+// CHECK-USES-TEMPLATE-FUNCTION-DAG: _Z16templateFunctionIiET_S0_
+// CHECK-SPECIALIZES-TEMPLATE-FUNCTION-DAG: _Z16templateFunctionIiET_S0_
+template <typename T>
+T templateFunction(T t) { return t; }
+
+#ifdef USE_TEMPLATE_FUNCTION
+int FortyTwo = templateFunction<int>(42);
+#endif
+
+#ifdef SPECIALIZE_TEMPLATE_FUNCTION
+template <>
+int templateFunction<int>(int t);
+// TODO: Make it so that -emit-interface-stubs does not emit
+// _Z16templateFunctionIiET_S0_ if there is no user of the specialization.
+int foo() { return templateFunction(42); }
+#endif
diff --git a/test/InterfaceStubs/hidden-class-inheritance.cpp b/test/InterfaceStubs/hidden-class-inheritance.cpp
new file mode 100644
index 0000000000..de4c2993c7
--- /dev/null
+++ b/test/InterfaceStubs/hidden-class-inheritance.cpp
@@ -0,0 +1,153 @@
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 \
+// RUN: -DPARENT_CLASS_VISIBILITY="" -DCHILD_CLASS_VISIBILITY="" \
+// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
+// RUN: FileCheck -check-prefix=CHECK-X %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c \
+// RUN: -DPARENT_CLASS_VISIBILITY="" -DCHILD_CLASS_VISIBILITY="" \
+// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
+// RUN: llvm-readelf -s - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-X-RE %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 \
+// RUN: -DPARENT_CLASS_VISIBILITY=HIDDEN -DCHILD_CLASS_VISIBILITY="" \
+// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
+// RUN: FileCheck -check-prefix=CHECK-HP %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 \
+// RUN: -DPARENT_CLASS_VISIBILITY=HIDDEN -DCHILD_CLASS_VISIBILITY="" \
+// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
+// RUN: FileCheck -check-prefix=CHECK-HP2 %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c \
+// RUN: -DPARENT_CLASS_VISIBILITY=HIDDEN -DCHILD_CLASS_VISIBILITY="" \
+// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
+// RUN: llvm-readelf -s - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-HP-RE %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 \
+// RUN: -DPARENT_CLASS_VISIBILITY="" -DCHILD_CLASS_VISIBILITY=HIDDEN \
+// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
+// RUN: FileCheck -check-prefix=CHECK-HC %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 \
+// RUN: -DPARENT_CLASS_VISIBILITY="" -DCHILD_CLASS_VISIBILITY=HIDDEN \
+// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
+// RUN: FileCheck -check-prefix=CHECK-HC2 %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c \
+// RUN: -DPARENT_CLASS_VISIBILITY="" -DCHILD_CLASS_VISIBILITY=HIDDEN \
+// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
+// RUN: llvm-readelf -s - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-HC-RE %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 \
+// RUN: -DPARENT_CLASS_VISIBILITY=HIDDEN -DCHILD_CLASS_VISIBILITY=HIDDEN \
+// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
+// RUN: FileCheck -check-prefix=CHECK-HP-HC %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c \
+// RUN: -DPARENT_CLASS_VISIBILITY=HIDDEN -DCHILD_CLASS_VISIBILITY=HIDDEN \
+// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
+// RUN: llvm-readelf -s - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-HP-HC-RE %s
+
+// CHECK-X-DAG: _ZN1CC2Ev
+// CHECK-X-DAG: _ZN1CD0Ev
+// CHECK-X-DAG: _ZN1CD2Ev
+// CHECK-X-DAG: _ZN1SC2Ev
+// CHECK-X-DAG: _ZN1SD0Ev
+// CHECK-X-DAG: _ZN1SD2Ev
+// CHECK-X-DAG: _ZN1C1mEv
+// CHECK-X-DAG: _ZN1S1nEv
+
+// CHECK-X-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1C1mEv
+// CHECK-X-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1CC2Ev
+// CHECK-X-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1CD0Ev
+// CHECK-X-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1CD2Ev
+// CHECK-X-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1S1nEv
+// CHECK-X-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1SC2Ev
+// CHECK-X-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1SD0Ev
+// CHECK-X-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1SD2Ev
+
+// CHECK-HP2-DAG: _ZN1CC2Ev
+// CHECK-HP2-DAG: _ZN1CD0Ev
+// CHECK-HP2-DAG: _ZN1CD2Ev
+// CHECK-HP2-DAG: _ZN1C1mEv
+
+// CHECK-HP-NOT: _ZN1S1nEv
+// CHECK-HP-NOT: _ZN1SC2Ev
+// CHECK-HP-NOT: _ZN1SD0Ev
+// CHECK-HP-NOT: _ZN1SD2Ev
+
+// CHECK-HP-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1C1mEv
+// CHECK-HP-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1CC2Ev
+// CHECK-HP-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1CD0Ev
+// CHECK-HP-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1CD2Ev
+// CHECK-HP-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1S1nEv
+// CHECK-HP-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1SC2Ev
+// CHECK-HP-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1SD0Ev
+// CHECK-HP-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1SD2Ev
+
+// CHECK-HC2-DAG: _ZN1SC2Ev
+// CHECK-HC2-DAG: _ZN1SD0Ev
+// CHECK-HC2-DAG: _ZN1SD2Ev
+// CHECK-HC2-DAG: _ZN1S1nEv
+
+// CHECK-HC-NOT: _ZN1C1mEv
+// CHECK-HC-NOT: _ZN1CC2Ev
+// CHECK-HC-NOT: _ZN1CD0Ev
+// CHECK-HC-NOT: _ZN1CD2Ev
+
+// CHECK-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1C1mEv
+// CHECK-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1CC2Ev
+// CHECK-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1CD0Ev
+// CHECK-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1CD2Ev
+// CHECK-HC-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1S1nEv
+// CHECK-HC-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1SC2Ev
+// CHECK-HC-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1SD0Ev
+// CHECK-HC-RE: FUNC WEAK DEFAULT {{[0-9]+}} _ZN1SD2Ev
+
+// CHECK-HP-HC-NOT: _ZN1CC2Ev
+// CHECK-HP-HC-NOT: _ZN1CD0Ev
+// CHECK-HP-HC-NOT: _ZN1CD2Ev
+// CHECK-HP-HC-NOT: _ZN1SC2Ev
+// CHECK-HP-HC-NOT: _ZN1SD0Ev
+// CHECK-HP-HC-NOT: _ZN1SD2Ev
+// CHECK-HP-HC-NOT: _ZN1C1mEv
+// CHECK-HP-HC-NOT: _ZN1S1nEv
+
+// CHECK-HP-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1C1mEv
+// CHECK-HP-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1CC2Ev
+// CHECK-HP-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1CD0Ev
+// CHECK-HP-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1CD2Ev
+// CHECK-HP-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1S1nEv
+// CHECK-HP-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1SC2Ev
+// CHECK-HP-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1SD0Ev
+// CHECK-HP-HC-RE: FUNC WEAK HIDDEN {{[0-9]+}} _ZN1SD2Ev
+
+// TODO: clang+llvm does not materialize complete ctors and dtors for the
+// Itanium abi. Figure out why and add the check-not for these:
+// _ZN1CC1Ev
+// _ZN1CD1Ev
+// _ZN1SC1Ev
+// _ZN1SD1Ev
+
+#define HIDDEN __attribute__((__visibility__("hidden")))
+#define DEFAULT __attribute__((__visibility__("default")))
+
+struct PARENT_CLASS_VISIBILITY S {
+ virtual ~S() {}
+ virtual PARENT_METHOD_VISIBILITY void n() {}
+};
+
+class CHILD_CLASS_VISIBILITY C : public S {
+public:
+ virtual CHILD_METHOD_VISIBILITY void m() {}
+};
+
+void f() {
+ C c;
+ c.m();
+ c.n();
+}
diff --git a/test/InterfaceStubs/inline.c b/test/InterfaceStubs/inline.c
new file mode 100644
index 0000000000..c64771185f
--- /dev/null
+++ b/test/InterfaceStubs/inline.c
@@ -0,0 +1,67 @@
+// RUN: %clang -DINLINE=inline -target x86_64-unknown-linux-gnu -o - \
+// RUN: -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 -std=gnu89 -xc %s | \
+// RUN: FileCheck -check-prefix=CHECK-GNU %s
+// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -O0 -o - -c \
+// RUN: -std=gnu89 -xc %s | llvm-nm - | FileCheck -check-prefix=CHECK-GNU %s
+
+// RUN: %clang -DINLINE="__attribute__((always_inline))" \
+// RUN: -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 -xc %s | \
+// RUN: FileCheck -check-prefix=CHECK-GNU %s
+// RUN: %clang -DINLINE="__attribute__((always_inline))" \
+// RUN: -target x86_64-linux-gnu -O0 -o - -c -xc %s | \
+// RUN: llvm-nm - | FileCheck -check-prefix=CHECK-GNU %s
+
+// RUN: %clang -DINLINE=inline -target x86_64-unknown-linux-gnu -o - \
+// RUN: -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 -std=c99 -xc %s | \
+// RUN: FileCheck -check-prefix=CHECK-STD %s
+// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -O0 -o - -c -std=c99 \
+// RUN: -xc %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-STD %s
+
+// RUN: %clang -DINLINE="__attribute__((noinline))" \
+// RUN: -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 -std=c99 -xc %s | \
+// RUN: FileCheck -check-prefix=CHECK-NOINLINE %s
+// RUN: %clang -DINLINE="__attribute__((noinline))" -target x86_64-linux-gnu \
+// RUN: -O0 -o - -c -std=c99 -xc %s | llvm-nm - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-NOINLINE %s
+
+// RUN: %clang -DINLINE="static" -target x86_64-unknown-linux-gnu -o - \
+// RUN: -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 -std=c99 -xc %s | \
+// RUN: FileCheck -check-prefix=CHECK-STATIC %s
+// RUN: %clang -DINLINE="static" -target x86_64-linux-gnu -O0 -o - -c \
+// RUN: -std=c99 -xc %s | llvm-nm - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-STATIC %s
+
+// CHECK-GNU-DAG: foo
+// CHECK-GNU-DAG: foo.var
+// CHECK-NOINLINE-DAG: foo
+// CHECK-NOINLINE-DAG: foo.var
+// CHECK-STATIC-NOT: foo
+// CHECK-STATIC-NOT: foo.var
+// CHECK-STD-NOT: foo
+#pragma clang diagnostic ignored "-Wstatic-local-in-inline"
+INLINE int foo() {
+ static int var = 42;
+ return var;
+}
+
+// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -o - \
+// RUN: -emit-interface-stubs -interface-stub-version=experimental-tapi-elf-v1 \
+// RUN: -std=gnu89 -xc %s | FileCheck -check-prefix=CHECK-TAPI %s
+
+// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -o - \
+// RUN: -emit-interface-stubs -interface-stub-version=experimental-tapi-elf-v1 \
+// RUN: -std=gnu89 -xc %s | FileCheck -check-prefix=CHECK-SYMBOLS %s
+// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -o - \
+// RUN: -c -std=gnu89 -xc %s | llvm-nm - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-SYMBOLS %s
+
+// CHECK-TAPI-DAG: foo: { Type: Func }
+// CHECK-TAPI-DAG: foo.var: { Type: Object, Size: 4 }
+// CHECK-SYMBOLS-DAG: foo
+// CHECK-SYMBOLS-DAG: foo.var
+#include "inline.h"
diff --git a/test/InterfaceStubs/inline.h b/test/InterfaceStubs/inline.h
new file mode 100644
index 0000000000..fe16519e94
--- /dev/null
+++ b/test/InterfaceStubs/inline.h
@@ -0,0 +1,4 @@
+INLINE int bar() {
+ static int var = 42;
+ return var;
+}
diff --git a/test/InterfaceStubs/object.cpp b/test/InterfaceStubs/object.cpp
new file mode 100644
index 0000000000..68b5ee781c
--- /dev/null
+++ b/test/InterfaceStubs/object.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | \
+// RUN: FileCheck -check-prefix=CHECK-TAPI %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | \
+// RUN: FileCheck -check-prefix=CHECK-SYMBOLS %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c %s | llvm-nm - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-SYMBOLS %s
+
+// CHECK-TAPI: data: { Type: Object, Size: 4 }
+// CHECK-SYMBOLS: data
+int data = 42;
diff --git a/test/InterfaceStubs/template-namespace-function.cpp b/test/InterfaceStubs/template-namespace-function.cpp
new file mode 100644
index 0000000000..879318122b
--- /dev/null
+++ b/test/InterfaceStubs/template-namespace-function.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | \
+// RUN: FileCheck %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c %s | llvm-nm - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-SYMBOLS %s
+
+// CHECK: Symbols:
+// CHECK-DAG: _ZN3qux3barEii: { Type: Func }
+// CHECK-DAG: _ZN3baz3addIiEET_S1_S1_: { Type: Func }
+// CHECK-DAG: _Z4fbarff: { Type: Func }
+// CHECK-DAG: _ZN3baz3addIfEET_S1_S1_: { Type: Func }
+
+// Same symbols just different order.
+// CHECK-SYMBOLS-DAG: _Z4fbarff
+// CHECK-SYMBOLS-DAG: _ZN3baz3addIfEET_S1_S1_
+// CHECK-SYMBOLS-DAG: _ZN3baz3addIiEET_S1_S1_
+// CHECK-SYMBOLS-DAG: _ZN3qux3barEii
+
+namespace baz {
+template <typename T>
+T add(T a, T b) {
+ return a + b;
+}
+} // namespace baz
+
+namespace qux {
+int bar(int a, int b) { return baz::add<int>(a, b); }
+} // namespace qux
+
+float fbar(float a, float b) { return baz::add<float>(a, b); }
diff --git a/test/InterfaceStubs/virtual.cpp b/test/InterfaceStubs/virtual.cpp
new file mode 100644
index 0000000000..b861b7e802
--- /dev/null
+++ b/test/InterfaceStubs/virtual.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | \
+// RUN: FileCheck -check-prefix=CHECK-TAPI %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | \
+// RUN: FileCheck -check-prefix=CHECK-TAPI2 %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c %s | \
+// RUN: llvm-readelf -s - 2>&1 | FileCheck -check-prefix=CHECK-SYMBOLS %s
+
+#define HIDDEN __attribute__((__visibility__(("hidden"))))
+#define DEFAULT __attribute__((__visibility__(("default"))))
+
+// CHECK-TAPI-NOT: _ZNK1Q5func1Ev
+// CHECK-TAPI-NOT: _ZNK1Q5func2Ev
+// CHECK-SYMBOLS-DAG: NOTYPE GLOBAL HIDDEN {{.*}} _ZNK1Q5func1Ev
+// CHECK-SYMBOLS-DAG: NOTYPE GLOBAL DEFAULT {{.*}} _ZNK1Q5func2Ev
+struct Q {
+ virtual HIDDEN int func1() const;
+ virtual DEFAULT int func2() const;
+} q;
+
+// CHECK-TAPI-NOT: _ZNK1S5func1Ev
+// CHECK-TAPI2-DAG: _ZNK1S5func2Ev
+// CHECK-SYMBOLS-DAG: FUNC WEAK HIDDEN {{.*}} _ZNK1S5func1Ev
+// CHECK-SYMBOLS-DAG: FUNC WEAK DEFAULT {{.*}} _ZNK1S5func2Ev
+struct S {
+ virtual HIDDEN int func1() const { return 42; }
+ virtual DEFAULT int func2() const { return 42; }
+} s;
+
+// CHECK-TAPI-NOT: _ZNK1R5func1Ev
+// CHECK-TAPI-NOT: _ZNK1R5func2Ev
+// CHECK-SYMBOLS-NOT: _ZNK1R5func1Ev
+// CHECK-SYMBOLS-NOT: _ZNK1R5func2Ev
+struct R {
+ virtual HIDDEN int func1() const = 0;
+ virtual DEFAULT int func2() const = 0;
+};
+
+int a = q.func1() + q.func2();
+
diff --git a/test/InterfaceStubs/visibility.cpp b/test/InterfaceStubs/visibility.cpp
new file mode 100644
index 0000000000..87ea7ea7bd
--- /dev/null
+++ b/test/InterfaceStubs/visibility.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 -fvisibility=hidden \
+// RUN: %s | FileCheck --check-prefix=CHECK-CMD-HIDDEN %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 -fvisibility=hidden \
+// RUN: %s | FileCheck --check-prefix=CHECK-CMD-HIDDEN %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | \
+// RUN: FileCheck --check-prefix=CHECK-CMD %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 %s | \
+// RUN: FileCheck --check-prefix=CHECK-CMD %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | \
+// RUN: FileCheck --check-prefix=CHECK-CMD2 %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 %s | \
+// RUN: FileCheck --check-prefix=CHECK-CMD2 %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c %s | llvm-readelf -s - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-SYMBOLS %s
+
+// Always Be Hidden:
+// CHECK-CMD-HIDDEN-NOT: _Z6hiddenv
+// CHECK-CMD2-NOT: _Z6hiddenv
+__attribute__((visibility("hidden"))) void hidden() {}
+
+// Always Be Visible:
+// CHECK-CMD-HIDDEN: _Z9nothiddenv
+// CHECK-CMD-DAG: _Z9nothiddenv
+__attribute__((visibility("default"))) void nothidden() {}
+
+// Do Whatever -fvisibility says:
+// CHECK-CMD-HIDDEN-NOT: _Z10cmdVisiblev
+// CHECK-CMD-DAG: _Z10cmdVisiblev
+void cmdVisible() {}
+
+// CHECK-SYMBOLS-DAG: DEFAULT {{.*}} _Z10cmdVisiblev
+// CHECK-SYMBOLS-DAG: HIDDEN {{.*}} _Z6hiddenv
+// CHECK-SYMBOLS-DAG: DEFAULT {{.*}} _Z9nothiddenv
diff --git a/test/InterfaceStubs/weak.cpp b/test/InterfaceStubs/weak.cpp
new file mode 100644
index 0000000000..e089225b5d
--- /dev/null
+++ b/test/InterfaceStubs/weak.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang -target x86_64-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s | \
+// RUN: FileCheck %s
+
+// RUN: %clang -target x86_64-linux-gnu -o - -emit-interface-stubs \
+// RUN: -interface-stub-version=experimental-yaml-elf-v1 %s | \
+// RUN: FileCheck --check-prefix=CHECK-YAML %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c %s | llvm-nm - 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-SYMBOLS %s
+
+// CHECK: Symbols:
+// CHECK-DAG: _Z8weakFuncv: { Type: Func, Weak: true }
+// CHECK-DAG: _Z10strongFuncv: { Type: Func }
+
+// CHECK-YAML: Symbols:
+// CHECK-YAML-DAG: - Name: _Z8weakFuncv
+// CHECK-YAML-DAG: Type: STT_FUNC
+// CHECK-YAML-DAG: Binding: STB_WEAK
+// CHECK-YAML-DAG: - Name: _Z10strongFuncv
+// CHECK-YAML-DAG: Type: STT_FUNC
+// CHECK-YAML-DAG: Binding: STB_GLOBAL
+
+// CHECK-SYMBOLS-DAG: _Z10strongFuncv
+// CHECK-SYMBOLS-DAG: _Z8weakFuncv
+__attribute__((weak)) void weakFunc() {}
+int strongFunc() { return 42; }