HP Version 7.1, Version 6.5 C++ User guide
PDF
Dokument
Reklama
Reklama
HP C++
Using HP C++ for Tru64 UNIX and
Linux Alpha
August 2005
This manual contains information about developing HP C++ programs on
HP Tru64 UNIX and Linux Alpha systems.
Software Version:
HP C++ Version 7.1 for Tru64 UNIX
HP C++ Version 6.5 for Linux Alpha
Hewlett-Packard Company Palo Alto, California
© Copyright 2005 Hewlett-Packard Development Company, L.P.
Confidential computer software. Valid license from HP 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.
The information contained herein is subject to change without notice. The only warranties
for HP products and services are set forth in the express warranty statements accompanying
such products and services. Nothing herein should be construed as constituting an additional
warranty. HP shall not be liable for technical or editorial errors or omissions contained herein.
Intel and Itanium are trademarks or registered trademarks of Intel Corporation or its
subsidiaries in the United States and other countries.
UNIX is a registered trademark of The Open Group.
X/Open is a registered trademark of X/Open Company Ltd. in the UK and other countries.
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-2002 Rogue Wave Software, Inc.
Printed in the US
Confidential computer software. Valid license from HP and/or its subsidiaries 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 vendors standard commercial license.
Neither HP nor any of its subsidiaries shall be liable for technical or editorial errors or
omissions contained herein. The information is provided ‘‘as is’’ without warranty of any kind
and is subject to change without notice. The warranties for HP products are set forth in the
express limited warranty statements accompanying such products. Nothing herein should be
construed as constituting an additional warranty.
This document is available on CD–ROM.
This document was prepared using DECdocument, Version 3.3-1n.
Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
xi
1 Building and Running C++ Programs
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1–1
1–2
1–2
1–3
1–4
1–5
1–5
1–5
1–6
1–6
1–6
1–6
1–6
1–8
1–8
1–9
2.1
Implementation-Specific Attributes . . . . . . . . . . . .
2.1.1
#pragma Preprocessor Directive . . . . . . . . . . . .
2.1.1.1
#pragma define_template Directive . . . . . .
2.1.1.2
#pragma instantiate Directive . . . . . . . . . .
2.1.1.3
#pragma environment Directive . . . . . . . . .
2.1.1.4
#pragma extern_prefix Directive . . . . . . . .
2.1.1.5
#pragma ident Directive . . . . . . . . . . . . . . .
2.1.1.6
#pragma [no]inline Directive . . . . . . . . . . .
2.1.1.7
#pragma intrinsic Directive . . . . . . . . . . . .
2.1.1.8
#pragma [no]member_alignment Directive .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2–1
2–1
2–2
2–2
2–2
2–4
2–4
2–5
2–5
2–6
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.8.1
1.8.2
1.8.3
1.8.4
1.9
1.9.1
1.9.2
1.10
Compiling a Program . . . . . . . . . . . . . . . . . . . . . .
Linking a Program . . . . . . . . . . . . . . . . . . . . . . . .
Name Demangling . . . . . . . . . . . . . . . . . . . . . . . .
C++ Standard Library . . . . . . . . . . . . . . . . . . . . .
C++ Class Library . . . . . . . . . . . . . . . . . . . . . . . .
Linking With Non-Default Libraries . . . . . . . . . .
Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Improving Build Performance . . . . . . . . . . . . . . .
Object File Compression [Tru64] . . . . . . . . . .
Using Shared Libraries . . . . . . . . . . . . . . . . .
Using Precompiled Headers . . . . . . . . . . . . . .
Performance Optimization Options . . . . . . . .
Deploying Your Application [Tru64] . . . . . . . . . . .
Redistributing the C++ Run-Time Library . . .
Instructions for Installing Redistribution Kit .
Using OpenMP . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 HP C++ Implementation
iii
2.1.1.9
#pragma message Directive . . . . . . . . . . . . . . . . . . . . .
2.1.1.10
#pragma module Directive . . . . . . . . . . . . . . . . . . . . . . .
2.1.1.11
#pragma once Directive . . . . . . . . . . . . . . . . . . . . . . . . .
2.1.1.12
#pragma pack Directive . . . . . . . . . . . . . . . . . . . . . . . . .
2.1.1.13
#pragma pointer_size Directive [Tru64] . . . . . . . . . . . . .
2.1.1.14
#pragma required_pointer_size Directive [Tru64] . . . . .
2.1.1.15
#pragma required_vptr_size Directive [Tru64] . . . . . . . .
2.1.1.16
#pragma [no]standard Directive . . . . . . . . . . . . . . . . . . .
2.1.1.17
#pragma weak Directive . . . . . . . . . . . . . . . . . . . . . . . .
2.1.2
Protecting System Header Files . . . . . . . . . . . . . . . . . . . . . .
2.1.2.1
Using the Compiler’s Header File Protection Option . . .
2.1.2.2
Modifying Each Header File . . . . . . . . . . . . . . . . . . . . .
2.1.3
Predefined Macro Names . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1.4
Translation Limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1.5
Numerical Limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1.6
Argument-Passing and Return Mechanisms . . . . . . . . . . . .
2.2
Implementation Extensions and Features . . . . . . . . . . . . . . . . .
2.2.1
Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.1.1
Character Limit for Long Names . . . . . . . . . . . . . . . . . .
2.2.2
Order of Static Object Initialization . . . . . . . . . . . . . . . . . . .
2.2.3
Integral Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.4
Floating-Point Conversions . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.5
Explicit Type Conversion . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.6
The sizeof Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.7
Explicit Type Conversion . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.8
Multiplicative Operators . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.9
Additive Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.10
Shift Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.11
Equality Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.12
volatile Type Specifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.13
_ _unaligned Type Specifier . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.14
Linkage Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.15
Temporary Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.15.1
Nonconstant Reference Initialization with a Temporary
Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.16
Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.17
File Inclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.18
Inheritance and Header Files . . . . . . . . . . . . . . . . . . . . . . . .
2.2.19
Nested Enums and Overloading . . . . . . . . . . . . . . . . . . . . . .
2.2.20
Guiding Declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3
Run-time Type Identification . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4
Implementation of Polymorphism During Object Construction .
2.5
Message Control Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iv
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2–7
2–9
2–9
2–9
2–11
2–12
2–12
2–13
2–13
2–13
2–14
2–14
2–14
2–19
2–20
2–20
2–21
2–21
2–21
2–21
2–21
2–22
2–22
2–22
2–22
2–23
2–23
2–23
2–23
2–24
2–25
2–26
2–26
.
.
.
.
.
.
.
.
.
2–27
2–27
2–28
2–28
2–29
2–31
2–31
2–32
2–33
2.6
Message Information Options . . . . . . . . . . . . . . . . . . . . . . . . . . .
2–34
3 HP C++ Language Environment
3.1
3.1.1
3.1.2
3.2
3.3
3.4
3.4.1
3.4.2
3.4.3
3.5
3.6
3.6.1
3.6.2
3.6.3
3.6.4
Using Existing C Header Files . . . . . . . . . . . . . . . . . . . .
Providing C and C++ Linkage . . . . . . . . . . . . . . . . .
Resolving C++ Keyword Conflicts . . . . . . . . . . . . . . .
Using HP C++ with Other Languages . . . . . . . . . . . . . .
Linkage to Non-C++ Code and Data . . . . . . . . . . . . . . .
How to Organize Your C++ Code . . . . . . . . . . . . . . . . . .
Code That Does Not Use Templates . . . . . . . . . . . . .
Code That Uses Templates . . . . . . . . . . . . . . . . . . . .
Creating Libraries . . . . . . . . . . . . . . . . . . . . . . . . . .
Using 32-bit Pointers (xtaso) . . . . . . . . . . . . . . . . . . . . .
Hints for Designing Upwardly Compatible C++ Classes
Source Compatibility . . . . . . . . . . . . . . . . . . . . . . . .
Link Compatibility . . . . . . . . . . . . . . . . . . . . . . . . . .
Run Compatibility . . . . . . . . . . . . . . . . . . . . . . . . . .
Additional Reading . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3–1
3–1
3–2
3–2
3–3
3–3
3–4
3–5
3–7
3–7
3–11
3–12
3–12
3–13
3–13
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4–1
4–3
4–4
4–4
4–6
4–7
4–7
4–7
4–7
4–7
4–8
4–9
4–9
4–9
4–9
4–9
4–10
4–10
4–11
4–11
4–12
4 Porting to HP C++
4.1
4.2
4.2.1
4.2.2
4.2.3
4.2.4
4.3
4.3.1
4.3.2
4.3.3
4.4
4.5
4.6
4.6.1
4.6.2
4.6.3
4.6.4
4.7
4.8
4.9
4.10
Compatibility with Other C++ Compilers . . . . . . . . .
Compatibility With Version 5.n Compilers [Tru64] . .
Compiler Version Options [Tru64] . . . . . . . . . . .
Language Differences [Tru64] . . . . . . . . . . . . . .
Implementation Differences [Tru64] . . . . . . . . . .
Library Differences [Tru64] . . . . . . . . . . . . . . . .
Using Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Friend Declarations . . . . . . . . . . . . . . . . . . . . . .
Member Access . . . . . . . . . . . . . . . . . . . . . . . . .
Base Class Initializers . . . . . . . . . . . . . . . . . . . .
Undefined Global Symbols for Static Data Members
Functions and Function Declaration Considerations
Using Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Pointer Conversions . . . . . . . . . . . . . . . . . . . . . .
Bound Pointers . . . . . . . . . . . . . . . . . . . . . . . . .
Constants in Function Returns . . . . . . . . . . . . .
Pointers to Constants . . . . . . . . . . . . . . . . . . . . .
Using typedefs . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Initializing References . . . . . . . . . . . . . . . . . . . . . . .
Using the switch and goto Statements . . . . . . . . . . .
Using Volatile Objects . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
v
4.11
4.12
4.13
4.14
4.15
4.16
4.17
4.18
4.19
4.20
Preprocessing . . . . . . . . . . . . . . . . . . . . . . . . . .
Managing Memory . . . . . . . . . . . . . . . . . . . . . .
Size-of-Array Argument to delete Operator . . .
Flushing the Output Buffer . . . . . . . . . . . . . . .
Missing Parenthesis Error Message . . . . . . . . .
Link Using cxx . . . . . . . . . . . . . . . . . . . . . . . . .
Source File Extensions . . . . . . . . . . . . . . . . . . .
Incrementing Enumerations . . . . . . . . . . . . . .
Scope of Variables Declared on a for Statement
Guidelines for Writing Clean 64-Bit Code . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4–12
4–12
4–13
4–13
4–13
4–14
4–14
4–14
4–14
4–15
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Automatic Template Instantiation . . . . . . . . . . . . . . . . . . . . . .
Specifying Alternate Repositories . . . . . . . . . . . . . . . . . . . .
Reducing Compilation Time with the -ttimestamp Option .
Implicit Inclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Compiling Programs with Automatic Instantiation . . . . . .
Linking Programs with Automatic Instantiation . . . . . . . .
Manual Template Instantiation . . . . . . . . . . . . . . . . . . . . . . . .
Instantiation Directives . . . . . . . . . . . . . . . . . . . . . . . . . . .
#pragma define_template . . . . . . . . . . . . . . . . . . . . . . .
#pragma instantiate and #pragma do_not_instantiate .
Advanced Program Development and Templates . . . . . . . . . . .
Dependency Management . . . . . . . . . . . . . . . . . . . . . . . . .
Mixing Automatic and Manual Instantiation . . . . . . . . . . .
Creating Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Creating A Common Instantiation Library . . . . . . . . . . . .
Multiple Repositories . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Template Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Compatibility with Earlier Versions of C++ . . . . . . . . . . . . . . .
Linking with Version 5.n Instantiations . . . . . . . . . . . . . . .
Linking Version 5.n Applications Against Version 6.n
Repositories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5–1
5–2
5–2
5–2
5–3
5–4
5–5
5–7
5–7
5–7
5–11
5–12
5–12
5–13
5–13
5–14
5–17
5–17
5–20
5–21
..
5–21
5 Using Templates
5.1
5.2
5.2.1
5.2.2
5.3
5.3.1
5.3.2
5.4
5.4.1
5.4.1.1
5.4.1.2
5.5
5.5.1
5.5.2
5.5.3
5.5.4
5.5.5
5.6
5.7
5.7.1
5.8
vi
6 Precompiled Headers
6.1
6.2
6.3
6.4
6.5
Automatic Precompiled Header Processing . . . . . . . . .
Manual Precompiled Header Processing . . . . . . . . . . .
Other Ways for Users To Control Precompiled Headers
Performance Issues . . . . . . . . . . . . . . . . . . . . . . . . . . .
Command-Line Options for Precompiled Headers . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6–2
6–5
6–6
6–6
6–7
Important Compatibility Information . . . . . . . . . . . . . . . . . . . . .
–[no]using_std Compiler Compatibility Switch . . . . . . . . . . .
Pre-ANSI/ANSI Iostreams Compatibility . . . . . . . . . . . . . . .
Support for pre-ANSI and ANSI operator new( ) . . . . . . . . .
Overriding operator new( ) . . . . . . . . . . . . . . . . . . . . . . . . . .
Support for Global array new and delete Operators . . . . . . .
How to Build Programs Using the C++ Standard Library . . . . .
Optional Switch to Control Buffering . . . . . . . . . . . . . . . . . . . . .
Enhanced Compile-time Performance of ANSI Iostreams . . . . .
Upgrading from the Class Library to the Version 6.n Standard
Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Upgrading from the Class Library Vector to the Standard
Library Vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Upgrading from the Class Library Stack to the Standard
Library Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Upgrading from the Class Library String Package Code . . .
Upgrading from the Class Library Complex to the ANSI
Complex Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Upgrading from the Pre-ANSI iostream library to the
Standard Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
7–3
7–3
7–3
7–6
7–7
7–9
7–10
7–10
7–11
.
7–11
.
7–11
.
.
7–12
7–13
.
7–15
.
7–18
.
.
.
.
.
.
.
.
8–1
8–2
8–3
8–3
8–3
8–4
8–4
8–5
7 The C++ Standard Library
7.1
7.1.1
7.1.2
7.1.3
7.1.4
7.1.5
7.2
7.3
7.4
7.5
7.5.1
7.5.2
7.5.3
7.5.4
7.5.5
8 Handling Exceptions
8.1
8.2
8.3
8.4
8.5
8.6
8.7
8.8
Structure . . . . . . . . . . . . . . . . . . . . . .
Run-Time Considerations . . . . . . . . . .
Coding Recommendations . . . . . . . . .
Mixed-Language Applications . . . . . .
Finding Information about Exceptions
Using the dlclose Routine . . . . . . . . . .
Catching Signals and C Exceptions . .
C++ Exceptions and Threads [Tru64] .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
vii
9 Using the Ladebug Debugger
Debugging C++ Programs . . . . . . . . . . . . . . . . . . . . . . . . .
Using Absolute and Relative Path Names . . . . . . . . . . . . .
Debugging Programs Containing C and C++ Code . . . . . . .
Setting the Class Scope . . . . . . . . . . . . . . . . . . . . . . . . . . .
Displaying Class Information . . . . . . . . . . . . . . . . . . . . . . .
Displaying Object Information . . . . . . . . . . . . . . . . . . . . . .
Displaying Virtual and Inherited Class Information . . . . .
Modifying Class and Object Data Members . . . . . . . . . . . .
Member Functions on the Stack Trace . . . . . . . . . . . . . . . .
Resolving Ambiguous References to Overloaded Functions
Setting Breakpoints in Member Functions . . . . . . . . . . . . .
Setting Breakpoints in Overloaded Functions . . . . . . .
Setting Breakpoints in Constructors and Destructors .
Calling Overloaded Functions . . . . . . . . . . . . . . . . . . . . . .
Using Typecasts to Display Program Expressions . . . . . . .
Class Templates and Function Templates . . . . . . . . . . . . .
Debugging C++ Exception Handlers . . . . . . . . . . . . . . . . .
Setting Breakpoints in Exception Handlers . . . . . . . . .
Examining and Modifying Variables in Exception
Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.16
Advanced Program Information: Verbose Mode . . . . . . . . .
9.17
Reducing Object File Size During Debugging . . . . . . . . . . .
9.17.1
Using the -gall and -gall_pattern Options . . . . . . . . . .
9.17.2
Hints for Using the -gall Option Effectively . . . . . . . . .
9.1
9.2
9.3
9.4
9.5
9.6
9.7
9.8
9.9
9.10
9.11
9.11.1
9.11.2
9.12
9.13
9.14
9.15
9.15.1
9.15.2
A Class Library Restrictions
B Built-In Functions
C Third Degree Messages
Index
viii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9–1
9–2
9–3
9–4
9–5
9–7
9–8
9–12
9–12
9–13
9–16
9–18
9–21
9–22
9–23
9–25
9–30
9–30
.
.
.
.
.
....
....
....
....
....
9–31
9–31
9–35
9–36
9–37
Examples
9–1
9–2
9–3
9–4
9–5
9–6
9–7
9–8
9–9
9–10
9–11
9–12
9–13
9–14
9–15
9–16
9–17
9–18
9–19
9–20
9–21
9–22
9–23
9–24
9–25
9–26
9–27
9–28
9–29
Switching Between C++ and C Debugging Modes . . . . . .
Setting the Class Scope . . . . . . . . . . . . . . . . . . . . . . . . . .
Displaying Class Information . . . . . . . . . . . . . . . . . . . . . .
Displaying Object Information . . . . . . . . . . . . . . . . . . . . .
Printing Information on a Derived Class . . . . . . . . . . . . .
Resolving References to Objects of Multiple Inherited
Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Resolving Overloaded Functions by Selection Menu . . . .
Resolving Overloaded Functions by Type Signature . . . . .
Setting Breakpoints in Member Functions . . . . . . . . . . . .
Setting Breakpoints in Virtual Member Functions . . . . . .
Setting Breakpoints in Member Functions for a Specific
Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Setting Breakpoints in Specific Overloaded Functions . . .
Setting Breakpoints in All Versions of an Overloaded
Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Setting Breakpoints in Overloaded Functions by Line
Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Setting Breakpoints in Constructors . . . . . . . . . . . . . . . .
Setting Breakpoints in Destructors . . . . . . . . . . . . . . . . .
Calling an Overloaded Function . . . . . . . . . . . . . . . . . . . .
Using a Cast to Perform Data Coercion . . . . . . . . . . . . . .
Using Casts on a Derived Class Object . . . . . . . . . . . . . .
Using a Cast with Pointer Notation to Perform a Type
Transfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Using a Cast with Reference Type Notation to Perform a
Type Transfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Example of a Function Template . . . . . . . . . . . . . . . . . . .
Setting a Breakpoint in the Template Function . . . . . . . .
Displaying the Current Function Context for a Function
Template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Displaying an Instantiated Class Template . . . . . . . . . . .
Displaying an Instantiated Class Template . . . . . . . . . . .
Setting Breakpoints in an Instantiated Class Function . .
Setting Current Class Scope to an Instantiated Class . . .
Alternate Method of Setting Current Class Scope . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9–4
9–5
9–7
9–8
9–9
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9–10
9–13
9–15
9–16
9–17
...
...
9–18
9–19
...
9–20
.
.
.
.
.
.
.
.
.
.
.
.
9–21
9–22
9–22
9–23
9–24
9–24
...
9–25
...
...
...
9–25
9–26
9–26
.
.
.
.
.
.
9–26
9–27
9–28
9–28
9–28
9–29
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
ix
9–30
9–31
9–32
9–33
Setting Breakpoints in Exception Handlers . .
Printing a Class Description in Verbose Mode
Printing Base Pointer Information . . . . . . . . .
Printing a Stack Trace in Verbose Mode . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9–30
9–32
9–33
9–35
A Stack Trace Displaying a Member Function . . . . . . . . . . . .
9–12
Conventions Used in this Manual . . . . . . . . .
Standard Macro Names . . . . . . . . . . . . . . . . .
System Identification Macro Names . . . . . . . .
Other Predefined Macro Names . . . . . . . . . . .
Language Dialect Macro Names . . . . . . . . . . .
Implementation Compatibility Macro Names .
_ _DECC_VER Version-Type Encodings . . . . . . .
xiv
2–15
2–15
2–16
2–17
2–17
2–19
Figures
9–1
Tables
1
2–1
2–2
2–3
2–4
2–5
2–6
x
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Preface
This manual contains information for developing and debugging HP 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 HP
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 HP
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:
•
Chapter 1 shows how to create, compile, link, and run HP C++ programs.
•
Chapter 2 describes features and characteristics that are specific to the HP
C++ implementation.
•
Chapter 3 describes how to modify existing C header files to be accepted by
HP C++.
•
Chapter 4 contains tips for moving applications built with other C++
implementations to HP C++.
•
Chapter 5 describes how to use templates with HP C++.
xi
•
Chapter 6 describes how to use precompiled headers with HP C++.
•
Chapter 7 describes the HP C++ implementation of the C++ Standard
Library.
•
Chapter 8 explains how to use C++ exception handling.
•
Chapter 9 describes how to use the Ladebug debugger.
•
Appendix A describes Class Library restrictions.
•
Appendix B describes built-in functions.
•
Appendix C describes Third Degree messages generated by the C++ Class
and Standard Libraries.
•
The cxx(1) reference page describes command line options.
Associated Documents
The following documents contain information associated with topics in this
manual:
•
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.
•
C++ Class Library Reference Manual
This manual describes the class library packages supplied with HP C++.
•
HP C++ Installation Guide for Tru64 UNIX
This document supplies the information necessary to install HP C++. on
Tru64 UNIX systems. Instructions for installing HP C++ on Linux Alpha
systems are provided in a README document supplied with the C++ for
Linux Alpha kit.
•
The AT&T C++ Language System, Release 2.0, Library Manual
This document describes the AT&T class library package.
xii
Related Documents
The following documents are not included in the HP C++ documentation set.
Refer to them for additional information on the C++ programming language,
HP C, or Tru64 UNIX and Linux Alpha programming.
•
Stroustrup, Bjarne and Margaret Ellis. The Annotated C++ Reference
Manual. Reading, Massachusetts: Addison-Wesley, 1990.
This text contains the current language definition of C++.
•
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.
•
Myers, Scott. Effective C++: 50 Specific Ways to Improve Your Programs
and Designs, 3rd edition. Reading, Massachusetts: Addison-Wesley, 1997.
•
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.
•
Tru64 UNIX Programmer’s Guide
This guide describes the programming environment on the Tru64 UNIX
operating system, emphasizing the C programming language.
•
HP C Language Reference Manual
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 HP C.
•
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.
•
International Standard ISO/IEC 14882
Defines the C++ International Standard. The document is available for
downloading at the ANSI Electronic Store (start at
The printed version is also available for purchase from the same web site.
Choose ‘‘Catalogs/Standards Information’’, then ‘‘ANSI-ISO-IEC Online
Catalog’’, then search for ‘‘14882’’.
xiii
Conventions Used in this Manual
Table 1 lists the conventions used in this manual.
Table 1 Conventions Used in this Manual
Convention
Meaning
%
class complex {
A percent sign (%) is the default user prompt.
.
.
.
A vertical ellipsis indicates that some intervening
program code or output is not shown. Only the
more pertinent material is shown in the example.
};
, ...
The
The
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.
generic class . . .
get( ) function . . .
Monospaced type denotes the names of HP C++
language elements, and also the names of classes,
members, and nonmembers. Monospaced type
is also used in text to reference code elements
displayed in examples and file-name extensions.
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
lowercase
The Tru64 UNIX and Linux Alpha 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 HP C++
document, by electronic mail to the following Internet address:
[email protected].
Include the title of the document, section and page number where the error
occurred.
xiv
Product Support
Premium support is available on a per-incident basis
http://www.hp.com/hps/perevent/pv_software.html
and annual contracts
http://www.hp.com/hps/os/os_tru64.html
from HP Services in the US and some other countries. In the US and Canada,
call, toll-free, 1-800-354-9000. In other countries, support phone numbers are
available on the web at:
http://welcome.hp.com/country/us/en/wwcontact.html
Free support is limited to bug reports that can be sent to
[email protected]
Send a complete but short example reproducing the problem, including the
following:
•
Compiler and operating system versions
•
All necessary sources (such as INCLUDE files and module sources)
•
Data files
•
Commands used to compile, link and run the program
•
Expected results and incorrect results obtained
Please try to reduce the problem to as small a source as possible, because we
may be unable to diagnose large applications.
We answer most quickly those problem reports that include a small but
complete reproducible example, along with descriptions of the compile and link
options used and the exact text of any diagnostic messages or other incorrect
results. Reports that include only program fragments or involve very large
applications generally will not be accepted.
Please note that this is not a ‘‘programming consulting service’’ and that you
should have clear evidence of a product problem before contacting us. If you
need consulting services, please contact HP Services.
xv
1
Building and Running C++ Programs
This chapter provides information about the basic steps involved in developing
a HP C++ program. It explains how to compile, link, and debug programs.
HP C++ is an implementation of the C++ programming language. The compiler
is part of the HP Tru64 UNIX and Linux Alpha compiler systems. See the HP
Tru64 UNIX and Linux Alpha Programmer’s Guide for program development
information that applies to all HP 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
(HP 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.ps | .txt
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 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.
Building and Running C++ Programs 1–1
Building and Running C++ Programs
1.2 Linking a Program
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 HP 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.
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.
1–2 Building and Running C++ Programs
Building and Running C++ Programs
1.3 Name Demangling
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
-show_mangled_name
-no_vtable_info
Read from the standard input file.
Display encoded name in parentheses after demangled name.
Suppress the display of information concerning internal
symbols (specifically _ _vtbl and _ _btbl).
Example
demangle file
This command demangles a file containing HP C++ encoded names.
ld main.o foo.o |& demangle
This command (from the C shell) demangles the output from the linker (ld)
when linking the main.o and foo.o files.
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.ps | .txt
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, HP will continue to provide the C++ Class Library. Note
that on Linux Alpha, the Class Library task package in not supported.
On Tru64 UNIX, the Class Library task package will gradually be retired.
Starting with Version 6.3 of the compiler, the task library is no longer
distributed in the shared format.
Building and Running C++ Programs 1–3
Building and Running C++ Programs
1.4 C++ Standard Library
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.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 HP C++. Class libraries offer a variety of predefined classes
that enable you to work more efficiently.
See the 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–4 Building and Running C++ Programs
Building and Running C++ Programs
1.6 Linking With Non-Default Libraries
1.6 Linking With Non-Default Libraries
When you use the cxx command to compile and link programs that use symbols
not found in the default libraries, you must explicitly link your program
with the library that contains those symbols. Link the libraries by specifying
-lstring, where string is an abbreviation of the library name. Failure to do so
will result in unresolved symbols at link time.
Consider the following program, sqrt_example.cxx:
// sqrt_example.cxx
#include <math.h>
int main() {
double d = 3.14;
d = sqrt(d);
return 0;
}
If you enter the command cxx sqrt_example.cxx to compile the program, the
following error appears at link time:
ld:
Unresolved:
sqrt
You can use the cxx driver to resolve the symbol ‘‘sqrt’’ found in the math
library libm.a by entering the following command:
cxx sqrt_example.cxx -lm
Invoking the man command with the unresolved symbol as an argument
usually provides clues to help you find the name of the library that contains
the symbol.
1.7 Debugging
The Ladebug Debugger is a source-level debugger that supports HP C++.
Neither the dbx nor the gdb debugger supports debugging C++ programs. For
details on using the Ladebug Debugger, see Chapter 9.
1.8 Improving Build Performance
This section contains suggestions for improving build performance when using
HP C++ on your system.
Building and Running C++ Programs 1–5
Building and Running C++ Programs
1.8 Improving Build Performance
1.8.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.8.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.8.3 Using Precompiled Headers
Using precompiled headers can reduce compilation time in environments where
•
Many primary sources include the same set of headers in the same order.
•
These headers introduce many lines of code.
See Chapter 6 for details.
1.8.4 Performance Optimization Options
For a description of performance optimization options, see the cxx(1) reference
page.
1.9 Deploying Your Application [Tru64]
Applications developed using the HP 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.
1–6 Building and Running C++ Programs
Building and Running C++ Programs
1.9 Deploying Your Application [Tru64]
While we strongly recommend upgrading for bug fixes, this is not mandatory.
Read the compiler Release Notes at http://h30097.www3.hp.com/cplus/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. In previous versions,
this typically results in undefined symbol errors from the loader at runtime.
Starting in V6.3, failure to do so will result in the following diagnosic from the
loader at runtime:
slab> a.out
333677:a.out: /sbin/loader: Fatal Error: object libcxx.so from liblist in a.out
has version "cxx6.3", which does not match the found object: libcxx.so (with
version ":V4.0.1")
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.
OS
Default C++ Library
Shipped with System
Highest Version of C++ Compiler
Not Requiring Redistribution Kit
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
5.1
6.2-037
6.2-040
5.1A
6.3-001
6.5-nnn
5.1B
6.5-014
6.5-nnn
Building and Running C++ Programs 1–7
Building and Running C++ Programs
1.9 Deploying Your Application [Tru64]
1.9.1 Redistributing the C++ Run-Time Library
If you are a third-party vendor who is shipping a product based on Version
6.5 or later, you must ensure your that your customers have a V6.3 or later
C++ Run-Time Library. To do so, you can direct them to download the latest
redistribution kit from the HP 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/version/CXXREDIST650Vmm.tar
mm is the revision numbers for this release. This tar file contains a setld kit
that installs /usr/lib/cmplrs/cxx/version/libcxx.so and places a symbolic
link in /usr/lib/cmplrs/cxx to the latest runtime installed on the system.
1.9.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_V60500001 exists in the
image on your system, then you do not need to install this kit.
# nm /usr/lib/cmplrs/cxx/libcxx.so | grep libcxx_V
__libcxx_V60200002
| 0004396996916008 | G | 0000000000000000
__libcxx_V60200003
| 0004396996916016 | G | 0000000000000000
__libcxx_V60300001
| 0004396996918728 | G | 0000000000000000
__libcxx_V60500001
| 0004396996920176 | 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
CXXREDIST610 installed HP C++ Run-Time Library ...
# /usr/sbin/setld -d CXXREDIST610
3. Install the redistribution kit
# tar -xvf CXXREDIST650Vmm.tar
# /usr/sbin/setld -l CXXREDIST650.kit
1–8 Building and Running C++ Programs
Building and Running C++ Programs
1.10 Using OpenMP
1.10 Using OpenMP
The compiler supports C/C++ OpenMP Version 1.0. C++ exception handling
within an OpenMP parallel region is not initially supported but will be
supported in a later release. By default, the compiler ignores all C++ OpenMP
directives unless you specify the -omp option. For example:
cxx -omp omp_program.cxx
Building and Running C++ Programs 1–9
2
HP C++ Implementation
This chapter discusses the features and characteristics specific to the HP 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 HP 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 HP 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.
builtins
inline
linkage2
use_linkage2
dictionary1
noinline
module
extern_model
member_alignment
message
define_template
extern_prefix
1 Not
supported; specific to C on OpenVMS
2 Not
supported; specific to C
HP C++ Implementation 2–1
HP C++ Implementation
2.1 Implementation-Specific Attributes
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 Section 5.4.
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:
•
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.
It provides the same functionality as the explicit instantiation syntax
described in Section 14.7.2 of the C++ International Standard.
•
The do_not_instantiate pragma suppresses the instantiation of a
specified entity. It is typically used to suppress the instantiation of an
entity for which a specific definition will be supplied.
For more information on how to use templates with the #pragma instantiate
directive, see Section 5.4.
2.1.1.3 #pragma environment Directive
The #pragma environment preprocessor directive offers a way to singlehandedly 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 HP 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
2–2 HP C++ Implementation
HP C++ Implementation
2.1 Implementation-Specific Attributes
#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 HP 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.
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.
HP C++ Implementation 2–3
HP C++ Implementation
2.1 Implementation-Specific Attributes
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:
#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 #pragma extern_prefix directive is an OpenVMS pragma that cannot be
used on HP 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.
2–4 HP C++ Implementation
HP C++ Implementation
2.1 Implementation-Specific Attributes
In version 4.n of HP’s HP 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 HP 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 intrinsic Directive
The #pragma intrinsic directive specifies that calls to the specified functions
are intrinsic. Intrinsic functions are functions in which the compiler generates
optimize code in certain situations, possibly avoiding a function call.
The #pragma intrinsic directive has the following syntax:
#pragma intrinsic (function1[,function2, . . . ])
You can use this directive to make intrinsic the default form of functions that
have intrinsic forms. The following functions have intrinsic forms:
abs
fabs
labs
alloca
You can use the #pragma function directive to override the #pragma intrinsic
directive for specified functions.
The function must have a declaration visable at the time the compiler
encounters the #pragma intrinsic directive. The compiler takes no action
if the compiler does not recognize the specified function name as an intrinsic.
HP C++ Implementation 2–5
HP C++ Implementation
2.1 Implementation-Specific Attributes
2.1.1.8 #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.
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;
int b;
};
/*3 bytes of filler follow c */
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.
2–6 HP C++ Implementation
HP C++ Implementation
2.1 Implementation-Specific Attributes
The optional base_alignment parameter can be used to specify the basealignment 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)
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.9 #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
HP C++ Implementation 2–7
HP 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:
•
A single message identifier
•
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
•
A single message identifier enclosed in parentheses
•
A single message group name enclosed in parentheses
•
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.
The save and restore options are useful primarily within header files. See
Section 2.1.1.3.
2–8 HP C++ Implementation
HP C++ Implementation
2.1 Implementation-Specific Attributes
2.1.1.10 #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.11 #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.1.1.12 #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 datadeclaration 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)]
HP C++ Implementation 2–9
HP C++ Implementation
2.1 Implementation-Specific Attributes
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 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
2–10 HP C++ Implementation
HP C++ Implementation
2.1 Implementation-Specific Attributes
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.1.1.13 #pragma pointer_size Directive [Tru64]
The #pragma pointer_size preprocessor directive controls pointer size
allocation for the following:
•
References
•
Pointers to member declarations
•
Function declarations
•
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.
HP C++ Implementation 2–11
HP C++ Implementation
2.1 Implementation-Specific Attributes
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.
Use of short pointers is restricted to the HP C++ and the C compilers resident
on HP 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.
HP 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:
•
Two functions defined differ in argument types only with respect to pointer
sizes.
•
Two functions differ in return type only with respect to pointer size.
•
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.14 #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.15 #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}
#pragma required_vptr_size {short | 32}
#pragma required_vptr_size restore
2–12 HP C++ Implementation
HP C++ Implementation
2.1 Implementation-Specific Attributes
#pragma required_vptr_size save
The parameters have the same meaning as with #pragma required_pointer_size
(see Section 2.1.1.13).
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.16 #pragma [no]standard Directive
Use the #pragma nostandard and #pragma standard preprocessor 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.1.17 #pragma weak Directive
Use the #pragma weak preprocessor directive to create weak symbols. Weak
symbols are symbols that can be overridden by strong symbols. Symbols are
strong by default.
This pragma has the following syntax:
#pragma weak weak_name
#pragma weak weak_name = strong_name
#pragma weak ( weak_name, strong_name )
The first form of the pragma makes the specified name a weak symbol. The
other two make a weak symbol that refers to the same symbol as the other
name.
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:
•
Use a header file protection option provided by the compiler.
•
Modify each header file.
HP C++ Implementation 2–13
HP 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 HP-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
#pragma __environment header_defaults
// Save pointer size
// 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.1.3 Predefined Macro Names
The following tables list predefined C++ macros used by HP 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.
2–14 HP C++ Implementation
HP C++ Implementation
2.1 Implementation-Specific Attributes
For information on using predefined macros in header files in the common
language environment, see Section 3.1.
Table 2–1 Standard Macro Names
_ _cplusplus
Defined 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
_ _alpha1 , _ _alpha_ _, _ _ALPHA
System has an Alpha processor.
_ _arch64_ _
System with 64-bit architecture.
_ _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. However, some
open-source libraries use it.
_ _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.
HP C++ Implementation 2–15
HP C++ Implementation
2.1 Implementation-Specific Attributes
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 HP C++.
_ _DECCXX_VER
Compiler version identifier in
string form.
_ _IEEE_FLOAT
The compiler supports IEEE
floating point.
_ _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
HP C++ recognizes intrinsic
functions.
_ _LANGUAGE_C_ _, _ _LANGUAGE_C,
LANGUAGE_C
[Linux] Compiler 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.
_WCHAR_T1 , _ _WCHAR_T2
wchar_t is a typedef or a keyword.
1 Use
2 This
this form for portability.
form is used on OpenVMS systems.
(continued on next page)
2–16 HP C++ Implementation
HP C++ Implementation
2.1 Implementation-Specific Attributes
Table 2–3 (Cont.) Other Predefined Macro Names
Macro Name
Description
_ _X_FLOAT
System has default long double size
of 128 bits.
Predefined Language Dialect Macro Names
Table 2–4 shows the macro names defined by specifying the listed commandline options.
Table 2–4 Language Dialect Macro Names
Command-line Option
Macro Name
-std arm
-std ansi
-std cfront, -cfront
_ _STD_ARM
-std gnu
-std ms, -ms
-std strict_ansi
-std strict_ansi_errors
_ _STD_GNU
_ _STD_ANSI
As of C++ Version 7.1, the -std cfront and
-cfront options are no longer supported.
_ _MS, _ _STD_MS
_ _STD_STRICT_ANSI, _ _PURE_CNAME
_ _STD_STRICT_ANSI_ERRORS,
_ _PURE_CNAME
Predefined Implementation Compatibility Macro Names
Table 2–5 shows the macro names defined by specifying the listed commandline options.
Table 2–5 Implementation Compatibility Macro Names
Command-line Option
Macro Name
-alternative_tokens
-fprm
-global_array_new
-ieee
-implicit_include
_ _ALTERNATIVE_TOKENS
_ _FLT_ROUNDS
_ _GLOBAL_ARRAY_NEW
_ _IEEE_FP
_ _IMPLICIT_INCLUDE_ENABLED
(continued on next page)
HP C++ Implementation 2–17
HP C++ Implementation
2.1 Implementation-Specific Attributes
Table 2–5 (Cont.) Implementation Compatibility Macro Names
Command-line Option
Macro Name
-long_double_size
-model ansi
-model arm
-pch,-create_pch,-use_pch
-pthread
-pure_cname
-rtti
-stdnew
-threads
-using_std
_ _X_FLOAT
_ _MODEL_ANSI
_ _MODEL_ARM
_ _PCH_ENABLED
_REENTRANT
_ _PURE_CNAME
_ _RTTI
_ _STDNEW
_REENTRANT, _PTHREAD_USED_D4
_ _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:
•
T is the version type (letter).
•
MM is the major version number.
•
mm is the update (minor version number).
•
eee is the edit suffix number.
The format of the integer encoding for _ _DECCXX_VER is:
vvuuteeee
Where:
•
vv is the major version number.
•
uu is the update (minor version number).
•
t is the numerical encoding of the alphabetic version type from the versionidentifier string.
Table 2–6 lists the possible version types and their encodings
2–18 HP C++ Implementation
HP C++ Implementation
2.1 Implementation-Specific Attributes
•
eeee is the edit suffix number.
Table 2–6 _ _DECC_VER Version-Type Encodings
Type
Numerical
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 10,000,000 (ten million).
2. The minor version (the digits between the period (.) and any edit suffix)
is multiplied by 100,000 (one hundred thousand) 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
string
T5.2-003
V6.0-001
__DECCXX_VER
vvuuteeee
-->
-->
50,260,003
60,090,001
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.
HP C++ Implementation 2–19
HP C++ Implementation
2.1 Implementation-Specific Attributes
Limit
Meaning
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:
•
The number of bits in a character of the execution character set is 8 bits.
•
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).
•
The representation and set of values for the short type is 16 bits.
•
The representation and set of values for the types int, unsigned int, and
float are 32 bits.
•
The representation and set of values for type double are 64 bits.
•
The representation and set of values for type long double is 128 bits on
HP 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).
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.
2–20 HP C++ Implementation
HP C++ Implementation
2.1 Implementation-Specific Attributes
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
HP C++ for Tru64 UNIX and Linux Alpha systems.
2.2.1 Identifiers
In HP 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.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 implementation. Relying on
this order is not good programming practice. For HP 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.
HP C++ Implementation 2–21
HP C++ Implementation
2.2 Implementation Extensions and Features
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.
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 HP 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>, 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–22 HP C++ Implementation
HP C++ Implementation
2.2 Implementation Extensions and Features
2.2.8 Multiplicative Operators
The semantics of the division (/) and remainder (%) operator are as follows:
•
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).
•
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:
•
Both pointers are NULL.
•
The same address expression (&) created both pointers.
When comparing two pointers to members, the compiler guarantees inequality
if either of the following conditions hold:
•
Only one pointer is NULL.
•
Each pointer produces a different member if applied to the same object.
When created by different address expressions, two pointers to members may
compare as equal if they produce the same member when applied to the same
object; otherwise, they are unequal.
HP C++ Implementation 2–23
HP C++ Implementation
2.2 Implementation Extensions and Features
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:
•
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.
•
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.
•
Optimizations that alter an object’s existence; for example, loop induction
to actually eliminate a variable reference.
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:
•
The volatile specifier can be used to qualify any data type, including a
single member of a structure or union.
•
Redundant use of the volatile keyword elicits a warning message. For
example:
volatile volatile int x;
2–24 HP C++ Implementation
HP C++ Implementation
2.2 Implementation Extensions and Features
•
When volatile is used with an aggregate type declaration, 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;
*/
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 specifier. 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.)
HP C++ Implementation 2–25
HP C++ Implementation
2.2 Implementation Extensions and Features
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:
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:
•
An object is returned from a function.
•
An object is passed as an argument.
•
An object is created using the constructor notation.
•
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 effects in the constructors or destructors
of temporary objects.
2–26 HP C++ Implementation
HP C++ Implementation
2.2 Implementation Extensions and Features
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:
•
Applications that do not have exception handlers incur no overhead.
•
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.
•
As much as possible, overhead for exceptions is incurred when throwing an
exception. Entering or leaving a try block incurs no overhead.
In HP 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, 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. Beware of such conflicting exception specifications,
particularly if you have exception specifications in prototypes that are in
header files accessible to other programs.
HP C++ Implementation 2–27
HP C++ Implementation
2.2 Implementation Extensions and Features
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 HP C++ functions and macros in the program stream.
The #include directive has the following search path semantics:
•
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,
/usr/include/cxx_cname, and /usr/include directories, then in the
/usr/include/cxx_cname directory.
•
Angle-bracketed files are searched for in the list of directories
specified on the command line, then in the /usr/include/cxx,
/usr/include/cxx_cname, and finally in the /usr/include directory.
•
By default, the compiler searches for include files in the standard
directories /usr/include/cxx, /usr/include/cxx_cname, and in the
/usr/include directory in the order described above. If you want to
override this behavior and force the compiler to search only in directories
specified on the command line, use the -I open without any arguments.
(See the description of the -I option in the cxx.1 reference page.)
2.2.18 Inheritance and Header Files
Inheritance means that one object or file derives some of its contents by virtual
copying from another object or file. In the case of C++ header files, for example,
one header file includes another and then replaces or adds something.
If the inheriting header file and the base header file have different names,
inheritance is straightforward: simply write #include "base" in the inheriting
file.
However, if it is necessary to give the inheriting file the same name as the base
file, inheritance is less straightforward.
For example, suppose an application program uses the system header file
sys/signal.h, but the version of /usr/include/sys/signal.h on a particular
system does not do what the program expects. You could define a local version,
perhaps with the name /usr/local/include/sys/signal.h, to override or add
2–28 HP C++ Implementation
HP C++ Implementation
2.2 Implementation Extensions and Features
to the one supplied by the system. Using the -I option for compilation, you
could then write a file sys/signal.h that does what the application program
expects. But if you try to include the standard sys/signal.h in your version
using #include <sys/signal.h>, the result is an infinite recursion and a fatal
compilation error.
Specifying #include </usr/include/sys/signal.h> would include the correct
file, but that technique makes maintenance difficult because it assumes that
the location of the system header files will never change.
You should therefore use the #include_next directive, which means ‘‘Include
the next file with this name.’’ This directive works like #include but starts
searching the list of header file directories after the directory in which the
current file was found.
Suppose you specify -I /usr/local/include, and the list of directories to
search also includes /usr/include. Then suppose that both directories contain
a file named sys/signal.h. Specifying #include <sys/signal.h> finds your
version of the file in the /usr/local/include directory. If that file contains
#include_next <sys/signal.h>, the search starts after that directory and
finds the correct system standard file in /usr/include.
2.2.19 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 HP 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.
HP C++ Implementation 2–29
HP C++ Implementation
2.2 Implementation Extensions and Features
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:
#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.
2–30 HP C++ Implementation
HP 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.20 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 <class T> void f(T) {
printf("In template f\n");
}
void f(int);
int main() {
f(0);
// invokes non-template f
f<>(0.0); // invokes template f
return 0;
}
void f(int) {
printf("In non-template f\n");
}
Because there is no concept of guiding declaration in the current version of
the C++ International Standard, the function f in the example is not regarded
as an instance of function template f. Furthermore, there are two functions
named f that take an int parameter. A call of f(0) would invoke the former,
while 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++ types is not generated. The default is
to enable runtime type information features and generate static information in
the object file.
HP C++ Implementation 2–31
HP C++ Implementation
2.3 Run-time Type Identification
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 information on how to convert to each. The
typeinfo references are mangled in the form _ _T_ _<class>.
2.4 Implementation of Polymorphism During Object
Construction
During object construction, the compiler allocates intermediate virtual function
tables on the constructor’s stack for each virtual base class. If the object
currently under construction is a subobject of a more derived object, the
compiler uses the local virtual function tables. Each table’s Run-Time Type
Identification contains the offset to convert successfully from the virtual base
class to the object being constructed. This offset is known at runtime through
the object’s virtual base table and can be assigned into the corresponding local
virtual function table’s RTTI information. Virtual function calls that occur
during construction can then correctly adjust the ‘‘this’’ pointer.
Compiler-generated thunks to this pointers (‘‘interludes’’) take advantage of the
RTTI’s offset:
void __INTER__1S_funcname_2Vn_type(Vn *this)
{
this = this + this.vptr[RTTI_INDEX].offset;
funcname(this);
}
Again, this offset represents the proper delta to convert from a virtual base
class to the more derived class that overrode the virtual function declared
within the virtual base class. For example:
struct V {
V() { f(); }
virtual void f() { g(); }
virtual void g() { printf("V::g, this = %x\n", this); }
};
struct S : virtual V {
S() { f(); }
virtual void g() { printf("S::g, this = %x\n", this); }
};
struct D : virtual S {
D() { f(); }
virtual void g() { printf("D::g, this = %x\n", this); }
};
S’s constructor would be rewritten as follows:
2–32 HP C++ Implementation
HP C++ Implementation
2.4 Implementation of Polymorphism During Object Construction
S()
{
if (most_derived) {
Assign btbls;
Call virtual base class constructors;
}
if (!most_derived) {
/* For each virtual base generate the following code */
/* Vn represents a particular virtual base class */
int *__local_vtbl__2Vn1S[Vn_vtbl_compile_time_known_size];
memmove(__local_vtbl__2Vn1S, __vtbl__2Vn1S,
Vn_vtbl_compile_time_known_size);
__local_vtbl__2Vn1S[RTTI_INDEX].offset = S.bptr[Vn];
Vn.vptr = &__local_vtbl__2Vn1S;
} else {
Assign vtbls like we do today;
}
Call non-virtual direct base class constructors
/* body of S’s constructor */
if (!most_derived) {
Reassign vtbls like we do today;
}
}
2.5 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
HP C++ Implementation 2–33
HP C++ Implementation
2.5 Message Control Options
–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.
2.6 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.5.
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.5.
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.
2–34 HP C++ Implementation
HP C++ Implementation
2.6 Message Information Options
–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
HP C++ Implementation 2–35
3
HP 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 HP C++ programs. In particular, be sure to address the
following issues:
•
Enable the proper linkage for each language.
•
Ensure that C++ keywords are not used as identifiers.
•
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.
HP C++ Language Environment 3–1
HP 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.
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
const_cast
export
mutable
private
static_cast
true
virtual
bool
delete
false
namespace
protected
template
try
wchar_t
catch
dynamic_cast
friend
new
public
this
typeid
class
explicit
inline
operator
reinterpret_cast
throw
typename
3.2 Using HP C++ with Other Languages
The following are suggestions regarding the use of HP C++ with other
languages:
•
Passing entities, such as classes, by reference is safest.
•
You cannot invoke class member functions from within any language other
than C++.
•
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);
3–2 HP C++ Language Environment
HP C++ Language Environment
3.2 Using HP C++ with Other Languages
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.
•
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 when it
links tiny.o.
The following is an example of the resulting display on HP Tru64 UNIX
Version 4.0 systems or higher and Linux Alpha:
/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 HP C++ program and export HP 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 HP C++ users to organize an application
into files; it assumes that you are using automatic instantiation to instantiate
any template classes and functions.
HP C++ Language Environment 3–3
HP C++ Language Environment
3.4 How to Organize Your C++ Code
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:
•
Class declarations
•
Global function declarations
•
Global data declarations
•
Inline function definitions
The following items belong in library source files:
•
Static member data definitions
•
Out-of-line member function definitions
•
Out-of-line global function definitions
•
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
3–4 HP C++ Language Environment
HP 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:
•
Declarations of global function templates
•
Declarations of class templates
•
Declarations of global function template specializations
•
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 the declaration is in the header file inc1.h, these
corresponding definitions could be in file inc1.cxx.
•
Definitions of out-of-line global function templates
•
Definitions of static member data of class templates
•
Definitions of out-of-line member functions of class templates
HP C++ Language Environment 3–5
HP C++ Language Environment
3.4 How to Organize Your C++ Code
The following must be placed in library source files to prevent multiple
definition errors:
•
Definitions of global function template specializations
•
Definitions of static member data specializations of class templates
•
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
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) { ; }
3–6 HP C++ Language Environment
HP C++ Language Environment
3.4 How to Organize Your C++ Code
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 straightforward: you simply
compile each library source file and place the resulting object file in your
library.
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, HP 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.
HP C++ Language Environment 3–7
HP C++ Language Environment
3.5 Using 32-bit Pointers (xtaso)
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:
•
Mixing 32-bit and 64-bit pointers may introduce new porting problems if
the data structures in system libraries still use 64-bit pointers.
•
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_size
Has the same effect as #pragma 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:
•
#pragma pointer_size is enabled. This pragma has an effect only if you
specify a pointer size compiler option on the command line.
•
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.
3–8 HP C++ Language Environment
HP C++ Language Environment
3.5 Using 32-bit Pointers (xtaso)
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:
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:
HP C++ Language Environment 3–9
HP C++ Language Environment
3.5 Using 32-bit Pointers (xtaso)
#pragma
#pragma
#pragma
#pragma
pointer_size save
required_vptr_size save
pointer_size short
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
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. 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:
3–10 HP C++ Language Environment
HP C++ Language Environment
3.5 Using 32-bit Pointers (xtaso)
int x;
int *px;
int X::*pXk;
sizeof(int*)=4
sizeof(px)=4
sizeof(&x)=8
sizeof(int X::*)=8
sizeof(pXk)=8
sizeof(&X::k)=16
HP 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.
HP C++ Language Environment 3–11
HP 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:
•
Add new data members and classes.
•
Add new virtual and nonvirtual functions (as long as they do not change
overload resolution of existing calls).
•
Loosen protection.
•
Change inline functions to out-of-line and out-of-line functions to inline.
•
Change the implementation of functions.
•
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 representation of class objects
and interfaces must remain constant. In general, you can make the following
changes to your library and still maintain link compatibility:
•
Change the implementation of an out-of-line function.
•
Loosen protection.
•
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.
3–12 HP C++ Language Environment
HP C++ Language Environment
3.6 Hints for Designing Upwardly Compatible C++ Classes
The following are changes that you cannot make in your library:
•
Add, move, or delete data members.
•
Add, move, or delete virtual functions.
•
Change the signature of virtual and nonvirtual functions.
•
Remove nonvirtual functions.
•
Change inline function definitions.
•
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. HP suggests using one of the
following design approaches:
•
Set aside dummy (reserved-for-future-use) data fields and virtual functions
within your classes. This assumes you can foresee how much your classes
will grow and change in the future.
•
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.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 ld reference pages 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.
HP C++ Language Environment 3–13
4
Porting to HP C++
HP 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 Chapter 7 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:
•
Run-time type identification (RTTI), with dynamic_cast and the typeid
operator (see Section 2.3)
•
New-style casts (static_cast, reinterpret_cast, and const_cast).
•
Array new and delete
For compatibility with previous versions, the compiler provides the following
language mode options:
Porting to HP C++ 4–1
Porting to HP C++
4.1 Compatibility with Other C++ Compilers
-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
To enhance compatibility with other C++ compilers, HP C++ supports options
that direct the compiler to interpret the source program according to certain
rules followed by other implementations:
-std cfront
As of C++ Version 7.1, this option is no longer supported.
-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:
•
These options are enabled by default:
4–2 Porting to HP C++
Porting to HP C++
4.1 Compatibility with Other C++ Compilers
-alternative_tokens, -tlocal, and -no_implicit_include
•
Access control is not enforced for types defined inside a class.
•
Unrecognized character escape sequences in string literals produce an
informational instead of a warning message.
•
The _ _inline keyword is enabled and is equivalent to inline.
•
When overloading, enum types are treated as integral types.
The following known incompatibilities are not addressed in the -std gnu mode:
•
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.
-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 -std ms 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.
•
Language differences
•
Implementation differences
•
Library differences
Porting to HP C++ 4–3
Porting to HP C++
4.2 Compatibility With Version 5.n Compilers [Tru64]
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.
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 HP 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:
•
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.
•
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 HP 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.
•
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.
4–4 Porting to HP C++
Porting to HP C++
4.2 Compatibility With Version 5.n Compilers [Tru64]
•
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
Alternative representation keywords are as follows:
and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, xor_eq
•
Creation of temporaries and their lifetimes vary among compiler modes.
•
Taking the address of a bit field is not allowed in the current version.
•
Macro expansion in pragmas can give different results in the current and
previous versions.
•
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);
•
The current version does not allow converting a pointer to member from a
derived class to a virtual base class.
•
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(); // will seg fault
if (ad==NULL) cout << "ok";
}
•
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.
Porting to HP C++ 4–5
Porting to HP C++
4.2 Compatibility With Version 5.n Compilers [Tru64]
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.
•
The current version does not cause pragmas to become effective within
function bodies when scanning template definitions.
•
The current version does not permit dropping qualifiers on pointer
assignments. For example, the following is not permitted:
volatile int *vptr; int *ptr=vptr;
•
The current version does not allow the ‘‘virtual’’ storage class modifier to be
used with member function definitions outside a class.
•
The current version does not allow declaration of pointers to members of
type void. For example, the following is not allowed:
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:
•
The automatic template instantiation model has been redesigned for the
current version. See Using Templates.
•
The current version does not support the -show statistics option
implemented in Version 5.7.
•
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.
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.
•
The current and previous versions differ in interpreting undefined behavior,
as when incrementing takes effect in this example:
f(i++, i++);
•
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.
4–6 Porting to HP C++
Porting to HP C++
4.2 Compatibility With Version 5.n Compilers [Tru64]
•
The current version displays #line number in -E output. The previous
version displays #number.
•
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 Chapter 7.
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.3.2 Member Access
Unlike some older C++ implementations, HP 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, HP 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:
Porting to HP C++ 4–7
Porting to HP C++
4.3 Using Classes
class Base {
// . . .
public:
Base (int);
};
class Derived : public Base {
// . . .
public:
// Derived(int i) : (i) {/* . . .
Derived(int i) : Base(i) {/* . . .
};
*/}
** not legal
*/} // ** 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 HP 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:
#include <stdio.h>
class C {
public:
static int i;
};
//missing definition
//int C::i = 5;
int main ()
{
int x;
x=C::i;
printf("x %d\n",x);
return 0;
}
The compiler does not issue any messages during compilation; 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–8 Porting to HP C++
Porting to HP C++
4.5 Functions and Function Declaration Considerations
4.5 Functions and Function Declaration Considerations
HP C++ requires the use of function definitions as described in The C++
Programming Language, 3rd Edition. For examples of outdated syntax not
allowed in HP 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.6 Using Pointers
This section explains how to use pointers effectively in HP C++.
4.6.1 Pointer Conversions
In HP 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 HP 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};
Porting to HP C++ 4–9
Porting to HP C++
4.6 Using Pointers
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.
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–10 Porting to HP C++
Porting to HP C++
4.8 Initializing References
4.8 Initializing References
HP C++ warns against initializing nonconstant references to refer to temporary
objects. The following example demonstrates the problems that can result:
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;
myint m = 0;
{
int j = 0;
myint m = 0;
}
case 2:
break;
// . . .
}
//not initialized at this case label
//not initialized at this case label
// legal within the braces
// legal within the braces
For more information on using the switch statement, see of The C++
Programming Language, 3rd Edition.
Porting to HP C++ 4–11
Porting to HP 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
HP 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.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–12 Porting to HP C++
Porting to HP C++
4.13 Size-of-Array Argument to delete Operator
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 conformance 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.
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 different indentifier.
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.
Porting to HP C++ 4–13
Porting to HP C++
4.16 Link Using cxx
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
•
Segmentation faults (signal SEGV) occur while running your program
•
Undefined symbols
•
Static constructors not being executed
4.17 Source File Extensions
HP C++ automatically treats files with a .c extension as C language source
files and passes the files to the cc command. For HP C++ to compile them,
your files must have one of the following extensions:
.cxx
.cpp
.cc
.C
.CXX
.CPP
.CC
.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; HP 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);
}
4–14 Porting to HP C++
Porting to HP C++
4.19 Scope of Variables Declared on a for Statement
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.
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:
•
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.
•
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.
•
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.
•
Variables declared as int should not be used to hold an address; sizeof
(int) does not equal sizeof (char *) on Alpha systems.
•
Remember that register variables and unsigned variables default to int
(32 bits).
•
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;
•
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.
•
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.
Porting to HP C++ 4–15
Porting to HP C++
4.20 Guidelines for Writing Clean 64-Bit Code
•
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.
•
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.
•
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 HP Tru64 UNIX Migration Guide.
4–16 Porting to HP C++
5
Using Templates
The C++ template instantiation model includes the following features:
•
Automatic template instantiation occurs at compile time. Necessary
templates are instantiated automatically by the compilation of the source
file that needs them and has access to the template definitions.
•
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.
•
For automatic instantiation, the compiler does not require that template
declarations and definitions appear in header files.
•
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);
};
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:
Using Templates 5–1
Using Templates
5.1 Overview
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. The first repository named is the read-write repository
into which the compiler writes instantiation objects when processing. At link
time, all repositories are read only. 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.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.
5–2 Using Templates
Using Templates
5.2 Automatic Template Instantiation
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
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.
Using Templates 5–3
Using Templates
5.3 Implicit Inclusion
2. If the #include for the header file containing the template declaration is
specified with a relative path name, take the following action:
•
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.
•
Otherwise, append the relative path name to all the -I directories
and look in those resulting directories for files with the appropriate
suffixes.
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:
•
Cause the compilation of the file file.cxx
•
Create any instantiations that are required whose definitions are visible to
the compiler
•
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.
5–4 Using Templates
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 application 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
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
Using Templates 5–5
Using Templates
5.3 Implicit Inclusion
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 a file that contains that external. If such a file is
found, add it at the top of the list of object files being searched.
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:
•
Instantiations that appear in explicitly linked object files or libraries hide
instantiations in the repositories.
•
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.
•
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–6 Using Templates
Using Templates
5.4 Manual Template Instantiation
5.4 Manual Template Instantiation
The compiler provides the following methods to instantiate templates
manually:
•
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.
•
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.
HP strongly recommends using the explicit template instantiation syntax
when possible.
•
Using the command-line option method
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 instantiation, 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.
Using Templates 5–7
Using Templates
5.4 Manual Template Instantiation
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];
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 instantiation, 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;
}
5–8 Using Templates
Using Templates
5.4 Manual Template Instantiation
template <class T>
int entity<T>::operator < (const entity<T> &operand) const
{
return member < operand.member;
}
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"
int al[100];
float a2[100];
entity<int> a3[100];
Using Templates 5–9
Using Templates
5.4 Manual Template Instantiation
int main()
{
sort(a1);
sort(a2);
sort(a3);
return EXIT_SUCCESS;
}
// sort.cxx
#include "sort.h"
#include "entity.h"
template <class T> void
{
/*body of sort*/
}
#pragma define_template
#pragma define_template
#pragma define_template
sort (T* array)
sort<int>
sort<float>
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 sort.cxx entity.cxx
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 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–10 Using Templates
Using Templates
5.4 Manual Template Instantiation
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:
•
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.
•
The do_not_instantiate pragma suppresses the instantiation 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 declaration
class A<int>
a member function name
A<int>::f
a static data member name
A<int>::i
a static data declaration
A<int>::i
a member function declaration
void A<int>::f(int, char)
a template function declaration
char* f(int, float)
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 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.
Using Templates 5–11
Using Templates
5.4 Manual Template Instantiation
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 instantiated (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*)
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
5–12 Using Templates
Using Templates
5.5 Advanced Program Development and Templates
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.
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 successfully, 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:
•
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.
•
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
Using Templates 5–13
Using Templates
5.5 Advanced Program Development and Templates
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
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.
5–14 Using Templates
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"
#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
Using Templates 5–15
Using Templates
5.5 Advanced Program Development and Templates
2. Add these instantiations into C.h and change ‘‘instantiate’’ 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 {};
#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
4. Link with the inst object file. It will use instantiations from that file
instead of creating them automatically:
cxx foo.cxx inst.o
To verify that your procedure worked correctly, you can remove all files
from 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 instantiations 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.6). You must then link all the required
individual object files in the repository into your library.
5–16 Using Templates
Using Templates
5.5 Advanced Program Development and Templates
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, iteratively, 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 in the first pass. Any reference arising from an instantiation
in lib_repository in the first pass would be resolved by instantiations in
./cxx_repository in the second pass.
5.6 Template Options
HP C++ includes various template instantiation modes that control when,
where, and how a template is instantiated:
•
Manual instantiaion, automatic instantion, or both
•
Placing templates in the output object or into a repository
•
Using local or external linkage
•
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 instantiation 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:
Using Templates 5–17
Using Templates
5.6 Template Options
-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.
-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 and is the default when -std gnu is
specified.
5–18 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.
-Hx
Stops the cxx command after the prelinker runs and before the final link.
Provided for compatibility with previous versions of C++.
-[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.
-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.
Using Templates 5–19
Using Templates
5.6 Template Options
-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 repositories 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.
If you used both Version 6.n and Version 5.n to build applications, HP strongly
recommends that you use different repositories to contain automatic template
instantiations 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–20 Using Templates
Using Templates
5.7 Compatibility with Earlier Versions of C++
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 -Hx 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 -Hx -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.
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.
Using Templates 5–21
6
Precompiled Headers
Using precompiled header (PCH) files can dramatically reduce compilation
time in environments where:
•
Many primary sources include the same set of headers in the same order.
•
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. HP C++ for Linux
Alpha does not support precompiled headers.
This chapter describes mechanisms used to generate and process PCH files.
Topics include the following:
•
Automatic precompiled header processing
•
Manual precompiled header processing
•
Other ways to control precompiled headers
•
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 processing 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. 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 preprocessing 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.
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:
•
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; };
6–2 Precompiled Headers
Precompiled Headers
6.1 Automatic Precompiled Header Processing
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;
•
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 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.
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:
•
The compiler version, including the date and time the compiler was built
•
The current directory (that is, the directory in which the compilation is
occurring)
•
The command-line options
•
The initial sequence of preprocessing directives from the primary source
file, including #include directives
•
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:
Precompiled Headers 6–3
Precompiled Headers
6.1 Automatic Precompiled Header Processing
// 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.
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:
6–4 Precompiled Headers
Precompiled Headers
6.1 Automatic Precompiled Header Processing
•
The precompiled header file is based on at least one out-of-date header file
but is otherwise applicable for the current compilation.
•
The precompiled header file has the same base name as the source file
being compiled (for example, xxx.pch and xxx.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.
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.
Precompiled Headers 6–5
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:
•
#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.)
•
#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.
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.
6–6 Precompiled Headers
Precompiled Headers
6.4 Performance Issues
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.
–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 (-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–7
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.ps | .txt
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 HP
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 HP 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.
In this release, the shared libraries for the Complex and Task packages have
been removed from the compiler kit. The redistribution kits that ship on the
Tru64 Associated Products disribution have been removed from releases after
Tru64 5.0A. Although applications can continue to use these libraries, they
are linked statically. These libraries may be completely removed in a future
release.
HP recommends that code using complex be migrated as documented in
Section 7.5.4. Code using task should migrate to using Posix Threads (see man
pthread).
The C++ Standard Library 7–1
The C++ Standard Library
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:
-[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 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( ) implementation; this is the
default when compiling -std arm 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.
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 HP 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,
gnu, 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.
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, gnu, 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 iostreams 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.
The C++ Standard Library 7–3
The C++ Standard Library
7.1 Important Compatibility Information
In arm, ms, and ansi modes, specify use of the ANSI iostreams in one of the
following ways:
•
Enter -D_ _USE_STD_IOSTREAM on the command line.
•
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:
•
Enter -D_ _NO_USE_STD_IOSTREAM on the command line.
•
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, gnu, -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 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.
7–4 The C++ Standard Library
The C++ Standard Library
7.1 Important Compatibility Information
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.
// 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;
}
The C++ Standard Library 7–5
The C++ Standard Library
7.1 Important Compatibility Information
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 implementation 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 (myobj);
}
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 (myobj)) == 0)
call_failure_routine();
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 (myobj, 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, gnu, and -std ms, nostdnew is the default. The compiler defines the macro _ _STDNEW when the
-stdnew option is specified.
7–6 The C++ Standard Library
The C++ Standard Library
7.1 Important Compatibility Information
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:
For module to be compiled with -stdnew
1. Include two entry points for your version of global operator new( ):
•
_ _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.
•
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
The C++ Standard Library 7–7
The C++ Standard Library
7.1 Important Compatibility Information
#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);
}
For module to be compiled with -nostdnew
1. Include two entry points for your version of global operator new( ):
•
_ _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.
•
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);
}
7–8 The C++ Standard Library
The C++ Standard Library
7.1 Important Compatibility Information
7.1.5 Support for Global array new and delete Operators
HP 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 mode, -noglobal_array_new is the default. A macro
_ _GLOBAL_ARRAY_NEW is predefined by the compiler when -global_array_new is
used.
The C++ Standard Library 7–9
The C++ Standard Library
7.2 How to Build Programs Using the C++ Standard Library
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 HP 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.
[Linux] Thread Safety
The Standard Library provided with HP C++ for Linux Alpha is not
thread safe.
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:
•
Preallocate 16K bytes of space on the stack.
•
Allocate the required amount of storage dynamically.
7–10 The C++ Standard Library
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 Version 6.n
Standard Library
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.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:
•
Change the name of your #include statement from <vector.h> or
<vector.hxx> to <vector>.
•
Remove the vectordeclare and vectorimplement declarations from your
code.
The C++ Standard Library 7–11
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
•
Change all vector(type) declarations to vector<type>. For example,
vector(int) vi should become vector<int> vi.
•
Note that the following member functions are replaced in the Standard
Library:
Nonstandard Vector Function
Standard Library Vector 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)
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.
•
Another difference in behavior occurs when you specify a negative index for
a vector.
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.
•
When an out-of-bounds error occurs, the Class Library 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:
•
Change the name of your #include statement from <stack.h> or
<stack.hxx> to <stack>.
•
Remove the stackdeclare and stackimplement declarations from your
code.
7–12 The C++ Standard Library
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
•
Change all stack(type) declarations to stack<type, deque<type> >. For
example, stack(int) si should become stack<int, deque<int> > si.
•
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).
•
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( )
pop( )
Does not exist because the stack always is full.
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();
•
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 nonstandard code to use the
Standard Library basic_string:
•
Change #include <string.h> or #include <string.hxx> to #include
<string>.
•
Change all declarations of String to string (uppercase S to lowercase s).
•
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:
The C++ Standard Library 7–13
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
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 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
•
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:
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
7–14 The C++ Standard Library
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
•
The String Package index( ) member function does not exist. The
basic_string library equivalent is find( ).
•
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 s1("abcde");
string s2 = s1(1,3); // does not compile
string s2 = s1.substr(1,3); // ok
•
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 pre-ANSI library, complex objects are not templatized. In the ANSI
library, complex objects are templatized on the type of the real and imaginary
parts. The pre-ANSI library assumes the type is double, whereas the ANSI
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 following is a detailed list of important changes:
•
Change #include <complex.h> or #include <complex.hxx> to #include
<complex>.
•
Change all declarations of complex to complex<double>, for example:
complex c;
Change to:
complex<double> c;
•
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
The C++ Standard Library 7–15
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
Change to:
complex<double> c;
c = polar(c,0.0);
•
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
•
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);
•
The sqr( ) and arg1( ) functions do not exist. 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)
{
T r_val(real(a));
T i_val(imag(a));
return complex<T>
(r_val * r_val i-val * i_val,
2 * r_val * -_val);
}
template <class T>
inline T arg1(const complex<T>& a)
{
T 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);
}
7–16 The C++ Standard Library
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
•
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.
•
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 complex input operator (>>) does not raise an Objection if bad input is
detected; it instead sets input stream’s state to ios::failbit.
•
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.
•
You should no longer need to link your program explicitly 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;
% cxx example.cxx #error
% cxx example.cxx -1m #okay
}
The C++ Standard Library 7–17
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
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:
•
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 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.
•
•
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.hxx>
#include <fstream.h>
#include <fstream.hxx>
#include <strstream.h>
#include <strstream.hxx>
#include <iomanip.h>
#include <iomanip.hxx>
#include <iostream>
#include <fstream>
#include <strstream>
#include <iomanip>
All Standard Library names in the ANSI iostream 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.
7–18 The C++ Standard Library
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
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;
•
•
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 iostream library, make the following changes:
change
change
#include <iomanip.h>
#include <strstream.h>
to
to
#include <iomanip>
#include <iostream>
using namespace std;
#include <strstream>
#include <iostream>
using namespace std;
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 functionality replaced
by construction and destruction of std::istream::sentry objects and
std::ostream::sentry object respectively. For example:
#include <iostream.hxx>
void func (istream &is)
{
if (is.ipfx())
...
is.isfx();
}
|
|
|
|
|
|
|
|
Would be coded as:
|
|
#include <iostream>
|
void func (istream &is)
|
{
|
istream::sentry ipfx(is);
|
if (ipfx)
|
...
|
//is.isfx(); implicit in dtor |
}
|
#include <iostream.hxx>
void func (ostream &os)
{
if (os.opfx())
...
os.osfx();
}
Would be coded as:
#include <iostream>
void func (ostream &os)
{
ostream::sentry opfx(os);
if (opfx)
...
//os.osfx(); implicit in dtor
}
The C++ Standard Library 7–19
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
•
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.
•
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();
}
•
ios::bitalloc( ) is no longer available in the ANSI iostream library.
•
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();
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:
7–20 The C++ Standard Library
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
#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 filebuf(fd) extension, you
could recode:
filebuf fb(fd,buf,BUFLEN); as filebuf fb(fd); and
filebuf fb1(fd); as filebuf fb1(fd);
•
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.
•
The following functions are not defined in the ISO/ANSI Standard. They
are provided in the standard iostream library for backward compatibility
only. Their use is not portable.
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);
•
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:
The C++ Standard Library 7–21
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
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 ios enumerators for controlling the opening of files, ios::nocreate and
ios::noreplace, are not available in the ANSI iostream library.
•
The istream_withassign and ostream_withassign classes are not
available in the ANSI iostream library.
•
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 iostream 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.
7–22 The C++ Standard Library
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
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;
}
In the ANSI iostream library the output is:
^^^^^^^^^x
[^^^^^^^^^x]
In the pre-ANSI iostream library the output is:
x
[x]^^^^^^^^^
•
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
The C++ Standard Library 7–23
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
To obtain output equivalent to the pre-ANSI iostreams, you might do the
following:
cout << hex << showbase << (long) ss << " " << (long) us << endl;
•
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:
#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;
•
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
7–24 The C++ Standard Library
// failbit not set
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
•
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 iostreams 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
•
In the ANSI iostream library, the istream::getline(s,n); function
extracts characters and stores them into successive locations of an array
whose first element is designated by s. If fewer than n characters are
input, failbit is set. This was not the case in the pre-ANSI iostream library.
Consider the following:
#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 C++ Standard Library 7–25
The C++ Standard Library
7.5 Upgrading from the Class Library to the Version 6.n Standard Library
The output in the pre-ANSI iostream library is:
0 123456789
•
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
•
basic_filebuf::setbuf is a protected member function in the ANSI
iostream library. Therefore, the following no longer compiles:
#include <stdlib.h>
int main() {
filebuf fb;
...
fb.setbuf(0,0);
return EXIT_SUCCESS;
}
7–26 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.
HP 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 HP 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 HP
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++:
.
.
.
void might_break(int i)
{
if (i == 1) throw "something!";
if (i == 4) throw 4;
// . . .
}
Handling Exceptions 8–1
Handling Exceptions
8.1 Structure
void p (int i)
{
//
try
//
{
//
might_break(i);
//
}
//
catch (const char *p)
//
{
//
cout << "caught " << p; //
// fix whatever...
//
}
//
}
//
.
.
.
begin try block
begin handler
.
.
.
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 C++ International Standard.
8.2 Run-Time Considerations
HP C++ optimizes the implementation of exception handling for normal
execution, as follows:
•
As much as possible, the overhead for exceptions is incurred when throwing
an exception.
•
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.
8–2 Handling Exceptions
Handling Exceptions
8.2 Run-Time Considerations
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
HP C++ are:
•
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.
•
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.
Handling Exceptions 8–3
Handling Exceptions
8.5 Finding Information about Exceptions
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.7 Catching Signals and C Exceptions
HP 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
8–4 Handling Exceptions
Handling Exceptions
8.7 Catching Signals and C Exceptions
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;
}
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 HP 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.
Handling Exceptions 8–5
Handling Exceptions
8.8 C++ Exceptions and Threads [Tru64]
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.
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);
8–6 Handling Exceptions
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;
printf("begin main\n");
pthread_attr_init(&attr);
Handling Exceptions 8–7
Handling Exceptions
8.8 C++ Exceptions and Threads [Tru64]
// 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);
}
8–8 Handling Exceptions
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 environment for HP 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 HP C++ programs. For more
information, see the DEC FUSE Debugger Manual.
9.1 Debugging C++ Programs
The Ladebug debugger is a source-level debugger that debugs C++ programs
compiled with the HP C++ compiler. For general information on how to use the
Ladebug debugger, see the HP Tru64 UNIX Ladebug Debugger Manual and
the Ladebug(1) reference page.
When debugging C++ code, the debugger supports the following features:
•
C++ names and expressions, including:
Using an explicit and implicit this pointer to refer to class members
The scope resolution operator (::)
Using the Ladebug Debugger 9–1
Using the Ladebug Debugger
9.1 Debugging C++ Programs
The member access operators, period (.) and right arrow (->)
Reference types
Template instantiations
C++ exception handling
•
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
•
Changing the current class scope to set breakpoints and examine static
members of a class that are not currently in scope
•
Calling overloaded functions
•
Debugging programs containing a mixture of C and C++ code
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
9–2 Using the Ladebug Debugger
Using the Ladebug Debugger
9.2 Using Absolute and Relative Path Names
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.
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
Using the Ladebug Debugger 9–3
Using the Ladebug Debugger
9.3 Debugging Programs Containing C and C++ Code
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
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)
"C++"
(Ladebug)
1
(Ladebug)
(Ladebug)
4
(Ladebug)
4
(Ladebug)
print $lang
print sizeof(’a’)
set $lang = "C"
print sizeof(’a’)
print sizeof(int)
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 automatically
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 functions and examine data without
explicitly mentioning the class name. If you do not want to affect the current
9–4 Using the Ladebug Debugger
Using the Ladebug Debugger
9.4 Setting the Class Scope
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.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.
Using the Ladebug Debugger 9–5
Using the Ladebug Debugger
9.5 Displaying Class Information
The whatis command displays the class type declaration, 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.
9–6 Using the Ladebug Debugger
Using the Ladebug Debugger
9.5 Displaying Class Information
Example 9–3 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
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.
Using the Ladebug Debugger 9–7
Using the Ladebug Debugger
9.6 Displaying Object Information
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;
}
(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.
9–8 Using the Ladebug Debugger
Using the Ladebug Debugger
9.7 Displaying Virtual and Inherited Class Information
Example 9–5 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;
}
(Ladebug) whatis b
class T : S {
int j;
T (void);
~T (void);
} b
(continued on next page)
Using the Ladebug Debugger 9–9
Using the Ladebug Debugger
9.7 Displaying Virtual and Inherited Class Information
Example 9–5 (Cont.) Printing Information on a Derived Class
(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.
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
(continued on next page)
9–10 Using the Ladebug Debugger
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) 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;
(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.
Using the Ladebug Debugger 9–11
Using the Ladebug Debugger
9.8 Modifying Class and Object Data Members
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 HP 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:
•
Variables of type const may be assigned a new value.
•
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.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
(ladebug)stop in S::foo; run
[#1: stop in int S::foo(void) ]
[1] stopped at [int S::foo(void):13 0x120000638]
Class type of "this"
13
return i;
Address of "this"
(ladebug)where
>0 0x120000638 in ((S*)0x140000000)−>foo() c++ex.C:13
#1 0x120000788 in main() c++ex.C:28
Function name
Function parameters
ZK−6051A−GE
9–12 Using the Ladebug Debugger
Using the Ladebug Debugger
9.10 Resolving Ambiguous References to Overloaded Functions
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.
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)
Using the Ladebug Debugger 9–13
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
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.
9–14 Using the Ladebug Debugger
Using the Ladebug Debugger
9.10 Resolving Ambiguous References to Overloaded Functions
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 *);
}
(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*)
(continued on next page)
Using the Ladebug Debugger 9–15
Using the Ladebug Debugger
9.10 Resolving Ambiguous References to Overloaded Functions
Example 9–8 (Cont.) Resolving Overloaded Functions by Type Signature
(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
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)
9–16 Using the Ladebug Debugger
Using the Ladebug Debugger
9.11 Setting Breakpoints in Member Functions
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.
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:
Using the Ladebug Debugger 9–17
Using the Ladebug Debugger
9.11 Setting Breakpoints in Member Functions
stop in object.function if & object = = this
stop in objectpointer->function if & objectpointer = = this
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 parameters, 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–18 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 *);
}
(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*)
(continued on next page)
Using the Ladebug Debugger 9–19
Using the Ladebug Debugger
9.11 Setting Breakpoints in Member Functions
Example 9–12 (Cont.) Setting Breakpoints in Specific Overloaded Functions
(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.
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);
(continued on next page)
9–20 Using the Ladebug Debugger
Using the Ladebug Debugger
9.11 Setting Breakpoints in Member Functions
Example 9–13 (Cont.) Setting Breakpoints in All Versions of an Overloaded
Function
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.
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.
Using the Ladebug Debugger 9–21
Using the Ladebug Debugger
9.11 Setting Breakpoints in Member Functions
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)
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 destructor.
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.
9–22 Using the Ladebug Debugger
Using the Ladebug Debugger
9.12 Calling Overloaded Functions
Example 9–17 Calling an Overloaded Function
(Ladebug) set $overloadmenu = 1
(Ladebug) call foo(15)
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.
Using the Ladebug Debugger 9–23
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)
9–24 Using the Ladebug Debugger
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.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.
Using the Ladebug Debugger 9–25
Using the Ladebug Debugger
9.14 Class Templates and Function Templates
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) ]
(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 context, 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.
9–26 Using the Ladebug Debugger
Using the Ladebug Debugger
9.14 Class Templates and Function Templates
Example 9–25 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–27
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
(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
(continued on next page)
9–28 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) 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);
}
(Ladebug) stop in push
[#5: stop in stack<int,100>::push(int) ]
(Ladebug)
Additional limitations for debugging templates include:
•
You cannot specify a template by name in a debugger command. You must
use the name of the instantiation of the template.
•
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).
•
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.
Using the Ladebug Debugger 9–29
Using the Ladebug Debugger
9.15 Debugging C++ Exception Handlers
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.
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)
9–30 Using the Ladebug Debugger
Using the Ladebug Debugger
9.15 Debugging C++ Exception Handlers
As this example shows, you can also set breakpoints in C++ functions used to
handle exceptions as follows:
terminate
unexpected
Gains control when any unhandled exception occurs
Gains control when a function containing an exception specification
tries to throw an exception that is not in the exception specification
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:
•
Derived classes
•
Virtual pointer tables for virtual functions
•
Compiler-generated function members
•
Compiler-generated temporary variables
•
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.
Using the Ladebug Debugger 9–31
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
(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.
9–32 Using the Ladebug Debugger
Using the Ladebug Debugger
9.16 Advanced Program Information: Verbose Mode
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());
(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–33
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.
9–34 Using the Ladebug Debugger
Using the Ladebug Debugger
9.16 Advanced Program Information: Verbose Mode
Example 9–33 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.
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:
•
A class description may be in a library object file that is not linked into the
final debuggable executable.
•
A class description may be in a different shared object than the shared
object you may be trying to debug.
•
The object file that would have contained the class description does not
because it was compiled without the -g option.
Using the Ladebug Debugger 9–35
Using the Ladebug Debugger
9.17 Reducing Object File Size During Debugging
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:
•
Specify -gall_pattern on the command line
•
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.
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.
9–36 Using the Ladebug Debugger
Using the Ladebug Debugger
9.17 Reducing Object File Size During Debugging
(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:
•
Supply -gall on the command line (useful for hand builds):
cxx -g -gall -O0 opaque_file.cxx
•
Supply -gall_pattern (useful for a generic rule in a makefile):
cxx -g -gall_pattern opaque_file.cxx -O0 opaque_file.cxx
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
•
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:
•
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
•
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:
•
Use the -gall option only when you see a class or struct described as
<opaque>.
•
Try to compile as few files with -gall as possible.
Using the Ladebug Debugger 9–37
Using the Ladebug Debugger
9.17 Reducing Object File Size During Debugging
•
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–38 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
and will soon be retired from the Tru64 UNIX platform.
The following restrictions apply for the C++ Class Library:
•
Conflict with redefinition of clear( )
If your program includes both <curses.h> and <iostream.hxx>, HP 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.
•
Because of a bug in the task package, if you are using that package and
you compiled your application with HP C++ Version 6.n, your application
may encounter runtime errors such as segmentation faults. To avoid these
problems, recompile your application specifying the -preempt_symbol
option. For more information about the -preempt_symbol option, see the
cxx(1) reference page.
•
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.
Class Library Restrictions A–1
Class Library Restrictions
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
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.
•
Displacing global operator new in C++ Standard Library/Class Library
If a C++ program defines a global operator new( ) that 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.
A–2 Class Library Restrictions
Class Library Restrictions
•
Restrictions on printing some cases of bool/wchar_t Types with pre-ANSI
Library
Objects of a class which contain a user defined conversion operator to
either bool or wchar_t can not be output directly with cout when including
<iostream.h>. For example, the following program will give compilation
errors indicating that more than one operator "<<" matches these operands:
#include <stdlib.h>
#include <iostream.h>
struct B {
operator bool() { return true; }
};
struct W {
operator wchar_t() { return L’0’; }
};
int main() {
B b;
cout << b << endl; // V6.1 ambiguity error
W w;
cout << w << endl; // V6.1 ambiguity error
return EXIT_SUCCESS;
}
If you try to output the subscript operator of vector<bool> directly with
cout, you will encounter this problem in the library. The following will
generate an ambiguity error:
#include <stdlib.h>
#include <iostream.h>
#include <vector>
int main ()
{
vector<bool> vb;
// V6.1 ambiguity error
cout << vb[1] << endl;
return EXIT_SUCCESS;
}
The workaround is to cast your class to either (bool) or (wchar_t)
respectively. You would code the previous programs as follows:
#include <stdlib.h>
int main() {
B b;
cout << (bool)b << endl;
W w;
cout << (wchar_t)w << endl;
return EXIT_SUCCESS;
}
Class Library Restrictions A–3
Class Library Restrictions
int main ()
{
vector<bool> vb;
cout << (bool)vb[1] << endl;
return EXIT_SUCCESS;
}
•
The Class Library does not include support for 128-bit long doubles.
•
The Class Library has many non-reserved names that are declared in the
global namespace. Using any name that that includes the prefixes cxxl_
or decc$ or any of the following names (except as they are intended to
be used from the Class Library) at global scope can lead to unpredictable
results and should be avoided:
Mutex
Stopwatch
istream
iostream_withassign
ifstream
strstream
cin
lock
resetiosflags
octendl
ws
imanip_*
smanipref_*
iomanipref_*
Messages
setiosfill
String
iostream
ostream_withassign
Iostream_init
ofstream
ios
clog
unlock
dec
ends
setw
omanip_*
imanipref_*
vector
Objection
InternalMutex
ostream
istream_withassign
fstream
streambuf
cout
cerr
setfill
hex
flush
smanip_*
iomanip_*
omainpref_*
stack
setprecision
If linking with complex: complex
If linking with task:
task
timer
randint
Interrupt_handler
A–4 Class Library Restrictions
object
qhead
urand
histogram
sched
qtail
erand
Class Library Restrictions
•
The C++ class library IOStreams does not support denormalized IEEE
numbers. The workaround is to to use libc functions like printf and
scanf instead.
Class Library Restrictions A–5
B
Built-In Functions
This appendix describes built-in functions available when you compile on HP
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)
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 */
#pragma intrinsic (asm, fasm, dasm)
Built-In Functions B–1
Built-In Functions
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:
•
These functions are not user-defined functions.
•
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>
;
<macro_sequence>
:
|
|
|
;
<register_name> :
number
<register_name>
"f" number | "F" number
"r" number | "R" number
/* 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"
B–2 Built-In Functions
Built-In Functions
/* stack pointer: R30 */
| "sp" | "SP" | "$sp" | "$SP"
|
|
|
|
|
"RA"
"PV"
"AI"
"FP"
"RZ"
|
|
|
|
|
"ra"
"pv"
"ai"
"fp"
"rz" | "zero"
/*
/*
/*
/*
/*
return addr:
procedure value:
arg info:
frame pointer:
sink/source: R31 ==
R26
R27
R25
R29
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.
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.
Built-In Functions B–3
Built-In Functions
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");
}
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
"stq
"ldt
"cvtqf
%a0,
%a1,
%f0,
%f0,
%a1, %a1;"
0(%a2);"
0(%a2);"
%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.
•
A return register must be specified in the metalanguage for the result to
appear in the expected place.
•
For intructions that do not take any argument and do not have a return
type, leave out the arguments. For example:
asm("MB");
B–4 Built-In Functions
Built-In Functions
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
_ _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);
Built-In Functions B–5
Built-In Functions
encoded_software_trap
The particular software condition that has occurred.
_ _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).
B–6 Built-In Functions
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 loadlocked/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.
...
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.
Built-In Functions B–7
Built-In Functions
AND Atomic Longword ( _ _AND_ATOMIC_LONG)
The _ _AND_ATOMIC_LONG function performs a bit-wise or arithmetic 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 bit-wise or arithmetic 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, ...);
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.
B–8 Built-In Functions
Built-In Functions
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 loadlocked/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.
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 loadlocked/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.
Built-In Functions B–9
Built-In Functions
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 AND Longword (_ _ATOMIC_AND_LONG)
The _ _ATOMIC_AND_LONG function performs a bit-wise or arithmetic 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 bit-wise or arithmetic 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–10 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 bit-wise or arithmetic 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);
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.
Built-In Functions B–11
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 OR Quadword (_ _ATOMIC_OR_QUAD)
The _ _ATOMIC_OR_QUAD function performs a bit-wise or arithmetic 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 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/storeconditional 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);
B–12 Built-In Functions
Built-In Functions
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/storeconditional 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/storeconditional 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);
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/storeconditional 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.
Built-In Functions B–13
Built-In Functions
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.
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.
B–14 Built-In Functions
Built-In Functions
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);
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_C
_ _MULF_C
_ _ADDS_C
_ _MULS_C
_ _SUBF_C
_ _DIVF_C
_ _SUBS_C
_ _DIVS_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_C
_ _MULG_C
_ _ADDT_C
_ _MULT_C
_ _SUBG_C
_ _DIVG_C
_ _SUBT_C
_ _DIVT_C
They have the following format:
double _ _op{G,T}_C (double operand1, double operand2);
Built-In Functions B–15
Built-In Functions
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.
Copy Sign Built-in Functions
Built-in functions are provided to copy selected portions of single- and doubleprecision, 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.
B–16 Built-In Functions
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);
operand
A double-precision, VAX floating-point number.
Built-In Functions B–17
Built-In Functions
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.
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);
B–18 Built-In Functions
Built-In Functions
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.
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 <stdlib.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.
Built-In Functions B–19
Built-In Functions
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 <stdlib.h>
double _ _SIN (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 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:
•
Returns the complement of the specified bit before being cleared
•
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.
B–20 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.
Test for Bit Set then Set Bit Interlocked ( _ _TESTBITSSI)
The _ _TESTBITSSI function performs the following operations in interlocked
fashion:
•
Returns the value of the specified bit before being set
•
Sets the bit
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);
Built-In Functions B–21
Built-In Functions
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 HP Tru64 UNIX and Linux Alpha data type unsigned _ _int64.
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–22 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 HP 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
pc = 0x3ff81d35c04
pc = 0x3ff81d35e20
__init_cxx_exc
libc.so
libcxx.so
libcxx.so
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 the operating system, rather than C++
code, deletes the storage. The operating system deletes this storage for
these reasons:
•
The compiler does not slow down exit for all C++ programs.
Third Degree Messages C–1
Third Degree Messages
•
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 HP 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;}
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 HP 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:
C–2 Third Degree Messages
Third Degree Messages
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 HP 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:
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:
Third Degree Messages C–3
Third Degree Messages
------------------------------------------------ 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
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
C–4 Third Degree Messages
Third Degree Messages
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
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;
}
Third Degree Messages C–5
Index
A
_ _ABS built-in function, B–6
Access
member, 4–7
_ _ADAWI built-in function, B–6
_ _ADDF_C built-in function, B–15
_ _ADDG_C built-in function, B–15
Additive operators, 2–23
_ _ADDS_C built-in function, B–15
_ _ADDT_C built-in function, B–15
_ _ADD_ATOMIC_LONG built-in function,
B–7
_ _ADD_ATOMIC_QUAD built-in function,
B–7
_ _ALLOCA built-in function, B–15
ALTERNATIVE_TOKENS macro, 2–17
_ _AND_ATOMIC_LONG built-in function,
B–8
_ _AND_ATOMIC_QUAD built-in function,
B–8
Application
deploying, 1–6
Applications
mixed-language, 8–3
Arguments
mechanisms for passing, 2–20
asm intrinsic function, B–1
ASMs, B–1
assign debugger command, 9–12
Assignment
to the this pointer, 4–12
_ _ATOMIC_ADD_LONG built-in function,
B–9
_ _ATOMIC_ADD_QUAD built-in function,
B–9
_ _ATOMIC_AND_LONG built-in function,
B–10
_ _ATOMIC_AND_QUAD built-in function,
B–10
_ _ATOMIC_DECREMENT_LONG built-in
function, B–13
_ _ATOMIC_DECREMENT_QUAD built-in
function, B–13
_ _ATOMIC_EXCH_LONG built-in function,
B–14
_ _ATOMIC_EXCH_QUAD built-in function,
B–14
_ _ATOMIC_INCREMENT_LONG built-in
function, B–12
_ _ATOMIC_INCREMENT_QUAD built-in
function, B–13
_ _ATOMIC_OR_LONG built-in function,
B–11
_ _ATOMIC_OR_QUAD built-in function,
B–12
B
Base class initializers, 4–7
BIASED_FLT_ROUNDS macro, 2–17
64-bit coding guidelines, 4–15
bptr pointer, 9–32
Breakpoints
in C++ exception handlers, 9–30
in constructors and destructors, 9–21
in overloaded functions, 9–18
Index–1
Breakpoints (cont’d)
in templates, 9–26
Buffer, output
flushing, 4–13
Built-in functions, B–1, B–22
_ _ABS, B–6
_ _ADAWI, B–6
_ _ADDF_C, B–15
_ _ADDG_C, B–15
_ _ADDS_C, B–15
_ _ADDT_C, B–15
_ _ADD_ATOMIC_LONG, B–7
_ _ADD_ATOMIC_QUAD, B–7
_ _ALLOCA, B–15
_ _AND_ATOMIC_LONG, B–8
_ _AND_ATOMIC_QUAD, B–8
_ _ATOMIC_ADD_LONG, B–9
_ _ATOMIC_ADD_QUAD, B–9
_ _ATOMIC_AND_LONG, B–10
_ _ATOMIC_AND_QUAD, B–10
_ _ATOMIC_DECREMENT_LONG,
_ _ATOMIC_DECREMENT_QUAD,
_ _ATOMIC_EXCH_LONG, B–14
_ _ATOMIC_EXCH_QUAD, B–14
_ _ATOMIC_INCREMENT_LONG,
_ _ATOMIC_INCREMENT_QUAD,
_ _ATOMIC_OR_LONG, B–11
_ _ATOMIC_OR_QUAD, B–12
_ _CMP_STORE_LONG, B–16
_ _CMP_STORE_QUAD, B–17
Copy sign functions, B–16
_ _COS, B–17
_ _CPYS, B–16
_ _CPYSE, B–16
_ _CPYSEF, B–16
_ _CPYSF, B–16
_ _CPYSN, B–16
_ _CPYSNF, B–16
_ _CVTGF_C, B–17
_ _CVTGQ, B–18
_ _CVTTQ, B–18
_ _CVTTS_C, B–18
_ _DIVF_C, B–15
_ _DIVG_C, B–15
_ _DIVS_C, B–15
Index–2
B–13
B–13
B–12
B–13
Built-in functions (cont’d)
_ _DIVT_C, B–15
Double-precision, floating-point
arithmetic, B–15
_ _FABS, B–18
_ _LABS, B–19
_leadz, B–22
_ _MB, B–19
_ _MEMCPY, B–19
_ _MEMMOVE, B–19
_ _MEMSET, B–19
_ _MULF_C, B–15
_ _MULG_C, B–15
_ _MULS_C, B–15
_ _MULT_C, B–15
PALcodes, B–5, B–6
_ _PAL_BPT, B–5
_ _PAL_BUGCHK, B–5
_ _PAL_DRAINA, B–5
_ _PAL_GENTRAP, B–5
_ _PAL_HALT, B–6
_popcnt, B–22
_poppar, B–22
_ _RPCC, B–20
_ _SIN built-in function, B–20
Single-precision, floating-point arithmetic,
B–15
_ _SUBF_C, B–15
_ _SUBG_C, B–15
_ _SUBS_C, B–15
_ _SUBT_C, B–15
_ _TESTBITCCI, B–20
_ _TESTBITSSI, B–21
_trailz, B–22
_ _TRAPB, B–21
_ _UMULH, B–21
C
C++ predefined function
terminate, 9–31
unexpected, 9–31
call debugger command, 9–22
Class
friend declarations, 4–7
function definitions, 4–9
Class (cont’d)
implementation details, 4–7 to 4–8
initializer, 4–7
library packages, 1–4
member access, 4–7
pointer conversions, 4–9
class debugger command, 9–4
Class Library, 1–4
Third Degree Messages, C–1
_ _CMP_STORE_LONG built-in function,
B–16
_ _CMP_STORE_QUAD built-in function,
B–17
Coding recommendations, 8–3
Common instantiation library
creating, 5–14
_ _COMPAQ_CXX_VER_ _ predefined macro,
2–18
Compatibility, 3–11
Compatibility macros, 2–17
Compiler, 1–1
cxx command, 1–1
-nocleanup option, 8–3
-std ansi option, 4–1
-std arm option, 4–1
-std gnu option, 4–2
-std ms option, 4–3
-std strict_ansi option, 4–3
-std strict_ansi_errors option,
4–3
mixed pointer size options, 3–7
template
advanced program development,
5–12
automatic instantiation, 5–2
compatibility with earlier versions,
5–20
creating common instantiation
library, 5–14
creating libraries, 5–13
dependency management, 5–12
implicit inclusion, 5–3
linking Version 5.n applications
against Version 6.n repositories,
5–21
Compiler
template (cont’d)
linking with Version 5.n
instantiations, 5–21
mixing automatic and manual
instantiation, 5–13
overview, 5–1
repositories, 5–17
template instantiation options, 5–17
Constant
in function returns, 4–9
pointer to, 4–10
Constructors and Destructors, setting
breakpoints in, 9–21
Conversion
explicit type, 2–22
floating-point number, 2–22
integer, 2–21, 2–22
pointer, 4–9
Copy sign built-in functions, B–16
_ _COS built-in function, B–17
_ _CPYS built-in function, B–16
_ _CPYSE built-in function, B–16
_ _CPYSEF built-in function, B–16
_ _CPYSF built-in function, B–16
_ _CPYSN built-in function, B–16
_ _CPYSNF built-in function, B–16
_ _CVTGF_C built-in function, B–17
_ _CVTGQ built-in function, B–18
_ _CVTTQ built-in function, B–18
_ _CVTTS_C built-in function, B–18
cxx compiler command, 1–1
/cxx_repository directory, 5–2
/cxx_repository instantiation file, 5–2
<c_asm.h> header file, B–1
D
dasm intrinsic function, B–1
Debugger, assignments allowed by, 9–12
Debugger commands
assign, 9–12
call, 9–22
class, 9–4
displaying class information, 9–5
print
Index–3
Debugger commands
print (cont’d)
displaying base pointer information,
9–32
stop in, 9–16, 9–17, 9–21
whatis, 9–5, 9–14, 9–25, 9–31
Debugging, 1–5, 9–1 to 9–38
absolute and relative path names, 9–2
class and function scope, 9–5
class and function templates, 9–25
displaying type signature, 9–6
examining data members, 9–4
examining inlined member functiona,
9–11
exception handler support, 9–30
member functions on stack trace, 9–12
mixed C and C++ programs, 9–3
resolving ambiguous references, 9–13
resolving references to objects, 9–10
setting breakpoints in member functions,
9–16
setting class scope, 9–4
setting language mode, 9–4
type casting, 9–23
type transfer, 9–25
verbose mode, 9–31
_ _DECCXX_VER predefined macro, 2–18
Declarations
friend, 4–7
define_template pragma, 2–2
delete operator
size-of-array argument to, 4–13
demangle command, 1–2 to 1–3
Dialect macro, 2–17
Directive
#pragma define_template, 2–2
#pragma environment, 2–3
#pragma ident, 2–4
#pragma instantiate, 2–2
#pragma message, 2–7
#pragma module, 2–9
#pragma once, 2–9
#pragma pack, 2–9
#pragma pointer_size, 2–11, 3–8
#pragma required_pointer_size, 3–8
Index–4
Directive (cont’d)
#pragma required_vptr_size, 2–12,
3–8
#pragma weak, 2–13
#pragma [no]inline, 2–5
#pragma [no]member_alignment, 2–6
#pragma [no]standard, 2–13
_ _DIVF_C built-in function, B–15
_ _DIVG_C built-in function, B–15
Division operator, 2–23
_ _DIVS_C built-in function, B–15
_ _DIVT_C built-in function, B–15
Double-precision, floating-point arithmetic
built-in functions, B–15
E
Enumerated types
incrementing, 4–14
environment pragma, 2–3
Equality operators, 2–23
Error message
missing parenthesis, 4–13
Exception handling, 2–27, 8–1
catching signals and C excpetions, 8–4
finding information, 8–3
structure for, 8–1 to 8–2
threads, 8–5
EXCEPTIONS macro, 2–17
Explicit type conversion, 2–22
Explicit type conversion, language extension,
2–22
Extended Truncated Address Support Option
(XTASO), 3–7
Extensions
source file, 4–14
extern specifier, 3–1
F
_ _FABS built-in function, B–18
fasm intrinsic function, B–1
Faults
segmentation, 4–14
File inclusion directive, #include, 2–28
<float.h> header file, 2–20
Floating-point arithmetic built-in functions,
B–15
Floating-point number
converting to and from an integer, 2–22
FORCE_INSTANTIATIONS macro, 2–17
Friend declarations, 4–7
Function
constant in returns, 4–9
definitions, 4–9
Function returns
constants in, 4–9
Functions, 4–9
G
GLOBAL_ARRAY_NEW macro, 2–17
goto statement, 4–11
Guiding declarations, 2–31
H
Header file
implicit inclusion, 3–5, 3–6
protecting, 2–13
Header files
<float.h>, 2–20
<limits.h>, 2–20
modifying, 3–1 to 3–2
<stdio.h>, 4–15
using existing, 3–1
header files and inheritance, 2–28
I
Identifiers, 2–21
ident pragma, 2–4
IEEE_FP macro, 2–17
#ifdef preprocessor directive, 4–12
Implementation extensions, 2–21
Implementation features, 2–21
Implicit inclusion, 3–5, 3–6
template, 5–2, 5–3
defining file extensions, 5–4
Implicit inclusion
template (cont’d)
disabling, 5–19
enabled by default, 5–19
IMPLICIT_INCLUDE_ENABLED macro,
2–17
IMPLICIT_USING_STD Macro
defined by command line qualifier
_ _IMPLICIT_USING_STD, 2–17
#include directive, 2–28
#include_next pragma, 2–28
Inheritance, 9–24
inheritance and header files, 2–28
Initializers
using base class name with, 4–7
Initializing references, 4–11
In-line assembly code (ASMs), B–1
inline pragma, 2–5
instantiate pragma, 2–2
Instantiation
automatic
linking with, 5–5
directives, 5–7
#pragma define_template, 5–7
#pragma do_not_instantiate, 5–11
#pragma instantiate, 5–11
manual, 5–7
mixed automatic and manual, 5–13
template, 5–1 to 5–21
Instantiation file, 5–2 to 5–5
Integer
converting to and from a floating-point
number, 2–22
Integral conversions, 2–21
Intrinsic functions
ASMs, B–1
intrinsic pragma, 2–5
K
Keywords
conflict resolution, 3–2
Index–5
L
_ _LABS built-in function, B–19
Ladebug debugger, 9–1 to 9–38
Language mode, setting for debugging, 9–4
$lang variable, 9–4
ld linker command, 1–2
Library
linking with non-default, 1–5
Limits
numerical, 2–20
translation, 2–19
<limits.h> header file, 2–20
Linkage
between C and C++, 3–1
specification, 2–26, 3–3
Linkage specifications, 3–3
Link compatibility, 3–12
Linker, 1–2
Local Virtual function table
using to implement polymorphism, 2–32
M
Macro
defined by command line qualifier
_ _ALTERNATIVE_TOKENS, 2–17
_ _BIASED_FLT_ROUNTS, 2–17
_ _EXCEPTIONS, 2–17
_ _FORCE_INSTANTIATIONS, 2–17
_ _GLOBAL_ARRAY_NEW, 2–17
_ _IEEE_FP, 2–17
_ _IMPLICIT_INCLUDE_ENABLED,
2–17
_ _MODEL_ANSI, 2–17
_ _MODEL_ARM, 2–17
_ _NOUSE_STD_IOSTREAM, 2–17
_ _RTTI, 2–17
_ _STD_ANSI, 2–17
_ _STD_ARM, 2–17
_ _STD_GNU, 2–17
_ _STD_MS, 2–17
_ _STD_NEW, 2–17
_ _STD_STRICT_ANSI, 2–17
Index–6
Macro
defined by command line qualifier (cont’d)
_ _STD_STRICT_ANSI_ERRORS,
2–17
_ _USE_STD_IOSTREAM, 2–17
_ _USING_STD, 2–17
_ _X_FLOAT, 2–17
Macro names
predefined, 2–14
_ _MB built-in function, B–19
Member access, 4–7
_ _MEMCPY built-in function, B–19
_ _MEMMOVE built-in function, B–19
Memory management, 4–12
_ _MEMSET built-in function, B–19
Message control option, 2–33, 2–34
Missing parenthesis error message, 4–13
Mixed-Language applications, 8–3
Mixed-language programs, debugging, 9–3
MODEL_ANSI macro, 2–17
MODEL_ARM macro, 2–17
_ _MULF_C built-in function, B–15
_ _MULG_C built-in function, B–15
_ _MULS_C built-in function, B–15
Multiplicative operators, 2–23
_ _MULT_C built-in function, B–15
N
Name demangling, 1–2
Nested enums, 2–29
noinline pragma, 2–5
Non-C++ code, access to, 3–3
NOUSE_STD_IOSTREAM macro, 2–17
[no]standard pragma, 2–13
Numerical limits, 2–20
O
Object
temporary, 2–26
volatile, 4–12
Object construction
implementing polymorphism, 2–32
once pragma, 2–9
OpenMP, 1–9
Operators
additive, 2–23
delete, 4–13
division, 2–23
equality, 2–23
multiplicative, 2–23
remainder, 2–23
shift, 2–23
sizeof, 2–22
Output buffer
flushing, 4–13
$overloadmenu variable, 9–13
P
pack pragma, 2–9
PALcode built-in functions, B–5, B–6
_ _PAL_BPT built-in function, B–5
_ _PAL_BUGCHK built-in function, B–5
_ _PAL_DRAINA built-in function, B–5
_ _PAL_GENTRAP built-in function, B–5
_ _PAL_HALT built-in function, B–6
PCH file
See Precompiled header file
Pointer, 4–9
bound to member function, 4–9
conversions, 4–9
mixing 32-bit and 64-bit sizes, 3–7
to constants, 4–10
pointer_size pragma, 2–11, 3–8
Polymorphism
implementing, 2–32
Pragma
See also Preprocessor directive
define_template, 2–2
environment, 2–3
ident, 2–4
inline, 2–5
instantiate, 2–2
[no]standard, 2–13
once, 2–9
pack, 2–9
pointer_size, 2–11, 3–8
Pragma (cont’d)
#pragma message, 2–7
#pragma module, 2–9
#pragma [no]member_alignment, 2–6
required_pointer_size, 3–8
required_vptr_size, 2–12, 3–8
weak, 2–13
pragma #include_next, 2–28
#pragma ident preprocessor directive, 2–4
#pragma intrinsic preprocessor directive,
B–1
#pragma intrinsic preprocessor directive,
2–5
#pragma once preprocessor directive, 2–9
#pragma pack preprocessor directive, 2–9
Pragmas
intrinsic, 2–5
#pragma [no]inline preprocessor directive,
2–5
Precompiled header file, 6–1 to 6–7
automatic processing, 6–2
controlling, 6–6
manual processing, 6–5
options, 6–7
performance issues, 6–6
Predefined macro, _ _COMPAQ_CXX_VER_ _,
2–18
Predefined macro, _ _DECCXX_VER, 2–18
Predefined macro, compatibility, 2–17
Predefined macro, dialect, 2–17
Predefined macro names, 2–14
Preprocessor directive
#ifdef, 4–12
#pragma, 2–1 to 2–13
#pragma intrinsic, 2–5
Preprocessor directives
#pragma intrinsic, B–1
print debugger command
displaying base pointer information, 9–32
displaying class information, 9–5
Printing base pointer information, 9–32
Product support, xv
Programs
compiling, 1–1
linking, 1–2
Index–7
Protecting header files, 2–13
R
Reader’s comments, sending, xiv
References
initializing, 4–11
Remainder operator, 2–23
required_pointer_size pragma, 3–8
required_vptr_size pragma, 2–12, 3–8
Return mechanisms, 2–20
_ _RPCC built-in function, B–20
RTTI
See Run-Time Type Identification
RTTI macro, 2–17
Run compatibility, 3–13
Run-Time Type Identification (RTTI), 2–31
S
Segmentation faults, 4–14
Shift operators, 2–23
Signal
exception handling, 8–4
_ _SIN built-in function, B–20
Single-precision, floating-point arithmetic
built-in functions, B–15
Size-of-array argument
to delete operator, 4–13
sizeof operator, 2–22
Source compatibility, 3–12
Source file extensions, 4–14
Specification
linkage, 2–26, 3–3
Specifiers
extern, 3–1
type, 2–24, 2–25
typedef, 4–10
Standard Library, 1–3
building programs with, 7–10
compatibility issues, 7–3 to 7–9
global array new and delete, 7–9
-[no]using_std compatibility
switch, 7–3
overriding operator(new), 7–7
Index–8
Standard Library
compatibility issues (cont’d)
pre-ANSI/ANSI iostreams
compatibility, 7–3
pre-ANSI and ANSI operator(new),
7–6
Third Degree Messages, C–1
Standard Template Library
building programs with, 7–10
Statement
goto, 4–11
switch, 4–11
Static object initialization
order of, 2–21
-std ansi mode, 4–1
-std arm mode, 4–1
<stdio.h> header file, 4–15
STD_ANDI macro, 2–17
STD_ARM macro, 2–17
STD_GNU macro, 2–17
STD_MS macro, 2–17
STD_NEW macro, 2–17
STD_STRICT_ANSI macro, 2–17
STD_STRICT_ANSI_ERRORSmacro, 2–17
stop in debugger command, 9–16, 9–17,
9–21
-strict_ansi mode, 4–1
-strict_ansi_errors mode, 4–1
String Library
building programs with, 7–10
_ _SUBF_C built-in function, B–15
_ _SUBG_C built-in function, B–15
_ _SUBS_C built-in function, B–15
_ _SUBT_C built-in function, B–15
switch statement, 4–11
T
Template instantiation, 5–1 to 5–21
Templates
debugging limitations, 9–29
Temporary objects, 2–26
terminate C++ predefined function, 9–31
_ _TESTBITCCI built-in function, B–20
_ _TESTBITSSI built-in function, B–21
Third Degree
C++ Class and Standard Library
Messages, C–1
this pointer, 9–7, 9–12, 9–17, 9–34
this pointer
assignment to, 4–12
system default size, 3–9
Thread safety, 7–10
Translation limits, 2–19
_ _TRAPB built-in function, B–21
Type conversion
explicit, 2–22
typedef specifier, 4–10
Type specifier
_ _unaligned, 2–25
volatile, 2–24
USING_STD macro, 2–17
V
Variable
declared on for statement, 4–14
$verbose variable, 9–31
Virtual function table
local, 2–32
Volatile object, 4–12
volatile type specifier, 2–24
W
weak pragma, 2–13
whatis debugger command, 9–5, 9–14,
9–25, 9–31
X
U
_ _UMULH built-in function, B–21
_ _unaligned type specifier, 2–25
unexpected C++ predefined function, 9–31
USE_STD_IOSTREAM macro, 2–17
XTASO
See Extended Truncated Address Support
Option
X_FLOAT macro, 2–17
Index–9
">
/
Stáhnout
Jen přátelské upozornění. Dokument si můžete prohlédnout přímo zde. Ale co je nejdůležitější, naše AI si ho již přečetla. Dokáže složité věci vysvětlit jednoduchými slovy, zodpovědět vaše otázky v jakémkoli jazyce a pomoci vám rychle se orientovat i v těch nejdelších nebo nejsložitějších dokumentech.
Reklama