このセクションでは、Oracle Developer Studio 12.5 C++ 5.14 コンパイラリリースに導入された新機能および変更された機能のサマリーを一覧で提供します。
SPARC M6、M7、および T7 プロセッサのサポート。
Intel Broadwell/avx2_i プロセッサのサポート。
x86 データ領域プロファイリングのサポート。
Oracle Solaris のデフォルトコンパイルモードは –library=Cstd で –compat=5 です (Sun ABI および libCstd ライブラリでの C++03 モード)。Oracle Linux のデフォルトコンパイルモードは –std=c++03 です (g++ ABI および実行時ライブラリでの C++03 モード)。
すべてのプラットフォーム上で –compat=5 モードのとき、正しい名前の符号化がデフォルトになっています。以前は、名前の符号化のバグは、SPARC および –m32 を指定した x86 でデフォルトでした。
新しいコンパイラオプション:
–abiopt=[mangle5|mangle6] は –compat=5 モードでのみ使用できます。デフォルトは mangle6 で、正しい名前の符号化です。Oracle Solaris SPARC および –m32 を指定した Oracle Solaris x86 では、バグの多い可能性がある、古いコンパイラの名前の符号化との互換性を確保するために mangle5 を指定できます。
–features=[no%]mergestrings を指定すると、コンパイラは文字列リテラルやその他の適切な const または読み取り専用データを、リンカーが重複した文字列を削除するバイナリの特殊なセクションに配置します。このオプションは、SPARC でのみ使用できます。
–pedantic は、デフォルトでは受け入れられるものの C++ 標準には準拠していないコードに対して警告またはエラーを出力します。
–xatomic は、どの不可分サポート実行時ライブラリがリンクされるかを指定します。
–xcheck=noreturn は、「戻らない」として記述されているルーチンが戻った場合に実行時エラーを発生させるコードを追加するように、コンパイラに通知します。
–xsecure_code_analysis は、コンパイル時に潜在的なメモリーのセキュリティー違反を検出して表示する、コンパイラセキュアコード解析を有効にします。
Oracle Developer Studio 12.5 は C++11 の完全なサポートを提供します。
Oracle Solaris Studio 12.4 で提供されている g++ 4.8.2 ライブラリは C++11 のすべての要件には従っていませんでした。特に、標準の文字列クラスとリストクラスは、バイナリ互換性を損なう変更を必要としていました。
g++ 5.1 リリースでは、g++ 4.x との互換性を確保するか、C++ 標準に準拠するかを選択できます。これらの両方を選択することはできません。g++ の使用に関する詳細な情報は、GCC5 および C++11 ABI の記事に記載されています。
Oracle Developer Studio 12.5 で –std=c++11 または –std=c++14 モードの場合は、Oracle Solaris Studio 12.4 および g++ 4.8.2 との互換性が提供されます。Oracle Developer Studio 12.5 は、標準に準拠する非互換のオプションを提供しません。
g++ 5.1 バイナリを Oracle Developer Studio バイナリと結合する場合、g++ バイナリは、すべての g++ コマンド行において、–D_GLIBCXX_USE_CXX11_ABI=0 オプションを使用してすべてコンパイルされる必要があります。
Oracle Developer Studio 12.5 は、C++14 標準に対して限定されたサポートを提供します。次の機能がサポートされています。
バイナリリテラル
サイズ指定の割り当て解除
非推奨の属性
単一引用符の桁区切り文字
メンバーの初期化と集合体
不可分機能は C++ 2011 標準の新しい言語機能です。不可分機能は –std=c++11 および –std=c++14 オプションでのみ使用できます。サポートされる機能および型については、C++ 言語規格と atomic_fence(3A)、atomic_flag(3A)、および stdatomic.h(3A) のマニュアルページを参照してください。
不可分機能には実行時サポートが必要です。実行時ライブラリの詳細については、バンドルされている不可分ライブラリを参照してください。
Oracle Developer Studio 12.5 C++ 5.14 コンパイラは一部の C++ 規則を過去のコンパイラよりも厳密に適用します。以前のコンパイラでは、誤った規則を実行すると一部の有効なコードが不正確に処理されました。このセクションでは、より厳密な実行について説明し、問題を生じさせるコードの例とコードの修正方法を示します。すべての例において、コードは変更でき、そのコードは新旧どちらのコンパイラでも機能するはずです。
以前のコンパイラは、テンプレートがインスタンス化されるまでテンプレート定義を解析しなかったため、次の結果が生じました。
以前のコンパイラは、テンプレートを定義するまで宣言されていない名前の使用を許可していました。明らかな矛盾のせいで無効なコードが受け入れられたり、有効なコードが拒否されたり、または誤った宣言が使用されたりする可能性がありました。
インスタンス化されていないテンプレート内の無制限エラーが診断されませんでした。
T がインスタンス化されるまで、テンプレートパラメータに依存しないテンプレート T の定義内の名前がインスタンス化されませんでした。これらは、T が定義された時点で暗黙的にインスタンス化されるべきです。
例 1:
template< class T > int f(int i = j) // j is not visible { return i; } int j = 2; int main() { return f<int>(); }
以前のコンパイラは、j が定義されるまでテンプレート f が解析されないため、このコードを受け入れていました。
解決策: j の宣言をテンプレートの前に移動します。
例 2:
#include <stdio.h> void f(double d) { printf("f(double)\n"); } template< class C > struct B { B() { f(1); } // f is not dependent on template parameter }; void f(int d) { printf("f(int)\n"); } int main() { B<int> b; // should print "f(double)" }
解決策: テンプレートが依存する宣言がテンプレートの定義より前に行われるようにします。
テンプレート定義内の未修飾名を検索する場合、テンプレートパラメータに依存するベースクラスを調べるべきではありません。以前のコンパイラは誤った名前検索を行なっていました。
例:
template <typename T> struct Base { }; template <typename T> struct Derived : Base <T> { Derived() : Base() { } // unqualified Base should not be found }; Derived <int> x; template <typename T> struct Derived2 : Base <T> { Derived2() : Base<T>() { } // OK }; Derived2<int> x2; int main() { }
クラス Derived では、テンプレート引数なしで未修飾の Base を使用することは有効ではありません。
解決策: クラス Derived2 では、この使用法は適正です。
テンプレートパラメータの名前を再宣言できなくなりました。
例:
template <typename T> class A { typedef int T; }; // re-declare T
解決策: テンプレートパラメータまたは局所名の別の名前を選択します。
テンプレートの前方宣言はサポートされなくなりました。
例:
$ cat x.cc template <> struct A<int>; . $ CC x.cc "x.cc", line 1: Error: A class template name was expected instead of A<int>.
以前のリリースの Oracle Developer Studio C++ では、1 つの型パラメータで名前「A」によって暗黙的に宣言されたテンプレートの明示的な特殊化として、これを暗黙的に受け入れます。
解決策: 明示的な特殊化の前にプライマリテンプレートを宣言します。
template<class T> struct A; template <> struct A<int>;
template<> なしで明示的特殊化を宣言する 1998 年以前のスタイルは許可されなくなりました。
例:
template <typename T> class A { static T m; }; int A<int>::m = 0; // now an error
解決策:
template<> int A<int>::m = 0;
テンプレート定義の分離を参照してください。「テンプレート定義の分離」コンパイルモデルがより厳密になりました。ヘッダー X.h で宣言されているテンプレートの定義を持つ X.cc ファイルを作成する場合、そのファイル内の項目以外 (つまり、その定義に直接関連付けられている項目以外) を含まないように特に注意が必要です。この規則に違反すると、「複数定義」のエラーが生じやすくなっています。
例:
% cat extdef.h template <typename T> T foo(T); % cat extdef.cc #include "extdef.h" int main() { foo(1); } % CC extdef.cc -template=extdef "extdef.cc", line 3: Error: main() already had a body defined. 1 Error(s) detected.
解決策: テンプレート定義に必要ないすべてのものを X.cc ファイルから削除します。X.cc ファイルは X.h ファイルがインクルードされると常に自動的にインクルードされるため、このファイルの明示的なコンパイルは想定されていないことを思い出してください。
多くの変更が必要な場合は、-template=no%extdef オプションによるコンパイルを検討することもできます。この動作はほかのコンパイラのデフォルトであり、現在はこのリリースのデフォルトです。
C++ では int 型の暗黙的な宣言が許可されたことはありませんが、以前のコンパイラでは警告付きで許可されることがありました。正しいテンプレート処理の妨げとなるため、コンパイラはユーザーが int 型を宣言していると見なさなくなりました。
例:
static i = 0; // now an error
解決策: 宣言で型を明示的に指定します。
関数のクラス C またはクラス T 内のフレンド宣言が T の最初の宣言だった場合、以前のコンパイラは T の宣言を周囲のスコープに誤って挿入していました。このことは、有効なプログラムの誤った解釈を招く可能性があるため、Oracle Developer Studio 12.5 C++ 5.14 コンパイラではこのように動作しなくなりました。
例:
class A { friend class B; // not previously declared friend void foo(); // not previously declared B* bar() // Error: B is not defined. { foo(); // Error: The function "foo" must have a prototype. return 0; } };
解決策: フレンド関数またはクラスを、それをフレンドであると宣言するクラス宣言の前に、クラス外のスコープで宣言します。
class B; void foo(); class A { friend class B; // refers to prior declaration friend void foo(); // refers to prior declaration B* bar() // OK { foo(); // OK return 0; } };
デフォルト引数を指定するフレンド宣言も、関数定義である必要があります。
例:
class C { friend int f1(int i = 0); // Error friend int f2(int i = 0) { return i; } // OK }
以前のリリースの C++ コンパイラはこの規則を適用しませんでした。フレンド宣言のデフォルト引数を許可すると、適切なテンプレート処理の妨げになるため、許可されなくなりました。
依存関数呼び出しで名前を検索する場合、以前のコンパイラはスコープ内の静的関数を誤って無視していました。Oracle Developer Studio 12.5 C++ 5.14 コンパイラは static 関数と extern 関数を同じように扱うようになりました。
例:
// previous compiliers ignored this bar() in dependent name lookup static int bar(int) { return 1; } int bar(long) { return 0; } template <typename T> int foo(T t) { // function call depends on template argument return bar(t); } int main() { return foo(0); }
以前のコンパイラでコンパイルした場合、プログラムは 0 を返していました。Oracle Developer Studio 12.5 C++ コンパイラ 5.14 では、プログラムは 1 を返します。
名前検索で静的関数のみが見つかった場合、以前のコンパイラは次のようなエラーを返していました。
"Reference to static bar(int) not allowed in template foo(int), try using -features=tmplrefstatic."
extern 関数 bar(long) が削除された前述の例を参照してください。このコードは技術的には C++03 標準の拡張機能であるため、現在、このコンパイラは -compat=5 モードでの警告のみ発行します。C++11 モードでは、このコードは有効な C++11 であるため暗黙的に受け入れられます。
オプション -features=no%tmplrefstatic は引き続き受け入れられますが、テンプレートから静的オブジェクトへの参照が常に許可されているため、実際の影響はありません。
以前のコンパイラでは、キーワード const のプロパティーを保持するすべての規則が適用されませんでした。
例:
void f1(int**) { printf("f1(int**)\n"); } void f2(int**) { printf("Error: f2(int**)\n"); } void f2(...) { printf("OK: f1(...)\n"); } int main() { int* const p = 0; f1(&p); // #1 Should be an error f2(&p); // #2 Should choose f2(...) }
以前のコンパイラは間違って #1 を受け入れ、#2 については間違って f2(int**) を呼び出していました。行 #2 が示すように、コンパイラの誤った動作のために、正しくない多重定義関数または誤ったテンプレート特殊化が選択される可能性があります。
行 #1 は、
int* p = 0;
の宣言によって修正するか、f1 の定義の変更または多重定義の追加によって修正できます。
void f1(int * const*);
既存の無効なコードを引き続きコンパイルする場合、ドキュメントに記載されていない次のオプション
-W0,-xconstcheck=false [note: W-zero, not W-oh]
を CC コマンド行に追加でき、そうすると const の正確さについての警告が表示されます。