は、次のtest.c
を考えてみましょう:なぜ#lineディレクティブがclangの#ifで処理されないのですか?
int main(void)
{
int a;
#if 1==0
#line 1 "test.c"
#endif
a = 1;
return 0;
}
注意、#if
条件がここに偽であること。
:
clang -g test.c
objdump -D a.out >dis
sed -i 's/line 1/line 2/' test.c
clang -g test.c
objdump -D a.out | diff dis -
違いを明確にするために:私たちは一例で1==1
に1==0
を変更した場合、上 を実行しますコマンドは、我々は次のような出力を得る:他の言葉で
749c749
< 33: 05 05 0a c8 05 add $0x5c80a05,%eax
---
> 33: 05 05 0a c9 05 add $0x5c90a05,%eax
を、私はいつも内部#line
ディレクティブを称えるclang
を作成する必要があります、それが偽であっても。
これは、ctangleからの出力を正しくコンパイルするために必要です。 それ以外の場合、警告とデバッグ行番号がすべて間違っています。
#if-#endif内の行は、とにかくスキャンされた であるため、これを行うのは難しくありません。
#if-#endifの外側にある#lineディレクティブ(および内部が真の場合)は必要に応じて処理されます。
したがって、これらの2つの動作を組み合わせるだけで済みます。#if-#endifの中で#lineディレクティブに必要な処理を実行します( )。
誰かが正しい方向を教えてくれますか? (いずれかのバージョンがどうなるclang
)
コンパイラは、コードのセクションの内容を無視するように、標準を書いた人に厳しい指示の下にあるため、満たされていないプリプロセッサディレクティブのスキップ( '#if'などの入れ子を決定するために必要な範囲を除く)。 '#line'はスキップされるので、無視しなければなりません。処理したい場合は、スキップしてはいけません。 –
ISO/IEC 9899:2011§6.10.1条件付き包含¶6 - 各指令の状態は順番にチェックされます。 false(ゼロ)と評価された場合、制御するグループ はスキップされます。ディレクティブは、ネストされた条件のレベルを追跡するためにディレクティブ を決定する名前によってのみ処理されます。 ディレクティブの前処理トークンの残りの部分は無視され、 グループの他の前処理トークンも無視されます。制御条件が真(非ゼロ)と評価される最初のグループのみが処理され、 になります。 –
[...継続...] _条件のどれもが真と評価されず、 '#else'指示文がある場合、'#else'によって制御される グループが処理されます。 '#if'、'#ifdef'、 '#ifdef'で制御されている行を記述するために' group'という用語が使用されています。 '#elif'、' #endif')ディレクティブです。 –