2.7.2. Function Attributes

The following function attributes are supported by the compiler:

See C29x Security Model for information about protected calls and use of the c29_protected_call function attribute.

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);
}
...
%> c29clang -mcpu=c29.c0 -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:

%> c29clang -mcpu=c29.c0 alias_func_attr.c -o a.out -Wl,-llnk.cmd,-ma.map

The output when the program is loaded and run is as follows:

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");
}
%> c29clang -mcpu=c29.c0 alias_func_attr.c event_handler_impl.c -o a.out -Wl,-llnk.cmd,-ma.map

The output when the program is loaded and run is as follows:

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

%> c29clang -mcpu=c29.c0 aligned_func_attr.c -o a.out -Wl,-llnk.cmd,-ma.map

The output when the program is loaded and run is as follows:

This function's 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 c29clang 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 inlines the body of emit_msg, even though no optimization was specified on the command line:

The compiler-generated assembly code also contains 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. 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.5. constructor

Applying a constructor attribute to a function causes 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:

%> c29clang -mcpu=c29.c0 constructor_function_attr.c -o a.out -Wl,-llnk.cmd,-ma.map

The output when the program is loaded and run is as follows:

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.6. 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, c29clang will emit a warning diagnostic to indicate a reference to the deprecated function dep_func has been encountered:

%> c29clang -mcpu=c29.c0 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.7. 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 c29clang compiler performs 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, c29clang reports 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.

%> c29clang -mcpu=c29.c0 -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.8. 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, c29clang reports 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.

%> c29clang -mcpu=c29.c0 -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.9. 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.10. 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 to handle errors that led to function exits.

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 c29clang compiler supports the following interrupt-type identifiers:

    • __attribute__((interrupt("RTINT")))

    • __attribute__((interrupt("INT")))

You can generate a Realtime Interrupt (RTINT) or maskable interrupt (INT) from C using the __attribute__((interrupt())) function attribute. For example:

void my_high_priority interrupt() __attribute__((interrupt("RTINT")));
void my_low_priority interrupt() __attribute__((interrupt("INT")));

__attribute__((interrupt("RTINT"))) void int2() {
  do_something2();
}
__attribute__((interrupt("INT"))) void int3() {
  do_something3();
}

An interrupt is responsible for saving any and all registers that may be used, so as to preserve the state of the registers as they were before the interrupt was called. An interrupt containing a call will save a large number of registers, which degrades code size and speed.

See C29x Security Model for information about protected calls and use of the c29_protected_call function attribute.

In addition, built-in C29 interrupt intrinsics can be used to disable/enable INT interrupts and block RTINT/INT interrupts. See Built-In Functions and Intrinsics for details.

2.7.2.11. location

The location function attribute can be used to specify a function’s run-time address from within the C/C++ source. The c29clang 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.

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;
}
%> c29clang -mcpu=c29.c0 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.12. 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.13. naked

When a naked function attribute is applied to a function, it informs the compiler that the function is written entirely in GNU-syntax C29x 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 D0, D0, D1");
}

2.7.2.14. 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 generates assembly instructions for main that do not inline incr_counter. However, the loop is unrolled to eliminate the loop control flow overhead.

2.7.2.15. 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 generates assembly instructions for the definition of caller_func that do not merge calls to callee_func.

2.7.2.16. 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);
}
%> c29clang -mcpu=c29.c0 -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.17. 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; }
%> c29clang -mcpu=c29.c0 -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.18. 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 generates assembly instructions that reference park_and_wait even though the -O2 optimization option was specified. 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.

2.7.2.19. 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.20. 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:

%> c29clang -mcpu=c29.c0 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.21. used/retain

The used or retain function attribute, when applied, will instruct the c29clang 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:

%> c29clang -mcpu=c29.c0 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.22. 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:

%> c29clang -mcpu=c29.c0 -c visibility_function_attr.c
%> c29ofd -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.23. weak

The weak function attribute causes the c29clang 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:

%> c29clang -mcpu=c29.c0 weak_func_attr.c weak_func_def.c -o a.out -Wl,-llnk.cmd,-ma.map

The output when the program is loaded and run is as follows:

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:

%> c29clang -mcpu=c29.c0 weak_func_attr.c weak_func_def.c strong_func_def.c -o a.out -Wl,-llnk.cmd,-ma.map

The output when the program is loaded and run is as follows:

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.24. 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:

%> c29clang -mcpu=c29.c0 weakref_func_attr.c weak_func_def.c -o a.out -Wl,-llnk.cmd,-ma.map

The output when the program is loaded and run is as follows:

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:

%> c29clang -mcpu=c29.c0 weakref_func_attr.c weak_func_def.c strong_func_def.c -o a.out -Wl,-llnk.cmd,-ma.map

The output when the program is loaded and run is as follows:

my_alias returns this is a strong definition of my_func