16.2.1 Function Attributes

The compiler keyword __attribute__ allows you to specify special attributes of functions. This keyword is followed by an attribute specification inside double parentheses.

You may also specify attributes with __ (double underscore) preceding and following each keyword (e.g., __noreturn__ instead of noreturn). This allows you to use them in header files without being concerned about a possible macro of the same name.

To specify multiple attributes, separate them by commas within the double parentheses, for example:
__attribute__ ((address(0x100), keep))

The attribute specifier can be placed either before or after the function's return type.

Note: It is important to use function attributes consistently throughout a project. For example, if a function is defined in file A with the an attribute, and declared extern in file B without the same attribute, then a link error might result.

address(addr)

The address attribute specifies an absolute physical address at which the attributed routine will be placed in memory. It can be used with C and C++ functions.

The compiler performs no error checking on the address value, so the application must ensure the value is valid for the target device. The section containing the function will be located at the specified address regardless of the memory-regions specified in the linker script or the actual memory ranges on the target device. The application code must ensure that the address is valid for the target device.

To make effective use of absolute sections and the new best-fit allocator, standard program-memory and data-memory sections should not be mapped in the linker script. The built-in linker script does not map most standard sections, such as the .text, .data, .bss or .ramfunc sections. By not mapping these sections in the linker script, we allow these sections to be allocated using the best-fit allocator rather than the sequential allocator. Sections that are unmapped in the linker script can flow around absolute sections, whereas sections that are linker-script mapped are grouped together and allocated sequentially, potentially causing conflicts with absolute sections.

alias ("symbol")

Indicates that the function is an alias for another symbol. For example:
 void foo (void) { /* stuff */ }
 __attribute__ ((alias("foo"))) void bar (void);

In the above example, the symbol bar is considered to be an alias for the symbol foo.

always_inline

Instructs the compiler to always inline a function declared as inline, even if no optimization level was specified.

const

If the result of a pure function is determined exclusively from its parameters (i.e., does not depend on the values of any global variables), it may be declared with the const attribute, allowing for even more aggressive optimization. Note that a function which de-references a pointer argument cannot be declared const if it depends on the referenced value, as the referenced storage is not considered a parameter of the function.

deprecated


deprecated (msg)

When a function specified as deprecated is used, the compiler will generate a warning. The optional msg argument, which must be a string, will be printed in the warning if present. The deprecated attribute may also be used for variables and types.

externally_visible

This attribute when used with a function ensures the function remains visible outside the current compilation unit. This might prevent certain optimizations from being performed on the function.

format (type, format_index, first_to_check)

The format attribute indicates that the function takes a printf, scanf, strftime, or strfmon style format string at position index in the argument list, and instructs the compiler to type-check the arguments starting at first_to_check against the conversion specifiers in the format string, just as it does for the standard library functions.

The type parameter is one of printf, scanf, strftime or strfmon (optionally with surrounding double underscores, e.g., __printf__) and determines how the format string will be interpreted.

The format_index parameter specifies the position of the format string in the function's parameters. Function parameters are numbered from the left, starting from index 1.

The first_to_check parameter specifies the position of the first parameter to check against the format string. All parameters following the parameter indicated by first_to_check will be checked. If first_to_check is zero, type checking is not performed, and the compiler only checks the format string for consistency.

format_arg(index)

The format_arg attribute specifies that a function manipulates a printf style format string and that the compiler should check the format string for consistency. The index parameter gives the position of the format string in the parameter list of the function, numbered from the left beginning at index 1.

interrupt


interrupt(type)

Functionally equivalent to the isr attribute.

isr

isr(type)

Instructs the compiler to generate prologue and epilogue code for the function as an interrupt handler function, as described in 17 Interrupts. For Cortex-A devices, the type argument specifies the type of the interrupt, which may be one of the identifiers irq, fiq, abort, undef or swi, in lowercase or uppercase. Any argument specifed is ignore when building for Cortex-M devices.

keep

The keep attribute prevents the linker from removing an unused function when --gc-sections is in effect.

long_call

Always call the function with an indirect call instruction.

malloc

The malloc attribute asserts that any non-null pointer return value from the function will not be aliased to any other pointer which is live at the point of return from the function. This allows the compiler to perform more aggressive optimizations.

naked

Indicates that the compiler should generate no prologue or epilogue code for the function.

noinline

A function declared with the noinline attribute will never be considered for inlining, regardless of optimization level.

nonnull(index, ...)

Indicate to the compiler that one or more pointer arguments to the function must be non-null. When the -Wnonnull option is in effect, the compiler will issue a warning diagnostic if it can determine that the function is called with a null pointer supplied for any nonnull argument. The index argument(s) indicate the position of the pointer arguments required to be non-null in the parameter list of the function, numbered from the left starting at index 1. If no arguments are provided, all pointer arguments of the function will be marked as non-null.

nopa

Indicate to the compiler that the assembly code generated for this function should not be considered when performing procedural abstraction.

noreturn

Indicate to the compiler that the function will never return control to its caller. In some situations, this can allow the compiler to generate more efficient code in the calling function, since optimizations can be performed without regard to behavior if the function ever did return. Functions declared with noreturn should always have a void return type.

optimize(optimization)

