Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 96374 Details for
Bug 146817
patches for gcc-4.1.1 to fix visibility-related bugs
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
second patch
99-visibility03.patch (text/plain), 59.20 KB, created by
Jan Jitse Venselaar
on 2006-09-08 03:09:47 UTC
(
hide
)
Description:
second patch
Filename:
MIME Type:
Creator:
Jan Jitse Venselaar
Created:
2006-09-08 03:09:47 UTC
Size:
59.20 KB
patch
obsolete
>Index: gcc/attribs.c >=================================================================== >--- gcc/attribs.c (revision 116504) >+++ gcc/attribs.c (revision 116505) >@@ -250,6 +250,14 @@ > } > } > >+ if (TYPE_P (*anode) >+ && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE) >+ && TYPE_SIZE (*anode) != NULL_TREE) >+ { >+ warning (OPT_Wattributes, "type attributes ignored after type is already defined"); >+ continue; >+ } >+ > if (spec->handler != NULL) > returned_attrs = chainon ((*spec->handler) (anode, name, args, > flags, &no_add_attrs), >Index: gcc/doc/extend.texi >=================================================================== >--- gcc/doc/extend.texi (revision 116504) >+++ gcc/doc/extend.texi (revision 116505) >@@ -2335,6 +2335,17 @@ > > Not all ELF targets support this attribute. > >+A C++ namespace declaration can also have the visibility attribute. >+This attribute applies only to the particular namespace body, not to >+other definitions of the same namespace; it is equivalent to using >+@samp{#pragma GCC visibility} before and after the namespace >+definition (@pxref{Visibility Pragmas}). >+ >+In C++, if a template argument has limited visibility, this >+restriction is implicitly propagated to the template instantiation. >+Otherwise, template instantiations and specializations default to the >+visibility of their template. >+ > @item warn_unused_result > @cindex @code{warn_unused_result} attribute > The @code{warn_unused_result} attribute causes a warning to be emitted >@@ -2513,10 +2524,7 @@ > An attribute specifier list may appear as part of a @code{struct}, > @code{union} or @code{enum} specifier. It may go either immediately > after the @code{struct}, @code{union} or @code{enum} keyword, or after >-the closing brace. It is ignored if the content of the structure, union >-or enumerated type is not defined in the specifier in which the >-attribute specifier list is used---that is, in usages such as >-@code{struct __attribute__((foo)) bar} with no following opening brace. >+the closing brace. The former syntax is preferred. > Where attribute specifiers follow the closing brace, they are considered > to relate to the structure, union or enumerated type defined, not to any > enclosing declaration the type specifier appears in, and the type >@@ -3180,13 +3188,14 @@ > @cindex type attributes > > The keyword @code{__attribute__} allows you to specify special >-attributes of @code{struct} and @code{union} types when you define such >-types. This keyword is followed by an attribute specification inside >-double parentheses. Six attributes are currently defined for types: >-@code{aligned}, @code{packed}, @code{transparent_union}, @code{unused}, >-@code{deprecated} and @code{may_alias}. Other attributes are defined for >-functions (@pxref{Function Attributes}) and for variables >-(@pxref{Variable Attributes}). >+attributes of @code{struct} and @code{union} types when you define >+such types. This keyword is followed by an attribute specification >+inside double parentheses. Seven attributes are currently defined for >+types: @code{aligned}, @code{packed}, @code{transparent_union}, >+@code{unused}, @code{deprecated}, @code{visibility}, and >+@code{may_alias}. Other attributes are defined for functions >+(@pxref{Function Attributes}) and for variables (@pxref{Variable >+Attributes}). > > You may also specify any one of these attributes with @samp{__} > preceding and following its keyword. This allows you to use these >@@ -3194,14 +3203,13 @@ > macro of the same name. For example, you may use @code{__aligned__} > instead of @code{aligned}. > >-You may specify the @code{aligned} and @code{transparent_union} >-attributes either in a @code{typedef} declaration or just past the >-closing curly brace of a complete enum, struct or union type >-@emph{definition} and the @code{packed} attribute only past the closing >-brace of a definition. >+You may specify type attributes either in a @code{typedef} declaration >+or in an enum, struct or union type declaration or definition. > >-You may also specify attributes between the enum, struct or union >-tag and the name of the type rather than after the closing brace. >+For an enum, struct or union type, you may specify attributes either >+between the enum, struct or union tag and the name of the type, or >+just past the closing curly brace of the @emph{definition}. The >+former syntax is preferred. > > @xref{Attribute Syntax}, for details of the exact syntax for using > attributes. >@@ -3450,6 +3458,13 @@ > @option{-fstrict-aliasing}, which is on by default at @option{-O2} or > above in recent GCC versions. > >+@item visibility >+ >+In C++, attribute visibility (@pxref{Function Attributes}) can also be >+applied to class, struct, union and enum types. Unlike other type >+attributes, the attribute must appear between the initial keyword and >+the name of the type; it cannot appear after the body of the type. >+ > @subsection ARM Type Attributes > > On those ARM targets that support @code{dllimport} (such as Symbian >@@ -9226,6 +9241,7 @@ > * Symbol-Renaming Pragmas:: > * Structure-Packing Pragmas:: > * Weak Pragmas:: >+* Visibility Pragmas:: > @end menu > > @node ARM Pragmas >@@ -9466,6 +9482,26 @@ > translation unit. > @end table > >+@node Visibility Pragmas >+@subsection Visibility Pragmas >+ >+@table @code >+@item #pragma GCC visibility push(@var{visibility}) >+@itemx #pragma GCC visibility pop >+@cindex pragma, visibility >+ >+This pragma allows the user to set the visibility for multiple >+declarations without having to give each a visibility attribute >+@xref{Function Attributes}, for more information about visibility and >+the attribute syntax. >+ >+In C++, @samp{#pragma GCC visibility} affects only namespace-scope >+declarations. Class members and template specializations are not >+affected; if you want to override the visibility for a particular >+member or instantiation, you must use an attribute. >+ >+@end table >+ > @node Unnamed Fields > @section Unnamed struct/union fields within structs/unions > @cindex struct >Index: gcc/doc/invoke.texi >=================================================================== >--- gcc/doc/invoke.texi (revision 116504) >+++ gcc/doc/invoke.texi (revision 116505) >@@ -1585,13 +1585,13 @@ > appear in the export table of a DSO and do not require a PLT indirection > when used within the DSO@. Enabling this option can have a dramatic effect > on load and link times of a DSO as it massively reduces the size of the >-dynamic export table when the library makes heavy use of templates. While >-it can cause bloating through duplication of code within each DSO where >-it is used, often the wastage is less than the considerable space occupied >-by a long symbol name in the export table which is typical when using >-templates and namespaces. For even more savings, combine with the >-@option{-fvisibility=hidden} switch. >+dynamic export table when the library makes heavy use of templates. > >+You may mark a method as having a visibility explicitly to negate the >+effect of the switch for that method. For example, if you do want to >+compare pointers to a particular inline method, or the method has >+local static data, you might mark it as having default visibility. >+ > @item -fno-weak > @opindex fno-weak > Do not use weak symbol support, even if it is provided by the linker. >@@ -13157,6 +13157,20 @@ > Note that due to ISO C++ specification requirements, operator new and > operator delete must always be of default visibility. > >+@samp{extern} declarations are not affected by @samp{-fvisibility}, so >+a lot of code can be recompiled with @samp{-fvisibility=hidden} with >+no modifications. However, this means that calls to @samp{extern} >+functions with no explicit visibility will use the PLT, so it is more >+effective to use @samp{__attribute ((visibility))} and/or >+@samp{#pragma GCC visibility} to tell the compiler which @samp{extern} >+declarations should be treated as hidden. >+ >+Note that @samp{-fvisibility} does affect C++ vague linkage >+entities. This means that, for instance, an exception class that will >+be thrown between DSOs must be explicitly marked with default >+visibility so that the @samp{type_info} nodes will be unified between >+the DSOs. >+ > An overview of these techniques, their benefits and how to use them > is at @w{@uref{http://gcc.gnu.org/wiki/Visibility}}. > >Index: gcc/flags.h >=================================================================== >--- gcc/flags.h (revision 116504) >+++ gcc/flags.h (revision 116505) >@@ -58,15 +58,16 @@ > debugging information. */ > extern bool use_gnu_debug_info_extensions; > >-/* Enumerate visibility settings. */ >+/* Enumerate visibility settings. This is deliberately ordered from most >+ to least visibility. */ > #ifndef SYMBOL_VISIBILITY_DEFINED > #define SYMBOL_VISIBILITY_DEFINED > enum symbol_visibility > { > VISIBILITY_DEFAULT, >- VISIBILITY_INTERNAL, >+ VISIBILITY_PROTECTED, > VISIBILITY_HIDDEN, >- VISIBILITY_PROTECTED >+ VISIBILITY_INTERNAL > }; > #endif > >Index: gcc/tree.c >=================================================================== >--- gcc/tree.c (revision 116504) >+++ gcc/tree.c (revision 116505) >@@ -3136,14 +3136,6 @@ > else if (code == FUNCTION_DECL) > DECL_MODE (t) = FUNCTION_MODE; > >- if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) >- { >- /* Set default visibility to whatever the user supplied with >- visibility_specified depending on #pragma GCC visibility. */ >- DECL_VISIBILITY (t) = default_visibility; >- DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma; >- } >- > return t; > } > >Index: gcc/tree.h >=================================================================== >--- gcc/tree.h (revision 116504) >+++ gcc/tree.h (revision 116505) >@@ -1050,7 +1050,7 @@ > expressions. */ > #define TREE_OVERFLOW(NODE) ((NODE)->common.public_flag) > >-/* In a VAR_DECL or FUNCTION_DECL, >+/* In a VAR_DECL, FUNCTION_DECL, NAMESPACE_DECL or TYPE_DECL, > nonzero means name is to be accessible from outside this module. > In an IDENTIFIER_NODE, nonzero means an external declaration > accessible from outside this module was previously seen >@@ -2260,9 +2260,9 @@ > enum symbol_visibility > { > VISIBILITY_DEFAULT, >- VISIBILITY_INTERNAL, >+ VISIBILITY_PROTECTED, > VISIBILITY_HIDDEN, >- VISIBILITY_PROTECTED >+ VISIBILITY_INTERNAL > }; > #endif > >Index: gcc/testsuite/g++.old-deja/g++.pt/enum5.C >=================================================================== >--- gcc/testsuite/g++.old-deja/g++.pt/enum5.C (revision 116504) >+++ gcc/testsuite/g++.old-deja/g++.pt/enum5.C (revision 116505) >@@ -1,4 +1,4 @@ > // { dg-do assemble } > >-template <> // { dg-error "" } template declaration of enum >-enum E {e}; >+template <> >+enum E {e}; // { dg-error "" } template declaration of enum >Index: gcc/testsuite/g++.dg/ext/attrib9.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/attrib9.C (revision 116504) >+++ gcc/testsuite/g++.dg/ext/attrib9.C (revision 116505) >@@ -1,5 +1,10 @@ >-class __attribute__((unused)) C; // { dg-warning "type attributes" } >-struct __attribute__((unused)) S; // { dg-warning "type attributes" } >-union __attribute__((unused)) U; // { dg-warning "type attributes" } >+class __attribute__((unused)) C; >+struct __attribute__((unused)) S; >+union __attribute__((unused)) U; > enum e {}; >-enum __attribute__((unused)) e; // { dg-warning "type attributes" } >+enum __attribute__((unused)) e; // { dg-warning "already defined" } >+ >+struct __attribute((unused)) B *p; // { dg-warning "attributes" } >+ >+template <class T> struct A { }; >+struct __attribute((unused)) A<int>; // { dg-warning "attributes" } >Index: gcc/testsuite/g++.dg/ext/attrib14.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/attrib14.C (revision 116504) >+++ gcc/testsuite/g++.dg/ext/attrib14.C (revision 116505) >@@ -3,11 +3,11 @@ > // parsing of the class, causing some variants to have it and some not. > > struct __attribute__((bogus)) A >-{ >+{ // { dg-warning "ignored" "" } > virtual ~A(); > void foo(const A&); > void bar(const A&); >-}; // { dg-warning "ignored" "" } >+}; > > void A::foo(const A&) {} > void A::bar(const A& a) { foo(a); } >Index: gcc/testsuite/g++.dg/ext/visibility/anon1.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/anon1.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/anon1.C (revision 116505) >@@ -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() { } >+} >Index: gcc/testsuite/g++.dg/ext/visibility/anon2.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/anon2.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/anon2.C (revision 116505) >@@ -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 () { } >Index: gcc/testsuite/g++.dg/ext/visibility/redecl1.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/redecl1.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/redecl1.C (revision 116505) >@@ -0,0 +1,7 @@ >+// Test that we complain about redeclaration with different visibility >+ >+struct __attribute((visibility("hidden"))) B; >+struct __attribute((visibility("default"))) B; // { dg-warning "visibility" } >+ >+__attribute ((visibility ("hidden"))) void f(); // { dg-warning "previous" } >+__attribute ((visibility ("default"))) void f(); // { dg-warning "visibility" } >Index: gcc/testsuite/g++.dg/ext/visibility/class1.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/class1.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/class1.C (revision 116505) >@@ -0,0 +1,20 @@ >+// PR c++/26905 >+// Init should not be hidden, so calling it should use the PLT. >+ >+// { dg-require-visibility "" } >+// { dg-options "-fpic" } >+// { dg-do compile { target i?86-*-* x86_64-*-* } } >+// { 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(); >+} >Index: gcc/testsuite/g++.dg/ext/visibility/template1.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/template1.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/template1.C (revision 116505) >@@ -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 >Index: gcc/testsuite/g++.dg/ext/visibility/fvisibility-override2.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/fvisibility-override2.C (revision 116504) >+++ gcc/testsuite/g++.dg/ext/visibility/fvisibility-override2.C (revision 116505) >@@ -6,7 +6,7 @@ > > class Foo > { >- __attribute__ ((visibility ("default"))) void method(); >+ __attribute__ ((visibility ("internal"))) void method(); > }; > > void Foo::method() { } >Index: gcc/testsuite/g++.dg/ext/visibility/template2.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/template2.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/template2.C (revision 116505) >@@ -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 >Index: gcc/testsuite/g++.dg/ext/visibility/template3.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/template3.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/template3.C (revision 116505) >@@ -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>; >Index: gcc/testsuite/g++.dg/ext/visibility/template4.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/template4.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/template4.C (revision 116505) >@@ -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 >Index: gcc/testsuite/g++.dg/ext/visibility/prop1.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/prop1.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/prop1.C (revision 116505) >@@ -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>(); >+} >+ >Index: gcc/testsuite/g++.dg/ext/visibility/assign1.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/assign1.C (revision 116504) >+++ gcc/testsuite/g++.dg/ext/visibility/assign1.C (revision 116505) >@@ -6,11 +6,12 @@ > B& operator=(const B&); > }; > >-struct D : public B { >+struct __attribute__((visibility("hidden"))) D : public B { > // The implicit assignment operator should be hidden. >-} __attribute__((visibility("hidden"))); >+}; > >-D d1, d2; >+__attribute__((visibility("hidden"))) D d1; >+__attribute__((visibility("hidden"))) D d2; > > void f() { > d1 = d2; >Index: gcc/testsuite/g++.dg/ext/visibility/typeinfo1.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/typeinfo1.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/typeinfo1.C (revision 116505) >@@ -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 *)); >Index: gcc/testsuite/g++.dg/ext/visibility/virtual.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/virtual.C (revision 116504) >+++ gcc/testsuite/g++.dg/ext/visibility/virtual.C (revision 116505) >@@ -1,9 +1,15 @@ >-/* Test that setting visibility for class affects virtual table. */ >+/* 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" } } */ > >-class __attribute__ ((visibility ("hidden"))) Foo >+struct A { }; >+ >+class __attribute__ ((visibility ("hidden"))) Foo: virtual public A > { > virtual void method(); > }; >Index: gcc/testsuite/g++.dg/ext/visibility/warn1.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/warn1.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/warn1.C (revision 116505) >@@ -0,0 +1,13 @@ >+// Warn when a declaration is specified with greater visibility than that >+// of its type. >+ >+// { dg-do compile } >+// { dg-require-visibility "" } >+// { dg-final { scan-hidden "_Z1fv" } } >+ >+namespace N __attribute ((__visibility__ ("hidden"))) >+{ >+ struct A { }; >+} >+ >+N::A f() { } // { dg-warning "visibility" "" } >Index: gcc/testsuite/g++.dg/ext/visibility/warn2.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/warn2.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/warn2.C (revision 116505) >@@ -0,0 +1,19 @@ >+// Complain when a class is specified with greater visibility than one of >+// its members' types or bases, and when a declaration has greater >+// visibility than its type. >+ >+// { dg-require-visibility "" } >+ >+namespace N __attribute ((__visibility__ ("hidden"))) >+{ >+ struct A { }; >+} >+ >+struct B >+{ // { dg-warning "visibility" } >+ N::A a; >+}; >+ >+B f () { } // { dg-warning "visibility" } >+ >+struct C: public N::A { }; // { dg-warning "visibility" } >Index: gcc/testsuite/g++.dg/ext/visibility/warn3.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/warn3.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/warn3.C (revision 116505) >@@ -0,0 +1,11 @@ >+// Warn when a class member is specified to have greater visibility than >+// its class. >+ >+// { dg-require-visibility "" } >+ >+struct __attribute ((visibility ("hidden"))) A >+{ >+ __attribute ((visibility ("default"))) void f (); // { dg-warning "visibility" } >+}; >+ >+void A::f() { } >Index: gcc/testsuite/g++.dg/ext/visibility/warn4.C >=================================================================== >--- gcc/testsuite/g++.dg/ext/visibility/warn4.C (revision 0) >+++ gcc/testsuite/g++.dg/ext/visibility/warn4.C (revision 116505) >@@ -0,0 +1,10 @@ >+// Error 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-error "already defined" } >Index: gcc/testsuite/g++.dg/template/anon2.C >=================================================================== >--- gcc/testsuite/g++.dg/template/anon2.C (revision 0) >+++ gcc/testsuite/g++.dg/template/anon2.C (revision 116505) >@@ -0,0 +1,15 @@ >+// PR c++/28279 >+// finish_static_data_member_decl was confused by the anonymous >+// namespace causing TREE_PUBLIC to be unset >+ >+template<typename T> >+struct is_pointer_impl { >+ static const bool value = true; >+}; >+ >+namespace { >+ class prefix_name_mapper {}; >+} >+ >+static const bool val = is_pointer_impl<prefix_name_mapper>::value; >+ >Index: gcc/objcp/objcp-decl.c >=================================================================== >--- gcc/objcp/objcp-decl.c (revision 116504) >+++ gcc/objcp/objcp-decl.c (revision 116505) >@@ -59,7 +59,7 @@ > CLASSTYPE_DECLARED_CLASS (s) = 0; /* this is a 'struct', not a 'class'. */ > xref_basetypes (s, NULL_TREE); /* no base classes here! */ > >- return begin_class_definition (s); >+ return begin_class_definition (s, NULL_TREE); > } > > tree >Index: gcc/cp/class.c >=================================================================== >--- gcc/cp/class.c (revision 116504) >+++ gcc/cp/class.c (revision 116505) >@@ -5047,6 +5047,9 @@ > DECL_SORTED_FIELDS (TYPE_MAIN_DECL (t)) = field_vec; > } > >+ /* Complain if one of the field types requires lower visibility. */ >+ constrain_class_visibility (t); >+ > /* Make the rtl for any new vtables we have created, and unmark > the base types we marked. */ > finish_vtbls (t); >Index: gcc/cp/decl.c >=================================================================== >--- gcc/cp/decl.c (revision 116504) >+++ gcc/cp/decl.c (revision 116505) >@@ -1863,6 +1863,11 @@ > > SET_DECL_TEMPLATE_SPECIALIZATION (olddecl); > >+ /* Don't propagate visibility from the template to the >+ specialization here. We'll do that in determine_visibility if >+ appropriate. */ >+ DECL_VISIBILITY_SPECIFIED (olddecl) = 0; >+ > /* [temp.expl.spec/14] We don't inline explicit specialization > just because the primary template says so. */ > } >@@ -3128,6 +3133,7 @@ > gcc_assert (global_namespace == NULL_TREE); > global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name, > void_type_node); >+ TREE_PUBLIC (global_namespace) = 1; > begin_scope (sk_namespace, global_namespace); > > current_lang_name = NULL_TREE; >@@ -5281,6 +5287,9 @@ > else > abstract_virtuals_error (decl, type); > >+ /* This needs to happen after the linkage is set. */ >+ determine_visibility (decl); >+ > if (TREE_CODE (decl) == FUNCTION_DECL > || TREE_TYPE (decl) == error_mark_node) > /* No initialization required. */ >@@ -5307,10 +5316,6 @@ > initialize_local_var (decl, init); > } > >- /* The variable is being defined, so determine its visibility. >- This needs to happen after the linkage is set. */ >- determine_visibility (decl); >- > /* If a variable is defined, and then a subsequent > definition with external linkage is encountered, we will > get here twice for the same variable. We want to avoid >Index: gcc/cp/method.c >=================================================================== >--- gcc/cp/method.c (revision 116504) >+++ gcc/cp/method.c (revision 116505) >@@ -163,6 +163,9 @@ > DECL_DECLARED_INLINE_P (thunk) = 0; > /* Nor has it been deferred. */ > DECL_DEFERRED_FN (thunk) = 0; >+ /* Nor is it a template instantiation. */ >+ DECL_USE_TEMPLATE (thunk) = 0; >+ DECL_TEMPLATE_INFO (thunk) = NULL; > > /* Add it to the list of thunks associated with FUNCTION. */ > TREE_CHAIN (thunk) = DECL_THUNKS (function); >Index: gcc/cp/rtti.c >=================================================================== >--- gcc/cp/rtti.c (revision 116504) >+++ gcc/cp/rtti.c (revision 116505) >@@ -1145,6 +1145,10 @@ > ti->name = get_identifier (real_name); > ti->vtable = NULL_TREE; > >+ /* Pretend this is public so determine_visibility doesn't give vtables >+ internal linkage. */ >+ TREE_PUBLIC (TYPE_MAIN_DECL (ti->type)) = 1; >+ > va_end (ap); > } > >Index: gcc/cp/tree.c >=================================================================== >--- gcc/cp/tree.c (revision 116504) >+++ gcc/cp/tree.c (revision 116505) >@@ -1394,6 +1394,30 @@ > } > } > >+/* Returns true if decl is within an anonymous namespace, however deeply >+ nested, or false otherwise. */ >+ >+bool >+decl_anon_ns_mem_p (tree decl) >+{ >+ while (1) >+ { >+ if (decl == NULL_TREE) >+ return false; >+ if (TREE_CODE (decl) == NAMESPACE_DECL >+ && DECL_NAME (decl) == NULL_TREE) >+ return true; >+ /* Classes and namespaces inside anonymous namespaces have >+ TREE_PUBLIC == 0, so we can shortcut the search. */ >+ else if (TYPE_P (decl)) >+ return (TREE_PUBLIC (TYPE_NAME (decl)) == 0); >+ else if (TREE_CODE (decl) == NAMESPACE_DECL) >+ return (TREE_PUBLIC (decl) == 0); >+ else >+ decl = DECL_CONTEXT (decl); >+ } >+} >+ > /* Return truthvalue of whether T1 is the same tree structure as T2. > Return 1 if they are the same. Return 0 if they are different. */ > >@@ -2176,7 +2200,8 @@ > template instantiations have internal linkage (in the object > file), but the symbols should still be treated as having external > linkage from the point of view of the language. */ >- if (TREE_CODE (decl) != TYPE_DECL && DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl)) >+ if (TREE_CODE (decl) != TYPE_DECL && DECL_LANG_SPECIFIC (decl) >+ && DECL_COMDAT (decl)) > return lk_external; > > /* Things in local scope do not have linkage, if they don't have >Index: gcc/cp/cp-tree.h >=================================================================== >--- gcc/cp/cp-tree.h (revision 116504) >+++ gcc/cp/cp-tree.h (revision 116505) >@@ -3984,6 +3984,8 @@ > extern tree coerce_delete_type (tree); > extern void comdat_linkage (tree); > extern void determine_visibility (tree); >+extern void constrain_class_visibility (tree); >+extern void update_member_visibility (tree); > extern void import_export_decl (tree); > extern tree build_cleanup (tree); > extern tree build_offset_ref_call_from_tree (tree, tree); >@@ -4299,7 +4301,7 @@ > extern void finish_translation_unit (void); > extern tree finish_template_type_parm (tree, tree); > extern tree finish_template_template_parm (tree, tree); >-extern tree begin_class_definition (tree); >+extern tree begin_class_definition (tree, tree); > extern void finish_template_decl (tree); > extern tree finish_template_type (tree, tree, int); > extern tree finish_base_specifier (tree, tree, bool); >@@ -4381,6 +4383,7 @@ > extern tree break_out_target_exprs (tree); > extern tree get_type_decl (tree); > extern tree decl_namespace_context (tree); >+extern bool decl_anon_ns_mem_p (tree); > extern tree lvalue_type (tree); > extern tree error_type (tree); > extern int varargs_function_p (tree); >Index: gcc/cp/pt.c >=================================================================== >--- gcc/cp/pt.c (revision 116504) >+++ gcc/cp/pt.c (revision 116505) >@@ -2147,13 +2147,7 @@ > template it specializes. */ > TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl); > TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl); >- /* The specialization has the same visibility as the >- template it specializes. */ >- if (DECL_VISIBILITY_SPECIFIED (gen_tmpl)) >- { >- DECL_VISIBILITY_SPECIFIED (decl) = 1; >- DECL_VISIBILITY (decl) = DECL_VISIBILITY (gen_tmpl); >- } >+ > /* If DECL is a friend declaration, declared using an > unqualified name, the namespace associated with DECL may > have been set incorrectly. For example, in: >@@ -3605,9 +3599,9 @@ > > if (!constant_address_p) > { >- error ("%qE is not a valid template argument for type %qT " >- "because it is not a constant pointer", expr, type); >- return NULL_TREE; >+ error ("%qE is not a valid template argument for type %qT " >+ "because it is not a constant pointer", expr, type); >+ return NULL_TREE; > } > } > /* [temp.arg.nontype]/5, bullet 3 >@@ -4793,6 +4787,10 @@ > code that generates debugging information will crash. */ > DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1; > >+ /* Possibly limit visibility based on template args. */ >+ TREE_PUBLIC (type_decl) = 1; >+ determine_visibility (type_decl); >+ > POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t); > } > timevar_pop (TV_NAME_LOOKUP); >@@ -6608,6 +6606,11 @@ > SET_DECL_FRIEND_CONTEXT (r, > tsubst (DECL_FRIEND_CONTEXT (t), > args, complain, in_decl)); >+ >+ /* Possibly limit visibility based on template args. */ >+ DECL_VISIBILITY (r) = VISIBILITY_DEFAULT; >+ DECL_VISIBILITY_SPECIFIED (r) = 0; >+ determine_visibility (r); > } > break; > >@@ -6804,6 +6807,13 @@ > if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL)) > SET_DECL_RTL (r, NULL_RTX); > DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0; >+ if (TREE_CODE (r) == VAR_DECL) >+ { >+ /* Possibly limit visibility based on template args. */ >+ DECL_VISIBILITY (r) = VISIBILITY_DEFAULT; >+ DECL_VISIBILITY_SPECIFIED (r) = 0; >+ determine_visibility (r); >+ } > > if (!local_p) > { >Index: gcc/cp/semantics.c >=================================================================== >--- gcc/cp/semantics.c (revision 116504) >+++ gcc/cp/semantics.c (revision 116505) >@@ -2151,7 +2151,7 @@ > /* Begin a class definition, as indicated by T. */ > > tree >-begin_class_definition (tree t) >+begin_class_definition (tree t, tree attributes) > { > if (t == error_mark_node) > return error_mark_node; >@@ -2190,6 +2190,9 @@ > maybe_process_partial_specialization (t); > pushclass (t); > TYPE_BEING_DEFINED (t) = 1; >+ >+ cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); >+ > if (flag_pack_struct) > { > tree v; >Index: gcc/cp/name-lookup.c >=================================================================== >--- gcc/cp/name-lookup.c (revision 116504) >+++ gcc/cp/name-lookup.c (revision 116505) >@@ -3032,7 +3032,12 @@ > /* Make a new namespace, binding the name to it. */ > d = build_lang_decl (NAMESPACE_DECL, name, void_type_node); > DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace); >- TREE_PUBLIC (d) = 1; >+ /* The name of this namespace is not visible to other translation >+ units if it is an anonymous namespace or member thereof. */ >+ if (anon || decl_anon_ns_mem_p (current_namespace)) >+ TREE_PUBLIC (d) = 0; >+ else >+ TREE_PUBLIC (d) = 1; > pushdecl (d); > if (anon) > { >@@ -4972,6 +4977,10 @@ > gcc_assert (TREE_CODE (decl) == TYPE_DECL); > TYPE_STUB_DECL (type) = decl; > >+ /* Set type visibility now if this is a forward declaration. */ >+ TREE_PUBLIC (decl) = 1; >+ determine_visibility (decl); >+ > POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type); > } > >Index: gcc/cp/decl2.c >=================================================================== >--- gcc/cp/decl2.c (revision 116504) >+++ gcc/cp/decl2.c (revision 116505) >@@ -754,8 +754,6 @@ > tree asmspec_tree, > int flags) > { >- gcc_assert (TREE_PUBLIC (decl)); >- > DECL_CONTEXT (decl) = current_class_type; > > /* We cannot call pushdecl here, because that would fill in the >@@ -765,7 +763,7 @@ > if (!asmspec_tree && current_class_type) > DECL_INITIAL (decl) = error_mark_node; > >- if (! processing_template_decl) >+ if (! processing_template_decl && TREE_PUBLIC (decl)) > note_vague_linkage_var (decl); > > if (LOCAL_CLASS_P (current_class_type)) >@@ -1578,6 +1576,110 @@ > return true; > } > >+/* A special return value from type_visibility meaning internal >+ linkage. */ >+ >+enum { VISIBILITY_STATIC = VISIBILITY_INTERNAL+1 }; >+ >+/* walk_tree helper function for type_visibility. */ >+ >+static tree >+min_vis_r (tree *tp, int *walk_subtrees, void *data) >+{ >+ int *vis_p = (int *)data; >+ if (! TYPE_P (*tp)) >+ { >+ *walk_subtrees = 0; >+ } >+ else if (CLASS_TYPE_P (*tp)) >+ { >+ if (!TREE_PUBLIC (TYPE_MAIN_DECL (*tp))) >+ { >+ *vis_p = VISIBILITY_STATIC; >+ return *tp; >+ } >+ else if (CLASSTYPE_VISIBILITY (*tp) > *vis_p) >+ *vis_p = CLASSTYPE_VISIBILITY (*tp); >+ } >+ return NULL; >+} >+ >+/* Returns the visibility of TYPE, which is the minimum visibility of its >+ component types. */ >+ >+static int >+type_visibility (tree type) >+{ >+ int vis = VISIBILITY_DEFAULT; >+ walk_tree_without_duplicates (&type, min_vis_r, &vis); >+ return vis; >+} >+ >+/* Limit the visibility of DECL to VISIBILITY. SPECIFIED is true if the >+ constraint comes from an attribute or pragma; REASON is the source of >+ the constraint. */ >+ >+static bool >+constrain_visibility (tree decl, int visibility, bool specified, >+ const char *reason) >+{ >+ if (visibility == VISIBILITY_STATIC) >+ { >+ TREE_PUBLIC (decl) = 0; >+ DECL_INTERFACE_KNOWN (decl) = 1; >+ if (DECL_LANG_SPECIFIC (decl)) >+ DECL_NOT_REALLY_EXTERN (decl) = 1; >+ } >+ else if (visibility > DECL_VISIBILITY (decl)) >+ { >+ if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))) >+ warning (OPT_Wattributes, "%q+D: visibility attribute requests " >+ "greater visibility than its %s allows", decl, reason); >+ DECL_VISIBILITY (decl) = visibility; >+ if (!DECL_VISIBILITY_SPECIFIED (decl)) >+ DECL_VISIBILITY_SPECIFIED (decl) = specified; >+ return true; >+ } >+ return false; >+} >+ >+/* Constrain the visibility of DECL based on the visbility of its template >+ arguments. */ >+ >+static void >+constrain_visibility_for_template (tree decl, tree targs) >+{ >+ /* If this is a template instantiation, check the innermost >+ template args for visibility constraints. The outer template >+ args are covered by the class check. */ >+ tree args = INNERMOST_TEMPLATE_ARGS (targs); >+ int i; >+ for (i = TREE_VEC_LENGTH (args); i > 0; --i) >+ { >+ int vis = 0; >+ >+ tree arg = TREE_VEC_ELT (args, i-1); >+ if (TYPE_P (arg)) >+ vis = type_visibility (arg); >+ else if (TREE_TYPE (arg) && POINTER_TYPE_P (TREE_TYPE (arg))) >+ { >+ STRIP_NOPS (arg); >+ if (TREE_CODE (arg) == ADDR_EXPR) >+ arg = TREE_OPERAND (arg, 0); >+ if (TREE_CODE (arg) == VAR_DECL >+ || TREE_CODE (arg) == FUNCTION_DECL) >+ { >+ if (! TREE_PUBLIC (arg)) >+ vis = VISIBILITY_STATIC; >+ else >+ vis = DECL_VISIBILITY (arg); >+ } >+ } >+ if (vis) >+ constrain_visibility (decl, vis, false, "template parameter"); >+ } >+} >+ > /* Like c_determine_visibility, but with additional C++-specific > behavior. > >@@ -1589,13 +1691,19 @@ > > Note that because namespaces have multiple independent definitions, > namespace visibility is handled elsewhere using the #pragma visibility >- machinery rather than by decorating the namespace declaration. */ >+ machinery rather than by decorating the namespace declaration. > >+ The goal is for constraints from the type to give a diagnostic, and >+ other constraints to be applied silently. */ >+ > void > determine_visibility (tree decl) > { >- tree class_type; >+ tree class_type = NULL_TREE; >+ bool use_template; > >+ /* Remember that all decls get VISIBILITY_DEFAULT when built. */ >+ > /* Only relevant for names with external linkage. */ > if (!TREE_PUBLIC (decl)) > return; >@@ -1605,10 +1713,31 @@ > maybe_clone_body. */ > gcc_assert (!DECL_CLONED_FUNCTION_P (decl)); > >- /* Give the common code a chance to make a determination. */ >- if (c_determine_visibility (decl)) >- return; >+ if (TREE_CODE (decl) == TYPE_DECL) >+ { >+ if (CLASS_TYPE_P (TREE_TYPE (decl))) >+ use_template = CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)); >+ else if (TYPE_TEMPLATE_INFO (TREE_TYPE (decl))) >+ use_template = 1; >+ else >+ use_template = 0; >+ } >+ else if (DECL_LANG_SPECIFIC (decl)) >+ use_template = DECL_USE_TEMPLATE (decl); >+ else >+ use_template = 0; > >+ /* Anything that is exported must have default visibility. */ >+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES >+ && lookup_attribute ("dllexport", >+ TREE_CODE (decl) == TYPE_DECL >+ ? TYPE_ATTRIBUTES (TREE_TYPE (decl)) >+ : DECL_ATTRIBUTES (decl))) >+ { >+ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; >+ DECL_VISIBILITY_SPECIFIED (decl) = 1; >+ } >+ > /* If DECL is a member of a class, visibility specifiers on the > class can influence the visibility of the DECL. */ > if (DECL_CLASS_SCOPE_P (decl)) >@@ -1619,6 +1748,8 @@ > class_type = TREE_TYPE (DECL_NAME (decl)); > else > { >+ /* Not a class member. */ >+ > /* Virtual tables have DECL_CONTEXT set to their associated class, > so they are automatically handled above. */ > gcc_assert (TREE_CODE (decl) != VAR_DECL >@@ -1626,79 +1757,140 @@ > > if (DECL_FUNCTION_SCOPE_P (decl)) > { >+ /* Local statics and classes get the visibility of their >+ containing function. */ > tree fn = DECL_CONTEXT (decl); > DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn); > DECL_VISIBILITY_SPECIFIED (decl) = DECL_VISIBILITY_SPECIFIED (fn); >+ >+ /* Local classes in templates have CLASSTYPE_USE_TEMPLATE set, >+ but have no TEMPLATE_INFO, so don't try to check it. */ >+ use_template = 0; > } >+ else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl)) >+ { >+ /* tinfo visibility is based on the type it's for. */ >+ constrain_visibility >+ (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))), >+ false, "type"); >+ } >+ else if (use_template) >+ /* Template instantiations and specializations get visibility based >+ on their template unless they override it with an attribute. */; >+ else if (! DECL_VISIBILITY_SPECIFIED (decl)) >+ { >+ /* Set default visibility to whatever the user supplied with >+ #pragma GCC visibility or a namespace visibility attribute. */ >+ DECL_VISIBILITY (decl) = default_visibility; >+ DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma; >+ } >+ } > >- /* Entities not associated with any class just get the >- visibility specified by their attributes. */ >- return; >+ if (use_template) >+ { >+ tree tinfo = (TREE_CODE (decl) == TYPE_DECL >+ ? TYPE_TEMPLATE_INFO (TREE_TYPE (decl)) >+ : DECL_TEMPLATE_INFO (decl)); >+ tree args = TI_ARGS (tinfo); >+ int depth = TMPL_ARGS_DEPTH (args); >+ >+ /* If the template has explicit visibility and the specialization >+ doesn't, use the visibility from the template. */ >+ if (!DECL_VISIBILITY_SPECIFIED (decl)) >+ { >+ tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo)); >+ DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern); >+ } >+ >+ /* FIXME should TMPL_ARGS_DEPTH really return 1 for null input? */ >+ if (args && depth > template_class_depth (class_type)) >+ /* Don't let it have more visibility than its template type >+ arguments. */ >+ constrain_visibility_for_template (decl, args); > } > >- /* By default, static data members and function members receive >- the visibility of their containing class. */ > if (class_type) >- { >- determine_visibility_from_class (decl, class_type); >+ determine_visibility_from_class (decl, class_type); > >- /* Give the target a chance to override the visibility associated >- with DECL. */ >- if (TREE_CODE (decl) == VAR_DECL >- && (DECL_TINFO_P (decl) >- || (DECL_VTABLE_OR_VTT_P (decl) >- /* Construction virtual tables are not exported because >- they cannot be referred to from other object files; >- their name is not standardized by the ABI. */ >- && !DECL_CONSTRUCTION_VTABLE_P (decl))) >- && TREE_PUBLIC (decl) >- && !DECL_REALLY_EXTERN (decl) >- && DECL_VISIBILITY_SPECIFIED (decl) >- && (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))) >- targetm.cxx.determine_class_data_visibility (decl); >- } >+ /* Don't let it have more visibility than its type. */ >+ if (TREE_CODE (decl) != TYPE_DECL) >+ if (constrain_visibility (decl, type_visibility (TREE_TYPE (decl)), >+ false, "type")) >+ warning (OPT_Wattributes, "\ >+%q+D declared with greater visibility than its type", >+ decl); >+ >+ if (decl_anon_ns_mem_p (decl)) >+ /* Names in an anonymous namespace get internal linkage. >+ This might change once we implement export. */ >+ constrain_visibility (decl, VISIBILITY_STATIC, >+ false, "namespace"); > } > >+/* By default, static data members and function members receive >+ the visibility of their containing class. */ >+ > static void > determine_visibility_from_class (tree decl, tree class_type) > { >- if (TARGET_DLLIMPORT_DECL_ATTRIBUTES >- && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class_type))) >- { >- DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; >- DECL_VISIBILITY_SPECIFIED (decl) = 1; >- } >- else if (TREE_CODE (decl) == FUNCTION_DECL >- && DECL_DECLARED_INLINE_P (decl) >- && visibility_options.inlines_hidden) >- { >- /* Don't change it if it has been set explicitly by user. */ >- if (!DECL_VISIBILITY_SPECIFIED (decl)) >- { >- DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; >- DECL_VISIBILITY_SPECIFIED (decl) = 1; >- } >- } >- else if (CLASSTYPE_VISIBILITY_SPECIFIED (class_type)) >- { >- DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type); >- DECL_VISIBILITY_SPECIFIED (decl) = 1; >- } >- else if (TYPE_CLASS_SCOPE_P (class_type)) >- determine_visibility_from_class (decl, TYPE_CONTEXT (class_type)); >- else if (TYPE_FUNCTION_SCOPE_P (class_type)) >- { >- tree fn = TYPE_CONTEXT (class_type); >- DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn); >- DECL_VISIBILITY_SPECIFIED (decl) = DECL_VISIBILITY_SPECIFIED (fn); >- } >- else if (!DECL_VISIBILITY_SPECIFIED (decl)) >- { >- DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type); >- DECL_VISIBILITY_SPECIFIED (decl) = 0; >- } >+ if (visibility_options.inlines_hidden >+ /* Don't do this for inline templates; specializations might not be >+ inline, and we don't want them to inherit the hidden >+ visibility. We'll set it here for all inline instantiations. */ >+ && !processing_template_decl >+ && ! DECL_VISIBILITY_SPECIFIED (decl) >+ && TREE_CODE (decl) == FUNCTION_DECL >+ && DECL_DECLARED_INLINE_P (decl)) >+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; >+ >+ /* The decl can't have more visibility than its class. */ >+ constrain_visibility (decl, CLASSTYPE_VISIBILITY (class_type), >+ CLASSTYPE_VISIBILITY_SPECIFIED (class_type), >+ "class"); >+ >+ /* Give the target a chance to override the visibility associated >+ with DECL. */ >+ if (TREE_CODE (decl) == VAR_DECL >+ && (DECL_TINFO_P (decl) >+ || (DECL_VTABLE_OR_VTT_P (decl) >+ /* Construction virtual tables are not exported because >+ they cannot be referred to from other object files; >+ their name is not standardized by the ABI. */ >+ && !DECL_CONSTRUCTION_VTABLE_P (decl))) >+ && TREE_PUBLIC (decl) >+ && !DECL_REALLY_EXTERN (decl) >+ && DECL_VISIBILITY_SPECIFIED (decl) >+ && (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))) >+ targetm.cxx.determine_class_data_visibility (decl); > } > >+/* Constrain the visibility of a class TYPE based on the visibility of its >+ field types. Warn if any fields require lesser visibility. */ >+ >+void >+constrain_class_visibility (tree type) >+{ >+ tree decl = TYPE_MAIN_DECL (type); >+ tree binfo = TYPE_BINFO (type); >+ tree t; >+ int i; >+ >+ for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t)) >+ if (TREE_CODE (t) == FIELD_DECL) >+ if (constrain_visibility (decl, type_visibility (TREE_TYPE (t)), >+ false, "field type")) >+ warning (OPT_Wattributes, "\ >+%qT declared with greater visibility than the type of its field %qD", >+ type, t); >+ >+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, t); ++i) >+ if (constrain_visibility (decl, type_visibility (TREE_TYPE (t)), >+ false, "base type")) >+ warning (OPT_Wattributes, "\ >+%qT declared with greater visibility than its base %qT", >+ type, TREE_TYPE (t)); >+} >+ > /* DECL is a FUNCTION_DECL or VAR_DECL. If the object file linkage > for DECL has not already been determined, do so now by setting > DECL_EXTERNAL, DECL_COMDAT and other related flags. Until this >Index: gcc/cp/parser.c >=================================================================== >--- gcc/cp/parser.c (revision 116504) >+++ gcc/cp/parser.c (revision 116505) >@@ -9411,7 +9411,7 @@ > if (declarator != cp_error_declarator) > { > decl = grokdeclarator (declarator, &decl_specifiers, >- NORMAL, 0, NULL); >+ NORMAL, 0, &decl_specifiers.attributes); > /* Turn access control back on for names used during > template instantiation. */ > pop_deferring_access_checks (); >@@ -9560,22 +9560,11 @@ > switch (keyword) > { > case RID_ENUM: >- /* 'enum' [identifier] '{' introduces an enum-specifier; >- 'enum' <anything else> introduces an elaborated-type-specifier. */ >- if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_BRACE >- || (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME >- && cp_lexer_peek_nth_token (parser->lexer, 3)->type >- == CPP_OPEN_BRACE)) >+ /* Look for the enum-specifier. */ >+ type_spec = cp_parser_enum_specifier (parser); >+ /* If that worked, we're done. */ >+ if (type_spec) > { >- if (parser->num_template_parameter_lists) >- { >- error ("template declaration of %qs", "enum"); >- cp_parser_skip_to_end_of_block_or_statement (parser); >- type_spec = error_mark_node; >- } >- else >- type_spec = cp_parser_enum_specifier (parser); >- > if (declares_class_or_enum) > *declares_class_or_enum = 2; > if (decl_specs) >@@ -10077,6 +10066,7 @@ > /*type_p=*/true, > is_declaration); > /* For everything but enumeration types, consider a template-id. */ >+ /* For an enumeration type, consider only a plain identifier. */ > if (tag_type != enum_type) > { > bool template_p = false; >@@ -10108,7 +10098,6 @@ > type = TREE_TYPE (decl); > } > >- /* For an enumeration type, consider only a plain identifier. */ > if (!type) > { > identifier = cp_parser_identifier (parser); >@@ -10236,11 +10225,6 @@ > else > ts = ts_global; > >- /* Warn about attributes. They are ignored. */ >- if (attributes) >- warning (OPT_Wattributes, >- "type attributes are honored only at type definition"); >- > template_p = > (parser->num_template_parameter_lists > && (cp_parser_next_token_starts_class_definition_p (parser) >@@ -10253,6 +10237,21 @@ > type = xref_tag (tag_type, identifier, ts, template_p); > } > } >+ >+ /* Allow attributes on forward declarations of classes. */ >+ if (attributes) >+ { >+ if (tag_type != enum_type && CLASSTYPE_TEMPLATE_INSTANTIATION (type) >+ && ! processing_explicit_instantiation) >+ warning (OPT_Wattributes, >+ "attributes ignored on template instantiation"); >+ else if (is_declaration && cp_parser_declares_only_class_p (parser)) >+ cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); >+ else >+ warning (OPT_Wattributes, >+ "attributes ignored on elaborated-type-specifier that is not a forward declaration"); >+ } >+ > if (tag_type != enum_type) > cp_parser_check_class_key (tag_type, type); > >@@ -10269,27 +10268,43 @@ > enum identifier [opt] { enumerator-list [opt] } > > GNU Extensions: >- enum identifier [opt] { enumerator-list [opt] } attributes >+ enum attributes[opt] identifier [opt] { enumerator-list [opt] } >+ attributes[opt] > >- Returns an ENUM_TYPE representing the enumeration. */ >+ Returns an ENUM_TYPE representing the enumeration, or NULL_TREE >+ if the token stream isn't an enum-specifier after all. */ > > static tree > cp_parser_enum_specifier (cp_parser* parser) > { > tree identifier; > tree type; >+ tree attributes; > >+ /* Parse tentatively so that we can back up if we don't find a >+ enum-specifier. */ >+ cp_parser_parse_tentatively (parser); >+ > /* Caller guarantees that the current token is 'enum', an identifier > possibly follows, and the token after that is an opening brace. > If we don't have an identifier, fabricate an anonymous name for > the enumeration being defined. */ > cp_lexer_consume_token (parser->lexer); > >+ attributes = cp_parser_attributes_opt (parser); >+ > if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) > identifier = cp_parser_identifier (parser); > else > identifier = make_anon_name (); > >+ /* Look for the `{' but don't consume it yet. */ >+ if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) >+ cp_parser_simulate_error (parser); >+ >+ if (!cp_parser_parse_definitely (parser)) >+ return NULL_TREE; >+ > /* Issue an error message if type-definitions are forbidden here. */ > cp_parser_check_type_definition (parser); > >@@ -10301,6 +10316,12 @@ > /* Consume the opening brace. */ > cp_lexer_consume_token (parser->lexer); > >+ if (type == error_mark_node) >+ { >+ cp_parser_skip_to_end_of_block_or_statement (parser); >+ return error_mark_node; >+ } >+ > /* If the next token is not '}', then there are some enumerators. */ > if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE)) > cp_parser_enumerator_list (parser, type); >@@ -12909,7 +12930,7 @@ > scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)); > old_scope = push_inner_scope (scope); > } >- type = begin_class_definition (type); >+ type = begin_class_definition (type, attributes); > > if (type == error_mark_node) > /* If the type is erroneous, skip the entire body of the class. */ >@@ -12926,10 +12947,7 @@ > has_trailing_semicolon = (token->type == CPP_SEMICOLON); > /* Look for trailing attributes to apply to this class. */ > if (cp_parser_allow_gnu_extensions_p (parser)) >- { >- tree sub_attr = cp_parser_attributes_opt (parser); >- attributes = chainon (attributes, sub_attr); >- } >+ attributes = cp_parser_attributes_opt (parser); > if (type != error_mark_node) > type = finish_struct (type, attributes); > if (nested_name_specifier_p) >Index: gcc/c-decl.c >=================================================================== >--- gcc/c-decl.c (revision 116504) >+++ gcc/c-decl.c (revision 116505) >@@ -3448,18 +3448,16 @@ > /* If #pragma weak was used, mark the decl weak now. */ > maybe_apply_pragma_weak (decl); > >- /* If this is a variable definition, determine its ELF visibility. */ >- if (TREE_CODE (decl) == VAR_DECL >- && TREE_STATIC (decl) >- && !DECL_EXTERNAL (decl)) >- c_determine_visibility (decl); >- > /* Output the assembler code and/or RTL code for variables and functions, > unless the type is an undefined structure or union. > If not, it will get done when the type is completed. */ > > if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) > { >+ /* Determine the ELF visibility. */ >+ if (TREE_PUBLIC (decl)) >+ c_determine_visibility (decl); >+ > /* This is a no-op in c-lang.c or something real in objc-act.c. */ > if (c_dialect_objc ()) > objc_check_decl (decl); >Index: gcc/varasm.c >=================================================================== >--- gcc/varasm.c (revision 116504) >+++ gcc/varasm.c (revision 116505) >@@ -4955,7 +4955,7 @@ > default_assemble_visibility (tree decl, int vis) > { > static const char * const visibility_types[] = { >- NULL, "internal", "hidden", "protected" >+ NULL, "protected", "hidden", "internal" > }; > > const char *name, *type; >Index: gcc/c-common.c >=================================================================== >--- gcc/c-common.c (revision 116504) >+++ gcc/c-common.c (revision 116505) >@@ -4805,21 +4805,28 @@ > static tree > handle_visibility_attribute (tree *node, tree name, tree args, > int ARG_UNUSED (flags), >- bool *no_add_attrs) >+ bool *ARG_UNUSED (no_add_attrs)) > { > tree decl = *node; > tree id = TREE_VALUE (args); >+ enum symbol_visibility vis; > >- *no_add_attrs = true; >- > if (TYPE_P (*node)) > { >- if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE) >- { >- warning (OPT_Wattributes, "%qE attribute ignored on non-class types", >- name); >- return NULL_TREE; >- } >+ if (TREE_CODE (*node) == ENUMERAL_TYPE) >+ /* OK */; >+ else if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE) >+ { >+ warning (OPT_Wattributes, "%qE attribute ignored on non-class types", >+ name); >+ return NULL_TREE; >+ } >+ else if (TYPE_FIELDS (*node)) >+ { >+ error ("%qE attribute ignored because %qT is already defined", >+ name, *node); >+ return NULL_TREE; >+ } > } > else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl)) > { >@@ -4848,23 +4855,33 @@ > } > > if (strcmp (TREE_STRING_POINTER (id), "default") == 0) >- DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; >+ vis = VISIBILITY_DEFAULT; > else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0) >- DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL; >+ vis = VISIBILITY_INTERNAL; > else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0) >- DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; >+ vis = VISIBILITY_HIDDEN; > else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0) >- DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED; >+ vis = VISIBILITY_PROTECTED; > else >- error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); >+ { >+ error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); >+ vis = VISIBILITY_DEFAULT; >+ } >+ >+ if (DECL_VISIBILITY_SPECIFIED (decl) >+ && vis != DECL_VISIBILITY (decl) >+ && lookup_attribute ("visibility", (TYPE_P (*node) >+ ? TYPE_ATTRIBUTES (*node) >+ : DECL_ATTRIBUTES (decl)))) >+ error ("%qD redeclared with different visibility", decl); >+ >+ DECL_VISIBILITY (decl) = vis; > DECL_VISIBILITY_SPECIFIED (decl) = 1; > >- /* For decls only, go ahead and attach the attribute to the node as well. >- This is needed so we can determine whether we have VISIBILITY_DEFAULT >- because the visibility was not specified, or because it was explicitly >- overridden from the class visibility. */ >- if (DECL_P (*node)) >- *no_add_attrs = false; >+ /* Go ahead and attach the attribute to the node as well. This is needed >+ so we can determine whether we have VISIBILITY_DEFAULT because the >+ visibility was not specified, or because it was explicitly overridden >+ from the containing scope. */ > > return NULL_TREE; > } >@@ -4901,6 +4918,13 @@ > return true; > } > >+ /* Set default visibility to whatever the user supplied with >+ visibility_specified depending on #pragma GCC visibility. */ >+ if (!DECL_VISIBILITY_SPECIFIED (decl)) >+ { >+ DECL_VISIBILITY (decl) = default_visibility; >+ DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma; >+ } > return false; > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 146817
:
96372
|
96373
| 96374 |
96375