1 คะแนน โดย GN⁺ 1 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • รีลีสใหม่ของ GNU Compiler Collection ถือเป็นจุดเปลี่ยนสำคัญที่ เปลี่ยนมาตรฐาน C++ เริ่มต้นเป็น gnu++20 และไม่มองการรองรับ C++20 ว่าเป็นสถานะแบบ experimental อีกต่อไป
  • มีการเพิ่มการรองรับฟีเจอร์ C++26 อย่าง reflection, contracts และ constexpr, ฟีเจอร์ C++23 และไลบรารี C++23·C++26 แบบ experimental อีกทั้งการวินิจฉัยข้อผิดพลาดของ template และ type trait constraint failure ก็ละเอียดขึ้นด้วย ข้อความแบบลำดับชั้น
  • OpenMP และ OpenACC ขยายการรองรับ GPU memory allocation, target memset และ device memcpy API และใน front end ของ Ada·Fortran·Modula-2·Algol 68 ก็มี ฟีเจอร์ภาษาใหม่และคอมไพเลอร์เชิงทดลอง เพิ่มเข้ามา
  • x86-64 รองรับ AMD Zen6, Intel Wildcat Lake และ Intel Nova Lake แล้ว และยังมีการเพิ่ม ฟีเจอร์เฉพาะเป้าหมายและการเปลี่ยนแปลง ABI ฝั่ง AMD GPU·LoongArch·IBM z Systems·Solaris·Windows ด้วย
  • มีการถอดรูปแบบการวินิจฉัยแบบ JSON ออก พร้อมเสริม SARIF·HTML diagnostics, ปรับปรุง static analyzer และเพิ่ม 37 entrypoint ใน libgdiagnostics ทำให้ การเชื่อมต่อกับเครื่องมือและโครงสร้างพื้นฐานด้านการวินิจฉัย กว้างขึ้นมาก

การเปลี่ยนแปลงด้านความเข้ากันได้และการปรับปรุงทั่วไป

  • บน Solaris ค่าอย่าง int8_t เป็นต้น ได้เปลี่ยนเป็น signed char เพื่อให้สอดคล้องกับมาตรฐาน C99 ซึ่งเป็นการเปลี่ยนแปลงที่ไม่เข้ากันย้อนหลัง
  • บน Solaris ตัวเลือก -pthread จะไม่ predefine _REENTRANT อีกต่อไป
  • รูปแบบ json ของ -fdiagnostics-format= ถูกถอดออกแล้ว และควรใช้ SARIF สำหรับการวินิจฉัยที่เครื่องอ่านได้
  • Link-Time Optimization จัดการคำสั่ง asm ระดับบนสุดได้ดีขึ้นด้วย -flto-toplevel-asm-heuristics
  • speculative devirtualization รองรับการจัดการ indirect function call ทั่วไป และรองรับการคาดเดาปลายทางได้มากกว่าหนึ่งรายการ
  • vectorizer มีความยืดหยุ่นมากขึ้นในการระบุ loop-invariant parallelism ของ reduction และรองรับการทำเวกเตอร์ไรซ์กับลูปที่ไม่ทราบจำนวนรอบการทำซ้ำและ uncounted loop
    • ยังรองรับการ peeling เพื่อจัดแนวของ vector length agnostic loop ที่ใช้ masking, mutual peeling for alignment และการตัดการคำนวณ vector induction ของลูปแบบ early break ด้วย
  • GCC Command Options และ option index ได้รับการแก้ไขให้ครอบคลุมตัวเลือกจำนวนมากที่ก่อนหน้านี้ตกหล่น
  • เอกสาร GCC-specific attributes ถูกปรับให้ทันสมัย โดยเน้นรูปแบบ standard attribute syntax ที่ GCC อนุญาตในทุก C/C++ dialect ที่รองรับมากขึ้น
    • เนื้อหาเกี่ยวกับ attribute ถูกจัดโครงสร้างใหม่เพื่อลดความซ้ำซ้อน และมีการเพิ่ม attribute index ใหม่
    • เอกสาร parameter และ option spec file ถูกย้ายไปยัง GCC internals manual สำหรับนักพัฒนา GCC และผู้ใช้ที่ต้องการคอนฟิก GCC แบบกำหนดเอง

