- Type qualifiers on the this parameter may to be dropped
in contexts such as this example:
struct A {
void f() const;
};
void (A::*fp)() = &A::f;
This is actually a safe operation.
A pointer to a const function may be put into a pointer to
non-const, because a call using the pointer is permitted to
modify the object and the function pointed to will actually not
modify the object. The opposite assignment would not be safe.
- Conversion operators specifying conversion to void are
allowed.
- A nonstandard friend declaration may introduce a new type.
A friend declaration that omits the elaborated type specifier
is allowed in default mode, but in cfront mode the declaration
is also allowed to introduce a new type name.
struct A {
friend B;
};
- The third operand of the "?" operator is a conditional
expression instead of an assignment expression as it is in the
current X3J16/WG21 Working Paper.
- A reference to a pointer type may be initialized from a pointer
value without use of a temporary even when the reference pointer
type has additional type qualifiers above those present in the
pointer value. For example,
int *p;
const int *&r = p; // No temporary used
- A reference may be initialized with a null.
- Because cfront does not check the accessibility of types,
access errors for types are issued as warnings instead of errors.
- When matching arguments of an overloaded function, a const
variable with value zero is not considered to be a null pointer
constant. In general, in overload resolution a null pointer constant
must be spelled "0" to be considered a null pointer
constant (e.g., '\0' is not considered a null pointer constant).
- No warning is issued when an operator()() function has
default argument expressions.
- An alternate form of declaring pointer-to-member-function
variables is supported, namely:
struct A {
void f(int);
static void sf(int);
typedef void A::T3(int); // nonstd typedef decl
typedef void T2(int); // std typedef
};
typedef void A::T(int); // nonstd typedef decl
T* pmf = &A::f; // nonstd ptr-to-member decl
A::T2* pf = A::sf; // std ptr to static mem decl
A::T3* pmf2 = &A::f; // nonstd ptr-to-member decl
where
T is construed to name a routine type for a nonstatic member
function of class A that takes an int argument and returns
void; the use of such types is restricted to nonstandard pointer-to-member
declarations. The declarations of T and pmf in combination
are equivalent to a single standard pointer-to-member declaration:
void (A::* pmf)(int) = &A::f;
A nonstandard pointer-to-member
declaration that appears outside of a class declaration, such
as the declaration of T, is normally invalid and would cause
an error to be issued. However, for declarations that appear within
a class declaration, such as A::T3, this feature changes the
meaning of a valid declaration. cfront version 2.1 accepts declarations,
such as T, even when A is an incomplete type; so this
case is also excepted.
- Protected member access checking is not done when the address
of a protected member is taken. For example:
class B { protected: int i; };
class D : public B { void mf(); };
void D::mf() {
int B::* pmi1 = &B::i; // error, OK in cfront mode
int D::* pmi2 = &D::i; // OK
}
Note that protected member access checking for other operations
(i.e., everything except taking a pointer-to- member address)
is done in the normal manner.
- The destructor of a derived class may implicitly call the
private destructor of a base class. In default mode this is an
error but in cfront mode it is reduced to a warning. For example:
class A {
~A();
};
class B : public A {
~B();
};
B::~B(){} // Error except in cfront mode
- When disambiguation requires deciding whether something is
a parameter declaration or an argument expression, the pattern
type-name-or-keyword(identifier...) is treated
as an argument. For example:
class A { A(); };
double d;
A x(int(d));
A(x2);
By default int(d) is interpreted as a parameter
declaration (with redundant parentheses), and so x is a function;
but in cfront-compatibility mode int(d) is an argument and
x is a variable.
The declaration A(x2); is also misinterpreted
by cfront. It should be interpreted as the declaration of an object
named x2, but in cfront mode is interpreted as a function
style cast of x2 to the type A.
Similarly, the declaration
int xyz(int());
declares a function named xyz, that
takes a parameter of type "function taking no arguments and
returning an int." In cfront mode this is interpreted
as a declaration of an object that is initialized with the value
int() (which evaluates to zero).
- A named bit-field may have a size of zero. The declaration
is treated as though no name had been declared.
- Plain bit fields (i.e., bit fields declared with a type of
int) are always unsigned.
- The name given in an elaborated type specifier is permitted
to be a typedef name that is the synonym for a class name,
e.g.,
typedef class A T;
class T *pa; // No error in cfront mode
- No warning is issued on duplicate size and sign specifiers.
short short int i; // No warning in cfront mode
- Virtual function table pointer update code is not generated
in destructors for base classes of classes without virtual functions,
even if the base class virtual functions might be overridden in
a further-derived class. For example:
struct A {
virtual void f() {}
A() {}
~A() {}
};
struct B : public A {
B() {}
~B() {f();} // Should call A::f according to ARM 12.7
};
struct C : public B {
void f() {}
} c;
In cfront compatibility mode, B::~B calls C::f.
- An extra comma is allowed after the last argument in an argument
list, as for example in
f(1, 2, );
- A constant pointer-to-member-function may be cast to a pointer-to-function.
A warning is issued.
struct A {int f();};
int main () {
int (*p)();
p = (int (*)())A::f; // Okay, with warning
return 0;
}
- Arguments of class types that allow bitwise copy construction
but also have destructors are passed by value (i.e., like C structures),
and the destructor is not called on the "copy." In normal
mode, the class object is copied into a temporary, the address
of the temporary is passed as the argument, and the destructor
is called on the temporary after the call returns. Note that because
the argument is passed differently (by value instead of by address),
code like this compiled in cfront mode is not calling-sequence
compatible with the same code compiled in normal mode. In practice,
this is not much of a problem, since classes that allow bitwise
copying usually do not have destructors.
- A union member may be declared to have the type of a class
for which the user has defined an assignment operator (as long
as the class has no constructor or destructor). A warning is issued.
- When an unnamed class appears in a typedef declaration,
the typedef name may appear as the class name in an elaborated
type specifier.
typedef struct { int i, j; } S;
struct S x; // No error in cfront mode
- Two member functions may be declared with the same parameter
types when one is static and the other is nonstatic with a function
qualifier.
class A {
void f(int) const;
static void f(int); // No error in cfront mode
};
- The scope of a variable declared in the for-init-statement
is the scope to which the for statement belongs.
int f(int i) {
for (int j = 0; j < i; ++j) { /* ... */ }
return j; // No error in cfront mode
}
- Function types differing only in that one is declared extern
"C" and the other extern "C++" can be
treated as identical:
typedef void (*PF)();
extern "C" typedef void (*PCF)();
void f(PF);
void f(PCF);
PF and PCF are considered identical and
void f(PCF) is treated as a compatible redeclaration of f.
(By contrast, in standard C++ PF and PCF are different
and incompatible types - PF is a pointer to an extern "C++"
function whereas PCF is a pointer to an extern "C"
function - and the two declarations of f create an overload
set.)
It is possible in cfront-compatibility mode an implicit
type conversion will always be done between a pointer to an extern
"C" function and a pointer to an extern "C++"
function. This extension would have to be enable via a custom
porting arrangement.
- Functions declared inline have internal linkage.
(c)© 1997-2013 Comeau Computing, EDG. All rights reserved.