6.33.1 Общие атрибуты функций ¶
Следующие атрибуты поддерживаются на большинстве целевых платформ.
access (access-mode, ref-index)access (access-mode, ref-index, size-index)-
Атрибут
accessпозволяет обнаруживать некорректные или небезопасные обращения функций, к которым он применяется, или их вызывающих функций, а также обращения только для записи к объектам, из которых никогда не читаются данные. Такие обращения могут диагностироваться предупреждениями, такими как -Wstringop-overflow, -Wuninitialized, -Wunused и другими.Атрибут
accessуказывает, что функция, к аргументам которой по ссылке применяется атрибут, обращается к ссылаемому объекту в соответствии с access-mode. Аргумент access-mode обязателен и должен быть одним из четырёх имён:read_only,read_write,write_only, илиnone. Остальные два — позиционные аргументы.Обязательный позиционный аргумент ref-index обозначает аргумент функции типа указатель (или в C++, ссылка), который подвергается доступу. Один и тот же аргумент типа указатель может быть упомянут в атрибуте
accessне более одного раза.Необязательный позиционный аргумент size-index обозначает аргумент функции целого типа, который определяет максимальный размер доступа. Размер представляет собой количество элементов указанного типа, ссылаемого аргументом ref-index, или количество байтов, когда тип указателя —
void*. Если аргумент size-index не указан, аргумент типа указатель должен быть либо нулевым, либо указывать на область памяти, которая должным образом выровнена и достаточно велика для размещения хотя бы одного объекта указанного типа (это подразумевает, что указатель за границами массива не является допустимым аргументом). Фактический размер доступа может быть меньше, но не больше.Режим доступа
read_onlyуказывает, что указатель, к которому он применяется, используется для чтения ссылаемого объекта, но не для записи в него. Если аргумент, определяющий размер доступа, обозначенный как size-index, не равен нулю, то ссылаемый объект должен быть инициализирован. Данный режим подразумевает более сильную гарантию, чем квалификатор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. Он указывает, что указатель, к которому он применяется, используется как для чтения, так и для записи в ссылаемый объект. Если аргумент, определяющий размер доступа, обозначенный как size-index, не равен нулю, то объект, на который указывает указатель, должен быть инициализирован. Пример использования режима доступа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указывает, что указатель, к которому он применяется, вообще не используется для доступа к ссылаемому объекту. Если указатель не нулевой, то ссылаемый объект должен существовать и иметь размер, указанный аргументом size-index. При отсутствии необязательного аргумента size-index для аргумента типаvoid*фактический аргумент-указатель игнорируется. Ссылаемый объект не обязан быть инициализирован. Режим предназначен для проверки ожидаемого размера объекта, например, в функциях, которые вызывают__builtin_object_size. См. Встроенные функции проверки размера объектов. alias ("target")-
Атрибут
aliasзаставляет объявление выводить как псевдоним для другого символа, который должен быть предварительно объявлен с тем же типом, а для переменных также с тем же размером и выравниванием. Объявление псевдонима с типом, отличным от целевого, неопределено и может быть диагностировано. В качестве примера, следующие объявления:void __f () { /* Do something. */; } void f () __attribute__ ((weak, alias ("__f")));определяют ‘f’ как слабый псевдоним для ‘__f’. В C++, для целевого символа должно использоваться mangeld имя. Ошибка возникает, если ‘__f’ не определено в том же трансляционном блоке.
Данный атрибут требует поддержки в ассемблере и объектных файлах и может быть недоступен на всех целевых платформах.
alignedaligned (alignment)-
Атрибут
alignedопределяет минимальное выравнивание первого машинного кода функции, измеренное в байтах. Если указано, alignment должно быть целочисленной константой, являющейся степенью двойки. Отсутствие аргумента alignment подразумевает оптимальное выравнивание для целевой платформы. Оператор__alignof__может быть использован для определения этого выравнивания (см. Определение выравнивания функций, типов или переменных). Атрибут не имеет эффекта, когда определение функции не представлено в том же трансляционном блоке.Атрибут не может быть использован для уменьшения выравнивания функции, ранее объявленной с более строгим выравниванием; только для его увеличения. Попытки сделать обратное диагностируются. Некоторые целевые платформы задают минимальное значение выравнивания по умолчанию для функций, которое больше 1. На таких платформах указание менее строгого выравнивания игнорируется. Использование атрибута переопределяет действие опции -falign-functions (см. Параметры оптимизации) для этой функции.
Обратите внимание, что эффективность атрибутов
alignedможет быть ограничена внутренними ограничениями системного компоновщика и/или формата объектных файлов. На некоторых системах компоновщик может выровнять функции только до определённого максимального выравнивания. (Для некоторых компоновщиков максимальное поддерживаемое выравнивание может быть очень маленьким.) Обратитесь к документации вашего компоновщика для получения дополнительной информации.Атрибут
alignedтакже может использоваться для переменных и полей (см. Указание атрибутов переменных.) alloc_align (position)-
Атрибут
alloc_alignможет быть применён к функции, возвращающей указатель и принимающей по меньшей мере один аргумент целочисленного или перечислимого типа. Он указывает, что возвращаемый указатель выровнен на границе, определяемой аргументом функции в позиции position. Значимые выравнивания — степени двойки, большие единицы. 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может быть применён к функции, возвращающей указатель и принимающей по меньшей мере один аргумент целочисленного или перечислимого типа. Он указывает, что возвращаемый указатель указывает на память, размер которой задаётся аргументом функции в позиции position-1, или произведением аргументов в позициях position-1 и position-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может быть применён к функции, возвращающей указатель. Он указывает, что возвращаемый указатель выровнен на границе, заданной alignment. Если атрибут имеет два аргумента, второй аргумент — сдвиг смещения offset. Значимые значения alignment — степени двойки, большие единицы. Значимые значения offset — больше нуля и меньше alignment.Например
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, как холодные, чтобы улучшить оптимизацию горячих функций, которые редко вызывают помеченные функции.Когда доступна обратная связь профиля, через -fprofile-use, холодные функции автоматически обнаруживаются, и этот атрибут игнорируется.
const
-
Вызовы функций, значение которых не изменяется при изменении наблюдаемого состояния программы и которые не оказывают наблюдаемого влияния на это состояние, кроме возвращения значения, могут подходить для оптимизаций, таких как устранение общих подвыражений. Объявление таких функций с атрибутом
constпозволяет GCC избегать вывода некоторых вызовов при повторных вызовах функции с одинаковыми значениями аргументов.Например,
int square (int) __attribute__ ((const));
указывает GCC, что последующие вызовы функции
squareс одинаковым значением аргумента могут быть заменены результатом первого вызова независимо от предшествующих и последующих операторов.Атрибут
constзапрещает функции чтение объектов, влияющих на возвращаемое значение, между последовательными вызовами. Однако функции, объявленные с этим атрибутом, могут безопасно читать объекты, которые не изменяют возвращаемое значение, такие как константы без модификаторов.Атрибут
constнакладывает более строгие ограничения на определение функции, чем аналогичный атрибутpure. Объявление одной и той же функции с атрибутамиconstиpureдиагностируется. Поскольку функция const не может иметь побочных эффектов, она не должна возвращатьvoid. Объявление такой функции диагностируется.Обратите внимание, что функция, имеющая аргументы указателей и проверяющая данные, на которые эти указатели ссылаются, не должна быть объявлена
const, если данные, на которые указывают эти указатели, могут измениться между последовательными вызовами функции. В общем случае, поскольку функция не может различать данные, которые могут измениться, от данных, которые не могут измениться, функции const никогда не должны принимать аргументы указателей или, в C++, ссылки. Аналогично, функция, которая вызывает не-const функцию, обычно сама не должна быть const. constructordestructorconstructor (priority)destructor (priority)-
Атрибут
constructorвызывает автоматическое вызов функции перед тем, как выполнение переходит вmain (). Аналогично, атрибутdestructorвызывает автоматическое вызов функции после завершенияmain ()или вызоваexit (). Функции с этими атрибутами полезны для инициализации данных, которые неявно используются во время выполнения программы.На некоторых платформах атрибуты также принимают целочисленный аргумент для задания приоритета, чтобы управлять порядком выполнения конструкторов и деструкторов. Конструктор с меньшим номером приоритета выполняется перед конструктором с большим номером приоритета; обратная связь действует для деструкторов. Таким образом, если у вас есть конструктор, который выделяет ресурс, и деструктор, который освобождает тот же ресурс, обе функции обычно имеют одинаковый приоритет. Приоритеты конструкторов и деструкторов такие же, как и для объектов C++ на уровне пространства имён (см. Атрибуты переменных, функций и типов в C++). Однако в настоящее время порядок вызова конструкторов для объектов C++ со статической областью хранения и функций, помеченных атрибутом
constructor, не определён. При смешанных объявлениях атрибутinit_priorityможет быть использован для наложения конкретного порядка.Использование форм аргументов атрибутов
constructorиdestructorна платформах, где данная функция не поддерживается, приводит к ошибке. copycopy (function)-
Атрибут
copyприменяет набор атрибутов, с которыми была объявлена функция function, к объявлению функции, к которой применяется данный атрибут. Атрибут предназначен для библиотек, которые определяют псевдонимы или функции разрешения, которые должны указывать тот же набор атрибутов, что и их целевые функции. Атрибут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); deprecateddeprecated (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используется в объявлении функции, и вызов такой функции не устраняется благодаря устранению неиспользуемого кода или другим оптимизациям, диагностируется ошибка или предупреждение (соответственно), включающее message. Это полезно для проверки на этапе компиляции, особенно вместе с__builtin_constant_pи встроенными функциями, где проверка аргументов встроенной функции невозможна с помощьюextern char [(condition) ? 1 : -1];трюков.Хотя можно оставить функцию неопределённой и тем самым вызвать ошибку компоновки (определить функцию с сообщением в разделе
.gnu.warning*), при использовании этих атрибутов проблема диагностируется раньше и с точным местоположением вызова даже при наличии встроенных функций или при отсутствии отладки информации. externally_visible-
Этот атрибут, прикреплённый к глобальной переменной или функции, аннулирует эффект командной строки -fwhole-program, поэтому объект остаётся видимым вне текущей единицы компиляции.
Если -fwhole-program используется вместе с -flto и
goldиспользуется в качестве плагина компоновщика, атрибутыexternally_visibleавтоматически добавляются к функциям (но не к переменным, из-за текущей проблемыgold) которые обращаются за пределами объектов LTO в соответствии с файлом разрешения, созданнымgold. Для других компоновщиков, которые не могут сгенерировать файл разрешения, явные атрибутыexternally_visibleпо-прежнему необходимы. 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-времени выполнения, в то время как значения, начинающиеся с ‘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, а аргументы для проверки начинаются с третьего аргумента, поэтому правильные параметры для атрибута format — 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/Openstrfmon, а также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, каждый с отдельным значением аргумента, соответствующие фактические аргументы функции проверяются на соответствие всем строкам формата, обозначенным атрибутами. Эта возможность предназначена для поддержки функций семейства GNUngettext.Параметр 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__определён. См. Встроенная функция так же быстра, как макрос.В C++, этот атрибут никоим образом не зависит от
extern, но он всё ещё требует ключевое словоinlineдля активации его специального поведения. hot-
Атрибут
hotдля функции сообщает компилятору, что функция является горячей точкой скомпилированной программы. Функция оптимизируется более агрессивно, и на многих целевых платформах она помещается в специальный подсекции секции текста, так что все горячие функции располагаются близко друг к другу, улучшая локальность.Когда обратная связь профиля доступна через -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")));Косвенные функции не могут быть слабыми. Для использования этой функции требуются версия Binutils 2.20.1 или выше и GNU C Library версии 2.11.1 или выше.
interruptinterrupt_handler-
Многие бэкэнды GCC поддерживают атрибуты для указания того, что функция является обработчиком прерывания, что сообщает компилятору сгенерировать последовательности входа и выхода из функции, отличающиеся от последовательностей обычных функций. Точный синтаксис и поведение зависят от целевой архитектуры; см. следующие подразделы для получения подробностей.
leaf-
Вызовы внешних функций с этим атрибутом должны возвращаться в текущий трансляционный модуль только посредством возврата или обработки исключений. В частности, функция-листок не может вызывать функции обратного вызова, переданные ей из текущего трансляционного модуля, напрямую вызывать функции, экспортированные этим модулем, или
longjmpв модуль. Функции-листки всё ещё могут вызывать функции из других трансляционных модулей, и поэтому они не обязательно являются функциями-листками в том смысле, что не содержат никаких вызовов функций.Атрибут предназначен для функций библиотек, чтобы улучшить анализ потока данных. Компилятор принимает подсказку о том, что любые данные, не покидающие текущий трансляционный модуль, не могут использоваться или изменяться функцией-листком. Например, функция
sinявляется функцией-листком, но функцияqsort— нет.Обратите внимание, что функции-листки могут косвенно выполнять обработчик сигнала, определённый в текущем трансляционном модуле, который использует статические переменные. Аналогично, при ленивой разрешении символов функции-листки могут вызывать косвенные функции, функция-разрешитель или функция реализации которых определены в текущем трансляционном модуле и используют статические переменные. Нет стандартного способа написать такой обработчик сигнала, функцию-разрешителя или функцию реализации, и лучше всего удалить атрибут
leafили пометить все такие статические переменныеvolatile. Наконец, для систем на основе ELF, которые поддерживают интерпозицию символов, следует быть осторожным, чтобы функции, определённые в текущем трансляционном модуле, не интерпонировали другие символы неожиданным образом на основе определённого режима стандарта и определённых макросов проверки функций; в противном случае будет добавлено непреднамеренное обратное обращение.Атрибут не оказывает никакого влияния на функции, определённые в текущем трансляционном модуле. Это позволяет легко объединить несколько трансляционных модулей в один, например, с помощью оптимизации на этапе компоновки. По этой причине атрибут не допускается для типов, чтобы аннотировать косвенные вызовы.
mallocmalloc (deallocator)malloc (deallocator, ptr-index)-
Атрибут
mallocуказывает, что функция являетсяmalloc-подобной, то есть что указатель P, возвращаемый функцией, не может иметь общих областей с любым другим указателем, действительным при возврате функции, и кроме того, никакие указатели на действительные объекты не встречаются в любом хранилище, адресованном P. Кроме того, GCC предсказывает, что функция с этим атрибутом возвращает ненулевое значение в большинстве случаев.Независимо от этого, форма атрибута с одним или двумя аргументами связывает
deallocatorкак подходящую функцию освобождения для указателей, возвращаемых изmalloc-подобной функции. ptr-index обозначает позиционный аргумент, которому при передаче указателя в вызовахdeallocatorпроисходит его освобождение.Использование атрибута без аргументов предназначено для повышения оптимизации, полагаясь на свойство, которое он подразумевает. Функции, подобные
mallocиcalloc, обладают этим свойством, поскольку они возвращают указатель на неинициализированное или обнулённое, только что полученное хранилище. Однако функции, подобныеrealloc, не обладают этим свойством, так как они могут возвращать указатели на хранилище, содержащее указатели на существующие объекты. Кроме того, поскольку все такие функции, предположительно, возвращают ноль только нечасто, вызывающие функции могут быть оптимизированы на основе этого предположения.Связывание функции с 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. Он выведет диагностические сообщения -Wanalyzer-possible-null-dereference и -Wanalyzer-possible-null-argument, если существуют пути выполнения, в которых непроверенный результат вызова функции выделения обращается по указателю или передаётся функции, требующей ненулевого аргумента. Если функция выделения всегда возвращает ненулевое значение, используйте
__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_addressno_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_split_stack-
Если задана опция -fsplit-stack, функции имеют небольшой пролог, который определяет, следует ли разделять стек. Функции с атрибутом
no_split_stackне имеют этого пролога и, следовательно, могут выполняться с небольшим количеством доступного стекового пространства. no_stack_limit-
Этот атрибут локально переопределяет параметры командной строки -fstack-limit-register и -fstack-limit-symbol; он имеет эффект отключения проверки лимитов стека в функции, к которой он применяется.
noclone-
Этот атрибут функции предотвращает рассмотрение функции для клонирования — механизма, который создаёт специализированные копии функций, и который (в настоящее время) выполняется межпроцедурной константной подстановкой.
noinline-
Этот атрибут функции предотвращает рассмотрение функции для встраивания. Если функция не имеет побочных эффектов, есть оптимизации, помимо встраивания, которые приводят к тому, что вызовы функций оптимизируются, хотя вызов функции активен. Чтобы предотвратить оптимизацию таких вызовов, поместите
asm ("");(см. Расширенный Ассемблер - Ассемблерные инструкции с операндами выражений C) в вызываемой функции, чтобы служить специальным побочным эффектом.
noipa-
Отключить межпроцедурные оптимизации между функцией с этим атрибутом и её вызывающими функциями, как если бы тело функции было недоступно при оптимизации вызывающих функций, а вызывающие функции были недоступны при оптимизации тела. Этот атрибут подразумевает атрибуты
noinline,nocloneиno_icf. Однако этот атрибут не эквивалентен комбинации других атрибутов, потому что его цель — подавить существующие и будущие оптимизации, использующие межпроцедурный анализ, включая те, которые не имеют атрибута для их отключения индивидуально. Этот атрибут поддерживается в основном для целей тестирования компилятора. nonnullnonnull (arg-index, …)-
Атрибут
nonnullможет быть применён к функции, которая принимает по меньшей мере один аргумент типа указателя. Он указывает, что ссылаемые аргументы должны быть указателями не равными нулю. Например, объявление:extern void * my_memcpy (void *dest, const void *src, size_t len) __attribute__((nonnull (1, 2)));заставляет компилятор проверять, что при вызовах
my_memcpy, аргументы dest и src являются указателями не равными нулю. Если компилятор определяет, что нулевой указатель передан в слот аргумента, помеченного как не нулевой, и опция -Wnonnull включена, выдаётся предупреждение. См. Параметры для запроса или подавления предупреждений. Если не отключено с помощью опции -fno-delete-null-pointer-checks, компилятор также может выполнять оптимизации, основанные на знании, что некоторые аргументы функций не могут быть равными нулю. Кроме того, опция -fisolate-erroneous-paths-attribute может быть указана, чтобы GCC преобразовал вызовы с аргументами нулевыми для функций не нулевыми в ловушки. См. Параметры, которые управляют оптимизацией.Если атрибуту
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в хвостовые вызовы.Не предполагайте, что регистры, сохранённые вызывающей функцией, восстанавливаются перед вызовом функции
noreturn.Не имеет смысла, чтобы функция
noreturnимела тип возвращаемого значения, отличный отvoid. nothrow-
Атрибут
nothrowиспользуется для информирования компилятора о том, что функция не может выбросить исключение. Например, большинство функций в стандартной библиотеке C могут быть гарантированы как не вызывающие исключение, за исключениемqsortиbsearch, которые принимают аргументы указателей на функции. optimize (level, …)optimize (string, …)-
Атрибут
optimizeиспользуется для указания, что функция должна быть скомпилирована с другими параметрами оптимизации, чем указанные в командной строке. Допустимыми аргументами являются постоянные неотрицательные целые числа и строки. Каждое числовое значение определяет уровень оптимизации level. Каждый аргумент типа string состоит из одной или более подстрок, разделённых запятыми. Каждая подстрока, начинающаяся с буквы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, могут безопасно читать любые не-volatile объекты и изменять значения объектов, не влияя на их возвращаемое значение или наблюдаемое состояние программы.Например,
int hash (char *) __attribute__ ((pure));
сообщает GCC, что последующие вызовы функции
hashс той же строкой могут быть заменены результатом первого вызова, при условии, что состояние программы, наблюдаемое функциейhash, включая содержимое массива, не меняется между вызовами. Несмотря на то, чтоhashпринимает аргумент типа не-const указатель, она не должна изменять массив, на который он указывает, или любой другой объект, значение которого может зависеть от остальной части программы. Однако, вызывающая сторона может безопасно изменять содержимое массива между последовательными вызовами функции (это действие отключает оптимизацию). Ограничение также относится к объектам-членам, на которые указывает указательthisв нестатических членах функций в C++.Примеры чистых функций включают
strlenилиmemcmp. Интересными нечистыми функциями являются функции с бесконечными циклами или те, которые зависят от volatile памяти или других системных ресурсов, которые могут измениться между последовательными вызовами (например, стандартная функция Cfeofв многопоточной среде).Атрибут
pureнакладывает аналогичные, но более слабые ограничения на определение функции, чем атрибутconst:pureразрешает функции читать любую не-volatile память, даже если она изменяется между последовательными вызовами функции. Объявление одной и той же функции с атрибутамиpureиconstдаст диагностическое сообщение. Поскольку чистая функция не может иметь никаких наблюдаемых побочных эффектов, для такой функции не имеет смысла возвращатьvoid. Объявление такой функции даст диагностическое сообщение. returns_nonnull-
Атрибут
returns_nonnullуказывает, что возвращаемое значение функции должно быть указателем, отличным от нуля. Например, объявление:extern void * mymalloc (size_t len) __attribute__((returns_nonnull));
позволяет компилятору оптимизировать вызывающие функции, зная, что возвращаемое значение никогда не будет нулевым.
returns_twice-
Атрибут
returns_twiceсообщает компилятору, что функция может возвращаться более одного раза. Компилятор гарантирует, что все регистры освобождены до вызова такой функции и выдает предупреждение о переменных, которые могут быть изменены после второго возврата из функции. Примеры таких функций —setjmpиvfork. Аналог функции, подобнойlongjmp, если таковой имеется, может потребовать метку атрибутомnoreturn. section ("section-name")-
Обычно компилятор размещает сгенерированный код в секции
text. Однако иногда вам нужны дополнительные секции или нужно, чтобы определённые функции располагались в специальных секциях. Атрибутsectionуказывает, в какой конкретной секции будет размещена функция. Например, объявление:extern void foobar (void) __attribute__ ((section ("bar")));размещает функцию
foobarв секцииbar.Некоторые форматы файлов не поддерживают произвольные секции, поэтому атрибут
sectionнедоступен на всех платформах. Если вам необходимо отобразить всё содержимое модуля в определённую секцию, используйте возможности компоновщика. sentinelsentinel (position)-
Этот атрибут функции указывает, что аргумент в вызове функции ожидается как явный
NULL. Атрибут действителен только для вариадических функций. По умолчанию, sentinel ожидается в качестве последнего аргумента вызова функции. Если опциональный аргумент position указан в атрибуте, sentinel должен находиться на позиции position, считая от конца списка аргументов.__attribute__ ((sentinel)) is equivalent to __attribute__ ((sentinel(0)))
Атрибут автоматически устанавливается с позицией 0 для встроенных функций
execlиexeclp. Встроенная функцияexecleимеет атрибут, установленный с позицией 1.Допустимым
NULLв данном контексте является ноль с любым типом указателя объекта. Если ваша система определяет макросNULLс типом целого числа, вам нужно добавить явное приведение типа. Во время установки GCC заменяет системный заголовок<stddef.h>копией, которая переопределяет NULL соответствующим образом.Предупреждения о пропущенных или некорректных sentinel включены с помощью -Wformat.
simdsimd("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.
no_stack_protector-
Этот атрибут предотвращает добавление кода защиты стека для функции.
target (string, …)-
Несколько целевых модулей обратной связи реализуют атрибут
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 для получения подробностей.
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 компоновщиком. 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? unused-
Этот атрибут, прикреплённый к функции, означает, что функция потенциально не используется. GCC не выводит предупреждение для этой функции.
used-
Этот атрибут, прикреплённый к функции, означает, что код должен быть сгенерирован для функции, даже если функция, по-видимому, не ссылается. Это полезно, например, когда функция ссылается только в ассемблерном коде встраивания.
При применении к члену-функции шаблона класса C++, атрибут также означает, что функция будет инстанцирована, если класс сам будет инстанцирован.
retain-
Для целевых платформ ELF, поддерживающих GNU или FreeBSD OSABI, этот атрибут сохранит функцию от сбора мусора линковщиком. Для поддержки этого поведения функции, которые не были размещены в определённых секциях (например, с помощью атрибута
sectionили опции-ffunction-sections), будут размещены в новых, уникальных секциях.Эта дополнительная функциональность требует Binutils версии 2.36 или более поздней.
visibility ("visibility_type")-
Этот атрибут влияет на связь объявления, к которому он прикреплён. Он может применяться к переменным (см. Общие атрибуты переменных) и типам (см. Общие атрибуты типов), а также к функциям.
Поддерживаются четыре значения visibility_type: default, hidden, protected или internal visibility.
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 ассемблера и линковщика. weakrefweakref ("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")));Слабая ссылка — это псевдоним, который сам по себе не требует предоставления определения целевого символа. Если целевой символ ссылается только через слабые ссылки, то он становится слабо неопределённым символом. Однако если он напрямую проинициализирован, то такие сильные ссылки превалируют, и определение символа требуется, не обязательно в том же файле трансляции.
Эффект эквивалентен перемещению всех ссылок на псевдоним в отдельный файл трансляции, переименованию псевдонима в алиасированный символ, объявлению его как слабого, компиляции двух отдельных файлов трансляции и выполнению линкинга с релокируемым выводом (т.е.
ld -r) на них.Объявление, к которому прикреплён атрибут
weakrefи которое связано с именованнымtargetдолжно бытьstatic. zero_call_used_regs ("choice")
-
Атрибут
zero_call_used_regsзаставляет компилятор обнулить подмножество всех регистров, используемых вызовом функции7, при возврате из функции. Это используется для повышения безопасности программы, либо смягчая атаки Return-Oriented Programming (ROP), либо предотвращая утечку информации через регистры.Для удовлетворения различных потребностей в безопасности и одновременного контроля накладных расходов во время выполнения, параметр choice предоставляет гибкий способ выбора подмножества регистров вызова функции для обнуления. Три основных значения choice:
- ‘skip’ не обнуляет регистры, используемые при вызове функции.
- ‘used’ обнуляет только регистры, используемые при вызове функции. Регистр «используемый» — это тот, содержимое которого было установлено или использовано в функции.
- ‘all’ обнуляет все регистры, используемые при вызове функции.
В дополнение к этим трём основным вариантам, можно модифицировать ‘used’ или ‘all’ следующим образом:
- Добавление ‘-gpr’ ограничивает обнуление универсальными регистрами.
- Добавление ‘-arg’ ограничивает обнуление регистрам, которые могут использоваться для передачи аргументов функции. Это включает все регистры аргументов, определенные преобразованием вызова платформы, независимо от того, использует ли функция эти регистры для аргументов функции или нет.
Модификаторы могут использоваться по отдельности или вместе. Если они используются вместе, они должны появляться в порядке, указанном выше.
Полный список choice:
skip-
не обнуляет регистры, используемые при вызове функции.
used-
обнуляет только регистры, используемые при вызове функции.
used-gpr-
обнуляет только универсальные регистры, используемые при вызове функции.
used-arg-
обнуляет только регистры, используемые при вызове функции и для передачи аргументов.
used-gpr-arg-
обнуляет только универсальные регистры, используемые при вызове функции и для передачи аргументов.
all-
обнуляет все регистры, используемые при вызове функции.
all-gpr-
обнуляет все универсальные регистры, используемые при вызове функции.
all-arg-
обнуляет все регистры, используемые при вызове функции для передачи аргументов.
all-gpr-argобнуляет все универсальные регистры, используемые при вызове функции для передачи аргументов.
Из этого списка ‘used-arg’, ‘used-gpr-arg’, ‘all-arg’, и ‘all-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-11.4.0/gcc/Common-Function-Attributes.html