การเปลี่ยนแปลงสำคัญแยกตามภาษา

  • OpenMP และ OpenACC

    • มีการเสริมการรองรับการจัดสรรหน่วยความจำของ OpenMP โดย pinned trait allocator และ ompx_gnu_pinned_mem_alloc จะใช้ CUDA API เมื่อใช้งานได้ และช่วยปรับปรุงประสิทธิภาพการเข้าถึงหน่วยความจำดังกล่าวบน Nvidia GPU
    • allocator ompx_gnu_managed_mem_alloc และ ompx_gnu_managed_mem_space ซึ่งเป็น GNU extension จะจัดสรรหน่วยความจำที่อุปกรณ์สามารถเข้าถึงได้จาก host
      • อุปกรณ์ยังสามารถเข้าถึงได้แม้ไม่รองรับ unified-shared memory และแม้ในระบบที่หน่วยความจำทั้งหมดของ host สามารถเข้าถึงได้จากอุปกรณ์ พฤติกรรม page-migration ก็อาจแตกต่างจากหน่วยความจำประเภทอื่น
    • OpenMP 5.0 เพิ่มการรองรับ declare mapper แบบจำกัดใน C/C++ และ clause uses_allocators ครอบคลุมทั้งการเปลี่ยนไวยากรณ์ของ OpenMP 5.2 และการรองรับ semicolon ของ OpenMP 6.0
    • OpenMP 5.1 เพิ่มการรองรับเบื้องต้นของตัวแก้ไข iterator สำหรับ map clause และ target update construct ใน C/C++
    • OpenMP 5.2 รองรับ directive begin declare variant ใน C/C++
    • OpenMP 6.0 เพิ่ม API routine omp_target_memset และ omp_target_memset_async และยังสามารถใช้ assumptions clause no_openmp_constructs ได้ด้วย
    • directive และ clause ที่ถูก deprecated ใน OpenMP 5.0, 5.1 และ 5.2 จะมี deprecation warning ตามค่าเริ่มต้น และปิดได้ด้วย -Wno-deprecated-openmp
      • การใช้ named constant หรือ API routine ที่ deprecated ก็จะมี warning เช่นกัน และปิดได้ด้วย -Wno-deprecated-declarations
    • OpenACC เพิ่ม API routine acc_memcpy_device และ acc_memcpy_device_async สำหรับ C/C++/Fortran
    • directive wait ของ OpenACC 3.0 รับ if clause ได้ และ API routine ของ Fortran ใน OpenACC 3.3 คือ acc_attach และ acc_detach จะมาเสริม counterpart ฝั่ง C/C++ ของ OpenACC 2.6
    • ใน OpenACC 3.4 สามารถใช้ named constant PARAMETER ใน Fortran data clause ได้ทั้งตามสเปกและใน GCC แต่ใน GCC จะไม่ส่งผลต่อพฤติกรรมตอน compile-time และ runtime
  • Ada, Fortran, Modula-2, Algol 68

    • มีการเพิ่ม Constructor และ Destructor ให้กับ Ada GNAT extension ทำให้มีกลไก construction/finalization ที่แตกต่างจาก Ada มาตรฐานอย่างมาก
    • มีการเพิ่ม aspect ของ Ada ได้แก่ Implicit with, Structural Generic instantiation, และ Extended_Access
      • Extended_Access สามารถระบุใน general access type declaration ที่ชี้ไปยัง unconstrained array subtype ได้ โดยจะเปลี่ยน pointer representation และช่วยให้ Ada ทำงานร่วมกับ foreign language เพื่อจัดการหน่วยความจำที่ Ada ไม่ได้จัดสรรได้ง่ายขึ้น
    • Ada สามารถใช้ VAST สำหรับการดีบักคอมไพเลอร์ได้ด้วย -gnatd_V หรือ -gnatd_W ใน verbose mode และยังมีการปรับปรุง semantic analysis ของ Ada 2022 Reduction Expressions, Ada.Containers.Bounded_Indefinite_Holders, การติดตั้ง accessibility rule และการรองรับ Android
    • Fortran รองรับ coarray ที่ใช้ native shared memory multithreading บนเครื่อง single node และฟีเจอร์ TEAM ของ Fortran 2018
    • มีการปรับปรุงการรองรับ Parameterized Derived Types ของ Fortran 2003 และแม้การจัดการ LEN parameter จะทำงานได้ แต่ยังต้องมีการเปลี่ยน representation ในอนาคตตาม PR82649
    • Fortran 2018 รองรับส่วนขยายของ IMPORT statement, intrinsic REDUCE และ GENERIC statement ใหม่
    • Fortran 2023 รองรับส่วนเพิ่มของฟังก์ชันตรีโกณมิติอย่าง sinpi, intrinsic subroutine split และ c_f_pointer ที่รับ optional lower bound เป็นอาร์กิวเมนต์
    • ตัวเลือก -fexternal-blas64 จะเรียก external BLAS routine จาก MATMUL ด้วยอาร์กิวเมนต์จำนวนเต็ม 64-bit และใช้ได้เฉพาะบนระบบ 64-bit เมื่อใช้ -ffrontend-optimize
    • Modula-2 จะแสดง spelling hint ระหว่างการจัดการ import list, ชื่อโมดูล และสัญลักษณ์ใน nested scope และเพิ่มการใช้งาน wide set แบบใหม่พร้อม library module M2WIDESET
      • การเปลี่ยนแปลงของ wide set นี้เปลี่ยน ABI และอาจทำให้เกิด link-time error กับ object file จาก GCC เวอร์ชันก่อนหน้า
    • มีการเพิ่มโมดูลพจนานุกรมไบนารี BinDict ในไลบรารีพื้นฐานของ Modula-2 พร้อมทั้งมี procedure Write และ WriteLn ให้ในหลายโมดูล และปรับปรุงการเข้าถึง external library module ด้วยตัวเลือก -fm2-pathname-root=
    • GCC รวม ga68 ซึ่งเป็นคอมไพเลอร์ Algol 68 แบบ experimental ไว้ด้วย โดยมีเป้าหมายเพื่ออิมพลีเมนต์ Revised Report และ errata ที่ได้รับการอนุมัติจาก IFIP WG2.1 Algol 68 Support subcommittee
      • มีการอิมพลีเมนต์ GNU extension บางส่วนและ POSIX prelude ด้วย โดยข้อมูลภาษาอยู่ที่ Algol 68 website และข้อมูล front end ดูได้ที่ wiki

