# Language compatibility

LLVM strives to both conform to current language standards, and to
implement many widely used extensions available in other compilers,
so that most correct code will *just work* when compiled with LLVM.
However, LLVM is more strict than other popular compilers, and it
might reject incorrect code that other compilers allow.

This chapter describes common compatibility and portability issues
with LLVM to help you understand and fix the problem in your code
when LLVM emits an error message.

## C compatibility

This section describes common compatibility and portability issues
with LLVM C.

### Differences between various standard modes

LLVM supports the -std option, which changes what language mode LLVM
uses. The supported modes for C are c89, gnu89, c94, c99, gnu99, c11,
gnu11, and various aliases for those modes. If no -std option is
specified, LLVM defaults to gnu99 mode. The c\* and gnu\* modes have
the following differences:

- The c\* modes define `__STRICT_ANSI__`.
- Target-specific defines not prefixed by underscores (such as linux)
are defined in gnu\* modes.
- The default setting for trigraphs in gnu\* modes is OFF. Trigraphs
can be enabled by the -trigraphs option.
- The parser recognizes asm and typeof as keywords in the gnu\* modes.
The `__asm__` and `__typeof__` variants are recognized in all modes.
- Arrays that are VLAs according to the standard, but which can be
constant-folded by the compiler front end, are treated as fixed size
arrays.

For example, int X[(1, 2)]; is technically a VLA. The c\* modes are
strictly compliant and treat these as VLAs.

- The Apple blocks extension is recognized by default in gnu\* modes on
some platforms. It can be enabled in any mode with the -fblocks
option.

    The \*99 and \*11 modes have the following differences:
- Warnings for use of C11 features are disabled.
- `__STDC_VERSION__` is defined to 201112L rather than 199901L. The \*89 and
\*99 modes have the following differences:
- The default setting for \*99 modes is to implement inline as
specified in C11, while the

    \*89 modes implement the GNU version.

    The `__gnu_inline__` attribute can be used to override the default for
individual functions.
- Digraphs are not recognized in c89 mode.
- The scope of names defined in a for, if, switch, while, or do
statement is different. For example, if ((struct x {int x;}\*)0) {}.
- `__STDC_VERSION__` is not defined in \*89 modes.
- inline is not recognized as a keyword in c89 mode.
- restrict is not recognized as a keyword in \*89 modes.
- Commas are allowed in integer constant expressions in \*99 modes.
- Arrays that are not lvalues are not implicitly promoted to pointers
in \*89 modes.
- Some warnings are different.
c94 mode is identical to c89 mode except that digraphs are enabled in c94 mode.

### GCC extensions not yet implemented

LLVM tries to be compatible with GCC as much as possible, but the
following GCC extensions are not yet implemented in LLVM:

- #pragma weak

    Will probably be implemented at some point in the future, at least
partially.
- Decimal floating (\_Decimal32, and so on) and fixed-point types
(\_Fract, and so on)

    No one has expressed interest in this extension yet; currently, it is
not clear when they will be implemented.
- Nested functions

    A complex feature that is infrequently used, so it is unlikely to be
implemented soon.
- Global register variables

    Requires additional LLVM back-end support, so this extension is
unlikely to be implemented soon.
- Static initialization of flexible array members

    A rarely used extension, but it could be implemented pending user
demand.
- `__builtin_va_arg_pack` and `__builtin_va_arg_pack_len`

    Rarely used, but they might be implemented in potentially interesting
places such as the glibc headers, pending user demand.

    Because LLVM pretends to be like GCC 4.2 and this extension was
introduced in GCC 4.3, the glibc headers currently do not try to use
this extension with LLVM.
- Forward-declaring function parameters

    This extension has not shown up in any real-world code yet, though,
so it might never be implemented.

### Intentionally unsupported GCC extensions

LLVM intentionally does not implement the following GCC extensions:

- Variable-length arrays in structures

    This extension is not implemented for several reasons:

    - It is tricky to implement
    - The extension is completely undocumented
    - The extension appears to be rarely used

LLVM supports flexible array members (arrays with a zero or
unspecified size at the end of a structure).

- An equivalent to GCC’s fold

    This extension implies that LLVM does not accept some constructs GCC
might accept in contexts where a constant expression is required,
such as x-x, where x is a variable.
- `__builtin_apply` and related attributes

    This extension is extremely obscure and difficult to reliably
implement.

### Lvalue casts

