如何不修改源码让Clang编译存在LPTSTR转OLECHAR*错误的C++代码?
Clang编译Windows C++代码的字符类型不匹配问题
问题场景
使用Clang 12.0.0编译一段Windows平台的C++代码时,执行命令clang TestClass.cpp -m32 -w出现类型转换错误:无法将LPTSTR(别名char *)转换为const OLECHAR *(别名const wchar_t *),导致找不到匹配的SysAllocString函数调用。要求不修改源代码,让Clang成功完成编译。
源代码(TestClass.cpp)
#include <Windows.h> class TestClass { public: TestClass(LPTSTR test); }; TestClass::TestClass(LPTSTR i_dumpPath) { BSTR bstr = SysAllocString(i_dumpPath); }
编译错误输出
TestClass.cpp:9:17: error: no matching function for call to 'SysAllocString' BSTR bstr = SysAllocString(i_dumpPath); ^~~~~~~~~~~~~~ C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\oleauto.h:64:21: note: candidate function not viable: no known conversion from 'LPTSTR' (aka 'char *') to 'const OLECHAR *' (aka 'const wchar_t *') for 1st argument WINOLEAUTAPI_(BSTR) SysAllocString(__in_z_opt const OLECHAR * psz); ^ 1 error generated.
详细编译输出
clang version 12.0.0 Target: x86_64-pc-windows-msvc Thread model: posix InstalledDir: C:\Program Files\LLVM-12\bin "C:\\Program Files\\LLVM-12\\bin\\clang.exe" -cc1 -triple x86_64-pc-windows-msvc19.16.27042 -emit-obj -mrelax-all -mincremental-linker-compatible --mrelax-relocations -disable-free -disable-llvm-verifier -discard-value-names -main-file-name TestClass.cpp -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -v -resource-dir "C:\\Program Files\\LLVM-12\\lib\\clang\\12.0.0" -internal-isystem "C:\\Program Files\\LLVM-12\\lib\\clang\\12.0.0\\include" -internal-isystem "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\VC\\Tools\\MSVC\\14.16.27023\\include" -internal-isystem "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\VC\\Tools\\MSVC\\14.16.27023\\atlmfc\\include" -internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.17763.0\\ucrt" -internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.17763.0\\shared" -internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.17763.0\\um" -internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.17763.0\\winrt" -fdeprecated-macro -fdebug-compilation-dir "C:\\Users\\Administrator\\Documents\\Veno\\CodeChecker" -ferror-limit 19 -fmessage-length=142 -fno-use-cxa-atexit -fms-extensions -fms-compatibility -fms-compatibility-version=19.16.27042 -std=c++14 -fdelayed-template-parsing -fcxx-exceptions -fexceptions -fcolor-diagnostics -faddrsig -o "C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\TestClass-5ef61a.o" -x c++ TestClass.cpp clang -cc1 version 12.0.0 based upon LLVM 12.0.0 default target x86_64-pc-windows-msvc #include "..." search starts here: #include <...> search starts here: C:\Program Files\LLVM-12\lib\clang\12.0.0\include C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\include C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\atlmfc\include C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt End of search list. TestClass.cpp:9:17: error: no matching function for call to 'SysAllocString' BSTR bstr = SysAllocString(i_dumpPath); ^~~~~~~~~~~~~~ C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um\oleauto.h:74:21: note: candidate function not viable: no known conversion from 'LPTSTR' (aka 'char *') to 'const OLECHAR *' (aka 'const wchar_t *') for 1st argument WINOLEAUTAPI_(BSTR) SysAllocString(_In_opt_z_ const OLECHAR * psz); ^ 1 error generated.
环境信息
- 操作系统:Windows 10
- Clang版本:12.0.0
- 目标平台:x86_64-pc-windows-msvc
- 线程模型:posix
解决方案
错误根源在于:默认情况下Clang未定义UNICODE和_UNICODE宏,导致Windows头文件将LPTSTR映射为char*;而SysAllocString的参数要求是const wchar_t*(OLECHAR是wchar_t的别名),两者类型不匹配。
只需在编译命令中添加两个宏定义,让LPTSTR映射为宽字符指针wchar_t*,即可匹配函数参数类型,无需修改源代码:
clang TestClass.cpp -m32 -w -DUNICODE -D_UNICODE
添加-DUNICODE和-D_UNICODE后,Windows头文件会自动将LPTSTR替换为LPWSTR(即wchar_t*),此时SysAllocString的调用参数类型完全匹配,编译即可通过。
内容的提问来源于stack exchange,提问作者Veno
相关产品推荐
相关产品推荐

