在llvm中,有原生的ast clone,卻沒有乙個比較好的stmt copy功能,基於scout在llvm上進行的修改,我們實現了自己的stmt clone功能。
要進行stmt clone,肯定需要新建新的ast節點,首先用乙個立即介紹如何進行ast節點的構建,以新建乙個全域性的variable為例。
首先分析下需求,新建variable,自然的有幾個問題:
1.變數如何新建
2.新建的變數應該處於程式的哪個部分
以如下的**為例子:
intmain()
我們有兩個地方可以插入新建的variable,乙個是將其作為全域性變數進行插入,乙個是作為main函式的區域性變數進行插入,這裡選擇作為全域性變數進行插入。那麼插入後,示例**會變成:
intmain()
inta;
(想要有個比較系統的了解的,建議看下tools/clang/lib/staticanalyzer,staticanalyzer是乙個良好的例子)
std::string keyname = "a";int value = 0
;identifiertable& idtable = context->idents;
identifierinfo& idinfo =idtable.get
(keyname);
const
sourcelocation nopos;
vardecl *tmpvar = vardecl::create(*context, context->gettranslationunitdecl(), nopos, nopos, &idinfo, context->intty, context->createtypesourceinfo(context->intty), sc_none);
context->gettranslationunitdecl()->adddeclinternal (tmpvar);
integerliteral *init = integerliteral::create(*context,llvm::apint(context->getintwidth(context->intty),value,true
), context->intty,nopos);
if (init != 0
)
如果想新建乙個int *a;這種的,稍微比較麻煩,因為需要自己新建型別。在context中只提供了基礎型別的:
//builtin types.
canqualtype voidty;
canqualtype boolty;
canqualtype charty;
canqualtype wcharty;
//[c++ 3.9.1p5].
canqualtype widecharty; //
same as wcharty in c++, integer type in c99.
canqualtype wintty; //
[c99 7.24.1], integer type unchanged by default promotions.
canqualtype char16ty; //
[c++0x 3.9.1p5], integer type in c99.
canqualtype char32ty; //
[c++0x 3.9.1p5], integer type in c99.
canqualtype signedcharty, shortty, intty, longty, longlongty, int128ty;
canqualtype unsignedcharty, unsignedshortty, unsignedintty, unsignedlongty;
canqualtype unsignedlonglongty, unsignedint128ty;
canqualtype floatty, doublety, longdoublety, float128ty;
canqualtype halfty;
//[opencl 6.1.1.1], arm neon
canqualtype floatcomplexty, doublecomplexty, longdoublecomplexty;
canqualtype float128complexty;
canqualtype voidptrty, nullptrty;
canqualtype dependentty, overloadty, boundmemberty, unknownanyty;
canqualtype builtinfnty;
canqualtype pseudoobjectty, arcunbridgedcastty;
canqualtype objcbuiltinidty, objcbuiltinclassty, objcbuiltinselty;
canqualtype objcbuiltinboolty;
#define image_type(imgtype, id, singletonid, access, suffix) \canqualtype singletonid;
#include
"clang/basic/openclimagetypes.def
"canqualtype oclsamplerty, ocleventty, oclclkeventty;
canqualtype oclqueuety, oclndrangety, oclreserveidty;
canqualtype omparraysectionty;
//types for deductions in c++0x [stmt.ranged]'s desugaring. built on demand.
mutable qualtype autodeductty; //
deduction against 'auto'.
mutable qualtype autorrefdeductty; //
deduction against 'auto &&'.
//decl used to help define __builtin_va_list for some targets.
//the decl is built when constructing 'builtinvalistdecl'.
mutable decl *valisttagdecl;
新建int *a;第一步自然是在原始碼中手動插入這樣的**,使用clang -fsyntax-only -xclang -ast-dump test.cpp來檢視這個新建的ast節點是如何表達的,再尋找對應的新建方式。
vardecl 0xccec418 col:6 a 'int *'
經過查詢,我們發現,假如我們在遍歷ast樹根節點的子節點的時候,新增如下的處理**:
elseif(isa(*d))
vartp = pointtp ->getpointeetype();
}std::cout
<<"
********
"<}
輸出的**如下:
vardecl 0xde9dcf02:1, col:6> col:6 a '
int *
'pointertype
0xd732d00
'int *
'`-builtintype 0xd6a8140
'int
'builtintype
0xd6a8140
'int
'<<>>
********
這裡就比較明顯了,這個vardecl的qualtype是 pointertype,而pointertype對應的pointee是int。
這樣模仿上邊的**,如果新建乙個int **aaaa;的節點,可以使用:
std::string keyname = "aaaa";
identifiertable& idtable = context->idents;
identifierinfo& idinfo =idtable.get
(keyname);
const
sourcelocation nopos;
qualtype pointerty_1 = context->getpointertype(context->getinttypeforbitwidth(32, 1
));qualtype pointerty_2 = context->getpointertype(pointerty_1);
vardecl *tmpvar = vardecl::create(*context, context->gettranslationunitdecl(), nopos, nopos, &idinfo, pointerty_2, context->createtypesourceinfo(pointerty_2), sc_none);
context->gettranslationunitdecl()->adddecl (tmpvar);
本來想寫stmt clone的,太多了,不好講,先鴿。
static全域性變數 全域性變數
1 全域性變數 外部變數 的說明之前再冠以static 就構成了靜態的全域性變數。全域性變數本身就是靜態儲存方式,靜態全域性變數當然也是靜態儲存方式。這兩者在儲存方式上並無不同。這兩者的區別在於非靜態全域性變數的作用域是整個源程式,當乙個源程式由多個原始檔組成時,非靜態的全域性變數在各個原始檔中都是...
全域性變數和靜態全域性變數
全域性變數和區域性變數是從變數的作用域的角度劃分。靜態變數和動態變數是從變數的記憶體分配的角度劃分。全域性變數本身就是靜態儲存方式,靜態全域性變數當然也是靜態儲存方式。這兩者在儲存方式上並無不同,區別在於非靜態全域性變數的作用域是整個源程式,當乙個源程式由多個原始檔組成時,非靜態的全域性變數在各個原...
c 全域性變數 靜態全域性變數
全域性變數是靜態儲存方式,靜態全域性變數也是靜態儲存方式,這兩者在儲存方式上並無不同。區別 雖在於非靜態全域性變數的作用域是整個源程式,當乙個源程式由多個原始檔組成時,靜態全域性變數在各個原始檔中都是有效的。靜態區域性變數則限制了其作用域,只在定義該變數的原始檔內有效,在同一源程式的其它原始檔中不能...