Релиз набора компиляторов LLVM 21

После шести месяцев разработки представлее релиз проекта LLVM 21.1.0, развивающего инструментарий (компиляторы, оптимизаторы и генераторы кода), компилирующий программы в промежуточный биткод RISC-подобных виртуальных инструкций (низкоуровневая виртуальная машина с многоуровневой системой оптимизаций). Сгенерированный псевдокод может быть преобразован в машинный код для заданной целевой платформы или использован JIT-компилятором для формирования машинных инструкций непосредственно во время выполнения программы. На базе технологий LLVM проектом развивается компилятор Clang, поддерживающий языки программирования C, C++ и Objective-C. Начиная с ветки 18.x проект перешёл на новую схему формирования номеров версий, в соответствии с которой нулевой выпуск (“N.0”) используется в процессе разработки, а первая стабильная версия снабжается номером “N.1”.

Среди улучшений в Clang 21:

  • Возможности, связанные с С++:
    • По аналогии с GCC реализована возможность использования константных выражений в ассемблерных вставках, определяемых директивой “asm”: int foo() { asm((std::string_view(“nop”)) ::: (std::string_view(“memory”))); }
    • Добавлены расширенные варианты выражений “new” и “delete”, поддерживающие аргумент “std::type_identity”, через который можно указать информацию о типе объекта, для которого выделяется или освобождается память.
    • Добавлена возможность вычисления лямбда-функций, захватывающих структурированные привязки (structured binding), на этапе компиляции в контексте константного выражения.
  • Возможности, связанные с будущим стандартом C++2с (C++26):
    • В структурированные привязки добавлена возможность использования синтаксиса “…” для указания пакетов (pack), захватывающих оставшееся число элементов из присваиваемой последовательности. auto [x,y,z] = f(); // в переменные x, y, z будут записаны три элемента, возвращённые f(). auto […xs] = f(); // в пакет xs будут записаны все элементы, возвращённые f(). auto [x, …rest] = f(); // В x будет записан первый элемент, а в rest – остальные. auto [x, y, …rest] = f(); // В x будет записан первый элемент, в y – второй, а в rest – третий. auto [x, …rest, z] = f(); // в x – первый, в rest – второй, в z – третий.
    • Добавлена поддержка “тривиальной перемещаемости” типов (Trivial Relocatability), позволяющей оптимизировать перемещения объектов заданного типа через их клонирование в памяти без вызова конструкторов или деструкторов. Для классов реализованы свойства memberwise_trivially_relocatable и memberwise_replaceable, а для низкоуровневого перемещения одного или нескольких объектов добавлены функции trivially_relocate_at и trivially_relocate.
    • Возможность применения структурированного связывания (structured binding) в качестве условия в операторах if и switch.
    • Реализована поддержка прикрепления функции main к глобальному модулю и определения функции main в именованных модулях.
  • Возможности, развиваемые для будущего стандарта C2y:
    • Устранено неопределённое поведение при использовании выражений с типом void в некоторых контекстах, например, “(void)(void)1;”.
    • Разрешено не завершать файл с исходным кодом символом новой строки.
    • Добавлены новые префиксы для восьмеричных литералов – 0o и 0O, а также восьмеричные и шестнадцатеричные escape-последовательности “o{…}” и x{…}. Поддержка восьмеричных литералов 0xxx объявлена устаревшей. Например, “0o123” и “o{123}” вместо “0123”.
    • Добавлен оператор “_Countof” для определения количества элементов в массиве. Также добавлен заголовочный файл stdcountof.h, определяющий вариант макроса “countof”, реализованный через “_Countof”.
  • Возможности, определённые в Си-стандарте C23:
    • Разрешено переопределять tag‑типы (struct, union, enum) в пределах одного блока трансляции, если повторные определения структурно эквивалентны (то же число членов, одинаковые типы и имена тегов).
    • Упрощено использование списков с переменным числом аргументов (variadic). Разрешено использовать
      одиночный вариативный параметр в имени типа.
    • Добавлена совместимая с GCC встроенная функция “__builtin_c23_va_start()”, улучшающая поведение диагностики для макроса va_start() в режиме C23.
  • В режиме совместимости с компилятором MSVC разрешено использование спецификатора inline при объявлении типа функции через typedef, например, “typedef int inline Foo(int);”
  • Разрешено использовать квалификатор “restrict” для типов массивов с элементами-указателями.
  • Новые предупреждения компилятора:
    • “-Wdefault-const-init-var” и “-Wdefault-const-init-field” – выявление помеченных признаком const переменных и полей, определённых без явной инициализации.
    • “-Wimplicit-void-ptr-cast” – выводится при неявном преобразовании из типа “void*” в другой тип указателя.
    • “-Wc++-keyword” – выводится при использовании ключевых слов “C++” в качестве идентификаторов в “C”.
    • “-Wc++-hidden-decl” – выявление использования типов тегов, видимых в “C”, но не видимых в “C++” из-за ограничения области видимости.
    • “-Wimplicit-int-enum-cast” – выявление неявных преобразований в С-коде из целочисленных типов в тип перечислений, несовместимых с “C++”.
    • “-Wtentative-definition-compat” – диагностика предварительных определений в “C” с несколькими определениями, несовместимыми с “C++”.
    • “-Wunterminated-string-initialization” и “-Wc++-unterminated-string-initialization” – выявление ситуаций инициализации из строкового литерала, в которых не может быть сохранён разделитель с нулевым кодом. Для пометки полей и переменных в коде на Си, не требующих финального нулевого символа, добавлен атрибут
      “nonstring”.
    • “-Wjump-misses-init” – диагностика перехода через goto или switch/case, пропускающего инициализацию локальной переменной.
    • “-Wundef-true” – предупреждает об использовании значения “true” в препроцессоре C без определения.
    • “-Wnrvo” – диагностика пропущенных NRVO (Named Return Value Optimization).
  • Новые флаги компилятора:
    • “-fprofile-continuous” – включение непрерывной синхронизации профиля в файл.
    • “-ftime-report-json” – вывод сведений о времени компиляции в формате JSON.
    • “-ignore-pch” – отключение предкомпилированных заголовков.
    • “-fthinlto-distributor” и “-Xthinlto-distributor” – для применения DTLTO (Integrated Distributed ThinLTO).
    • “-static-libclosure” – для статического связывания runtime расширения Blocks на платформе Windows.
  • Расширены средства диагностики и статического анализа, добавлены новые проверки (более сотни улучшений, связанных с диагностикой).
  • Улучшены бэкенды для архитектур ARM, Aarch64, AMDGPU, x86, RISC-V, LoongArch, MIPS и PowerPC. В бэкенд для RISC-V добавлена экспериментальная поддержка ассемблера для [[https://llvm.org/docs/RISCVUsage.html расширенийъъ Qualcomm uC, Andes и SiFive.
  • Release. Ссылка here.