Old versions of GCC permit casting the left-hand side of an
assignment to a different type. LLVM produces an error for code like
this:

lvalue.c:2:3: error: assignment to cast is illegal, lvalue casts are not supported
    (int*)addr = val;
    ^~~~~~~~~~ ~
    Copy to clipboard

To fix this problem, move the cast to the right-hand side. For
example:

addr = (float *)val;
    Copy to clipboard

### Jumps to within `__block` variable scope

LLVM disallows jumps into the scope of a block variable. Variables
marked with block require special runtime initialization. A jump into
the scope of a block variable bypasses this initialization, leaving
the variable’s metadata in an invalid state. Consider the following
code fragment:

int fetch_object_state(struct MyObject *c) {
       if (!c->active)
          goto error;
    
       __block int result;
       run_specially_somehow(^{ result = c->state; });
       return result;
    
       error:
          fprintf(stderr, "error while fetching object state");
          return -1;
    }
    Copy to clipboard

GCC accepts this code, but it produces code that typically crashes
when the result goes out of scope if the jump is taken. (It is
possible for this bug to go undetected, because it often does not
crash if the stack is fresh; that is, it is still zeroed.) Therefore,
LLVM rejects this code with a hard error:

t.c:3:5: error: goto into protected scope
       goto error;
       ^
    t.c:5:15: note: jump bypasses setup of __block variable
       __block int result;
                   ^
    Copy to clipboard

The fix is to rewrite the code so it does not require jumping into
the scope of a `__block` variable; for example, by limiting that scope:

{
       block int result;
       run_specially_somehow(^{ result = c->state; });
       return result;
    }
    Copy to clipboard

### Non-initialization of `__block` variables

In the following example, the variable x is used before it is
defined:

int f0() {
       block int x;
       return ^(){
          return x;
       }();
    }
    Copy to clipboard

By an accident of implementation, GCC and llvm-gcc unintentionally
always zero any initialized block variables. However, any programs
that depend on this behavior relies on unspecified compiler behavior.
Programs must explicitly initialize all local block variables before
they are used, as with other local variables.

LLVM does not zero-initialize local block variables—thus any programs
that rely on such behavior will most likely break when built with
LLVM.

### Inline assembly

Typically, LLVM is highly compatible with the GCC inline assembly
extensions, allowing the same set of constraints, modifiers, and
operands as GCC inline assembly.

## C++ compatibility

This section describes common compatibility and portability issues
with LLVM C++.

The types in C++ code that are compiled with -std=c++11 are not
inter-operable with the following:

- Types in C++ code that are compiled with `-std=c++03`
- Code compiled with no `-std=` specification

For example, the std::string from a C++03 compilation is unrelated to
a std::string from a C++11 compilation, and the two std::string types
cannot be easily converted to each other.

### Deleted special member functions

In C++11, the explicit declaration of a move constructor, or a move
assignment operator within a class, deletes the implicit declaration
of the copy constructor and copy assignment operator. This change
occurred fairly late in the C++11 standardization process, so early
implementations of C++11 (including LLVM before 3.0, GCC before 4.7,
and Visual Studio 2010) do not implement this rule, leading them to
accept the following ill-formed code:

struct X {
       X(X&&); // deletes implicit copy constructor:
       // X(const X&) = delete;
    };
    void f(X x); void g(X x) {
       f(x); // error: X has a deleted copy constructor
    }
    Copy to clipboard

