Spec-Zone.ru › GCC 14

6.33.1 Общие атрибуты функций

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

access (access-mode, ref-index)
access (access-mode, ref-index, size-index)

Атрибут access позволяет обнаруживать некорректные или небезопасные обращения функций, к которым он применяется, или их вызывающих функций, а также односторонние записи в объекты, которые никогда не считываются. Такие обращения могут быть диагностированы с помощью предупреждений, таких как -Wstringop-overflow, -Wuninitialized, -Wunused и другие.

Атрибут access указывает, что функция, к аргументам которой по ссылке применяется атрибут, обращается к объекту по ссылке в соответствии с режимом-доступа. Аргумент режим-доступа обязателен и должен быть одним из четырёх имён: read_only, read_write, write_only, или none. Остальные два — позиционные аргументы.

Обязательный позиционный аргумент индекс-ссылки обозначает аргумент функции типа указателя (или, в C++, ссылки), который подлежит обращению. Один и тот же аргумент указателя может быть упомянут не более чем в одном отличительном атрибуте access.

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

Режим доступа read_only указывает, что указатель, к которому он применяется, используется для чтения объекта по ссылке, но не для записи в него. Если аргумент, определяющий размер доступа, обозначенный индекс-размера, не равен нулю, объект по ссылке должен быть инициализирован. Данный режим подразумевает более сильную гарантию, чем квалификатор const, который, когда снимается с указателя, не предотвращает модификацию объекта, на который указывает указатель. Примеры использования режима доступа read_only — аргумент функции puts, или второй и третий аргументы функции memcpy.

__attribute__ ((access (read_only, 1)))
int puts (const char*);

__attribute__ ((access (read_only, 2, 3)))
void* memcpy (void*, const void*, size_t);

Режим доступа read_write применяется к аргументам типа указателя без квалификатора const. Он указывает, что указатель, к которому он применяется, используется как для чтения, так и для записи в объект по ссылке. Если аргумент, определяющий размер доступа, обозначенный индекс-размера, не равен нулю, объект, на который указывает указатель, должен быть инициализирован. Пример использования режима доступа read_write — первый аргумент функции strcat.

__attribute__ ((access (read_write, 1), access (read_only, 2)))
char* strcat (char*, const char*);

Режим доступа write_only применяется к аргументам типа указателя без квалификатора const. Он указывает, что указатель, к которому он применяется, используется для записи в объект по ссылке, но не для чтения из него. Объект, на который указывает указатель, не обязательно должен быть инициализирован. Пример использования режима доступа write_only — первый аргумент функции strcpy, или первые два аргумента функции fgets.

__attribute__ ((access (write_only, 1), access (read_only, 2)))
char* strcpy (char*, const char*);

__attribute__ ((access (write_only, 1, 2), access (read_write, 3)))
int fgets (char*, int, FILE*);

Режим доступа none указывает, что указатель, к которому он применяется, вообще не используется для доступа к объекту по ссылке. Если указатель не равен нулю, объект по ссылке должен существовать и иметь как минимум тот размер, который обозначен аргументом индекс-размера. Когда необязательный аргумент индекс-размера опущен для аргумента типа void*, фактический аргумент указателя игнорируется. Объект по ссылке не обязательно должен быть инициализирован. Режим предназначен для проверки ожидаемого размера объекта, например, в функциях, которые вызывают __builtin_object_size. См. Проверка размера объекта.

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

alias ("target")

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

void __f () { /* Do something. */; }
void f () __attribute__ ((weak, alias ("__f")));

определяют ‘f’ как слабый псевдоним для ‘__f’. В C++, должно использоваться закодированное имя целевого символа. Ошибка возникает, если ‘__f’ не определено в той же единице трансляции.

Данный атрибут требует поддержки в ассемблере и объектных файлах и может быть недоступен на всех целевых платформах.

aligned
aligned (alignment)

Атрибут aligned задаёт минимальное выравнивание первого инструкций функции, измеряемое в байтах. При указании выравнивание должно быть целочисленной константой, являющейся степенью двойки. Не указание аргумента выравнивание подразумевает идеальное выравнивание для целевой платформы. Атрибут __alignof__ можно использовать для определения этого значения (см. Определение выравнивания функций, типов или переменных). Атрибут не имеет эффекта, если определение функции не предоставлено в той же единице трансляции.

Атрибут нельзя использовать для уменьшения выравнивания функции, ранее объявленной с более жёстким выравниванием; только для увеличения. Попытки сделать обратное будут диагностированы. Некоторые целевые платформы задают минимальное значение по умолчанию для выравнивания функций, большее 1. На таких платформах указание менее жёсткого выравнивания будет проигнорировано. Использование атрибута переопределяет действие опции -falign-functions (см. Опции, контролирующие оптимизацию) для данной функции.

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

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

alloc_align (position)

Атрибут alloc_align может быть применён к функции, возвращающей указатель и принимающей как минимум один аргумент целочисленного или перечислимого типа. Он указывает, что возвращаемый указатель выровнен на границе, заданной аргументом функции в позиции. Значимые значения выравнивания — степени двойки, большие единицы. GCC использует эту информацию для улучшения анализа выравнивания указателей.

Параметр функции, обозначающий выравнивание выделенной памяти, задаётся одним целочисленным аргументом, число которого является аргументом атрибута. Нумерация аргументов начинается с единицы.

Например,

void* my_memalign (size_t, size_t) __attribute__ ((alloc_align (1)));

объявляет, что my_memalign возвращает память с минимальным выравниванием, заданным параметром 1.

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

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

Параметр(ы) функции, обозначающие выделенный размер, задаются одним или двумя целочисленными аргументами, переданными атрибуту. Выделенный размер — либо значение единственного заданного аргумента функции, либо произведение двух заданных аргументов функции. Нумерация аргументов начинается с единицы для обычных функций и со второй для нестатических функций-членов в C++.

Например,

void* my_calloc (size_t, size_t) __attribute__ ((alloc_size (1, 2)));
void* my_realloc (void*, size_t) __attribute__ ((alloc_size (2)));

объявляет, что my_calloc возвращает память размера, равного произведению параметра 1 и 2, и что my_realloc возвращает память размера, равного параметру 2.

always_inline

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

artificial

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

assume_aligned (alignment)
assume_aligned (alignment, offset)

Атрибут assume_aligned может быть применён к функции, возвращающей указатель. Он указывает, что возвращаемый указатель выровнен на границе, заданной выравнивание. Если у атрибута есть два аргумента, второй аргумент — смещение невыравнивания смещение. Значимые значения выравнивание — степени двойки, большие единицы. Значимые значения смещение — больше нуля и меньше выравнивание.

Например

void* my_alloc1 (size_t) __attribute__((assume_aligned (16)));
void* my_alloc2 (size_t) __attribute__((assume_aligned (32, 8)));

объявляет, что my_alloc1 возвращает 16-байтовые выровненные указатели и что my_alloc2 возвращает указатель, значение которого по модулю 32 равно 8.

cold

