Spec-Zone.ru › GCC 13

6.39 Синтаксис атрибутов

В этом разделе описан синтаксис, с помощью которого __attribute__ могут быть использованы в языке C, а также конструкции, к которым привязываются спецификаторы атрибутов. Некоторые детали могут отличаться для C++ и Objective-C. Из-за ограничений грамматики атрибутов некоторые формы, описанные здесь, могут не быть успешно проанализированы во всех случаях.

Существуют некоторые проблемы с семантикой атрибутов в C++. Например, нет преобразований для атрибутов, хотя они могут влиять на генерацию кода, поэтому могут возникнуть проблемы при использовании типов с атрибутами совместно с шаблонами или перегрузкой. Аналогично, typeid не различает типы с различными атрибутами. Поддержка атрибутов в C++ может быть ограничена в будущем только атрибутами в объявлениях, но не вложенных деклараторах.

См. Объявление атрибутов функций для подробностей о семантике атрибутов, применяемых к функциям. См. Указание атрибутов переменных для подробностей о семантике атрибутов, применяемых к переменным. См. Указание атрибутов типов для подробностей о семантике атрибутов, применяемых к структурам, объединениям и перечислениям. См. Атрибуты меток для подробностей о семантике атрибутов, применяемых к меткам. См. Атрибуты перечислителей для подробностей о семантике атрибутов, применяемых к перечислителям. См. Атрибуты операторов для подробностей о семантике атрибутов, применяемых к операторам.

Спецификатор атрибута имеет вид __attribute__ ((attribute-list)). Список атрибутов — это, возможно, пустая последовательность атрибутов, разделенных запятыми, где каждый атрибут является одним из следующих:

  • Пустое значение. Пустые атрибуты игнорируются.
  • Имя атрибута (которое может быть идентификатором, например unused, или ключевым словом, например const).
  • Имя атрибута, за которым следует список параметров в скобках. Эти параметры имеют один из следующих видов:
    • Идентификатор. Например, атрибуты mode используют эту форму.
    • Идентификатор, за которым следует запятая и список выражений, разделенных запятыми. Например, атрибуты format используют эту форму.
    • Возможный пустой список выражений, разделенных запятыми. Например, атрибуты format_arg используют эту форму со списком, состоящим из единственного целочисленного константного выражения, и атрибуты alias используют эту форму со списком, состоящим из единственной строковой константы.

Список спецификаторов атрибутов — это последовательность одного или нескольких спецификаторов атрибутов, не разделенных другими токенами.

Вы можете необязательно указать имена атрибутов с помощью ‘__’ перед и после имени. Это позволяет использовать их в заголовочных файлах, не беспокоясь о возможной макрокоманде с тем же именем. Например, вы можете использовать имя атрибута __noreturn__ вместо noreturn.

Атрибуты меток

В GNU C список спецификаторов атрибутов может появиться после двоеточия, следующего за меткой, кроме метки case или default. GNU C++ допускает атрибуты в метках только в том случае, если спецификатор атрибута непосредственно следует за точкой с запятой (т. е. метка относится к пустому оператору). Если точка с запятой отсутствует, атрибуты меток в C++ являются неоднозначными, так как в C++ разрешено объявление, которое может начинаться со списка атрибутов, которое может быть помечено меткой. В C90 или C99 объявления не могут быть помечены метками, поэтому неоднозначность не возникает.

Атрибуты перечислителей

В GNU C список спецификаторов атрибутов может быть частью перечислителя. Атрибут следует за константой перечисления, перед =, если она присутствует. Необязательный атрибут в перечислителе относится к константе перечисления. Невозможно поместить атрибут после константного выражения, если оно присутствует.

Атрибуты операторов

В GNU C список спецификаторов атрибутов может появиться как часть оператора присваивания. Атрибут предшествует точке с запятой.

Атрибуты типов

Список спецификаторов атрибутов может появиться как часть спецификатора struct, union или enum. Он может идти непосредственно после ключевых слов struct, union или enum, или после закрывающей фигурной скобки. Первый синтаксис предпочтительнее. В случае, когда спецификаторы атрибутов следуют за закрывающей фигурной скобкой, они рассматриваются как относящиеся к определенной структуре, объединению или перечислению, а не к любому окружающему объявлению, в котором появляется спецификатор типа, и определенный тип не завершается до спецификаторов атрибутов.

Все остальные атрибуты

В противном случае спецификатор атрибута появляется как часть объявления, учитывая объявления безымянных параметров и имен типов, и относится к этому объявлению (которое может быть вложено в другое объявление, например, в случае объявления параметра), или к конкретному декларатору в объявлении. Когда спецификатор атрибута применяется к параметру, объявленному как функция или массив, он должен применяться к функции или массиву, а не к указателю, в который параметр неявно преобразуется, но это еще не реализовано.

Любой список спецификаторов и квалификаторов в начале объявления может содержать спецификаторы атрибутов, независимо от того, может ли такой список в данном контексте содержать спецификаторы класса хранения. (Однако некоторые атрибуты по своей сути являются спецификаторами класса хранения и имеют смысл только там, где могут использоваться спецификаторы класса хранения; например, section). Существует одно необходимое ограничение этого синтаксиса: первое объявление параметра старого стиля в определении функции не может начинаться со спецификатора атрибута, потому что такой атрибут применяется к функции вместо этого по описанному ниже синтаксису (который, однако, еще не реализован в этом случае). В некоторых других случаях спецификаторы атрибутов разрешены этой грамматикой, но пока не поддерживаются компилятором. Все спецификаторы атрибутов в этом месте относятся к объявлению в целом. В устаревшем использовании, где тип int подразумевается отсутствием спецификаторов типа, такой список спецификаторов и квалификаторов может быть списком спецификаторов атрибутов без других спецификаторов или квалификаторов.

