 
















                     Compaq_C++____________________________________
                     Using Compaq C++ for Tru64 UNIX and Linux
                     Alpha


                     June 2000

                     This manual contains information about developing
                     Compaq C++ programs on Compaq Tru64 UNIX and Linux
                     Alpha systems.






                     Software Version:            Compaq C++ Version
                                                  6.2 for Tru64 UNIX
                                                  Compaq C++ Version
                                                  6.3 for Linux Alpha











                     Compaq Computer Corporation
                     Houston, Texas

 






           __________________________________________________________
           First Printing, March 1993
           Tenth Revision, June 2000

            2000 Compaq Computer Corporation.

           COMPAQ, the Compaq logo, and Alpha, DEC, Ladebug, OpenVMS,
           Tru64 UNIX, and VMS are registered in the U.S. Patent and
           Trademark Office.

           AT&T is a registered trademark of American Telephone and
           Telegraph Company.

           Hewlett-Packard is a registered tradmark of the Hewlett-
           Packard Company.

           IEEE is a registered trademark of the Institute of
           Electrical and Electronics Engineers, Inc.

           Microsoft, Windows and Windows NT are registered
           trademarks and Visual C++ is a trademark of Microsoft
           Corporation in the United States and/or other countries.

           Motif, OSF/1, UNIX and the "X" device are registered
           trademarks and IT DialTone and The Open Group are
           trademarks of The Open Group in the United States and/or
           other countries.

           POSIX is a registered certification mark of the Institute
           of Electrical and Electronic Engineers.

           All other product names mentioned herein may be trademarks
           or registered trademarks of their respective companies.

           Portions of the ANSI C++ Standard Library have been
           implemented using source licensed from and copyrighted
           by Rogue Wave Software, Inc.

           Information pertaining to the C++ Standard Library has
           been edited and reprinted with permission of Rogue Wave
           Software, Inc. All rights reserved.

           Portions copyright 1994-2000 Rogue Wave Software, Inc.

           Compaq shall not be liable for technical or editorial
           errors or omissions contained herein. The information in
           this document is subject to change without notice.

           Confidential computer software. Valid license from Compaq
           required for possession, use or copying. Consistent with
           FAR 12.211 and 12.212, Commercial Computer Software,
           Computer Software Documentation, and Technical Data for
           Commercial Items are licensed to the U.S. Government under
           vendor's standard commercial license.

           This document is available on CD-ROM.

                                                               ZK6388

           This document prepared using DECdocument, Version 3.3-1b.

 













   ________________________________________________________________

                                                           Contents


   Preface..................................................     xi


   1  Building and Running C++ Programs

         1.1   Compiling a Program..........................    1-1
         1.2   Linking a Program............................    1-2
         1.3   Name Demangling..............................    1-2
         1.4   C++ Standard Library.........................    1-4
         1.5   C++ Class Library............................    1-5
         1.6   Debugging....................................    1-5
         1.7   Improving Build Performance..................    1-6
         1.7.1     Object File Compression [Tru64]..........    1-6
         1.7.2     Using Shared Libraries...................    1-6
         1.7.3     Using Precompiled Headers................    1-6
         1.7.4     Performance Optimization Options.........    1-6
         1.8   Deploying Your Application [Tru64]...........    1-7
         1.8.1     Redistributing the C++ Run-Time
                   Library..................................    1-8
         1.8.2     Instructions for Installing
                   Redistribution Kit.......................    1-8

   2  Compaq C++ Implementation

         2.1   Implementation-Specific Attributes...........    2-1
         2.1.1     #pragma Preprocessor Directive...........    2-1
         2.1.1.1     #pragma define_template Directive......    2-2
         2.1.1.2     #pragma instantiate Directive..........    2-2
         2.1.1.3     #pragma environment Directive..........    2-3
         2.1.1.4     #pragma extern_prefix Directive........    2-5
         2.1.1.5     #pragma ident Directive................    2-5
         2.1.1.6     #pragma [no]inline Directive...........    2-6


                                                                iii

 






           2.1.1.7     #pragma [no]member_alignment
                       Directive..............................    2-6
           2.1.1.8     #pragma message Directive .............    2-8
           2.1.1.9     #pragma module Directive...............   2-10
           2.1.1.10    #pragma once Directive.................   2-10
           2.1.1.11    #pragma pack Directive.................   2-11
           2.1.1.12    #pragma pointer_size Directive
                       [Tru64]................................   2-13
           2.1.1.13    #pragma required_pointer_size Directive
                       [Tru64]................................   2-14
           2.1.1.14    #pragma required_vptr_size Directive
                       [Tru64]................................   2-14
           2.1.1.15    #pragma [no]standard Directive.........   2-15
           2.1.2     Protecting System Header Files...........   2-15
           2.1.2.1     Using the Compiler's Header File
                       Protection Option......................   2-16
           2.1.2.2     Modifying Each Header File.............   2-16
           2.1.3     Predefined Macro Names...................   2-17
           2.1.4     Translation Limits.......................   2-23
           2.1.5     Numerical Limits.........................   2-23
           2.1.6     Argument-Passing and Return Mechanisms...   2-24
           2.2   Implementation Extensions and Features.......   2-24
           2.2.1     Identifiers..............................   2-24
           2.2.1.1     Character Limit for Long Names.........   2-25
           2.2.2     Order of Static Object Initialization....   2-25
           2.2.3     Integral Conversions.....................   2-25
           2.2.4     Floating-Point Conversions...............   2-25
           2.2.5     Explicit Type Conversion.................   2-26
           2.2.6     The sizeof Operator......................   2-26
           2.2.7     Explicit Type Conversion.................   2-26
           2.2.8     Multiplicative Operators.................   2-27
           2.2.9     Additive Operators.......................   2-27
           2.2.10    Shift Operators..........................   2-27
           2.2.11    Equality Operators.......................   2-27
           2.2.12    volatile Type Specifier..................   2-28
           2.2.13    __unaligned Type Specifier ..............   2-30
           2.2.14    Linkage Specifications...................   2-31
           2.2.15    Temporary Objects........................   2-31
           2.2.15.1    Nonconstant Reference Initialization
                       with a Temporary Object................   2-32
           2.2.16    Exception Handling.......................   2-32
           2.2.17    File Inclusion...........................   2-33
           2.2.18    Nested Enums and Overloading.............   2-34


     iv

 






              2.2.19    Guiding Declarations.....................   2-36
              2.3   Run-time Type Identification.................   2-36
              2.4   Message Control Options......................   2-37
              2.5   Message Information Options..................   2-38


        3  Compaq C++ Language Environment

              3.1   Using Existing C Header Files................    3-1
              3.1.1     Providing C and C++ Linkage..............    3-1
              3.1.2     Resolving C++ Keyword Conflicts..........    3-2
              3.2   Using Compaq C++ with Other Languages........    3-3
              3.3   Linkage to Non-C++ Code and Data.............    3-4
              3.4   How to Organize Your C++ Code................    3-4
              3.4.1     Code That Does Not Use Templates.........    3-4
              3.4.2     Code That Uses Templates.................    3-6
              3.4.3     Creating Libraries.......................    3-8
              3.5   Using 32-bit Pointers (xtaso)................    3-9
              3.6   Hints for Designing Upwardly Compatible C++
                    Classes......................................   3-14
              3.6.1     Source Compatibility.....................   3-15
              3.6.2     Link Compatibility.......................   3-15
              3.6.3     Run Compatibility........................   3-17
              3.6.4     Additional Reading.......................   3-17

        4  Porting to Compaq C++

              4.1   Compatibility with Other C++ Compilers.......    4-1
              4.2   Compatibility With Version 5.n Compilers
                    [Tru64]......................................    4-4
              4.2.1     Compiler Version Options [Tru64].........    4-4
              4.2.2     Language Differences [Tru64].............    4-5
              4.2.3     Implementation Differences [Tru64].......    4-7
              4.2.4     Library Differences [Tru64]..............    4-8
              4.3   Using Classes................................    4-8
              4.3.1     Friend Declarations......................    4-8
              4.3.2     Member Access............................    4-9
              4.3.3     Base Class Initializers..................    4-9
              4.4   Undefined Global Symbols for Static Data
                    Members......................................    4-9
              4.5   Functions and Function Declaration
                    Considerations...............................   4-10
              4.6   Using Pointers...............................   4-11
              4.6.1     Pointer Conversions......................   4-11

                                                                       v

 






           4.6.2     Bound Pointers...........................   4-11
           4.6.3     Constants in Function Returns............   4-11
           4.6.4     Pointers to Constants....................   4-12
           4.7   Using typedefs...............................   4-12
           4.8   Initializing References......................   4-12
           4.9   Using the switch and goto Statements.........   4-13
           4.10  Using Volatile Objects.......................   4-14
           4.11  Preprocessing................................   4-14
           4.12  Managing Memory..............................   4-15
           4.13  Size-of-Array Argument to delete Operator....   4-15
           4.14  Flushing the Output Buffer...................   4-15
           4.15  Missing Parenthesis Error Message............   4-16
           4.16  Link Using cxx...............................   4-16
           4.17  Source File Extensions.......................   4-17
           4.18  Incrementing Enumerations....................   4-17
           4.19  Scope of Variables Declared on a for
                 Statement....................................   4-17
           4.20  Guidelines for Writing Clean 64-Bit Code.....   4-18


     5  Using Templates

           5.1   Overview.....................................    5-1
           5.2   Automatic Template Instantiation.............    5-2
           5.2.1     Specifying Alternate Repositories........    5-2
           5.2.2     Reducing Compilation Time with the
                     -ttimestamp Option.......................    5-3
           5.3   Implicit Inclusion...........................    5-4
           5.3.1     Compiling Programs with Automatic
                     Instantiation............................    5-5
           5.3.2     Linking Programs with Automatic
                     Instantiation............................    5-6
           5.4   Manual Template Instantiation................    5-8
           5.4.1     Instantiation Directives.................    5-9
           5.4.1.1     #pragma define_template................    5-9
           5.4.1.2     #pragma instantiate and #pragma
                       do_not_instantiate.....................   5-13
           5.5   Advanced Program Development and Templates...   5-15
           5.5.1     Dependency Management....................   5-15
           5.5.2     Mixing Automatic and Manual
                     Instantiation............................   5-15
           5.5.3     Creating Libraries.......................   5-16
           5.5.4     Creating A Common Instantiation
                     Library..................................   5-17

     vi

 






              5.5.5     Multiple Repositories....................   5-20
              5.6   Template Options.............................   5-21
              5.7   Compatibility with Earlier Versions of C++...   5-24
              5.7.1     Linking with Version 5.n
                        Instantiations...........................   5-25
              5.8   Linking Version 5.n Applications Against
                    Version 6.n Repositories.....................   5-26


        6  Precompiled Headers

              6.1   Automatic Precompiled Header Processing......    6-2
              6.2   Manual Precompiled Header Processing.........    6-6
              6.3   Other Ways for Users To Control Precompiled
                    Headers......................................    6-7
              6.4   Performance Issues...........................    6-7
              6.5   Command-Line Options for Precompiled
                    Headers......................................    6-8

        7  The C++ Standard Library

              7.1   Important Compatibility Information..........    7-3
              7.1.1     -[no]using_std Compiler Compatibility
                        Switch...................................    7-3
              7.1.2     Pre-ANSI/ANSI IOStreams Compatibility....    7-3
              7.1.3     Support for pre-ANSI and ANSI operator
                        new() ...................................    7-6
              7.1.4     Overriding operator new() ...............    7-7
              7.1.5     Support for Global array new and delete
                        Operators................................   7-10
              7.2   How to Build Programs Using the C++ Standard
                    Library......................................   7-11
              7.3   Optional Switch to Control Buffering.........   7-11
              7.4   Enhanced Compile-time Performance of ANSI
                    IOStreams....................................   7-12
              7.5   Upgrading from the Class Library to the
                    Standard Library Provided with Version 6.n...   7-12
              7.5.1     Upgrading from the Class Library Vector
                        to the Standard Library Vector...........   7-13
              7.5.2     Upgrading from the Class Library Stack to
                        the Standard Library Stack...............   7-14
              7.5.3     Upgrading from the Class Library String
                        Package Code.............................   7-15


                                                                     vii

 






           7.5.4     Upgrading from the Class Library Complex
                     to the ANSI Complex Class................   7-17
           7.5.5     Upgrading from the Pre-ANSI IOStream
                     Library to the Standard Library..........   7-20
           7.5.6     Upgrading Pre-ANSI bit_vector to ANSI
                     vector<bool>.............................   7-31


     8  Handling Exceptions

           8.1   Structure....................................    8-1
           8.2   Run-Time Considerations......................    8-3
           8.3   Coding Recommendations.......................    8-3
           8.4   Mixed-Language Applications..................    8-4
           8.5   Finding Information about Exceptions.........    8-4
           8.6   Using the dlclose Routine....................    8-4
           8.7   Catching Signals and C Exceptions............    8-5
           8.8   C++ Exceptions and Threads [Tru64]...........    8-6

     9  Using the Ladebug Debugger

           9.1   Debugging C++ Programs.......................    9-2
           9.2   Using Absolute and Relative Path Names.......    9-3
           9.3   Debugging Programs Containing C and C++
                 Code.........................................    9-4
           9.4   Setting the Class Scope......................    9-5
           9.5   Displaying Class Information.................    9-7
           9.6   Displaying Object Information................    9-8
           9.7   Displaying Virtual and Inherited Class
                 Information..................................   9-10
           9.8   Modifying Class and Object Data Members......   9-14
           9.9   Member Functions on the Stack Trace..........   9-15
           9.10  Resolving Ambiguous References to Overloaded
                 Functions....................................   9-15
           9.11  Setting Breakpoints in Member Functions......   9-19
           9.11.1    Setting Breakpoints in Overloaded
                     Functions................................   9-22
           9.11.2    Setting Breakpoints in Constructors and
                     Destructors..............................   9-26
           9.12  Calling Overloaded Functions.................   9-27
           9.13  Using Typecasts to Display Program
                 Expressions..................................   9-28
           9.14  Class Templates and Function Templates.......   9-31
           9.15  Debugging C++ Exception Handlers.............   9-36

     viii

 






              9.15.1    Setting Breakpoints in Exception
                        Handlers.................................   9-36
              9.15.2    Examining and Modifying Variables in
                        Exception Handlers.......................   9-38
              9.16  Advanced Program Information: Verbose Mode...   9-38
              9.17  Reducing Object File Size During Debugging...   9-43
              9.17.1    Using the -gall and -gall_pattern
                        Options..................................   9-44
              9.17.2    Hints for Using the -gall Option
                        Effectively..............................   9-46


        A  Class Library Restrictions

        B  Built-In Functions

              B.0.0.1     In-line Assembly Code-ASMs.............    B-1

        C  Third Degree Messages


        Index


        Examples

              9-1       Switching Between C++ and C Debugging
                        Modes....................................    9-5

              9-2       Setting the Class Scope..................    9-6

              9-3       Displaying Class Information.............    9-7

              9-4       Displaying Object Information............    9-9

              9-5       Printing Information on a Derived
                        Class....................................   9-10

              9-6       Resolving References to Objects of
                        Multiple Inherited Classes...............   9-13

              9-7       Resolving Overloaded Functions by
                        Selection Menu...........................   9-16

              9-8       Resolving Overloaded Functions by Type
                        Signature................................   9-18

              9-9       Setting Breakpoints in Member
                        Functions................................   9-20

                                                                      ix

 






           9-10      Setting Breakpoints in Virtual Member
                     Functions................................   9-21

           9-11      Setting Breakpoints in Member Functions
                     for a Specific Object....................   9-22

           9-12      Setting Breakpoints in Specific
                     Overloaded Functions.....................   9-23

           9-13      Setting Breakpoints in All Versions of an
                     Overloaded Function......................   9-25

           9-14      Setting Breakpoints in Overloaded
                     Functions by Line Number.................   9-26

           9-15      Setting Breakpoints in Constructors......   9-26

           9-16      Setting Breakpoints in Destructors.......   9-27

           9-17      Calling an Overloaded Function...........   9-27

           9-18      Using a Cast to Perform Data Coercion....   9-29

           9-19      Using Casts on a Derived Class Object....   9-29

           9-20      Using a Cast with Pointer Notation to
                     Perform a Type Transfer..................   9-30

           9-21      Using a Cast with Reference Type Notation
                     to Perform a Type Transfer...............   9-30

           9-22      Example of a Function Template...........   9-31

           9-23      Setting a Breakpoint in the Template
                     Function.................................   9-31

           9-24      Displaying the Current Function Context
                     for a Function Template..................   9-32

           9-25      Displaying an Instantiated Class
                     Template.................................   9-32

           9-26      Displaying an Instantiated Class
                     Template.................................   9-34

           9-27      Setting Breakpoints in an Instantiated
                     Class Function...........................   9-34

           9-28      Setting Current Class Scope to an
                     Instantiated Class.......................   9-34

           9-29      Alternate Method of Setting Current Class
                     Scope....................................   9-35

           9-30      Setting Breakpoints in Exception
                     Handlers.................................   9-37

           9-31      Printing a Class Description in Verbose
                     Mode.....................................   9-39

           9-32      Printing Base Pointer Information........   9-40

     x

 






              9-33      Printing a Stack Trace in Verbose Mode...   9-42


        Figures

              9-1       A Stack Trace Displaying a Member
                        Function.................................   9-15

        Tables

              1         Conventions Used in this Manual..........    xiv

              2-1       Standard Macro Names.....................   2-17

              2-2       System Identification Macro Names........   2-17

              2-3       Other Predefined Macro Names.............   2-18

              2-4       Language Dialect Macro Names.............   2-20

              2-5       Implementation Compatibility Macro
                        Names....................................   2-20

              2-6       __DECC_VER Version-Type Encodings .......   2-22





















                                                                      xi

 











        ________________________________________________________________

                                                                 Preface



              This manual contains information for developing and
              debugging Compaq C++ programs on Tru64 UNIX and Linux
              Alpha systems, and includes information on other Tru64
              UNIX and Linux Alpha features and tools that work with
              Compaq C++.

                ________________________Note  ________________________

                Most information in this manual applies to both the
                Tru64 UNIX and Linux Alpha platforms. The notation
                [Tru64] introduces information that applies only
                to Tru64 UNIX; the notation [Linux] introductes
                information that applies only to Linux Alpha.

                _____________________________________________________

        Intended Audience

              This manual is intended for experienced programmers
              who need to develop Compaq C++ programs on Tru64 UNIX
              and Linux Alpha systems. Users of this manual should
              have a basic understanding of the C++ language and some
              familiarity with the Tru64 UNIX and Linux Alpha operating
              systems.

        Structure of this Document

              This manual is organized as follows:

              o  Chapter 1 shows how to create, compile, link, and run
                 Compaq C++ programs.

              o  Chapter 2 describes features and characteristics that
                 are specific to the Compaq C++ implementation.

                                                                      xi

 






           o  Chapter 3 describes how to modify existing C header
              files to be accepted by Compaq C++.

           o  Chapter 4 contains tips for moving applications built
              with other C++ implementations to Compaq C++.

           o  Chapter 5 describes how to use templates with Compaq
              C++.

           o  Chapter 6 describes how to use precompiled headers with
              Compaq C++.

           o  Chapter 7 describes the Compaq C++ implementation of
              the C++ Standard Library.

           o  Chapter 8 explains how to use C++ exception handling.

           o  Chapter 9 describes how to use the Ladebug debugger.

           o  Appendix A describes Class Library restrictions.

           o  Appendix B describes built-in functions.

           o  Appendix C describes Third Degree messages generated by
              the C++ Class and Standard Libraries.

           o  The cxx(1) reference page describes command line
              options.

     Associated Documents

           The following documents contain information associated
           with topics in this manual:

           o  Stroustrup, Bjarne. The C++ Programming Language, 3rd
              Edition. Reading, Massachusetts: Addison-Wesley, 1997.

              Provides an exhaustive introduction to the C++
              programming language, including sophisticated language
              features. This book also includes the text but not the
              annotations of The Annotated C++ Reference Manual.

           o  C++ Class Library Reference Manual

              This manual describes the class library packages
              supplied with Compaq C++.

           o  Compaq C++ Installation Guide for Tru64 UNIX

     xii

 






                 This document supplies the information necessary
                 to install Compaq C++. on Tru64 UNIX  systems.
                 Instructions for installing Compaq C++ on Linux Alpha
                 systems are provided in a README document supplied with
                 the C++ for Linux Alpha kit.

              o  The AT&T C++ Language System, Release 2.0, Library
                 Manual

                 This document describes the AT&T class library package.

        Related Documents

              The following documents are not included in the Compaq
              C++ documentation set. Refer to them for additional
              information on the C++ programming language, Compaq C,
              or Tru64 UNIX and Linux Alpha programming.

              o  Stroustrup, Bjarne and Margaret Ellis. The Annotated
                 C++ Reference Manual. Reading, Massachusetts: Addison-
                 Wesley, 1990.

                 This text contains the current language definition of
                 C++.

              o  Carroll, Martin D. and Margaret E. Ellis. Designing and
                 Coding Reusable C++. Reading, Massachusetts: Addison-
                 Wesley, 1995.

                 This text provides practical information for designing
                 and implementing C++ programs.

              o  Myers, Scott. Effective C++: 50 Specific Ways to
                 Improve Your Programs and Designs, 3rd edition.
                 Reading, Massachusetts: Addison-Wesley, 1997.

              o  Myers, Scott. More Effective C++: 35 New Ways
                 to Improve Your Programs and Designs. Reading,
                 Massachusetts: Addison-Wesley, 1995.

                 These texts provide practical information for designing
                 and implementing C++ programs.

              o  Tru64 UNIX Programmer's Guide

                 This guide describes the programming environment on
                 the Tru64 UNIX operating system, emphasizing the C
                 programming language.

              o  Compaq C Language Reference Manual

                                                                    xiii

 






              Provides a complete technical description of the C
              language as specified by the ANSI X3J11 committee.
              This manual also fully describes all extensions to this
              standard implemented in Compaq C.

           o  ULTRIX to Tru64 UNIX Migration Guide

              Describes how to migrate from an ULTRIX system to a
              Tru64 UNIX system. This book includes information on
              porting applications from ULTRIX to Tru64 UNIX systems.

     Conventions Used in this Manual

           Table 1 lists the conventions used in this manual.

           Table_1_Conventions_Used_in_this_Manual___________________

           Convention____________Meaning_____________________________

           %                     A percent sign (%) is the default
                                 user prompt.

           class complex {       A vertical ellipsis indicates that
                 .               some intervening program code or
                 .               output is not shown. Only the more
                 .               pertinent material is shown in the
           };                    example.

           , . . .               A horizontal ellipsis in a syntax
                                 description indicates that you
                                 can enter additional parameters,
                                 options, or values. A comma
                                 preceding the ellipsis indicates
                                 that successive items must be
                                 separated by commas.

           The generic           Monospaced type denotes the names of
           class . . .           Compaq C++ language elements, and
           The get() func-       also the names of classes, members,
           tion . . .            and nonmembers. Monospaced type is
                                 also used in text to reference code
                                 elements displayed in examples and
                                 file-name extensions.

                                             (continued on next page)

     xiv

 






              Table_1_(Cont.)_Conventions_Used_in_this_Manual___________

              Convention____________Meaning_____________________________

              italic                Italic type denotes the names of
                                    variables that appear as parameters
                                    or in arguments to functions, and
                                    also denotes book titles.

              boldface              Boldface type in text indicates the
                                    first instance of terms defined in
                                    text.

              UPPERCASE             The Tru64 UNIX and Linux Alpha
              lowercase             operating systems distinquish
                                    between uppercase and lowercase
                                    characters. Literal strings
                                    that appear in text, examples,
                                    syntax descriptions, and function
                                    definitions must be entered exactly
                                    as shown.

              cxx(1)                Cross-references to reference pages
                                    include the appropriate section
              ______________________number_in_parentheses.______________

        Reader's Comments

              You may send comments or suggestions regarding this
              manual, or any Compaq C++ document, by electronic mail
              to the following Internet address:

                    cxx_docs@zko.dec.com

        Product Support

              Support for Tru64 UNIX and Linux Alpha and C++ products is
              provided worldwide by Compaq MultivendorCustomer Services.
              To request information on support services in the United
              States and Canada, call toll-free

                    1.800.344.4825

              For information on support in other countries, contact
              your local customer services organization.

                                                                      xv

 






           When reporting problems to Compaq, please provide the
           following information:

           o  Name and version of compiler (from a listing file or by
              specify the -V command-line option).

           o  Name and version of operating system (type cat
              /etc/motd.

           o  Smallest possible complete source and commands needed
              to reproduce the problem.

           o  An example of the incorrect results and the desired
              results































     xvi

 









                                                                       1
        ________________________________________________________________

                                       Building and Running C++ Programs



              This chapter provides information about the basic steps
              involved in developing a Compaq C++ program. It explains
              how to compile, link, and debug programs.

              Compaq C++ is an implementation of the C++ programming
              language. The compiler is part of the Compaq Tru64 UNIX
              and Linux Alpha compiler systems. See the Compaq Tru64
              UNIX and Linux Alpha Programmer's Guide for program
              development information that applies to all Compaq
              Tru64 UNIX and Linux Alpha languages, such as using the
              compiler system, creating shared libraries, profiling, and
              optimization.

        1.1 Compiling a Program

              The cxx command invokes the compiler. For information
              about using the cxx (Compaq C++ compiler) command,
              including a description of command options, refer to the
              cxx(1) reference page. For information about this release,
              see the online release notes in:

              /usr/lib/cmplrs/cxx/CompaqCXXversion.release-notes

              or

              /usr/lib/compaq/cxx-version/alpha-linux/doc/readme.ps | .txt

              You can compile a mixture of C++ and C source code by
              entering a single cxx compile command. The compiler
              distinguishes between C++ source files (for example, .cxx)
              and C source files (for example, .c) based on their file
              extensions, and it compiles the modules appropriately.

              Unless you use the -x option to direct the compiler to
              ignore file-name extensions, passing a file with a .c
              extension to the cxx command causes the compiler driver
              to treat the file as a C file and pass it on to the cc

                                   Building and Running C++ Programs 1-1

 



     Building and Running C++ Programs
     1.1 Compiling a Program

           command on Tru64 UNIX or the ccc command on Linux Alpha
           . If the file contains C++ code instead of C code, the
           compilation might produce errors.

     1.2 Linking a Program

           Always use the cxx command to link your programs. Linking
           through the cxx command ensures that all the necessary
           link options are passed to the ld linker. If your program
           is not linked properly, some static objects will not be
           initialized at program startup. If a module is built
           using Version 6.n, it must be linked with the Version
           6.n library.

           If you choose to use the ld linker directly, you might
           need to modify your ld command whenever you install a new
           version of the compiler or the Compaq Tru64 UNIX and Linux
           Alpha operating system. After the installation, follow
           these steps:

           1. Invoke the cxx command and specify the -v option to
              display the ld command in use.

           2. Compare this ld command with your ld command and make
              any necessary changes.

           If you are using templates, you must modify the ld command
           by replacing the -input argument with a list of your
           template instantiation object files. The replacement
           string is normally cxx_repository/*.o.

           To use automatic template instantiation, you must link
           with cxx.

           See the cxx(1) and the ld(1) reference pages for more
           information.

     1.3 Name Demangling

           The C++ compiler encodes type information in function
           names to enable type-safe linkage. This encoding is called
           name mangling. Function name mangling allows object code
           to have distinct names for functions that share the same
           name in the C++ source code and enables type-safe linkage.

     1-2 Building and Running C++ Programs

 



                                       Building and Running C++ Programs
                                                     1.3 Name Demangling

              It is often difficult to decipher mangled names that might
              appear in diagnostic messages from system tools such as
              the ld linker. A name demangler is provided to translate
              such mangled names into the function names that appear
              in the source code, so that they are recognizable by the
              user.

              You can use either the cxx command or the demangle command
              to help interpret mangled messages from the linker. If
              you use the cxx command to invoke the linker, the compiler
              pipes any linker output to the name demangler unless you
              specify the -nodemangle option.

              The demangle command reads each file in sequence,
              demangles any names encoded by the compiler, and displays
              the results on the standard output device. See the
              demangle(1) reference page for more information.

              Syntax

              demangle [-show_mangled_name][-no_vtable_info][-
        ][file . . . ]

              If no input file is given, or if a minus sign is
              encountered as an argument (for example, demangle -),
              the demangle command reads from the standard input file.
              The demangle utility supports the processing of 8-bit
              characters.

              Options

              -               Read from the standard input file.

              -show_mangled_namesplay encoded name in parentheses after
                              demangled name.

              -no_vtable_     Suppress the display of information
              info            concerning internal symbols (specifically
                              __vtbl and __btbl).

              Examples

              demangle file

              This command demangles a file containing Compaq C++
              encoded names.

              ld main.o foo.o |& demangle

                                   Building and Running C++ Programs 1-3

 



     Building and Running C++ Programs
     1.3 Name Demangling

           This command (from the C shell) demangles the output from
           the linker (ld) when linking the main.o and foo.o files.

           cxx foo.cxx |& demangle

           This command (from the C shell) demangles the output from
           the linker when it is invoked implicitly through the cxx
           command to compile foo.cxx.

     1.4 C++ Standard Library

           The C++ Standard Library defines a complete specification
           of the International C++ Standard, with some differences,
           as described in the online release notes in:

           /usr/lib/cmplrs/cxx/CompaqCXXversion.release-notes

           or

           /usr/lib/compaq/cxx-version/alpha-linux/doc/readme.ps | .txt

           Some of the components in the C++ Standard Library are
           designed to replace nonstandard components that are
           currently distributed in the C++ Class Library. However,
           Compaq will continue to provide the C++ Class Library.
           Note that on Linux Alpha, the Class Library task package
           in not supported.

           Linking to the Standard Library

           When you use the cxx command to compile and link programs
           that use the C++ Standard Library, no special switches
           are required. The C++ driver automatically includes the
           Standard Library run-time support (-lcxxstd ) on the link
           command, and automatic template instantiation (-pt ) is
           the default mode.

           For example, to build a program called prog.cxx that uses
           the Standard Library, you enter the following command:

           cxx prog.cxx

           For detailed information about the Standard Library, refer
           to Chapter 7.

     1-4 Building and Running C++ Programs

 



                                       Building and Running C++ Programs
                                                   1.5 C++ Class Library

        1.5 C++ Class Library

              Reusing code is a cornerstone of object-oriented
              programming. To minimize the time it takes to develop new
              applications, a set of reusable classes is an essential
              part of Compaq C++. Class libraries offer a variety
              of predefined classes that enable you to work more
              efficiently.

              See the C++ Class Library Reference Manual C++ Class
              Library Reference Manual for a detailed explanation of
              the Class Library packages supplied with the compiler. The
              iostream class library package is from AT&T. See The AT&T
              C++ Language System, Release 2.0, Library Manual for a
              description of this package.

              Linking to the C++ Class Library

              Most of the C++ Class Library packages are automatically
              included in your program when needed. However, when
              using the complex package, you must provide the following
              explicit information for the linker:

              -lcomplex -lm

              [Tru64] To use the task package, specify the following
              when linking using the cxx command:

              -threads -ltask

              For example:

              cxx thread_program.cxx -threads -ltask

              If you link using the -non_shared option to the cxx
              command, you must also specify -lcmalib. For example:

              cxx -non_shared thread_program.cxx -threads -ltask -lcmalib

              These and other Class Library packages are documented in
              the C++ Class Library Reference Manual.

        1.6 Debugging

              The Ladebug Debugger is a source-level debugger that
              supports Compaq C++. The neither the dbx nor the gdb
              debugger not supports debugging C++ programs. For details
              on using the Ladebug Debugger, see Chapter 9.

                                   Building and Running C++ Programs 1-5

 



     Building and Running C++ Programs
     1.7 Improving Build Performance

     1.7 Improving Build Performance

           This section contains suggestions for improving build
           performance when using Compaq C++ on your system.

     1.7.1 Object File Compression [Tru64]

           By default, the compiler compresses object files. This
           reduces object file size and can result in shortened
           link times, depending on characteristics of the system
           and the application. For some large applications, object
           file compression can significantly slow down the compiler
           and the linker and can significantly increase the amount
           of virtual memory required when linking. For some large
           applications, it is advantageous to compile without object
           file compression. To do so, specify the -nocompress option
           on the cxx command.

     1.7.2 Using Shared Libraries

           Partitioning a large application into several shared
           libraries, which are then linked into an executable,
           is a useful technique for reducing link times during
           development. See Chapter 3 for details.

     1.7.3 Using Precompiled Headers

           Using precompiled headers can reduce compilation time in
           environments where

           o  Many primary sources include the same set of headers in
              the same order.

           o  These headers introduce many lines of code.

           See Chapter 6 for details.

     1.7.4 Performance Optimization Options

           For a description of performance optimization options, see
           the cxx(1) reference page.




     1-6 Building and Running C++ Programs

 



                                       Building and Running C++ Programs
                                  1.8 Deploying Your Application [Tru64]

        1.8 Deploying Your Application [Tru64]


              Applications developed using the Compaq C++ compiler
              require functionality provided in the C++ Run-Time
              Library. While this run-time library ships with the Tru64
              UNIX operating system, newer versions are released with
              each new version of the compiler. These newer versions
              provide bug fixes and support for new features in the
              compiler.

              The C++ library redistribution kit gives the user the
              oportunity to upgrade the C++ library to the most up-to-
              date libraries without having to upgrade the entire OS and
              alleviates the need for application developers to include
              it in their distributions. Because the library is built
              to be upwardly compatible, a later version of the library
              works with applications developed by all prior versions of
              the compiler.

              While we strongly recommend upgrading for bug fixes,
              this is not mandatory. Read the compiler release notes
              at http://www.unix.digital.com/cplus/docs/rnu.htm to
              determine whether your application depends on these bug
              fixes.

              Upgrading for new compiler feature support is not
              optional. To run an application developed using verion
              n of the compiler, you must use a version of the library
              that provides support for all its features. Failure to do
              so typically results in undefined symbol errors from the
              loader at runtime.

              The following table provides the version of the library
              that shipped with each version of the OS. The C++ Compiler
              Feature Version is the absolute highest version of the
              compiler with which an application could have been
              developed and be deployed on this platform without the
              redistribution kit. An application developed with a
              newer compiler or that depends on a bug fix requires the
              installation of the redistribution kit.




                                   Building and Running C++ Programs 1-7

 



     Building and Running C++ Programs
     1.8 Deploying Your Application [Tru64]

           The current redistribution kit, CXXREDIST621V01.tar,
           contains files that have been incorporated into the Tru64
           UNIX V4.0G and V5.0A or later, but might be needed for
           4.0D, 4.0E, 4.0F, and 5.0 of Tru64 UNIX.

           __________________________________________________________
                 C++ Library   C++ Compiler
           OS____Version_______Feature_Version_______________________

           4.0D  6.0-021       6.1-031

           4.0E  6.0-021       6.1-031

           4.0F  6.1-031       6.1-031

           4.0G  6.2-037       6.2-040

           5.0   6.2-024       6.2-040

           5.0A__6.2-037_______6.2-040_______________________________

     1.8.1 Redistributing the C++ Run-Time Library

           If you are a third-party vendor who is shipping a product
           based on Version 6.2 or later, you must ensure your that
           your customers have a Version 6.2 or later C++ Run-Time
           Library. To do so, you can direct them to download the
           latest redistribution kit from the  Compaq C++ web site,
           or you can redistribute it under conditions stated in the
           Software Product Description.

           The mechanism for redistributing the library is for you to
           provide the file /usr/lib/cmplrs/cxx/CXXREDISTnnnVmm.tar
           (where nnn is 620 and mm is 01). This tar file contains a
           setld kit that installs /usr/lib/cmplrs/cxx/libcxx.so.

     1.8.2 Instructions for Installing Redistribution Kit

           To install the kit, follow these steps:

           1. Check if the installed libcxx is earlier than the one
              on this redistribution kit

              Newer libcxx.so images have symbols defined which
              identify the version of the run-time library. If the
              symbol __libcxx_v6020003 exists in the image on your
              system, then you do not need to install this kit.

     1-8 Building and Running C++ Programs

 



                                       Building and Running C++ Programs
                                  1.8 Deploying Your Application [Tru64]

                    # nm /usr/lib/cmplrs/cxx/libcxx.so | grep libcxx_V
                    __libcxx_V60200002    | 0004396996916008 | G | 0000000000000000
                    __libcxx_V60200003    | 0004396996916016 | G | 0000000000000000

              2. If an older redistribution kit was previously installed
                 on the system, it must be removed prior to the
                 installation of the new one.

                 The subset name could be CXXLIBnnn or CXXREDISTnnn

                    # /usr/sbin/setld -i | egrep "CXXLIB|CXXREDIST" | grep install
                    CXXREDIST620   installed  Compaq C++ Run-Time Library ...

                    # /usr/sbin/setld -d CXXREDIST620

              3. Install the redistribution kit

                    # tar -xvf CXXREDIST621V01.tar
                    # /usr/sbin/setld -l CXXREDIST621.kit


























                                   Building and Running C++ Programs 1-9

 









                                                                       2
        ________________________________________________________________

                                               Compaq C++ Implementation



              This chapter discusses the features and characteristics
              specific to the Compaq C++ implementation, including
              pragmas, predefined names, numerical limits, and
              other implementation-dependent aspects of the language
              definition.

        2.1 Implementation-Specific Attributes

              This section describes pragmas, predefined names, and
              limits placed on the number of characters and arguments
              used in Compaq C++ programs.

        2.1.1 #pragma Preprocessor Directive

              The #pragma preprocessor directive is a standard method
              for implementing features that differ from one compiler
              to the next. This section describes pragmas specifically
              implemented in the compiler for Compaq Tru64 UNIX and
              Linux Alpha systems.

              Note that the compiler accepts double underscore
              forms of keywords (for example, #pragma __inline) for
              compatibility with user-written header files.

              Although certain #pragma directives are subject to macro
              expansion, not all of those new to the language in
              this and later releases are subject to such expansion.
              Therefore, users should not write programs that rely on
              macro expansion of the newer pragmas.

              The following #pragma directives are subject to macro
              expansion. A macro reference can occur anywhere after the
              pragma keyword.


                                           Compaq C++ Implementation 2-1

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes


           builtins         inline           linkage[2]       use_
                                                              linkage[2]

           dictionary[1]    noinline         module           extern_
                                                              model

           member_          message          define_template  extern_
           alignment                                          prefix
           [1]Not_supported;_specific_to_C_on_OpenVMS________________

           [2]Not supported; specific to C

     2.1.1.1 #pragma define_template Directive

           The #pragma define_template preprocessor directive
           instructs the compiler to define a template with the
           arguments specified in the pragma. This pragma has the
           following syntax:

           #pragma define_template name < template-argument-list >

           For example, the following statement instructs the
           compiler to define the template mytempl with the arguments
           arg1 and arg2:

           #pragma define_template mytempl<arg1, arg2>

           For more information on how to use templates with the
           #pragma
           define_template directive, see Chapter 5.

     2.1.1.2 #pragma instantiate Directive

           The compiler provides several other pragmas that
           provide finer control over the instantiation process.
           Instantiation pragmas can be used to control the
           instantiation of specific template entities or sets of
           template entities. There are two instantiation pragmas:

           o  The instantiate pragma causes a specified entity to be
              instantiated, similar to the define_template pragma.
              It provides finer instantiation control than define_
              template when instantiating function templates.

           o  The do_not_instantiate pragma suppresses the instan-
              tiation of a specified entity. It is typically used
              to suppress the instantiation of an entity for which a
              specific definition will be supplied.

     2-2 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

              For more information on how to use templates with the
              #pragma instantiate directive, see Chapter 5.

        2.1.1.3 #pragma environment Directive

              The #pragma environment preprocessor directive offers a
              way to single-handedly set, save, or restore the states
              of context pragmas. This directive protects include files
              from contexts set by encompassing programs and protects
              encompassing programs from contexts that could be set in
              header files that they include.

              On Compaq Tru64 UNIX and Linux Alpha systems, the #pragma
              environment directive affects the following pragmas:

                 #pragma member_alignment/pack
                 #pragma message
                 #pragma extern_model
                 [Tru64] #pragma pointer_size/required_pointer_size
                 #pragma required_vptr_size

              This pragma has the following syntax:

              #pragma environment command_line
              #pragma environment header_defaults
              #pragma environment restore
              #pragma environment save

              command_line
              Sets, as specified on the command line, the states of all
              the context pragmas. You can use this pragma to protect
              header files from environment pragmas that take effect
              before the header file is included.

              header_defaults
              Sets the states of all the context pragmas to their
              default values for Compaq Tru64 UNIX and Linux Alpha
              systems. This is almost equivalent to the situation
              in which a program with no command-line options and
              no pragmas is compiled; except that this pragma sets
              the pragma message state to #pragma nostandard, as is
              appropriate for system header files.

              restore
              Restores the current state of every pragma that has an
              associated context.

                                           Compaq C++ Implementation 2-3

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

           save
           Saves the current state of every pragma that has an
           associated context.

           Someone who creates a general purpose library, distributed
           as an archive or shared library, typically distributes
           header files that specify the interface to the library.
           For calls to the library to work, the header file must
           normally use the same member alignment, pointer size,
           extern model, and other compilation options as when the
           library was built.

           The header file should contain pragmas to save the user's
           compilation options, set the correct compilation options
           for the library, and then restore the user's compilation
           options when the include file ends. The pragmas let
           library users choose whatever compilation options are
           appropriate for their own code without unintentionally
           affecting the interface to the library.

           Not only is the #pragma environment preprocessor directive
           more convenient than explicitly specifying each individual
           pragma that controls a compilation option, it is also
           upwardly compatible. As new pragmas are added to the
           compiler , #pragma environment header_defaults will be
           enhanced to set the state of the new pragmas to their
           default. Thus, a header file that uses #pragma environment
           sets a known state for not only the current pragmas in the
           compiler, but future pragmas as well.

           Without requiring further changes to the source code, you
           can use #pragma environment to protect header files from
           things like language extensions and enhancements that
           might introduce additional contexts.

           A header file can selectively inherit the state of a
           pragma from the including file and then use additional
           pragmas as needed to set the compilation to nondefault
           states. For example:






     2-4 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

              #ifdef __PRAGMA_ENVIRONMENT
              #pragma __environment save  1
              #pragma __environment header_defaults 2
              #pragma member_alignment restore 3
              #pragma member_alignment save 4
              #endif
              .
              .  /* contents of header file */
              .
              #ifdef __PRAGMA_ENVIRONMENT
              #pragma __environment restore
              #endif

              In this example:

              1  Saves the state of all context pragmas

              2  Sets the default compilation environment

              3  Pops the member alignment context from the #pragma
                 member_alignment stack that was pushed by #pragma
                 __environment save (restoring the member alignment
                 context to its preexisting state)

              4  Pushes the member alignment context back onto the stack
                 so that the #pragma __environment restore can pop off
                 the entry

              Thus, the header file is protected from all pragmas,
              except for the member alignment context that the header
              file was meant to inherit.

        2.1.1.4 #pragma extern_prefix Directive

              The The #pragma extern_prefix directive is an OpenVMS
              pragma that cannot be used on Compaq Tru64 UNIX and Linux
              Alpha systems.

        2.1.1.5 #pragma ident Directive

              The #pragma ident directive enables insertion of an
              identification string into the object and executable
              (usually a version number). The string can be found by
              using the strings command or, if the string contains a
              specific recognized substring, by using the what command.
              For more information on the strings and what commands, see
              the reference pages.

                                           Compaq C++ Implementation 2-5

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

           In version 4.n of Compaq's Compaq Tru64 UNIX, the contents
           of the string are placed in the .rconst section of the
           object file and in the executable. In the next major
           release of the operating system, the contents of the
           string are placed in the .comment section of the object
           and the executable. The .comment section is present in the
           executable on disk but is not mapped into virtural memory
           at load-time.

           The mcs command allows users to perform operations
           on the comment section .comment of (e)COFF object
           files. This section can contain information such
           as the "ident" string from a source file and other
           information used by components of the Compaq Tru64 UNIX
           development environment. Users can optionally add their
           own information to the comment section by using the mcs
           tool.

           For additional information, refer to the Revision Contol
           System (RCS) and Source Code Control System (SCCS)
           reference pages.

           The pragma has the following syntax:

           #pragma ident "user-defined string"

     2.1.1.6 #pragma [no]inline Directive

           This is a C pragma that cannot be used in C++. Use the
           inline keyword instead.

     2.1.1.7 #pragma [no]member_alignment Directive

           By default, the compiler aligns structure members so that
           members are stored on the next boundary appropriate to the
           type of the member; that is, bytes are on the next byte
           boundary, words are on the next word boundary, and so on.

           You can use the #pragma member_alignment preprocessor
           directive to explicitly specify member alignment. For
           example, using #pragma member_alignment aligns a long
           variable on the next longword boundary, and it aligns a
           short variable on the next word boundary.

           Using #pragma nomember_alignment causes the compiler
           to align structure members on the next byte boundary
           regardless of the type of the member. The only exception
           to this is for bit-field members.

     2-6 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

              If used, the nomember_alignment pragma remains in effect
              until the compiler encounters the member_alignment pragma.

              This pragma has the following syntax:

              #pragma member_alignment
              #pragma member_alignment save
              #pragma member_alignment restore
              #pragma nomember_alignment [base_alignment]

              When #pragma member_alignment is used, the compiler aligns
              structure members on the next boundary appropriate to
              the type of the member, rather than on the next byte. For
              example, a long variable is aligned on the next longword
              boundary; a short variable is aligned on the next word
              boundary. Consider the following example:

              #pragma nomember_alignment
              struct x {
                         char c;
                         int b;
                         };
              #pragma member_alignment

              struct y {
                        char c;       /*3 bytes of filler follow c */
                        int b;
                        };

              main ()

              {
                      printf( "The sizeof y is: %d\n", sizeof (struct y) );
                      printf( "The sizeof x is: %d\n", sizeof (struct x) );
              }

        When this example is executed, it shows the difference between
        #pragma member_alignment and #pragma nomember_alignment.

              The optional base_alignment parameter can be used to
              specify the base-alignment of the structure. Use one of
              the following keywords for the base_alignment:

                 byte (1 byte)
                 word (2 bytes)
                 longword (4 bytes)
                 quadword (8 bytes)

                                           Compaq C++ Implementation 2-7

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

              octaword (16 bytes)

           The #pragma member_alignment save and #pragma member_
           alignment restore directives can be used to save the
           current state of the member_alignment and to restore the
           previous state, respectively. This feature is necessary
           for writing header files that require member_alignment or
           nomember_alignment, or that require inclusion in a member_
           alignment that is already set.

     2.1.1.8 #pragma message Directive

           The #pragma message preprocessor directive controls the
           kinds of individual diagnostic messages or groups of
           messages that the compiler issues.

           Default severities used by the compiler can be changed
           only if they are informationals, warnings or discretionary
           errors. Attempts to change more severe severities are
           ignored. If a message severity has not been altered by
           the command line and is not currently being controlled by
           a pragma, the compiler checks to see whether the message
           severity should be changed because of the "quiet" state.
           If not, the message is issued using the default severity.

           Error message severities start out with command line
           severities applied to default compiler severities.
           Pragma message severities are then applied. In general,
           pragma severities override command line severities, which
           override default severities. The single exception this is
           that command line options can always be used to downgrade
           messages. However, command line options cannnot be used
           to raise the severity of messages currently controlled by
           pragmas.

           The #pragma message directive has the following syntax:

           #pragma message disable (message-list)
           #pragma message enable (message-list)
           #pragma message restore
           #pragma message save
           #pragma message error
           #pragma message informational
           #pragma message warning

     2-8 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

              disable
              Suppresses the compiler-issued messages specified in the
              message-list argument. The message-list argument can be
              any one of the following:

              o  A single message identifier

              o  The keyword for a single message group as follows:

                    all-All messages issued by the compiler
                    check-All messages about potentially poor coding
                    practices
                    portable-All messages about portability

              o  A single message identifier enclosed in parentheses

              o  A single message group name enclosed in parentheses

              o  A comma-separated list of message identifiers or group
                 names (freely mixed) enclosed in parentheses

              The message identifier is the name following the message
              text when the -verbose option is set. A D: preceding
              the message identifier indicates that the message is
              discretionary; that is, you can change its severity or
              disable it. For example, consider the following message:

              Non-void function "name" does not contain a return statement. (D:missingreturn).

              The message identifier is missingreturn. To prevent the
              compiler from issuing this message, use the following
              directive:

              #pragma message disable missingreturn

              enable
              Enables the compiler to issue the messages specified in
              the message-list argument.

              restore
              Restores the saved state of enabling or disabling compiler
              messages.

              save
              Saves the current state of enabling or disabling compiler
              messages.

                                           Compaq C++ Implementation 2-9

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

           The save and restore options are useful primarily within
           header files. See Section 2.1.1.4.

     2.1.1.9 #pragma module Directive

           When you compile source files to create an object file,
           the compiler assigns the first of the file names specified
           in the compilation unit to the name of the object file.
           The compiler adds the .o file extension to the object
           file. Internally, the operating system and the debugger
           recognize the object module by the file extension.

           To change the system-recognized module name and version
           number, use the #pragma module directive.

           You can find the module name and the module version number
           listed in the compiler listing file and the linker load
           map.

           You can use the #pragma module directive when compiling in
           any mode.

           The #pragma module directive has the following syntax:

           #pragma module identifier identifier

           #pragma module identifier string

           The first parameter must be an identifier and specifies
           the module name. This is primarily used by the linker on
           OpenVMS systems, but is also used in the heading of the
           listing file. The second parameter specifies the optional
           identification. See Section 2.1.1.5 for more information
           about this.

     2.1.1.10 #pragma once Directive

           The #pragma once preprocessor directive specifies that the
           header file is evaluated only once.

           The #pragma once directive has the following format:

           #pragma once


     2-10 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

        2.1.1.11 #pragma pack Directive

              The #pragma pack preprocessor directive specifies packing
              alignment for structure and union members. Whereas the
              packing alignment of structures and unions is set for
              an entire translation unit by the -ZpN (N = 1, 2, or 4)
              and the -nomember_align option, the packing alignment
              is set at the data-declaration level by the pack pragma.
              The pragma takes effect at the first structure or union
              declaration after the pragma is seen; the pragma has no
              effect on definitions.

              The #pragma pack directive has the following format:

              #pragma pack [(n)]

              When you use #pragma pack(n), where n is 1, 2, 4, 8, or
              16, each structure member after the first is stored on
              the smaller member type or n-byte boundaries. If you use
              #pragma pack without an argument, structure members are
              packed to the value specified by -Zp. The default -Zp
              packing size is -Zp8.

              The compiler also supports the following enhanced syntax:

              #pragma pack( [ [ { push | pop}, ] [ identifier, ] ] [ n ]
        )

              This syntax allows you to combine program components into
              a single translation unit if the various components use
              pack pragmas to specify different packing alignments.

              Each occurrence of a pack pragma with a push argument
              stores the current packing alignment on an internal
              compiler stack. The pragma's argument list is read from
              left to right. If you use push, the current packing
              value is stored. If you provide a value for n, that
              value becomes the new packing value. If you specify an
              identifier, a name of your choosing, the identifier is
              associated with the new packing value.

              Each occurrence of a pack pragma with a pop argument
              retrieves the value at the top of an internal compiler
              stack and makes that value the new packing alignment.
              If you use pop and the internal compiler stack is empty,
              the alignment value is that set from the command-line and
              a warning is issued. If you use pop and specify a value

                                          Compaq C++ Implementation 2-11

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

           for n, that value becomes the new packing value. If you
           use pop and specify an identifier, all values stored on
           the stack are removed from the stack until a matching
           identifier is found. The packing value associated with the
           identifier is also removed from the stack and the packing
           value that existed just before the identifier was pushed
           becomes the new packing value. If no matching identifier
           is found, the packing value set from the command line
           is used and a level-one warning is issued. The default
           packing alignment is 8.

           The pack pragma allows you to write header files that
           ensure that packing values are the same before and after
           the header file is encountered:

           /* File name: include1.h
           */
           #pragma pack( push, enter_include1 )
           /* Your include-file code ... */
           #pragma pack( pop, enter_include1 )
           /* End of include1.h */

           In the previous example, the current pack value is
           associated with the identifier enter_include1 and pushed,
           remembered, on entry to the header file. The pack pragma
           at the end of the header file removes all intervening
           pack values that may have occurred in the header file and
           removes the pack value associated with enter_include1. The
           header file thus ensures that the pack value is the same
           before and after the header file.

           The new functionality also allows you to use code, such
           as header files, that uses pack pragmas to set packing
           alignments that differ from the packing value set in your
           code:

           #pragma pack( push, before_include1 )
           #include "include1.h"
           #pragma pack( pop, before_include1 )

     In the previous example, your code is protected from any changes
     to the packing value that might occur in include.h.



     2-12 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

        2.1.1.12 #pragma pointer_size Directive [Tru64]

              The #pragma pointer_size preprocessor directive controls
              pointer size allocation for the following:

              o  References

              o  Pointers to member declarations

              o  Function declarations

              o  Array declarations

              For this pragma to have any effect, you must specify -
              xtaso, -xtaso_short, -vptr_size, or -vptr_size_short on
              the cxx command.

              This pragma has the following syntax:

              #pragma pointer_size {long|64}
              #pragma pointer_size {short|32}
              #pragma pointer_size restore
              #pragma pointer_size save

              long, or 64
              Sets as 64 bits all pointer sizes in declarations that
              follow this directive, until the compiler encounters
              another #pragma pointer_size directive.

              short, or 32
              Sets as 32 bits all pointer sizes in declarations that
              follow this directive, until the compiler encounters
              another #pragma pointer_size directive.

              restore
              Restores the saved pointer size from the pointer size
              stack.

              save
              Saves the current pointer size on a pointer size stack.

              The save and restore option are particularly useful for
              specifying mixed pointer support and for protecting header
              files that interface to older objects. Objects compiled
              with multiple pointer size pragmas will not be compatible
              with old objects, and the compiler cannot discern that
              incompatible objects are being mixed.

                                          Compaq C++ Implementation 2-13

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

           Use of short pointers is restricted to the Compaq C++ and
           the C compilers resident on Compaq Tru64 UNIX systems.
           Programs should not attempt to pass short pointers from
           C++ routines to routines written in any other language
           except the C programming language.

           Compaq C++ might require explicit conversion of short
           pointers to long pointers in applications that use short
           pointers. You should first port those applications in
           which you are considering using short pointers, and then
           analyze them to determine if short pointers would be
           beneficial.

           A difference in the size of a pointer in a function
           declaration is not sufficient to overload a function.

           The compiler issues an error-level diagnostic if:

           o  Two functions defined differ in argument types only
              with respect to pointer sizes.

           o  Two functions differ in return type only with respect
              to pointer size.

           o  The compiler encounters a member function that tries to
              overload another that differs only with respect to the
              pointer size of the this parameter.

     2.1.1.13 #pragma required_pointer_size Directive [Tru64]

           The #pragma required_pointer_size preprocessor directive
           controls pointer size allocation in the same way as
           #pragma pointer_size but without interaction with command-
           line options. This pragma is always enabled, whether or
           not you specify any pointer size options on the command
           line. The same syntax, precautions, and restrictions
           pertain as with #pragma pointer_size. Neither the pragma
           name nor its arguments are subject to macro expansion.

     2.1.1.14 #pragma required_vptr_size Directive [Tru64]

           The #pragma required_vptr_size preprocessor directive
           controls pointer size allocation in the same way as
           #pragma required_pointer_size, but it applies to virtual
           function pointers and virtual bases in a C++ class object.
           This pragma has the following syntax:

           #pragma required_vptr_size {long|64}

     2-14 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

              #pragma required_vptr_size {short|32}
              #pragma required_vptr_size restore
              #pragma required_vptr_size save

              The parameters have the same meaning as with #pragma
              required_pointer_size (see Section 2.1.1.12).

              The #pragma required_vptr_size directive takes effect at
              the opening brace of a class declaration. This pragma is
              always enabled, whether or not you specify any pointer
              size options on the command line.

        2.1.1.15 #pragma [no]standard Directive

              Use the #pragma nostandard and #pragma standard prepro-
              cessor directives to disable all but the most significant
              messages from header file processing.

              This pragma has the following syntax:

              #pragma [no]standard

              Use #pragma nostandard to mark the start of reduced
              message activity.

              Use #pragma standard to mark the resumption of normal
              message activity.

        2.1.2 Protecting System Header Files

              It is important to protect system header files from
              generating diagnostics and from user-specified changes
              to member alignment and pointer sizes.

              To provide the necessary protection you can do one of the
              following:

              o  Use a header file protection option provided by the
                 compiler.

              o  Modify each header file.




                                          Compaq C++ Implementation 2-15

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

     2.1.2.1 Using the Compiler's Header File Protection Option

           With this option, you can place special header files
           in a directory. the compiler processes these special
           header files before and after each file included with
           the #include directive from this directory. These special
           header files are named:

              __DECC_include_prologue.h
              __DECC_include_epilogue.h

           The compiler checks for files with these special names
           when processing #include directives. If the special
           prologue file exists in the same directory as a file
           with the #include directive, the contents of the prologue
           file are processed just before the file included with
           the #include directive. Similarly, if the epilogue file
           exists in the same directory as the file included with the
           #include directive, it is processed just after that file.

           For convenience, you can protect header files using the
           script supplied in the following directory:

           /usr/lib/cmplrs/cxx/protect_system_headers.sh

           This script creates, in all directories in a directory
           tree that contain header files, symbolic links to Compaq-
           supplied header prologue and epilogue files.

           The default directory tree root assumed by the script is
           /usr/include, but you can specify other roots.

     2.1.2.2 Modifying Each Header File

           If you choose to modify each header file that needs
           protection, you can use the #pragma environment directive,
           as in the following example:

           #pragma __environment save              // Save pointer size
           #pragma __environment header_defaults   // set to system defaults

           // existing header file

           #pragma__environment restore            // Restore pointer size

           See Section 2.1.1.3 for more information about using this
           pragma.

     2-16 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

        2.1.3 Predefined Macro Names

              The following tables list predefined C++ macros used
              by Compaq C++. These names are useful in preprocessor
              #ifdef and #if defined directives to isolate code intended
              for one of the particular cases. The names can be used
              anywhere you use other defined names, including within
              macros.

              For information on using predefined macros in header files
              in the common language environment, see Section 3.1.

              Table_2-1_Standard_Macro_Names____________________________

              __cplusplusefined by the C++ compiler when compiling
                        source code.

              __LINE__  The current line number (a decimal integer).

              __FILE__  The current file name (a character string).

              __DATE__  The source file's compilation date (a character
                        string literal of the form "Mmm dd yyyy", where
                        the month names are the same as those generated
                        by the asctime function, and the first character
                        of "dd" is a space character if the value is
                        less than 10.)

              __STDC__  [Linux] Compiler supports ANSI C language
                        constructs.

              __TIME__  The source file's compilation time (a character
                        string literal of the form "hh:mm:ss"), as in
              __________the_time_generated_by_the_asctime_function._____

              Table_2-2_System_Identification_Macro_Names_______________

              Macro_Name______________________Description_______________

              __alpha[1], __alpha__,          System has an Alpha
              __ALPHA                         processor.

              __arch64__                      System with 64-bit
                                              architecture.

              [1]Use_this_form_for_portability._________________________

                                                (continued on next page)

                                          Compaq C++ Implementation 2-17

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

           Table_2-2_(Cont.)_System_Identification_Macro_Names_______

           Macro_Name______________________Description_______________

           __digital__                     System identification name
                                           on Tru64 UNIX.

           __linux, __linux__[1]           System is a Linux Alpha
                                           system.

           linux                           [Linux] System is a Linux
                                           Alpha system. Provided
                                           for GNU compatibility;
                                           use of this macro is not
                                           recommended.

           __osf__                         System is a Tru64 UNIX
                                           system.

           __unix, __unix__                System is a UNIX system.

           unix                            [Linux] System is a UNIX
                                           system. Provided for GNU
                                           compatibility; use of this
                                           macro is not recommended.
           [1]Use_this_form_for_portability._________________________

           __________________________________________________________

           Table_2-3_Other_Predefined_Macro_Names____________________

           Macro_Name______________________Description_______________

           _BOOL_EXISTS                    Indicates that bool is a
                                           typedef or keyword

           __BOOL_IS_A_RESERVED_WORD       Indicates that bool is a
                                           keyword

           __DECCXX                        Compiler is Compaq C++.

           __DECCXX_VER                    Compiler version
                                           identifier in string form.

           __IEEE_FLOAT                    The compiler supports IEEE
                                           floating point.

                                             (continued on next page)

     2-18 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

              Table_2-3_(Cont.)_Other_Predefined_Macro_Names____________

              Macro_Name______________________Description_______________

              __INITIAL_POINTER_SIZE          [Tru64] A decimal constant
                                              containing the initial
                                              pointer size allocation,
                                              as specified by the
                                              command line. Legal
                                              values on Tru64 UNIX are:
                                              0 (no pointer size option
                                              set), 32 (short or 32-
                                              bit pointers allocated),
                                              and 64 (long or 64-bit
                                              pointers allocated). The
                                              only legal value on Linux
                                              Alpha is 0.

              __INTRINSICS                    Compaq C++ recognizes
                                              intrinsic functions.

              __LANGUAGE_C__, __LANGUAGE_C,   [Linux] Compiler
              LANGUAGE_C                      translates C language
                                              constructs and keywords.
                                              Provided for GNU
                                              compatibility; use of
                                              these macros is not
                                              recommended.

              _LONGLONG                       Compiler supports "long
                                              long" type declarations.

              __PRAGMA_ENVIRONMENT            The compiler supports
                                              pragma environment.

              __STDC_VERSION__                Version number of ANSI C
                                              support, in string form;
                                              not defined by the C++
                                              compiler.

              _SYSTYPE_BSD                    Compiler supports BSD type
                                              system headers.

                                                (continued on next page)

                                          Compaq C++ Implementation 2-19

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

           Table_2-3_(Cont.)_Other_Predefined_Macro_Names____________

           Macro_Name______________________Description_______________

           _WCHAR_T[1], __WCHAR_T[2]       wchar_t is a typedef or a
                                           keyword.

           __X_FLOAT                       System has default long
                                           double size of 128 bits.
           [1]Use_this_form_for_portability._________________________

           [2]This form is used on OpenVMS systems.
           __________________________________________________________

           Predefined Language Dialect Macro Names

           Table 2-4 shows the macro names defined by specifying the
           listed command-line options.

           Table_2-4_Language_Dialect_Macro_Names____________________

           Command-line_Option______Macro_Name_______________________

           -std arm                 __STD_ARM

           -std ansi                __STD_ANSI

           -std cfront, -cfront     __CFRONT, __STD_CFRONT

           -std gnu                 __STD_GNU

           -std ms, -ms             __MS, __STD_MS

           -std strict_ansi         __STD_STRICT_ANSI

           -std_strict_ansi_errors____STD_STRICT_ANSI_ERRORS_________

           Predefined Implementation Compatibility Macro Names

           Table 2-5 shows the macro names defined by specifying the
           listed command-line options.

           Table_2-5_Implementation_Compatibility_Macro_Names________

           Command-line_Option______Macro_Name_______________________

           -fprm                    __FLT_ROUNDS

           -global_array_new        __GLOBAL_ARRAY_NEW

                                             (continued on next page)

     2-20 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

              Table 2-5 (Cont.) Implementation Compatibility Macro
              __________________Names___________________________________

              Command-line_Option______Macro_Name_______________________

              -ieee                    __IEEE_FP

              -implicit_include        __IMPLICIT_INCLUDE_ENABLED

              -long_double_size        __X_FLOAT

              -model ansi              __MODEL_ANSI

              -model arm               __MODEL_ARM

              -pch,-create_pch,-use_   __PCH_ENABLED
              pch

              -pthreads                _REENTRANT

              -rtti                    __RTTI

              -stdnew                  __STDNEW

              -threads                 _REENTRANT, _PTHREAD_USED_D4

              -using_std_________________IMPLICIT_USING_STD_____________

              Predefined __DECCXX_VER Version Number Macro

              These macros provide an integer encoding of the compiler
              version-identifier string that is suitable for use in a
              preprocessor #if expression, such that a larger number
              corresponds to a more recent version.

              The format of the compiler version-identifier string is:

              TMM.mm-eee

              Where:

              o  T is the version type (letter).

              o  MM is the major version number.

              o  mm is the update (minor version number).

              o  eee is the edit suffix number.

              The format of the integer encoding for __DECCXX_VER is:

              vvuuteeee

              Where:

              o  vv is the major version number.

                                          Compaq C++ Implementation 2-21

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

           o  uu is the update (minor version number).

           o  t is the numerical encoding of the alphabetic version
              type from the version-identifier string.

              Table 2-6 lists the possible version types and their
              encodings

           o  eeee is the edit suffix number.

           Table_2-6___DECC_VER__Version-Type_Encodings______________

                Numerical
           Type_Encoding__Description________________________________

           T    6         Field-test version

           S    8         Customer special

           V____9_________Officially_supported_version_______________

           The following describes how the __DECCXX_VER integer
           value is calculated from the compiler version-identifier
           string:

           1. The major version is multiplied by 10000000.

           2. The minor version (the digits between the period (.)
              and any edit suffix) is multiplied by 100000 and added
              to the suffix value (the suffix value has a range of 0
              to 999).

           3. If the character immediately preceding the first digit
              of the major version number is one of those listed
              in Table 2-6, its numerical encoding is multiplied by
              10000.

           4. The preceding values are added together.

           The following examples show how different compiler
           version-identifier strings map to __DECCXX_VER encodings:

           ident           __DECCXX_VER
           string          vvuuteeee

           T5.2-003   -->   50260003
           V6.0-001   -->   60090001

     2-22 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                  2.1 Implementation-Specific Attributes

        2.1.4 Translation Limits

              The only translation limits imposed in the compiler are as
              follows:

              __________________________________________________________
              Limit__Meaning____________________________________________

              32,767 Characters in an internal identifier or macro name.

              32,767 Characters in a logical or physical source line.

              32,767 Bytes in the representation of a string literal.
                     This limit does not apply to string literals formed
                     by concatenation.

              32,767 Significant characters in an external identifier.
                     A warning is issued if such an identifier is
                     truncated. Linking further limits external
              _______identifiers_to_1022_characters.____________________

        2.1.5 Numerical Limits

              The numerical limits, as defined in the header files
              <limits.h> and <float.h>, are as follows:

              o  The number of bits in a character of the execution
                 character set is 8 bits.

              o  The representation and set of values for type char and
                 for type signed char are the same. You can change this
                 equivalence from signed char to unsigned char using the
                 -unsigned option (see the cxx(1) reference page).

              o  The representation and set of values for the short type
                 is 16 bits.

              o  The representation and set of values for the types int,
                 unsigned int, and float are 32 bits.

              o  The representation and set of values for type double
                 are 64 bits.

              o  The representation and set of values for type long
                 double is 128 bits on Compaq Tru64 UNIX Version 5.0
                 and later. You can change this equivalence using the
                 -long_double_size 64 option (see the cxx(1) reference
                 page).

                                          Compaq C++ Implementation 2-23

 



     Compaq C++ Implementation
     2.1 Implementation-Specific Attributes

           Numerical limits not described in this list are defined in
           the C++ International Standard.

     2.1.6 Argument-Passing and Return Mechanisms


           Even if an argument is declared pass by value, the
           compiler passes arrays, functions, and class objects
           that have non-trivial copy constructors or destructors
           by reference. In the first two cases, this behavior is
           defined by the language standard.

           Class objects have non-trivial copy constructors if they
           have user-declared copy constructors, or if they have
           virtual bases, virtual functions, or non-static data
           members that require virtual table initialization.

           In the case of a class with a non-trivial copy constructor
           or a destructor, the compiler calls a copy constructor
           to copy the object to a temporary location, and then
           it passes the address of that location to the called
           function. All other objects are passed by value.

           If the return value of a function is a class that has a
           non-trivial copy constructor or destructor or is greater
           than 64 bits, storage is allocated by the caller, and the
           address of this storage is passed in the first parameter
           to the called function. The called function uses the
           storage provided to construct the return value.

     2.2 Implementation Extensions and Features

           This section describes the extensions and implementation-
           specific features of Compaq C++ for Tru64 UNIX and Linux
           Alpha systems.

     2.2.1 Identifiers

           In Compaq C++, the dollar sign ($) is a valid character in
           an identifier.

           For each external function with C++ linkage, the compiler
           decorates the function name with a representation of the
           function's type.

     2-24 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                              2.2 Implementation Extensions and Features

        2.2.1.1 Character Limit for Long Names

              If an external name has more than 1022 characters, the
              compiler truncates the name to 1022 characters. The
              compiler keeps the first 1015 characters intact, reduces
              (hashes) the remaining characters to a string of 7
              characters, and appends the 7 hashed characters to the
              first 1015.

        2.2.2 Order of Static Object Initialization

              The order of static objects is defined by the implemen-
              tation. Relying on this order is not good programming
              practice. For Compaq C++, static objects are initialized
              in declaration order within a compilation unit. On Tru64
              UNIX the order across compilation units is the order on
              the link. On Linux Alpha, the order across compilation
              units is reversed. The order is a function of the linker,
              not the compiler, and is the same as G++ on Linux.

        2.2.3 Integral Conversions

              When demoting an integer to a signed integer, if the value
              is too large to be represented, the result is truncated
              and the high-order bits are discarded.

              Conversions between signed and unsigned integers of the
              same size involve no representation change.

        2.2.4 Floating-Point Conversions

              When converting an integer to a floating-point number that
              cannot exactly represent the original value, the compiler
              rounds off the result of the conversion to the nearest
              value that can be represented exactly.

              When the result of converting a floating-point number to
              an integer or other floating-point number at compile time
              cannot be represented, the compiler issues a diagnostic
              message.

              When converting an integral number or a double floating-
              point number to a floating-point number that cannot
              exactly represent the original value, the compiler rounds
              off the result to the nearest value of type float.

                                          Compaq C++ Implementation 2-25

 



     Compaq C++ Implementation
     2.2 Implementation Extensions and Features

           When demoting a double value to float, if the converted
           value is within range but cannot exactly represent the
           original value, the compiler rounds off the result to the
           nearest representable float value.

           The compiler performs similar rounding for demotions from
           long double to double or float.

     2.2.5 Explicit Type Conversion

           In Compaq C++, the expression T() (where T is a simple
           type specifier) creates an rvalue of the specified type,
           whose value is determined by default initialization.
           According to The C++ Programming Language, 3rd Edition,
           the behavior is undefined if the type is not a class with
           a constructor, but the ANSI working draft removes this
           restriction. With this change you can now write:

               int i=int(); // i must be initialized to 0

     2.2.6 The sizeof Operator

           The type of the sizeof operator is size_t. In the header
           file <stddef.h>, this type is defined as unsigned long,
           which is the type of the integer that holds the maximum
           size of an object.

     2.2.7 Explicit Type Conversion

           A pointer takes up the same amount of memory storage
           as objects of type long (or the unsigned equivalent).
           Therefore, a pointer can convert to any of these types and
           back again without changing its value. No scaling occurs
           and the representation of the value is unchanged.

           Conversions to and from a shorter integer and a pointer
           are similar to conversions to and from a shorter integer
           and unsigned long. If the shorter integer type was signed,
           conversion fills the high-order bits of the pointer with
           copies of the sign bit.





     2-26 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                              2.2 Implementation Extensions and Features

        2.2.8 Multiplicative Operators

              The semantics of the division (/) and remainder (%)
              operator are as follows:

              o  If either operand of the division operator is negative,
                 the compiler truncates the result toward 0 (that
                 is, the smallest integer larger than the algebraic
                 quotient).

              o  If either operand of the remainder operator is
                 negative, the result takes the same sign as that of
                 the first operand.

              In the following cases of undefined behavior detected at
              compile time, the compiler issues a warning:

                 Integer overflow
                 Division by 0
                 Remainder by 0

        2.2.9 Additive Operators

              You can subtract pointers to members of the same array or
              a pointer that points just past the end of an array. The
              result is the number of elements between the two array
              members, and is of type ptrdiff_t. In the header file
              <stddef.h>, the compiler defines this type as long.

        2.2.10 Shift Operators

              The expression E1 >> E2 shifts E1 to the right E2
              positions. If E1 has a signed type, the compiler fills
              the vacated high-order bits of the shifted value E1 with a
              copy of E1's sign bit (arithmetic shift).

        2.2.11 Equality Operators

              When comparing two pointers to members, the compiler
              guarantees equality if either of the following conditions
              hold:

              o  Both pointers are NULL.

              o  The same address expression (&) created both pointers.

                                          Compaq C++ Implementation 2-27

 



     Compaq C++ Implementation
     2.2 Implementation Extensions and Features

           When comparing two pointers to members, the compiler
           guarantees inequality if either of the following
           conditions hold:

           o  Only one pointer is NULL.

           o  Each pointer produces a different member if applied to
              the same object.

           When created by different address expressions, two
           pointers to members may compare either as equal or as
           unequal if they produce the same member when applied to
           the same object; otherwise, they are unequal.

     2.2.12 volatile Type Specifier

           For variables that are modifiable in ways unknown to the
           compiler, use the volatile type specifier. Declaring
           an object to be volatile means that every reference to
           the object in the source code results in a reference to
           memory. Volatile quantities are also referenced atomically
           in the hardware; that is, they are fetched and stored with
           single assembler instructions. Attempts to make a volatile
           quantity be declared as not aligned incurs a compiler
           error.

           Any object whose type includes the volatile type qualifier
           indicates that the object should not be subject to
           compiler optimizations altering references to, or
           modifications of, the object.

           Optimizations that are defeated by using the volatile
           specifier can be categorized as follows:

           o  Optimizations that alter an object's duration; for
              example, cases where references to the object are
              shifted or moved to another part of the program.

           o  Optimizations that alter an object's locality; for
              example, cases where a variable serving as a loop
              counter is stored in a register to save the cost of
              doing a memory reference.

           o  Optimizations that alter an object's existence;
              for example, loop induction to actually eliminate a
              variable reference.

     2-28 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                              2.2 Implementation Extensions and Features

              An object without the volatile specifier does not
              compel the compiler to perform these optimizations; it
              indicates that the compiler has the freedom to apply the
              optimizations depending on program context and compiler
              optimization level.

              The volatile specifier forces the compiler to allocate
              memory for the volatile object, and to always access
              the object from memory. This qualifier is often used
              to declare that an object can be accessed in some way
              not under the compiler's control. Therefore, an object
              qualified by the volatile keyword can be modified or
              accessed in ways by other processes or hardware, and is
              especially vulnerable to side effects.

              The following rules apply to the use of the volatile
              specifier:

              o  The volatile specifier can be used to qualify any
                 data type, including a single member of a structure
                 or union.

              o  Redundant use of the volatile keyword elicits a warning
                 message. For example:

                 volatile volatile int x;

              o  When volatile is used with an aggregate type declara-
                 tion, all members of the aggregate type are qualified
                 with volatile. When volatile is used to qualify a
                 member of an aggregate type, only that member is
                 qualified. For example:

                 volatile struct employee {
                     char *name;
                     int   birthdate; /* name, birthdate, job_code, and salary are */
                     int   job_code;  /* treated as though declared with volatile. */
                     float salary;
                     } a,b;          /*  All members of a and b are volatile-qualified  */

                 struct employee2 {
                     char *name;
                     volatile int birthdate;  /*  Only this member is qualified    */
                     int job_code;
                     float salary;
                     } c, d;

                                          Compaq C++ Implementation 2-29

 



     Compaq C++ Implementation
     2.2 Implementation Extensions and Features

              If the tag employee is used to specify another
              structure later in the program, the volatile specifier
              does not apply to the new structure's members unless
              explicitly specified.

              The const specifier can be used with the volatile spec-
              ifier. This is useful, for example, in a declaration of
              a data object that is immutable by the source process
              but can be changed by other processes, or as a model of
              a memory-mapped input port such as a real-time clock.
              The address of a non-volatile object can be assigned
              to a pointer that points to a volatile object. For
              example:

              const int *intptr;
              volatile int x;
              intptr = &x;

              Likewise, the address of a volatile object can be
              assigned to a pointer that points to a non-volatile
              object.

     2.2.13 __unaligned  Type Specifier

           Use this data-type specifier in pointer definitions to
           indicate to the compiler that the data pointed to is not
           properly aligned on a correct address. (To be properly
           aligned, the address of an object must be a multiple of
           the size of the type. For example, two-byte objects must
           be aligned on even addresses.)

           When data is accessed through a pointer declared
           __unaligned, the compiler generates the additional
           code necessary to copy or store the data without causing
           alignment errors. It is best to avoid use of misaligned
           data altogether, but in some cases the usage may be
           justified by the need to access packed structures, or
           by other considerations.

           Here is an example of a typical use of __unaligned:





     2-30 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                              2.2 Implementation Extensions and Features

              typedef enum {int_kind, float_kind, double_kind} kind;
              void foo(void *ptr, kind k) {
                  switch (k) {
                  case int_kind:
                      printf("%d", *(__unaligned int *)ptr);
                      break;
                  case float_kind:
                      printf("%f", *(__unaligned float *)ptr);
                      break;
                  case double_kind:
                      printf("%f", *(__unaligned double *)ptr);
                      break;
                  }
              }

        2.2.14 Linkage Specifications

              Specifying linkage other than "C++" or "C" generates a
              compile-time error.

              In object files, the compiler decorates with type
              information the names of functions with C++ linkage. This
              permits overloading and provides rudimentary type checking
              across compilation units. The type-encoding algorithm used
              is similar to that given in 7.2.1c of The Annotated C++
              Reference Manual.

        2.2.15 Temporary Objects

              The compiler creates temporary objects for class objects
              with constructors:

              o  An object is returned from a function.

              o  An object is passed as an argument.

              o  An object is created using the constructor notation.

              o  A user-defined conversion is implicitly used.

              Variations in the compiler generation of such temporary
              objects can adversely affect their reliability in user
              programs. The compiler avoids introducing a temporary
              object whenever it discovers that the temporary object is
              not needed for accurate compilation. Therefore, you should
              modify or write your programs so as not to depend on side

                                          Compaq C++ Implementation 2-31

 



     Compaq C++ Implementation
     2.2 Implementation Extensions and Features

           effects in the constructors or destructors of temporary
           objects.

     2.2.15.1 Nonconstant Reference Initialization with a Temporary
              Object

           If your program tries to initialize a nonconstant
           reference with a temporary object, the compiler generates
           a warning. For example:

           struct A {
             A(int);
           };
           void f(A& ar);

           void g() {
             f(5);  // warning!!
           }

     2.2.16 Exception Handling

           The compiler optimizes the implementation of exception
           handling for normal execution, as follows:

           o  Applications that do not have exception handlers incur
              no overhead.

           o  Applications with handlers that run without causing
              exceptions incur only slight overhead:

              -  The size of an executable image increases slightly
                 because of the tables that describe the handlers.

              -  Code optimization is less aggressive in the presence
                 of handlers.

           o  As much as possible, overhead for exceptions is
              incurred when throwing an exception. Entering or
              leaving a try block incurs no overhead.

           In Compaq C++, a procedure with handlers has no intrinsic
           overhead. For example, procedures with handlers do not
           have frame pointers or additional register usage.

           Some procedures without explicit handlers may have
           implicit handlers. The compiler creates a handler for
           each automatic object that has a destructor. The compiler
           also creates handlers for constructors that initialize
           subobjects that have destructors. In such a constructor,

     2-32 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                              2.2 Implementation Extensions and Features

              the compiler creates a handler for each member with a
              destructor, and a handler for each base class with a
              destructor.

              The -nocleanup option suppresses generation of such
              implicit handlers, which results in an executable file
              that is slightly smaller. You should use this option for
              programs that do not use exception handling or that do not
              require destruction of automatic objects during exception
              processing.

              Exception specifications in function prototypes that
              conflict with function definitions are illegal. Chapter 8
              describes how the compiler handles such conflicts. Beware
              of such conflicting exception specifications, particularly
              if you have exception specifications in prototypes that
              are in header files accessible to other programs.

        2.2.17 File Inclusion

              The #include directive inserts external text into the
              source stream delivered to the compiler. Programmers
              often use this directive to include global definitions for
              use with Compaq C++ functions and macros in the program
              stream.

              The #include directive has the following search path
              semantics:

              o  Quoted path names:

                 1. Quoted path names are first searched for in the
                    directory that contains the file with the #include
                    directive.

                 2. If the file is not found, the search continues to
                    the list of directories specified on the command
                    line with the -I directoryname compiler option, in
                    order.

                 3. If the file is still not found, the compiler
                    searches the /usr/include/cxx and /usr/include
                    directories.


                                          Compaq C++ Implementation 2-33

 



     Compaq C++ Implementation
     2.2 Implementation Extensions and Features

           o  Angle-bracketed files are searched for in the list
              of directories specified on the command line, then in
              the /usr/include/cxx directory, and finally, in the
              /usr/include directory.

     2.2.18 Nested Enums and Overloading

           The C++ language allows programmers to give distinct
           functions the same name, and uses either overloading or
           class scope to differentiate the functions:

           void f(int);
           void f(int *);
           class C {void f(int);};
           class D {void f(int);};

           All compilers, including Compaq C++, use name mangling
           to assign unique names to these functions. These unique
           mangled names allow the linker to tell the overloaded
           functions apart.

           The compiler forms a mangled name by appending an encoding
           of the parameter types of the function to the function's
           name. If the function is a member function, the compiler
           qualifies the function name by the names of the classes
           within which it is nested.

           For example, for the function declarations at the
           beginning of this section, the compiler generates the
           mangled names f__Xi, f__XPi,  f__1CXi, and f__1DXi
           respectively. In these names, i means a parameter type
           was int, P means "pointer to", 1C means nested within
           class C, and 1D means nested within class D.

           There is a flaw in the name mangling scheme used by the
           compiler that can cause problems in uncommon cases. The
           compiler fails to note in the encoding of an enum type in
           a mangled name whether the enum type was nested within a
           class. This can cause distinct overloaded functions to be
           assigned the same mangled name:





     2-34 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                              2.2 Implementation Extensions and Features

              #include <stdlib.h>
              struct C1 {enum E {red, blue};};
              struct C2 {enum E {red, blue};};

              extern "C" int printf(const char *, ...);
              void f(C1::E x) {printf("f(C1::E)\n");}
              void f(C2::E x) {printf("f(C2::E)\n");}

              int main()
              {
                  f(C1::red);
                  f(C2::red);
                  return EXIT_SUCCESS;
              }

              In the previous example, the two overloaded functions
              named f differ only in that one takes an argument of enum
              type C1::E and the other takes an argument of enum type
              C2::E. Because the compiler fails to include the names
              of the classes containing the enum type in the mangled
              name, both functions have mangled names that indicate the
              argument type is just E. This causes both functions to
              receive the same mangled name.

              In some cases, the compiler detects this problem at
              compile-time and issues a message that both functions
              have the same type-safe linkage. In other cases, the
              compiler issues no message, but the linker complains about
              duplicate symbol definitions.

              If you encounter such problems, you can recompile using
              the
              -distinguish_nested_enums command line switch. This causes
              the compiler to include the name of class or classes that
              an enum is nested within when forming a mangled name. This
              eliminates cases where different functions receive the
              same mangled name.

              Because the -distinguish_nested_enums command-line switch
              changes the external symbols the compiler produces, you
              can get undefined symbol messages from the linker if some
              modules are compiled with -distinguish_nested_enums
              and some are compiled without it. Because of this,
              -distinguish_nested_enums might make it difficult to link
              against old object files or libraries of code.

                                          Compaq C++ Implementation 2-35

 



     Compaq C++ Implementation
     2.2 Implementation Extensions and Features

           If you compile your code with -distinguish_nested_enums
           and try to link against a library that was compiled
           without the -distinguish_nested_enums command line switch,
           you will receive an undefined symbol message from the
           linker if you attempt to call a function from the library
           that takes an argument of a nested enum type. The mangled
           name of the function in the library will be different from
           the mangled name your code is using to call the function.

     2.2.19 Guiding Declarations

           A guiding declaration is a function declaration that
           matches a function template, does not introduce a function
           definition (implies an instantiation of the template
           body and not a explicit specialization), and is subject
           to different argument matching rules than those that
           apply to the template itself-therefore affecting overload
           resolution. Consider the following example:

           template  void f(T) { ... }
           void f(int);                // guiding declaration in non strict_ansi mode

           Because there is no concept of guiding declaration in
           the current version of the C++ International standard,
           guiding_decls_allowed is FALSE by default. This means,
           in the example above, that function f is not regarded as
           an instance of function template f. Furthermore, it means
           that there are two functions named f that take an int
           parameter: the one that is explicitly declared, and the
           one that is an instance of the template. A call of f(0)
           would invoke the former, whereas a call of f<>(0) would be
           required to invoke the latter.

     2.3 Run-time Type Identification

           The compiler emits type information for run-time type
           identification (RTTI) in the object module with the
           virtual function table, for classes that have virtual
           function tables.

           You can specify the -[no]rtti option to enable or
           disable support for RTTI (runtime type identification)
           features: dynamic_cast and typeid. Disabling runtime type
           identification can also save space in your object file
           because static information to describe polymorphic C++

     2-36 Compaq C++ Implementation

 



                                               Compaq C++ Implementation
                                        2.3 Run-time Type Identification

              types is not generated. The default is to enable runtime
              type information features and generate static information
              in the object file.

              Specifying -nortti does not disable exception handling.

              The type information for the class may include references
              to the type information for each base class and informa-
              tion on how to convert to each. The typeinfo references
              are mangled in the form __T__<class>.

        2.4 Message Control Options

              The compiler supports the following message control
              options. The options apply only to discretionary, warning,
              and informational messages. The tag variable can be the
              keyword all, a tag obtained from -msg_display_tag, or a
              number obtained from -msg_display_number. The tag variable
              is preferred.

              -msg_inform tag,...
              Reduce message(s) severity to informational.

              -msg_warn tag,...
              Reduce message(s) severity to warning.

              -msg_error tag,...
              Increase message(s) severity to error

              -msg_enable tag,...
              Enable specific messages that would normally not be
              issued. You can also use this option to re-enable messages
              disabled with -msg_disable.

              -msg_disable tag,...
              Disable message. Can be used for any nonerror message.

              -msg_quiet
              Be more like Version 5.n error reporting. Fewer messages
              are issued using this option. This is the default in arm
              mode (-std arm). All other modes default to -nomsg_quiet.

              You can use the msg_enable option with this option
              to enable specific messages normally disabled using
              -msg_quiet.

                                          Compaq C++ Implementation 2-37

 



     Compaq C++ Implementation
     2.5 Message Information Options

     2.5 Message Information Options

           The compiler supports the following message information
           options. Both are disabled by default.

              ________________________Note ________________________

              "D" (meaning discretionary) indicates that the
              severity of the message can be controlled from the
              command line. The message number can be used as
              the tag in the message control options described
              in Section 2.4. If "D" is not displayed with the
              message number, any attempt to control the message
              is ignored.

              _____________________________________________________

           -msg_display_tag
           A more descriptive tag is issued at the end of each
           message issued. "D" indicates the severity of the message
           can be controlled from the command line. The tag displayed
           can be used as the tag in the message control options
           described in Section 2.4.

           Example:

           cxx -msg_display_tag t.cxx
           cxx: ... is nonstandard ("int" assumed) (D:nonstd_implicit_int)
           cxx -msg_disable nonstd_implicit_int  t.cxx

           Note that you can change the severity of a diagnostic
           message if the message is discretionary. For example,
           -msg_inform nonstd_implicit_int changes the severity to an
           informational. These options interact with -w0, -w1, and
           -w2.

           -msg_display_number
           The error number is displayed at the beginning of each
           message issued.

           Example:

           cxx -msg_display_number t.cxx
           cxx: Warning: t.cxx, line 1: #117-D non-void function "f" ...
           cxx -msg_disable 117 t.cxx

     2-38 Compaq C++ Implementation

 









                                                                       3
        ________________________________________________________________

                                         Compaq C++ Language Environment



              This chapter describes the guidelines and procedures
              for customizing your language environment. It includes
              sections on changing your C header files to work with
              C++, using 32-bit pointers, organizing your C++ files,
              interfacing to other programming languages, and designing
              upwardly compatible C++ classes.

        3.1 Using Existing C Header Files

              C header files that already conform to ANSI C standards
              must be slightly modified for use by Compaq C++ programs.
              In particular, be sure to address the following issues:

              o  Enable the proper linkage for each language.

              o  Ensure that C++ keywords are not used as identifiers.

              o  Reconcile any name space and scoping differences.

              The following sections provide details on how to properly
              modify your header files.

        3.1.1 Providing C and C++ Linkage

              To modify header files, use conditional compilation and
              the extern specifier.

              When programming header files to be used for both C and
              C++ programs, use the following convention for predefined
              macros. The system header files also provide an example of
              correct usage of the predefined macros.




                                     Compaq C++ Language Environment 3-1

 



     Compaq C++ Language Environment
     3.1 Using Existing C Header Files

           #if defined __cplusplus
               /* If the functions in this header have C linkage, this
                * will specify linkage for all C++ language compilers.
                */
               extern "C" {
           #endif
           extern int func1(int);
           extern int func2(int);
              .
              .
              .
           #if defined __cplusplus
               }   /* matches the linkage specification at the beginning. */
           #endif

           See The C++ Programming Language, 3rd Edition for more
           information on linkage specifications.

           The C compiler has special built-in macros defined in
           the header files <stdarg.h> and <varargs.h>. These step
           through the argument list of a routine.

           Programs that take the address of a parameter, and use
           pointer arithmetic to step through the argument list to
           obtain the value of other parameters, assume that all
           arguments reside on the stack and that arguments appear
           in increasing order. These assumptions are not valid for
           Compaq C++.

           The macros in <varargs.h> can be used only by C functions
           with old-style definitions that are not legal in C++.
           To reference variable-length argument lists, use the
           <stdarg.h> header file.

     3.1.2 Resolving C++ Keyword Conflicts

           If your program uses any of the following C++ language
           keywords as identifiers, you must replace them with
           nonconflicting identifiers:

           asm         bool        catch             class
           const_cast  delete      dynamic_cast      explicit
           export      false       friend            inline
           mutable     namespace   new               operator

     3-2 Compaq C++ Language Environment

 



                                         Compaq C++ Language Environment
                                       3.1 Using Existing C Header Files


              private     protected   public            reinterpret_cast
              static_     template    this              throw
              cast
              true        try         typeid            typename
              virtual     wchar_t


        3.2 Using Compaq C++ with Other Languages

              The following are suggestions regarding the use of Compaq
              C++ with other languages:

              o  Passing entities, such as classes, by reference is
                 safest.

              o  You cannot invoke class member functions from within
                 any language other than C++.

              o  Every C++ routine that will be called from the other
                 language should be declared in C++ with extern "C". For
                 example:

                 extern "C"
                    int myroutine(int, float);

                 The extern "C" will cause the routine to have an
                 unmangled name, so that you can refer to it as
                 myroutine from a language such as Cobol or Fortran.
                 Otherwise the routine's link name will be mangled into
                 something like myrout__Xif.

              o  If the main routine is defined in the other language,
                 you will probably need to use the other language's
                 command-line interface to perform your link step. To
                 include the appropriate C++ libraries and startup file,
                 you will need to add some arguments to the command
                 line. The most reliable way to determine what is needed
                 is to test with a small C++ program as follows:

                 cxx -c tiny.cxx
                 cxx -v tiny.o

                 The -v option causes the compiler to display the
                 command line passed to the C driver when it links
                 tiny.o.

                                     Compaq C++ Language Environment 3-3

 



     Compaq C++ Language Environment
     3.2 Using Compaq C++ with Other Languages

              The following is an example of the resulting display on
              Compaq Tru64 UNIX and Linux Alpha Version 4.0 systems
              or higher:

              /usr/lib/cmplrs/cxx/cc -G 8 -g0 -O1 -call_shared \
                      /usr/lib/cmplrs/cxx/_main.o tiny.o -v -lcxxstd -lcxx -lexc \
                      |& /usr/lib/cmplrs/cxx/demangle

              This invokes the linker as follows:

              /usr/lib/cmplrs/cc/ld -g0 -O1 -call_shared /usr/lib/cmplrs/cc/crt0.o \
                      /usr/lib/cmplrs/cxx/_main.o tiny.o -lcxxstd -lcxx -lexc -lc

              In this example, for your link step involving a
              language other than C++, you would add the following to
              the command line:

              /usr/lib/cmplrs/cxx/_main.o -lcxxstd -lcxx -lexc

              If your language uses the linker directly, you would
              also need to add the following:

              /usr/lib/cmplrs/cc/crt0.o  . . .  -lc

     3.3 Linkage to Non-C++ Code and Data

           With linkage specifications, you can both import code and
           data written in other languages into a Compaq C++ program
           and export Compaq C++ code and data for use with other
           languages. See The C++ Programming Language, 3rd Edition
           for details on the extern "C" declaration.

     3.4 How to Organize Your C++ Code

           This section explains the best way for Compaq C++ users
           to organize an application into files; it assumes that
           you are using automatic instantiation to instantiate any
           template classes and functions.

     3.4.1 Code That Does Not Use Templates

           The general rule is to place declarations in header
           files and place definitions in library source files. The
           following items belong in header files:

           o  Class declarations

           o  Global function declarations

     3-4 Compaq C++ Language Environment

 



                                         Compaq C++ Language Environment
                                       3.4 How to Organize Your C++ Code

              o  Global data declarations

              o  Inline function definitions

              The following items belong in library source files:

              o  Static member data definitions

              o  Out-of-line member function definitions

              o  Out-of-line global function definitions

              o  Global data definitions

              Header files should be directly included by modules that
              need them. Because several modules may include the same
              header file, a header file must not contain definitions
              that would generate multiply defined symbols when all the
              modules are linked together.

              Library source files should be compiled individually and
              then linked into your application. Because each library
              source file is compiled only once, the definitions it
              contains will exist in only one object module and multiply
              defined symbols are thus avoided.

              For example, to create a class called "array" you would
              create the following two files:

              Header file, array.h:

              // array.h
              #ifndef ARRAY_H
              #define ARRAY_H

              class array {
              private:
                      int curr_size;
                      static int max_array_size;
              public:
                      array() :curr_size(0) {;}
                      array(int);
              };

              #endif

                                     Compaq C++ Language Environment 3-5

 



     Compaq C++ Language Environment
     3.4 How to Organize Your C++ Code

           Library source file, array.cxx:

           // array.cxx
           #include "array.h"

           int array::max_array_size = 256;

           array::array(int size) :  curr_size(size) {  . . . ;  }

           You would then compile the array.cxx library source file
           using the following command:

           cxx array.cxx

           The resulting object file could either be linked directly
           into your application or placed in a library (see
           Section 3.4.3).

           Note that the header file uses header guards, which is a
           technique to prevent multiple inclusion of the same header
           file.

     3.4.2 Code That Uses Templates

           With the widespread use of templates in C++, determining
           the proper place to put declarations and definitions
           becomes more complicated.

           The general rule is to place template declarations and
           definitions in header files, and to place specializations
           in library source files.

           Thus, the following items belong in template declaration
           files:

           o  Declarations of global function templates

           o  Declarations of class templates

           o  Declarations of global function template specializa-
              tions

           o  Declarations of class template specializations

           The following items can be placed either in the header
           file with the corresponding template declaration or in
           a separate header file that can be implicitly included
           when needed. This file has the same basename as the
           corresponding declaration header file, with a suffix
           that is found by implicit inclusion. For example, if

     3-6 Compaq C++ Language Environment

 



                                         Compaq C++ Language Environment
                                       3.4 How to Organize Your C++ Code

              the declaration is in the header file inc1.h, these
              corresponding definitions could be in file inc1.cxx.

              o  Definitions of out-of-line global function templates

              o  Definitions of static member data of class templates

              o  Definitions of out-of-line member functions of class
                 templates

              The following must be placed in library source files to
              prevent multiple definition errors:

              o  Definitions of global function template specializations

              o  Definitions of static member data specializations of
                 class templates

              o  Definitions of out-of-line class member function
                 specializations

              These guidelines also apply to nontemplate nested classes
              inside of template classes.

                ________________________Note  ________________________

                Do not place definitions of nontemplate class
                members, nontemplate functions, or global data
                within template header files; these must be placed
                in library source files.

                _____________________________________________________

              All these header files should use header guards, to
              ensure that they are not included more that once either
              explicitly or by implicit inclusion.

              For example, the array class from Section 3.4.1, modified
              to use templates, could now look as follows:

              Template declaration file array.h:

               // array.h

               #ifndef ARRAY_H
               #define ARRAY_H

                                     Compaq C++ Language Environment 3-7

 



     Compaq C++ Language Environment
     3.4 How to Organize Your C++ Code

            template <class T>
            class array {
            private:
                    int curr_size;
                    static int max_array_size;
            public:
                    array() :curr_size(0) {;}
                    array(T);
            };

            #endif

           Template definition file array.cxx:

            // array.cxx
            template <class T>
            int array<T>::max_array_size = 256;

            template <class T>
            array<T>::array(int size) :  curr_size(size) { ; }

           You would then create, as follows, the source file
           myprog.cxx that uses the array class:

            // myprog.cxx

            #include <array.h>

            main() {
                    array<int> ai;

                    // ...
            }

     3.4.3 Creating Libraries

           Libraries are useful for organizing the sources within
           your application as well as for providing a set of
           routines for other applications to use. Libraries can
           be either object libraries or shareable libraries. Use
           an object library when you want the library code to be
           contained within an application's image; use shareable
           libraries when you want multiple applications to share the
           same library code.

           Creating a library from nontemplate code is straight-
           forward: you simply compile each library source file and
           place the resulting object file in your library.

     3-8 Compaq C++ Language Environment

 



                                         Compaq C++ Language Environment
                                       3.4 How to Organize Your C++ Code

              Creating a library from template code requires that you
              explicitly request the instantiations that you want to
              provide in your library. Alternatively, if automatic
              template instantiation has been used, the instantiation
              object files in the repository can be placed in your
              library. See Chapter 7 for details.

              If you make your library available to other users,
              you must also supply the corresponding declarations
              and definitions that are needed at compile time. For
              nontemplate interfaces, you must supply the header files
              that declare your classes, functions, and global data.
              For template interfaces, you must provide your template
              declaration files as well as your template definition
              files.

              For more information on creating libraries, see the ar(1)
              reference page and the loader(1) reference page.

        3.5 Using 32-bit Pointers (xtaso)

              Normally, Compaq C++ uses 64 bits for all pointers in
              generated code. The Extended Truncated Address Support
              Option (xtaso), and other #pragma directives and compiler
              options, let code with 32-bit pointers coexist within this
              64-bit operating system environment. Such a capability can
              be useful when the data layout used for pointers must be
              compatible with the layout on a 32-bit processor.

              The 32-bit pointer data type lets application developers
              minimize the amount of memory used by dynamically
              allocated pointers. Using 32-bit pointers can sometimes
              improve performance if the volume of data occupied by
              pointers is large. In certain instances, the capability
              can be helpful in porting applications that contain
              assumptions about pointer sizes, although the following
              precautions apply:

              o  Mixing 32-bit and 64-bit pointers may introduce new
                 porting problems if the data structures in system
                 libraries still use 64-bit pointers.




                                     Compaq C++ Language Environment 3-9

 



     Compaq C++ Language Environment
     3.5 Using 32-bit Pointers (xtaso)

           o  Anyone who supplies object modules (or libraries)
              compiled with 32-bit pointers thereby restricts users
              of those objects to the use of 32-bit pointers and
              requires those users to be aware of the difficulties of
              using 32-bit pointers in a mixed 32/64-bit environment.

           To use 32-bit pointers, you must use a combination of
           #pragma preprocessor directives and command-line compiler
           options. These #pragmas are described in Section 2.1.1 and
           are summarized in the following table:

           __________________________________________________________
           #pragma_Directive___Description___________________________

           pointer_size        Controls the pointer size of all
                               pointers except virtual function and
                               virtual base pointers in a C++ class
                               object.

                               Has an effect only if you specify one
                               or more of the pointer-size compiler
                               options.

           required_pointer_   Has the same effect as #pragma
           size                pointer_size but is always enabled,
                               whether or not you specify any
                               pointer-size compiler options.

           required_vptr_size  Controls the size of virtual function
                               and virtual base pointers in a C++
                               class object.

                               Always enabled, whether or not you
                               specify any pointer size compiler
           ____________________options.______________________________

           The pointer size compiler options are -xtaso, -xtaso_
           short, -vptr_size, and -vptr_size_short. Whenever any
           of these options are specified on the command line, the
           following actions occur:

           o  #pragma pointer_size is enabled. This pragma has an
              effect only if you specify a pointer size compiler
              option on the command line.

     3-10 Compaq C++ Language Environment

 



                                         Compaq C++ Language Environment
                                       3.5 Using 32-bit Pointers (xtaso)

              o  The cxx command automatically passes the -taso option
                 to the linker. This option causes the linker to load
                 the executable in the lower 31-bit addressable virtual
                 address range and causes memory allocations to be made
                 from the same virtual address page. Thus, your program
                 is limited to a 31-bit virtual address space whenever
                 you use any of the pointer-size compiler options.

              Individually, the pointer size options have following
              effects:

              __________________________________________________________
              Compiler_Option___Description_____________________________

              -xtaso            Sets the default pointer size of the
                                compilation unit to 64 bits (for all
                                pointers except virtual function and
                                virtual base pointers in a C++ class
                                object). This is the normal default
                                unless overridden by -xtaso_short.

              -xtaso_short      Sets the default pointer size of the
                                compilation unit to 32 bits (for all
                                pointers except virtual function and
                                virtual base pointers in a C++ class
                                object).

              -vptr_size        Makes 64 bits the default size of
                                virtual function and virtual base
                                pointers in a C++ class object. This
                                is the normal default unless overridden
                                by -vptr_size_short.

              -vptr_size_short  Makes 32 bits the default size of
                                virtual function and virtual base
              __________________pointers_in_a_C++_class_object._________

              You cannot reset the size of the this pointer. The this
              pointer always remains the system default pointer size,
              which is 64 bits.

              When using these #pragma directives and compiler options,
              you must take particular care if you call functions in
              any library compiled with different pointer sizes. The
              approaches that you can use to mix 32- and 64-bit pointers
              are as follows:

                                    Compaq C++ Language Environment 3-11

 



     Compaq C++ Language Environment
     3.5 Using 32-bit Pointers (xtaso)

           1. Make 64 bits the default pointer size and use 32-bit
              pointers for particular declarations.

           2. Make 32 bits the default pointer size.

           The second approach generally is more difficult because
           of problems in combining your code with code that expects
           64-bit pointers. The sections that follow discuss these
           approaches in more detail.

           Approach 1: Making 64 bits the default pointer size

           With this approach, most pointers in your application are
           64 bits, and 32 bits are used for selected pointers. To
           use this approach, you must compile with -xtaso to enable
           #pragma pointer_size and cause the cxx command to pass
           -taso to the linker.

           You use #pragma pointer_size, #pragma required_pointer_
           size, and #pragma required_vptr_size to control the
           pointer sizes for particular declarations. For example,
           to save space in an object, you can declare a class as
           follows:

           #pragma pointer_size save
           #pragma required_vptr_size save
           #pragma pointer_size short
           #pragma required_vptr_size long
                   class Table_Node {
                           char *table;    // 32-bit pointers
                           Table_Node *next;
                           Table_Node *(Table_Node::*search)(char *);
                                           // pointer to member has
                                           // 2 32-bit fields
                   public:
           #pragma pointer_size long
                           void insert_node(char *);
                           Table_Node *extract_node(char *);
                           Table_Node *search_forward(char *);
                           Table_Node *search_backward(char *);
                   };
           #pragma pointer_size restore
           #pragma required_vptr_size restore


     3-12 Compaq C++ Language Environment

 



                                         Compaq C++ Language Environment
                                       3.5 Using 32-bit Pointers (xtaso)

              With this approach, you must take care to specify the
              pointer size #pragma directives after any #include
              directives, so that header files that assume 64-bit
              pointer sizes are not affected.

              Approach 2: Making 32 bits the default pointer size

              To use this approach, compile using the -xtaso_short and
              -vptr_size_short options on the cxx command. With this
              approach, the default pointer size is 32 bits; you must
              take care when interfacing to code that expects 64-bit
              pointers.

              Specifically, you must protect header files so that the
              pointer size assumptions made in compiling the header
              file are the same as those made when the associated code
              was compiled. None of the system header files, including
              those for the standard C library, are protected. Thus,
              most programs do not work correctly when compiled with the
              -xtaso_short option unless you protect the system header
              files and any other header files associated with code that
              assumes 64-bit pointers.

              When compiling with the -xtaso_short option, you must
              protect header files so that pointer size assumptions
              made when a header file is included into a compilation
              unit using the #include directive are the same as those
              made when the code associated with the header file was
              compiled. For more information, see Section 2.1.2.

              No matter which approach you use, you must take particular
              care when passing any data that contains pointers (for
              example, an array of pointers or a struct that contains
              pointers) to be sure that the pointer size is the same as
              expected by the called function.

              Pointer expressions are normal sized regardless of the
              currect pointer size. For example:

              int x;
              int *px;
              int X::*pXk;

              sizeof(int*)=4
              sizeof(px)=4
              sizeof(&x)=8

                                    Compaq C++ Language Environment 3-13

 



     Compaq C++ Language Environment
     3.5 Using 32-bit Pointers (xtaso)

           sizeof(int X::*)=8
           sizeof(pXk)=8
           sizeof(&X::k)=16

           Compaq C++ does not permit overloading based on pointer
           sizes. To minimize problems, you should declare functions,
           including member functions with long pointer sizes. During
           calls to such functions, the compiler promotes short
           pointers to long pointers.

     3.6 Hints for Designing Upwardly Compatible C++ Classes

           If you produce a library of C++ classes and expect to
           release future revisions of your library, you should
           consider the upward compatibility of your library. Having
           your library upwardly compatible makes upgrading to higher
           versions of your library easier for users. And if you
           design your library properly from the start, you can
           accomplish upward compatibility with minimal development
           costs.

           The levels of compatibility discussed in this section are
           as follows:

           1. Source compatibility

           2. Link compatibility

           3. Run or binary compatibility

           The format in which your library ships determines the
           levels of compatibility that apply:

           __________________________________________________________
           If you ship your library
           in_._._.__________________The_following_apply:____________

           Source format             Source compatibility only

           Object format             Source and link compatibility

           Shareable_library_format__All_three_kinds_of_compatibility

           If you break compatibility between releases, you should at
           least document the incompatible changes and provide hints
           for upgrading between releases.

     3-14 Compaq C++ Language Environment

 



                                         Compaq C++ Language Environment
                 3.6 Hints for Designing Upwardly Compatible C++ Classes

        3.6.1 Source Compatibility

              Achieving source compatibility means that users of your
              library will not have to make any source code changes
              when they upgrade to your new library release. Their
              applications will compile cleanly against your updated
              header files and will have the same run-time behavior as
              with your previous release.

              To maintain source compatibility, you must ensure that
              existing functions continue to have the same semantics
              from the user's standpoint. In general, you can make
              the following changes to your library and still maintain
              source compatibility:

              o  Add new data members and classes.

              o  Add new virtual and nonvirtual functions (as long as
                 they do not change overload resolution of existing
                 calls).

              o  Loosen protection.

              o  Change inline functions to out-of-line and out-of-line
                 functions to inline.

              o  Change the implementation of functions.

              o  Add arguments with default values to existing member
                 functions.

        3.6.2 Link Compatibility

              Achieving link compatibility means that users of your
              library can relink an application against your new object
              or shareable library and not be required to recompile
              their sources.

              What can change

              To maintain link compatibility, the internal representa-
              tion of class objects and interfaces must remain constant.
              In general, you can make the following changes to your
              library and still maintain link compatibility:

              o  Change the implementation of an out-of-line function.

              o  Loosen protection.

                                    Compaq C++ Language Environment 3-15

 



     Compaq C++ Language Environment
     3.6 Hints for Designing Upwardly Compatible C++ Classes

           o  Add a new nonvirtual member function (as long as
              it does not change overload resolution for existing
              calls).

           What cannot change

           Because the user may be linking object modules from
           your previous release with object modules from your new
           release, the layout and size of class objects must be
           consistent between releases. Any user-visible interfaces
           must also be unchanged; even the seemingly innocent change
           of adding const to an existing function will change the
           mangled name and thus break link compatibility.

           The following are changes that you cannot make in your
           library:

           o  Add, move, or delete data members.

           o  Add, move, or delete virtual functions.

           o  Change the signature of virtual and nonvirtual
              functions.

           o  Remove nonvirtual functions.

           o  Change inline function definitions.

           o  Change functions from out-of-line to inline.

           Designing Your C++ Classes for Link Compatibility

           Although the changes you are allowed to make in your
           library are severely restricted when you aim for link
           compatibility, you can take steps to prepare for this and
           thereby reduce the restrictions. Compaq suggests using one
           of the following design approaches:

           o  Set aside dummy (reserved-for-future-use) data fields
              and virtual functions within your classes. This assumes
              you can forsee how much your classes will grow and
              change in the future.

           o  Add a level of indirection to hide your virtual
              functions and data fields from the user. This lets
              you add and change data fields and virtual functions
              without affecting the library user; however, there
              may be some disadvantages such as in performance. This
              approach is detailed in Effective C++, Section 34, by
              Scott Meyers.

     3-16 Compaq C++ Language Environment

 



                                         Compaq C++ Language Environment
                 3.6 Hints for Designing Upwardly Compatible C++ Classes

        3.6.3 Run Compatibility

              Achieving run compatibility means that users of your
              library can run an application against your new shareable
              library and not be required to recompile or relink the
              application.

              This requires that you follow the guidelines for link
              compatibility as well as any operating system guidelines
              for shareable libraries. For example, you need to ensure
              your version identifier is upwardly compatible between
              releases. Refer to the reference pages for ld for
              information on creating a shareable library.

        3.6.4 Additional Reading

              The C++ Programming Language, 3rd Edition offers some
              advice on compatibility issues. Another good reference is
              Designing and Coding Reusable C++, Chapter 7, by Martin D.
              Carroll and Margaret E. Ellis.

























                                    Compaq C++ Language Environment 3-17

 









                                                                       4
        ________________________________________________________________

                                                   Porting to Compaq C++



              Compaq C++ implements the International C++ Standard, with
              some differences, as described in the online release notes
              in:

              /usr/lib/cmplrs/cxx/DECCXXnnn.release-notes

              This language differs significantly from The Annotated
              C++ Reference Manual, implemented by the Version 5.n
              compilers. When switching from a Version 5.n compiler,
              you might need to modify your source files, especially if
              you use the default language mode. In addition, language
              changes can affect the run-time behavior of your programs.
              If you want to compile existing source code with minimal
              source changes, compile using the -std arm option. See for
              information on and changes to the Standard Library.

              This chapter describes ways to avoid having the compiler
              reject program code that previously worked with other
              C++ implementations that adhere less strictly to the C++
              language definition. References to applicable portions of
              The C++ Programming Language, 3rd Edition indicate where
              you can find additional help.

        4.1 Compatibility with Other C++ Compilers

              In default mode (-std ansi), the compiler implements most
              features of the International C++ Standard including:

              o  Run-time type identification (RTTI), with dynamic_cast
                 and the typeid operator (see Section 2.3)

              o  New-style casts (static_cast, reinterpret_cast, and
                 const_cast).

              o  Array new and delete

                                               Porting to Compaq C++ 4-1

 



     Porting to Compaq C++
     4.1 Compatibility with Other C++ Compilers

           For compatibility with previous versions, the compiler
           provides the following language mode options:

           -std ansi
           Specify this option if you want an ANSI C++ compiler that
           supports some commonly used extensions and is somewhat
           less strict than the standard. This is the default
           compiler mode.

           If you want to use ANSI mode but find that the compiler
           generates too many diagnostics in that mode, you can
           use the -msg_quiet option with the -std ansi option. The
           -msg_quiet option relaxes error checking and suppresses
           or reduces the severity of many diagnostics. It also
           suppresses many warnings that are generated in ANSI mode
           but were not issued by Version 5.6. For information on
           message control options, see Message Control Options in
           Chapter 2.

           -std arm
           Specify this option if you want to compile programs
           developed using Version 5.n and want to minimize source
           changes.

           If you usually want your compilations done in this mode
           and don't want to specify -std arm on each cxx command,
           define environment variable DEC_CXX as follows:

                setenv DEC_CXX "-std arm"

           You can place a single vertical bar ("|") within the
           variable. All arguments preceding the bar are evaluated
           before any explicit command-line arguments; all arguments
           following the bar are evaluated afterwards. In the absence
           of a vertical bar, all arguments are evaluated before the
           explicit command-line arguments.

           Specify -v to obtain the definition of DEC_CXX For
           example, assuming the definition of DEC_CXX above, the
           cxx -v command results in the following:

                % cxx -v
                $DEC_CXX contains: -std arm


     4-2 Porting to Compaq C++

 



                                                   Porting to Compaq C++
                              4.1 Compatibility with Other C++ Compilers

              To enhance compatibility with other C++ compilers, Compaq
              C++ supports options that direct the compiler to interpret
              the source program according to certain rules followed by
              other implementations:

              -std cfront
              Specify this option if you want to compile programs
              developed using cfront or a compiler based on cfront.


              -std gnu
              Use this option if you want to compile programs developed
              using the GNU compiler. This option also defines the
              __STD_GNU macro. The following changes in behavior are
              provided for compatibility with the GNU C++ compiler:

              o  These options are enabled by default:

                 -alternative_tokens, -tlocal, and -no_implicit_include

              o  Access control is not enforced for types defined inside
                 a class.

              o  Unrecognized character escape sequences in string
                 literals produce an informational instead of a warning
                 message.

              o  The __inline keyword is enabled and is equivalent to
                 inline.

              o  The severity of the error "incompatible parameter" (tag
                 incompatibleprm) is reduced to warning.

              o  When overloading, enum types are treated as integral
                 types.

              The following known incompatibilities are not addressed in
              the -std gnu mode:

              o  The compiler strictly enforces the requirement to
                 define functions before they are used. This requirement
                 also applies to built-in functions such as strlen.

        )

              -std ms
              Specify this option if you want the compiler to accept
              additional Microsoft Visual C++ extensions.

                                               Porting to Compaq C++ 4-3

 



     Porting to Compaq C++
     4.1 Compatibility with Other C++ Compilers

           -std strict_ansi
           Specify this option if you want the compiler to enforce
           the ANSI C++ standard strictly but permit some ANSI
           violations that should be errors to be warnings.

           -std strict_ansi_errors
           Specify this option if you want strict_ansi and also want
           errors to be issued for all ANSI violations.

           With either -std ms or -std cfront you might also want
           to specify -msg_quiet to reduce the number of diagnostic
           messages generated. For details, see (Message Control
           Options in Chapter 2.

     4.2 Compatibility With Version 5.n Compilers [Tru64]

           This section provides information about differences
           between the current compiler and Version 5.n compilers.

           o  Language differences

           o  Implementation differences

           o  Library differences

           o  Run-Time library differences

     4.2.1 Compiler Version Options [Tru64]

           This release provides the following compiler version
           options:

           -newcxx
           Invokes the Version 6.3 compiler. This is the default.

           -oldcxx
           Invokes a bug fix update to the Version 5.7 compiler.

           The -oldcxx option is provided for cases where the Version
           6.n compiler requires excessive source changes or for
           problems in using that compiler. If extensive source
           changes are required to correct errors, try using the
           -std arm option. For excessive warnings, try the -msg_
           quiet option.

     4-4 Porting to Compaq C++

 



                                                   Porting to Compaq C++
                    4.2 Compatibility With Version 5.n Compilers [Tru64]

              If you want -oldcxx to be the default, define the DEC_CXX
              environment variable as follows:

                   setenv DEC_CXX "-oldcxx"

              Before you can use the -oldcxx option, the optional -
              oldcxx subset must be installed. See the  Compaq C++
              Installation Guide for Tru64 UNIX .

        4.2.2 Language Differences [Tru64]

              Be aware of the following language differences between the
              current compiler and Version 5.n compilers:

              o  The most important language differences result from
                 the implementation of the International C++ Standard
                 in Version 6.n. If you want to compile existing source
                 code with minimal source changes, specify the -std arm
                 option.

              o  Because the current compiler performs more error
                 checking than previous versions, it generates
                 significantly more diagnostic messages. However, you
                 can use the -msg_quiet option to relax error checking
                 and reduce the severity of many diagnostics. See Compaq
                 C++ Implementation.

                 With some option combinations, you might see unwanted
                 diagnostics from system header files. If so, you
                 might obtain better results if you protect your
                 system header files using the script provided in
                 /usr/lib/cmplrs/cxx/protect_system_headers.sh. For
                 more information, see Protecting System Header Files.

              o  The current compiler fixes several class member access
                 bugs in previous versions. Some illegal programs
                 that compiled cleanly with previous versions require
                 modification to compile with the current version.

              o  The following keywords, introduced with the International
                 C++ Standard, are always keywords in all compiler
                 modes:

                 bool, const_cast, explicit, export, false, mutable, dynamic_cast,
                 reinterpret_cast, static_cast, truce, typeid, typename, wchar_t

                                               Porting to Compaq C++ 4-5

 



     Porting to Compaq C++
     4.2 Compatibility With Version 5.n Compilers [Tru64]

              Alternative representation keywords are as follows:

              and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, xor_eq

           o  Creation of temporaries and their lifetimes vary among
              compiler modes.

           o  Taking the address of a bit field is not allowed in the
              current version.

           o  Macro expansion in pragmas can give different results
              in the current and previous versions.

           o  The following are distinct types in the current
              version; they were the same type in previous versions:

                 typedef void (*PF)();             // Pointer to an extern "C++" function
                 extern "C" typedef void (*PCF)(); // Pointer to an extern "C" function
                 void f(PF);
                 void f(PCF);

           o  The current version does not allow converting a pointer
              to member from a derived class to a virtual base class.

           o  Calling a nonstatic member function through a null
              pointer is undefined behavior. Certain cases that used
              to run without errors in previous versions no longer
              run in the current version. For example:

                   #include <iostream.h>

                   struct A {
                       int a;
                   };

                   struct D : public virtual A
                   {
                       A* toA(){ return (A*) this; }
                   };

                   main ()
                   {
                       D* d = NULL;
                       A* ad = d->toA();
                       if (ad==NULL) cout << "ok"; // will seg fault
                   }

     4-6 Porting to Compaq C++

 



                                                   Porting to Compaq C++
                    4.2 Compatibility With Version 5.n Compilers [Tru64]

              o  In the current version, bool is a built in type. In
                 previous versions, it is user defined, typically as
                 int in system header files. Mangling therefore differs
                 between the current and previous versions.

                 In the current version, the size of bool is 1. In
                 previous versions, bool is user defined, typically
                 as int with a size of 4.

                 In the current version, the size of a boolean
                 expression (sizeof(a && b)) is 1. In previous versions,
                 the size is 4, independent of the size of bool.

              o  The current version does not cause pragmas to become
                 effective within function bodies when scanning template
                 definitions.

              o  The current version does not permit dropping qualifiers
                 on pointer assignments. For example, the following is
                 not permitted:

                      volatile int *vptr;  int *ptr=vptr;

              o  The current version does not allow the "virtual"
                 storage class modifier to be used with member function
                 definitions outside a class.

              o  The current version does not allow typedef void Z::*
                 any_ptom;.

        4.2.3 Implementation Differences [Tru64]

              Users should be aware of the following implementation
              differences between the current and previous versions of
              the compiler:

              o  The automatic template instantiation model has
                 been redesigned for the current version. See Using
                 Templates.

              o  The current version does not support the -show
                 statistics option implemented in Version 5.7.

              o  The current version drops qualifiers on parameters
                 when determining the function type, as dictated by
                 the International C++ Standard. For instance, in the
                 following example, the function declarations are the
                 same function.

                                               Porting to Compaq C++ 4-7

 



     Porting to Compaq C++
     4.2 Compatibility With Version 5.n Compilers [Tru64]

                   f(const int p1);
                   f(int p1);

              For compatibility with previous versions, if qualifiers
              are included in function declarations, they are also
              included in the mangled name.

           o  The current and previous versions differ in inter-
              preting undefined behavior, as when incrementing takes
              effect in this example:

                   f(i++, i++);

           o  The current version cannot handle a #pragma define_
              template that spans multiple lines without the
              backslash ( \ ) delimiter. Version 5.6 can handle this
              without problems.

           o  The current version displays #line number in -E output.
              The previous version displays #number.

           o  After encountering an illegal multibyte character
              sequence, the current version issues a warning
              diagnostic and continues processing. The previous
              version issues an error and stops processing.

     4.2.4 Library Differences [Tru64]

           Aspects of memory allocation and deallocation have
           changed. For detailed information, see

     4.3 Using Classes

           This section discusses porting issues pertaining to C++
           classes.

     4.3.1 Friend Declarations

           When making friend declarations, use the elaborated form
           of type specifier. The following code fragment implements
           the legal and comments out the illegal friend declaration:

           class Y;
           class Z;
           class X;
              //friend Y;  ** not legal
              friend class Z; // legal
           };

     4-8 Porting to Compaq C++

 



                                                   Porting to Compaq C++
                                                       4.3 Using Classes

        4.3.2 Member Access

              Unlike some older C++ implementations, Compaq C++ strictly
              enforces accessibility rules for public, protected, and
              private members of a base class. For more information, see
              The C++ Programming Language, 3rd Edition.

        4.3.3 Base Class Initializers

              Unlike some older C++ implementations, Compaq C++ requires
              you to use the base class name in the initializer for a
              derived class. The following code fragment implements a
              legal initializer and comments out an illegal initializer:

              class Base {
                  //  . . .
              public:
                  Base (int);
              };
              class Derived : public Base {
                  //  . . .
              public:
                  // Derived(int i) : (i)  {/*  . . .
        */}    ** not legal
                  Derived(int i) : Base(i) {/*  . . .
        */} // ** legal, supplies class name
              };

              For more information, see The C++ Programming Language,
              3rd Edition.

        4.4 Undefined Global Symbols for Static Data Members

              When a static data member is declared, the compiler issues
              a reference to the external identifier in the object
              code, which must be resolved by a definition. On Compaq
              Tru64 UNIX and Linux Alpha systems, the compiler does
              not support the declaration anachronism shown in The C++
              Programming Language, 3rd Edition.

              For example, consider the following code fragment:




                                               Porting to Compaq C++ 4-9

 



     Porting to Compaq C++
     4.4 Undefined Global Symbols for Static Data Members

           class C {
                   static int i;
                   };
           //missing definition
           //int C::i = 5;
           int main ()
           {
               int x;
               x=C::i;
               return 0;
           }

           The compiler does not issue any messages during com-
           pilation; however, when you attempt to link a program
           containing this code, the linker issues a message similar
           to the following:

           ld:
           Error: Undefined:
           i__1C

     4.5 Functions and Function Declaration Considerations

           Compaq C++ requires the use of function definitions as
           described in The C++ Programming Language, 3rd Edition.
           For examples of outdated syntax not allowed in Compaq C++,
           see The C++ Programming Language, 3rd Edition.

           Because all linkage specifications for a name must agree,
           function prototypes are not permitted if the function is
           later declared as an inline function. The following code
           is an example of such a conflicting function declaration:

           int f();
           inline int f() { return l; }

           In this example, f is declared with both internal and
           external linkage, which causes a compiler error.

           Similarly, the declaration int f(i,j) causes an error
           even when the declaration is defined with the "C" linkage
           specification, because the linkage specification has no
           effect on the semantics of the declaration.


     4-10 Porting to Compaq C++

 



                                                   Porting to Compaq C++
                                                      4.6 Using Pointers

        4.6 Using Pointers

              This section explains how to use pointers effectively in
              Compaq C++.

        4.6.1 Pointer Conversions

              In Compaq C++, you cannot implicitly convert a const
              pointer to a nonconstant pointer. For example, char *
              and const char * are not equivalent; explicitly performing
              such a cast can lead to unexpected results.

              For more information, see The C++ Programming Language,
              3rd Edition.

        4.6.2 Bound Pointers

              Binding a pointer to a member function with a particular
              object as an argument to the function is not allowed in
              Compaq C++. For more information on the illegality of
              casting bound pointers, see The C++ Programming Language,
              3rd Edition.

        4.6.3 Constants in Function Returns

              Because the return value cannot be an lvalue, a constant
              in a function return has no effect on the semantics of
              the return. However, using a constant in a function return
              does affect the type signature. For example:

              static int f1( int a, int b) {;}
              const int (* const (f2[])) (int a, int b) = {f1};

              In this example, the referenced type of the pointer value
              f1 in the initializer for f2[] is function (signed
              int, signed int), which returns signed int. This is
              incompatible with function (signed int, signed int), which
              returns const signed int.

              You can omit the const of int because it affects only the
              constant return signature.




                                              Porting to Compaq C++ 4-11

 



     Porting to Compaq C++
     4.6 Using Pointers

     4.6.4 Pointers to Constants

           The following example shows a type mismatch between a
           pointer to a char and a pointer to a const char:

           void foo (const char* argv[]) {}
           int main()
           {
                   static char* args[2] = {"foo","bar"};
           /* 'In this statement, the referenced type of the pointer value
            "args" is "pointer to char"' which is not compatible with
            "pointer to const char"'*/
                   foo (args);
           return 0;
           }

           You can correct this example by changing static char to
           static const char. Use an explicit type cast to get an
           argument match only if no other option is available; such
           a cast may break on some C++ implementations.

     4.7 Using typedefs

           Using a synonym after a class, struct, or union prefix is
           illegal. Using a synonym in the names for constructors and
           destructors within the class declaration itself is also
           illegal.

           In the following example, the illegal typedef specifier is
           commented out:

           typedef struct { /*  . . .  */ } foo;
           // typedef struct foo foobar;             ** not legal

           For more information, see The C++ Programming Language,
           3rd Edition.

     4.8 Initializing References

           Compaq C++ warns against initializing nonconstant
           references to refer to temporary objects. The following
           example demonstrates the problems that can result:



     4-12 Porting to Compaq C++

 



                                                   Porting to Compaq C++
                                             4.8 Initializing References

              static void f()
              {
                  int i = 5;
                  i++;        // OK
                  int &ri = 23;
                  ri++;       // In the initializer for ri, the initialization of a
                              // non-const reference requires a temporary for "23".
              }

              The issue of reference initialization arises most often in
              assignment operators and in copy constructors. Wherever
              possible, declare all reference arguments as const.

              For more information, see The C++ Programming Language,
              3rd Edition.

        4.9 Using the switch and goto Statements

              Branching around a declaration with an explicit or
              implicit initializer is not legal, unless the declaration
              is in an inner block that is completely bypassed. To
              satisfy this constraint, enclose the declaration in a
              block. For example:

              int i;

              switch (i) {
              case 1:
                  int l = 0;     //not initialized at this case label
                  myint m = 0;   //not initialized at this case label
                  {
                  int j = 0;     // legal within the braces
                  myint m = 0;   // legal within the braces
                  }
              case 2:
                  break;
              //  . . .
              }

              For more information on using the switch statement, see of
              The C++ Programming Language, 3rd Edition.




                                              Porting to Compaq C++ 4-13

 



     Porting to Compaq C++
     4.10 Using Volatile Objects

     4.10 Using Volatile Objects

           You must supply the meaning of copy constructing and
           assigning from volatile objects, because the compiler
           generates no copy constructors or assignment operators
           that copy or assign from volatile objects. The following
           example contains examples of such errors, as noted in the
           comments:

           class A {
           public:
             A() { }
             // A(volatile A&) { }
             // operator=(volatile A&) { return 0; }
           };

           void foo()
           {
             volatile A va;
             A a;

             A cca(va);  // error - cannot copy construct from volatile object
             a = va;     // error - cannot assign from volatile object

             return;
           }

           For more information, see The C++ Programming Language,
           3rd Edition.

     4.11 Preprocessing

           Compaq C++ allows identifiers, but not expressions, on the
           #ifdef preprocessor directive. For example:

           // this is not legal
           // #ifdef KERNEL && !defined(__POSIX_SOURCE)

           The following is the legal alternative:

           // use this instead
           #if defined(KERNEL) && !defined(__POSIX_SOURCE)

           For more information, see The C++ Programming Language,
           3rd Edition.

     4-14 Porting to Compaq C++

 



                                                   Porting to Compaq C++
                                                    4.12 Managing Memory

        4.12 Managing Memory

              The proper way to manage memory for a class is to overload
              the new and delete operators. This is in contrast to some
              older C++ implementations, which let you manage memory
              through assignment to the this pointer.

              For more information, see The C++ Programming Language,
              3rd Edition.

              Program developers must take care that any user-defined
              new operators always return pointers to quadword aligned
              memory.

        4.13 Size-of-Array Argument to delete Operator

              If a size-of-array argument accompanies a delete operator,
              the compiler ignores the argument and issues a warning.
              The following example includes an anachronistic use of the
              delete operator:

              int main()
              {
                      int *a = new int [20];
                      int *b = new int [20];
                      delete[20] a;     //old-style; argument ignored, warning issued
                      delete[] b;
              return 0;
              }

        4.14 Flushing the Output Buffer

              Do not depend on the newline character (\n) to flush your
              terminal output buffer. A previous stream implementation
              might have done so, but this behavior is not in confor-
              mance with Version 2.0 of the AT&T iostream library.
              If you want to flush the output buffer, use the endl
              manipulator or the flush member function.







                                              Porting to Compaq C++ 4-15

 



     Porting to Compaq C++
     4.15 Missing Parenthesis Error Message

     4.15 Missing Parenthesis Error Message

           Situations occur in which a simple typographical error
           generates a missing parenthesis error message. In the
           following example, the class name CaseSensitive is
           incorrectly specified as Casesensitive in the constructor
           declaration:

           class CaseSensitive {
               void Test( const Casesensitive &foo );
           };

           As the compiler parses the argument declaration list:

           1. It interprets const as a type specifier.

           2. It interprets Casesensitive as a dname.

           Among the next legal tokens are the equal sign, comma,
           and closing parenthesis. Upon finding an ampersand, the
           compiler expects a closing parenthesis. With all other
           possibilities exhausted, the compiler has what appears to
           be a legal argument declaration list, after which the
           closing parenthesis is the only allowable token. The
           compiler expected one thing but encountered something
           else. Often, inserting newline characters can isolate the
           offending token.

     4.16 Link Using cxx

           Use the cxx command, not the ld command, to build a
           binary; otherwise, the run-time startup and other crucial
           code will not build properly. Some symptoms of linking
           incorrectly are

           o  Segmentation faults (signal SEGV) occur while running
              your program

           o  Undefined symbols

           o  Static constructors not being executed




     4-16 Porting to Compaq C++

 



                                                   Porting to Compaq C++
                                             4.17 Source File Extensions

        4.17 Source File Extensions

              Compaq C++ automatically treats files with a .c extension
              as C language source files and passes the files to the cc
              command. For Compaq C++ to compile them, your files must
              have one of the following extensions:

              .cxx        .CXX
              .cpp        .CPP
              .cc         .CC
              .C          .C++

              You also can use the -x option to direct the compiler to
              ignore file-name extensions and treat all named files,
              other than those with an .a or .o extension, as C++ source
              files.

        4.18 Incrementing Enumerations

              Some other C++ implementations let you perform integer
              arithmetic, including ++, on enumerated types; Compaq C++
              does not allow this.

        4.19 Scope of Variables Declared on a for Statement

              If the for-init-statement is a declaration, the scope
              of the name(s) declared extends to the end of the for-
              statement, as shown in the following example:

              int i=5;

              void f()
              {
                for (int i=0;i<10;i++);

                printf("%d\n",i);
              }

              When compiled -std ansi, strict_ansi, or strict_ansi_
              errors, the compiler produces the results expected by
              the International C++ Standard. In all other modes, the
              compiler produces the results expected by The Annotated
              C++ Reference Manual; that is, the scope of the names
              declared extends to the end of the enclosing scope.

                                              Porting to Compaq C++ 4-17

 



     Porting to Compaq C++
     4.20 Guidelines for Writing Clean 64-Bit Code

     4.20 Guidelines for Writing Clean 64-Bit Code

           Paying careful attention to data types can ensure that
           your code works on both 32-bit and 64-bit systems. Use the
           following guidelines to write clean 64-bit code:

           o  Variables that should be 32 bits in size on both 32-bit
              systems and 64-bit Alpha systems should be declared as
              int (not long). Even better would be to declare them as
              int32, which is a macro you define to be int.

           o  Variables that should be 32 bits in size on a 32-bit
              system and 64 bits in size on a 64-bit Alpha system
              should be declared as long. Even better would be to
              declare them as long-int, which is a macro you define
              to be long.

           o  Check any variables in your code that are declared
              long. If the variable must be 32 bits in size, you must
              change its type to int.

           o  Variables declared as int should not be used to hold an
              address; sizeof (int) does not equal sizeof (char *) on
              Alpha systems.

           o  Remember that register variables and unsigned variables
              default to int (32 bits).

           o  Constants are 32-bit quantities by default. Performing
              shift operations or bit operations on constants will
              give 32-bit results. You must add L to the constant to
              get a 64-bit result. For example:

              long foo, bar;
              foo = 1L << bar;

           o  Using a 0 where you should use NULL generates a 32-bit
              constant. On Alpha systems, this could yield 0 in the
              low 32 bits and useless data in the high 32 bits when
              passed into a function that accepts a variable number
              of arguments. Using NULL from the <stdio.h> header file
              provides the correct value.

           o  Assigning to a char is not atomic on Alpha processors
              before the EV56. You will obtain a load of 32 or 64
              bits, followed by byte operations to extract, mask, and
              shift the byte, followed by a store of 32 or 64 bits.

     4-18 Porting to Compaq C++

 



                                                   Porting to Compaq C++
                           4.20 Guidelines for Writing Clean 64-Bit Code

              o  Bit-fields declared as int on Alpha systems generate
                 load/store 32 bits. Bit-fields declared as long on
                 Alpha systems generate load/store 64 bits.

              o  If you do not explicitly declare the formal parameters
                 to functions, their sizes may not match the caller
                 sizes. The default is int, which truncates 64-bit
                 addresses.

              o  The %d and %x format specifiers print 32 bits of data.
                 Use %ld or %lx with printf to print 64 bits of data.
                 You can use %p on both 32- and 64-bit systems to print
                 the value of pointers.

              For more information, see the ULTRIX to Compaq Tru64 UNIX
              Migration Guide.





























                                              Porting to Compaq C++ 4-19

 









                                                                       5
        ________________________________________________________________

                                                         Using Templates



              The C++ template instantiation model includes the
              following features:

              o  Automatic template instantiation occurs at compile
                 time. Necessary templates are instantiated automati-
                 cally by the compilation of the source file that needs
                 them and has access to the template definitions.

              o  During automatic template instantiation, instantiations
                 are written into the repository (./cxx_repository)
                 as object files. Compilation of instantiations in no
                 longer done at link time.

              o  For automatic instantiation, the compiler does not
                 require that template declarations and definitions
                 appear in header files.

              o  Several manual template instantiation pragmas are
                 availble.

        5.1 Overview

              A C++ template is a framework for defining a set of
              classes or functions. The process of instantiation creates
              a particular class or function of the set by resolving the
              C++ template with a group of arguments that are themselves
              types or values. For example:

              template <class T> class Array {
                  T *data;
                  int size;
              public:
                  T &operator[](int);
              };

                                                     Using Templates 5-1

 



     Using Templates
     5.1 Overview

           The code in this example declares a C++ class template
           named Array that has two data members named data and size
           and one subscript operator member function. Array<int>
           instantiates Array with type int. This instantiation
           generates the following class definition:

           class Array {
               int *data;
               int size;
           public:
               int &operator[](int);
           };

           The compiler supports instantiation of C++ class,
           function, and static data member templates. The following
           sections describe the alternative methods available
           for instantiating templates: automatic or manual
           instantiation.

     5.2 Automatic Template Instantiation

           In automatic template instantiation mode, the compiler
           attempts to instantiate every referenced template at
           compile time. For automatic instantiation to work, at
           least one compilation that references a template function
           must be able to find the template definition. There is
           no restriction on where a template can be declared or
           defined, as long as the definition is visible to the
           compilation unit. You can use implicit inclusion to find
           it.

           The compiler writes instantiation object files to a
           directory called the repository; file names are based on
           the names of the entities being instantiated. The default
           repository is ./cxx_repository.

     5.2.1 Specifying Alternate Repositories

           You can use the -ptr command-line option to specify one or
           more alternate repository directories. There is one object
           file in the repository for each instantiated template
           function, for each instantiated static data member, and
           for each virtual table required for virtual functions.

           When the program is linked, the linker searches the
           repositories for needed template instantiations.

     5-2 Using Templates

 



                                                         Using Templates
                                    5.2 Automatic Template Instantiation

        5.2.2 Reducing Compilation Time with the -ttimestamp Option

              To keep instantiations up to date, the compiler always
              instantiates templates by default, even if the required
              template already exists in the respository. However, in
              environments that share many templates among many sources,
              this process can increase compilation time.

              In these environments, users can specify the -ttimestamp
              option to override the default behavior and thereby reduce
              compilation time. This option causes the compiler to
              create a timestamp file named TIMESTAMP in the repository.
              Thereafter, instantiations are added or regenerated only
              if needed; that is, if they do not alreay exist, or if
              existing ones are older than the timestamp.

              The -ttimestamp option is immediately useful when building
              a system from scratch, starting with an empty repository.
              It avoids reinstantiating unchanged code and is totally
              safe, because all required instantiations are generated
              and up to date.

              Incremental application building is normally done without
              this option, so that new instantiations overwrite earlier
              ones as sources are recompiled.

              Although the -ttimestamp option is intended mainly for
              initial builds, you can use it for ongoing development
              in a structured way. Because the compiler creates a new
              timestamp file only if one does not already exist, you
              must remove or modify any existing timestamp file before
              making changes to your code base. This procedure ensures
              that all subsequent compilations generate up-to-date
              instantiations. In the following example, the file is
              removed before and immediately after the compilation of
              a.cxx, b.cxx, and c.cxx.

              rm cxx_repository/TIMESTAMP
              cxx -ttimestamp -c a.cxx
              cxx -ttimestamp -c b.cxx
              cxx -ttimestamp -c c.cxx
              rm cxx_repository/TIMESTAMP



                                                     Using Templates 5-3

 



     Using Templates
     5.2 Automatic Template Instantiation

           The compiler generates all instantiations needed by a.cxx,
           b.cxx, and a.cxx only once, as opposed to the default
           scheme, in which it would generate them once for each
           module that used the instantiations.

           Specifying the -ptv option causes the compiler to emit
           an informational message naming the instantiation and
           repository file being skipped in this mode.

     5.3 Implicit Inclusion

           When implicit inclusion is enabled, the compiler assumes
           that if it needs a definition to instantiate a template
           entity declared in a .h or .hxx file, it can implicitly
           include the corresponding implementation file to obtain
           the source code for the definition.

           If a template entity ABC::f is declared in file xyz.h, and
           if an instantiation of ABC::f is required in a compilation
           but no definition of ABC::f appears in the source code,
           the compiler checks whether a file xyz.cxx exists. If it
           does, the compiler processes it as if it were included at
           the end of the main source file.

           When looking for a template definition, the compiler uses
           the following lookup order:

           1. If the #include name for the header file containing the
              template declaration is specified with an absolute path
              name, look only in the directory specified by the path
              name.

           2. If the #include for the header file containing the
              template declaration is specified with a relative path
              name, take the following action:

              o  If the header file name is specified with double
                 quotation marks (" ") and the -nocurrent_include
                 option was not specified, append the relative path
                 name to the directory containing the source file and
                 search for files with the appropriate suffixes.

              o  Otherwise, append the relative path name to all
                 the -I directories and look in those resulting
                 directories for files with the appropriate
                 suffixes.

     5-4 Using Templates

 



                                                         Using Templates
                                                  5.3 Implicit Inclusion

              For source files, the appropriate suffixes are, in order
              of preference: .cxx, .CXX, .C, .cc, .CC, .cpp, and .c, or
              as defined by the -ptsuf command-line option.

              The compiler ignores any file extension that does not
              begin with a dot (.).

              The -ptsuf command-line option allows the user to
              explicitly define the file extensions to be used with
              implicit inclusion. For example:

               cxx -ptsuf ".CPP.CC" file.cxx

              This command searches for template definition files with
              the extensions .CPP and .CC.

        5.3.1 Compiling Programs with Automatic Instantiation

              In general, the use of automatic template instantiation is
              transparent to the user. Automatic template instantiation
              is enabled by default. The following commands are
              equivalent:

               cxx file.cxx

               cxx -pt file.cxx

               cxx -pt -ptr ./cxx_repository file.cxx

              These commands:

              o  Cause the compilation of the file file.cxx

              o  Create any instantiations that are required whose
                 definitions are visible to the compiler

              o  Create an executable, a.out, by linking together the
                 generated object file and any instantiations required
                 from the repository

              You can specify the repository explicitly with the -ptr
              switch. For example:

               cxx -pt -ptr /project/repository -c file.cxx

              This command compiles file.cxx, produces a file.o in the
              current directory, and puts instantiated template files in
              the directory /project/repository.

                                                     Using Templates 5-5

 



     Using Templates
     5.3 Implicit Inclusion

           The compiler attempts to instantiate templates at compile
           time; therefore, any specialization used in the program
           must be declared in each file in which the specialization
           is referenced, to prevent the instantiation of the
           overridden template function.

           If a template instantiation refers to a static function,
           that function is created as an external entry point in the
           primary object file, and the instantiation object file in
           the repository then refers to this __STF function.

           If the template instantiation is linked into an appli-
           cation that does not have the original primary object
           file, an unresolved reference to the __STF function
           occurs. If this happens, recompile an object file that
           regenerates the instantiation or use manual instantiation
           to reinstantiate the template.

     5.3.2 Linking Programs with Automatic Instantiation

           When all source files are compiled and linked in the
           same step, the operation is transparent. For example,
           the following command compiles a.cxx and b.cxx, writes
           instantiations to ./cxx_repository, and links the
           application using the object files and the instantiations
           from ./cxx_repository:

            cxx a.cxx b.cxx

           When compiling and linking an application in separate
           steps, the repositories that were used during the
           compilation step must be used in the link step as well.
           For example, the following command uses ./cxx_repository
           implicitly in both the compile and link step:

            cxx -c a.cxx b.cxx
            cxx a.o b.o

           If a repository is explicitly named in the compile step,
           then it must also be named in the link step. For example:

            cxx -c -ptr my_repository a.cxx b.cxx
            cxx -ptr my_repository a.o b.o


     5-6 Using Templates

 



                                                         Using Templates
                                                  5.3 Implicit Inclusion

              It is easiest if the compilation of all sources use the
              same repository:

               cxx -c -ptr my_repository a.cxx
               cxx -c -ptr my_repository b.cxx
               cxx -ptr my_repository a.o b.o

              If different repositories are used for the compilation of
              the sources, then all repositories must by specified on
              the link step, as follows:

               cxx -c -ptr repository1 a.cxx
               cxx -c -ptr repository2 b.cxx
               cxx -ptr repository1 -ptr repository2 a.o b.o

              At link time, the specified repositories are searched in
              the order given, to find the required instantiations. If
              one of the repositories used is the default repository, it
              must be explicitly specified on the link step if more than
              one repository is used, as follows:

               cxx -c  a.cxx
               cxx -c -ptr repository2 b.cxx
               cxx -ptr ./cxx_repository -ptr repository2 a.o b.o

              It is usually much easier and safer to use a single
              repository, because the same instantiations could
              potentially be present in multiple repositories, and it
              is possible to update some but not all repositories when
              changes are made to templates.

              The link phase of cxx processes object files so that all
              the external symbol references are resolved. The objects
              are linked together in the following order:

              1. The order in which object files and object libraries
                 are specified on the command line.

              2. If -nopt is specified, stop.

              3. For each unresolved external, search the repositories
                 in the order specified on the command line for an file
                 that contains that external. If such a file is found,
                 add it at the top of the list of object files being
                 searched.

                                                     Using Templates 5-7

 



     Using Templates
     5.3 Implicit Inclusion

           4. Link again and repeat Step 3 until no more externals
              are found or until no more object files are found in
              which to resolve the external.

           The following apply to instantiations:

           o  Instantiations that appear in explicitly linked
              object files or libraries hide instantiations in the
              repositories.

           o  Only template instantiations that are actually
              referenced in sources that can instantiate them appear
              in the repository. You must specify any other wanted
              instantiations manually or use the -tall_repository
              switch.

           o  Instantiations are satisfied from the list of
              unsatisfied externals from the linking of specified
              files, but are linked at the beginning of those files.
              This means that they are linked in only if they are
              satisfied from no specified file given the file order
              behavior of ld, and bring in any external references
              that they need from the first library that satisfies
              them.

     5.4 Manual Template Instantiation

           The compiler provides the following methods to instantiate
           templates manually:

           o  Using the #pragma directives

              You can use an instantiation pragma to direct the
              compiler to instantiate a specific template, as
              described in Section 5.4.1.

           o  Using explicit template instantiation syntax

              The C++ language defines specific syntax for specifying
              that a template should be instantiated. See The C++
              Programming Language, 3rd Edition.

              Compaq strongly recommends using the explicit template
              instantiation syntax when possible.

           o  Using the command-line option method

     5-8 Using Templates

 



                                                         Using Templates
                                       5.4 Manual Template Instantiation

                 This method directs the compiler to instantiate
                 templates at compile time in the user's .o file.
                 Several options are available to control linkage and
                 extent of template instantiation. For more information
                 about this option, see Section 5.2.

        5.4.1 Instantiation Directives

              The next sections describe the following instantitation
              directives:

                 #pragma define_template
                 #pragma instantiate_template
                 #pragma do_not_instantiate_template

        5.4.1.1 #pragma define_template

              The compiler provides a mechanism for manual instan-
              tiation, using the #pragma define_template directive.
              This directive lets you tell the compiler what class
              or function template to instantiate in conjunction with
              the actual arguments with which the template is to be
              instantiated. The #pragma define_template directive has
              the following format:

              #pragma define_template identifier  <template_arguments>

              Identifier is the name of the class or function template
              that the compiler is directed to instantiate at compile
              time. For the instantiation to succeed, the definition
              of the template must appear before the #pragma define_
              template directive.

              Template_arguments is a list of one or more actual
              types that correspond to the template parameters for the
              particular class or function template being instantiated.
              Whatever type is specified is used as the type for the
              instantiation.

              The following is an example of a valid template manual
              instantiation:

                     //main.cxx
                     #include <stdlib.h>
                     template <class T> void sort (T*);

                     int al[100];
                     float a2[100];

                                                     Using Templates 5-9

 



     Using Templates
     5.4 Manual Template Instantiation

                  int main()
                  {
                      sort(a1);
                      sort(a2);
                      return EXIT_SUCCESS;
                  }

                  //sort.cxx
                  template <class T> void sort (T *array)
                  {
                      /* body of sort */
                  }

                  #pragma define_template sort<int>
                  #pragma define_template sort<float>

           To compile and link these sources, enter the following
           command:

                cxx -nopt main.cxx sort.cxx

           When you use #pragma define_template or explicit instan-
           tiation, only the specified template is instantiated;
           templates to which it refers because of member types or
           base classes are not instantiated.

           Sorting an array of template class elements requires the
           use of additional pragmas for the module sort.cxx. For
           example:

                  template <class T> void sort (T* array)
                  {
                      /*body of sort*/
                  }

                  template <class T> class entity {
                  public:
                      T member;
                      int operator < (const entity<T> &) const;
                  }

                  template <class T>
                  int entity<T>::operator < (const entity<T> &operand) const
                  {
                       return member < operand.member;
                  }

     5-10 Using Templates

 



                                                         Using Templates
                                       5.4 Manual Template Instantiation

                     int al[100];
                     float a2[100];
                     entity<int> a3[100];

                     #pragma define_template sort<int>
                     #pragma define_template sort<float>
                     #pragma define_template sort<entity<int> >

                     void sort_all_arrays ()
                     {
                         sort(a1);
                         sort(a2);
                         sort(a3);
                     }

              The define_template pragma is position sensitive. If a
              define_template occurs lexically before a function, member
              function, or static data member template definition,
              the compiler is unable to instantiate the corresponding
              template because the body of that template is not present
              before the pragma directive.

              The compiler instantiates all instances of sort and of
              entity::operator < needed for this compilation unit.

              To organize a program to use the define_template pragma,
              you can place the declarations of class and functions
              templates into header files, and instantiate all instances
              of a particular template from a single compilation unit.
              The following example shows how to do this:

                     // sort.h
                     #include <stdlib.h>
                     template <class T> void sort (T*);

                     // entity.h
                     template <class T> class entity {
                     public:
                         T member;
                         int operator < (const entity<T> &) const;
                     };

                     // main.cxx
                     #include "sort.h"
                     #include "entity.h"

                                                    Using Templates 5-11

 



     Using Templates
     5.4 Manual Template Instantiation

                  int al[100];
                  float a2[100];
                  entity<int> a3[100];

                  int main()
                  {
                      sort(a1);
                      sort(a2);
                      sort(a3);
                      return EXIT_SUCCESS;
                  }

                  // sort.cxx
                  #include "sort.h"
                  #include "entity.h"
                  template <class T> void sort (T* array)
                  {
                      /*body of sort*/
                  }
                  #pragma define_template sort<int>
                  #pragma define_template sort<float>
                  #pragma define_template sort<entity<int> >

           Compiling the following file provides a definition of
           entity::operator < with type int:

                  // entity.cxx
                  #include "entity.h"

                  template <class T>
                  int entity<T>::operator < (const entity<T> &operand) const
                  {
                       return member < operand.member;
                  }

                  #pragma define_template entity<int>

           To compile this example, issue the following command:

                  cxx main.cxx main.o sort.cxx sort.o entity.cxx entity.o

           If the program uses other instantiations of entity in
           other compilation units, you can provide definitions
           of operator < for those entities by adding define_
           template pragmas to entity.cxx. For example, if other
           compilation units use the following instantiations of
           entity, appending the following pragmas to entity.cxx

     5-12 Using Templates

 



                                                         Using Templates
                                       5.4 Manual Template Instantiation

              causes the compiler to generate instantiations of operator
              < for those requests of entity:

                 entity<long> and entity< entity<int> >,
                 #pragma define_template entity<long>
                 #pragma define_template entity< entity<int> >

        5.4.1.2 #pragma instantiate and #pragma do_not_instantiate

              The compiler also provides several pragmas that provide
              fine control over the instantiation process. Instantiation
              pragmas, for example, can be used to control the
              instantiation of specific template entities or sets of
              template entities. There are two instantiation pragmas:

              o  The instantiate pragma causes a specified entity to be
                 instantiated, similar to the define_template pragma.
                 It provides finer instantiation control than define_
                 template when instantiating function templates.

              o  The do_not_instantiate pragma suppresses the instan-
                 tiation of a specified entity. It is typically used
                 to suppress the instantiation of an entity for which a
                 specific definition is supplied.

              The argument to the instantiation pragma can be:

              a template class name     A<int>

              a template class          class A<int>
              declaration

              a member function name    A<int>::f

              a static data member      A<int>::i
              name

              a static data declara-    A<int>::i
              tion

              a member function         void A<int>::f(int, char)
              declaration

              a template function       char* f(int, float)
              declaration

              A pragma in which the argument is a template class name
              (for example, A<int> or class A<int> is equivalent to
              repeating the pragma for each member function and static
              data member declared in the class. When instantiating
              an entire class, a given member function or static data

                                                    Using Templates 5-13

 



     Using Templates
     5.4 Manual Template Instantiation

           member may be excluded using the do_not_instantiate
           pragma. For example:

            #pragma instantiate A<int>
            #pragma do_not_instantiate A<int>::f

           The template definition of a template entity must be
           present in the compilation for an instantiation to occur.
           If an instantiation is explicitly requested by use of the
           instantiate pragma and no template definition is available
           or a specific definition is provided, an error is issued.

            template <class T> void f1(T);  // No body provided
            template <class T> void g1(T);  // No body provided
            void f1(int) {}  // Specific definition
                   #include <stdlib.h>
             int main()
            {
              int     i;
              double  d;
              f1(i);
              f1(d);
              g1(i);
              g1(d);
                     return EXIT_SUCCESS;
            }
            #pragma instantiate void f1(int) // error - specific definition
            #pragma instantiate void g1(int) // error - no body provided

           The functions f1(double) and g1(double) are not instanti-
           ated (because no bodies were supplied) but no errors are
           produced during the compilation (if no bodies are supplied
           at link time, a linker error is produced).

           A member function name (for example, A<int>::f can
           be used as a pragma argument only if it refers to a
           single user-defined member function (that is, not an
           overloaded function). Compiler-generated functions are
           not considered, so a name may refer to a user-defined
           constructor even if a compiler-generated copy constructor
           of the same name exists. Overloaded member functions can
           be instantiated by providing the complete member function
           declaration:

            #pragma instantiate char* A<int>::f(int, char*)

     5-14 Using Templates

 



                                                         Using Templates
                                       5.4 Manual Template Instantiation

              The argument to an instantiation pragma must not be a
              compiler-generated function, an inline function, or a pure
              virtual function.

        5.5 Advanced Program Development and Templates

              The following sections discuss templates in the context of
              advanced program development.

        5.5.1 Dependency Management

              The compiler does no dependency management of its own.
              Because template instantiations are compiled when source
              files that reference those instantiations are compiled,
              those source files must be recompiled if the template
              declaration or definition changes.

              The -M output from the compiler lists the implicitly
              included files, so that the make program can automatically
              recompile any source files that depend upon template
              files. If make is not being used, it is the user's
              responsibility to ensure that instantiations that have
              changed are recompiled. The user does so by recompiling
              at least one source file that references the changed
              instantiations.

              The compiler does not check command line dependencies
              of template instantiations at link time. If you compile
              two different source files that instantiate a specific
              template with two different sets of options, the last
              option setting affects the template instantiation. Use
              consistent option settings for each build into each
              repository.

        5.5.2 Mixing Automatic and Manual Instantiation

              Object files that have been compiled using manual
              instantiation can be linked freely with objects that have
              been compiled using automatic instantiation. To ensure
              that the template instantiations needed by the files
              compiled with automatic instantiation are provided, the
              application must be linked using automatic instantiation,
              and the appropriate repositories must be present.


                                                    Using Templates 5-15

 



     Using Templates
     5.5 Advanced Program Development and Templates

           When a template instantiation is present in an explicitly
           named object file or object library it takes precedence
           over the same named instantiation in a repository.

     5.5.3 Creating Libraries

           Creating libraries with object files created with
           automatic instantiations is relatively straightforward.
           You must decide where the instantiations that were
           generated automatically are provided to the users of the
           library.

           For applications that use the library to link success-
           fully, all template instantiations that are needed by
           the code in the library must be available at link time.
           Because template instantiation happens at compile time,
           the object files that contain the instantiated templates
           must be available at link time. This can be done in two
           ways:

           o  Put the instantiations in the library. They hide the
              same named instantiations in any repositories or any
              libraries following the library on the command line.

           o  Provide a repository that contains the instantiations.

           It is usually easiest to put the instantiations in the
           library. This is a good choice if the instantiations are
           internal to the library and are not instantiated directly
           by the user's code. To put the instantiations in the
           library, add all of the object files in the repositories
           required by the library into the library, as shown in the
           following example:

            cxx -c -ptr lib_repository a.cxx b.cxx c.cxx
            ar r mylib.a a.o b.o c.o lib_repository/*.o

           If the template instantiations can be overridden by the
           user, the templates should be provided in a repository
           that the user specifies after all the user's repositories.
           For the previous example, create the library as follows:

            cxx -c -ptr lib_repository a.cxx b.cxx c.cxx
            ar r mylib.a a.o b.o c.o

     5-16 Using Templates

 



                                                         Using Templates
                          5.5 Advanced Program Development and Templates

              When linking the application, the user would specify lib_
              repository as the last read-only repository on the line as
              follows:

               cxx -c -ptr ./cxx_repository -ptr lib_repository user_code.cxx mylib.a

              The user must explicitly name the repository when linking,
              even if it is the default repository ./cxx_repository.
              The compiler first satisfies all unresolved instantiations
              from ./cxx_repository, and then it uses lib_repository to
              resolve any remaining unresolved instantiations.

              Only the instantiations that are required by the code in
              the library are generated in the library repository lib_
              repository. If you must provide other instantiations that
              the user requires but cannot instantiate, you must provide
              these instantiations using manual template instantiation.

        5.5.4 Creating A Common Instantiation Library

              If you want to put all current instantiations into a
              common instantiation library, follow these steps:

              1. Compile with the -ptv option and save the results to a
                 file.

              2. Edit that file and save the names that appear after
                 the "automatically instantiating ..." string. You can
                 ignore any messages about instantiating vtables. Put
                 #pragma instantiate before each name.

              3. Put the result of that edit into a separate source file
                 and include at the top of the file any headers needed
                 for template definitions.

              4. Put matching #pragma do_not_instantiate (see Section 5.4.1.2)
                 into the headers that define each of these template
                 classes or functions.

              5. Place each #pragma do_not_instantiate directive between
                 an #ifndef of the form #ifndef SOME_MACRO_NAME and an
                 #endif.

              6. Compile the inst.cxx file with SOME_MACRO_NAME defined.

              7. Link the source file with the resulting object file.

                                                    Using Templates 5-17

 



     Using Templates
     5.5 Advanced Program Development and Templates

           The following examples show how to create a common
           instantiation library for all the instantiations currently
           being automatically instantiated for this file.

           // foo.cxx
           #include <stdlib.h>
           #include <vector>
           #include "C.h"

           int main() {
            vector<C> v;
            v.resize(20);
                   return EXIT_SUCCESS;
           }

           // C.h
           #ifndef __C_H

           class C {};

           #endif

           Compiling with the -ptv option shows which instantiations
           occur automatically:

           Writable_repository: ./cxx_repository
           Repository_list: ./cxx_repository
           cxx: Info: /usr/proj/decc2/mainline/exxalphaosf/stdlibinclude/vector.cc, line
           90:
                     automatically instantiating void std::vector<C, std::allocator<C >
                     >::resize(unsigned long)
           void vector<T,Allocator>::resize (size_type new_size)
           // etc. etc.

           1. Place all these instantiations into a file called
              inst.cxx that is built separately or into a library:

              // inst.cxx
              #include <vector>
              #include "C.h"





     5-18 Using Templates

 



                                                         Using Templates
                          5.5 Advanced Program Development and Templates

                 #pragma instantiate void std::vector<C, std::allocator<C > >::resize(unsigned
                 long)
                 #pragma instantiate void std::vector<C, std::allocator<C > >::insert(C *,
                 unsigned long, const C &)
                 #pragma instantiate void std::vector<C, std::allocator<C > >::__insert(C *,
                 unsigned long, const C &, __true_category)
                 #pragma instantiate C *std::copy_backward(C *, C *, C *)
                 #pragma instantiate void std::fill(C *, C *, const C &)
                 #pragma instantiate C *std::copy(C *, C *, C *)
                 #pragma instantiate const unsigned long std::basic_string<char,
                 std::char_traits<char >, std::allocator<void> >::npos

              2. Add these instantiations into C.h and change "instan-
                 tiate" to "do_not_instantiate". Add an #ifndef, so
                 that when building inst.cxx, the compiler creates these
                 instantiations in the inst object file:

                 #ifndef __C_H

                 class C {};

                 #include <vector>

                 #ifndef __BUILDING_INSTANTIATIONS
                 #pragma do_not_instantiate void std::vector<C,
                         std::allocator<C > >::resize(unsigned long)
                 #pragma do_not_instantiate void std::vector<C,
                         std::allocator<C > >::insert(C*, unsigned long, const C &)
                 #pragma do_not_instantiate void std::vector<C,
                         std::allocator<C > >::__insert(C*, unsigned long,
                         const C &, __true_category)
                 #pragma do_not_instantiate C *std::copy_backward(C *, C *, C *)
                 #pragma do_not_instantiate void std::fill(C *, C *, const C &)
                 #pragma do_not_instantiate C *std::copy(C *, C *, C *)
                 #pragma do_not_instantiate const unsigned long
                         std::basic_string<char, std::char_traits<char >,
                         std::allocator<void> >::npos
                 #endif
                 #endif

              3. Build the inst object file:

                 cxx -D__BUILDING_INSTANTIATIONS -c inst.cxx


                                                    Using Templates 5-19

 



     Using Templates
     5.5 Advanced Program Development and Templates

           4. Link with the inst object file. It will use instan-
              tiations from that file instead of creating them
              automatically:

              cxx foo.cxx inst.o

           To verify that your procedure worked correctly, you
           can remove the cxx_repository subdirectory before you
           compile foo.cxx. This subdirectory should contain no
           instantiations after linking with the inst object file.

           If you have an inst.cxx file that contains many instan-
           tiations and you do not want all the symbols in the inst
           object file to be put into a user's executable even if
           only some symbols are used, (as happens with archive
           libraries), you can either split the inst.cxx into many
           smaller source files, or specify the -tused_repository
           qualifier to create the instantiations as separate object
           files in the repository (see Section 5.7). You must then
           link all the individual object files in the repository
           into your library.

     5.5.5 Multiple Repositories

           As shown in Section 5.5.4, multiple repositories can be
           specified to link an application. The first repository
           named is the read-write repository, and when processing,
           the compiler writes instantiation object files into it. At
           link time, all repositories are read only.

           The repositories are searched in a linear order, iter-
           atively, and satisfy only the unresolved instantiations
           from each pass. That is, references from instantiations
           that are added in one pass are not resolved until the next
           pass. Consider the link line in the previous example:

              cxx -c -ptr ./cxx_repository -ptr lib_repository user_code.cxx mylib.a

           In this example, all references that could be resolved
           from lib_repository would be resolved. Any reference
           arising from an instantiation in lib_repository would
           be resolved by instantiations in ./cxx_repository.



     5-20 Using Templates

 



                                                         Using Templates
                                                    5.6 Template Options

        5.6 Template Options

              Compaq C++ includes various template instantiation
              modes that control when, where, and how a template is
              instantiated:

              o  Manual instantiaion, automatic instantion, or both

              o  Placing templates in the output object or into a
                 repository

              o  Using local or external linkage

              o  As needed or complete instantiation

              A C++ program can cause the compiler to perform a template
              instantiation in two ways: explicitly or implicitly.
              A template instantiation is explicitly requested by
              using #pragma define_template, #pragma instantiate,
              or an explicit instantiation request (see Stroustrup,
              section C.13.10). A template instantiation is implicitly
              requested by simply using the template. Requesting a
              template instantiation explicitly is referred to as manual
              instantiation, while the process by which the compiler
              instantiates implicit requests is referred to as automatic
              template instantiation.

              When a template is manually instantiated, it is completely
              instantiated. For a template class, a complete instan-
              tiation means all its member functions and static data
              members are instantiated even if they were not used.
              Automatically instantiated templates may optionally be
              completely instantiated.

              Each of the following modes is mutually exclusive. Only
              one should be specified on the command line:

              -pt
              Automatically instantiate templates into the repository
              with external linkage. Manually instantiated templates are
              placed in the output object with external linkage. This
              option is the default.

              -tused
              Similar to -pt, except that automatically instantiated
              templates are placed in the output object.

                                                    Using Templates 5-21

 



     Using Templates
     5.6 Template Options

           -tused_repository (cxx -newcxx only)
           Similar to -pt, except that manually instantiated
           templates are placed in the repository.

           -nopt
           Disable automatic template instantiation. Manually
           instantiated templates are placed in the output object
           with external linkage.

           -define_templates
           -tall
           Automatically instantiate templates completely and place
           them in the output object with external linkage. Manually
           instantiated templates are also placed in the output
           object with external linkage.

           -tall_repository (cxx -newcxx only)
           Same as -tall except that all instantiations are placed in
           the repository instead of the output object. This option
           is useful for creating a pre-instantiation library.

           -tlocal
           Instantiate templates automatically, placing them in the
           output object with internal linkage. Manually instantiated
           templates are also placed in the output object with
           internal linkage. This option provides a simple mechanism
           for getting started with templates, but it has a number
           of limitations. Because the templates have local storage,
           they must be instantiated in every module that uses them,
           and code bloat could occur. In addition, a variable that
           would otherwise have a single global copy can instead have
           many local copies that do not share the same state.

           -timplicit_local (cxx -newcxx only)
           Same as -tlocal, except that manually instantiated
           templates are placed in the repository with external
           linkage. This is useful for build systems that need
           to have explicit control of the template instantiation
           mechanism. This mode can suffer the same limitations
           as -tlocal. The mode is the default when -std gnu is
           specified.




     5-22 Using Templates

 



                                                         Using Templates
                                                    5.6 Template Options

              -tweak (cxx -newcxx only)
              Same as -timplicit_local, but automatically instantiated
              templates receive weak linkage. Weak linkage resembles
              external linkage, except that duplicate symbols do not
              result in a link error. The linker simply chooses one of
              the symbols. While this behavior can still result in code
              bloat, it avoids the problem of having multiple copies of
              the same variable not sharing the same state.

              The cxx command supports the following additional options
              for the instantiation of templates:

              -pending_instantiations n
              Limit the depth of recursive instantiations so that
              infinite instantiation loops can be detected before some
              resource is exhausted. -pending_instantiations requires
              a positive non-zero value n as argument and issues an
              error when n instantiations are pending for the same class
              template. The default value for n is 64.

              -ttimestamp (cxx -newcxx only)
              Used with automatic instantiation. Causes automatic
              instantiation to instantiate templates only if they
              are not already in the repository, or if the existing
              instantiations in the repository are older than the
              timestamp in the repository.

              -Hf
              Stops the cxx command after the prelinker runs and before
              the final link. Provided for compatibility with previous
              versions of C++. This option has no effect with the
              Version 6.n compiler.

              -[no]implicit_include (cxx -newcxx only)
              Effective only with Version 6.0 and later. Enable or
              disable inclusion of source files as a method of finding
              definitions of template entities. Implicit inclusion is
              enabled by default, and it is disabled when compiling with
              -E or -P. The search rules for finding template definition
              files are the same as for include files. This option also
              defines the macro __IMPLICIT_INCLUDE_ENABLED. You might
              want to disable implicit inclusion with the -ms and -std
              ms options to match the behavior on Microsoft C++ more
              closely.

                                                    Using Templates 5-23

 



     Using Templates
     5.6 Template Options

           -nopragma_template
           Directs the compiler to ignore any #pragma define_template
           directives. This option is provided for users who want to
           migrate quickly to automatic instantiation without having
           to remove all the pragma directives from their code base.

           -ptr dir
           Specifies a repository, with ./cxx_repository as the
           default. If you specify several repositories, only the
           first is writable, and the rest are read only. Read-only
           reposi- tories are used only at link time. Specifying
           this option at link time enables C++ to recognize and use
           the template instantiation information files within the
           specified repository. If you use this option, make sure
           that the repository specified at compile time is the same
           one specified at link time.

           -ptsuf
           Specifies a list of file name suffixes that are valid
           for template definition files. Items in the list
           must be separated by commas and each suffix preceded
           by a period. A suffix may have no more than eight
           characters excluding the beginning period. The default
           is ".cxx,.CXX,.C,.cc,.CC,.cpp,.c".

           -ptv
           Turns on verbose or verify mode to display each phase of
           instantiation as it occurs. This option is useful as a
           debugging aid.

     5.7 Compatibility with Earlier Versions of C++

           The automatic template instantiation model is not
           directly compatible with previous C++ automatic template
           instantiation.

           The compiler invoked when you use the -oldcxx option is a
           Version 5.n compiler. Where possible, it is safest to
           start fresh with an empty repository, and create the
           required instantiations by compiling all source files.
           If this is not possible, there are some strategies that
           can be used to link mixed generation instantiations.



     5-24 Using Templates

 



                                                         Using Templates
                          5.7 Compatibility with Earlier Versions of C++

              If you used both Version 6.n and Version 5.n to build
              applications, Compaq strongly recommends that you use
              different repositories to contain automatic template in-
              stantiations for Version 6.n and Version 5.n compilations.

              The default repository name is the same for Version 6.n as
              for prior versions. Thus, if you use Version 6.n with
              older C++ compilers, you should do compilations in a
              different directory for each compiler or explicitly
              specify a different repository for each using the -ptr
              option.

        5.7.1 Linking with Version 5.n Instantiations

              When linking applications using Version 6.n against
              instantiations created with Version 5.n, it is necessary
              to complete the Version 5.n instantiation process, to
              create instantiation object files. This can be done with
              the -oldcxx and -Hf command-line options when linking.
              If old_repository is a Version 5.n repository then you
              would create the Version 5.n instantiation object files by
              using:

               cxx -oldcxx -Hf  -ptr old_repository <Version 5.n object files>

              The <Version 5.n object files> are the object files
              that were created using the Version 5.n compiler; old_
              repository now contains the instantiation object files.
              Create a library of these object files as follows:

               ar r lib_old_repository.a old_repository/*.o

              When linking using Version 6.n, specify lib_old_
              repository.a after all of the Version 5.n object files
              that are being linked.

              It is possible for repositories to reference objects in
              libraries that had not been referenced previously. If
              this case, you must specify the library on the command
              line again after the repository. The library might
              also reference objects not previously referenced. Some
              cycles might therefore require a single repository to be
              specified multiple times on the command line.


                                                    Using Templates 5-25

 



     Using Templates
     5.8 Linking Version 5.n Applications Against Version 6.n Repositories

     5.8 Linking Version 5.n Applications Against Version 6.n
         Repositories

           In a similar way, you can create a library of Version
           6.n instantiation object files to link into a Version 5.n
           application being linked using C++ Version 5.n. If new_
           repository is the Version 6.n repository, then a library
           of the instantiations would be created by:

            ar r lib_new_repository.a new_repository/*.o

           When linking using Version 5.n, specify lib_new_
           repository.a after all of the Version 6.n object files
           that are being linked.

           It is possible for repositories to reference objects in
           libraries that had not been referenced previously. If
           this case, you must specify the library on the command
           line again after the repository. The library might
           also reference objects not previously referenced. Some
           cycles might therefore require a single repository to be
           specified multiple times on the command line.























     5-26 Using Templates

 









                                                                       6
        ________________________________________________________________

                                                     Precompiled Headers



              Using precompiled header (PCH) files can dramatically
              reduce compilation time in environments where:

              o  Many primary sources include the same set of headers in
                 the same order.

              o  These headers introduce many lines of code.

              The Version 6.0 compiler provides a mechanism that, in
              effect, takes a snapshot of the compilation state at
              a particular point and writes it to a disk file before
              completing the compilation. Then, when recompiling the
              same source file or compiling another file with the same
              set of headers, the compiler can recognize the snapshop
              point, verify that the corresponding PCH file is reusable,
              and read it back in.

              PCH files can be large (from a minimum of 250 KB to
              several megabytes or more). To achieve the maximum
              performance gain at the smallest cost, as many sources as
              possible should share the same PCH files. The performance
              gain is thereby achieved at the smallest cost in disk
              storage.

              This chapter describes mechanisms used to generate and
              process PCH files. Topics include the following:

              o  Automatic precompiled header processing

              o  Manual precompiled header processing

              o  Other ways to control precompiled headers

              o  Performance issues

              Section 6.5 describes command-line options.

                                                 Precompiled Headers 6-1

 



     Precompiled Headers
     6.1 Automatic Precompiled Header Processing

     6.1 Automatic Precompiled Header Processing

           You enable automatic precompiled header process-
           ing by specifying the -pch command-line option (see
           Section 6.5). The compiler automatically looks for a
           qualifying precompiled header file to read in, or it
           creates one for use on a subsequent compilation. In some
           cases, it performs both operations.

           The PCH file contains a snapshot of all the code preceding
           the header stop point, typically the first token in
           the primary source file that does not belong to a
           preprocessing directive. You also can specify the stop
           point directly by using #pragma hdrstop if that comes
           first (see Section 6.3). For example:

                #include "xxx.h"
                #include "yyy.h"
                int i;

           The header stop point is int (the first nonpreprocessor
           token), and the PCH file contains a snapshot reflecting
           the inclusion of xxx.h and yyy.h. If the first non
           preprocessor token or the #pragma hdrstop appears within
           a #if block, the header stop point is the outermost
           enclosing #if. For example:

                #include "xxx.h"
                #ifndef YYY_H
                #define YYY_H 1
                #include "yyy.h"
                #endif
                #if TEST
                int i;
                #endif

           Here, the first token that does not belong to a prepro-
           cessing directive is again int, but the header stop point
           is the start of the #if block containing it. The PCH file
           reflects the inclusion of xxx.h and conditionally the
           definition of YYY_H and inclusion of yyy.h; it does not
           contain the state produced by #if TEST.



     6-2 Precompiled Headers

 



                                                     Precompiled Headers
                             6.1 Automatic Precompiled Header Processing

              A PCH file is produced only if the header stop point
              and the code preceding it (mainly, the header files
              themselves) meet the following requirements:

              o  The header stop point must appear at file scope-it may
                 not be within an unclosed scope established by a header
                 file. For example, a PCH file is not created in this
                 case:

                          // xxx.h
                          class A {

                          // xxx.C
                          #include "xxx.h"
                          int i; };

                 The header stop point may not be inside a declaration
                 started within a header file, nor may it be part of
                 a declaration list of a linkage specification. For
                 example, in the following case the header stop point
                 is int, but because it is not the start of a new
                 declaration, no PCH file is created:

                          // yyy.h
                          static

                          // yyy.C
                          #include "yyy.h"
                          int i;

              o  The header stop point cannot be inside a #if block or
                 a #define started within a header file. The processing
                 preceding the header stop must not have produced any
                 errors. (Warnings and other diagnostics are generally
                 not reproduced when the PCH file is reused.)

                 No references to predefined macros __DATE__ or
                 __TIME__ may have appeared. No use of the #line
                 preprocessing directive may have appeared; #pragma no_
                 pch (see Section 6.3) must not have appeared. The code
                 preceding the header stop point must have introduced
                 a sufficient number of declarations to justify the
                 overhead associated with precompiled headers.


                                                 Precompiled Headers 6-3

 



     Precompiled Headers
     6.1 Automatic Precompiled Header Processing

           When a precompiled header file is produced, it contains,
           in addition to the snapshot of the compiler state, some
           information that can be checked to determine under what
           circumstances it can be reused. This includes:

           o  The compiler version, including the date and time the
              compiler was built

           o  The current directory (that is, the directory in which
              the compilation is occurring)

           o  The command-line options

           o  The initial sequence of preprocessing directives from
              the primary source file, including #include directives

           o  The date and time of the header files specified in
              #include directives

           This information comprises the PCH prefix. The prefix
           information of a given source file can be compared to the
           prefix information of a PCH file to determine whether the
           latter is applicable to the current compilation.

           As an illustration, consider two source files:

                // a.C
                #include "xxx.h"
                 . . .          // Start of code

                // b.C
                #include "xxx.h"
                 . . .          // Start of code

           When a.C is compiled with -pch:

           1. A precompiled header file named a.pch is created.

           2. When b.C is compiled (or when a.C is recompiled), the
              prefix section of a.pch is read in for comparison with
              the current source file.

           If the command-line options are identical, if xxx.h has
           not been modified, and so forth, then, instead of opening
           xxx.h and processing it line by line, the compiler reads
           in the rest of a.pch and thereby establishes the state for
           the rest of the compilation.

     6-4 Precompiled Headers

 



                                                     Precompiled Headers
                             6.1 Automatic Precompiled Header Processing

              It may be that more than one PCH file is applicable to
              a given compilation. If so, the largest (that is,the one
              representing the most preprocessing directives from the
              primary source file) is used. For instance, consider a
              primary source file that begins as follows:

                   #include "xxx.h"
                   #include "yyy.h"
                   #include "zzz.h"

              If there is one PCH file for xxx.h and a second for xxx.h
              and yyy.h, the latter will be selected (assuming both are
              applicable to the current compilation). Moreover, after
              the PCH file for the first two headers is read in and the
              third is compiled, a new PCH file for all three headers
              may be created.

              When a precompiled header file is created, it takes the
              name of the primary source file, with the suffix replaced
              by .pch. Unless -pch_dir is specified, it is created in
              the current directory.

              When a precompiled header file is created or used, a
              message such as the following is issued:

                   "test.C": creating precompiled header file "test.pch"

              The user may suppress the message by using the command-
              line option -no_pch_messages.

              In automatic mode (that is, when -pch is used) the
              compiler will deem a precompiled header file obsolete
              and delete it under either of the following circumstances:

              o  The precompiled header file is based on at least one
                 out-of-date header file but is otherwise applicable for
                 the current compilation.

              o  The precompiled header file has the same base name
                 as the source file being compiled (for example,
                 xxx.pch andxxx.C) but is not applicable for the current
                 compilation (for example, because of different command-
                 line options).

              This handles some common cases; the user must manage other
              PCH file clean up.

                                                 Precompiled Headers 6-5

 



     Precompiled Headers
     6.1 Automatic Precompiled Header Processing

           Only header files that were included in the original PCH
           file are checked for modification. If the user changes
           the structure of the header files, such that different
           files would be included now from when the PCH file was
           generated, without modifying at least one of the original
           header files that were included in the PCH file, the
           change would go undetected, and an out of date PCH file
           would be used.

           For example, adding a prolog or epilog file to a directory
           that previously did not have one would not automatically
           result in a new PCH file being created.

           Also, consider the following:

            cxx -Iinc1 -Iinc2 -pch foo.c

           Where foo.c includes the file foo.h. If file foo.h is
           found in directory inc2 when the PCH file is created, but
           a new foo.h is added to directory inc1, thereby hiding the
           old foo.h in inc2, a new PCH file would not be created.

           It is the user's responsibility to remove any PCH
           files that may be out of date because of these kinds of
           changes.

     6.2 Manual Precompiled Header Processing

           Command-line option -create_pch file-name specifies that
           a precompiled header file of the specified name should be
           created.

           Command-line option -use_pch file-name specifies that the
           indicated precompiled header file should be used for this
           compilation; if it is invalid (that is, if its prefix does
           not match the prefix for the current primary source file),
           a warning will be issued and the PCH file will not be
           used.

           When either of these options is used in conjunction with
           -pch_dir, the indicated file name (which may be a path
           name) is tacked on to the directory name, unless the file
           name is an absolute path name.


     6-6 Precompiled Headers

 



                                                     Precompiled Headers
                                6.2 Manual Precompiled Header Processing

              The -create_pch, -use_pch, and -pch options may not be
              used together. If more than one of these options is
              specified, only the last one will apply. Nevertheless,
              most of the description of automatic PCH processing
              applies to one or the other of these modes-header stop
              points are determined the same way, PCH file applicability
              is determined the same way, and so forth.

        6.3 Other Ways for Users To Control Precompiled Headers

              The user can control and tune how precompiled headers are
              created and used in several ways:

              o  #pragma hdrstop may be inserted in the primary source
                 file at a point prior to the first token that does not
                 belong to a preprocessing directive. This enables the
                 user to specify where the set of header files that is
                 subject to precompilation ends. For example,

                          #include "xxx.h"
                          #include "yyy.h"
                          #pragma hdrstop
                          #include "zzz.h"

                 Here, the precompiled header file includes processing
                 state for xxx.h and yyy.h but not zzz.h. (This is
                 useful if the user decides that the information added
                 by what follows the #pragma hdrstop does not justify
                 the creation of another PCH file.)

              o  #pragma no_pch may be used to prevent the generation of
                 a pch file for a given source.

                 Command-line option -pch_dir directory-name is used to
                 specify the directory in which to search for or create
                 a PCH file.

        6.4 Performance Issues

              The relative overhead incurred in writing out and reading
              back in a precompiled header file is quite small for
              reasonably large header files.



                                                 Precompiled Headers 6-7

 



     Precompiled Headers
     6.4 Performance Issues

           In general, it does not cost much to write a precompiled
           header file even if it does not end up being used, and
           if it is used, it almost always produces a significant
           decrease in compilation time.

           Despite the faster recompilations, precompiled header
           processing is not likely to be justified for an arbitrary
           set of files with nonuniform initial sequences of
           preprocessing directives.

           The greatest benefit occurs when a number of source files
           can share the same PCH file. The more sharing, the less
           disk space is consumed. With sharing, the disadvantage of
           large precompiled header files can be minimized, without
           giving up the advantage of a significant decrease in
           compilation times.

           Consequently, to take full advantage of header file
           precompilation, users should expect to reorder the
           #include sections of their source files and to group
           #include directives within a commonly used header file.

           Different environments and different projects will have
           different needs, but in general, users should be aware
           that making the best use of the precompiled header support
           will require some experimentation and probably some minor
           changes to source code.

     6.5 Command-Line Options for Precompiled Headers

           You can specify the following options for precompiled
           headers:

           -create_pch file-name
           If other conditions are satisfied, create a precompiled
           header file with the specified name. If -pch (automatic
           PCH mode) or -use_pch appears on the command line
           following this option, the last option is used. This
           option defines the macro __PCH_ENABLED.

           -pch
           Automatically use, create, or both, a precompiled header
           file. If -use_pch or -create_pch (manual PCH mode) appears
           on the command line following this option, the last option
           is used. This option defines the macro __PCH_ENABLED.

     6-8 Precompiled Headers

 



                                                     Precompiled Headers
                        6.5 Command-Line Options for Precompiled Headers

              -pch_dir directory-name
              The directory in which to search for, create, or both,
              a precompiled header file. You can use this option with
              automatic PCH mode (-use_pch or -pch) or manual PCH mode
              -create_pch or -use_pch.

              -pch_messages
              -no_pch_messages
              Enable or disable the display of a message indicating
              that a precompiled header file was created or used in the
              current compilation. The default is -pch_messages.

              -use_pch file-name
              Use a precompiled header file of the specified name as
              part of the current compilation. If -pch (automatic PCH
              mode) or -create_pch appears on the command line following
              this option, the last option is used. This option defines
              the macro __PCH_ENABLED.



























                                                 Precompiled Headers 6-9

 









                                                                       7
        ________________________________________________________________

                                                The C++ Standard Library



              The C++ Standard Library provided with this release
              defines a complete specification of the International
              C++ Standard, with some differences, as described in the
              online release notes in:

              /usr/lib/cmplrs/cxx/CompaqCXXversion.release-notes

              or

              /usr/lib/compaq/cxx-version/alpha-linux/doc/readme.ps | .txt

              The Standard Library in this release includes the ANSI
              locale and iostream libraries.

              Portions of the ANSI C++ Standard Library have been
              implemented in Compaq C++ using source licensed from
              and copyrighted by Rogue Wave Software, Inc. Information
              pertaining to the C++ Standard Library has been edited and
              incorporated into Compaq C++ documentation with permission
              of Rogue Wave Software, Inc. All rights reserved.

              On Tru64 UNIX, some of the components in the C++ Standard
              Library are designed to replace nonstandard components
              that are currently distributed in the Class Library.
              The Class Library will continue to be provided in its
              nonstandard form. However, you now have the option of
              using new standard components.

              This chapter provides information about the implementation
              of the Standard Library, including upward compatibility,
              compiling, linking, and thread safety. Small example
              programs showing how to use the C++ standard library are
              located in the directory /usr/examples/cxx.

              The following are Standard Library options:

                                            The C++ Standard Library 7-1

 



     The C++ Standard Library


           -[no]using_std
           Controls whether Standard Library header files are
           processed as though the compiled code were written as
           follows:

                using namespace std;
                #include <header>

           These options are provided for compatibility for users who
           do not want to qualify use of each Standard Library name
           with std:: or put using namespace std; at the top of their
           sources.

           -using_std turns implicit using namespace std on; this is
           the default when compiling -std arm, -std cfront, -std ms,
           or -std ansi.

           -nousing_std turns implicit using namespace std off; this
           is the default when compiling -std strict_ansi or -std
           strict_ansi_errors.

           -[no]stdnew
           Controls whether calls are generated to the ANSI or pre-
           ANSI implementation of the operator new(). On memory
           allocation failure, the ANSI implementation throws
           std::bad_alloc, while the pre-ANSI implementation returns
           0.

           -stdnew generates calls to the ANSI new() implementation;
           this is the default when compiling -std ansi, -std strict_
           ansi and -std strict_ansi_errors.

           -nostdnew generates calls to the pre-ANSI new() implemen-
           tation; this is the default when compiling -std arm, -std
           cfront and -std ms.

           -[no]global_array_new
           Controls whether calls to global array new and delete are
           generated as specified by ANSI. Pre-ANSI global array new
           generated calls to operator new(). According to ANSI, use
           of global array new generate calls to operator new()[].

           -global_array_new generates calls to operator new()[]  for
           global array new expressions such as new int[4]; this is
           the default when compiling -std ansi, -std strict_ansi,
           -std strict_ansi_errors, and -std ms.

     7-2 The C++ Standard Library

 



                                                The C++ Standard Library


              -noglobal_array_new generates calls to operator new()
              for global array new expressions such as new int[4] and
              preserves compatibility with Version 5.n; this is the
              default when compiling -std arm and -std cfront.


        7.1 Important Compatibility Information


              The following sections describe specific compatibility
              issues.

        7.1.1 -[no]using_std Compiler Compatibility Switch

              All Standard Library names in Compaq C++ are inside the
              namespace std. Typically you would qualify each Standard
              Library name with std:: or put using namespace std; at the
              top of your source file.

              To make things easier for existing users, using namespace
              std; is included in a file provided with every Standard
              Library header when you are in arm, cfront, ms, or ansi
              compiler modes. This is not the default in strict_ansi or
              strict_ansi_errors mode.

              The compiler supplied switches -nousing_std and -using_std
              can be used to override the default. -nousing_std turns
              the implicit using namespace std off; -using_std turns it
              on.

        7.1.2 Pre-ANSI/ANSI IOStreams Compatibility

              The C++ Standard Library offers support for the standard
              IOStreams library based on the International C++ Standard.
              These standard iostream classes are in the new header
              files <iostream>, <ostream>, <istream>, and so on (no .h
              or .hxx extension).

              For backward compatibility, the pre-ANSI IOStream library
              is still provided in the old header files iostream.hxx,
              istream.hxx, and so on. The two libraries exhibit subtle
              differences and incompatibilities.

              Users can choose which version (ANSI or pre-ANSI) of
              iostreams they want to use; either version of iostreams
              can be integrated seamlessly with the new Standard Library
              and string functionality.

                                            The C++ Standard Library 7-3

 



     The C++ Standard Library
     7.1 Important Compatibility Information

           To accomplish this goal, macros called __USE_STD_IOSTREAM
           and
           __NO_USE_STD_IOSTREAM are provided. If you do not set
           these macros explicitly, the default in arm, cfront, ms,
           and ansi modes is to use the pre-ANSI IOStream library. In
           strict_ansi and strict_ansi_errors mode, the default is to
           use the ANSI IOStream library.

           You override the default by defining __USE_STD_IOSTREAM
           or
           __NO_USE_STD_IOSTREAM on either the command line or in
           your source code.

           In arm, cfront, ms, and ansi modes, specify use of the
           ANSI iostreams in one of the following ways:

           o  Enter -D__USE_STD_IOSTREAM on the command line.

           o  Put #define __USE_STD_IOSTREAM in your source file
              before any include files.

           In strict_ansi and strict_ansi_errors modes specify use of
           the pre-ANSI iostreams in one of the following ways:

           o  Enter -D__NO_USE_STD_IOSTREAM on the command line.

           o  Put #define __NO_USE_STD_IOSTREAM in your source file
              before any include files.

           A #error warning appears:

           1. If you have explicitly included the wrong header for
              the current mode. For example, if you say #include
              <iostream> (an ANSI header) and you are in -std ansi,
              -std cfront, -std ms or -std arm mode, and if you have
              not entered -D__USE_STD_IOSTREAM on the command line,
              an error message appears.

           2. If you are in -std strict_ansi or -std strict_ansi_
              errors, and you enter #include <iostream.h>, an error
              message appears unless you also enter -D__NO_USE_STD_
              IOSTREAM.

           Many of the other headers, <string> for example, make
           use of the iostream classes. The default version of
           iostreams that is automatically included when you include
           one of these headers depends on the mode you compile in

     7-4 The C++ Standard Library

 



                                                The C++ Standard Library
                                 7.1 Important Compatibility Information

              and the setting of the macros __USE_STD_IOSTREAM and
              __NO_USE_STD_IOSTREAM as described earlier.

              Because the standard locale class and the standard
              iostream class are so closely tied, you cannot use the
              standard locale class with the pre-standard iostream
              classes. If you want to use locale, you must use the
              standard iostream classes.

              It is possible to use the pre-ANSI and the ANSI IOStream
              library in the same source file, because all the standard
              iostream names (that is, cout, cin, and so on) are in
              namespace std, and all the pre-ANSI names are in the
              global namespace. This is not recommended, though,
              because there is no guarantee of stream objects being
              the same size or, for example, of ::cout being in sync
              with std::cout.

              To do this in all modes, include a pre-ANSI iostreams
              header before an ANSI iostreams header as follows:

                #include <stdlib.h>
                #undef __USE_STD_IOSTREAM
                #include <iostream.h>
                #define __USE_STD_IOSTREAM
                #include <iostream>

                int main()
                {
                  std::string s("abc");
                  ::cout << "abc" << endl;         // pre-standard iostreams
                  std::cout << "abc" << std::endl; // standard iostreams
                  return EXIT_SUCCESS;
                }

              To do this in all modes, if you include an ANSI iostreams
              header before a pre-ANSI iostreams header, follow these
              steps:

              1. Compile your source using -nousing_std.

              2. Use the __USE_STD_IOSTREAM macro as shown in the
                 following example. You must define __USE_STD_IOSTREAM
                 at the end of your include file list so that the
                 template definition files (the .cc files) are included
                 in the correct mode.

                                            The C++ Standard Library 7-5

 



     The C++ Standard Library
     7.1 Important Compatibility Information

                // Compile this with -nousing_std
                #include <stdlib.h>
                #define __USE_STD_IOSTREAM
                #include <iostream>
                #undef __USE_STD_IOSTREAM
                #include <iostream.h>
                #define __USE_STD_IOSTREAM // so the template definition files are ok

                int main()
                {
                  std::string s("abc");
                  ::cout << "abc" << endl; // pre-standard iostreams
                  std::cout << "abc" << std::endl; // standard iostreams
                  return EXIT_SUCCESS;
                }

     7.1.3 Support for pre-ANSI and ANSI operator new()

           The Standard C++ Library supports the ANSI implementation
           of the operator new() as well as the pre-ANSI implemen-
           tation of operator new(). The ANSI implementation throws
           std::bad_alloc on memory allocation failures.

           The pre-ANSI implementation of the operator new() returns
           0 on memory allocation failures. Because the ANSI behavior
           is incompatible with pre-ANSI applications, a compile time
           switch has been added (-[no]stdnew) to control whether
           calls to ANSI new() or pre-ANSI new are generated.

           The following examples show how ANSI versus pre-ANSI
           new() check for memory allocation. First, here is an
           ANSI new() check for memory allocation failure:

                       try {
                           myobjptr = new (myobjptr);
                       }
                       catch (std::bad_alloc e) {
                           cout << e.what() << endl;
                       };

           The following example shows a pre-ANSI new() check for
           memory allocation failure:

                       if ((myobjptr = new (myobjptr)) == 0)
                           call_failure_routine();

     7-6 The C++ Standard Library

 



                                                The C++ Standard Library
                                 7.1 Important Compatibility Information

              When upgrading pre-ANSI new() code to work with the C++
              Standard Library you also can use the nothrow version of
              ANSI new(). To do so in the pre-ANSI example, you could
              recode it as follows:

                          if ((myobjptr = new (myobjptr, nothrow)) == 0)
                               call_failure_routine();

              Two command line switches are available in the compiler
              to control whether calls are generated to the ANSI or
              pre-ANSI implementation of operator new(). Use the
              -stdnew switch to generate calls to the ANSI new()
              implementation. Use the -nostdnew switch to generate calls
              to the pre-ANSI new() implementation.

              You can override global new() by declaring your own
              functions.

              When compiling with -std ansi, -std strict_ansi, and -std
              strict_ansi_errors, -stdnew is the default. When compiling
              with -std arm, -std cfront, and -std ms, -nostdnew is the
              default. The compiler defines the macro __STDNEW when the
              -stdnew option is specified.

        7.1.4 Overriding operator new()

              If you want to define a global operator new() to displace
              the version used by the C++ Standard Library or C++ Class
              Library, follow these steps:

              1. Define a module that will contain two entry points for
                 your version of global operator new(): one for the
                 Standard Library and one for the Class Library.

                 When you link with this module, your version of the
                 global operator new() displaces the version used by
                 either the C++ Standard Library or C++ Class Library.

              2. Decide whether you want to compile the module using the
                 -stdnew or the -nostdnew option. You must always use
                 the same option when compiling the module.

              3. Code the module for the compilation method you have
                 chosen, as follows:

                                            The C++ Standard Library 7-7

 



     The C++ Standard Library
     7.1 Important Compatibility Information

              For module to be compiled with -stdnew

              1. Include two entry points for your version of global
                 operator new():

                 o  __7__nw__FUl  (-model ansi) or __nw__XUl  (-model
                    arm), which is used to override global operator
                    new() in the Class Library. This entry point has
                    the name generated by the Class Library version
                    of global operator new(), which is the mangled
                    name used in the Class Library.

                 o  new, which is used to override global operator
                    new() in the Standard Library. This entry point
                    has the name generated by the Standard Library
                    version of global operator new().

              2. Define global operator new() in terms of the entry
                 point new. The __7__nw__FUl  (-model ansi) or
                 __nw__XUl  (-model arm) version is declared with
                 extern C and simply calls the first version. Your
                 module will contain two routines similar to the
                 following:

                      #include <new>
                      ...

                      // Redefine global operator new(),
                      // entry point into C++ Standard Library.
                      // Also override user calls to operator new()

                      void *operator new(size_t size) throw(std::bad_alloc) {
                      printf("in my global new\n");
                      ...
                      }

                      // Entry point into C++ Class Library

                      #ifdef __MODEL_ANSI
                      extern "C" void *__7__nw__FUl(size_t size) {
                      #else  //__MODEL_ARM
                      extern "C" void *__nw__XUl(size_t size) {
                      #endif
                           return ::operator new(size);
                      }

     7-8 The C++ Standard Library

 



                                                The C++ Standard Library
                                 7.1 Important Compatibility Information

                 For module to be compiled with -nostdnew

                 1. Include two entry points for your version of global
                    operator new():

                    o  __7__stdnw__FUl  (-model ansi) or __stdnw__XUl
                       (-model arm), which is used to override global
                       operator new() in the Standard Library. This
                       entry point has the name generated by the
                       Standard Library version of global operator
                       new(), which is the mangled name used in the
                       Standard Library.

                    o  new, which is used to override global operator
                       new() in the Class Library. This entry point has
                       the name generated by the Class Library version
                       of global operator new().

                 2. Define global operator new in terms of the entry
                    point new. The __7__stdnw__FUl  (-model ansi) or
                    __stdnw__XUl (-model arm) version is declared with
                    extern C and simply calls the first version. Your
                    module will contain two routines similar to the
                    following:

                         #include <new>
                         ...

                         // Redefine global operator new(),
                         // entry point into C++ Class Library.
                         // Also override user calls to operator new().

                         void *operator new(size_t size) {
                         printf("in my global new\n");
                         ...
                         }

                         // Entry point into C++ Standard Library

                         #ifdef __MODEL_ANSI
                         extern "C" void *__7__stdnw__FUl(size_t size) {
                         #else  //__MODEL_ARM
                         extern "C" void *__stdnw__XUl(size_t size) {
                         #endif
                              return ::operator new(size);
                         }

                                            The C++ Standard Library 7-9

 



     The C++ Standard Library
     7.1 Important Compatibility Information

     7.1.5 Support for Global array new and delete Operators

           Compaq C++ Version 6.n fully supports the array new
           and delete operators as described in the ANSI standard.
           Previous versions did not. You might therefore encounter a
           compatibility problem if you have overridden the run-time
           library's operator new() with your own version.

           For example:

           #include <stdlib.h>
           #include <iostream.h>

           inline void* operator new(size_t s) {
            cout << "called my operator new" << endl;
            return 0;
           }

           int main() {
            new int;    // ok, this still calls your own
            new int[4]; // In V6.0 calls the C++ library's operator new[]
                   return EXIT_SUCCESS;
           }

           In older versions, both new int and new int[4] would
           generate a call to operator new() (they would just be
           asking for different sizes). With the current compiler,
           new int still generates a call to operator new().
           However, new int[4] generates a call to operator new()[].
           This means that if you still want to override the
           library's operator new you must do one of the following:

           1. Provide your own definition of operator new()[].

           2. Use the -noglobal_array_new switch.

           The -noglobal_array_new switch converts all expressions
           such as new int[4] to calls to the global operator
           new(), thus preserving compatibility with older compiler
           versions.

           This switch has no effect on class-specific array operator
           new and delete; it affects only the global operators.

           When compiling with -std ansi, -std strict_ansi, -std
           strict_ansi_errors, and -std ms modes, -global_array_
           new is the default. When compiling with -std arm or -std
           cfront modes, -noglobal_array_new is the default. A macro

     7-10 The C++ Standard Library

 



                                                The C++ Standard Library
                                 7.1 Important Compatibility Information

              __GLOBAL_ARRAY_NEW is predefined by the compiler when
              -global_array_new is used.

        7.2 How to Build Programs Using the C++ Standard Library

              When you use the cxx command to compile and link programs
              that use the C++ Standard Library, no special switches are
              required. The Compaq C++ driver automatically includes the
              Standard Library run-time support (-lcxxstd) on the link
              command, and automatic template instantiation (-pt) is the
              default mode.

              For example, to build a program called prog.cxx that uses
              the Standard Library, you can simply use the following
              command:

              cxx prog.cxx

                _______________ [Tru64] Thread Safety _______________

                The Standard Library provided with this release is
                thread safe but not thread reentrant. Thread safe
                means that all library internal and global data
                is protected from simultaneous access by multiple
                threads. In this way, internal buffers as well as
                global data like cin and cout are protected during
                each individual library operation. Users, however,
                are responsible for protecting their own objects.

                According to the C++ standard, results of recursive
                initialization are undefined. To guarantee thread
                safety, the compiler inserts code to implement a
                spinlock if another thread is initializing local
                static data. If recursive initialization occurs, the
                code deadlocks even if threads are not used.

                _____________________________________________________

        7.3 Optional Switch to Control Buffering

              The inplace_merge, stable_sort, and stable_partition
              algorithms require the use of a temporary buffer. Two
              methods are available for allocating this buffer:

              o  Preallocate 16K bytes of space on the stack.

              o  Allocate the required amount of storage dynamically.

                                           The C++ Standard Library 7-11

 



     The C++ Standard Library
     7.3 Optional Switch to Control Buffering

           By default, the current library makes use of the
           preallocated buffer, which avoids the overhead of run-time
           allocation. If your application requires a buffer that
           exceeds 16K, it can not take advantage of this default.

           If you are concerned with minimizing the use of stack
           space in your program, or if your application requires
           a buffer that exceeds 16K, define the __DEC_DYN_ALLOC
           macro to enable dynamic buffering. Do this by adding the
           following to your compile command line:

           -D__DEC_DYN_ALLOC

     7.4 Enhanced Compile-time Performance of ANSI IOStreams

           To speed up the compile-time performance of programs that
           use the standard iostream and locale components, many
           common template instantiations of these components have
           been included in the Standard Library.

           To force programs to create instantiations at compile-
           time (for example, if you want to debug them and thus
           need them to be compiled with the -gall option), define
           the macro __FORCE_INSTANTIATIONS on the command line.
           This definition suppresses the #pragma do_not_instantiate
           directives in the headers so that the compiler creates the
           instantiations in your repository directory.

           You must then specify the -nopreinst option to force the
           compiler to link your instantiations instead of those in
           the Standard Library.

     7.5 Upgrading from the Class Library to the Standard Library
         Provided with Version 6.n

           The following discussion guides you through upgrading
           the Class Library code to use the Standard Library,
           specifically replacing the vector and stack classes in
           the vector.hxx header file to the Standard Library vector
           and stack classes.





     7-12 The C++ Standard Library

 



                                                The C++ Standard Library
 the     Class Library to the Standard Library Provided with Version 6.n

        7.5.1 Upgrading from the Class Library Vector to the Standard
              Library Vector

              To change your code from using the Class Library vector
              to the Standard Library vector, consider the following
              actions:

              o  Change the name of your #include statement from
                 <vector.h> or <vector.hxx> to <vector>.

              o  Remove the vectordeclare and vectorimplement declara-
                 tions from your code.

              o  Change all vector(type) declarations to vector<type>.
                 For example, vector(int) vi should become vector<int>
                 vi.

              o  Note that the following member functions are replaced
                 in the Standard Library:

                 _______________________________________________________
                 Nonstandard Vector      Standard Library Vector
                 Function________________Function_______________________

                 elem(int index)         operator[](size_t index)
                                         (no bounds checking)

                 operator[](int index)   at(size_t index)
                                         (bounds checking)

                 setsize(int_newsize)____resize(size_t_newsize)_________

              o  When copying vectors of unequal lengths, note that the
                 Standard Library vector has a different behavior as
                 follows:

                 When using the Standard Library vector, if the target
                 vector is smaller than the source vector, the target
                 vector automatically increases to accommodate the
                 additional elements.

                 The Class Library vector displays an error and aborts
                 when this situation occurs.

              o  Another difference in behavior occurs when you specify
                 a negative index for a vector.

                                           The C++ Standard Library 7-13

 



     The C++ Standard Library
     7.5 Upgrading from the Class Library to the Standard Library Provided with Version 6.n

              The Class Library vector class detects the negative
              specification and issues an error message. However, the
              Standard Library vector silently converts the negative
              value to a large positive value, because indices are
              represented as type size_t (unsigned long) rather than
              int.

           o  When an out-of-bounds error occurs, the existing
              vector prints an error message and aborts, whereas
              the Standard Library vector throws an out-of-range
              object.

     7.5.2 Upgrading from the Class Library Stack to the Standard
           Library Stack

           To change your code from using the existing stack to the
           Standard Library stack, consider the following actions:

           o  Change the name of your #include statement from
              <vector.h> or <vector.hxx> to <stack>.

           o  Remove the stackdeclare and stackimplement declarations
              from your code.

           o  Change all stack(type) declarations to stack<type,
              deque<type> >. For example, stack(int) si should become
              stack<int, deque<int> > si.

           o  Do not specify an initial size for a Standard Library
              stack. The stack must start out empty and grow
              dynamically (as you push and pop).

           o  The following member functions are not supported or
              have different semantics:

              _______________________________________________________
              Class_Library_Stack___Standard_Library_Stack___________

              size_used()           Does not exist because the
                                    size() function always is equal
                                    to the size_used() function.

              full()                Does not exist because the stack
                                    always is full.

     7-14 The C++ Standard Library

 



                                                The C++ Standard Library
 the     Class Library to the Standard Library Provided with Version 6.n

                 _______________________________________________________
                 Class_Library_Stack___Standard_Library_Stack___________

                 pop()                 Does not return the popped
                                       element. To simulate Class
                                       Library behavior, first obtain
                                       the element as the return type
                                       from the top() function and then
                                       call the pop() function. For
                                       example, change int i=s.pop();
                                       to the following:

                                       int i=s.top();
                 ______________________s.pop();_________________________

              o  The Standard Library stack differs from the Class
                 Library stack in the way errors are detected. Unlike
                 the nonstandard stack, you cannot overflow a Standard
                 Library stack because space is allocated dynamically as
                 you push elements onto the stack.

        7.5.3 Upgrading from the Class Library String Package Code

              The Standard Library basic_string can replace the Class
              Library String Package.

              The following list guides you through upgrading nonstan-
              dard code to use the Standard Library basic_string:

              o  Change #include <string.h> or #include <string.hxx> to
                 #include <string>.

              o  Change all declarations of String to string (uppercase
                 S to lowercase s).

              o  The String Package allowed assignment of a string
                 directly to a char *; however, the basic_string library
                 does not allow this. You can assign the string's const
                 char* representation using the c_str() or data()
                 basic_string member functions. For example:

                 string s("abc");
                 char* cp = s; // not allowed
                 const char* cp = s.data(); // ok

                 The state of the string is undefined if the result of
                 data() is cast to a non-const char* and then the value
                 of that char* is changed.

                                           The C++ Standard Library 7-15

 



     The C++ Standard Library
     7.5 Upgrading from the Class Library to the Standard Library Provided with Version 6.n

           o  The String Package member functions upper() and
              lower() are not in the basic_string library. You
              can write these functions as nonmember functions, as
              follows:

              template <class charT, class traits, class Allocator>
              inline
              basic_string<charT, traits, Allocator>
              upper(const basic_string<charT,traits, Allocator>& str) {
                      basic_string<charT, traits, Allocator> newstr(str);
                      for (size_t index = 0; index < str.length(); index++)
                              if (islower(str[index]))
                                      newstr[index] = toupper(str[index]);
                      return newstr;
              }

              template <class charT, class traits, class Allocator>
              inline
              basic_string<charT, traits, Allocator>
              lower(const basic_string<charT,traits, Allocator>& str) {
                      basic_string<charT, traits, Allocator> newstr(str);
                      for (size_t index = 0; index < str.length(); index++)
                              if (isupper(str[index]))
                                      newstr[index] = tolower(str[index]);
                      return newstr;
              }

              Then instead of calling upper() and lower()  as member
              functions of the basic_string, pass the string as an
              argument. For example:

              s2 = s1.upper(); // does not compile
              s2 = upper(s1); // ok

           o  The String Package match() member function does not
              exist. Equivalent functionality exists in the Standard
              Library algorithm mismatch(), although using it is
              more complicated. For example:







     7-16 The C++ Standard Library

 



                                                The C++ Standard Library
 the     Class Library to the Standard Library Provided with Version 6.n

                 string s1("abcdef");
                 string s2("abcdgf");
                 assert(s1.match(s2)==4); // does not compile
                 pair<string::iterator,string::iterator> p(0,0); // ok
                 p=mismatch(s1.begin(),s1.end(),s2.begin());
                 assert(p.first-s1.begin()==4);
                 string s3 = s1;
                 p=mismatch(s1.begin(),s1.end(),s3.begin());
                 assert(p.first == s1.end()); // everything matched

              o  The String Package index() member function does not
                 exist. The basic_string library equivalent is find().

              o  The String Package constructor that takes two
                 positional parameters (a start and end position) and
                 constructs a new string does not exist. It is replaced
                 in the basic_string library with the member function
                 substr(). For example:

                 string s("abcde");
                 string s2 = s1(1,3); // does not compile
                 string s2 = s1.substr(1,3); // ok

              o  Many previously undetected run-time errors now throw
                 standard exceptions in the String library.

        7.5.4 Upgrading from the Class Library Complex to the ANSI
              Complex Class

              This section explains how to upgrade from the pre-ANSI
              complex library to the current standard complex library.

              In the ANSI library, complex objects are templatized on
              the type of the real and imaginary parts, the pre-ANSI
              library, complex objects are not templatized. The pre-
              ANSI library assumes the type is double, whereas the new
              library provides specializations for float, double, and
              long double as well as allowing users to specialize on
              their own floating point types.

              Mathematical error checking is not supported in the
              ANSI library. Users who rely on detection of underflow,
              overflow, and divide by zero should continue using the
              pre-ANSI complex library.

                                           The C++ Standard Library 7-17

 



     The C++ Standard Library
     7.5 Upgrading from the Class Library to the Standard Library Provided with Version 6.n

           The following is a detailed list of important changes:

           o  Change #include <complex.h> or #include <complex.hxx>
              to #include <complex>.

           o  Change all declarations of complex to complex<double>,
              for example:

              complex c;

              Change to:

              complex<double> c;

           o  The polar() function no longer supplies a default
              value of 0 for the second argument. Users will have
              to explicitly add it to any calls that have only one
              argument, for example:

              complex c;
              c = polar(c); // get polar

              Change to:

              complex<double> c;
              c = polar(c,0.0);

           o  If you are calling a mathematical function or
              mathematical operator that takes scalars as arguments
              (polar() for example), then you must adjust the
              arguments you pass in to be the same type as the
              complex template parameter type. For example, you would
              have to change:

              complex c = polar(0,0);
              complex c2 = c+1;

              Change to:

              complex<double> c = polar(0.0,0.0); // 0.0 is double
              complex<double> c2= c + 1.0; // 1.0 is double

           o  The complex_zero variable is not declared in the
              complex header file. If you want to use it, you will
              have to declare it yourself. For example, add the
              following to the top of your source file:

              static const complex<double> complex_zero(0.0,0.0);

     7-18 The C++ Standard Library

 



                                                The C++ Standard Library
 the     Class Library to the Standard Library Provided with Version 6.n

              o  The sqr() and arg1() functions are gone. If you want
                 to continue to use them, you should define them in one
                 of your own headers, using the following definitions:

                 template <class T>
                 inline complex<T> sqr(const complex<T>& a)
                 {
                    return complex<T>(real(a) * real(a) - imag(a) * imag(a),
                         2 * real(a) * imag(a));
                 }

                 template <class T>
                 inline T arg1(const complex<T>& a)

                 {
                     double val = arg(a);

                     if(val > -M_PI && val <= M_PI)
                         return val;

                     if(val > M_PI)
                         return val - (2*M_PI);

                     // val <= -PI
                     return val + (2*M_PI);
                 }

              o  The pow(complex, int) function is no longer provided.
                 You must use pow(complex<double>, double). This means
                 changing calls such as:

                 pow(c,1);

                 to:

                 pow(c,1.0);

                 This might yield different results. If the function
                 previously was underflowing or overflowing, it might
                 not continue to happen.

              o  The complex output operator (<<) does not insert a
                 space between the comma and the imaginary part. If you
                 want the space, you would need to print the real and
                 imaginary parts separately, adding your own comma and
                 space; that is:

                 complex<double> c;
                 cout << "(" << c.real() << ", " << c.imag() << ")"; // add extra space

                                           The C++ Standard Library 7-19

 



     The C++ Standard Library
     7.5 Upgrading from the Class Library to the Standard Library Provided with Version 6.n

           o  The complex input operator (>>) does not raise an
              Objection if bad input is detected; it instead sets
              input stream's state to ios::failbit.

           o  Floating point overflow, underflow, and divide by zero
              do not set errno and will cause undefined behavior.
              Complex error checking and error notification are
              planned in a subsequent release.

           o  You should no longer need to explicitly link your
              program with the complex library. It is automatically
              linked in as part of the Standard Library. However, you
              must still explicitly link in the C math library, as
              shown in the following example:

              #include <stdlib.h>
              #include <complex>

              int main() {
                      complex<double> c1(1,1), c2(3.14,3.14);
                      cout << "c2/c1: " << c2/c1 << endl;
                      return EXIT_SUCCESS;
              }

     7.5.5 Upgrading from the Pre-ANSI IOStream Library to the
           Standard Library

           This section explains how to upgrade from the pre-ANSI
           IOStream library to the ANSI IOStream library. In this
           section, pre-ANSI IOStream refers to versions of the
           IOStream library found in the Class Library; ANSI IOStream
           refers to versions found in the Standard Library.

           There are a number of differences between the pre-ANSI
           and ANSI IOstream library. One major difference between
           the pre-ANSI and ANSI IOstream library is that the ANSI
           library is templatized on the object input/output on which
           operations are being performed. In the pre-ANSI library,
           IOStreams has no templates. The ANSI library also provides
           specializations for char and wchar_t.

           Important differences are as follows:

           o  With the current compiler, you access the pre-ANSI
              IOstream library by default in non strict_ansi compiler
              modes. You can control the version of IOStreams you use
              with the __USE_STD_IOSTREAM and __NO_USE_STD_IOSTREAM

     7-20 The C++ Standard Library

 



                                                The C++ Standard Library
 the     Class Library to the Standard Library Provided with Version 6.n

                 macros. If you want to use the ANSI IOstream library,
                 do either of the following:

                    -D__USE_STD_IOSTREAM on the command line.
                    #define __USE_STD_IOSTREAM in your source file
                    before any include files.

              o  Header names are different in the ANSI library, so to
                 use ANSI IOStreams, change the IOStreams headers you
                 include as follows:

                 _______________________________________________________
                 From_____________________To____________________________

                 #include <iostream.h>    #include <iostream>
                 #include <iostream.hxx>

                 #include <fstream.h>     #include <fstream>
                 #include <fstream.hxx>

                 #include <strstream.h>   #include <strstream>
                 #include <strstream.hxx>

                 #include <iomanip.h>     #include <iomanip>
                 #include_<iomanip.hxx>_________________________________

              o  All Standard Library names in the ANSI IOStreams
                 library are in namespace std. Typically you would
                 qualify each Standard Library name with std:: or put
                 using namespace std; at the top of your source file.

                 To facilitate upgrading in all but strict_ansi and
                 strict_ansi_errors mode, using namespace std; is set by
                 default. In strict_ansi or strict_ansi_errors modes,
                 after including an ANSI IOStream header, you must
                 qualify each name inside namespace std individually
                 or do

                       using namespace std;

              o  In the pre-ANSI IOstream library, including <iomanip.h>
                 or <strstream.h> gave you access to cout, cin, and
                 cerr. To access the predefined streams with the ANSI
                 IOStreams library, make the following changes:

                                           The C++ Standard Library 7-21

 



     The C++ Standard Library
     7.5 Upgrading from the Class Library to the Standard Library Provided with Version 6.n


              change                        change
              #include <iomanip.h>          #include <strstream.h>
              to                            to
              #include <iomanip>            #include <strstream>
              #include <iostream>           #include <iostream>
              #include using namespace      #include using namespace
              std;                          std;

           o  The istream::ipfx, istream::isfx, ostream::opfx,
              ostream::osfx do not exist in the ANSI IOStreams. Their
              functionality is provided by the sentry class found in
              basic_istream and basic_ostream, respectively.

              Common prefix code is provided by the sentry's
              constructor. Common suffix code is provided by the
              sentry's destructor. As a result, calls to ipfx(),
              isfx(), opfx(),  and osfx() have their function-
              ality replaced by construction and destruction of
              std::istream::sentry objects and std::ostream::sentry
              object respectively. For example:

              #include <iostream.hxx>           |  #include <iostream.hxx>
              void func (istream &is)           |  void func (ostream &os)
              {                                 |  {
                 if (is.ipfx())                 |     if (os.opfx())
                     ...                        |         ...
                 is.isfx();                     |     os.osfx();
              }                                 |  }
                                                |
              Would be coded as:                |  Would be coded as:
                                                |
              #include <iostream>               |  #include <iostream>
              void func (istream &is)           |  void func (ostream &os)
              {                                 |  {
                 istream::sentry ipfx(is);      |     ostream::sentry opfx(os);
                 if (ipfx)                      |     if (opfx)
                    ...                         |        ...
                 //is.isfx(); implicit in dtor  |     //os.osfx(); implicit in dtor
              }                                 |   }





     7-22 The C++ Standard Library

 



                                                The C++ Standard Library
 the     Class Library to the Standard Library Provided with Version 6.n

              o  The following macros from the pre-ANSI <iomanip.h> are
                 no longer available in <iomanip>:

                 SMANIP, IMANIP, OMANIP, IOMANIP,
                 SAPP,   IAPP,   OAPP,   IOAPP,
                 SMANIPREF, IMANIPREF, OMANIPREF, IOMANIPREF,
                 SAPPREF, IAPPREF, OAPPREF, IOAPPREF

                 You can add them yourself, but their use will not be
                 portable.

              o  The streambuf::stossc() function, which advances
                 the get pointer forward by one character in a stream
                 buffer, is not available in the ANSI IOstream library.
                 You can make use of the std::streambuf::sbumpc()
                 function to move the get pointer forward one place.
                 This function returns the character it moved past.
                 These two functions are not exactly equivalent-if the
                 get pointer is already beyond the end, stossc() does
                 nothing, and sbumpc() returns EOF.

                      istream &extract(istream &is)
                      {
                         ...
                         is.rdbuf()->stossc();
                      }

              o  ios::bitalloc() is no longer available in the ANSI
                 IOstream library.

              o  The filebuf constructors have changed in the ANSI
                 IOstream library. The pre-ANSI filebuf class contained
                 three constructors:

                     class filebuf : public streambuf
                     {
                        filebuf();
                        filebuf(int fd);
                        filebuf(int fd, char * p, int len);
                        ...
                     }

                 In the ANSI IOstream library, filebuf is a typedef for
                 basic_filebuf<char>, and the C++ Working Paper defines
                 one filebuf constructor:

                     basic_filebuf();

                                           The C++ Standard Library 7-23

 



     The C++ Standard Library
     7.5 Upgrading from the Class Library to the Standard Library Provided with Version 6.n

              To facilitate backward compatibility, the ANSI IOStream
              library does provide basic_filebuf(int fd) as an
              extension. However, the use of extensions is not
              portable.

              For example, consider the filebuf constructors in the
              following pre-ANSI IOStream library program:

              #include <fstream.hxx>

              int main () {
                  int fd = 1;
                  const int BUFLEN = 1024;
                  char buf [BUFLEN];
                  filebuf fb(fd,buf,BUFLEN);
                  filebuf fb1(fd);
                  return 0;
              }

              To be strictly ANSI conforming, you would need to
              recode as follows:

                filebuf fb(fd,buf,BUFLEN); as filebuf fb();  and
                filebuf fb1(fd); as filebuf fb1();

              If you want to make use of the ANSI IOStream file-
              buf(fd) extension, you could recode:

                filebuf fb(fd,buf,BUFLEN); as filebuf fb(fd);  and
                filebuf fb1(fd); as filebuf fb1(fd);

           o  The ANSI IOstream library contains support for the
              filebuf::fd() function, which returns the file
              descriptor for the filebuf object and EOF if the
              filebuf object is closed as a nonportable extension.

              This function is not supported under the -std strict_
              ansi or -std strict_ansi_errors compiler modes.

           o  The following functions are not defined in the ANSI
              IOStreams library. They are provided in the ANSI
              IOstream library for backward compatibility only. Their
              use is not portable.


     7-24 The C++ Standard Library

 



                                                The C++ Standard Library
 the     Class Library to the Standard Library Provided with Version 6.n

                     ifstream::ifstream(int fd);
                     ifstream::ifstream(int fd, char *p, int len)
                     ofstream::ofstream(int fd);
                     ofstream::ofstream(int fd, char *p, int len);
                     fstream::fstream(int fd);
                     fstream::fstream(int fd, char *p, int len);

              o  The following attach functions, which attach,
                 respectively, a filebuf, fstream, ofstream, and
                 ifstream to a file are not available in the ANSI
                 IOstream library:

                    filebuf::attach(int);
                    fstream::attach(int);
                    ifstream::attach(int);
                    ofstream::attach(int);

                 If you do not want to make use of ANSI IOstream library
                 extensions, you must recode the use of attach as
                 follows:

                 From:

                 #include <fstream.hxx>
                 #include <stdio.h>
                 #include <fcntl.h>
                 int main () {
                     int fd;
                     fd = open("t27.in",O_RDWR | O_CREAT, 0644);
                     ifstream ifs;
                     ifs.attach(fd);
                     fd = creat("t28.out",0644);
                     ofstream of;
                     of.attach(fd);
                     return 0;
                 }

                 To:

                 #include <fstream>
                 int main () {
                     ifstream ifs("t27.in", ios::in | ios::out);
                     ofstream ofs("t28.out");
                     return 0;
                 }

                                           The C++ Standard Library 7-25

 



     The C++ Standard Library
     7.5 Upgrading from the Class Library to the Standard Library Provided with Version 6.n

           o  The ios enumerators for controlling the opening of
              files, ios::nocreate and ios::noreplace, are not
              available in the ANSI IOstream library.

           o  The istream_withassign and ostream_withassign classes
              are not available in the ANSI IOstream library.

           o  In the ANSI IOstream library ios_base::width() applies
              to all formatted inserters including operator <<
              (char). This means that the stream width specified by
              either the manipulator setw() or the ios_base::width()
              member function will apply padding to the next output
              item even if it is a char.

              This was not the case in the pre-ANSI IOStreams
              library, where width() applied to all formatted
              inserters except the char inserter. The reasons for
              the change (to allow ostream::operator<<(char) to do
              formatting) are:

              1. It allows operator<< functions to do formatting
                 consistently.

              2. It allows operator<<(char) and put(char) (formatted
                 and unformatted operations on char) to have
                 different functionality.

              Consider the following example:

              #ifdef __USE_STD_IOSTREAM
              #   include <iostream>
              #   include <iomanip>
              #else
              #   include <iostream.hxx>
              #   include <iomanip.hxx>
              #endif
              int main () {
                  cout.width(10);
                  cout.fill('^');
                  cout << 'x' << '\n';
                  cout << '[' << setw(10) << 'x' << ']' << endl;
                  return 0;
              }


     7-26 The C++ Standard Library

 



                                                The C++ Standard Library
 the     Class Library to the Standard Library Provided with Version 6.n

                 In the ANSI IOstream library the output is:

                 ^^^^^^^^^x
                 [^^^^^^^^^x]

                 In the pre-ANSI IOstream library the output is:

                 x
                 [x]^^^^^^^^^

              o  In the pre-ANSI IOstream library, printing signed
                 char * or a unsigned char * printed the address of
                 the string. In the ANSI IOstream library the string is
                 printed. Consider the following example:

                 #ifdef __USE_STD_IOSTREAM
                 #include <iostream>
                 #else
                 #include <iostream.hxx>
                 #endif

                 int main () {
                     char * cs = (char *) "Hello";
                     signed char *ss = (signed char *) "world";
                     unsigned char *us = (unsigned char *) "again";

                     cout << cs << " " << ss << " " << us << endl;
                     return 0;
                 }

                 The output in the ANSI IOstream library is:

                 Hello world again

                 The output in the pre-ANSI IOstream library is:

                 Hello 0x120001748 0x120001740

                 To obtain output equivalent to the pre-ANSI IOStreams,
                 you might do the following:

                 cout << hex << showbase << (long) ss << " " << (long) us << endl;

              o  In the pre-ANSI IOstream library printing a signed char
                 prints its integer value. In the ANSI IOstream library
                 printing a signed char prints it as a character.
                 Consider the following example:

                                           The C++ Standard Library 7-27

 



     The C++ Standard Library
     7.5 Upgrading from the Class Library to the Standard Library Provided with Version 6.n

              #ifdef __USE_STD_IOSTREAM
              #include <iostream>
              #else
              #include <iostream.hxx>
              #endif

              int main () {
                  signed char c = (signed char) 'c';
                  cout << c << endl;
                  return 0;
              }

              The output in the ANSI IOstream library is:

              c

              The output in the pre-ANSI IOstream library is:

              99

              To obtain output equivalent to the pre-ANSI IOStreams,
              you must do the following:

              cout << (long) c << endl;

           o  In the ANSI IOstream library, reading invalid floating
              point input (where invalid input is caused by no digits
              following the letter e or E and an optional sign) from
              a stream sets failbit to flag this error state. In
              the pre-ANSI IOstream library, these type of error
              conditions might not be detected. Consider this program
              fragment:

                  double i;
                  cin >> i;
                  cout << cin.rdstate() << ' ' << i << endl;

              On the input: 123123e

              The output in the ANSI IOstream library is:

              4 2.65261e-314          // failbit set

              The output in the pre-ANSI IOstream library is:

              0 123123                // goodbit set

     7-28 The C++ Standard Library

 



                                                The C++ Standard Library
 the     Class Library to the Standard Library Provided with Version 6.n

              o  In the ANSI IOstream library, reading integer input
                 (which is truncated as the result of a conversion
                 operation) from a stream sets failbit to flag this
                 overflow condition. In the pre-ANSI IOStream library,
                 these types of conditions might not be detected.
                 Consider this program fragment:

                     int i;
                     cin >> i;
                     cout << cin.rdstate() << ' ' << i << endl;

                 On the input: 9999999999999999

                 The output in the ANSI IOstream library is:

                 4  1874919423       // failbit set

                 The output in the pre-ANSI IOstream library is:

                 0  1874919423       // goodbit set

                 In the ANSI IOstream library, reading -0 from a stream
                 into an unsigned int outputs 0; this was not the
                 case with the pre-ANSI IOstream library. Consider the
                 following:

                    unsigned int ui;
                    cin >> ui;
                    cout << cin.rdstate() << ' ' << ui << endl;

                 On the input: -0

                 The output in the ANSI IOstream library is:

                 0 0

              o  In the ANSI IOstream library, the istream::getline()
                 function extracts characters and stores them into
                 successive locations of an array whose first element is
                 designated by s. If n-1 characters are stored, failbit
                 is set. This was not the case in the pre-ANSI IOstream
                 library. Consider the following:



                                           The C++ Standard Library 7-29

 



     The C++ Standard Library
     7.5 Upgrading from the Class Library to the Standard Library Provided with Version 6.n

              #include <stdlib.h>
              int main()
              {
                      char buffer[10];
                      cin.getline (buffer,10);
                      cout << cin.rdstate() << ' ' << buffer << endl;
                      return EXIT_SUCCESS;
              }

              With input of: 1234567890

              The output in the ANSI IOstream library is:

              4 123456789

              The output in the pre-ANSI IOstream library is:

              0 123456789

           o  When printing addresses, the ANSI library does not
              print a leading "0x" to indicate a hexadecimal base.
              The pre-ANSI library did. Consider the following:

              #include <stdlib.h>
              #include <iostream>
              int main()
              {
              double d;
              int i;
                      void *p = (void *) &d;
                      int *pi = &i;
                      cout << (void *) 0 << ' ' << p << ' ' pi << endl;
                      return EXIT_SUCCESS;
              }

              The output in the ANSI IOstream library is:

              0 11fffe7a0 11fffe798

              The output in the pre-ANSI IOstream library is:

              0x0 0x11fffdc40 0x11fffdc38

           o  basic_filebuf::setbuf is a protected member function in
              the ANSI IOstream library. Therefore, the following no
              longer compiles:

     7-30 The C++ Standard Library

 



                                                The C++ Standard Library
 the     Class Library to the Standard Library Provided with Version 6.n

                 #include <stdlib.h>
                 int main() {
                    filebuf fb;
                    ...
                    fb.setbuf(0,0);
                    return EXIT_SUCCESS;
                 }

        7.5.6 Upgrading Pre-ANSI bit_vector to ANSI vector<bool>

              The bit_vector class provided in the library previous to
              the current compiler is no longer available. The current
              compiler provides this functionality with the ANSI C++
              vector<bool> class. For example, consider a program making
              use of bit_vector as follows:

              #include <vector>
              #include <iostream.h>
              int main () {
                bit_vector bv(3);
                bv[0] = bv[2] = 1; bv[1] = 0;
                bit_vector::iterator bi=bv.begin();
                (*bi).flip();
                cout << bv[0] << bv[1] << bv[2] << endl;
                return 0;
              }

              This would be coded as follows using the pre-ANSI
              <iostream.h> header:

              #include <vector>
              #include <iostream.h>
              using namespace std;
              int main () {
                vector<bool> bv(3);
                bv[0] = bv[2] = true; bv[1] = false;
                vector<bool>::iterator bi=bv.begin();
                (*bi).flip();
                cout << (bool)bv[0] << endl; //cast vector<bool> subscript operator
                return 0;
              }




                                           The C++ Standard Library 7-31

 



     The C++ Standard Library
     7.5 Upgrading from the Class Library to the Standard Library Provided with Version 6.n

           Or it would be coded as follows using the ANSI <iostream>
           header:

           #define __USE_STD_IOSTREAM
           #include <vector>
           #include <iostream>
           using namespace std;
           int main () {
             vector<bool> bv(3);
             bv[0] = bv[2] = true; bv[1] = false;
             vector<bool>::iterator bi=bv.begin();
             (*bi).flip();
             cout << bv[0] << bv[1] << bv[2] << endl;
             return 0;
           }






























     7-32 The C++ Standard Library

 









                                                                       8
        ________________________________________________________________

                                                     Handling Exceptions



              C++ incorporates an exception mechanism for handling
              unusual program events (not necessarily just errors).
              Exception handling enables you to detect program events
              and to provide handlers to deal with the events.

              Compaq C++ implements the exception handling model
              described in the International C++ Standard.

              This chapter provides a brief introduction to exception
              handling, describes the run-time considerations of
              exception handling in Compaq C++, and recommends ways
              to use exception handlers for optimum performance. For
              a detailed description of C++ exception handling in
              general, see Chapter 14 in The C++ Programming Language,
              3rd Edition.

              Readers of this chapter should be familiar with the C++
              exception-handling terminology, such as throwing and
              catching exceptions.

              For information on debugging programs with exception
              handlers, see the Compaq Tru64 UNIX Ladebug Debugger
              Manual, which is included with the operating system
              documentation.

        8.1 Structure

              The following example shows the basic structure for
              declaring and using exception handlers in C++:






                                                 Handling Exceptions 8-1

 



     Handling Exceptions
     8.1 Structure

               .
               .
               .
           void might_break(int i)
           {
               if (i == 1) throw "something!";
               if (i == 4) throw 4;
               //  . . .
           }

           void p (int i)
           {                                //
               try                          //        begin try block
               {                            //
                   might_break(i);          //
               }                            //
               catch (const char *p)        //        begin handler
               {                            //         .
                   cout << "caught " << p;  //         .
                   // fix whatever...       //         .
               }                            //        end try block
           }                                //        end handler
               .
               .
               .

           In this example, calling p with a value of anything other
           than 1 or 4 causes the program to execute normally, with
           no exception thrown. If p is called with a value of 1,
           the might_break function throws a string object to the p
           handler, which prints caught something!.

           If p is called with 4, an int is thrown. Because p
           cannot catch values of type int, the search for a handler
           proceeds up the call stack until an appropriate handler
           can be found. If nothing on the stack can handle an int,
           program execution terminates immediately after calling the
           std::terminate function.

           C++ exception handling represents a termination model,
           which means that program execution never proceeds past
           a throw. For additional information, see the ANSI C++
           Working Paper.


     8-2 Handling Exceptions

 



                                                     Handling Exceptions
                                             8.2 Run-Time Considerations

        8.2 Run-Time Considerations

              Compaq C++ optimizes the implementation of exception
              handling for normal execution, as follows:

              o  As much as possible, the overhead for exceptions is
                 incurred when throwing an exception.

              o  Applications that have try blocks and that run without
                 causing exceptions incur only slight overhead as
                 follows:

                 -  The size of an executable image increases 3 x 128
                    bits for a simple try-catch block because of tables
                    that describe the handlers.

                 -  When entering or exiting a handler, the frame
                    number is saved to be used for finding any exception
                    raised.

              Some functions without explicit handlers may have
              implicit handlers. The compiler creates a handler for
              each automatic object that has a destructor. The compiler
              also creates handlers for constructors that initialize
              subobjects that have destructors. In such a constructor,
              the compiler creates a handler for each member with a
              destructor, and a handler for each base class with a
              destructor.

              The -nocleanup option suppresses generation of such
              implicit handlers, which results in a slightly smaller
              executable file. Use the -nocleanup option for programs
              that do not use exception handling or do not require
              destruction of automatic objects during exception
              processing.

        8.3 Coding Recommendations

              Some recommendations for optimal results when using
              exception handling in Compaq C++ are:

              o  Use destructors where necessary, but avoid creating
                 them where they are not useful.

                 The existence of a destructor can cause the compiler
                 to create an implicit exception handler - as in
                 the example of an implicit exception handler for an
                 automatic object with a destructor.

                                                 Handling Exceptions 8-3

 



     Handling Exceptions
     8.3 Coding Recommendations

           o  Use fewer and larger try blocks, instead of many small
              try blocks, wherever possible.

              Whereas a single try block with several handlers may
              improve performance compared to several small try
              blocks with one handler each, the improvement may not
              always be enough to justify making awkward changes to
              your program logic.

     8.4 Mixed-Language Applications

           When C functions are intermixed with C++ functions, the
           compiler treats them as C++ functions without exception
           handlers. The C functions can have their own exception
           handlers. Each function within a program can point to its
           own language-specific handler.

     8.5 Finding Information about Exceptions

           To obtain more information about an exception that was
           thrown, you can call the function __cxx_exception_info
           from a catch(...) clause.

           The function returns the system_exrec_type defined in
           excpt.h, which points to the facility that raised the
           exception and to other information.

           The prototype is found in cxx_exception.h and is:

           system_exrec_type *__cxx_exception_info();

           For more information about the system_exrec_type, see the
           excpt reference page.

     8.6 Using the dlclose Routine

           The dlclose routine cannot be used to delete a shared
           object (.so) until after any handlers handling an
           exception, thrown from the shared object, have exited.
           This restriction is necessary because, when exiting from a
           handler, the C++ exception support needs to reference data
           structures that were defined at the throw point.



     8-4 Handling Exceptions

 



                                                     Handling Exceptions
                                   8.7 Catching Signals and C Exceptions

        8.7 Catching Signals and C Exceptions

              Compaq Tru64 UNIX and Linux Alpha report divides by zero
              and other "bad behavior" by libc as signals. To manage
              signals, you can install a signal handler.

              If you want C exceptions, you can install exc_raise_
              signal_exception as the handler for particular signals.
              When a signal occurs, a C exception is thrown.

              Although C++ catch clauses (catch(...)) recognize C
              exceptions, the exceptions are not coverted to exception
              as defined in <exception>.

              Consider the following example:

              #include <stdlib.h>
              #include <excpt.h> //new
              #include <signal.h> //new
              struct sigaction foo =   //new
               {(void (*)(int))exc_raise_signal_exception,0,0}; // new

              #include <iostream.h>
              #include <exception>

              int main()
              {
                double x, y, z;

                sigaction(SIGFPE,&foo,0); //new

                cerr << "testing divide by 0" << endl;
                try {
                  x = 0.0;
                  y = 1.0;
                  z = y / x;
                  cerr << "z is " << z << endl;
                }
                catch (exception e) {
                  cerr << "caught exception " << e.what() << endl;
                }
                catch(...) {
                  cerr << "caught ... exception" << endl;
                }
                return EXIT_SUCCESS;
              }

                                                 Handling Exceptions 8-5

 



     Handling Exceptions
     8.7 Catching Signals and C Exceptions

           The resulting output is as follows:

           tagged 1062% a.out
           testing divide by 0
           caught ... exception

     8.8 C++ Exceptions and Threads [Tru64]

           C++ exceptions are thread safe. This means that multiple
           threads within a process can throw and catch exceptions
           concurrently. However, exceptions do not propagate
           from one thread to another, nor can one thread catch an
           exception thrown by another thread.

           Because C++ exceptions are implemented using the exception
           handling facilities described in the Compaq Tru64 UNIX
           Calling Standard for Alpha System, C++ modules do work
           properly when they are part of a program that makes other
           uses of the same exception handling facilities.

           The raising and handling of DECthreads exceptions can
           result in the destruction of C++ automatic objects. If the
           handling of a DECthreads exception results in an unwind
           through a C++ function's stack frame, then destructors
           are called for automatic objects declared in that stack
           frame, just as though a C++ exception had been caught by a
           handler in an outer stack frame.

           The C++ exception handling facility can also be used to
           catch DECthreads exceptions that are raised independently
           of C++ throw expressions. A C++ catch( .. . ) handler
           catches both C++ thrown exceptions and DECthreads
           exceptions.

           However, C++ exception mechanisms (try, catch, throw)
           cannot be used within the same function as DECthreads
           exception mechanisms (TRY, CATCH, RAISE, and so forth).
           Because both exception mechanisms attempt to establish
           their own specific handlers, the results will be
           undefined.

           The set_terminate() and set_unexpected()  functions set
           the terminate() and unexpected()  handlers for the calling
           thread. Therefore, each thread in a program has its own
           terminate() and unexpected()  handlers.

     8-6 Handling Exceptions

 



                                                     Handling Exceptions
                                  8.8 C++ Exceptions and Threads [Tru64]

              If you want every thread in your program to use the same
              nondefault terminate() or unexpected() handlers, you must
              call the set_terminate() and set_unexpected() functions
              separately from each thread.

              For more information about threads and DECthreads
              exceptions, see the Guide to DECthreads manual.

              Note that The advantage of using C++ exceptions is that
              entering the try block is much faster than entering a
              pthread try block.

              The advantage of using pthread exceptions is that you
              can call pthread_exc_report_np(THIS_CATCH) to give more
              information about the exception caught, as shown in the
              following example.

              #include <pthread.h>
              #include <pthread_exception.h>
              #include <stdio.h>

              struct C {
               int i;
               static int count;
               C() : i(count++) { printf("ctor %d\n", i); }
               ~C() { printf("dtor %d\n", i); }
              };

              int C::count =0;

              int foo(int i, int j, int *p) {
                  int k = j / i;
                  *p = 25; /* illegal mem access */
                  return k;
              }

              // C++ version.
              void * theThread_cxx(void * arg)
              {
                int i = 0, j = 10, k, *p;

                printf("Enter thread\n");
                sleep(2);

                try {
                  k = foo(i,j,p);

                                                 Handling Exceptions 8-7

 



     Handling Exceptions
     8.8 C++ Exceptions and Threads [Tru64]

             } catch (...) {
                 printf("Caught some exception...\n");
                 // pthread_exc_report_np(THIS_CATCH);
             }

             printf("exit thread\n");
             return(0);
           }

           // Threads version.
           void * theThread(void * arg)
           {
             C d;
             int i = 0, j = 10, k, *p;

             printf("Enter thread\n");
             sleep(2);

             TRY
               k = foo(i,j,p);

              CATCH_ALL
                 printf("Caught some exception...\n");
                 pthread_exc_report_np(THIS_CATCH);
                 throw 5;
              ENDTRY

               printf("exit thread\n");
             return(0);
           }

           void * theThread_wrapper(void * arg)
           {
             try {
               theThread(arg);
             } catch (int) {
               printf("caught an int\n");
             }
             return 0;
           }

           int main()
           {
             pthread_t thread;
             pthread_attr_t attr;
             int status = 0;
             register int i;

     8-8 Handling Exceptions

 



                                                     Handling Exceptions
                                  8.8 C++ Exceptions and Threads [Tru64]

                printf("begin main\n");
                pthread_attr_init(&attr);

                // Make 3 copies of the pthread exception handling thread.
                for(i=0; i<3; i++) {
                    status = pthread_create(&thread, &attr, theThread_wrapper, 0);
                    if(status)
                      {
                        printf("***ERROR***, pthread_create failed\n");
                      }
                    pthread_join(thread, 0);
                  }

                // Make the C++ exception handling thread.
                status = pthread_create(&thread, &attr, theThread_cxx, 0);
                if(status)
                      {
                        printf("***ERROR***, pthread_create failed\n");
                      }
                pthread_join(thread, 0);
                printf("end main\n");

                return(0);
              }





















                                                 Handling Exceptions 8-9

 









                                                                       9
        ________________________________________________________________

                                              Using the Ladebug Debugger



              A debugger helps you find run-time errors by letting you
              observe and interactively manipulate execution step by
              step, until you discover where the program functions
              incorrectly.

              The language of the source program you are currently
              debugging determines the format you use to enter and
              display data. It also determines the format used for
              features, such as comment characters, operators, and
              operator precedence, which have language-specific
              settings. If you have modules written in another language,
              you can switch from one language to another during your
              debugging session.

              This chapter discusses debugging programs using the
              command line interface to the Ladebug Debugger. A
              graphical user interface is also available through DEC
              FUSE, which supports all of the Ladebug commands mentioned
              in this chapter.

              DEC FUSE is the integrated software development environ-
              ment for Compaq Tru64 UNIX systems. Besides the Ladebug
              commands described in this chapter, DEC FUSE provides
              the programmer with a class browser, call graph browser,
              and cross-referencing capability to assist in debugging
              Compaq C++ programs. For more information, see the DEC
              FUSE Debugger Manual.








                                          Using the Ladebug Debugger 9-1

 



     Using the Ladebug Debugger
     9.1 Debugging C++ Programs

     9.1 Debugging C++ Programs

           The Ladebug debugger is a source-level debugger that
           debugs C++ programs compiled with the Compaq C++ compiler.
           For general information on how to use the Ladebug
           debugger, see the Compaq Tru64 UNIX Ladebug Debugger
           Manual and the Ladebug(1) reference page.

           When debugging C++ code, the debugger supports the
           following features:

           o  C++ names and expressions, including:

              -  Using an explicit and implicit this pointer to refer
                 to class members

              -  The scope resolution operator (::)

              -  The member access operators, period (.) and right
                 arrow (->)

              -  Reference types

              -  Template instantiations

              -  C++ exception handling

           o  Setting breakpoints in:

              -  Member functions, including static and virtual
                 functions

              -  A member function in a particular object

              -  Overloaded functions

              -  Constructors and destructors

              -  Template instantiations

              -  Exception handlers

           o  Changing the current class scope to set breakpoints
              and examine static members of a class that are not
              currently in scope

           o  Calling overloaded functions

           o  Debugging programs containing a mixture of C and C++
              code

     9-2 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                                              9.1 Debugging C++ Programs

              The debugger interprets C++ names and expressions using
              the language rules described in the International C++
              Standard. C++ is a distinct language, rather than a
              superset of C. Where the semantics of C and C++ differ,
              the debugger provides the interpretation appropriate for
              the language of the program being debugged.

              To make the debugger more useful, the debugger relaxes
              some standard C++ name visibility rules. For example, you
              can reference both public and private class members.

        9.2 Using Absolute and Relative Path Names

              If your program supplies an absolute filename like
              two/two.cxx, the object file contains that name. For
              example:

              $ gemc_cxx -ptr ~/cxx_repository -I templates two/two.cxx
              $ a.out
              in is_zero(long) templates/template.hxx
              in is_zero(double) templates/template.hxx

              If you supply the full path name, the object file contains
              the full name:

              $ gemc_cxx -ptr ~/cxx_repository -I ~/templates two/two.cxx
              $ a.out
              in is_zero(long) /usr/users/smith/templates/template.hxx
              in is_zero(double) /usr/users/smith/templates/template.hxx

              There are advantages and disadvantages to using relative
              path names versus complete path names. With relative
              pathnames, you can move the development tree and continue
              to debug. With absolute path names, you can move your
              executable and continue to debug, and using multiple
              repositories is easier.

              Although moving development trees might not be common,
              mounting them on some other system is, and there is no
              reason why the mount points on the two systems need have
              the same name-for example, in a cluster.

              On sys1, /usr/users/smith points to /usr/var/ase/mnt/ab-nfs/ab-users/users4/smith.
              On sys2, /usr/users/smith points to /tmp_mnt/var/users/smith.

                                          Using the Ladebug Debugger 9-3

 



     Using the Ladebug Debugger
     9.2 Using Absolute and Relative Path Names

           Consider what would happen if the compiler tried to save
           the complete path name of a file instead of the name
           as supplied. It would use something like getcwd() to
           complete the name. On sys1, the compiler would save the
           name

           /usr/var/ase/mnt/abcd-nfs/abcd_users/users45/smith/templates/template.hxx

           You would be unable to debug the program on sys2, which
           does not have access to

           /usr/var/ase/mnt/abcd-nfs/abcd_users/users45/smith/templates/template.hxx

           By saving the name the user supplies, the compiler gives
           the user control over how they access the files. If you
           want full path names, supply them on the command line. If
           you want relative path names, supply those instead.

     9.3 Debugging Programs Containing C and C++ Code

           The debugger lets you debug mixed-language programs.
           Program flow of control across functions written in
           different languages is transparent.

           The debugger automatically identifies the language of
           the current function or code segment based on information
           embedded in the executable file. If program execution is
           suspended in a C function, the current language is C. If
           the program executes a C++ function, the current language
           becomes C++.

           The current language determines the valid expression
           syntax for the debugger. When the current language is
           C, printing an expression such as S::foo causes an error,
           because scope resolution operators and class types are
           not valid in C expressions. The current language of the
           debugger also affects the semantics used to evaluate an
           expression. For example, in C, all character constants
           are of type int. In C++, single character constants are
           of type char. In C, sizeof('a') = sizeof(int). In C++,
           sizeof('a') = 1.

           The debugger sets the variable $lang to the language of
           the current function or code segment. By manually setting
           the debugger variable $lang, you can force the debugger to
           interpret expressions used in commands by the rules and

     9-4 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                        9.3 Debugging Programs Containing C and C++ Code

              semantics of a particular language. Example 9-1 shows how
              to switch between C++ and C modes while debugging.


              Example 9-1 Switching Between C++ and C Debugging Modes

              (Ladebug) print $lang
              "C++"
              (Ladebug) print sizeof('a')
              1
              (Ladebug) set $lang = "C"
              (Ladebug) print sizeof('a')
              4
              (Ladebug) print sizeof(int)
              4
              (Ladebug)

              When the debugger reaches the end of your program, the
              $lang variable is set to the language of the final
              function of your program, rather than the language of
              the _exit routine. The _exit routine is written in machine
              code and is the last function executed by every C or C++
              program.

        9.4 Setting the Class Scope

              The debugger maintains the concept of a current context
              in which to perform lookup of program variable names.
              The current context includes a file scope and either a
              function scope or a class scope. The debugger automati-
              cally updates the current context when program execution
              suspends.

              The class command lets you set the scope to a class in
              the program you are debugging. The syntax for the class
              command is as follows:

              class  class_name

              Explicitly setting the debugger's current context to a
              class allows visibility into a class to set a breakpoint
              in a member function, to print static data members, or
              to examine any data member's type. After the class scope
              is set, you can set breakpoints in the class's member

                                          Using the Ladebug Debugger 9-5

 



     Using the Ladebug Debugger
     9.4 Setting the Class Scope

           functions and examine data without explicitly mentioning
           the class name. If you do not want to affect the current
           context, you can use the scope resolution operator (::) to
           access a class whose members are not currently visible.

           There can be only one current context. If you set a class
           scope, you invalidate the current function scope. The
           opposite is also true: if you set a function scope, you
           invalidate the current class scope.

           To display the current class scope (if one exists), enter
           the class command with no argument.

           Example 9-2 shows the use of the class command to set the
           class scope to S to make member function foo visible so a
           breakpoint can be set in foo.

           Example 9-2 Setting the Class Scope

           (Ladebug) stop in main; run
           [#1: stop in main ]
           [1] stopped at [int main(void):26 0x120000744]
                26      int result = s.bar();
           (Ladebug) stop in foo
           Symbol foo not visible in current scope.
           foo has no valid breakpoint address
           Warning: Breakpoint not set
           (Ladebug)  class S
           class S  {
             int i;
             int j;
             S (void);
             ~S (void);
             int foo (void);
             virtual int bar (void);
           }

           (Ladebug) stop in foo
           [#2: stop in foo (void) ]
           (Ladebug)





     9-6 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                                        9.5 Displaying Class Information

        9.5 Displaying Class Information

              The whatis and print commands display information
              about a class. Use the whatis command to display static
              information about the classes. Use the print command to
              view dynamic information about class objects.

              The whatis command displays the class type declara-
              tion, including the data members, member functions,
              constructors, destructors, static data members, and
              static member functions. For classes that are derived
              from other classes, the data members and member functions
              inherited from the base class are not displayed. However,
              any member functions that are redefined from the base
              class are displayed.

              The whatis command used on a class name displays all class
              information, including constructors. To use this command
              on a constructor only, use the following syntax:

              whatis  class_name::class_name

              Constructors and destructors of nested classes must be
              accessed using one of the following syntaxes:

              class  class_name::(type signature)

              class  class_name~::(type signature)

              The print command lets you display the value of data
              members and static members.

              Information regarding the public, private, or protected
              status of class members is not provided because the
              debugger relaxes these rules to be more helpful to you.

              The type signatures of member functions, constructors, and
              destructors are displayed in a form that is appropriate
              for later use in resolving references to overloaded
              functions.

              Example 9-3 shows the whatis and print commands in
              conjunction with a class.

              Example 9-3 Displaying Class Information

                                                (continued on next page)

                                          Using the Ladebug Debugger 9-7

 



     Using the Ladebug Debugger
     9.5 Displaying Class Information

           Example 9-3 (Cont.) Displaying Class Information

           (Ladebug) list 1, 9
                 1 class S {
                 2 public:
                 3      int i;
                 4      int j;
                 5      S() { i = 1; j = 2; }
                 6      ~S() { }
                 7      int foo ();
                 8      virtual int bar();
                 9 };
           (Ladebug) whatis S
           class S  {
             int i;
             int j;
             S (void);
             ~S (void);
             int foo (void);
             virtual int bar (void);
           } S
           (Ladebug) whatis S :: bar
           int bar (void)
           (Ladebug) stop in S :: foo
           [#2: stop in S :: foo ]
           (Ladebug) run
           [2] stopped at [int S::foo(void):13 0x120000648]
                13      return i;

           (Ladebug) print S :: i
           1
           (Ladebug)

     9.6 Displaying Object Information

           The print and whatis commands also display information
           on instances of classes (objects). Use the whatis command
           to display the class type of an object. Use the print
           command to display the current value of an object. You can
           print an object's contents all at once using the following
           syntax:

           print  object


     9-8 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                                       9.6 Displaying Object Information

              You can also display individual object members using the
              member access operators, period (.) and right arrow (->)
              in a print command. Static data members are treated as
              members of objects, so you can reference them by object
              name. If the debugger stops in a member function of an
              object, you can access other members of that same object
              using the this pointer implicitly or explicitly.

              You can use the scope resolution operator (::) to
              reference global variables, to reference hidden members
              in base classes, to explicitly reference a member that
              is inherited, or to otherwise name a member hidden by the
              current context.

              When you are in the context of a nested class, you must
              use the scope resolution operator to access members of the
              enclosing class.

              Example 9-4 shows how to use the print and whatis commands
              to display object information.

              Example 9-4 Displaying Object Information

              (Ladebug) whatis s
              class S  {
                int i;
                int j;
                S (void);
                ~S (void);
                int foo (void);
                virtual int bar (void);
              } s
              (Ladebug) stop in S::foo; run
              [#1: stop in s.foo ]
              [1] stopped at [int S::foo(void):13 0x120000638]
                   35      return i;
              (Ladebug) print *this
              class {
                      i = 1;
                      j = 2;
                  }

                                                (continued on next page)


                                          Using the Ladebug Debugger 9-9

 



     Using the Ladebug Debugger
     9.6 Displaying Object Information

           Example 9-4 (Cont.) Displaying Object Information

           (Ladebug) print i, j
           1 2

           (Ladebug) print this->i, this->j
           1 2
           (Ladebug)

     9.7 Displaying Virtual and Inherited Class Information

           When you use the print command to display information on
           an instance of a derived class, the debugger displays both
           the new class members as well as the members inherited
           from a base class. Base class member information is nested
           within the inherited class information.

           Pointers to members of a class are not supported.
           Example 9-5 shows the format the debugger uses to print
           information on derived classes.

           Example 9-5 Printing Information on a Derived Class

                                             (continued on next page)





















     9-10 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                  9.7 Displaying Virtual and Inherited Class Information

              Example 9-5 (Cont.) Printing Information on a Derived
                                  Class

              (Ladebug) list 1, 23
                    1 class S {
                    2 public:
                    3      int i;
                    4      S() {i=1;};
                    5      ~S() {i=0;};
                    6      int foo();
                    7 };
                    8
                    9 S::foo()
                   10 {
                   11    i = i + 1;
                   12    return i;
                   13 }
                   14
                   15 class T : public S {
                   16 public:
                   17      int j;
                   18      T() {j=2;};
                   19      ~T() {i=0;};
                   20 };
                   21
                   22 S a;
                   23 T b;
              (Ladebug) stop in main ; run
              [#1: stop in main(void) ]
              [1] stopped at [main(void):27 0x1200007f4]
                   27    a.i = 1;
              (Ladebug) print b
              class {
                      S = class {
                          i = 1;
                      };
                      j = 2;
                  }

                                                (continued on next page)





                                         Using the Ladebug Debugger 9-11

 



     Using the Ladebug Debugger
     9.7 Displaying Virtual and Inherited Class Information

           Example 9-5 (Cont.) Printing Information on a Derived
                               Class

           (Ladebug) whatis b
           class T : S {
             int j;
             T (void);
             ~T (void);
           } b

           (Ladebug) whatis S
           class S  {
             int i;
             S (void);
             ~S (void);
             int foo (void);
           } S
           (Ladebug)

           The whatis b command in this example displays the class
           type of the object b. Descriptions of derived classes
           obtained with the whatis command do not include members
           inherited from base classes. Class T inherits the public
           members of class S; in this case, integer variable i and
           member function foo.

           If you have two members in an object with the same name
           but different base class types (multiple inheritance), you
           can refer to the members using the following syntax:

           object.class::member

           This syntax is more effective than using the object.member
           and object->member syntaxes, which can be ambiguous. In
           all cases, the Ladebug debugger uses the C++ language
           rules as defined in The Annotated C++ Reference Manual to
           determine which member you are specifying.

           Example 9-6 shows a case where the expanded syntax is
           necessary. In this example, two base classes, B and C
           inherit the public members of base class V. Derived class
           D inherits the public members of both class B and class
           C.


     9-12 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                  9.7 Displaying Virtual and Inherited Class Information

              Example 9-6 Resolving References to Objects of Multiple
                          Inherited Classes

              (Ladebug) whatis D
              class D : B, C {
                D (void);
                ~D (void);
                void g (void);
              } D
              (Ladebug) whatis C
              class C : virtual V {
                int ambig;
                C (void);
                ~C (void);
              } C
              (Ladebug) whatis B
              class B : virtual V {
                int x;
                int ambig;
                B (void);
                ~B (void);
                int f (void);
              } B
              (Ladebug) whatis V
              class V  {
                int v;
                int x;
                V (void);
                ~V (void);
                int f (void);
              } V
              (Ladebug) stop in main; run
              [#1: stop in main(void) ]
              [1] stopped at [main(void):59 0x120001024]
                   59   D dinst;
              (Ladebug) next
              stopped at [main(void):60 0x120001030]
                   60   V vinst;
              (Ladebug) <Return>
              stopped at [main(void):62 0x120001038]
                   62   printf("%d\en", dinst;

                                                (continued on next page)


                                         Using the Ladebug Debugger 9-13

 



     Using the Ladebug Debugger
     9.7 Displaying Virtual and Inherited Class Information

           Example 9-6 (Cont.) Resolving References to Objects of
                               Multiple Inherited Classes

           (Ladebug) print dinst.ambig
           Ambiguous reference
           Selecting 'ambig' failed!
           Error: no value for dinst.ambig
           (Ladebug) print dinst.B::ambig
           2
           (Ladebug)

           Trying to examine an inlined member function that is not
           called results in the following error:

           Member function has been inlined.

           Ladebug will report this error regardless of the
           settings of the -noinline_auto compilation switches. As a
           workaround, include a call to the given member function
           somewhere in your program. (The call does not need to be
           executed.)

           If a program is not compiled with the -g option, a
           breakpoint set on an inline member function may confuse
           the debugger.

     9.8 Modifying Class and Object Data Members

           When debugging C++ code, the debugger lets you modify
           a class's static data members and object data members
           as you would modify any other program variable by using
           the debugger's assign command. See the Compaq Tru64 UNIX
           Ladebug Debugger Manual for details on how to use the
           assign command to modify variable values. The following
           assignments are allowed by the debugger even though they
           are prohibited in the C++ language:

           o  Variables of type const may be assigned a new value.

           o  Variables declared as reference types (using a type&
              type definition) may be assigned a new value. The
              address referred to by a reference type may not be
              changed, but the value at that address may be changed.


     9-14 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                                 9.9 Member Functions on the Stack Trace

        9.9 Member Functions on the Stack Trace

              The implicit this pointer, which is a part of all
              nonstatic member functions, is displayed as the address
              on the stack trace. The class type of the object is also
              given.

              Sometimes the debugger does not see class type names with
              internal linkage. When this happens, the debugger gives
              the following error message:

              Name is overloaded.

              The stack trace in Figure 9-1 displays a member function
              foo of an object declared with class type S.

              Figure 9-1 A Stack Trace Displaying a Member Function







        9.10 Resolving Ambiguous References to Overloaded Functions

              In most cases, the debugger works with one specific
              function at a time. In the case of overloaded function
              names, you must specify the desired overloaded function.
              There are two ways to resolve references to overloaded
              function names. Both ways are under the control of the
              debugger variable $overloadmenu. The default setting of
              this debugger variable is 0.

              One way to specify the desired function name is to choose
              the correct reference from a selection menu. To enable
              menu selection of overloaded names, set the $overloadmenu
              variable to 1. If you use this method, whenever you
              specify a function name that is overloaded, a menu will
              appear with all the possible functions; you must select
              from this menu. In Example 9-7, a breakpoint is set in
              foo, which is overloaded.



                                         Using the Ladebug Debugger 9-15

 



     Using the Ladebug Debugger
     9.10 Resolving Ambiguous References to Overloaded Functions

           Example 9-7 Resolving Overloaded Functions by Selection
                       Menu

           (Ladebug) set $overloadmenu = 1
           (Ladebug) class S
           class S  {
             int i;
             float f;
             double d;
             char c;
             S (void);
             ~S (void);
             int foo (void);
             int foo ( S);
             int foo ( S *);
             int foo (int&);
             int foo (const int&);
             int foo (float*&);
             int foo (int, float, char *, unsigned short, long&, const char*&);
             int foo (const double *);
             int foo (char);
             void foo (short);
             void foo (unsigned);
             void foo (long);
             void foo (int, float, char *, unsigned short, long&, char*&);
             void foo (double);
             void foo (char *);
             void foo (const char *);
           }

                                             (continued on next page)














     9-16 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
             9.10 Resolving Ambiguous References to Overloaded Functions

              Example 9-7 (Cont.) Resolving Overloaded Functions by
                                  Selection Menu

              (Ladebug) stop in foo
              Enter the number of the overloaded function you want
              ----------------------------------------------------
                   1 int foo (void)
                   2 void foo (const char *)
                   3 void foo (char *)
                   4 void foo (double)
                   5 void foo (int, float, char *, unsigned short, long&, char*&)
                   6 void foo (long)
                   7 void foo (unsigned)
                   8 void foo (short)
                   9 int foo (char)
                  10 int foo (const double *)
                  11 int foo (int, float, char *, unsigned short, long&, const char*&)
                  12 int foo (float*&)
                  13 int foo (const int&)
                  14 int foo (int&)
                  15 int foo ( S *)
                  16 int foo ( S)
                  17 None of the above
              ----------------------------------------------------

              10
              [#1: stop in int S::foo(const double*) ]
              (Ladebug)

              The other way to resolve ambiguous overloaded function
              names is to enter the function name with its full
              type signature. If you prefer this method, set the
              $overloadmenu variable to 0. To see the possible type
              signatures for the overloaded function, first display all
              the declarations of an overloaded function by using one of
              the following syntax lines:

              whatis  function

              whatis  class_name::function





                                         Using the Ladebug Debugger 9-17

 



     Using the Ladebug Debugger
     9.10 Resolving Ambiguous References to Overloaded Functions

           You cannot select a version of an overloaded function that
           has a type signature containing ellipsis points. Pointers
           to functions with type signatures that contain parameter
           list or ellipsis arguments are not supported.

           Use one of the displayed function type signatures to refer
           to the desired version of the overloaded function. If a
           function has no parameter, include the parameter void as
           the function's type signature. In Example 9-8 the function
           context is set to foo(), which is overloaded.

           Example 9-8 Resolving Overloaded Functions by Type
                       Signature

           (Ladebug) print $overloadmenu
           0
           (Ladebug) class S
           class S  {
             int i;
             float f;
             double d;
             char c;
             S (void);
             ~S (void);
             int foo (void);
             int foo ( S);
             int foo ( S *);
             int foo (int&);
             int foo (const int&);
             int foo (float*&);
             int foo (int, float, char *, unsigned short, long&, const char*&);
             int foo (const double *);
             int foo (char);
             void foo (short);
             void foo (unsigned);
             void foo (long);
             void foo (int, float, char *, unsigned short, long&, char*&);
             void foo (double);
             void foo (char *);
             void foo (const char *);
           }

                                             (continued on next page)


     9-18 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
             9.10 Resolving Ambiguous References to Overloaded Functions

              Example 9-8 (Cont.) Resolving Overloaded Functions by
                                  Type Signature

              (Ladebug) whatis foo
              Overloaded Function. Functions are:
              int S::foo(void)
              int S::foo(S)
              int S::foo(S*)
              int S::foo(int&)
              int S::foo(const int&)
              int S::foo(float*&)
              int S::foo(int, float, char*, unsigned short, long&, const char*&)
              int S::foo(const double*)
              int S::foo(char)
              void S::foo(short)
              void S::foo(unsigned)
              void S::foo(long)
              void S::foo(int, float, char*, unsigned short, long&, char*&)
              void S::foo(double)
              void S::foo(char*)
              void S::foo(const char*)
              (Ladebug) func foo
              Error: foo is overloaded

              (Ladebug) func foo(double)
              S::foo(double) in c++over.C line No. 156:
                  156     printf ("void S::foo (double d = %f)\n", d);
              (Ladebug)

        9.11 Setting Breakpoints in Member Functions

              When you set a breakpoint in a C function, the debugger
              confirms the breakpoint by echoing the breakpoint command
              along with the status number for the breakpoint. When
              you set a breakpoint in a C++ function, the debugger also
              prints the type signature of the function in which the
              breakpoint was set.

              To set a breakpoint that stops in a member function, use
              one of the following syntax lines:

              stop in  function



                                         Using the Ladebug Debugger 9-19

 



     Using the Ladebug Debugger
     9.11 Setting Breakpoints in Member Functions

           stop in  class_name::function

           This form of specifying a breakpoint in a function uses
           the static class type information to determine the address
           of the function at which to set the breakpoint, and
           presumes that no run-time information from an object is
           needed.

           In Example 9-9 a breakpoint is set for member function bar
           of class S.

           Example 9-9 Setting Breakpoints in Member Functions

           (Ladebug) stop in S :: bar
           [#1: stop in S::bar(void) ]
           (Ladebug) status
           #1 PC==0x120000658 in S::bar(void) "c++ex.C":18 { break }
           (Ladebug) run
           [1] stopped at [S::bar(void):18 0x120000658]
                18      return j;
           (Ladebug) where
           >0  0x120000658 in ((S*)0x120000658)->bar() c++ex.C:18
           #1  0x120000750 in main() c++ex.C:26
           (Ladebug)

           If you need run-time information from the object to
           determine the correct virtual function at which to set
           a breakpoint, qualify the function name with the object
           using one of the following syntax lines:

           stop in  object.function

           stop in  objectpointer->function

           Setting the breakpoint in this way causes the debugger
           to stop at the member function in all objects declared
           with the same class type as the specified object. In
           Example 9-10, objects s and t are both declared to be
           of class type S. A breakpoint is set for member function
           bar. The first time the debugger stops at bar() is for
           object s. The second time the debugger stops in bar() for
           object t.



     9-20 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                            9.11 Setting Breakpoints in Member Functions

              Example 9-10 Setting Breakpoints in Virtual Member
                           Functions

              (Ladebug) stop in main
              [#1: stop in main(void) ]
              (Ladebug) run
              [1] stopped at [main(void):26 0x120000744]
                   26      int result = s.bar();
              (Ladebug) stop in s.bar
              [#2: stop in S::bar(void) ]
              (Ladebug) status
              #1 PC==0x120000744 in main(void) "c++ex.C":26 { break }
              #2 PC==0x120000658 in S::bar(void) "c++ex.C":18 { break }
              (Ladebug) print &s
              0x140000000
              (Ladebug) print &t
              0x140000008
              (Ladebug) cont
              [2] stopped at [S::bar(void):18 0x120000658]
                   18      return j;

              (Ladebug) where
              >0  0x120000658 in ((S*)0x140000000)->bar() c++ex.C:18
              #1  0x120000750 in main() c++ex.C:26
              (Ladebug) cont
              [2] stopped at [S::bar(void):18 0x120000658]
                   18      return j;
              (Ladebug) where
              >0  0x120000658 in ((S*)0x140000008)->bar() c++ex.C:18
              #1  0x12000076c in main() c++ex.C:27
              (Ladebug)

              To set a breakpoint that stops only in the member function
              for this specific object and not all instances of the
              same class type, you must specify this as an additional
              conditional clause to the stop command. Use one of the
              following syntax lines:

              stop in  object.function if & object == this

              stop in  objectpointer->function if & objectpointer ==
                       this



                                         Using the Ladebug Debugger 9-21

 



     Using the Ladebug Debugger
     9.11 Setting Breakpoints in Member Functions

           This form of the breakpoint command instructs the debugger
           to stop in the function only for the object specified by
           the this pointer. In Example 9-11, which is running the
           same program as Example 9-10, the breakpoint is set for
           the member function for object s only. After stopping
           in bar() for object s, further execution of the program
           results in the program running to completion.


           Example 9-11 Setting Breakpoints in Member Functions for
                        a Specific Object

           (Ladebug) stop in s.bar if &s==this
           [#2: stop in s.bar if &s==this ]
           (Ladebug) status
           #1 PC==0x120000744 in main(void) "c++ex.C":26 { break }
           #2 (PC==0x120000658 in S::bar(void) "c++ex.C":18 and if &s==this) {break}
           (Ladebug) print &s
           0x140000000
           (Ladebug) cont
           [2] stopped at [S::bar(void):18 0x120000658]
                18      return j;

           (Ladebug) where
           >0  0x120000658 in ((S*)0x10000010)->bar() c++ex.C:18
           #1  0x120000750 in main() c++ex.C:26
           (Ladebug) cont
           Thread has finished executing
           (Ladebug)

     9.11.1 Setting Breakpoints in Overloaded Functions

           To set a breakpoint in an overloaded function, you must
           provide the full type signature of the function. Use one
           of the following command syntax lines:

           stop in  function (type_signature)

           stop in  class_name::function (type_signature)

           If the desired version of the function has no param-
           eters, you must enter void for the type signature. In
           Example 9-12 the breakpoint is set for specific versions
           of the overloaded function foo.

     9-22 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                            9.11 Setting Breakpoints in Member Functions

              Example 9-12 Setting Breakpoints in Specific Overloaded
                           Functions

              (Ladebug) class S
              class S  {
                int i;
                float f;
                double d;
                char c;
                S (void);
                ~S (void);
                int foo (void);
                int foo ( S);
                int foo ( S *);
                int foo (int&);
                int foo (const int&);
                int foo (float*&);
                int foo (int, float, char *, unsigned short, long&, const char*&);
                int foo (const double *);
                int foo (char);
                void foo (short);
                void foo (unsigned);
                void foo (long);
                void foo (int, float, char *, unsigned short, long&, char*&);
                void foo (double);
                void foo (char *);
                void foo (const char *);
              }

                                                (continued on next page)















                                         Using the Ladebug Debugger 9-23

 



     Using the Ladebug Debugger
     9.11 Setting Breakpoints in Member Functions

           Example 9-12 (Cont.) Setting Breakpoints in Specific
                                Overloaded Functions

           (Ladebug) whatis foo
           Overloaded Function. Functions are:
           int S::foo(void)
           int S::foo(S)
           int S::foo(S*)
           int S::foo(int&)
           int S::foo(const int&)
           int S::foo(float*&)
           int S::foo(int, float, char*, unsigned short, long&, const char*&)
           int S::foo(const double*)
           int S::foo(char)
           void S::foo(short)
           void S::foo(unsigned)
           void S::foo(long)
           void S::foo(int, float, char*, unsigned short, long&, char*&)
           void S::foo(double)
           void S::foo(char*)
           void S::foo(const char*)

           (Ladebug) stop in foo(double)
           [#1: stop in void S::foo(double) ]
           (Ladebug) stop in foo(void)
           [#2: stop in int S::foo(void) ]
           (Ladebug) status
           #1 PC==0x120001508 in void S::foo(double) "c++over.C":156 { break }
           #2 PC==0x120000ef4 in int S::foo(void) "c++over.C":59 { break }
           (Ladebug)

           To set a breakpoint that stops in all versions of an
           overloaded function, use one of the following syntax
           lines:

           stop in all  function

           stop in all  class_name::function

           In Example 9-13 the breakpoint is set for all versions of
           the overloaded function foo.




     9-24 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                            9.11 Setting Breakpoints in Member Functions

              Example 9-13 Setting Breakpoints in All Versions of an
                           Overloaded Function

              (Ladebug) class S
              class S  {
                int i;
                float f;
                double d;
                char c;
                S (void);
                ~S (void);
                int foo (void);
                int foo ( S);
                int foo ( S *);
                int foo (int&);
                int foo (const int&);
                int foo (float*&);
                int foo (int, float, char *, unsigned short, long&, const char*&);
                int foo (const double *);
                int foo (char);
                void foo (short);
                void foo (unsigned);
                void foo (long);
                void foo (int, float, char *, unsigned short, long&, char*&);
                void foo (double);
                void foo (char *);
                void foo (const char *);
              }

              (Ladebug) stop in all foo
              [#1: stop in all foo ]
              (Ladebug)

              You can also set a breakpoint in an overloaded function by
              setting a breakpoint at the line number where the function
              begins. Be sure the current file context points to the
              file containing the function's source code before setting
              the breakpoint. In Example 9-14 the breakpoint is set for
              the overloaded functions by line number.






                                         Using the Ladebug Debugger 9-25

 



     Using the Ladebug Debugger
     9.11 Setting Breakpoints in Member Functions

           Example 9-14 Setting Breakpoints in Overloaded Functions
                        by Line Number

           (Ladebug) stop at 59
           [#1: stop at "c++over.C":59 ]
           (Ladebug) stop at 156
           [#2: stop at "c++over.C":156 ]

           (Ladebug) status
           #1 PC==0x120000ef4 in S::foo(void) "c++over.C":59 { break }
           #2 PC==0x120001508 in S::foo(double) "c++over.C":156 { break }
           (Ladebug)


     9.11.2 Setting Breakpoints in Constructors and Destructors

           To set a breakpoint in a constructor, use one of the
           following syntax lines:

           stop in  class_name::class_name [(type_signature)]

           stop in  class_name [(type_signature)]

           The type signature is necessary only to resolve the
           ambiguity for a constructor that is overloaded. In
           Example 9-15, a breakpoint is set in a constructor.

           Example 9-15 Setting Breakpoints in Constructors

           (Ladebug) class S
           class S  {
             int i;
             int j;
             S (void);
             ~S (void);
             int foo (void);
             virtual int bar (void);
           }
           (Ladebug) stop in S
           [#1: stop in S::S(void) ]
           (Ladebug) status
           #1 PC==0x1200005b8 in S::S(void) "c++ex.C":5 { break }
           (Ladebug)


     9-26 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                            9.11 Setting Breakpoints in Member Functions

              You can similarly set a breakpoint in a destructor using
              the following syntax:

              stop in  ~class_name

              In Example 9-16, the breakpoint is set for the destruc-
              tor.

              Example 9-16 Setting Breakpoints in Destructors

              (Ladebug) stop in ~S
              [#1: stop in S::~S(void) ]

              (Ladebug) status
              #1 PC==0x1200005f8 in S::~S(void) "c++ex.C":6 { break }
              (Ladebug)

              As with any function's type signature specification,
              constructors and destructors that have no parameters must
              be referenced with a type signature of void.

        9.12 Calling Overloaded Functions

              To call overloaded functions from the debugger, you must
              set $overloadmenu to 1. Then, use the following call
              command syntax:

              call  function ([parameter[, . . . ]])

              The debugger will call the function that you select
              from the menu of overloaded names. In Example 9-17 the
              overloaded function foo is called.

              Example 9-17 Calling an Overloaded Function

              (Ladebug) set $overloadmenu = 1
              (Ladebug) call foo(15)

                                                (continued on next page)






                                         Using the Ladebug Debugger 9-27

 



     Using the Ladebug Debugger
     9.12 Calling Overloaded Functions

           Example 9-17 (Cont.) Calling an Overloaded Function

           Enter the number of the overloaded function you want
           ----------------------------------------------------
                1 void foo (const char *)
                2 void foo (char *)
                3 void foo (double)
                4 void foo (float)
                5 void foo (unsigned)
                6 void foo (long)
                7 void foo (short)
                8 int foo (const double *)
                9 int foo (int, float)
               10 int foo (float*&)
               11 int foo (const int&)
               12 int foo (int&)
               13 int foo (char)
               14 int foo ( S *)
               15 int foo ( S)
               16 None of the above
           ----------------------------------------------------

           6
           global foo (long):              15
           (Ladebug)

     9.13 Using Typecasts to Display Program Expressions

           When debugging C++ programs, the debugger interprets casts
           as defined in the International C++ Standard. A cast has
           the following syntax:

           (type) variable

           The type is the type the debugger will use to interpret
           the program variable variable. The debugger does not allow
           cast conversion from an unsigned short type to a long int
           type.

           In Example 9-18, a variable of type float is interpreted
           as an integer.




     9-28 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                     9.13 Using Typecasts to Display Program Expressions

              Example 9-18 Using a Cast to Perform Data Coercion

              (Ladebug) whatis f
              float f
              (Ladebug) print f
              3.2

              (Ladebug) print (int)f
              3
              (Ladebug)

              You can also use casts to interpret a base class object
              as a derived class object, or to interpret a derived
              class object as a base class object. In Example 9-19,
              the class derived inherits the public members of class
              base. A pointer to an object of class derived is declared
              to be a pointer to an object of class base. A cast is used
              to display the object's contents using the correct class
              type.

              Example 9-19 Using Casts on a Derived Class Object

              (Ladebug) whatis bvar
               base * bvar
              (Ladebug) whatis derived
              class derived : base {
                int i;
                derived (void);
                ~derived (void);
                virtual int foo (void);
              } derived
              (Ladebug) whatis base
              class base  {
                int j;
                base (void);
                ~base (void);
                virtual int foo (void);
              } base
              (Ladebug) print *bvar
              class {
                      j = 0;
                  }

                                                (continued on next page)

                                         Using the Ladebug Debugger 9-29

 



     Using the Ladebug Debugger
     9.13 Using Typecasts to Display Program Expressions

           Example 9-19 (Cont.) Using Casts on a Derived Class
                                Object

           (Ladebug) print *(derived *)bvar
           class {
                   base = class {
                       j = 0;
                   };
                   i = 4195376;
               }
           (Ladebug)

           Example 9-20 shows how to use a type transfer to interpret
           a variable of type float as an integer.

           Example 9-20 Using a Cast with Pointer Notation to
                        Perform a Type Transfer

           (Ladebug) print &f
           0x11ffffe84

           (Ladebug) print *(int *)&f
           1078774989
           (Ladebug)

           You can also perform the type transfer shown in this
           example by using C++ reference types. Example 9-21 shows
           how to use reference type notation to perform a type
           transfer.

           Example 9-21 Using a Cast with Reference Type Notation to
                        Perform a Type Transfer

           (Ladebug) print &f
           0x11ffffe84

           (Ladebug) print (int&)f
           1078774989
           (Ladebug)






     9-30 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                             9.14 Class Templates and Function Templates

        9.14 Class Templates and Function Templates

              The debugger provides support for debugging class
              templates and function templates in much the same way as
              other classes and functions in C++, with the limitations
              described in this section.

              You can use the whatis command on an instantiation of the
              function template as shown in Example 9-22.

              Example 9-22 Example of a Function Template

              (Ladebug) list 1
                    1 // remember to compile with -define_templates
                    2 template<class T> int compare(T t1, T t2)
                    3 {
                    4         if (t1 < t2) return 0;
                    5         else         return 1;
                    6 }
                    7
                    8 main()
                    9 {
              >    10         int i = compare(1,2);
                   11 }

              (Ladebug) whatis compare
              int compare (int, int)
              (Ladebug)

              You can set a breakpoint in a template function as shown
              in Example 9-23.

              Example 9-23 Setting a Breakpoint in the Template
                           Function

              (Ladebug) stop in compare
              [#2: stop in compare(int, int) ]








                                         Using the Ladebug Debugger 9-31

 



     Using the Ladebug Debugger
     9.14 Class Templates and Function Templates


           (Ladebug) run
           [2] stopped at [compare(int, int):4 0x120000560]
                 4         if (t1 < t2) return 0;
           (Ladebug)

           As shown in Example 9-24, while inside the function
           template, you can set or ask for the current function con-
           text, and the instantiated function will be displayed.


           Example 9-24 Displaying the Current Function Context for
                        a Function Template

           (Ladebug) func
           compare(int, int) in c++functemp.C line No. 4:
                 4         if (t1 < t2) return 0;
           (Ladebug)

           For class templates, you cannot use the whatis command
           with the template name, but you can use the whatis command
           on a specific instantiation of the class template. This
           is the instantiated name that the debugger prints when
           it encounters variables of the template class type.
           Example 9-25 displays the class definition of a particular
           instantiation of a parameterized stack.

           Example 9-25 Displaying an Instantiated Class Template

                                             (continued on next page)















     9-32 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                             9.14 Class Templates and Function Templates

              Example 9-25 (Cont.) Displaying an Instantiated Class
                                   Template

              (Ladebug) list 1, 24
                    1 #include <iostream.h>
                    2
                    3 template <class T, int size> class stack {
                    4         T s[size];
                    5         int top;
                    6 public:
                    7         stack() { top = 0; }
                    8         void push(T item)
                    9              {
                   10               s[top++] = item;
                   11              }
                   12         T pop();
                   13 };
                   14
                   15 template<class T, int size> T stack<T,size>::pop()
                   16 {
                   17         return s[--top];
                   18 }
                   19
                   20 stack<int,10*10> S;
                   21 stack<double,10> F;
                   22
                   23 #pragma define_template stack<int,100>
                   24 #pragma define_template stack<double,10>

              (Ladebug) whatis stack<int,100>
              class stack<int,100>  {
                array [subrange 0 ... 99 of int] of int s;
                int top;
                stack<int,100> (void);
                void push (int);
                int pop (void);
              } stack<int,100>
              (Ladebug)

              Similarly, as shown in Example 9-26, you can use the
              whatis S command. The instance of S is displayed as
              stack<int,100> rather than just S.



                                         Using the Ladebug Debugger 9-33

 



     Using the Ladebug Debugger
     9.14 Class Templates and Function Templates

           Example 9-26 Displaying an Instantiated Class Template

           (Ladebug) whatis S
           class stack<int,100>  {
             array [subrange 0 ... 99 of int] of int s;
             int top;
             stack<int,100> (void);
             void push (int);
             int pop (void);
           } S
           (Ladebug)

           As shown in Example 9-27, you can set breakpoints in
           template functions and ask for the current function
           context while inside a template function.

           Example 9-27 Setting Breakpoints in an Instantiated Class
                        Function

           (Ladebug) stop in S.pop
           [#1: stop in stack<int,100>::pop(void) ]
           (Ladebug) run
           stopped at [stack<int,100>::pop(void):17 0x120001e0c]
                17         return s[--top];
           (Ladebug) func
           stack<int,100>::pop(void) in c++classtemp.C line No. 17:
                17         return s[--top];

           (Ladebug) print top
           2
           (Ladebug)

           You can explicitly set your current class scope to a
           particular instantiation of a class template if you
           are not in the proper class scope. See Example 9-28 and
           Example 9-29.

           Example 9-28 Setting Current Class Scope to an Instantiated
                        Class

                                             (continued on next page)




     9-34 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                             9.14 Class Templates and Function Templates

              Example 9-28 (Cont.) Setting Current Class Scope to an
                                   Instantiated Class

              (Ladebug) stop in push
              Symbol push not visible in current scope.
              push has no valid breakpoint address
              Warning: Breakpoint not set
              (Ladebug) class
              Current context is not a class
              (Ladebug) class S
              class stack<int,100>  {
                array [subrange 0 ... 99 of int] of int s;
                int top;
                stack<int,100> (void);
                ~stack<int,100> (void);
                void push (int);
                int pop (void);
              }
              (Ladebug) stop in push
              [#4: stop in stack<int,100>::push(int) ]

              (Ladebug) run
              [4] stopped at [stack<int,100>::push(int):10 0x120001cd0]
                   10               s[top++] = item;
              (Ladebug)

              Example 9-29 Alternate Method of Setting Current Class
                           Scope

              (Ladebug) class stack<int,100>
              class stack<int,100>  {
                array [subrange 0 ... 99 of int] of int s;
                int top;
                stack<int,100> (void);
                ~stack<int,100> (void);
                void push (int);
                int pop (void);
              }

                                                (continued on next page)





                                         Using the Ladebug Debugger 9-35

 



     Using the Ladebug Debugger
     9.14 Class Templates and Function Templates

           Example 9-29 (Cont.) Alternate Method of Setting Current
                                Class Scope

           (Ladebug) stop in push
           [#5: stop in stack<int,100>::push(int) ]
           (Ladebug)

           Additional limitations for debugging templates include:

           o  You cannot specify a template by name in a debugger
              command. You must use the name of the instantiation of
              the template.

           o  In C++, expressions in the instantiated template
              name can be full constant expressions such as
              stack<double,f*10>. This form is not yet supported
              in the Ladebug debugger; you must enter the value of
              the expression (for example, if f is 10 in the stack
              example, you must enter 100).

           o  Setting a breakpoint at a line number that is inside
              a template function will not necessarily stop at all
              instantiations of the function within the given file,
              but only a randomly chosen few. This limitation is
              due to the limited symbol information generated by the
              compiler for templates.

     9.15 Debugging C++ Exception Handlers

           You can debug C++ exception handlers in programs by
           setting breakpoints in the exception handler or in the
           predefined C++ functions that are used when exceptions
           occur. You can also examine and modify variables that are
           used in exception handlers.

     9.15.1 Setting Breakpoints in Exception Handlers

           As shown in Example 9-30, you can set a breakpoint in
           an exception handler by setting a breakpoint at the line
           number where the code for the exception handler begins.
           You can then step through the exception handler, examine
           or modify variables, or continue executing the program.



     9-36 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                                   9.15 Debugging C++ Exception Handlers

              Example 9-30 Setting Breakpoints in Exception Handlers

              (Ladebug) list 24
                   24     try
                   25     {
                   26          foo();
                   27     }
                   28     catch(char * str) { printf("Caught %s.\n",str); }
                   29     catch(...) { printf("Caught something.\n"); }
                   30
                   31 return 0;
                   32 }
              (Ladebug) stop at 24
              [#1: stop at "except.C":26 ]
              (Ladebug) stop in unexpected
              [#2: stop in unexpected ]
              (Ladebug) run
              [1] stopped at [int main(void):26 0x400370]
                   26          foo();
              (Ladebug) cont
              [2] stopped at [unexpected:631 0x4010a8]
              (Cannot find source file cxx_exc.c)
              (Ladebug) cont
              In my_unexpected().
              Caught HELP.
              Thread has finished executing
              (Ladebug)

              As this example shows, you can also set breakpoints in C++
              functions used to handle exceptions as follows:

              terminate   Gains control when any unhandled exception
                          occurs

              unexpected  Gains control when a function containing
                          an exception specification tries to throw
                          an exception that is not in the exception
                          specification







                                         Using the Ladebug Debugger 9-37

 



     Using the Ladebug Debugger
     9.15 Debugging C++ Exception Handlers

     9.15.2 Examining and Modifying Variables in Exception Handlers

           After you set a breakpoint to stop the execution in the
           exception handler, you can access the variables used in
           the exception handler the same way you would examine and
           modify other program variables.

     9.16 Advanced Program Information: Verbose Mode

           By default, the debugger gives no information on virtual
           base class pointers for the following:

           o  Derived classes

           o  Virtual pointer tables for virtual functions

           o  Compiler-generated function members

           o  Compiler-generated temporary variables

           o  Implicit parameters in member functions

           By setting the $verbose debugger variable to 1, you can
           request that this information be printed in subsequent
           debugger responses. This section explains the normally
           suppressed information that the debugger provides if the
           $verbose debugger variable is set to 1.

           When the $verbose debugger variable is set to 1 and you
           display the contents of a class using the whatis command,
           several of the class members listed are not in the source
           code of the original class definition. The following line
           shows sample output from the whatis command:

           array [subrange 0 ... 0 of int] of vtable * _\|_vptr;

           The vtable variable contains the addresses of all virtual
           functions associated with the class. Several other class
           members are generated by the compiler for internal use.
           When the $verbose debugger variable is set to 1, you
           can see these members and reference them as you would
           reference any other member function.

           The compiler generates additional parameters for nonstatic
           member functions. When the $verbose debugger variable is
           set to 1, these extra parameters are displayed as part of
           each member function's type signature.

     9-38 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                         9.16 Advanced Program Information: Verbose Mode

              If you are specifying a version of an overloaded function
              by entering its type signature and the $verbose variable
              is set to 1, you must include these parameters.

              If the $verbose debugger variable is set to 0, you should
              not include the compiler-generated parameters in the type
              signature. When the $verbose variable is set to 1, the
              output of the dump command includes not only standard
              program variables but also compiler-generated temporary
              variables.

              Example 9-31 prints class information using the whatis
              command when the $verbose variable is set to 1.

              Example 9-31 Printing a Class Description in Verbose Mode

              (Ladebug) print $verbose
              0
              (Ladebug) whatis S
              class S  {
                int i;
                int j;
                S (void);
                ~S (void);
                int foo (void);
                virtual int bar (void);
              } S
              (Ladebug) set $verbose = 1
              (Ladebug) print $verbose
              1

                                                (continued on next page)













                                         Using the Ladebug Debugger 9-39

 



     Using the Ladebug Debugger
     9.16 Advanced Program Information: Verbose Mode

           Example 9-31 (Cont.) Printing a Class Description in
                                Verbose Mode

           (Ladebug) whatis S
           class S  {
             int i;
             int j;
             array [subrange 0 ... 0 of int] of vtbl * _\|_vptr;
             S (S* const);
             S (S* const, const S&);
             ~S (S* const, int);
             int foo (S* const);
             S& operator = (S* const, const S&);
             virtual int bar (S* const);
           } S
           (Ladebug)

           When displaying information on virtual base classes, the
           debugger prints pointers to the table describing the
           base class for each virtual base class object member.
           This pointer is known as the base pointer bptr. The bptr
           pointer is printed after the class member information.
           Example 9-32 shows a print command that displays the bptr
           pointer information when the $verbose variable is set to
           1.

           Example 9-32 Printing Base Pointer Information

           (Ladebug) stop at 66
           [#1: stop at "c++multinher.C":66 ]
           (Ladebug) run
           0
           1
           3
           [1] stopped at [main(void):66 0x1200010b8]
                66   printf("%d\n", dinst.f());

                                             (continued on next page)







     9-40 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                         9.16 Advanced Program Information: Verbose Mode

              Example 9-32 (Cont.) Printing Base Pointer Information

              (Ladebug) whatis dinst
              class D : B, C {
                D (void);
                ~D (void);
                void g (void);
              } dinst
              (Ladebug) print dinst
              class {
                      B = class {
                          V = class {
                              v = 1;
                              x = 3;
                          };
                          x = 2;
                          ambig = 2;
                      };
                      C = class {
                          V = class {
                              v = 1;
                              x = 3;
                          };
                          ambig = 3;
                      };
                  }
              (Ladebug) set $verbose = 1

                                                (continued on next page)
















                                         Using the Ladebug Debugger 9-41

 



     Using the Ladebug Debugger
     9.16 Advanced Program Information: Verbose Mode

           Example 9-32 (Cont.) Printing Base Pointer Information

           (Ladebug) print dinst
           class {
                   B = class {
                       V = class {
                           v = 1;
                           x = 3;
                       };
                       x = 2;
                       ambig = 2;
                       _\|_bptr = 0x10001168;
                   };
                   C = class {
                       V = class {
                           v = 1;
                           x = 3;
                       };
                       ambig = 3;
                       _\|_bptr = 0x1000116c;
                   };
                   _\|_bptr = 0x10001168;
               }
           (Ladebug)

           When a class appears on the stack and the $verbose
           debugger variable is set to 0, the class's members are
           represented with an ellipsis { . . . }. When the $verbose
           debugger variable is set to 1, the debugger prints all
           members of classes on the stack trace.

           Example 9-33 shows that member functions on the stack
           trace are printed with their this pointer value explicitly
           when the $verbose variable is set to 1.

           Example 9-33 Printing a Stack Trace in Verbose Mode

                                             (continued on next page)







     9-42 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                         9.16 Advanced Program Information: Verbose Mode

              Example 9-33 (Cont.) Printing a Stack Trace in Verbose
                                   Mode

              (Ladebug) where
              >0  0x120000789in ((S*)0x10000010)->bar(t={ ... }) c++exv.C:42
              #1  0x1200008bc in main() c++exv.C:50
              (Ladebug) set $verbose = 1
              (Ladebug) where
              >0  0x120000789c in ((S*)0x10000010)->bar(this=0x10000010, t=class {
                      i = 1;
                      j = 2;
                      _\|_vptr = 0x10000960;
                      virtual T::tbar = (function [0x400290]);
                  }) c++exv.C:42
              #1  0x1200008bc in main() c++exv.C:50
              (Ladebug)


        9.17 Reducing Object File Size During Debugging

              With Version 5.6 and higher, the compiler reduces the
              amount of debugging information in object files when -g is
              specified. If the debugger describes a class as <opaque>
              or lacks debugging information, you may need to compile
              using the -gall option. See Section 9.17.1 for information
              on how to use the -gall option.

              Before Version 5.6, debug information for classes and
              structs was generated whenever they were processed by
              the compiler. Thus, debug information for particular
              classes and structs defined in header files often appeared
              in multiple object files, which increased the overall
              size of objects and executables. To reduce debuggable
              executable size, the compiler now attempts to generate
              debug information for a particular class or struct as few
              times as possible. Describing classes and structs this way
              has tremendous savings; reductions in executable sizes of
              up to 70% have been observed for some applications.







                                         Using the Ladebug Debugger 9-43

 



     Using the Ladebug Debugger
     9.17 Reducing Object File Size During Debugging

           In most cases, the object file that contains the debug
           information for a particular class is linked into the
           executable and is available to the debugger. However,
           there are some situations where this might not be the
           case:

           o  A class description may be in a library object
              file that is not linked into the final debuggable
              executable.

           o  A class description may be in a different shared object
              than the shared object you may be trying to debug.

           o  The object file that would have contained the class
              description does not because it was compiled without
              the -g option.

     9.17.1 Using the -gall and -gall_pattern Options

           If Ladebug describes a class or struct as <opaque>, you
           should compile the file in which the class or struct is
           described as <opaque> with the -gall option. Compiling a
           file with the -gall option generates debug information for
           all classes and structs that appear in that source file.

           You can generate complete debugging information when
           compiling a particular file by specifying the -gall option
           on the command line. You can also define a pattern using
           the -gall_pattern option so that a file is compiled with
           complete debugging only if the file name matches the
           pattern. Specifying -gall_pattern lets you compile all
           files with the same command and still have particular
           files compiled with the -gall option to generate complete
           debugging information. You can specify a pattern in two
           ways:

           o  Specify -gall_pattern on the command line

           o  Define environment variable CXX_GALL_PATTERN as the
              pattern

           The -gall_pattern option accepts a list of file names
           (with each file name separated by a comma or colon),
           filename patterns, or a combination of a file name list
           and filename patterns. See fnmatch(3) for valid filename
           patterns.

     9-44 Using the Ladebug Debugger

 



                                              Using the Ladebug Debugger
                         9.17 Reducing Object File Size During Debugging

              If you specify -gall, -g is assumed. The -gall_pattern
              option is ignored unless -g, -g2, or -g3 is also
              specified.

              Example:

              The following example shows how opaque_class is initially
              described as <opaque> by Ladebug, and how this is remedied
              by compiling the file opaque_file.cxx with the -gall
              option:

              Welcome to the Ladebug Debugger Version 4.0-48
               . . .

                   object file name: opaque_file
                   Reading symbolic information ...done
                   (Ladebug) # First, note the class is <opaque>
                   (Ladebug) whatis opaque_class
                   class opaque_class <opaque>

                   Information:  An <opaque> type was presented during execution of the previous
                   command.  For complete type information on this symbol, recompilation of the
                   program will be necessary.  Consult the compiler man pages for details on
                   producing full symbol table information using the -g (and -gall) for cxx)
                   flags.

                   (Ladebug) # Next, find the offending file with Ladebug's "file" command
                   (Ladebug) file
                   opaque_file.cxx
                   (Ladebug) # Quit to recompile opaque_file.cxx with the -gall option
                   (Ladebug) quit

              Recompile the file opaque_file.cxx with the -gall option
              in one of the following ways:

              o  Supply -gall on the command line (useful for hand
                 builds):

                      cxx -g -gall -O0 opaque_file.cxx

              o  Supply -gall_pattern (useful for a generic rule in a
                 makefile):

                      cxx -g -gall_pattern opaque_file.cxx -O0 opaque_file.cxx

                                         Using the Ladebug Debugger 9-45

 



     Using the Ladebug Debugger
     9.17 Reducing Object File Size During Debugging

              In a makefile, this may look something like the
              following:

                   CXX      = cxx
                   CXXFLAGS = -g -gall_pattern opaque_file.cxx -O0
                   $(CXX) $(CXXFLAGS) opaque_file.cxx

           o  Supply the pattern to the environment variable CXX_
              GALL_PATTERN (useful for not modifying the makefile):

                   setenv CXX_GALL_PATTERN "opaque_file.cxx"
                   cxx -g -O0 opaque_file.cxx

           Here are some alternate methods, showing the pattern
           capabilities of the -gall_pattern option:

           o  Compile both opaque_file.cxx and another_file.cxx with
              -gall_pattern:

              cxx -g -gall_pattern opaque_file.cxx,another_file.cxx -O0 opaque_file.cxx

           o  Compile any file starting with opaque or another with
              -gall_pattern:

                   setenv CXX_GALL_PATTERN "opaque*.cxx:another*.cxx"
                   cxx -g -O0 opaque_file.cxx

     9.17.2 Hints for Using the -gall Option Effectively

           For best debugging and smallest objects and executables,
           we recommend that you use the -gall option selectively as
           follows:

           o  Use the -gall option only when you see a class or
              struct described as <opaque>.

           o  Try to compile as few files with -gall as possible.

           o  Choose these few files wisely. If you are seeing
              <opaque> types in only one file, try compiling only
              that file with the -gall option. If you are seeing
              <opaque> types in many files, try compiling a file
              that includes many project header files with the -gall
              option. Doing so will increase the chance that <opaque>
              messages will disappear for the entire application.

     9-46 Using the Ladebug Debugger

 









                                                                       A
        ________________________________________________________________

                                              Class Library Restrictions



              This appendix describes known problems and restrictions
              for the Class Library. Please note that String Package,
              which is part of the Class Library, is entirely different
              from the String class that is part of the newly-
              implemented C++ Standard Library and known as the
              String Library. Do not confuse these two contrasting
              implementations.

              Note also that the Task Package is not supported on the
              Linux Alpha platform.

              The following restrictions apply for the C++ Class
              Library:

              o  Conflict with redefinition of clear()

                 If your program includes both <curses.h> and <iostream.hxx>,
                 Compaq C++ might fail to compile your program
                 because clear() is defined by both header files. In
                 <curses.h>, clear() is defined as a macro whereas
                 in <iostream.hxx> clear() is defined as a member
                 function.

                 Workarounds:

                 If your program does not use either clear() or uses
                 the <curses.h> clear(), include the <iostream.hxx>
                 header first, followed by <curses.h>.

                 If your program uses the ios::clear() function,
                 undefine the clear() macro directly after the #include
                 <curses.h> statement.

              o  Because of a bug in the task package, if you are using
                 that package and you compiled your application with
                 Compaq C++ Version 6.n, your application may encounter
                 runtime errors such as segmentation faults. To avoid
                 these problems, recompile your application specifying

                                          Class Library Restrictions A-1

 



     Class Library Restrictions


              the -preempt_symbol option. For more information about
              the -preempt_symbol option, see the cxx(1) reference
              page.

           o  Use of clog() and the iostream package's clog

              A single application is restricted from using both
              the math library function clog() and the iostream
              package's clog object. This restriction is necessary
              because libm and libcxx each contain a definition
              for the global symbol clog and these definitions are
              incompatible.

              For example, consider a program that makes use of the
              iostream clog object:

                   #include <stdlib.h>
                   #include <iostream.hxx>
                   int main()
                   {
                       clog << "abc";
                       return EXIT_SUCCESS;
                   }

              If you link with the math library first as:

                   cxx clog.cxx -lm -lcxx

              Executing the program results in a segmentation fault.
              The compiler links against shared object libraries
              by default. Identical symbols in subsequent object
              libraries are resolved to the first definition by the
              symbol preemption feature. So in this case use of clog
              from iostreams is resolved to the definition in libm.

              If you link -non_shared with the math library first as:

                  cxx clog.cxx -non_shared -lm -lcxx

              The linker gives a multiply defined message similar to
              the following:

                  ld:
                  /usr/lib/cmplrs/cxx/libcxx.a(iostream_globals.o): clog: multiply defined

     A-2 Class Library Restrictions

 



                                              Class Library Restrictions


                 In this case, if you link with the Class library first,
                 the program executes correctly. As described earlier,
                 the compiler links against shared object libraries
                 by default. Identical symbols in subsequent object
                 libraries are resolved to the first definition by the
                 symbol preemption feature. So in this case use of clog
                 from iostreams is resolved to the definition in libcxx:

                      cxx clog.cxx -lcxx -lm

                 Therefore, applications that reference either of the
                 clog symbols should not include both -lcxx and -lm on
                 their ld command line.

              o  Displacing global operator new in C++ Standard
                 Library/Class Library

                 If a C++ program defines a global operator new() which
                 is intended to displace the version used by the C++
                 Standard Library, it must be compiled with the compiler
                 command line switch -stdnew. If a C++ program defines
                 a global operator new() which is intended to displace
                 the version used by the C++ Class Library, it must
                 be compiled with the compiler command line switch
                 -nostdnew.

              o  The Class Library does not include support for 128-bit
                 long doubles.

















                                          Class Library Restrictions A-3

 









                                                                       B
        ________________________________________________________________

                                                      Built-In Functions



              This appendix describes built-in functions available when
              you compile on Compaq Tru64 UNIX and Linux Alpha systems.
              These functions allow you to access hardware and machine
              instructions directly.

              Be sure to include the </machine/builtins.h> header
              file in your source program to access these built-in
              functions. Definitions for return types int64 and uint64
              are contained in the header file ints.h.

              Translation Macros

              Compaq C++ supports the following translation macros for
              built-in functions:

              _BBCCI(position, address)

              _BBSSI(position, address)

        B.0.0.1 In-line Assembly Code-ASMs

              The compiler supports in-line assembly code, commonly
              called ASMs on UNIX platforms.

              Like builtin-functions, ASMs are implemented with a
              function-call syntax. But unlike built-in functions,
              to use ASMs you must include the <c_asm.h> header file
              containing prototypes for the three types of ASMs, and the
              #pragma intrinsic preprocessor directive.

              These functions have the following format:

              __int64  asm(const char *, . . . );   /* for integer
        operations, like MULQ */
              float fasm(const char *, . . . );    /* for single
              precision float instructions, like MULS */
              double dasm(const char *, . . . );    /* for double
              precision float instructions, like MULT */

                                                  Built-In Functions B-1

 



     Built-In Functions


           #pragma intrinsic (asm, fasm, dasm)

           const char *
           The first argument to the asm, fasm, or dasm function
           contains the instruction(s) to be generated inline and
           the metalanguage that describes the interpretation of the
           arguments.

            . . .
           The source and destination arguments (if any) for the
           instruction being generated, and any other values used in
           the generated instructions.

           These values are made available to the instructions
           through the normal argument passing conventions of the
           calling standard (the first integer argument is available
           in register R16).

           The #pragma intrinsic directive in the <c_asm.h> header
           file is required when using ASMs. It notifies the compiler
           that:

           o  These functions are not user-defined functions.

           o  The special ASM processing should be applied to
              analyze at compile time the first argument and generate
              machine-code instructions as specified by the contents
              of the string.

           The metalanguage for the argument references has the
           following form:

           <metalanguage_sequence> : <register_alias>
                                   | <register_number>
                                   | <register_macro>
                                   ;

           <register_number>       : "$" number
                                   ;

           <register_macro>        : "%" <macro_sequence>
                                   ;



     B-2 Built-In Functions

 



                                                      Built-In Functions


              <macro_sequence>        : number
                                      | <register_name>
                                      | "f" number | "F" number
                                      | "r" number | "R" number
                                      ;

              <register_name> :     /* argument registers: R16-R21 */
                                   "a0" | "a1" | "a2" | "a3" | "a4" | "a5"

                                   /* return value: R0 or F0, depending on type */
                                 | "v0"

                                   /* scratch registers: R1, R22-R24, R28 */
                                 | "t0" | "t1" | "t2" | "t3" | "t4"

                                   /* save registers: R2-R15 */
                                 | "s0" | "s1" | "s2" | "s3" | "s4"  | "s5"  | "s6"  | "s7"
                                 | "s8" | "s7" | "s8" | "s9" | "s10" | "s11" | "s12" | "s13"

                                   /* stack pointer: R30 */
                                 | "sp" | "SP" | "$sp" | "$SP"

                                 | "RA" | "ra"           /* return addr:        R26  */
                                 | "PV" | "pv"           /* procedure value:    R27  */
                                 | "AI" | "ai"           /* arg info:           R25  */
                                 | "FP" | "fp"           /* frame pointer:      R29  */
                                 | "RZ" | "rz" | "zero"  /* sink/source: R31 == zero */

              Syntactically, the metalanguage can appear anywhere within
              an instruction sequence.

              The literal string that contains instructions, operands,
              and metalanguage must follow the general form:

              <string_contents>       :  <instruction_seq>
                                      |  <string_contents> ";" <instruction_seq>
                                      |  error
                                      |  <string_contents> error
                                      ;

              <instruction_seq>       :  instruction_operand
                                      |  directive
                                      ;

              An instruction_operand is generally recognized as an
              assembly language instruction separated by whitespace
              from a sequence of comma-separated operands.

                                                  Built-In Functions B-3

 



     Built-In Functions


           You can code multiple instruction sequences into one
           literal string, separating them by semicolons.

           Because adjacent string literals are concatenated into
           a single string, successive instructions can be written
           as separate strings, one per line (as is normally done
           in assembly language) as long as each instruction is
           terminated by a semicolon (as shown in the examples).

           There are semantic and syntax rules associated with ASMs:

              The first argument to an ASM call is interpreted as
              the instructions to be assembled in the metalanguage,
              and must be fully understood by the compiler at compile
              time. Therefore, it must be a literal string (or a
              macro expanding to a literal string) and must not be
              a run-time value containing a string. Therefore, the
              following are not allowed: indirections, table lookups,
              structure dereferences, and so on.

              The remaining arguments are loaded into the argument
              registers like normal function arguments, except that
              the second argument to the ASM call is treated as the
              first argument for purposes of the calling standard.

              For example, in the following test, the six arguments
              are loaded into arg registers a0 through a5, and the
              result of each subexpression is stored in the value
              return register v0. Since v0 is the calling standard's
              return value register (R0 for an integer function), the
              result of the final MULQ is the value returned by the
              "call":

                 if (asm("mulq %a0, %a1,  %v0;"
                         "mulq %a2, %v0,  %v0;"
                         "mulq %a3, %v0,  %v0;"
                         "mulq %a4, %v0,  %v0;"
                         "mulq %a5, %v0,  %v0;", 1, 2, 3, 4, 5, 6) != 720){
                   error_cnt++;
                   printf ("Test failed\n");
                      }




     B-4 Built-In Functions

 



                                                      Built-In Functions


                 The following example does not work. There is no
                 value loaded into the floating-point return register.
                 Furthermore, it results in a compile-time warning
                 stating that r2 is used before it is set, because the
                 arguments are loaded into the arg registers and not
                 into r2:

                 z =  fasm("mulq %r2, %a1 %r5", x=10, y=5);

                 The correct way of doing this is to specify an argument
                 register number in place of r2. A correct version of
                 the above would be:

                 z = fasm("mulq   %a0, %a1, %a1;"
                          "stq    %a1, 0(%a2);"
                          "ldt    %f0, 0(%a2);"
                          "cvtqf  %f0, %f0;",  x=10, y=5, &temp);

                 Note that the memory location used for the transfer
                 from integer to floating-point register is made
                 available to the asm code by passing as an argument
                 the address of a variable allocated in the C code for
                 that purpose.

              o  A return register must be specified in the metalanguage
                 for the result to appear in the expected place.

              o  For intructions that do not take any argument and do
                 not have a return type, leave out the arguments. For
                 example:

                 asm("MB");

              Privileged Architecture Library Code Instructions

              The following Privileged Architecture Library Code
              (PALcode) instructions are available as built-in
              functions:

              __PAL_GENTR
              __PAL_HALT
              __PAL_BPT
              __PAL_BUGCHK
              __PAL_DRAINA

                                                  Built-In Functions B-5

 



     Built-In Functions


           __PAL_BPT

           This function is provided for program debugging. It
           switches the processor to kernel mode and pushes registers
           R2 to R7, the updated PC, and PS onto the kernel stack. It
           then dispatches to the address in the breakpoint vector,
           which is stored in a control block.

           This function has the following format:

           void  __PAL_BPT (void);

           __PAL_BUGCHK

           This function is provided for error reporting. It switches
           the processor to kernel mode and pushes registers R2 to
           R7, the updated PC, and PS onto the kernel stack. It then
           dispatches to the address in the bugcheck vector, which is
           stored in a control block.

           This function has the following format:

           void  __PAL_BUGCHK (unsigned long);

           __PAL_DRAINA

           This function stalls instruction issuing until all prior
           instructions are guaranteed to complete without incurring
           aborts.

           This function has the following format:

           void  __PAL_DRAINA (void);

           __PAL_GENTRAP

           This function is used for reporting run-time software
           conditions.

           This function has the following format:

           void  __PAL_GENTRAP (uint64 encoded_software_trap);

           encoded_software_trap
           The particular software condition that has occurred.

     B-6 Built-In Functions

 



                                                      Built-In Functions


              __PAL_HALT

              This function halts the processor when executed by a
              process running in kernel mode. This is a privileged
              function.

              This function has the following format:

              void  __PAL_HALT (void);

              Absolute Value ( __ABS)

              The __ABS built-in is functionally equivalent to its
              counterpart, abs, in the standard header file <stdlib.h>.

              Its format is also the same:

              #include <stdlib.h>
              int  __ABS (int x);

              This built-in function does, however, offer performance
              improvements because there is less call overhead
              associated with its use.

              If you include <stdlib.h>, the built-in function is
              automatically used for all occurrences of abs. To disable
              the built-in function, use #undef abs.

              Add Aligned Word Interlocked ( __ADAWI)

              The __ADAWI function adds its source operand to the
              destination. This function is interlocked against similar
              operations by other processors or devices in the system.

              This function has the following format:

              int  __ADAWI (short src, short *dest);

              src
              The value to be added to the destination.

              dest
              A pointer to the destination. The destination must be
              aligned on a word boundary. (You can achieve alignment
              using the _align storage-class modifier.)

              The __ADAWI function returns a simulated VAX processor
              status longword (PSL).

                                                  Built-In Functions B-7

 



     Built-In Functions


           Add Atomic Longword ( __ADD_ATOMIC_LONG)

           The __ADD_ATOMIC_LONG function adds the specified
           expression to the longword data segment pointed to by the
           address parameter within a load-locked/store-conditional
           code sequence.

           This function has the following format:

           int  __ADD_ATOMIC_LONG int fnc(volatile void *, int,
     ...);

           address
           The address of the data segment.

           expression
           An integer expression.

            . . .
           An optional retry count of type int. If specified, the
           retry count indicates the number of times the operation
           is attempted. If the operation cannot be performed
           successfully in the specified number of retries, a value
           of 0 is returned.

           A value of 1 is returned upon successful completion.

           Add Atomic Quadword ( __ADD_ATOMIC_QUAD)

           The __ADD_ATOMIC_QUAD function adds the specified
           expression to the quadword data segment pointed to by the
           address parameter within a load-locked/store-conditional
           code sequence.

           This function has the following format:

           int  __ADD_ATOMIC_QUAD (void *address, int expression,
     ...);

           address
           The address of the data segment.

           expression
           An integer expression.

     B-8 Built-In Functions

 



                                                      Built-In Functions


               . . .
              An optional retry count of type int. If specified, the
              retry count indicates the number of times the operation
              is attempted. If the operation cannot be performed
              successfully in the specified number of retries, a value
              of 0 is returned.

              A value of 1 is returned upon successful completion.

              AND Atomic Longword ( __AND_ATOMIC_LONG)

              The __AND_ATOMIC_LONG function performs a logical AND
              of the specified expression with the longword data
              segment pointed to by the address parameter within a
              load-locked/store-conditional code sequence.

              This function has the following format:

              int  __AND_ATOMIC_LONG (void *address, int expression,
        ...);

              address
              The address of the data segment.

              expression
              An integer expression.

               . . .
              An optional retry count of type int. If specified, the
              retry count indicates the number of times the operation
              is attempted. If the operation cannot be performed
              successfully in the specified number of retries, a value
              of 0 is returned.

              A value of 1 is returned upon successful completion.

              AND Atomic Quadword ( __AND_ATOMIC_QUAD)

              The __AND_ATOMIC_QUAD function performs a logical AND of
              the specified expression with the aligned quadword pointed
              to by the address parameter within a load-locked/store-
              conditional code sequence.

              This function has the following format:

              int  __AND_ATOMIC_QUAD (void *address, int expression,
        ...);

                                                  Built-In Functions B-9

 



     Built-In Functions


           address
           The address of the aligned quadword.

           expression
           An integer expression.

            . . .
           An optional retry count of type int. If specified, the
           retry count indicates the number of times the operation
           is attempted (which will be at least once, even if the
           count argument is 0). If the operation cannot be performed
           successfully in the specified number of retries, a value
           of 0 is returned.

           A value of 1 is returned upon successful completion.

           Atomic Add Longword (__ATOMIC_ADD_LONG)

           The __ATOMIC_ADD_LONG function adds the specified
           expression to the aligned longword pointed to by the
           address parameter within a load-locked/store-conditional
           code sequence and returns the value of the longword before
           the addition was performed.

           This function has one of the following formats:

           int  __ATOMIC_ADD_LONG (volatile void *address, int
     expression);

           int  __ATOMIC_ADD_LONG_RETRY (volatile void *address, int
           expression, int retry, int *status);

           address
           The longword-aligned address of the data segment.

           expression
           An integer expression.

           retry
           A retry count of type int that indicates the number
           of times the operation is attempted (which is at least
           once, even if the retry argument is 0). If the operation
           cannot be performed successfully in the specified number
           of retries, the function returns without updating the
           longword.

     B-10 Built-In Functions

 



                                                      Built-In Functions


              status
              A pointer to an integer that is set to 0 if the operation
              did not succeed within the specified number of retries,
              and set to 1 if the operation succeeded.

              Atomic Add Quadword (__ATOMIC_ADD_QUAD)

              The __ATOMIC_ADD_QUAD function adds the specified
              expression to the aligned quadword pointed to by the
              address parameter within a load-locked/store-conditional
              code sequence and returns the value of the quadword before
              the addition was performed.

              This function has one of the following formats:

              int  __ATOMIC_ADD_QUAD (volatile void *address, int
        expression);

              int  __ATOMIC_ADD_QUAD_RETRY (volatile void *address, int
              expression, int retry, int *status);

              address
              The quadword-aligned address of the data segment.

              expression
              An integer expression.

              retry
              A retry count of type int that indicates the number
              of times the operation is attempted (which is at least
              once, even if the retry argument is 0). If the operation
              cannot be performed successfully in the specified number
              of retries, the function returns without updating the
              quadword.

              status
              A pointer to an integer that is set to 0 if the operation
              did not succeed within the specified number of retries,
              and set to 1 if the operation succeeded.






                                                 Built-In Functions B-11

 



     Built-In Functions


           Atomic AND Longword (__ATOMIC_AND_LONG)

           The __ATOMIC_AND_LONG function performs a logical AND of
           the specified expression with the aligned longword pointed
           to by the address parameter within a load-locked/store-
           conditional code sequence and returns the value of the
           longword before the operation was performed.

           This function has one of the following formats:

           int  __ATOMIC_AND_LONG (volatile void *address, int
     expression);

           int  __ATOMIC_AND_LONG_RETRY (volatile void *address, int
           expression, int retry, int *status);

           address
           The longword-aligned address of the data segment.

           expression
           An integer expression.

           retry
           A retry count of type int that indicates the number
           of times the operation is attempted (which is at least
           once, even if the retry argument is 0). If the operation
           cannot be performed successfully in the specified number
           of retries, the function returns without updating the
           longword.

           status
           A pointer to an integer that is set to 0 if the operation
           did not succeed within the specified number of retries,
           and set to 1 if the operation succeeded.

           Atomic AND Quadword (__ATOMIC_AND_QUAD)

           The __ATOMIC_AND_QUAD function performs a logical AND of
           the specified expression with the aligned quadword pointed
           to by the address parameter within a load-locked/store-
           conditional code sequence and returns the value of the
           quadword before the operation was performed.



     B-12 Built-In Functions

 



                                                      Built-In Functions


              This function has one of the following formats:

              int  __ATOMIC_AND_QUAD (volatile void *address, int
        expression);

              int  __ATOMIC_AND_QUAD_RETRY (volatile void *address, int
              expression, int retry, int *status);

              address
              The quadword-aligned address of the data segment.

              expression
              An integer expression.

              retry
              A retry count of type int that indicates the number
              of times the operation is attempted (which is at least
              once, even if the retry argument is 0). If the operation
              cannot be performed successfully in the specified number
              of retries, the function returns without updating the
              quadword.

              status
              A pointer to an integer that is set to 0 if the operation
              did not succeed within the specified number of retries,
              and set to 1 if the operation succeeded.

              Atomic OR Longword (__ATOMIC_OR_LONG)

              The __ATOMIC_OR_LONG function performs a logical OR of
              the specified expression with the aligned longword pointed
              to by the address parameter within a load-locked/store-
              conditional code sequence and returns the value of the
              longword before the operation was performed.

              This function has one of the following formats:

              int  __ATOMIC_OR_LONG (volatile void *address, int
        expression);

              int  __ATOMIC_OR_LONG_RETRY (volatile void *address, int
              expression, int retry, int *status);



                                                 Built-In Functions B-13

 



     Built-In Functions


           address
           The longword-aligned address of the data segment.

           expression
           An integer expression.

           retry
           A retry count of type int that indicates the number
           of times the operation is attempted (which is at least
           once, even if the retry argument is 0). If the operation
           cannot be performed successfully in the specified number
           of retries, the function returns without updating the
           longword.

           status
           A pointer to an integer that is set to 0 if the operation
           did not succeed within the specified number of retries,
           and set to 1 if the operation succeeded.

           Atomic OR Quadword (__ATOMIC_OR_QUAD)

           The __ATOMIC_OR_QUAD function performs a logical OR of
           the specified expression with the aligned quadword pointed
           to by the address parameter within a load-locked/store-
           conditional code sequence and returns the value of the
           quadword before the operation was performed.

           This function has one of the following formats:

           int  __ATOMIC_OR_QUAD (volatile void *address, int
     expression);

           int  __ATOMIC_OR_QUAD_RETRY (volatile void *address, int
           expression, int retry, int *status);

           address
           The quadword-aligned address of the data segment.

           expression
           An integer expression.

           retry
           A retry count of type int that indicates the number
           of times the operation is attempted (which is at least
           once, even if the retry argument is 0). If the operation
           cannot be performed successfully in the specified number

     B-14 Built-In Functions

 



                                                      Built-In Functions


              of retries, the function returns without updating the
              quadword.

              status
              A pointer to an integer that is set to 0 if the operation
              did not succeed within the specified number of retries,
              and set to 1 if the operation succeeded.

              Atomic Increment Longword (__ATOMIC_INCREMENT_LONG)

              The __ATOMIC_INCREMENT_LONG function increments by 1
              the aligned longword pointed to by the address parameter
              within a load-locked/store-conditional code sequence and
              returns the value of the longword before the operation was
              performed.

              This function has the following format:

              int  __ATOMIC_INCREMENT_LONG (volatile void *address);

              address
              The longword-aligned address of the data segment.

              Atomic Increment Quadword (__ATOMIC_INCREMENT_QUAD)

              The __ATOMIC_INCREMENT_QUAD function increments by 1
              the aligned quadword pointed to by the address parameter
              within a load-locked/store-conditional code sequence and
              returns the value of the quadword before the operation was
              performed.

              This function has the following format:

              int  __ATOMIC_INCREMENT_QUAD (volatile void *address);

              address
              The quadword-aligned address of the data segment.

              Atomic Decrement Longword (__ATOMIC_DECREMENT_LONG)

              The __ATOMIC_DECREMENT_LONG function decrements by 1
              the aligned longword pointed to by the address parameter
              within a load-locked/store-conditional code sequence and
              returns the value of the longword before the operation was
              performed.

              This function has the following format:

              int  __ATOMIC_DECREMENT_LONG (volatile void *address);

                                                 Built-In Functions B-15

 



     Built-In Functions


           address
           The longword-aligned address of the data segment.

           Atomic Decrement Quadword (__ATOMIC_DECREMENT_QUAD)

           The __ATOMIC_DECREMENT_QUAD function decrements by 1
           the aligned quadword pointed to by the address parameter
           within a load-locked/store-conditional code sequence and
           returns the value of the quadword before the operation was
           performed.

           This function has the following format:

           int  __ATOMIC_DECREMENT_QUAD (volatile void *address);

           address
           The quadword-aligned address of the data segment.

           Atomic Exchange Longword (__ATOMIC_EXCH_LONG)

           The __ATOMIC_EXCH_LONG function stores the value of the
           specified expression into the aligned longword pointed
           to by the address parameter within a load-locked/store-
           conditional code sequence and returns the value of the
           longword before the operation was performed.

           This function has one of the following formats:

           int  __ATOMIC_EXCH_LONG (volatile void *address, int
     expression);

           int  __ATOMIC_EXCH_LONG_RETRY (volatile void *address,
           int expression, int retry, int *status);

           address
           The longword-aligned address of the data segment.

           expression
           An integer expression.

           retry
           A retry count of type int that indicates the number
           of times the operation is attempted (which is at least
           once, even if the retry argument is 0). If the operation
           cannot be performed successfully in the specified number
           of retries, the function returns without updating the
           longword.

     B-16 Built-In Functions

 



                                                      Built-In Functions


              status
              A pointer to an integer that is set to 0 if the operation
              did not succeed within the specified number of retries,
              and set to 1 if the operation succeeded.

              Atomic Exchange Quadword (__ATOMIC_EXCH_QUAD)

              The __ATOMIC_EXCH_QUAD function stores the value of the
              specified expression into the aligned quadword pointed
              to by the address parameter within a load-locked/store-
              conditional code sequence and returns the value of the
              quadword before the operation was performed.

              This function has one of the following formats:

              int  __ATOMIC_EXCH_QUAD (volatile void *address, int
        expression);

              int  __ATOMIC_EXCH_QUAD_RETRY (volatile void *address,
              int expression, int retry, int *status);

              address
              The quadword-aligned address of the data segment.

              expression
              An integer expression.

              retry
              A retry count of type int that indicates the number
              of times the operation is attempted (which is at least
              once, even if the retry argument is 0). If the operation
              cannot be performed successfully in the specified number
              of retries, the function returns without updating the
              quadword.

              status
              A pointer to an integer that is set to 0 if the operation
              did not succeed within the specified number of retries,
              and set to 1 if the operation succeeded.

              Allocate Bytes from Stack ( __ALLOCA)

              The __ALLOCA function allocates n bytes from the stack.

              This function has the following format:

              void  *__ALLOCA (unsigned int n);

                                                 Built-In Functions B-17

 



     Built-In Functions


           n
           The number of bytes to be allocated.

           A pointer to the allocated memory is returned.

           Single-Precision, Floating-Point Arithmetic Built-in
           Functions

           The following built-in functions provide single-precision,
           floating-point chopped arithmetic:

           __ADDF_   __ADDS_   __SUBF_   __SUBS_C
           C         C         C

           __MULF_   __MULS_   __DIVF_   __DIVS_C
           C         C         C

           They have the following format:

           float  __op{F,S}_C (float operand1, float operand2);

           Where op is one of ADD, SUB, MUL, DIV, and {F,S}
           represents VAX or IEEE floating-point arithmetic.

           The result of the arithmetic operation is returned.

           Double-Precision, Floating-Point Arithmetic Built-in
           Functions

           The following built-in functions provide double-precision,
           floating-point chopped arithmetic:

           __ADDG_   __ADDT_   __SUBG_   __SUBT_C
           C         C         C

           __MULG_   __MULT_   __DIVG_   __DIVT_C
           C         C         C

           They have the following format:

           double  __op{G,T}_C (double operand1, double operand2);

           Where op is one of ADD, SUB, MUL, DIV, and {G,T}
           represents VAX or IEEE floating-point arithmetic.

           The result of the arithmetic operation is returned.

     B-18 Built-In Functions

 



                                                      Built-In Functions


              Copy Sign Built-in Functions

              Built-in functions are provided to copy selected portions
              of single- and double-precision, floating-point numbers.

              These built-in functions have the following format:

              float   __CPYSF (float operand1, float operand2);
              double  __CPYS (double operand1, double operand2);

              float   __CPYSNF (float operand1, float operand2);
              double  __CPYSN (double operand1, double operand2);

              float   __CPYSEF (float operand1, float operand2);
              double  __CPYSE (double operand1, double operand2);

              The copy sign built-in functions (__CPYSF and __CPYS)
              fetch the sign bit in operand1, concatenate it with the
              exponent and fraction bits from operand2, and return the
              result.

              The copy sign negate built-in functions (__CPYSNF and
              __CPYSN) fetch the sign bit in operand1, complement it,
              concatenate it with the exponent and fraction bits from
              operand2, and return the result.

              The copy sign exponent built-in functions (__CPYSEF and
              __CPYSE) fetch the sign and exponent bits from operand1,
              concatenate them with the fraction bits from operand2, and
              return the result.

              Compare Store Longword ( __CMP_STORE_LONG)

              The __CMP_STORE_LONG function has the following format:

              int  __CMP_STORE_LONG (void *source, int old_value, int
        new_value, void *dest);

              This function compares the value pointed to by source with
              the longword old_value. If they are equal, the longword
              new_value is stored into the value pointed to by dest.

              The function returns 0 if the two values are unequal, and
              returns 1 if the two values are equal.

                                                 Built-In Functions B-19

 



     Built-In Functions


           Compare Store Quadword ( __CMP_STORE_QUAD)

           The __CMP_STORE_QUAD function has the following format:

           int  __CMP_STORE_QUAD (void *source, int64 old_value,
     int64 new_value, void *dest);

           This function compares the value pointed to by source with
           the quadword old_value. If they are equal, the quadword
           new_value is stored into the value pointed to by dest.

           The function returns 0 if the two values are unequal, and
           returns 1 if the two values are equal.

           Cosine ( __COS)

           The __COS built-in function is functionally equivalent
           to its counterpart, cos, in the standard header file
           <math.h>.

           Its format is also the same:

           #include <math.h>
           double  __COS (double x);

           x
           A radian value.

           This built-in function does, however, offer performance
           improvements because there is less call overhead
           associated with its use.

           If you include <math.h>, the built-in function is
           automatically used for all occurrences of cos. To disable
           the built-in function, use #undef cos.

           Convert G_Floating to F_Floating Chopped ( __CVTGF_C)

           The __CVTGF_C function converts a double-precision, VAX
           G_floating-point number to a single-precision, VAX F_
           floating-point number. This conversion chops to single-
           precision; then the 8-bit exponent range is checked for
           overflow or underflow.

           This function has the following format:

           float  __CVTGF_C (double operand);

     B-20 Built-In Functions

 



                                                      Built-In Functions


              operand
              A double-precision, VAX floating-point number.

              Convert G-Floating to Quadword ( __CVTGQ)

              The __CVTGQ function rounds a double-precision, VAX
              floating-point number to a 64-bit integer value and
              returns the result.

              This function has the following format:

              int64  __CVTGQ (double operand);

              operand
              A double-precision, VAX floating-point number.

              Convert IEEE T_Floating to IEEE S_Floating Chopped
              ( __CVTTS_C)

              The __CVTTS_C function converts a double-precision, IEEE
              T_floating-point number to a single-precision, IEEE S_
              floating-point number. This conversion chops to single-
              precision; then the 8-bit exponent range is checked for
              overflow or underflow.

              This function has the following format:

              float  __CVTTS_C (double operand);

              operand
              A double-precision, IEEE floating-point number.

              Convert IEEE T-Floating to Quadword ( __CVTTQ)

              The __CVTTQ function rounds a double-precision, IEEE-
              floating-point number to a 64-bit integer value and
              returns the result.

              This function has the following format:

              int64  __CVTTQ (double operand);

              operand
              A double-precision, IEEE T-floating-point number.

                                                 Built-In Functions B-21

 



     Built-In Functions


           Floating-Point Absolute Value ( __FABS)

           The __FABS built-in function is functionally equivalent
           to its counterpart, fabs, in the standard header file
           <math.h>.

           Its format is also the same:

           #include <math.h>
           double  __FABS (double x);

           x
           A floating-point number.

           This built-in function does, however, offer performance
           improvements because there is no call overhead associated
           with its use.

           If you include <math.h>, the built-in function is
           automatically used for all occurrences of fab. To disable
           the built-in function, use #undef fab.

           Longword Absolute Value ( __LABS)

           The __LABS built-in function is functionally equivalent
           to its counterpart, labs, in the standard header file
           <stdlib.h>.

           Its format is also the same:

           #include <stdlib.h>
           long int  __LABS (long int x);

           x
           An integer.

           This built-in function does, however, offer performance
           improvements because there is less call overhead
           associated with its use.

           If you include <stdlib.h>, the built-in function is
           automatically used for all occurrences of labs. To disable
           the built-in function, use #undef labs.


     B-22 Built-In Functions

 



                                                      Built-In Functions


              Memory Barrier ( __MB)

              The __MB function directs the compiler to generate a
              memory barrier instruction.

              This function has the following format:

              void  __MB (void);

              Memory Copy and Set Functions ( __MEMCPY, __MEMMOVE,
              __MEMSET)

              The __MEMCPY, __MEMMOVE, and __MEMSET  built-in functions
              are functionally equivalent to their counterparts in the
              standard header file <string.h>.

              Their format is also the same:

              #include <string.h>
              void  *__MEMCPY (void *s1, const void *s2, size_t size);
              void  *__MEMMOVE (void *s1, const void *s2, size_t size);
              void  *__MEMSET (void *s, int value, size_t size);

              These built-in functions do, however, offer performance
              improvements because there is less call overhead
              associated with their use.

              If you include <string.h>, the built-in functions are
              automatically used for all occurrences of memcpy, memmove,
              and memset. To disable the built-in functions, use #undef
              memcpy, #undef memmove, and #undef memset.

              Read Process Cycle Counter ( __RPCC)

              The __RPCC function reads the current process cycle
              counter.

              This function has the following format:

              int64  __RPCC (void);

              Sine ( __SIN)

              The __SIN built-in function is functionally equivalent to
              its counterpart in the standard header file <math.h>.

              Its format is also the same:

              #include <math.h>
              double  __SIN (double x);

                                                 Built-In Functions B-23

 



     Built-In Functions


           x
           A radian value.

           This built-in function does, however, offer performance
           improvements because there is less call overhead
           associated with its use.

           If you include <math.h>, the built-in function is used
           automatically for all occurrences of sin. To disable the
           built-in function, use #undef sin.

           Test for Bit Clear then Clear Bit Interlocked
           ( __TESTBITCCI)

           The __TESTBITCCI function performs the following
           operations in interlocked fashion:

           o  Returns the complement of the specified bit before
              being cleared

           o  Clears the bit

           This function has the following format:

           int  __TESTBITCCI (void *address, int position, ...);

           address
           The base address of the field.

           position
           The position within the field of the bit that you want
           cleared.

            . . .
           An optional retry count of type int. If specified, the
           retry count indicates the number of times the operation
           is attempted. If the operation cannot be performed
           successfully in the specified number of retries, a value
           of 0 is returned.

           Test for Bit Set then Set Bit Interlocked ( __TESTBITSSI)

           The __TESTBITSSI function performs the following
           operations in interlocked fashion:

           o  Returns the value of the specified bit before being set

           o  Sets the bit

     B-24 Built-In Functions

 



                                                      Built-In Functions


              This function has the following format:

              int  __TESTBITSSI (void *address, int position, ...);

              address
              The base address of the field.

              position
              The position within the field of the bit that you want
              set.

               . . .
              An optional retry count of type int. If specified, the
              retry count indicates the number of times the operation
              is attempted. If the operation cannot be performed
              successfully in the specified number of retries, a value
              of 0 is returned.

              Trap Barrier Instruction ( __TRAPB)

              The __TRAPB function allows software to guarantee that,
              in a pipeline implementation, all previous arithmetic
              instructions will be completed without incurring any
              arithmetic traps before any instructions after the TRAPB
              instruction are issued.

              This function has the following format:

              void  __TRAPB (void);

              Unsigned Quadword Multiply High ( __UMULH)

              The __UMULH function performs a quadword multiply high
              instruction.

              This function has the following format:

              uint64  __UMULH (uint64 operand1, uint64 operand2);

              operand1
              A 64-bit unsigned integer.

              operand2
              A 64-bit unsigned integer.

              The two operands are multiplied as unsigned integers to
              produce a 128-bit result. The high order 64-bits are
              returned. Note that uint64 is a typedef for the Compaq
              Tru64 UNIX and Linux Alpha data type unsigned  __int64.

                                                 Built-In Functions B-25

 



     Built-In Functions


           Other Builtins

           int64 _popcnt(unsigned long);
           Returns the number of "1" bits in the argument (0 to 64).
           For example, _popcnt(12) returns 2.

           int64 _poppar(unsigned long);
           Returns "1" if the number of "1" bits in the argument is
           odd; otherwise, returns "0". otherwise. For example: _
           poppar(12) returns 0.

           int64 _leadz(unsigned long);
           Returns the number of leading zeroes (starting at the most
           significant bit position) in the argument. For example,
           _leadz(1) returns 63. Note that _leadz(0) returns 64.

           int64 _trailz(unsigned long);
           Returns the number of trailing zeroes (counting after the
           least significant set bit to the least significant bit
           position) in the argument: For example, _trailz(2) returns
           1. Note that _trailz(0) returns 64.
























     B-26 Built-In Functions

 









                                                                       C
        ________________________________________________________________

                                                   Third Degree Messages



              This appendix describes Third Degree messages generated
              by the C++ Class and Standard Libraries. None of the
              following messages contribute to memory corruption
              in programs or cause memory depletion in long running
              applications.

              1. Third degree 576 byte leak and 16 byte leak messages
                 from __init_cxx_exc

                 When you instrument a Compaq C++ program with Third
                 degree, the tool might generate 576 byte leak and 16
                 byte leak messages like the following from the Class
                 Library routine __init_cxx_exe:

                 576 bytes in 1 leak created at:
                     malloc                         libc.so
                     pc = 0x3ff81d35c04             libcxx.so
                     pc = 0x3ff81d35e20             libcxx.so
                     __init_cxx_exc                 libcxx.so

                 16 bytes in 1 leak (including 1 super leak) created at:
                     malloc                         libc.so
                     pc = 0x3ff81d35c04             libcxx.so
                     pc = 0x3ff81d35ca4             libcxx.so
                     pc = 0x3ff81d35dfc             libcxx.so
                     __init_cxx_exc                 libcxx.so

                 A program like the following would generate the
                 previous messages:

                 int main () {return 0;}

                 These two leaks are generated by the C++ exception
                 handling code. This storage is memory allocated to
                 process exception handling during program startup
                 and is deleted by the operating system when the
                 program exits. Third degree reports a leak because

                                               Third Degree Messages C-1

 



     Third Degree Messages


              the operating system, rather than C++ code, deletes the
              storage. The operating system deletes this storage for
              these reasons:

              o  The compiler does not slow down exit for all C++
                 programs.

              o  After the program terminates, the compiler verifies
                 that no additional C++ exceptions need handling.

           2. Third degree 8/24/48 byte leak messages from __init_
              cxx_exc

              When you instrument a Compaq C++ program with Third
              degree, the tool might generate four 8, four 24, and
              four 48 byte leak messages like the following from the
              Class Library routine __init_cxx_exe:

              48 bytes in 1 leak created at:
                  malloc                         libc.so
                  __cma_tis_mutex_create         libc.so
                  AllocateInternalMutex(void)    libcxx.so
                  Mutex::Mutex(void)             libcxx.so
                  Iostream_init::initialize(void) libcxx.so
                  Iostream_init::Iostream_init(void) libcxx.so
                  __init_cxxl_init142DB80C       libcxx.so

              24 bytes in 1 leak created at:
                  operator new(unsigned long)    libcxx.so
                  AllocateInternalMutex(void)    libcxx.so
                  Mutex::Mutex(void)             libcxx.so
                  Iostream_init::initialize(void) libcxx.so
                  Iostream_init::Iostream_init(void) libcxx.so
                  __init_cxxl_init142DB80C       libcxx.so

              8 bytes in 1 leak (including 1 super leak) created at:
                  operator new(unsigned long)    libcxx.so
                  Iostream_init::initialize(void) libcxx.so
                  Iostream_init::Iostream_init(void) libcxx.so
                  __init_cxxl_init142DB80C       libcxx.so

              A program like the following would generate the
              previous messages:

              int main () {return 0;}

     C-2 Third Degree Messages

 



                                                   Third Degree Messages


                 The messages originate from the creation of Class
                 Library Iostream mutexes for cin, cout, clog, and cerr,
                 which are created at program startup. The operating
                 system cleans up the memory rather than deleting it at
                 program exit from C++.

              3. Additional Third degree 48/24 byte leak messages from
                 __init_cxx_exc

                 When you instrument a Compaq C++ program with Third
                 degree, the tool might generate an additional 24 and 48
                 byte leak messages like the following from the Class
                 Library routine __init_cxx_exe:

                 48 bytes in 1 leak created at:
                     malloc                         libc.so
                     __cma_tis_mutex_create         libc.so
                     AllocateInternalMutex(void)    libcxx.so
                     Mutex::Mutex(void)             libcxx.so
                     Iostream_init::Iostream_init(void) libcxx.so
                     __init_cxxl_init142DB80C       libcxx.so

                 24 bytes in 1 leak created at:
                     operator new(unsigned long)    libcxx.so
                     AllocateInternalMutex(void)    libcxx.so
                     Mutex::Mutex(void)             libcxx.so
                     Iostream_init::Iostream_init(void) libcxx.so
                     __init_cxxl_init142DB80C       libcxx.so

                 A program like the following would generate the
                 previous messages:

                 int main () {return 0;}

                 The messages also come from a mutex used in Iostream
                 locking; they are created at program startup and are
                 cleaned up by the operating system rather than being
                 deleting at program exit by C++.

              4. Third degree 48 byte leak messages from __init_cxxl_
                 initxxxxxxxx

                 When you instrument a Compaq C++ program with Third
                 degree, the tool might generate an additional 48 byte
                 leak message like the following from the Class Library
                 routine __init_cxxl_initxxxxxxxx:

                                               Third Degree Messages C-3

 



     Third Degree Messages


              48 bytes in 1 leak (including 1 super leak) created at:
                  malloc                         libc.so
                  __cma_tis_mutex_create         libc.so
                  pc = 0x3ff81d3a46c             libcxx.so
                  __cma_tis_once                 libc.so
                  __cxx_test_and_set_atomic      libcxx.so
                  __init_cxxl_init142DB80C       libcxx.so

              A program like the following would generate the
              previous message:

              int main () {return 0;}

              This message comes from the mutex used to initialize
              the Class Library; the mutex is created at program
              startup and is deleted by the operating system rather
              than by C++ code at program exit.

           5. Third degree fon warning message from __init_cxx_exe

              When you instrument a C++ program with Third degree,
              the tool might generate a fon warning like the
              following from the C++ Class Library routine __init_
              cxx_exe:

              ------------------------------------------------ fon -- 0 --
              calling free(0)
                  free                           fon
                  pc = 0x120068090               fon
                  __init_cxx_exc                 fon

              --------------------------------------------------------------

              A program like the following would generate the
              previous message:

              int main () {return 0;}

              The message, freeing a NULL pointer, is only a warning.
              In this case, the library does in fact free a NULL
              pointer, but this is valid behavior. You can ignore the
              message.

           6. Third degree wis error from __vec_new_eh

     C-4 Third Degree Messages

 



                                                   Third Degree Messages


                 When you instrument a C++ program with Third degree,
                 the tool might generate a wis error like the following
                 from the C++ Standard Library routine __vec_new_eh:

                 ------------------------------------------------ wis -- 1 --
                 wis.cxx: 5: writing invalid stack at byte 64 of 64 in frame of
                 array_new_general
                 (void*, int, unsigned long, void*, void (*)(void*, int), void*
                 (*)(unsigned long),
                 void (*)(void*), int, int, unsigned int)
                 array_new_general(void*, int, unsigned long, void*, void (*)(void*,
                 int), void*
                 (*)(unsigned long), void (*)(void*), int, int, unsigned int)
                                                    wis
                     __vec_new_eh                   wis

                 --------------------------------------------------------------

                 A program like the following would generate the
                 previous message:

                 struct C {C() {};};
                 int main () {
                     C* pc = new C[5];
                     delete []pc;
                     return 0;
                     }

                 Programs using global array new can generate the
                 message when Third degree encounters a special
                 scheduling instruction. This false positive message
                 has been reported to Third degree.

              7. Third degree rin error message

                 The following error message is generated in programs
                 that use exception handling in the Class Library.
                 This false positive message has been reported to Third
                 degree.

                 rin.c: 7: reading invalid stack at byte 656 of 656 in frame of main
                     proc_at_0x12000e350            rin
                     __exc_virtual_unwind           rin
                     exc_virtual_unwind             rin
                     main                           rin, rin.c, line 7
                     __start                        rin

                                               Third Degree Messages C-5

 



     Third Degree Messages


           8. Third degree might report false positive uninitiated
              memory errors

              As of Atom 2.47, Third degree might report false
              positive uninitiated memory errors where variables
              of less than 32 bits are involved. Note that bool data
              types, which the Standard Library uses extensively,
              fall into this category.

              For example, when you instrument a C++ program with
              Third degree, the tool might generate a rus error with
              Atom version 2.47 in the STL map class. The error would
              be generated by a program like the following:

              #include <map>
              main() {
                  map <int, int> the_test_map;
                  the_test_map[1] = 1;
                  the_test_map[2] = 2;
              }

              The following is an example of a small, self-contained
              program (reduced from the above program) that generates
              the same error.

              struct tree
              {
                  bool       b;
                  void init () {;}
                  tree(const int i = 3, bool b = true) : b(b)
                  {
                    init();
                  }
              };
              void main() {
                   tree t;
              }








     C-6 Third Degree Messages

 













     ________________________________________________________________

                                                                Index


     A                                    Arguments
     ___________________________           mechanisms for passing,
     __ABS built-in function,                 2-24
        B-7                               asm intrinsic function,
     Access                                 B-1
       member, 4-9                        ASMs, B-1
     __ADAWI built-in function,           assign debugger command,
        B-7                                 9-14
     __ADDF_C built-in function,          Assignment
        B-18                               to the this pointer,  4-15
     __ADDG_C built-in function,          __ATOMIC_ADD_LONG built-in
        B-18                                function,  B-10
     Additive operators,  2-27            __ATOMIC_ADD_QUAD built-in
     __ADDS_C built-in function,            function,  B-11
        B-18                              __ATOMIC_AND_LONG built-in
     __ADDT_C built-in function,            function,  B-12
        B-18                              __ATOMIC_AND_QUAD built-in
     __ADD_ATOMIC_LONG built-in             function,  B-12
        function, B-8                     __ATOMIC_DECREMENT_LONG
     __ADD_ATOMIC_QUAD built-in             built-in function,  B-15
        function, B-8                     __ATOMIC_DECREMENT_QUAD
     __ALLOCA built-in function,            built-in function,  B-16
        B-17                              __ATOMIC_EXCH_LONG built-in
     __AND_ATOMIC_LONG built-in             function,  B-16
        function, B-9                     __ATOMIC_EXCH_QUAD built-in
     __AND_ATOMIC_QUAD built-in             function,  B-17
        function, B-9                     __ATOMIC_INCREMENT_LONG
     Application                            built-in function,  B-15
       deploying, 1-7                     __ATOMIC_INCREMENT_QUAD
     Applications                           built-in function,  B-15
       mixed-language, 8-4



                                                              Index-1

 






     __ATOMIC_OR_LONG built-in            Built-in functions (cont'd)
        function, B-13                     __ATOMIC_INCREMENT_LONG,
     __ATOMIC_OR_QUAD built-in                B-15
        function, B-14                     __ATOMIC_INCREMENT_QUAD,

                                              B-15
     B__________________________           __ATOMIC_OR_LONG,  B-13

     Base class initializers,              __ATOMIC_OR_QUAD,  B-14
        4-9                                __CMP_STORE_LONG,  B-19
     64-bit coding guidelines,             __CMP_STORE_QUAD,  B-20
        4-18                               Copy sign functions,  B-19
     bptr pointer,  9-40                   __COS,  B-20
     Breakpoints                           __CPYS,  B-19
       in C++ exception handlers           __CPYSE,  B-19
         ,  9-36                           __CPYSEF,  B-19
       in constructors and                 __CPYSF,  B-19
         destructors,  9-26                __CPYSN,  B-19
       in overloaded functions,            __CPYSNF,  B-19
         9-22                              __CVTGF_C,  B-20
       in templates, 9-31                  __CVTGQ,  B-21
     Buffer, output                        __CVTTQ,  B-21
       flushing, 4-15                      __CVTTS_C,  B-21
     Built-in functions,  B-1 to           __DIVF_C,  B-18
                                           __DIVG_C,  B-18
        B-26                               __DIVS_C,  B-18
       __ABS,  B-7                         __DIVT_C,  B-18
       __ADAWI,  B-7                       Double-precision,
       __ADDF_C,  B-18                        floating-point
       __ADDG_C,  B-18                        arithmetic,  B-18
       __ADDS_C,  B-18                     __FABS,  B-22
       __ADDT_C,  B-18                     __LABS,  B-22
       __ADD_ATOMIC_LONG,  B-8             _leadz,  B-26
       __ADD_ATOMIC_QUAD,  B-8             __MB,  B-23
       __ALLOCA,  B-17                     __MEMCPY,  B-23
       __AND_ATOMIC_LONG,  B-9             __MEMMOVE,  B-23
       __AND_ATOMIC_QUAD,  B-9             __MEMSET,  B-23
       __ATOMIC_ADD_LONG,  B-10            __MULF_C,  B-18
       __ATOMIC_ADD_QUAD,  B-11            __MULG_C,  B-18
       __ATOMIC_AND_LONG,  B-12            __MULS_C,  B-18
       __ATOMIC_AND_QUAD,  B-12            __MULT_C,  B-18
       __ATOMIC_DECREMENT_LONG,            PALcodes,  B-5 to B-7
         B-15                              __PAL_BPT,  B-6
       __ATOMIC_DECREMENT_QUAD,            __PAL_BUGCHK,  B-6
         B-16                              __PAL_DRAINA,  B-6
       __ATOMIC_EXCH_LONG,  B-16           __PAL_GENTRAP,  B-6
       __ATOMIC_EXCH_QUAD,  B-17           __PAL_HALT,  B-7

     Index-2

 






        Built-in functions (cont'd)         __CMP_STORE_LONG  built-in
         _popcnt,  B-26                        function, B-19
         _poppar,  B-26                     __CMP_STORE_QUAD  built-in
         __RPCC,  B-23                         function, B-20
         __SIN,  B-23                       Coding recommendations,
         Single-precision,                     8-3
            floating-point                  Common instantiation
            arithmetic,  B-18                  library
         __SUBF_C,  B-18                      creating,  5-17
         __SUBG_C,  B-18                    __COMPAQ_CXX_VER__
         __SUBS_C,  B-18                       predefined macro, 2-21
         __SUBT_C,  B-18                    Compatibility,  3-14
         __TESTBITCCI,  B-24                Compatibility macros,  2-20
         __TESTBITSSI,  B-24                Compiler,  1-1
         _trailz,  B-26                       cxx command,  1-1
         __TRAPB,  B-25                          -nocleanup option,  8-3
         __UMULH,  B-25                          -std ansi option,  4-1
                                                 -std arm option,  4-1
        C__________________________              -std cfront option,
        C++ predefined function                     4-3
         terminate,  9-37                        -std gnu option,  4-3
         unexpected,  9-37                       -std ms option,  4-3
        call debugger command,                   -std strict_ansi
          9-27                                      option, 4-3
        cfront                                   -std strict_ansi_
         porting to Compaq C++                      errors option, 4-4
            from,  4-1 to 4-17                mixed pointer size
        Class                                    options, 3-9
         friend declarations,  4-8            template
         function definitions,                   advanced program
            4-10                                    development, 5-15
         implementation details,                 automatic
            4-8 to 4-9                              instantiation, 5-2
         initializer,  4-9                       compatibility with
         library packages,  1-5                     earlier versions,
         member access,  4-9                        5-24
         pointer conversions,  4-11              creating common
        class debugger command,                     instantiation
          9-5                                       library, 5-17
        Class Library, 1-5                       creating libraries,
         Third Degree Messages,                     5-16
            C-1                                  dependency management,
                                                    5-15


                                                                 Index-3

 






     Compiler                             __CPYSF built-in function,
       template (cont'd)                    B-19
          implicit inclusion,             __CPYSN built-in function,
            5-4                             B-19
          linking Version                 __CPYSNF built-in function,
            5.n applications                B-19
            against Version 6.n           __CVTGF_C built-in function
            repositories,  5-26             ,  B-20
          linking with Version            __CVTGQ built-in function,
            5.n instantiations,             B-21
            5-25                          __CVTTQ built-in function,
          mixing automatic and              B-21
            manual instantiation          __CVTTS_C built-in function
            ,  5-15                         ,  B-21
          overview, 5-1                   cxx compiler command, 1-1
          repositories, 5-20              /cxx_repository directory,
       template instantiation               5-2
         options,  5-21                   /cxx_repository
     Constant                               instantiation file,  5-2
       in function returns, 4-11          <c_asm.h> header file, B-1

       pointer to, 4-12
     Constructors and                     D__________________________

        Destructors, setting              dasm intrinsic function,
        breakpoints in, 9-26                B-1
     Conversion                           Debugger, assignments
       explicit type, 2-26                  allowed by,  9-14
       floating-point number,             Debugger commands
         2-25                              assign,  9-14
       integer, 2-25                       call,  9-27
       pointer, 4-11                       class,  9-5
     Copy sign built-in                    displaying class
        functions, B-19                       information,  9-7
     __COS built-in function,              print
        B-20                                  displaying base
     __CPYS built-in function,                   pointer information,
        B-19                                     9-40
     __CPYSE built-in function,            stop in,  9-19, 9-21, 9-26
        B-19                               whatis,  9-7, 9-17, 9-31,
     __CPYSEF built-in function,              9-38
        B-19                              Debugging, 1-5, 9-2 to
                                            9-46
                                           absolute and relative
                                              path names,  9-3

     Index-4

 






        Debugging (cont'd)                  Directive
         class and function scope,            #pragma define_template,
            9-6                                  2-2
         class and function                   #pragma environment,  2-3
            templates,  9-31                  #pragma ident,  2-5
         displaying type signature            #pragma instantiate,  2-2
            ,  9-7                            #pragma message,  2-8
         examining data members,              #pragma module,  2-10
            9-5                               #pragma once,  2-10
         examining inlined member             #pragma pack,  2-11
            functiona,  9-14                  #pragma pointer_size,
         exception handler support               2-13, 3-10
            ,  9-36                           #pragma required_pointer_
         member functions on stack               size, 3-10
            trace,  9-15                      #pragma required_vptr_
         mixed C and C++ programs,               size, 2-14, 3-10
            9-4                               #pragma [no]inline,  2-6
         resolving ambiguous                  #pragma [no]member_
            references,  9-15                    alignment, 2-6
         resolving references to              #pragma [no]standard,
            objects,  9-12                       2-15
         setting breakpoints in             __DIVF_C  built-in function,
            member functions,  9-19            B-18
         setting class scope,  9-5          __DIVG_C  built-in function,
         setting language mode,                B-18
            9-4                             Division operator,  2-27
         type casting,  9-28                __DIVS_C  built-in function,
         type transfer,  9-30                  B-18
         verbose mode,  9-38                __DIVT_C  built-in function,
        __DECCXX_VER predefined                B-18
          macro,  2-21                      Double-precision, floating-
        Declarations                           point arithmetic built-
         friend,  4-8                          in functions, B-18

        define_template pragma,
          2-2                               E__________________________

        delete operator                     Enumerated types
         size-of-array argument               incrementing,  4-17
            to,  4-15                       environment pragma,  2-3
        demangle command, 1-3 to            Equality operators,  2-27
          1-4                               Error message
        Dialect macro, 2-20                   missing parenthesis,  4-16


                                                                 Index-5

 






     Exception handling,  2-32,
        8-1                               G__________________________
       catching signals and C             goto statement, 4-13
         excpetions,  8-5                 Guiding declarations, 2-36
       finding information, 8-4
       structure for, 8-1 to 8-2          H__________________________
       threads, 8-6                       Header file
     Explicit type conversion,             protecting,  2-15
        2-26                              Header files
     Explicit type conversion,             <float.h>,  2-23
        language extension, 2-26           <limits.h>,  2-23
     Extended Truncated Address            modifying,  3-1 to 3-3
        Support Option (XTASO),            <stdarg.h>,  3-2
        3-9                                <stdio.h>,  4-18
     Extensions                            using existing,  3-1
       source file, 4-17                   <varargs.h>,  3-2
     extern specifier,  3-1

     F                                    I__________________________
     ___________________________          Identifiers, 2-24
     __FABS built-in function,            ident pragma, 2-5
        B-22                              #ifdef preprocessor
     fasm intrinsic function,               directive,  4-14
        B-1                               Implementation extensions,
     Faults                                 2-24 to 2-25
       segmentation, 4-16                 Implementation features,
     File inclusion directive,              2-24 to 2-25
        #include, 2-33 to 2-34            #include directive, 2-33
     <float.h> header file,                 to 2-34
        2-23                              Inheritance, 9-29
     Floating-point arithmetic            Initializers
        built-in functions, B-18           using base class name
     Floating-point number                    with,  4-9
       converting to and from an          Initializing references,
         integer,  2-25                     4-12
     Friend declarations,  4-8            In-line assembly code
     Function                               (ASMs),  B-1
       constant in returns, 4-11          inline pragma, 2-6
       definitions, 4-10                  instantiate pragma, 2-2
     Function returns                     Instantiation
       constants in, 4-11                  automatic
     Functions,  4-10                         linking with,  5-6

                                           directives,  5-9

     Index-6

 






        Instantiation                       Linkage specifications,
         directives (cont'd)                   3-4
            #pragma define_                 Link compatibility,  3-15
               template,  5-9               Linker,  1-2

            #pragma do_not_
               instantiate,  5-13           M__________________________

            #pragma instantiate,            Macro names
               5-13                           predefined,  2-17
         manual,  5-8                       Macros
         mixed automatic and                  <stdarg.h>,  3-2
            manual,  5-15                     <varargs.h>,  3-2
         template,  5-1 to 5-26             __MB  built-in function,
        Instantiation file, 5-2 to             B-23
          5-6                               Member access,  4-9
        Integer                             __MEMCPY  built-in function,
         converting to and from a              B-23
            floating-point number,          __MEMMOVE  built-in function
            2-25                               , B-23
        Integral conversions, 2-25          Memory management,  4-15
        Intrinsic functions                 __MEMSET  built-in function,
         ASMs,  B-1                            B-23
                                            Message control option,
        K__________________________            2-37, 2-38
        Keywords                            Missing parenthesis error
         conflict resolution,  3-2             message, 4-16
                                            Mixed-Language applications
        L                                      , 8-4
        ___________________________         Mixed-language programs,
        __LABS built-in function,              debugging, 9-4
          B-22                              __MULF_C  built-in function,
        Ladebug debugger, 9-2 to               B-18
          9-46                              __MULG_C  built-in function,
        Language mode, setting for             B-18
          debugging,  9-4                   __MULS_C  built-in function,
        $lang variable, 9-4                    B-18
        ld linker command, 1-2              Multiplicative operators,
        Limits                                 2-27
         numerical,  2-23                   __MULT_C  built-in function,
         translation,  2-23                    B-18
        <limits.h> header file,
          2-23
        Linkage
         between C and C++,  3-1
         specification,  2-31, 3-4

                                                                 Index-7

 






                                          __PAL_HALT built-in
     N__________________________            function,  B-7

     Name demangling,  1-2                PCH file

     Nested enums,  2-34                   See Precompiled header
     noinline pragma,  2-6                    file
     Non-C++ code, access to,             Pointer, 4-11
        3-4                                bound to member function,
     [no]standard pragma,  2-15               4-11
     Numerical limits,  2-23               conversions,  4-11

                                           mixing 32-bit and 64-bit
     O__________________________              sizes,  3-9
     Object                                to constants,  4-12
       temporary, 2-31                    pointer_size pragma, 2-13,
       volatile, 4-14                       3-10
     once pragma,  2-10                   Porting
     Operators                             from cfront to Compaq
       additive, 2-27                         C++,  4-1 to 4-17
       delete, 4-15                       Pragma
       division, 2-27                      See also Preprocessor
       equality, 2-27                         directive
       multiplicative, 2-27                define_template,  2-2
       remainder, 2-27                     environment,  2-3
       shift, 2-27                         ident,  2-5
       sizeof, 2-26                        inline,  2-6
     Output buffer                         instantiate,  2-2
       flushing, 4-15                      [no]standard,  2-15
     $overloadmenu variable,               once,  2-10
        9-15                               pack,  2-11
                                           pointer_size,  2-13, 3-10
     P__________________________           #pragma message,  2-8
     pack pragma,  2-11                    #pragma module,  2-10
     PALcode built-in functions,           #pragma [no]member_
        B-5 to B-7                            alignment,  2-6
     __PAL_BPT built-in function           required_pointer_size,
        , B-6                                 3-10
     __PAL_BUGCHK built-in                 required_vptr_size,  2-14,
        function, B-6                         3-10
     __PAL_DRAINA built-in                #pragma ident preprocessor
        function, B-6                       directive,  2-5

     __PAL_GENTRAP built-in
        function, B-6

     Index-8

 






        #pragma intrinsic                   Protecting header files,
          preprocessor directive,              2-15
          B-1
        #pragma once preprocessor           R__________________________
          directive,  2-10                  Reader's comments, sending,
        #pragma pack preprocessor              xv
          directive,  2-11                  References
        #pragma [no]inline                    initializing,  4-12
          preprocessor directive,           Remainder operator,  2-27
          2-6                               required_pointer_size
        Precompiled header file,               pragma, 3-10
          6-1 to 6-9                        required_vptr_size pragma,
         automatic processing,  6-2            2-14, 3-10
         controlling,  6-7                  Return mechanisms,  2-24
         manual processing,  6-6            __RPCC  built-in function,
         options,  6-8                         B-23
         performance issues,  6-7           Run compatibility,  3-17
        Predefined macro, __COMPAQ_
          CXX_VER__,  2-21                  S__________________________
        Predefined macro, __DECCXX_         Segmentation faults,  4-16
          VER,  2-21                        Shift operators,  2-27
        Predefined macro,                   Signal
          compatibility,  2-20                exception handling,  8-5
        Predefined macro, dialect,          __SIN  built-in function,
          2-20                                 B-23
        Predefined macro names,             Single-precision, floating-
          2-17                                 point arithmetic built-
        Preprocessor directive                 in functions, B-18
         #ifdef,  4-14                      Size-of-array argument
         #pragma,  2-1 to 2-15                to delete operator,  4-15
        Preprocessor directives             sizeof operator,  2-26
         #pragma intrinsic,  B-1            Source compatibility,  3-15
        print debugger command              Source file extensions,
         displaying base pointer               4-17
            information,  9-40              Specification
         displaying class                     linkage,  2-31, 3-4
            information,  9-7               Specifiers
        Printing base pointer                 extern,  3-1
          information,  9-40                  type,  2-28, 2-30
        Product support, xv                   typedef,  4-12
        Programs                            Standard Library,  1-4
         compiling,  1-1                      building programs with,
         linking,  1-2                           7-11


                                                                 Index-9

 






     Standard Library (cont'd)            __SUBF_C built-in function,
       compatibility issues, 7-3            B-18
         to 7-11                          __SUBG_C built-in function,
          global array new and              B-18
            delete,  7-10                 __SUBS_C built-in function,
          -[no]using_std                    B-18
            compatibility switch          __SUBT_C built-in function,
            ,  7-3                          B-18
          overriding                      switch statement, 4-13

            operator(new),  7-7
          pre-ANSI/ANSI                   T__________________________

            IOStreams                     Template instantiation,
            compatibility,  7-3             5-1 to 5-26
          pre-ANSI and ANSI               Templates
            operator(new),  7-6            debugging limitations,
       Third Degree Messages,                 9-36
         C-1                              Temporary objects, 2-31
     Standard Template Library            terminate C++ predefined
       building programs with,              function,  9-37
         7-11                             __TESTBITCCI built-in
     Statement                              function,  B-24
       goto, 4-13                         __TESTBITSSI built-in
       switch, 4-13                         function,  B-24
     Static object                        Third Degree
        initialization                     C++ Class and Standard
       order of, 2-25                         Library Messages,  C-1
     -std ansi mode,  4-1                 this pointer, 9-9, 9-15,
     <stdarg.h> header file,                9-21, 9-42
        3-2                               this pointer
     -std arm mode,  4-1                   assignment to,  4-15
     <stdio.h> header file,                system default size,  3-11
        4-18                              Thread safety, 7-11
     stop in debugger command,            Translation limits, 2-23
        9-19, 9-21, 9-26                  __TRAPB built-in function,
     -strict_ansi mode,  4-1                B-25
     -strict_ansi_errors mode,            Type conversion
        4-1                                explicit,  2-26
     String Library                       typedef specifier, 4-12
       building programs with,            Type specifier
         7-11                              __unaligned,  2-30
                                           volatile,  2-28


     Index-10

 






                                            Variable-length argument
        U__________________________            list, 3-2
        __UMULH built-in function,          $verbose variable,  9-38
          B-25                              Volatile object,  4-14
        __unaligned type specifier,         volatile type specifier,
          2-30                                 2-28

        unexpected C++ predefined           W
          function,  9-37                   ___________________________
                                            whatis debugger command,
        V__________________________            9-7, 9-17, 9-31, 9-38

        <varargs.h> header file,            X
          3-2                               ___________________________
        Variable                            XTASO
         declared on for statement            See Extended Truncated
            ,  4-17                              Address Support Option




























                                                                Index-11
