From ecc607fc08d8d9345406ff824063fcaf500f9021 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 18 Sep 2009 17:25:18 -0400 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 11 +++++++++ gcc/cp/cp-tree.h | 4 +++ gcc/cp/decl.c | 12 ++++----- gcc/cp/decl2.c | 28 ++++++++++++++++++++- gcc/cp/tree.c | 41 +++++++++++++++++++++++++------ gcc/testsuite/ChangeLog | 2 ++ gcc/testsuite/g++.dg/cpp0x/nolinkage1.C | 21 ++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/nolinkage1.h | 8 ++++++ gcc/testsuite/g++.dg/cpp0x/nolinkage1a.cc | 15 +++++++++++ 9 files changed, 127 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/nolinkage1.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/nolinkage1.h create mode 100644 gcc/testsuite/g++.dg/cpp0x/nolinkage1a.cc 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 + * 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 + * g++.dg/cpp0x/nolinkage1{.C,.h,a.cc}: New. + * g++.dg/cpp0x/initlist-deduce.C: New. 2009-09-18 Janis Johnson 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 a; + +static void g() +{ + struct B { }; + A 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 +struct A +{ + A(); +}; + +template +A::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 b; + +static void g() +{ + struct B { }; + A a; +} + +int dummy() { g(); f(0); } -- 2.7.4