6.4.1.1 Общие атрибуты функций
Следующие атрибуты поддерживаются на большинстве целевых платформ.
-
access (access-mode, ref-index) access (access-mode, ref-index, size-index)-
Атрибут
accessпозволяет обнаруживать недопустимые или небезопасные обращения функций, к которым он применяется, или их вызывающих функций, а также обращения только для записи к объектам, из которых никогда не производится чтение. Такие обращения могут диагностироваться с помощью предупреждений, таких как -Wstringop-overflow, -Wuninitialized, -Wunused и другие.Атрибут
accessуказывает, что аргумент-указатель или аргумент-ссылка функции используется в соответствии с режимом access-mode, который должен быть одним из следующих:read_only,read_write,write_onlyилиnone. Семантика этих режимов описана ниже.Аргумент, к которому применяется атрибут, определяется параметром ref-index — целочисленной константой, указывающей его позицию в списке аргументов. Нумерация аргументов начинается с 1. Можно указать несколько атрибутов
access, чтобы описать режимы доступа для разных аргументов, однако несколько атрибутов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. См. Проверка размера объекта.Обратите внимание, что атрибут
accessлишь указывает, как можно обращаться к объекту, на который ссылается аргумент-указатель; он не означает, что такое обращение произойдет. Кроме того, атрибутaccessне подразумевает ни атрибутnonnull, ни атрибутnonnull_if_nonzero; может быть уместно добавить оба атрибута в объявление функции, которая безусловно обрабатывает буфер через аргумент-указатель. Дополнительные сведения и предостережения см. в описании атрибутов функцийnonnullиnonnull_if_nonzeroдалее в этом разделе. -
alias ("target") -
Атрибут
aliasприводит к тому, что объявление выводится как псевдоним другого символа, который должен быть предварительно объявлен с тем же типом, а для переменных — также с тем же размером и выравниванием. Объявление псевдонима с типом, отличным от типа целевого символа, имеет неопределенное поведение и может диагностироваться. Например, следующие объявления:void __f () { /* Do something. */; } void f () __attribute__ ((weak, alias ("__f")));определяют ‘f’ как слабый псевдоним для ‘__f’. В C++ необходимо использовать декорированное имя целевого символа. Если ‘__f’ не определен в той же единице трансляции, возникает ошибка.
Для этого атрибута требуется поддержка со стороны ассемблера и формата объектных файлов; он может быть доступен не на всех целевых платформах.
-
aligned aligned (alignment)-
Атрибут
alignedзадает минимальное выравнивание первой инструкции функции в байтах. Если параметр alignment указан, он должен быть целочисленной константой — степенью 2. Если аргумент alignment не указан, используется оптимальное для целевой платформы выравнивание. Чтобы определить его значение, можно использовать оператор__alignof__(см. Определение выравнивания функций, типов и переменных). Атрибут не действует, если определение функции отсутствует в той же единице трансляции.Атрибут нельзя использовать для уменьшения выравнивания функции, ранее объявленной с более строгим выравниванием; его можно только увеличить. Попытки сделать обратное диагностируются. На некоторых целевых платформах задано минимальное выравнивание функций по умолчанию, превышающее 1. На таких платформах указание менее строгого выравнивания молча игнорируется. Использование атрибута переопределяет для этой функции действие параметра -falign-functions (см. Параметры, управляющие оптимизацией).
Обратите внимание, что возможности атрибутов
alignedмогут быть ограничены особенностями системного компоновщика и/или формата объектных файлов. В некоторых системах компоновщик может выравнивать функции только до определенного максимального значения. (У некоторых компоновщиков поддерживаемое максимальное выравнивание может быть очень и очень малым.) Дополнительные сведения см. в документации к компоновщику.Атрибут
alignedможно также использовать для переменных и полей (см. Задание атрибутов переменных.) -
alloc_align (position) -
Атрибут
alloc_alignможно применять к функции, которая возвращает указатель и принимает как минимум один аргумент целочисленного или перечислимого типа. Он указывает, что возвращаемый указатель выровнен по границе, задаваемой аргументом функции с номером position. Допустимыми значениями выравнивания являются степени 2, превышающие единицу. 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 -
Как правило, функции не встраиваются, если не указана оптимизация. Для функций, объявленных как inline, этот атрибут встраивает функцию независимо от любых ограничений, которые обычно применяются к встраиванию. Если такую функцию не удается встроить, это диагностируется как ошибка. Обратите внимание: если такая функция вызывается косвенно, компилятор может встроить ее или не встроить в зависимости от уровня оптимизации; отсутствие встраивания при косвенном вызове может диагностироваться, а может и нет.
Если встроенную функцию необходимо использовать в нескольких единицах трансляции, следует поместить атрибут
always_inlineв определение функции в заголовочном файле, подключаемом во всех единицах трансляции, где используется эта функция. Оптимизация на этапе компоновки может встраивать функции из разных единиц трансляции, но только если дополнительно указан уровень оптимизации, который обычно разрешает встраивание. -
artificial -
Этот атрибут полезен для небольших встроенных оберток, которые по возможности должны отображаться при отладке как единое целое. В зависимости от формата отладочной информации он либо помечает функцию как искусственную, либо указывает использовать местоположение вызывающей стороны для всех инструкций во встроенном теле функции.
-
assume_aligned (alignment) assume_aligned (alignment, offset)-
Атрибут
assume_alignedможно применять к функции, которая возвращает указатель. Он указывает, что возвращаемый указатель выровнен по границе, заданной параметром alignment. Если у атрибута два аргумента, второй аргумент задает смещение offset относительно выравнивания. Допустимыми значениями alignment являются степени 2, превышающие единицу. Допустимые значения 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, чтобы улучшить оптимизацию часто выполняемых функций, которые в редких случаях вызывают помеченные функции. В C++ атрибутcoldможно применять к типам; в этом случае он распространяется на функции-члены. См. Атрибуты переменных, функций и типов, специфичные для C++.Если доступна обратная связь по профилю с помощью -fprofile-use, редко вызываемые функции определяются автоматически, и этот атрибут игнорируется.
-
const -
Вызовы функций, значение результата которых не зависит от изменений наблюдаемого состояния программы и которые не оказывают на это состояние наблюдаемых воздействий, кроме возврата значения, могут подвергаться таким оптимизациям, как исключение общих подвыражений. Объявление таких функций с атрибутом
constпозволяет GCC не выполнять некоторые вызовы при повторных вызовах функции с одинаковыми значениями аргументов.Например,
int square (int) __attribute__ ((const));
сообщает GCC, что последующие вызовы функции
squareс тем же значением аргумента можно заменить результатом первого вызова независимо от промежуточных инструкций.Атрибут
constзапрещает функции считывать между последовательными вызовами объекты, влияющие на возвращаемое ею значение. Однако функции с этим атрибутом могут безопасно считывать объекты, не изменяющие возвращаемое значение, например неизменяемые константы.Атрибут
constнакладывает на определение функции более строгие ограничения, чем аналогичный атрибутpure. Объявление одной и той же функции с атрибутамиconstиpureдиагностируется. Поскольку функция const не может иметь наблюдаемых побочных эффектов, возвращатьvoidне имеет смысла. Объявление такой функции диагностируется.Обратите внимание: функцию с аргументами-указателями, которая анализирует данные, на которые они указывают, нельзя объявлять с атрибутом
const, если эти данные могут измениться между последовательными вызовами функции. В общем случае функции const никогда не должны принимать аргументы-указатели или, в C++, аргументы-ссылки, поскольку функция не может отличить данные, которые могут измениться, от тех, которые не могут. Аналогичным образом, функция, вызывающая функцию, не являющуюся const, обычно сама не должна быть const. -
constructor destructorconstructor (priority)destructor (priority)-
Атрибут
constructorприводит к автоматическому вызову функции перед началом выполненияmain (). Аналогично, атрибутdestructorприводит к автоматическому вызову функции после завершенияmain ()или вызоваexit (). Функции с этими атрибутами полезны для инициализации данных, неявно используемых во время выполнения программы.На большинстве целевых платформ атрибуты также принимают целочисленный аргумент, задающий приоритет, который определяет порядок вызова функций-конструкторов и функций-деструкторов. Аргумент priority представляет собой константное целочисленное выражение в диапазоне от 101 до 65535 включительно; приоритеты 0–100 зарезервированы для компилятора и его библиотек времени выполнения. Конструктор с меньшим номером приоритета выполняется раньше конструктора с большим номером; для деструкторов действует обратный порядок. Поэтому, если конструктор выделяет ресурс, а деструктор освобождает тот же ресурс, обычно обеим функциям задают одинаковый приоритет.
Порядок вызова конструкторов объектов C++ со статической длительностью хранения относительно функций, помеченных атрибутом
constructor, обычно не определен. Чтобы задать определенный порядок, можно использовать атрибутinit_priority(см. Атрибуты переменных, функций и типов, специфичные для C++) в объявлениях объектов C++ в пространстве имен; аргумент priority атрибутаinit_priorityимеет тот же эффект, что и аргумент priority атрибутаconstructor.Использование формы атрибутов
constructorиdestructorс аргументом на целевых платформах, где эта возможность не поддерживается, приводит к ошибке. Такое использование запрещено лишь на нескольких целевых платформах (обычно не использующих формат объектных файлов ELF или компоновщик GNU). -
copy copy (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); -
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используется в объявлении функции, а вызов этой функции не устраняется удалением мертвого кода или другими оптимизациями, выдается ошибка или предупреждение (соответственно), включающее message. Это полезно для проверок во время компиляции, особенно в сочетании с__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__.) Значения archetype, такие какprintf, относятся к форматам, принимаемым системной библиотекой времени выполнения C, а значения с префиксом ‘gnu_’ всегда относятся к форматам, принимаемым библиотекой GNU C.На целевых платформах MinGW и Microsoft Windows также доступны
ms_printf,ms_scanfиms_strftime. Значения с префиксом ‘ms_’ относятся к форматам, принимаемым библиотекой msvcrt.dll.Целевые платформы Solaris также поддерживают тип
cmn_err(или__cmn_err__).cmn_errподдерживает подмножество стандартных преобразованийprintfи двухаргументное преобразование%bдля отображения битовых полей. Дополнительные сведения см. на странице руководства Solaris дляcmn_err.Целевые платформы Darwin также поддерживают тип
CFString(или__CFString__) в атрибутеformat. Объявления с этим типом проверяются на правильность синтаксиса и типов аргументов. Однако разбор самой строки формата и проверка передаваемых аргументов на соответствие ей при вызовах таких функций в настоящее время не выполняются.Для диалектов Objective-C в том же контексте распознается
NSString(или__NSString__). Объявления с этими атрибутами формата проверяются на правильность синтаксиса, однако результат проверки таких строк формата пока не определен, и эта версия компилятора ее не выполняет.Параметр 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/Openstrfmon, а такжеprintf_unlockedиfprintf_unlocked. См. Параметры, управляющие диалектом C. -
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.Аналогичным образом, на целевых платформах Darwin в качестве аргументов формата можно также использовать
CFStringRefs(определённый в заголовкахCoreFoundation). Обратите внимание, что соответствующие заголовки, вероятнее всего, доступны только в установках Darwin (OSX). В таких установках документация XCode и системы содержит описанияCFString,CFStringRefsи связанных функций. -
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функции сообщает компилятору, что эта функция является часто выполняемым участком скомпилированной программы. Функция оптимизируется более агрессивно, а на многих целевых платформах помещается в специальный подраздел текстового раздела, чтобы все часто выполняемые функции располагались рядом, повышая локальность. В 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")));Косвенные функции не могут быть слабыми. Для использования этой возможности требуются Binutils версии 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 предполагает, что функция с этим атрибутом в большинстве случаев возвращает ненулевой указатель.Независимо от этого, форма атрибута с одним или двумя аргументами связывает
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, если существует путь выполнения, на котором значение передаётся функции освобождения памяти более одного раза.
- Анализатор учитывает возможность того, что функция выделения памяти завершится неудачей и вернёт нулевой указатель. Если существуют пути выполнения, на которых непроверенный результат вызова функции выделения памяти разыменовывается или передаётся функции, требующей ненулевой аргумент, анализатор выдаёт диагностики -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, если функция освобождения памяти используется для глобальной переменной или переменной в стеке.
Анализатор предполагает, что функции освобождения памяти корректно обрабатывают нулевой указатель. Если это не так, функцию освобождения памяти можно пометить атрибутом
__attribute__((nonnull)), чтобы -fanalyzer мог выдавать диагностику -Wanalyzer-possible-null-argument для путей выполнения, в которых функции освобождения передаётся нулевой указатель. -
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функций сообщает компилятору, что не следует выполнять инструментирование кода для фаззинга с управлением по покрытию кода (-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 преобразовал вызовы функций, требующих ненулевые аргументы, но получающих нулевые, в ловушки. См. Параметры управления оптимизацией.
- Компилятор также может выполнять оптимизации, основываясь на том, что определённые аргументы функции не могут быть нулевыми. Эти оптимизации можно отключить параметром -fno-delete-null-pointer-checks. См. Параметры управления оптимизацией.
Для определений функций:
- Если компилятор определяет, что параметр функции, помеченный как ненулевой, сравнивается с нулём, и включён параметр -Wnonnull-compare, выдаётся предупреждение. См. Параметры включения и подавления предупреждений.
- Компилятор также может выполнять оптимизации, основываясь на том, что параметры
nonnullне могут быть нулевыми. В настоящее время отключить это можно только удалив атрибут nonnull.
Если атрибуту
nonnullне передан arg-index, все аргументы-указатели помечаются как ненулевые. Например, следующее объявление эквивалентно предыдущему примеру:extern void * my_memcpy (void *dest, const void *src, size_t len) __attribute__((nonnull)); -
nonnull_if_nonzero nonnull_if_nonzero (arg-index, arg2-index)-
Атрибут
nonnull_if_nonzeroявляется условной версией атрибутаnonnull. У него два аргумента: первый должен быть индексом аргумента-указателя, который в некоторых случаях должен быть ненулевым, а второй — индексом целочисленного аргумента (не булева). Если целочисленный аргумент равен нулю, аргумент-указатель может быть нулевым; если он не равен нулю, аргумент-указатель должен быть ненулевым.extern void * my_memcpy (void *dest, const void *src, size_t len) __attribute__((nonnull (1, 2))); extern void * my_memcpy2 (void *dest, const void *src, size_t len) __attribute__((nonnull_if_nonzero (1, 3), nonnull_if_nonzero (2, 3)));При таких объявлениях недопустимо вызывать
my_memcpy (NULL, NULL, 0);илиmy_memcpy2 (NULL, NULL, 4);, но вызовmy_memcpy2 (NULL, NULL, 0);допустим. Этот атрибут следует использовать для объявлений, в которых, например, предусмотрено исключение для нулевого размера, когда можно передать нулевой указатель. -
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, принимающих аргументы-указатели на функции. -
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 для функции действуют так, как если бы они были добавлены в командную строку.Допустимыми аргументами являются постоянные неотрицательные целые числа и строки. Каждый числовой аргумент задает уровень оптимизации. Каждый аргумент типа строка состоит из одной или нескольких подстрок, разделенных запятыми. Каждая подстрока, начинающаяся с буквы
O, обозначает параметр оптимизации, например -O0 или -Os. Остальные подстроки рассматриваются как суффиксы префикса-f, которые вместе образуют имя параметра оптимизации. См. Параметры управления оптимизацией.‘#pragma GCC optimize’ можно использовать для задания параметров оптимизации более чем для одной функции. Подробности о директиве pragma см. в разделе Директивы pragma для параметров отдельных функций.
Передача нескольких строк в качестве аргументов, разделенных запятыми, для указания нескольких параметров эквивалентна разделению суффиксов параметров запятыми (‘,’) внутри одной строки. Пробелы внутри строк не допускаются.
Не каждый параметр оптимизации с префиксом -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принимает аргумент-указатель на неконстантные данные, она не должна изменять массив, на который он указывает, или любой другой объект, от значения которого может зависеть остальная часть программы. Однако вызывающий код может безопасно изменять содержимое массива между последовательными вызовами функции (это отключает оптимизацию). Это ограничение также распространяется на объекты-члены, на которые ссылается указательthisв нестатических функциях-членах C++.Распространенные примеры чистых функций:
strlenилиmemcmp. К интересным примерам нечистых функций относятся функции с бесконечными циклами или функции, зависящие от volatile-памяти либо другого системного ресурса, который может изменяться между последовательными вызовами (например, стандартная функция Cfeofв многопоточной среде).Атрибут
pureнакладывает на определение функции ограничения, аналогичные, но более мягкие, чем ограничения атрибутаconst:pureпозволяет функции читать любую нев volatile-память, даже если она изменяется между последовательными вызовами функции. Объявление одной и той же функции с атрибутамиpureиconstприводит к диагностике. Поскольку чистая функция не может иметь наблюдаемых побочных эффектов, возвращатьvoidтакой функции не имеет смысла. Такое объявление приводит к диагностике. -
unsequenced -
Этот атрибут является аналогом GNU атрибута C23
[[unsequenced]]и используется для указания указателей на функции, которые, согласно определению C23, не имеют побочных эффектов, идемпотентны, не зависят от состояния и независимы.В отличие от стандартного атрибута C23, его также можно указывать в атрибутах, относящихся к объявлениям функций; в этом случае он применяется к их типу функции.
Функции без указателей или ссылок в аргументах, выполняемые без упорядочивания, подобны функциям с атрибутом
const, за исключением того, что атрибутconstтакже требует конечности. Поэтому функции с атрибутамиconstиunsequencedмогут оптимизироваться путем устранения общих подвыражений, но только функции с атрибутомconstмогут оптимизироваться путем удаления мертвого кода, если их результат не используется или используется только мертвым кодом. Функции без указателей или ссылок в аргументах, выполняемые без упорядочивания и имеющие тип возвращаемого значенияvoid, приводят к диагностике, поскольку они не могут сохранять результаты и не имеют других наблюдаемых побочных эффектов.Функции с указателями или ссылками в аргументах, выполняемые без упорядочивания, могут проверять объекты через переданные указатели или ссылки, а также через ссылки на указатели; они могут сохранять дополнительные результаты через эти указатели или ссылки либо через ссылки на указатели.
Атрибут
unsequencedнакладывает больше ограничений, чем аналогичный атрибутreproducible, и меньше ограничений, чем атрибутconst, поэтому при оптимизацииconstимеет приоритет надunsequenced, а тот, в свою очередь, — надreproducible. -
reproducible -
Этот атрибут является аналогом GNU атрибута C23
[[reproducible]]и используется для указания указателей на функции, которые, согласно определению C23, не имеют побочных эффектов и идемпотентны.В отличие от стандартного атрибута C23, его также можно указывать в атрибутах, относящихся к объявлениям функций; в этом случае он применяется к их типу функции.
Воспроизводимые функции без указателей или ссылок в аргументах, а также функции, не изменяющие объекты, на которые ссылаются аргументы-указатели или аргументы-ссылки, подобны функциям с атрибутом
pure, за исключением того, что атрибутpureтакже требует конечности. Поэтому функции с атрибутамиpureиreproducibleмогут оптимизироваться путем устранения общих подвыражений, если глобальное состояние или любые данные, доступные через аргументы-указатели или аргументы-ссылки, не изменяются, но только функции с атрибутомpureмогут оптимизироваться путем удаления мертвого кода, если их результат не используется или используется только мертвым кодом. Воспроизводимые функции без указателей или ссылок в аргументах и с типом возвращаемого значения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));
позволяет компилятору оптимизировать вызывающий код, исходя из того, что возвращаемое значение никогда не будет равно null.
-
returns_twice -
Атрибут
returns_twiceсообщает компилятору, что функция может возвращаться более одного раза. Перед вызовом такой функции компилятор обеспечивает, чтобы все регистры были свободны, и выдает предупреждение о переменных, значения которых могут быть затерты после второго возврата из функции. Примерами таких функций являютсяsetjmpиvfork. Если существует аналог такой функции, подобныйlongjmp, его, возможно, потребуется пометить атрибутом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)))
Для встроенных функций
execlиexeclpатрибут задается автоматически со значением позиции 0. Для встроенной функции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, …) -
В нескольких целевых серверных модулях реализован атрибут
target, позволяющий указать, что функция должна компилироваться с параметрами целевой платформы, отличными от заданных в командной строке. Исходные параметры целевой платформы из командной строки игнорируются. В качестве аргументов можно указать одну или несколько строк. Каждая строка состоит из одного или нескольких суффиксов, разделенных запятыми; они добавляются к префиксу-mи вместе образуют имя машинно-зависимого параметра. См. Машинно-зависимые параметры.Атрибут
targetможно использовать, например, чтобы скомпилировать функцию с другой ISA (архитектурой набора команд), чем заданная по умолчанию. ‘#pragma GCC target’ можно использовать для задания параметров, специфичных для целевой платформы, более чем для одной функции. Подробности о директиве pragma см. в разделе Директивы pragma для параметров отдельных функций.Например, на 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 и Атрибуты функций 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, а другой — с параметрами по умолчанию. Для использования атрибутаtarget_clonesGCC должен быть настроен на использование GLIBC 2.23 или новее.Также создается функция-разрешитель (см. описание атрибута
ifuncвыше), которая динамически выбирает клон, подходящий для текущей архитектуры. Разрешитель создается, только если функция с атрибутомtarget_clonesгде-либо используется.Обратите внимание: любой последующий вызов функции без
target_cloneиз вызывающей функции сtarget_cloneне приведет к копированию (клонированию для целевой платформы) вызываемой функции. Если требуется принудительно обеспечить такое поведение, рекомендуется объявить вызывающую функцию с атрибутомflatten? -
unavailable unavailable (msg)-
Атрибут
unavailableприводит к ошибке, если функция используется где-либо в исходном файле. Это полезно при выявлении функций, удаленных из конкретного варианта интерфейса. За исключением выдачи ошибки вместо предупреждения, атрибутunavailableработает так же, какdeprecated.Атрибут
unavailableтакже можно использовать для переменных и типов (см. разделы Указание атрибутов переменных и Указание атрибутов типов.) -
unused -
Этот атрибут, примененный к функции, означает, что функция, возможно, не используется. GCC не выдает предупреждение для этой функции.
-
used -
Этот атрибут, примененный к функции, означает, что код функции должен генерироваться, даже если функция, по-видимому, не вызывается. Это полезно, например, когда на функцию ссылаются только во встроенном ассемблерном коде.
Если атрибут применен к функции-члену шаблона класса C++, он также означает, что функция создается при инстанцировании самого класса.
-
visibility ("visibility_type") -
Этот атрибут влияет на связывание объявления, к которому он применен. Его можно применять не только к функциям, но и к переменным (см. раздел Общие атрибуты переменных) и типам (см. раздел Общие атрибуты типов).
Поддерживаются четыре значения visibility_type: видимость по умолчанию, скрытая, защищенная или внутренняя.
void __attribute__ ((visibility ("protected"))) f () { /* Do something. */; } int i __attribute__ ((visibility ("hidden")));Возможные значения visibility_type соответствуют настройкам видимости в ELF gABI.
default-
Видимость по умолчанию — обычный случай для формата объектных файлов. Это значение доступно для атрибута видимости, чтобы переопределять другие параметры, которые могут менять предполагаемую видимость сущностей.
В ELF видимость по умолчанию означает, что объявление доступно другим модулям, а в разделяемых библиотеках — что объявленная сущность может быть переопределена.
В Darwin видимость по умолчанию означает, что объявление доступно другим модулям.
Видимость по умолчанию соответствует «внешнему связыванию» в языке.
hidden-
Скрытая видимость означает, что объявленная сущность имеет новую форму связывания, которую мы называем «скрытым связыванием». Два объявления объекта со скрытым связыванием ссылаются на один и тот же объект, если они находятся в одном и том же разделяемом объекте.
internal-
Внутренняя видимость подобна скрытой видимости, но имеет дополнительные процессор-зависимые семантические свойства. Если в psABI не указано иное, GCC определяет внутреннюю видимость как гарантию того, что функция никогда не вызывается из другого модуля. Сравните это со скрытыми функциями: хотя на них нельзя ссылаться напрямую из других модулей, на них можно ссылаться косвенно через указатели на функции. Указание, что функцию нельзя вызвать извне модуля, позволяет GCC, например, опустить загрузку PIC-регистра, поскольку известно, что вызывающая функция загрузила правильное значение.
protected-
Защищенная видимость подобна видимости по умолчанию, но указывает, что ссылки внутри определяющего модуля связываются с определением в этом модуле. То есть объявленная сущность не может быть переопределена другим модулем.
Все виды видимости поддерживаются во многих, но не во всех целях ELF (поддержка имеется, если ассемблер поддерживает псевдооперацию ‘.visibility’). Видимость по умолчанию поддерживается везде. Скрытая видимость поддерживается для целей Darwin.
Атрибут видимости следует применять только к объявлениям, которые в противном случае имели бы внешнее связывание. Атрибут следует применять единообразно: одну и ту же сущность нельзя объявлять с разными значениями этого атрибута.
В C++ атрибут видимости применяется как к типам, так и к функциям и объектам, поскольку в C++ типы имеют связывание. Видимость класса не должна быть выше видимости типов его нестатических членов данных и базовых классов, а члены класса по умолчанию наследуют видимость класса. Кроме того, объявление без явно заданной видимости ограничено видимостью своего типа.
В C++ атрибут видимости можно применять к функциям-членам и статическим переменным-членам класса. Это полезно, если известно, что определенный метод или статическая переменная-член должны использоваться только из одного разделяемого объекта; тогда их можно пометить как скрытые, оставив для остальной части класса видимость по умолчанию. Необходимо соблюдать осторожность, чтобы не нарушить правило одного определения; например, обычно нет смысла помечать встроенный метод как скрытый, не пометив весь класс как скрытый.
Атрибут видимости можно также применять к объявлению пространства имен C++.
namespace nspace1 __attribute__ ((visibility ("protected"))) { /* Do something. */; }Этот атрибут применяется только к конкретному телу пространства имен, а не к другим определениям того же пространства имен; он эквивалентен использованию ‘#pragma GCC visibility’ до и после определения пространства имен (см. раздел Директивы pragma видимости).
В 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заставляет компилятор обнулять подмножество всех используемых при вызове регистров5 при возврате из функции. Это используется для повышения безопасности программы: для смягчения атак с использованием программирования, ориентированного на возврат (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.
Сноски
(5)
«Используемый при вызове» регистр — это регистр, содержимое которого может измениться при вызове функции; поэтому вызывающая функция не может рассчитывать на то, что после возврата из функции содержимое регистра останется таким же, каким было до её вызова. Такие регистры также называются «разрушаемыми при вызове», «сохраняемыми вызывающей стороной» или «летучими».
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Common-Function-Attributes.html