search    
Hewlett-Packard
Migrating from HP C++ (cfront) to HP aC++

This section discusses differences in syntax and functionality that you need to consider when migrating from HP C++ (cfront) to HP aC++.

It discusses the following topics:

General Guidelines for Migration

Because of incompatibilities in areas such as name mangling, libraries, and object layout, all of your C++ code for an application or library must be compiled and linked with either HP C++ (cfront) or with HP aC++. You cannot mix object files compiled with HP C++ (cfront) with those compiled with HP aC++.

This section discusses the following general guidelines when migrating from HP C++ (cfront) to HP aC++:


Getting Started with Migration

Complete the following procedure to migrate your code from HP C++ (cfront) to HP aC++:

  1. Compile your code with the HP C++ (cfront) compiler using the +p option. This option requests the compiler to treat anachronistic constructs as errors. Fix the anachronisms.
    For example:
    CC +p cfrontfile.C
  2. In your Makefiles:
    • Change CC to aCC.
    • Set the path to /opt/aCC/bin.
    • Review command-line options and change when necessary.
  3. Compile and fix syntax errors.
    • Note that cfront-generated object code and libraries are not compatible with those produced by aCC.
    • If your program uses operator new, allow for memory allocation exceptions that may occur. Modify your cfront code to handle memory allocation failures to avoid a program abort.
  4. Make library changes. Begin migration to the Standard C++ Library and Tools.h++ Library.
  5. Make template changes.
    • If a program or library uses templates, consider source code changes that may be required to direct template instantiation.
    • Use the +inst_directed option with the initial compilation to defer consideration of compile-time errors due to template instantiation.


Writing Code for both Compilers

Use the __cplusplus macro (defined by the draft standard) to write code that can be compiled by both HP C++ and HP aC++.

Example:

#if __cplusplus >= 199707L
// HP aC++ code
#else
// HP C++ code
#endif // __cplusplus >= 199707L


Explicit Loading and Unloading of Shared Libraries

HP aC++ uses system calls rather than C++ function calls to explicitly load and unload shared libraries. When migrating to HP aC++, make the following source code changes:

  • Change cxxshl_load() to shl_load().
  • Change cxxshl_unload() to shl_unload().
  • Change #include to #include <dl.h>.


Memory Allocation

See Memory Allocation Failure and operator new for more information.

Command-Line Differences

In HP aC++, you invoke the compiler with the aCC command instead of the CC command used to invoke HP C++.

The following sections describe differences in command-line options:


New Command-Line Options

The following table describes the new options for HP aC++. These options are not available for HP C++ (cfront). However, if a related option exists, it is noted here.

Option Description
-g0 Replaces the -g debugger option. It generates complete debug information for the debugger.
+help Invokes the HP aC++ Online Programmer’s Guide.
+noeh

Disables exception handling. In HP aC++, exception handling is enabled by default.

In HP C++ (cfront), exception handling is disabled by default. To enable it, use the +eh option, which is obsolete in HP aC++.

Precompiled Header File Options Reduces compilation time and executable file size by precompiling common include (header) files.
Template Options

There are new options and new functionality for template processing.

For more information about HP aC++ templates, see Using HP aC++ Templates.

See Command-Line Options for a complete list of HP aC++ command-line options.


Obsolete Command-Line Options

The following table describes obsolete command-line options for HP aC++.

Option Description
Debugging Option
-y In HP C++ (cfront), the -y option generates a Static Analysis database if SoftBench is installed and /opt/softbench/bin is at the beginning of your path. The option is not required in HP aC++.
Exception Handling Option
+eh

Enables exception handling in HP C++.

In HP aC++, exception handling is enabled by default. To disable exception handling off, compile with the +noeh option

.
Library Option
-depth

In HP C++, this option instructs runtime system to traverse the shared library list in a depth-first manner when calling static constructors and when loading the libraries. The default is to traverse the shared libraries in a left-to-right order when calling static constructors. The order of execution of static constructors within each shared library is not affected by this option.

In HP aC++, -depth functionality is the default option.

Preprocessor Options
-Ac

Requests the compatibility mode HP C++ preprocessor, cpp. This option is not available in HP aC++.

-C

Prevents the preprocessor from stripping comments from your source file. In HP aC++ comments are retained.

-Wp

The -W option no longer accepts p as a subprocess parameter. In HP aC++, there is no separate subprocess for the preprocessor.

Use the CC command (HP C++) as a workaround:

Example:
CC prog.C -I /opt/aCC/include -I /opt/aCC/include/iostream -I /usr -I /usr/include

See Migration Considerations Related to Preprocessing for more information.