C++ และ libstdc++

  • เวอร์ชันภาษาปริยายของการคอมไพล์ C++ เปลี่ยนจาก -std=gnu++17 เป็น -std=gnu++20
    • โค้ดที่อาศัยมาตรฐาน C++ รุ่นก่อนหน้าต้องเพิ่ม -std= ใน build flag หรือพอร์ตโค้ด และดู 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 ที่ถูกนำมาใช้งานแล้วได้แก่ P2036R3, P2590R2, P2246R1
  • ข้อความ error ของ C++ มี โครงสร้างแบบลำดับชั้น สำหรับปัญหาที่เกี่ยวข้องกับ template เป็นต้น โดยใช้ indentation และ bullet point เพื่อแสดงการซ้อนของข้อความ
  • การรองรับ experimental C++20 modules จะเพิ่มตัวเลือก --compile-std-module เพื่อ build <bits/stdc++.h> header unit และโมดูล std, std.compat ก่อนคอมไพล์ source file
    • หากมีการ build <bits/stdc++.h> header unit แล้ว #include ของ standard library header ที่ import ได้จะถูกแปลงแบบโปร่งใสเป็นการ import <bits/stdc++.h>
    • มีการแก้ไขบั๊กที่มีการรายงานไว้จำนวนมาก
  • constraint failure diagnostics ของ standard library type trait จะบอกรายละเอียดมากขึ้นว่าเหตุใด is_constructible_v, is_invocable_v เป็นต้น จึงเป็น false
  • ใน libstdc++ target ที่รองรับ 128-bit integer จะทำให้ std::is_integral<__int128> และ trait ที่คล้ายกันเป็น true เสมอ
    • ก่อนหน้านี้ใน GNU dialect จะเป็น true แต่ใน strict dialect จะไม่เป็นเช่นนั้น
  • P0952R2: A new specification for std::generate_canonical ถูกนำมาใช้งานในทุกโหมดที่ได้รับผลกระทบตั้งแต่ C++11 เป็นต้นมา และส่งผลต่อ output ที่สังเกตได้
    • สามารถกลับไปใช้พฤติกรรมเดิมได้ด้วยการกำหนด _GLIBCXX_USE_OLD_GENERATE_CANONICAL
  • ABI ของ std::variant ถูกอัปเดตให้สอดคล้องกับโหมด C++20 ขึ้นไป และส่งผลต่อ class layout ของบางกรณีในโหมด C++17
    • สามารถกลับไปใช้พฤติกรรมเดิมได้ด้วยการกำหนด _GLIBCXX_USE_VARIANT_CXX17_OLD_ABI และผลกระทบนี้มีเฉพาะในโหมด C++17 เท่านั้น
  • การทำงานของ std::regex ถูกเขียนใหม่ให้ใช้ stack แบบอิง heap แทน system stack เพื่อหลีกเลี่ยง stack overflow ระหว่างการจับคู่ string ที่มีขนาดใหญ่ขึ้น
  • การรองรับ C++20 ไม่ถือเป็น experimental อีกต่อไปแล้ว และ std::chrono::current_zone() ทำงานได้บน Windows
  • เนื่องจากการรองรับ C++20 ก่อน GCC 16 ยังเป็น experimental จึงควรถือว่าโปรแกรมที่ใช้คอมโพเนนต์ C++20 จะไม่เข้ากันกับรุ่นเก่า
    • รายการที่มีการเปลี่ยนแปลง ABI ได้แก่ฟังก์ชัน waiting/notifying ใน <atomic>, ชนิด semaphore ใน <semaphore>, synchronization ใน <syncstream>, อาร์กิวเมนต์ของ std::format และ representation ของ std::formatter, std::partial_ordering ใน <compare>, รวมถึง representation ของ adaptor บางตัวใน <ranges>
  • การรองรับไลบรารี C++23 แบบ experimental ครอบคลุม std::mdspan, ranges::starts_with, ranges::ends_with, ranges::shift_left, ranges::shift_right, std::allocator_traits::allocate_at_least
  • การรองรับไลบรารี C++26 แบบ experimental ครอบคลุม std::simd, std::inplace_vector, std::optional<T&>, std::copyable_function, std::function_ref, std::indirect, std::polymorphic, std::owner_equal สำหรับ shared pointer, และ header <debugging> เป็นต้น

