1 ポイント 投稿者 GN⁺ 2 시간 전 | 1件のコメント | WhatsAppで共有
  • GNU Compiler Collectionの新しいリリースは、C++のデフォルト標準を gnu++20 に変更し、C++20実装をもはや experimental と見なさない重要な転換点となる
  • C++26 の reflection・contracts・constexpr 機能、C++23 機能、experimental な C++23・C++26 library サポートが追加され、template エラーと type trait constraint failure の診断は階層型メッセージでより詳細になった
  • OpenMP と OpenACC は GPU メモリ割り当て、target memset、device memcpy API を拡張し、Ada・Fortran・Modula-2・Algol 68 front end にも新しい言語機能と実験的コンパイラが加わった
  • x86-64 は AMD Zen6、Intel Wildcat Lake、Intel Nova Lake をサポートし、AMD GPU・LoongArch・IBM z Systems・Solaris・Windows 向けでもターゲット別機能と ABI の変更が追加された
  • JSON 診断形式の削除と SARIF・HTML 診断の強化、static analyzer の改善、libgdiagnostics の 37 個の entrypoint 追加により、ツール連携と診断インフラが大きく広がった

互換性の変更と共通改善

  • Solaris では int8_t などは C99 標準準拠のため signed char になり、これは互換性のない変更である
  • Solaris では -pthread オプションはもはや _REENTRANT を事前定義しない
  • -fdiagnostics-format=json 形式は削除され、機械可読な診断には SARIF を使う必要がある
  • Link-Time Optimization-flto-toplevel-asm-heuristics により最上位 asm 文の処理をより適切に扱えるようになった
  • speculative devirtualization は一般的な間接関数呼び出しを処理し、2 つ以上の対象推測をサポートする
  • vectorizer は reduction のループ内並列性の識別がより柔軟になり、反復回数を特定できないループと uncounted loop のベクトル化をサポートする
    • masking を使う vector length agnostic loop のアラインメント用 peeling、mutual peeling for alignment、early break ループの vector induction 計算削除もサポートする
  • GCC Command Optionsoption index は、以前は抜けていた多くのオプションを含むよう修正された
  • GCC-specific attributes 文書は、GCC がサポートするすべての C/C++ dialect で許可される標準 attribute 構文をより強調するように現代化された
    • attribute 関連資料は重複を減らすよう再構成され、新しい attribute index が追加された
    • parameter と option spec file の文書は、GCC 開発者および custom GCC 構成が必要なユーザー向けの GCC internals manual に移された

