# Port code from GCC

This chapter describes issues commonly encountered while porting to
LLVM 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-VB419-99/topic/language_compatibility.html#ch-language-compatibility).

## Command options

LLVM 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 [Section 4.3.5](https://docs.qualcomm.com/doc/80-VB419-99/topic/use_the_compilers.html#sec-warning-and-error-messages).

## Errors and warnings

LLVM 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 LLVM, 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

LLVM 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 LLVM, 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:

    [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

LLVM 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 LLVM, 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

LLVM does not allow the aligned attribute to appear inside the
alignof operator.

To satisfy this restriction when porting to LLVM, 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

LLVM does not support the GCC extension to place global variables in
specific registers.

To satisfy this restriction when porting to LLVM, 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

LLVM 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 needs 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. LLVM
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.

Last Published: May 10, 2024

[Previous Topic
Compiler security tools](https://docs.qualcomm.com/bundle/publicresource/80-VB419-99/topics/compiler_security_tools.md) [Next Topic
Coding practices](https://docs.qualcomm.com/bundle/publicresource/80-VB419-99/topics/coding_practices.md)