Template Options
-pta Instantiates all members of used template classes and all needed template functions.
-ptb Invokes ld instead of nm to do simulated linking.
-pth Uses short file names for template instantiation files.
-ptH"list" Specifies file name extensions for template declaration files (header files).
-ptn Instantiates at link time rather than at compile time.
-ptrpath Specifies an alternate location for the template repository.
-pts Splits template instantiations into separate object files.
-ptS"list" Specifies file name extensions for template definition files.
-ptv Provides verbose information about template processing. For HP aC++, use the +inst v option.
Translator Mode Options
+a0 Causes the translator to produce Classic C style declarations.
+a1 Causes the translator to produce ANSI C style declarations.
-F Runs only the preprocessor and translator, and sends the resulting source code to standard output (stdout).
-Fc Similar to the -F option, except that C source code is generated.
+i Generates an intermediate C language source file that has the file name suffix ..c in the current directory.
+m Provides maximum compatibility with the USL C++ implementation.
+Rnumber Promotes only first number register variables to the register class.
+T Requests translator mode.
+xfile Reads a file of data types, sizes, and alignments that the compiler uses when generating code.
Virtual Table Options
+e0 Causes virtual tables to be external and defined elsewhere, that is, uninitialized.
+e1 Causes virtual tables to be declared externally and defined in a given module, that is initialized.


Changed Command-Line Options

Functionality for the following options is different for HP C++ (cfront) than it is for HP aC++. The following table describes the obsolete command-line options for HP aC++.

Option Description
-E Runs the preprocessor only on named C++ files, not on assembly files, and sends the result to standard output (stdout).
-g

Generates minimal information for the debugger (as does the -g1 option). This is the default option. The -g0 option replaces -g and generates complete debug information for the debugger.

See Debugging Options for more information.

-tx,name

The following values for x are related to translator mode and template subprocesses and are not supported in HP aC++.

  • 0 (zero) - C compiler
  • c - C compiler
  • i - Link-time template processor, c++ptlink
  • m - merge tool, c++merge
  • p - preprocessor
  • P - patch tool, c++patch
  • r - Compile-time template processor, c++ptcomp

-Wx,args

The following values for x are related to translator mode and template subprocesses and are not supported in HP aC++.

  • 0 (zero) - C compiler
  • c - C compiler
  • i - Link-time template processor, c++ptlink
  • m - merge tool, c++merge
  • p - preprocessor
  • P - patch tool, c++patch
  • r - Compile-time template processor, c++ptcomp

Migration Considerations when Debugging

The HP/DDE Debugger supports HP aC++. The HP Symbolic Debugger, xdb, is not supported. Functionality of the -g debugger option has changed. It now generates minimal information for the debugger as does the -g1 option. This is the default.

The -g0 option replaces the -g option and generates full debug information for the debugger.

See Debugging Options for complete information.

Migration Considerations when Using Exception Handling

When migrating exception handling code, the following characteristics of HP aC++ differ from those of HP C++ (cfront):


Exception Handling is the Default

In HP aC++ exception handling is enabled by default. Use the +noeh option to disable exception handling.

With exception handling disabled, the keywords throw and try generate a compiler error. The HP C++ (cfront) compiler, behaves differently; the default is exception handling off. To turn it on, you must use the +eh option.

If your executable throws no exceptions, object files compiled with and without the +noeh option can be mixed freely. However, in an executable that throws exceptions (HP aC++ runtime libraries throw exceptions), you must be certain that no exception is thrown in your application which will unwind through a function compiled without the exception handling option turned on.

In order to prevent this, the call graph for the program must never have calls from functions compiled without exception handling to functions compiled with exception handling (either direct calls or calls made through a callback mechanism). If such calls do exist, and an exception is thrown, the unwinding can cause:

  • non-destruction of local objects (including compiler generated temporaries)
  • memory leaks when destructors are not executed
  • runtime errors when no catch clause is found


Memory Allocation Failure and operator new

In HP aC++ programs, when either operator new ( ) or operator new [ ] cannot obtain a block of storage, a bad_alloc exception results. This is required by the ANSI/ISO C++ International Standard.

In HP C++, memory allocation failures return a null pointer (zero) to the caller of operator new ().

To handle memory allocation failures in HP aC++ and to avoid a program abort, do one of the following:

  • Write try or catch clauses to handle the bad_alloc exception.
  • Use the nothrow_t parameter to specify the type when calling operator new and check for a null pointer.
Example:
operator new (size_t size, const nothrow_t &) throw();
operator new [] (size_t size, const nothrow_t &) throw();
    .
    .
    .
#include 
#include 

class X{};

void foo1() {
 X* xp1 = new(nothrow())X;   // returns 0 when creating a nothrow
                             // object, if space is not allocated
}

void foo2() {
 X* xp2 = newX:              // may throw bad_alloc
}

