summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2004-08-06 02:03:29 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2004-08-06 02:03:29 +0000
commit3aa0c315acad780f429033997add7a41275eec8c (patch)
tree69d71a8f79d4ab453d9ed298e91ba4813f6f9760
parent4cea1d717bbe18fdc740c2f3bcc738ef03966516 (diff)
downloadgcc-3aa0c315acad780f429033997add7a41275eec8c.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@85621 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog37
-rw-r--r--gcc/c-common.c36
-rw-r--r--gcc/c-common.h1
-rw-r--r--gcc/c-decl.c9
-rw-r--r--gcc/config/arm/arm.c5
-rw-r--r--gcc/config/arm/pe.h2
-rw-r--r--gcc/config/i386/cygming.h2
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c8
-rw-r--r--gcc/config/i386/winnt.c74
-rw-r--r--gcc/config/mcore/mcore.c2
-rw-r--r--gcc/config/mcore/mcore.h2
-rw-r--r--gcc/config/sh/symbian-pre.h2
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl.c9
-rw-r--r--gcc/cp/decl2.c23
-rw-r--r--gcc/defaults.h6
-rw-r--r--gcc/doc/extend.texi87
-rw-r--r--gcc/doc/tm.texi16
-rw-r--r--gcc/testsuite/ChangeLog27
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/assign1.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/fvisibility.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/memfuncts.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/new1.C5
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/pragma.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/staticmemfuncts.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/virtual.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-1.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-2.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-3.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-4.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-5.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-6.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-7.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-8.C45
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/dll.x20
-rw-r--r--gcc/testsuite/gcc.dg/dll-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/visibility-10.c19
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp6
-rw-r--r--gcc/testsuite/lib/scanasm.exp26
-rw-r--r--gcc/tree.c77
-rw-r--r--gcc/tree.h5
43 files changed, 410 insertions, 194 deletions
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 <mark@codesourcery.com>
+
+ * 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 <rakdver@atrey.karlin.mff.cuni.cz>
* 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 <mark@codesourcery.com>
+
+ * decl.c (start_preparsed_function): Move determine_visibility
+ call.
+ * decl2.c (determine_visibility): Incorporate dllexport testing.
+
2004-08-05 Geoffrey Keating <geoffk@apple.com>
* 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 <mark@codesourcery.com>
+
+ * 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 <edelsohn@gnu.org>
* 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