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
This commit is contained in:
parent
5f5babf18b
commit
ecc607fc08
9 changed files with 127 additions and 15 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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>
|
||||
|
|
21
gcc/testsuite/g++.dg/cpp0x/nolinkage1.C
Normal file
21
gcc/testsuite/g++.dg/cpp0x/nolinkage1.C
Normal file
|
@ -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); }
|
8
gcc/testsuite/g++.dg/cpp0x/nolinkage1.h
Normal file
8
gcc/testsuite/g++.dg/cpp0x/nolinkage1.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
template <class T>
|
||||
struct A
|
||||
{
|
||||
A();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
A<T>::A() { }
|
15
gcc/testsuite/g++.dg/cpp0x/nolinkage1a.cc
Normal file
15
gcc/testsuite/g++.dg/cpp0x/nolinkage1a.cc
Normal file
|
@ -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); }
|
Loading…
Add table
Reference in a new issue