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