2017-07-17 5 views
1

は、次の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==11==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

+1

コンパイラは、コードのセクションの内容を無視するように、標準を書いた人に厳しい指示の下にあるため、満たされていないプリプロセッサディレクティブのスキップ( '#if'などの入れ子を決定するために必要な範囲を除く)。 '#line'はスキップされるので、無視しなければなりません。処理したい場合は、スキップしてはいけません。 –

+1

ISO/IEC 9899:2011§6.10.1条件付き包含¶6 - 各指令の状態は順番にチェックされます。 false(ゼロ)と評価された場合、制御するグループ はスキップされます。ディレクティブは、ネストされた条件のレベルを追跡するためにディレクティブ を決定する名前によってのみ処理されます。 ディレクティブの前処理トークンの残りの部分は無視され、 グループの他の前処理トークンも無視されます。制御条件が真(非ゼロ)と評価される最初のグループのみが処理され、 になります。 –

+1

[...継続...] _条件のどれもが真と評価されず、 '#else'指示文がある場合、'#else'によって制御される グループが処理されます。 '#if'、'#ifdef'、 '#ifdef'で制御されている行を記述するために' group'という用語が使用されています。 '#elif'、' #endif')ディレクティブです。 –

答えて

0

次の修正この(打ち鳴らす-4.0にし、上記の該当する):

clang/lib/Lex/PPDirectives.cpp: 

@@ -358,7 +358,7 @@ 

    char FirstChar = RI[0]; 
    if (FirstChar >= 'a' && FirstChar <= 'z' && 
-  FirstChar != 'i' && FirstChar != 'e') { 
+  FirstChar != 'i' && FirstChar != 'e' && FirstChar != 'l') { 
     CurPPLexer->ParsingPreprocessorDirective = false; 
     // Restore comment saving mode. 
     if (CurLexer) CurLexer->resetExtendedTokenMode(); 
@@ -479,6 +479,11 @@ 
     } 
     } 
    } 
+ else if (Directive[0] == 'l') { 
+  CurPPLexer->LexingRawMode = false; 
+  HandleLineDirective(); 
+  CurPPLexer->LexingRawMode = true; 
+ } 

    CurPPLexer->ParsingPreprocessorDirective = false; 
    // Restore comment saving mode. 

今、私たちが唯一知られている#ifdefなどの条件文を含むプリプロセッサの条件(、内のセクションを使用することができますコンパイル時に)。 そして、プリプロセッサの条件を変更する変更ファイルを使うことができます。

も参照してくださいhttps://bugs.llvm.org/show_bug.cgi?id=33806

gccのためのパッチは歓迎です...

関連する問題