การรองรับเป้าหมายและระบบปฏิบัติการ

  • IA-32/x86-64

    • CPU ที่อิง AMD Zen6 รองรับด้วย -march=znver6 และจะเปิดใช้ AVX512_BMM, AVX_NE_CONVERT, AVX_IFMA, AVX_VNNI_INT8, AVX512_FP16 เพิ่มเติมจาก ISA extension ที่เปิดใช้งานใน Zen5
    • เมื่อเปิดการรองรับ AVX512 และมีการ tuning เป็น znver4, znver5, znver6 การทำ auto-vectorization จะพยายามใช้ masked vector epilog เพื่อลดขนาดโค้ดและปรับปรุงประสิทธิภาพ
    • Intel Wildcat Lake รองรับด้วย -march=wildcatlake และ Intel Nova Lake รองรับด้วย -march=novalake
      • -march=novalake จะเปิดใช้ APX_F, AVX10.1, AVX10.2, PREFETCHI เพิ่มเติมจาก ISA extension ที่อิง Panther Lake
    • ตั้งแต่ GCC 16 เป็นต้นไป ได้ยกเลิกการเปิดใช้ AMX-TRANSPOSE, USER_MSR, CLDEMOTE, KL, WIDEKL, PREFETCHI ในหลาย -march= switch
    • -mavx10.1-256, -mavx10.1-512, -mevex512 ถูกถอดออก และคำเตือนการเปลี่ยนพฤติกรรมของ -mavx10.1 ก็หายไปด้วย
    • การรองรับ AMX-TRANSPOSE ถูกถอดออกใน GCC 16 และ GCC จะไม่รับ -mamx-transpose อีกต่อไป
    • configure option ใหม่ --enable-x86-64-mfentry จะเปิดใช้ -mfentry ซึ่งใช้ __fentry__ แทน mcount สำหรับการทำ profiling บน x86-64 และจะเปิดเป็นค่าเริ่มต้นบน glibc target
    • --enable-tls=DIALECT รองรับการควบคุม TLS dialect เริ่มต้น โดยค่าเริ่มต้นคือ gnu และค่าที่อนุญาตคือ gnu กับ gnu2 สำหรับ TLS descriptor
  • AMD GPU, LoongArch, IBM z Systems

    • overhead ในการ launch ของ OpenMP target region และ OpenACC compute region บน AMD GPU offloading ลดลงอย่างมาก
    • เพิ่มการรองรับแบบ experimental สำหรับอุปกรณ์ AMD Instinct MI300 gfx942 และรวมถึง gfx950 ที่เข้ากันได้กับ generic gfx9-4-generic เป็นส่วนใหญ่
    • ชุด multilib build เริ่มต้นของ AMD GPU เปลี่ยนเป็น gfx908, gfx90a, gfx9-generic, gfx9-4-generic, gfx10-3-generic, gfx11-generic
      • หากมี generic arch แล้ว จะไม่ build multilib สำหรับอุปกรณ์เฉพาะเป็นค่าเริ่มต้นอีกต่อไป
      • generic architecture ต้องใช้ ROCm 6.4.0 ขึ้นไป
      • ชุด multilib เริ่มต้นใหม่ต้องใช้ assembler และ linker ของ LLVM 20 ขึ้นไป
      • ดู AMD installation notes และ configuration notes ของ GCC
    • LoongArch รองรับ bit-precise integer type เช่น _BitInt (N) และ unsigned _BitInt (N)
    • LoongArch รองรับ Function Multi-Versioning ผ่าน attribute target_clones เพื่อสร้าง function version ตาม CPU feature และเลือกเวอร์ชันที่เหมาะสมที่สุดโดยอัตโนมัติขณะ runtime
    • เพิ่มการรองรับสถาปัตยกรรม LoongArch32 โดยมี ABI เริ่มต้นเป็น ilp32d และรวม ABI ilp32f, ilp32s
      • ครอบคลุมทั้ง LA32 ซึ่งเป็นเวอร์ชัน 32-bit มาตรฐาน และ LA32R ซึ่งเป็นเวอร์ชัน 32-bit แบบลดรูป ทำให้สามารถสร้าง target code แบบ 32-bit สำหรับ embedded application ได้
      • ความสามารถนี้ขึ้นอยู่กับการรองรับจาก Binutils และ glibc
    • S/390, System z, IBM z Systems รองรับ bit-precise integer type และ floating-point type แบบ _Float16
      • การทำงานของ _Float16 จะดำเนินการด้วยซอฟต์แวร์หรือคำสั่ง float
    • ในตระกูล S/390 ได้เพิ่ม global stack protector สำหรับรองรับ runtime patching ของ Linux kernel สำหรับการโหลด canary address ด้วย -mstack-protector-guard=global และเพิ่ม -mstack-protector-guard-record ด้วย
    • การรองรับ -m31 ในตระกูล S/390 ถูกประกาศเลิกใช้แล้ว และจะถูกถอดออกในรีลีสถัดไป
  • ระบบปฏิบัติการ

    • Solaris รองรับการสร้าง Solaris CTF หรือ Compact C Type Format ได้สะดวกผ่านตัวเลือก -gsctf
    • Windows รองรับ native TLS หรือ Thread-Local Storage
      • หากต้องการเปิดใช้ ต้องระบุ --enable-tls ตอน configure และใช้ GNU binutils 2.44 ขึ้นไป

