Spec-Zone.ru › GCC 7

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

В этом разделе описывается синтаксис, с помощью которого __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’, приведённых выше, пока не поддерживается.

END_OF_DOCUMENT_MARKER

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

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

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

Spec-Zone.ru

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