Spec-Zone.ru › GCC 6

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

В этом разделе описывается синтаксис, с помощью которого __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 список спецификаторов атрибутов может появляться как часть перечислителя. Атрибут следует за константой перечисления, перед =, если он есть. Необязательный атрибут в перечислителе относится к константе перечисления. Невозможно разместить атрибут после константного выражения, если оно присутствует.

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

Список спецификаторов атрибутов может появляться как часть спецификатора 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.

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

END_OF_DOCUMENT_MARKER

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

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

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

Spec-Zone.ru

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