言語別の主な変更

  • OpenMPとOpenACC

    • OpenMP のメモリ割り当てサポートが強化され、pinned trait allocator と ompx_gnu_pinned_mem_alloc は利用可能な場合に CUDA API を使用し、Nvidia GPU で当該メモリへのアクセス性能を改善する
    • GNU 拡張の ompx_gnu_managed_mem_alloc allocator と ompx_gnu_managed_mem_space は、host 上で device-accessible memory を割り当てる
      • unified-shared memory がサポートされていなくても device からアクセス可能であり、すべての host memory が device-accessible であるシステムでも、ほかのメモリとは page-migration の動作が異なる場合がある
    • OpenMP 5.0 は C/C++ で限定的な declare mapper サポートを追加し、uses_allocators clause は OpenMP 5.2 の文法変更と OpenMP 6.0 の semicolon サポートまで含む
    • OpenMP 5.1 は C/C++ で map clause と target update construct の iterator modifier の初期サポートを追加する
    • OpenMP 5.2 は C/C++ で begin declare variant directive をサポートする
    • OpenMP 6.0 は omp_target_memsetomp_target_memset_async API routine を追加し、no_openmp_constructs assumptions clause も利用できる
    • OpenMP 5.0、5.1、5.2 で deprecated になった directive と clause はデフォルトで deprecation warning を出し、-Wno-deprecated-openmp で無効化できる
      • deprecated named constant または API routine を使用した場合にも warning が出て、-Wno-deprecated-declarations で無効化できる
    • OpenACC は C/C++/Fortran 向けに acc_memcpy_deviceacc_memcpy_device_async API routine を追加する
    • OpenACC 3.0 の wait directive は if clause を受け付け、OpenACC 3.3 の Fortran API routine acc_attachacc_detach は OpenACC 2.6 の C/C++ counterpart を補完する
    • OpenACC 3.4 では Fortran data clause の named constant PARAMETER の使用が仕様と GCC で許可されるが、GCC では compile-time と runtime の動作に影響しない
  • Ada、Fortran、Modula-2、Algol 68

    • Ada GNAT 拡張には ConstructorDestructor が追加され、標準 Ada とかなり異なる construction/finalization メカニズムを提供する
    • Ada の Implicit withStructural Generic instantiationExtended_Access aspect が追加される
      • Extended_Access は unconstrained array subtype を指す general access type declaration に指定でき、pointer representation を変更して、Ada が割り当てていないメモリを foreign language と連携しやすくする
    • Ada は -gnatd_V または verbose mode の -gnatd_W で compiler debugging 用の VAST を利用でき、Ada 2022 Reduction Expressions の semantic analysis、Ada.Containers.Bounded_Indefinite_Holders、accessibility rule の実装、Android サポートが改善される
    • Fortran は single node machine で native shared memory multithreading を使う coarray と、Fortran 2018 の TEAM feature を扱う
    • Fortran 2003 Parameterized Derived Types のサポートが改善され、LEN parameter の処理は動作するが、PR82649 に基づく将来的な representation の変更が必要となる
    • Fortran 2018 は IMPORT statement の拡張、REDUCE intrinsic、新しい GENERIC statement をサポートする
    • Fortran 2023 は sinpi のような三角関数の追加、split intrinsic subroutine、optional lower bound を引数に取る c_f_pointer をサポートする
    • -fexternal-blas64 オプションは MATMUL で 64-bit integer argument を使って external BLAS routine を呼び出し、64-bit system かつ -ffrontend-optimize 適用時のみ有効である
    • Modula-2 は import list、module name、nested scope symbol の処理中に spelling hint を表示し、新しい wide set 実装と M2WIDESET library module を導入する
      • wide set の変更は ABI を変更し、以前の GCC バージョンの object file との間で link-time error を引き起こす可能性がある
    • Modula-2 の基本 library には BinDict binary dictionary module が追加され、複数の module に WriteWriteLn procedure が提供され、-fm2-pathname-root= オプションにより external library module へのアクセスが改善される
    • GCC には experimental な Algol 68 compiler である ga68 が含まれ、Revised Report と IFIP WG2.1 Algol 68 Support subcommittee が承認した errata の実装を目指す
      • 一部の GNU extension と POSIX prelude も実装され、言語情報は Algol 68 website、front end 情報は wiki を参照