void main() {
  try {
    foo1();
    foo2();
  }

  catch (bad_alloc) {
    // code to handle bad_alloc
  }
  catch(...) {
    // code to handle all other exceptions
  }
}


Possible Differences when Exiting a Signal Handler

Behavior when exiting a signal handler through a throw may differ between the two compilers.

In HP aC++, a try block begins following the first call after the try keyword. This conforms to the standard that a legal exception cannot be thrown prior to the first call. The current handlers of try block are considered candidates to catch the exception.

In HP C++, the try keyword defines the beginning of a try block.

In this situation, when a signal is taken while executing between the try keyword and the return point of the first call, a throw from the signal handler does not find the associated handlers as candidates for catching the exception.


Differences in setjmp/longjmp Behavior

Interoperability with setjmp/longjmp is not implemented.

The standard specifies that an implementation need not clean up objects whose lifetimes are shortened by a longjmp:.

The function signature longjmp(jmp_buf jbuf, int val) has more restricted behavior in this International Standard. When automatic objects are destroyed by a thrown exception, transferring control to a destination point in the program, a call to longjmp(jbuf, val) at the throw point transfers control to the destination point results in undefined behavior.


Calling unexpected

Unlike HP C++, in HP aC++, when an unexpected handler wants to exit through a throw, it must throw an exception that is legal according to the exception specification that calls unexpected(), unless that exception specification includes the predefined type bad_exception. If it includes bad_exception, and the type thrown from the unexpected handler is not in the exception specification, then the thrown object is replaced by a bad_exception object and throw processing continues.

The following example is legal in HP C++ but not in HP aC++. You can make the example legal by including the exception header and adding bad_exception to foo’s throw specification. The catch(...) in main will then catch a bad_exception object. This is the only legal way an unexpected-handler can rethrow the original exception.

//     #include <exception<  Needed to make the example legal.

void my_unexpected_handler() { throw; }

void foo() throw() {

//     void foo() throw(bad_exception) {   To make the example legal,
//                                         replace the previous line
//                                         of code with this line.

   throw 1000;
}

int main() {
   set_unexpected( my_unexpected_handler );
   try {
   foo();
   }
catch(...) {
   printf("fail - not legal in aCC\n");
   }
return 0;
}

Following is an example, illegal because my_unexpected_handler rethrows an int. A possible conversion is to throw &x instead, as this is a pointer to int and therefore legal with respect to the original throw specification. Alternatively, you can add bad_exception to the throw specification, as in the prior example.

int x = 1000;

void my_unexpected_handler() { throw; }

void foo() throw( int * ) {
   throw 1000;
}

int main() {
   set_unexpected( my_unexpected_handler );
try {
   foo();
}
catch(...) {
   printf("fail - not legal in aCC\n");
}
return 0;
}


Unreachable catch Clauses

Unreachable catch clauses are diagnosed by HP C++ but not by HP aC++. For example,

class C {
// ...
};

class D : public C {
// ...
};

...

catch(C) {
}
catch(D) {          // Unreachable since previous catch masks this one.
                    // Throw of D will be caught by catch for base class.
}

catch(C * ) {
}
catch(D * ) {       // Unreachable since previous catch masks this one.
                    // Throw of D * will be caught by catch for pointer
                    // to base class.)
}


Throwing an Object having an Ambiguous Base Class

HP C++ generates an object throw error that has an ambiguous base class. In HP aC++, a throw of an object having an ambiguous base class is not caught by a handler for that base, since that would involve a prohibited derived-to-base conversion.

In the following example, the throws are caught by the handlers for D1 and D1*, respectively. The handlers for C are disqualified because C is an ambiguous base class of E:

extern "C" int printf(char*,...);

class C {
public:
C() {};
};

class D1 : public C {
public:
D1() {};
};

class D2 : public C {
public:
D2() {};
};

class E: public D1, public D2 {
public:
E() {};
};

int main() {
E e;
try {
throw e;
}
catch(C) {
printf("caught a C object\n");
}
catch(D1) {
printf("caught a D1 object\n");
}
catch(D2) {
printf("caught a D2 object\n");
}
catch(E) {
printf("caught an E object\n");
}

try {
throw & e;
}
catch(C*) {
printf("caught ptr to C object\n");
}
catch(D1*) {
printf("caught ptr to D1 object\n");
}
catch(D2*) {
printf("caught ptr to D2 object\n");
}
catch(E*) {
printf("caught ptr to E object\n");
}
return 0;
}
Migration Considerations when Using Libraries
The following sections contain information about library migration from HP C++ (cfront) to HP aC++.
Standards Based Libraries

HP aC++ provides the following libraries that are not part of the HP C++ (cfront) compiler:

