2.7.2. Function Attributes

The following function attributes are supported by the tiarmclang compiler:

Note

Function Attribute Syntax

A function attribute specification can appear at the beginning or end of a function declaration statement:

<function declaration> __attribute__((*attribute-list*));

or

__attribute__((*attribute-list*)) <function declaration>;

However, when a function attribute is specified with the function definition, if it appears between the function specification and the opening curly brace that indicates the start of the function body, the compiler will emit a warning diagnostic. For example,

// always_inline_function_attr.c
...
void emit_msg(void) __attribute__((always_inline)) {
  printf("this is call #%d\n", ++counter);
}
...
%> tiarmclang -mcpu=cortex-m0 -c always_inline_function_attr.c
always_inline_function_attr.c:8:36: warning: GCC does not allow
'always_inline' attribute in this position on a function
definition [-Wgcc-compat]
void emit_msg(void) __attribute__((always_inline)) {
                                   ^
1 warning generated.

The warning can be disabled using the -Wgcc-compat option or by moving the function attribute specification before the function specification.

2.7.2.1. alias

The alias function attribute can be applied to a function declaration to instruct the compiler to interpret the function symbol being declared as an alias for another function symbol that is defined in the same compilation unit.

Syntax

<return type> source symbol (<arguments>) __attribute__((alias(target symbol)));

  • source symbol - is the subject of the function declaration that will become an alias of the target symbol.

  • target symbol - is a function symbol defined in the same compilation unit as the declaration of source symbol, to which references to source symbol will resolve to.

Example

In the following C code, both a weak and an alias attribute are applied to the declaration of event_handler so that calls to event_handler will be resolved by default_handler unless a strong definition of event_handler overrides the weak definition at link-time:

// alias_func_attr.c
#include <stdio.h>

void default_handler() {
  printf("This is the default handler\n");
}

void event_handler(void) __attribute__((weak, alias("default_handler")));

int main() {
  event_handler();
  return 0;
}

If the above code is compiled and linked and run, the output reveals that the reference to event_handler resolves to a call to default_handler:

%> tiarmclang -mcpu=cortex-m0 alias_func_attr.c -o a.out -Wl,-llnk.cmd,-ma.map
%> load470 -q a.out
This is the default handler

If we add a strong definition of event_handler to the build, then the reference to event_handler will be resolved by the strong function definition of event_handler:

#include <stdio.h>

void event_handler() {
  printf("This is the event handler implementation\n");
}
%> tiarmclang -mcpu=cortex-m0 alias_func_attr.c event_handler_impl.c -o a.out -Wl,-llnk.cmd,-ma.map
%> load470 -q a.out
This is the event handler implementation

2.7.2.2. aligned

The aligned function attribute can be applied to a function in order to set a minimum byte-alignment constraint on the target memory address where the function symbol is defined.

Syntax

<return type> symbol (<arguments>) __attribute__((aligned(alignment)));

  • alignment - is the minimum byte-alignment for the definition of the symbol. The alignment value must be a power of 2. The default alignment for a symbol is 4-bytes.

Example

The following example shows a program that calls a function with an aligned attribute applied to it:

#include <stdio.h>

__attribute__((aligned(64))) void aligned_func() {
  printf("This functions address is: 0x%08lx\n",
         (unsigned long)&aligned_func);
}

int main() {
  aligned_func();
  return 0;
}

When compiled and linked and run, the output of the program shows that the effective address of aligned_func is on a 64-byte boundary (the 1 in the LS bit of the printed address indicates the code state for the function; 1 in this case, indicates that aligned_func is a THUMB function):

%> tiarmclang -mcpu=cortex-m0 aligned_func_attr.c -o a.out -Wl,-llnk.cmd,-ma.map
%> load470 -q a.out
This functions address is: 0x00001981

2.7.2.3. always_inline

The always_inline function attribute can be applied to a function to instruct the compiler that the function is to be inlined at any call sites, even if no optimization is specified on the tiarmclang command line.

Syntax

<return type> symbol (<arguments>) __attribute__((always_inline));

Example

The following use of the always_inline function attribute will cause the body of emit_msg to be inlined where main calls emit_msg:

#include <stdio.h>

int counter = 0;

__attribute__((always_inline)) void emit_msg() {
  printf("this is call #%d\n", ++counter);
}

int main() {
  emit_msg();
  emit_msg();
  emit_msg();
}

The compiler-generated assembly source for the above C code shows that the body of emit_msg has been inlined even though no optimization was specified on the command-line:

%> tiarmclang -mcpu=cortex-m0 -S always_inline_function_attr.c
%> cat always_inline_function_attr.s
...
        .section        .text.main,"ax",%progbits
        .hidden main                            @ -- Begin function main
        .globl  main
        .p2align        2
        .type   main,%function
        .code   16                              @ @main
        .thumb_func
main:
        .fnstart
@ %bb.0:                                @ %entry
        .save   {r7, lr}
        push    {r7, lr}
        .pad    #8
        sub     sp, #8
        ldr     r0, .LCPI1_0
        str     r0, [sp]                        @ 4-byte Spill
        ldr     r1, [r0]
        adds    r1, r1, #1
        str     r1, [r0]
        ldr     r0, .LCPI1_1
        str     r0, [sp, #4]                    @ 4-byte Spill
        bl      printf
...

The compiler-generated assembly code will also contain the definition of the emit_msg function, but when the program is compiled and linked, the section containing the definition of emit_msg will not be included in the link since all of the references to it have been inlined.

2.7.2.4. cmse_nonsecure_call

The cmse _nonsecure_call function attribute is a Cortex-M (ARMv8-M only) Security Extension (CMSE) and is only accepted by the tiarmclang compiler when the -mcpu=cortex-m33 and -mcmse options are specified on the compiler command-line.

The cmse_nonsecure_call attribute is used to declare a non-secure function type to facilitate the use of a non-secure function pointer in secure memory code so that the secure code can execute a call to a function that is defined in non-secure memory. Secure code can only call non-secure code via a function pointer.

Syntax

typedef void __attribute__((cmse_nonsecure_call)) non-secure function type name (<arguments>);

Example

The following example C code contains a definition of a secure function that is callable from non-secure code (via cmse_nonsecure_entry attribute) that is passed a pointer to a callback function. The secure function checks whether the callback function is defined in secure or non-secure memory and then calls the callback function.

// cmse_nonsecure_call_ex.c
#include <arm_cmse.h>

// Declare non-secure function type
typedef void __attribute__((cmse_nonsecure_call)) nsfunc(void);

// Set up non-secure function pointer to call default handler
extern void secure_callback_handler(void);
void secure_defaul(void) { secure_callback_handler(); }
nsfunc *cbp = (nsfunc *) secure_default;

// Definition of non-secure callable secure function
void __attribute__((cmse_nonsecure_entry)) ns_callable(nsfunc *callback) {
  // Convert the callback function address so that it can be queried
  // as to whether it resides in secure or non-secure memory
  cbp = cmse_nsfptr_create(callback); // non-secure function pointer
}

// Callback function is called via non-secure function pointer, cbp
void call_callback(void) {
  // If callback function is defined in non-secure memory, call it
  // via a non-secure function pointer
  if (cmse_is_nsfptr(cbp)){ cbp(); }

  // Otherwise, the non-secure function pointer will be cast to a
  // normal function pointer before making the call
  else { ((void (*)(void)) cbp)(); }
}

Note

#include <arm_cmse.h>

The code that facilitates calls from secure code to non-secure code relies on the cmse_nsfptr_create and cmse_is_nsfptr intrinsics that are declared in arm_cmse.h. When writing secure code that needs to call non-secure code, be sure to include the arm_cmse.h header file in the compilation unit. The arm_cmse.h header file is provided with the tiarmclang compiler tools installation.

Related Reference

2.7.2.5. cmse_nonsecure_entry

The cmse _nonsecure_entry function attribute is a Cortex-M (ARMv8-M only) Security Extension (CMSE) and is only accepted by the tiarmclang compiler when the -mcpu=cortex-m33 and -mcmse options are specified on the compiler command-line.

The cmse_nonsecure_entry attribute can be applied to a function defined in secure memory to indicate that the function is callable from non-secure memory. For secure functions that are marked with the cmse_nonsecure_entry attribute, to prevent information leakage from the secure state, the compiler takes the precaution of setting general-purpose registers and the N, Z, C, V, Q, and GE bits of the APSR register to a known value. If floating-point support is enabled when compiling a non-secure entry function, then the compiler will also set floating point registers and the FPSCR register to a known value.

Syntax

void __attribute__((cmse_nonsecure_entry)) symbol (<arguments>);

extern “C” void __attribute__((cmse_nonsecure_entry)) symbol (<arguments>);

Example

The following example C code defines a secure function that is callable from non-secure memory:

#include <arm_cmse.h>

extern void handle_service_request(int v);

void __attribute__((cmse_nonsecure_entry)) ns_service_request(int val) {
  handle_service_request(val);
}

Related Reference

2.7.2.6. const

The const function attribute applied to a function declaration informs the compiler that the function has no side effects except for the value it returns. The function will not examine any values outside its body with the exception of arguments that are passed into it. It does not access any global data.

Note that if the function has a pointer argument and it accesses memory via that pointer, then the const attribute should not be applied to its declaration. Also, the const attribute should not be applied to a function which calls a non-const function.

Syntax

<return type> symbol (<arguments>) __attribute__((const));

Example

The following C code is a simple example of the use of the const attribute:

#include <stdio.h>

float square_flt(float a_flt) __attribute__((const));
float square_flt(float a_flt) {
  return (a_flt * a_flt);
}

float tot_flt = 0.0;

int main(void) {
  int i;
  for (i = 0; i < 10; i++)
  {
    tot_flt += square_flt(i);
    printf ("iter #%d, tot_flt is: %f\n", i, tot_flt);
  }
}

2.7.2.7. constructor

Applying a constructor attribute to a function will cause the function to be called prior to executing the code in main. Use of this attribute provides a means of initializing data that is used implicitly during the execution of a program.

Syntax

void constructor function name () __attribute__((constructor[(priority)]));

  • priority - is an optional integer argument used to indicate the order in which this constructor function is to be called relative to other functions that have been annotated with the constructor attribute. If no priority argument is specified, then constructor-annotated functions that do not have priority arguments will be called in the order in which they are encountered in the compilation unit. If a priority argument is specified, then a constructor-annotated function with a lower priority value will be called before a constructor-annotated function with a higher priority value or no priority argument.

Example

Consider the following C program containing 4 functions that have been annotated with a constructor attribute:

#include <stdio.h>

__attribute__((constructor)) void init2() {
  printf("run init2\n");
}

__attribute__((constructor)) void init1() {
  printf("run init1\n");
}

__attribute__((constructor(5))) void init3() {
  printf("run init3\n");
}

__attribute__((constructor(50))) void init4() {
  printf("run init4\n");
}

int main() {
  printf("run main\n");
  return 0;
}

When compiled and linked and run, the output of the program shows the order in which the constructor-annotated functions are called:

%> tiarmclang -mcpu=cortex-m0 constructor_function_attr.c -o a.out -Wl,-llnk.cmd,-ma.map
%> load470 -q a.out
run init3
run init4
run init2
run init1
run main

The iniit3 constructor is run first since its priority value is lower than init4. The init2 and init1 constructors are run after init4 because they don’t have a priority argument. Finally, init2 is run before init1 since it is encountered before init1 in the compilation unit.

2.7.2.8. deprecated

The deprecated function attribute can be applied to a function to mark it as deprecated so that the compiler will emit a warning when it sees a reference to the function in its compilation unit. This can be useful during program development when trying to remove references to a function whose definition will eventually be removed.

Syntax

<return type> symbol (<arguments>) __attribute__((deprecated));

Example

In this example, the function dep_func has been marked with a deprecated attribute, but main contains a call to the function:

#include <stdio.h>

__attribute__((deprecated)) void dep_func(void) {
  printf("this function has been deprecated\n");
}

int main() {
  dep_func();
  printf("run main\n");
  return 0;
}

When compiled, tiarmclang will emit a warning diagnostic to indicate a reference to the deprecated function dep_func has been encountered:

%> tiarmclang -mcpu=cortex-m4 deprecated_function_attr.c -o a.out -Wl,-llnk.cmd,-ma.map
deprecated_function_attr.c:9:3: warning: 'dep_func' is deprecated [-Wdeprecated-declarations]
  dep_func();
  ^
deprecated_function_attr.c:4:16: note: 'dep_func' has been explicitly marked deprecated here
__attribute__((deprecated)) void dep_func(void) {
             ^
1 warning generated.

2.7.2.9. format

The format function attribute can be applied to a function to indicate that the function accepts a printf or scanf-like format string and corresponding arguments or a va_list that contains these arguments.

The tiarmclang compiler will perform two kinds of checks with this attribute.

  1. The compiler will check that the function is called with a format string that uses format specifiers that are allowed, and that arguments match the format string. If the compiler encounters an issue with this check, a warning diagnostic will be emitted at compile-time.

  2. If the format-nonliteral warning category is enabled (off by default), then the compiler will emit a warning if the format string argument is not a literal string.

Syntax

<return type> symbol (<arguments>) __attribute__((format(archtype, string-index, first-to-check)));

  • archtype - identifies the runtime library function that informs the compiler how to interpret the format string argument. The compiler will accept printf, scanf, and strftime as valid archtype argument values.

  • string-index - is an integer value identifying which argument in the argument list is the format string argument. Index numbering starts with the integer 1.

  • first-to-check - is an integer value identifying the first argument to check against the format string. Index numbering starts with the integer 1. For format functions where the arguments are not available to be checked, the first-to-check argument for the format attribute should be zero.

Example

Consider the following C code that uses a wrapper function for printf called my_printf that has been declared with a format attribute:

#include <stdio.h>

__attribute__((format(printf, 2, 3)))
int my_printf(int n, const char* fmt, ...);

int main() {
  my_printf(10, "call with int: %d\n", 20);
  my_printf(30, "wrong number of args: %d\n", 40, 50);

  return 0;
}

When the above code is compiled, tiarmclang will report a warning diagnostic about the second call to my_printf since the call provides more arguments than can be handled by the specified format string.

%> tiarmclang -mcpu=cortex-m4 -c format_function_attr.c
format_function_attr.c:9:51: warning: data argument not used by format string [-Wformat-extra-args]
  my_printf(30, "wrong number of args: %d\n", 40, 50);
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~      ^
1 warning generated.

2.7.2.10. format_arg

The format_arg function attribute can be applied to a function that takes a format string as an argument and returns a potentially updated version of the format string that is to be used as a format string argument for a printf-style function (like printf, scanf, strftime, etc.). The format_arg attribute enables the compiler to perform a type check between the format specifiers in the format string and the other arguments that are passed to the printf-style function.

Syntax

<return type> symbol (<arguments>) __attribute__((format_arg(string-index)));

Example

In the following C code, the my_format function is declared with a format_arg attribute, identifying the index of the format string argument in the my_format function interface. The main function then contains a series of calls to printf where the format string to the printf call is the return value of the my_format function. The compiler will check the format string passed to my_format against the other arguments that are passed to printf in each case:

#include <stdio.h>

char *my_format(int n, const char *fmt) __attribute__((format_arg(2)));

extern int i1, i2;
extern float f1, f2;

int main() {
  printf(my_format(10, "one int: %d\n"), i1);
  printf(my_format(20, "too many ints: %d\n"), i1, i2);
  printf(my_format(20, "wrong type: %d %f\n"), f1, f2);
  return 0;
}

When the above code is compiled, tiarmclang will report warning diagnostics about the incorrect number of arguments in the second call to printf and the argument type mismatch in the third call to printf.

%> tiarmclang -mcpu=cortex-m0 -c format_arg_function_attr.c
%format_arg_function_attr.c:11:52: warning: data argument not used by format string [-Wformat-extra-args]
  %printf(my_format(20, "too many ints: %d\n"), i1, i2);
                       %~~~~~~~~~~~~~~~~~~~~~       ^
%format_arg_function_attr.c:12:48: warning: format specifies type 'int' but the argument has type 'float' [-Wformat]
  %printf(my_format(20, "wrong type: %d %f\n"), f1, f2);
                                    %~~         ^~
                                    %%f
%2 warnings generated.

2.7.2.11. fully_populate_jump_tables

The fully_populate_jump_tables function attribute will allow a function’s switch statements to use fully populated jump tables (if possible) with no minimum density up to a maximum range limit of 100 entries. This capability can eliminate non-deterministic control flow and is useful in embedded systems that require ISRs to execute with deterministic timing.

Note

This attribute may negatively impact code size depending on the size of the jump table

2.7.2.12. interrupt

The interrupt function attribute can be applied to a function definition to identify it as an interrupt function so that the compiler can generate additional code on function entry and exit to preserve the system state. The function can then be used as an exception handler.

The tiarmclang compiler will re-align the stack pointer to an 8-byte boundary on entry into a function marked with the interrupt attribute because the Arm Procedure Call Standard (AAPCS) requires this alignment for all public interfaces.

For Arm Cortex-M processor applications, the architecture includes mechanisms to preserve all general-purpose integer registers. When compiling for an Arm Cortex-R processor, the compiler will generate code to preserve general-purpose registers and a sequence of instructions to effect an appropriate exception return for the processor.

Note

FPU Registers are Not Automatically Preserved by Interrupt Functions

The compiler will not generate code to preserve FPU registers in a function marked with the interrupt attribute. If floating-point operations are required in the scope of an interrupt, then the FPU registers must be preserved manually.

Syntax

__attribute__((interrupt)) <return type> symbol (<arguments>) { … }

__attribute__((interrupt[(”interrupt-type”)])) void symbol () { … }

  • interrupt-type - is the optional string literal argument that indicates the type of interrupt being defined. The tiarmclang compiler supports the following interrupt-type identifiers:

    • IRQ

    • FIQ

    • SWI

    • ABORT

    • UNDEF

    Interrupt types other than FIQ will save all core registers except the lr and sp registers. FIQ type interrupts will save r0-r7.

    Note that if an interrupt-type argument is specified with the interrupt attribute specification, then the function interface may not take any arguments and may not return a value.

Example

Here are some examples of the interrupt attribute applied to functions:

extern int  do_something1(int n) __attribute__((interrupt));
extern void do_something2(void) __attribute__((interrupt("IRQ")));
extern void do_something3(void) __attribute__((interrupt("FIQ")));
extern void do_something4(void) __attribute__((interrupt("SWI")));
extern void do_something5(void) __attribute__((interrupt("ABORT")));
extern void do_something6(void) __attribute__((interrupt("UNDEF")));

__attribute__((interrupt)) void int1(int n) {
  do_something1(n);
}
__attribute__((interrupt("IRQ"))) void int2() {
  do_something2();
}
__attribute__((interrupt("FIQ"))) void int3() {
  do_something3();
}
__attribute__((interrupt("SWI"))) void int4() {
  do_something4();
}
__attribute__((interrupt("ABORT"))) void int5() {
  do_something5();
}
__attribute__((interrupt("UNDEF"))) void int6() {
  do_something6();
}

When compiled with the -mcpu=cortex-r5 option, the compiler-generated assembly snippet shows general-purpose registers being preserved during the function’s entry and exit code, the re-alignment of the stack pointer via a forced adjustment to the stack and a “bfc sp, #0, #3” instruction. In the example shown, the stack is adjusted prior to the “bfc sp, #0, #3” instruction by pushing an extra two registers (r10 and r11) onto the stack. In other cases, the compiler may use a “sub sp, sp, #8” instruction to force an adjustment to the stack prior to the “bfc sp, #0, #3” instruction. The return from the interrupt function is effected with the addition of the “subs pc, lr, #4” instruction.

%> tiarmclang -mcpu=cortex-r5 -S interrupt_function_attr.c
%> cat interrupt_function_attr.s
...
int2:
        .fnstart
@ %bb.0:                                @ %entry
        push    {r0, r1, r2, r3, r10, r11, r12, lr}
        add     r11, sp, #20
        bfc     sp, #0, #3
        bl      do_something2
        sub     sp, r11, #20
        pop     {r0, r1, r2, r3, r10, r11, r12, lr}
        subs    pc, lr, #4
...

2.7.2.13. local

When using Smart Function and Data Placement, the local function attribute can be used to more easily place a function in memory local to the processor (for example, in Tightly Coupled Memory (TCM)).

Syntax

__attribute__((local(priority))) <return type> symbol (<arguments>) { … }

  • priority - is an optional integer argument indicating the placement order of the object relative to other objects aggregated in the same output section. This influences how the placements are sorted at link-time. If omitted, the priority is assumed to be the highest priority, which is ‘1’.

Example

__attribute__((local(3))) int main() {
  printf("Good morning, Dave.\n");
  return 0;
}

2.7.2.14. location

The location function attribute can be used to specify a function’s run-time address from within the C/C++ source. The tiarmclang compiler will embed linker instructions within a given compiler-generated object file that will dictate where in target memory the function definition will be placed at link-time.

Syntax

<return type> symbol (<arguments>) __attribute__((location(address)));

  • address - is the run-time target memory address where the definition of the function symbol is to be placed at link-time. When specifying the address for a THUMB mode function, a 1 must be set in the least significant bit of the specified address value since it is assumed that the specified value includes the ARM/THUMB mode bit.

Example

In the following example, the location attribute is applied to main using an address argument of 0x2001 to place the definition of main at target address 0x2000.

#include <stdio.h>

__attribute__((location(0x2001))) int main() {
  printf("Good morning, Dave.\n");
  return 0;
}
%> tiarmclang -mcpu=cortex-m0 location_function_atr.c -o a.out -Wl,-llnk.cmd,-ma.map
%> cat a.map
SECTION ALLOCATION MAP

 output                                  attributes/
section   page    origin      length       input sections
--------  ----  ----------  ----------   ----------------
...
.text.main
*          0    00002000    0000002c
                  00002000    0000001c     location_function_attr-9108ac.o (.text.main)
...

2.7.2.15. malloc

The malloc function attribute can be applied to a function to inform the compiler that the function performs dynamic memory allocation. This information will then be incorporated into associated optimizations that the compiler may perform. For example, the compiler can assume that the pointer returned by the function that is annotated with a malloc attribute cannot alias any other pointer that is valid at the time the function returns. The compiler can also assume that no other pointer to a valid object has access to any storage that was allocated by the malloc-like function.

Syntax

<object type> * symbol (<arguments>) __attribute__((malloc));

Example

The following C code is an example of a function that is designated as malloc-like with the application of the malloc attribute:

char *alloc_buffer(int sz) __attribute__((malloc));

2.7.2.16. naked

When a naked function attribute is applied to a function, it informs the compiler that the function is written entirely in GNU-syntax Arm assembly language via the use of asm() statements. The compiler will not generate function prologue or epilogue code for such functions.

Note that only simple asm() statements can be used to compose the assembly language content of a naked function, and the content must adhere to the applicable C/C++ calling conventions in terms of how arguments are passed into the function and how the return value is placed in the proper return register (for a function with a non-void return type).

Syntax

<return type> symbol (<arguments>) __attribute__((naked));

Example

Here is a simple example of a naked function:

__attribute__((naked)) int sub(int arg1, int arg2) {
  __asm(" SUB r0, r0, r1");
}

2.7.2.17. noinline

The noinline function attribute will suppress the inlining of the function that it applies to at any function call sites in the same compilation unit.

Syntax

<return type> symbol (<arguments>) __attribute__((noinline));

Example

Consider the following program in which incr_counter is marked with a noinline attribute so that it cannot be inlined at the site of main’s call to the function, even with optimization enabled:

#include <stdio.h>

int my_counter = 0;

__attribute__((noinline)) void incr_counter(void) { ++my_counter; }

int main() {
  int i;
  for (i = 0; i < 10; i++) {
    incr_counter();
  }

  printf("my counter is: %d\n", my_counter);
}

When compiled with -O2 optimization, the compiler generated assembly for main shows that calls to incr_counter are not inlined, but the loop has been unrolled to eliminate the loop control flow overhead:

%> tiarmclang -mcpu=cortex-m0 -S -O2 noinline_function_attr.c
%> cat noinline_function_attr.s
...
        .section        .text.main,"ax",%progbits
        .hidden main                            @ -- Begin function main
        .globl  main
        .p2align        2
        .type   main,%function
        .code   16                              @ @main
        .thumb_func
main:
        push    {r7, lr}
        bl      incr_counter
        bl      incr_counter
        bl      incr_counter
        bl      incr_counter
        bl      incr_counter
        bl      incr_counter
        bl      incr_counter
        bl      incr_counter
        bl      incr_counter
        bl      incr_counter
        ldr     r0, .LCPI1_0
        ldr     r1, [r0]
        ldr     r0, .LCPI1_1
        bl      printf
        movs    r0, #0
...

2.7.2.18. nomerge

When a nomerge attribute is applied to a function, the compiler will be prevented from merging calls to the function. The nomerge attribute will not affect indirect calls to the function.

Syntax

<return type> symbol (<arguments>) __attribute__((nomerge));

Example

Consider the following C code containing an if block and an else block both of which call callee_func with slightly different arguments. If the nomerge attribute is not applied to the callee_func declaration, the compiler will tail-merge the calls into a single call when using optimization. However, the use of the nomerge attribute prevents the calls to callee_func from being merged:

void callee_func(const char *str) __attribute__((nomerge));

int caller_func(int n) {

  if (n < 10) {
    callee_func("string for return 1");
    return 1;
  }

  else {
    callee_func("string for return 2");
    return 2;
  }

  return 0;
}

The compiler-generated assembly code for the definition of caller_func shows that the calls to callee_func are not merged:

%> tiarmclang -mcpu=cortex-m4 -Oz -S nomerge_function_attr.c
%> cat nomerge_function_attr.s
...
        .section        .text.caller_func,"ax",%progbits
        .hidden caller_func                     @ -- Begin function caller_func
        .globl  caller_func
        .p2align        2
        .type   caller_func,%function
        .code   16                              @ @caller_func
        .thumb_func
caller_func:
@ %bb.0:                                @ %entry
        push    {r7, lr}
        cmp     r0, #9
        bgt     .LBB0_2
@ %bb.1:                                @ %if.then
        ldr     r0, .LCPI0_1
        bl      callee_func
        movs    r0, #1
        pop     {r7, pc}
.LBB0_2:                                @ %if.else
        ldr     r0, .LCPI0_0
        bl      callee_func
        movs    r0, #2
        pop     {r7, pc}
...

2.7.2.19. nonnull

The nonnull function attribute can be applied to a function to inform the compiler that pointer arguments to the function should not be null pointers. The compiler will emit a warning diagnostic if it detects an incoming null pointer argument.

Syntax

<return type> symbol (<arguments>) __attribute__((nonull));

Example

In the following C code, when the declaration of callee_func is annotated with a nonnull attribute, it enables the compiler to emit a warning diagnostic when it detects a NULL pointer being passed as an argument at one of the call sites for callee_func:

void callee_func(int n, int *p) __attribute__((nonnull));

void caller_func(int n) {
  callee_func(n, &n);
  callee_func(n, (int *)0);
}
%> tiarmclang -mcpu=cortex-m0 -c nonnull_function_attr.c
nonnull_function_attr.c:6:26: warning: null passed to a callee that requires a non-null argument [-Wnonnull]
  callee_func(n, (int *)0);
                 ~~~~~~~~^
1 warning generated.

2.7.2.20. noreturn

The noreturn function attribute can be used to identify a function that should not return to its caller. With noreturn applied to a function, the compiler will generate a warning diagnostic if a return from the function is detected.

The noreturn attribute cannot be applied to a function pointer.

Syntax

void symbol (<arguments>) __attribute__((noreturn));

Example

The following example, when compiled, will emit a warning since fake_return contains a return statement:

__attribute__((noreturn)) void fake_noreturn() { return; }
%> tiarmclang -mcpu=cortex-m0 -c noreturn_warn.c
noreturn_warn.c:2:50: warning: function 'fake_noreturn' declared 'noreturn' should not return [-Winvalid-noreturn]
__attribute__((noreturn)) void fake_noreturn() { return; }
                                                 ^
1 warning generated.

2.7.2.21. nothrow

When applied to a function, the nothrow attribute informs the compiler that the function cannot throw an exception. If the compiler knows that a function cannot throw an exception, it may be able to optimize the size of exception-handling tables for callers of the function.

Syntax

<return type> symbol (<arguments>) __attribute__((nothrow));

See C++ Exception Handling for more about exception handling.

2.7.2.22. offchip

When using Smart Function and Data Placement, the offchip function attribute can be used to more easily place a function in offchip FLASH.

Syntax

__attribute__((offchip(priority))) <return type> symbol (<arguments>) { … }

  • priority - is an optional integer argument indicating the placement order of the object relative to other objects aggregated in the same output section. This influences how the placements are sorted at link-time. If omitted, the priority is assumed to be the highest priority, which is ‘1’.

Example

__attribute__((offchip(2))) int main() {
  printf("Good morning, Dave.\n");
  return 0;
}

2.7.2.23. onchip

When using Smart Function and Data Placement, the onchip function attribute can be used to more easily place a function in onchip RAM.

Syntax

__attribute__((onchip(priority))) <return type> symbol (<arguments>) { … }

  • priority - is an optional integer argument indicating the placement order of the object relative to other objects aggregated in the same output section. This influences how the placements are sorted at link-time. If omitted, the priority is assumed to be the highest priority, which is ‘1’.

Example

__attribute__((onchip(5))) int main() {
  printf("Good morning, Dave.\n");
  return 0;
}

2.7.2.24. optnone

The optnone function attribute can be applied to a function to instruct the compiler not to apply non-trivial optimizations in the generation of code for the function.

Syntax

<return type> symbol (<arguments>) __attribute__((optnone));

Example

In the following C example, the park_and_wait function contains an empty while loop that the compiler would optimize away and remove references to the function if not for the application of the optnone attribute to park_and_wait:

void check_peripheral();
__attribute__((optnone)) void park_and_wait();

void run_a_check_on_peripheral(void) {
  check_peripheral();
}

void check_peripheral() {
  if (*((unsigned long *)(268612608)) != 286529877) {
    park_and_wait();
  }
}

__attribute__((optnone)) void park_and_wait() {
  while(1) {
    ;
  }
}

The compiler-generated assembly for the above code shows that even though the -O2 optimization option was specified, the reference to park_and_wait remains intact. If the optnone attribute had not been applied to the park_and_wait function, the optimizer would have detected the empty while loop in park_and_wait and removed the reference to it in check_peripheral:

%> tiarmclang -mcpu=cortex-m4 -O2 -S optnone_function_attr.c
%> cat optnone_function_attr.s
...
        .section        .text.check_peripheral,"ax",%progbits
        .hidden check_peripheral                @ -- Begin function check_peripheral
        .globl  check_peripheral
        .p2align        2
        .type   check_peripheral,%function
        .code   16                              @ @check_peripheral
        .thumb_func
check_peripheral:
        movw    r0, #46080
        movt    r0, #4098
        ldr     r0, [r0]
        movw    r1, #6485
        movt    r1, #4372
        cmp     r0, r1
        it      eq
        bxeq    lr
.LBB1_1:                                @ %if.then
        bl      park_and_wait
...

2.7.2.25. pure

The pure function attribute can be applied to a function that is known to have no other observable effects on the state of a program other than to return a value. This information is useful to the compiler in performing optimizations such as common subexpression elimination.

Syntax

<return type> symbol (<arguments>) __attribute__((pure));

Example

Here is a simple example of applying the pure attribute to a function:

int decode(const char *str) __attribute__((pure));

The implication is that decode computes a value based on the string pointed to by str without modifying any other part of the program state.

2.7.2.26. section

The section function attribute can be used to instruct the compiler to place the definition of a function in a specific section. This is useful if you’d like to place specific functions separately from their default sections (e.g. .text).

Syntax

<return type> symbol (<arguments>) __attribute__((section(”section name”)));

Example

In this program, main will get defined in a section called main_section:

#include <stdio.h>

__attribute__((section("main_section"))) int main() {
  printf("hello\n");
  return 0;
}

When compiled and linked, the linker-generated map file shows that the symbol main is defined at address 0x22e1, which corresponds to the location of the main_section (with the THUMB function mode bit cleared to discern the actual target memory address of the section):

%> tiarmclang -mcpu=cortex-m0 section_function_attr.c -o a.out -Wl,-llnk.cmd,-ma.map
%> cat a.map
...
SECTION ALLOCATION MAP

 output                                  attributes/
section   page    origin      length       input sections
--------  ----  ----------  ----------   ----------------
...
main_section
*          0    000022e0    0000001c
                  000022e0    0000001c     section_function_attr-2eb101.o (main_section)
...
GLOBAL SYMBOLS: SORTED ALPHABETICALLY BY Name

address   name
-------   ----
...
000022e1  main
...

2.7.2.27. used/retain

The used or retain function attribute, when applied, will instruct the tiarmclang compiler to embed information in the compiler-generated code to instruct the linker to include the definition of the function in the link of a given application, even if it is not referenced elsewhere in the application.

Syntax

<return type> symbol (<arguments>) __attribute__((used));

<return type> symbol (<arguments>) __attribute__((retain));

Example

In the following program, the retain attribute is applied to gb so that its definition is kept in the link even though it is not called:

#include <stdio.h>

void __attribute__((retain)) gb(void) {
  printf("goodbye\n");
}

int main() {
  printf("hello\n");
  return 0;
}

When compiled and linked, the linker-generated map file a.map shows that space has been allocated in target memory for the section where gb is defined:

%> tiarmclang -mcpu=cortex-m0 retain_global_func.c -o a.out -Wl,-llnk.cmd,-ma.map
%> cat a.map
...
SECTION ALLOCATION MAP

 output                                  attributes/
section   page    origin      length       input sections
--------  ----  ----------  ----------   ----------------
.text      0    00000020    000012b4
...
                  0000125c    00000010     retain_global_func-242de9.o (.text.gb)
...

2.7.2.28. visibility

The visibility function attribute provides a way for you to dictate what visibility setting is to be associated with a function in the compiler-generated ELF symbol table. Visibility is particularly applicable for applications that make use of dynamic linking.

Syntax

<return type> symbol (<arguments>) __attribute__((visibility(”visibility-kind”)));

  • visibility-kind indicates the visibility setting to be written into the symbol table entry for symbol in the compiler-generated ELF object file. The specified visibility kind will override the visibility setting that the compiler would otherwise assign to the symbol. The specified visibility-kind must be one of the following:

    • default - external linkage; symbol will be included in the dynamic symbol table, if applicable, and can be accessed from other dynamic objects in the same application. This is the default visibility if no visibility-kind argument is specified with the visibility attribute.

    • hidden - not included in the dynamic symbol table; symbol cannot be directly accessed from outside the current object, but may be accessed via an indirect pointer.

    • protected - the symbol is included in the dynamic symbol table; references from within the same dynamic module will bind to the symbol and other dynamic modules cannot override the symbol.

Example

In the following C code, the visibility attribute is applied to my_func to mark it as protected:

#include <stdio.h>

int my_func(int n) __attribute__((visibility("protected")));

void print_result(int n) {
  printf("my func returns: %d\n", my_func(n));
}

When compiled to an object file, the visibility setting for the my_func symbol is set to STV_PROTECTED in the symbol table:

%> tiarmclang -mcpu=cortex-m0 -c visibility_function_attr.c
%> tiarmofd -v visibility_function_attr.o
...
 Symbol Table ".symtab"
...
    <6> "my_func"
       Value:    0x00000000  Kind:        undefined
       Binding:  global      Type:        none
       Size:     0x0         Visibility:  STV_PROTECTED
...

2.7.2.29. weak

The weak function attribute causes the tiarmclang compiler to emit a weak symbol to the symbol table for the function symbol’s declaration. At link-time, if a strong definition of a function symbol with the same name is included in the link, then the strong definition of the function will override the weak definition.

Syntax

<return type> symbol (<arguments>) __attribute__((weak));

Example

Consider the following program with weak_func_attr.c:

#include <stdio.h>

extern const char *my_func();

int main() {
  printf("my_func is: %s\n", my_func());
  return 0;
}

and weak_func_def.c:

__attribute__((weak)) const char *my_func() {
  return "this is a weak definition of my_func\n";
}

and strong_func_def.c:

const char *my_func() {
  return "this is a strong definition of my_func\n";
}

If the program is compiled and linked without strong_func_def.c, then the weak definition of my_func will be chosen by the linker to resolve the reference to it in weak_func_attr.c:

%> tiarmclang -mcpu=cortex-m0 weak_func_attr.c weak_func_def.c -o a.out -Wl,-llnk.cmd,-ma.map
%> load470 -q a.out
my_func is: this is a weak definition of my_func

If both weak_func_def.c and strong_func_def.c are included in the program build, then the linker will choose the strong definition of my_func to resolve the reference to it in weak_func_attr.c:

%> tiarmclang -mcpu=cortex-m0 weak_func_attr.c weak_func_def.c strong_func_def.c -o a.out -Wl,-llnk.cmd,-ma.map
%> load470 -q a.out
my_func is: this is a strong definition of my_func

Note

Strong vs. Weak and Object Libraries

At link-time, if a weak definition of a symbol is available in the object files that are input to the linker and a strong definition of the symbol exists in an object library that is made available to the link, then the linker will not use the strong definition of the symbol since the reference to the symbol has already been resolved.

2.7.2.30. weakref

The weakref function attribute can be used to mark a declaration of a static function as a weak reference. The function symbol that the attribute applies to is interpreted as an alias of a target symbol, and also indicates that a definition of the target symbol is not required.

Syntax

<return type> symbol (<arguments>) __attribute__((weakref(”target symbol)));

<return type> symbol (<arguments>) __attribute__((weakref, alias(”target symbol”)));

  • target symbol - identifies the name of a function that the symbol being declared is to be treated as an alias for. If a target symbol argument is provided with the weakref attribute, then symbol is interpreted as an alias of target symbol. Otherwise, an alias attribute must be combined with the weakref attribute to identify the target symbol.

Example

Consider the following program with weakref_func_attr.c:

#include <stdio.h>

extern const char *my_func();
static const char *my_alias() __attribute__((weakref("my_func")));

int main(void) {
  printf("my_alias returns %s", my_alias());
  return 0;
}

and weak_func_def.c:

__attribute__((weak)) const char *my_func() {
  return "this is a weak definition of my_func\n";
}

and strong_func_def.c:

const char *my_func() {
  return "this is a strong definition of my_func\n";
}

If the above program is compiled and linked without strong_def.c, the linker will choose the weak definition of my_func to resolve the call to my_func that goes through the my_alias weakref symbol:

%> tiarmclang -mcpu=cortex-m0 weakref_func_attr.c weak_func_def.c -o a.out -Wl,-llnk.cmd,-ma.map
%> load470 -q a.out
my_alias returns this is a weak definition of my_func

If strong_func_def.c is included in the program build, the my_alias will resolve to the strong definition of my_func:

%> tiarmclang -mcpu=cortex-m0 weakref_func_attr.c weak_func_def.c strong_func_def.c -o a.out -Wl,-llnk.cmd,-ma.map
%> load470 -q a.out
my_alias returns this is a strong definition of my_func