Атрибут cold для функций сообщает компилятору, что функция вряд ли будет выполнена. Функция оптимизирована для размера, а не скорости, и на многих целевых платформах она размещается в специальной секции текстовой секции, чтобы все холодные функции располагались близко друг к другу, улучшая локальность кода для нехолодных частей программы. Пути, ведущие к вызовам холодных функций в коде, отмечаются как маловероятные механизмом предсказания ветвей. Поэтому полезно помечать функции, используемые для обработки маловероятных условий, такие как perror, как холодные, чтобы улучшить оптимизацию горячих функций, которые иногда вызывают помеченные функции. В C++, атрибут cold может быть применён к типам с эффектом распространения на методы-члены. См. C++-специфические атрибуты переменных, функций и типов.

Когда доступна обратная связь профилирования, через -fprofile-use, холодные функции автоматически обнаруживаются, и этот атрибут игнорируется.

const

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

Например,

int square (int) __attribute__ ((const));

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

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

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

Обратите внимание, что функция с указателями в качестве аргументов и проверяющая данные по указателям не должна быть объявлена const, если данные, на которые указывают указатели, могут измениться между последовательными вызовами функции. В общем случае, поскольку функция не может отличить данные, которые могут измениться, от данных, которые не могут, константные функции никогда не должны принимать указатели или, в C++, ссылки в качестве аргументов. Аналогично, функция, которая вызывает неконстантную функцию, обычно не должна быть константной.

constructor
destructor
constructor (priority)
destructor (priority)

Атрибут constructor вызывает автоматический вызов функции перед входом в main (). Аналогично, атрибут destructor вызывает автоматический вызов функции после завершения main () или вызова exit (). Функции с этими атрибутами полезны для инициализации данных, которые используются неявно во время выполнения программы.

На некоторых целевых платформах атрибуты также принимают целочисленный аргумент для задания приоритета, чтобы контролировать порядок выполнения функций-конструкторов и деструкторов. Конструктор с меньшим номером приоритета выполняется перед конструктором с большим номером приоритета; обратное отношение верно для деструкторов. Обратите внимание, что приоритеты 0-100 зарезервированы. Поэтому, если у вас есть конструктор, который выделяет ресурс, и деструктор, который освобождает этот же ресурс, обе функции обычно имеют одинаковый приоритет. Приоритеты для функций-конструкторов и деструкторов такие же, как и для объектов C++ на уровне пространства имён (см. C++-специфические атрибуты переменных, функций и типов). Однако в настоящее время порядок вызова конструкторов для объектов C++ со статическим временем хранения и функций, помеченных атрибутом constructor, не определён. При смешанных объявлениях атрибут init_priority может быть использован для навязывания определённого порядка.

Использование форм аргументов атрибутов constructor и destructor на целевых платформах, где эта функция не поддерживается, приводит к ошибке.

copy
copy (function)

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

Например, макрос StrongAlias ниже использует атрибуты alias и copy для определения псевдонима, названного alloc, для функции allocate, объявленной с атрибутами alloc_size, malloc и nothrow. Благодаря оператору __typeof__ псевдоним имеет тот же тип, что и целевая функция. В результате атрибута copy псевдоним также разделяет те же атрибуты, что и целевая функция.

