9. Configuration for expressions

  1. 9.1. Cast expressions
  2. 9.2. Initialiser expressions
  3. 9.3. Lvalue expressions

9.1. Cast expressions

ISO C++ introduces the constructs static_cast, const_cast and reinterpret_cast, which can be used in various contexts where an old style explicit cast would previously have been used. By default, an explicit cast can perform any combination of the conversions performed by these three constructs. To aid migration to the new style casts the directives:

#pragma TenDRA++ explicit cast as cast-state allow
#pragma TenDRA++ explicit cast allow

where cast-state is defined as follows:

cast-state :
			static_cast
			const_cast
			reinterpret_cast
			static_cast | cast-state
			const_cast | cast-state
			reinterpret_cast | cast-state

can be used to restrict the conversions which can be performed using explicit casts. The first form sets the interpretation of explicit cast to be combinations of the given constructs; the second resets the interpretation to the default. For example:

#pragma TenDRA++ explicit cast as static_cast | const_cast allow

means that conversions requiring reinterpret_cast (the most unportable conversions) will not be allowed to be performed using explicit casts, but will have to be given as a reinterpret_cast construct. Changing allow to warning will also cause a warning to be issued for every explicit cast expression.

9.2. Initialiser expressions

C, but not C++, only allows constant expressions in static initialisers. The directive:

#pragma TenDRA variable initialization allow

can be enable support for C++-style dynamic initialisers. Conversely, it can be used in C++ to detect such dynamic initialisers.

In older dialects of C it was not possible to initialise an automatic variable of structure or union type. This can be checked for using the directive:

#pragma TenDRA initialization of struct/union (auto) allow

The directive:

#pragma TenDRA++ complete initialization analysis on

can be used to check aggregate initialisers. The initialiser should be fully bracketed (i.e. with no elision of braces), and should have an entry for each member of the structure or array.

9.3. Lvalue expressions

C++ defines the results of several operations to be lvalues, whereas they are rvalues in C. The directive:

#pragma TenDRA conditional lvalue allow

is used to apply the C++ rules for lvalues in conditional (?:) expressions.

Older dialects of C++ allowed this to be treated as an lvalue. It is possible to enable support for this dialect feature using the directive:

#pragma TenDRA++ this lvalue allow

however it is recommended that programs using this feature should be modified.

The ? operator cannot normally be used to define an lvalue, so that for example, the program:

struct s {
    int a, b;
};

void f ( int n, struct s *s1, struct s *s2 )
{
    ( n ? s1 : s2) -> a = 0;
}

is not allowed in ISO C. The pragma:

#pragma TenDRA conditional lvalue allow

allows conditional lvalues if:

  • Both options of the conditional operator have compatible compound types;

  • Both options of the conditional are lvalues.

(there is also a disallow variant, but warning is not permitted in this case).