การวินิจฉัย, ปลั๊กอิน, การวิเคราะห์แบบสถิต

  • GCC รองรับเอาต์พุตการวินิจฉัยในรูปแบบ HTMLด้วย -fdiagnostics-add-output=experimental-html
  • เอาต์พุต SARIF จะอ้างอิงตาม dump directory และในตัวอย่างเอาต์พุต build-dir/foo.o นั้น GCC 16 จะเขียน SARIF ไปที่ build-dir/foo.c.sarif
    • ในตัวอย่างเดียวกัน GCC 15 เขียนไปที่ foo.c.sarif
  • เอาต์พุต SARIF จะเก็บ logical location nesting และในหลายกรณีจะมี description property อยู่ใน fix object
  • kinds property ของ SARIF threadFlowLocation ได้เพิ่มค่า throw, catch, unwind, setjmp, longjmp สำหรับการแสดง control flow ที่ไม่เป็นมาตรฐาน
  • GCC diagnostics สามารถเชื่อม directed graph ได้ และยังสามารถรายงาน global directed graph ได้ด้วย
    • graph จะถูกละเลยใน text sink แต่จะถูกเก็บใน SARIF sink และ experimental-html จะเรนเดอร์เป็นแบบ SVG โดยใช้ dot
    • หากตั้งค่า cfgs=yes ใน SARIF หรือ HTML diagnostic sink จะเปิดใช้งานการเก็บ GCC intermediate representation ของทุกฟังก์ชันในทุก optimization pass
  • GCC diagnostics สามารถอ้างอิง logical location ภายในไฟล์ XML และ JSON ได้
    • เครื่องมือ sarif-replay ใช้สิ่งนี้เพื่อให้ JSON pointer เมื่อรายงานปัญหาจาก SARIF input
  • หากตั้งค่า GCC_DIAGNOSTICS_LOG ไว้ใน environment ระบบย่อยการวินิจฉัยจะส่งออก text log ไปยัง stderr หรือไฟล์ที่ระบุชื่อไว้
    • ใช้เพื่อติดตามการตัดสินใจภายใน เช่น การ reject diagnostic ว่าเกิดขึ้นเมื่อใดและเพราะเหตุใด
  • หากตั้งค่า EXPERIMENTAL_SARIF_SOCKET ไว้ใน environment GCC จะพยายามเชื่อมต่อกับ socket ดังกล่าวตอนเริ่มต้น และส่ง JSON-RPC notification สำหรับ diagnostic ทุกตัวที่เกิดขึ้น
  • สำหรับผู้เขียนปลั๊กอิน มีการเพิ่มเฟรมเวิร์กแบบ publish/subscribe สำหรับส่งต่อข้อความแบบ strongly-typed ระหว่าง sender และ receiver ที่ loosely-coupled
    • ในรีลีสนี้ topic ที่ปลั๊กอินสามารถ subscribe ได้มีเพียง event เริ่ม/หยุดของ optimization pass ของฟังก์ชันที่กำหนด และ event ที่เกี่ยวข้องกับ static analyzer
  • GCC diagnostic sink สามารถมี extension object ที่มี finalizer hook ได้ และปลั๊กอินสามารถใช้สิ่งนี้เพื่อเก็บข้อมูลเพิ่มเติมลงในไฟล์เอาต์พุต SARIF
  • ใน GCC 16 มีการจัดระเบียบ diagnostic machinery ครั้งใหญ่ และไม่ควรส่งผลกระทบต่อปลั๊กอินที่ใช้เพียง diagnostic-core.h
    • ผู้ดูแลปลั๊กอินที่ใช้งาน diagnostics แบบซับซ้อนกว่านี้ควรดู porting guide
  • Static analyzer รองรับการทำงานกับ C++ Named Return Value Optimization และการรองรับ exception ขั้นต้น ทำให้ใช้งานได้กับ simple C++ example
    • แต่เนื่องจากปัญหาเรื่อง scaling จึงมีแนวโน้มว่ายังใช้งานกับ production C++ code ได้ยากในรีลีสนี้
  • -fanalyzer จะถือว่า external function call ที่ไม่มี nothrow attribute อาจ throw exception ได้เมื่อเปิดใช้ -fexceptions
    • ตัวเลือกใหม่ -fanalyzer-assume-nothrow ใช้ปิดสมมติฐานนี้
    • มีไว้เพื่อหลีกเลี่ยง warning ที่เพิ่มขึ้นในโปรเจกต์ที่ใช้ -fexceptions กับโค้ด C เพื่อการทำงานร่วมกับ C++ แต่ C API ที่ใช้งานอยู่มีโอกาส throw exception ต่ำ
  • โครงสร้างข้อมูล representation ของ user code ใน -fanalyzer ถูกเขียนใหม่เพื่อให้เข้าใจและ debug ได้ง่ายขึ้น และปรับปรุง diagnostic location เล็กน้อย
    • แต่แลกมากับการใช้หน่วยความจำของ analyzer ที่เพิ่มขึ้น
  • โครงสร้างข้อมูลสำหรับ simulation เนื้อหาหน่วยความจำของ -fanalyzer ถูกนำไป implement ใหม่ ทำให้เร็วขึ้นและดูแลรักษาง่ายขึ้น
  • analyzer เริ่มใช้ value_range machinery ของ GCC แล้ว จึงช่วยกำจัด false positive บางส่วน