#define StrongAlias(TargetFunc, AliasDecl)  \
  extern __typeof__ (TargetFunc) AliasDecl  \
    __attribute__ ((alias (#TargetFunc), copy (TargetFunc)));

extern __attribute__ ((alloc_size (1), malloc, nothrow))
  void* allocate (size_t);
StrongAlias (allocate, alloc);
deprecated
deprecated (msg)

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

int old_fn () __attribute__ ((deprecated));
int old_fn ();
int (*fn_ptr)() = old_fn;

приводит к появлению предупреждения на строке 3, но не на строке 2. Необязательный аргумент msg, который должен быть строкой, печатается в предупреждении, если он присутствует.

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

Сообщение, связанное с атрибутом, зависит от настройки параметра -fmessage-length.

error ("message")
warning ("message")

Если атрибут error или warning используется в объявлении функции, и вызов такой функции не устраняется благодаря устранению неиспользуемого кода или другим оптимизациям, генерируется ошибка или предупреждение (соответственно), содержащее сообщение. Это полезно для проверки на этапе компиляции, особенно вместе с __builtin_constant_p и встроенными функциями, где проверка аргументов встроенной функции невозможна с помощью extern char [(condition) ? 1 : -1]; уловок.

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

expected_throw

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

Этот намёк в основном игнорируется компилятором. Единственный эффект наблюдается, когда он применяется к функциям noreturn и включен параметр «-fharden-control-flow-redundancy», и параметр «-fhardcfr-check-noreturn-calls=not-always» не переопределён.

externally_visible

Этот атрибут, прикреплённый к глобальной переменной или функции, делает недействительным действие командной строки -fwhole-program, поэтому объект остаётся видимым вне текущей единицы компиляции.

Если -fwhole-program используется вместе с -flto и gold используется в качестве плагина компоновки, атрибуты externally_visible автоматически добавляются к функциям (не к переменным пока из-за текущей gold проблемы) которые обращаются за пределами объектов LTO в соответствии с файлом разрешения, созданным gold. Для других компоновочных модулей, которые не могут сгенерировать файл разрешения, явные атрибуты externally_visible всё равно необходимы.

fd_arg
fd_arg (N)

Атрибут fd_arg может быть применён к функции, которая принимает открытый дескриптор файла в аргументе N.

Он указывает, что переданный дескриптор файла не должен быть закрыт. Поэтому, когда анализатор включён с помощью -fanalyzer, анализатор может выдать диагностику -Wanalyzer-fd-use-after-close, если обнаружит путь кода, в котором функция с этим атрибутом вызывается с закрытым дескриптором файла.

Атрибут также указывает, что дескриптор файла должен быть проверен на корректность перед использованием. Поэтому анализатор может выдать диагностику -Wanalyzer-fd-use-without-check, если обнаружит путь кода, в котором функция с этим атрибутом вызывается с дескриптором файла, который не был проверен на корректность.

fd_arg_read
fd_arg_read (N)

Атрибут fd_arg_read идентичен атрибуту fd_arg, но с дополнительным требованием, что он может читать из дескриптора файла, а значит, дескриптор файла не должен был быть открыт только для записи.

Анализатор может вывести диагностическое сообщение -Wanalyzer-access-mode-mismatch, если обнаружит путь выполнения кода, в котором функция с этим атрибутом вызывается с дескриптором файла, открытым с помощью O_WRONLY.

fd_arg_write
fd_arg_write (N)

Атрибут fd_arg_write идентичен атрибуту fd_arg_read, за исключением того, что анализатор может вывести диагностическое сообщение -Wanalyzer-access-mode-mismatch, если обнаружит путь выполнения кода, в котором функция с этим атрибутом вызывается с дескриптором файла, открытым с помощью O_RDONLY.

flatten

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

format (archetype, string-index, first-to-check)

Атрибут format указывает, что функция принимает аргументы типа printf, scanf, strftime или strfmon, которые должны быть проверены на соответствие строке формата. Например, объявление:

extern int
my_printf (void *my_object, const char *my_format, ...)
      __attribute__ ((format (printf, 2, 3)));

приводит к тому, что компилятор проверяет аргументы в вызовах функции my_printf на соответствие строке формата стиля printf аргументу my_format.

Параметр archetype определяет, как интерпретируется строка формата, и должен быть printf, scanf, strftime, gnu_printf, gnu_scanf, gnu_strftime или strfmon. (Также можно использовать __printf__, __scanf__, __strftime__ или __strfmon__. На целевых платформах MinGW также присутствуют ms_printf, ms_scanf и ms_strftime. Значения archetype, такие как printf, относятся к форматам, поддерживаемым системной библиотекой C runtime, а значения, начинающиеся с ‘gnu_’, всегда относятся к форматам, поддерживаемым GNU C Library. На целевых платформах Microsoft Windows значения, начинающиеся с ‘ms_’, относятся к форматам, поддерживаемым библиотекой msvcrt.dll. Параметр string-index указывает, какой аргумент является аргументом строки формата (начиная с 1), а first-to-check — номер первого аргумента для проверки по отношению к строке формата. Для функций, где аргументы недоступны для проверки (например, vprintf), укажите третий параметр как ноль. В этом случае компилятор проверяет только строку формата на соответствие. Для форматов strftime третий параметр должен быть равен нулю. Так как у нестатических методов C++ есть неявный аргумент this, аргументы таких методов следует считать с двух, а не с одного, при указании значений для string-index и first-to-check.

В примере выше строка формата (my_format) является вторым аргументом функции my_print, а проверяемые аргументы начинаются с третьего, поэтому правильные параметры для атрибута формата — 2 и 3.

Атрибут format позволяет идентифицировать собственные функции, принимающие строки формата в качестве аргументов, чтобы GCC мог проверять вызовы этих функций на ошибки. Компилятор всегда (если не используется -ffreestanding или -fno-builtin) проверяет форматы для стандартных функций библиотеки printf, fprintf, sprintf, scanf, fscanf, sscanf, strftime, vprintf, vfprintf и vsprintf, когда такие предупреждения запрашиваются (с помощью -Wformat), поэтому нет необходимости изменять заголовочный файл stdio.h. В режиме C99 также проверяются функции snprintf, vsnprintf, vscanf, vfscanf и vsscanf. Кроме строго соответствующих режимов стандарта C, функция X/Open strfmon также проверяется, как и printf_unlocked и fprintf_unlocked. См. Параметры, контролирующие диалект C.

Для диалектов Objective-C, NSString (или __NSString__) распознается в том же контексте. Объявления, включающие эти атрибуты формата, анализируются на правильность синтаксиса, однако результат проверки таких строк формата пока не определён и не выполняется этой версией компилятора.

Цель может также предоставлять дополнительные типы проверок форматов. См. Проверки форматов, специфичные для конкретных целевых машин.

format_arg (string-index)

Атрибут format_arg указывает, что функция принимает одну или несколько строк формата для функции типа printf, scanf, strftime или strfmon и модифицирует её (например, переводит её на другой язык), чтобы результат мог быть передан функции типа printf, scanf, strftime или strfmon (при сохранении остальных аргументов функции формата). К одной функции могут быть применены несколько атрибутов format_arg, каждый из которых обозначает отдельный параметр в качестве строки формата. Например, объявление:

extern char *
my_dgettext (char *my_domain, const char *my_format)
      __attribute__ ((format_arg (2)));

приводит к проверке компилятором аргументов в вызовах функций типа printf, scanf, strftime или strfmon, аргумент строки формата которых является вызовом функции my_dgettext, на соответствие строке формата my_format. Если бы атрибут format_arg не был указан, компилятор мог бы лишь определить, что аргумент строки формата не является константой; это вызвало бы предупреждение при использовании -Wformat-nonliteral, но вызовы не могли бы быть проверены без атрибута.

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

Параметр string-index указывает, какой аргумент является аргументом строки формата (начиная с единицы). Поскольку у нестатических методов C++ есть неявный аргумент this, аргументы таких методов следует считать с двух.

Атрибут format_arg позволяет идентифицировать собственные функции, которые изменяют строки формата, чтобы GCC мог проверять вызовы функций типа printf, scanf, strftime или strfmon, операнды которых являются вызовом одной из ваших собственных функций. Компилятор всегда обрабатывает gettext, dgettext, и dcgettext таким образом, за исключением случаев запроса строгой поддержки ISO C с помощью -ansi или соответствующего параметра -std, или если используется -ffreestanding или -fno-builtin. См. Параметры, контролирующие диалект C.

Для диалектов Objective-C атрибут format-arg может ссылаться на NSString ссылку для совместимости с атрибутом format выше.

Цель может также разрешить дополнительные типы в атрибутах format-arg. См. Проверки форматов, специфичные для конкретных целевых машин.

gnu_inline

Этот атрибут следует использовать с функцией, которая также объявлена с ключевым словом inline. Он направляет GCC рассматривать функцию так, как если бы она была определена в режиме gnu90, даже при компиляции в режимах C99 или gnu99.

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

В C, если функция не extern и не static, тогда функция компилируется как самостоятельная функция, а также встраивается, где возможно.

Так GCC традиционно обрабатывал функции, объявленные inline. Поскольку ISO C99 определяет разные семантику для inline, этот атрибут функции предоставляется как мера перехода и как полезная функция сама по себе. Этот атрибут доступен в GCC 4.1.3 и новее. Он доступен, если определён один из препроцессорных макросов __GNUC_GNU_INLINE__ или __GNUC_STDC_INLINE__. См. Функция, помеченная как inline, так же быстрая, как и макрос.

В C++, этот атрибут никак не зависит от extern, но всё ещё требует ключевое слово inline для включения своего специального поведения.

hot

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

Когда обратная связь профилирования доступна через -fprofile-use, горячие функции автоматически обнаруживаются, и этот атрибут игнорируется.

ifunc ("resolver")

Атрибут ifunc используется для маркировки функции как косвенной функции, используя расширение типа символа STT_GNU_IFUNC к стандарту ELF. Это позволяет динамически определить значение символа во время загрузки и выбрать оптимизированную версию подпрограммы для конкретного процессора или других характеристик системы, определенных в этот момент. Для использования этого атрибута сначала необходимо определить доступные реализации функций и функцию-резольвер, которая возвращает указатель на выбранную реализующую функцию. Объявления реализующих функций должны соответствовать API реализуемой функции. Функция-резольвер должна быть объявлена как функция без аргументов, возвращающая указатель на функцию того же типа, что и реализация. Например:

void *my_memcpy (void *dst, const void *src, size_t len)
{
  …
  return dst;
}

static void * (*resolve_memcpy (void))(void *, const void *, size_t)
{
  return my_memcpy; // we will just always select this routine
}

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

extern void *memcpy (void *, const void *, size_t);

позволяя пользователю вызывать memcpy как обычную функцию, не зная фактической реализации. Наконец, косвенная функция должна быть определена в том же модуле трансляции, что и функция-резольвер:

void *memcpy (void *, const void *, size_t)
     __attribute__ ((ifunc ("resolve_memcpy")));

В C++, атрибут ifunc принимает строку, которая является искаженным именем функции-резольвера. Функция-резольвер C++ для нестатического метода-члена класса C должна быть объявлена для возврата указателя на функцию без указания класса, принимающую указатель на C в качестве первого аргумента, за которым следуют те же аргументы, что и в реализующей функции. G++ проверяет подписи двух функций и выдает предупреждение -Wattribute-alias при несовпадениях. Чтобы подавить предупреждение о необходимости приведения от указателя на реализующий член функции к типу соответствующей функции без указания класса, используйте опцию -Wno-pmf-conversions. Например:

class S
{
private:
  int debug_impl (int);
  int optimized_impl (int);

  typedef int Func (S*, int);

  static Func* resolver ();
public:

  int interface (int);
};

int S::debug_impl (int) { /* … */ }
int S::optimized_impl (int) { /* … */ }

S::Func* S::resolver ()
{
  int (S::*pimpl) (int)
    = getenv ("DEBUG") ? &S::debug_impl : &S::optimized_impl;

  // Cast triggers -Wno-pmf-conversions.
  return reinterpret_cast<Func*>(pimpl);
}

int S::interface (int) __attribute__ ((ifunc ("_ZN1S8resolverEv")));

Косвенные функции не могут быть слабыми. Для использования этой функции требуются версия бинарных утилит 2.20.1 или выше и GNU C Library версии 2.11.1 или выше.

interrupt
interrupt_handler

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

leaf

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

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

Обратите внимание, что функции-листья могут косвенно запускать обработчик сигналов, определённый в текущем модуле компиляции, который использует статические переменные. Аналогично, при отложенном разрешении символов функции-листья могут вызывать косвенные функции, функция-резольвер или реализующая функция которых определены в текущем модуле компиляции и используют статические переменные. Нет стандартного способа написать такой обработчик сигналов, функцию-резольвер или реализующую функцию, и лучше всего удалить атрибут leaf или отметить все такие статические переменные volatile. Наконец, для систем ELF, поддерживающих интерпозицию символов, следует позаботиться о том, чтобы функции, определённые в текущем модуле компиляции, не интерпонировали другие символы непредвиденным образом, исходя из определённого стандартного режима и определённых макросов тестов функций; в противном случае будет добавлен нежелательный обратный вызов.

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

malloc
malloc (deallocator)
malloc (deallocator, ptr-index)

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

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

Использование атрибута без аргументов предназначено для улучшения оптимизации, опираясь на свойство алиасирования, которое он подразумевает. Функции, подобные malloc и calloc, обладают этим свойством, так как они возвращают указатель на неинициализированное или обнуленное, недавно полученное хранилище. Однако функции, подобные realloc, не обладают этим свойством, так как они могут возвращать указатели на хранилище, содержащее указатели на существующие объекты. Кроме того, поскольку все такие функции предполагаются возвращающими null только нечасто, вызывающие функции могут оптимизироваться на основе этого предположения.

Связывание функции с deallocator помогает обнаруживать вызовы несовпадающих функций выделения и освобождения и диагностировать их под управлением таких опций, как -Wmismatched-dealloc. Это также позволяет диагностировать попытки освобождения объектов, которые не были выделены динамически, с помощью -Wfree-nonheap-object. Для указания того, что функция выделения удовлетворяет свойству неалиасирования и имеет связанную функцию освобождения, необходимо использовать как обычную форму атрибута, так и форму с аргументом deallocator. Одна и та же функция может быть как функцией выделения, так и функцией освобождения. Поскольку инлайнинг одной из связанных функций, но не другой, может привести к видимым несовпадениям, эта форма атрибута malloc не принимается для инлайновых функций. По той же причине использование атрибута предотвращает инлайнинг как функции выделения, так и функции освобождения.

Например, помимо утверждения о том, что функции возвращают указатели, не являющиеся алиасами других, следующие объявления делают fclose подходящей функцией освобождения для указателей, возвращаемых из всех функций, кроме popen, а pclose — единственной подходящей функцией освобождения для указателей, возвращаемых из popen. Функции освобождения должны быть объявлены до их использования в атрибуте.

int fclose (FILE*);
int pclose (FILE*);

__attribute__ ((malloc, malloc (fclose, 1)))
  FILE* fdopen (int, const char*);
__attribute__ ((malloc, malloc (fclose, 1)))
  FILE* fopen (const char*, const char*);
__attribute__ ((malloc, malloc (fclose, 1)))
  FILE* fmemopen(void *, size_t, const char *);
__attribute__ ((malloc, malloc (pclose, 1)))
  FILE* popen (const char*, const char*);
__attribute__ ((malloc, malloc (fclose, 1)))
  FILE* tmpfile (void);

Предупреждения, защищённые -fanalyzer, учитывают пары выделения и освобождения, помеченные атрибутом malloc. В частности:

  • Анализатор выводит диагностику -Wanalyzer-mismatching-deallocation, если существует путь выполнения, в котором результат вызова выделения передаётся другому освободителю.
  • Анализатор выводит диагностику -Wanalyzer-double-free, если существует путь выполнения, в котором значение передаётся более одного раза в вызов освобождения.
  • Анализатор рассматривает возможность того, что функция выделения может завершиться неудачей и вернуть null. Если существуют пути выполнения, в которых результат вызова выделения, не проверяемый на null, дереферируется или передаётся в функцию, требующую не-null аргумент, он выводит диагностики -Wanalyzer-possible-null-dereference и -Wanalyzer-possible-null-argument. Если функция выделения всегда возвращает не-null, используйте __attribute__ ((returns_nonnull)) для подавления этих предупреждений. Например:
    char *xstrdup (const char *)
      __attribute__((malloc (free), returns_nonnull));
  • Анализатор выводит диагностику -Wanalyzer-use-after-free, если существует путь выполнения, в котором память, переданная по указателю в вызов освобождения, используется после освобождения.
  • Анализатор выводит диагностику -Wanalyzer-malloc-leak, если существует путь выполнения, в котором результат вызова выделения утечка (без передачи освободителю).
  • Анализатор выводит диагностику -Wanalyzer-free-of-non-heap, если функция освобождения используется на глобальной или стековой переменной.

Анализатор предполагает, что освободители могут корректно обрабатывать указатель null. Если это не так, освободитель может быть помечен __attribute__((nonnull)), чтобы -fanalyzer мог выводить диагностику -Wanalyzer-possible-null-argument для путей кода, в которых освободитель вызывается с null.

no_icf

Этот атрибут функции предотвращает слияние функции с другой семантически эквивалентной функцией.

no_instrument_function

Если заданы опции -finstrument-functions, -p или -pg, генерируются функции профилирования для вызовов функций в начале и конце большинства функций, скомпилированных пользователем. Функции с этим атрибутом не профилируются.

no_profile_instrument_function

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

no_reorder

Не переупорядочивайте функции или переменные, помеченные как no_reorder, относительно друг друга или инструкций ассемблера верхнего уровня в исполняемом файле. Фактический порядок в программе будет зависеть от командной строки линкера. Статические переменные, помеченные таким образом, также не удаляются. Это имеет аналогичный эффект, как опция -fno-toplevel-reorder, но применяется только к помеченным символам.

no_sanitize ("sanitize_option")

Атрибут no_sanitize для функций используется для информирования компилятора о том, что он не должен выполнять проверку на наличие указанных в sanitize_option опций. Можно предоставить список значений, допустимых для опции -fsanitize.

void __attribute__ ((no_sanitize ("alignment", "object-size")))
f () { /* Do something. */; }
void __attribute__ ((no_sanitize ("alignment,object-size")))
g () { /* Do something. */; }
no_sanitize_address
no_address_safety_analysis

Атрибут no_sanitize_address для функций используется для информирования компилятора о том, что он не должен инструментировать доступ к памяти в функции при компиляции с опцией -fsanitize=address. Атрибут no_address_safety_analysis является устаревшим псевдонимом атрибута no_sanitize_address, в новом коде следует использовать no_sanitize_address.

no_sanitize_thread

Атрибут no_sanitize_thread для функций используется для информирования компилятора о том, что он не должен инструментировать доступ к памяти в функции при компиляции с опцией -fsanitize=thread.

no_sanitize_undefined

Атрибут no_sanitize_undefined для функций используется для информирования компилятора о том, что он не должен проверять неопределенное поведение в функции при компиляции с опцией -fsanitize=undefined.

no_sanitize_coverage

Атрибут no_sanitize_coverage для функций используется для информирования компилятора о том, что он не должен включать инструментирование для поведенческой fuzzing-тестирования на основе покрытия кода (-fsanitize-coverage).

no_split_stack

Если задана опция -fsplit-stack, функции имеют небольшой пролог, который определяет, следует ли разделить стек. Функции с атрибутом no_split_stack не имеют этого пролога и, следовательно, могут выполняться только с небольшим объёмом доступной памяти стека.

no_stack_limit

Этот атрибут локально переопределяет опции командной строки -fstack-limit-register и -fstack-limit-symbol; он имеет эффект отключения проверки ограничений стека в функции, к которой он применяется.

no_stack_protector

Этот атрибут предотвращает код защиты стека для функции.

noclone

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

noinline

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

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

asm ("");

(см. Расширенный ассемблер — инструкции ассемблера с операндами выражений C) в вызываемой функции, чтобы использовать её как особый побочный эффект.

noipa

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

nonnull
nonnull (arg-index, …)

Атрибут nonnull может быть применён к функции, которая принимает по крайней мере один аргумент типа указателя. Он указывает, что ссылаемые аргументы должны быть указателями, отличными от нуля. Например, объявление:

extern void *
my_memcpy (void *dest, const void *src, size_t len)
        __attribute__((nonnull (1, 2)));

информирует компилятор о том, что в вызовах my_memcpy аргументы dest и src должны быть указателями, отличными от нуля.

Атрибут влияет как на вызовы функций, так и на определения функций.

Для вызовов функций:

  • Если компилятор определяет, что указатель с нулевым значением передаётся в аргумент, помеченный как не нулевой, и опция -Wnonnull включена, выводится предупреждение. См. Опции для запроса или подавления предупреждений.
  • Опция -fisolate-erroneous-paths-attribute может быть задана для того, чтобы GCC преобразовывал вызовы с аргументами со значением NULL в функции, ожидающие не NULL, в ловушки. См. Опции, управляющие оптимизацией.
  • Компилятор также может выполнять оптимизации, основанные на знании, что некоторые аргументы функций не могут быть NULL. Эти оптимизации можно отключить с помощью опции -fno-delete-null-pointer-checks. См. Опции, управляющие оптимизацией.

Для определений функций:

  • Если компилятор определяет, что параметр функции, помеченный как nonnull, сравнивается с нулём, и опция -Wnonnull-compare включена, выводится предупреждение. См. Опции для запроса или подавления предупреждений.
  • Компилятор также может выполнять оптимизации, основанные на знании, что параметры nonnull не могут быть нулём. В настоящее время это невозможно отключить иначе, чем удалением атрибута nonnull.

Если атрибуту nonnull не указан arg-index, все аргументы типа указателя помечаются как не равные нулю. Чтобы проиллюстрировать это, следующее объявление эквивалентно предыдущему примеру:

extern void *
my_memcpy (void *dest, const void *src, size_t len)
        __attribute__((nonnull));
noplt

Атрибут noplt является аналогом опции -fno-plt. Вызовы функций, помеченных этим атрибутом в позиционно-независимом коде, не используют PLT.

/* Externally defined function foo.  */
int foo () __attribute__ ((noplt));

int
main (/* … */)
{
  /* … */
  foo ();
  /* … */
}

Атрибут noplt для функции foo сообщает компилятору, что функция foo определена внешне и вызов foo должен избегать PLT в позиционно-независимом коде.

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

noreturn

Некоторые стандартные функции библиотеки, такие как abort и exit, не могут возвращаться. GCC автоматически это знает. Некоторые программы определяют собственные функции, которые никогда не возвращаются. Вы можете объявить их как noreturn , чтобы сообщить об этом компилятору. Например,

void fatal () __attribute__ ((noreturn));

void
fatal (/* … */)
{
  /* … */ /* Print error message. */ /* … */
  exit (1);
}

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

Ключевое слово noreturn не влияет на исключительный путь, если он применяется: функция с меткой noreturn может всё ещё возвращаться вызывающей функции, выбросив исключение или вызвав longjmp.

Для сохранения трассировок GCC никогда не преобразует вызовы функций noreturn в tail-вызовы.

Не предполагайте, что регистры, сохранённые вызывающей функцией, будут восстановлены до вызова функции noreturn.

Для функции noreturn не имеет смысла иметь тип возвращаемого значения, отличный от void.

nothrow

Атрибут nothrow используется для информирования компилятора о том, что функция не может выбросить исключение. Например, большинство функций в стандартной библиотеке C могут быть гарантированы как не вызывающие исключений, за исключением qsort и bsearch, которые принимают аргументы типа указателя на функцию.

null_terminated_string_arg
null_terminated_string_arg (N)

Атрибут null_terminated_string_arg может быть применён к функции, принимающей char * или const char * в качестве аргумента N.

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

В частности, при включённом анализаторе (через -fanalyzer), если указатель не равен нулю, он будет имитировать поиск первого нулевого байта в указанном буфере и, возможно, выводить -Wanalyzer-use-of-uninitialized-value или -Wanalyzer-out-of-bounds при некорректно завершённых буферах.

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

char *example_1 (const char *p)
  __attribute__((null_terminated_string_arg (1)));

анализатор проверит, что все указатели, переданные функции, корректно завершены.

Если параметр должен быть не нулевым, целесообразно использовать как этот атрибут, так и атрибут nonnull, например:

extern char *example_2 (const char *p)
  __attribute__((null_terminated_string_arg (1),
                 nonnull (1)));

Дополнительную информацию и замечания см. в атрибуте nonnull.

Если аргумент-указатель также упоминается с помощью атрибута access в функции с access-mode либо read_only, либо read_write, и последний атрибут имеет необязательный аргумент size-index, ссылающийся на аргумент размера, это выражает максимальный размер доступа. Например, при:

extern char *example_fn (const char *p, size_t n)
  __attribute__((null_terminated_string_arg (1),
                 access (read_only, 1, 2),
                 nonnull (1)));

анализатор потребует, чтобы первый параметр был не нулевым и либо корректно завершался нулём, либо корректно считывался до размера, заданного вторым параметром.

optimize (level, …)
optimize (string, …)

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

Допустимые аргументы — это константные неотрицательные целые числа и строки. Каждый числовой аргумент задаёт уровень оптимизации level. Каждый строковый аргумент состоит из одной или нескольких подстрок, разделённых запятыми. Каждая подстрока, начинающаяся с буквы O, относится к параметру оптимизации, такому как -O0 или -Os. Другие подстроки рассматриваются как суффиксы префикса -f и вместе образуют имя параметра оптимизации. См. Параметры, контролирующие оптимизацию.

‘#pragma GCC optimize’ может быть использован для установки параметров оптимизации для более чем одной функции. См. Специальные параметры оптимизации для функций для подробностей о псевдокоманде.

Предоставление нескольких строк в качестве аргументов, разделённых запятыми, для задания нескольких параметров, эквивалентно разделению суффиксов параметров запятой (‘,’) в одной строке. Пробелы внутри строк запрещены.

Не каждый параметр оптимизации, начинающийся с префикса -f и указанный в атрибуте, обязательно повлияет на функцию. Атрибут optimize следует использовать только для отладки. Он не подходит для кода в производственной среде.

patchable_function_entry

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

Атрибут функции patchable_function_entry может быть использован для изменения количества NOP на любое желаемое значение. Двухзначный синтаксис аналогичен переключателю командной строки -fpatchable-function-entry=N,M, генерирующему N команд NOP, при этом точка входа функции находится перед M-ой командой NOP. M по умолчанию равен 0, если опущен, например, точка входа функции находится перед первой командой NOP.

Если глобально включить поддержку патчабельных точек входа функций с помощью опции командной строки -fpatchable-function-entry=N,M, то необходимо отключить инструментирование для всех функций, которые являются частью инструментального фреймворка, с помощью атрибута patchable_function_entry (0) для предотвращения рекурсии.

pure

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

Атрибут pure запрещает функции изменять состояние программы, наблюдаемое другими средствами, кроме проверки значения возврата функции. Тем не менее, функции, объявленные с атрибутом pure могут безопасно считывать любые непеременные объекты и изменять значение объектов таким образом, чтобы это не повлияло на их значение возврата или наблюдаемое состояние программы.

Например,

int hash (char *) __attribute__ ((pure));

говорит GCC, что последующие вызовы функции hash со строкой, которая уже использовалась, могут быть заменены результатом первого вызова при условии, что состояние программы, которое может наблюдать hash, в том числе содержимое самого массива, не изменится между вызовами. Несмотря на то, что hash принимает аргумент-указатель без const, он не должен изменять массив, на который он указывает, или любой другой объект, значение которого может зависеть от остальной части программы. Однако вызывающая программа может безопасно изменять содержимое массива между последовательными вызовами функции (так как это отключает оптимизацию). Ограничение также относится к объектам-членам, на которые указывает указатель this в нестатических функциях-членах C++.

Некоторые общие примеры чистых функций — strlen или memcmp. Интересные нечистые функции — функции с бесконечными циклами или функции, зависящие от переменной памяти или других системных ресурсов, которые могут измениться между последовательными вызовами (например, стандартная C feof функция в среде многопоточности).

Атрибут pure накладывает аналогичные, но менее строгие ограничения на определение функции, чем атрибут const: pure позволяет функции считывать любые непеременные данные памяти, даже если они изменяются между последовательными вызовами функции. Объявление одной и той же функции с обоих атрибутами pure и const даёт диагностическое сообщение. Поскольку чистая функция не может иметь побочных эффектов, не имеет смысла, чтобы такая функция возвращала void. Объявление такой функции даёт диагностическое сообщение.

retain

Для целевых объектов ELF, которые поддерживают GNU или FreeBSD OSABI, этот атрибут спасёт функцию от удаления сборщиком мусора линковщика. Для поддержки этого поведения функции, которые не были помещены в определённые разделы (например, атрибутом section или опцией -ffunction-sections), будут помещены в новые уникальные разделы.

Для этой дополнительной функциональности требуется версия Binutils 2.36 или более поздняя.

returns_nonnull

Атрибут returns_nonnull указывает, что значение возврата функции должно быть указателем, не равным нулю. Например, объявление:

extern void *
mymalloc (size_t len) __attribute__((returns_nonnull));

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

returns_twice

Атрибут returns_twice сообщает компилятору, что функция может возвращать значение более одного раза. Компилятор гарантирует, что все регистры освобождены перед вызовом такой функции, и выводит предупреждение о переменных, которые могут быть изменены после второго возврата из функции. Примерами таких функций являются setjmp и vfork. Аналогичная функция, если она есть, может потребовать маркировки атрибутом noreturn.

section ("section-name")

Обычно компилятор помещает сгенерированный код в раздел text. Иногда, однако, вам требуются дополнительные разделы, или вам нужны определённые функции, чтобы появляться в специальных разделах. Атрибут section указывает, что функция находится в определённом разделе. Например, объявление:

extern void foobar (void) __attribute__ ((section ("bar")));

помещает функцию foobar в раздел bar.

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

sentinel
sentinel (position)

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

__attribute__ ((sentinel))
is equivalent to
__attribute__ ((sentinel(0)))

Атрибут автоматически устанавливается с позицией 0 для встроенных функций execl и execlp. У встроенной функции execle атрибут установлен с позицией 1.

Действительный NULL в этом контексте определяется как ноль с любым типом указателя объекта. Если ваша система определяет макрос NULL с типом целого числа, вам необходимо добавить явное приведение типов. Во время установки GCC заменяет системный заголовок <stddef.h> копией, которая корректно переопределяет NULL.

Предупреждения о пропущенных или неправильных сигнальных элементах включаются с помощью -Wformat.

simd
simd("mask")

Этот атрибут позволяет создать одну или несколько версий функции, которые могут обрабатывать несколько аргументов с использованием инструкций SIMD из одного вызова. Указание этого атрибута позволяет компилятору предположить, что такие версии доступны во время линковки (предоставлены в том же или другом модуле трансляции). Сгенерированные версии зависят от целевой платформы и описаны в соответствующем документе Vector ABI. Для целевой платформы x86_64 этот документ можно найти здесь.

Необязательный аргумент mask может иметь значение notinbranch или inbranch, и соответственно инструктирует компилятор генерировать не-маскированные или маскированные клоны. По умолчанию генерируются все клоны.

Если атрибут указан и #pragma omp declare simd присутствует в объявлении, а также задан ключ -fopenmp или -fopenmp-simd, то атрибут игнорируется.

stack_protect

Этот атрибут добавляет код защиты стека к функции, если установлены флаги -fstack-protector, -fstack-protector-strong или -fstack-protector-explicit.

symver ("name2@nodename")

На целевых платформах ELF этот атрибут создает версию символа. Часть name2 параметра — это фактическое имя символа, по которому к нему будет осуществляться внешний доступ. Часть nodename должна быть именем узла, указанного в скрипте версии, предоставляемом линковщику при построении разделяемой библиотеки. Версионированный символ должен быть определен и должен быть экспортирован со стандартной видимостью.

__attribute__ ((__symver__ ("foo@VERS_1"))) int
foo_v1 (void)
{
}

Это приведет к направлению .symver foo_v1, foo@VERS_1 в выходных данных ассемблера.

Можно также определить несколько версий для данного символа (начиная с binutils 2.35).

__attribute__ ((__symver__ ("foo@VERS_2"), __symver__ ("foo@VERS_3")))
int symver_foo_v1 (void)
{
}

Этот пример создает имя символа symver_foo_v1, который будет иметь версию VERS_2 и VERS_3 символа foo.

Если у вас более старая версия binutils, то необходимо использовать псевдоним символа:

__attribute__ ((__symver__ ("foo@VERS_2")))
int foo_v1 (void)
{
  return 0;
}

__attribute__ ((__symver__ ("foo@VERS_3")))
__attribute__ ((alias ("foo_v1")))
int symver_foo_v1 (void);

Наконец, если параметр равен "name2@@nodename", то помимо создания версии символа (как если бы использовалось "name2@nodename") версия также будет использоваться для разрешения name2 линковщиком.

tainted_args

Атрибут tainted_args используется для указания того, что функция вызывается таким образом, что требует санизации её аргументов, например, системный вызов в ядре операционной системы. Такая функция может считаться частью «поверхности атаки» программы. Атрибут может использоваться как в объявлениях функций, так и в объявлениях полей, содержащих указатели на функции. В последнем случае любая функция, используемая в качестве инициализатора такого вызываемого поля, будет рассматриваться как вызываемая с заражёнными аргументами.

При использовании -fanalyzer анализатор будет уделять особое внимание таким функциям, потенциально выдавая предупреждения, защищённые -Wanalyzer-tainted-allocation-size, -Wanalyzer-tainted-array-index, -Wanalyzer-tainted-divisor, -Wanalyzer-tainted-offset и -Wanalyzer-tainted-size.

target (string, …)

Несколько целевых back-end реализуют атрибут target для указания того, что функция должна быть скомпилирована с различными параметрами целевой платформы, отличными от указанных в командной строке. Исходные параметры целевой платформы из командной строки игнорируются. В качестве аргументов могут быть предоставлены одна или несколько строк. Каждая строка состоит из одного или нескольких разделённых запятыми суффиксов к префиксу -m, вместе образующих имя машинозависимого параметра. См. Параметры машинозависимого моделирования.

Атрибут target может использоваться, например, для компиляции функции с другим ISA (инструкционной архитектурой), отличным от стандартного. '#pragma GCC target' может использоваться для задания параметров, специфичных для целевой платформы, для более чем одной функции. Подробности см. в Параметры, специфичные для функции, псевдодирективы.

Например, на x86 вы можете объявить одну функцию с атрибутом target("sse4.1,arch=core2") и другую с target("sse4a,arch=amdfam10"). Это эквивалентно компиляции первой функции с параметрами -msse4.1 и -march=core2, а второй — с -msse4a и -march=amdfam10. Вы должны убедиться, что функция вызывается только на машине, поддерживающей конкретный ISA, для которого она скомпилирована (например, с помощью cpuid на x86, чтобы определить используемые биты функций и семейство архитектуры).

int core2_func (void) __attribute__ ((__target__ ("arch=core2")));
int sse3_func (void) __attribute__ ((__target__ ("sse3")));

Предоставление нескольких строк в качестве аргументов, разделённых запятыми, для указания нескольких параметров эквивалентно разделению суффиксов параметров запятой (‘,’) в одной строке. Пробелы внутри строк не допускаются.

Поддерживаемые параметры специфичны для каждой целевой платформы; см. Атрибуты функций x86, Атрибуты функций PowerPC, Атрибуты функций ARM, Атрибуты функций AArch64, Атрибуты функций Nios II и Атрибуты функций S/390 для получения подробностей.

target_clones (options)

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

Например, на x86 вы можете скомпилировать функцию с target_clones("sse4.1,avx"). GCC создаст два клоны функции, один скомпилированный с -msse4.1, а другой с -mavx.

На PowerPC вы можете скомпилировать функцию с target_clones("cpu=power9,default"). GCC создаст два клоны функции, один скомпилированный с -mcpu=power9, а другой — с параметрами по умолчанию. GCC должен быть сконфигурирован для использования GLIBC 2.23 или более поздней версии для использования атрибута target_clones.

Он также создаёт функцию-разрешитель (см. атрибут ifunc выше), которая динамически выбирает клон, подходящий для текущей архитектуры. Разрешитель создаётся только при использовании функции с атрибутом target_clones.

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

unavailable
unavailable (msg)

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

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

unused

Этот атрибут, прикреплённый к функции, означает, что функция потенциально не используется. GCC не выводит предупреждение для этой функции.

used

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

При применении к члену-функции шаблона класса C++, атрибут также означает, что функция будет инстанцирована, если сам класс инстанцирован.

visibility ("visibility_type")
END_OF_DOCUMENT_MARKER

Этот атрибут влияет на связь объявления, к которому он прикреплён. Он может применяться к переменным (см. Общие атрибуты переменных) и типам (см. Общие атрибуты типов), а также к функциям.

Поддерживаются четыре значения visibility_type: default, hidden, protected или internal.

void __attribute__ ((visibility ("protected")))
f () { /* Do something. */; }
int i __attribute__ ((visibility ("hidden")));

Возможные значения visibility_type соответствуют настройкам видимости в ELF gABI.

default

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

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

В Darwin, видимость по умолчанию означает, что объявление видно другим модулям.

Видимость по умолчанию соответствует «внешней связи» в языке.

hidden

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

internal

Видимость internal похожа на видимость hidden, но с дополнительными особенностями, специфичными для процессора. Если не указано иначе psABI, GCC определяет внутреннюю видимость так, что функция никогда не вызывается из другого модуля. Сравните это со скрытыми функциями, которые, хотя и не могут быть напрямую проинициализированы другими модулями, могут быть проинициализированы косвенно через указатели на функции. Указывая, что функция не может быть вызвана извне модуля, GCC, например, может опустить загрузку регистра PIC, поскольку известно, что вызывающая функция загрузила правильное значение.

protected

Видимость protected похожа на видимость по умолчанию, за исключением того, что она указывает на то, что ссылки внутри определяющего модуля привязываются к определению в этом модуле. То есть, объявленная сущность не может быть переопределена другим модулем.

Все виды видимости поддерживаются во многих, но не во всех, ELF-целях (поддерживаются, когда ассемблер поддерживает псевдооператор ‘.visibility’). Видимость по умолчанию поддерживается везде. Скрытая видимость поддерживается в Darwin-целях.

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

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

В C++, вы можете помечать методы-члены и статические переменные-члены класса атрибутом видимости. Это полезно, если вы знаете, что определённый метод или статическая переменная-член должны использоваться только из одного разделяемого объекта; тогда вы можете пометить его как скрытый, в то время как остальная часть класса имеет видимость по умолчанию. Следует соблюдать осторожность, чтобы не нарушить правило «одно определение»; например, обычно нецелесообразно помечать встроенный метод как скрытый, не помечая весь класс как скрытый.

Объявление пространства имён C++ также может иметь атрибут видимости.

namespace nspace1 __attribute__ ((visibility ("protected")))
{ /* Do something. */; }

Этот атрибут применяется только к конкретному телу пространства имён, а не к другим определениям того же пространства имён; он эквивалентен использованию ‘#pragma GCC visibility’ до и после определения пространства имён (см. Атрибуты видимости).

В C++, если аргумент шаблона имеет ограниченную видимость, это ограничение неявно распространяется на экземпляр шаблона. В противном случае экземпляры и специализации шаблонов по умолчанию имеют видимость своего шаблона.

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

warn_unused_result

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

int fn () __attribute__ ((warn_unused_result));
int foo ()
{
  if (fn () < 0) return -1;
  fn ();
  return 0;
}

приводит к предупреждению на строке 5.

weak

Атрибут weak вызывает объявление внешнего символа как слабого символа, а не глобального. Это в первую очередь полезно для определения функций библиотеки, которые могут быть переопределены в пользовательском коде, хотя может быть использовано и с объявлениями, не являющимися функциями. Переопределяющий символ должен иметь тот же тип, что и слабый символ. Кроме того, если это переменная, она должна иметь также тот же размер и выравнивание, что и слабый символ. Слабые символы поддерживаются для ELF-целей, а также для целей a.out при использовании GNU ассемблера и компоновщика.

weakref
weakref ("target")

Атрибут weakref помечает объявление как слабое ссылочное значение. Без аргументов он должен сопровождаться атрибутом alias, который указывает целевой символ. В качестве альтернативы, target может быть задан как аргумент для weakref, указывая целевое определение псевдонима. target должен иметь тот же тип, что и объявление. Кроме того, если это переменная, она должна иметь также тот же размер и выравнивание, что и объявление. В любом из этих форм объявления weakref неявно помечает объявленный символ как weak. Без target, заданного аргументом к weakref или alias, weakref эквивалентно weak (в этом случае объявление может быть extern).

/* Given the declaration: */
extern int y (void);

/* the following... */
static int x (void) __attribute__ ((weakref ("y")));

/* is equivalent to... */
static int x (void) __attribute__ ((weakref, alias ("y")));

/* or, alternatively, to... */
static int x (void) __attribute__ ((weakref));
static int x (void) __attribute__ ((alias ("y")));

Слабая ссылка — это псевдоним, для которого сам по себе не требуется определение целевого символа. Если целевой символ ссылается только через слабые ссылки, то он становится weak неопределённым символом. Однако, если на него есть прямые ссылки, такие сильные ссылки имеют приоритет, и для символа требуется определение, необязательно в том же файле перевода.

Эффект эквивалентен перемещению всех ссылок на псевдоним в отдельный файл перевода, переименованию псевдонима в целевой символ, объявлению его как слабого, компиляции двух отдельных файлов перевода и выполнению компоновки с релоцируемым выходом (т.е. ld -r) на них.

Объявление, к которому прикреплён weakref и которое связано с именованным target должно быть static.

zero_call_used_regs ("choice")

Атрибут zero_call_used_regs заставляет компилятор обнулять подмножество всех регистров, используемых вызовом функции7, при возвращении из функции. Это используется для повышения безопасности программы путём смягчения атак Return-Oriented Programming (ROP) или предотвращения утечки информации через регистры.

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

  • ‘skip’ — не обнуляет регистры, используемые вызовом функции.
  • ‘used’ — обнуляет только те регистры, используемые вызовом функции, которые были использованы в функции. Регистр «используется», если его содержимое было установлено или обработано в функции.
  • ‘all’ — обнуляет все регистры, используемые вызовом функции.
  • ‘leafy’ — ведет себя как ‘used’ в листовой функции и как ‘all’ в нелистовой функции. Это обеспечивает более экономное обнуление в листовых функциях, где множество используемых регистров известно, что может быть достаточно для некоторых целей обнуления регистров.

В дополнение к этим трём основным вариантам, можно модифицировать ‘used’, ‘all’ и ‘leafy’ следующим образом:

  • Добавление ‘-gpr’ ограничивает обнуление универсальными регистрами.
  • Добавление ‘-arg’ ограничивает обнуление регистрам, которые могут использоваться для передачи аргументов функций. Это включает все регистры аргументов, определённые правилами вызова платформы, независимо от того, использует ли функция эти регистры для аргументов или нет.

Модификаторы могут использоваться по отдельности или вместе. Если они используются вместе, они должны быть указаны в вышеупомянутом порядке.

Полный список choice:

skip

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

used

обнуляет только регистры, используемые вызовом функции, которые были использованы в функции.

used-gpr

обнуляет только универсальные регистры, используемые вызовом функции, которые были использованы в функции.

used-arg

обнуляет только регистры, используемые вызовом функции, которые были использованы в функции и для передачи аргументов.

used-gpr-arg

обнуляет только универсальные регистры, используемые вызовом функции, которые были использованы в функции и для передачи аргументов.

all

обнуляет все регистры, используемые вызовом функции.

all-gpr

обнуляет все универсальные регистры, используемые вызовом функции.

all-arg

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

all-gpr-arg

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

leafy

То же, что и ‘used’ в листовой функции и то же, что и ‘all’ в нелистовой функции.

leafy-gpr

То же, что и ‘used-gpr’ в листовой функции и то же, что и ‘all-gpr’ в нелистовой функции.

leafy-arg

То же, что и ‘used-arg’ в листовой функции и то же, что и ‘all-arg’ в нелистовой функции.

leafy-gpr-arg

То же, что и ‘used-gpr-arg’ в листовой функции и то же, что и ‘all-gpr-arg’ в нелистовой функции.

Из этого списка ‘used-arg’, ‘used-gpr-arg’, ‘all-arg’, ‘all-gpr-arg’, ‘leafy-arg’ и ‘leafy-gpr-arg’ в основном используются для смягчения атак ROP.

Значение по умолчанию для атрибута контролируется -fzero-call-used-regs.

Примечания

(7)

Регистр «используемый вызовом» — это регистр, содержимое которого может быть изменено вызовом функции; поэтому вызывающая сторона не может предполагать, что регистр будет содержать то же самое содержимое при возвращении из функции, что и до вызова функции. Такие регистры также называются «изменяемые вызовом», «сохраненные вызывающей стороной» или «изменяемые».

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

Spec-Zone.ru

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