15.2.1 Function Attributes

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

The access attribute provides additional information about how a function accesses memory. It can assist in diagnosing potential bugs related to memory access via compiler warnings and help the compiler perform better optimizations.

The ref_index argument is the index (starting from the left with index 1) of the function pointer argument that points to the target object being accessed. A function pointer argument can be referenced by at most one distinct access attribute.

The access_mode argument specifies the type of memory access made by the pointer referenced by the ref_index and can be one of:
read_only
The pointer only reads from the target object. Unless the indexed size argument is zero, the target object must be initialized. This check is more robust than just using the const qualifier with the target as it cannot be cast away.
write_only
The pointer (which cannot be to a const-qualified type) only writes to the target object. The object referenced by the pointer need not be initialized.
read_write
The pointer (which cannot be to a const-qualified type) both reads from and writes to the target object. Unless the indexed size argument is zero, the target object must be initialized.
none
The pointer does not access the target object at all. Unless the pointer is NULL, the target object must exist and have at least the size held by the size-index argument. If the size-index argument is omitted for a pointer of void * type, the actual pointer argument is ignored. The referenced object need not be initialized. The mode is intended to be used as a means to help validate the expected object size, for example in functions that call __builtin_object_size.

The optional size_index argument is the index of the function argument that specifies the number of elements of the pointer type referenced by ref-index, or the number of bytes when the pointer type is void *. When this argument is not specified, the pointer argument must be either NULL or point to a space that is suitably aligned and sized for at least one object of the referenced type (this implies that a past-the-end pointer is not a valid argument). The actual size of the access may be less but it must not be more.

For example, the following code uses the access attribute to declare that the pointer argument to puts() will only read its target of unspecified size. The attribute is used again to indicate that the second argument to memcpy() only reads its target and that this target has a size indicated by the value of the third function argument.
__attribute__ ((access (read_only, 1))) int puts(const char *);

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

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 address attribute specifies an absolute virtual address for the function. Be sure to specify the address attribute using an appropriate virtual address for the target device. The address is typically in the range [0x9D000000,0x9D0FFFFC], as defined in the linker script as the kseg0_program_mem memory region. For example:
__attribute__((address(0x9D008000))) void bar (void);

The compiler performs no error checking on the address. 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.

Sections used to hold functions placed at an absolute address will use a name .address.N.decl, where N is the address and decl is the name of the declaration.

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);

Symbol bar is considered to be an alias for the symbol foo.

always_inline

If the function is declared inline, always inline the function, even if no optimization level was specified, for example:
void __attribute__ ((always_inline))  foo (void);

at_vector

Place the body of the function at the indicated exception vector address, for example:
void __attribute__ ((interrupt(IPL4SOFT))) __attribute__ ((at_vector(54)))
foo void);

See also Interrupts and Exception Handlers.

const

If a pure function determines its return value exclusively from its parameters (that is, does not examine any global variables), it may be declared const, allowing for even more aggressive optimization. Note that a function which de-references a pointer argument is not const since the pointer de-reference uses a value which is not a parameter, even though the pointer itself is a parameter. For example:
int __attribute((const)) rv(int a);

deprecated

deprecated (msg)

When a function specified as deprecated is used, a warning is generated. The optional msg argument, which must be a string, will be printed in the warning if present, for example:
void __attribute__ ((deprecated ("The bar function is no longer used"))) bar (void);
The deprecated attribute may also be used for variables and types.

externally_visible

This attribute when used with a function, nullifies the effect of the -fwhole-program command-line option, so the function remains visible outside the current compilation unit, for example:
void __attribute__((externally_visible)) foo (void);
This might prevent certain optimizations from being performed on the function.

far

Always invoke the function by first loading its address into a register and then using the contents of that register. This allows calling a function located beyond the 28-bit addressing range of the direct CALL instruction. For example:
void __attribute__((far)) foo (void);

format (type, format_index, first_to_check)

