-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[Support] Silence warnings when retrieving exported functions #97905
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… function Since functions exported from DLLs are type-erased, before this patch I was seeing the new Clang 19 warning `-Wcast-function-type-mismatch`. This happens when building LLVM on Windows.
@llvm/pr-subscribers-platform-windows @llvm/pr-subscribers-llvm-support Author: Alexandre Ganea (aganea) ChangesSince functions exported from DLLs are type-erased, before this patch I was seeing the new Clang 19 warning This happens when building LLVM on Windows. Full diff: https://github.com/llvm/llvm-project/pull/97905.diff 3 Files Affected:
diff --git a/llvm/include/llvm/Support/Windows/WindowsSupport.h b/llvm/include/llvm/Support/Windows/WindowsSupport.h
index d3aacd14b2097..1f4bd71aec49f 100644
--- a/llvm/include/llvm/Support/Windows/WindowsSupport.h
+++ b/llvm/include/llvm/Support/Windows/WindowsSupport.h
@@ -245,6 +245,12 @@ std::error_code GetCommandLineArguments(SmallVectorImpl<const char *> &Args,
std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16,
size_t MaxPathLen = MAX_PATH);
+/// Dynamically retrieve an exported function from a DLL, while casting it to a
+/// known type. This avoids -Wcast-function-type-mismatch.
+template <typename T> T funcFromModule(HMODULE Mod, StringRef Name) {
+ return (T)(void *)::GetProcAddress(Mod, Name.data());
+}
+
} // end namespace windows
} // end namespace sys
} // end namespace llvm.
diff --git a/llvm/lib/Support/Windows/Process.inc b/llvm/lib/Support/Windows/Process.inc
index 34d294b232c32..4f6a41e23904e 100644
--- a/llvm/lib/Support/Windows/Process.inc
+++ b/llvm/lib/Support/Windows/Process.inc
@@ -482,7 +482,8 @@ static RTL_OSVERSIONINFOEXW GetWindowsVer() {
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
assert(hMod);
- auto getVer = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
+ auto getVer = llvm::sys::windows::funcFromModule<RtlGetVersionPtr>(
+ hMod, "RtlGetVersion");
assert(getVer);
RTL_OSVERSIONINFOEXW info{};
diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc
index 29ebf7c696e04..432b2e9b8dfd7 100644
--- a/llvm/lib/Support/Windows/Signals.inc
+++ b/llvm/lib/Support/Windows/Signals.inc
@@ -168,25 +168,27 @@ static bool isDebugHelpInitialized() {
}
static bool load64BitDebugHelp(void) {
+ using namespace llvm::sys::windows;
+
HMODULE hLib =
::LoadLibraryExA("Dbghelp.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (hLib) {
fMiniDumpWriteDump =
- (fpMiniDumpWriteDump)::GetProcAddress(hLib, "MiniDumpWriteDump");
- fStackWalk64 = (fpStackWalk64)::GetProcAddress(hLib, "StackWalk64");
+ funcFromModule<fpMiniDumpWriteDump>(hLib, "MiniDumpWriteDump");
+ fStackWalk64 = funcFromModule<fpStackWalk64>(hLib, "StackWalk64");
fSymGetModuleBase64 =
- (fpSymGetModuleBase64)::GetProcAddress(hLib, "SymGetModuleBase64");
+ funcFromModule<fpSymGetModuleBase64>(hLib, "SymGetModuleBase64");
fSymGetSymFromAddr64 =
- (fpSymGetSymFromAddr64)::GetProcAddress(hLib, "SymGetSymFromAddr64");
+ funcFromModule<fpSymGetSymFromAddr64>(hLib, "SymGetSymFromAddr64");
fSymGetLineFromAddr64 =
- (fpSymGetLineFromAddr64)::GetProcAddress(hLib, "SymGetLineFromAddr64");
+ funcFromModule<fpSymGetLineFromAddr64>(hLib, "SymGetLineFromAddr64");
fSymGetModuleInfo64 =
- (fpSymGetModuleInfo64)::GetProcAddress(hLib, "SymGetModuleInfo64");
- fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64)::GetProcAddress(
+ funcFromModule<fpSymGetModuleInfo64>(hLib, "SymGetModuleInfo64");
+ fSymFunctionTableAccess64 = funcFromModule<fpSymFunctionTableAccess64>(
hLib, "SymFunctionTableAccess64");
- fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib, "SymSetOptions");
- fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib, "SymInitialize");
- fEnumerateLoadedModules = (fpEnumerateLoadedModules)::GetProcAddress(
+ fSymSetOptions = funcFromModule<fpSymSetOptions>(hLib, "SymSetOptions");
+ fSymInitialize = funcFromModule<fpSymInitialize>(hLib, "SymInitialize");
+ fEnumerateLoadedModules = funcFromModule<fpEnumerateLoadedModules>(
hLib, "EnumerateLoadedModules64");
}
return isDebugHelpInitialized();
|
template <typename T> T funcFromModule(HMODULE Mod, StringRef Name) { | ||
return (T)(void *)::GetProcAddress(Mod, Name.data()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about something like:
template <typename ReturnType, typename... Arguments>
auto funcFromModule(HMODULE hMod, StringRef Name) -> ReturnType ((*)(Arguments...)) {
return reinterpret_cast<ReturnType (*)(Arguments...)>(::GetProcAddress(hMod, Name.data());
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't destructure a C function pointer like this, can you? This needs std::remove_pointer_t<>
on the calling site?
I reverted back to C-casting to a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is confusing to me. I think that we should declare typedefs for the function pointer type. I doubt that anyone wants to build on 32-bit at this point, but the calling convention differences on Windows really do require that we create typedefs for the function pointer type so that we can account for the calling convention. As an example:
typedef (NTSTATUS)(*RtlGetVersionTy)(PRTL_OSVERSIONINFOW);
FWIW, I continuously build and test LLVM (both running LLVM itself on, and generating code for) on 32 bit Windows targets, both i386 and arm. |
In that case, I think that the suggestion is more a requirement - we cannot risk losing thee calling convention attribute on the function pointer. |
We do have typedefs with proper calling convention for all functions retrieved with What would be the way forward here? Are we fine with the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, the void*
is an intermediate cast to drop the FARPROC
. That seems fine to me. The one final piece - the function is type erased irrespective of windows or not and DLL exported or not. Symbols on ELF and MachO libraries will also be "type erased".
Thanks @compnerd! I will apply the same receipe for other places where this occurs in the codebase (compiler-rt for instance) |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/154/builds/2148 Here is the relevant piece of the build log for the reference:
|
/cherry-pick 39e192b |
…7905) Since functions exported from DLLs are type-erased, before this patch I was seeing the new Clang 19 warning `-Wcast-function-type-mismatch`. This happens when building LLVM on Windows. Following discussion in llvm@593f708#commitcomment-143905744 (cherry picked from commit 39e192b)
/pull-request #101266 |
…7905) Since functions exported from DLLs are type-erased, before this patch I was seeing the new Clang 19 warning `-Wcast-function-type-mismatch`. This happens when building LLVM on Windows. Following discussion in llvm@593f708#commitcomment-143905744 (cherry picked from commit 39e192b)
This fixes a few of these warnings, when building with Clang ToT on Windows: ``` [622/7618] Building CXX object projects\compiler-rt\lib\sanitizer_common\CMakeFiles\RTSanitizerCommonSymbolizer.x86_64.dir\sanitizer_symbolizer_win.cpp.obj C:\src\git\llvm-project\compiler-rt\lib\sanitizer_common\sanitizer_symbolizer_win.cpp(74,3): warning: cast from 'FARPROC' (aka 'long long (*)()') to 'decltype(::StackWalk64) *' (aka 'int (*)(unsigned long, void *, void *, _tagSTACKFRAME64 *, void *, int (*)(void *, unsigned long long, void *, unsigned long, unsigned long *), void *(*)(void *, unsigned long long), unsigned long long (*)(void *, unsigned long long), unsigned long long (*)(void *, void *, _tagADDRESS64 *))') converts to incompatible function type [-Wcast-function-type-mismatch] ``` This is similar to #97905
This fixes the following warning, when building with Clang ToT on Windows: ``` [6668/7618] Building CXX object tools\lldb\source\Plugins\Process\Windows\Common\CMakeFiles\lldbPluginProcessWindowsCommon.dir\TargetThreadWindows.cpp.obj C:\src\git\llvm-project\lldb\source\Plugins\Process\Windows\Common\TargetThreadWindows.cpp(182,22): warning: cast from 'FARPROC' (aka 'long long (*)()') to 'GetThreadDescriptionFunctionPtr' (aka 'long (*)(void *, wchar_t **)') converts to incompatible function type [-Wcast-function-type-mismatch] ``` This is similar to: #97905
Since functions exported from DLLs are type-erased, before this patch I was seeing the new Clang 19 warning
-Wcast-function-type-mismatch
.This happens when building LLVM on Windows.
Following discussion in 593f708#commitcomment-143905744