HP recommends that you use these standards based libraries whenever possible, instead of the cfront compatibility libraries.

See Creating and Using Libraries for more information.


HP C++ (cfront) Compatibility Libraries

HP aC++ provides the following library, whose functionality is part of the HP C++ (cfront) compiler. This library is not Standards based.


IOStream Library

The shared version of this library is located at /usr/lib/hpux##/libstream.so. The archive version is at /usr/lib/hpux##/libstream.a. (## is 32 or 64 - provided as part of the HP-UX core system).

Manpages: The following manpages are located in the /opt/aCC/share/man/man3.Z directory:

  • IOS.INTRO(3C++) - Introduction to the C++ stream library
  • filebuf(3C++) - Buffer for file input and output
  • fstream(3C++) - iostream and streambuf specialized to files
  • ios(3C++) - input/output formatting
  • istream(3C++) - formatted and unformatted input
  • manip(3C++) - iostream manipulators
  • ostream(3C++) - insertion (storing) into a streambuf
  • sbuf.prot(3C++) - interface for derived classes
  • sbuf.pub(3C++) - public interface of character buffering class
  • ssbuf(3C++) - streambuf specialized to arrays
  • stdiobuf(3C++) - iostream specialized to stdio file
  • strstream(3C++) - iostream specialized to arrays

Header Files: Use the following header files with the IOStream library.

  • iostream.h - I/O streams classes ios, istream, ostream, and streambuf
  • fstream.h
  • strstream.h - streambuf specialized to arrays
  • iomanip.h - predefined manipulators and macros
  • stdiostream.h - specialized streams and streambufs for interaction with stdio
  • stream.h - includes iostream.h, fstream.h, stdiostream.h and iomanip.h for compatibility with AT&T USL C++ v 1.2
To direct the compiler to search these header files, enter the following command:
-I/opt/aCC/include/iostream.


Standard Components Library

Use the similar features of the Standard C++ Library in place of the Standard Components Library.

Migration Considerations Related to Preprocessing

The HP C++ (cfront) compiler provides ANSI mode (the default) and K&R compatibility mode preprocessing. HP aC++ preprocessing complies with the ANSI/ISO C++ International Standard. Therefore, if you are migrating from cfront ANSI mode preprocessing to HP aC++, in general, no changes are required.

HP aC++ does not support K&R compatibility mode preprocessing.


Obsolete Preprocessor Options

HP aC++ provides support for ANSI/ISO C++ International Standard preprocessing. Since the standard categorizes support of pre-ISO preprocessing as an anachronism, the ANSI preprocessing options of HP C++ (cfront) are not supported.

For a list of obsolete preprocessor options, see Obsolete Command-Line Options.

Migration Considerations Related to Standardization

The ANSI/ISO C++ International Standard redefines the rules, syntax, and features of C++ language. If your existing code contains any of the standards based keywords as variable names, you must change the variable names when you convert your program to an HP aC++ program.

In addition to keyword changes, there are changes in the following:


C++ Semantics

Following lists the differences in code behavior when you migrate from HP C++ to HP aC++:


Note: These differences can occur inspite of compiling your code without errors.

Implicit Typing of Character String Literals

HP C++ implicitly types character string literals as char *. HP aC++, in accordance with the ANSI/ISO C++ International Standard, types character string literals as const char *. This difference affects function overloading resolution.

Example:
In the following code, HP aC++ calls the first function a; cfront calls the second.

void a(const char *);
void a(char *);

f() {
    a("A_STRING");
    }

To prevent existing code from breaking, assign a string literal to a non-const pointer as shown in the following example:
char *p = "B_STRING";

Also, you cannot convert const char * to char * in a conditional expression in this context.

Example:

char *p = f() ? “A” : “B”;

In such a scenario, you must change the code as in the following example:

const char *p = f() ? “A” : “B”;
or
char *p = const_cast(f() ? “A” : “B”);


Overload Resolution Ambiguity of Subscripting Operator

HP C++ and HP aC++ have different overload resolution models. When you migrate to HP aC++, you may see an overload resolution ambiguity for the subscripting operator. The following code illustrates the problem:

struct String {
   char& operator[](unsigned);
   operator char*();
// ...
};

void f(String &s) {
   s[0] = '0';
}

HP C++ accepts the above code, selecting String::operator[](unsigned) rather than the user-defined conversion, String::operator char*(), followed by the built-in operator[].

Compiling the code with HP aC++ produces the following error:

Error 225: "c.C", line 8 # Ambiguous overloaded function call;
    more than one acceptable function found. Two such functions
    that matched were "char &String::operator [](unsigned int)"
    ["c.C", line 2] and "char &operator [](char *,int)"
    [Built-in operator].
            s[0] = '0';

