3 LANGUAGE IMPLEMENTATION

This chapter contains the following sections:

Introduction
C++ Language Extension Keywords
C++ Dialect Accepted
New Language Features Accepted
New Language Features Not Accepted
Anachronisms Accepted
Extensions Accepted in Normal C++ Mode
Extensions Accepted in Cfront 2.1 Compatibility Mode
Extensions Accepted in Cfront 2.1 and 3.0 Compatibility Mode
Namespace Support
Template Instantiation
Automatic Instantiation
Instantiation Modes
Instantiation #pragma Directives
Implicit Inclusion
Predefined Macros
Precompiled Headers
Automatic Precompiled Header Processing
Manual Precompiled Header Processing
Other Ways to Control Precompiled Headers
Performance Issues

3.1 Introduction

The TASKING C++ compiler ( cp563) offers a new approach to high-level language programming for the DSP56xxx family. The C++ compiler accepts the C++ language as defined by the ISO/IEC 14882:1998 standard, with the exceptions listed in section 3.3 . It also accepts the language extensions of the C compiler.

This chapter describes the C++ language extensions and some specific features.

3.2 C++ Language Extension Keywords

The C++ compiler supports the same language extension keywords as the C compiler. These language extensions are enabled by default (--embedded), but you can disable them by specifying the --no_embedded command line option. When -A is used, the extensions will be disabled.

The following language extensions are supported:

additional data types

In addition to the standard data types, cp563 supports the fractional type (_fract), long fractional type (long _fract), enumerated type (enum) and complex data type (_complex).

_at

You can specify a variable to be at an absolute address.

_nosat

You can specify a variable to wrap around instead of going into saturation during calculations.

storage specifiers

Apart from a memory category (extern, static, ...) you can specify a storage specifier in each declaration. This way you obtain a memory model-independent addressing of variables in several address ranges (_X, _Y, _L, _P, _near, _internal, _external). The _near, _internal and _external modifiers can also be used on functions to force them in a specific memory region.

reentrant functions

In the mixed model (DSP5600x only) you can selectively define functions as reentrant (_reentrant keyword). Reentrant functions can be invoked recursively. Interrupt programs can also call reentrant functions.

interrupt functions

You can specify interrupt functions directly through interrupt vectors in the C language (_fast_interrupt, _long_interrupt keyword).

inline C functions

You can specify to inline a function body instead of calling the function by using the _inline keyword.

special calling conventions

With the _compatible keyword you can specify that a function must have the same calling convention as the Motorola C compiler. The _callee_save keyword can be used to indicate that a function must save all registers, instead of leaving this to the caller.

circular buffers

cp563 supports the type modifier _circ for circular data structures and pointers.

intrinsic functions

A number of pre-declared functions can be used to generate inline assembly code at the location of the intrinsic (built-in) function call. This avoids the overhead which is normally used to do parameter passing and context saving before executing the called function.

pragmas

The C++ compiler supports the same pragmas as the C compiler. Pragmas give directions to the code generator of the compiler.

All of the language extensions mentioned above are described in detail in the C Cross-Compiler User's Guide.

3.3 C++ Dialect Accepted

The C++ compiler accepts the C++ language as defined by the ISO/IEC 14882:1998 standard, with the exceptions listed below.

The C++ compiler also has a cfront compatibility mode, which duplicates a number of features and bugs of cfront 2.1 and 3.0.x. Complete compatibility is not guaranteed or intended; the mode is there to allow programmers who have unwittingly used cfront features to continue to compile their existing code. In particular, if a program gets an error when compiled by cfront, the C++ compiler may produce a different error or no error at all.

Command line options are also available to enable and disable anachronisms and strict standard-conformance checking.

3.3.1 New Language Features Accepted

The following features not in traditional C++ (the C++ language of "The Annotated C++ Reference Manual" by Ellis and Stroustrup (ARM)) but in the standard are implemented:

3.3.2 New Language Features Not Accepted

The following features of the C++ standard are not implemented yet:

