Bug 5815 – Using -O is causing wrong code to be generated for extern(C) method call.

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2011-04-06T10:55:00Z
Last change time
2015-06-09T01:31:14Z
Assigned to
nobody
Creator
opantm+spam

Comments

Comment #0 by opantm+spam — 2011-04-06T10:55:30Z
When attempting to call a Windows API function, PathRemoveFileSpecA, invalid results are returned when using the -O compiler flag. When using the same file, but without -O, the correct output is generated. Test Case: import std.stdio; import std.c.windows.windows; static const ushort MAX_PATH = 260; extern(C) BOOL PathRemoveFileSpecA(LPTSTR); static void TrimToNull(ref char[] String) { for(int i = 0; i < String.length; i++) if(String[i] == '\0') { String = String[0..i]; return; } } static char[] GetDirectoryPath(string FilePath) { char[] Copy = FilePath.dup; uint Result = PathRemoveFileSpecA(Copy.ptr); TrimToNull(Copy); return Copy; } int main(string[] args) { string Path = "D:\\Test Path\\Test.exe"; auto Dir = GetDirectoryPath(Path); writefln("Dir: " ~ Dir); return 0; } Output without -O: "Dir: D:\Test Path" Output with -O: "object.Error: Access Violation" For this particular example, shlwapi.lib must be generated with Implib.exe and linked. The version of DMD being used is 2.052. OS is Windows, and compiled with: "dmd testfile.d shlwapi.lib (-O)".
Comment #1 by bugzilla — 2011-04-06T13:11:33Z
x86_64 (i.e. 64 bit code) is not currently supported by DMD on Windows. Changing to x86.
Comment #2 by r.sagitario — 2011-04-06T14:09:38Z
> extern(C) BOOL PathRemoveFileSpecA(LPTSTR); You are probably using the wrong calling convention here, it should be "extern(Windows)", which corresponds to __stdcall in while "extern(C)" is __cdecl in the SDK C++ headers.
Comment #3 by opantm+spam — 2011-04-08T19:29:19Z
(In reply to comment #1) > x86_64 (i.e. 64 bit code) is not currently supported by DMD on Windows. > Changing to x86. Sorry, I did mean x86. (In reply to comment #2) > > extern(C) BOOL PathRemoveFileSpecA(LPTSTR); > > You are probably using the wrong calling convention here, it should be > "extern(Windows)", which corresponds to __stdcall in while "extern(C)" is > __cdecl in the SDK C++ headers. As far as I can tell, the calling convention is C. According to MSDN, the header is "BOOL PathRemoveFileSpec(__inout LPTSTR pszPath)". As a comparison, GetCurrentDirectory (which uses extern(Windows)) is "DWORD WINAPI GetCurrentDirectory(__in DWORD nBufferLength, __out LPTSTR lpBuffer)". When using extern(Windows), it fails to compile due to an undefined symbol error.
Comment #4 by r.sagitario — 2011-04-08T23:22:01Z
If you look it up in shlwapi.h in the SDK, it is declared as LWSTDAPI_(BOOL) PathRemoveFileSpecA(__inout LPSTR pszPath); and LWSTDAPI_(BOOL) expands to 'extern "C" __declspec(dllimport) BOOL __stdcall'. __stdcall translates to D as extern(Windows). I have tried your code, and I get a link error with "extern(C)". I have used coff2implib to convert the library from the sdk, because I have had problems with implib on DLLs in the past, it especially misses a number of symbols. With "extern(Windows)", I can link and run your code without problems.
Comment #5 by r.sagitario — 2011-04-08T23:23:56Z
> I have used coff2implib sorry, it is called coffimplib and available from the digitalmars ftp area.
Comment #6 by opantm+spam — 2011-04-09T10:27:41Z
(In reply to comment #4) > If you look it up in shlwapi.h in the SDK, it is declared as > > LWSTDAPI_(BOOL) PathRemoveFileSpecA(__inout LPSTR pszPath); > > and LWSTDAPI_(BOOL) expands to 'extern "C" __declspec(dllimport) BOOL > __stdcall'. > __stdcall translates to D as extern(Windows). > > I have tried your code, and I get a link error with "extern(C)". I have used > coff2implib to convert the library from the sdk, because I have had problems > with implib on DLLs in the past, it especially misses a number of symbols. > > With "extern(Windows)", I can link and run your code without problems. Awesome. After getting coffimplib and converting with it instead as well as changing to extern(Windows), it works both with and without -O. :) Thanks for the help. I guess this bug report is invalid.