From b2ca370228811541d31d023ffd1280f5a819d8f2 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Fri, 6 Aug 2004 02:03:29 +0000 Subject: [PATCH] tree.c (handle_dll_attribute): Move here from i383/winnt.c. * tree.c (handle_dll_attribute): Move here from i383/winnt.c. Replace use of DECL_INLINE with DECL_DECLARED_INLINE_P. Set DECL_VISIBLITY. Test TARGET_DLLIMPORT_DECL_ATTRIBUTES with #if. * tree.h (handle_dll_attribute): Declare. Test TARGET_DLLIMPORT_DECL_ATTRIBUTES with #if. * c-common.h (c_determine_visibility): Declare. * c-common.c (c_determine_visibility): New function. * c-decl.c (finish_decl): Use it. (finish_function): Likewise. * defaults.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define it to zero, by default. Use #if, not #ifdef, to test it. * config/arm/arm.c (arm_attribute_table): Use handle_dll_attribute. Test TARGET_DLLIMPORT_DECL_ATTRIBUTES with #if. * config/arm/pe.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define to 1. * config/i386/cygming.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define to 1. * config/i386/i386-protos.h (ix86_handle_dll_attribute): Remove. * config/i386/i386.c (ix86_attribute_table): Use handle_dll_attribute for dllimport/dllexport. Test TARGET_DLLIMPORT_DECL_ATTRIBUTES with #if. * config/i386/winnt.c (ix86_handle_dll_attribute): Remove. * config/mcore/mcore.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define it to 1. * config/mcore/mcore.c (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Test it with #if. * config/sh/symbian-pre.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define it to 1. * doc/extend.texi (dllexport): Clarify and correct documentation. (dllimport): Likewise. * doc/tm.texi (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Mention handle_dll_attribute. * decl.c (start_preparsed_function): Move determine_visibility call. * decl2.c (determine_visibility): Incorporate dllexport testing. * g++.dg/ext/visibility/assign1.C: Use scan-hidden and dg-require-visiblity. * g++.dg/ext/visibility/fvisibility-inlines-hidden.C: Likewise. * g++.dg/ext/visibility/fvisibility.C: Likewise. * g++.dg/ext/visibility/memfuncts.C: Likewise. * g++.dg/ext/visibility/new1.C: Likewise. * g++.dg/ext/visibility/pragma.C: Likewise. * g++.dg/ext/visibility/staticmemfuncts.C: Likewise. * g++.dg/ext/visibility/virtual.C: Likewise. * g++/dg/ext/visibility/visibility-1.C: Likewise. * g++/dg/ext/visibility/visibility-2.C: Likewise. * g++/dg/ext/visibility/visibility-3.C: Likewise. * g++/dg/ext/visibility/visibility-4.C: Likewise. * g++/dg/ext/visibility/visibility-5.C: Likewise. * g++/dg/ext/visibility/visibility-6.C: Likewise. * g++/dg/ext/visibility/visibility-7.C: Likewise. * g++/dg/ext/visibility/visibility-8.C: New test. * gcc.c-torture/compile/dll.x: Remove. * gcc.dg/dll-2.c: Use dg-require-dll * gcc.dg/visibility-10.c: New test. * lib/gcc-dg.exp (dg-require-dll): Add Symbian to list of targets supporting DLLs. * testsuite/lib/scanasm.exp (scan_hidden): New function. (scan_not_hidden): Likewise. From-SVN: r85621 --- gcc/ChangeLog | 37 +++++++- gcc/c-common.c | 36 ++++++++ gcc/c-common.h | 1 + gcc/c-decl.c | 9 ++ gcc/config/arm/arm.c | 5 +- gcc/config/arm/pe.h | 2 +- gcc/config/i386/cygming.h | 2 +- gcc/config/i386/i386-protos.h | 1 - gcc/config/i386/i386.c | 8 +- gcc/config/i386/winnt.c | 74 ---------------- gcc/config/mcore/mcore.c | 2 +- gcc/config/mcore/mcore.h | 2 +- gcc/config/sh/symbian-pre.h | 2 +- gcc/cp/ChangeLog | 6 ++ gcc/cp/decl.c | 9 +- gcc/cp/decl2.c | 23 +++-- gcc/defaults.h | 6 +- gcc/doc/extend.texi | 87 ++++++++++--------- gcc/doc/tm.texi | 16 ++-- gcc/testsuite/ChangeLog | 27 ++++++ gcc/testsuite/g++.dg/ext/visibility/assign1.C | 2 +- .../visibility/fvisibility-inlines-hidden.C | 2 +- .../g++.dg/ext/visibility/fvisibility.C | 2 +- .../g++.dg/ext/visibility/memfuncts.C | 2 +- gcc/testsuite/g++.dg/ext/visibility/new1.C | 5 +- gcc/testsuite/g++.dg/ext/visibility/pragma.C | 2 +- .../g++.dg/ext/visibility/staticmemfuncts.C | 2 +- gcc/testsuite/g++.dg/ext/visibility/virtual.C | 2 +- .../g++.dg/ext/visibility/visibility-1.C | 4 +- .../g++.dg/ext/visibility/visibility-2.C | 4 +- .../g++.dg/ext/visibility/visibility-3.C | 4 +- .../g++.dg/ext/visibility/visibility-4.C | 4 +- .../g++.dg/ext/visibility/visibility-5.C | 4 +- .../g++.dg/ext/visibility/visibility-6.C | 4 +- .../g++.dg/ext/visibility/visibility-7.C | 4 +- .../g++.dg/ext/visibility/visibility-8.C | 45 ++++++++++ gcc/testsuite/gcc.c-torture/compile/dll.x | 20 ----- gcc/testsuite/gcc.dg/dll-2.c | 4 +- gcc/testsuite/gcc.dg/visibility-10.c | 19 ++++ gcc/testsuite/lib/gcc-dg.exp | 6 +- gcc/testsuite/lib/scanasm.exp | 26 ++++++ gcc/tree.c | 77 +++++++++++++++- gcc/tree.h | 5 +- 43 files changed, 410 insertions(+), 194 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/visibility/visibility-8.C delete mode 100644 gcc/testsuite/gcc.c-torture/compile/dll.x create mode 100644 gcc/testsuite/gcc.dg/visibility-10.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 33753a63bb6..d7d4abd4ff7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,38 @@ +2004-08-05 Mark Mitchell + + * tree.c (handle_dll_attribute): Move here from i383/winnt.c. + Replace use of DECL_INLINE with DECL_DECLARED_INLINE_P. Set + DECL_VISIBLITY. Test TARGET_DLLIMPORT_DECL_ATTRIBUTES with #if. + * tree.h (handle_dll_attribute): Declare. Test + TARGET_DLLIMPORT_DECL_ATTRIBUTES with #if. + * c-common.h (c_determine_visibility): Declare. + * c-common.c (c_determine_visibility): New function. + * c-decl.c (finish_decl): Use it. + (finish_function): Likewise. + * defaults.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define it to + zero, by default. Use #if, not #ifdef, to test it. + * config/arm/arm.c (arm_attribute_table): Use + handle_dll_attribute. Test TARGET_DLLIMPORT_DECL_ATTRIBUTES with + #if. + * config/arm/pe.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define to 1. + * config/i386/cygming.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define + to 1. + * config/i386/i386-protos.h (ix86_handle_dll_attribute): Remove. + * config/i386/i386.c (ix86_attribute_table): Use + handle_dll_attribute for dllimport/dllexport. Test + TARGET_DLLIMPORT_DECL_ATTRIBUTES with #if. + * config/i386/winnt.c (ix86_handle_dll_attribute): Remove. + * config/mcore/mcore.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define + it to 1. + * config/mcore/mcore.c (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Test it + with #if. + * config/sh/symbian-pre.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define + it to 1. + * doc/extend.texi (dllexport): Clarify and correct documentation. + (dllimport): Likewise. + * doc/tm.texi (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Mention + handle_dll_attribute. + 2004-08-05 Zdenek Dvorak * tree-ssa-loop-manip.c: New file. @@ -184,7 +219,7 @@ * defaults.h (TARGET_DECLSPEC): New macro. * c-cppbuiltin.c (c_cpp_builtins): Handle TARGET_DECLSPEC. * config/arm/pe.h (SUBTARGET_CPP_SPEC): Remove __declspec support. - * config/arm/symbian. (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define. + * config/arm/symbian.h (TARGET_DLLIMPORT_DECL_ATTRIBUTES): Define. * config/i386/beof-elf.h (TARGET_OS_CPP_BUILTINS): Remove __declspec support. (TARGET_DECLSPEC): Define. diff --git a/gcc/c-common.c b/gcc/c-common.c index 5e5bbad319d..c3dc4ea6359 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -4600,6 +4600,42 @@ handle_visibility_attribute (tree *node, tree name, tree args, return NULL_TREE; } +/* Determine the ELF symbol visibility for DECL, which is either a + variable or a function. It is an error to use this function if a + definition of DECL is not available in this translation unit. + Returns true if the final visibility has been determined by this + function; false if the caller is free to make additional + modifications. */ + +bool +c_determine_visibility (tree decl) +{ + my_friendly_assert (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL, + 20040805); + + /* If the user explicitly specified the visibility with an + attribute, honor that. DECL_VISIBILITY will have been set during + the processing of the attribute. We check for an explicit + attribute, rather than just checking DECL_VISIBILITY_SPECIFIED, + to distinguish the use of an attribute from the use of a "#pragma + GCC visibility push(...)"; in the latter case we still want other + considerations to be able to overrule the #pragma. */ + if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))) + return true; + + /* Anything that is exported must have default visibility. */ + if (TARGET_DLLIMPORT_DECL_ATTRIBUTES + && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) + { + DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; + DECL_VISIBILITY_SPECIFIED (decl) = 1; + return true; + } + + return false; +} + /* Handle an "tls_model" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-common.h b/gcc/c-common.h index 6b9bd7559c6..e8d245c88b1 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -654,6 +654,7 @@ extern void constant_expression_warning (tree); extern tree convert_and_check (tree, tree); extern void overflow_warning (tree); extern void unsigned_conversion_warning (tree, tree); +extern bool c_determine_visibility (tree); #define c_sizeof(T) c_sizeof_or_alignof_type (T, SIZEOF_EXPR, 1) #define c_alignof(T) c_sizeof_or_alignof_type (T, ALIGNOF_EXPR, 1) diff --git a/gcc/c-decl.c b/gcc/c-decl.c index ff535524c4e..c03c1262f3b 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -3000,6 +3000,12 @@ finish_decl (tree decl, tree init, tree asmspec_tree) if (current_scope == file_scope) 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. */ @@ -6347,6 +6353,9 @@ finish_function (void) && !targetm.have_ctors_dtors) static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors); + /* Finalize the ELF visibility for the function. */ + c_determine_visibility (fndecl); + /* Genericize before inlining. Delay genericizing nested functions until their parent function is genericized. Since finalizing requires GENERIC, delay that as well. */ diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 8b1ae87f757..882824aa4ee 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -172,7 +172,7 @@ static bool arm_cxx_cdtor_returns_this (void); /* Initialize the GCC target structure. */ -#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES +#if TARGET_DLLIMPORT_DECL_ATTRIBUTES #undef TARGET_MERGE_DECL_ATTRIBUTES #define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes #endif @@ -2466,6 +2466,9 @@ const struct attribute_spec arm_attribute_table[] = { "dllimport", 0, 0, true, false, false, NULL }, { "dllexport", 0, 0, true, false, false, NULL }, { "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute }, +#elif TARGET_DLLIMPORT_DECL_ATTRIBUTES + { "dllimport", 0, 0, false, false, false, handle_dll_attribute }, + { "dllexport", 0, 0, false, false, false, handle_dll_attribute }, #endif { NULL, 0, 0, false, false, false, NULL } }; diff --git a/gcc/config/arm/pe.h b/gcc/config/arm/pe.h index 7db549e68f3..34e9457d7ce 100644 --- a/gcc/config/arm/pe.h +++ b/gcc/config/arm/pe.h @@ -40,7 +40,7 @@ /* Get tree.c to declare a target-specific specialization of merge_decl_attributes. */ -#define TARGET_DLLIMPORT_DECL_ATTRIBUTES +#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1 #undef SUBTARGET_CPP_SPEC #define SUBTARGET_CPP_SPEC "-D__pe__" diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h index 9c2e22aa706..bc690f74d4b 100644 --- a/gcc/config/i386/cygming.h +++ b/gcc/config/i386/cygming.h @@ -93,7 +93,7 @@ Boston, MA 02111-1307, USA. */ /* Get tree.c to declare a target-specific specialization of merge_decl_attributes. */ -#define TARGET_DLLIMPORT_DECL_ATTRIBUTES +#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1 /* This macro defines names of additional specifications to put in the specs that can be used in various specifications like CC1_SPEC. Its definition diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index aae3c7acb0f..4559abc2657 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -205,7 +205,6 @@ extern int ix86_return_pops_args (tree, tree, int); extern int ix86_data_alignment (tree, int); extern int ix86_local_alignment (tree, int); extern int ix86_constant_alignment (tree, int); -extern tree ix86_handle_dll_attribute (tree *, tree, tree, int, bool *); extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *); extern unsigned int i386_pe_section_type_flags (tree, const char *, int); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index f05ff5e5ede..22de6e36217 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -977,7 +977,7 @@ static void init_ext_80387_constants (void); /* Initialize the GCC target structure. */ #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE ix86_attribute_table -#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES +#if TARGET_DLLIMPORT_DECL_ATTRIBUTES # undef TARGET_MERGE_DECL_ATTRIBUTES # define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes #endif @@ -1609,9 +1609,9 @@ const struct attribute_spec ix86_attribute_table[] = /* Regparm attribute specifies how many integer arguments are to be passed in registers. */ { "regparm", 1, 1, false, true, true, ix86_handle_regparm_attribute }, -#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES - { "dllimport", 0, 0, false, false, false, ix86_handle_dll_attribute }, - { "dllexport", 0, 0, false, false, false, ix86_handle_dll_attribute }, +#if TARGET_DLLIMPORT_DECL_ATTRIBUTES + { "dllimport", 0, 0, false, false, false, handle_dll_attribute }, + { "dllexport", 0, 0, false, false, false, handle_dll_attribute }, { "shared", 0, 0, true, false, false, ix86_handle_shared_attribute }, #endif { "ms_struct", 0, 0, false, false, false, ix86_handle_struct_attribute }, diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index f0b1aec0821..08e7864371e 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -63,80 +63,6 @@ static void i386_pe_mark_dllimport (tree); #define DLL_EXPORT_PREFIX "#e." #endif -/* Handle a "dllimport" or "dllexport" attribute; - arguments as in struct attribute_spec.handler. */ -tree -ix86_handle_dll_attribute (tree * pnode, tree name, tree args, int flags, - bool *no_add_attrs) -{ - tree node = *pnode; - - /* These attributes may apply to structure and union types being created, - but otherwise should pass to the declaration involved. */ - if (!DECL_P (node)) - { - if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT - | (int) ATTR_FLAG_ARRAY_NEXT)) - { - *no_add_attrs = true; - return tree_cons (name, args, NULL_TREE); - } - if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) - { - warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } - - return NULL_TREE; - } - - /* Report error on dllimport ambiguities seen now before they cause - any damage. */ - else if (is_attribute_p ("dllimport", name)) - { - /* Like MS, treat definition of dllimported variables and - non-inlined functions on declaration as syntax errors. - We allow the attribute for function definitions if declared - inline, but just ignore it in i386_pe_dllimport_p. */ - if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node) - && !DECL_INLINE (node)) - { - error ("%Jfunction `%D' definition is marked dllimport.", node, node); - *no_add_attrs = true; - } - - else if (TREE_CODE (node) == VAR_DECL) - { - if (DECL_INITIAL (node)) - { - error ("%Jvariable `%D' definition is marked dllimport.", - node, node); - *no_add_attrs = true; - } - - /* `extern' needn't be specified with dllimport. - Specify `extern' now and hope for the best. Sigh. */ - DECL_EXTERNAL (node) = 1; - /* Also, implicitly give dllimport'd variables declared within - a function global scope, unless declared static. */ - if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) - TREE_PUBLIC (node) = 1; - } - } - - /* Report error if symbol is not accessible at global scope. */ - if (!TREE_PUBLIC (node) - && (TREE_CODE (node) == VAR_DECL - || TREE_CODE (node) == FUNCTION_DECL)) - { - error ("%Jexternal linkage required for symbol '%D' because of " - "'%s' attribute.", node, node, IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } - - return NULL_TREE; -} - /* Handle a "shared" attribute; arguments as in struct attribute_spec.handler. */ tree diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index bdf50ccfac2..69e05c89c17 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -156,7 +156,7 @@ static bool mcore_return_in_memory (tree, tree); #undef TARGET_ASM_EXTERNAL_LIBCALL #define TARGET_ASM_EXTERNAL_LIBCALL mcore_external_libcall -#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES +#if TARGET_DLLIMPORT_DECL_ATTRIBUTES #undef TARGET_MERGE_DECL_ATTRIBUTES #define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes #endif diff --git a/gcc/config/mcore/mcore.h b/gcc/config/mcore/mcore.h index dde4e093c50..4e299e66c21 100644 --- a/gcc/config/mcore/mcore.h +++ b/gcc/config/mcore/mcore.h @@ -33,7 +33,7 @@ /* Get tree.c to declare a target-specific specialization of merge_decl_attributes. */ -#define TARGET_DLLIMPORT_DECL_ATTRIBUTES +#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1 #define TARGET_CPU_CPP_BUILTINS() \ do \ diff --git a/gcc/config/sh/symbian-pre.h b/gcc/config/sh/symbian-pre.h index 44fb4a939e2..53e2d92a1df 100644 --- a/gcc/config/sh/symbian-pre.h +++ b/gcc/config/sh/symbian-pre.h @@ -30,7 +30,7 @@ #define SUBTARGET_CPP_SPEC "" /* Get tree.c to declare merge_dllimport_decl_attributes(). */ -#define TARGET_DLLIMPORT_DECL_ATTRIBUTES +#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1 /* The Symbian OS currently does not support exception handling. */ #define SUBTARGET_CC1PLUS_SPEC "-fno-exceptions" diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 09f671844ae..fda326ff209 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2004-08-05 Mark Mitchell + + * decl.c (start_preparsed_function): Move determine_visibility + call. + * decl2.c (determine_visibility): Incorporate dllexport testing. + 2004-08-05 Geoffrey Keating * g++spec.c (lang_specific_driver): An -Xlinker or -Wl, option diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 96534362226..1d5b78c12a0 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9629,9 +9629,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags) && lookup_attribute ("noinline", attrs)) warning ("%Jinline function '%D' given attribute noinline", decl1, decl1); - /* Determine the ELF visibility attribute for the function. */ - determine_visibility (decl1); - if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1)) /* This is a constructor, we must ensure that any default args introduced by this definition are propagated to the clones @@ -9769,6 +9766,12 @@ start_preparsed_function (tree decl1, tree attrs, int flags) fntype = TREE_TYPE (decl1); } + /* Determine the ELF visibility attribute for the function. We must + not do this before calling "pushdecl", as we must allow + "duplicate_decls" to merge any attributes appropriately. */ + if (!DECL_CLONED_FUNCTION_P (decl1)) + determine_visibility (decl1); + /* Reset these in case the call to pushdecl changed them. */ current_function_decl = decl1; cfun->decl = decl1; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 90f1cd176c5..ae4ccc871e9 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1611,7 +1611,8 @@ maybe_emit_vtables (tree ctype) return true; } -/* Determine the ELF symbol visibility for DECL. */ +/* Like c_determine_visibility, but with additional C++-specific + behavior. */ void determine_visibility (tree decl) @@ -1621,9 +1622,14 @@ determine_visibility (tree decl) /* Cloned constructors and destructors get the same visibility as the underlying function. That should be set up in maybe_clone_body. */ - if (DECL_CLONED_FUNCTION_P (decl)) + my_friendly_assert (!DECL_CLONED_FUNCTION_P (decl), 20040804); + + /* Give the common code a chance to make a determination. */ + if (c_determine_visibility (decl)) return; + /* 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)) class_type = DECL_CONTEXT (decl); else if (TREE_CODE (decl) == VAR_DECL @@ -1643,11 +1649,16 @@ determine_visibility (tree decl) /* By default, static data members and function members receive the visibility of their containing class. */ - if (class_type - && (TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL) - && !lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))) + if (class_type) { + if (TARGET_DLLIMPORT_DECL_ATTRIBUTES + && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class_type))) + { + DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; + DECL_VISIBILITY_SPECIFIED (decl) = 1; + return; + } + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) && visibility_options.inlines_hidden) diff --git a/gcc/defaults.h b/gcc/defaults.h index 3cd779ca29d..a1e5300a006 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -415,8 +415,12 @@ do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \ #define PIC_OFFSET_TABLE_REGNUM INVALID_REGNUM #endif +#ifndef TARGET_DLLIMPORT_DECL_ATTRIBUTES +#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 0 +#endif + #ifndef TARGET_DECLSPEC -#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES +#if TARGET_DLLIMPORT_DECL_ATTRIBUTES /* If the target supports the "dllimport" attribute, users are probably used to the "__declspec" syntax. */ #define TARGET_DECLSPEC 1 diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 1b4b76b569f..f563893317e 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1610,40 +1610,49 @@ types (@pxref{Variable Attributes}, @pxref{Type Attributes}.) @item dllexport @cindex @code{__declspec(dllexport)} -On Microsoft Windows targets and Symbian targets the @code{dllexport} -attribute causes the compiler to provide a global pointer to a pointer -in a dll, so that it can be referenced with the @code{dllimport} -attribute. The pointer name is formed by combining @code{_imp__} and -the function or variable name. +On Microsoft Windows targets and Symbian OS targets the +@code{dllexport} attribute causes the compiler to provide a global +pointer to a pointer in a DLL, so that it can be referenced with the +@code{dllimport} attribute. On Microsoft Windows targets, the pointer +name is formed by combining @code{_imp__} and the function or variable +name. + +You can use @code{__declspec(dllexport)} as a synonym for +@code{__attribute__ ((dllexport))} for compatibility with other +compilers. + +On systems that support the @code{visibility} attribute, this +attribute also implies ``default'' visibility, unless a +@code{visibility} attribute is explicitly specified. You should avoid +the use of @code{dllexport} with ``hidden'' or ``internal'' +visibility; in the future GCC may issue an error for those cases. -Currently, the @code{dllexport}attribute is ignored for inlined -functions, but export can be forced by using the -@option{-fkeep-inline-functions} flag. The attribute is also ignored for -undefined symbols. +Currently, the @code{dllexport} attribute is ignored for inlined +functions, unless the @option{-fkeep-inline-functions} flag has been +used. The attribute is also ignored for undefined symbols. When applied to C++ classes. the attribute marks defined non-inlined member functions and static data members as exports. Static consts initialized in-class are not marked unless they are also defined out-of-class. -On cygwin, mingw, arm-pe and sh-symbianelf targets, -@code{__declspec(dllexport)} is recognized as a synonym for -@code{__attribute__ ((dllexport))} for compatibility with other -Microsoft Windows and Symbian compilers. - For Microsoft Windows targets there are alternative methods for -including the symbol in the dll's export table such as using a +including the symbol in the DLL's export table such as using a @file{.def} file with an @code{EXPORTS} section or, with GNU ld, using the @option{--export-all} linker flag. @item dllimport @cindex @code{__declspec(dllimport)} -On Microsoft Windows and Symbian targets, the @code{dllimport} +On Microsoft Windows and Symbian OS targets, the @code{dllimport} attribute causes the compiler to reference a function or variable via -a global pointer to a pointer that is set up by the Microsoft Windows -dll library. The pointer name is formed by combining @code{_imp__} and -the function or variable name. The attribute implies @code{extern} -storage. +a global pointer to a pointer that is set up by the DLL exporting the +symbol. The attribute implies @code{extern} storage. On Microsoft +Windows targets, the pointer name is formed by combining @code{_imp__} +and the function or variable name. + +You can use @code{__declspec(dllimport)} as a synonym for +@code{__attribute__ ((dllimport))} for compatibility with other +compilers. Currently, the attribute is ignored for inlined functions. If the attribute is applied to a symbol @emph{definition}, an error is reported. @@ -1657,31 +1666,27 @@ member functions and static data members as imports. However, the attribute is ignored for virtual methods to allow creation of vtables using thunks. -For Symbian targets the @code{dllimport} attribute also has another -affect - it can cause the vtable and run-time type information for a -class to be exported. This happens when the class has a dllimport'ed -constructor or a non-inline, non-pure virtual function and, for either -of those two conditions, the class also has a inline constructor or -destructor and has a key function that is defined in the current -translation unit. - -On cygwin, mingw, arm-pe sh-symbianelf targets, -@code{__declspec(dllimport)} is recognized as a synonym for -@code{__attribute__ ((dllimport))} for compatibility with other -Microsoft Windows and Symbian compilers. +On the SH Symbian OS target the @code{dllimport} attribute also has +another affect - it can cause the vtable and run-time type information +for a class to be exported. This happens when the class has a +dllimport'ed constructor or a non-inline, non-pure virtual function +and, for either of those two conditions, the class also has a inline +constructor or destructor and has a key function that is defined in +the current translation unit. For Microsoft Windows based targets the use of the @code{dllimport} attribute on functions is not necessary, but provides a small -performance benefit by eliminating a thunk in the dll. The use of the +performance benefit by eliminating a thunk in the DLL. The use of the @code{dllimport} attribute on imported variables was required on older -versions of GNU ld, but can now be avoided by passing the -@option{--enable-auto-import} switch to ld. As with functions, using -the attribute for a variable eliminates a thunk in the dll. - -One drawback to using this attribute is that a pointer to a function or -variable marked as dllimport cannot be used as a constant address. The -attribute can be disabled for functions by setting the -@option{-mnop-fun-dllimport} flag. +versions of the GNU linker, but can now be avoided by passing the +@option{--enable-auto-import} switch to the GNU linker. As with +functions, using the attribute for a variable eliminates a thunk in +the DLL. + +One drawback to using this attribute is that a pointer to a function +or variable marked as @code{dllimport} cannot be used as a constant +address. On Microsoft Windows targets, the attribute can be disabled +for functions by setting the @option{-mnop-fun-dllimport} flag. @item eightbit_data @cindex eight bit data on the H8/300, H8/300H, and H8S diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 2a0147cfd4d..a250742098c 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -8338,12 +8338,16 @@ attribute is nullified by a subsequent definition. This function may call @code{merge_attributes} to handle machine-independent merging. @findex TARGET_DLLIMPORT_DECL_ATTRIBUTES -If the only target-specific handling you require is @samp{dllimport} for -Microsoft Windows targets, you should define the macro -@code{TARGET_DLLIMPORT_DECL_ATTRIBUTES}. This links in a function -called @code{merge_dllimport_decl_attributes} which can then be defined -as the expansion of @code{TARGET_MERGE_DECL_ATTRIBUTES}. This is done -in @file{i386/cygwin.h} and @file{i386/i386.c}, for example. +If the only target-specific handling you require is @samp{dllimport} +for Microsoft Windows targets, you should define the macro +@code{TARGET_DLLIMPORT_DECL_ATTRIBUTES} to @code{1}. The compiler +will then define a function called +@code{merge_dllimport_decl_attributes} which can then be defined as +the expansion of @code{TARGET_MERGE_DECL_ATTRIBUTES}. You can also +add @code{handle_dll_attribute} in the attribute table for your port +to perform initial processing of the @samp{dllimport} and +@samp{dllexport} attributes. This is done in @file{i386/cygwin.h} and +@file{i386/i386.c}, for example. @end deftypefn @defmac TARGET_DECLSPEC diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dd221c85ed0..a04b598e47b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,30 @@ +2004-08-05 Mark Mitchell + + * g++.dg/ext/visibility/assign1.C: Use scan-hidden and + dg-require-visiblity. + * g++.dg/ext/visibility/fvisibility-inlines-hidden.C: Likewise. + * g++.dg/ext/visibility/fvisibility.C: Likewise. + * g++.dg/ext/visibility/memfuncts.C: Likewise. + * g++.dg/ext/visibility/new1.C: Likewise. + * g++.dg/ext/visibility/pragma.C: Likewise. + * g++.dg/ext/visibility/staticmemfuncts.C: Likewise. + * g++.dg/ext/visibility/virtual.C: Likewise. + * g++/dg/ext/visibility/visibility-1.C: Likewise. + * g++/dg/ext/visibility/visibility-2.C: Likewise. + * g++/dg/ext/visibility/visibility-3.C: Likewise. + * g++/dg/ext/visibility/visibility-4.C: Likewise. + * g++/dg/ext/visibility/visibility-5.C: Likewise. + * g++/dg/ext/visibility/visibility-6.C: Likewise. + * g++/dg/ext/visibility/visibility-7.C: Likewise. + * g++/dg/ext/visibility/visibility-8.C: New test. + * gcc.c-torture/compile/dll.x: Remove. + * gcc.dg/dll-2.c: Use dg-require-dll + * gcc.dg/visibility-10.c: New test. + * lib/gcc-dg.exp (dg-require-dll): Add Symbian to list of targets + supporting DLLs. + * testsuite/lib/scanasm.exp (scan_hidden): New function. + (scan_not_hidden): Likewise. + 2004-08-05 David Edelsohn * gcc.dg/sh4a-fprun.c: Fix dg-do typo. diff --git a/gcc/testsuite/g++.dg/ext/visibility/assign1.C b/gcc/testsuite/g++.dg/ext/visibility/assign1.C index 6d7392fd04b..cbd909ee191 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/assign1.C +++ b/gcc/testsuite/g++.dg/ext/visibility/assign1.C @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-visibility "" } */ -/* { dg-final { scan-assembler "\\.hidden.*_ZN1DaSERKS_" } } */ +/* { dg-final { scan-hidden "_ZN1DaSERKS_" } } */ struct B { B& operator=(const B&); diff --git a/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden.C b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden.C index 4b610229b46..2ee8f0767ba 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden.C +++ b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden.C @@ -2,7 +2,7 @@ /* { dg-do compile } */ /* { dg-require-visibility "" } */ /* { dg-options "-fvisibility-inlines-hidden" } */ -/* { dg-final { scan-assembler "\\.hidden.*Foo.methodEv" } } */ +/* { dg-final { scan-hidden "_ZN3Foo6methodEv" } } */ class Foo { diff --git a/gcc/testsuite/g++.dg/ext/visibility/fvisibility.C b/gcc/testsuite/g++.dg/ext/visibility/fvisibility.C index fd2c7e2fc3e..4358d25a960 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/fvisibility.C +++ b/gcc/testsuite/g++.dg/ext/visibility/fvisibility.C @@ -2,7 +2,7 @@ /* { dg-do compile } */ /* { dg-require-visibility "" } */ /* { dg-options "-fvisibility=hidden" } */ -/* { dg-final { scan-assembler "\\.hidden.*Foo.methodEv" } } */ +/* { dg-final { scan-hidden "_ZN3Foo6methodEv" } } */ class Foo { diff --git a/gcc/testsuite/g++.dg/ext/visibility/memfuncts.C b/gcc/testsuite/g++.dg/ext/visibility/memfuncts.C index 19a5c9d506b..45eb641b29e 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/memfuncts.C +++ b/gcc/testsuite/g++.dg/ext/visibility/memfuncts.C @@ -1,7 +1,7 @@ /* Test that setting visibility for class member functions works. */ /* { dg-do compile } */ /* { dg-require-visibility "" } */ -/* { dg-final { scan-assembler "\\.hidden.*Foo.methodEv" } } */ +/* { dg-final { scan-hidden "_ZN3Foo6methodEv" } } */ class __attribute__ ((visibility ("hidden"))) Foo { diff --git a/gcc/testsuite/g++.dg/ext/visibility/new1.C b/gcc/testsuite/g++.dg/ext/visibility/new1.C index 0f0be5148da..ec201cbc20d 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/new1.C +++ b/gcc/testsuite/g++.dg/ext/visibility/new1.C @@ -1,7 +1,6 @@ -// { dg-require-visibility } -// { dg-do compile } +// { dg-require-visibility "" } // { dg-options "-fvisibility=hidden" } -// { dg-final { scan-assembler-not "\\.hidden\[^\n\]*_Znwj" } } +// { dg-final { scan-not-hidden "_Znwj" } } void f() { new int; diff --git a/gcc/testsuite/g++.dg/ext/visibility/pragma.C b/gcc/testsuite/g++.dg/ext/visibility/pragma.C index 860b2284e15..98384c9c42a 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/pragma.C +++ b/gcc/testsuite/g++.dg/ext/visibility/pragma.C @@ -1,7 +1,7 @@ /* Test that #pragma GCC visibility affects class members. */ /* { dg-do compile } */ /* { dg-require-visibility "" } */ -/* { dg-final { scan-assembler "\\.hidden.*Foo.methodEv" } } */ +/* { dg-final { scan-hidden "_ZN3Foo6methodEv" } } */ #pragma GCC visibility push(hidden) class Foo diff --git a/gcc/testsuite/g++.dg/ext/visibility/staticmemfuncts.C b/gcc/testsuite/g++.dg/ext/visibility/staticmemfuncts.C index b49cbd5bab9..e745caa5a74 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/staticmemfuncts.C +++ b/gcc/testsuite/g++.dg/ext/visibility/staticmemfuncts.C @@ -1,7 +1,7 @@ /* Test that setting visibility for static class member functions works. */ /* { dg-do compile } */ /* { dg-require-visibility "" } */ -/* { dg-final { scan-assembler "\\.hidden.*Foo.methodEv" } } */ +/* { dg-final { scan-hidden "_ZN3Foo6methodEv" } } */ class __attribute__ ((visibility ("hidden"))) Foo { diff --git a/gcc/testsuite/g++.dg/ext/visibility/virtual.C b/gcc/testsuite/g++.dg/ext/visibility/virtual.C index 604c552bcb6..746c489d0b1 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/virtual.C +++ b/gcc/testsuite/g++.dg/ext/visibility/virtual.C @@ -1,7 +1,7 @@ /* Test that setting visibility for class affects virtual table. */ /* { dg-do compile } */ /* { dg-require-visibility "" } */ -/* { dg-final { scan-assembler "\\.hidden.*ZTV3Foo" } } */ +/* { dg-final { scan-hidden "ZTV3Foo" } } */ class __attribute__ ((visibility ("hidden"))) Foo { diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-1.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-1.C index d579eb27206..8ea270bf8c0 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/visibility-1.C +++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-1.C @@ -1,6 +1,6 @@ /* Test visibility attribute on function definition. */ -/* { dg-do compile { target *86-*-linux* } } */ -/* { dg-final { scan-assembler "\\.hidden.*_Z3foov" } } */ +/* { dg-require-visibility "" } +/* { dg-final { scan-hidden "_Z3foov" } } */ void __attribute__((visibility ("hidden"))) diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-2.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-2.C index 89e853c4dc5..26272abb1f9 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/visibility-2.C +++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-2.C @@ -1,6 +1,6 @@ /* Test that visibility attribute on declaration extends to definition. */ -/* { dg-do compile { target *86-*-linux* } } */ -/* { dg-final { scan-assembler "\\.hidden.*_Z3foov" } } */ +/* { dg-require-visibility "" } +/* { dg-final { scan-hidden "_Z3foov" } } */ void __attribute__((visibility ("hidden"))) foo(); diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-3.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-3.C index d0cc8912efb..e4f499fccb0 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/visibility-3.C +++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-3.C @@ -1,6 +1,6 @@ /* Test visibility attribute on forward declaration of global variable */ -/* { dg-do compile { target *86-*-linux* } } */ -/* { dg-final { scan-assembler "\\.hidden.*xyzzy" } } */ +/* { dg-require-visibility "" } +/* { dg-final { scan-hidden "xyzzy" } } */ int __attribute__((visibility ("hidden"))) diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-4.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-4.C index d217bc9ec5d..f6765958709 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/visibility-4.C +++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-4.C @@ -1,6 +1,6 @@ /* Test visibility attribute on forward declaration of global variable */ -/* { dg-do compile { target *86-*-linux* } } */ -/* { dg-final { scan-assembler "\\.hidden.*xyzzy" } } */ +/* { dg-require-visibility "" } +/* { dg-final { scan-hidden "xyzzy" } } */ extern int __attribute__ ((visibility ("hidden"))) xyzzy; diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-5.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-5.C index 9cdc8021e47..592529e665d 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/visibility-5.C +++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-5.C @@ -1,7 +1,7 @@ /* Test visibility attribute on definition of a function that has already had a forward declaration. */ -/* { dg-do compile { target *86-*-linux* } } */ -/* { dg-final { scan-assembler "\\.hidden.*_Z3foov" } } */ +/* { dg-require-visibility "" } +/* { dg-final { scan-hidden "_Z3foov" } } */ void foo(); diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-6.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-6.C index 6e8f0ce1135..0fecf6b74e9 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/visibility-6.C +++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-6.C @@ -1,7 +1,7 @@ /* Test visibility attribute on definition of global variable that has already had a forward declaration. */ -/* { dg-do compile { target *86-*-linux* } } */ -/* { dg-final { scan-assembler "\\.hidden.*xyzzy" } } */ +/* { dg-require-visibility "" } +/* { dg-final { scan-hidden "xyzzy" } } */ extern int xyzzy; diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C index 40acb72463f..dbd7010d028 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C +++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C @@ -1,6 +1,6 @@ /* Test warning from conflicting visibility specifications. */ -/* { dg-do compile { target *86-*-linux* } } */ -/* { dg-final { scan-assembler "\\.hidden.*xyzzy" } } */ +/* { dg-require-visibility "" } */ +/* { dg-final { scan-hidden "xyzzy" } } */ extern int __attribute__((visibility ("hidden"))) 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 00000000000..f6487263975 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-8.C @@ -0,0 +1,45 @@ +// 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 "_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 { + void i(); + __declspec(dllexport) void j(); + __declspec(dllexport) static int 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/gcc.c-torture/compile/dll.x b/gcc/testsuite/gcc.c-torture/compile/dll.x deleted file mode 100644 index 63a1e180e2c..00000000000 --- a/gcc/testsuite/gcc.c-torture/compile/dll.x +++ /dev/null @@ -1,20 +0,0 @@ -# This test examines the attribute support for DLLs. -# Only COFF/PE formats support DLLs, (plus, as a special case -# the mcore-elf toolchain), so the code here tries to determine -# the file format and decide whether the test should be marked -# as unsupported. - -set torture_eval_before_compile { - - if ![istarget "mcore-*-elf"] { - - set objformat [gcc_target_object_format] - - if { $objformat != "pe" } { - unsupported "dll.c" - return 1 - } - } -} - -return 0 diff --git a/gcc/testsuite/gcc.dg/dll-2.c b/gcc/testsuite/gcc.dg/dll-2.c index 45456ce8330..00c683a728c 100644 --- a/gcc/testsuite/gcc.dg/dll-2.c +++ b/gcc/testsuite/gcc.dg/dll-2.c @@ -8,9 +8,7 @@ In C, it's ok to redeclare a variable so this works for variables and functions. In C++, it only works for functions. */ -/* { dg-do compile { target arm*-*-pe* } } */ -/* { dg-do compile { target i?86-pc-cygwin } } */ -/* { dg-do compile { target i?86-pc-mingw* } } */ +/* { dg-require-dll } */ __declspec (dllimport) int foo1 (); __declspec (dllexport) int foo1 (); diff --git a/gcc/testsuite/gcc.dg/visibility-10.c b/gcc/testsuite/gcc.dg/visibility-10.c new file mode 100644 index 00000000000..d86ce1b1a30 --- /dev/null +++ b/gcc/testsuite/gcc.dg/visibility-10.c @@ -0,0 +1,19 @@ +/* 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 "g" } } */ +/* { dg-final { scan-not-hidden "h" } } */ +/* { dg-final { scan-not-hidden "k" } } */ +/* { dg-final { scan-not-hidden "l" } } */ + +__declspec(dllexport) void g() {} + +__declspec(dllexport) void h(); +void h() {} + +__declspec(dllexport) int k; + +__declspec(dllexport) extern int l; +int l; diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index 7080df8267b..3f2d9aa701e 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -338,8 +338,10 @@ proc dg-require-profiling { args } { proc dg-require-dll { args } { global target_triplet - # As a special case, the mcore-*-elf supports dllimport/dllexport. - if { [string match "mcore-*-elf" $target_triplet] } { + # As a special case, the mcore-*-elf supports these attributes. + # All Symbian OS targets also support these attributes. + if { [string match "mcore-*-elf" $target_triplet] + || [string match "*-*-symbianelf" $target_triplet]} { return } # PE/COFF targets support dllimport/dllexport. diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index 79d93cbf089..9116afc1c41 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -79,6 +79,32 @@ proc scan-assembler-not { args } { dg-scan "scan-assembler-not" 0 $testcase $output_file $args } +# Check that a symbol is defined as a hidden symbol in the .s file +# produced by the compiler. + +proc scan-hidden { args } { + upvar 2 name testcase + set output_file "[file rootname [file tail $testcase]].s" + + set symbol [lindex $args 0] + set args [lreplace $args 0 0 "hidden\[ \t_\]*$symbol"] + + dg-scan "scan-hidden" 1 $testcase $output_file $args +} + +# Check that a symbol is not defined as a hidden symbol in the .s file +# produced by the compiler. + +proc scan-not-hidden { args } { + upvar 2 name testcase + set output_file "[file rootname [file tail $testcase]].s" + + set symbol [lindex $args 0] + set args [lreplace $args 0 0 "hidden\[ \t_\]*$symbol"] + + dg-scan "scan-not-hidden" 0 $testcase $output_file $args +} + # Look for a pattern in OUTPUT_FILE. See dg-scan for details. proc scan-file { output_file args } { diff --git a/gcc/tree.c b/gcc/tree.c index ef73afdbe6c..c8153b8f535 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -2887,7 +2887,7 @@ merge_decl_attributes (tree olddecl, tree newdecl) DECL_ATTRIBUTES (newdecl)); } -#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES +#if TARGET_DLLIMPORT_DECL_ATTRIBUTES /* Specialization of merge_decl_attributes for various Windows targets. @@ -2940,6 +2940,81 @@ merge_dllimport_decl_attributes (tree old, tree new) return a; } +/* Handle a "dllimport" or "dllexport" attribute; arguments as in + struct attribute_spec.handler. */ + +tree +handle_dll_attribute (tree * pnode, tree name, tree args, int flags, + bool *no_add_attrs) +{ + tree node = *pnode; + + /* These attributes may apply to structure and union types being created, + but otherwise should pass to the declaration involved. */ + if (!DECL_P (node)) + { + if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT + | (int) ATTR_FLAG_ARRAY_NEXT)) + { + *no_add_attrs = true; + return tree_cons (name, args, NULL_TREE); + } + if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; + } + + /* Report error on dllimport ambiguities seen now before they cause + any damage. */ + if (is_attribute_p ("dllimport", name)) + { + /* Like MS, treat definition of dllimported variables and + non-inlined functions on declaration as syntax errors. We + allow the attribute for function definitions if declared + inline. */ + if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node) + && !DECL_DECLARED_INLINE_P (node)) + { + error ("%Jfunction `%D' definition is marked dllimport.", node, node); + *no_add_attrs = true; + } + + else if (TREE_CODE (node) == VAR_DECL) + { + if (DECL_INITIAL (node)) + { + error ("%Jvariable `%D' definition is marked dllimport.", + node, node); + *no_add_attrs = true; + } + + /* `extern' needn't be specified with dllimport. + Specify `extern' now and hope for the best. Sigh. */ + DECL_EXTERNAL (node) = 1; + /* Also, implicitly give dllimport'd variables declared within + a function global scope, unless declared static. */ + if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) + TREE_PUBLIC (node) = 1; + } + } + + /* Report error if symbol is not accessible at global scope. */ + if (!TREE_PUBLIC (node) + && (TREE_CODE (node) == VAR_DECL + || TREE_CODE (node) == FUNCTION_DECL)) + { + error ("%Jexternal linkage required for symbol '%D' because of " + "'%s' attribute.", node, node, IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + #endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES */ /* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask diff --git a/gcc/tree.h b/gcc/tree.h index 49fcd0debb2..8bd1219240b 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2894,10 +2894,13 @@ extern tree lookup_attribute (const char *, tree); extern tree merge_attributes (tree, tree); -#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES +#if TARGET_DLLIMPORT_DECL_ATTRIBUTES /* Given two Windows decl attributes lists, possibly including dllimport, return a list of their union . */ extern tree merge_dllimport_decl_attributes (tree, tree); + +/* Handle a "dllimport" or "dllexport" attribute. */ +extern tree handle_dll_attribute (tree *, tree, tree, int, bool *); #endif /* Check whether CAND is suitable to be returned from get_qualified_type -- 2.30.2