3.3.3 Anachronisms Accepted

The following anachronisms are accepted when anachronisms are enabled (with --anachronisms):

3.3.4 Extensions Accepted in Normal C++ Mode

The following extensions are accepted in all modes (except when strict ANSI violations are diagnosed as errors):

3.3.5 Extensions Accepted in Cfront 2.1 Compatibility Mode

The following extensions are accepted in cfront 2.1 compatibility mode in addition to the extensions listed in the 2.1/3.0 section following (i.e., these are things that were corrected in the 3.0 release of cfront):

- A member in a base class must have the same name as an identifier at the global scope. The member may be a function, static data member, or non-static data member. Member type names do not apply because a nested type will be promoted to the global scope by cfront which disallows a later declaration of a type with the same name at the global scope.

- The declaration of the global scope name must occur between the declaration of the derived class and the declaration of an out-of-line constructor or destructor. The global scope name must be a type name.

- No other member function definition, even one for an unrelated class, may appear between the destructor and the offending reference. This has the effect that the nonstandard lookup applies to only one class at any given point in time. For example:

3.3.6 Extensions Accepted in Cfront 2.1 and 3.0 Compatibility Mode

The following extensions are accepted in both cfront 2.1 and cfront 3.0 compatibility mode (i.e., these are features or problems that exist in both cfront 2.1 and 3.0):

Protected member access checking for other operations (i.e., everything except taking a pointer-to-member address) is done in the normal manner.

3.4 Namespace Support

Namespaces are enabled by default except in the cfront modes. You can use the command-line options --namespaces and --no_namespaces to enable or disable the features.

Name lookup during template instantiations now does something that approximates the two-phase lookup rule of the standard. When a name is looked up as part of a template instantiation but is not found in the local context of the instantiation, it is looked up in a synthesized instantiation context. The C++ compiler follows the new instantiation lookup rules for namespaces as closely as possible in the absence of a complete implementation of the new template name binding rules. Here is an example:

The lookup of names in template instantiations does not conform to the rules in the standard in the following respects:

The lookup rules for overloaded operators are implemented as specified by the standard, which means that the operator functions in the global scope overload with the operator functions declared extern inside a function, instead of being hidden by them. The old operator function lookup rules are used when namespaces are turned off. This means a program can have different behavior, depending on whether it is compiled with namespace support enabled or disabled:

3.5 Template Instantiation

The C++ language includes the concept of templates. A template is a description of a class or function that is a model for a family of related classes or functions.1

1 Since templates are descriptions of entities (typically, classes) that are parameterizable according to the types they operate upon, they are sometimes called parameterized types. ))> For example, one can write a template for a Stack class, and then use a stack of integers, a stack of floats, and a stack of some user-defined type. In the source, these might be written Stack<int>, Stack<float>, and Stack<X>. From a single source description of the template for a stack, the compiler can create instantiations of the template for each of the types required.

The instantiation of a class template is always done as soon as it is needed in a compilation. However, the instantiations of template functions, member functions of template classes, and static data members of template classes (hereafter referred to as template entities) are not necessarily done immediately, for several reasons:

(It should be noted that certain template entities are always instantiated when used, e.g., inline functions.)

From these requirements, one can see that if the compiler is responsible for doing all the instantiations automatically, it can only do so on a program-wide basis. That is, the compiler cannot make decisions about instantiation of template entities until it has seen all the source files that make up a complete program.

This C++ compiler provides an instantiation mechanism that does automatic instantiation at link time. For cases where you want more explicit control over instantiation, the C++ compiler also provides instantiation modes and instantiation pragmas, which can be used to exert fine-grained control over the instantiation process.

3.5.1 Automatic Instantiation

The goal of an automatic instantiation mode is to provide painless instantiation. You should be able to compile source files to object code, then link them and run the resulting program, and never have to worry about how the necessary instantiations get done.

In practice, this is hard for a compiler to do, and different compilers use different automatic instantiation schemes with different strengths and weaknesses:


Copyright © 2002 Altium BV