libgdiagnostics และปัญหาที่แก้ไขแล้ว

  • libgdiagnostics ได้รับ entrypoint ใหม่ทั้งหมด 37 รายการ
  • เพิ่ม entrypoint 5 รายการสำหรับการทำงานกับ logical location
  • เพิ่ม entrypoint 2 รายการสำหรับตัวเลือก command-line และการรองรับ SARIF playback
  • เพิ่ม entrypoint 12 รายการสำหรับการทำงานกับ directed graph เพื่อรองรับการสร้าง graph, การส่งผ่าน global graph, การเชื่อมต่อ diagnostic graph, การเพิ่มและค้นหา node กับ edge, และการตั้งค่า label กับ location ของ node
  • เพิ่ม entrypoint 17 รายการสำหรับประกอบ diagnostic text เป็น buffer
    • รวมถึงการสร้างและปล่อย message buffer, การ append string/text/byte/printf, การ append event id, การจัดการช่วง URL/quote/color, การ dump, และการ finish diagnostic แบบอิง buffer พร้อมการเพิ่ม location label/event
  • เพิ่ม diagnostic_manager_set_debug_physical_locations() ด้วย
  • สามารถดูรายการ problem report ที่ระบบติดตามบั๊กของ GCC ระบุว่า fixed ในรีลีส 16.1 ได้ที่ PR list
    • รายการดังกล่าวอาจไม่สมบูรณ์ และอาจมี PR บางส่วนที่แก้ไขแล้วแต่ไม่ได้ถูกรวมไว้

