Spec-Zone.ru › GCC 11

Далее: Прототипы функций и определения функций старого стиля, Предыдущее: Атрибуты операторов, Выше: Расширения языков семейства C [Оглавление][Индекс]

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’, приведённых выше, пока не поддерживается.

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

Далее: Прототипы функций и определения функций старого стиля, Предыдущее: Атрибуты операторов, Вверх: Расширения языка семейства C [Содержание][Индекс]

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

Spec-Zone.ru

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