The optimize attribute allows a function to be built with optimizations that differ to what has been specified on the command line and which will be applied to the rest of the program. The optimization argument can either be a number or a string. String arguments represent the command-line option used to control an optimization, so for example, to enable peephole optimizations (-fpeephole), use optimize("peephole"). The -f option prefix does not need to be specified with the argument. If you want to specify more than one optimization, separate the arguments with commas but with no space characters. Arguments that begin with O are assumed to be an optimization level option, for example optimize("O1,unroll-loops") turns on level 1 optimizations and the unroll-loops optimizations (controlled by the -funroll-loops command-line option). A numerical argument is also assumed to be an optimization level, for example optimize(3) turns on level 3 optimizations and is equivalent to the full usage of the attribute in the following example.
int __attribute__((optimize("O3"))) pandora (void) {
  if (maya > axton)
    return 1;
  return 0;
}
This feature can be used, for instance, to have frequently executed functions compiled with more aggressive optimization options that produce faster and larger code, while other functions can be called with less aggressive options. Typically, however, it is not used for production builds.

pure

Indicates to the compiler that the function is pure, allowing for more aggressive optimizations in the presence of calls to the function. A pure function has no side effects other than its return value, and the return value is dependent only on parameters and/or (non-volatile) global variables.

ramfunc

The ramfunc attribute locates the attributed routine in RAM rather than in Flash memory on devices that normally execute code from Flash. This attribute can be used for both C functions and C++ class methods. The compiler's default runtime startup code uses the data-initialization template to copy the code associated with functions using this attribute from Flash to RAM at program startup.

For example, the following defines a C function placed in data memory:
__attribute__((ramfunc))
unsigned int myramfunct(void)
{ /* code */ }
The <sys/attribs.h> header file provides a __ramfunc__ macro that is useful for this purpose. For example:
#include <sys/attribs.h>
__ramfunc__ unsigned int myramfunct(void)
{ /* code */ }
In C++ code, it can be used with class methods, as shown in the following example.
class printmyname {
    // Access specifier
public:
    // Data  Members
    string myname;
    int  dummy ;
    // Member Functions()
    printmyname (){
        myname = "microchip";
    }
    
    void  __attribute__((ramfunc, long_call)) set_name(string newname){
        myname = newname;
        dummy = 9;
    }
    void printname() { cout << "name is:" << myname; }
};
The branch/call instruction BL has a limited range (32MB for ARM instructions, 16MB for Thumb2 and 4MB for Thumb). As a result, RAM might not be within range of calls made from code in Flash. To allow such calls, additionally use the long_call attribute with the definition of the function located in RAM when it must be called from functions in Flash. For example:
__attribute__((ramfunc, long_call))
unsigned int myramfunct(void)
{ /* code */ }
The <sys/attribs.h> header file provides a __longramfunc__ macro that will specify both the ramfunc and long_call attributes. For example:
#include <sys/attribs.h>
__longramfunc__ unsigned int myramfunct(void)
{ /* code */ }
If a function in Flash is called by a function located in RAM, the Flash-based function definition must include the long_call attribute.
__attribute__ ((long_call))
unsigned int myflashfunct(void)
{ /* code */ }

__attribute__((ramfunc))
unsigned int myramfunct(void)
{
        return myflashfunct();
}

Having functions located in RAM rather than Flash can increase code size as well as startup time, as the attributed functions must be copied from Flash to RAM at startup. It may also have an impact on runtime performance, depending on your target device. Verify that your application meets your startup timing constraints. Also verify that the increased runtime performance meets your application's timing requirements and that your application does not have hidden dependencies on timing that is negatively impacted by this design selection.

section("name")

Place the function into the given named section. For example:

void __attribute__ ((section (".wilma"))) baz () {return;}

In the above example, function baz will be placed in section .wilma. The -ffunction-sections command line option has no effect on functions declared with the section attribute.

short_call

Always call the function using an absolute call instruction, even when the -mlong-calls command line option is specified.

space(id)

Place the function in the memory space identified by the id argument. The id argument may be prog, which places the function in the program space (i.e., ROM), or data, which places the function in a data section (i.e., RAM). Unlike the section attribute, the actual section is not explicitly specified.

stack_protect

This attribute adds stack protection code to the function if one of the following options is set: -fstack-protector, -fstack-protector-strong, or -fstack-protector-explicit.

Optimizations can affect stack protection:

  • Function inlining can affect whether a function is protected.
  • Removal of an unused variable can prevent a function from being protected.

tcm

Attempt to place the function in tightly-coupled memory (TCM), providing highly consistent access times. The actual section will be determined by the compiler, possibly based on other attributes such as space. For example:

void __attribute__((tcm)) foo (void) {return;}

In the above example, the compiler will attempt to place foo in the itcm memory section, or the tcm section on those processors where the code and data memory spaces are combined. Note that the amount of TCM available in program or data memory on the target device may vary, so the compiler cannot ensure all functions with the tcm attribute can be placed in TCM.

Also see 7.5 Tightly-Coupled Memories.

unique_section

Place the function in a uniquely named section, as if -ffunction-sections were in effect. If the function also has a section attribute, the given section name will be used as a prefix for the generated unique section name. For example:

void __attribute__ ((section (".fred"), unique_section) foo (void) {return;}

In the above example, function foo will be placed in section .fred.foo.

unsupported

Indicate to the compiler that the function is not supported, similar to the deprecated attribute. A warning will be issued if the function is called.

unused

Indicate to the compiler that the function may not be used. The compiler will not issue a warning for this function if it is not used.

used

Indicate to the compiler that the function is always used and code must be generated for the function even if the compiler cannot determine that the function is called, e.g., if a status function is only called from an inline assembly statement.

warn_unused_result

A warning will be issued if the return value of the indicated function is unused by a caller.

weak

A weak symbol indicates that if another version of the same symbol is available, that version should be used instead. For example, this is useful when a library function is implemented such that it can be overridden by a user written function.