This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: [mingw/cygwin] Add "selectany" (=linkonce) attribute for initialized global data


Hello

The apended patch adds the "selectany" attribute, which causes an
initialized global variable to have link-once semantics, for windows
targets.  The attribute is declared on other compilers using the
synonym __declspec(selectany)) and is commonly used in MS win32api
headers to define ids (GUID objects) used to register Common Object
Model (COM) "interfaces". It is also use extensively in such COM code
as MS's proprietary "Active Template Library" (ATL) to allow in-header
definition of static data members of C++ classes.

I have only added this as a subtarget attribute for windows targets,
since it specifies a very restricted type of COMDAT linkage that, AFAIK,
is common only in the MS world.  Does it have any wider utility?

Bootstrapped and tested on i686-pc-mingw32 with C, C++.
gcc version 4.1.0 20050304 (experimental)

OK for mainline?

Danny



Changelog

2005-03-06  Danny Smith  <dannysmith@users.sourceforge.net>

	* config/i386/cygming.h (SUBTARGET_ATTRIBUTE_TABLE): Define,
	with entry for selectany attribute.
	* config/i386/i386-protos.h (ix86_handle_selectany_attribute):
	Declare.
	* config/i386/winnt.c (ix86_handle_selectany_attribute): Define.
	(i386_pe_asm_named_section): Handle sections generated by
	selectany attribute.
	* doc/extend.texi (selectany): Document attribute.
	