This affects some early C++11 code, including Boost’s popular
shared\_ptr, up to version 1.47.0. The fix for Boost’s shared\_ptr is described here:
[https://svn.boost.org/trac/boost/changeset/73202](https://svn.boost.org/trac/boost/changeset/73202)

### Variable-length arrays

GCC and C11 allow the size of an array to be determined at runtime.
This extension is not permitted in standard C++. However, LLVM
supports such variable length arrays in very limited circumstances
for compatibility with GNU C and C11 programs.

- The element type of a variable length array must be a
<abbr title="plain old data">POD</abbr> type. It cannot have any user-declared
constructors or destructors, any base classes, or any members of
non-POD type. All C types are POD types.
- Variable length arrays cannot be used as the type of a non-type
template parameter.

    If the code uses variable length arrays in a manner that LLVM does
not support, several methods are available to fix the code:
- Replace the variable length array with a fixed-size array if you can
determine a reasonable upper bound at compile time. Sometimes this is
as simple as changing int size = …; to const int size = …; (if
the initializer is a compile-time constant).
- Use std::vector or some other suitable container type.
- Allocate the array on the heap instead using new Type[]; remember to
delete it using delete[].

### Unqualified lookup in templates

Some versions of GCC accept the following invalid code:

template <typename T> T Squared(T x) {
       return Multiply(x, x);
    }
    int Multiply(int x, int y) {
       return x * y;
    }
    int main() {
       Squared(5);
    }
    Copy to clipboard

LLVM flags this code with the following messages:

my_file.cpp:2:10: error: call to function 'Multiply' that is neither
    visible in the template definition nor found by argument-dependent
    lookup
    return Multiply(x, x);
           ^
    
    my_file.cpp:10:3: note: in instantiation of function template
    specialization 'Squared<int>' requested here
       Squared(5);
       ^
    
    my_file.cpp:5:5: note: 'Multiply' should be declared prior to the call site
       int Multiply(int x, int y) {
           ^
    Copy to clipboard

The C++ standard states that unqualified names such as Multiply are
looked up in two ways:

- First, the compiler performs an *unqualified lookup* in the scope
where the name was written.

    For a template, this means the lookup is done at the point where the
template is defined, not where it is instantiated. Because Multiply
has not been declared yet at this point, unqualified lookup will not
find it.
- Second, if the name is called like a function, the compiler also does
an argument- dependent lookup (ADL).

    In an ADL, the compiler looks at the types of all the arguments to
the call. When it finds a class type, it looks up the name in that
class’s namespace. The result is all the declarations it finds in
those namespaces plus the declarations from unqualified lookup.
However, the compiler does not do an ADL until it knows all the
argument types.

In the example code, Multiply is called with dependent arguments, so
an ADL is not done until the template is instantiated. At that point,
the arguments both have type int, which does not contain any class
types, and so the ADL does not look in any namespaces. Because
neither form of lookup found the declaration of Multiply, the code
does not compile.

Following is another example that uses overloaded operators, which
obey very similar rules.

#include <iostream>
    
    template<typename T>
    
    void Dump(const T& value) { std::cout << value << "\n";
    }
    
    namespace ns { struct Data {};
    }
    
    std::ostream& operator<<(std::ostream& out, ns::Data data) { return
    out << "Some data";
    }
    
    void Use() { Dump(ns::Data());
    }
    Copy to clipboard

Again, LLVM flags this code with the following messages:

my_file2.cpp:5:13: error: call to function 'operator<<' that is
    neither visible in the template definition nor found by argument-
    dependent lookup
       std::cout << value << "\n";
                 ^
    
    my_file2.cpp:17:3: note: in instantiation of function template
    specialization 'Dump<ns::Data>' requested here
       Dump(ns::Data());
       ^
    
    my_file2.cpp:12:15: note: 'operator<<' should be declared prior to
    the call site or in namespace 'ns'
       std::ostream& operator<<(std::ostream& out, ns::Data data) {
                     ^
    Copy to clipboard

As before, unqualified lookup did not find any declarations with the
name, operator&lt;&lt;. Unlike before, the argument types both contain
class types:

- One type is an instance of the class template type, std::basic\_ostream
- The other is the type ns::Data that is declared in the example Therefore,
the ADL looks in the std and ns namespaces for an
operator&lt;&lt;. Because one of the argument types was still dependent
during the template definition, the ADL is not done until the
template is instantiated during Use, which means the operator&lt;&lt; it
finds has already been declared. Unfortunately, it was declared in
the global namespace, not in either of the namespaces that the ADL
look in.

    Two methods exist to fix this problem:

    - Make sure the function you want to call is declared before the
template that might call it.

        This is the only option if none of its argument types contain
classes. Either move the template definition or function definition,
or add a forward declaration of the function before the template.
    - Move the function into the same namespace as one of its arguments so
that the ADL applies.

### Unqualified lookup into dependent bases of class templates

Some versions of GCC accept the following invalid code:

template <typename T> struct Base {
       void DoThis(T x) {}
       static void DoThat(T x) {}
    };
    template <typename T> struct Derived : public Base<T> {
       void Work(T x) {
          DoThis(x); // Invalid!
          DoThat(x); // Invalid!
       }
    };
    Copy to clipboard

LLVM correctly rejects this code with the following errors (when
Derived is eventually instantiated):

my_file.cpp:8:5: error: use of undeclared identifier 'DoThis'
       DoThis(x);
       ^
       this->
    
    my_file.cpp:2:8: note: must qualify identifier to find this
    declaration in dependent base class
       void DoThis(T x) {}
       ^
    
    my_file.cpp:9:5: error: use of undeclared identifier 'DoThat'
       DoThat(x);
       ^
       this->
    
    my_file.cpp:3:15: note: must qualify identifier to find this
    declaration in dependent base class
    static void DoThat(T x) {}
    Copy to clipboard

As noted in [Section 11.2.3](https://docs.qualcomm.com/doc/80-VB419-99/topic/language_compatibility.html#sec-unqualified-lookup-in-templates),
unqualified names such as DoThis and DoThat are looked up when the
Derived template is defined, not when it is instantiated. When
looking up a name used in a class, you typically look into the base
classes. However, you cannot look into the Base&lt;T&gt; base class because
its type depends on the template argument T, so the standard says to
ignore it.

As LLVM indicates, the fix is to tell the compiler that you want a
class member by prefixing the calls with this-&gt;:

void Work(T x) {
       this->\ DoThis(x);
       this->\ DoThat(x);
    }
    Copy to clipboard

Alternatively, you can tell the compiler exactly where to look:

void Work(T x) {
       Base<T>::DoThis(x);
       Base<T>::DoThat(x);
    }
    Copy to clipboard

This approach works whether the methods are static or not, but be
careful: if DoThis is virtual, calling it this way will bypass
virtual dispatch.

### Incomplete types in templates

The following code is invalid, but compilers are allowed to accept
it:

class IOOptions;
    
    template <class T> bool read(T &value) {
       IOOptions opts;
       return read(opts, value);
    }
    
    class IOOptions { bool ForceReads; };
    bool read(const IOOptions &opts, int &x);
    template bool read<>(int &);
    Copy to clipboard

According to the standard, types that do not depend on template
parameters must be complete when a template is defined if they affect
the program’s behavior. However, the standard also says that
compilers are free to not enforce this rule. Most compilers enforce
it to some extent; for example, it would be an error in GCC to write
opts.ForceReads in the code example.

In LLVM, the decision to enforce the rule consistently provides a
better experience, but unfortunately, it also results in some code
that is rejected when other compilers will accept it.

### Templates with no valid instantiations

The following code contains a typo: `innit()` was written instead of
`init()`.

template <class T> class Processor {
       ...
       void init();
       ...
    };
    ...
    template <class T> void process() {
       Processor<T> processor;
       processor.innit(); // <-- should be 'init()'
       ...
    }
    Copy to clipboard

Unfortunately, the compiler cannot flag this mistake as soon as it
detects it. Inside a template, assumptions cannot be made about
dependent types such as Processor&lt;T&gt;. Suppose that later in this file
you add an explicit specialization of Processor, like the following
example:

template <> class Processor<char\*> {
       void innit();
    };
    Copy to clipboard

The program will work, but only if you instantiate process() with T =
char\*. Therefore, it is hard, and sometimes impossible, to diagnose
mistakes in a template definition before it is instantiated.

The standard states that a template with no valid instantiations is
ill-formed. LLVM tries to do as much checking as possible at
definition time instead of instantiation time; not only does

this produce clearer diagnostics, but it also substantially improves
compile times when using precompiled headers. The downside to this
philosophy is that LLVM sometimes fails to process files because they
contain broken templates that are no longer used. The solution is
simple: because the code is unused, remove it.

### Default initialization of const variable of class type

The default initialization of a const variable of a class type
requires a user-defined default constructor.

If a class or structure has no user-defined default constructor, C++
does not allow you to default-construct a const instance of it. For
example:

class Foo {
    public:
       // The compiler-supplied default constructor works fine, so we
       // don't bother with defining one.
       ...
    }
    void Bar() {
       const Foo foo; // Error!
       ...
    }
    Copy to clipboard

To fix this issue, define a default constructor for the class:

class Foo {
    public:
       Foo() {}
       ...
    };
    void Bar() {
       const Foo foo; // Now the compiler is happy.
       ...
    }
    Copy to clipboard

### Parameter name lookup

Due to a bug in its implementation, GCC allows the redeclaration of
function parameter names within a function prototype in C++ code. For
example:

void f(int a, int a);
    Copy to clipboard

LLVM diagnoses this error (where the parameter name has been
redeclared). To fix this problem, rename one of the parameters.

Last Published: May 10, 2024

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