12

こんにちは、clang を使用して c ファイルから情報を抽出しています。そして、マクロの値を抽出しようとしています。

たとえば、これから値「13」または ast (+ (* 3 4) 1) が必要です。

#define SOME_CONSTANT 3*4+1

またはマクロ関数から、ast eg (SOME_MACROFUNC (xy) (+ (add4 x) (* y 9))) が必要です:

int add4(int q) {return q+4;}
#define SOME_MACROFUNC(x,y) add4(x)+y*9

これまでのところ、「プリプロセッサ」クラスの macro_begin() および macro_end() 関数を介してすべてのマクロを反復処理することができました。

それからマクロ名を取得し、「MacroInfo」クラスから、マクロが関数型 (パラメーター名を含む) であるかどうかを取得できました。マクロ内のトークンにもアクセスできますが、トークンの種類 (string_literal、identifier、comma、l_paren、r_paren など) しか取得できません。

だから2つのこと:

  1. トークンの種類だけでなく、トークンの実際の値にアクセスするにはどうすればよいですか。

  2. トークンを指定してマクロから ast を生成する方法はありますか? 私が考えた 1 つの方法は、ソース コードを解析してからマクロを抽出し、それらの名前を使用して、それらのマクロを含むコードをソースに追加し、再解析して ast を取得することです。

例:

char *tempSOME_CONSTANT = SOME_CONSTANT;    
void tempSOME_MACROFUNC(char *x, char *y) {SOME_MACROFUNC(x,y);}

この方法は非常にハッキリしているように見えますが、ステートメントや式ではないマクロでは問題が発生する可能性があります。

ありがとう。

編集:明確にするために、主に各マクロの展開された本体(マクロがなくなるまで、非マクロトークンのみ)が必要です。

edit2 いくつか解決したもの:

興味のある方は、マクロの本体を手動で展開するつもりです。

「preprocessor.getSpelling(token)」でトークン値を取得します。

「preprocessor.getIdentifierTable().get(StringRef(spelling))」でトークンの identinfo を取得します。

また、「clang\lib\Lex\PPMacroExpansion.cpp」を参考にしてください。

ソースツリー全体を再解析せずにパーサーに渡す方法をまだ考えていますが、それを理解するのはそれほど難しくありません。

議論をしてくれた Ira Baxter のおかげで、問題を解決することができました。

4

2 に答える 2

7

私は非常によく似たものに取り組んでいます。マクロが定義されているコンテキスト (wrt クラス、関数など) を収集するために clang フロント エンドを使用し、(疑似) 式パーサーを使用して、マクロ本体が有効な式であるかどうかを判断します。最終的な目標は、マクロを C++ 宣言に変換することです。最近、これを達成する方法を説明する論文がICSM -2012 に採択されました。

マクロを削除するために使用されるツール - demacrofier - は、ここでホストされています

Ira Baxter の例は、マクロの使用方法について非常に洞察に満ちています。ただし、これらのマクロの %age は非常に少なくなります\ref(Ernst らによる C プリプロセッサの使用に関する経験的分析)。現在、私はより一般的なケースに焦点を当てています。

于 2012-07-13T00:31:19.030 に答える