# 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 POD 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 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' 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 template 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' 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<<. 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<<. 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<< 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 struct Base { void DoThis(T x) {} static void DoThat(T x) {} }; template struct Derived : public Base { 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<T> 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->: 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::DoThis(x); Base::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 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 Processor { ... void init(); ... }; ... template void process() { Processor 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<T>. Suppose that later in this file you add an explicit specialization of Processor, like the following example: template <> class Processor { 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)