The error message appears because the compiler cannot choose between:

  1. Not converting s, but converting 0 from type int to type unsigned int; this implies using the user-provided subscript operator[]
  2. Converting s to type char* (using the user-defined conversion operator), but not converting 0; this corresponds to using the built-in subscript operator[].

In order to disambiguate this situation in favor of the user-provided subscript operator[], make the conversion of 0 in alternative (1.) no worse* than the conversion of 0 in alternative (2.).

Because the subscript type for the built-in operator[] is ptrdiff_t (as defined in <stddef.h>), this is also the type that should be used for user-defined subscript operators. Replace the previous example by:

#include <stddef.h>

struct String {
   char& operator[](ptrdiff_t);
   operator char*();
   // ...
};

void f(String &s) {
   s[0] = '0';
}
*worse is relative to a ranking of conversions as described in the ANSI/ISO C++ International Standard on overloading. In general, a user-defined conversion is worse than a standard conversion, which in turn is worse than no conversion at all. The complete rules are more fine grained.


Execution Order of Static Constructors in Shared Libraries

In HP C++ (cfront), static constructors in shared libraries listed on the link-line are executed, by default, in left-to-right order. HP aC++ executes static constructors in depth-first order; that is, shared libraries on which other files depend are initialized first. Use the -depth command-line option on the CC command line for enhanced compatibility with HP aC++.

In addition, HP aC++ reverses the initialization order of .o files on the link-line. To aid in migration, you can group all .o files together and all .so files together.

Example:

aCC file1.o file2.o lib1.so lib2.so lib3.so

In this scenario, cfront would initialize file2.o first, and then file1.o, while HP aC++ initializes file1.o and then file2.o. You must take this into account in your cfront code to avoid link problems with HP aC++.


More Frequent Inlining of Inline Code

HP C++ does not inline some functions even when you request for it. This happens when the function is too complex. If you use the +w option, the compiler displays a message whenever it does not inline a requested function.

HP aC++ almost always inlines functions for which you have specified the inline keyword.


C++ Syntax

When you migrate from HP C++ to HP aC++, in addition to changes related to standards based keywords, you may need to make changes to your source code in the following areas:


Explicit int Declaration

In HP C++, you do not need to explicitly specify int types. In HP aC++, you must explicitly declare int types. This change reduces ambiguity among expressions involving function-like casts and declarations.

Example:

The following code is valid in HP C++:

void f(const parm);
const n = 3;
main()
The equivalent, valid HP aC++ code follows:
void f(const int parm);
const int n = 3;
int main()


for Statement - New Scoping Rules

In HP C++, variables declared in the initializer list are allowed after the for statement. In the ANSI/ISO C++ International Standard, variables declared in the initializer list are not allowed after the for statement. HP aC++ provides this functionality when you specify the following aCC command-line option:

-WC,-ansi_for_scope,on

If you do not specify this option, (or you specify the -WC,-ansi_for_scope,off option), by default, the new rules do not take effect.

In this scenario, HP aC++ provides this standard functionality as an option to ease conversion of existing code to the standard. No code change is currently required. Future plans are to make the ANSI/ISO C++ International Standard syntax the default. HP recommends that you correct your code, by moving the declaration of the for loop variable to its enclosing block.

Example:

The following code currently compiles without errors with HP C++ and HP aC++. In the future, HP aC++, will generate an error.

int main(int argc) {
        for (int i = 1; i < argc; ++i) {
        }
        for (i = 0; i < argc; ++i) {
        }
}
Correct the code as follows:
int main(int argc) {
        int i;
        for (i = 1; i < argc; ++i) {
        }
        for (i = 0; i < argc; ++i) {
        }
}


struct as Template Type Parameter is Permitted

In HP C++, an error is generated when a struct is used as a template type parameter. In HP aC++, when a struct is used as a template type parameter, it is correctly compiled, in accordance with draft standard syntax. This is a new feature.

Example:

template  class A {
public:
struct T a;
};
struct B {};
A b;

The following error is displayed when you compile this code with HP C++:

CC: "DDB4325.C", line 3: error: T of type any redeclared as struct (1479)
This code compiles without error with HP aC++.


Base Template Class Reference Syntax Change

In HP C++, you can reference a member of a base template class without qualifying the member. In HP aC++, when you reference a member of a base template class, you must qualify the member by adding this->.

Adding this-> defers name resolution until instantiation. This allows the compiler to find members in template base classes. However, it prevents the compiler from finding names declared in enclosing scopes.

Example:

template  class BaseT {
public:
  T t;
  int i;
};
template  class DerivedT : public BaseT {
public:
  void foo1 () { t = 1; i = 1; }               //  warning 721
                                               //  t and i could be global.

  void foo2 () { this->t = 2; this->i = 2; }   //  Correct syntax, no warning.
};
DerivedT d;             // Here is the point of instantiation.


