Spec-Zone.ru › GCC 14

6.35.1 Атрибуты типов общего назначения

Следующие атрибуты типа поддерживаются на большинстве целевых платформ.

aligned
aligned (alignment)

Атрибут aligned задаёт минимальное выравнивание (в байтах) для переменных указанного типа. Если указано, alignment должно быть степенью двойки. Если аргумент alignment не указан, подразумевается максимальное выравнивание для целевой платформы, которое часто, но не всегда, составляет 8 или 16 байт. Например, объявления:

struct __attribute__ ((aligned (8))) S { short f[3]; };
typedef int more_aligned_int __attribute__ ((aligned (8)));

принуждают компилятор гарантировать (насколько это возможно), что каждая переменная, тип которой struct S или more_aligned_int, выделяется и выравнивается по крайней мере на границе 8 байт. На платформе SPARC выравнивание всех переменных типа struct S на 8-байтовую границу позволяет компилятору использовать инструкции ldd и std (загрузка и сохранение двойных слов) при копировании одной переменной типа struct S в другую, что повышает эффективность выполнения.

Обратите внимание, что выравнивание любого типа struct или union согласно стандарту ISO C должно быть по крайней мере кратным наименьшему общему кратному выравниваний всех членов структуры struct или union соответственно. Это означает, что вы можете эффективно настроить выравнивание типа struct или union при добавлении атрибута aligned к любому из членов такого типа, но обозначение, приведенное в примере выше, является более явным, интуитивным и читабельным способом запроса компилятору настроить выравнивание всего типа struct или union.

Как и в предыдущем примере, вы можете явно указать выравнивание (в байтах), которое вы хотите использовать для типа struct или union. В качестве альтернативы, вы можете опустить фактор выравнивания и попросить компилятор выровнять тип до максимального полезного выравнивания для целевой машины, для которой выполняется компиляция. Например, вы можете написать:

struct __attribute__ ((aligned)) S { short f[3]; };

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

В примере выше, если размер каждого short составляет 2 байта, то размер всего типа struct S составляет 6 байт. Наименьшая степень двойки, которая больше или равна этому значению, равна 8, поэтому компилятор устанавливает выравнивание для всего типа struct S до 8 байт.

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

Обратите внимание, что эффективность атрибутов aligned может быть ограничена внутренними ограничениями вашего компоновщика. На многих системах компоновщик может только организовать выравнивание переменных до определенного максимального выравнивания. (Для некоторых компоновщиков максимальное поддерживаемое выравнивание может быть очень и очень маленьким.) Если ваш компоновщик может выравнивать переменные только до максимального выравнивания 8 байт, то указание aligned (16) в атрибуте __attribute__ всё равно предоставляет вам только 8-байтовое выравнивание. Для получения дополнительной информации см. документацию вашего компоновщика.

При использовании с структурой или членом структуры атрибут aligned может только увеличить выравнивание; для его уменьшения необходимо также указать атрибут packed. При использовании в качестве части typedef атрибут aligned может как увеличивать, так и уменьшать выравнивание, а указание атрибута packed генерирует предупреждение.

alloc_size (position)
alloc_size (position-1, position-2)

Атрибут alloc_size может быть применён к определению типа функции, возвращающей указатель и принимающей как минимум один аргумент целочисленного типа. Он указывает, что возвращаемый указатель указывает на объект, размер которого задаётся аргументом функции в позиции position-1 или произведением аргументов в позициях position-1 и position-2. Значимые размеры — это положительные значения, меньшие PTRDIFF_MAX. Другие размеры диагностируются при обнаружении. GCC использует эту информацию для улучшения результатов __builtin_object_size.

Например, следующие объявления

typedef __attribute__ ((alloc_size (1, 2))) void*
  calloc_type (size_t, size_t);
typedef __attribute__ ((alloc_size (1))) void*
  malloc_type (size_t);

указывают, что calloc_type — это тип функции, которая, подобно стандартной C-функции calloc, возвращает объект, размер которого задаётся произведением аргументов 1 и 2, и что malloc_type, подобно стандартной C-функции malloc, возвращает объект, размер которого задаётся первым аргументом функции.

copy
copy (expression)

Атрибут copy применяет набор атрибутов, с которыми был объявлен тип expression, к объявлению типа, к которому применяется атрибут. Атрибут предназначен для библиотек, которые определяют псевдонимы, которые, как ожидается, указывают тот же набор атрибутов, что и алиасируемые символы. Атрибут copy может использоваться с типами, переменными или функциями. Однако вид символа, к которому применяется атрибут (либо переменная, либо функция), должен совпадать с видом символа, на который ссылается аргумент. Атрибут copy копирует только синтаксические и семантические атрибуты, но не атрибуты, влияющие на связь или видимость символа, такие как alias, visibility, или weak. Атрибут deprecated также не копируется. См. Общие атрибуты функций. См. Общие атрибуты переменных.

Например, предположим, что struct A ниже определён в заголовке третьей стороны библиотеки, чтобы потребовать выравнивания N и выдать предупреждение, если переменная типа не выровнена из-за атрибута packed. Указание атрибута copy в определении несвязанного struct B оказывает влияние на копирование всех соответствующих атрибутов из типа, на который ссылается выражение указателя, к struct B.

struct __attribute__ ((aligned (N), warn_if_not_aligned (N)))
A { /* … */ };
struct __attribute__ ((copy ( (struct A *)0)) B { /* … */ };
deprecated
deprecated (msg)

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

typedef int T1 __attribute__ ((deprecated));
T1 x;
typedef T1 T2;
T2 y;
typedef T1 T3 __attribute__ ((deprecated));
T3 z __attribute__ ((deprecated));

приводит к появлению предупреждения на строках 2 и 3, но не на строках 4, 5 или 6. Предупреждение не выдаётся для строки 4, потому что T2 явно не устарел. Строка 5 не содержит предупреждения, потому что T3 явно устарел. Аналогично для строки 6. Необязательный аргумент msg, который должен быть строкой, выводится в предупреждении, если он присутствует. Контрольные символы в строке будут заменены на последовательности escape, а если опция -fmessage-length установлена в 0 (по умолчанию), то все символы новой строки будут игнорироваться.

Атрибут deprecated также может использоваться для функций и переменных (см. Объявление атрибутов функций, см. Указание атрибутов переменных.)

Сообщение, прикреплённое к атрибуту, зависит от установки опции -fmessage-length.

designated_init

Этот атрибут может быть применён только к типам структур. Он указывает, что любая инициализация объекта этого типа должна использовать обозначенные инициализаторы, а не позиционные. Цель этого атрибута — позволить программисту указать, что структура может измениться, и что, следовательно, полагание на позиционную инициализацию приведёт к будущим проблемам.

GCC по умолчанию выдаёт предупреждения на основе этого атрибута; используйте -Wno-designated-init для их подавления.

hardbool
hardbool (false_value)
hardbool (false_value, true_value)
END_OF_DOCUMENT_MARKER

Этот атрибут может быть применён только к целочисленным типам в C для введения защищённых булевых типов. Он преобразует целочисленный тип в булеподобный тип с тем же размером и точностью, который использует указанные значения в качестве представлений для false и true. Внутри он фактически является перечислением, но его наблюдаемое поведение подобно _Bool, за исключением строгих внутренних представлений, проверенных проверками во время выполнения.

Если true_value опущено, используется побитовое отрицание false_value. Если false_value опущено, используется ноль. Названные значения представлений должны быть различны при преобразовании к исходному целочисленному типу. Более узкие битовые поля отклоняются, если представления становятся неразличимыми.

Значения таких типов автоматически распадаются до _Bool, в этот момент выбранные значения представления сопоставляются с соответствующими _Bool значениями. Если представленное значение не определено на этапе компиляции, как false_value или true_value, вызов __builtin_trap происходит во время выполнения, если это не так. Это то, что делает их защищёнными булевыми типами.

При преобразовании скалярных типов к таким защищённым булевым типам, неявно или явно, поведение соответствует преобразованию в _Bool, за которым следует сопоставление false и true соответственно с false_value и true_value.

typedef char __attribute__ ((__hardbool__ (0x5a))) hbool;
hbool first = 0;       /* False, stored as (char)0x5a.  */
hbool second = !first; /* True, stored as ~(char)0x5a.  */

static hbool zeroinit; /* False, stored as (char)0x5a.  */
auto hbool uninit;     /* Undefined, may trap.  */

При инициализации переменной или поля защищённого булевого типа нулём (предположительно хранящегося в статической памяти), неявный инициализатор нулём преобразуется в _Bool, а затем в защищённый булевый тип, так что начальное значение является защищённым представлением для false. Использование этого значения определено. Это не относится к случаям, когда переменные и поля таких типов не инициализированы (предположительно хранящиеся в автоматической или динамической памяти): их значения неопределённы, и их использование вызывает неопределённое поведение. Их использование может вызвать ошибку или не вызвать, в зависимости от битов, хранящихся в памяти (используемой) для переменной, если таковая имеется, и от оптимизаций, которые может выполнить компилятор, исходя из того, что использование неинициализированных значений вызывает неопределённое поведение.

Пользователи -ftrivial-auto-var-init должны понимать, что битовые шаблоны, используемые в качестве инициализаторов, не преобразуются в hardbool типы, поэтому использование hardbool переменной, которая неявно инициализируется с помощью -ftrivial-auto-var-init, может вызвать ошибку, если значения представлений, выбранные для false и true не совпадают с инициализатором.

Поскольку это расширение языка, доступное только в C, взаимодействие с другими языками может вызвать трудности. Оно должно взаимодействовать с булевыми типами Ada, определёнными с тем же размером и эквивалентными предложениями представления, а также с перечислениями или другими целочисленными типами языков, которые соответствуют выбранному целочисленному типу C.

may_alias

Доступ через указатели к типам с этим атрибутом не подпадает под анализ алиасов на основе типов, а вместо этого предполагается, что они могут быть алиасами любых других типов объектов. В контексте раздела 6.5 абзаца 7 стандарта C99 выражение lvalue, разыменовывающее такой указатель, обрабатывается как имеющее тип символа. См. -fstrict-aliasing для получения дополнительной информации о проблемах алиасирования. Это расширение существует для поддержки некоторых векторных API, в которых разрешено, чтобы указатели на один векторный тип были алиасами указателей на другой векторный тип.

Обратите внимание, что объект типа с этим атрибутом не имеет каких-либо специальных семантик.

Пример использования:

typedef short __attribute__ ((__may_alias__)) short_a;

int
main (void)
{
  int a = 0x12345678;
  short_a *b = (short_a *) &a;

  b[1] = 0;

  if (a == 0x12345678)
    abort();

  exit(0);
}

Если вы заменили short_a на short в объявлении переменной, вышеприведенная программа завершится ошибкой при компиляции с -fstrict-aliasing, которая включена по умолчанию при -O2 и выше.

mode (mode)

Этот атрибут определяет тип данных для объявления — любой тип, соответствующий режиму mode. Это позволяет запросить целочисленный или вещественный тип в соответствии с его шириной.

См. Режимы машин в руководстве GNU Compiler Collection (GCC) для списка возможных ключевых слов для mode. Вы также можете указать режим byte или __byte__ для обозначения режима, соответствующего однобайтовому целому числу, word или __word__ для режима одного слова целого числа и pointer или __pointer__ для режима, используемого для представления указателей.

objc_root_class (Objective-C and Objective-C++ only)

Этот атрибут помечает класс как корневой класс и, таким образом, позволяет компилятору устранить любые предупреждения об отсутствующем суперклассе и выполнить дополнительные проверки необходимых методов по мере необходимости.

packed

Этот атрибут, присоединённый к определению struct, union, или C++ class типа, указывает, что каждый его член (кроме полей шириной ноль) размещается таким образом, чтобы минимизировать необходимый объём памяти. Это эквивалентно указанию атрибута packed для каждого из членов.

При присоединении к определению enum атрибут packed указывает, что должен использоваться наименьший целочисленный тип. Указание флага -fshort-enums в командной строке эквивалентно указанию атрибута packed для всех определений enum.

В следующем примере члены struct my_packed_struct упакованы плотно, но внутренняя структура его члена s не упакована — для этого struct my_unpacked_struct тоже должен быть упакован.

struct my_unpacked_struct
 {
    char c;
    int i;
 };

struct __attribute__ ((__packed__)) my_packed_struct
  {
     char c;
     int  i;
     struct my_unpacked_struct s;
  };

Вы можете указать атрибут packed только при определении enum, struct, union, или class, а не для typedef, который не определяет также перечисление, структуру, объединение или класс.

scalar_storage_order ("endianness")

При присоединении к union или struct, этот атрибут задаёт порядок хранения, или порядок следования байтов (эндианность), скалярных полей типа, а также массивов, компоненты которых являются скалярными. Поддерживаемые порядки следования байтов — big-endian и little-endian. Атрибут не оказывает влияния на поля, которые сами являются union, struct или массивом, компоненты которого являются union или struct, и для этих полей может быть установлен другой порядок хранения скалярных данных, чем для окружающего типа.

Обратите внимание, что ни указатели, ни векторные поля не считаются скалярными полями в этом контексте, поэтому атрибут не оказывает на них влияния.

Этот атрибут поддерживается только для целей, которые используют единый порядок хранения скалярных данных по умолчанию (к счастью, большинство из них), то есть для целей, которые хранят скаляры либо в формате big-endian, либо в формате little-endian.

Дополнительные ограничения налагаются для типов с обратным порядком хранения скалярных данных относительно порядка хранения скалярных данных целевой системы:

  • Взятие адреса скалярного поля union или struct с обратным порядком хранения скаляров запрещено и приводит к ошибке.
  • Взятие адреса массива, компоненты которого являются скалярами, от union или struct с обратным порядком хранения скаляров разрешено, но приводит к предупреждению, если не указан -Wno-scalar-storage-order.
  • Взятие адреса union или struct с обратным порядком хранения скаляров разрешено.

Эти ограничения существуют потому, что атрибут порядка хранения теряется при взятии адреса скаляра или массива со скалярной компонентой, поэтому косвенное хранение через этот адрес, как правило, не работает. Однако второй случай разрешён для возможности выполнения блочного копирования в или из массива.

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

strub

Этот атрибут определяет свойства очистки стека для функций и переменных, так что функции, которые обращаются к конфиденциальным данным, могут иметь свои кадры стека обнулены при возврате или распространении исключений. Это может быть включено явно, выбрав определенные strub режимы для конкретных функций, или неявно с помощью strub переменных.

Как атрибут типа, он прикрепляется к типам, даже если указан в объявлениях функций и переменных. При применении к типам функций он принимает необязательный строковый аргумент. При применении к типу указателя на функцию, если необязательный аргумент указан, он передается типу функции.

/* A strub variable.  */
int __attribute__ ((strub)) var;
/* A strub variable that happens to be a pointer.  */
__attribute__ ((strub)) int *strub_ptr_to_int;
/* A pointer type that may point to a strub variable.  */
typedef int __attribute__ ((strub)) *ptr_to_strub_int_type;

/* A declaration of a strub function.  */
extern int __attribute__ ((strub)) foo (void);
/* A pointer to that strub function.  */
int __attribute__ ((strub ("at-calls"))) (*ptr_to_strub_fn)(void) = foo;

Функция, связанная с at-calls strub режимом (strub("at-calls"), или просто strub), претерпевает изменения интерфейса. Ее вызывающие функции корректируются для соответствия изменениям и для очистки (заполнения нулями) пространства стека, используемого вызываемой функцией после возврата. Изменение интерфейса делает тип функции несовместимым с необработанным, но в остальном эквивалентным типом, поэтому каждое объявление и каждый тип, которые могут быть использованы для вызова функции, должны быть связаны с этим режимом очистки.

Функция, связанная с internal strub режимом (strub("internal") ), сохраняет неизмененный, совместимый с типом интерфейс, но она может быть преобразована в обертку, которая вызывает обернутое тело с помощью пользовательского интерфейса. Обёртка затем очищает пространство стека, используемое обернутым телом. Хотя пространство стека обернутого тела очищается, пространство стека обёртки нет, поэтому аргументы и возвращаемые значения могут оставаться неочищенными даже при вызове такой функции другой функцией, которая включает strub . Вот почему при компиляции с -fstrub=strict контекст strub не допускается вызывать internal strub функции.

/* A declaration of an internal-strub function.  */
extern int __attribute__ ((strub ("internal"))) bar (void);

int __attribute__ ((strub))
baz (void)
{
  /* Ok, foo was declared above as an at-calls strub function.  */
  foo ();
  /* Not allowed in strict mode, otherwise allowed.  */
  bar ();
}

Автоматически выделенная переменная, связанная с атрибутом strub, приводит к тому, что функция (непосредственно) окружающая функцию имеет strub включённым.

Статически выделенная переменная, связанная с атрибутом strub, заставляет функции, которые считывают ее, через ее strub тип данных, иметь strub включённым. Чтение данных путем разыменования указателя на тип данных strub имеет тот же эффект. Примечание: атрибут не переносится от составного типа к типам его компонентов, поэтому ожидаемого эффекта может не быть получено с нескалярными типами.

При выборе strub-включенного режима для функции, которая не явно связана с ним, из-за strub переменных или указателей на данные, функция должна удовлетворять требованиям жизнеспособности режима internal (см. ниже), даже когда at-calls режим также жизнеспособен и, будучи более эффективным, в конечном итоге выбирается в качестве оптимизации.

/* zapme is implicitly strub-enabled because of strub variables.
   Optimization may change its strub mode, but not the requirements.  */
static int
zapme (int i)
{
  /* A local strub variable enables strub.  */
  int __attribute__ ((strub)) lvar;
  /* Reading strub data through a pointer-to-strub enables strub.  */
  lvar = * (ptr_to_strub_int_type) &i;
  /* Writing to a global strub variable does not enable strub.  */
  var = lvar;
  /* Reading from a global strub variable enables strub.  */
  return var;
}

Контекст strub — это тело (в отличие от интерфейса) функции, у которой включено strub, будь то явно, через at-calls или internal режимы, или неявно из-за strub переменных или параметров командной строки.

Функция типа, связанного с disabled strub режимом (strub("disabled")) не будет иметь своего собственного пространства стека, очищенного. К таким функциям нельзя обращаться изнутри контекстов strub.

Чтобы функция могла быть вызвана изнутри контекстов strub без очистки её пространства стека, свяжите её с callable strub режимом (strub("callable")) .

Когда функции не присвоен режим strub, явно или неявно, режим по умолчанию callable, за исключением компиляции с -fstrub=strict, которая устанавливает режим strub по умолчанию как disabled.

extern int __attribute__ ((strub ("callable"))) bac (void);
extern int __attribute__ ((strub ("disabled"))) bad (void);
 /* Implicitly disabled with -fstrub=strict, otherwise callable.  */
extern int bah (void);

int __attribute__ ((strub))
bal (void)
{
  /* Not allowed, bad is not strub-callable.  */
  bad ();
  /* Ok, bac is strub-callable.  */
  bac ();
  /* Not allowed with -fstrub=strict, otherwise allowed.  */
  bah ();
}

Типы функций, помеченные callable и disabled не являются взаимно совместимыми типами, но базовые интерфейсы совместимы, поэтому безопасно преобразовывать указатели между ними, а также использовать такие указатели или альтернативные объявления для их вызова. Интерфейсы также взаимозаменяемы между ними и internal (но не at-calls!), но добавление internal к типу указателя не заставит функцию, на которую указывает указатель, выполнять очистку стека.

void __attribute__ ((strub))
bap (void)
{
  /* Assign a callable function to pointer-to-disabled.
     Flagged as not quite compatible with -Wpedantic.  */
  int __attribute__ ((strub ("disabled"))) (*d_p) (void) = bac;
  /* Not allowed: calls disabled type in a strub context.  */
  d_p ();

  /* Assign a disabled function to pointer-to-callable.
     Flagged as not quite compatible with -Wpedantic.  */
  int __attribute__ ((strub ("callable"))) (*c_p) (void) = bad;
  /* Ok, safe.  */
  c_p ();

  /* Assign an internal function to pointer-to-callable.
     Flagged as not quite compatible with -Wpedantic.  */
  c_p = bar;
  /* Ok, safe.  */
  c_p ();

  /* Assign an at-calls function to pointer-to-callable.
     Flaggged as incompatible.  */
  c_p = bal;
  /* The call through an interface-incompatible type will not use the
     modified interface expected by the at-calls function, so it is
     likely to misbehave at runtime.  */
  c_p ();
}

Контексты Strub никогда не встраиваются в контексты, не являющиеся strub. Когда функция internal-очистки стека разбивается, оболочка часто может быть встроена, но обернутое тело никогда не встраивается. Функция, помеченная как always_inline, даже если ей явно назначен режим очистки internal, не будет обернута, поэтому ее тело встраивается по мере необходимости.

inline int __attribute__ ((strub ("at-calls")))
inl_atc (void)
{
  /* This body may get inlined into strub contexts.  */
}

inline int __attribute__ ((strub ("internal")))
inl_int (void)
{
  /* This body NEVER gets inlined, though its wrapper may.  */
}

inline int __attribute__ ((strub ("internal"), always_inline))
inl_int_ali (void)
{
  /* No internal wrapper, so this body ALWAYS gets inlined,
     but it cannot be called from non-strub contexts.  */
}

void __attribute__ ((strub ("disabled")))
bat (void)
{
  /* Not allowed, cannot inline into a non-strub context.  */
  inl_int_ali ();
}

Некоторые параметры командной строки -fstrub=* неявно включают strub режимы там, где это возможно. Режим strub жизнеспособен для функции только если функция подходит для этого режима и если выполняются другие условия, описанные ниже. Если функция не подходит для режима, попытки явного связывания её с этим режимом отклоняются с сообщением об ошибке. Если она подходит, этот режим может быть назначен явно через этот атрибут, но неявное назначение через параметры командной строки может потребовать дополнительных условий жизнеспособности.

Функция не подходит для режима at-calls strub если запрошен другой режим strub, если присутствует атрибут noipa, или если она вызывает __builtin_apply_args. Режим At-calls strub , если он не запрошен через тип функции, жизнеспособен только для подходящей функции, если функция невидима для других единиц трансляции, если её адрес не взят, и если она никогда не вызывается с переопределением типа функции.

/* bar is eligible for at-calls strub mode,
   but not viable for that mode because it is visible to other units.
   It is eligible and viable for internal strub mode.  */
void bav () {}

/* setp is eligible for at-calls strub mode,
   but not viable for that mode because its address is taken.
   It is eligible and viable for internal strub mode.  */
void setp (void) { static void (*p)(void); = setp; }

Функция не подходит для режима internal strub если запрошен другой режим strub, или если присутствует атрибут noipa. Для функции always_inline выполнение этих требований достаточно для её пригодности. Любая функция, у которой есть атрибут noclone, которая использует такие расширения, как нелокальные метки, вычисленные переходы, альтернативные интерфейсы передачи аргументов переменной, __builtin_next_arg, или __builtin_return_address, или которая принимает слишком много аргументов (около 64К), не подходит, если только она не является always_inline. Для режима internal strub все подходящие функции жизнеспособны.

/* flop is not eligible, thus not viable, for at-calls strub mode.
   Likewise for internal strub mode.  */
__attribute__ ((noipa)) void flop (void) {}

/* flip is eligible and viable for at-calls strub mode.
   It would be ineligible for internal strub mode, because of noclone,
   if it weren't for always_inline.  With always_inline, noclone is not
   an obstacle, so it is also eligible and viable for internal strub mode.  */
inline __attribute__ ((noclone, always_inline)) void flip (void) {}
transparent_union

Этот атрибут, прикрепленный к определению типа union, указывает, что любой параметр функции с этим типом объединения вызывает вызовы этой функции, которые обрабатываются особым образом.

Во-первых, аргумент, соответствующий прозрачному типу объединения, может быть любого типа в объединении; преобразование не требуется. Кроме того, если объединение содержит тип указателя, соответствующий аргумент может быть константой нулевого указателя или выражением указателя типа void; а если объединение содержит тип указателя void, соответствующий аргумент может быть любым выражением указателя. Если тип члена объединения является указателем, квалификаторы, такие как const для типа, на который ссылается указатель, должны соблюдаться, как и при обычных преобразованиях указателей.

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

Прозрачные объединения предназначены для функций библиотек, которые имеют несколько интерфейсов по причинам совместимости. Например, предположим, что функция wait должна принимать либо значение типа int * для соответствия POSIX, либо значение типа union wait * для соответствия интерфейсу 4.1BSD. Если параметр wait был void *, wait бы принимал оба вида аргументов, но он также принимал бы любой другой тип указателя, и это сделало бы проверку типа аргумента менее полезной. Вместо этого <sys/wait.h> мог бы определить интерфейс следующим образом:

typedef union __attribute__ ((__transparent_union__))
  {
    int *__ip;
    union wait *__up;
  } wait_status_ptr_t;

pid_t wait (wait_status_ptr_t);

Этот интерфейс позволяет передавать аргументы int * или union wait *, используя соглашения вызова int *. Программа может вызвать wait с аргументами любого из типов:

int w1 () { int w; return wait (&w); }
int w2 () { union wait w; return wait (&w); }

С этим интерфейсом реализация wait может выглядеть так:

pid_t wait (wait_status_ptr_t p)
{
  return waitpid (-1, p.__ip, 0);
}
unavailable
unavailable (msg)

Атрибут unavailable ведёт себя так же, как и атрибут deprecated, но генерирует ошибку вместо предупреждения. Он используется для обозначения того, что тип (возможно, ранее deprecated) больше не может быть использован.

Атрибут unavailable также может быть использован для функций и переменных (см. Объявление атрибутов функций, см. Указание атрибутов переменных.)

unused

При присоединении к типу (включая union или struct) этот атрибут означает, что переменные этого типа могут быть неиспользуемыми. GCC не выдаёт предупреждения для переменных этого типа, даже если переменная, по-видимому, ничего не делает. Это часто происходит с классами блокировки или потоков, которые обычно определены и затем не ссылаются, но содержат конструкторы и деструкторы, которые имеют нетривиальные функции учёта.

vector_size (bytes)

Этот атрибут задаёт размер вектора для типа, измеряемый в байтах. Тип, к которому он применяется, известен как базовый тип. Аргумент bytes должен быть положительной степенью двойки, кратной размеру базового типа. Например, следующие объявления:

typedef __attribute__ ((vector_size (32))) int int_vec32_t ;
typedef __attribute__ ((vector_size (32))) int* int_vec32_ptr_t;
typedef __attribute__ ((vector_size (32))) int int_vec32_arr3_t[3];

определяют int_vec32_t как 32-байтовый векторный тип, состоящий из единиц размером int. При размере int в 4 байта, тип определяет вектор из восьми единиц, по четыре байта каждая. Режим переменных типа int_vec32_t равен V8SI. int_vec32_ptr_t затем определяется как указатель на такой векторный тип, а int_vec32_arr3_t — как массив из трёх таких векторов. Подробности работы с объектами векторных типов см. в разделе Использование векторных инструкций через встроенные функции.

Этот атрибут применим только к целочисленным и плавающим скалярным типам. В объявлениях функций атрибут применяется к возвращаемому типу функции.

Например, следующее:

__attribute__ ((vector_size (16))) float get_flt_vec16 (void);

объявляет get_flt_vec16 как функцию, возвращающую 16-байтовый вектор с базовым типом float.

visibility

В C++, атрибут видимости (см. Объявление атрибутов функций) также может применяться к типам class, struct, union и enum. В отличие от других атрибутов типа, атрибут должен располагаться между ключевым словом и именем типа; он не может появляться после тела типа.

Обратите внимание, что видимость типа применяется к неявным связным сущностям, связанным с классом (vtable, узел typeinfo и т. д.). В частности, если класс выброшен как исключение в одном общем объекте и перехвачен в другом, класс должен иметь стандартную видимость. В противном случае два общих объекта не смогут использовать один и тот же узел typeinfo, и обработка исключений будет нарушена.

warn_if_not_aligned (alignment)

Этот атрибут задаёт порог для поля структуры, измеряемый в байтах. Если выравнивание поля структуры ниже порога, будет выведено предупреждение. Например, объявление:

typedef unsigned long long __u64
   __attribute__((aligned (4), warn_if_not_aligned (8)));

struct foo
{
  int i1;
  int i2;
  __u64 x;
};

приводит к тому, что компилятор выводит предупреждение о struct foo, например, «предупреждение: выравнивание 4 для 'struct foo' меньше 8». Оно используется для определения struct foo таким образом, что struct foo имеет тот же макет, а поле структуры x имеет то же выравнивание, когда __u64 выровнено либо на 4, либо на 8 байта. Выравнивание struct foo на 8 байт:

struct __attribute__ ((aligned (8))) foo
{
  int i1;
  int i2;
  __u64 x;
};

отключает предупреждение. Компилятор также выводит предупреждение, например, «предупреждение: смещение 'x' 12 в 'struct foo' не выровнено по 8», когда поле структуры имеет неправильное смещение:

struct __attribute__ ((aligned (8))) foo
{
  int i1;
  int i2;
  int i3;
  __u64 x;
};

Это предупреждение можно отключить с помощью -Wno-if-not-aligned.

Для указания нескольких атрибутов разделяйте их запятыми в двойных скобках: например, «__attribute__ ((aligned (16), packed))».

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Type-Attributes.html

Spec-Zone.ru

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