Index: config/i386/winnt.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/i386/winnt.c,v retrieving revision 1.47 diff -c -3 -p -r1.47 winnt.c *** config/i386/winnt.c 21 May 2003 00:33:26 -0000 1.47 --- config/i386/winnt.c 29 May 2003 22:16:34 -0000 *************** void i386_pe_mark_dllimport PARAMS ((tre *** 66,81 **** /* Handle a "dllimport" or "dllexport" attribute; arguments as in struct attribute_spec.handler. */ tree ! ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs) ! tree *node; tree name; tree args; int flags; bool *no_add_attrs; { /* These attributes may apply to structure and union types being created, but otherwise should pass to the declaration involved. */ ! if (!DECL_P (*node)) { if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT | (int) ATTR_FLAG_ARRAY_NEXT)) --- 66,83 ---- /* Handle a "dllimport" or "dllexport" attribute; arguments as in struct attribute_spec.handler. */ tree ! ix86_handle_dll_attribute (pnode, name, args, flags, no_add_attrs) ! tree * pnode; tree name; tree args; int flags; bool *no_add_attrs; { + tree node = *pnode; + /* These attributes may apply to structure and union types being created, but otherwise should pass to the declaration involved. */ ! if (!DECL_P (node)) { if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT | (int) ATTR_FLAG_ARRAY_NEXT)) *************** ix86_handle_dll_attribute (node, name, a *** 83,102 **** *no_add_attrs = true; return tree_cons (name, args, NULL_TREE); } ! if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE) { warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } } ! /* `extern' needn't be specified with dllimport. ! Specify `extern' now and hope for the best. Sigh. */ ! else if (TREE_CODE (*node) == VAR_DECL ! && is_attribute_p ("dllimport", name)) { ! DECL_EXTERNAL (*node) = 1; ! TREE_PUBLIC (*node) = 1; } return NULL_TREE; --- 85,141 ---- *no_add_attrs = true; return tree_cons (name, args, NULL_TREE); } ! if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) { warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); *no_add_attrs = true; + return NULL_TREE; + } + } + + /* Throw errpor on dllimport ambiguities seen now before they cause any damage. */ + else if (is_attribute_p ("dllimport", name)) + { + /* 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, but just ignore it in i386_pe_dllimport_p. */ + if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node) + && !DECL_INLINE (node)) + { + error ("%Hfunction `%D' definition is marked dllimport.", + &DECL_SOURCE_LOCATION (node), node); + *no_add_attrs = true; + } + + else if (TREE_CODE (node) == VAR_DECL) + { + if (DECL_INITIAL (node)) + { + error ("%Hvariable `%D' definition is marked dllimport.", + &DECL_SOURCE_LOCATION (node), node); + *no_add_attrs = true; + } + + /* `extern' needn't be specified with dllimport. Specify + `extern' now and hope for the best. Be careful that we don't + set TREE_PUBLIC for variables declared static (class static + data is already public) so we can catch syntax ambiguity + below. */ + if (!TREE_STATIC (node)) + TREE_PUBLIC (node) = 1; + DECL_EXTERNAL (node) = 1; } } ! /* Throw error if symbol is not accessible at global scope. */ ! if (!TREE_PUBLIC (node) ! && (TREE_CODE (node) == VAR_DECL ! || TREE_CODE (node) == FUNCTION_DECL)) { ! error ("%Hexternal linkage required for symbol '%D' because of '%s' attribute.", ! &DECL_SOURCE_LOCATION (node), node,IDENTIFIER_POINTER (name)); ! *no_add_attrs = true; } return NULL_TREE; *************** i386_pe_dllimport_p (decl) *** 181,187 **** tree decl; { tree imp; ! if (TREE_CODE (decl) == FUNCTION_DECL && TARGET_NOP_FUN_DLLIMPORT) return 0; --- 220,227 ---- tree decl; { tree imp; ! int context_imp = 0; ! if (TREE_CODE (decl) == FUNCTION_DECL && TARGET_NOP_FUN_DLLIMPORT) return 0; *************** i386_pe_dllimport_p (decl) *** 189,205 **** if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return 0; imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); - if (imp) - return 1; /* Class members get the dllimport status of their class. */ ! if (associated_type (decl)) { imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (associated_type (decl))); if (imp) ! return 1; } return 0; --- 229,312 ---- 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, then an error is raised. This ! handles the case when the definition overrides an earlier ! declaration. */ ! if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) ! && !DECL_INLINE (decl)) ! { ! warning ("%Hdefinition of '%D' previously marked as dllimport: attribute ignored", ! &DECL_SOURCE_LOCATION (decl), decl); ! return 0; ! } ! ! /* We ignore the dllimport attribute for inlined functions ! This differs from MSVC behaviour which treats it like GNUC ! 'extern inline' extension. */ ! else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl)) ! { ! if (extra_warnings) ! warning ("%Hinline function '%D' marked as dllimport: attribute ignored.", ! &DECL_SOURCE_LOCATION (decl), decl); ! return 0; ! } ! ! /* Turn off importing C++ virtual methods to able to create ! vtables using thunks. */ ! else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE ! && DECL_VIRTUAL_P (decl)) ! { ! return 0; ! } ! ! /* Class static data members */ ! else if (TREE_CODE (decl) == VAR_DECL ! && TREE_STATIC (decl) && TREE_PUBLIC (decl) ! && context_imp) ! { ! if (DECL_VIRTUAL_P (decl)) ! { ! /* Mark vtable symbol with _imp_, only if we ! know it is defined externally. */ ! if (!DECL_EXTERNAL (decl)) ! return 0; ! } ! ! /* Don't allow definition of static data members. */ ! else if (!DECL_EXTERNAL (decl)) ! { ! error ("%Hdefinition of static data member '%D' of dllimport'd class.", ! &DECL_SOURCE_LOCATION (decl), decl); ! return 0; ! } ! ! /* Should in-class initialization of static consts raise an ! error too, or just ignore the attribute, as here? */ ! else if (DECL_INITIAL (decl) ! && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) ! { ! warning ("%Hin-class initialization of '%D': dllimport attribute ignored.", ! &DECL_SOURCE_LOCATION (decl), decl); ! return 0; ! } ! } ! ! return 1; } return 0; *************** i386_pe_mark_dllexport (decl) *** 246,253 **** else abort (); if (i386_pe_dllimport_name_p (oldname)) ! /* Remove DLL_IMPORT_PREFIX. */ ! oldname += strlen (DLL_IMPORT_PREFIX); else if (i386_pe_dllexport_name_p (oldname)) return; /* already done */ --- 353,365 ---- else abort (); if (i386_pe_dllimport_name_p (oldname)) ! { ! warning ("%Hinconsistent dll linkage for '%D, dllexport assumed.", ! &DECL_SOURCE_LOCATION (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 */ *************** i386_pe_mark_dllimport (decl) *** 291,331 **** } else if (i386_pe_dllimport_name_p (oldname)) { ! /* Already done, but force correct linkage since the redeclaration ! might have omitted explicit extern. Sigh. */ ! if (TREE_CODE (decl) == VAR_DECL ! /* ??? Is this test for vtables needed? */ ! && !DECL_VIRTUAL_P (decl)) { ! DECL_EXTERNAL (decl) = 1; ! TREE_PUBLIC (decl) = 1; } return; } - /* ??? One can well ask why we're making these checks here, - and that would be a good question. */ - - /* Imported variables can't be initialized. Note that C++ classes - are marked initial, so we need to check. */ - if (TREE_CODE (decl) == VAR_DECL - && !DECL_VIRTUAL_P (decl) - && (DECL_INITIAL (decl) - && ! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))) - { - error_with_decl (decl, "initialized variable `%s' is marked dllimport"); - return; - } - /* Nor can they be static. */ - if (TREE_CODE (decl) == VAR_DECL - /* ??? Is this test for vtables needed? */ - && !DECL_VIRTUAL_P (decl) - && 0 /*???*/) - { - error_with_decl (decl, "static variable `%s' is marked dllimport"); - return; - } - newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1); sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname); --- 403,418 ---- } 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 ("%Hfailure in redeclaration of '%D': dllimport'd symbol lacks external linkage.", ! &DECL_SOURCE_LOCATION (decl), decl); ! abort(); } return; } newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1); sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname); *************** i386_pe_encode_section_info (decl, rtl, *** 443,449 **** /* 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. */ if (i386_pe_dllexport_p (decl)) i386_pe_mark_dllexport (decl); --- 530,536 ---- /* 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. */ if (i386_pe_dllexport_p (decl)) i386_pe_mark_dllexport (decl); *************** i386_pe_encode_section_info (decl, rtl, *** 466,471 **** --- 553,564 ---- tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX)); rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); + warning ("%H%s of %s '%D', previously marked with '_imp_' dllimport prefix.", + &DECL_SOURCE_LOCATION (decl), + DECL_INITIAL (decl) ? "definition" : "redeclaration", + TREE_CODE (decl) == VAR_DECL ? "variable" : "function", + decl); + XEXP (DECL_RTL (decl), 0) = newrtl; DECL_NON_ADDR_CONST_P (decl) = 0; *************** void i386_pe_output_labelref (stream, na *** 519,526 **** { if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX)) == 0) ! /* A dll import */ ! { if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX) /* A dllimport fastcall symbol. */ { --- 612,619 ---- { if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX)) == 0) ! /* A dll import */ ! { if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX) /* A dllimport fastcall symbol. */ { *************** i386_pe_asm_file_end (file) *** 796,799 **** } } } - --- 889,891 ---- Index: testsuite/g++.dg/ext/dllimport1.C =================================================================== RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/ext/dllimport1.C,v retrieving revision 1.1 diff -c -3 -p -r1.1 dllimport1.C *** testsuite/g++.dg/ext/dllimport1.C 12 Apr 2003 20:01:29 -0000 1.1 --- testsuite/g++.dg/ext/dllimport1.C 29 May 2003 22:16:34 -0000 *************** *** 1,12 **** ! // { dg-do compile { target i?86-*-cygwin* } } class __attribute__((dllimport)) Foo { public: virtual void dummy_foo_func(void) ! {} }; class Bar : public Foo { public: --- 1,20 ---- ! // PR c++/7910 ! // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } ! // { dg-options { -Wall -W } } class __attribute__((dllimport)) Foo { public: virtual void dummy_foo_func(void) ! {} // { dg-warning "inline function" } ! virtual void dummy_foo_fun2(void); ! virtual ~Foo(); // avoid warning }; + void Foo::dummy_foo_fun2() + { // { dg-warning "definition" } + } + class Bar : public Foo { public: *************** Bar::~Bar() *** 19,21 **** --- 27,31 ---- void Bar::dummy_bar_func() {} + + // { dg-final { scan-assembler-not "__imp___ZN3Foo14dummy_foo_fun" } } Index: testsuite/g++.dg/ext/dllimport2.C =================================================================== RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/ext/dllimport2.C,v retrieving revision 1.1 diff -c -3 -p -r1.1 dllimport2.C *** testsuite/g++.dg/ext/dllimport2.C 21 May 2003 00:33:27 -0000 1.1 --- testsuite/g++.dg/ext/dllimport2.C 29 May 2003 22:16:34 -0000 *************** *** 1,15 **** // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } ! // PR 9738 Dllimport attribute is overriden by later definition void __attribute__((dllimport)) Bar(void); ! void Foo(void) ! { ! Bar(); ! } ! void Bar(void) ! { ! } --- 1,15 ---- // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } ! // PR c++/9738 Dllimport attribute is overriden by later definition void __attribute__((dllimport)) Bar(void); ! void Foo(void) ! { ! Bar(); ! } ! void Bar(void) ! { // { dg-warning "definition" } ! } Index: testsuite/g++.dg/ext/dllimport3.C =================================================================== RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/ext/dllimport3.C,v retrieving revision 1.1 diff -c -3 -p -r1.1 dllimport3.C *** testsuite/g++.dg/ext/dllimport3.C 21 May 2003 00:33:27 -0000 1.1 --- testsuite/g++.dg/ext/dllimport3.C 29 May 2003 22:16:34 -0000 *************** struct Foo *** 15,21 **** void* dummy = &f; } ! struct Foo f; // Dllimport sets DECL_NON_ADDR_CONST_P to 1, so following // assignment would require static_initialization_and_destruction --- 15,21 ---- void* dummy = &f; } ! struct Foo f; // { dg-warning "redeclaration" } // Dllimport sets DECL_NON_ADDR_CONST_P to 1, so following // assignment would require static_initialization_and_destruction *** /dev/null Fri May 30 01:30:45 2003 --- testsuite/g++.dg/ext/dllimport4.C Thu May 29 03:04:48 2003 *************** *** 0 **** --- 1,6 ---- + // Throw error if explicit dllimport attribute in definition itself. + // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } + + __attribute__((dllimport)) void bar () { } // { dg-error "definition" } + + __attribute__((dllimport)) int foo = 1; // { dg-error "definition" } *** /dev/null Fri May 30 01:30:56 2003 --- testsuite/g++.dg/ext/dllimport5.C Mon May 26 04:07:19 2003 *************** *** 0 **** --- 1,25 ---- + // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } + // Raise error if static symbol definition has dllimport attribute. + + + __attribute__((dllimport)) + static int static_impvar; // { dg-error "external linkage required" } + + __attribute__((dllexport)) + static int static_expvar; // { dg-error "external linkage required" } + + __attribute__((dllimport)) + static void static_impfun(void); // { dg-error "external linkage required" } + + void foo() + { + __attribute__((dllimport)) int foovar; // OK, implicit "extern" + foovar++; + } + + void bar() + { + __attribute__((dllexport)) int barvar; // { dg-error "external linkage required" } + barvar++; + } + *** /dev/null Fri May 30 01:31:03 2003 --- testsuite/g++.dg/ext/dllimport6.C Thu May 29 03:15:16 2003 *************** *** 0 **** --- 1,32 ---- + // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } + // Do mark class static members as dllimport. + // Don't mark in-class initialized static consts as dllimport. + + struct Baz + { + Baz(int a_ =0) : a(a_) {}; + int a; + }; + + class __attribute__ ((dllimport)) Bar + { + public: + enum {one = 1}; + static const int two = 2; // { dg-warning "in-class initialization" } + static const int three; // Do import. + static const Baz null_baz; // Do import. + }; + + int foo() + { + Bar foobar; + int a = foobar.two; + int b = foobar.three; + int c = foobar.null_baz.a; + return (a + b + c); + } + + // { dg-final { scan-assembler __imp___ZN3Bar8null_bazE } } + // { dg-final { scan-assembler-not __imp___ZN3Bar3twoE } } + // { dg-final { scan-assembler __imp___ZN3Bar5threeE } } + *** /dev/null Fri May 30 01:31:09 2003 --- testsuite/g++.dg/ext/dllimport7.C Tue May 27 10:11:40 2003 *************** *** 0 **** --- 1,30 ---- + // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } + + // Throw errors on definition of dllimport'd static data member . + + + struct Baz + { + Baz(int a_ =0) : a(a_) {}; + int a; + }; + + class __attribute__ ((dllimport)) Bar + { + public: + enum {one = 1}; + static const int two; + static const int three; + static const Baz null_baz; + }; + + const int Bar::three = 3; // { dg-error "definition of static data" } + const Baz Bar::null_baz; // { dg-error "definition of static data" } + + void foo() + { + Bar foobar; + int a = foobar.two; + int b = foobar.three; + int c = foobar.null_baz.a; + } *** /dev/null Fri May 30 01:31:14 2003 --- testsuite/g++.dg/ext/dllimport8.C Thu May 29 04:50:11 2003 *************** *** 0 **** --- 1,30 ---- + // PR c++/8378 + // Ignore dllimport of static members if marked inlined. + // or if definition follows declaration in dllimported class. + + // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } + // { dg-options { -Wall -W } } + + + struct __attribute__((dllimport)) Foo + { + static int static_int; + static void static_func1(); + static void static_func2(); + }; + + void Foo::static_func1() + { // { dg-warning "definition" } + } + + inline void Foo::static_func2() + { // { dg-warning "inline function" } + } + + void testfoo() + { + Foo::static_func1(); + Foo::static_func2(); + } + + // { dg-final { scan-assembler-not "__imp__" } } *** /dev/null Fri May 30 01:31:20 2003 --- testsuite/g++.dg/ext/dllimport9.C Thu May 29 10:47:04 2003 *************** *** 0 **** --- 1,30 ---- + // Handle dllimport attribute for functions declared inline. + // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } + // { dg-options -fkeep-inline-functions } + + __attribute__((dllimport)) inline void bar() { } + + __attribute__((dllimport)) void foo (); + inline void foo() { } + + struct __attribute__ ((dllimport)) Blah + { + void in_blah () { } + void out_blah (); + }; + + inline void Blah::out_blah(){ } + + __attribute__((dllimport)) void boo (); + void baz() { boo (); } + inline void boo() { foo (); } // { dg-warning "definition" } + + + // { dg-final { scan-assembler "_Z3barv" } } + // { dg-final { scan-assembler-not "__imp___Z3barv" } } + // { dg-final { scan-assembler "_Z3foov" } } + // { dg-final { scan-assembler-not "__imp___Z3foov" } } + // { dg-final { scan-assembler "_ZN4Blah8out_blahEv" } } + // { dg-final { scan-assembler-not "__imp___ZN4Blah8out_blahEv" } } + // { dg-final { scan-assembler "_ZN4Blah7in_blahEv" } } + // { dg-final { scan-assembler-not "__imp___ZN4Blah7in_blahEv" } } *** /dev/null Fri May 30 01:31:26 2003 --- testsuite/g++.dg/ext/dllimport10.C Thu May 29 04:50:39 2003 *************** *** 0 **** --- 1,21 ---- + // PR c++/11021 + // Inherit a virtual method from a dllimport'd base class + + // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } + + class __declspec(dllimport) Base_in_Dll { + public: + virtual void vfunc1(void) const; + virtual void vfunc2(void) const; + }; + + class Derived_in_App : public Base_in_Dll + { + public: + void vfunc1(void) const + { + } + // inherit vfunc2 + }; + + Derived_in_App appclass; *** /dev/null Fri May 30 01:31:35 2003 --- testsuite/g++.dg/ext/dllexport1.C Fri May 23 10:14:44 2003 *************** *** 0 **** --- 1,19 ---- + // Test that inline functions are exported with -fkeep-inline-functions. + // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} } + // { dg-options -fkeep-inline-functions } + + __attribute__((dllexport)) inline int foo(int a) { return a;} + + class __attribute__((dllexport)) Bar + { + public: + int inline_bar(int a) {return a;} + int outline_bar(int a); + }; + + int Bar::outline_bar(int a) {return a;} + + + // { dg-final { scan-assembler "\.section\[ \t\]*.drectve\n.*_ZN3Bar11outline_barEi" } } + // { dg-final { scan-assembler " -export:_ZN3Bar10inline_barEi" } } + // { dg-final { scan-assembler " -export:_Z3fooi" } }