После шести месяцев разработки представлен релиз проекта 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‹T›», через который можно указать информацию о типе объекта, для которого выделяется или освобождается память.
- Добавлена возможность вычисления на этапе компиляции (в контексте константного выражения) лямбда-функций, захватывающих структурированные привязки (structured binding) .
- По аналогии с GCC реализована возможность использования константных выражений в ассемблерных вставках, определяемых директивой «asm»:
- Возможности, связанные с будущим стандартом 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() в именованных модулях.
- В структурированные привязки добавлена возможность использования синтаксиса «…» для указания пакетов (pack), захватывающих оставшееся число элементов из присваиваемой последовательности.
- Возможности, развиваемые для будущего стандарта 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++» из-за ограничения области видимости.
struct S { struct T { int x; } t; }; struct T t; // предупреждение, так как корректно в Си, но некорректно в C++
- «-Wimplicit-int-enum-cast» — выявление неявных преобразований в С-коде из целочисленных типов в тип перечислений, несовместимых с «C++».
- «-Wtentative-definition-compat» — диагностика повторяющихся определений в «C», несовместимых с «C++» (например, «int i;int i;»).
- «-Wunterminated-string-initialization» и «-Wc++-unterminated-string-initialization» — выявление операций инициализации строковых литералов, в которых не вмещается разделитель с нулевым кодом. Для пометки полей и переменных в коде на Си, не требующих финального нулевого символа, добавлен атрибут
«nonstring».char buf1[3] = "foo"; // предупреждение char buf2[3] = "fo "; // всё Ok.
- «-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 добавлена экспериментальная поддержка ассемблера для расширений Qualcomm uC, Andes и SiFive.
Источник: http://www.opennet.ru/opennews/art.shtml?num=63783