Hello, Everyone. Attached patch is just backport from gcc mailine. More correctly: its backport of these patches:
http://gcc.gnu.org/ml/gcc-cvs/2005-10/msg00474.html http://gcc.gnu.org/ml/gcc-cvs/2005-10/msg00718.html The main aim of patches is better handling of dll* attributes especially set on C++ stuff. More patches will follow. However, this is the biggest one. There are 3 files attached: patch against current llvm-gcc sources + 2 new files, which should be placed to gcc/config/i386 directory. -- With best regards, Anton Korobeynikov. Faculty of Mathematics & Mechanics, Saint Petersburg State University.
diff -r 9a4f61828020 gcc/config.gcc --- a/gcc/config.gcc Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/config.gcc Fri Feb 16 00:46:07 2007 +0300 @@ -1209,9 +1209,9 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*) xm_file=i386/xm-cygwin.h tmake_file="i386/t-cygwin i386/t-cygming" target_gtfiles="\$(srcdir)/config/i386/winnt.c" - extra_objs=winnt.o + extra_objs="winnt.o winnt-stubs.o" c_target_objs=cygwin2.o - cxx_target_objs=cygwin2.o + cxx_target_objs="cygwin2.o winnt-cxx.o" extra_gcc_objs=cygwin1.o if test x$enable_threads = xyes; then thread_file='posix' @@ -1222,7 +1222,8 @@ i[34567]86-*-mingw32*) xm_file=i386/xm-mingw32.h tmake_file="i386/t-cygming i386/t-mingw32" target_gtfiles="\$(srcdir)/config/i386/winnt.c" - extra_objs=winnt.o + extra_objs="winnt.o winnt-stubs.o" + cxx_target_objs="winnt-cxx.o" case ${enable_threads} in "" | yes | win32) thread_file='win32' ;; esac diff -r 9a4f61828020 gcc/config/i386/cygming.h --- a/gcc/config/i386/cygming.h Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/config/i386/cygming.h Thu Feb 15 22:47:25 2007 +0300 @@ -422,6 +422,9 @@ extern int i386_pe_dllimport_p (tree); #undef TARGET_USE_LOCAL_THUNK_ALIAS_P #define TARGET_USE_LOCAL_THUNK_ALIAS_P(DECL) (!DECL_ONE_ONLY (DECL)) +#define TARGET_VALID_DLLIMPORT_ATTRIBUTE_P i386_pe_valid_dllimport_attribute_p +#define TARGET_CXX_ADJUST_CLASS_AT_DEFINITION i386_pe_adjust_class_at_definition + #undef TREE #ifndef BUFSIZ diff -r 9a4f61828020 gcc/config/i386/i386-protos.h --- a/gcc/config/i386/i386-protos.h Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/config/i386/i386-protos.h Thu Feb 15 23:09:35 2007 +0300 @@ -261,6 +261,13 @@ extern const char *i386_pe_strip_name_en extern const char *i386_pe_strip_name_encoding (const char *); extern const char *i386_pe_strip_name_encoding_full (const char *); extern void i386_pe_output_labelref (FILE *, const char *); +extern int i386_pe_valid_dllimport_attribute_p (tree); + +/* In winnt-cxx.c and winnt-stubs.c */ +extern void i386_pe_adjust_class_at_definition (tree); +extern bool i386_pe_type_dllimport_p (tree); +extern bool i386_pe_type_dllexport_p (tree); + extern rtx maybe_get_pool_constant (rtx); extern char internal_label_prefix[16]; diff -r 9a4f61828020 gcc/config/i386/i386.c --- a/gcc/config/i386/i386.c Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/config/i386/i386.c Thu Feb 15 19:01:42 2007 +0300 @@ -2323,7 +2323,7 @@ ix86_function_ok_for_sibcall (tree decl, #if TARGET_DLLIMPORT_DECL_ATTRIBUTES /* Dllimport'd functions are also called indirectly. */ - if (decl && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)) + if (decl && DECL_DLLIMPORT_P (decl) && ix86_function_regparm (TREE_TYPE (decl), NULL) >= 3) return false; #endif diff -r 9a4f61828020 gcc/config/i386/t-cygming --- a/gcc/config/i386/t-cygming Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/config/i386/t-cygming Thu Feb 15 19:05:50 2007 +0300 @@ -16,4 +16,17 @@ winnt.o: $(srcdir)/config/i386/winnt.c $ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/i386/winnt.c +winnt-cxx.o: $(srcdir)/config/i386/winnt-cxx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ + $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \ + $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H) + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/config/i386/winnt-cxx.c + + +winnt-stubs.o: $(srcdir)/config/i386/winnt-stubs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ + $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \ + $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H) + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/config/i386/winnt-stubs.c + STMP_FIXINC=stmp-fixinc diff -r 9a4f61828020 gcc/config/i386/winnt.c --- a/gcc/config/i386/winnt.c Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/config/i386/winnt.c Thu Feb 15 23:46:59 2007 +0300 @@ -83,131 +83,64 @@ static tree static tree associated_type (tree decl) { - tree t = NULL_TREE; - - /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer - to the containing class. So we look at the 'this' arg. */ - if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) - { - /* Artificial methods are not affected by the import/export status - of their class unless they are COMDAT. Implicit copy ctor's and - dtor's are not affected by class status but virtual and - non-virtual thunks are. */ - if (!DECL_ARTIFICIAL (decl) || DECL_COMDAT (decl)) - t = TYPE_MAIN_VARIANT - (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))))); - } - else if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) - t = DECL_CONTEXT (decl); - - return t; -} - -/* Return nonzero if DECL is a dllexport'd object. */ + return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) + ? DECL_CONTEXT (decl) : NULL_TREE; +} + +/* Return true if DECL is a dllexport'd object. */ int i386_pe_dllexport_p (tree decl) { - tree exp; - if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return 0; - exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)); - if (exp) + + if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) return 1; - /* Class members get the dllexport status of their class. */ - if (associated_type (decl)) - { - exp = lookup_attribute ("dllexport", - TYPE_ATTRIBUTES (associated_type (decl))); - if (exp) - return 1; - } - + /* Also mark class members of exported classes with dllexport. */ + if (associated_type (decl) + && lookup_attribute ("dllexport", + TYPE_ATTRIBUTES (associated_type (decl)))) + return i386_pe_type_dllexport_p (decl); + return 0; } -/* Return nonzero if DECL is a dllimport'd object. */ +/* Return true if DECL is a dllimport'd object. */ int i386_pe_dllimport_p (tree decl) { - tree imp; - int context_imp = 0; - - if (TREE_CODE (decl) == FUNCTION_DECL - && TARGET_NOP_FUN_DLLIMPORT) - return 0; - if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return 0; - imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); - - /* Class members get the dllimport status of their class. */ - if (!imp && associated_type (decl)) - { - imp = lookup_attribute ("dllimport", - TYPE_ATTRIBUTES (associated_type (decl))); - if (imp) - context_imp = 1; - } - - if (imp) - { - /* Don't mark defined functions as dllimport. If the definition - itself was marked with dllimport, than ix86_handle_dll_attribute - reports an error. This handles the case when the definition - overrides an earlier declaration. */ - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) - && !DECL_INLINE (decl)) - { - /* Don't warn about artificial methods. */ - if (!DECL_ARTIFICIAL (decl)) - warning ("%Jfunction '%D' is defined after prior declaration " - "as dllimport: attribute ignored", decl, decl); - return 0; - } - - /* We ignore the dllimport attribute for inline member functions. - This differs from MSVC behavior which treats it like GNUC - 'extern inline' extension. */ - else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl)) - { - if (extra_warnings) - warning ("%Jinline function '%D' is declared as dllimport: " - "attribute ignored.", decl, decl); - return 0; - } - - /* Don't allow definitions of static data members in dllimport class, - Just ignore attribute for vtable data. */ - else if (TREE_CODE (decl) == VAR_DECL - && TREE_STATIC (decl) && TREE_PUBLIC (decl) - && !DECL_EXTERNAL (decl) && context_imp) - { - if (!DECL_VIRTUAL_P (decl)) - error ("%Jdefinition of static data member '%D' of " - "dllimport'd class.", decl, decl); - return 0; - } - - /* Since we can't treat a pointer to a dllimport'd symbol as a - constant address, we turn off the attribute on C++ virtual - methods to allow creation of vtables using thunks. Don't mark - artificial methods either (in associated_type, only COMDAT - artificial method get import status from class context). */ - else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE - && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl))) - return 0; - - return 1; - } + /* Lookup the attribute rather than rely on the DECL_DLLIMPORT_P flag. + We may need to override an earlier decision. */ + if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))) + return 1; + + /* The DECL_DLLIMPORT_P flag was set for decls in the class definition + by targetm.cxx.adjust_class_at_definition. Check again to emit + warnings if the class attribute has been overriden by an + out-of-class definition. */ + if (associated_type (decl) + && lookup_attribute ("dllimport", + TYPE_ATTRIBUTES (associated_type (decl)))) + return i386_pe_type_dllimport_p (decl); return 0; +} + +/* Handle the -mno-fun-dllimport target switch. */ +int +i386_pe_valid_dllimport_attribute_p (tree decl) +{ + if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL) + return 0; + return 1; } /* Return nonzero if SYMBOL is marked as being dllexport'd. */ @@ -251,10 +184,9 @@ i386_pe_mark_dllexport (tree decl) if (i386_pe_dllimport_name_p (oldname)) { warning ("%Jinconsistent dll linkage for '%D', dllexport assumed.", - decl, decl); + decl, decl); /* Remove DLL_IMPORT_PREFIX. */ oldname += strlen (DLL_IMPORT_PREFIX); - DECL_NON_ADDR_CONST_P (decl) = 0; } else if (i386_pe_dllexport_name_p (oldname)) return; /* already done */ @@ -301,12 +233,13 @@ i386_pe_mark_dllimport (tree decl) else if (i386_pe_dllimport_name_p (oldname)) { /* Already done, but do a sanity check to prevent assembler errors. */ - if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)) - { - error ("%Jfailure in redeclaration of '%D': dllimport'd " - "symbol lacks external linkage.", decl, decl); - abort(); - } + if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl) + || !DECL_DLLIMPORT_P (decl)) + { + error ("%Jfailure in redeclaration of '%D': dllimport'd " + "symbol lacks external linkage.", decl, decl); + abort(); + } return; } @@ -324,8 +257,7 @@ i386_pe_mark_dllimport (tree decl) newrtl = gen_rtx_MEM (Pmode,symref); XEXP (DECL_RTL (decl), 0) = newrtl; - /* Can't treat a pointer to this as a constant address */ - DECL_NON_ADDR_CONST_P (decl) = 1; + DECL_DLLIMPORT_P (decl) = 1; } /* Return string which is the former assembler name modified with a @@ -338,7 +270,7 @@ gen_stdcall_or_fastcall_suffix (tree dec int total = 0; /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead of DECL_ASSEMBLER_NAME. */ - const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); char *newsym; char *p; tree formal_type; @@ -351,7 +283,7 @@ gen_stdcall_or_fastcall_suffix (tree dec if (formal_type != NULL_TREE) { /* These attributes are ignored for variadic functions in - i386.c:ix86_return_pops_args. For compatibility with MS + i386.c:ix86_return_pops_args. For compatibility with MS compiler do not add @0 suffix here. */ if (TREE_VALUE (tree_last (formal_type)) != void_type_node) return DECL_ASSEMBLER_NAME (decl); @@ -360,17 +292,17 @@ gen_stdcall_or_fastcall_suffix (tree dec by convert_arguments in c-typeck.c or cp/typeck.c. */ while (TREE_VALUE (formal_type) != void_type_node && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) - { - int parm_size - = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); - /* Must round up to include padding. This is done the same - way as in store_one_arg. */ - parm_size = ((parm_size + PARM_BOUNDARY - 1) - / PARM_BOUNDARY * PARM_BOUNDARY); - total += parm_size; - formal_type = TREE_CHAIN (formal_type);\ - } - } + { + int parm_size + = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); + /* Must round up to include padding. This is done the same + way as in store_one_arg. */ + parm_size = ((parm_size + PARM_BOUNDARY - 1) + / PARM_BOUNDARY * PARM_BOUNDARY); + total += parm_size; + formal_type = TREE_CHAIN (formal_type); \ + } + } /* Assume max of 8 base 10 digits in the suffix. */ newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1); @@ -392,62 +324,43 @@ i386_pe_encode_section_info (tree decl, tree newid = NULL_TREE; if (lookup_attribute ("stdcall", type_attributes)) - newid = gen_stdcall_or_fastcall_suffix (decl, false); + newid = gen_stdcall_or_fastcall_suffix (decl, false); else if (lookup_attribute ("fastcall", type_attributes)) - newid = gen_stdcall_or_fastcall_suffix (decl, true); + newid = gen_stdcall_or_fastcall_suffix (decl, true); if (newid != NULL_TREE) - { - rtx rtlname = XEXP (rtl, 0); - if (GET_CODE (rtlname) == MEM) - rtlname = XEXP (rtlname, 0); - XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid); - /* These attributes must be present on first declaration, - change_decl_assembler_name will warn if they are added - later and the decl has been referenced, but duplicate_decls - should catch the mismatch before this is called. */ - change_decl_assembler_name (decl, newid); - } + { + rtx rtlname = XEXP (rtl, 0); + if (GET_CODE (rtlname) == MEM) + rtlname = XEXP (rtlname, 0); + XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid); + /* These attributes must be present on first declaration, + change_decl_assembler_name will warn if they are added + later and the decl has been referenced, but duplicate_decls + should catch the mismatch before this is called. */ + change_decl_assembler_name (decl, newid); + } } /* Mark the decl so we can tell from the rtl whether the object is - dllexport'd or dllimport'd. This also handles dllexport/dllimport - override semantics. */ + dllexport'd or dllimport'd. tree.c: merge_dllimport_decl_attributes + handles dllexport/dllimport override semantics. */ if (i386_pe_dllexport_p (decl)) i386_pe_mark_dllexport (decl); else if (i386_pe_dllimport_p (decl)) i386_pe_mark_dllimport (decl); - /* It might be that DECL has already been marked as dllimport, but a - subsequent definition nullified that. The attribute is gone but - DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove - that. Ditto for the DECL_NON_ADDR_CONST_P flag. */ - else if ((TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == VAR_DECL) - && DECL_RTL (decl) != NULL_RTX - && GET_CODE (DECL_RTL (decl)) == MEM - && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM - && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF - && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0))) - { - const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0); - - /* Remove DLL_IMPORT_PREFIX. */ - tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX)); - rtx symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); - SYMBOL_REF_DECL (symref) = decl; - XEXP (DECL_RTL (decl), 0) = symref; - DECL_NON_ADDR_CONST_P (decl) = 0; - - /* We previously set TREE_PUBLIC and DECL_EXTERNAL. - We leave these alone for now. */ - - if (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl)) - warning ("%J'%D' defined locally after being " - "referenced with dllimport linkage", decl, decl); - else - warning ("%J'%D' redeclared without dllimport attribute " - "after being referenced with dllimport linkage", decl, decl); - } + /* It might be that DECL has been declared as dllimport, but a + subsequent definition nullified that. Assert that + tree.c: merge_dllimport_decl_attributes has removed the attribute + before the RTL name was marked with the DLL_IMPORT_PREFIX. */ + else + gcc_assert(!((TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == VAR_DECL) + && rtl != NULL_RTX + && GET_CODE (rtl) == MEM + && GET_CODE (XEXP (rtl, 0)) == MEM + && GET_CODE (XEXP (XEXP (rtl, 0), 0)) == SYMBOL_REF + && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (rtl, 0), 0), 0)))); } /* Strip only the leading encoding, leaving the stdcall suffix and fastcall @@ -595,8 +508,8 @@ i386_pe_section_type_flags (tree decl, c flags = SECTION_WRITE; if (decl && TREE_CODE (decl) == VAR_DECL - && lookup_attribute ("shared", DECL_ATTRIBUTES (decl))) - flags |= SECTION_PE_SHARED; + && lookup_attribute ("shared", DECL_ATTRIBUTES (decl))) + flags |= SECTION_PE_SHARED; } if (decl && DECL_ONE_ONLY (decl)) @@ -612,7 +525,7 @@ i386_pe_section_type_flags (tree decl, c else { if (decl && **slot != flags) - error ("%J'%D' causes a section type conflict", decl, decl); + error ("%J'%D' causes a section type conflict", decl, decl); } return flags; @@ -751,11 +664,11 @@ i386_pe_file_end (void) /* Positively ensure only one declaration for any given symbol. */ if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl)) - { - TREE_ASM_WRITTEN (decl) = 1; - i386_pe_declare_function_type (asm_out_file, p->name, - TREE_PUBLIC (decl)); - } + { + TREE_ASM_WRITTEN (decl) = 1; + i386_pe_declare_function_type (asm_out_file, p->name, + TREE_PUBLIC (decl)); + } } if (export_head) @@ -763,11 +676,11 @@ i386_pe_file_end (void) struct export_list *q; drectve_section (); for (q = export_head; q != NULL; q = q->next) - { - fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n", - i386_pe_strip_name_encoding (q->name), - (q->is_data) ? ",data" : ""); - } + { + fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n", + i386_pe_strip_name_encoding (q->name), + (q->is_data) ? ",data" : ""); + } } } diff -r 9a4f61828020 gcc/target-def.h --- a/gcc/target-def.h Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/target-def.h Thu Feb 15 19:29:42 2007 +0300 @@ -416,6 +416,10 @@ Foundation, 59 Temple Place - Suite 330, #define TARGET_DWARF_HANDLE_FRAME_UNSPEC 0 +#ifndef TARGET_VALID_DLLIMPORT_ATTRIBUTE_P +#define TARGET_VALID_DLLIMPORT_ATTRIBUTE_P hook_bool_tree_true +#endif + #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_false #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_false #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_false @@ -530,6 +534,11 @@ Foundation, 59 Temple Place - Suite 330, #endif /* APPLE LOCAL end mainline 4.2 2006-03-01 4311680 */ + +#ifndef TARGET_CXX_ADJUST_CLASS_AT_DEFINITION +#define TARGET_CXX_ADJUST_CLASS_AT_DEFINITION hook_void_tree +#endif + #define TARGET_CXX \ { \ TARGET_CXX_GUARD_TYPE, \ @@ -543,6 +552,7 @@ Foundation, 59 Temple Place - Suite 330, TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY, \ TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT, \ /* APPLE LOCAL end mainline 4.2 2006-03-01 4311680 */ \ + TARGET_CXX_ADJUST_CLASS_AT_DEFINITION \ } /* The whole shebang. */ @@ -604,6 +614,7 @@ Foundation, 59 Temple Place - Suite 330, TARGET_MD_ASM_CLOBBERS, \ TARGET_DWARF_CALLING_CONVENTION, \ TARGET_DWARF_HANDLE_FRAME_UNSPEC, \ + TARGET_VALID_DLLIMPORT_ATTRIBUTE_P, \ TARGET_CALLS, \ TARGET_CXX, \ TARGET_HAVE_NAMED_SECTIONS, \ diff -r 9a4f61828020 gcc/target.h --- a/gcc/target.h Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/target.h Thu Feb 15 19:22:02 2007 +0300 @@ -524,6 +524,11 @@ struct gcc_target (set (reg) (unspec_volatile [...] UNSPECV_INDEX)) to let the backend emit the call frame instructions. */ void (* dwarf_handle_frame_unspec) (const char *, rtx, int); + + /* DECL is a variable or function with __attribute__((dllimport)) + specified. Use this hook if the target needs to add extra validation + checks to handle_dll_attribute (). */ + bool (* valid_dllimport_attribute_p) (tree decl); /* Functions relating to calls - argument passing, returns, etc. */ struct calls { @@ -628,6 +633,11 @@ struct gcc_target only one translation unit will not be COMDAT. */ bool (*class_data_always_comdat) (void); /* APPLE LOCAL end mainline 4.2 2006-03-01 4311680 */ + /* TYPE is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that + has just been defined. Use this hook to make adjustments to the + class (eg, tweak visibility or perform any other required + target modifications). */ + void (*adjust_class_at_definition) (tree type); } cxx; /* Leave the boolean fields at the end. */ diff -r 9a4f61828020 gcc/tree.c --- a/gcc/tree.c Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/tree.c Thu Feb 15 23:55:58 2007 +0300 @@ -1632,7 +1632,7 @@ staticp (tree arg) case VAR_DECL: return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg)) && ! DECL_THREAD_LOCAL (arg) - && ! DECL_NON_ADDR_CONST_P (arg) + && ! DECL_DLLIMPORT_P (arg) ? arg : NULL); case CONST_DECL: @@ -3044,34 +3044,34 @@ build_type_attribute_variant (tree ttype hashcode = iterative_hash_object (code, hashcode); if (TREE_TYPE (ntype)) - hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (ntype)), - hashcode); + hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (ntype)), + hashcode); hashcode = attribute_hash_list (attribute, hashcode); switch (TREE_CODE (ntype)) - { - case FUNCTION_TYPE: - hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode); - break; - case ARRAY_TYPE: - hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)), - hashcode); - break; - case INTEGER_TYPE: - hashcode = iterative_hash_object - (TREE_INT_CST_LOW (TYPE_MAX_VALUE (ntype)), hashcode); - hashcode = iterative_hash_object - (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode); - break; - case REAL_TYPE: - { - unsigned int precision = TYPE_PRECISION (ntype); - hashcode = iterative_hash_object (precision, hashcode); - } - break; - default: - break; - } + { + case FUNCTION_TYPE: + hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode); + break; + case ARRAY_TYPE: + hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)), + hashcode); + break; + case INTEGER_TYPE: + hashcode = iterative_hash_object + (TREE_INT_CST_LOW (TYPE_MAX_VALUE (ntype)), hashcode); + hashcode = iterative_hash_object + (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode); + break; + case REAL_TYPE: + { + unsigned int precision = TYPE_PRECISION (ntype); + hashcode = iterative_hash_object (precision, hashcode); + } + break; + default: + break; + } ntype = type_hash_canon (hashcode, ntype); ttype = build_qualified_type (ntype, TYPE_QUALS (ttype)); @@ -3113,16 +3113,16 @@ is_attribute_with_length_p (const char * gcc_assert (attr[attr_len - 1] == '_'); gcc_assert (attr[1] == '_'); if (ident_len == attr_len - 4 - && strncmp (attr + 2, p, attr_len - 4) == 0) - return 1; + && strncmp (attr + 2, p, attr_len - 4) == 0) + return 1; } else { if (ident_len == attr_len + 4 - && p[0] == '_' && p[1] == '_' - && p[ident_len - 2] == '_' && p[ident_len - 1] == '_' - && strncmp (attr, p + 2, attr_len) == 0) - return 1; + && p[0] == '_' && p[1] == '_' + && p[ident_len - 2] == '_' && p[ident_len - 1] == '_' + && strncmp (attr, p + 2, attr_len) == 0) + return 1; } return 0; @@ -3155,7 +3155,7 @@ lookup_attribute (const char *attr_name, { gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE); if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l))) - return l; + return l; } return NULL_TREE; @@ -3178,34 +3178,34 @@ merge_attributes (tree a1, tree a2) else if (a2 != 0 && ! attribute_list_contained (a1, a2)) { if (attribute_list_contained (a2, a1)) - attributes = a2; + attributes = a2; else - { - /* Pick the longest list, and hang on the other list. */ - - if (list_length (a1) < list_length (a2)) - attributes = a2, a2 = a1; - - for (; a2 != 0; a2 = TREE_CHAIN (a2)) - { - tree a; - for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), - attributes); - a != NULL_TREE; - a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), - TREE_CHAIN (a))) - { - if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1) - break; - } - if (a == NULL_TREE) - { - a1 = copy_node (a2); - TREE_CHAIN (a1) = attributes; - attributes = a1; - } - } - } + { + /* Pick the longest list, and hang on the other list. */ + + if (list_length (a1) < list_length (a2)) + attributes = a2, a2 = a1; + + for (; a2 != 0; a2 = TREE_CHAIN (a2)) + { + tree a; + for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), + attributes); + a != NULL_TREE; + a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), + TREE_CHAIN (a))) + { + if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1) + break; + } + if (a == NULL_TREE) + { + a1 = copy_node (a2); + TREE_CHAIN (a1) = attributes; + attributes = a1; + } + } + } } return attributes; } @@ -3245,39 +3245,74 @@ merge_dllimport_decl_attributes (tree ol merge_dllimport_decl_attributes (tree old, tree new) { tree a; - int delete_dllimport_p; - - old = DECL_ATTRIBUTES (old); - new = DECL_ATTRIBUTES (new); + int delete_dllimport_p = 1; /* What we need to do here is remove from `old' dllimport if it doesn't appear in `new'. dllimport behaves like extern: if a declaration is marked dllimport and a definition appears later, then the object - is not dllimport'd. */ - if (lookup_attribute ("dllimport", old) != NULL_TREE - && lookup_attribute ("dllimport", new) == NULL_TREE) - delete_dllimport_p = 1; + is not dllimport'd. We also remove a `new' dllimport if the old list + contains dllexport: dllexport always overrides dllimport, regardless + of the order of declaration. */ + if (!VAR_OR_FUNCTION_DECL_P (new)) + delete_dllimport_p = 0; + else if (DECL_DLLIMPORT_P (new) + && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old))) + { + DECL_DLLIMPORT_P (new) = 0; + warning ("%qD already declared with dllexport attribute: " + "dllimport ignored", new); + } + else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new)) + { + /* Warn about overriding a symbol that has already been used. eg: + extern int __attribute__ ((dllimport)) foo; + int* bar () {return &foo;} + int foo; + */ + if (TREE_USED (old)) + { + warning ("%qD redeclared without dllimport attribute " + "after being referenced with dll linkage", new); + /* If we have used a variable's address with dllimport linkage, + keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the + decl may already have had TREE_INVARIANT and TREE_CONSTANT + computed. + We still remove the attribute so that assembler code refers + to '&foo rather than '_imp__foo'. */ + if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old)) + DECL_DLLIMPORT_P (new) = 1; + } + + /* Let an inline definition silently override the external reference, + but otherwise warn about attribute inconsistency. */ + else if (TREE_CODE (new) == VAR_DECL + || !DECL_DECLARED_INLINE_P (new)) + warning ("%qD redeclared without dllimport attribute: " + "previous dllimport ignored", new); + } else delete_dllimport_p = 0; - a = merge_attributes (old, new); + a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new)); if (delete_dllimport_p) { tree prev, t; + const size_t attr_len = strlen ("dllimport"); /* Scan the list for dllimport and delete it. */ for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t)) - { - if (is_attribute_p ("dllimport", TREE_PURPOSE (t))) - { - if (prev == NULL_TREE) - a = TREE_CHAIN (a); - else - TREE_CHAIN (prev) = TREE_CHAIN (t); - break; - } - } + { + if (is_attribute_with_length_p ("dllimport", attr_len, + TREE_PURPOSE (t))) + { + if (prev == NULL_TREE) + a = TREE_CHAIN (a); + else + TREE_CHAIN (prev) = TREE_CHAIN (t); + break; + } + } } return a; @@ -3298,15 +3333,15 @@ handle_dll_attribute (tree * pnode, tree { if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT | (int) ATTR_FLAG_ARRAY_NEXT)) - { - *no_add_attrs = true; - return tree_cons (name, args, NULL_TREE); - } + { + *no_add_attrs = true; + return tree_cons (name, args, NULL_TREE); + } if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) - { - warning ("%qs attribute ignored", IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } + { + warning ("%qs attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } return NULL_TREE; } @@ -3315,34 +3350,45 @@ handle_dll_attribute (tree * pnode, tree any damage. */ if (is_attribute_p ("dllimport", name)) { + /* Honor any target-specific overides. */ + if (!targetm.valid_dllimport_attribute_p (node)) + *no_add_attrs = true; + + else if (TREE_CODE (node) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (node)) + { + warning ("inline function %qD declared as " + " dllimport: attribute ignored", node); + *no_add_attrs = true; + } /* Like MS, treat definition of dllimported variables and - non-inlined functions on declaration as syntax errors. We - allow the attribute for function definitions if declared - inline. */ - if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node) - && !DECL_DECLARED_INLINE_P (node)) - { - error ("%Jfunction %qD definition is marked dllimport.", node, node); - *no_add_attrs = true; - } + non-inlined functions on declaration as syntax errors. */ + else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node)) + { + error ("%Jfunction %qD definition is marked dllimport.", node, node); + *no_add_attrs = true; + } else if (TREE_CODE (node) == VAR_DECL) - { - if (DECL_INITIAL (node)) - { - error ("%Jvariable %qD definition is marked dllimport.", - node, node); - *no_add_attrs = true; - } - - /* `extern' needn't be specified with dllimport. - Specify `extern' now and hope for the best. Sigh. */ - DECL_EXTERNAL (node) = 1; - /* Also, implicitly give dllimport'd variables declared within - a function global scope, unless declared static. */ - if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) - TREE_PUBLIC (node) = 1; - } + { + if (DECL_INITIAL (node)) + { + error ("%Jvariable %qD definition is marked dllimport.", + node, node); + *no_add_attrs = true; + } + + /* `extern' needn't be specified with dllimport. + Specify `extern' now and hope for the best. Sigh. */ + DECL_EXTERNAL (node) = 1; + /* Also, implicitly give dllimport'd variables declared within + a function global scope, unless declared static. */ + if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) + TREE_PUBLIC (node) = 1; + } + + if (*no_add_attrs == false) + DECL_DLLIMPORT_P (node) = 1; } /* Report error if symbol is not accessible at global scope. */ @@ -3351,7 +3397,7 @@ handle_dll_attribute (tree * pnode, tree || TREE_CODE (node) == FUNCTION_DECL)) { error ("%Jexternal linkage required for symbol %qD because of " - "%qs attribute.", node, node, IDENTIFIER_POINTER (name)); + "%qs attribute.", node, node, IDENTIFIER_POINTER (name)); *no_add_attrs = true; } diff -r 9a4f61828020 gcc/tree.h --- a/gcc/tree.h Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/tree.h Thu Feb 15 20:01:54 2007 +0300 @@ -2375,9 +2375,8 @@ namespace llvm { class Value; } #define DECL_LANG_FLAG_6(NODE) (DECL_CHECK (NODE)->decl.lang_flag_6) #define DECL_LANG_FLAG_7(NODE) (DECL_CHECK (NODE)->decl.lang_flag_7) -/* Used to indicate that the pointer to this DECL cannot be treated as - an address constant. */ -#define DECL_NON_ADDR_CONST_P(NODE) (DECL_CHECK (NODE)->decl.non_addr_const_p) +/* Used to indicate that the DECL is a dllimport. */ +#define DECL_DLLIMPORT_P(NODE) (DECL_CHECK (NODE)->decl.dllimport_flag) /* Used in a FIELD_DECL to indicate that we cannot form the address of this component. */ @@ -2470,7 +2469,7 @@ struct tree_decl GTY(()) unsigned artificial_flag : 1; unsigned weak_flag : 1; - unsigned non_addr_const_p : 1; + unsigned dllimport_flag : 1; unsigned no_instrument_function_entry_exit : 1; unsigned comdat_flag : 1; unsigned malloc_flag : 1; diff -r 9a4f61828020 gcc/varasm.c --- a/gcc/varasm.c Tue Feb 13 11:41:51 2007 +0000 +++ b/gcc/varasm.c Thu Feb 15 23:48:37 2007 +0300 @@ -477,7 +477,7 @@ named_section (tree decl, const char *na { flags = get_named_section_flags (name); if ((flags & SECTION_OVERRIDE) == 0) - error ("%J%D causes a section type conflict", decl, decl); + error ("%J%D causes a section type conflict", decl, decl); } named_section_real (name, flags, decl); @@ -943,14 +943,14 @@ make_decl_rtl (tree decl) reg_number = decode_reg_name (name); /* First detect errors in declaring global registers. */ if (reg_number == -1) - error ("%Jregister name not specified for %qD", decl, decl); + error ("%Jregister name not specified for %qD", decl, decl); else if (reg_number < 0) - error ("%Jinvalid register name for %qD", decl, decl); + error ("%Jinvalid register name for %qD", decl, decl); else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode) - error ("%Jdata type of %qD isn%'t suitable for a register", + error ("%Jdata type of %qD isn%'t suitable for a register", decl, decl); else if (! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl)))) - error ("%Jregister specified for %qD isn%'t suitable for data type", + error ("%Jregister specified for %qD isn%'t suitable for data type", decl, decl); /* Now handle properly declared static register variables. */ else @@ -3705,7 +3705,7 @@ initializer_constant_valid_p (tree value if (value && TREE_CODE (value) == FUNCTION_DECL && ((decl_function_context (value) && !DECL_NO_STATIC_CHAIN (value)) - || DECL_NON_ADDR_CONST_P (value))) + || DECL_DLLIMPORT_P (value))) return NULL_TREE; return value;
/* Target support for C++ classes on Windows. Contributed by Danny Smith ([EMAIL PROTECTED]) Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #include "system.h" #include "coretypes.h" #include "tm.h" #include "rtl.h" #include "regs.h" #include "hard-reg-set.h" #include "output.h" #include "tree.h" #include "cp/cp-tree.h" /* this is why we're a separate module */ #include "flags.h" #include "tm_p.h" #include "toplev.h" #include "hashtab.h" bool i386_pe_type_dllimport_p (tree decl) { gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL); if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL) return false; /* We ignore the dllimport attribute for inline member functions. This differs from MSVC behavior which treats it like GNUC 'extern inline' extension. Also ignore for template instantiations with linkonce semantics and artificial methods. */ if (TREE_CODE (decl) == FUNCTION_DECL && (DECL_DECLARED_INLINE_P (decl) || DECL_TEMPLATE_INSTANTIATION (decl) || DECL_ARTIFICIAL (decl))) return false; /* Since we can't treat a pointer to a dllimport'd symbol as a constant address, we turn off the attribute on C++ virtual methods to allow creation of vtables using thunks. */ else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE && DECL_VIRTUAL_P (decl)) { /* Even though we ignore the attribute from the start, warn if we later see an out-of class definition, as we do for other member functions in tree.c:merge_dllimport_decl_attributes. If this is the key method, the definition may affect the import-export status of vtables, depending on how we handle MULTIPLE_SYMBOL_SPACES in cp/decl2.c. */ if (DECL_INITIAL (decl)) { warning ("%q+D redeclared without dllimport attribute: " "previous dllimport ignored", decl); #ifdef PE_DLL_DEBUG if (decl == CLASSTYPE_KEY_METHOD (DECL_CONTEXT (decl))) warning ("key method %q+D of dllimport'd class defined" decl); #endif } return false; } /* Don't mark defined functions as dllimport. This code will only be reached if we see a non-inline function defined out-of-class. */ else if (TREE_CODE (decl) == FUNCTION_DECL && (DECL_INITIAL (decl))) return false; /* Don't allow definitions of static data members in dllimport class, If vtable data is marked as DECL_EXTERNAL, import it; otherwise just ignore the class attribute. */ else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl) && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl)) { if (!DECL_VIRTUAL_P (decl)) error ("definition of static data member %q+D of " "dllimport'd class", decl); return false; } return true; } bool i386_pe_type_dllexport_p (tree decl) { gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL); /* Avoid exporting compiler-generated default dtors and copy ctors. The only artificial methods that need to be exported are virtual and non-virtual thunks. */ if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl)) return false; return true; } static inline void maybe_add_dllimport (tree decl) { if (i386_pe_type_dllimport_p (decl)) DECL_DLLIMPORT_P (decl) = 1; } void i386_pe_adjust_class_at_definition (tree t) { tree member; gcc_assert (CLASS_TYPE_P (t)); /* We only look at dllimport. The only thing that dllexport does is add stuff to a '.drectiv' section at end-of-file, so no need to do anything for dllexport'd classes until we generate RTL. */ if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) == NULL_TREE) return; /* We don't actually add the attribute to the decl, just set the flag that signals that the address of this symbol is not a compile-time constant. Any subsequent out-of-class declaration of members wil cause the DECL_DLLIMPORT_P flag to be unset. (See tree.c: merge_dllimport_decl_attributes). That is just right since out-of class declarations can only be a definition. We recheck the class members at RTL generation to emit warnings if this has happened. Definition of static data member of dllimport'd class always causes an error (as per MS compiler). */ /* Check static VAR_DECL's. */ for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) if (TREE_CODE (member) == VAR_DECL) maybe_add_dllimport (member); /* Check FUNCTION_DECL's. */ for (member = TYPE_METHODS (t); member; member = TREE_CHAIN (member)) if (TREE_CODE (member) == FUNCTION_DECL) maybe_add_dllimport (member); /* Check vtables */ for (member = CLASSTYPE_VTABLES (t); member; member = TREE_CHAIN (member)) if (TREE_CODE (member) == VAR_DECL) maybe_add_dllimport (member); /* We leave typeinfo tables alone. We can't mark TI objects as dllimport, since the address of a secondary VTT may be needed for static initialization of a primary VTT. VTT's of dllimport'd classes should always be link-once COMDAT. */ }
/* Dummy subroutines for language-specific support on Windows. Contributed by Danny Smith ([EMAIL PROTECTED]) Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" #include "coretypes.h" #include "tm.h" #include "rtl.h" #include "regs.h" #include "hard-reg-set.h" #include "output.h" #include "tree.h" #include "flags.h" #include "tm_p.h" #include "toplev.h" #include "hashtab.h" bool i386_pe_type_dllimport_p (tree decl ATTRIBUTE_UNUSED) { return false; } bool i386_pe_type_dllexport_p (tree decl ATTRIBUTE_UNUSED) { return false; } void i386_pe_adjust_class_at_definition (tree t ATTRIBUTE_UNUSED) { }
_______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits