6.33.1 Общие атрибуты функций
Следующие атрибуты поддерживаются на большинстве целевых платформ.
-
access (access-mode, ref-index) access (access-mode, ref-index, size-index)-
Атрибут
accessпозволяет обнаруживать некорректные или небезопасные обращения функций, к которым он применяется, или их вызывающих функций, а также односторонние записи в объекты, которые никогда не считываются. Такие обращения могут быть диагностированы с помощью предупреждений, таких как -Wstringop-overflow, -Wuninitialized, -Wunused и другие.Атрибут
accessуказывает, что функция, к аргументам которой по ссылке применяется атрибут, обращается к объекту по ссылке в соответствии с режимом-доступа. Аргумент режим-доступа обязателен и должен быть одним из четырёх имён:read_only,read_write,write_only, илиnone. Остальные два — позиционные аргументы.Обязательный позиционный аргумент индекс-ссылки обозначает аргумент функции типа указателя (или, в C++, ссылки), который подлежит обращению. Один и тот же аргумент указателя может быть упомянут не более чем в одном отличительном атрибуте
access.Необязательный позиционный аргумент индекс-размера обозначает аргумент функции целочисленного типа, который указывает максимальный размер доступа. Размер — это количество элементов типа, на который ссылается индекс-ссылки, или количество байтов, когда тип указателя —
void*. Если аргумент индекс-размера не указан, аргумент указателя должен быть либо нулевым, либо указывать на область памяти, которая надлежащим образом выровнена и достаточно велика для как минимум одного объекта указанного типа (это подразумевает, что указатель, указывающий на область за пределами массива, не является допустимым аргументом). Фактический размер доступа может быть меньше, но не больше.Режим доступа
read_onlyуказывает, что указатель, к которому он применяется, используется для чтения объекта по ссылке, но не для записи в него. Если аргумент, определяющий размер доступа, обозначенный индекс-размера, не равен нулю, объект по ссылке должен быть инициализирован. Данный режим подразумевает более сильную гарантию, чем квалификаторconst, который, когда снимается с указателя, не предотвращает модификацию объекта, на который указывает указатель. Примеры использования режима доступаread_only— аргумент функцииputs, или второй и третий аргументы функцииmemcpy.__attribute__ ((access (read_only, 1))) int puts (const char*); __attribute__ ((access (read_only, 2, 3))) void* memcpy (void*, const void*, size_t);
Режим доступа
read_writeприменяется к аргументам типа указателя без квалификатораconst. Он указывает, что указатель, к которому он применяется, используется как для чтения, так и для записи в объект по ссылке. Если аргумент, определяющий размер доступа, обозначенный индекс-размера, не равен нулю, объект, на который указывает указатель, должен быть инициализирован. Пример использования режима доступаread_write— первый аргумент функцииstrcat.__attribute__ ((access (read_write, 1), access (read_only, 2))) char* strcat (char*, const char*);
Режим доступа
write_onlyприменяется к аргументам типа указателя без квалификатораconst. Он указывает, что указатель, к которому он применяется, используется для записи в объект по ссылке, но не для чтения из него. Объект, на который указывает указатель, не обязательно должен быть инициализирован. Пример использования режима доступаwrite_only— первый аргумент функцииstrcpy, или первые два аргумента функцииfgets.__attribute__ ((access (write_only, 1), access (read_only, 2))) char* strcpy (char*, const char*); __attribute__ ((access (write_only, 1, 2), access (read_write, 3))) int fgets (char*, int, FILE*);
Режим доступа
noneуказывает, что указатель, к которому он применяется, вообще не используется для доступа к объекту по ссылке. Если указатель не равен нулю, объект по ссылке должен существовать и иметь как минимум тот размер, который обозначен аргументом индекс-размера. Когда необязательный аргумент индекс-размера опущен для аргумента типаvoid*, фактический аргумент указателя игнорируется. Объект по ссылке не обязательно должен быть инициализирован. Режим предназначен для проверки ожидаемого размера объекта, например, в функциях, которые вызывают__builtin_object_size. См. Проверка размера объекта.Обратите внимание, что атрибут
accessпросто определяет, как можно получить доступ к объекту по ссылке, указанному аргументом указателя; это не подразумевает, что доступ будет осуществлён. Также атрибутaccessне подразумевает атрибутnonnull; может быть уместно добавить оба атрибута в объявление функции, которая безусловно манипулирует буфером через аргумент указателя. Дополнительную информацию и замечания см. в атрибутеnonnull. -
alias ("target") -
Атрибут
aliasзаставляет объявление генерироваться как псевдоним для другого символа, который должен был быть объявлен ранее с тем же типом и, для переменных, также с тем же размером и выравниванием. Объявление псевдонима с типом, отличным от целевого, не определено и может быть диагностировано. Например, следующие объявления:void __f () { /* Do something. */; } void f () __attribute__ ((weak, alias ("__f")));определяют ‘f’ как слабый псевдоним для ‘__f’. В C++, должно использоваться закодированное имя целевого символа. Ошибка возникает, если ‘__f’ не определено в той же единице трансляции.
Данный атрибут требует поддержки в ассемблере и объектных файлах и может быть недоступен на всех целевых платформах.
-
aligned aligned (alignment)-
Атрибут
alignedзадаёт минимальное выравнивание первого инструкций функции, измеряемое в байтах. При указании выравнивание должно быть целочисленной константой, являющейся степенью двойки. Не указание аргумента выравнивание подразумевает идеальное выравнивание для целевой платформы. Атрибут__alignof__можно использовать для определения этого значения (см. Определение выравнивания функций, типов или переменных). Атрибут не имеет эффекта, если определение функции не предоставлено в той же единице трансляции.Атрибут нельзя использовать для уменьшения выравнивания функции, ранее объявленной с более жёстким выравниванием; только для увеличения. Попытки сделать обратное будут диагностированы. Некоторые целевые платформы задают минимальное значение по умолчанию для выравнивания функций, большее 1. На таких платформах указание менее жёсткого выравнивания будет проигнорировано. Использование атрибута переопределяет действие опции -falign-functions (см. Опции, контролирующие оптимизацию) для данной функции.
Обратите внимание, что эффективность атрибутов
alignedможет быть ограничена присущими ограничениями системного линкера и/или формата объектных файлов. На некоторых системах линкер может только обеспечить выравнивание функций до определённого максимального значения. (Для некоторых линковщиков максимальное поддерживаемое выравнивание может быть очень маленьким). См. документацию своего линкера для получения дополнительной информации.Атрибут
alignedтакже может быть использован для переменных и полей (см. Указание атрибутов переменных.) -
alloc_align (position) -
Атрибут
alloc_alignможет быть применён к функции, возвращающей указатель и принимающей как минимум один аргумент целочисленного или перечислимого типа. Он указывает, что возвращаемый указатель выровнен на границе, заданной аргументом функции в позиции. Значимые значения выравнивания — степени двойки, большие единицы. GCC использует эту информацию для улучшения анализа выравнивания указателей.Параметр функции, обозначающий выравнивание выделенной памяти, задаётся одним целочисленным аргументом, число которого является аргументом атрибута. Нумерация аргументов начинается с единицы.
Например,
void* my_memalign (size_t, size_t) __attribute__ ((alloc_align (1)));
объявляет, что
my_memalignвозвращает память с минимальным выравниванием, заданным параметром 1. -
alloc_size (position) alloc_size (position-1, position-2)-
Атрибут
alloc_sizeможет быть применён к функции, возвращающей указатель и принимающей как минимум один аргумент целочисленного или перечислимого типа. Он указывает, что возвращаемый указатель указывает на память, размер которой задаётся аргументом функции в позиции-1, или произведением аргументов в позиции-1 и позиции-2. Значимые значения размеров — положительные значения, меньшиеPTRDIFF_MAX. GCC использует эту информацию для улучшения результатов__builtin_object_size.Параметр(ы) функции, обозначающие выделенный размер, задаются одним или двумя целочисленными аргументами, переданными атрибуту. Выделенный размер — либо значение единственного заданного аргумента функции, либо произведение двух заданных аргументов функции. Нумерация аргументов начинается с единицы для обычных функций и со второй для нестатических функций-членов в C++.
Например,
void* my_calloc (size_t, size_t) __attribute__ ((alloc_size (1, 2))); void* my_realloc (void*, size_t) __attribute__ ((alloc_size (2)));
объявляет, что
my_callocвозвращает память размера, равного произведению параметра 1 и 2, и чтоmy_reallocвозвращает память размера, равного параметру 2. -
always_inline -
В общем случае функции не встраиваются, если не указана оптимизация. Для функций, объявленных встраиваемыми, данный атрибут встраивает функцию независимо от ограничений, которые в противном случае применяются к встраиванию. Невозможность встраивания такой функции диагностируется как ошибка. Обратите внимание, что если такая функция вызывается косвенно, компилятор может или не может встроить её в зависимости от уровня оптимизации, и неспособность встроить косвенный вызов может или не может быть диагностирована.
-
artificial -
Данный атрибут полезен для небольших встраиваемых обёртках, которые, если это возможно, должны отображаться во время отладки как единый блок. В зависимости от формата отладочной информации это либо означает маркирование функции как искусственной, либо использование местоположения вызывающей функции для всех инструкций внутри встраиваемого тела.
-
assume_aligned (alignment) assume_aligned (alignment, offset)-
Атрибут
assume_alignedможет быть применён к функции, возвращающей указатель. Он указывает, что возвращаемый указатель выровнен на границе, заданной выравнивание. Если у атрибута есть два аргумента, второй аргумент — смещение невыравнивания смещение. Значимые значения выравнивание — степени двойки, большие единицы. Значимые значения смещение — больше нуля и меньше выравнивание.Например
void* my_alloc1 (size_t) __attribute__((assume_aligned (16))); void* my_alloc2 (size_t) __attribute__((assume_aligned (32, 8)));
объявляет, что
my_alloc1возвращает 16-байтовые выровненные указатели и чтоmy_alloc2возвращает указатель, значение которого по модулю 32 равно 8. -
cold
-
Атрибут
coldдля функций сообщает компилятору, что функция вряд ли будет выполнена. Функция оптимизирована для размера, а не скорости, и на многих целевых платформах она размещается в специальной секции текстовой секции, чтобы все холодные функции располагались близко друг к другу, улучшая локальность кода для нехолодных частей программы. Пути, ведущие к вызовам холодных функций в коде, отмечаются как маловероятные механизмом предсказания ветвей. Поэтому полезно помечать функции, используемые для обработки маловероятных условий, такие какperror, как холодные, чтобы улучшить оптимизацию горячих функций, которые иногда вызывают помеченные функции. В C++, атрибутcoldможет быть применён к типам с эффектом распространения на методы-члены. См. C++-специфические атрибуты переменных, функций и типов.Когда доступна обратная связь профилирования, через -fprofile-use, холодные функции автоматически обнаруживаются, и этот атрибут игнорируется.
-
const -
Вызовы функций, значение возврата которых не изменяется изменениями наблюдаемого состояния программы и которые не оказывают наблюдаемого влияния на это состояние, кроме возврата значения, могут быть оптимизированы, например, путём устранения общих подвыражений. Объявление таких функций с атрибутом
constпозволяет GCC избегать выдачи некоторых вызовов при повторных вызовах функции с одинаковыми значениями аргументов.Например,
int square (int) __attribute__ ((const));
сообщает GCC, что последующие вызовы функции
squareс одинаковым значением аргумента могут быть заменены результатом первого вызова независимо от промежуточных инструкций.Атрибут
constзапрещает функции читать объекты, влияющие на её значение возврата, между последовательными вызовами. Однако функции, объявленные с этим атрибутом, могут безопасно читать объекты, не изменяющие их значение возврата, такие как константы без побочных эффектов.Атрибут
constнакладывает более жёсткие ограничения на определение функции, чем похожий атрибутpure. Объявление одной и той же функции с атрибутамиconstиpureприводит к диагностике. Поскольку константная функция не может иметь каких-либо наблюдаемых побочных эффектов, она не должна возвращатьvoid. Объявление такой функции приводит к диагностике.Обратите внимание, что функция с указателями в качестве аргументов и проверяющая данные по указателям не должна быть объявлена
const, если данные, на которые указывают указатели, могут измениться между последовательными вызовами функции. В общем случае, поскольку функция не может отличить данные, которые могут измениться, от данных, которые не могут, константные функции никогда не должны принимать указатели или, в C++, ссылки в качестве аргументов. Аналогично, функция, которая вызывает неконстантную функцию, обычно не должна быть константной. -
constructor destructorconstructor (priority)destructor (priority)-
Атрибут
constructorвызывает автоматический вызов функции перед входом вmain (). Аналогично, атрибутdestructorвызывает автоматический вызов функции после завершенияmain ()или вызоваexit (). Функции с этими атрибутами полезны для инициализации данных, которые используются неявно во время выполнения программы.На некоторых целевых платформах атрибуты также принимают целочисленный аргумент для задания приоритета, чтобы контролировать порядок выполнения функций-конструкторов и деструкторов. Конструктор с меньшим номером приоритета выполняется перед конструктором с большим номером приоритета; обратное отношение верно для деструкторов. Обратите внимание, что приоритеты 0-100 зарезервированы. Поэтому, если у вас есть конструктор, который выделяет ресурс, и деструктор, который освобождает этот же ресурс, обе функции обычно имеют одинаковый приоритет. Приоритеты для функций-конструкторов и деструкторов такие же, как и для объектов C++ на уровне пространства имён (см. C++-специфические атрибуты переменных, функций и типов). Однако в настоящее время порядок вызова конструкторов для объектов C++ со статическим временем хранения и функций, помеченных атрибутом
constructor, не определён. При смешанных объявлениях атрибутinit_priorityможет быть использован для навязывания определённого порядка.Использование форм аргументов атрибутов
constructorиdestructorна целевых платформах, где эта функция не поддерживается, приводит к ошибке. -
copy copy (function)-
Атрибут
copyприменяет набор атрибутов, с помощью которых была объявлена функция, к объявлению функции, к которой применяется атрибут. Атрибут предназначен для библиотек, которые определяют псевдонимы или разрешители функций, которые должны указывать тот же набор атрибутов, что и их целевые функции. Атрибутcopyможет использоваться с функциями, переменными или типами. Однако тип символа, к которому применяется атрибут (функция или переменная), должен совпадать с типом символа, к которому относится аргумент. Атрибутcopyкопирует только синтаксические и семантические атрибуты, но не атрибуты, влияющие на связь или видимость символа, такие какalias,visibilityилиweak. Атрибутыdeprecatedиtarget_clonesтакже не копируются. См. Общие атрибуты типов. См. Общие атрибуты переменных.Например, макрос StrongAlias ниже использует атрибуты
aliasиcopyдля определения псевдонима, названного alloc, для функции allocate, объявленной с атрибутами alloc_size, malloc и nothrow. Благодаря оператору__typeof__псевдоним имеет тот же тип, что и целевая функция. В результате атрибутаcopyпсевдоним также разделяет те же атрибуты, что и целевая функция.#define StrongAlias(TargetFunc, AliasDecl) \ extern __typeof__ (TargetFunc) AliasDecl \ __attribute__ ((alias (#TargetFunc), copy (TargetFunc))); extern __attribute__ ((alloc_size (1), malloc, nothrow)) void* allocate (size_t); StrongAlias (allocate, alloc); -
deprecated deprecated (msg)-
Атрибут
deprecatedприводит к появлению предупреждения, если функция используется где-либо в исходном файле. Это полезно для выявления функций, которые, как ожидается, будут удалены в будущей версии программы. Предупреждение также включает расположение объявления устаревшей функции, чтобы пользователи могли легко найти дополнительную информацию о том, почему функция устарела или что им следует сделать вместо этого. Обратите внимание, что предупреждения возникают только при использовании:int old_fn () __attribute__ ((deprecated)); int old_fn (); int (*fn_ptr)() = old_fn;
приводит к появлению предупреждения на строке 3, но не на строке 2. Необязательный аргумент msg, который должен быть строкой, печатается в предупреждении, если он присутствует.
Атрибут
deprecatedтакже может использоваться для переменных и типов (см. Указание атрибутов переменных, см. Указание атрибутов типов).Сообщение, связанное с атрибутом, зависит от настройки параметра -fmessage-length.
-
error ("message") warning ("message")-
Если атрибут
errorилиwarningиспользуется в объявлении функции, и вызов такой функции не устраняется благодаря устранению неиспользуемого кода или другим оптимизациям, генерируется ошибка или предупреждение (соответственно), содержащее сообщение. Это полезно для проверки на этапе компиляции, особенно вместе с__builtin_constant_pи встроенными функциями, где проверка аргументов встроенной функции невозможна с помощьюextern char [(condition) ? 1 : -1];уловок.Хотя можно оставить функцию неопределённой и тем самым вызвать ошибку компоновки (для определения функции с сообщением в
.gnu.warning*разделе), при использовании этих атрибутов проблема диагностируется раньше и с точным указанием места вызова даже в присутствии встроенных функций или при отсутствии отладочной информации. -
expected_throw -
Этот атрибут, прикреплённый к функции, указывает компилятору, что функция более склонна к возбуждению или распространению исключения, чем к возврату, бесконечному циклу или завершению программы.
Этот намёк в основном игнорируется компилятором. Единственный эффект наблюдается, когда он применяется к функциям
noreturnи включен параметр «-fharden-control-flow-redundancy», и параметр «-fhardcfr-check-noreturn-calls=not-always» не переопределён. -
externally_visible -
Этот атрибут, прикреплённый к глобальной переменной или функции, делает недействительным действие командной строки -fwhole-program, поэтому объект остаётся видимым вне текущей единицы компиляции.
Если -fwhole-program используется вместе с -flto и
goldиспользуется в качестве плагина компоновки, атрибутыexternally_visibleавтоматически добавляются к функциям (не к переменным пока из-за текущейgoldпроблемы) которые обращаются за пределами объектов LTO в соответствии с файлом разрешения, созданнымgold. Для других компоновочных модулей, которые не могут сгенерировать файл разрешения, явные атрибутыexternally_visibleвсё равно необходимы. -
fd_arg fd_arg (N)-
Атрибут
fd_argможет быть применён к функции, которая принимает открытый дескриптор файла в аргументе N.Он указывает, что переданный дескриптор файла не должен быть закрыт. Поэтому, когда анализатор включён с помощью -fanalyzer, анализатор может выдать диагностику -Wanalyzer-fd-use-after-close, если обнаружит путь кода, в котором функция с этим атрибутом вызывается с закрытым дескриптором файла.
Атрибут также указывает, что дескриптор файла должен быть проверен на корректность перед использованием. Поэтому анализатор может выдать диагностику -Wanalyzer-fd-use-without-check, если обнаружит путь кода, в котором функция с этим атрибутом вызывается с дескриптором файла, который не был проверен на корректность.
-
fd_arg_read fd_arg_read (N)
-
Атрибут
fd_arg_readидентичен атрибутуfd_arg, но с дополнительным требованием, что он может читать из дескриптора файла, а значит, дескриптор файла не должен был быть открыт только для записи.Анализатор может вывести диагностическое сообщение -Wanalyzer-access-mode-mismatch, если обнаружит путь выполнения кода, в котором функция с этим атрибутом вызывается с дескриптором файла, открытым с помощью
O_WRONLY. -
fd_arg_write fd_arg_write (N)-
Атрибут
fd_arg_writeидентичен атрибутуfd_arg_read, за исключением того, что анализатор может вывести диагностическое сообщение -Wanalyzer-access-mode-mismatch, если обнаружит путь выполнения кода, в котором функция с этим атрибутом вызывается с дескриптором файла, открытым с помощьюO_RDONLY. -
flatten -
Встраивание в функцию обычно ограничено. Для функции, помеченной этим атрибутом, каждое вызов внутри этой функции встраивается, включая вызовы, которые встраивание вводит в функцию (но не рекурсивные вызовы самой функции), если это возможно. Функции, объявленные с атрибутом
noinlineи аналогичными, не встраиваются. Будет ли сама функция рассматриваться для встраивания, зависит от её размера и текущих параметров встраивания. -
format (archetype, string-index, first-to-check) -
Атрибут
formatуказывает, что функция принимает аргументы типаprintf,scanf,strftimeилиstrfmon, которые должны быть проверены на соответствие строке формата. Например, объявление:extern int my_printf (void *my_object, const char *my_format, ...) __attribute__ ((format (printf, 2, 3)));приводит к тому, что компилятор проверяет аргументы в вызовах функции
my_printfна соответствие строке формата стиляprintfаргументуmy_format.Параметр archetype определяет, как интерпретируется строка формата, и должен быть
printf,scanf,strftime,gnu_printf,gnu_scanf,gnu_strftimeилиstrfmon. (Также можно использовать__printf__,__scanf__,__strftime__или__strfmon__. На целевых платформах MinGW также присутствуютms_printf,ms_scanfиms_strftime. Значения archetype, такие какprintf, относятся к форматам, поддерживаемым системной библиотекой C runtime, а значения, начинающиеся с ‘gnu_’, всегда относятся к форматам, поддерживаемым GNU C Library. На целевых платформах Microsoft Windows значения, начинающиеся с ‘ms_’, относятся к форматам, поддерживаемым библиотекой msvcrt.dll. Параметр string-index указывает, какой аргумент является аргументом строки формата (начиная с 1), а first-to-check — номер первого аргумента для проверки по отношению к строке формата. Для функций, где аргументы недоступны для проверки (например,vprintf), укажите третий параметр как ноль. В этом случае компилятор проверяет только строку формата на соответствие. Для форматовstrftimeтретий параметр должен быть равен нулю. Так как у нестатических методов C++ есть неявный аргументthis, аргументы таких методов следует считать с двух, а не с одного, при указании значений для string-index и first-to-check.В примере выше строка формата (
my_format) является вторым аргументом функцииmy_print, а проверяемые аргументы начинаются с третьего, поэтому правильные параметры для атрибута формата — 2 и 3.Атрибут
formatпозволяет идентифицировать собственные функции, принимающие строки формата в качестве аргументов, чтобы GCC мог проверять вызовы этих функций на ошибки. Компилятор всегда (если не используется -ffreestanding или -fno-builtin) проверяет форматы для стандартных функций библиотекиprintf,fprintf,sprintf,scanf,fscanf,sscanf,strftime,vprintf,vfprintfиvsprintf, когда такие предупреждения запрашиваются (с помощью -Wformat), поэтому нет необходимости изменять заголовочный файл stdio.h. В режиме C99 также проверяются функцииsnprintf,vsnprintf,vscanf,vfscanfиvsscanf. Кроме строго соответствующих режимов стандарта C, функция X/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__. См. Функция, помеченная как inline, так же быстрая, как и макрос.В C++, этот атрибут никак не зависит от
extern, но всё ещё требует ключевое словоinlineдля включения своего специального поведения. -
hot
-
Атрибут
hotдля функции информирует компилятор, что функция является горячей точкой в скомпилированной программе. Функция оптимизируется более агрессивно, и на многих целевых платформах она помещается в специальный подсекцию секции текста, чтобы все горячие функции располагались близко друг к другу, улучшая локальность. В C++, атрибутhotможет применяться к типам с эффектом распространения на методы-члены. См. Атрибуты C++-специфичных переменных, функций и типов.Когда обратная связь профилирования доступна через -fprofile-use, горячие функции автоматически обнаруживаются, и этот атрибут игнорируется.
-
ifunc ("resolver") -
Атрибут
ifuncиспользуется для маркировки функции как косвенной функции, используя расширение типа символа STT_GNU_IFUNC к стандарту ELF. Это позволяет динамически определить значение символа во время загрузки и выбрать оптимизированную версию подпрограммы для конкретного процессора или других характеристик системы, определенных в этот момент. Для использования этого атрибута сначала необходимо определить доступные реализации функций и функцию-резольвер, которая возвращает указатель на выбранную реализующую функцию. Объявления реализующих функций должны соответствовать API реализуемой функции. Функция-резольвер должна быть объявлена как функция без аргументов, возвращающая указатель на функцию того же типа, что и реализация. Например:void *my_memcpy (void *dst, const void *src, size_t len) { … return dst; } static void * (*resolve_memcpy (void))(void *, const void *, size_t) { return my_memcpy; // we will just always select this routine }Экспортируемый заголовочный файл, объявляющий вызываемую пользователем функцию, будет содержать:
extern void *memcpy (void *, const void *, size_t);
позволяя пользователю вызывать
memcpyкак обычную функцию, не зная фактической реализации. Наконец, косвенная функция должна быть определена в том же модуле трансляции, что и функция-резольвер:void *memcpy (void *, const void *, size_t) __attribute__ ((ifunc ("resolve_memcpy")));В C++, атрибут
ifuncпринимает строку, которая является искаженным именем функции-резольвера. Функция-резольвер C++ для нестатического метода-члена классаCдолжна быть объявлена для возврата указателя на функцию без указания класса, принимающую указатель наCв качестве первого аргумента, за которым следуют те же аргументы, что и в реализующей функции. G++ проверяет подписи двух функций и выдает предупреждение -Wattribute-alias при несовпадениях. Чтобы подавить предупреждение о необходимости приведения от указателя на реализующий член функции к типу соответствующей функции без указания класса, используйте опцию -Wno-pmf-conversions. Например:class S { private: int debug_impl (int); int optimized_impl (int); typedef int Func (S*, int); static Func* resolver (); public: int interface (int); }; int S::debug_impl (int) { /* … */ } int S::optimized_impl (int) { /* … */ } S::Func* S::resolver () { int (S::*pimpl) (int) = getenv ("DEBUG") ? &S::debug_impl : &S::optimized_impl; // Cast triggers -Wno-pmf-conversions. return reinterpret_cast<Func*>(pimpl); } int S::interface (int) __attribute__ ((ifunc ("_ZN1S8resolverEv")));Косвенные функции не могут быть слабыми. Для использования этой функции требуются версия бинарных утилит 2.20.1 или выше и GNU C Library версии 2.11.1 или выше.
-
interrupt interrupt_handler-
Многие бэкенды GCC поддерживают атрибуты для указания того, что функция является обработчиком прерываний, что сообщает компилятору генерировать последовательности входа и выхода из функции, отличающиеся от последовательностей обычных функций. Точный синтаксис и поведение зависят от целевой платформы; см. следующие подсекции для получения подробной информации.
-
leaf -
Вызовы внешних функций с этим атрибутом должны возвращаться в текущий модуль компиляции только через возврат или обработку исключений. В частности, функция-листок не может вызывать функции обратного вызова, переданные ей из текущего модуля компиляции, напрямую вызывать функции, экспортируемые модулем, или
longjmpв модуль. Функции-листья всё ещё могут вызывать функции из других модулей компиляции, и поэтому они не обязательно являются листьями в том смысле, что они не содержат никаких вызовов функций вообще.Этот атрибут предназначен для функций библиотек, чтобы улучшить анализ потока данных. Компилятор получает подсказку о том, что любые данные, не покидающие текущий модуль компиляции, не могут использоваться или изменяться функцией-листом. Например, функция
sinявляется функцией-листом, ноqsortне является.Обратите внимание, что функции-листья могут косвенно запускать обработчик сигналов, определённый в текущем модуле компиляции, который использует статические переменные. Аналогично, при отложенном разрешении символов функции-листья могут вызывать косвенные функции, функция-резольвер или реализующая функция которых определены в текущем модуле компиляции и используют статические переменные. Нет стандартного способа написать такой обработчик сигналов, функцию-резольвер или реализующую функцию, и лучше всего удалить атрибут
leafили отметить все такие статические переменныеvolatile. Наконец, для систем ELF, поддерживающих интерпозицию символов, следует позаботиться о том, чтобы функции, определённые в текущем модуле компиляции, не интерпонировали другие символы непредвиденным образом, исходя из определённого стандартного режима и определённых макросов тестов функций; в противном случае будет добавлен нежелательный обратный вызов.Атрибут не оказывает никакого влияния на функции, определённые в текущем модуле компиляции. Это позволяет легко объединять несколько модулей компиляции в один, например, с помощью оптимизации при компоновке. По этой причине атрибут не разрешается для типов, чтобы аннотировать косвенные вызовы.
-
malloc malloc (deallocator)malloc (deallocator, ptr-index)-
Атрибут
mallocуказывает, что функция является похожей наmalloc, т.е. что указатель P, возвращаемый функцией, не может быть алиасом любого другого указателя, действительного при возврате функции, и, кроме того, ни один указатель на допустимые объекты не встречается в любом хранилище, адресуемом P. Кроме того, GCC прогнозирует, что функция с этим атрибутом возвращает не-null в большинстве случаев.В отдельности, форма атрибута с одним или двумя аргументами ассоциирует
deallocatorкак подходящую функцию освобождения для указателей, возвращаемых из функции, подобнойmalloc. ptr-index обозначает позиционный аргумент, при передаче указателя в вызовыdeallocator, имеющий эффект освобождения указателя.Использование атрибута без аргументов предназначено для улучшения оптимизации, опираясь на свойство алиасирования, которое он подразумевает. Функции, подобные
mallocиcalloc, обладают этим свойством, так как они возвращают указатель на неинициализированное или обнуленное, недавно полученное хранилище. Однако функции, подобныеrealloc, не обладают этим свойством, так как они могут возвращать указатели на хранилище, содержащее указатели на существующие объекты. Кроме того, поскольку все такие функции предполагаются возвращающими null только нечасто, вызывающие функции могут оптимизироваться на основе этого предположения.Связывание функции с deallocator помогает обнаруживать вызовы несовпадающих функций выделения и освобождения и диагностировать их под управлением таких опций, как -Wmismatched-dealloc. Это также позволяет диагностировать попытки освобождения объектов, которые не были выделены динамически, с помощью -Wfree-nonheap-object. Для указания того, что функция выделения удовлетворяет свойству неалиасирования и имеет связанную функцию освобождения, необходимо использовать как обычную форму атрибута, так и форму с аргументом deallocator. Одна и та же функция может быть как функцией выделения, так и функцией освобождения. Поскольку инлайнинг одной из связанных функций, но не другой, может привести к видимым несовпадениям, эта форма атрибута
mallocне принимается для инлайновых функций. По той же причине использование атрибута предотвращает инлайнинг как функции выделения, так и функции освобождения.Например, помимо утверждения о том, что функции возвращают указатели, не являющиеся алиасами других, следующие объявления делают
fcloseподходящей функцией освобождения для указателей, возвращаемых из всех функций, кромеpopen, аpclose— единственной подходящей функцией освобождения для указателей, возвращаемых изpopen. Функции освобождения должны быть объявлены до их использования в атрибуте.int fclose (FILE*); int pclose (FILE*); __attribute__ ((malloc, malloc (fclose, 1))) FILE* fdopen (int, const char*); __attribute__ ((malloc, malloc (fclose, 1))) FILE* fopen (const char*, const char*); __attribute__ ((malloc, malloc (fclose, 1))) FILE* fmemopen(void *, size_t, const char *); __attribute__ ((malloc, malloc (pclose, 1))) FILE* popen (const char*, const char*); __attribute__ ((malloc, malloc (fclose, 1))) FILE* tmpfile (void);
Предупреждения, защищённые -fanalyzer, учитывают пары выделения и освобождения, помеченные атрибутом
malloc. В частности:- Анализатор выводит диагностику -Wanalyzer-mismatching-deallocation, если существует путь выполнения, в котором результат вызова выделения передаётся другому освободителю.
- Анализатор выводит диагностику -Wanalyzer-double-free, если существует путь выполнения, в котором значение передаётся более одного раза в вызов освобождения.
- Анализатор рассматривает возможность того, что функция выделения может завершиться неудачей и вернуть null. Если существуют пути выполнения, в которых результат вызова выделения, не проверяемый на null, дереферируется или передаётся в функцию, требующую не-null аргумент, он выводит диагностики -Wanalyzer-possible-null-dereference и -Wanalyzer-possible-null-argument. Если функция выделения всегда возвращает не-null, используйте
__attribute__ ((returns_nonnull))для подавления этих предупреждений. Например:char *xstrdup (const char *) __attribute__((malloc (free), returns_nonnull));
- Анализатор выводит диагностику -Wanalyzer-use-after-free, если существует путь выполнения, в котором память, переданная по указателю в вызов освобождения, используется после освобождения.
- Анализатор выводит диагностику -Wanalyzer-malloc-leak, если существует путь выполнения, в котором результат вызова выделения утечка (без передачи освободителю).
- Анализатор выводит диагностику -Wanalyzer-free-of-non-heap, если функция освобождения используется на глобальной или стековой переменной.
Анализатор предполагает, что освободители могут корректно обрабатывать указатель null. Если это не так, освободитель может быть помечен
__attribute__((nonnull)), чтобы -fanalyzer мог выводить диагностику -Wanalyzer-possible-null-argument для путей кода, в которых освободитель вызывается с null. -
no_icf -
Этот атрибут функции предотвращает слияние функции с другой семантически эквивалентной функцией.
-
no_instrument_function -
Если заданы опции -finstrument-functions, -p или -pg, генерируются функции профилирования для вызовов функций в начале и конце большинства функций, скомпилированных пользователем. Функции с этим атрибутом не профилируются.
-
no_profile_instrument_function -
Атрибут
no_profile_instrument_functionдля функций сообщает компилятору, что он не должен обрабатывать никакую оптимизацию кода профилирования, основанную на обратной связи. -
no_reorder
-
Не переупорядочивайте функции или переменные, помеченные как
no_reorder, относительно друг друга или инструкций ассемблера верхнего уровня в исполняемом файле. Фактический порядок в программе будет зависеть от командной строки линкера. Статические переменные, помеченные таким образом, также не удаляются. Это имеет аналогичный эффект, как опция -fno-toplevel-reorder, но применяется только к помеченным символам. -
no_sanitize ("sanitize_option") -
Атрибут
no_sanitizeдля функций используется для информирования компилятора о том, что он не должен выполнять проверку на наличие указанных в sanitize_option опций. Можно предоставить список значений, допустимых для опции -fsanitize.void __attribute__ ((no_sanitize ("alignment", "object-size"))) f () { /* Do something. */; } void __attribute__ ((no_sanitize ("alignment,object-size"))) g () { /* Do something. */; } -
no_sanitize_address no_address_safety_analysis-
Атрибут
no_sanitize_addressдля функций используется для информирования компилятора о том, что он не должен инструментировать доступ к памяти в функции при компиляции с опцией -fsanitize=address. Атрибутno_address_safety_analysisявляется устаревшим псевдонимом атрибутаno_sanitize_address, в новом коде следует использоватьno_sanitize_address. -
no_sanitize_thread -
Атрибут
no_sanitize_threadдля функций используется для информирования компилятора о том, что он не должен инструментировать доступ к памяти в функции при компиляции с опцией -fsanitize=thread. -
no_sanitize_undefined -
Атрибут
no_sanitize_undefinedдля функций используется для информирования компилятора о том, что он не должен проверять неопределенное поведение в функции при компиляции с опцией -fsanitize=undefined. -
no_sanitize_coverage -
Атрибут
no_sanitize_coverageдля функций используется для информирования компилятора о том, что он не должен включать инструментирование для поведенческой fuzzing-тестирования на основе покрытия кода (-fsanitize-coverage). -
no_split_stack -
Если задана опция -fsplit-stack, функции имеют небольшой пролог, который определяет, следует ли разделить стек. Функции с атрибутом
no_split_stackне имеют этого пролога и, следовательно, могут выполняться только с небольшим объёмом доступной памяти стека. -
no_stack_limit -
Этот атрибут локально переопределяет опции командной строки -fstack-limit-register и -fstack-limit-symbol; он имеет эффект отключения проверки ограничений стека в функции, к которой он применяется.
-
no_stack_protector -
Этот атрибут предотвращает код защиты стека для функции.
-
noclone -
Этот атрибут функции предотвращает рассмотрение функции для клонирования — механизма, создающего специализированные копии функций, который (в настоящее время) выполняется с помощью межпроцедурного распространения констант.
-
noinline -
Этот атрибут функции предотвращает рассмотрение функции для встраивания. Также он отключает некоторые другие межпроцедурные оптимизации; предпочтительнее использовать более универсальный атрибут
noipaвместо него, если это ваша цель.Даже если функция объявлена с атрибутом
noinline, существуют оптимизации, отличные от встраивания, которые могут привести к тому, что вызовы будут оптимизированы, если они не имеют побочных эффектов, хотя вызов функции активен. Чтобы предотвратить оптимизацию таких вызовов, поместитеasm ("");(см. Расширенный ассемблер — инструкции ассемблера с операндами выражений C) в вызываемой функции, чтобы использовать её как особый побочный эффект.
-
noipa -
Отключить межпроцедурные оптимизации между функцией с этим атрибутом и её вызывающими функциями, как будто тело функции недоступно при оптимизации вызывающих функций, а вызывающие функции недоступны при оптимизации тела. Этот атрибут подразумевает атрибуты
noinline,nocloneиno_icf. Однако этот атрибут не эквивалентен комбинации других атрибутов, потому что его цель заключается в подавлении существующих и будущих оптимизаций, использующих межпроцедурный анализ, включая те, для которых нет подходящего атрибута для их отключения по отдельности. -
nonnull nonnull (arg-index, …)-
Атрибут
nonnullможет быть применён к функции, которая принимает по крайней мере один аргумент типа указателя. Он указывает, что ссылаемые аргументы должны быть указателями, отличными от нуля. Например, объявление:extern void * my_memcpy (void *dest, const void *src, size_t len) __attribute__((nonnull (1, 2)));информирует компилятор о том, что в вызовах
my_memcpyаргументы dest и src должны быть указателями, отличными от нуля.Атрибут влияет как на вызовы функций, так и на определения функций.
Для вызовов функций:
- Если компилятор определяет, что указатель с нулевым значением передаётся в аргумент, помеченный как не нулевой, и опция -Wnonnull включена, выводится предупреждение. См. Опции для запроса или подавления предупреждений.
- Опция -fisolate-erroneous-paths-attribute может быть задана для того, чтобы GCC преобразовывал вызовы с аргументами со значением NULL в функции, ожидающие не NULL, в ловушки. См. Опции, управляющие оптимизацией.
- Компилятор также может выполнять оптимизации, основанные на знании, что некоторые аргументы функций не могут быть NULL. Эти оптимизации можно отключить с помощью опции -fno-delete-null-pointer-checks. См. Опции, управляющие оптимизацией.
Для определений функций:
- Если компилятор определяет, что параметр функции, помеченный как nonnull, сравнивается с нулём, и опция -Wnonnull-compare включена, выводится предупреждение. См. Опции для запроса или подавления предупреждений.
- Компилятор также может выполнять оптимизации, основанные на знании, что параметры
nonnullне могут быть нулём. В настоящее время это невозможно отключить иначе, чем удалением атрибута nonnull.
Если атрибуту
nonnullне указан arg-index, все аргументы типа указателя помечаются как не равные нулю. Чтобы проиллюстрировать это, следующее объявление эквивалентно предыдущему примеру:extern void * my_memcpy (void *dest, const void *src, size_t len) __attribute__((nonnull)); -
noplt -
Атрибут
nopltявляется аналогом опции -fno-plt. Вызовы функций, помеченных этим атрибутом в позиционно-независимом коде, не используют PLT./* Externally defined function foo. */ int foo () __attribute__ ((noplt)); int main (/* … */) { /* … */ foo (); /* … */ }
Атрибут
nopltдля функцииfooсообщает компилятору, что функцияfooопределена внешне и вызовfooдолжен избегать PLT в позиционно-независимом коде.В позиционно-зависимом коде некоторые целевые системы также преобразуют вызовы функций, которые помечены как не использующие PLT, в использование GOT вместо этого.
-
noreturn -
Некоторые стандартные функции библиотеки, такие как
abortиexit, не могут возвращаться. GCC автоматически это знает. Некоторые программы определяют собственные функции, которые никогда не возвращаются. Вы можете объявить их какnoreturn, чтобы сообщить об этом компилятору. Например,void fatal () __attribute__ ((noreturn)); void fatal (/* … */) { /* … */ /* Print error message. */ /* … */ exit (1); }
Ключевое слово
noreturnсообщает компилятору, чтоfatalне может возвращаться. Тогда он может оптимизировать, не учитывая то, что произойдёт, еслиfatalвернётся. Это делает код немного лучше. Более важно, это помогает избежать ложных предупреждений об инициализированных переменных.Ключевое слово
noreturnне влияет на исключительный путь, если он применяется: функция с меткойnoreturnможет всё ещё возвращаться вызывающей функции, выбросив исключение или вызвавlongjmp.Для сохранения трассировок GCC никогда не преобразует вызовы функций
noreturnв tail-вызовы.Не предполагайте, что регистры, сохранённые вызывающей функцией, будут восстановлены до вызова функции
noreturn.Для функции
noreturnне имеет смысла иметь тип возвращаемого значения, отличный отvoid. -
nothrow -
Атрибут
nothrowиспользуется для информирования компилятора о том, что функция не может выбросить исключение. Например, большинство функций в стандартной библиотеке C могут быть гарантированы как не вызывающие исключений, за исключениемqsortиbsearch, которые принимают аргументы типа указателя на функцию. -
null_terminated_string_arg null_terminated_string_arg (N)
-
Атрибут
null_terminated_string_argможет быть применён к функции, принимающейchar *илиconst char *в качестве аргумента N.Он указывает, что переданный аргумент должен быть строкой с нулевым завершением в стиле C. Конкретно, наличие этого атрибута подразумевает, что если указатель не равен нулю, функция может сканировать указанный буфер, ища первый нулевой байт.
В частности, при включённом анализаторе (через -fanalyzer), если указатель не равен нулю, он будет имитировать поиск первого нулевого байта в указанном буфере и, возможно, выводить -Wanalyzer-use-of-uninitialized-value или -Wanalyzer-out-of-bounds при некорректно завершённых буферах.
Например, при следующем:
char *example_1 (const char *p) __attribute__((null_terminated_string_arg (1)));
анализатор проверит, что все указатели, переданные функции, корректно завершены.
Если параметр должен быть не нулевым, целесообразно использовать как этот атрибут, так и атрибут
nonnull, например:extern char *example_2 (const char *p) __attribute__((null_terminated_string_arg (1), nonnull (1)));Дополнительную информацию и замечания см. в атрибуте
nonnull.Если аргумент-указатель также упоминается с помощью атрибута
accessв функции с access-mode либоread_only, либоread_write, и последний атрибут имеет необязательный аргумент size-index, ссылающийся на аргумент размера, это выражает максимальный размер доступа. Например, при:extern char *example_fn (const char *p, size_t n) __attribute__((null_terminated_string_arg (1), access (read_only, 1, 2), nonnull (1)));анализатор потребует, чтобы первый параметр был не нулевым и либо корректно завершался нулём, либо корректно считывался до размера, заданного вторым параметром.
-
optimize (level, …) optimize (string, …)-
Атрибут
optimizeиспользуется для указания того, что функция должна быть скомпилирована с разными параметрами оптимизации, чем указанные в командной строке. Аргументы атрибута optimize функции ведут себя так, как будто они добавлены в командную строку.Допустимые аргументы — это константные неотрицательные целые числа и строки. Каждый числовой аргумент задаёт уровень оптимизации level. Каждый строковый аргумент состоит из одной или нескольких подстрок, разделённых запятыми. Каждая подстрока, начинающаяся с буквы
O, относится к параметру оптимизации, такому как -O0 или -Os. Другие подстроки рассматриваются как суффиксы префикса-fи вместе образуют имя параметра оптимизации. См. Параметры, контролирующие оптимизацию.‘#pragma GCC optimize’ может быть использован для установки параметров оптимизации для более чем одной функции. См. Специальные параметры оптимизации для функций для подробностей о псевдокоманде.
Предоставление нескольких строк в качестве аргументов, разделённых запятыми, для задания нескольких параметров, эквивалентно разделению суффиксов параметров запятой (‘,’) в одной строке. Пробелы внутри строк запрещены.
Не каждый параметр оптимизации, начинающийся с префикса -f и указанный в атрибуте, обязательно повлияет на функцию. Атрибут
optimizeследует использовать только для отладки. Он не подходит для кода в производственной среде. -
patchable_function_entry -
В случае, если текстовый сегмент целевого объекта можно сделать записываемым во время выполнения любым способом, заполнение входа функции несколькими командами NOP может быть использовано для предоставления универсального инструмента для инструментирования.
Атрибут функции
patchable_function_entryможет быть использован для изменения количества NOP на любое желаемое значение. Двухзначный синтаксис аналогичен переключателю командной строки -fpatchable-function-entry=N,M, генерирующему N команд NOP, при этом точка входа функции находится перед M-ой командой NOP. M по умолчанию равен 0, если опущен, например, точка входа функции находится перед первой командой NOP.Если глобально включить поддержку патчабельных точек входа функций с помощью опции командной строки -fpatchable-function-entry=N,M, то необходимо отключить инструментирование для всех функций, которые являются частью инструментального фреймворка, с помощью атрибута
patchable_function_entry (0)для предотвращения рекурсии. -
pure -
Вызовы функций, не оказывающие наблюдаемого влияния на состояние программы, кроме как возврата значения, могут быть подвержены оптимизациям, таким как устранение общих подвыражений. Объявление таких функций с атрибутом
pureпозволяет GCC избегать вывода некоторых вызовов при многократных вызовах функции с одинаковыми значениями аргументов.Атрибут
pureзапрещает функции изменять состояние программы, наблюдаемое другими средствами, кроме проверки значения возврата функции. Тем не менее, функции, объявленные с атрибутомpureмогут безопасно считывать любые непеременные объекты и изменять значение объектов таким образом, чтобы это не повлияло на их значение возврата или наблюдаемое состояние программы.Например,
int hash (char *) __attribute__ ((pure));
говорит GCC, что последующие вызовы функции
hashсо строкой, которая уже использовалась, могут быть заменены результатом первого вызова при условии, что состояние программы, которое может наблюдатьhash, в том числе содержимое самого массива, не изменится между вызовами. Несмотря на то, чтоhashпринимает аргумент-указатель без const, он не должен изменять массив, на который он указывает, или любой другой объект, значение которого может зависеть от остальной части программы. Однако вызывающая программа может безопасно изменять содержимое массива между последовательными вызовами функции (так как это отключает оптимизацию). Ограничение также относится к объектам-членам, на которые указывает указательthisв нестатических функциях-членах C++.Некоторые общие примеры чистых функций —
strlenилиmemcmp. Интересные нечистые функции — функции с бесконечными циклами или функции, зависящие от переменной памяти или других системных ресурсов, которые могут измениться между последовательными вызовами (например, стандартная Cfeofфункция в среде многопоточности).Атрибут
pureнакладывает аналогичные, но менее строгие ограничения на определение функции, чем атрибутconst:pureпозволяет функции считывать любые непеременные данные памяти, даже если они изменяются между последовательными вызовами функции. Объявление одной и той же функции с обоих атрибутамиpureиconstдаёт диагностическое сообщение. Поскольку чистая функция не может иметь побочных эффектов, не имеет смысла, чтобы такая функция возвращалаvoid. Объявление такой функции даёт диагностическое сообщение. -
retain -
Для целевых объектов ELF, которые поддерживают GNU или FreeBSD OSABI, этот атрибут спасёт функцию от удаления сборщиком мусора линковщика. Для поддержки этого поведения функции, которые не были помещены в определённые разделы (например, атрибутом
sectionили опцией-ffunction-sections), будут помещены в новые уникальные разделы.Для этой дополнительной функциональности требуется версия Binutils 2.36 или более поздняя.
-
returns_nonnull -
Атрибут
returns_nonnullуказывает, что значение возврата функции должно быть указателем, не равным нулю. Например, объявление:extern void * mymalloc (size_t len) __attribute__((returns_nonnull));
позволяет компилятору оптимизировать вызывающие программы, зная, что возвращаемое значение никогда не будет нулевым.
-
returns_twice -
Атрибут
returns_twiceсообщает компилятору, что функция может возвращать значение более одного раза. Компилятор гарантирует, что все регистры освобождены перед вызовом такой функции, и выводит предупреждение о переменных, которые могут быть изменены после второго возврата из функции. Примерами таких функций являютсяsetjmpиvfork. Аналогичная функция, если она есть, может потребовать маркировки атрибутомnoreturn. -
section ("section-name") -
Обычно компилятор помещает сгенерированный код в раздел
text. Иногда, однако, вам требуются дополнительные разделы, или вам нужны определённые функции, чтобы появляться в специальных разделах. Атрибутsectionуказывает, что функция находится в определённом разделе. Например, объявление:extern void foobar (void) __attribute__ ((section ("bar")));помещает функцию
foobarв разделbar.Некоторые форматы файлов не поддерживают произвольные разделы, поэтому атрибут
sectionнедоступен на всех платформах. Если вам нужно отобразить всё содержимое модуля в определённый раздел, воспользуйтесь возможностями линковщика. -
sentinel sentinel (position)-
Этот атрибут функции указывает, что аргумент в вызове функции ожидается как явный
NULL. Этот атрибут допустим только для функций с переменным числом аргументов. По умолчанию сигнальный элемент ожидается в качестве последнего аргумента вызова функции. Если необязательный аргумент position указан в атрибуте, сигнальный элемент должен находиться в позиции position при подсчёте с конца списка аргументов.__attribute__ ((sentinel)) is equivalent to __attribute__ ((sentinel(0)))
Атрибут автоматически устанавливается с позицией 0 для встроенных функций
execlиexeclp. У встроенной функцииexecleатрибут установлен с позицией 1.Действительный
NULLв этом контексте определяется как ноль с любым типом указателя объекта. Если ваша система определяет макросNULLс типом целого числа, вам необходимо добавить явное приведение типов. Во время установки GCC заменяет системный заголовок<stddef.h>копией, которая корректно переопределяет NULL.Предупреждения о пропущенных или неправильных сигнальных элементах включаются с помощью -Wformat.
-
simd simd("mask")
-
Этот атрибут позволяет создать одну или несколько версий функции, которые могут обрабатывать несколько аргументов с использованием инструкций SIMD из одного вызова. Указание этого атрибута позволяет компилятору предположить, что такие версии доступны во время линковки (предоставлены в том же или другом модуле трансляции). Сгенерированные версии зависят от целевой платформы и описаны в соответствующем документе Vector ABI. Для целевой платформы x86_64 этот документ можно найти здесь.
Необязательный аргумент mask может иметь значение
notinbranchилиinbranch, и соответственно инструктирует компилятор генерировать не-маскированные или маскированные клоны. По умолчанию генерируются все клоны.Если атрибут указан и
#pragma omp declare simdприсутствует в объявлении, а также задан ключ -fopenmp или -fopenmp-simd, то атрибут игнорируется. -
stack_protect -
Этот атрибут добавляет код защиты стека к функции, если установлены флаги -fstack-protector, -fstack-protector-strong или -fstack-protector-explicit.
-
symver ("name2@nodename") -
На целевых платформах ELF этот атрибут создает версию символа. Часть name2 параметра — это фактическое имя символа, по которому к нему будет осуществляться внешний доступ. Часть
nodenameдолжна быть именем узла, указанного в скрипте версии, предоставляемом линковщику при построении разделяемой библиотеки. Версионированный символ должен быть определен и должен быть экспортирован со стандартной видимостью.__attribute__ ((__symver__ ("foo@VERS_1"))) int foo_v1 (void) { }Это приведет к направлению
.symver foo_v1, foo@VERS_1в выходных данных ассемблера.Можно также определить несколько версий для данного символа (начиная с binutils 2.35).
__attribute__ ((__symver__ ("foo@VERS_2"), __symver__ ("foo@VERS_3"))) int symver_foo_v1 (void) { }Этот пример создает имя символа
symver_foo_v1, который будет иметь версиюVERS_2иVERS_3символаfoo.Если у вас более старая версия binutils, то необходимо использовать псевдоним символа:
__attribute__ ((__symver__ ("foo@VERS_2"))) int foo_v1 (void) { return 0; } __attribute__ ((__symver__ ("foo@VERS_3"))) __attribute__ ((alias ("foo_v1"))) int symver_foo_v1 (void);Наконец, если параметр равен
"name2@@nodename", то помимо создания версии символа (как если бы использовалось"name2@nodename") версия также будет использоваться для разрешения name2 линковщиком. -
tainted_args -
Атрибут
tainted_argsиспользуется для указания того, что функция вызывается таким образом, что требует санизации её аргументов, например, системный вызов в ядре операционной системы. Такая функция может считаться частью «поверхности атаки» программы. Атрибут может использоваться как в объявлениях функций, так и в объявлениях полей, содержащих указатели на функции. В последнем случае любая функция, используемая в качестве инициализатора такого вызываемого поля, будет рассматриваться как вызываемая с заражёнными аргументами.При использовании -fanalyzer анализатор будет уделять особое внимание таким функциям, потенциально выдавая предупреждения, защищённые -Wanalyzer-tainted-allocation-size, -Wanalyzer-tainted-array-index, -Wanalyzer-tainted-divisor, -Wanalyzer-tainted-offset и -Wanalyzer-tainted-size.
-
target (string, …) -
Несколько целевых back-end реализуют атрибут
targetдля указания того, что функция должна быть скомпилирована с различными параметрами целевой платформы, отличными от указанных в командной строке. Исходные параметры целевой платформы из командной строки игнорируются. В качестве аргументов могут быть предоставлены одна или несколько строк. Каждая строка состоит из одного или нескольких разделённых запятыми суффиксов к префиксу-m, вместе образующих имя машинозависимого параметра. См. Параметры машинозависимого моделирования.Атрибут
targetможет использоваться, например, для компиляции функции с другим ISA (инструкционной архитектурой), отличным от стандартного. '#pragma GCC target' может использоваться для задания параметров, специфичных для целевой платформы, для более чем одной функции. Подробности см. в Параметры, специфичные для функции, псевдодирективы.Например, на x86 вы можете объявить одну функцию с атрибутом
target("sse4.1,arch=core2")и другую сtarget("sse4a,arch=amdfam10"). Это эквивалентно компиляции первой функции с параметрами -msse4.1 и -march=core2, а второй — с -msse4a и -march=amdfam10. Вы должны убедиться, что функция вызывается только на машине, поддерживающей конкретный ISA, для которого она скомпилирована (например, с помощьюcpuidна x86, чтобы определить используемые биты функций и семейство архитектуры).int core2_func (void) __attribute__ ((__target__ ("arch=core2"))); int sse3_func (void) __attribute__ ((__target__ ("sse3")));Предоставление нескольких строк в качестве аргументов, разделённых запятыми, для указания нескольких параметров эквивалентно разделению суффиксов параметров запятой (‘,’) в одной строке. Пробелы внутри строк не допускаются.
Поддерживаемые параметры специфичны для каждой целевой платформы; см. Атрибуты функций x86, Атрибуты функций PowerPC, Атрибуты функций ARM, Атрибуты функций AArch64, Атрибуты функций Nios II и Атрибуты функций S/390 для получения подробностей.
-
target_clones (options) -
Атрибут
target_clonesиспользуется для указания того, что функция должна быть клонирована в несколько версий, скомпилированных с различными параметрами целевой платформы, отличными от указанных в командной строке. Поддерживаемые параметры и ограничения такие же, как и для атрибутаtarget.Например, на x86 вы можете скомпилировать функцию с
target_clones("sse4.1,avx"). GCC создаст два клоны функции, один скомпилированный с -msse4.1, а другой с -mavx.На PowerPC вы можете скомпилировать функцию с
target_clones("cpu=power9,default"). GCC создаст два клоны функции, один скомпилированный с -mcpu=power9, а другой — с параметрами по умолчанию. GCC должен быть сконфигурирован для использования GLIBC 2.23 или более поздней версии для использования атрибутаtarget_clones.Он также создаёт функцию-разрешитель (см. атрибут
ifuncвыше), которая динамически выбирает клон, подходящий для текущей архитектуры. Разрешитель создаётся только при использовании функции с атрибутомtarget_clones.Обратите внимание, что любое последующее обращение к функции без атрибута
target_cloneиз вызывающей функции с атрибутомtarget_cloneне приведёт к копированию (клонированию под целевую платформу) вызываемой функции. Если вы хотите принудительно обеспечить такое поведение, рекомендуется объявить вызывающую функцию с атрибутомflatten? -
unavailable unavailable (msg)-
Атрибут
unavailableприводит к ошибке, если функция используется где-либо в исходном файле. Это полезно при идентификации функций, которые были удалены из конкретного варианта интерфейса. Помимо выдачи ошибки вместо предупреждения, атрибутunavailableработает так же, как и атрибутdeprecated.Атрибут
unavailableтакже может использоваться для переменных и типов (см. Указание атрибутов переменных, см. Указание атрибутов типов.) -
unused -
Этот атрибут, прикреплённый к функции, означает, что функция потенциально не используется. GCC не выводит предупреждение для этой функции.
-
used -
Этот атрибут, прикреплённый к функции, означает, что код должен быть сгенерирован для функции, даже если кажется, что на неё нет ссылок. Это полезно, например, когда функция упоминается только в inline ассемблере.
При применении к члену-функции шаблона класса C++, атрибут также означает, что функция будет инстанцирована, если сам класс инстанцирован.
-
visibility ("visibility_type")
-
Этот атрибут влияет на связь объявления, к которому он прикреплён. Он может применяться к переменным (см. Общие атрибуты переменных) и типам (см. Общие атрибуты типов), а также к функциям.
Поддерживаются четыре значения visibility_type: default, hidden, protected или internal.
void __attribute__ ((visibility ("protected"))) f () { /* Do something. */; } int i __attribute__ ((visibility ("hidden")));Возможные значения visibility_type соответствуют настройкам видимости в ELF gABI.
default-
По умолчанию видимость — это нормальный случай для формата файла объекта. Это значение доступно для атрибута видимости, чтобы переопределить другие параметры, которые могут изменить предполагаемую видимость сущностей.
В ELF, видимость по умолчанию означает, что объявление видно другим модулям и, в разделяемых библиотеках, означает, что объявленная сущность может быть переопределена.
В Darwin, видимость по умолчанию означает, что объявление видно другим модулям.
Видимость по умолчанию соответствует «внешней связи» в языке.
hidden-
Видимость hidden указывает, что объявленная сущность имеет новый тип связи, который мы называем «скрытой связью». Два объявления объекта со скрытой связью относятся к одному объекту, если они находятся в одной и той же разделяемой библиотеке.
internal-
Видимость internal похожа на видимость hidden, но с дополнительными особенностями, специфичными для процессора. Если не указано иначе psABI, GCC определяет внутреннюю видимость так, что функция никогда не вызывается из другого модуля. Сравните это со скрытыми функциями, которые, хотя и не могут быть напрямую проинициализированы другими модулями, могут быть проинициализированы косвенно через указатели на функции. Указывая, что функция не может быть вызвана извне модуля, GCC, например, может опустить загрузку регистра PIC, поскольку известно, что вызывающая функция загрузила правильное значение.
protected-
Видимость protected похожа на видимость по умолчанию, за исключением того, что она указывает на то, что ссылки внутри определяющего модуля привязываются к определению в этом модуле. То есть, объявленная сущность не может быть переопределена другим модулем.
Все виды видимости поддерживаются во многих, но не во всех, ELF-целях (поддерживаются, когда ассемблер поддерживает псевдооператор ‘.visibility’). Видимость по умолчанию поддерживается везде. Скрытая видимость поддерживается в Darwin-целях.
Атрибут видимости должен применяться только к объявлениям, которые в противном случае имели бы внешнюю связь. Атрибут должен применяться последовательно, так что одна и та же сущность не должна объявляться с различными настройками атрибута.
В C++, атрибут видимости применяется к типам, а также к функциям и объектам, потому что в C++ типы имеют связь. Класс не должен иметь большей видимости, чем его нестатические типы данных членов и баз, а члены класса по умолчанию имеют видимость своего класса. Также объявление без явной видимости ограничено видимостью его типа.
В C++, вы можете помечать методы-члены и статические переменные-члены класса атрибутом видимости. Это полезно, если вы знаете, что определённый метод или статическая переменная-член должны использоваться только из одного разделяемого объекта; тогда вы можете пометить его как скрытый, в то время как остальная часть класса имеет видимость по умолчанию. Следует соблюдать осторожность, чтобы не нарушить правило «одно определение»; например, обычно нецелесообразно помечать встроенный метод как скрытый, не помечая весь класс как скрытый.
Объявление пространства имён C++ также может иметь атрибут видимости.
namespace nspace1 __attribute__ ((visibility ("protected"))) { /* Do something. */; }Этот атрибут применяется только к конкретному телу пространства имён, а не к другим определениям того же пространства имён; он эквивалентен использованию ‘#pragma GCC visibility’ до и после определения пространства имён (см. Атрибуты видимости).
В C++, если аргумент шаблона имеет ограниченную видимость, это ограничение неявно распространяется на экземпляр шаблона. В противном случае экземпляры и специализации шаблонов по умолчанию имеют видимость своего шаблона.
Если и шаблон, и содержащий класс имеют явную видимость, используется видимость из шаблона.
-
warn_unused_result -
Атрибут
warn_unused_resultвызывает предупреждение, если вызывающая функция с этим атрибутом не использует возвращаемое значение. Это полезно для функций, где игнорирование результата является либо проблемой безопасности, либо всегда ошибкой, например,realloc.int fn () __attribute__ ((warn_unused_result)); int foo () { if (fn () < 0) return -1; fn (); return 0; }приводит к предупреждению на строке 5.
-
weak -
Атрибут
weakвызывает объявление внешнего символа как слабого символа, а не глобального. Это в первую очередь полезно для определения функций библиотеки, которые могут быть переопределены в пользовательском коде, хотя может быть использовано и с объявлениями, не являющимися функциями. Переопределяющий символ должен иметь тот же тип, что и слабый символ. Кроме того, если это переменная, она должна иметь также тот же размер и выравнивание, что и слабый символ. Слабые символы поддерживаются для ELF-целей, а также для целей a.out при использовании GNU ассемблера и компоновщика. -
weakref weakref ("target")-
Атрибут
weakrefпомечает объявление как слабое ссылочное значение. Без аргументов он должен сопровождаться атрибутомalias, который указывает целевой символ. В качестве альтернативы, target может быть задан как аргумент дляweakref, указывая целевое определение псевдонима. target должен иметь тот же тип, что и объявление. Кроме того, если это переменная, она должна иметь также тот же размер и выравнивание, что и объявление. В любом из этих форм объявленияweakrefнеявно помечает объявленный символ какweak. Без target, заданного аргументом кweakrefилиalias,weakrefэквивалентноweak(в этом случае объявление может бытьextern)./* Given the declaration: */ extern int y (void); /* the following... */ static int x (void) __attribute__ ((weakref ("y"))); /* is equivalent to... */ static int x (void) __attribute__ ((weakref, alias ("y"))); /* or, alternatively, to... */ static int x (void) __attribute__ ((weakref)); static int x (void) __attribute__ ((alias ("y")));Слабая ссылка — это псевдоним, для которого сам по себе не требуется определение целевого символа. Если целевой символ ссылается только через слабые ссылки, то он становится
weakнеопределённым символом. Однако, если на него есть прямые ссылки, такие сильные ссылки имеют приоритет, и для символа требуется определение, необязательно в том же файле перевода.Эффект эквивалентен перемещению всех ссылок на псевдоним в отдельный файл перевода, переименованию псевдонима в целевой символ, объявлению его как слабого, компиляции двух отдельных файлов перевода и выполнению компоновки с релоцируемым выходом (т.е.
ld -r) на них.Объявление, к которому прикреплён
weakrefи которое связано с именованнымtargetдолжно бытьstatic. -
zero_call_used_regs ("choice")
-
Атрибут
zero_call_used_regsзаставляет компилятор обнулять подмножество всех регистров, используемых вызовом функции7, при возвращении из функции. Это используется для повышения безопасности программы путём смягчения атак Return-Oriented Programming (ROP) или предотвращения утечки информации через регистры.Чтобы удовлетворить пользователей с различными потребностями в безопасности и в то же время контролировать накладные расходы во время выполнения, параметр choice предоставляет гибкий способ выбора подмножества регистров, используемых вызовом функции, для обнуления. Четыре основных значения choice:
- ‘skip’ — не обнуляет регистры, используемые вызовом функции.
- ‘used’ — обнуляет только те регистры, используемые вызовом функции, которые были использованы в функции. Регистр «используется», если его содержимое было установлено или обработано в функции.
- ‘all’ — обнуляет все регистры, используемые вызовом функции.
- ‘leafy’ — ведет себя как ‘used’ в листовой функции и как ‘all’ в нелистовой функции. Это обеспечивает более экономное обнуление в листовых функциях, где множество используемых регистров известно, что может быть достаточно для некоторых целей обнуления регистров.
В дополнение к этим трём основным вариантам, можно модифицировать ‘used’, ‘all’ и ‘leafy’ следующим образом:
- Добавление ‘-gpr’ ограничивает обнуление универсальными регистрами.
- Добавление ‘-arg’ ограничивает обнуление регистрам, которые могут использоваться для передачи аргументов функций. Это включает все регистры аргументов, определённые правилами вызова платформы, независимо от того, использует ли функция эти регистры для аргументов или нет.
Модификаторы могут использоваться по отдельности или вместе. Если они используются вместе, они должны быть указаны в вышеупомянутом порядке.
Полный список choice:
skip-
не обнуляет ни одного регистра, используемого вызовом функции.
used-
обнуляет только регистры, используемые вызовом функции, которые были использованы в функции.
used-gpr-
обнуляет только универсальные регистры, используемые вызовом функции, которые были использованы в функции.
used-arg-
обнуляет только регистры, используемые вызовом функции, которые были использованы в функции и для передачи аргументов.
used-gpr-arg-
обнуляет только универсальные регистры, используемые вызовом функции, которые были использованы в функции и для передачи аргументов.
all-
обнуляет все регистры, используемые вызовом функции.
all-gpr-
обнуляет все универсальные регистры, используемые вызовом функции.
all-arg-
обнуляет все регистры, используемые вызовом функции, которые передают аргументы.
all-gpr-arg-
обнуляет все универсальные регистры, используемые вызовом функции, которые передают аргументы.
leafy-
То же, что и ‘used’ в листовой функции и то же, что и ‘all’ в нелистовой функции.
leafy-gpr-
То же, что и ‘used-gpr’ в листовой функции и то же, что и ‘all-gpr’ в нелистовой функции.
leafy-arg-
То же, что и ‘used-arg’ в листовой функции и то же, что и ‘all-arg’ в нелистовой функции.
leafy-gpr-arg-
То же, что и ‘used-gpr-arg’ в листовой функции и то же, что и ‘all-gpr-arg’ в нелистовой функции.
Из этого списка ‘used-arg’, ‘used-gpr-arg’, ‘all-arg’, ‘all-gpr-arg’, ‘leafy-arg’ и ‘leafy-gpr-arg’ в основном используются для смягчения атак ROP.
Значение по умолчанию для атрибута контролируется -fzero-call-used-regs.
Примечания
(7)
Регистр «используемый вызовом» — это регистр, содержимое которого может быть изменено вызовом функции; поэтому вызывающая сторона не может предполагать, что регистр будет содержать то же самое содержимое при возвращении из функции, что и до вызова функции. Такие регистры также называются «изменяемые вызовом», «сохраненные вызывающей стороной» или «изменяемые».
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Function-Attributes.html