C++とlibstdc++

  • C++ compilationのデフォルト言語バージョンが -std=gnu++17 から -std=gnu++20 に変更
    • 以前のC++標準に依存するコードは、build flagに -std= を追加するか、コードをportingする必要があり、porting notes を参照
    • C++20 modulesサポートは引き続きexperimentalで、-fmodules で有効化する必要がある
  • C++26機能では、reflection、annotations for reflection、base class subobject splicing、function parameter reflection、contracts、constexpr exceptions、constexpr virtual inheritance など多数が実装
    • P2996R13 Reflection-std=c++26 -freflection で有効化される
    • 一部の P2686R4 は部分サポートで、structured binding は constexpr にできるが、constexpr automatic variable参照はまだ許可されていない
  • C++23機能では P2036R3P2590R2P2246R1 が実装
  • C++ error messageは、template関連の問題などで 階層構造 を持ち、indentationとbullet pointでmessage nestingを表示
  • experimentalなC++20 modulesサポートでは、--compile-std-module オプションを追加して、<bits/stdc++.h> header unitと stdstd.compat moduleをsource file compile前にビルドする
    • <bits/stdc++.h> header unitがビルド済みであれば、import可能なstandard library headerの #include<bits/stdc++.h> importへ透過的に変換する
    • 報告されていた多くのbugが修正
  • standard library type traitのconstraint failure diagnosticsは、is_constructible_vis_invocable_v などがなぜ false なのかをより詳しく知らせる
  • libstdc++で128-bit integerをサポートするtargetでは、std::is_integral<__int128> と類似のtraitが常にtrueになる
    • 以前はGNU dialectではtrueだったが、strict dialectではそうではなかった
  • P0952R2: A new specification for std::generate_canonical が、C++11以降で影響を受けるすべてのmodeに実装され、観測されるoutputに影響する
    • 以前の挙動は _GLIBCXX_USE_OLD_GENERATE_CANONICAL 定義で復元可能
  • std::variant ABIはC++20以降のmodeと一貫するよう更新され、特定のC++17 modeのclass layoutに影響する
    • 以前の挙動は _GLIBCXX_USE_VARIANT_CXX17_OLD_ABI 定義で復元可能で、影響はC++17 modeにのみ該当する
  • std::regex executionはsystem stackではなくheap-based stackを使うように再実装され、より大きなstring matching中のstack overflowを回避
  • C++20実装はもはやexperimentalではなく、Windowsで std::chrono::current_zone() が動作する
  • GCC 16以前のC++20サポートはexperimentalだったため、C++20 componentを使うprogramはolder releaseと互換性がないとみなすべき
    • ABI変更の対象には、<atomic> waiting/notifying function、<semaphore> semaphore type、<syncstream> synchronization、std::format argsと std::formatter representation、<compare>std::partial_ordering、一部の <ranges> adaptor representation などが含まれる
  • experimentalなC++23 libraryサポートには、std::mdspanranges::starts_withranges::ends_withranges::shift_leftranges::shift_rightstd::allocator_traits::allocate_at_least が含まれる
  • experimentalなC++26 libraryサポートには、std::simdstd::inplace_vectorstd::optional<T&>std::copyable_functionstd::function_refstd::indirectstd::polymorphic、shared pointer向けの std::owner_equal<debugging> header などが含まれる

