ARM Technical Support Knowledge Articles

Which GNU language extensions are supported by the ARM Compiler?

Applies to: DS-5, RealView Development Suite (RVDS)

Answer

The ARM Compiler supports several extensions to the C language that are also supported by the GNU C compiler.  The extensions are:

Most of these extensions are only available in GNU mode. To compile in GNU mode, use the --gnu compiler command line option.  Some extensions are only available in a subset of the supported language modes (C90, C99 and C++).  The supported modes are detailed in each section below.


Alternate keywords

Alternate keywords are a GNU language extension to the default C90 implementation of the C language used by the compiler tools. The ARM compiler recognizes keywords of the form __keyword__. These alternate keywords have the same behavior as the original keywords.

Example:

__const__ float pi = 3.14f; // Same as const float pi = 3.14f

Supported modes: GNU C90, GNU C99, GNU C++.


The asm keyword

The ARM compiler supports the asm keyword as a GNU language extension to the default C90 implementation of the C language.

Use of this keyword in C mandates the use of the --gnu compiler command-line option. However, in C++, it is part of the language.

Supported modes: Standard C++, GNU C90, GNU C++.


Case ranges

The ARM compiler supports ranges of values in switch statements as a GNU extension to the default C90 implementation of the C language and as an extension to the C99 and C++ languages.

Example:

int Case_Ranges_0(int arg)
{
    int aLocal;
    int bLocal =arg;
    switch (bLocal)
    {
        case 0 ... 10:
            aLocal= 1;
            break;
        case 11 ... 100:
            aLocal =2;
            break;
        default:
            aLocal=-1;
    }
    return aLocal;
}

Supported modes: GNU C90, GNU C99, GNU C++.


Labels as values

The ARM compiler supports GCC labels as values using the && operator. This support is provided as a GNU extension to the default C90 implementation of the C language and as an extension to the C99 and C++ languages.

Examples:

A table of labels:

int f(int n)
{
    void *const table[] = { &&a1, &&a2};
    goto *table[n];
a1: return 1;
a2: return 2;
}

A label used for continuation:

void *toggle(void *lab, int *x)
{
    if (lab) goto *lab;
a1: *x = 1; return &&a2;
a2: *x = 0; return &&a1;
} 

Supported modes: GNU C90, GNU C99, GNU C++.


Pointer arithmetic

The ARM compiler supports arithmetic on void pointers and function pointers. This support is provided as a GNU extension to the default C90 implementation of the C language and as an extension to the C99 language.

Example:

int ptr_arith_0(void)
{
    void * pointer;
    return sizeof *pointer;
}
int ptr_arith_1(void)
{
    static int diff;
    diff = ptr_arith_0 - ptr_arith_1;
    return sizeof ptr_arith_0;
}

Supported modes: GNU C90, GNU C99.


Zero-length arrays

The ARM compiler supports zero-length arrays as a GNU extension to the default C90 implementation of the C language and as an extension to the C99 language.

Example:

struct string {
    int string_length;
    char characters[0]; /* string contents are optional and can vary in length */
};

void foo(int this_string_len)
{
    struct string *this_string = (struct string *)malloc(sizeof (struct string) + this_string_len);

    this_string->string_length = this_string_len;
    ...
}

Supported modes: GNU C90, GNU C99.


Access to unnamed embedded structures or unions

When embedding a structure or union within another structure or union, you do not have to name the internal structure. You can access the contents of the unnamed structure without using a name to reference the structure. The ARM compiler provides this functionality as a GNU language extension to the default C90 implementation of the C language and as an extension to the C99 and C++ languages.

Unnamed fields are the same as anonymous unions and structures.

Example:

struct
{
    int a;
    union
    {
      int b;
      float c;
    };
    int d;
} Unnamed_Fields_0;

int Unnamed_Fields_1()
{
    return Unnamed_Fields_0.b;
}

Supported modes: GNU C90, GNU C99, GNU C++.


Union casts

The ARM compiler supports union casts as a GNU extension to the default C90 implementation of the C language and as an extension to the C99 language.

A cast to a union type is similar to other casts, except that the type specified is a union type. You can specify the type either with a union tag or with a typedef name.

Example:

typedef union
{
    double d;
    int i;
} foo_t;
int Cast_to_Union_0(int a, double b)
{
    foo_t u;
    if (a>100)
        u = (foo_t) a ; // automatically equivalent to u.i=a;
    else
        u = (foo_t) b ; // automatically equivalent to u.d=b;
    return u.i;
}

Supported modes: GNU C90, GNU C99.


