[PATCH] PE/COFF: Implement visibility attribute via .drectve
Oleg Tolmatcev <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
On PE/COFF targets (MinGW, Cygwin), the visibility attribute was previously ignored with a warning. This patch makes it functional by emitting -exclude-symbols directives into the .drectve section, matching Clang's behavior. The GNU linker already reads and respects these directives during auto-export, so hidden/internal symbols are now correctly excluded from DLL exports. gcc/ChangeLog: * config/mingw/winnt.cc (i386_pe_assemble_visibility): Emit -exclude-symbols directive into .drectve for VISIBILITY_HIDDEN and VISIBILITY_INTERNAL instead of warning. gcc/testsuite/ChangeLog: * gcc.target/i386/visibility-hidden-mingw.c: New test. Signed-off-by: Oleg Tolmatcev <[email protected]> --- gcc/config/mingw/winnt.cc | 20 +++++++++------- .../gcc.target/i386/visibility-hidden-mingw.c | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/visibility-hidden-mingw.c diff --git a/gcc/config/mingw/winnt.cc b/gcc/config/mingw/winnt.cc index 66d7450652..6f2d85b090 100644 --- a/gcc/config/mingw/winnt.cc +++ b/gcc/config/mingw/winnt.cc @@ -256,18 +256,22 @@ i386_pe_maybe_mangle_decl_assembler_name (tree decl, tree id) /* Emit an assembler directive to set symbol for DECL visibility to the visibility type VIS, which must not be VISIBILITY_DEFAULT. - As for PE there is no hidden support in gas, we just warn for - user-specified visibility attributes. */ + Emit a -exclude-symbols directive into .drectve, compatible with + what Clang emits for hidden visibility on PE/COFF. */ void -i386_pe_assemble_visibility (tree decl, int) +i386_pe_assemble_visibility (tree decl, int vis) { - if (!decl - || !lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))) + if (!decl) return; - if (!DECL_ARTIFICIAL (decl)) - warning (OPT_Wattributes, "visibility attribute not supported " - "in this configuration; ignored"); + + if (vis == VISIBILITY_HIDDEN || vis == VISIBILITY_INTERNAL) + { + tree id = DECL_ASSEMBLER_NAME (decl); + const char *name = IDENTIFIER_POINTER (id); + drectve_section (); + fprintf (asm_out_file, "\t.ascii \" -exclude-symbols:%s\"\n", name); + } } #if !defined (TARGET_AARCH64_MS_ABI) diff --git a/gcc/testsuite/gcc.target/i386/visibility-hidden-mingw.c b/gcc/testsuite/gcc.target/i386/visibility-hidden-mingw.c new file mode 100644 index 0000000000..12d792631d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/visibility-hidden-mingw.c @@ -0,0 +1,24 @@ +/* { dg-do link { target *-*-mingw* *-*-cygwin* } } */ +/* { dg-require-dll "" } */ +/* { dg-options "-shared -fvisibility=hidden -Wl,--output-def,visibility-hidden-mingw.def" } */ + +void __attribute__((visibility("default"))) exported_func(void) {} +void hidden_func(void) {} +void __attribute__((visibility("hidden"))) explicit_hidden_func(void) {} +void __attribute__((visibility("internal"))) internal_func(void) {} + +/* exported_func has default visibility, so it should be exported. */ +/* { dg-final { scan-file visibility-hidden-mingw.def "(?n)^\\s*exported_func(?:\\s+@\[0-9\]+)?$" } } */ + +/* hidden_func gets hidden from -fvisibility=hidden, so it should not be + auto-exported. */ +/* { dg-final { scan-file-not visibility-hidden-mingw.def "(?n)^\\s*hidden_func(?:\\s+@\[0-9\]+)?$" } } */ + +/* explicit_hidden_func is explicitly hidden, so it should not be + auto-exported. */ +/* { dg-final { scan-file-not visibility-hidden-mingw.def "(?n)^\\s*explicit_hidden_func(?:\\s+@\[0-9\]+)?$" } } */ + +/* internal_func has internal visibility, so it should not be auto-exported. */ +/* { dg-final { scan-file-not visibility-hidden-mingw.def "(?n)^\\s*internal_func(?:\\s+@\[0-9\]+)?$" } } */ + +/* { dg-final { remove-build-file "visibility-hidden-mingw.def" } } */ -- 2.55.0.windows.1