The format attribute indicates that the function takes a printf, scanf, strftime, or strfmon style format string and arguments and that the compiler should type check those arguments against the format string, just as it does for the standard library functions, for example:
extern int __attribute__ ((format (printf, 2, 3))) my_printf (void *my_object, const char *my_format, ...);

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

The format_index parameter specifies which function parameter is the format string. Function parameters are numbered from the left-most parameter, starting from 1.

The first_to_check parameter specifies which parameter is the first to check against the format string. If first_to_check is zero, type checking is not performed and the compiler only checks the format string for consistency (for example, vfprintf).

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 function attribute which is a format string is identified by index. For example:
extern char * __attribute__ ((format_arg (2))) my_foo (char *my_str, const char *my_format);

function_replacement_prologue

This feature allows the application to redirect one function to another implementation at runtime without replacing the existing function. This is achieved by changing the method of invoking functions through a function replacement table instead of from a linker-resolved address. Initially the function address in the table points to the location of the entry point of the original function's prologue. The application can then replace the table entry with the new function address. Now, during the program execution, the control will pass to the new function address and returns to the caller function. This feature adds a new function_replacement_prologue function attribute. To redirect the function, modify the corresponding Function Replacement Table entry at runtime.

Example C code:

int a, b, c, d;
int __attribute__((function_replacement_prologue)) foo (void)
{
   a = b + c;
   return (a);
}
int main()
{
   d = foo();
   return 0;
}

Example generated assembly code:

# Function Replacement Table entries, located in data memory
   .section .fixtable, data
fixtable.foo:
   .word     cont.foo         # By default, populate the table with the address
                              # of the original implementation. Redirect to
                              # another implementation by overwriting this
                              # location with the address of the new implementation.

   .section .text, code
   .globl foo
   .ent foo
   .type foo, @function
foo:
   # Begin Function Replacement Table Prologue
   lui $25,%hi(fixtable.foo)        # Load address from .fixtable above
   lw $25,%lo(fixtable.foo)($25)
   j $25                            # Jump to address loaded from table
   nop
cont.foo:
   # End Function Replacement Table Prologue
   addiu $sp,$sp,-8
   sw $fp,4($sp)
   move $fp,$sp
   lw $3,%gp_rel(b)($28)
   ...........
   j $31
   nop

interrupt (priority)

Generate prologue and epilogue code for the function as an interrupt handler function. See Interrupts . The argument specified the interrupt priority level using the symbols IPLnSOFT, IPLnSRS, or IPLnAUTO where n represents the 7 levels of priority and SOFT|SRS|AUTO specifies the context saving mode.

keep

The __attribute__((keep)) may be applied to a function. The keep attribute will prevent the linker from removing the function with --gc-sections, even if it is unused, for example:
void __attribute__((keep)) foo(void);

longcall

Functionally equivalent to far, for example:
void __attribute__((longcall)) foo (void);

malloc

Any non-Null Pointer return value from the indicated function will not alias any other pointer which is live at the point when the function returns, for example:
void __attribute__ ((malloc)) *custom_malloc (int size_t);  
This allows the compiler to improve optimization.

micromips

Generate code for the function in the compressed microMIPS instruction set, for example:
void __attribute__ ((microcmips)) foo(void);

mips16

Generate code for the function in the MIPS16 instruction set, for example:
void __attribute__ ((mips16)) foo(void);

naked

Generate no prologue or epilogue code for the function. This attribute is intended for functions that exclusively contain extended inline assembly code. Using C code within such an attributed function might not work properly. Since the compiler will not generate prologue or epilogue code for functions using this attribute, the application code within is responsible for managing the stack and additionally handling formal parameters, return values, and the function return. For example:
void __attribute__ ((naked)) foo(void);

near

Always invoke the function with an absolute CALL instruction, even when the -mlong-calls command line option is specified, for example:
void __attribute__ ((near)) foo(void);

no_fpu