ターゲットとオペレーティングシステムのサポート

  • IA-32/x86-64

    • AMD Zen6ベースのCPUは -march=znver6 でサポートされ、Zen5で有効化されたISA拡張に加えて AVX512_BMM、AVX_NE_CONVERT、AVX_IFMA、AVX_VNNI_INT8、AVX512_FP16 を有効化
    • AVX512サポートが有効で、znver4znver5znver6 チューニング時には、自動ベクトル化が masked vector epilog の使用を試み、コードサイズを削減し性能を改善
    • Intel Wildcat Lake は -march=wildcatlake、Intel Nova Lake は -march=novalake でサポート
      • -march=novalake は Panther Lake ベースのISA拡張に APX_F、AVX10.1、AVX10.2、PREFETCHI を追加で有効化
    • GCC 16から、複数の -march= スイッチで AMX-TRANSPOSE、USER_MSR、CLDEMOTE、KL、WIDEKL、PREFETCHI の有効化が削除
    • -mavx10.1-256-mavx10.1-512-mevex512 は削除され、-mavx10.1 の behavior change warning もあわせて廃止
    • AMX-TRANSPOSE サポートは GCC 16 で削除され、GCC はもはや -mamx-transpose を受け付けない
    • 新しい --enable-x86-64-mfentry configure option は、x86-64プロファイリングで mcount の代わりに __fentry__ を使う -mfentry を有効化し、glibcターゲットではデフォルトで有効
    • --enable-tls=DIALECT はデフォルトTLS dialect の制御をサポートし、デフォルト値は gnu、許可される値は gnu と TLS descriptor 用の gnu2
  • AMD GPU、LoongArch、IBM z Systems

    • AMD GPUオフロードでは、OpenMP target region と OpenACC compute region の起動オーバーヘッドが大幅に削減
    • AMD Instinct MI300 gfx942 デバイスの実験的サポートが追加され、generic gfx9-4-generic と大部分で互換性のある gfx950 も含まれる
    • AMD GPUのデフォルト multilib build set は gfx908gfx90agfx9-genericgfx9-4-genericgfx10-3-genericgfx11-generic に変更
      • generic arch がある場合、specific device 向け multilib はデフォルトではもうビルドされない
      • generic architecture には ROCm 6.4.0 以降が必要
      • 新しいデフォルト multilib set には LLVM 20 以降の assembler と linker が必要
      • GCC の AMD installation notesconfiguration notes を参照
    • LoongArch は _BitInt (N)unsigned _BitInt (N) のような bit-precise integer type をサポート
    • LoongArch は target_clones 属性により、CPU feature ごとの function version を作成し、実行時に最適な version を自動選択する Function Multi-Versioning をサポート
    • LoongArch32 architecture のサポートが追加され、ilp32d デフォルトABIと ilp32filp32s ABI を含む
      • 標準32-bit版 LA32 と縮小32-bit版 LA32R の両方を扱い、組み込みアプリケーション向けの32-bitターゲットコード生成を可能にする
      • この機能は Binutils と glibc のサポートに依存
    • S/390、System z、IBM z Systems は bit-precise integer type と _Float16 floating-point type をサポート
      • _Float16 演算は software または float 命令で実行される
    • S/390 系には、Linux kernel の canary address loading runtime patching をサポートするための global stack protector が -mstack-protector-guard=global として追加され、-mstack-protector-guard-record も追加
    • S/390 系の -m31 サポートは deprecated となり、今後の release で削除予定
  • オペレーティングシステム

    • Solaris は -gsctf オプションにより、Solaris CTF、すなわち Compact C Type Format の生成を容易にサポート
    • Windows は native TLS、すなわち Thread-Local Storage をサポート
      • 有効化するには configure 時に --enable-tls の指定と GNU binutils 2.44 以降が必要

