clang分析源碼前判斷是按C模式還是按C++模式分析的過程?
這個過程我是指clang前端在分析源文件.c/.cpp里的內容前它是怎麼通過文件後綴判斷進而選擇是按c標準分析還是c++標準分析的?windows下clang編譯後會生成clang.exe和clang++.exe,前者分析c後者分析c++(調用clang.exe單獨分析包含class的.h分析不出來class節點)。不涉及後面生成ast的過程,只是前面判斷到底是按c還算是按c++分析這個過程,如何進行處理判斷的?
clang++其本質是clang的一個軟連接,這兩個是一樣的,判斷到底是C還是C++,後綴名是一個很重要的特點,clang++的++的主要影響在標準庫的鏈接上,如clang不會選擇鏈接libc++等C++標準庫,如下面簡單的例子:
#include &
int main(int argc, char const* argv[])
{
std::cout &<&< "Hello
";
return 0;
}
可以看到,是可以很正常的編譯的,但是會在鏈接的時候找不到C++標準庫,你只需要鏈接上即可。
更多的一些過程可以參考我這篇文章:誰說不能與龍一起跳舞:Clang / LLVM (2)
但是在那一篇文章中我並沒有闡述是如何根據文件後綴來判斷是C還是C++的,然而其實這裡面是很簡單的,所以我當時就略過去了,其實就是在一個名叫lookupTypeForExtension的函數中,就是直接暴力窮舉文件後綴名,判定是C還是C++。
types::ID types::lookupTypeForExtension(const char *Ext) {
return llvm::StringSwitch&
.Case("c", TY_C)
.Case("i", TY_PP_C)
.Case("m", TY_ObjC)
.Case("M", TY_ObjCXX)
.Case("h", TY_CHeader)
.Case("C", TY_CXX)
.Case("H", TY_CXXHeader)
.Case("f", TY_PP_Fortran)
.Case("F", TY_Fortran)
.Case("s", TY_PP_Asm)
.Case("asm", TY_PP_Asm)
.Case("S", TY_Asm)
.Case("o", TY_Object)
.Case("obj", TY_Object)
.Case("lib", TY_Object)
.Case("ii", TY_PP_CXX)
.Case("mi", TY_PP_ObjC)
.Case("mm", TY_ObjCXX)
.Case("bc", TY_LLVM_BC)
.Case("cc", TY_CXX)
.Case("CC", TY_CXX)
.Case("cl", TY_CL)
.Case("cp", TY_CXX)
.Case("cu", TY_CUDA)
.Case("cui", TY_PP_CUDA)
.Case("hh", TY_CXXHeader)
.Case("ll", TY_LLVM_IR)
.Case("hpp", TY_CXXHeader)
.Case("ads", TY_Ada)
.Case("adb", TY_Ada)
.Case("ast", TY_AST)
.Case("c++", TY_CXX)
.Case("C++", TY_CXX)
.Case("cxx", TY_CXX)
.Case("cpp", TY_CXX)
.Case("CPP", TY_CXX)
.Case("CXX", TY_CXX)
.Case("for", TY_PP_Fortran)
.Case("FOR", TY_PP_Fortran)
.Case("fpp", TY_Fortran)
.Case("FPP", TY_Fortran)
.Case("f90", TY_PP_Fortran)
.Case("f95", TY_PP_Fortran)
.Case("F90", TY_Fortran)
.Case("F95", TY_Fortran)
.Case("mii", TY_PP_ObjCXX)
.Case("pcm", TY_ModuleFile)
.Case("pch", TY_PCH)
.Case("gch", TY_PCH)
.Case("rs", TY_RenderScript)
.Default(TY_INVALID);
}
按照我的使用經驗,它完全不判斷。如果你調用clang,那他就認為你是在編譯C;如果調用clang++,就認為你在編譯C++。具體使用哪個版本的語言標準,取決於編譯器標準。
我平常寫代碼都用CMake控制編譯過程,它按照擴展名來選擇用哪個前端。
不過不管怎樣,顯然你總是可以硬點一個:
$ clang -std=c++11 -l/path/to/your/libstdc++ -o boy_next_door boy_next_door.cpp
推薦閱讀:
※如果有一天,所有的 編譯器都消失了,人類應該如何最快恢復?
※編譯後的c/c++ 程序, 如何判斷一個函數 是否 真的inline了(如果不看反彙編話)?
※Swift,Haskell這種可以自定義運算符的語言(不僅僅是重載),在實現編譯器時跟其他語言又什麼區別嗎?
※新版本編譯器是用自己(新版本編譯器)重新編譯後發布還是用舊版本編譯器編譯發布?