クラン。 パート1:はじめに

Clangとは何ですか?



ここ数ヶ月、 LLVMフロントエンドであるClangで作業しました。 Clangは、Cファミリの言語(C、C ++、ObjectiveCなど)のソースコードを解析および分析でき、使いやすい驚くべきモジュール構造を備えています。









静的コードアナライザーを探している場合、Clangを強くお勧めします。Clangは他の静的アナライザー(CILなど)よりもはるかに優れており、十分に文書化されています。 また、Clangメーリングリストは非常にアクティブであり、何かにこだわっている場合に役立ちます。



個人的には、Clangを使用して、 カメラ ドライバーやグラフィックカードDRMドライバーなどのLinuxカーネルI / O ドライバーを静的に分析します。 カーネルコード、特にドライバーコードは非常に複雑で解析が難しい場合がありますが、Clangでは簡単に保守できます。 それで何ができるか見てみましょう。



Clangはどのように機能しますか?



ほとんどの場合、Clangはプリプロセッサ(すべてのマクロを展開する)を起動し、ソースを解析して、抽象構文ツリー(AST)に変換します。 ASTはソースコードよりも作業がはるかに簡単ですが、ソースへのリンクをいつでも取得できます。 実際、コード(AST、CFGなど)を表すために使用されるClangのすべての構造には、分析、リファクタリングなどに役立つ元のソースへのリンクが常にあります。



ソースレベルでコードを分析および変更する必要がある場合、ClangはLLVMよりも優れています。 LLVMを使用した分析は、アセンブリ言語と同様に、LLVM内部表現言語を使用できることを意味します。



Clang AST



ほとんどすべてのコンパイラおよび静的アナライザーは、ASTを使用してソースコードを表します。 Clangで使用されるASTは非常に詳細で洗練されていますが、Clang AST要素のさまざまなクラスを探索して楽しむことができます。 以下はClang ASTの簡単な紹介ですが、学習する最も簡単な方法は、単純なソースのASTを単にダンプし、どのASTがそれらに一致するかを確認することです。



一般に、Clang ASTは2つの非常に柔軟なクラスで構成されています:DeclとStmt。 どちらにも多くのサブクラスがありますが、ここにいくつかの例を示します。



FunctionDecl-プロトタイプまたは関数の宣言

BinaryOperator-バイナリ演算子、たとえば(a + b)

CallExpr -foo(x)などの関数呼び出し。



ほとんどのクラスには、ForStmt、IfStmt、ReturnStmtなどの「話す」名前があります。 ASTを数分間遊んでみることで、ASTの本質を理解できます。 「Clang FunctionDecl」のようなものを探して、ASTクラスのドキュメントを見つけることができます。



Clangの使用方法



Clangはgccの直接の代替として使用でき、いくつかのクールな静的解析ツールを提供します。 プログラマーとして(通常のユーザーとしてではなく!)、clangをライブラリとして使用することで、決定方法に応じて3つの方法のいずれかでclangのすべての機能にアクセスできます。



開始するには、 clang インターフェイスの説明をご覧ください。 この説明に記載されている内容に加えて、さまざまなclangインターフェイスのその他の重要な違いを強調します。



Clangプラグイン



コードはプラグインであり、各ソースファイルに対して毎回再実行されます。つまり、2つの異なるソースファイル間でグローバル情報またはその他のコンテキスト情報を保存することはできません(ただし、多くのファイルに対してプラグインを順番に実行できます)。 プラグインは、コマンドライン引数を介して適切なオプションをコンパイルシステム(Clang、Makeなど)に渡すことで起動します。 これは、GCCで最適化を有効にする方法(つまり、「-O1」)に似ています。 ソースファイルが分析される前または後にタスクを開始することはできません。



LibTooling(Clangツール)



コードは、通常のmain()関数を備えた通常のC ++プログラムです。 LibToolingは、通常のコンパイルプロセスを開始せずに、ソースコード(必要に応じて多くのファイルを使用)でいくつかの分析を実行するために使用されます。 新しいソースファイルごとに、分析用のコードの新しいコピー(および新しいAST)が作成されます(Clangプラグインの場合のように)が、グローバル変数のソースファイル間のコンテキスト情報を保存できます。 main()関数があるため、clangがソースファイルの分析を完了する前または後に、任意のタスクを実行できます。



リブクラン



LibClangは安定したAPIであるため優れています。 Clangは定期的に変更されます。プラグインまたはLibtoolingを使用する場合は、コードを編集してこれらの変更を追跡する必要があります(ただし、それほど難しくありません!)。 C ++以外の言語(Pythonなど)からClang APIにアクセスする必要がある場合は、LibClangを使用する必要があります。



:LibClangはASTへのフルアクセス(高レベルアクセスのみ)を提供しませんが、他の2つのオプションは提供します。 原則として、ASTへのフルアクセスが必要です。



使用するものを決定できない場合は、LibToolingインターフェースから始めることをお勧めします。 シンプルで、期待どおりに機能します。 ソースファイル間のグローバルコンテキストを失うことなく、柔軟性とプラグインのようなASTへのフルアクセスを提供します。 LibToolingはプラグインよりも難しくありません。



Clangを使い始める



これで基本がわかったので、始めましょう! この命令は、Linux(および場合によってはOS X)のどのバージョンでも動作しますが、Ubuntuでテストされています。 LLVMとClangを入手するには、次の手順を実行します(Clangの公式指示から取得)。



必要なすべてのパッケージをダウンロードしてインストールします(たとえば、apt-getを使用)。

(典型的なLinuxディストリビューションには、Subversionを除く必要なものがすべて付属しています)。

LLVMをインストールするディレクトリ(たとえば、〜/ static_analysis /)にディレクトリを変更します。 これを最上位ディレクトリと呼びます。 ターミナルで次のコマンドを実行します。



$ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm $ cd llvm/tools $ svn co http://llvm.org/svn/llvm-project/cfe/trunk clang $ cd clang/tools $ svn co http://llvm.org/svn/llvm-project/clang-tools-extra/trunk extra $ cd ../../../.. #go back to top directory $ cd llvm/projects $ svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt $ cd ../.. #go back to top directory $ cd llvm $ ./configure $ make #this takes a few hours $ sudo make install
      
      





LLVMとClangのコンパイルには時間がかかります。



実行を確認するには:



 $ clang --version
      
      





古典的なHello Worldの例を実行して、Clangをテストできます。



 $ clang hello.c -o hello $ ./hello
      
      





このチュートリアルでは、Ubuntu 13.04でClang 3.4を使用しますが、両方に他のオプションを使用できます。



それでは、Clangでのプログラミングに移りましょう。



継続する。



All Articles