診断、プラグイン、静的解析

  • GCC は -fdiagnostics-add-output=experimental-html により HTML 形式の診断出力 をサポートする
  • SARIF 出力は dump directory に従い、build-dir/foo.o 出力の例では GCC 16 は build-dir/foo.c.sarif に SARIF を書き込む
    • GCC 15 は同じ例で foo.c.sarif に書き込んでいた
  • SARIF 出力は logical location nesting をキャプチャし、多くの場合 fix object に description property を含む
  • SARIF threadFlowLocationkinds property は、非標準の control flow 表現のために throw, catch, unwind, setjmp, longjmp の値が新たに追加された
  • GCC diagnostics は directed graph を関連付けることができ、global directed graph も report できる
    • graph は text sink では無視されるが SARIF sink にキャプチャされ、experimental-html は dot を使って SVG ベースでレンダリングする
    • SARIF または HTML diagnostic sink で cfgs=yes を設定すると、すべての optimization pass のすべての function に対する GCC intermediate representation キャプチャが有効になる
  • GCC diagnostics は XML と JSON file 内の logical location を参照できる
    • sarif-replay tool はこれを使って SARIF input の issue report 時に JSON pointer を提供する
  • GCC_DIAGNOSTICS_LOG が environment に設定されていると、diagnostic subsystem は stderr または named file に text log を出力する
    • diagnostic が正確にいつ、なぜ reject されるのかといった内部決定の追跡に使われる
  • EXPERIMENTAL_SARIF_SOCKET が environment に設定されていると、GCC は startup 時にその socket への接続を試み、発生したすべての diagnostic について JSON-RPC notification を送る
  • Plugin author 向けに publish/subscribe framework が追加され、loosely-coupled な sender と receiver の間で strongly-typed message を伝達する
    • 今回の release で plugin が subscribe できる topic は、特定の function の optimization pass の開始/終了 event と static analyzer 関連 event のみである
  • GCC diagnostic sink は finalizer hook を持つ extension object を持てるようになり、plugin はこれを使って SARIF output file に追加情報をキャプチャできる
  • GCC 16 では diagnostic machinery が大幅に整理され、diagnostic-core.h だけを使う plugin には影響がないはずだ
    • diagnostics をより複雑に使う plugin maintainer は porting guide を参照する必要がある
  • Static analyzer は C++ Named Return Value Optimization と exception の初期サポートを扱えるようになり、単純な C++ の例で利用できる
    • ただし scaling issue のため、今回の release では production C++ code で使うのは難しい可能性が高い
  • -fanalyzer-fexceptions が有効な場合、nothrow attribute のない external function call が exception を投げる可能性があると仮定する
    • 新しい -fanalyzer-assume-nothrow オプションはこの仮定を無効にする
    • C++ interoperability のために C code で -fexceptions を使うが、使用中の C API が exception を投げる可能性は低い project で warning 増加を回避する用途である
  • -fanalyzer の user code representation データ構造は、理解と debugging をより容易にするために書き直され、diagnostic location がわずかに改善された
    • その代わり analyzer の memory usage は増加した
  • -fanalyzer の memory contents simulation データ構造は再実装され、より高速で保守しやすくなった
  • analyzer は GCC の value_range machinery を使い始め、一部の false positive を取り除く

libgdiagnostics と修正された問題

