Главная » Хабрахабр » [Перевод] Clang. Часть 1: введение

[Перевод] Clang. Часть 1: введение

Что такое Clang?

Я провёл последние несколько месяцев, работая с Clang, фронтендом LLVM. Clang умеет парсить и анализировать любой исходный код на языках семейства С (C, C++, ObjectiveC, и т.п....) и имеет удивительную модульную структуру, которая делает его простым в использовании.

Если вы ищете статический анализатор кода, я настоятельно рекомендую Clang, он существенно превосходит другие статические анализаторы (такие, как CIL...) и хорошо документирован. Также список рассылки Clang очень активен и полезен, если вы застряли на чём-то.

Код ядра, особенно код драйвера, может быть очень сложным и трудным для анализа, но Clang позволяет нам легко поддерживать его. Лично я использую Clang для статического анализа драйверов ввода-вывода ядра Linux, включая драйвера камеры и драйвера DRM графической карты. Давайте посмотрим, что можно сделать с его помощью.

Как работает Clang?

В большинстве случаев, Clang запустит препроцессор (который разворачивает все макросы) и парсит исходник, превращая ео в абстрактное синтаксическое дерево (AST). C AST работать гораздо проще, чем с исходным кодом, но вы всегда можете получить ссылки на исходник. Фактически, каждая структура в Clang-е, используемая для представления кода (AST, CFG и т.п.), всегда имеет ссылку на оригинальный исходник, полезный для целей анализа, рефакторинга и т.п.

Анализ с помощью LLVM означает, что вы можете использовать язык внутреннего представления LLVM, похожий на ассемблер. если вам нужно анализировать и модифицировать код на уровне исходника, Clang лучше, чем LLVM.

Clang AST

Практически каждый компилятор и статический анализатор использует AST для представления исходного кода. AST, используемое в Clang, очень детализированное и сложное, но вы получите удовольствие, изучая различные классы элементов Clang AST. Ниже приводится краткое введение в Clang AST, но самый простой путь изучить его, это просто делать дампы AST для простых исходников, и смотреть, какое AST им соответствует.

У обоих есть множество подклассов, вот несколько примеров: В общем, Clang AST сделано из двух очень гибких классов: Decl и Stmt.

FunctionDecl — прототип или объявление функции
BinaryOperator — бинарный оператор, например (a + b)
CallExpr — вызов функции, например, foo(x);

Вы поймёте суть AST, поиграв с ним несколько минут. Большинство классов имеют «говорящие» имена, например, ForStmt, IfStmt, и ReturnStmt. Вы можете найти документацию по классам AST, поискав что-либо вроде “Clang FunctionDecl.”

Как использовать Clang?

Clang может использоваться как прямая замена gcc и предлагает несколько крутых инструментов статического анализа. Как программист (а не как нормальный пользователь!), вы можете получить доступ к всей мощи clang, используя его как библиотеку одним из трёх способов, в зависимости от того, как вы решите.

В дополнение к тому, что написано в этом описании, я выделю другие существенные различия между различными интерфейсами clang. Для начала, ознакомьтесь с описанием интерфейсов clang.

Clang Plugin

Ваш код является плагином, и запускается каждый раз заново для каждого файла исходника, что означает, что вы не можете сохранять глобальную информацию или другую контекстную информацию между двумя разными исходными файлами (но вы можете запустить плагин для множества файлов последовательно). Плагин запускается путём передачи соответствующих опций системе компиляции (Clang, Make и т.п.) через аргументы командной строки. Это похоже на то, как вы включаете оптимизацию в GCC (т.е. "-O1"). Вы не можете запустить какую-либо свою задачу до или после того, как исходный файл будет проанализирован.

LibTooling (Clang Tool)

Ваш код — обычная программа на С++, с нормальной функцией main(). LibTooling используется для запуска некоторого анализа на исходном коде (с множеством файлов, при желании) без запуска обычного процесса компиляции. Новый экземпляр кода для анализа (и новый AST) будет создан для каждого нового файла исходника (как и в случае Clang Plugin), но вы можете сохранять контекстную информацию между файлами исходников в своих глобальных переменных. Так как у вас есть функция main(), вы можете запускать какие-либо задачи перед или после того, как clang завершит анализ ваших исходных файлов.

LibClang

LibClang хорош тем, что это стабильный API. Clang периодически меняется, и если вы используете Plugin или Libtooling, вам нужно будет править ваш код, чтобы отслеживать эти изменения (но это не так сложно!). Если вам нужен доступ к Clang API из языков, отличных от C++ (например, из Python), вы должны использовать LibClang.

Как правило, нам нужен полный доступ к AST. Примечание: LibClang не даёт полный доступ к AST (только высокоуровневый доступ), но другие два варианта дают.

Он проще, и работает так, как вы ожидаете. Если вы не можете решить, что использовать, я бы порекомендовал начать с интерфейса LibTooling. LibTooling не сложнее в использовании, чем Plugin. Он предлагает гибкость и полный доступ к AST, как и Plugin, без потери глобального контекста между исходными файлами.

Начинаем работать с 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

Можно протестировать Clang, запустив классический пример Hello World:

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

В этом руководстве я использую Clang 3.4 на Ubuntu 13.04, но вы можете использовать другие варианты и того, и другого.

Сейчас перейдём к программированию на Clang.

Продолжение следует.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Переезд с Ubuntu на Windows 10, Hyper-V и избавление от железного маршрутизатора

Купив новый ноутбук, я с сожалением заметил, что моя любимая Ubuntu больше не поддерживает работу сенсоров и вентиляторы постоянно жужжат, делая работу не комфортной. В тоже время, если загрузить предустановленную Windows 10 Pro с оригинального жесткого диска, то наступает приятная ...

«Монстры в играх или как удивить игрока»

Привет, друзья! Уже подошёл третий материал в цикле статей, который вы встречаете очень положительно, за что вам огромное спасибо! Сегодня продолжим разбирать монстров по кусочкам Knee Deep In The Dead! И так, сегодня статья будет наполнена массой примеров и отлично ...