# Port code from GCC This section describes issues commonly encountered while porting to the LLVM compiler an application that was previously built only with GCC. Note For more information on GCC compatibility, see [Language compatibility](https://docs.qualcomm.com/doc/80-N3040-23/topic/language-compatibility.html). ## Command options The LLVM compiler supports many but not all of the GCC command options. Unsupported options are either ignored or flagged with a warning or error message; most receive warning messages. For more information, see [Warning and error messages](https://docs.qualcomm.com/doc/80-N3040-23/topic/use-the-compilers.html#hccpp-compiler-options-warn-err-msgs-sub). ## Errors and warnings The LLVM compiler enforces strict conformance to the C11 language standard. As a result, you might encounter new errors and warnings when compiling GCC code. To handle these messages when porting to the LLVM compiler, consider the following steps: 1. Remove the `-Werror` command option if it is being used (because it converts all warnings into errors). 2. Update the code to eliminate the remaining errors and warnings. ## Function declarations The LLVM compiler enforces the C11 rules for function declarations. In particular: - A function declared with a non-void return type must return a value of that type. - A function referenced before being declared is assumed to return a value of type int. If the function is subsequently declared to return some other type, it is flagged as an error. - A function declaration with the inline attribute assumes the existence of a separate definition for the function, which does not include the inline attribute. If no such definition appears in the program, a link-time error will occur. To satisfy these restrictions when porting to the LLVM compiler, consider the following steps: 1. Use `-Wreturn-type` to generate a warning whenever a function definition does not return a value of its declared type. 2. Use -Wimplicit-function-declaration to generate a warning whenever a function is used before being declared. 3. Update the code to eliminate the remaining errors and warnings. For more information on inlining, go to: [http://clang.llvm.org/compatibility.html#inline](http://clang.llvm.org/compatibility.html#inline) For a discussion of different inlining approaches, go to: [http://www.greenend.org.uk/rjk/tech/inline.html](http://www.greenend.org.uk/rjk/tech/inline.html) ## Casting to incompatible types The LLVM compiler enforces the C11 rules for *strict aliasing*. In the C language, two pointers that reference the same memory location are said to *alias* one another. Because any store through an aliased pointer might modify the data referenced by one of its pointer aliases, pointer aliases can limit the compiler’s ability to generate optimized code. In strict aliasing, pointers to different types are prevented from being aliased with one another. The compiler flags pointer aliases with an error message. Strict aliasing has a few exceptions: - Any pointer type can be cast to `char*` or `void*`. - A `char*` or `void*` can be cast to any pointer type. - Pointers to types that differ only by whether they are signed or unsigned (for example, `int` versus `unsigned int`) can be aliased. To satisfy strict aliasing when porting to the LLVM compiler, consider the following steps: 1. Use `-Wcast-align` to generate a warning whenever a pointer alias is detected. 2. Update the code to eliminate the resulting warnings. Note Dereferencing a pointer that is cast from a less strictly aligned type has undefined behavior. ## aligned attribute The LLVM compiler does not allow the aligned attribute to appear inside the `__alignof__` operator. To satisfy this restriction when porting to the LLVM compiler, create a typedef with the `aligned` attribute. For example: typedef unsigned char u8; #ifdef __llvm__ typedef u8 __attribute((aligned)) aligned_u8; #endif unsigned int foo() { #ifndef __llvm__ return __alignof__(u8 __attribute__ ((aligned))); #else return __alignof__(aligned_u8); #endif } Copy to clipboard ## Reserved registers The LLVM compiler does not support the GCC extension to place global variables in specific registers. To satisfy this restriction when porting to the LLVM compiler, use the equivalent LLVM intrinsics whenever possible. For example: #ifndef __llvm__ register unsigned long current_frame_pointer asm("r11"); #endif ... #ifndef __llvm__ fp = current_frame_pointer; #else fp = (unsigned long)__builtin_frame_address(0); #endif Copy to clipboard ## Inline versus extern inline The LLVM compiler conforms to the C11 language standard, which defines different semantics for the inline keyword than GCC. For example, consider the following code: inline int add(int i, int j) { return i + j; } int main() { int i = add(4, 5); return i; } Copy to clipboard In C11 the function attribute `inline` specifies that a function’s definition is provided only for inlining, and that another definition (without the `inline` attribute) is specified elsewhere in the program. This implies that this example is incomplete, because if `add()` is not inlined (for example, when compiling without optimization), `main()` will include an unresolved reference to that other function definition. This will result in the following link-time error: Undefined symbols: "_add", referenced from: _main in cc-y1jXIr.o Copy to clipboard By contrast, GCC’s default behavior follows the GNU89 dialect, which is based on the C89 language standard. C89 does not support the `inline` keyword; however, GCC recognizes it as a language extension, and treats it as a hint to the optimizer. There are several ways to fix this problem: - Change `add()` to a static inline function. This is usually the right solution if only one translation unit intends to use the function. Static inline functions are always resolved within the translation unit, so it will not be necessary to add a non-inline definition of the function elsewhere in the program. - Remove the `inline` keyword from this definition of `add()`. The inline `keyword` is not required for a function to be inlined, nor does it guarantee that it will be. Some compilers ignore it completely. The LLVM compiler treats it as a mild suggestion from the programmer. - Provide an external (non-inline) definition of `add()` somewhere else in the program. The two definitions *must* be equivalent. - Compile with the GNU89 dialect by adding `-std=gnu89` to the set of LLVM options. We do not recommend this approach. ## Lightweight instrumentation The LLVM compiler adds new options for instrumentation, including lightweight instrumentation (LWI) modes for applications where sizeand performance overhead is a concern. Workflows using flags such as `-fprofile-instr-generate` demonstrate significant code growth and performance slowdown due to generating counters and associated instructions for profiling purposes. LWI workflows instead insert a single custom call to a handler function responsible for data collection, which reduces the overall number of instructions needed to profile at runtime. LWI is enabled via a flag corresponding to the desired instrumentation style and specifying the handler function in a runtime library. The default manner of instrumentation is enabled via `-fprofile-lwi-generate`, which is a direct analog to `-fprofile-instr-generate` in terms of probe placement. The following is a simple void `foo(){}` example of the results of compiling with `-fprofile-lwi-generate`. _Z3foov: // @_Z3foov // %bb.0: // %entry { call __llvm_lwi_handler allocframe(r29,#0):raw } { r31:30 = dealloc_return(r30):raw } Copy to clipboard The `llvm_lwi_handler` may, for instance, log the return address for code coverage purposes. void __llvm_lwi_handler () { void *addr = __builtin_extract_return_addr(__builtin_return_address (0)); (… user defined address recording method here…) } Copy to clipboard Other instrumentation modes are available for instrumenting just function entries and exits, as well as just loop entries and exits for further overhead size reduction depending on specific project needs. The scope of insertion of probes can further be controlled via the `-flwi-attr` flag and associated LWI function attributes. When the `-flwi-attr` flag is used, only functions marked with `__attribute__ ((lwi_func)` will receive entry and exit instrumentations. Functions marked with `__attribute__ ((no_lwi_func)`, do not receive function entry and exit instrumentations, regardless of the LWI flag combinations used. Last Published: Oct 06, 2026 [Previous Topic Postprocessor](https://docs.qualcomm.com/bundle/publicresource/80-N3040-23/topics/compiler-security-tools.md) [Next Topic Coding practices](https://docs.qualcomm.com/bundle/publicresource/80-N3040-23/topics/coding-practices.md)