В настоящее время первый параметр в прототипе функции должен иметь какой-либо спецификатор типа, который не является спецификатором атрибута; это устраняет неоднозначность в интерпретации void f(int (__attribute__((foo)) x)), но может быть изменено. В настоящее время, если скобки декларатора функции содержат только атрибуты, то эти атрибуты игнорируются, а не генерируется ошибка или предупреждение, или подразумевается единственный параметр типа int, но это может быть изменено.

Список спецификаторов атрибутов может появиться непосредственно перед декларатором (кроме первого) в списке деклараторов, разделенных запятыми, в объявлении более чем одного идентификатора с использованием одного списка спецификаторов и квалификаторов. Такие спецификаторы атрибутов применяются только к идентификатору, перед декларатором которого они появляются. Например, в

__attribute__((noreturn)) void d0 (void),
    __attribute__((format(printf, 1, 2))) d1 (const char *, ...),
     d2 (void);

атрибут noreturn применяется ко всем объявленным функциям; атрибут format применяется только к d1.

Список спецификаторов атрибутов может появиться непосредственно перед запятой, = или точкой с запятой, завершающими объявление идентификатора, отличного от определения функции. Такие спецификаторы атрибутов применяются к объявленному объекту или функции. Когда указывается имя сборки для объекта или функции (см. Управление именами, используемыми в ассемблерном коде), атрибут должен следовать за asm спецификацией.

В будущем может быть разрешено размещение списка спецификаторов атрибутов после декларатора в определении функции (перед объявлениями параметров старого стиля или телом функции).

Спецификаторы атрибутов могут быть смешаны с квалификаторами типов, появляющимися внутри [] декларатора массива параметра, в конструкции C99, посредством которой такие квалификаторы применяются к указателю, в который неявно преобразуется массив. Такие спецификаторы атрибутов применяются к указателю, а не к массиву, но в настоящее время это не реализовано, и они игнорируются.

Список спецификаторов атрибутов может появиться в начале вложенного декларатора. В настоящее время существуют некоторые ограничения в этом использовании: атрибуты правильно применяются к декларатору, но для большинства отдельных атрибутов семантика, которую это подразумевает, не реализована. Когда спецификаторы атрибутов следуют за * декларатора указателя, они могут быть смешаны с любыми присутствующими квалификаторами типов. Следующее описывает формальную семантику этого синтаксиса. Это имеет наибольший смысл, если вы знакомы с формальным описанием деклараторов в стандарте ISO C.

Рассмотрим (как в подпункте 6.7.5 пункте 4 C99) объявление T D1, где T содержит спецификаторы объявления, которые определяют тип Type (например, int) и D1 является декларатором, который содержит идентификатор ident. Тип, указанный для ident для деклараторов производных, тип которых не включает спецификатор атрибута, такой же, как и в стандарте ISO C.

Если D1 имеет вид ( attribute-specifier-list D ), и объявление T D указывает тип «derived-declarator-type-list Type» для ident, то T D1 указывает тип «derived-declarator-type-list attribute-specifier-list Type» для ident.

Если D1 имеет вид * type-qualifier-and-attribute-specifier-list D, и объявление T D указывает тип «derived-declarator-type-list Type» для ident, то T D1 указывает тип «derived-declarator-type-list type-qualifier-and-attribute-specifier-list указатель на Type» для ident.

Например,

void (__attribute__((noreturn)) ****f) (void);

указывает тип «указатель на указатель на указатель на указатель на функцию без возвращаемого значения, возвращающую void». В качестве еще одного примера,

char *__attribute__((aligned(8))) *f;

указывается тип “указатель на 8-байтовый выровненный указатель на char”. Обратите внимание, что это не работает со многими атрибутами; например, использование атрибутов ‘aligned’ и ‘noreturn’, приведенных выше, пока не поддерживается.

Для совместимости со существующим кодом, написанным для версий компилятора, которые не реализовывали атрибуты вложенных деклараторов, допускается некоторая свобода в размещении атрибутов. Если атрибут, который применяется только к типам, применяется к объявлению, он обрабатывается как применяемый к типу этого объявления. Если атрибут, который применяется только к объявлениям, применяется к типу объявления, он обрабатывается как применяемый к этому объявлению; и для совместимости с кодом, размещающим атрибуты непосредственно перед идентификатором, объявленным, такой атрибут, применяемый к типу возвращаемого значения функции, обрабатывается как применяемый к типу функции, а такой атрибут, применяемый к типу элемента массива, обрабатывается как применяемый к типу массива. Если атрибут, который применяется только к типам функций, применяется к типу указателя на функцию, он обрабатывается как применяемый к типу целевого указателя; если такой атрибут применяется к типу возвращаемого значения функции, который не является указателем на функцию, он обрабатывается как применяемый к типу функции.

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-13.3.0/gcc/Attribute-Syntax.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API