Bug 34749

Summary: Incorrect warning when applying dllimport to friend function
Product: gcc Reporter: Stephen Lee <sldev327>
Component: c++Assignee: Danny Smith <dannysmith>
Status: RESOLVED FIXED    
Severity: normal CC: bangerth, gcc-bugs, ktietz, vhaisman
Priority: P3    
Version: 4.2.1   
Target Milestone: ---   
Host: Target:
Build: Known to work: 3.4.5
Known to fail: 4.2.0, 4.3.0 Last reconfirmed: 2008-01-13 08:32:51

Description Stephen Lee 2008-01-12 14:15:27 UTC
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)
Comment 1 Wolfgang Bangerth 2008-01-13 02:12:42 UTC
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.
Comment 2 Stephen Lee 2008-01-13 05:52:02 UTC
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
Comment 3 Danny Smith 2008-01-13 06:50:41 UTC
(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.
Comment 4 Danny Smith 2008-01-13 08:32:51 UTC
Testing a patch.
Comment 5 Danny Smith 2008-01-19 08:33:43 UTC
(In reply to comment #4)
> Testing a patch.
> 

Here it is:
http://gcc.gnu.org/ml/gcc-patches/2008-01/msg00881.html
Comment 6 dannysmith@gcc.gnu.org 2008-02-24 09:20:25 UTC
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

Comment 7 Danny Smith 2008-09-26 03:15:31 UTC
*** Bug 37652 has been marked as a duplicate of this bug. ***
Comment 8 R. Konstantin 2009-01-11 12:08:13 UTC
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?
Comment 9 Danny Smith 2009-01-12 02:07:02 UTC
(In reply to comment #8)
> still unfixed?

Please provide a compilable self-contained testcase. 
Danny
Comment 10 R. Konstantin 2009-01-13 08:12:42 UTC
(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.
Comment 11 Kai Tietz 2010-12-03 12:23:00 UTC
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.