testsuite/Changelog

	* g++.dg/ext/selectany1.C: New file. Test for linkonce sections.
	* g++.dg/ext/selectany2.C: New file. Test for errors with invalid
	selectany usage.


Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.241
diff -c -3 -p -r1.241 extend.texi
*** doc/extend.texi	25 Feb 2005 18:29:28 -0000	1.241
--- doc/extend.texi	5 Mar 2005 22:09:53 -0000
*************** struct S  __attribute__ ((vector_size (1
*** 2965,2970 ****
--- 2965,2990 ----
  is invalid even if the size of the structure is the same as the size of
  the @code{int}.
  
+ @item selectany
+ The @code{selectany} attribute causes an initialized global variable to
+ have link-once semantics.  When multiple definitions of the variable are
+ encountered by the linker, the first is selected and the remainder are
+ discarded.  Following usage by the Microsoft compiler, the linker is told
+ @emph{not} to warn about size or content differences of the multiple
+ definitions.
+ 
+ Although the primary usage of this attribute is for POD types, the
+ attribute can also be applied to global C++ objects that are initialized
+ by a constructor.  In this case, the static initialization and destruction
+ code for the object is emitted in each translation defining the object,
+ but the calls to the constructor and destructor are protected by a
+ link-once guard variable. 
+ 
+ The @code{selectany} attribute is only available on Microsoft Windows
+ targets.  You can use @code{__declspec (selectany)} as a synonym for
+ @code{__attribute__ ((selectany))} for compatibility with other
+ compilers.
+ 
  @item weak
  The @code{weak} attribute is described in @xref{Function Attributes}.
  
Index: config/i386/cygming.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/cygming.h,v
retrieving revision 1.24
diff -c -3 -p -r1.24 cygming.h
*** config/i386/cygming.h	13 Dec 2004 06:57:12 -0000	1.24
--- config/i386/cygming.h	5 Mar 2005 22:09:56 -0000
*************** extern int i386_pe_dllimport_name_p (con
*** 418,423 ****
--- 418,427 ----
  #undef TARGET_USE_LOCAL_THUNK_ALIAS_P
  #define TARGET_USE_LOCAL_THUNK_ALIAS_P(DECL) (!DECL_ONE_ONLY (DECL))
  
+ #define SUBTARGET_ATTRIBUTE_TABLE \
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ \
+   { "selectany", 0, 0, true, false, false, ix86_handle_selectany_attribute }
+ 
  #undef TREE
  
  #ifndef BUFSIZ
Index: config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.131
diff -c -3 -p -r1.131 i386-protos.h
*** config/i386/i386-protos.h	2 Feb 2005 00:30:25 -0000	1.131
--- config/i386/i386-protos.h	5 Mar 2005 22:09:56 -0000
*************** extern int ix86_data_alignment (tree, in
*** 216,221 ****
--- 216,222 ----
  extern int ix86_local_alignment (tree, int);
  extern int ix86_constant_alignment (tree, int);
  extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
+ extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *); 
  
  extern unsigned int i386_pe_section_type_flags (tree, const char *, int);
  extern void i386_pe_asm_named_section (const char *, unsigned int, tree);
Index: config/i386/winnt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/winnt.c,v
retrieving revision 1.75
diff -c -3 -p -r1.75 winnt.c
*** config/i386/winnt.c	9 Nov 2004 10:13:02 -0000	1.75
--- config/i386/winnt.c	5 Mar 2005 22:09:58 -0000
*************** ix86_handle_shared_attribute (tree *node
*** 78,83 ****
--- 78,113 ----
  
    return NULL_TREE;
  }
+ 
+ /* Handle a "selectany" attribute;
+    arguments as in struct attribute_spec.handler.  */
+ tree
+ ix86_handle_selectany_attribute (tree *node, tree name,
+ 			         tree args ATTRIBUTE_UNUSED,
+ 			         int flags ATTRIBUTE_UNUSED,
+ 				 bool *no_add_attrs)
+ {
+   /* The attribute applies only to objects that are initialized and have
+      external linkage,  */	
+   if (TREE_CODE (*node) == VAR_DECL && TREE_PUBLIC (*node)
+       && (DECL_INITIAL (*node)
+           /* If a global object is initialized with a ctor, the static
+ 	     initialization and destruction code for it is present in
+ 	     each unit defining the object.  The code that calls the
+ 	     ctor is protected by a link-once guard variable, so that
+ 	     the object still has link-once semantics.  */
+     	  || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (*node))))
+     make_decl_one_only (*node);
+   else
+     {	
+       error ("%qs attribute applies only to initialized variables"
+        	     " with external linkage",  IDENTIFIER_POINTER (name));
+       *no_add_attrs = true;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
  
  /* Return the type that we should use to determine if DECL is
     imported or exported.  */
*************** i386_pe_section_type_flags (tree decl, c
*** 622,628 ****
  
  void
  i386_pe_asm_named_section (const char *name, unsigned int flags, 
! 			   tree decl ATTRIBUTE_UNUSED)
  {
    char flagchars[8], *f = flagchars;
  
--- 652,658 ----
  
  void
  i386_pe_asm_named_section (const char *name, unsigned int flags, 
! 			   tree decl)
  {
    char flagchars[8], *f = flagchars;
  
*************** i386_pe_asm_named_section (const char *n
*** 649,658 ****
    if (flags & SECTION_LINKONCE)
      {
        /* Functions may have been compiled at various levels of
!          optimization so we can't use `same_size' here.
!          Instead, have the linker pick one.  */
        fprintf (asm_out_file, "\t.linkonce %s\n",
! 	       (flags & SECTION_CODE ? "discard" : "same_size"));
      }
  }
  
--- 679,694 ----
    if (flags & SECTION_LINKONCE)
      {
        /* Functions may have been compiled at various levels of
! 	 optimization so we can't use `same_size' here.
! 	 Instead, have the linker pick one, without warning.
! 	 If 'selectany' attibute has been specified,  MS compiler
! 	 sets 'discard' characteristic, rather than telling linker
! 	 to warn of size or content mismatch, so do the same.  */ 
!       bool discard = (flags & SECTION_CODE)
! 		      || lookup_attribute ("selectany",
! 					   DECL_ATTRIBUTES (decl));	 
        fprintf (asm_out_file, "\t.linkonce %s\n",
! 	       (discard  ? "discard" : "same_size"));
      }
  }
  
*** /dev/null	Sun Mar  6 14:28:54 2005
--- testsuite/g++.dg/ext/selectany1.C	Sun Mar  6 14:22:05 2005
***************
*** 0 ****
--- 1,21 ----
+ // { dg-do compile { target i?86-pc-cygwin } }
+ // { dg-do compile { target i?86-pc-mingw* } }
+ 
+ // Check that selectany attribute puts symbols into link-once sections.
+ 
+ // { dg-final { scan-assembler "\.section\t\.data\\\$foo\[^\n\]*\n\t\.linkonce discard" } }
+ // { dg-final { scan-assembler "\.section\t\.data\\\$x\[^\n\]*\n\t\.linkonce discard" } }
+ // { dg-final { scan-assembler-dem "\nguard variable for x:" } }
+ 
+ __declspec (selectany) int foo = 1;
+ 
+ class X
+ {
+ private:
+   int m_i;
+ public:
+   X(int i): m_i(i){}
+   ~X(){};
+ };
+ 
+ __declspec(selectany) X x(1);
*** /dev/null	Sun Mar  6 14:28:58 2005
--- testsuite/g++.dg/ext/selectany2.C	Sun Mar  6 10:21:41 2005
***************
*** 0 ****
--- 1,30 ----
+ // { dg-do compile { target i?86-pc-cygwin } }
+ // { dg-do compile { target i?86-pc-mingw* } }
+ 
+ // Check for errors with invalid usage of selectany attribute.
+ 
+ extern int foo;
+ __declspec (selectany) int foo = 1;  // OK
+ 
+ struct d
+ {
+   static int foo;
+ };
+ __declspec (selectany) int d::foo = 1;  // OK 
+ 
+ struct  f
+ {
+   int i;
+ };
+ __declspec (selectany) struct f  F= {1}; // OK
+ 
+ __declspec (selectany) int boo;	//{ dg-error "selectany" }
+ 
+ __declspec (selectany) static int bar = 1; // { dg-error "selectany" }
+ int use_bar = bar;  //  Avoid defined but not used warning. 
+ 
+ int baz()
+ {
+   __declspec (selectany)  int foo = 1;  // { dg-error "selectany" }
+   return foo;
+ }

Find local movie times and trailers on Yahoo! Movies.
http://au.movies.yahoo.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]