The no_fpu attribute must be used in conjunction with the interrupt (priority) attribute and specifies that the interrupt service routine (ISR) should not preserve the Floating-Point Unit (FPU) context. In addition it causes the compiler to insert code into the ISR that will disable the FPU, by clearing the CU1 bit of the CP0 Status register. If your ISR attempts to perform floating-point operations while the FPU is disabled, the device will trigger a general exception. This also means that any higher-priority ISR interrupting an ISR using the no_fpu attribute must re-enable the FPU if floating-point operations are required. The ISR restores the original value of the status register before returning from the interrupt. For example:
void __attribute__((interrupt(IPL7SRS), vector(_CORE_TIMER_VECTOR), no_fpu)) isr(void);

noinline

The function will never be considered for inlining, for example:
void __attribute__ ((noinline)) foo(void);

noload

Causes the variable or function to be placed in a section that has the noload attribute set. It tells consumers of the ELF files not to load the contents of the section. This attribute can be useful when you just want to reserve memory for something, but you don’t want to clear or initialize memory. For example:
void __attribute__ ((noload)) foo(void);

nomips16

Always generate code for the function in the MIPS32® instruction set, even when compiling the translation unit with the -mips16 command line option, for example:
void __attribute__ ((nomips16)) foo(void);

nonnull (index, ...)

Indicate to the compiler that one or more pointer arguments to the function must be non-null. If the compiler determines that a Null Pointer is passed as a value to a non-null argument, and the -Wnonnull command line option was specified, a warning diagnostic is issued.

If no arguments are given to the nonnull attribute, all pointer arguments of the function are marked as non-null. For example:
void * __attribute__((nonnull)) my_memset (void * ptr, int x, size_t len);

noreturn

Indicate to the compiler that the function will never return. 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 as noreturn should always have a return type of void. For example:
void __attribute__ ((noreturn)) myExit(void);

optimize(optimization)

The optimize attribute allows a function to be built with optimizations that differ from 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, 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

If a function has no side effects other than its return value, and the return value is dependent only on parameters and/or (nonvolatile) global variables, the compiler can perform more aggressive optimizations around invocations of that function. Such functions can be indicated with the pure attribute, for example:
void __attribute__ ((pure)) foo(void);

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.

When this attribute is used with C functions, the function is placed at the highest appropriately aligned address for executable code. Note that due to ramfunc alignment and placement requirements, the address attribute should not be used with the ramfunc attribute. The presence of the ramfunc section causes the linker to emit the symbols necessary for the crt0.S start-up code to initialize the bus matrix appropriately for executing code out of data memory.

Use this attribute along with the far/longcall attribute and the section attribute. For example:
  __attribute__((ramfunc,section(".ramfunc"),far,unique_section))
  unsigned int myramfunct (void_
    { /* code */ }
A macro in the <sys/attribs.h> header file makes the ramfunc attribute simple to use:
  #include <sys/attribs.h>
  __longramfunc__ unsigned int  myramfunct (void)
    { /* code */ }
In C++ code, the attribute 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; }
};

section("name")

Place the function into the named section.

For example:

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

Function baz will be placed in section .wilma.

The -ffunction-sections command line option has no effect on functions defined with a section attribute.

unique_section

Place the function in a uniquely named section, as if -ffunction-sections had been specified. If the function also has a section attribute, use that section name as the prefix for generating the unique section name.

For example:

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

Function foo will be placed in section .fred.foo.

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, for example:
void __attribute__ ((unused)) opt_setting(void);

used

Indicate to the compiler that the function is always used and code must be generated for the function even if the compiler cannot see a reference to the function. Such might be the case if inline assembly is the only reference to a static function. For example:
void __attribute__ ((used)) foo(void);

vector (num)

Generate a branch instruction at the indicated exception vector which targets the function. See Interrupts and Exception Handlers. For example:
void __attribute__((vector(0), interrupt(IPL7AUTO))) myisr(void);

warn_unused_result

A warning will be issued if the return value of the indicated function is unused by a caller, for example:
void __attribute__ ((warn_unused_result)) foo(void);

weak

A weak symbol indicates that if another version of the same symbol is available, that version should be used instead. This is useful when a library function is implemented such that it can be overridden by a user written function. For example:
void __attribute__ ((weak)) foo(void);