I was playing with some code and got a warning about dllimport in some headers. I looked around a bit and came up with this test case. The warning seems to imply that dllimport is ignored on bar(), but looking at the output the call to bar() is indeed mangled with __imp prefix. I'm using MinGW g++ 4.2.1-dw2. ## begin df.cpp __attribute__((dllimport)) int bar(); class Foo { private: int foo(); friend __attribute__((dllimport)) int bar(); }; int Foo::foo() { return bar(); } ## end df.cpp D:> g++ -S df.cpp df.cpp:7: warning: 'int bar()' redeclared without dllimport attribute: previous dllimport ignored D:> g++ -v Using built-in specs. Target: mingw32 Configured with: ../gcc-4.2.1-2-src/configure --with-gcc --enable-libgomp --host =mingw32 --build=mingw32 --target=mingw32 --program-suffix=-dw2 --with-arch=i486 --with-tune=generic --disable-werror --prefix=/mingw --with-local-prefix=/mingw --enable-threads --disable-nls --enable-languages=c,c+ +,fortran,objc,obj-c++,ad a --disable-win32-registry --disable-sjlj-exceptions --enable-libstdcxx-debug -- enable-cxx-flags=-fno-function-sections -fno-data-sections --enable-version-spec ific-runtime-libs --disable-bootstrap Thread model: win32 gcc version 4.2.1-dw2 (mingw32-2)
One could make the argument that the dllimport specifier is a storage-class-specifier which, per 11.4/6 is not allowed on the friend declaration. Since a friend function declaration needs to be preceded by a declaration of the function itself, it will always be sufficient if the dllimport specifier is only on the original function declaration. I therefore think that the PR is invalid, but leave the final decision to someone with more knowledge. W.
I as well will leave the argument about syntax to more knowledgeable people. As to the validity of this PR, at the very least g++'s behavior is inconsistent. I suppose a case like df3.cpp is what the warning was intended for. g++ warns about __attribute__((dllimport)) not being there on line 7 of df.cpp (when in truth it is), and then goes on to honor it anyway as you can see comparing the output df.s and df3.s. ## begin df3.cpp __attribute__((dllimport)) int bar(); class Foo { private: int foo(); friend int bar(); // dllimport removed }; int Foo::foo() { return bar(); } # end df3.cpp D:> g++ -S df3.cpp df3.cpp:7: warning: 'int bar()' redeclared without dllimport attribute: previous dllimport ignored D:> diff -u df.s df3.s --- df.s Sun Jan 13 14:02:58 2008 +++ df3.s Sun Jan 13 14:04:51 2008 @@ -1,4 +1,4 @@ - .file "df.cpp" + .file "df3.cpp" .text .align 2 .globl __ZN3Foo3fooEv @@ -11,8 +11,7 @@ LCFI1: subl $8, %esp LCFI2: - movl __imp___Z3barv, %eax - call *%eax + call __Z3barv leave ret LFE2: @@ -55,3 +54,4 @@ .uleb128 0x5 .align 4 LEFDE1: + .def __Z3barv; .scl 2; .type 32; .endef
(In reply to comment #1) > One could make the argument that the dllimport specifier is > a storage-class-specifier which, per 11.4/6 is not allowed on > the friend declaration. Since a friend function declaration > needs to be preceded by a declaration of the function itself, > it will always be sufficient if the dllimport specifier is only > on the original function declaration. > MS semantics for dllimport for ordinary file scope functions, is that if a declaration with dllimport attribute is followed by a decl without, the prior dllimport is overriden. Hence, the warning that Stephen shows for df3.cc in comment #3 may make some sense, but I do not have a MS compiler handy to see what MS says for the friend case. The warning does not make sense, if the dllimport attribute is actually honoured (as it should be) in original testcase.
Testing a patch.
(In reply to comment #4) > Testing a patch. > Here it is: http://gcc.gnu.org/ml/gcc-patches/2008-01/msg00881.html
Subject: Bug 34749 Author: dannysmith Date: Sun Feb 24 09:19:39 2008 New Revision: 132585 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=132585 Log: cp PR c++/34749 * friend.c (do_friend): Call cplus_decl_attributes earlier. testsuite PR c++/34749 * g++.dg.ext/dllimport13.C: New test. Added: trunk/gcc/testsuite/g++.dg/ext/dllimport13.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/friend.c trunk/gcc/testsuite/ChangeLog
*** Bug 37652 has been marked as a duplicate of this bug. ***
class __declspec(dllimport) QBitArray { //... friend __declspec(dllimport) QDataStream &operator<<(QDataStream &, const QBitArray &); friend __declspec(dllimport) QDataStream &operator>>(QDataStream &, QBitArray &); //... }; //... __declspec(dllimport) QDataStream &operator<<(QDataStream &, const QBitArray &); __declspec(dllimport) QDataStream &operator>>(QDataStream &, QBitArray &); got ..\..\include/QtCore/../../src/corelib/tools/qbitarray.h:55: warning: 'QDataStream &operator<<(QDataStream &, const QBitArray &)' redeclared without dllimport attribute: previous dllimport ignored ..\..\include/QtCore/../../src/corelib/tools/qbitarray.h:56: warning: 'QDataStream &operator>>(QDataStream &, QBitArray &)' redeclared without dllimport attribute: previous dllimport ignored mingw, gcc 4.3.2(dw2) still unfixed?
(In reply to comment #8) > still unfixed? Please provide a compilable self-contained testcase. Danny
(In reply to comment #9) > (In reply to comment #8) > > still unfixed? > > Please provide a compilable self-contained testcase. > Danny > Here is compilable testcase: ## begin df.cpp __attribute__((dllimport)) int bar(); class Foo { private: int foo(); friend __attribute__((dllimport)) int bar(); }; int Foo::foo() { return bar(); } ## end df.cpp > g++ -S df.cpp I don't see that patch in 4.3.2 or in the 4.3 branch. This is fixed in mainline, so it'll appear in 4.4, I guess.
The reported issue was fixed for 4.4.x and there are no plans for backporting this fix to 4.3.x branch. I'll close this bug. I admit that we could think about to allow for prototypes only, that a dllimport attribute remains for following non-dllimport marked prototypes. On the other hand, it seems to be an extension.