何年も前にC++のinterpreterであるclang-interpreterを試した記事を書きました。
http://d.hatena.ne.jp/ohtorii/20110716/1310783800
秀丸エディタからclang-interpreterを呼び出してみた - とりあえず日記
当時は、STLとWindowsのヘッダファイルを扱うことが出来ない状況でした。
あれからClang/LLVMも相当バージョンアップされてるので、
気まぐれで久しぶりにビルドして動作を試してみました。
結果
相変わらず、STLとWindowsのヘッダファイルを扱えないです。
まあ、clang-interpreterはサンプルという位置づけなので真面目に実装されていないのかもしれません。
環境
LLVM 5.0.1
Microsoft Visual Studio Community 2017 Version 15.5.7
ビルド手順
VisualStudio2017でビルドしてclang-interpreter.exeを作ります。
(Clang/LLVMのマニュアルに従えば簡単に実行ファイルを作れます、なのでビルド手順は省略します。)
動かしてみた。(printf)
//sample_0.cpp include<stdio.h> int main(int argc, char*argv[]){ for(int i=0; i!=4 ; ++i){ printf("i=%d\n",i); } return 0; }
> clang-interpreter.exe sample_0.cpp i=0 i=1 i=2 i=3
おっ、正しく動いています。
動かしてみた。(file i/o)
//sample_1.cpp #include<stdio.h> int main(int argc, char*argv[]){ FILE* fp=fopen("out.txt","wt"); fprintf(fp,"%s\n","hello clang"); fprintf(fp,"%s\n","こんにちわ、clang"); fclose(fp); return 0; }
> clang-interpreter.exe sample_1.cpp sample_1.cpp:4:11: warning: 'fopen' is deprecated: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. [-Wdeprecated-declarations] FILE* fp=fopen("out.txt","wt"); ^ C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\ucrt\stdio.h:206:20: note: 'fopen' has been explicitly marked deprecated here _Check_return_ _CRT_INSECURE_DEPRECATE(fopen_s) ^ C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\vcruntime.h:255:55: note: expanded from macro '_CRT_INSECURE_DEPRECATE' #define _CRT_INSECURE_DEPRECATE(_Replacement) _CRT_DEPRECATE_TEXT( \ ^ C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\vcruntime.h:245:47: note: expanded from macro '_CRT_DEPRECATE_TEXT' #define _CRT_DEPRECATE_TEXT(_Text) __declspec(deprecated(_Text)) ^ 1 warning generated.
> type out.txt hello clang こんにちわ、clang
fopen関数じゃなくてfopen_s関数を使えと警告されましたが正しい結果を得られました。
動かしてみた。(class)
//sample_2.cpp #include<stdio.h> template<class T> class add{ public: add(T v) : m_base(v){ } T operator()(T v)const{ return v + m_base; }; private: T m_base; }; int main(int argc, char*argv[]){ add<int> obj(10); printf("value=%d\n", obj(20)); return 0; }
> clang-interpreter.exe sample_2.cpp value=30
こちらも、ちゃんと動いています。
動かしてみた。(Global ctor/dtor)
//sample_3.cpp #include<stdio.h> class foo{ public: foo(){ printf("ctor\n"); } ~foo(){ printf("dtor\n"); } }; foo g; // <------- Global ctor/dtor. int main(int argc, char*argv[]){ printf("Enter main.\n"); return 0; }
> clang-interpreter.exe sample_3.cpp LLVM ERROR: Undefined temporary symbol
エラーです。
動かしてみた。(STL)
//sample_4.cpp #include<vector> int main(int argc, char*argv[]){ std::vector<int> v; }
> clang-interpreter.exe sample_4.cpp LLVM ERROR: Undefined temporary symbol
またまた、エラーです。
動かしてみた。(windows.h)
//sample_5.cpp #include<windows.h> int main(int argc, char*argv[]){ DWORD t=MessageBox(NULL,"foo","bar", MB_OK); return 0; }
>clang-interpreter.exe sample_5.cpp In file included from sample_5.cpp:1: In file included from C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\windows.h:171: In file included from C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\shared\windef.h:24: In file included from C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\shared\minwindef.h:182: C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\winnt.h:959:5: error: MS-style inline assembly is not available: Unable to find target for this triple (no targets are registered) __asm { ^ C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\winnt.h:975:5: error: MS-style inline assembly is not available: Unable to find target for this triple (no targets are registered) __asm { ^ C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\winnt.h:991:5: error: MS-style inline assembly is not available: Unable to find target for this triple (no targets are registered) __asm { ^ 3 errors generated.
__asm構文で怒られました。
試したこと
幾つかエラーが発生したので回避できないかソースコードをいじくって試行錯誤してみました。
雰囲気でソースコードを変更しているので期待する動作は得られませんでした。
対象のソースコード
\llvm\tools\clang\examples\clang-interpreter\main.cpp
試行錯誤した痕跡。
#if 0 /* Original */ // FIXME: This is a hack to try to force the driver to do something we can // recognize. We need to extend the driver library to support this use model // (basically, exactly one input, and the operation mode is hard wired). SmallVector<const char *, 16> Args(argv, argv + argc); Args.push_back("-fsyntax-only"); #else /* Modify */ SmallVector<const char *, 256> Args(argv, argv + argc); Args.push_back("-fsyntax-only"); Args.push_back("-fms-compatibility-version=19.00"); Args.push_back("-fms-compatibility"); Args.push_back("-fms-extensions"); //Args.push_back("-fmsc-version=1912"); //Args.push_back("--target=x86_64-windows-msvc"); //Clash. //Args.push_back("--target=i686-windows-msvc"); //LLVM ERROR: Program used external function '___stdio_common_vfprintf' which could not be resolved! //Args.push_back("--target=i686-pc-win32"); //LLVM ERROR: Program used external function '___stdio_common_vfprintf' which could not be resolved! //Args.push_back("--target=x86_64-pc-windows-msvc"); //Crash. //Args.push_back("--target=x86_64"); //sample_0.cpp:1:9: fatal error: 'stdio.h' file not found //Args.push_back("--target="); #endif
最後に
元々、深入りするつもりもないのでこの辺にしておきます。