aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-09-18 17:25:18 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-09-18 17:25:18 -0400
commitecc607fc08d8d9345406ff824063fcaf500f9021 (patch)
treeec33a1350ff4e953d12da2838d2890d5f32c3181
parent5f5babf18b5bede638a67406cbd3ebf480cd4b8f (diff)
downloadgcc-ecc607fc08d8d9345406ff824063fcaf500f9021.zip
gcc-ecc607fc08d8d9345406ff824063fcaf500f9021.tar.gz
gcc-ecc607fc08d8d9345406ff824063fcaf500f9021.tar.bz2
decl2.c (determine_visibility): Make anonymous types internal.
* decl2.c (determine_visibility): Make anonymous types internal. (mark_used): Complain about types without linkage used in decls with internal linkage. (vague_linkage_fn_p): Split out from... * decl.c (maybe_commonize_var): ...here. (grokdeclarator): Adjust linkage when a typedef gives linkage name. * tree.c (no_linkage_check): Check the enclosing class and template arguments. * cp-tree.h (TYPE_NAMESPACE_SCOPE_P): New. From-SVN: r151868
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c12
-rw-r--r--gcc/cp/decl2.c28
-rw-r--r--gcc/cp/tree.c41
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nolinkage1.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nolinkage1.h8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nolinkage1a.cc15
9 files changed, 127 insertions, 15 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 350aa3e..6c2ce9c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,16 @@
2009-09-18 Jason Merrill <jason@redhat.com>
+ * decl2.c (determine_visibility): Make anonymous types internal.
+ (mark_used): Complain about types without linkage used in
+ decls with internal linkage.
+ (vague_linkage_fn_p): Split out from...
+ * decl.c (maybe_commonize_var): ...here.
+ (grokdeclarator): Adjust linkage when a typedef gives linkage name.
+ * tree.c (no_linkage_check): Check the enclosing class and template
+ arguments.
+
+ * cp-tree.h (TYPE_NAMESPACE_SCOPE_P): New.
+
* pt.c (get_pattern_parm): New.
(listify): Split out from...
(listify_autos): ...here.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7801f98..816b4ca 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2129,6 +2129,9 @@ struct GTY(()) lang_decl {
(!DECL_TEMPLATE_PARM_P (NODE) \
&& TREE_CODE (CP_DECL_CONTEXT (NODE)) == NAMESPACE_DECL)
+#define TYPE_NAMESPACE_SCOPE_P(NODE) \
+ (TREE_CODE (CP_TYPE_CONTEXT (NODE)) == NAMESPACE_DECL)
+
/* 1 iff NODE is a class member. */
#define DECL_CLASS_SCOPE_P(NODE) \
(DECL_CONTEXT (NODE) && TYPE_P (DECL_CONTEXT (NODE)))
@@ -4457,6 +4460,7 @@ extern bool check_java_method (tree);
extern tree build_memfn_type (tree, tree, cp_cv_quals);
extern void maybe_retrofit_in_chrg (tree);
extern void maybe_make_one_only (tree);
+extern bool vague_linkage_fn_p (tree);
extern void grokclassfn (tree, tree,
enum overload_flags);
extern tree grok_array_decl (tree, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0cfcb4f..614dbb0 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4615,13 +4615,7 @@ maybe_commonize_var (tree decl)
/* Don't mess with __FUNCTION__. */
&& ! DECL_ARTIFICIAL (decl)
&& DECL_FUNCTION_SCOPE_P (decl)
- /* Unfortunately, import_export_decl has not always been called
- before the function is processed, so we cannot simply check
- DECL_COMDAT. */
- && (DECL_COMDAT (DECL_CONTEXT (decl))
- || ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
- || DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
- && TREE_PUBLIC (DECL_CONTEXT (decl)))))
+ && vague_linkage_fn_p (DECL_CONTEXT (decl)))
{
if (flag_weak)
{
@@ -8845,6 +8839,10 @@ grokdeclarator (const cp_declarator *declarator,
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
= TYPE_IDENTIFIER (type);
+ /* Adjust linkage now that we aren't anonymous anymore. */
+ set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
+ determine_visibility (TYPE_MAIN_DECL (type));
+
/* FIXME remangle member functions; member functions of a
type with external linkage have external linkage. */
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index eb48c55..3e8c0d7 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1605,6 +1605,22 @@ maybe_make_one_only (tree decl)
}
}
+/* Returns true iff DECL, a FUNCTION_DECL, has vague linkage. This
+ predicate will give the right answer during parsing of the function,
+ which other tests may not. */
+
+bool
+vague_linkage_fn_p (tree fn)
+{
+ /* Unfortunately, import_export_decl has not always been called
+ before the function is processed, so we cannot simply check
+ DECL_COMDAT. */
+ return (DECL_COMDAT (fn)
+ || ((DECL_DECLARED_INLINE_P (fn)
+ || DECL_TEMPLATE_INSTANTIATION (fn))
+ && TREE_PUBLIC (fn)));
+}
+
/* Determine whether or not we want to specifically import or export CTYPE,
using various heuristics. */
@@ -2075,6 +2091,16 @@ determine_visibility (tree decl)
|| ! DECL_VISIBILITY_SPECIFIED (decl))
constrain_visibility (decl, tvis);
}
+ else if (no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/true))
+ /* DR 757: A type without linkage shall not be used as the type of a
+ variable or function with linkage, unless
+ o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
+ o the variable or function is not used (3.2 [basic.def.odr]) or is
+ defined in the same translation unit.
+
+ Since non-extern "C" decls need to be defined in the same
+ translation unit, we can make the type internal. */
+ constrain_visibility (decl, VISIBILITY_ANON);
/* If visibility changed and DECL already has DECL_RTL, ensure
symbol flags are updated. */
@@ -3966,7 +3992,7 @@ mark_used (tree decl)
o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
o the variable or function is not used (3.2 [basic.def.odr]) or is
defined in the same translation unit. */
- if (TREE_PUBLIC (decl)
+ if (decl_linkage (decl) != lk_none
&& !DECL_EXTERN_C_P (decl)
&& !DECL_ARTIFICIAL (decl)
&& !decl_defined_p (decl)
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 808a18a..51752a3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1513,7 +1513,7 @@ verify_stmt_tree (tree t)
/* Check if the type T depends on a type with no linkage and if so, return
it. If RELAXED_P then do not consider a class type declared within
- a TREE_PUBLIC function to have no linkage. */
+ a vague-linkage function to have no linkage. */
tree
no_linkage_check (tree t, bool relaxed_p)
@@ -1527,8 +1527,6 @@ no_linkage_check (tree t, bool relaxed_p)
switch (TREE_CODE (t))
{
- tree fn;
-
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
goto ptrmem;
@@ -1536,13 +1534,42 @@ no_linkage_check (tree t, bool relaxed_p)
case UNION_TYPE:
if (!CLASS_TYPE_P (t))
return NULL_TREE;
+
+ /* Check template type-arguments. I think that types with no linkage
+ can't occur in non-type arguments, though that might change with
+ constexpr. */
+ r = CLASSTYPE_TEMPLATE_INFO (t);
+ if (r)
+ {
+ tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (r));
+ int i;
+
+ for (i = TREE_VEC_LENGTH (args); i-- > 0; )
+ {
+ tree elt = TREE_VEC_ELT (args, i);
+ if (TYPE_P (elt)
+ && (r = no_linkage_check (elt, relaxed_p), r))
+ return r;
+ }
+ }
/* Fall through. */
case ENUMERAL_TYPE:
- if (TYPE_ANONYMOUS_P (t))
- return t;
- fn = decl_function_context (TYPE_MAIN_DECL (t));
- if (fn && (!relaxed_p || !TREE_PUBLIC (fn)))
+ /* Only treat anonymous types as having no linkage if they're at
+ namespace scope. This doesn't have a core issue number yet. */
+ if (TYPE_ANONYMOUS_P (t) && TYPE_NAMESPACE_SCOPE_P (t))
return t;
+
+ r = CP_TYPE_CONTEXT (t);
+ if (TYPE_P (r))
+ return no_linkage_check (TYPE_CONTEXT (t), relaxed_p);
+ else if (TREE_CODE (r) == FUNCTION_DECL)
+ {
+ if (!relaxed_p || !TREE_PUBLIC (r) || !vague_linkage_fn_p (r))
+ return t;
+ else
+ return no_linkage_check (CP_DECL_CONTEXT (r), relaxed_p);
+ }
+
return NULL_TREE;
case ARRAY_TYPE:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 43f42b5..3604d5b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,7 @@
2009-09-18 Jason Merrill <jason@redhat.com>
+ * g++.dg/cpp0x/nolinkage1{.C,.h,a.cc}: New.
+
* g++.dg/cpp0x/initlist-deduce.C: New.
2009-09-18 Janis Johnson <janis187@us.ibm.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C b/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C
new file mode 100644
index 0000000..a31394b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C
@@ -0,0 +1,21 @@
+// DR 757 allows using types without linkage in declarations with linkage.
+// Test that this doesn't lead to link-time collisions.
+
+// { dg-additional-sources "nolinkage1a.cc" }
+// { dg-do link }
+
+#include "nolinkage1.h"
+
+typedef struct { int i; } *AP;
+
+void f(AP) { }
+
+A<AP> a;
+
+static void g()
+{
+ struct B { };
+ A<B> a;
+}
+
+int main() { g(); f(0); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/nolinkage1.h b/gcc/testsuite/g++.dg/cpp0x/nolinkage1.h
new file mode 100644
index 0000000..3cb5f63
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nolinkage1.h
@@ -0,0 +1,8 @@
+template <class T>
+struct A
+{
+ A();
+};
+
+template <class T>
+A<T>::A() { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/nolinkage1a.cc b/gcc/testsuite/g++.dg/cpp0x/nolinkage1a.cc
new file mode 100644
index 0000000..f8528f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nolinkage1a.cc
@@ -0,0 +1,15 @@
+#include "nolinkage1.h"
+
+typedef struct { double d; } *BP;
+
+void f(BP) { }
+
+A<BP> b;
+
+static void g()
+{
+ struct B { };
+ A<B> a;
+}
+
+int dummy() { g(); f(0); }