1件のコメント

 
GN⁺ 2 시간 전
Hacker Newsのコメント
  • 採用されるべきなのに、実際にはあまり使われなさそうな実装機能として P2590R2 Explicit lifetime management を挙げたい
    これは std::start_lifetime_as のためのもので、ポインタを構造化型へ type-pun するときの UBではない方法 である
    外部 I/O バッファを扱うほぼすべての zero-copy コードはだいたい reinterpret_cast(buffer.get()) のような形をしており、これは undefined behavior だが、これからは reinterpret_caststart_lifetime_as に置き換えれば、もはや悪いことではなくなる
    https://en.cppreference.com/cpp/memory/start_lifetime_as

    • すでに合法的にできる方法はあり、本来はみんなそれを使っているべきだった。ポインタを no-op memmove で laundering する方法だ
      ここで reinterpret_cast を使うのはバグである
      start_lifetime_as は、メモリ laundering の呪文にきれいな標準名を与えるだけでなく、もう1つ役に立つ。意味的にはメモリに触れない一方で、no-op memmove は本質的にメモリに触れる。実際にはコンパイラが memmove が no-op だと見抜いて最適化できるため、大きな違いはあまりない
    • alignment 制約 を無視するなら read の実装次第である。コンパイラから見て完全に opaque なら、カーネルやネットワークカードのようなものが実際にそのバッファ内に Foo を構築していることになるので、cast は完全に正当化される
      start_lifetime_as は、バッファ lifetime がコンパイラに対して透過的で、aliasing の仮定を壊しうる場合に有用だ
    • cppreference の説明は少し怪しい
      T は完全に新しいオブジェクトで、その中に subobject があり、その1つが U 型だという意味に見える。Ubit_cast のように初期化されるが、おそらくそのアドレスにすでにあるビットから cast するという意味だったのだろう。だが obj が定義なしに出てくるので、正しいアドレスにある何かを指していると考えるしかない
      しかし E が何なのか が曖昧だ。ページには「E is the lvalue of type U denoting obj」とあるが、obj はおそらく char のような型のはずで、もし最初から U 型なら bit_cast は不要だったはずだ
    • char バッファでは type punning が許されている
    • そのコードは悪いだけでなく、alignment の問題 のため正しくもない
  • さっき調べるまで、GCC のリリース日程 がこんなに規則的だとは知らなかった: https://gcc.gnu.org/develop.html

    • 大規模プロジェクトはかなり前から 定期リリース に移行している
      90年代までは、欲しい機能をすべて入れた大型リリースを waterfall で作れると考えられていたが、プロジェクトが大きくなると、常にまだ準備できていない機能を作業している人が出てくる。定期リリースなら、それでも顧客にリリースを届けられる
      このやり方は、準備できるか不確かな開発者に不安定な機能を無効化するトグルを作らせることになり、現実的にはそれが最善に近い
    • 最近の GCC メジャーリリースはかなり規則的で、Fedora の春リリースとも近く、より大きなリズムの中に収まっているように見える。ヒントは Red Hat
    • Cygnus の人たちがプロジェクトを立て直してからそうなった。今では Red Hat→IBM へとつながっている
    • 記憶では、GCC が GPL3 になってからそうだった
      昔はもっと遅く、GCC 2.95 の C++ バグを回避するのにあまりに多くの時間を費やした
      問題だったバージョンをまだ覚えているという事実自体が多くを物語っている
  • もうしばらく使っている。Debian sid には trunk パッケージがある
    c++26 reflection が入っているので、reflection で魔法のようなことをいろいろやっていて、ser-des のような一部の用途ではずっと良い
    エコシステム内に LSP サーバー さえあればいいのだが

    • Debian 12 と 13 で GCC 16 バイナリ を実行すると、libstd が問題を起こしている
  • -fdiagnostics-format= のいわゆる json フォーマットは今回のリリースで削除され、GCC で machine-readable diagnostics が必要なら SARIF を使うよう書かれている
    その一方で、-fdiagnostics-add-output=experimental-html によって diagnostics を HTML 出力 できるようになったともある
    JSON 出力を削除しながら HTML 出力を追加した判断の背景が気になる

    • SARIF は正式なスキーマを持つ JSON のように見える。以前の JSON 出力は独自の非標準スキーマだったのだろう
  • 初歩的な質問だが、GCC は内部で LLVM をどこかに使っているのか、それとも独自の code generation と optimization pipeline を持っているのか気になる。LLVM と比べてどの程度なのかも知りたい

    • GCC は LLVM を使っていない
      LLVM より多くの target をサポートしており、多くの場合は同等かそれ以上に良い実行ファイルを生成する
    • Wikipedia 的に答えるなら、すでに出ているように GCC は LLVM よりはるかに古い
      Wikipedia によれば GCC は 1987年3月22日、LLVM の初期リリースは 2003年である
      さらに大きな違いはライセンスだ。GCC は GPL、LLVM は Apache License なので、両プロジェクトはコードを共有していない
    • 使っていない
    • 他の回答の「いいえ!」が正しいが、以前は GCC で LLVM backend を使う GCC プラグインがあった
      Apple は GCC から LLVM へ移行していた時期の 2012年ごろ、llvm-gcc を使っており、これは GCC front end と LLVM back end の組み合わせだった
      https://dragonegg.llvm.org
    • GCC は LLVM よりずっと古く、両者はコードを共有していない
  • -Ofast は今でも -fno-fast-math を無視するのか?

  • この約3か月、unstable ソース を使ってみた
    最近の GCC ではコンパイルできないが以前の GCC では問題なく動くプログラムがあり、現時点では全体として gcc 15.x のほうが自分には合っている
    それでも 3000本以上のプログラムをコンパイルすると考えれば、大半はうまくいき、一部だけがパッチを必要とする。そうしたパッチは LFS/BLFS で見つかることが多く、個別の問題を sed で直せばたいてい動く
    そうした問題が修正されていることを願う。私たちみんなには安定性と「ただ動くこと」が必要だ

    • その問題について バグレポート は出したのか?