Tokens after #endif

In HP C++, any character that follows the #endif preprocessor statement causes a warning and is ignored. In HP aC++, characters following the #endif preprocessor statement cause an error and the program does not compile. To change this, remove all characters following all #endif preprocessor statements or put the token in comments.

Example:

Compiling the following code with HP C++ causes a warning. Compiling with HP aC++ generates an error.

int main(){
   #ifdef FLAG
   int i;
   i=1;
   #endif FLAG
}
To compile with HP aC++, change the code to:
int main(){
   #ifdef FLAG
   int i;
   i=1;
   #endif //FLAG
}


overload not a Keyword

In HP C++, using the overload keyword to specify a function as an overloaded function causes an anachronistic warning and is ignored. In HP aC++, using the overload keyword causes an error and the program does not compile. To change this, remove all occurrences of the overload keyword.

Example:

Compiling the following code with HP C++ causes a warning. Compiling with HP aC++ generates an error stating that overload is used as a type, but has not been defined as a type.

int f(int i);
overload int f(float f); // Remove the word overload.
int main () {
return 1;
}


Dangling Comma in enum

In HP C++, a comma following the last element in an enum list is ignored. In HP aC++, a comma following the last element in an enum list generates an error. To avoid this error, remove the comma after the last element.

Example:

enum Colors { red,
              orange,
              yellow,
              green,
              blue,
              indigo,
              violet,   // This comma is illegal.
};


Static Member Definition Required

In HP C++, you can declare a static member and not define it. However, in HP aC++, you cannot do so. You must define the declared static data member.

Example:

Compiling and linking the following code on HP C++ gives no warning nor error. Compiling the code on HP aC++ gives neither a warning nor an error. Linking the resulting object file generates a linker (ld) error that states that there are unsatisfied symbols.

class A {
public:
   static int staticmember;
};
// int A::staticmember=0;   // This would fix the problem.
int main ()
{
   A::staticmember=1;
}


Declaring friend Classes

In HP C++, you can declare friend classes without the class keyword. In HP aC++, declaring friend classes without the class keyword generates an error. To change this, add the class keyword to all friend class declarations.

Example:

Compiling the following code on HP C++ does not generate a warning or an error. Compiling the code on HP aC++ generates an error stating that the friend declaration for B is not in the right form for either a function or a class.

class foo{

public:
   friend bar;   // Need to say:  friend class B
};
int main (){
   return 1;
}


Incorrect Syntax for Calls to operator new

In HP C++, you can use incorrect syntax to call operator new. In HP aC++, an error is generated when incorrect syntax for operator new is used. To change this, add parentheses around the use of operator new. This code compiles correctly with both HP C++ and HP aC++.

Example:

Compiling the following code on HP C++ does not generate a warning or an error. Compiling the code on HP aC++ generates errors stating operator expected instead of new and undeclared variable operator S.

struct S {
   int f();
};

int g() { 
   return new S->f();
}

// int g() { return (new S)->f();}    // This would fix the problem.

int S:: f( ) { 
      return 1;
}
main() {
   return 1; 
}

Using :: in Class Definitions

In HP C++, you can declare members of classes inside the class using the following incorrect syntax:

class_name::member_name
In HP aC++, this incorrect syntax is considered an error. You must remove the class_name:: specification from the member definition.

Example:

Compiling the following code on HP C++ does not generate a warning or an error. Compiling the code on HP aC++ generates an error stating that you cannot qualify members of class X in the class definition.

class X{
   int X::f();
// int f();     // This would fix the problem and
                // run successfully on both compilers.
>
int main(){
}

Duplicate Formal Argument Names

In HP C++, duplicate formal argument names are allowed. In HP aC++, duplicate formal argument names generate an error. To avoid this, use unique formal parameter names.

Example:

The following code compiles with HP C++. With HP aC++, an error is generated stating that symbol aParameter has been redefined and where it was previously defined.

int a(int aParameter, int * aParameter);


Ambiguous Function or Object Declaration

In HP C++, an ambiguous function or object declaration compiles without warning, assuming an object declaration. In HP aC++, an ambiguous function or object declaration generates an error. To change this, change the code to remove the ambiguity.

Example:

struct A {A(int);};
struct B {B(const A &); void g();};
void f(int p) {
   B b(A(p));   // Declaration of function or object?
   b.g();       // Error?
}

The ambiguity in the example code is whether b is declared as:

  • A function with one argument (named p) returning an object of type B.
  • An object of type B initialized with a temporary object of type A.

HP C++ compiles this code successfully and assumes b is an object. Compiling the code with HP aC++ generates the following error:

Error: File "objDeclaration.c", Line 5
Left side of '.' requires a class object; type found was a function 'B (A)'.
     Did you try to declare an object with a nested constructor call?
     Such a declaration is interpreted as a function declaration B b(A)
     [File "objDeclaration.c, Line 4].

Modify the code to the following to successfully compile it with both compilers:

struct A {A(int);};
struct B {B(const A &); void g();};

void f(int p) {
   B b = A(p);    // declaration of object
   b.g();         // method call
}


Overloaded Operations ++ and --

You must use the overloaded operations ++ and -- correctly. These operations require a member function with one argument. If the function has no argument, a warning is issued and a postfic is assumed in HP C++.

In HP aC++, the inconsistency between the overloaded function usage and definition is considered an error. To avoid this error, change the class definition so that each overloaded function definition has the correct number of arguments.

Example:

class T {
   public:
      T();
      const T& operator++ ();
};
int main () {
T t;
t++;
}

Compiling the above code with HP C++ generates the following warning:

CC: "pre.C", Line 8: warning: prefix ++/-- used as postfix (anachronism) (935)
Compiling the code with HP aC++ generates the following error:
Error 184: File "pre.C", Line 8
Arithmetic or pointer type expected for operator '++'; type found was 'T'.
To compile the code with HP C++ or HP aC++ use the following class definition:
class T {
   public:
      T();
      const T& operator++ ();     // prefix    old style postfix definition
      const T& operator++ (int);  // postfix
};


Reference Initialization

Illegal reference initialization is no longer allowed. In HP C++, a warning is generated stating that the initializer for a non-constant reference is not an lvalue (anachronism). In HP aC++, an illegal initialization of a reference type generates an error and the program does not compile. To avoid this error, use a constant reference.

Example:

void f() {
   char c = 1;
   int & r = c;
}
Compiling the above code with HP C++ generates the following warning:
C: "nonConstRef.C", line 6: warning: initializer for non-const
reference not an lvalue (anachronism)( (235)
Compiling the code with HP aC++ generates the following error:
Error: File "nonConstRef.C", Line 6
Type mismatch; cannot initialize a 'int &' with a 'char'.
Try changing 'int &' to 'const int &'.
For successful compilation with both compilers, change the code to the following:
void f() {
    char c = 1;
    const int & r = c;
}


Using operator new to Allocate Arrays

In HP C++, operator new is called to allocate memory for an array. In HP aC++, operator new [] is called to allocate memory for an array.

Example:

The following code compiles without error on HP C++.

typedef char CHAR;
typedef unsigned int size_t;
typedef const CHAR *LPCSTR, *PCSTR;
typedef unsigned char BYTE;

void* operator new (size_t nSize, LPCSTR lpszFileName, int nLine);
static char THIS_FILE[] = "mw2.C";
int main() {
   BYTE *p;
   p = new(THIS_FILE, 498) BYTE[50];
}
On HP aC++, the following error is generated:
Error: File "DDB4269.C", Line 10
Expected 1 argument(s) for void *operator new [ ](unsigned int); had 3 instead.


Parentheses in Static Member Initialization List

In HP C++, redundant parentheses are allowed in a static member initialization list. In HP aC++, redundant parentheses in a static member initialization list generate an error and the program does not compile. You must remove the redundant parentheses to compile the program with both compilers.

Example:

class A {
public:
   int i;
   static int (A::*p);
};

int (A::*(A::p)) = &(A::i);
Compiling this code HP aC++ generates the following error:
Error: File "DDB4270.C", Line 7
A pointer to member cannot be created from a parenthesized 
or unqualified name.
To successfully compile the code, remove the parentheses from the last line.
class A {
public:
   int i;
   static int (A::*p);
};

int (A::*(A::p)) = &A::i;


&qualified-id Required in Static Member Initialization List

In HP C++, you can use an unqualified function name in a static member initialization list. In HP aC++, an unqualified function name in a static member initialization list causes an error and the program does not compile. Use the unary operator & followed by a qualified-id in the member initialization list. The resulting code compiles correctly with HP C++ and HP aC++.

Example:

class A {
public:
   int i;
   int j();
static int (A::*p)();
};
int (A::*(A::p))() = j;
Compiling this code with HP aC++ generates the following error:
Error: File "DDB4270A.C", Line 7
Cannot initialize 'int (A::*)()' with 'int (*)()'.
To successfully compile with HP C++ and HP aC++, change the initialization list in line 7 to &A::j;
class A {
public:
   int i;
   int j();
static int (A::*p)();
};
int (A::*(A::p))() = &A::j;


Non-constant Reference Initialization

In HP C++, if you do not initialize a non-constant reference with an lvalue, an anachronistic warning is issued and compilation continues. In HP aC++, an error is issued if you do not use an lvalue for a non-constant reference initialization. Use an lvalue for the reference initialization, or define the reference as a const type.

Example:

void f(int &);
int main () {
   f(3);
   return 0;
}
Compiling this code with HP C++ generates the following warning:
CC: "DDB04313A.C", line 4: warning: temporary used for non-const int & argument;
 no changes will be propagated to actual argument (anachronism) (283)
Compiling the above code with HP aC++ generates the following error:
Future Error: File "DDB04313A.C", Line 4
The initializer for a non-constant reference must be an lvalue.
        Try changing 'int &' to 'const int &'.
To successfully compile the code with either compiler, use one of the two alternatives shown below:
void f(const int &);  // Use a constant reference.
int main () {
   f(3);
   return 0;
}

void f(int &);
int i;
int main () {
   i=3;
   f(i);              // Use an lvalue for reference initialization.
   return 0;
}


Digraph White Space Separators

HP C++ does not support alternative tokens (digraphs). In HP aC++, digraphs are supported and legal C++ syntax can be considered an error because of digraph substitution. Insert a blank between two characters of the digraph.

Example:

C<::A> a;
The characters <: are one of the alternative tokens (digraphs) for which HP aC++ performs a substitution. In this case, <: becomes [. The statement to be compiled becomes C[:A a;, which produces many compilation errors.

To successfully compile this program with either compiler, insert a blank between < and :.

  C< ::A> a;

Migration Considerations when Using Templates

In HP aC++, templates are processed differently than in HP C++ (cfront). HP aC++ does not have a repository. All instantiations are placed in an object (.o) file (with additional information in a .Ia file if you specify the +inst_auto command-line option). You cannot modify these files as was possible with the files in a repository.

See Using HP aC++ Templates for more information.

To begin migrating code containing templates to HP aC++, try to compile and link using the default compile-time instantiation. If this fails with compilation errors, you can compile using one of the following:

  • The +inst_all option to view all compile-time errors, including template instantiation errors. This may generate errors that will not occur in your program, because the draft standard allows template parameters that cannot instantiate all members. The +inst_all option forces instantiation of such members.
  • The +inst_directed option to mask compile-time template instantiation errors.

To reset after all translation units compile successfully:

  1. Remove any .o and .I files. Using a clobber makefile target to remove .I files is similar to removing the ptrepository directory in cfront.
  2. Recompile and link using compile-time instantiation.


Verbose Template Processing Information

Use the +inst v option to replace the cfront -ptv option to process verbose template information.


Common Template Migration Syntax Changes

You must use the keyword typname to distinguish types in template code in HP aC++. Also, use the this-> notation to reference data members.


The cfront Implicit Include Convention

The preferred method for specifying template declarations and definitions in HP aC++ is to put declarations and definitions in the same file.

In HP C++ (cfront), for any .h file that contains template declarations, there is a .c file that contains definitions for those templates.

HP aC++ provides the following options to ease migration from HP C++ (cfront):

  • +inst implicit_include: This option instructs the compiler to use the cfront default file, name lookup, for template definition files.
  • +inst include_suffixes: Use this option to replace the cfront -ptS"list" option. This specifies file name extensions for template definition files.


Converting Directed Mode to Explicit Instantiation

If you use directed mode instantiation with the cfront based compiler, an awk script can be used to convert your file to an instantiation file that uses the explicit instantiation syntax:

#!/usr/bin/ksh
# For a Directed-Mode Instantiation file that is the parameter
# to the script, create a file that can be compiled with the
# aC++ compiler using the Explicit Instantiation Syntax.
# (Note that this will only work for classes.)

closure_file=$1
closure_file_base_name=${1%\.*}
eis_file=$closure_file_base_name.eis.C

print "Output file:  $eis_file"
# Get all of the include directives.
grep "#include" $closure_file > /tmp/dmi2eis1.$$

# Collect all of the Directed-Mode Instantiation directives.
grep -v "#include" $closure_file \
  | grep -e ">" -e "<" \
  | grep -v "(" \
  | awk ' {if ($1 != "//") {print $0;} }' >/tmp/dmi2eis2.$$

# Print the line assuming that the last element is the variable
# name followed immediately by a semi-colon.
awk '{ n=split($0,sp0);
   printf("template class");
   for (i=1; i<=(n-1); i++) {
     printf(" %s", sp0[i]);
   }
   printf(";\n");
 }' < /tmp/dmi2eis2.$$ > /tmp/dmi2eis3.$$

    cat /tmp/dmi2eis1.$$ /tmp/dmi2eis3.$$ > $eis_file
    rm -f /tmp/dmi2eis*.$$