Compound literals

The ARM compiler supports compound literals as a GNU extension to the default C90 implementation of the C language and as an extension to the C99 language. All compound literals are lvalues.

The compiler is more relaxed about which compound literals it accepts as initializers in GNU mode than it is when compiling strict Standard C99 source code.

Example:

int y[] = (int []) {1, 2, 3}; // error in strict C99, okay in C99 --gnu
int z[] = (int [3]) {1};

Supported modes: Standard C99, GNU C90, GNU C99, GNU C++.


Designated initializers

The ARM compiler supports designated initializers as a GNU extension to the default C90 implementation of the C language and as an extension to the C99  and C++ languages. 

Example:

int a[6] = { [4] = 29, [2] = 15 };
int b[6] = { 0,0,15,0,29,0 }; // a[] is equivalent to b[]

Supported modes: Standard C99, GNU C90, GNU C99, GNU C++.


Extended lvalues

The definition of what constitutes an lvalue when looking at comma expressions and ?: constructs is relaxed in GNU mode. You can use compound expressions, conditional expressions, and casts as follows:

Note: Although this type of programming is possible, it is not normally recommended.

These extended lvalues are only accepted in some modes, and for some values of --gnu_version.

--gnu is mandatory for C, but not for C++. This is because in C++, these lvalues are permitted by the ISO/IEC standard for C++, but in C can only be used as extensions to the Standard C.

Supported modes: Standard C++, GNU C90, GNU C99, GNU C++.


Aggregate initializer elements for automatic variables

The elements of an aggregate initializer for an automatic variable are not required to be constant expressions in GNU mode. This functionality is supported as a GNU extension to the default C90 implementation of the C language. 

Example:

float Initializers_0 (float f, float g)
{
    float beat_freqs[2] = { f-g, f+g };
    float aLocal;
    int i=0;
    for (; i<2; i++)
        aLocal += beat_freqs[i];
    return aLocal;
}

Supported modes: Standard C99, Standard C++, GNU C90, GNU C99, GNU C++.


Escape sequence '\e' for the escape character

In GNU mode, the ARM compiler accepts the escape sequence '\e' for the escape character <ESC> (ASCII 27), in strings.

Example:

void foo(void)
{
    printf("Escape sequence is: \e\n");
}

Supported modes: GNU C90, GNU C99, GNU C++.


Conditional statements with omitted operands

In GNU mode, the middle operand in a conditional statement can be omitted if the result is to be the same as the test.

Examples:

The following statements are equivalent:

c = i ? : j; // middle operand omitted
c = i ? i : j;
if (i) c = i; else c = j; // expanded in full

This is most useful if the test modifies the value in some way, for example:

i++ ? : j;

where i++ comes from a macro. If you write code in this way, then i++ is evaluated only once.

If the original value of i is nonzero, the result is the original value of i. Regardless of this, i is incremented once.

Supported modes: GNU C90, GNU C99, GNU C++.


Inline functions

The inline function qualifier is a hint to the ARM compiler that the function is to be inlined.

static inline foo (){...}
foo is used internally to the file, and the symbol is not exported.

inline foo(){...}
foo is used internally to the file and an out of line version is made available and the name foo exported.

extern inline foo (){...}
In GNU mode, foo is used internally if it is inlined. If it is not inlined then an external version is referenced rather than using a call to the internal version. Also, the foo symbol is not emitted.

In non-GNU mode, extern is ignored and the functionality is the same as inline foo() for C++. In C, you must use __inline.

If you are using DS-5, see Extern inline functions in the ARM Compiler toolchain, Compiler Reference manual.

If you are using RVDS, see Extern inline functions in ARM C++ in the ARM Compiler toolchain, armcc User Guide.

Supported modes: Standard C99, Standard C++, GNU C90, GNU C99, GNU C++.


Statement expressions

Statement expressions enable you to place whole sections of code, including declarations, within braces({ }).

The result of a statement expression is the final item in the statement list.

Restrictions:

Branches into a statement expression are not allowed.

In C++ mode, branches out are also not allowed. Variable-length arrays, destructible entities, try, catch, local non-POD class definitions, and dynamically initialized local static variables are not permitted inside a statement expression.

Example:

int bar(int b, int foo)
{
    if (({
           int y = foo;
           int z;
           if (y > 0) z = y;
           else z = -y;
           z>b;
         }))
    b++;
    return b;
}

Supported modes: GNU C90, GNU C99, GNU C++.

--gnu

Article last edited on: 2014-02-10 15:00:13

Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential