Hi,
In Windows 7,
gcc:
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=C:/Program\ Files\ (x86)/mingw-w64/i686-4.8.2-win32-dwarf-rt
_v3-rev4/mingw32/bin/../libexec/gcc/i686-w64-mingw32/4.8.2/lto-wrapper.exe
Target: i686-w64-mingw32
Configured with: ../../../src/gcc-4.8.2/configure --host=i686-w64-mingw32 --buil
d=i686-w64-mingw32 --target=i686-w64-mingw32 --prefix=/mingw32 --with-sysroot=/c
/mingw482/i686-482-win32-dwarf-rt_v3-rev4/mingw32 --with-gxx-include-dir=/mingw3
2/i686-w64-mingw32/include/c++ --enable-shared --enable-static --disable-multili
b --enable-languages=ada,c,c++,fortran,objc,obj-c++,lto --enable-libstdcxx-time=
yes --enable-threads=win32 --enable-libgomp --enable-libatomic --enable-lto --en
able-graphite --enable-checking=release --enable-fully-dynamic-string --enable-v
ersion-specific-runtime-libs --disable-sjlj-exceptions --with-dwarf2 --disable-i
sl-version-check --disable-cloog-version-check --disable-libstdcxx-pch --disable
-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --d
isable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with
-arch=i686 --with-tune=generic --with-libiconv --with-system-zlib --with-gmp=/c/
mingw482/prerequisites/i686-w64-mingw32-static --with-mpfr=/c/mingw482/prerequis
ites/i686-w64-mingw32-static --with-mpc=/c/mingw482/prerequisites/i686-w64-mingw
32-static --with-isl=/c/mingw482/prerequisites/i686-w64-mingw32-static --with-cl
oog=/c/mingw482/prerequisites/i686-w64-mingw32-static --enable-cloog-backend=isl
--with-pkgversion='i686-win32-dwarf-rev4, Built by MinGW-W64 project' --with-bu
gurl=http://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -I/c/mingw482/i
686-482-win32-dwarf-rt_v3-rev4/mingw32/opt/include -I/c/mingw482/prerequisites/i
686-zlib-static/include -I/c/mingw482/prerequisites/i686-w64-mingw32-static/incl
ude' CXXFLAGS='-O2 -pipe -I/c/mingw482/i686-482-win32-dwarf-rt_v3-rev4/mingw32/o
pt/include -I/c/mingw482/prerequisites/i686-zlib-static/include -I/c/mingw482/pr
erequisites/i686-w64-mingw32-static/include' CPPFLAGS= LDFLAGS='-pipe -L/c/mingw
482/i686-482-win32-dwarf-rt_v3-rev4/mingw32/opt/lib -L/c/mingw482/prerequisites/
i686-zlib-static/lib -L/c/mingw482/prerequisites/i686-w64-mingw32-static/lib -Wl
,--large-address-aware'
Thread model: win32
gcc version 4.8.2 (i686-win32-dwarf-rev4, Built by MinGW-W64 project)
GNU ld (GNU Binutils) 2.24
mingw32.
Having this example code:
#include <Windows.h>
class Test
{
__attribute__((cdecl)) void functioncdecl();
void functionno();
int i;
};
void Test::functioncdecl()
{
i++;
}
void Test::functionno()
{
i++;
};
compiling with:
g++ -S pruebacdecl.cpp
I can see the assembler generated for functioncdecl, that is not following the cdecl attribute:
__ZN4Test13functioncdeclEv:
LFB473:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $4, %esp
movl %ecx, -4(%ebp)
movl -4(%ebp), %eax
movl (%eax), %eax
leal 1(%eax), %edx
movl -4(%ebp), %eax
movl %edx, (%eax)
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE473:
.align 2
.globl __ZN4Test10functionnoEv
.def __ZN4Test10functionnoEv; .scl 2; .type 32; .endef
__ZN4Test10functionnoEv:
LFB474:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $4, %esp
movl %ecx, -4(%ebp)
movl -4(%ebp), %eax
movl (%eax), %eax
leal 1(%eax), %edx
movl -4(%ebp), %eax
movl %edx, (%eax)
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
As we can see both functions remains the same,
But, if I comment the #include <windows.h> line, The output assembly is correct:</windows.h>
__ZN4Test13functioncdeclEv:
LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 8(%ebp), %eax
movl (%eax), %eax
leal 1(%eax), %edx
movl 8(%ebp), %eax
movl %edx, (%eax)
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
(Note that now follows the cdecl attribute)
So, it is ignoring the cdecl attribute, just by including Windows.h, and no warning is emitted.
Diff:
Sigh ... I do wish posters would use appropriate mark-up, when filing bug reports, (and use the "preview" facility, to see what a mess they are creating, otherwise).
Well, we don't support the foul-ups created by that renegade project. However, since this seems to be related to [#2256], I guess this could stand further scrutiny.
So, maybe an issue in
<windows.h>, which may be common to both projects. Curiously, for both GCC-3.4.5, and GCC-4.8.2, I see:so clearly, both versions of the compiler provide built-in, (and entirely correct and consistent), definitions for both
_cdecland__cdecl; it would seem that<windows.h>may be interfering with the_cdeclvariant.Related
Issues:
#2256Sorry, but I cannot reproduce this ... neither with my own self-built mingw32-g++ Linux hosted cross-compiler, nor with MinGW.org's g++-4.7.2 release running on Win7 Home Premium in VirtualBox. (In both cases, the MinGW headers are the current mingwrt-3.21.1 and w32api-3.17).
Since you didn't provide a downloadable copy, and I've had trouble simply copying and pasting from the browser in the past, I chose to retype the following adaptation of your test case:
Compiling with:
and subsequently comparing the two generated assembly code variants shows no effective difference whatsoever:
(sure, some local labels differ, but that isn't an effective difference).
The generated assembly code, effectively the same in both cases, is:
which seems to match what you say to be correct for
cdecl, in both cases.FWIW, I'm by no means a C++ expert ... I don't know what effect
cdeclshould be expected to produce here. I do know the distinction betweencdeclandstdcallinsofar as the latter requires the called function to pop the argument frame from the stack on return, whereas the former leaves that responsibility with the caller, but this example doesn't exercise that feature anyway, (since there are no arguments passed to either function). Why shouldcdeclbe required to produce different code, beyond satisfying this distinction, for functions which are otherwise identical?Hi, the difference I was looking is that for cdecl the 'this' pointer is passed in the stack:
and the stdcall pass 'this' pointer through the ecx register:
Sorry for the mark-up. I will try to reproduce this, and if i don't see this here i will try to submit this to MinGW-W64 project(sorry for this also, i didn't know they were separate projects)
Greetings.
Yes, I'd kind of figured that out, mostly by examining the (simpler) code generated when the
-O2compiler option is also given:vs. the corresponding code, with
__attribute__((fastcall))substituted in place of__attribute__((cdecl)):No,
stdcallwould also pass thethispointer on the stack; what we're seeing here is a compiler default choice which is equivalent to thefastcallprotocol:Many people are confused by this. Blame the mingw-w64 renegades, who persistently infringe the registered trade mark of MinGW.org, and who fail to make it clear that they are, in no way, associated with us.
Since I am unable to reproduce your issue, with any compiler which MinGW.org supports, I am closing this ticket. I'm not prepared to support a rogue fork from our code base.
Thanks, I already tried the same in a recent mingw I downloaded and couldn't see the problem.
Just to complete the picture:
Here's the compiler output I see, compiling with
-O2, and substituting__attribute__((stdcall))in place of__attribute__((cdecl)):Notice that, just like the
cdeclvariant, thethispointer is passed on the stack. The differences are that the function name is decorated by an additional@4suffix, indicating that the caller will provide a four byte stack frame to pass thethispointer, and that theret $4does indeed pop these four bytes from the stack, in addition to the return address, when this function returns, as is required by thestdcallprotocol.