Указаны ли этапы компиляции программы на C++ в стандарте?
Если да, то какие?
Если нет, то ответ для широко используемого компилятора (я бы предпочел MSVS)был бы замечательным.
Я говорю о препроцессинге, токенизации, парсинге и тому подобном. Каков порядок их выполнения и что они делают в частности?
EDIT: Я знаю, что делают компиляция, линковка и препроцессирование, меня в основном интересуют остальные и их порядок. Объяснения по этим вопросам, конечно, также приветствуются, поскольку я могу быть не единственным, кто заинтересован в ответе.
Стадии компиляции программы на C ++ определены стандартом?
Да и нет.
Стандарт C ++ определяет 9 «фаз перевода». Ссылаясь на черновик N3242 (10 МБ PDF) от 2011-02-28 (до выпуска официального стандарта C ++ 11), раздел 2.2:
Приоритет среди синтаксических правил перевода определяется следующими этапами [см. сноску] .
- Физические символы исходного файла отображаются, в зависимости от реализации, в базовый исходный набор символов (ввод символов новой строки для индикаторов конца строки), если необходимо. [SNIP]
- Каждый экземпляр символа обратной косой черты (\), за которым сразу следует символ новой строки, удаляется, объединяя физические исходные строки для формирования логических исходных строк. [SNIP]
- Исходный файл разбит на токены предварительной обработки (2.5) и последовательности символов пробела (включая комментарии). [SNIP]
- Выполняются директивы предварительной обработки, расширяются вызовы макросов и выполняются выражения унарного оператора _Pragma. [SNIP]
- Каждый элемент исходного набора символов в символьном литерале или строковом литерале, а также каждая escape-последовательность и универсальное имя-символа в символьном литерале или не-сырой строковый литерал, преобразуется в соответствующий член набора символов выполнения; [SNIP]
- Литеральные токены смежных строк объединяются.
- Пробельные символы, разделяющие токены, больше не являются значимыми. Каждый токен предварительной обработки преобразуется в токен. (2.7). Полученные токены синтаксически и семантически анализируются и переводятся как единица перевода. [SNIP]
- Переведенные единицы перевода и единицы реализации объединяются следующим образом: [SNIP]
- Все внешние ссылки на объекты разрешены. Компоненты библиотеки связаны для удовлетворения внешних ссылок на объекты, не определенные в текущем переводе. Весь такой вывод транслятора собирается в образ программы, который содержит информацию, необходимую для выполнения в среде выполнения.
[сноска] Реализации должны вести себя так, как будто эти отдельные фазы происходят, хотя на практике разные фазы могут складываться вместе.
Как отмечают маркеры [SNIP] , я не процитировал весь раздел, просто достаточно, чтобы изложить идею.
Чтобы подчеркнуть, компиляторы не обязаны следовать этой точной модели, пока конечный результат такой, как если бы они это сделали.
Фазы 1-6 в большей или меньшей степени соответствуют препроцессору, 7 - тому, что вы обычно воспринимаете как компиляцию, 8 имеет дело с шаблонами, а 9 соответствует связыванию.
(фазы перевода С аналогичны, но № 8 опущен.)