Microsoft Visual C ++ смогла сделать это, по крайней мере, начиная с Visual Studio 2005. Они называют это «Оптимизация всей программы» или «Генерация кода времени соединения». В этой реализации компилятор фактически не будет генерировать машинный код, а записывает предварительно обработанный код C ++ в объектные файлы. Затем компоновщик объединит весь код в одну огромную единицу кода и выполнит фактическую компиляцию.
GCC может делать это начиная с версии 4.5, а в GCC 4.7 появятся значительные улучшения. Насколько мне известно, эта функция все еще считается несколько экспериментальной (по крайней мере, во многих дистрибутивах Linux, не использующих ее). Реализация GCC работает очень схожим образом, сначала записав предварительно обработанный источник (на промежуточном языке GIMPLE) в объектные файлы, затем скомпилировав все объектные файлы в один объектный файл, который затем передается компоновщику (это позволяет GCC продолжать работу с существующими компоновщиками).
Многие большие проекты на C ++ также делают то, что сейчас называется «сборками единства». Вместо передачи сотен отдельных исходных файлов C ++ в компилятор создается один исходный файл, который включает в себя все остальные исходные файлы в проекте. Первоначальная цель заключается в том, чтобы уменьшить время компиляции (поскольку заголовки и т. Д. Не нужно анализировать снова и снова), но в качестве побочного эффекта он будет иметь тот же результат, что и методы LTO / LTCG, упомянутые выше: идеальный видимость компилятором всех функций во всех единицах компиляции.
Я прыгаю между впечатлением от изобретательности моего компилятора C ++ (MSVC 2010) и его глупостью. Некоторый код, который выполнял преобразование формата пикселей с помощью шаблонов, которые при правильной вставке могли бы преобразоваться в 5-10 инструкций по сборке, превратился в килобайты (!) Вызовов вложенных функций. В других случаях он действует так агрессивно, что целые классы исчезают, даже если они содержат нетривиальную функциональность.