Spec-Zone.ru › GCC 8

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.

Рассмотрим (как в C99 подпункте 6.7.5 пункт 4) объявление 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-8.5.0/gcc/Attribute-Syntax.html

Spec-Zone.ru

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