Migration Guide |
A |
![]() |
This document resides in the
Note - C++ 4.2 object code is not compatible with C++ 3.0 object code, so you must recompile your code, including any libraries, which might contain C++ code. C++ 4.2 object code is compatible with C++ 4.1 and 4.0 object code.
README
directory; it is included in both ASCII and PostScriptTM format. The PostScript file has a .ps suffix.
When writing a compiler, you need hard facts about every aspect of the language, and when you can't find a precise definition, you have to make the best guess you can. The developers chose to follow the ARM whenever it was clear enough, and to use the ongoing work of the ANSI committee, as described in the Draft Working Paper (DWP) to help clarify murky areas. The result is their best guess at what the language will become, but you can expect changes with the next release. Sun is actively involved in the ANSI committee and the entire C++ standardization effort, so the developers are tracking its progress closely.
The compiler supports the entire language described in the ARM, including templates and exceptions. It also includes support for wide characters, including a separate type for wchar_t. SPARCompiler C++ 4.2 is fully integrated with Solaris 2.x internationalization features. There is an extended long integer (long long int) and a true long double type.
Sun is aware that there is a lot of code that compiles with some version of C++ 3.0, but is not legal under the current (or possibly any) language definition. The compiler detects and flags these errors, finding bugs, and generally improving the code quality. However, you have to compile and use your existing code, so the developers have worked very hard to allow such programs to compile, and to flag these incompatibilities with warning messages. Though changes in the language make it impossible to be completely compatible, this compiler is much more backward-compatible than earlier versions of C++ 3.0.
_new_handler
, ld
issues an error that _new_handler
is undefined. Use set_new_handler() to set your own new handler.
extern int foo (int a, int a); |
C++ 4.2 does not allow this.
Error: Global operator new() is always used when there is no class version
Resolution of operator
new()
for nested classes in C++ 4.2 is different from C++ 3.0. C++ 3.0 erroneously uses the operator new()
from the outer class in preference to the global operator
new()
, as specified in the ARM.
C++ 3.0 execution produces "Hi!" while C++ 4.2 produces no output.
Foo::Bar::operator new()
and call Foo::operator new()
from the new function.
typedef
names for structure types. C++ 3.0 treats the typedef
name as a struct
name. For example, you could write:
typedef struct { int x; } A; |
The DWP and ARM state that the second declaration declares a new structure name
A
. This is an error since there is already an existing typedef name A
. The result is:Error: Multiple declaration for A.
These errors show up differently when there are local scopes involved, and interpreting the code the same way as C++ 3.0 can actually change the meaning of a legal program. The following code shows some of the confusion that may arise
Error: The type A is incomplete.
typedef struct { int x; } A; |
The error messages look like this:
line 5: Error: Cannot assign A(local)** to A**.
line 6: Error: The type "A(local)" is incomplete.
line 6: Error: Cannot assign A(local)* to A*.
typedef struct A { int x; } A; |
typedef int TI; |
or, using the same
typedef
class D {
TI TI;
};
Error: Redefining TI after use in C
Both cases are legal in C. C++ 3.0 does not detect this situation at all. C++ 4.2 always detects the situation, and for classes, where the usage could be disastrous, reports an error. For struct
s that use no member functions or other C++ features, the compiler gives a warning.
int (*pfp)(int, char); |
This error is not detected in a direct cast as the right hand side of an assignment, and pointers of type
int(*)(...)
cannot be assigned to other pointers to functions. This bug does not exist in C++ 4.2.
Other Errors
Error: Cannot return int from a function which should return char*
The expression (
anything, 0)
is not a null-pointer constant. For example, the following program results in a compilation error:
int error(); |
class A { }; |
class Foo { |
class Base { public: Base(const Base &); ~Base(); protected: Base(int); }; class Derived : public Base { public: Derived(int i): Base (i) {} static const Base xx; }; const Base Derived::xx(1); |
main()
has always been required to return int
, C++ 3.0 does not enforce this. Programs that return some other type may produce unpredictable results.
main()
so it returns int
.
const
parameters are seldom desirable, the preferred solution is to modify the copy constructor.
extern void f(int, int);
f(1, 2,)
const
type. For example:
extern void f(int&);This is always an error, but was accepted by earlier versions of C++. Even C++ 3.0 missed some cases, so this is a warning rather than a error.
f(1); // called with a non-lvalue
const
in the declaration, or there may be a program logic error.
delete[]
. C++ 4.2 allows this count, but ignores it.
operator
new()
, only to the default version.
class B { D::D(int i) : (i) {} |
D::D(int i) : B(i) {} |
new
() to allocate a const
object without providing an initial value or a default constructor, as shown in the following example:
const int * ip = new const int; |
const int * ip = new const int(0); |
Warning: Temporary used for non-const reference, now obsolete
Earlier versions of C++ allowed the initialization of a non-const
reference with an incompatible type or non-lvalue. This is obsolete now, but causes a warning message. To avoid the warning, check your program logic, and if you want a temporary, make an explicit one. For example, convert
short sv; |
short sv; |
int irtemp = sv; |
Formal argument AAAA of type BBBB is being passed CCCC
or Formal argument AAAA of type BBBB in call to CCCC is being passed DDDD
These warnings indicate that the conversion required to pass the argument is illegal, but that C++ 3.0 did not detect the illegality. Failure to handle const
and volatile
properly on pointers is a major cause of this problem. You can usually correct it with an explicit cast, but the error is probably the result of a logic error. Passing a value of type char**
to a parameter of type const char**
is illegal in both C++ and ANSI C. This is not an error or oversight in the standard as such assignments open a hole in the type system and violate const
safety. It is legal in C++ to pass a value of type const char** to a parameter of type const char* const*.
Other Warnings
Warning: Undefined character escape sequence
The only string or character constant escape sequences which are allowed in C++ are:
const
were involved. Passing a value of type char**
to a parameter of type const
char**
is illegal in both C++ and ANSI C. This is not an error or oversight in the standard as such assignments open a hole in the type system and violate const
safety. It is legal in C++ to pass a value of type const char** to a parameter of type const char* const*.
const
and volatile
properly on pointers is a major cause of this problem. You can usually correct it with an explicit cast, but the error is probably the result of a logic error.
extern int
; is useless and therefore flagged as an anachronism.
Using the Same Names in Base and Derived Classes
C++ 3.0 allows an enumerator name defined in a base class to be used as a derived class name. The following test case compiles without errors with C++ 3.0, but not with C++ 4.2
class foo { public: typedef enum { bar, foobar } footype; }; class bar : public foo { public: bar(); ~bar(); bar(const bar &b); // Error here bar &operator=(const bar &b); // Error here }; |
You can disambiguate the name `bar' in the derived class by using the keyword class, as follows
class foo { public: typedef enum { bar, foobar } footype; }; class bar : public foo { public: bar(); ~bar(); bar(const class bar &b); class bar &operator=(const class bar &b); }; |
Templates
If you are using templates with C++ 3.0, you may notice some differences when you move to C++ 4.2. C++ 3.0 generates (or instantiates) template functions when the program is being linked. A separate processor examines the object and library files, determines which template functions are needed, then uses the compiler to instantiate them. C++ 4.2 instantiates at compile time, generating those template instantiations needed by the module being compiled. Link Order When Using Templates
The 4.0.1 compiler had an error in constructing the link line when templates were involved. In these cases, the old compiler would automatically place archives at the end of the supplied (and inserted template) object files. This could have unknown consequences when link order was important. The new compiler leaves the link order exactly as supplied, and only inserts template object files before the first non-object file (such as archives or shared library). Specialization Registration
A specialization of a template is a user-defined version of a template that is normally generated by the compilation system. For example, for the template function:
template <class T> T foo ( T data ); |
int foo ( int data ); |
special foo(int); |
The information needed to properly handle specializations of templates is covered in depth in the C++ User's Guide.
Template Repositories
Generated templates and their supporting files are stored in a directory, the template database. Except for the options file, all the files in the database are object files and state information files, maintained by the compiler. The difference between using the template database in C++ 4.2 versus C++ 3.0 is: when you use the -ptr
option to specify the template database path, the path includes the database, named Templates.DB
. For example:-ptrMyDatabase
corresponds to a database located in ./MyDatabase.
-ptrMyDatabase
corresponds to a database located in ./MyDatabase/Templates.DB
. Central Database
You can use a central database to store generated templates. Do this by using the -ptr
command-line directive to specify the location of your database. The inherent problem with a central database is that dependencies, types, and environmental data can change between executables sharing a common template and template database. Changes can lead to confusion, strange behavior at runtime, and missing data in the database. Template objects and dependencies in the relevant state-information files are based on template and type names. Because of potential conflicts between targets and violations of the one-definition rule, using templates across multiple targets may lead to unexpected behavior. Multiple Databases
The template sources used during instantiation must be locatable from the directory where the referencing module is compiled. Use multiple databases by specifying multiple -ptr
options on the command line. The first -ptr
option is the writable template database. Whenever multiple databases are involved, specify -ptr
as the first -ptr
option. See the C++ User's Guide for details.
Placing Objects in Shared Memory
Placing objects with virtual functions into shared memory requires that the virtual tables needed by those objects be at the same virtual address in all tasks that refer to the objects. To achieve this, control virtual table generation using the +e0
and +e1
command-line flags. +e0
prevents generation of virtual tables. +e1
generates virtual tables for every class defined in that compilation unit. Follow these steps:
-noex
as well as +e1.
For example, assume that you have header files
type1.h
and type2.h
, and that all classes used within the program are defined in one of those files. You can compile most of the program using:
CC -c +e0 a.cc b.cc ... |
and create a file vt.cc
containing:
|
CC -c +e1 -noex vt.cc |
The file
vt.o
contains the virtual tables needed by the program.-noex
option on the CC
command line.