Static linkage and anonymous namespace
Martin von Loewis
martin@mira.isdn.cs.tu-berlin.de
Sun Aug 30 13:00:00 GMT 1998
Under the as-if rule, a conforming C++ compiler can avoid making
members of anonymous namespaces accessible to other translation units.
For g++, the unique name of the anonymous namespace is not entirely
unique, so making those identifiers .local improves conformance.
This patch introduces the private_flag for identifiers; the C++
back-end sets the flag for all identifiers that contain the anynomous
namespace name. Declarations with private names then get the public
flag cleared.
Should I commit this?
Martin
gcc/ChangeLog
Sun Aug 30 21:44:43 1998 Martin von Löwis <loewis@informatik.hu-berlin.de>
* tree.h (IDENTIFIER_PRIVATE): New macro.
* toplev.c (rest_of_decl_compilation, rest_of_compilation):
Clear TREE_PUBLIC on private identifiers.
cp/ChangeLog
1998-08-30 Martin von Löwis <loewis@informatik.hu-berlin.de>
* decl.c (push_namespace): Make anon_namespace_name global.
Mark it as a private name.
(pushtag): Use build_overload_id.
(grokdeclarator): Likewise.
* decl2.c (grokfield): Likewise.
(comdat_linkage): Private identifiers are not comdat...
(maybe_make_one_only): and not one-only.
* lex.c (build_lang_decl): Use build_overload_id.
(build_lang_field_decl): Likewise.
* method.c (identifier_private): New variable.
(OB_INIT, OB_PUTID): Propagate private flag.
(build_overload_id): New function.
(build_static_name): Set private flag.
(build_decl_overload_real): Likewise.
(build_typename_overload): Likewise.
(build_overload_with_type): Likewise.
(get_id_2): Likewise.
(make_thunk): Likewise.
* pt.c (lookup_template_class): Use build_overload_id.
Index: toplev.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/toplev.c,v
retrieving revision 1.91
diff -c -p -r1.91 toplev.c
*** toplev.c 1998/08/26 08:11:41 1.91
--- toplev.c 1998/08/30 19:27:13
*************** rest_of_decl_compilation (decl, asmspec,
*** 3115,3120 ****
--- 3115,3124 ----
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP, END)
#endif
+ if (DECL_ASSEMBLER_NAME (decl)
+ && IDENTIFIER_PRIVATE (DECL_ASSEMBLER_NAME (decl)))
+ TREE_PUBLIC (decl) = 0;
+
/* Forward declarations for nested functions are not "external",
but we need to treat them as if they were. */
if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
*************** rest_of_compilation (decl)
*** 3201,3206 ****
--- 3205,3213 ----
/* Likewise, for DECL_ARGUMENTS. */
tree saved_arguments = 0;
int failure = 0;
+
+ if (IDENTIFIER_PRIVATE (DECL_ASSEMBLER_NAME (decl)))
+ TREE_PUBLIC (decl) = 0;
/* If we are reconsidering an inline function
at the end of compilation, skip the stuff for making it inline. */
Index: tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.h,v
retrieving revision 1.51
diff -c -p -r1.51 tree.h
*** tree.h 1998/08/21 19:32:16 1.51
--- tree.h 1998/08/30 19:27:16
*************** struct tree_common
*** 236,241 ****
--- 236,243 ----
TREE_LIST or TREE_VEC
TREE_PRIVATE in
??? unspecified nodes
+ IDENTIFIER_PRIVATE in
+ IDENTIFIER_NODE
protected_flag:
*************** struct tree_common
*** 468,473 ****
--- 470,479 ----
/* Ditto, for `private' declarations. */
#define TREE_VIA_PRIVATE(NODE) ((NODE)->common.private_flag)
+
+ /* Nonzero if this identifier should not have public values. In C++,
+ identifier then contains the anonymous namespace name. */
+ #define IDENTIFIER_PRIVATE(NODE) TREE_PRIVATE(NODE)
/* Nonzero for TREE_LIST node means that the path to the
base class is via a `protected' declaration, which preserves
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.126
diff -c -p -r1.126 cp-tree.h
*** cp-tree.h 1998/08/28 16:11:31 1.126
--- cp-tree.h 1998/08/30 19:27:39
*************** extern void yyhook PROTO((int));
*** 2757,2762 ****
--- 2763,2769 ----
extern void init_method PROTO((void));
extern void do_inline_function_hair PROTO((tree, tree));
extern char *build_overload_name PROTO((tree, int, int));
+ extern tree build_overload_id PROTO((tree));
extern tree build_static_name PROTO((tree, tree));
extern tree build_decl_overload PROTO((tree, tree, int));
extern tree build_decl_overload_real PROTO((tree, tree, tree, tree,
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.198
diff -c -p -r1.198 decl.c
*** decl.c 1998/08/28 15:43:53 1.198
--- decl.c 1998/08/30 19:27:53
*************** int in_std = 0;
*** 337,342 ****
--- 337,345 ----
/* Expect only namespace names now. */
static int only_namespace_names;
+ /* The name of anonymous namespace is unique for the translation unit. */
+ tree anon_namespace_name = NULL_TREE;
+
/* In a destructor, the point at which all derived class destroying
has been done, just before any base class destroying will be done. */
*************** push_namespace (name)
*** 1781,1792 ****
}
else if (!name)
{
! /* The name of anonymous namespace is unique for the translation
! unit. */
! static tree anon_name = NULL_TREE;
! if (!anon_name)
! anon_name = get_file_function_name ('N');
! name = anon_name;
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d)
/* Reopening anonymous namespace. */
--- 1784,1795 ----
}
else if (!name)
{
! if (!anon_namespace_name)
! {
! anon_namespace_name = get_file_function_name ('N');
! IDENTIFIER_PRIVATE (anon_namespace_name) = 1;
! }
! name = anon_namespace_name;
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d)
/* Reopening anonymous namespace. */
*************** pushtag (name, type, globalize)
*** 2400,2407 ****
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
if (!uses_template_parms (type))
! DECL_ASSEMBLER_NAME (d)
! = get_identifier (build_overload_name (type, 1, 1));
}
}
if (b->parm_flag == 2)
--- 2403,2409 ----
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
if (!uses_template_parms (type))
! DECL_ASSEMBLER_NAME (d) = build_overload_id (type);
}
}
if (b->parm_flag == 2)
*************** grokdeclarator (declarator, declspecs, d
*** 10036,10043 ****
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl);
! DECL_ASSEMBLER_NAME (decl)
! = get_identifier (build_overload_name (type, 1, 1));
DECL_CONTEXT (decl) = NULL_TREE;
/* FIXME remangle member functions; member functions of a
--- 10041,10047 ----
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl);
! DECL_ASSEMBLER_NAME (decl) = build_overload_id (type);
DECL_CONTEXT (decl) = NULL_TREE;
/* FIXME remangle member functions; member functions of a
Index: cp/decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.123
diff -c -p -r1.123 decl2.c
*** decl2.c 1998/08/28 16:11:33 1.123
--- decl2.c 1998/08/30 19:27:58
*************** grokfield (declarator, declspecs, init,
*** 1644,1651 ****
name for this TYPE_DECL. */
DECL_ASSEMBLER_NAME (value) = DECL_NAME (value);
if (!uses_template_parms (value))
! DECL_ASSEMBLER_NAME (value) =
! get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
pushdecl_class_level (value);
return value;
--- 1657,1663 ----
name for this TYPE_DECL. */
DECL_ASSEMBLER_NAME (value) = DECL_NAME (value);
if (!uses_template_parms (value))
! DECL_ASSEMBLER_NAME (value) = build_overload_id (TREE_TYPE (value));
pushdecl_class_level (value);
return value;
*************** void
*** 2509,2514 ****
--- 2521,2532 ----
comdat_linkage (decl)
tree decl;
{
+ if (IDENTIFIER_PRIVATE (DECL_ASSEMBLER_NAME (decl)))
+ {
+ TREE_PUBLIC (decl) = 0;
+ return;
+ }
+
if (flag_weak)
make_decl_one_only (decl);
else
*************** maybe_make_one_only (decl)
*** 2536,2542 ****
We can't use make_decl_one_only for variables, because their
DECL_INITIAL may not have been set properly yet. */
! if (TREE_CODE (decl) == FUNCTION_DECL)
make_decl_one_only (decl);
else
comdat_linkage (decl);
--- 2554,2563 ----
We can't use make_decl_one_only for variables, because their
DECL_INITIAL may not have been set properly yet. */
! if (IDENTIFIER_PRIVATE (DECL_ASSEMBLER_NAME (decl)))
! /* Anonymous-namespace members are plain static. */
! TREE_PUBLIC (decl) = 0;
! else if (TREE_CODE (decl) == FUNCTION_DECL)
make_decl_one_only (decl);
else
comdat_linkage (decl);
Index: cp/lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.70
diff -c -p -r1.70 lex.c
*** lex.c 1998/08/28 17:36:09 1.70
--- lex.c 1998/08/30 19:28:06
*************** build_lang_decl (code, name, type)
*** 4538,4544 ****
if (code == TYPE_DECL)
{
tree id;
! id = get_identifier (build_overload_name (type, 1, 1));
DECL_ASSEMBLER_NAME (t) = id;
}
--- 4538,4544 ----
if (code == TYPE_DECL)
{
tree id;
! id = build_overload_id (type);
DECL_ASSEMBLER_NAME (t) = id;
}
*************** build_lang_field_decl (code, name, type)
*** 4567,4573 ****
if (code == TYPE_DECL)
{
tree id;
! id = get_identifier (build_overload_name (type, 1, 1));
DECL_ASSEMBLER_NAME (t) = id;
}
#endif
--- 4567,4573 ----
if (code == TYPE_DECL)
{
tree id;
! id = build_overload_id (type);
DECL_ASSEMBLER_NAME (t) = id;
}
#endif
Index: cp/method.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/method.c,v
retrieving revision 1.72
diff -c -p -r1.72 method.c
*** method.c 1998/08/27 02:04:26 1.72
--- method.c 1998/08/30 19:28:21
*************** int static_labelno;
*** 55,60 ****
--- 55,63 ----
static struct obstack scratch_obstack;
static char *scratch_firstobj;
+ /* Value for IDENTIFIER_PRIVATE. */
+ static int identifier_private;
+
static void icat PROTO((HOST_WIDE_INT));
static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT));
static void flush_repeats PROTO((int, tree));
*************** static int check_btype PROTO((tree));
*** 85,98 ****
static void build_mangled_name_for_type PROTO((tree));
static void build_mangled_name_for_type_with_Gcode PROTO((tree, int));
! # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
# define OB_PUTC2(C1,C2) \
(obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2)))
# define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1))
! # define OB_PUTID(ID) \
! (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID), \
! IDENTIFIER_LENGTH (ID)))
# define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S)))
# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
# define OB_LAST() (obstack_next_free (&scratch_obstack)[-1])
--- 88,110 ----
static void build_mangled_name_for_type PROTO((tree));
static void build_mangled_name_for_type_with_Gcode PROTO((tree, int));
! # define OB_INIT() \
! do \
! { \
! if (scratch_firstobj) \
! obstack_free (&scratch_obstack, scratch_firstobj); \
! identifier_private = 0; \
! }while(0)
# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
# define OB_PUTC2(C1,C2) \
(obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2)))
# define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1))
! # define OB_PUTID(ID) \
! do{ \
! obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID), \
! IDENTIFIER_LENGTH (ID)); \
! if (IDENTIFIER_PRIVATE (ID))identifier_private = 1; \
! }while(0)
# define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S)))
# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
# define OB_LAST() (obstack_next_free (&scratch_obstack)[-1])
*************** build_overload_name (parmtypes, begin, e
*** 1042,1047 ****
--- 1054,1068 ----
return ret ;
}
+ tree
+ build_overload_id (parmtypes)
+ tree parmtypes;
+ {
+ tree ret = get_identifier (build_overload_name (parmtypes, 1, 1));
+ IDENTIFIER_PRIVATE (ret) = identifier_private;
+ return ret;
+ }
+
/* Output the mangled representation for PARMTYPES. If PARMTYPES is a
TREE_LIST, then it is a list of parameter types. Otherwise,
PARMTYPES must be a single type. */
*************** build_static_name (context, name)
*** 1487,1493 ****
OB_FINISH ();
end_squangling ();
! return get_identifier ((char *)obstack_base (&scratch_obstack));
}
/* FOR_METHOD should be 1 if the declaration in question is for a member
--- 1508,1516 ----
OB_FINISH ();
end_squangling ();
! name = get_identifier ((char *)obstack_base (&scratch_obstack));
! IDENTIFIER_PRIVATE (name) = identifier_private;
! return name;
}
/* FOR_METHOD should be 1 if the declaration in question is for a member
*************** build_decl_overload_real (dname, parms,
*** 1631,1636 ****
--- 1654,1660 ----
tree n = get_identifier (obstack_base (&scratch_obstack));
if (IDENTIFIER_OPNAME_P (dname))
IDENTIFIER_OPNAME_P (n) = 1;
+ IDENTIFIER_PRIVATE (n) = identifier_private;
return n;
}
}
*************** build_typename_overload (type)
*** 1695,1700 ****
--- 1719,1725 ----
build_mangled_name (type, 0, 1);
id = get_identifier (obstack_base (&scratch_obstack));
IDENTIFIER_OPNAME_P (id) = 1;
+ IDENTIFIER_PRIVATE (id) = identifier_private;
#if 0
IDENTIFIER_GLOBAL_VALUE (id) = TYPE_MAIN_DECL (type);
#endif
*************** build_overload_with_type (name, type)
*** 1714,1720 ****
start_squangling ();
build_mangled_name (type, 0, 1);
end_squangling ();
! return get_identifier (obstack_base (&scratch_obstack));
}
tree
--- 1739,1747 ----
start_squangling ();
build_mangled_name (type, 0, 1);
end_squangling ();
! name = get_identifier (obstack_base (&scratch_obstack));
! IDENTIFIER_PRIVATE (name) = identifier_private;
! return name;
}
tree
*************** get_id_2 (name, name2)
*** 1722,1732 ****
char *name;
tree name2;
{
OB_INIT ();
OB_PUTCP (name);
OB_PUTID (name2);
OB_FINISH ();
! return get_identifier (obstack_base (&scratch_obstack));
}
/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */
--- 1749,1762 ----
char *name;
tree name2;
{
+ tree result;
OB_INIT ();
OB_PUTCP (name);
OB_PUTID (name2);
OB_FINISH ();
! result = get_identifier (obstack_base (&scratch_obstack));
! IDENTIFIER_PRIVATE (result) = identifier_private;
! return result;
}
/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */
*************** make_thunk (function, delta)
*** 1988,1993 ****
--- 2018,2024 ----
OB_PUTID (DECL_ASSEMBLER_NAME (func_decl));
OB_FINISH ();
thunk_id = get_identifier (obstack_base (&scratch_obstack));
+ IDENTIFIER_PRIVATE (thunk_id) = identifier_private;
thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
if (thunk && TREE_CODE (thunk) != THUNK_DECL)
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.191
diff -c -p -r1.191 pt.c
*** pt.c 1998/08/29 01:15:22 1.191
--- pt.c 1998/08/30 19:28:50
*************** lookup_template_class (d1, arglist, in_d
*** 3489,3496 ****
DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
if (!is_partial_instantiation)
{
! DECL_ASSEMBLER_NAME (type_decl)
! = get_identifier (build_overload_name (t, 1, 1));
/* For backwards compatibility; code that uses
-fexternal-templates expects looking up a template to
--- 3489,3495 ----
DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
if (!is_partial_instantiation)
{
! DECL_ASSEMBLER_NAME (type_decl) = build_overload_id (t);
/* For backwards compatibility; code that uses
-fexternal-templates expects looking up a template to
More information about the Gcc-patches
mailing list