1 ความคิดเห็น

 
GN⁺ 1 시간 전
ความเห็นจาก Hacker News
  • อยากชี้ไปที่ P2590R2 Explicit lifetime management ว่าเป็นฟีเจอร์ที่คนควรนำไปใช้ แต่ในความเป็นจริงน่าจะไม่ได้ถูกใช้กันมากนัก
    มันมีไว้สำหรับ std::start_lifetime_as ซึ่งเป็นวิธี ที่ไม่เป็น UB ในการ type-pun พอยน์เตอร์ให้เป็นชนิดข้อมูลแบบมีโครงสร้าง
    โค้ด zero-copy เกือบทั้งหมดที่จัดการ external I/O buffer มักมีหน้าตาประมาณ reinterpret_cast(buffer.get()) และนั่นคือ undefined behavior แต่ตอนนี้ถ้าเปลี่ยนจาก reinterpret_cast เป็น start_lifetime_as ก็จะไม่ใช่สิ่งที่ผิดอีกต่อไป
    https://en.cppreference.com/cpp/memory/start_lifetime_as

    • จริง ๆ แล้วก่อนหน้านี้ก็มีวิธีที่ทำได้อย่างถูกต้องตามกฎหมายอยู่แล้ว และทุกคนก็ควรใช้วิธีนั้น นั่นคือการ laundering พอยน์เตอร์ด้วย no-op memmove
      การใช้ reinterpret_cast ตรงนี้ถือเป็นบั๊ก
      start_lifetime_as ไม่ได้แค่ตั้งชื่อมาตรฐานที่ดูเรียบร้อยให้กับคาถา laundering หน่วยความจำเท่านั้น แต่ยังทำเพิ่มอีกอย่างด้วย คือในเชิงความหมายแล้วมันไม่แตะต้องหน่วยความจำ ขณะที่ no-op memmove โดยเนื้อแท้ยังถือว่าแตะหน่วยความจำอยู่ แม้ในทางปฏิบัติความต่างจะไม่มาก เพราะคอมไพเลอร์มักมองออกว่า memmove เป็น no-op และ optimize ทิ้งได้
    • ถ้าไม่นับ ข้อจำกัดเรื่อง alignment ก็ขึ้นอยู่กับ implementation ของ read ถ้าจากมุมมองของคอมไพเลอร์มัน opaque อย่างสมบูรณ์ ก็อาจมองได้ว่าเคอร์เนลหรือการ์ดเครือข่ายเป็นผู้สร้าง Foo ขึ้นมาจริง ๆ ภายในบัฟเฟอร์นั้น ทำให้ cast ดังกล่าวสมเหตุสมผลเต็มที่
      start_lifetime_as มีประโยชน์เมื่อ lifetime ของบัฟเฟอร์โปร่งใสต่อคอมไพเลอร์ จนไปทำลายสมมติฐานเกี่ยวกับ aliasing ได้
    • คำอธิบายใน cppreference ดูน่าสงสัยเล็กน้อย
      มันดูเหมือนจะหมายความว่า T เป็นอ็อบเจ็กต์ใหม่ที่สมบูรณ์ มี subobject อยู่ภายใน และหนึ่งในนั้นมีชนิดเป็น U โดย U จะถูก initialize แบบ bit_cast ซึ่งน่าจะตั้งใจสื่อว่ามัน cast จากบิตที่มีอยู่แล้ว ณ ตำแหน่งนั้น แต่ obj โผล่มาโดยไม่มีนิยาม จึงน่าจะต้องตีความว่าหมายถึงบางสิ่งที่อยู่ที่ address ที่ถูกต้อง
      แต่สิ่งที่กำกวมคือ E คืออะไร หน้าเว็บบอกว่า “E is the lvalue of type U denoting obj” ซึ่ง obj น่าจะเป็นชนิดอย่าง char และถ้ามันเป็น U อยู่แล้วก็คงไม่ต้องใช้ bit_cast
    • อนุญาตให้ทำ type punning กับบัฟเฟอร์ char ได้
    • โค้ดนั้นไม่ใช่แค่ไม่ดี แต่ยัง ไม่ถูกต้องเพราะปัญหา alignment อีกด้วย
  • เพิ่งมารู้ก่อนหน้านี้ไม่นานว่า รอบการออกรุ่นของ GCC มีความสม่ำเสมอขนาดนี้: https://gcc.gnu.org/develop.html

    • โปรเจ็กต์ใหญ่ ๆ เปลี่ยนมาใช้ การออกรุ่นแบบสม่ำเสมอ กันมานานแล้ว
      ย้อนกลับไปถึงยุค 90 ผู้คนยังคิดว่าสามารถทำรีลีสใหญ่แบบ waterfall โดยยัดฟีเจอร์ที่ต้องการทั้งหมดเข้าไปได้ แต่พอโปรเจ็กต์ใหญ่ขึ้น จะมีคนที่กำลังทำฟีเจอร์ซึ่งยังไม่พร้อมอยู่เสมอ ถ้ามีการออกรุ่นเป็นประจำ อย่างน้อยก็ยังส่งมอบรีลีสให้ลูกค้าได้
      วิธีนี้บังคับให้นักพัฒนาที่ยังไม่แน่ใจว่าฟีเจอร์จะพร้อมหรือไม่ ต้องทำ toggle สำหรับปิดฟีเจอร์ที่ยังไม่เสถียร ซึ่งในโลกความเป็นจริงก็นับว่าใกล้เคียงกับวิธีที่ดีที่สุดแล้ว
    • ช่วงหลัง ๆ การออกรุ่นใหญ่ของ GCC ค่อนข้างสม่ำเสมอ และยังใกล้เคียงกับรอบ spring release ของ Fedora เหมือนเป็นส่วนหนึ่งของจังหวะที่ใหญ่กว่า ใบ้ให้คำตอบคือ Red Hat
    • มันเป็นแบบนั้นมาตั้งแต่คนของ Cygnus เข้ามาจัดระเบียบโปรเจ็กต์ใหม่ ซึ่งตอนนี้สายต่อมาก็คือ RedHat→IBM
    • ถ้าจำไม่ผิด มันเริ่มตั้งแต่ตอนที่ GCC เปลี่ยนมาใช้ GPL3
      ก่อนหน้านั้นช้ากว่านี้มาก และผมเสียเวลาไปเยอะกับการหาทางเลี่ยงบั๊ก C++ ของ GCC 2.95
      แค่ยังจำเวอร์ชันเจ้าปัญหานั้นได้ก็บอกอะไรได้เยอะแล้ว
  • ผมใช้มันมาสักพักแล้ว Debian sid มีแพ็กเกจ trunk
    มันมี c++26 reflection ด้วย เลยได้ทำอะไรแนวเวทมนตร์กับ reflection อยู่บ้าง และในบางกรณี เช่น ser-des นั้นดีกว่ามาก
    ถ้ามี LSP server ใน ecosystem ด้วยก็คงดี

    • ตอนรัน ไบนารี GCC 16 บน Debian 12 และ 13 นั้น libstd กำลังก่อปัญหาอยู่
  • ฟอร์แมตที่เรียกว่า json ของ -fdiagnostics-format= ถูกถอดออกในรีลีสนี้ และบอกว่าถ้าต้องการ diagnostics แบบ machine-readable จาก GCC ให้ใช้ SARIF
    แต่ขณะเดียวกันก็เพิ่มความสามารถให้ส่งออก diagnostics เป็น HTML ได้ด้วย -fdiagnostics-add-output=experimental-html
    เลยสงสัยว่าเบื้องหลังการตัดสินใจลบ JSON output แต่เพิ่ม HTML output คืออะไร

    • SARIF ดูเหมือน JSON ที่มีสคีมาอย่างเป็นทางการ ส่วน JSON ที่เคยส่งออกมาก่อนหน้านี้น่าจะเป็นสคีมาเฉพาะที่ไม่เป็นมาตรฐาน
  • ขอถามแบบมือใหม่หน่อยว่า GCC ใช้ LLVM ภายในตรงไหนบ้างไหม หรือว่ามี code generation กับ optimization pipeline ของตัวเองทั้งหมด และถ้าเทียบกับ LLVM แล้วอยู่ระดับไหน

    • GCC ไม่ได้ใช้ LLVM
      มันรองรับ target ได้มากกว่า LLVM และในกรณีส่วนใหญ่ก็สร้าง executable ที่ใกล้เคียงกันหรือดีกว่า
    • ถ้าจะตอบแบบสไตล์วิกิพีเดีย อย่างที่มีคนตอบไปแล้ว GCC เก่ากว่า LLVM มาก
      ตาม Wikipedia, GCC คือวันที่ 22 มีนาคม 1987 ส่วน LLVM รุ่นแรกคือปี 2003
      อีกความต่างใหญ่คือเรื่องไลเซนส์ GCC เป็น GPL ส่วน LLVM เป็น Apache License ดังนั้นสองโปรเจ็กต์นี้จึงไม่แชร์โค้ดกัน
    • ไม่ใช้
    • คำตอบ “ไม่!” จากคนอื่นถูกต้อง แต่ในอดีตเคยมีปลั๊กอิน GCC ที่ใช้ LLVM backend อยู่
      Apple เคยใช้ llvm-gcc ราวปี 2012 ตอนที่กำลังเปลี่ยนจาก GCC ไป LLVM ซึ่งเป็นการจับคู่ 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 ก็มักจะใช้งานได้
    หวังว่าปัญหาเหล่านั้นจะถูกแก้แล้ว เพราะพวกเราทุกคนต้องการความเสถียรและความรู้สึกว่า “มันใช้งานได้เลย”

    • คุณส่ง รายงานบั๊ก สำหรับปัญหาเหล่านั้นหรือยัง?