Главная » Хабрахабр » [Перевод] 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 Интересное!

[Перевод] .NET Core + Docker на Raspberry Pi. А это законно?

Открытая платформа .NET Core работает практически на всем: Windows, Mac и десятке Linux-систем. Но еще есть SDK и Runtime. Раньше .NET Core SDK не поддерживался на чипах ARMv7/ARMv8, на которых работает Raspberry Pi. Но все изменилось. Подробнее о способах запуска ...

Финтех-дайджест: в магазине можно будет снять деньги с карты на кассе; PayPal хочет покупать больше компаний

Сегодня в дайджесте: В магазине можно будет снять деньги со своей карты; PayPal собирается тратить около $3 млрд в год на слияния и поглощения; «Альфа-Банк» тестирует международную блокчейн-платформу; Как банки будут собирать биометрические данные? Итак, в этом году отдельные банки ...