summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/ext/visibility
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/g++.dg/ext/visibility')
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon1.C10
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon10.C44
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon11.C13
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon2.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon3.C16
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon4.C16
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon5.C8
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon6.C28
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon7.C23
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon8.C35
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon9.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/arm1.C30
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/arm2.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/arm3.C36
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/assign1.C18
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/class1.C22
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-2.C19
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-3.C30
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden.C18
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/fvisibility-override1.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/fvisibility-override2.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/fvisibility.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/guard1.C29
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/local1.C25
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/memfuncts.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/ms-compat-1.C28
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/namespace1.C30
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/namespace2.C20
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/namespace3.C6
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/new1.C13
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/noPLT.C20
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/overload-1.C9
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/pragma-override1.C14
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/pragma-override2.C14
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/pragma.C13
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/prop1.C23
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/redecl1.C7
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/staticdatamem.C20
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/staticmemfuncts.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/symbian1.C22
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/symbian2.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/template1.C35
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/template2.C35
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/template3.C22
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/template4.C39
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/template6.C17
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/typeinfo1.C19
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/typeinfo2.C23
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/typeinfo3.C24
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/virtual.C17
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-1.C8
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-10.C19
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-11.C18
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-2.C7
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-3.C7
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-4.C8
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-5.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-6.C10
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-7.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-8.C56
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-9.C29
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/warn2.C16
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/warn3.C26
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/warn4.C10
64 files changed, 1228 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon1.C b/gcc/testsuite/g++.dg/ext/visibility/anon1.C
new file mode 100644
index 000000000..16647b228
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon1.C
@@ -0,0 +1,10 @@
+// PR c++/21581
+// Test for anonymous namespace internal linkage
+
+// { dg-do compile }
+// { dg-final { scan-assembler-not "globl.*_ZN.*1fEv" } }
+
+namespace
+{
+ int f() { }
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon10.C b/gcc/testsuite/g++.dg/ext/visibility/anon10.C
new file mode 100644
index 000000000..8c79631b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon10.C
@@ -0,0 +1,44 @@
+// http://bugzilla.redhat.com/411871
+// { dg-do compile }
+
+extern "C" int printf (const char *, ...);
+
+struct E
+{
+ template <typename T> E (const volatile T&);
+ template <typename T> E (T&);
+ char x[64];
+};
+
+template<typename T> struct D
+{
+ static E foo (E, ...);
+ static int foo (T, int);
+};
+
+template<typename T, typename U> struct C
+{
+ static T ca;
+ static const int value = sizeof (D<U>::foo (ca, 0)) == sizeof (int);
+};
+
+struct A
+{
+ int a;
+};
+
+namespace
+{
+ struct B
+ {
+ int a;
+ };
+}
+
+int bar (void)
+{
+ C<A, int> a;
+ C<B, int> b;
+
+ return a.value + b.value;
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon11.C b/gcc/testsuite/g++.dg/ext/visibility/anon11.C
new file mode 100644
index 000000000..dfb4f12bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon11.C
@@ -0,0 +1,13 @@
+// PR c++/55877
+// { dg-final { scan-assembler-not "\\.local" } }
+
+typedef struct {
+ typedef enum { X, Y } A;
+ typedef struct { } B;
+ struct C { };
+} D;
+
+D d;
+D::A a;
+D::B b;
+D::C c;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon2.C b/gcc/testsuite/g++.dg/ext/visibility/anon2.C
new file mode 100644
index 000000000..1d8e479b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon2.C
@@ -0,0 +1,11 @@
+// Test for propagation of anonymous namespace internal linkage
+
+// { dg-do compile }
+// { dg-final { scan-assembler-not "globl.*_Z1fv" } }
+
+namespace
+{
+ struct A { };
+}
+
+A f () { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon3.C b/gcc/testsuite/g++.dg/ext/visibility/anon3.C
new file mode 100644
index 000000000..9def559d2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon3.C
@@ -0,0 +1,16 @@
+// PR c++/31187
+// Bug: the repeated declaration was confusing the compiler into
+// thinking that foo1 had language internal linkage.
+
+class foo { };
+
+namespace
+{
+ extern foo foo1;
+ foo foo1;
+}
+
+template< foo * >
+class bar { };
+
+bar< &foo1 > bar1;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon4.C b/gcc/testsuite/g++.dg/ext/visibility/anon4.C
new file mode 100644
index 000000000..6d5d58ec3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon4.C
@@ -0,0 +1,16 @@
+// PR c++/31903
+// Test for anonymous namespace internal linkage, for typeinfo
+
+// { dg-do compile }
+// { dg-final { scan-assembler-not "globl.*_ZTIN*3fooE" } }
+
+#include <typeinfo>
+namespace
+{
+ class foo
+ {
+ virtual void bar();
+ };
+}
+
+const std::type_info &X = typeid(foo);
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon5.C b/gcc/testsuite/g++.dg/ext/visibility/anon5.C
new file mode 100644
index 000000000..d069eeab6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon5.C
@@ -0,0 +1,8 @@
+// PR c++/32596
+// { dg-do compile }
+
+namespace
+{
+ template<class T> inline void char_less(void) { }
+ template<> inline void char_less<char>(void) { }
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon6.C b/gcc/testsuite/g++.dg/ext/visibility/anon6.C
new file mode 100644
index 000000000..951de4964
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon6.C
@@ -0,0 +1,28 @@
+// PR c++/33094
+// { dg-final { scan-assembler "1BIiE1cE" } }
+// { dg-final { scan-assembler-not "globl.*1BIiE1cE" } }
+// { dg-final { scan-assembler-not "1CIiE1cE" } }
+
+// Test that B<int>::c is emitted as an internal symbol, and C<int>::c is
+// not emitted.
+
+namespace
+{
+ template <typename T>
+ class A
+ {
+ virtual T f1() { return c; }
+ static const T c = 0;
+ };
+
+ template <typename T>
+ class B
+ {
+ static const T c = 0;
+ };
+
+ template <typename T> const T B<T>::c;
+
+ template class A<int>;
+ template class B<int>;
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon7.C b/gcc/testsuite/g++.dg/ext/visibility/anon7.C
new file mode 100644
index 000000000..0c42ea866
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon7.C
@@ -0,0 +1,23 @@
+// PR c++/34094
+// { dg-do compile }
+
+namespace
+{
+ struct A {
+ static int bar ();
+ static int i; // { dg-error "used, but not defined" "" { xfail *-*-* } }
+ static int j;
+ static int k;
+ static int l;
+ static const int m = 16;
+ static const int n = 17;
+ };
+ int A::j = 4;
+ int A::k;
+ const int A::m;
+}
+
+int foo (void)
+{
+ return A::i + A::j + A::k + A::m + A::n + A::bar ();
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon8.C b/gcc/testsuite/g++.dg/ext/visibility/anon8.C
new file mode 100644
index 000000000..8ef8d6823
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon8.C
@@ -0,0 +1,35 @@
+// PR c++/34213
+// { dg-do compile }
+
+template <void (*fn) ()>
+void call () // { dg-message "note" }
+{
+ fn ();
+}
+
+namespace
+{
+ struct B1
+ {
+ static void fn1 () {}
+ static void fn4 ();
+ };
+ void fn3 () {}
+ void B1::fn4 () {}
+ static void fn5 () {}
+}
+
+int main ()
+{
+ struct B2
+ {
+ static void fn2 () {}
+ };
+ call<&B1::fn1> ();
+ call<&B2::fn2> (); // { dg-error "not external linkage|no matching" }
+ // { dg-message "candidate" "candidate note" { target *-*-* } 29 }
+ call<&fn3> ();
+ call<&B1::fn4> ();
+ call<&fn5> (); // { dg-error "not external linkage|no matching" }
+ // { dg-message "candidate" "candidate note" { target *-*-* } 33 }
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon9.C b/gcc/testsuite/g++.dg/ext/visibility/anon9.C
new file mode 100644
index 000000000..bb752253b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon9.C
@@ -0,0 +1,11 @@
+// PR c++/34238
+// { dg-do compile }
+
+namespace
+{
+ template <typename T = int> struct A
+ {
+ static const bool a = true;
+ };
+}
+struct A<> a;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/arm1.C b/gcc/testsuite/g++.dg/ext/visibility/arm1.C
new file mode 100644
index 000000000..2c2e3d066
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/arm1.C
@@ -0,0 +1,30 @@
+// { dg-do compile { target arm*-*-eabi* arm*-*-symbianelf* } }
+// { dg-require-dll "" }
+// { dg-options "-fvisibility=hidden" }
+// Most class data should be exported.
+// { dg-final { scan-not-hidden "_ZTV1S" } }
+// { dg-final { scan-not-hidden "_ZTI1S" } }
+// { dg-final { scan-not-hidden "_ZTS1S" } }
+// { dg-final { scan-not-hidden "_ZTV1U" } }
+// { dg-final { scan-not-hidden "_ZTT1U" } }
+// { dg-final { scan-not-hidden "_ZTI1U" } }
+// { dg-final { scan-not-hidden "_ZTS1U" } }
+// The construction vtable should be hidden.
+// { dg-final { scan-hidden "_ZTC1U0_1T" } }
+
+struct S {
+ virtual void f();
+};
+
+void S::f() {
+}
+
+struct T : public virtual S {
+ virtual void g();
+};
+
+struct U : public virtual T {
+ virtual void h();
+};
+
+void U::h() {}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/arm2.C b/gcc/testsuite/g++.dg/ext/visibility/arm2.C
new file mode 100644
index 000000000..7eed18d7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/arm2.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target arm*-*-*eabi* arm*-*-symbianelf* } }
+// Class data should be exported.
+// { dg-final { scan-not-hidden "_ZTV1S" } }
+// { dg-final { scan-not-hidden "_ZTI1S" } }
+// { dg-final { scan-not-hidden "_ZTS1S" } }
+
+struct S {
+ virtual void f();
+};
+
+void S::f() {}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/arm3.C b/gcc/testsuite/g++.dg/ext/visibility/arm3.C
new file mode 100644
index 000000000..9be7082ce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/arm3.C
@@ -0,0 +1,36 @@
+// { dg-do compile { target arm*-*-*eabi* } }
+// { dg-require-dll "" }
+// { dg-options "-fvisibility=hidden" }
+
+/* From ARM C++ ABI \S 3.2.5.5:
+
+ A class should be exported unless explicitly tagged otherwise.
+
+ This admonition applies even on DLL-based systems where hidden
+ visibility is the default. We want -fvisibility=hidden to behave
+ identically to the situation where hidden visibility is the
+ hard-wired default. So, both A and B are exported classes.
+
+ Furthermore:
+
+ If CAG symbol Y names one of the impedimenta associated with an
+ exported class X:
+
+ ...
+
+ * Otherwise, if X has no key function:
+
+ - Y is exported from ... each DLL that refers to X and uses Y.
+
+ So, the type-info and virtual-table symbols associated with A and B
+ must be exported. */
+
+// { dg-final { scan-not-hidden "_ZTI1A" } }
+// { dg-final { scan-not-hidden "_ZTS1A" } }
+// { dg-final { scan-not-hidden "_ZTV1B" } }
+// { dg-final { scan-not-hidden "_ZTI1B" } }
+// { dg-final { scan-not-hidden "_ZTS1B" } }
+
+struct A {};
+struct B : virtual public A {};
+B b;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/assign1.C b/gcc/testsuite/g++.dg/ext/visibility/assign1.C
new file mode 100644
index 000000000..b25999e8e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/assign1.C
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-final { scan-hidden "_ZN1DaSERKS_" } } */
+
+struct B {
+ B& operator=(const B&);
+};
+
+struct __attribute__((visibility("hidden"))) D : public B {
+ // The implicit assignment operator should be hidden.
+};
+
+__attribute__((visibility("hidden"))) D d1;
+__attribute__((visibility("hidden"))) D d2;
+
+void f() {
+ d1 = d2;
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/class1.C b/gcc/testsuite/g++.dg/ext/visibility/class1.C
new file mode 100644
index 000000000..792fc7891
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/class1.C
@@ -0,0 +1,22 @@
+// PR c++/26905
+// Init should not be hidden, so calling it should use the PLT.
+
+// { dg-options "-fpic" }
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-skip-if "" { *-*-darwin* } { "*" } { "" } }
+// { dg-require-visibility "" }
+// { dg-require-effective-target fpic }
+// { dg-final { scan-assembler "InitEv@PLT" } }
+
+#pragma GCC visibility push(hidden)
+struct __attribute__ ((visibility ("default"))) nsINIParser
+{
+ static void Init();
+};
+
+__attribute__ ((visibility ("default")))
+void
+CheckCompatibility(void)
+{
+ nsINIParser::Init();
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-2.C b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-2.C
new file mode 100644
index 000000000..ed38ebefe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-2.C
@@ -0,0 +1,19 @@
+/* Test that -fvisibility-inlines-hidden doesn't affect static variables. */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-fvisibility-inlines-hidden" } */
+/* { dg-final { scan-not-hidden "_ZZN3foo7my_funcEvE1x" } } */
+
+struct foo
+{
+ int my_func() {
+ static int x;
+ return x++;
+ }
+};
+
+int t()
+{
+ foo f;
+ return f.my_func();
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-3.C b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-3.C
new file mode 100644
index 000000000..50885a798
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-3.C
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-fvisibility-inlines-hidden" } */
+/* { dg-final { scan-not-hidden "_ZN1IIiE3fooEv" } } */
+/* { dg-final { scan-not-hidden "_ZN1OIiE3fooEv" } } */
+/* { dg-final { scan-hidden "_ZN1S3fooEv" } } */
+
+template <class T>
+struct O {
+ static inline void foo() { }
+};
+
+template void O<int>::foo();
+
+template <class T>
+struct I {
+ static inline void foo() { }
+};
+
+extern template void I<int>::foo();
+
+struct S {
+ static inline void foo() { }
+};
+
+void bar() {
+ I<int>::foo();
+ O<int>::foo();
+ S::foo();
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden.C b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden.C
new file mode 100644
index 000000000..2ee8f0767
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden.C
@@ -0,0 +1,18 @@
+/* Test that -fvisibility-inlines-hidden affects class members. */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-fvisibility-inlines-hidden" } */
+/* { dg-final { scan-hidden "_ZN3Foo6methodEv" } } */
+
+class Foo
+{
+public:
+ void method() { }
+};
+
+int main(void)
+{
+ Foo f;
+ f.method();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/fvisibility-override1.C b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-override1.C
new file mode 100644
index 000000000..685cd1309
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-override1.C
@@ -0,0 +1,12 @@
+/* Test that -fvisibility does not override class member specific settings. */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-fvisibility=hidden" } */
+/* { dg-final { scan-not-hidden "methodEv" } } */
+
+class __attribute__ ((visibility ("default"))) Foo
+{
+ void method();
+};
+
+void Foo::method() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/fvisibility-override2.C b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-override2.C
new file mode 100644
index 000000000..4b4b54d5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-override2.C
@@ -0,0 +1,12 @@
+/* Test that -fvisibility does not override class member specific settings. */
+/* { dg-do compile } */
+/* { dg-require-visibility "internal" } */
+/* { dg-options "-fvisibility=hidden" } */
+/* { dg-final { scan-not-hidden "Foo.methodEv" } } */
+
+class Foo
+{
+ __attribute__ ((visibility ("internal"))) void method();
+};
+
+void Foo::method() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/fvisibility.C b/gcc/testsuite/g++.dg/ext/visibility/fvisibility.C
new file mode 100644
index 000000000..4358d25a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/fvisibility.C
@@ -0,0 +1,12 @@
+/* Test that -fvisibility affects class members. */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-fvisibility=hidden" } */
+/* { dg-final { scan-hidden "_ZN3Foo6methodEv" } } */
+
+class Foo
+{
+ void method();
+};
+
+void Foo::method() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/guard1.C b/gcc/testsuite/g++.dg/ext/visibility/guard1.C
new file mode 100644
index 000000000..5290e2f8e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/guard1.C
@@ -0,0 +1,29 @@
+// { dg-options "-fvisibility=hidden" }
+// { dg-require-visibility "" }
+// { dg-final { scan-not-hidden "_ZGVZN5otherclEvE4s_cd" } }
+
+extern "C" int printf (const char *, ...);
+
+#define DLLEXPORT __attribute__ ((visibility("default")))
+
+struct class_data
+{
+ int apple;
+ class_data() { printf("non trivial ctor\n"); }
+};
+
+struct DLLEXPORT other
+{
+ class_data* operator ()()
+ {
+ static class_data s_cd;
+ return &s_cd;
+ }
+};
+
+int main()
+{
+ other aFoo;
+ aFoo();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/local1.C b/gcc/testsuite/g++.dg/ext/visibility/local1.C
new file mode 100644
index 000000000..7a04db601
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/local1.C
@@ -0,0 +1,25 @@
+// PR c++/19238
+// Test that hidden visibility on an inline function is inherited by static
+// local variables and local classes.
+
+// { dg-require-visibility "" }
+// { dg-final { scan-hidden "_Z1fv" } }
+// { dg-final { scan-hidden "_ZZ1fvE1i" } }
+// { dg-final { scan-hidden "_ZZ1fvEN1A1fEv" } }
+
+__attribute ((visibility ("hidden"))) inline int
+f()
+{
+ static int i = 2;
+ struct A
+ {
+ void f () { }
+ } a;
+ a.f();
+ return i;
+}
+
+int main()
+{
+ f();
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/memfuncts.C b/gcc/testsuite/g++.dg/ext/visibility/memfuncts.C
new file mode 100644
index 000000000..45eb641b2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/memfuncts.C
@@ -0,0 +1,11 @@
+/* Test that setting visibility for class member functions works. */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-final { scan-hidden "_ZN3Foo6methodEv" } } */
+
+class __attribute__ ((visibility ("hidden"))) Foo
+{
+ void method();
+};
+
+void Foo::method() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/ms-compat-1.C b/gcc/testsuite/g++.dg/ext/visibility/ms-compat-1.C
new file mode 100644
index 000000000..bce2aac55
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/ms-compat-1.C
@@ -0,0 +1,28 @@
+/* { dg-require-visibility "" } */
+/* { dg-options "-fvisibility-ms-compat" } */
+
+/* { dg-final { scan-not-hidden "_ZTI1S" } } */
+/* { dg-final { scan-hidden "_ZTI1T" } } */
+/* { dg-final { scan-not-hidden "_ZTI1U" } } */
+/* { dg-final { scan-not-hidden "_ZN1U6hide_4Ev" } } */
+
+class S {
+ virtual void hide_2();
+} hide_1;
+
+void S::hide_2() {
+}
+
+class __attribute__((visibility("hidden"))) T {
+ virtual void hide_4();
+} hide_3;
+
+void T::hide_4() {
+}
+
+class __attribute__((visibility("default"))) U {
+ virtual void hide_4();
+};
+
+void U::hide_4() {
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/namespace1.C b/gcc/testsuite/g++.dg/ext/visibility/namespace1.C
new file mode 100644
index 000000000..b7773dc9d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/namespace1.C
@@ -0,0 +1,30 @@
+// PR c++/21764
+// Test for namespace visibility attribute semantics.
+
+// { dg-require-visibility "" }
+// { dg-final { scan-hidden "_ZN3foo1fEv" } }
+// { dg-final { scan-hidden "_ZN3foo1gEv" } }
+// { dg-final { scan-hidden "_ZN3foo1A1mEv" } }
+// { dg-final { scan-hidden "_ZN3foo1tIiEEvv" } }
+// { dg-final { scan-not-hidden "_ZN3foo1hEv" } }
+
+namespace foo __attribute ((visibility ("hidden")))
+{
+ int f() { }
+ void g();
+ template <typename T> void t() { }
+ class A
+ {
+ void m ();
+ };
+}
+
+namespace foo
+{
+ void h() {}
+}
+
+void foo::g() { t<int> (); }
+
+void foo::A::m() { }
+
diff --git a/gcc/testsuite/g++.dg/ext/visibility/namespace2.C b/gcc/testsuite/g++.dg/ext/visibility/namespace2.C
new file mode 100644
index 000000000..96c5b0953
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/namespace2.C
@@ -0,0 +1,20 @@
+// PR c++/32470
+
+// { dg-require-visibility "" }
+// { dg-options "-fvisibility=hidden" }
+// { dg-final { scan-hidden "_ZN4Test4testEv" } }
+
+namespace std __attribute__((__visibility__("default"))) {
+ template<typename _CharT>
+ class basic_streambuf
+ {
+ friend void getline();
+ };
+ extern template class basic_streambuf<char>;
+}
+
+class Test
+{
+ void test();
+};
+void Test::test() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/namespace3.C b/gcc/testsuite/g++.dg/ext/visibility/namespace3.C
new file mode 100644
index 000000000..a07abdcd8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/namespace3.C
@@ -0,0 +1,6 @@
+// PR c++/41774
+// { dg-do compile }
+
+namespace std __attribute__ ((__visibility__ ("default"))) {
+#pragma GCC visibility pop // { dg-warning "no matching push for" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/new1.C b/gcc/testsuite/g++.dg/ext/visibility/new1.C
new file mode 100644
index 000000000..ec201cbc2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/new1.C
@@ -0,0 +1,13 @@
+// { dg-require-visibility "" }
+// { dg-options "-fvisibility=hidden" }
+// { dg-final { scan-not-hidden "_Znwj" } }
+
+void f() {
+ new int;
+}
+
+void *g();
+
+void *operator new(__SIZE_TYPE__) {
+ return g();
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/noPLT.C b/gcc/testsuite/g++.dg/ext/visibility/noPLT.C
new file mode 100644
index 000000000..38af05fd6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/noPLT.C
@@ -0,0 +1,20 @@
+/* Test that -fvisibility=hidden prevents PLT. */
+/* { dg-do compile { target fpic } } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-fPIC -fvisibility=hidden" } */
+/* { dg-final { scan-assembler-not "methodEv@PLT|indirect_symbol.*methodEv" } } */
+
+class Foo
+{
+public:
+ void method();
+};
+
+void Foo::method() { }
+
+int main(void)
+{
+ Foo f;
+ f.method();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/overload-1.C b/gcc/testsuite/g++.dg/ext/visibility/overload-1.C
new file mode 100644
index 000000000..d841c53fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/overload-1.C
@@ -0,0 +1,9 @@
+/* Test that visibility of function parameters propagates to an undecorated
+ function. */
+/* { dg-require-visibility "" }
+/* { dg-final { scan-hidden "_Z3fooP8a_struct" } } */
+
+struct __attribute__((visibility("hidden"))) a_struct;
+
+void foo(a_struct * p)
+{ }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/pragma-override1.C b/gcc/testsuite/g++.dg/ext/visibility/pragma-override1.C
new file mode 100644
index 000000000..4300d1ab1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/pragma-override1.C
@@ -0,0 +1,14 @@
+/* Test that #pragma GCC visibility does not override class member specific settings. */
+/* { dg-do compile } */
+/* { dg-require-visibility "internal" } */
+/* { dg-final { scan-assembler "\\.internal.*Foo.methodEv" { target { ! *-*-solaris2* } } } } */
+/* { dg-final { scan-assembler "\\.(internal|hidden).*Foo.methodEv" { target *-*-solaris2* } } } */
+
+#pragma GCC visibility push(hidden)
+class __attribute__ ((visibility ("internal"))) Foo
+{
+ void method();
+};
+#pragma GCC visibility pop
+
+void Foo::method() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/pragma-override2.C b/gcc/testsuite/g++.dg/ext/visibility/pragma-override2.C
new file mode 100644
index 000000000..f566cd2f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/pragma-override2.C
@@ -0,0 +1,14 @@
+/* Test that #pragma GCC visibility does not override class member specific settings. */
+/* { dg-do compile } */
+/* { dg-require-visibility "internal" } */
+/* { dg-final { scan-assembler "\\.internal.*Foo.methodEv" { target { ! *-*-solaris2* } } } } */
+/* { dg-final { scan-assembler "\\.(internal|hidden).*Foo.methodEv" { target *-*-solaris2* } } } */
+
+#pragma GCC visibility push(hidden)
+class Foo
+{
+ __attribute__ ((visibility ("internal"))) void method();
+};
+#pragma GCC visibility pop
+
+void Foo::method() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/pragma.C b/gcc/testsuite/g++.dg/ext/visibility/pragma.C
new file mode 100644
index 000000000..98384c9c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/pragma.C
@@ -0,0 +1,13 @@
+/* Test that #pragma GCC visibility affects class members. */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-final { scan-hidden "_ZN3Foo6methodEv" } } */
+
+#pragma GCC visibility push(hidden)
+class Foo
+{
+ void method();
+};
+#pragma GCC visibility pop
+
+void Foo::method() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/prop1.C b/gcc/testsuite/g++.dg/ext/visibility/prop1.C
new file mode 100644
index 000000000..f4574820d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/prop1.C
@@ -0,0 +1,23 @@
+// Test for propagation of visibility through template arguments
+
+// { dg-do compile }
+// { dg-require-visibility "" }
+// { dg-final { scan-hidden "_Z1fIN1N1AEEvT_" } }
+// { dg-final { scan-hidden "_Z1hIXadL_ZN1N1iEEEEvv" } }
+
+namespace N __attribute ((__visibility__ ("hidden")))
+{
+ struct A { };
+ int i;
+}
+
+template <class T> void f (T) { }
+template <int *I> void h() { }
+
+void g()
+{
+ N::A a;
+ f(a);
+ h<&N::i>();
+}
+
diff --git a/gcc/testsuite/g++.dg/ext/visibility/redecl1.C b/gcc/testsuite/g++.dg/ext/visibility/redecl1.C
new file mode 100644
index 000000000..b53335ef5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/redecl1.C
@@ -0,0 +1,7 @@
+// Test that we complain about redeclaration with different visibility
+
+struct __attribute((visibility("hidden"))) B;
+struct __attribute((visibility("default"))) B; // { dg-error "visibility" }
+
+__attribute ((visibility ("hidden"))) void f(); // { dg-warning "previous" }
+__attribute ((visibility ("default"))) void f(); // { dg-warning "visibility" }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/staticdatamem.C b/gcc/testsuite/g++.dg/ext/visibility/staticdatamem.C
new file mode 100644
index 000000000..4ec9479a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/staticdatamem.C
@@ -0,0 +1,20 @@
+// PR c++/18925
+// { dg-do compile { target ia64-*-linux* } }
+// { dg-options "-fPIC -fvisibility=hidden" }
+// { dg-final { scan-assembler-not "gprel" } }
+
+class __attribute__ ((visibility("default"))) Type
+{
+ private:
+ static long _staticTypeCount;
+ public:
+ Type() { _staticTypeCount++; }
+ ~Type();
+};
+
+long Type::_staticTypeCount = 0;
+
+Type::~Type()
+{
+ _staticTypeCount--;
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/staticmemfuncts.C b/gcc/testsuite/g++.dg/ext/visibility/staticmemfuncts.C
new file mode 100644
index 000000000..e745caa5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/staticmemfuncts.C
@@ -0,0 +1,11 @@
+/* Test that setting visibility for static class member functions works. */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-final { scan-hidden "_ZN3Foo6methodEv" } } */
+
+class __attribute__ ((visibility ("hidden"))) Foo
+{
+ static void method();
+};
+
+void Foo::method() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/symbian1.C b/gcc/testsuite/g++.dg/ext/visibility/symbian1.C
new file mode 100644
index 000000000..864ab2bb9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/symbian1.C
@@ -0,0 +1,22 @@
+// { dg-do compile { target arm*-*-symbianelf* } }
+// Class data should not be exported.
+// { dg-final { scan-hidden "_ZTV2K3" } }
+// But the constructor and destructor should be exported.
+// { dg-final { scan-not-hidden "_ZN2K3C2Ev" } }
+// { dg-final { scan-not-hidden "_ZN2K3D0Ev" } }
+
+class __declspec(notshared) K3 {
+public:
+ __declspec(dllimport) K3();
+ __declspec(dllimport) virtual ~K3();
+ virtual int m1();
+};
+
+__declspec(dllexport)
+ K3::K3(){}
+
+__declspec(dllexport)
+ K3::~K3(){}
+
+int K3::m1() { return 1; }
+
diff --git a/gcc/testsuite/g++.dg/ext/visibility/symbian2.C b/gcc/testsuite/g++.dg/ext/visibility/symbian2.C
new file mode 100644
index 000000000..767f0b54e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/symbian2.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target arm*-*-symbianelf* } }
+// Class data should not be exported.
+// { dg-final { scan-hidden "_ZTI1A" } }
+// { dg-final { scan-hidden "_ZTS1A" } }
+// { dg-final { scan-hidden "_ZTV1B" } }
+// { dg-final { scan-hidden "_ZTI1B" } }
+// { dg-final { scan-hidden "_ZTS1B" } }
+
+struct A {};
+struct B : virtual public A {};
+B b;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/template1.C b/gcc/testsuite/g++.dg/ext/visibility/template1.C
new file mode 100644
index 000000000..c5cee0d4b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/template1.C
@@ -0,0 +1,35 @@
+// PR c++/19134
+// -fvisibility-inlines-hidden doesn't apply to non-inline specializations
+
+// { dg-require-visibility "" }
+// { dg-options "-fvisibility-inlines-hidden" }
+// { dg-final { scan-not-hidden "_ZN1AIiE3fooEv" } }
+// { dg-final { scan-not-hidden "_ZN1AIiE3barEv" } }
+// { dg-final { scan-hidden "_ZN1AIlE3fooEv" } }
+// { dg-final { scan-hidden "_ZN1AIlE3barEv" } }
+// { dg-final { scan-hidden "_ZN1AIcE3barEv" } }
+
+template<class T>
+struct A {
+ void foo() {};
+ __attribute ((visibility ("hidden"))) void bar();
+};
+
+// This has default visibility.
+template<> void A<int>::foo() {}
+
+// This has hidden visibility because of -fvisibility-inlines-hidden.
+template<> inline void A<long>::foo() {}
+// Force the inline out.
+void f () { A<long> a; a.foo(); }
+
+// This has default visibility.
+template<> __attribute ((visibility ("default"))) void A<int>::bar() {}
+
+// This inherits hidden visibility from its template.
+template<> void A<long>::bar() { }
+
+// This also has hidden visibility; #pragma vis doesn't affect class members.
+#pragma GCC visibility push(default)
+template<> void A<char>::bar() { }
+#pragma GCC visibility pop
diff --git a/gcc/testsuite/g++.dg/ext/visibility/template2.C b/gcc/testsuite/g++.dg/ext/visibility/template2.C
new file mode 100644
index 000000000..8db96db56
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/template2.C
@@ -0,0 +1,35 @@
+// PR c++/27000
+// Implicitly instantiated templates should not be affected by
+// #pragma visibility.
+
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-final { scan-not-hidden "_ZN1SIiED1Ev" } } */
+/* { dg-final { scan-not-hidden "_ZN1SIiEC1ERKi" } } */
+
+template <class T>
+struct S
+{
+ S (const T &);
+ ~S ();
+ T t;
+};
+
+template <class T>
+S<T>::S (const T &x)
+{
+ t = x;
+}
+
+template <class T>
+S<T>::~S ()
+{
+}
+
+#pragma GCC visibility push(hidden)
+struct U
+{
+ S<int> s;
+ U () : s (6) { }
+} u;
+#pragma GCC visibility pop
diff --git a/gcc/testsuite/g++.dg/ext/visibility/template3.C b/gcc/testsuite/g++.dg/ext/visibility/template3.C
new file mode 100644
index 000000000..69cb6caba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/template3.C
@@ -0,0 +1,22 @@
+// PR c++/17470
+// Test that we can give visibility to explicit template instantiations
+
+// { dg-require-visibility "" }
+// { dg-final { scan-hidden "_ZN1AIlE1fEl" } }
+// { dg-final { scan-hidden "_ZN1AIiE1fEi" } }
+// { dg-final { scan-not-hidden "_ZN1AIcE1fEc" } }
+// { dg-final { scan-hidden "_Z8identityIdET_S0_" } }
+// { dg-final { scan-not-hidden "_Z8identityIiET_S0_" } }
+
+template <class T> T identity(T t) { return t; }
+template __attribute__((visibility("hidden"))) double identity(double);
+template int identity(int);
+
+
+template <class T> struct A { void f (T); };
+template <class T> void A<T>::f (T) { }
+template struct __attribute ((visibility ("hidden"))) A<int>;
+template<> struct __attribute ((visibility ("hidden"))) A<long> { void f(long); };
+// inherits hidden visibility from its class
+void A<long>::f (long) { }
+template struct A<char>;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/template4.C b/gcc/testsuite/g++.dg/ext/visibility/template4.C
new file mode 100644
index 000000000..add63a593
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/template4.C
@@ -0,0 +1,39 @@
+// Test for explicit visibility on template vs. #pragma vis at explicit
+// instantiation/specialization point for plain function templates.
+
+// { dg-require-visibility "" }
+// { dg-final { scan-hidden "_Z3fooIdEvT_" } }
+// { dg-final { scan-hidden "_Z3fooIlEvT_" } }
+// { dg-final { scan-hidden "_Z3fooIcEvT_" } }
+// { dg-final { scan-hidden "_Z3fooIiEvT_" } }
+// { dg-final { scan-not-hidden "_Z3fooIfEvT_" } }
+// { dg-final { scan-not-hidden "_Z3fooIsEvT_" } }
+
+// { dg-final { scan-hidden "_Z3barIdEvT_" } }
+// { dg-final { scan-hidden "_Z3barIlEvT_" } }
+// { dg-final { scan-hidden "_Z3barIiEvT_" } }
+// { dg-final { scan-hidden "_Z3barIcEvT_" } }
+// { dg-final { scan-not-hidden "_Z3barIfEvT_" } }
+// { dg-final { scan-not-hidden "_Z3barIsEvT_" } }
+
+#pragma GCC visibility push(hidden)
+template <class T> void bar(T) { }
+#pragma GCC visibility pop
+template void bar (long);
+template<> void bar (double) { }
+template __attribute ((visibility ("default"))) void bar (short);
+template<> __attribute ((visibility ("default"))) void bar (float) { }
+#pragma GCC visibility push(default)
+template<> void bar(char) { }
+template void bar(int);
+#pragma GCC visibility pop
+
+template <class T> __attribute ((visibility ("hidden"))) void foo(T) { }
+template void foo (long);
+template<> void foo (double) { }
+template __attribute ((visibility ("default"))) void foo (short);
+template<> __attribute ((visibility ("default"))) void foo (float) { }
+#pragma GCC visibility push(default)
+template<> void foo(char) { }
+template void foo(int);
+#pragma GCC visibility pop
diff --git a/gcc/testsuite/g++.dg/ext/visibility/template6.C b/gcc/testsuite/g++.dg/ext/visibility/template6.C
new file mode 100644
index 000000000..7892a46e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/template6.C
@@ -0,0 +1,17 @@
+// Test for explicit visibility taking precedence
+
+// { dg-require-visibility "" }
+// { dg-final { scan-not-hidden "_ZN1AIiE1fEv" } }
+
+template <class T> struct A
+{
+ // This attribute takes precedence over...
+ __attribute ((visibility ("default"))) void f ();
+};
+
+template <class T>
+void A<T>::f ()
+{ }
+
+// ...this attribute.
+template struct __attribute ((visibility ("hidden"))) A<int>;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/typeinfo1.C b/gcc/testsuite/g++.dg/ext/visibility/typeinfo1.C
new file mode 100644
index 000000000..99dfc1cd7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/typeinfo1.C
@@ -0,0 +1,19 @@
+// PR c++/26984
+// lazily generated typeinfos should not be affected by #pragma vis, but
+// they should be affected by the visibility of the type they describe.
+
+// { dg-require-visibility "" }
+// { dg-options "-fvisibility-inlines-hidden" }
+// { dg-final { scan-not-hidden "_ZTIPPi" } }
+// { dg-final { scan-not-hidden "_ZTSPPi" } }
+// { dg-final { scan-hidden "_ZTIP1A" } }
+// { dg-final { scan-hidden "_ZTSP1A" } }
+
+#include <typeinfo>
+
+#pragma GCC visibility push(hidden)
+const std::type_info* t = &(typeid(int **));
+struct A { };
+#pragma GCC visibility pop
+
+const std::type_info* t2 = &(typeid(A *));
diff --git a/gcc/testsuite/g++.dg/ext/visibility/typeinfo2.C b/gcc/testsuite/g++.dg/ext/visibility/typeinfo2.C
new file mode 100644
index 000000000..54f541d85
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/typeinfo2.C
@@ -0,0 +1,23 @@
+// PR c++/35368
+// { dg-require-visibility "" }
+
+#pragma GCC visibility push (hidden)
+
+struct A
+{
+ A();
+ virtual ~A() { }
+};
+
+A::A()
+{
+}
+
+void foo(A *a)
+{
+ delete a;
+}
+
+// { dg-final { scan-not-hidden "_ZTVN10__cxxabiv117__class_type_infoE" } }
+// { dg-final { scan-hidden "_ZTI1A" } }
+// { dg-final { scan-hidden "_ZTV1A" } }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/typeinfo3.C b/gcc/testsuite/g++.dg/ext/visibility/typeinfo3.C
new file mode 100644
index 000000000..5102b6492
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/typeinfo3.C
@@ -0,0 +1,24 @@
+// PR c++/35368
+// { dg-require-visibility "" }
+
+#pragma GCC visibility push (hidden)
+
+#include <typeinfo>
+
+const std::type_info& info1 = typeid(int []);
+const std::type_info& info2 = typeid(int);
+enum E { e = 0 };
+const std::type_info& info3 = typeid(E);
+struct S { S (); };
+const std::type_info& info4 = typeid(S);
+const std::type_info& info5 = typeid(int *);
+
+// { dg-final { scan-not-hidden "_ZTVN10__cxxabiv117__array_type_infoE" } }
+// { dg-final { scan-not-hidden "_ZTVN10__cxxabiv116__enum_type_infoE" } }
+// { dg-final { scan-hidden "_ZTI1S" } }
+// { dg-final { scan-hidden "_ZTS1S" } }
+// { dg-final { scan-hidden "info1" } }
+// { dg-final { scan-hidden "info2" } }
+// { dg-final { scan-hidden "info3" } }
+// { dg-final { scan-hidden "info4" } }
+// { dg-final { scan-hidden "info5" } }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/virtual.C b/gcc/testsuite/g++.dg/ext/visibility/virtual.C
new file mode 100644
index 000000000..770600368
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/virtual.C
@@ -0,0 +1,17 @@
+/* Test that setting visibility for class affects virtual table, VTT and
+ type_info name and node. */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-final { scan-hidden "ZTV3Foo" } } */
+/* { dg-final { scan-hidden "ZTT3Foo" } } */
+/* { dg-final { scan-hidden "ZTS3Foo" } } */
+/* { dg-final { scan-hidden "ZTI3Foo" } } */
+
+struct A { };
+
+class __attribute__ ((visibility ("hidden"))) Foo: virtual public A
+{
+ virtual void method();
+};
+
+void Foo::method() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-1.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-1.C
new file mode 100644
index 000000000..8ea270bf8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-1.C
@@ -0,0 +1,8 @@
+/* Test visibility attribute on function definition. */
+/* { dg-require-visibility "" }
+/* { dg-final { scan-hidden "_Z3foov" } } */
+
+void
+__attribute__((visibility ("hidden")))
+foo()
+{ }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-10.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-10.C
new file mode 100644
index 000000000..312d32309
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-10.C
@@ -0,0 +1,19 @@
+// { dg-require-visibility "" }
+// { dg-require-dll "" }
+
+extern void __attribute__((dllimport, visibility("hidden")))
+ f1(); // { dg-error "visibility" }
+extern void __attribute__((visibility("hidden"), dllimport))
+ f2(); // { dg-error "visibility" }
+extern void __attribute__((dllexport, visibility("hidden")))
+ f3(); // { dg-error "visibility" }
+extern void __attribute__((visibility("hidden"), dllexport))
+ f4(); // { dg-error "visibility" }
+extern void __attribute__((visibility("default"), dllimport))
+ f5();
+extern void __attribute__((dllimport, visibility("default")))
+ f6();
+extern void __attribute__((visibility("default"), dllexport))
+ f7();
+extern void __attribute__((dllexport, visibility("default")))
+ f8();
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-11.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-11.C
new file mode 100644
index 000000000..78f40c62b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-11.C
@@ -0,0 +1,18 @@
+// PR target/39175
+// { dg-do compile }
+// { dg-require-visibility "" }
+// { dg-options "-O2 -fvisibility=hidden -fpic" { target fpic } }
+
+__attribute__((noinline)) int
+foo (int x)
+{
+ return x;
+}
+
+int foo (int x);
+
+int
+bar (int x)
+{
+ return foo (x);
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-2.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-2.C
new file mode 100644
index 000000000..26272abb1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-2.C
@@ -0,0 +1,7 @@
+/* Test that visibility attribute on declaration extends to definition. */
+/* { dg-require-visibility "" }
+/* { dg-final { scan-hidden "_Z3foov" } } */
+
+void __attribute__((visibility ("hidden"))) foo();
+
+void foo() { }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-3.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-3.C
new file mode 100644
index 000000000..e4f499fcc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-3.C
@@ -0,0 +1,7 @@
+/* Test visibility attribute on forward declaration of global variable */
+/* { dg-require-visibility "" }
+/* { dg-final { scan-hidden "xyzzy" } } */
+
+int
+__attribute__((visibility ("hidden")))
+xyzzy = 5;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-4.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-4.C
new file mode 100644
index 000000000..f67659587
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-4.C
@@ -0,0 +1,8 @@
+/* Test visibility attribute on forward declaration of global variable */
+/* { dg-require-visibility "" }
+/* { dg-final { scan-hidden "xyzzy" } } */
+
+extern int __attribute__ ((visibility ("hidden")))
+xyzzy;
+
+int xyzzy = 5;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-5.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-5.C
new file mode 100644
index 000000000..592529e66
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-5.C
@@ -0,0 +1,11 @@
+/* Test visibility attribute on definition of a function that has
+ already had a forward declaration. */
+/* { dg-require-visibility "" }
+/* { dg-final { scan-hidden "_Z3foov" } } */
+
+void foo();
+
+void
+ __attribute__((visibility ("hidden")))
+foo()
+{ }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-6.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-6.C
new file mode 100644
index 000000000..0fecf6b74
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-6.C
@@ -0,0 +1,10 @@
+/* Test visibility attribute on definition of global variable that has
+ already had a forward declaration. */
+/* { dg-require-visibility "" }
+/* { dg-final { scan-hidden "xyzzy" } } */
+
+extern int xyzzy;
+
+int
+__attribute__((visibility ("hidden")))
+xyzzy = 5;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C
new file mode 100644
index 000000000..ae4589397
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C
@@ -0,0 +1,11 @@
+/* Test warning from conflicting visibility specifications. */
+/* { dg-require-visibility "protected" } */
+/* { dg-final { scan-hidden "xyzzy" } } */
+
+extern int
+__attribute__((visibility ("hidden")))
+xyzzy; /* { dg-warning "previous declaration here" "" } */
+
+int
+__attribute__((visibility ("protected")))
+xyzzy = 5; /* { dg-warning "visibility attribute ignored" "" } */
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-8.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-8.C
new file mode 100644
index 000000000..f0139b362
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-8.C
@@ -0,0 +1,56 @@
+// Test that a definition marked with dllexport has default
+// visibility.
+// { dg-require-visibility "" }
+// { dg-require-dll "" }
+// { dg-options "-fvisibility=hidden" }
+// { dg-final { scan-not-hidden "_ZN1A1fEv" } }
+// { dg-final { scan-not-hidden "_Z1gv" } }
+// { dg-final { scan-not-hidden "_Z1hv" } }
+// { dg-final { scan-not-hidden "_ZN1BC1Ev" } }
+// { dg-final { scan-not-hidden "_ZN1BC2Ev" } }
+// { dg-final { scan-not-hidden "_ZN1BD0Ev" } }
+// { dg-final { scan-not-hidden "_ZN1BD1Ev" } }
+// { dg-final { scan-not-hidden "_ZN1BD2Ev" } }
+// { dg-final { scan-not-hidden "_ZN1B1iEv" } }
+// { dg-final { scan-not-hidden "_ZN1B1jEv" } }
+// { dg-final { scan-not-hidden "_ZN1A1a" } }
+// { dg-final { scan-not-hidden "_ZN1B1b" } }
+// { dg-final { scan-not-hidden "k" } }
+// { dg-final { scan-not-hidden "l" } }
+
+struct __declspec(dllexport) A {
+ void f();
+ static int a;
+};
+
+void A::f() {}
+
+int A::a;
+
+__declspec(dllexport) void g() {}
+
+__declspec(dllexport) void h();
+void h() {}
+
+struct B {
+ B();
+ __declspec(dllexport) virtual ~B();
+ void i();
+ __declspec(dllexport) void j();
+ __declspec(dllexport) static int b;
+};
+
+__declspec(dllexport) B::B() {}
+
+B::~B() {}
+
+__declspec(dllexport) void B::i() {}
+
+void B::j() {}
+
+int B::b;
+
+__declspec(dllexport) int k;
+
+__declspec(dllexport) extern int l;
+int l;
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-9.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-9.C
new file mode 100644
index 000000000..06b5a17e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-9.C
@@ -0,0 +1,29 @@
+// Test that dllimport'd functions have default visibility.
+// { dg-require-visibility "" }
+// { dg-require-dll "" }
+// { dg-options "-fvisibility=hidden" }
+// { dg-final { scan-not-hidden "_Z2f1v" } }
+// { dg-final { scan-not-hidden "_ZN1S2f3Ev" } }
+
+extern void __attribute__((dllimport)) f1();
+void f2() {
+ f1();
+}
+
+struct __attribute__((visibility("hidden")) S1 {
+ __attribute__((dllimport)) void f3();
+};
+
+void f4() {
+ S1 s1;
+ s1.f3();
+}
+
+struct S2 {
+ __attribute__((dllimport)) void f5();
+};
+
+void f6() {
+ S2 s2;
+ s2.f5();
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/warn2.C b/gcc/testsuite/g++.dg/ext/visibility/warn2.C
new file mode 100644
index 000000000..475179fd6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/warn2.C
@@ -0,0 +1,16 @@
+// Complain when a class is specified with greater visibility than one of
+// its members' types or bases.
+
+// { dg-require-visibility "" }
+
+namespace N __attribute ((__visibility__ ("hidden")))
+{
+ struct A { };
+}
+
+struct B // { dg-warning "visibility" }
+{
+ N::A a;
+};
+
+struct C: public N::A { }; // { dg-warning "visibility" }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/warn3.C b/gcc/testsuite/g++.dg/ext/visibility/warn3.C
new file mode 100644
index 000000000..d1d3ba486
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/warn3.C
@@ -0,0 +1,26 @@
+// Tests for various visibility mismatch situations.
+
+// { dg-require-visibility "" }
+
+// { dg-final { scan-not-hidden "_ZN1A1fEv" } }
+
+struct __attribute ((visibility ("hidden"))) A
+{
+ // This is OK, A::f gets default visibility.
+ __attribute ((visibility ("default"))) void f ();
+};
+
+void A::f() { }
+
+// This gets a warning because B objects might rely
+// on hidden symbols from A.
+struct B // { dg-warning "visibility" }
+{
+ A a;
+};
+
+// This one has explicit visibility, so it doesn't get a warning.
+struct __attribute ((visibility ("default"))) C
+{
+ A a;
+};
diff --git a/gcc/testsuite/g++.dg/ext/visibility/warn4.C b/gcc/testsuite/g++.dg/ext/visibility/warn4.C
new file mode 100644
index 000000000..33e6f6785
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/warn4.C
@@ -0,0 +1,10 @@
+// Warn if we try to give an instantiation visibility after it's already
+// been instantiated.
+
+// { dg-require-visibility "" }
+
+template <class T> struct A { void f (T); };
+template <class T> void A<T>::f (T) { }
+
+A<double> ad;
+template struct __attribute ((visibility ("hidden"))) A<double>; // { dg-warning "already defined" }