更新日付: 2004 年 5 月 27 日 |
Sun[tm] Studio 9、 C++ コンパイラ Readme |
目次
- はじめに
- Sun Studio 9、C++ コンパイラ 5.6 について
- 新規および変更された機能
- ソフトウェアの修正事項
- 問題点と回避策
- 制限事項と互換性の問題
- 記述の誤りの訂正
- ライブラリの再配布について
- 未対応の言語仕様
A. はじめに
この文書には、Sun[tm] Studio 9、C++ 5.6 コンパイラに関する情報が記載されています。この文書では、このコンパイラをバージョン 5.6 の C++ コンパイラと表記します。このリリースで導入された新機能、ソフトウェアの修正事項、既知の問題点、制限事項、互換性の問題について説明します。また、本書の記載内容はソフトウェアマニュアルの情報を更新ないし補充します。
製品マニュアル
- リリースノート (Solaris プラットフォーム): http://docs.sun.com から入手可能です。リリースノートの情報は、各製品の Readme ファイルの情報に優先します。
- Sun Studio 9 のドキュメント: 製品のマニュアルページ、README の HTML バージョン、およびマニュアルは、installation_directory/SUNWspro/docs/ja/index.html からアクセスできます。デフォルトのインストールディレクトリは /opt です。index.html のページから次のマニュアルにアクセスできます。
- C++ FAQ
- C++ ユーザーズガイド
- C++ 移行 Readme
- C++ 移行ガイド
- 標準 C++ ライブラリ・クラスリファレンス / Standard C++ Library Class Reference (英語)
- 標準 C++ ライブラリ・ユーザーズガイド
- Tools.h++ 7.1.0 Readme
- Tools.h++ ユーザーズガイド
- Tools.h++ クラスライブラリ・リファレンスマニュアル
- 区間演算 Readme
- C++ 区間演算プログラミングリファレンス / C++ Interval Arithmetic Programming Reference (英語)
- 数学ライブラリ Readme
- 実行時ライブラリ Readme
- 数値計算ガイド
- インクリメンタルリンカー Readme
- CC(1) のマニュアルページ
- 3C++ マニュアルページ (標準 C++ ライブラリ)
- 3CC4 マニュアルページ (互換モードライブラリ)
- 統合開発環境 (IDE) のドキュメント: IDE にある「ヘルプ」メニューから Sun Studio 9 IDE の各コンポーネントのオンラインヘルプにアクセスできます。
- 開発者向けリソースのポータル: 技術資料、サンプルコード、ドキュメント、ナレッジベースについては、開発者向けポータルの http://developers.sun.com/prodtech/cc を参照してください。
この文書のテキスト版を表示するには、コマンドプロンプトで次のコマンドを入力します。
CC -xhelp=readme
この文書の HTML 版を表示するには、デフォルトのインストールディレクトリにある次のファイルを開きます。
file:/opt/SUNWspro/docs/index.html注 - Sun Studio 9 ソフトウェアが /opt 以外のディレクトリにインストールされている場合は、ご使用のシステムにおける実際のパスを、システム管理者に確認してください。
B. Sun Studio 9、C++ コンパイラ 5.6 について
このリリースの C++ コンパイラは、SPARC (R); プラットフォーム版 Solaris[tm] オペレーティング環境のバージョン 8、9、10 および x86 プラットフォーム版 Solaris オペレーティング環境のバージョン 8、9、10 で利用できます。
この バージョン 5.6 の C++ コンパイラは、バージョン 5.0 から 5.5 の C++ コンパイラのソースコードおよびバイナリコードと上方互換です。すなわち、C++ 5.6 コンパイラを使用して、バージョン 5.0、5.1、5.2、5.3、5.4、5.5 の C++ コンパイラ用に作成されたソースコードをコンパイルできます。また、バージョン 5.0 〜 5.5 の C++ コンパイラによって生成されたオブジェクトコードを C++ 5.6 コンパイラで生成されたオブジェクトコードとリンクできます。リンクする場合は、常に最新のコンパイラ、つまり今回のリリースであるバージョン 5.6 を使用してください。
C++ 5.6 コンパイラには、C++ 4.2 コンパイラ用に作成されたソースコードをコンパイルするための -compat オプションも用意されています。-compat オプションは、バージョン 5.0 から導入されたオプションです。
C. 新規および変更された機能
ここでは、このリリースで C++ コンパイラに新たに追加された機能と変更された機能を説明します。その他の Sun Studio 9 コンポーネントについては、『Sun Studio 9 の新機能』を参照してください。このマニュアルにアクセスするには、http://docs.sun.com に移動します。
-xarch、-xcode、-xmemalign、および -xprefetch オプションのデフォルトを変更、-O オプションの展開の変更によるパフォーマンスの向上
-xprefetch_auto_type および -sync_stdio オプションを追加することによる実行時パフォーマンスの向上
-xpch でのプリコンパイル済みヘッダーファイルの自動生成によるコンパイル時パフォーマンスの向上
デフォルトでの extern インライン関数のサポートと、-xrestrict オプションによる制限付きポインタの認識
#pragma opt 指令および -xmaxopt オプションによる最適化レベルの制御
-xustr オプションによる UTF-16 ワイド文字のサポート強化
-xarch のデフォルトを v8plus に変更
C++ コンパイラがコードを生成するときのデフォルトのアーキテクチャが、v8plus (UltraSPARC) になりました。今後のリリースで、v7 のサポートは廃止される予定です。
新しいデフォルトでは、現在使用されているほぼあらゆるマシンで実行時のパフォーマンスが向上します。ただし、UltraSPARC 以前のコンピュータへの配備を意図したアプリケーションは、そうしたコンピュータ上ではデフォルトで動作しなくなります。アプリケーションがそうしたコンピュータで動作するようにするには、-xarch=v8 でコンパイルしてください。
v8 システムに配備する場合は、各コンパイラコマンド行だけでなく、どのリンク時コマンドでも -xarch=v8 オプションを明示的に指定する必要があります。提供のシステムライブラリは、v8 アーキテクチャで動作します。
v7 システムに配備する場合は、各コンパイラコマンド行だけでなく、どのリンク時コマンドでも -xarch=v7 オプションを明示的に指定する必要があります。提供のシステムライブラリは、v8 命令セットを利用します。Sun Studio 9 リリースの場合、v7 についてサポートされているオペレーティングシステムは、Solaris 8 リリースだけです。v8 命令が検出された場合、Solaris 8 オペレーティングシステムはソフトウェアでその命令を解釈します。このためプログラムは実行されますが、パフォーマンスは低下します。
x86 プラットフォームの場合、-xarch はデフォルトで generic になります。x86 プラットフォームでは、-fast は -xarch=native に展開されることに注意してください。
-xarch の詳細は、C++ マニュアルページの CC(1) か 『C++ ユーザーズガイド』を参照してください。
x86 プラットフォーム向けの -xarch、-xtarget、-xchip のフラグを追加C++ コンパイラが、-xarch、-xtarget、および -xchip 用の新しいフラグをサポートするようになりました。これらの新しいフラグは、x86 プラットフォーム上での Solaris ソフトウェアによる sse および sse2 命令のサポートとの組み合わせで Pentium 3 および Pentium 4 チップを活用することを意図しています。新しいオプションは次のとおりです。
- -xchip=pentium3 は Pentium 3 方式のプロセッサ用に最適化します。
- -xchip=pentium4 は Pentium 4 方式のプロセッサ用に最適化します。
- -xtarget=pentium3 は、-xarch=sse、-xchip=pentium3、-xcache=16/32/4:256/32/4 に設定します。
- -xtarget=pentium4 は、-xarch=sse2、-xchip=pentium4、-xcache=8/64/4:256/128/8 に設定します。
- -xarch=sse は、pentium_pro 命令セットに SSE 命令セットを追加します。
- -xarch=sse2 は、SSE が許可する命令セットに SSE2 命令セットを追加します。
x86 に関する特記事項
Solaris x86 SSE/SSE2 Pentium 4 互換プラットフォームで動作するよう -xarch={sse | sse2} を付けてコンパイルしたプログラムは、SSE/SSE2 対応のプラットフォームでのみ実行する必要があります。SSE/SSE2 に対応していないプラットフォームでそうしたプログラムを実行すると、セグメント例外が発生したり、明示的な警告メッセージなしに不正な結果が発生したりすることがあります。SSE/SSE2 でコンパイルされたバイナリが SSE/SSE2 に対応していないプラットフォームで実行されることのないようにするための OS およびコンパイラに対するパッチが、後日提供される可能性があります。Pentium 4 互換プラットフォームの場合、Solaris 9 update 6 以降の OS リリースは SSE/SSE2 に対応しています。これより前のバージョンの Solaris OS は SSE/SSE2 に対応していません。
このことは、.il インラインアセンブリ言語関数を使用しているプログラムや、SSE/SSE2 命令を利用している __asm() アセンブラコードにも当てはまります。
コンパイルとリンクを別々に行う場合は、必ずコンパイラを使ってリンクし、-xarch={sse | sse2} で適切な起動ルーチンがリンクされるようにしてください。
実際のコンパイル時の適切な -xchip、-xtarget、および -xarch オプションの組み合わせは、次のガイドラインに基づいて決定することができます。
Solaris 9 update 6 か、それ以前の Solaris を実行する Pentium 3 または Pentium 4 で構築を行い、-fast、-xarch=native、または -xtarget=native を指定するかどうか。
この場合、コンパイラは次のように展開します。
Solaris 9 update 5 またはそれ以前の Solaris オペレーティングシステムは、SSE および SSE2 命令をサポートしないため、-xarch は pentium_pro に設定されます (pentium3 あるいは pentium4 ではありません)。
注: これらのバージョンの Solaris ソフトウェアを使用しているかどうかに関係なく、-xarch=sse あるいは -xarch=sse2 を指定することができますが、Solaris 9 update 6 以降の OS リリースは SSE および SSE2 命令をサポートしているため、構築で生成された実行可能ファイルは、そうしたバージョンの Solaris ソフトウェアが動作しているマシンで実行する必要があります。
- -xchip は、適宜 pentium3 または pentium4 に設定されます。
-xcache は、Pentium 3 プロセッサの場合 16/32/4:256/32/4、Pentium 4 プロセッサの場合 8/64/4:256/128/8 に設定されます。
Solaris 9 update 6 以降の Solaris を実行する Pentium 3 または Pentium 4 で構築を行い、-fast、-xarch=native、または -xtarget=native を指定するかどうか。
この場合、コンパイラは次のように展開します。
- -xarch は、Pentium 3 の場合 sse、 Pentium 4 の場合 sse2 に設定されます。
- -xchip は、適宜 pentium3 または pentium4 に設定されます。
- -xcache は、Pentium 3 プロセッサの場合 16/32/4:256/32/4、Pentium 4 プロセッサの場合 8/64/4:256/128/8 に設定されます。
-xarch、-xtarget、および -xchip の詳細は、C++ マニュアルページの CC(1) か 『C++ ユーザーズガイド』を参照してください。
-O の展開を変更(SPARC および x86) -O マクロは、-xO2 ではなく、-xO3 に展開されるようになりました。
このデフォルトの変更によって、実行時のパフォーマンスが向上します。ただし、あらゆる変数を自動的に volatile と見なすことを前提にするプログラムの場合、-xO3 は不適切になることがあります。このことを前提とする代表的なプログラムとしては、専用の同期方式を実装するデバイスドライバや古いマルチスレッドアプリケーションがあります。回避策は、-O ではなく、-xO2 を使ってコンパイルすることです。
-O の詳細は、C++ マニュアルページの CC(1) か 『C++ ユーザーズガイド』を参照してください。
-xprefetch のデフォルトを変更(SPARC のみ) -xprefetch のデフォルトが -xprefetch=auto,explicit になりました。基本的に非線形のメモリーアクセスパターンを持つアプリケーションには、この変更が良くない影響をもたらします。この変更を無効にするには、-xprefetch=no%auto,no%explicit を指定します。
-xprefetch の詳細は、C++ マニュアルページの CC(1) か 『C++ ユーザーズガイド』を参照してください。
-xmemalign のデフォルトを変更(SPARC のみ) v8 アーキテクチャの場合、-xmemalign は -xmemalign=8i になります。v9 アーキテクチャの場合は、デフォルトは -xmemalign=8s です。
-xmemalign の詳細は、C++ マニュアルページの CC(1) か 『C++ ユーザーズガイド』を参照してください。
-xcode のデフォルトを変更(SPARC のみ) v9 の場合、デフォルトは -xcode=abs44 です。v8 の場合は、-xcode=abs32 のままです。x86 プラットフォームでは、-xcode はサポートされません。
注 -- V9 の場合、共有ライブラリ向けのコードで、デフォルトの -xcode=abs44 は使用できません。そのような共有ライブラリの構築は、再配置エラーで失敗します。コンパイルでは、-xcode=abs64 を使用するか、-xcode=pic13 や -xcode=pic32 などの位置独立コードを生成するオプションを使用する必要があります。
-xcode の詳細は、C++ マニュアルページの CC(1) か 『C++ ユーザーズガイド』を参照してください。
-xchip および -xtarget のフラグを追加(SPARC のみ) -xchip および -xtarget オプションが、値として ultra3i および ultra4 をサポートするようになりました。このため、UltraSPARC IIIi および UltraSPARC IV 用に最適化されたアプリケーションを構築できます。
extern インライン関数C++ 規格では、static 宣言しない限り、インライン関数は非インライン関数のように外部リンケージを持つことになっています。C++ では、5.6 になって初めて、デフォルトでインライン関数に外部リンケージを持たせるようになりました。インライン関数をライン外で生成する必要がある場合は (たとえば、そのアドレスが必要な場合など)、コピー 1 つだけが最終プログラムにリンクされます。以前は、コピーを必要とするオブジェクトファイルが、それぞれローカルリンケージを持つ専用のコピーを持っていました。
この extern インライン関数の実装方法は、プログラムの動作は従来と同様に規格に適合しており、以前のコンパイラバージョンによって作成されたバイナリファイルと互換性があります。古いバイナリはインライン関数のローカルコピーを複数持っていることがありますが、新しいコードでは、extern インライン関数のコピー数は、最大 1 つになります。
この extern インライン関数の実装方法は、このリリースに含まれている C 5.6 コンパイラを使用する C99 版のインライン関数と互換性があります。すなわち、extern インライン関数に関する C および C++ 規則に従うことによって、同じインライン関数を C および C++ ファイルの両方で定義でき、その場合でも、最終プログラムでの外部関数のコピー数は 1 つだけになります。
しかし、両コンパイラの間には、非インライン関数がインライン関数をサポートする、すなわち、インライン関数に外部定義を提供することを C 言語が認めているという点で互換性の問題が 1 つあります。C++ 言語には、そのような概念はありません。このため、この 2 つのインライン化手法が混在していると、リンカーエラーになります。次の例で考えてみます。
// ファイル a.h #ifdef __cplusplus extern "C" { #endif inline int f() { return 1; } #ifdef __cplusplus } #endif // ファイル b.c #include "a.h" int g() { return f(); }ファイル b.c のインライン関数 f は、インライン関数のサポートを明示していない関数によってサポートされます。
// ファイル c.c int f() { return 1; }以下に示すように、 C++ での f と c.c を混在させると、定義が重複していることを示すエラーが、リンカーから返されます。
// ファイル d.cc #include "a.h" int h() { return f(); }この解決策は、関数 f がインライン関数をサポートしていることを C コンパイラに知らせることです。c.c の次の実装を使用します。
// ファイル c.c #include "a.h" extern inline int f();-xautopar、-xvector、-xdepend によるループの最適化C++ コンパイラが、計算の並列化が可能なループを最適化するための次のオプションをサポートするようになりました。これらのオプションは、-xO3 以上の最適化レベルで使用する必要があります。
- -xautopar
- -xvector
- -xdepend
詳細は、C++ マニュアルページの CC(1) の -xautopar、-xvector、および -xdepend の説明をお読みください。
ポインタに関する -xrestrict の制約C++ は、C99 で導入された restrict キーワードをサポートしていません。ただし、この C++ コンパイラでは、C コンパイラのオプション -xrestrict を受け付けるようになっています。
このオプションは、コンパイル時に関数に関して、ポインタ型の関数パラメータが、同じオブジェクト、またはオーバーラップするオブジェクトを参照していないとみなします。このことはヘッダーファイルに定義されているインライン関数には当てはまらないことがあり、C よりも C++ でより問題となります。
詳細は、C++ マニュアルページの CC(1) の -xrestrict の説明をお読みください。
#pragma opt および -xmaxopt 最適化レベルの制御#pragma opt 指令とコマンド行オプションの -xmaxopt を組み合わせて、コンパイラが個々の関数に適用する最適化レベルを指定することができます。
この組み合わせは、たとえば、スタックフレームの削除などのコード拡張を避けるために、特定の関数について最適化レベルを下げたり、あるいはその逆に、特定の関数について最適化レベルを上げたりする必要がある場合に有用です。
詳細は、C++ マニュアルページの CC(1) の -xmaxopt の説明をお読みください。
新しいオプション -xprefetch_auto_type による実行時パフォーマンスの向上新しいオプション -xprefetch_auto_type を利用することによって、直接メモリーアクセスに対してプリフェッチが生成されるのと同じ方法で、-xprefetch_level=[1|2|3] が指示するループに対して間接プリフェッチを生成することができます。
-xalias_level などのオプションと組み合わせると、-xprefetch_auto_type の最適化のメリットを増すことができます。これらのオプションはメモリー別名のあいまいさを排除する情報を生成するのに役立つため、間接プリフェッチ候補の計算の積極性に影響し、自動的な間接プリフェッチの挿入を促進します。
-xprefetch_auto_type の詳細は、C++ マニュアルページの CC(1) か 『C++ ユーザーズガイド』を参照してください。
新しいオプション -sync_stdio による実行時パフォーマンスの向上C++ の iostreams および C の stdio の同期が、実行時パフォーマンスの低下の原因の 1 つであることがあります。そうした同期は C++ 規格では必須で、デフォルトでは、コンパイラはそうした同期を有効にします。ただし、この同期は、-sync_stdio=no を指定することによって無効にすることができます。
-sync_stdio オプションの詳細は、『C++ ユーザーズガイド』か CC(1) のマニュアルページを参照してください。また、この問題の解決策については、『C++ FAQ』も参照してください。
-xustr による UTF-16 のサポート強化UTF-16 文字列リテラルのサポートは、バージョン 5.5 の C++ コンパイラで導入されました。このリリースでは、文字列の U"x" 構文に似た U'x' 構文を使用する UTF-16 文字リテラルもサポートされるようになっています。UTF-16 文字リテラルを認識できるようにするには、同じ -xustr オプションが必要です。
このリリースではまた、UTF-16 の文字および文字列リテラル内の数値エスケープもサポートしています。これは、通常の文字および文字列リテラル内の数値エスケープに似ています。以下に例を示します。
U"ab\123ef" // 文字の 8 進表現 U'\x456' // 文字の 16 進表現詳細は、C++ マニュアルページの CC(1) の -xustr の説明を参照してください。
-xpch によるプリコンパイル済みヘッダーファイルの自動生成このリリースの C++ コンパイラでは、プリコンパイル済みのヘッダー機能が拡張され、コンパイラの側でプリコンパイル済みヘッダーファイルを自動的に生成できるようになっています。ただし、これまでどおり、プリコンパイル済みヘッダーファイルを手動で生成することもできます。 コンパイラの新しい機能の詳細は、CC(1) のマニュアルページの -xpch オプションの説明を参照してください。また、CCadmin(1) のマニュアルページも参照してください。
D. ソフトウェアの修正事項
ここでは、次のソフトウェアの修正事項について説明します。
- サイズの大きい 10 進整定数の適切な解釈
- 注:あいまいな表現 : コンストラクタ呼び出しまたは関数へのポインタ
- Solaris 8 update 2 およびパッチにおける __ctype 未定義エラーの修正
- -instance=static および -instance=semiexplicit とテンプレート内の静的変数のサポート
- 関数にローカルな静的変数に対する extern インライン関数の動作の違い
- テンプレートの構文エラーの検出
サイズの大きい 10 進整定数の適切な解釈
C++ 規格では、接尾辞のない 10 進整定数は、値が int に収まる場合 int、そうでない場合 long int として扱うとなっています。ただし、値が long int にも収まらない場合の結果は定義されていません。
32 ビットモードの場合、型 int と long のサイズおよびデータ範囲は同じです。C++ コンパイラは 1990 C 規格の規則に従って、INT_MAX+1 と LONG_MAX の範囲の値を unsigned long として扱っていました。一部プロプラムでは、この扱いが原因で予期しない結果が生じていました。
1999 C 規格では、接尾辞のない 10 進整数に関するこの規則が変更され、unsigned 型として扱われなくなりました。型は、int、long、long long のうちの最初に値を表せる型になります。
標準モードでは、C++ 5.6 はこの C99 規則に従いますが、-compat=4 モードではこれまでどおり C90 の方に規則に従います。(-compat=4 モードでは、コンパイラは C++ 4.2 コンパイラのように動作します。)
サイズの大きい 10 進整数を unsigned として扱いたい場合の移植可能な解決策は、u または U 接尾辞を使用することです。その他の型にも、それぞれ接尾辞を使用することができます。以下に例を示します。
// note:2147483648 == (INT_MAX+1) 2147483648 // (signed) long long 2147483648LL // (signed) long long 2147483648U // 2147483648u と同じ注:あいまいな表現 : コンストラクタ呼び出しまたは関数へのポインタ
C++ では、あるときは宣言と解釈されたり、またあるときは式と解釈される可能性がある文があります。C++ のあいまい排除規則では、ある文を宣言文とみなすことができる場合は、その文は宣言文とすることになっています。
以前のバージョンのコンパイラでは、次のような事例を誤って解釈していました。
struct S { S(); }; struct T { T( const S& ); }; T v( S() ); // ???このプログラマはおそらく、最後の行で S 型の一時的な値で初期化される変数 v を定義するつもりでした。以前のバージョンのコンパイラは、この文をそのように解釈していました。
しかし、宣言コンテキスト内のコンストラクト、"S()" は、"S 型の値を戻すパラメータのない関数" を意味する抽象宣言子 (識別子のない抽象宣言子) とみなすこともできます。この事例では、関数ポインタ、"S(*)()" に自動的に変換されています。この文はまた、戻り値が T 型で、パラメータが関数ポインタ型の関数 v の宣言としても有効です。
現在ではコンパイラが正しい解釈をするようになったので、このプログラマが意図したようにならない可能性があります。
あいまいにならないようにコードを修正するには、次の 2 通りの方法があります。
T v1( (S()) ); // v1 は、初期化されるオブジェクト T v2( S(*)() ); // v2 は、関数1 行目の 1 対の余分な括弧は、v1 の構文が関数宣言としては不正であるので、"S 型の一時的な値で初期化される T 型のオブジェクト" という意味にしか解釈できません。
同様に、コンストラクト、 "S(*)()" は値とは考えられないので、関数宣言の意味にしか解釈できません。
最初の行は、次のように書くこともできます。
T v1 = S();意味は完全に明確になりますが、この初期設定の形式では、通常はそうでもないとはいえ、一時的な値として非常に大きな値が生成されることがあります。
次のようにコーディングするのはお勧めできません。 その理由は、意味が不明確で、コンパイラが異なると結果が異なる可能性があるからです。
T v( S() ); // 推奨しないSolaris 8 update 2 およびパッチにおける __ctype 未定義エラーの修正
Solaris 8 オペレーティングシステムに問題があり、<stdlib.h> の MB_CUR_MAX を使用すると、C++ コンパイラから「__ctype は定義されていません」というエラーが返されることがあります。
このバグは、Solaris 8 update 2 オペレーティングシステムで修正されました。これは、Solaris パッチ 109607-01 (SPARC)、109608-01 (x86) でも修正されています。
このアップデート版またはパッチをインストールしていない場合、この問題を回避するには、ヘッダー <stdlib.h> をインクルードする前に標準ヘッダー <ctype.h> をインクルードしてください。
-instance=static および -instance=semiexplicit とテンプレート内の静的変数のサポート
以前のバージョンの C++ コンパイラでは、テンプレート内の静的変数に対する静的インスタンスメソッドと半明示的インスタンスメソッドがサポートされていませんでした。バージョン 5.2 〜 5.6 の C++ コンパイラには、この制約はありません。
関数にローカルな静的変数に対する extern インライン関数の動作の違い
ARM 規則では、extern インライン関数の関数にローカルな静的変数はファイルに対して静的です。ISO 規格では、extern インライン関数の関数にローカルな静的変数は、コンパイルユニット間で共有されるグローバル変数です。
バージョン 5.0 および 5.1 の C++ コンパイラでは、互換 (-compat) および標準 (デフォルトのモード) のどちらのモードでも ARM の動作が実装されていました。これに対し、バージョン 5.2、5.3、5.4、5.5、および 5.6 の C++ コンパイラでは、互換モードで ARM の動作、標準モードで ISO の動作が実装されています。以下にその例を示します。
one.cc inline int inner() { static int variable = 0; return variable++; } int outer() { return inner(); } two.cc inline int inner() { static int variable = 0; return variable++; } int main() { return inner() + outer(); }互換モード (-compat) でコンパイルした場合、この 2 つの変数は異なり、main の結果は 0 になります。
標準モード (デフォルトモード) でコンパイルした場合は、この 2 つの変数が同じになり、main の結果は 1 になります。標準モードで古い動作にするには、インライン関数を static に宣言します。
テンプレートの構文エラーの検出
次のテンプレートの構文は不正ですが、Sun C++ 4 および 5.0 では、エラーになりませんでした。バージョン 5.1 〜 5.6 の C++ コンパイラでは、標準モード (デフォルトのモード) のコンパイルで、構文エラーとして報告されます。
template<class T> class MyClass<T> { ... }; // 定義エラー template<class T> class MyClass<T>; // 宣言エラーどちらの場合も、「MyClass<T>」の「<T>」は不正で、次の例に示すように削除する必要があります。
template<class T> class MyClass { ... }; // 定義 template<class T> class MyClass; // 宣言
E. 問題点と回避策
ここでは、これまでにわかっているソフトウェアの問題点とその回避策について説明します。最新情報またはパッチについては、http://developers.sun.com/prodtech/cc/support_index.html を参照してください。
- -instances=static で -xipo または -xcrossfile があると、リンクに失敗する
- 前処理済みの .i ファイルがコンパイルエラーを生成する
- 言語間リンクエラー
- リンク時の名前符号化の問題
- デバッグツールから、メンバー関数に余分な先行パラメータがあるという誤ったメッセージが返される
- 大域的ではない名前空間のオブジェクトをテンプレートから参照できない
- 名前空間内の #pragma align と符号化名
- 関数の多重定義の解決
- 代替スレッドを使用したマルチスレッド対応の C++ プログラムは、Solarais 8 でデバッグするとハングアップする
-instances=static で -xipo または -xcrossfile があると、リンクに失敗する
テンプレートオプションの -instances=static (または -pto) を -xcrossfile や -xipo オプションと組み合わせると、機能しません。この組み合わせを使用したプログラムは、リンクに失敗することがよくあります。
-xcrossfile または -xipo オプションを使用する場合は、デフォルトのテンプレートコンパイルモデルの -instances=global を使用してください。
一般に、-instances=static (および -pto) は使わないでください。使うメリットはすでになく、依然として、『C++ ユーザーズガイド』で説明しているデメリットがあります。
前処理済みの .i ファイルがコンパイルエラーを生成する
__global は、新しい xldscope コンパイラオプションの一部として C++ 5.5 で追加されたキーワードです。前処理済みの .i ファイルを古いコンパイラを使用して生成し、続いてこの .i ファイルをバージョン 5.5 または 5.6 でコンパイルする場合は、 .i ファイル内でキーワード __global が識別子として使用されていると、エラーメッセージが表示されることがあります。
この問題を解決するには、.i ファイルの先頭に #pragma disable_ldscope を追加してください。このコードが古いコンパイラを対象としている場合、新しいリンカースコーピングキーワード (__global など) は使用できません。ほかのファイルにインクルードする場合は、.i ファイルの最後に #pragma enable_ldscope という行を追加できます。
言語間リンクエラー
-xlang=f77 コマンドを実行すると、コンパイルプロセス中にリンカーエラーが発生します。エラーを回避するとともに適切な実行時ライブラリをインクルードするには、代わりに -xlang=f77,f90 を実行します。
リンク時の名前符号化の問題
次の場合に、リンク時に問題が発生することがあります。
- const パラメータ付きで宣言されている関数が、別の場所で const パラメータなしで宣言されている。
例:
void foo1(const int); void foo1(int);これらの宣言は等価ですが、コンパイラは異なる符号化名を付けます。この問題を回避するには、値のパラメータを const として宣言しないでください。たとえば、関数定義の本体などのあらゆる場所で void foo1(int); を使用します。
- 関数に同じ複合型のパラメータが 2 つあり、一方のパラメータだけ typedef で宣言されている。
例:
class T; typedef T x; // foo2 は複合型 (ポインタまたは配列) // パラメータ型 void foo2(T*, T*) void foo2(T*, x*); void foo2(x*, T*); void foo2(x*, x*);すべての foo2 宣言は等価で、これらは同様:w に符号化される必要があります。しかし、コンパイラは一部に異なった符号化を行なっています。この問題を回避するには、一貫して typedef を使用します。
typedef を一貫して使用できない場合は、回避策として、関数を定義しているファイルに weak シンボルを使用し、宣言とその定義を等価にします。以下に例を示します。
#pragma weak "__1_undefined_name" = "__1_defined_name"
注 -- 一部の符号化名は、ターゲットアーキテクチャによって異なります。たとえば、 size_t は SPARC V9 アーキテクチャでは unsigned long ですが、それ以外のアーキテクチャでは、unsigned int です。これは、2 つの異なったバージョンの符号化名がそれぞれ 1 つのモデルに存在するケースです。このような場合は、2 つのプラグマを用意し、適切な #if 指令で制御する必要があります。
詳細は、『C++ 移行ガイド』を参照してください。このマニュアルの HTML 版にアクセスするには、ブラウザで file:/opt/SUNWspro/docs/ja/index.html を開きます。
注 -Sun Studio 9 ソフトウェアが、/opt 以外にインストールされている場合は、 ご使用のシステムにおける実際のパスを、システム管理者に確認してください。
デバッグツールから、メンバー関数に余分な先行パラメータがあるという誤ったメッセージが返される
互換モード (-compat=4) では、C++ コンパイラはメンバー関数を指すポインタのリンク名を正しく符号化しません。このエラーのため、復号化プログラムおよび、 dbx や c++filt などのデバッグツールから、メンバー関数に余分な先行パラメータ (メンバー関数が属しているクラスタイプを示す) があると報告されます。この問題を解決するには、-Qoption ccfe -abiopt=pmfun1 フラグを追加します。しかし、一般に、このフラグを使用してソースをコンパイルすると、このフラグなしでコンパイルしたソースとの間のバイナリレベルの互換性が失われることがあります。標準モード (デフォルトモード) では、この問題は起きません。
大域的ではない名前空間のオブジェクトをテンプレートから参照できない
プログラムでテンプレートと静的オブジェクトを使用していると、未定義シンボルのリンク時エラーが発生します。現在コンパイラは、大域的でない名前空間スコープのオブジェクトに対するテンプレートからの参照をサポートしません。次の例で考えてみてください。
static int k; template<class T> class C { T foo(T t) { ... k ... } };この例では、テンプレートクラスのメンバーは静的な名前空間スコープ変数を参照します。名前空間スコープはファイルスコープを含むことに注意してください。コンパイラは、静的な名前空間スコープ変数を参照するテンプレートクラスのメンバーをサポートしません。複数のコンパイル単位からテンプレートがインスタンス化されると、各インスタンスは異なる k を参照します。 つまり、C++ ODR (One-Definition Rule) 違反が発生し、コードは定義されていない動作を起こします。
ユーザーは、k をどのように使用したいか、k によってどのような効果を得たいかにもとづき、次に示す代替方法を実施できます。2 番目のオプションは、クラスのメンバーの関数テンプレートにのみ使用できます。
- 変数に外部リンケージを持たせる
int k; // 静的ではないすべてのインスタンスは、k の同じコピーを使用します。- 変数をクラスの静的メンバーにする
template<class T> class C { static int k; T foo(T t) { ... k ... } };静的なクラスメンバーは外部リンケージを持ちます。C<T>::foo のインスタンスが使用する k はそれぞれ異なります。C<T>::k のインスタンスは、他の関数で共有することができます。通常はこのオプションが使用されます。変数を関数に対してローカルにする
template<class T> class C { T foo(T t) { static int k; ... k ... } };各 C<T>::foo のインスタンスは、関数の外部からは見えない独自の k のコピーを使用します。
名前空間内の #pragma align と符号化名
名前空間内で #pragma align を使用する場合は、符号化名を使用する必要があります。たとえば、次のコードでは、#pragma align 文は何の働きもしません。この問題を解決するには、#pragma align 文内の a、b、および c をそれぞれの符号化名に置き換える必要があります。
namespace foo { #pragma align 8 (a, b, c) // 有効でない // 符号化名を使用: #pragma align 8 (__1cDfooBa_, __1cDfooBb_, __1cDfooBc_) static char a; static char b; static char c; }関数の多重定義の解決
C++ コンパイラの以前のリリースでは、C++ 標準の要件に従って関数の多重定義の解決を行いませんでした。今回のリリースでは、多重定義された関数の呼び出しを解決して、多くのバグを修正しています。特に、コンパイラは、呼び出しが実際にあいまいな場合は関数をピッキングしたり、実際にはそうでない場合にも、呼び出しがあいまいであると表示したりする場合がありました。
あいまいであることを示すメッセージに関する回避策には、不要なものもあります。以前には報告されなかった、あいまいに関する新しいエラーが発生しています。
あいまいな関数呼び出しの主な原因の 1 つは、組み込み型のサブセットにさえも多重定義が発生することです。
int f1(short); int f1(float); ... f1(1); // あいまい。 "1" は int 型 f1(1.0); // あいまい、"1.0" は double 型この問題を修正するには、f1 を決して多重定義しないか、あるいは拡張されないすべての型 (int、unsigned int、long、unsigned long、double) で多重定義を行います (long long、unsigned long long、 および long double 型がある場合もあります)。
もう 1 つの主な原因はクラスにおける型変換関数で、特に多重定義された演算子が存在する場合です。
class T { public: operator int(); T(int); T operator+(const T&); }; T t; 1 + t // あいまいこの演算は、次のように解決できるので、あいまいです
T(1) + t // 多重定義された演算子 1 + t.operator int() // 組み込みの int を追加多重定義された演算子または型変換関数を使用できますが、両方使用すると、あいまいと判断されます。
実際、型変換関数そのものは、あいまいと判断されたり、意図しなかった場所で変換が発生したりすることがたびたびあります。変換を有効にする必要がある場合は、型変換関数ではなく名前付き関数を使用してください。たとえば、operator int(); の代わりに int to_int(); を使用します。
この変更により、演算子 1 + t はあいまいではなくなります。T(1) + t としか解釈できません。ほかの解釈が必要な場合は、次のように記述する必要があります。
1 + t.to_int().代替スレッドを使用したマルチスレッド対応の C++ プログラムは、Solarais 8 でデバッグするとハングアップする
/usr/lib/lwp/ にある代替スレッドライブラリを使用して構築した、マルチスレッド対応の C++ プログラムは、Solari 8 オペレーティングシステムでデバッグしようとすると、ハングアップします。-R /usr/lib/lwp コンパイラオプションで構築した 32 ビットマルチスレッド対応の C++ プログラムは、dbx で実行するとハングアップします。-R /usr/lib/lwp/sparcv9 コンパイラオプションで構築した 64 ビットマルチスレッド対応の C++ プログラムは、実行時検査を行なっている場合には特に、ハングアップする可能性があります。
この現象は、C++ コードを標準 (デフォルト) モードで (-compat=5 コンパイラオプションを使用して) コンパイルした場合に起こります。 互換モードで (-compat コンパイラオプションを使用して) コンパイルした場合には起こりません。
パフォーマンス調整の目的に代替スレッドライブラリの使用を考えているのであれば、まず、デフォルトのスレッドライブラリを使用して、マルチスレッド対応のプログラムをデバッグし、代替スレッドライブラリは、その後で使用してください。
この問題は、Solaris 8 でのみ発生します。
F. 制限事項と互換性の問題
ここでは、制限事項およびシステムまたはその他のソフトウェアとの互換性の問題について説明します。Sun Studio 9 リリースの最新情報については、http://docs.sun.com から入手可能なリリースノートを確認してください。リリースノートの情報は、各製品の Readme ファイルの情報に優先します。
-xia と -library=stlport4 の互換性の問題
C++ 区間演算機能を STLport C++ ライブラリとともに使用することはできません。-xia オプションを使用するプログラムは、『C++ Interval Arithmetic Programming Reference』の説明どおりにコンパイルおよびリンクすることしかできません。
C++ 共有ライブラリのパッチ
各対応プラットフォームについて、今回のリリースの Sun Studio 9 でサポートする Solaris オペレーティング環境のバージョンごとに SUNWlibC パッチが 1 つ用意されています。このパッチは、コンパイルに使用するシステムだけでなく、作成されたプログラムを稼働させるすべてのシステムにインストールする必要があります。これらのパッチをインストールしないと、一部のプログラムがリンクされなかったり、実行時エラーで異常終了したりすることがあります。たとえば、リンカーから次のようなメッセージが報告されることがあります。
Undefined symbol First referenced in file std::ostream &operator<<(std::ostream&,const RWCString&) test.o ld: fatal: Symbol referencing errors.No output written to test次のようなエラーメッセージが返されることもあります。
Hint: try checking whether the first non-inlined, non-pure virtual function of ...この Sun Studio 9 リリース用の必須および任意パッチについては、Sun Studio 9 の Web サイト、http://developers.sun.com/prodtech/cc/support_index.html を参照してください。
コンパイラのバージョン間の互換性の問題
ここでは、C++ コンパイラバージョン 4.0、4.1、4.2 と次に示すバージョン間の互換性の問題について説明します。
- Sun WorkShop C++ (5.0) コンパイラ
- Forte Developer 6 C++ (5.1) コンパイラ
- Forte Developer 6 update 1 C++ (5.2) コンパイラ
- Forte Developer 6 update 2 C++ (5.3) コンパイラ
- Forte Developer 7 C++ (5.4) コンパイラ
- Sun Open Net Environment (Sun ONE) Studio 8 C++ (5.5) コンパイラ
- Sun Studio 9 (5.6) コンパイラ
- キャッシュバージョンの違いによるコンパイルエラー
- C++ インタフェースの互換性の問題
- Tools.h++ の使用
- 複数のテンプレートリポジトリの使用 -ptr オプションが無視される
- const メンバー関数のポインタを含む 4.0.1 ライブラリとのリンク
- 以前のコンパイラでコンパイルしたライブラリとのリンク
- 異なるバージョンで生成されたオブジェクトコードの混在
キャッシュバージョンの違いによるコンパイルエラー
コンパイラを変更するときは、必ず SunWS_cache サブディレクトリを含むすべてのディレクトリに対して CCadmin -clean (rm -rf SunWS_cache でも可) を実行してください 。この操作を行わないと、次のようなコンパイルエラーが発生することがあります。
- SunWS_cache: Error: Database version mismatch
<path>/SunWS_cache/CC_version.
- "<path>/SunWS_cache/CC_state",
line 3: Error: "" not allowed here. ** Assertion ** : 0
C++ インタフェースの互換性の問題
バージョン 5.0 〜 5.6 の C++ コンパイラとバージョン 4.0、4.1、および 4.2 の C++ コンパイラとの間にバイナリレベルの互換性はありません (5.0 〜 5.6 のコンパイラによるコンパイル時に -compat オプションを使用した場合を除く)。これは、ANSI/ISO C++ 規格に定義されている仕様に合わせて、クラスの配置や呼び出しの順序、名前の符号化方法が変更されたことが原因です。
バージョン 5.0 〜 5.6 の C++ コンパイラには、バイナリレベルの互換性があります。
詳細は、『C++ 移行ガイド』を参照してください。このマニュアルの HTML 版にアクセスするには、ブラウザで file:/opt/SUNWspro/docs/ja/index.html を開きます。Solaris プラットフォームの場合、デフォルトのインストールディレクトリは、/opt です。Sun Studio 9 ソフトウェアが /opt 以外のディレクトリにインストールされている場合は、ご使用のシステムにおける実際のパスを、システム管理者に確認してください。
Tools.h++ の使用
C++ コンパイラは、デフォルトで標準の iostream を使用します。Tools.h++ を標準モードで使用する場合は、-library=rwtools7_std オプションを使用するか、または次に示すように、コンパイラオプションに libiostream 指定する必要があります。
example% CC -library=rwtools7_std foo.cc -> 標準の iostreams を使用 example% CC -library=rwtools7_std foo.cc -> 従来の iostreams を使用ただし、(-compat コンパイラオプションを使用した) 互換モードでは、標準ライブラリが使用できないため、-library=rwtools7_std を指定することはできません。
example% CC -compat foo.cc -library=rwtools7 -> 互換モードでは標準ライブラリを使用できない-library=rwtools7、-library=rwtools7_dbg、-library=rwtools7_std、また-library=rwtools7_std_dbg を -library=stlport4 とともに使用しないでください。Tools.h++ は STLport ではサポートされていません。
-library=rwtools7_std オプションと -library=rwtools7,iostream オプションで生成されたバイナリ間に互換性はありません。これらのオプションをどれか使用した場合は、コンパイルおよびリンクのあらゆる CC コマンドで同じオプションを使用してください。
また、『C++ 移行ガイド』も参照してください。このマニュアルの HTML 版にアクセスするには、ブラウザで file:/opt/SUNWspro/docs/ja/index.html を開きます。Solaris プラットフォームの場合、デフォルトのインストールディレクトリは、/opt です。Sun Studio 9 ソフトウェアが /opt 以外のディレクトリにインストールされている場合は、ご使用のシステムにおける実際のパスを、システム管理者に確認してください。
複数のテンプレートリポジトリの使用 (-ptrオプションの廃止)
注 -- デフォルトでのテンプレートリポジトリの作成は廃止されました。コンパイラにリポジトリを作成させるには、明示的に -instances=extern を指定する必要があります。
5.0 より前の C++ コンパイラでは、-ptr オプションを使用して、テンプレートのインスタンス化に使用するリポジトリを指定していました。バージョン 5.0 〜 5.6 の C++ コンパイラでは、-ptr オプションは不要です。 これは、コンパイルシステムが、読み取るオブジェクトファイルに対応するテンプレートリポジトリに含まれているテンプレートインスタンスを、CC コマンドで指定された出力先ディレクトリ内のリポジトリに書き込むためです。
-ptr オプションは、 5.5 C++ コンパイラで廃止されました。コンパイラは、-ptr オプションを無視します。オプションは無視されるとしても、すべてのコンパイルコマンドから -ptr は削除しておいてください。 その理由は、今後のリリースで、別の動作を行う -ptr が再実装される可能性があるためです。
注 -- 複数のアプリケーションやライブラリの間で 1 つのテンプレートリポジトリを共有することは、以前からできません。共有しようとすると、コンパイルが正しく行われないことがあり、その場合は、テンプレートが再定義されて、実行時に予測できない結果が生じます。詳細は、『C++ ユーザーズガイド』を参照してください。
このマニュアルの HTML 版にアクセスするには、ブラウザで file:/opt/SUNWspro/docs/ja/index.html を開きます。Solaris プラットフォームの場合、デフォルトのインストールディレクトリは、/opt です。Sun Studio 9 ソフトウェアが /opt 以外のディレクトリにインストールされている場合は、ご使用のシステムにおける実際のパスを、システム管理者に確認してください。
const メンバー関数のポインタを含む 4.0.1 ライブラリとのリンク
C++ 4.0.1 コンパイラが const メンバー関数のポインタに対して生成する符号化名は、バージョン 4.1、4.2、5.0 〜 5.6 の C++ コンパイラが生成する内容とは異なります。C++ コンパイラを使用していて、4.0.1 で構築された、符号化名を含むライブラリとリンクできない場合は、そのライブラリを再コンパイルするか、-compat -Qoption ccfe -abirel=4.0.1 フラグを指定して、プログラムの残り部分をコンパイルする必要があります。
注 -- 将来のリリースでは -abirel=4.0.1 オプションのサポートが廃止される可能性があります。
以前のコンパイラでコンパイルしたライブラリとのリンク
C++ 4.0.1 および C++ 4.1 コンパイラでは、extern "C" 関数でインスタンス化されたテンプレートに対して、解析不可能な符号化名が生成されていました。したがって、デバッグツールが正しく動作しませんでした。この問題は解決されましたが、一部ユーザーから、バージョン 5.0 〜 5.5 の C++ コンパイラでコンパイルしたオブジェクトを旧バージョンのコンパイラでコンパイルしたライブラリとリンクできないとの報告があります。この問題はまれにしか発生しませんが、発生した場合は、次のどちらかを行なってください。
- Sun Studio 9 C++ (5.6) コンパイラを使用してライブラリを再コンパイルするか、あるいは
- -compat および -Qoption ccfe -abirel=4.1 フラグを使用して、Sun Studio 9 C++ (5.6) コンパイラで新しいオブジェクトをコンパイルする。
注 -- 将来のリリースでは -abirel=4.1 フラグのサポートが廃止される可能性があります。
異なるバージョンで生成されたオブジェクトコードの混在
互換モードと標準モードのコードを混在させていない限り、異なるバージョンの C++ コンパイラで生成したオブジェクトコードを同じプログラムに混在させることができます。ただし、最終プログラムのリンクには、混用されているコンパイラの中で最新のバージョンを使用する必要があります。
注 -- バージョン 4.2 で生成したコードと標準モードの C++ コードをリンクすることはできません。
G.記述の誤りの訂正
現時点では新しい情報はありません。
H.ライブラリの再配布について
- 実行可能ファイルが、次のファイルに示されたサンの動的ライブラリを必要とする場合は、ライセンスにもとづいて、それらのライブラリを再配布できます。
/opt/SUNWspro/READMEs/ja/runtime.libraries
注 - Sun Studio 9 ソフトウェアが /opt 以外のディレクトリにインストールされている場合は、ご使用のシステムにおける実際のパスを、システム管理者に確認してください。
どのような形態でも、ヘッダーファイル、ソースコード、オブジェクトモジュール、オブ ジェクトモジュールの静的ライブラリを第三者に配付、公開することはできません。
使用ライセンスは、CD-ROM のケースの裏面にあるエンドユーザーオブジェクトコードライセンスに記載されています。
- libCstd および (または) libiostream の共有ライブラリバージョンを使用する場合は、次の 2 つのオプションがあります。
- 製品といっしょに SUNWlibC パッチを配布します。 または
- カスタマが http://www.sunsolve.sun.com のようなサンの Web サイトから最新の SUNWlibC パッチをダウンロードする必要があります。このパッチは無料で、何度でも配布可能です。
従来どおり、ライブラリを静的にリンクする場合は、それ以外のアクションもアクセス権も必要ありません。異なるバージョンのオペレーティングシステム上でのプログラムの互換性を確認するには、共有ライブラリにリンクします。
I.. 未対応の言語仕様
C++ コンパイラ (CC) は、C++、ISO IS 14882:1998、プログラミング言語 C++ の ISO 規格に対応しています。このリリースではサポートしていない ISO 規格の要件を次のリストで説明します。
- 次のような、関数テンプレートの関数パラメータリスト内のテンプレートの型名でないパラメータを含む式
template<int I> void foo(mytype<2*I> ) { ... }
- テンプレートパラメータテンプレート (正式なテンプレートパラメータとしてのテンプレート)
- 汎用文字名
- テンプレートコンパイルのエクスポートモデル
- C++ コンパイラの現行リリースと旧リリースのバイナリ互換性を維持するため、一部の libCstd 機能が実装されていません。 file:/opt/SUNWspro/docs/ja/index.html で C++ FAQ に関するリンクを調べてください。Solaris プラットフォームの場合、デフォルトのインストールディレクトリは、/opt です。Sun Studio 9 ソフトウェアが /opt 以外のディレクトリにインストールされている場合は、ご使用のシステムにおける実際のパスを、システム管理者に確認してください。
Copyright c 2004 Sun Microsystems, Inc. All rights reserved.Use is subject to license terms.