Spec-Zone.ru › GCC 5

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

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

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

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

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

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

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

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

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

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

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

Spec-Zone.ru

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